diff --git a/website/src/components/controls/AngleControl.tsx b/website/src/components/controls/AngleControl.tsx index bc5149c4ae..cc0bac5b09 100644 --- a/website/src/components/controls/AngleControl.tsx +++ b/website/src/components/controls/AngleControl.tsx @@ -1,10 +1,11 @@ import React, { memo, useCallback } from 'react' import styled from 'styled-components' -import { AngleControlAttrs, Flavor } from '../../types' +import { ChartProperty, Flavor } from '../../types' import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { TextInput } from './TextInput' import { Help } from './Help' +import { AngleControlConfig } from './types' const size = 36 const center = size / 2 @@ -12,25 +13,20 @@ const markerSize = 6 interface AngleControlProps { id: string - property: { - name: string - required?: boolean - help?: string - description?: string - flavors: Flavor[] - } + property: ChartProperty flavors: Flavor[] currentFlavor: Flavor value: number - options: AngleControlAttrs['controlOptions'] - onChange: (v: number) => void + config: AngleControlConfig + onChange: (value: number) => void + context?: any } export const AngleControl = memo( - ({ id, property, flavors, currentFlavor, value, options, onChange }: AngleControlProps) => { - const start = options.start || 0 - const min = options.min || 0 - const max = options.max || 360 + ({ id, property, flavors, currentFlavor, value, config, onChange }: AngleControlProps) => { + const start = config.start || 0 + const min = config.min || 0 + const max = config.max || 360 const handleChange = useCallback( event => { diff --git a/website/src/components/controls/ArrayControl.tsx b/website/src/components/controls/ArrayControl.tsx index 9d835efda2..5423db1e2b 100644 --- a/website/src/components/controls/ArrayControl.tsx +++ b/website/src/components/controls/ArrayControl.tsx @@ -1,37 +1,31 @@ -import React, { memo, Fragment, useMemo, useState, useCallback } from 'react' +import React, { memo, Fragment, useMemo, useState, useCallback, MouseEvent } from 'react' import styled from 'styled-components' import { PropertyHeader } from './PropertyHeader' import ControlsGroup from './ControlsGroup' import { Cell, Toggle } from './styled' import { Help } from './Help' +import { Flavor, ChartProperty } from '../../types' +import { ArrayControlConfig } from './types' interface ArrayControlProps { - /* - property: PropTypes.object.isRequired, - value: PropTypes.array.isRequired, - flavors: PropTypes.arrayOf(PropTypes.oneOf(['svg', 'html', 'canvas', 'api'])).isRequired, - currentFlavor: PropTypes.oneOf(['svg', 'html', 'canvas', 'api']).isRequired, - options: PropTypes.shape({ - props: PropTypes.array.isRequired, - shouldCreate: PropTypes.bool, - addLabel: PropTypes.string, - shouldRemove: PropTypes.bool, - removeLabel: PropTypes.string, - defaults: PropTypes.object, - getItemTitle: PropTypes.func, - }).isRequired, - onChange: PropTypes.func.isRequired, - */ + id: string + property: ChartProperty + value: unknown[] + flavors: Flavor[] + currentFlavor: Flavor + config: ArrayControlConfig + onChange: (value: unknown) => void + context?: any } -const ArrayControl = memo( +export const ArrayControl = memo( ({ property, flavors, currentFlavor, value, onChange, - options: { + config: { props, shouldCreate = false, addLabel = 'add', @@ -40,23 +34,24 @@ const ArrayControl = memo( defaults = {}, getItemTitle, }, - }) => { + }: ArrayControlProps) => { const [activeItems, setActiveItems] = useState([0]) const append = useCallback(() => { onChange([...value, { ...defaults }]) setActiveItems([value.length]) }, [value, onChange, defaults, setActiveItems]) + const remove = useCallback( - index => event => { + (index: number) => (event: MouseEvent) => { event.stopPropagation() - const items = value.filter((v, i) => i !== index) + const items = value.filter((_item: any, i) => i !== index) setActiveItems([]) onChange(items) }, [value, onChange, setActiveItems] ) const change = useCallback( - index => itemValue => { + (index: number) => (itemValue: unknown) => { onChange( value.map((v, i) => { if (i === index) return itemValue @@ -67,7 +62,7 @@ const ArrayControl = memo( [value, onChange] ) const toggle = useCallback( - index => () => { + (index: number) => () => { setActiveItems(items => { if (items.includes(index)) { return items.filter(i => i !== index) @@ -118,7 +113,6 @@ const ArrayControl = memo( controls={subProps} settings={item} onChange={change(index)} - isNested={true} /> )} @@ -128,8 +122,6 @@ const ArrayControl = memo( } ) -export default ArrayControl - const Header = styled(Cell)` border-bottom: 1px solid ${({ theme }) => theme.colors.borderLight}; @@ -144,7 +136,9 @@ const Title = styled.div` color: ${({ theme }) => theme.colors.textLight}; ` -const SubHeader = styled(Cell)` +const SubHeader = styled(Cell)<{ + isOpened: boolean +}>` cursor: pointer; font-weight: 600; user-select: none; diff --git a/website/src/components/controls/BlendModeControl.js b/website/src/components/controls/BlendModeControl.js deleted file mode 100644 index 01bf88971a..0000000000 --- a/website/src/components/controls/BlendModeControl.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react' -import { blendModes } from '@nivo/core' -import { ChoicesControl } from './ChoicesControl' - -const choices = blendModes.map(mode => ({ - label: mode, - value: mode, -})) - -const BlendModeControl = ({ options, ...props }) => ( - -) - -export default BlendModeControl diff --git a/website/src/components/controls/BlendModeControl.tsx b/website/src/components/controls/BlendModeControl.tsx new file mode 100644 index 0000000000..1af46c38df --- /dev/null +++ b/website/src/components/controls/BlendModeControl.tsx @@ -0,0 +1,33 @@ +import React from 'react' +// @ts-ignore +import { blendModes } from '@nivo/core' +import { ChoicesControl } from './ChoicesControl' +import { BlendModeControlConfig } from './types' +import { ChartProperty, Flavor } from '../../types' + +const choices = blendModes.map((mode: string) => ({ + label: mode, + value: mode, +})) + +interface BlendModeControlProps { + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + config: BlendModeControlConfig + value: string + onChange: (value: string) => void + context?: any +} + +export const BlendModeControl = ({ config, ...props }: BlendModeControlProps) => ( + +) diff --git a/website/src/components/controls/BoxAnchorControl.js b/website/src/components/controls/BoxAnchorControl.tsx similarity index 82% rename from website/src/components/controls/BoxAnchorControl.js rename to website/src/components/controls/BoxAnchorControl.tsx index 8045022180..cd0682c313 100644 --- a/website/src/components/controls/BoxAnchorControl.js +++ b/website/src/components/controls/BoxAnchorControl.tsx @@ -3,13 +3,15 @@ import styled from 'styled-components' import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { Help } from './Help' +import { ChartProperty, Flavor } from '../../types' +import { BoxAnchorControlConfig } from './types' const boxWidth = 80 const boxHeight = 50 const boxPadding = 10 const outlineRadius = 8 -const anchors = [ +const anchors: [string, number, number][] = [ ['center', boxWidth / 2, boxHeight / 2], ['top-left', 0, 0], ['top', boxWidth / 2, 0], @@ -33,11 +35,15 @@ const Rect = styled.rect` stroke-opacity: 0.6; ` -const Dot = styled.circle` +const Dot = styled.circle<{ + isSelected: boolean +}>` fill: ${({ isSelected, theme }) => (isSelected ? theme.colors.accent : theme.colors.textLight)}; ` -const DotOutline = styled.circle` +const DotOutline = styled.circle<{ + isSelected: boolean +}>` fill: red; fill-opacity: 0; stroke-width: 2px; @@ -54,7 +60,25 @@ const Value = styled.span` margin-left: 20px; ` -const BoxAnchorControl = ({ id, property, flavors, currentFlavor, value, onChange }) => { +interface BoxAnchorControlProps { + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + value: string + config: BoxAnchorControlConfig + onChange: (value: string) => void + context?: any +} + +export const BoxAnchorControl = ({ + id, + property, + flavors, + currentFlavor, + value, + onChange, +}: BoxAnchorControlProps) => { return ( ) } - -export default BoxAnchorControl diff --git a/website/src/components/controls/ChoicesControl.tsx b/website/src/components/controls/ChoicesControl.tsx index 27cdbc31dd..93617fdc91 100644 --- a/website/src/components/controls/ChoicesControl.tsx +++ b/website/src/components/controls/ChoicesControl.tsx @@ -4,6 +4,7 @@ import Select from './Select' import { PropertyHeader } from './PropertyHeader' import { Help } from './Help' import { Flavor } from '../../types' +import { ChoicesControlConfig } from './types' interface ChoicesControlProps { id: string @@ -12,9 +13,8 @@ interface ChoicesControlProps { currentFlavor: Flavor value: string | number | boolean onChange: (value: string | number | boolean) => void - options: { - choices: any - } + config: ChoicesControlConfig + context?: any } export const ChoicesControl = memo( @@ -24,11 +24,11 @@ export const ChoicesControl = memo( flavors, currentFlavor, value: _value, - options, + config, onChange, }: ChoicesControlProps) => { const handleUpdate = useCallback(value => onChange(value.value), [onChange]) - const value = options.choices.find(({ value: v }) => v === _value) + const value = config.choices.find(({ value: v }) => v === _value) return ( - {property.help} ) diff --git a/website/src/components/controls/ColorPickerControl.tsx b/website/src/components/controls/ColorPickerControl.tsx index 4c0e527cd2..da2ceaa203 100644 --- a/website/src/components/controls/ColorPickerControl.tsx +++ b/website/src/components/controls/ColorPickerControl.tsx @@ -3,12 +3,14 @@ import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { Help } from './Help' import { Flavor } from '../../types' +import { ColorPickerControlConfig } from './types' interface ColorPickerControlProps { id: string property: any flavors: Flavor[] currentFlavor: Flavor + config: ColorPickerControlConfig value: string onChange: (value: string) => void context: any diff --git a/website/src/components/controls/ColorsControl.tsx b/website/src/components/controls/ColorsControl.tsx index cd8c616461..3953f3f074 100644 --- a/website/src/components/controls/ColorsControl.tsx +++ b/website/src/components/controls/ColorsControl.tsx @@ -6,6 +6,7 @@ import { colorInterpolatorIds, colorInterpolators, } from '@nivo/colors' +// @ts-ignore import { components } from 'react-select' import { ColorsControlItem } from './ColorsControlItem' import { Control } from './Control' @@ -13,6 +14,7 @@ import { PropertyHeader } from './PropertyHeader' import { Help } from './Help' import Select from './Select' import { ChartProperty, Flavor } from '../../types' +import { ColorsControlConfig } from './types' const colors = colorSchemeIds.map(id => ({ id, @@ -24,21 +26,17 @@ const sequentialColors = colorInterpolatorIds.map(id => ({ colors: range(0, 1, 0.05).map(t => colorInterpolators[id](t)), })) -const SingleValue = props => { - return ( - - - - ) -} +const SingleValue = (props: any) => ( + + + +) -const Option = props => { - return ( - - - - ) -} +const Option = (props: any) => ( + + + +) interface ColorsControlProps { id: string @@ -47,9 +45,8 @@ interface ColorsControlProps { currentFlavor: Flavor onChange: any value: string - options?: { - includeSequential?: boolean - } + config: ColorsControlConfig + context?: any } export const ColorsControl = ({ @@ -58,7 +55,7 @@ export const ColorsControl = ({ flavors, currentFlavor, value, - options: controlOptions = {}, + config, onChange, }: ColorsControlProps) => { const handleChange = useCallback( @@ -68,8 +65,8 @@ export const ColorsControl = ({ [onChange] ) - let options = colors - if (controlOptions.includeSequential === true) { + let options: any[] = colors + if (config.includeSequential === true) { options = options.concat(sequentialColors) } options = options.map(({ id, colors }) => ({ diff --git a/website/src/components/controls/ControlsGroup.tsx b/website/src/components/controls/ControlsGroup.tsx index 91548a2e07..44c2f99f58 100644 --- a/website/src/components/controls/ControlsGroup.tsx +++ b/website/src/components/controls/ControlsGroup.tsx @@ -1,32 +1,32 @@ import React, { memo, useCallback } from 'react' import get from 'lodash/get' import snakeCase from 'lodash/snakeCase' -import ArrayControl from './ArrayControl' -import ObjectControl from './ObjectControl' +import { ArrayControl } from './ArrayControl' +import { ObjectControl } from './ObjectControl' import { SwitchControl } from './SwitchControl' -import SwitchableRangeControl from './SwitchableRangeControl' +import { SwitchableRangeControl } from './SwitchableRangeControl' import { ColorsControl } from './ColorsControl' -import QuantizeColorsControl from './QuantizeColorsControl' +import { QuantizeColorsControl } from './QuantizeColorsControl' import { ColorPickerControl } from './ColorPickerControl' -import TextControl from './TextControl' -import RadioControl from './RadioControl' +import { TextControl } from './TextControl' +import { RadioControl } from './RadioControl' import { RangeControl } from './RangeControl' import { ChoicesControl } from './ChoicesControl' -import BoxAnchorControl from './BoxAnchorControl' -import MarginControl from './MarginControl' +import { BoxAnchorControl } from './BoxAnchorControl' +import { MarginControl } from './MarginControl' import { OpacityControl } from './OpacityControl' -import LineWidthControl from './LineWidthControl' -import MotionConfigControl from './MotionConfigControl' +import { LineWidthControl } from './LineWidthControl' +import { MotionConfigControl } from './MotionConfigControl' import { NumberArrayControl } from './NumberArrayControl' import { AngleControl } from './AngleControl' -import OrdinalColorsControl from './OrdinalColorsControl' -import InheritedColorControl from './InheritedColorControl' -import BlendModeControl from './BlendModeControl' +import { OrdinalColorsControl } from './OrdinalColorsControl' +import { InheritedColorControl } from './InheritedColorControl' +import { BlendModeControl } from './BlendModeControl' import PropertyDocumentation from './PropertyDocumentation' -import ValueFormatControl from './ValueFormatControl' +import { ValueFormatControl } from './ValueFormatControl' import { ChartProperty, Flavor } from '../../types' -export const shouldRenderProperty = (property, currentSettings) => { +export const shouldRenderProperty = (property: ChartProperty, currentSettings: any) => { if (typeof property.when !== 'function') return true return property.when(currentSettings) } @@ -54,7 +54,7 @@ const ControlSwitcher = memo( // generate a unique identifier for the property const id = `${snakeCase(groupName)}-${property.name}` const value = get(settings, property.name) - const options = 'controlOptions' in property ? property.controlOptions : {} + const controlConfig = 'control' in property ? property.control : undefined const handleChange = useCallback( value => { onChange({ @@ -69,13 +69,13 @@ const ControlSwitcher = memo( return null } - let shouldRenderControl = property.controlType !== undefined + let shouldRenderControl = controlConfig !== undefined if (Array.isArray(property.flavors) && !property.flavors.includes(currentFlavor)) { shouldRenderControl = false } if ( Array.isArray(property.enableControlForFlavors) && - !property.enableControlForFlavors.includes('currentFlavor') + !property.enableControlForFlavors.includes(currentFlavor) ) { shouldRenderControl = false } @@ -95,7 +95,7 @@ const ControlSwitcher = memo( throw new Error(`no value defined for property: ${property.name}`) } - switch (property.controlType) { + switch (controlConfig!.type) { case 'array': return ( @@ -117,11 +117,8 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} - props={options.props} - defaults={options.defaults} - isOpenedByDefault={options.isOpenedByDefault} context={context} onChange={handleChange} /> @@ -134,7 +131,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -148,7 +145,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -162,7 +159,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -188,7 +185,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -202,7 +199,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -216,7 +213,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -230,7 +227,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -244,7 +241,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -258,7 +255,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -272,7 +269,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -286,7 +283,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -300,7 +297,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -314,7 +311,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -328,7 +325,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -342,7 +339,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -356,7 +353,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -370,7 +367,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -384,7 +381,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -398,7 +395,7 @@ const ControlSwitcher = memo( property={property} flavors={flavors} currentFlavor={currentFlavor} - options={options} + config={controlConfig} value={value} context={context} onChange={handleChange} @@ -407,7 +404,7 @@ const ControlSwitcher = memo( default: throw new Error( - `invalid control type: ${property.controlType} for property: ${property.name}` + `invalid control type: ${controlConfig!.type} for property: ${property.name}` ) } } diff --git a/website/src/components/controls/InheritedColorControl.tsx b/website/src/components/controls/InheritedColorControl.tsx index 3e86924660..fb932336ed 100644 --- a/website/src/components/controls/InheritedColorControl.tsx +++ b/website/src/components/controls/InheritedColorControl.tsx @@ -2,12 +2,14 @@ import React, { useState, useCallback } from 'react' import isString from 'lodash/isString' import isPlainObject from 'lodash/isPlainObject' import styled from 'styled-components' -import { inheritedColorPropType } from '@nivo/colors' +import { InheritedColorConfig } from '@nivo/colors' import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { Help } from './Help' import Select from './Select' import InheritedColorModifierControl from './InheritedColorModifierControl' +import { ChartProperty, Flavor } from '../../types' +import { InheritedColorControlConfig } from './types' const themeProperties = ['background', 'grid.line.stroke', 'labels.text.fill'].map(prop => ({ label: prop, @@ -17,33 +19,30 @@ const themeProperties = ['background', 'grid.line.stroke', 'labels.text.fill'].m const defaultInheritableProperties = ['color'] interface InheritedColorControlProps { - /* - property: PropTypes.object.isRequired, - flavors: PropTypes.arrayOf(PropTypes.oneOf(['svg', 'html', 'canvas', 'api'])).isRequired, - currentFlavor: PropTypes.oneOf(['svg', 'html', 'canvas', 'api']).isRequired, - onChange: PropTypes.func.isRequired, - defaultCustomColor: PropTypes.string.isRequired, - defaultThemeProperty: PropTypes.string.isRequired, - defaultFrom: PropTypes.string.isRequired, - value: inheritedColorPropType.isRequired, - options: PropTypes.shape({ - inheritableProperties: PropTypes.arrayOf(PropTypes.string), - }), - */ + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + value: InheritedColorConfig + config: InheritedColorControlConfig + onChange: (value: InheritedColorConfig) => any + context?: any } -const InheritedColorControl = ({ +export const InheritedColorControl = ({ id, property, flavors, currentFlavor, value, - defaultCustomColor = 'black', - defaultThemeProperty = 'background', - defaultFrom = 'color', onChange, - options: { inheritableProperties = defaultInheritableProperties } = {}, -}) => { + config: { + inheritableProperties = defaultInheritableProperties, + defaultCustomColor = 'black', + defaultThemeProperty = 'background', + defaultFrom = 'color', + }, +}: InheritedColorControlProps) => { const [customColor, setCustomColor] = useState(isString(value) ? value : defaultCustomColor) const [themeProp, setThemeProp] = useState( isPlainObject(value) && value.theme !== undefined ? value.theme : defaultThemeProperty @@ -140,7 +139,7 @@ const InheritedColorControl = ({ /> modifiers {modifiers.length === 0 && No modifier.} - {modifiers.map((modifier, i) => ( + {modifiers.map((modifier, i: number) => ( ` cursor: pointer; padding: 5px 9px; text-align: center; diff --git a/website/src/components/controls/LineWidthControl.js b/website/src/components/controls/LineWidthControl.tsx similarity index 68% rename from website/src/components/controls/LineWidthControl.js rename to website/src/components/controls/LineWidthControl.tsx index e07e9086f5..ca18b18598 100644 --- a/website/src/components/controls/LineWidthControl.js +++ b/website/src/components/controls/LineWidthControl.tsx @@ -4,31 +4,33 @@ import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { TextInput } from './TextInput' import { Help } from './Help' +import { ChartProperty, Flavor } from '../../types' +import { LineWidthControlConfig } from './types' const size = 24 -const Row = styled.div` - display: grid; - grid-template-columns: 60px ${size}px auto; - grid-column-gap: 9px; - align-items: center; - max-width: 240px; - margin-bottom: 5px; -` - -const Line = styled.line` - stroke: ${({ theme }) => theme.colors.border}; - stroke-width: 1px; - fill: none; -` - -const Marker = styled.line` - stroke: ${({ theme }) => theme.colors.accent}; - fill: none; -` +interface LineWidthControlProps { + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + config: LineWidthControlConfig + value: number + onChange: (value: number) => void + context?: any +} -const LineWidthControl = memo( - ({ id, property, flavors, currentFlavor, value, context, onChange }) => { +export const LineWidthControl = memo( + ({ + id, + property, + flavors, + currentFlavor, + value, + context, + onChange, + config, + }: LineWidthControlProps) => { const handleChange = useCallback( event => { onChange(Number(event.target.value)) @@ -57,7 +59,14 @@ const LineWidthControl = memo( strokeWidth={value} /> - + {property.help} @@ -65,6 +74,22 @@ const LineWidthControl = memo( } ) -LineWidthControl.displayName = 'LineWidthControl' +const Row = styled.div` + display: grid; + grid-template-columns: 60px ${size}px auto; + grid-column-gap: 9px; + align-items: center; + max-width: 240px; + margin-bottom: 5px; +` + +const Line = styled.line` + stroke: ${({ theme }) => theme.colors.border}; + stroke-width: 1px; + fill: none; +` -export default LineWidthControl +const Marker = styled.line` + stroke: ${({ theme }) => theme.colors.accent}; + fill: none; +` diff --git a/website/src/components/controls/MarginControl.tsx b/website/src/components/controls/MarginControl.tsx index e0e9084da0..5084f6eacb 100644 --- a/website/src/components/controls/MarginControl.tsx +++ b/website/src/components/controls/MarginControl.tsx @@ -1,72 +1,44 @@ -import React, { useCallback, useState } from 'react' +import React, { ChangeEvent, useCallback, useState } from 'react' import styled from 'styled-components' +import { Box as BoxType } from '@nivo/core' import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { TextInput } from './TextInput' import { Help } from './Help' +import { ChartProperty, Flavor } from '../../types' +import { MarginControlConfig } from './types' -const Grid = styled.div` - display: grid; - grid-template-columns: 50px 60px 50px 60px auto; - grid-column-gap: 9px; - grid-row-gap: 5px; - margin-bottom: 5px; -` - -const Label = styled.label` - text-align: right; -` - -const BoxCell = styled.div` - grid-column-start: 5; - grid-row-start: 1; - grid-row-end: 3; - padding: 5px 0; -` - -const Box = styled.div` - width: 100%; - height: 100%; - max-width: 80px; - margin-left: 12px; - border: 2px solid ${({ theme }) => theme.colors.border}; - ${({ side, theme }) => { - if (side === null) return '' - - return ` - border-${side}-color: ${theme.colors.accent}; - border-${side}-width: 3px; - ` - }} -` +type Side = keyof BoxType interface MarginControlProps { - /* - id: PropTypes.string.isRequired, - property: PropTypes.object.isRequired, - flavors: PropTypes.arrayOf(PropTypes.oneOf(['svg', 'html', 'canvas', 'api'])).isRequired, - currentFlavor: PropTypes.oneOf(['svg', 'html', 'canvas', 'api']).isRequired, - value: PropTypes.shape({ - top: PropTypes.number, - right: PropTypes.number, - bottom: PropTypes.number, - left: PropTypes.number, - }).isRequired, - onChange: PropTypes.func.isRequired, - */ + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + value: BoxType + config: MarginControlConfig + onChange: (value: BoxType) => void + context?: any } -const MarginControl = ({ id, property, flavors, currentFlavor, value, onChange }) => { - const [side, setSide] = useState(null) +export const MarginControl = ({ + id, + property, + flavors, + currentFlavor, + value, + onChange, +}: MarginControlProps) => { + const [side, setSide] = useState(null) - const handleChange = side => e => { + const handleChange = (side: Side) => (e: ChangeEvent) => { onChange({ ...value, [side]: Number(e.target.value), }) } - const handleFocus = side => () => { + const handleFocus = (side: Side) => () => { setSide(side) } @@ -133,4 +105,39 @@ const MarginControl = ({ id, property, flavors, currentFlavor, value, onChange } ) } -export default MarginControl +const Grid = styled.div` + display: grid; + grid-template-columns: 50px 60px 50px 60px auto; + grid-column-gap: 9px; + grid-row-gap: 5px; + margin-bottom: 5px; +` + +const Label = styled.label` + text-align: right; +` + +const BoxCell = styled.div` + grid-column-start: 5; + grid-row-start: 1; + grid-row-end: 3; + padding: 5px 0; +` + +const Box = styled.div<{ + side: Side | null +}>` + width: 100%; + height: 100%; + max-width: 80px; + margin-left: 12px; + border: 2px solid ${({ theme }) => theme.colors.border}; + ${({ side, theme }) => { + if (side === null) return '' + + return ` + border-${side}-color: ${theme.colors.accent}; + border-${side}-width: 3px; + ` + }} +` diff --git a/website/src/components/controls/MotionConfigControl.js b/website/src/components/controls/MotionConfigControl.js deleted file mode 100644 index 1a95b95ac1..0000000000 --- a/website/src/components/controls/MotionConfigControl.js +++ /dev/null @@ -1,177 +0,0 @@ -import React, { memo, useCallback, useState } from 'react' -import { config as springConfig } from '@react-spring/web' -import { isString } from 'lodash' -import styled from 'styled-components' -import { Control } from './Control' -import { PropertyHeader } from './PropertyHeader' -import { Radio } from './Radio' -import Select from './Select' -import { Switch } from './Switch' -import { Help } from './Help' - -const Row = styled.div` - display: grid; - grid-template-columns: 1fr; - grid-row-gap: 9px; -` - -const CustomControls = styled.div` - display: grid; - grid-template-columns: 50px 25px auto 50px 25px auto; - align-items: center; - column-gap: 9px; - row-gap: 9px; - margin-bottom: 9px; -` - -const presetOptions = Object.keys(springConfig).map(presetId => ({ - 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/MotionConfigControl.tsx b/website/src/components/controls/MotionConfigControl.tsx new file mode 100644 index 0000000000..db47387ec1 --- /dev/null +++ b/website/src/components/controls/MotionConfigControl.tsx @@ -0,0 +1,190 @@ +import React, { ChangeEvent, memo, useCallback, useState } from 'react' +import { config as springConfig } from '@react-spring/web' +import { isString } from 'lodash' +import styled from 'styled-components' +import { Control } from './Control' +import { PropertyHeader } from './PropertyHeader' +import { Radio } from './Radio' +import Select from './Select' +import { Switch } from './Switch' +import { Help } from './Help' +import { ChartProperty, Flavor } from '../../types' +import { MotionConfigControlConfig } from './types' + +const presetOptions = Object.keys(springConfig).map(presetId => ({ + value: presetId, + label: presetId, +})) + +const defaultConfig = { + mass: 1, + tension: 170, + friction: 26, + clamp: false, + precision: 0.01, + velocity: 0, +} + +interface MotionConfigControlProps { + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + config: MotionConfigControlConfig + value: any + onChange: (value: any) => void + context?: any +} + +export const MotionConfigControl = memo( + ({ id, property, flavors, currentFlavor, value, onChange }: MotionConfigControlProps) => { + 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: ChangeEvent) => { + const mass = Number(event.target.value) + const newCustomConfig = { + ...customConfig, + mass, + } + setCustomConfig(newCustomConfig) + onChange(newCustomConfig) + } + + const handleTensionChange = (event: ChangeEvent) => { + const tension = Number(event.target.value) + const newCustomConfig = { + ...customConfig, + tension, + } + setCustomConfig(newCustomConfig) + onChange(newCustomConfig) + } + + const handleFrictionChange = (event: ChangeEvent) => { + const friction = Number(event.target.value) + const newCustomConfig = { + ...customConfig, + friction, + } + setCustomConfig(newCustomConfig) + onChange(newCustomConfig) + } + + const handleClampChange = (clamp: boolean) => { + const newCustomConfig = { + ...customConfig, + clamp, + } + setCustomConfig(newCustomConfig) + onChange(newCustomConfig) + } + + return ( + + + + + {type === 'preset' && ( + + + + {value.tension} + + + + {value.friction} + + + + + + + )} + + {property.help} + + ) + } +) + +const Row = styled.div` + display: grid; + grid-template-columns: 1fr; + grid-row-gap: 9px; +` + +const CustomControls = styled.div` + display: grid; + grid-template-columns: 50px 25px auto 50px 25px auto; + align-items: center; + column-gap: 9px; + row-gap: 9px; + margin-bottom: 9px; +` diff --git a/website/src/components/controls/NumberArrayControl.tsx b/website/src/components/controls/NumberArrayControl.tsx index 00c4f4a5c6..603b162224 100644 --- a/website/src/components/controls/NumberArrayControl.tsx +++ b/website/src/components/controls/NumberArrayControl.tsx @@ -1,4 +1,4 @@ -import React, { ChangeEvent, Fragment, ReactNode, useCallback } from 'react' +import React, { ChangeEvent, Fragment, useCallback } from 'react' import styled from 'styled-components' import { ChartProperty, Flavor } from '../../types' import { Control } from './Control' @@ -6,23 +6,17 @@ import { PropertyHeader } from './PropertyHeader' import { Label } from './Label' import { TextInput } from './TextInput' import { Help } from './Help' +import { NumberArrayControlConfig } from './types' interface NumberArrayControlProps { id: string property: ChartProperty flavors: Flavor[] currentFlavor: Flavor - options: { - unit: 'px' | '°' - items: { - label: ReactNode - min: number - max: number - step?: number - }[] - } + config: NumberArrayControlConfig value: number[] onChange: (value: number[]) => void + context?: any } export const NumberArrayControl = ({ @@ -30,7 +24,7 @@ export const NumberArrayControl = ({ property, flavors, currentFlavor, - options: { unit, items }, + config: { unit, items }, value, onChange, }: NumberArrayControlProps) => { diff --git a/website/src/components/controls/ObjectControl.tsx b/website/src/components/controls/ObjectControl.tsx index 20f6aa605b..501e8335ab 100644 --- a/website/src/components/controls/ObjectControl.tsx +++ b/website/src/components/controls/ObjectControl.tsx @@ -4,39 +4,43 @@ import ControlsGroup from './ControlsGroup' import { PropertyHeader } from './PropertyHeader' import { Cell, Toggle } from './styled' import { Help } from './Help' +import { ChartProperty, Flavor } from '../../types' +import { ObjectControlConfig } from './types' interface ObjectControlProps { - /* - property: PropTypes.object.isRequired, - flavors: PropTypes.arrayOf(PropTypes.oneOf(['svg', 'html', 'canvas', 'api'])).isRequired, - currentFlavor: PropTypes.oneOf(['svg', 'html', 'canvas', 'api']).isRequired, - onChange: PropTypes.func.isRequired, - value: PropTypes.object.isRequired, - props: PropTypes.array.isRequired, - isOpenedByDefault: PropTypes.bool, - */ + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + onChange: (value: object) => void + value: object + isOpenedByDefault?: boolean + config: ObjectControlConfig + context: any } -const ObjectControl = memo( +export const ObjectControl = memo( ({ property, + config, flavors, currentFlavor, value, - props, onChange, context, isOpenedByDefault = false, - }) => { + }: ObjectControlProps) => { const [isOpened, setIsOpened] = useState(isOpenedByDefault) const toggle = useCallback(() => setIsOpened(flag => !flag), [setIsOpened]) - const subProps = useMemo(() => - props.map(prop => ({ - ...prop, - name: prop.key, - group: property.group, - })) + const subProps = useMemo( + () => + config.props.map(prop => ({ + ...prop, + name: prop.key, + group: property.group, + })), + [config.props] ) const newContext = { @@ -58,7 +62,6 @@ const ObjectControl = memo( controls={subProps} settings={value} onChange={onChange} - isNested={true} context={newContext} /> )} @@ -67,15 +70,15 @@ const ObjectControl = memo( } ) -export default ObjectControl - const Title = styled.div` white-space: nowrap; font-weight: 600; color: ${({ theme }) => theme.colors.accentLight}; ` -const Header = styled(Cell)` +const Header = styled(Cell)<{ + isOpened: boolean +}>` cursor: pointer; border-bottom: 1px solid ${({ theme }) => theme.colors.borderLight}; diff --git a/website/src/components/controls/OpacityControl.tsx b/website/src/components/controls/OpacityControl.tsx index dac5eb562e..b5fff36a9d 100644 --- a/website/src/components/controls/OpacityControl.tsx +++ b/website/src/components/controls/OpacityControl.tsx @@ -4,18 +4,22 @@ import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { TextInput } from './TextInput' import { Help } from './Help' +// @ts-ignore import { useTheme } from '../../theming/context' -import { Flavor, OpacityChartProperty } from '../../types' +import { Flavor, ChartProperty } from '../../types' +import { OpacityControlConfig } from './types' const size = 24 interface OpacityControlProps { id: string - property: OpacityChartProperty + property: ChartProperty flavors: Flavor[] currentFlavor: Flavor + config: OpacityControlConfig value: number onChange: (value: number) => void + context?: any } export const OpacityControl = ({ diff --git a/website/src/components/controls/OrdinalColorsControl.tsx b/website/src/components/controls/OrdinalColorsControl.tsx index 870b8e2ca4..3b2f768718 100644 --- a/website/src/components/controls/OrdinalColorsControl.tsx +++ b/website/src/components/controls/OrdinalColorsControl.tsx @@ -6,21 +6,24 @@ import { isDivergingColorScheme, isSequentialColorScheme, } from '@nivo/colors' +// @ts-ignore import { components } from 'react-select' import { ColorsControlItem } from './ColorsControlItem' import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { Help } from './Help' import Select from './Select' +import { ChartProperty, Flavor } from '../../types' +import { OrdinalColorsControlConfig } from './types' const options = colorSchemeIds.map(scheme => { let colors: string[] = [] if (isCategoricalColorScheme(scheme)) { - colors = colorSchemes[scheme] + colors = colorSchemes[scheme] as string[] } else if (isDivergingColorScheme(scheme)) { - colors = colorSchemes[scheme][11] + colors = colorSchemes[scheme][11] as string[] } else if (isSequentialColorScheme(scheme)) { - colors = colorSchemes[scheme][9] + colors = colorSchemes[scheme][9] as string[] } return { @@ -30,7 +33,7 @@ const options = colorSchemeIds.map(scheme => { } }) -const SingleValue = props => { +const SingleValue = (props: any) => { return ( @@ -38,7 +41,7 @@ const SingleValue = props => { ) } -const Option = props => { +const Option = (props: any) => { return ( @@ -47,20 +50,24 @@ const Option = props => { } interface OrdinalColorsControlProps { - /* - id: PropTypes.string.isRequired, - property: PropTypes.object.isRequired, - flavors: PropTypes.arrayOf(PropTypes.oneOf(['svg', 'html', 'canvas', 'api'])).isRequired, - currentFlavor: PropTypes.oneOf(['svg', 'html', 'canvas', 'api']).isRequired, - onChange: PropTypes.func.isRequired, - value: PropTypes.object.isRequired, - options: PropTypes.shape({ - includeSequential: PropTypes.bool, - }).isRequired, - */ + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + config: OrdinalColorsControlConfig + value: { scheme: string } + onChange: (value: { scheme: string }) => void + context?: any } -const OrdinalColorsControl = ({ id, property, flavors, currentFlavor, value, onChange }) => { +export const OrdinalColorsControl = ({ + id, + property, + flavors, + currentFlavor, + value, + onChange, +}: OrdinalColorsControlProps) => { const selectedOption = options.find(o => o.value === value.scheme) const handleChange = useCallback( option => { @@ -99,5 +106,3 @@ const OrdinalColorsControl = ({ id, property, flavors, currentFlavor, value, onC ) } - -export default OrdinalColorsControl diff --git a/website/src/components/controls/PropertyFlavors.tsx b/website/src/components/controls/PropertyFlavors.tsx index 6cdfd8ca94..a52228cb09 100644 --- a/website/src/components/controls/PropertyFlavors.tsx +++ b/website/src/components/controls/PropertyFlavors.tsx @@ -40,6 +40,7 @@ const Flavor = styled.span<{ isSupported: boolean }>` padding: 3px 8px 5px; border: 1px solid ${({ theme }) => theme.colors.border}; border-right-width: 0; + text-decoration: ${({ isSupported }) => (isSupported ? 'normal' : 'line-through')}; color: ${({ isSupported, theme }) => isSupported ? theme.colors.text : theme.colors.textLight}; diff --git a/website/src/components/controls/PropertyHeader.tsx b/website/src/components/controls/PropertyHeader.tsx index feade7d3da..5e478f7078 100644 --- a/website/src/components/controls/PropertyHeader.tsx +++ b/website/src/components/controls/PropertyHeader.tsx @@ -35,7 +35,8 @@ const getDefaultValue = (value: any) => { } type PropertyHeaderProps = ChartProperty & { - id: string + id?: string + name?: string context?: any } diff --git a/website/src/components/controls/QuantizeColorsControl.tsx b/website/src/components/controls/QuantizeColorsControl.tsx index 08977af873..be83391667 100644 --- a/website/src/components/controls/QuantizeColorsControl.tsx +++ b/website/src/components/controls/QuantizeColorsControl.tsx @@ -1,10 +1,13 @@ import React, { useCallback } from 'react' +// @ts-ignore import { quantizeColorScales } from '@nivo/core' import Select from './Select' import { ColorsControlItem } from './ColorsControlItem' import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { Help } from './Help' +import { ChartProperty, Flavor } from '../../types' +import { QuantizeColorsControlConfig } from './types' const options = Object.keys(quantizeColorScales).map(id => ({ id, @@ -13,16 +16,20 @@ const options = Object.keys(quantizeColorScales).map(id => ({ interface QuantizeColorsControlProps { id: string - property: any - onChange: any + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + config: QuantizeColorsControlConfig + onChange: (value: string) => void value: string + context?: any } -const renderOption = option => { +const renderOption = (option: { value: string; colors: string[] }) => { return } -const renderValue = value => { +const renderValue = (value: { value: string; colors: string[] }) => { return (
@@ -38,7 +45,7 @@ const renderValue = value => { ) } -const QuantizeColorsControl = ({ +export const QuantizeColorsControl = ({ id, property, flavors, @@ -47,7 +54,7 @@ const QuantizeColorsControl = ({ onChange, }: QuantizeColorsControlProps) => { const handleColorsChange = useCallback( - value => { + (value: { value: string }) => { onChange(value.value) }, [onChange] @@ -78,5 +85,3 @@ const QuantizeColorsControl = ({ ) } - -export default QuantizeColorsControl diff --git a/website/src/components/controls/RadioControl.tsx b/website/src/components/controls/RadioControl.tsx index 8dd899b51b..a2dcfaf0c9 100644 --- a/website/src/components/controls/RadioControl.tsx +++ b/website/src/components/controls/RadioControl.tsx @@ -3,42 +3,36 @@ import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { Help } from './Help' import { Radio } from './Radio' +import { ChartProperty, Flavor } from '../../types' +import { RadioControlConfig } from './types' interface RadioControlProps { - /* - id: PropTypes.string.isRequired, - property: PropTypes.object.isRequired, - flavors: PropTypes.arrayOf(PropTypes.oneOf(['svg', 'html', 'canvas', 'api'])).isRequired, - currentFlavor: PropTypes.oneOf(['svg', 'html', 'canvas', 'api']).isRequired, - value: PropTypes.string.isRequired, - options: PropTypes.shape({ - choices: PropTypes.arrayOf( - PropTypes.shape({ - value: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - }) - ).isRequired, - }).isRequired, - onChange: PropTypes.func.isRequired, - */ + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + value: string + config: RadioControlConfig + onChange: (value: string) => void + context?: any } -const RadioControl = memo(({ id, property, flavors, currentFlavor, options, value, onChange }) => { - const handleUpdate = useCallback(event => onChange(event.target.value), [onChange]) +export const RadioControl = memo( + ({ id, property, flavors, currentFlavor, config, value, onChange }: RadioControlProps) => { + const handleUpdate = useCallback(event => onChange(event.target.value), [onChange]) - return ( - - - - {property.help} - - ) -}) - -export default RadioControl + return ( + + + + {property.help} + + ) + } +) diff --git a/website/src/components/controls/RangeControl.tsx b/website/src/components/controls/RangeControl.tsx index fa7d3946e8..f32b84b0ad 100644 --- a/website/src/components/controls/RangeControl.tsx +++ b/website/src/components/controls/RangeControl.tsx @@ -6,6 +6,7 @@ import { TextInput } from './TextInput' import { PropertyHeader } from './PropertyHeader' import { Help } from './Help' import { Flavor } from '../../types' +import { RangeControlConfig } from './types' interface RangeControlProps { id: string @@ -14,16 +15,12 @@ interface RangeControlProps { currentFlavor: Flavor value: number onChange: (value: number) => void - options: { - unit: 'px' | '°' - min: number - max: number - step?: number - } + config: RangeControlConfig + context?: any } export const RangeControl = memo( - ({ id, property, flavors, currentFlavor, options, value, onChange }: RangeControlProps) => { + ({ id, property, flavors, currentFlavor, config, value, onChange }: RangeControlProps) => { const handleChange = useCallback(event => onChange(Number(event.target.value)), [onChange]) return ( @@ -39,7 +36,7 @@ export const RangeControl = memo( @@ -47,7 +44,7 @@ export const RangeControl = memo( type="range" value={value} onChange={handleChange} - {...pick(options, ['min', 'max', 'step'])} + {...pick(config, ['min', 'max', 'step'])} /> {property.help} diff --git a/website/src/components/controls/Select.js b/website/src/components/controls/Select.tsx similarity index 100% rename from website/src/components/controls/Select.js rename to website/src/components/controls/Select.tsx diff --git a/website/src/components/controls/SwitchableRangeControl.tsx b/website/src/components/controls/SwitchableRangeControl.tsx index fa0e7114e0..eec7a7001b 100644 --- a/website/src/components/controls/SwitchableRangeControl.tsx +++ b/website/src/components/controls/SwitchableRangeControl.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React, { useCallback, useState, ChangeEvent } from 'react' import styled from 'styled-components' import pick from 'lodash/pick' import { Control } from './Control' @@ -6,6 +6,8 @@ import { PropertyHeader } from './PropertyHeader' import { Help } from './Help' import { TextInput } from './TextInput' import { Switch } from './Switch' +import { SwitchableRangeControlConfig } from './types' +import { ChartProperty, Flavor } from '../../types' const SwitchRow = styled.div` display: flex; @@ -27,107 +29,87 @@ const RangeRow = styled.div` ` interface SwitchableRangeControlProps { - /* - id: PropTypes.string.isRequired, - property: PropTypes.object.isRequired, - flavors: PropTypes.arrayOf(PropTypes.oneOf(['svg', 'html', 'canvas', 'api'])).isRequired, - currentFlavor: PropTypes.oneOf(['svg', 'html', 'canvas', 'api']).isRequired, - value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - options: PropTypes.shape({ - unit: PropTypes.string, - defaultValue: PropTypes.number.isRequired, - disabledValue: PropTypes.any.isRequired, - min: PropTypes.number.isRequired, - max: PropTypes.number.isRequired, - step: PropTypes.number, - }).isRequired, - onChange: PropTypes.func.isRequired, - */ + id: string + property: ChartProperty + config: SwitchableRangeControlConfig + flavors: Flavor[] + currentFlavor: Flavor + value: number | string + onChange: (value: number | string) => void + context?: any } -export default class SwitchableRangeControl extends Component { - constructor(props) { - super(props) +export const SwitchableRangeControl = ({ + id, + property, + flavors, + currentFlavor, + value, + config, + onChange, +}: SwitchableRangeControlProps) => { + const [isSliderEnabled, setIsSliderEnabled] = useState(value !== config.disabledValue) + const [sliderValue, setSliderValue] = useState( + value === config.disabledValue ? config.defaultValue : value + ) - const { - value, - options: { disabledValue, defaultValue }, - } = this.props - this.state = { - isSliderEnabled: value !== disabledValue, - sliderValue: value === disabledValue ? defaultValue : value, - } - } - - handleSwitchUpdate = checked => { - const { - onChange, - options: { disabledValue }, - } = this.props - const { sliderValue } = this.state - if (checked === false) { - this.setState({ isSliderEnabled: true }) - onChange(Number(sliderValue)) - } else { - this.setState({ isSliderEnabled: false }) - onChange(disabledValue) - } - } + const handleSliderUpdate = useCallback( + (e: ChangeEvent) => { + setSliderValue(Number(e.target.value)) + onChange(Number(e.target.value)) + }, + [setSliderValue, onChange] + ) - handleSliderUpdate = e => { - const { onChange } = this.props - this.setState({ sliderValue: Number(e.target.value) }) - onChange(Number(e.target.value)) - } - - render() { - const { - id, - property, - flavors, - currentFlavor, - options: { disabledValue, unit }, - value, - } = this.props - const { isSliderEnabled, sliderValue } = this.state + const handleSwitchUpdate = useCallback( + (checked: boolean) => { + if (!checked) { + setIsSliderEnabled(true) + onChange(Number(sliderValue)) + } else { + setIsSliderEnabled(false) + onChange(config.disabledValue) + } + }, + [onChange, config.disabledValue, sliderValue, setIsSliderEnabled] + ) - return ( - - - - + + + + + {config.disabledValue} + + + {isSliderEnabled && ( + + + - - {disabledValue} - - - {isSliderEnabled && ( - - - - - )} - {property.help} - - ) - } + + )} + {property.help} + + ) } diff --git a/website/src/components/controls/TextControl.tsx b/website/src/components/controls/TextControl.tsx index 4eeecbe7dd..648d7ce34a 100644 --- a/website/src/components/controls/TextControl.tsx +++ b/website/src/components/controls/TextControl.tsx @@ -3,23 +3,22 @@ import { Control } from './Control' import { PropertyHeader } from './PropertyHeader' import { TextInput } from './TextInput' import { Help } from './Help' +import { ChartProperty, Flavor } from '../../types' +import { TextControlConfig } from './types' interface TextControlProps { - /* - id: PropTypes.string.isRequired, - property: PropTypes.object.isRequired, - flavors: PropTypes.arrayOf(PropTypes.oneOf(['svg', 'html', 'canvas', 'api'])).isRequired, - currentFlavor: PropTypes.oneOf(['svg', 'html', 'canvas', 'api']).isRequired, - value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - onChange: PropTypes.func.isRequired, - options: PropTypes.shape({ - disabled: PropTypes.bool, - }).isRequired, - */ + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + value: string | number + onChange: (value: string) => void + config: TextControlConfig + context?: any } -const TextControl = memo( - ({ id, property, flavors, currentFlavor, value, onChange, options = {} }) => { +export const TextControl = memo( + ({ id, property, flavors, currentFlavor, value, onChange, config = {} }: TextControlProps) => { const handleUpdate = useCallback(event => onChange(event.target.value), [onChange]) return ( @@ -36,12 +35,10 @@ const TextControl = memo( type="text" value={value} onChange={handleUpdate} - disabled={options.disabled === true} + disabled={config.disabled === true} /> {property.help} ) } ) - -export default TextControl diff --git a/website/src/components/controls/TextInput.tsx b/website/src/components/controls/TextInput.tsx index 16cd772c38..4d995c2f3a 100644 --- a/website/src/components/controls/TextInput.tsx +++ b/website/src/components/controls/TextInput.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components' type TextInputProps = { isNumber?: boolean - unit?: 'px' | '°' + unit?: 'px' | '°' | 'ms' } & InputHTMLAttributes export const TextInput = memo(({ unit, isNumber = false, ...props }: TextInputProps) => { diff --git a/website/src/components/controls/ValueFormatControl.js b/website/src/components/controls/ValueFormatControl.js deleted file mode 100644 index 88657239a8..0000000000 --- a/website/src/components/controls/ValueFormatControl.js +++ /dev/null @@ -1,374 +0,0 @@ -import React, { memo, useCallback, useMemo, useState } from 'react' -import styled from 'styled-components' -import { formatSpecifier as parseFormat, FormatSpecifier } from 'd3-format' -import { components } from 'react-select' -import { Control } from './Control' -import { PropertyHeader } from './PropertyHeader' -import { TextInput } from './TextInput' -import { Switch } from './Switch' -import Select from './Select' -import { Help } from './Help' -import { FaChevronUp, FaChevronDown } from 'react-icons/fa' - -const MainControls = styled.div` - display: grid; - grid-template-columns: 60px auto 100px; - align-items: center; - row-gap: 9px; - column-gap: 9px; - margin: 12px 0; -` - -const SubControls = styled.div` - display: grid; - grid-template-columns: 60px auto 60px auto; - align-items: center; - row-gap: 9px; - column-gap: 9px; - margin: 12px 0; -` - -const ToggleButton = styled.span` - cursor: pointer; - display: grid; - grid-template-columns: auto 24px; - grid-column-gap: 9px; - align-items: center; - white-space: nowrap; - color: ${props => props.theme.colors.accent}; - - path { - fill: ${props => props.theme.colors.border}; - } -` - -const typeOptions = [ - { - value: undefined, - label: 'none', - description: 'none', - }, - { - value: 'e', - label: 'e', - description: 'exponent notation.', - }, - { - value: 'f', - label: 'f', - description: 'fixed point notation.', - }, - { - value: 'g', - label: 'g', - description: 'either decimal or exponent notation, rounded to significant digits.', - }, - { - value: 'r', - label: 'r', - description: 'decimal notation, rounded to significant digits.', - }, - { - value: 's', - label: 's', - description: 'decimal notation with an SI prefix, rounded to significant digits.', - }, - { - value: '%', - label: '%', - description: 'multiply by 100, and then decimal notation with a percent sign.', - }, - { - value: 'p', - label: 'p', - description: - 'multiply by 100, round to significant digits, and then decimal notation with a percent sign.', - }, - { - value: 'b', - label: 'b', - description: 'binary notation, rounded to integer.', - }, - { - value: 'o', - label: 'o', - description: 'octal notation, rounded to integer.', - }, - { - value: 'd', - label: 'd', - description: 'decimal notation, rounded to integer.', - }, - { - value: 'x', - label: 'x', - description: 'hexadecimal notation, using lower-case letters, rounded to integer.', - }, - { - value: 'X', - label: 'X', - description: 'hexadecimal notation, using upper-case letters, rounded to integer.', - }, - { - value: 'c', - label: 'c', - description: 'converts the integer to the corresponding unicode character before printing.', - }, -] - -const alignOptions = [ - { - value: '>', - label: '>', - description: 'Force the field to be right-aligned within the available space.', - }, - { - value: '<', - label: '<', - description: 'Force the field to be left-aligned within the available space.', - }, - { - value: '^', - label: '^', - description: 'Force the field to be centered within the available space.', - }, - { - value: '=', - label: '=', - description: 'like >, but with any sign and symbol to the left of any padding.', - }, -] - -const signOptions = [ - { - value: '-', - label: '-', - description: 'nothing for zero or positive and a minus sign for negative.', - }, - { - value: '+', - label: '+', - description: 'a plus sign for zero or positive and a minus sign for negative.', - }, - { - value: '(', - label: '(', - description: 'nothing for zero or positive and parentheses for negative.', - }, - { - value: ' ', - label: '(space)', - description: 'a space for zero or positive and a minus sign for negative.', - }, -] - -const symbolOptions = [ - { - value: undefined, - label: 'none', - }, - { - value: '#', - label: '#', - }, - { - value: '$', - label: '$', - }, -] - -const Option = props => ( - - {props.value === undefined && 'none'} - {props.value !== undefined && ( - <> - {props.label} {props.data.description} - - )} - -) - -const ValueFormatControl = memo(({ id, property, flavors, currentFlavor, value, onChange }) => { - const [isEditing, setIsEditing] = useState(false) - const formatSpecifier = useMemo(() => parseFormat(value.format), [value.format]) - - const handleSwitch = useCallback( - enabled => { - onChange({ - format: formatSpecifier.toString(), - enabled, - }) - }, - [formatSpecifier, onChange] - ) - - const updateFormat = useCallback( - (property, propertyValue) => { - const updatedFormatSpecifier = new FormatSpecifier({ - ...formatSpecifier, - [property]: propertyValue, - }) - - onChange({ - format: updatedFormatSpecifier.toString(), - enabled: value.enabled, - }) - }, - [formatSpecifier, onChange, value.enabled] - ) - - const handleTypeChange = option => { - updateFormat('type', option.value) - } - - const handleFillChange = e => { - updateFormat('fill', e.target.value.slice(1)) - } - - const handleAlignChange = option => { - updateFormat('align', option.value) - } - - const handleSignChange = option => { - updateFormat('sign', option.value) - } - - const handleSymbolChange = option => { - updateFormat('symbol', option.value) - } - - const handleZeroChange = flag => { - updateFormat('zero', flag) - } - - const handleWidthChange = e => { - updateFormat('width', e.target.value) - } - - const handleCommaChange = flag => { - updateFormat('comma', flag) - } - - const handlePrecisionChange = e => { - updateFormat('precision', e.target.value) - } - - const handleTrimChange = flag => { - updateFormat('trim', flag) - } - - return ( - - - - - - - - - setIsEditing(flag => !flag)}> - {isEditing ? 'close' : 'open'} editor - {isEditing ? : } - - - {isEditing && ( - - - option.value === formatSpecifier.sign)} - clearable={false} - onChange={handleSignChange} - components={{ Option }} - /> - - - option.value === formatSpecifier.align)} - clearable={false} - onChange={handleAlignChange} - components={{ Option }} - /> - - - - - - - - - - - )} - {property.help} - - ) -}) - -ValueFormatControl.displayName = 'ValueFormatControl' - -export default ValueFormatControl diff --git a/website/src/components/controls/ValueFormatControl.tsx b/website/src/components/controls/ValueFormatControl.tsx new file mode 100644 index 0000000000..3ec4731f93 --- /dev/null +++ b/website/src/components/controls/ValueFormatControl.tsx @@ -0,0 +1,392 @@ +import React, { memo, useCallback, useMemo, useState } from 'react' +import styled from 'styled-components' +import { formatSpecifier as parseFormat, FormatSpecifier } from 'd3-format' +// @ts-ignore +import { components } from 'react-select' +import { Control } from './Control' +import { PropertyHeader } from './PropertyHeader' +import { TextInput } from './TextInput' +import { Switch } from './Switch' +import Select from './Select' +import { Help } from './Help' +import { FaChevronUp, FaChevronDown } from 'react-icons/fa' +import { ChartProperty, Flavor } from '../../types' +import { ValueFormatControlConfig } from './types' + +const typeOptions = [ + { + value: undefined, + label: 'none', + description: 'none', + }, + { + value: 'e', + label: 'e', + description: 'exponent notation.', + }, + { + value: 'f', + label: 'f', + description: 'fixed point notation.', + }, + { + value: 'g', + label: 'g', + description: 'either decimal or exponent notation, rounded to significant digits.', + }, + { + value: 'r', + label: 'r', + description: 'decimal notation, rounded to significant digits.', + }, + { + value: 's', + label: 's', + description: 'decimal notation with an SI prefix, rounded to significant digits.', + }, + { + value: '%', + label: '%', + description: 'multiply by 100, and then decimal notation with a percent sign.', + }, + { + value: 'p', + label: 'p', + description: + 'multiply by 100, round to significant digits, and then decimal notation with a percent sign.', + }, + { + value: 'b', + label: 'b', + description: 'binary notation, rounded to integer.', + }, + { + value: 'o', + label: 'o', + description: 'octal notation, rounded to integer.', + }, + { + value: 'd', + label: 'd', + description: 'decimal notation, rounded to integer.', + }, + { + value: 'x', + label: 'x', + description: 'hexadecimal notation, using lower-case letters, rounded to integer.', + }, + { + value: 'X', + label: 'X', + description: 'hexadecimal notation, using upper-case letters, rounded to integer.', + }, + { + value: 'c', + label: 'c', + description: 'converts the integer to the corresponding unicode character before printing.', + }, +] + +const alignOptions = [ + { + value: '>', + label: '>', + description: 'Force the field to be right-aligned within the available space.', + }, + { + value: '<', + label: '<', + description: 'Force the field to be left-aligned within the available space.', + }, + { + value: '^', + label: '^', + description: 'Force the field to be centered within the available space.', + }, + { + value: '=', + label: '=', + description: 'like >, but with any sign and symbol to the left of any padding.', + }, +] + +const signOptions = [ + { + value: '-', + label: '-', + description: 'nothing for zero or positive and a minus sign for negative.', + }, + { + value: '+', + label: '+', + description: 'a plus sign for zero or positive and a minus sign for negative.', + }, + { + value: '(', + label: '(', + description: 'nothing for zero or positive and parentheses for negative.', + }, + { + value: ' ', + label: '(space)', + description: 'a space for zero or positive and a minus sign for negative.', + }, +] + +const symbolOptions = [ + { + value: undefined, + label: 'none', + }, + { + value: '#', + label: '#', + }, + { + value: '$', + label: '$', + }, +] + +const Option = (props: any) => ( + + {props.value === undefined && 'none'} + {props.value !== undefined && ( + <> + {props.label} {props.data.description} + + )} + +) + +interface ValueFormatControlProps { + id: string + property: ChartProperty + flavors: Flavor[] + currentFlavor: Flavor + config: ValueFormatControlConfig + value: { format: string; enabled: boolean } + onChange: (value: { format: string; enabled: boolean }) => void + context?: any +} + +export const ValueFormatControl = memo( + ({ id, property, flavors, currentFlavor, value, onChange }: ValueFormatControlProps) => { + const [isEditing, setIsEditing] = useState(false) + const formatSpecifier = useMemo(() => parseFormat(value.format), [value.format]) + + const handleSwitch = useCallback( + enabled => { + onChange({ + format: formatSpecifier.toString(), + enabled, + }) + }, + [formatSpecifier, onChange] + ) + + const updateFormat = useCallback( + (property, propertyValue) => { + const updatedFormatSpecifier = new FormatSpecifier({ + ...formatSpecifier, + [property]: propertyValue, + }) + + onChange({ + format: updatedFormatSpecifier.toString(), + enabled: value.enabled, + }) + }, + [formatSpecifier, onChange, value.enabled] + ) + + const handleTypeChange = option => { + updateFormat('type', option.value) + } + + const handleFillChange = e => { + updateFormat('fill', e.target.value.slice(1)) + } + + const handleAlignChange = option => { + updateFormat('align', option.value) + } + + const handleSignChange = option => { + updateFormat('sign', option.value) + } + + const handleSymbolChange = option => { + updateFormat('symbol', option.value) + } + + const handleZeroChange = flag => { + updateFormat('zero', flag) + } + + const handleWidthChange = e => { + updateFormat('width', e.target.value) + } + + const handleCommaChange = flag => { + updateFormat('comma', flag) + } + + const handlePrecisionChange = e => { + updateFormat('precision', e.target.value) + } + + const handleTrimChange = flag => { + updateFormat('trim', flag) + } + + return ( + + + + + + + + + setIsEditing(flag => !flag)}> + {isEditing ? 'close' : 'open'} editor + {isEditing ? : } + + + {isEditing && ( + + + option.value === formatSpecifier.sign + )} + clearable={false} + onChange={handleSignChange} + components={{ Option }} + /> + + + option.value === formatSpecifier.align + )} + clearable={false} + onChange={handleAlignChange} + components={{ Option }} + /> + + + + + + + + + + + )} + {property.help} + + ) + } +) + +const MainControls = styled.div` + display: grid; + grid-template-columns: 60px auto 100px; + align-items: center; + row-gap: 9px; + column-gap: 9px; + margin: 12px 0; +` + +const SubControls = styled.div` + display: grid; + grid-template-columns: 60px auto 60px auto; + align-items: center; + row-gap: 9px; + column-gap: 9px; + margin: 12px 0; +` + +const ToggleButton = styled.span` + cursor: pointer; + display: grid; + grid-template-columns: auto 24px; + grid-column-gap: 9px; + align-items: center; + white-space: nowrap; + color: ${props => props.theme.colors.accent}; + + path { + fill: ${props => props.theme.colors.border}; + } +` diff --git a/website/src/components/controls/types.ts b/website/src/components/controls/types.ts new file mode 100644 index 0000000000..fa0a2a77c3 --- /dev/null +++ b/website/src/components/controls/types.ts @@ -0,0 +1,158 @@ +import { ChartProperty } from '../../types' + +export interface SwitchControlAttrs { + type: 'switch' +} + +export interface RangeControlConfig { + type: 'range' + min: number + max: number + step?: number + unit?: 'px' | '°' | 'ms' +} + +export interface MotionConfigControlConfig { + type: 'motionConfig' +} + +export interface BoxAnchorControlConfig { + type: 'boxAnchor' +} + +export interface ChoicesControlConfig { + type: 'choices' + disabled?: boolean + choices: { + label: string + value: string | boolean + }[] +} + +export interface RadioControlConfig { + type: 'radio' + choices: { + label: string + value: string + }[] +} + +export interface ValueFormatControlConfig { + type: 'valueFormat' +} + +export interface MarginControlConfig { + type: 'margin' +} + +export interface OpacityControlConfig { + type: 'opacity' +} + +export interface LineWidthControlConfig { + type: 'lineWidth' + step?: number +} + +export interface BlendModeControlConfig { + type: 'blendMode' +} + +export interface InheritedColorControlConfig { + type: 'inheritedColor' + inheritableProperties?: string[] + defaultCustomColor?: string + defaultThemeProperty?: string + defaultFrom?: string +} + +export interface OrdinalColorsControlConfig { + type: 'ordinalColors' +} + +export interface NumberArrayControlConfig { + type: 'numberArray' + unit?: 'px' | '°' | 'ms' + items: { + label: string + min?: number + max?: number + step?: number + }[] +} + +export interface ColorPickerControlConfig { + type: 'colorPicker' +} + +export interface QuantizeColorsControlConfig { + type: 'quantizeColors' +} + +export interface SwitchableRangeControlConfig { + type: 'switchableRange' + unit?: 'px' | '°' | 'ms' + disabledValue: string + defaultValue: number + min: number + max: number + step?: number +} + +export interface AngleControlConfig { + type: 'angle' + start?: number + min?: number + max?: number + step?: number +} + +export interface ObjectControlConfig { + type: 'object' + props: Omit[] +} + +export interface ArrayControlConfig { + type: 'array' + props: Omit[] + shouldCreate: boolean + addLabel?: string + shouldRemove: boolean + removeLabel?: string + defaults?: object + getItemTitle?: (index: number, item: unknown) => string +} + +export interface TextControlConfig { + type: 'text' + disabled?: boolean +} + +export interface ColorsControlConfig { + type: 'colors' + includeSequential?: boolean +} + +export type ControlConfig = + | SwitchControlAttrs + | RangeControlConfig + | MotionConfigControlConfig + | BoxAnchorControlConfig + | ChoicesControlConfig + | RadioControlConfig + | ValueFormatControlConfig + | MarginControlConfig + | OpacityControlConfig + | LineWidthControlConfig + | BlendModeControlConfig + | InheritedColorControlConfig + | OrdinalColorsControlConfig + | NumberArrayControlConfig + | ColorPickerControlConfig + | QuantizeColorsControlConfig + | SwitchableRangeControlConfig + | AngleControlConfig + | ObjectControlConfig + | ArrayControlConfig + | TextControlConfig + | ColorsControlConfig diff --git a/website/src/data/components/area-bump/props.ts b/website/src/data/components/area-bump/props.ts index 8d1ca6b932..c9d3533337 100644 --- a/website/src/data/components/area-bump/props.ts +++ b/website/src/data/components/area-bump/props.ts @@ -1,12 +1,22 @@ +// @ts-ignore import { AreaBumpDefaultProps as defaults } from '@nivo/bump' import { themeProperty, - axesProperties, defsProperties, groupProperties, motionProperties, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { + chartDimensions, + ordinalColors, + blendMode, + chartGrid, + axes, + isInteractive, +} from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg'] const props: ChartProperty[] = [ { @@ -31,57 +41,7 @@ const props: ChartProperty[] = [ type: 'object[]', flavors: ['svg'], }, - { - key: 'width', - group: 'Base', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using responsive component. - Also note that width does not include labels/axes, - so you should add enough margin to display them. - `, - type: 'number', - required: true, - flavors: ['svg'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - group: 'Base', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using responsive component. - Also note that height does not include labels/axes, - so you should add enough margin to display them. - `, - type: 'number', - required: true, - flavors: ['svg'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'margin', - group: 'Base', - type: 'object', - required: false, - help: 'Chart margin.', - flavors: ['svg'], - controlType: 'margin', - }, + ...chartDimensions(allFlavors), { key: 'align', group: 'Base', @@ -90,8 +50,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.align, flavors: ['svg'], - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: [ { label: 'start', value: 'start' }, { label: 'middle', value: 'middle' }, @@ -107,8 +67,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.interpolation, flavors: ['svg'], - controlType: 'radio', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'smooth', value: 'smooth' }, { label: 'linear', value: 'linear' }, @@ -119,53 +79,38 @@ const props: ChartProperty[] = [ key: 'spacing', group: 'Base', type: 'number', + help: 'Spacing.', required: false, flavors: ['svg'], defaultValue: defaults.spacing, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 32, }, }, { key: 'xPadding', + help: 'X padding.', group: 'Base', type: 'number', + required: false, defaultValue: defaults.xPadding, flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 1, step: 0.05, }, }, themeProperty(['svg']), - { - key: 'colors', - group: 'Style', - type: 'string | Function | string[]', - help: 'Defines color range.', - required: false, - defaultValue: defaults.colors, + ordinalColors({ flavors: allFlavors, defaultValue: defaults.colors }), + blendMode({ + target: 'areas', flavors: ['svg'], - controlType: 'ordinalColors', - }, - { - key: 'blendMode', - group: 'Style', - type: 'string', - help: 'Defines CSS mix-blend-mode property.', - description: ` - Defines CSS \`mix-blend-mode\` property, see - [MDN documentation](https://developer.mozilla.org/fr/docs/Web/CSS/mix-blend-mode). - `, - required: false, defaultValue: defaults.blendMode, - flavors: ['svg'], - controlType: 'blendMode', - }, + }), { key: 'fillOpacity', group: 'Style', @@ -174,7 +119,7 @@ const props: ChartProperty[] = [ help: 'Area fill opacity.', defaultValue: defaults.fillOpacity, flavors: ['svg'], - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'activeFillOpacity', @@ -184,7 +129,7 @@ const props: ChartProperty[] = [ help: 'Area fill opacity for active series.', defaultValue: defaults.activeFillOpacity, flavors: ['svg'], - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'inactiveFillOpacity', @@ -194,7 +139,7 @@ const props: ChartProperty[] = [ help: 'Area fill opacity for inactive series.', defaultValue: defaults.inactiveFillOpacity, flavors: ['svg'], - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'borderWidth', @@ -204,7 +149,7 @@ const props: ChartProperty[] = [ help: 'Area border width.', defaultValue: defaults.borderWidth, flavors: ['svg'], - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'activeBorderWidth', @@ -214,7 +159,7 @@ const props: ChartProperty[] = [ help: 'Area border width for active series.', defaultValue: defaults.activeBorderWidth, flavors: ['svg'], - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'inactiveBorderWidth', @@ -224,7 +169,7 @@ const props: ChartProperty[] = [ help: 'Area border width for inactive series.', defaultValue: defaults.inactiveBorderWidth, flavors: ['svg'], - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'borderColor', @@ -234,7 +179,7 @@ const props: ChartProperty[] = [ help: 'Method to compute area border color.', defaultValue: defaults.borderColor, flavors: ['svg'], - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'borderOpacity', @@ -244,7 +189,7 @@ const props: ChartProperty[] = [ help: 'Area border opacity.', flavors: ['svg'], defaultValue: defaults.borderOpacity, - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'activeBorderOpacity', @@ -254,7 +199,7 @@ const props: ChartProperty[] = [ help: 'Area border opacity for active series.', defaultValue: defaults.activeBorderOpacity, flavors: ['svg'], - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'inactiveBorderOpacity', @@ -264,7 +209,7 @@ const props: ChartProperty[] = [ help: 'Area border opacity for inactive series.', defaultValue: defaults.inactiveBorderOpacity, flavors: ['svg'], - controlType: 'opacity', + control: { type: 'opacity' }, }, ...defsProperties('Style', ['svg']), { @@ -284,8 +229,8 @@ const props: ChartProperty[] = [ help: 'Define area start label padding', defaultValue: defaults.startLabelPadding, flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 30, }, @@ -298,7 +243,7 @@ const props: ChartProperty[] = [ help: 'Method to compute start label text color.', flavors: ['svg'], defaultValue: defaults.startLabelTextColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'endLabel', @@ -317,8 +262,8 @@ const props: ChartProperty[] = [ help: 'Define area end label padding', defaultValue: defaults.endLabelPadding, flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 30, }, @@ -329,31 +274,20 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, defaultValue: defaults.endLabelTextColor, - controlType: 'inheritedColor', group: 'Labels', flavors: ['svg'], + control: { type: 'inheritedColor' }, }, - { - key: 'enableGridX', - group: 'Grid & Axes', - help: 'Enable/disable x grid.', - type: 'boolean', - required: false, - defaultValue: defaults.enableGridX, - controlType: 'switch', + ...chartGrid({ + flavors: allFlavors, + xDefault: defaults.enableGridX, + y: false, + }), + ...axes({ flavors: allFlavors, exclude: ['right', 'left'] }), + isInteractive({ flavors: ['svg'], - }, - ...axesProperties({ exclude: ['right', 'left'] }), - { - key: 'isInteractive', - group: 'Interactivity', - type: 'boolean', - help: 'Enable/disable interactivity.', - required: false, defaultValue: defaults.isInteractive, - controlType: 'switch', - flavors: ['svg'], - }, + }), { key: 'onMouseEnter', group: 'Interactivity', diff --git a/website/src/data/components/bar/props.ts b/website/src/data/components/bar/props.ts index 433cb2dade..95723e20a7 100644 --- a/website/src/data/components/bar/props.ts +++ b/website/src/data/components/bar/props.ts @@ -1,24 +1,34 @@ import { svgDefaultProps } from '@nivo/bar' import { themeProperty, - axesProperties, motionProperties, defsProperties, getLegendsProps, groupProperties, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { + chartDimensions, + ordinalColors, + chartGrid, + axes, + isInteractive, +} from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'canvas', 'api'] const props: ChartProperty[] = [ { key: 'data', + group: 'Base', help: 'Chart data.', type: 'object[]', required: true, - group: 'Base', + flavors: allFlavors, }, { key: 'indexBy', + group: 'Base', help: 'Key to use to index the data.', description: ` Key to use to index the data, @@ -28,27 +38,29 @@ const props: ChartProperty[] = [ receive the data item and must return the desired index. `, type: 'string | (datum: RawDatum): string | number', + flavors: allFlavors, required: false, defaultValue: svgDefaultProps.indexBy, - group: 'Base', }, { key: 'keys', + group: 'Base', help: 'Keys to use to determine each serie.', type: 'string[]', + flavors: allFlavors, required: false, defaultValue: svgDefaultProps.keys, - group: 'Base', }, { key: 'groupMode', + group: 'Base', help: `How to group bars.`, - type: 'grouped | stacked', + type: `'grouped' | 'stacked'`, + flavors: allFlavors, required: false, defaultValue: svgDefaultProps.groupMode, - controlType: 'radio', - group: 'Base', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'stacked', value: 'stacked' }, { label: 'grouped', value: 'grouped' }, @@ -57,13 +69,14 @@ const props: ChartProperty[] = [ }, { key: 'layout', + group: 'Base', help: `How to display bars.`, - type: 'horizontal | vertical', + type: `'horizontal' | 'vertical'`, + flavors: allFlavors, required: false, defaultValue: svgDefaultProps.layout, - controlType: 'radio', - group: 'Base', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'horizontal', value: 'horizontal' }, { label: 'vertical', value: 'vertical' }, @@ -72,19 +85,23 @@ const props: ChartProperty[] = [ }, { key: 'valueScale', - type: 'object', group: 'Base', + type: 'object', help: `value scale configuration.`, defaultValue: svgDefaultProps.valueScale, - controlType: 'object', - controlOptions: { + flavors: allFlavors, + required: false, + control: { + type: 'object', props: [ { key: 'type', help: `Scale type.`, type: 'string', - controlType: 'choices', - controlOptions: { + required: true, + flavors: allFlavors, + control: { + type: 'choices', disabled: true, choices: ['linear', 'symlog'].map(v => ({ label: v, @@ -97,19 +114,23 @@ const props: ChartProperty[] = [ }, { key: 'indexScale', - type: 'object', group: 'Base', + type: 'object', help: `index scale configuration.`, defaultValue: svgDefaultProps.indexScale, - controlType: 'object', - controlOptions: { + flavors: allFlavors, + required: false, + control: { + type: 'object', props: [ { key: 'type', help: `Scale type.`, type: 'string', - controlType: 'choices', - controlOptions: { + required: true, + flavors: ['svg', 'canvas', 'api'], + control: { + type: 'choices', disabled: true, choices: ['band'].map(v => ({ label: v, @@ -119,35 +140,39 @@ const props: ChartProperty[] = [ }, { key: 'round', + required: true, + flavors: ['svg', 'canvas', 'api'], help: 'Toggle index scale (for bar width) rounding.', type: 'boolean', - controlType: 'switch', + control: { type: 'switch' }, }, ], }, }, { key: 'reverse', + group: 'Base', help: 'Reverse bars, starts on top instead of bottom for vertical layout and right instead of left for horizontal one.', type: 'boolean', required: false, + flavors: allFlavors, defaultValue: svgDefaultProps.reverse, - controlType: 'switch', - group: 'Base', + control: { type: 'switch' }, }, { key: 'minValue', + group: 'Base', help: 'Minimum value.', description: ` Minimum value, if 'auto', will use min value from the provided data. `, required: false, + flavors: allFlavors, defaultValue: svgDefaultProps.minValue, type: `number | 'auto'`, - controlType: 'switchableRange', - group: 'Base', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: -1000, min: -1000, @@ -156,17 +181,18 @@ const props: ChartProperty[] = [ }, { key: 'maxValue', + group: 'Base', help: 'Maximum value.', description: ` Maximum value, if 'auto', will use max value from the provided data. `, required: false, + flavors: allFlavors, defaultValue: svgDefaultProps.maxValue, type: `number | 'auto'`, - controlType: 'switchableRange', - group: 'Base', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 1000, min: 0, @@ -185,18 +211,20 @@ const props: ChartProperty[] = [ which will receive the raw value and should return the formatted one. `, required: false, + flavors: allFlavors, type: 'string | (value: number) => string | number', - controlType: 'valueFormat', + control: { type: 'valueFormat' }, }, { key: 'padding', help: 'Padding between each bar (ratio).', type: 'number', required: false, + flavors: allFlavors, defaultValue: svgDefaultProps.padding, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', min: 0, max: 0.9, step: 0.05, @@ -207,87 +235,22 @@ const props: ChartProperty[] = [ help: 'Padding between grouped/stacked bars.', type: 'number', required: false, + flavors: allFlavors, defaultValue: svgDefaultProps.innerPadding, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 10, }, }, - { - key: 'width', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using \`ResponsiveBar\`. - Also note that width exclude left/right axes, - please add margin to make sure they're visible. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using \`ResponsiveBar\`. - Also note that width exclude left/right axes, - please add margin to make sure they're visible. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, - themeProperty(['svg', 'canvas', 'api']), - { - key: 'colors', - help: 'Defines color range.', - type: 'string | Function | string[]', - required: false, + ...chartDimensions(allFlavors), + themeProperty(allFlavors), + ordinalColors({ + flavors: allFlavors, defaultValue: svgDefaultProps.colors, - controlType: 'ordinalColors', - group: 'Style', - }, + }), { key: 'colorBy', type: `'id' | 'indexValue'`, @@ -295,11 +258,12 @@ const props: ChartProperty[] = [ description: ` Property to use to determine node color. `, + flavors: allFlavors, required: false, defaultValue: svgDefaultProps.colorBy, - controlType: 'choices', group: 'Style', - controlOptions: { + control: { + type: 'choices', choices: [ { label: 'id', @@ -316,11 +280,12 @@ const props: ChartProperty[] = [ key: 'borderRadius', help: 'Rectangle border radius.', type: 'number', + flavors: ['svg', 'canvas', 'api'], required: false, defaultValue: svgDefaultProps.borderRadius, - controlType: 'range', group: 'Style', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 36, @@ -330,10 +295,11 @@ const props: ChartProperty[] = [ key: 'borderWidth', help: 'Width of bar border.', type: 'number', + flavors: ['svg', 'canvas', 'api'], required: false, defaultValue: svgDefaultProps.borderWidth, - controlType: 'lineWidth', group: 'Style', + control: { type: 'lineWidth' }, }, { key: 'borderColor', @@ -343,10 +309,11 @@ const props: ChartProperty[] = [ [see dedicated documentation](self:/guides/colors). `, type: 'string | object | Function', + flavors: ['svg', 'canvas', 'api'], required: false, defaultValue: svgDefaultProps.borderColor, - controlType: 'inheritedColor', group: 'Style', + control: { type: 'inheritedColor' }, }, ...defsProperties('Style', ['svg']), { @@ -373,10 +340,11 @@ const props: ChartProperty[] = [ key: 'enableLabel', help: 'Enable/disable labels.', type: 'boolean', + flavors: ['svg', 'canvas', 'api'], required: false, defaultValue: svgDefaultProps.enableLabel, - controlType: 'switch', group: 'Labels', + control: { type: 'switch' }, }, { key: 'label', @@ -403,6 +371,7 @@ const props: ChartProperty[] = [ \`\`\` `, type: 'string | Function', + flavors: ['svg', 'canvas', 'api'], required: false, defaultValue: svgDefaultProps.label, }, @@ -410,11 +379,12 @@ const props: ChartProperty[] = [ key: 'labelSkipWidth', help: 'Skip label if bar width is lower than provided value, ignored if 0.', type: 'number', + flavors: ['svg', 'canvas', 'api'], required: false, defaultValue: svgDefaultProps.labelSkipWidth, - controlType: 'range', group: 'Labels', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 36, @@ -424,11 +394,12 @@ const props: ChartProperty[] = [ key: 'labelSkipHeight', help: 'Skip label if bar height is lower than provided value, ignored if 0.', type: 'number', + flavors: ['svg', 'canvas', 'api'], required: false, defaultValue: svgDefaultProps.labelSkipHeight, - controlType: 'range', group: 'Labels', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 36, @@ -438,54 +409,23 @@ const props: ChartProperty[] = [ key: 'labelTextColor', help: 'Defines how to compute label text color.', type: 'string | object | Function', + flavors: ['svg', 'canvas', 'api'], required: false, defaultValue: svgDefaultProps.labelTextColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Labels', }, - { - key: 'enableGridX', - group: 'Grid & Axes', - help: 'Enable/disable x grid.', - type: 'boolean', - required: false, - defaultValue: svgDefaultProps.enableGridX, - controlType: 'switch', - }, - { - key: 'gridXValues', - group: 'Grid & Axes', - help: 'Specify values to use for vertical grid lines.', - type: 'Array', - required: false, - }, - { - key: 'enableGridY', - group: 'Grid & Axes', - help: 'Enable/disable y grid.', - type: 'boolean', - required: false, - defaultValue: svgDefaultProps.enableGridY, - controlType: 'switch', - }, - { - key: 'gridYValues', - group: 'Grid & Axes', - help: 'Specify values to use for horizontal grid lines.', - type: 'Array', - required: false, - }, - ...axesProperties(), - { - key: 'isInteractive', + ...chartGrid({ + flavors: allFlavors, + xDefault: svgDefaultProps.enableGridX, + yDefault: svgDefaultProps.enableGridY, + values: true, + }), + ...axes({ flavors: allFlavors }), + isInteractive({ flavors: ['svg', 'canvas'], - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: svgDefaultProps.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'tooltip', flavors: ['svg', 'canvas'], @@ -522,7 +462,8 @@ const props: ChartProperty[] = [ group: 'Interactivity', help: 'Showcase custom tooltip component.', type: 'boolean', - controlType: 'switch', + required: false, + control: { type: 'switch' }, }, { key: 'onClick', @@ -555,13 +496,14 @@ const props: ChartProperty[] = [ type: 'object[]', help: `Optional chart's legends.`, group: 'Legends', - controlType: 'array', - controlOptions: { + required: false, + control: { + type: 'array', props: getLegendsProps(['svg']), shouldCreate: true, addLabel: 'add legend', shouldRemove: true, - getItemTitle: (index, legend) => + getItemTitle: (index: number, legend: any) => `legend[${index}]: ${legend.anchor}, ${legend.direction}`, svgDefaultProps: { dataFrom: 'keys', @@ -575,8 +517,8 @@ const props: ChartProperty[] = [ itemsSpacing: 0, symbolSize: 20, itemDirection: 'left-to-right', - onClick: data => { - alert(JSON.stringify(data, null, ' ')) + onClick: (data: any) => { + console.log(JSON.stringify(data, null, ' ')) }, }, }, @@ -585,6 +527,7 @@ const props: ChartProperty[] = [ { key: 'isFocusable', flavors: ['svg'], + required: false, group: 'Accessibility', help: 'Make the root SVG element and each bar item focusable, for keyboard navigation.', description: ` @@ -595,11 +538,12 @@ const props: ChartProperty[] = [ at a fixed location. `, type: 'boolean', - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'ariaLabel', flavors: ['svg'], + required: false, group: 'Accessibility', help: 'Main element [aria-label](https://www.w3.org/TR/wai-aria/#aria-label).', type: 'string', @@ -607,6 +551,7 @@ const props: ChartProperty[] = [ { key: 'ariaLabelledBy', flavors: ['svg'], + required: false, group: 'Accessibility', help: 'Main element [aria-labelledby](https://www.w3.org/TR/wai-aria/#aria-labelledby).', type: 'string', @@ -614,6 +559,7 @@ const props: ChartProperty[] = [ { key: 'ariaDescribedBy', flavors: ['svg'], + required: false, group: 'Accessibility', help: 'Main element [aria-describedby](https://www.w3.org/TR/wai-aria/#aria-describedby).', type: 'string', @@ -621,6 +567,7 @@ const props: ChartProperty[] = [ { key: 'barAriaLabel', flavors: ['svg'], + required: false, group: 'Accessibility', help: '[aria-label](https://www.w3.org/TR/wai-aria/#aria-label) for bar items.', type: '(data) => string', @@ -628,6 +575,7 @@ const props: ChartProperty[] = [ { key: 'barAriaLabelledBy', flavors: ['svg'], + required: false, group: 'Accessibility', help: '[aria-labelledby](https://www.w3.org/TR/wai-aria/#aria-labelledby) for bar items.', type: '(data) => string', @@ -635,6 +583,7 @@ const props: ChartProperty[] = [ { key: 'barAriaDescribedBy', flavors: ['svg'], + required: false, group: 'Accessibility', help: '[aria-describedby](https://www.w3.org/TR/wai-aria/#aria-describedby) for bar items.', type: '(data) => string', diff --git a/website/src/data/components/bullet/props.ts b/website/src/data/components/bullet/props.ts index 7e487176bc..dcbd861f1d 100644 --- a/website/src/data/components/bullet/props.ts +++ b/website/src/data/components/bullet/props.ts @@ -1,12 +1,16 @@ import { defaultProps } from '@nivo/bullet' import { themeProperty, motionProperties, groupProperties } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', help: 'Chart data.', + flavors: ['svg'], description: ` Chart data, which must conform to this structure: \`\`\` @@ -31,6 +35,7 @@ const props: ChartProperty[] = [ { key: 'minValue', help: 'Minimum value.', + flavors: ['svg'], description: ` Minimum value, if 'auto', will use min value from @@ -39,9 +44,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaultProps.minValue, type: `number | 'auto'`, - controlType: 'switchableRange', group: 'Base', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 0, min: 0, @@ -51,6 +56,7 @@ const props: ChartProperty[] = [ { key: 'maxValue', help: 'Maximum value.', + flavors: ['svg'], description: ` Maximum value, if 'auto', will use max value from @@ -59,56 +65,26 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaultProps.maxValue, type: `number | 'auto'`, - controlType: 'switchableRange', group: 'Base', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 100, min: 50, max: 100, }, }, - { - key: 'width', - enableControlForFlavors: ['api'], - group: 'Base', - help: 'Chart width.', - description: 'not required if using `ResponsiveBullet`.', - type: 'number', - required: true, - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - group: 'Base', - help: 'Chart height.', - description: 'not required if using `ResponsiveBullet`.', - type: 'number', - required: true, - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, + ...chartDimensions(allFlavors), { key: 'layout', group: 'Base', help: `How to display items.`, + flavors: ['svg'], type: 'string', required: false, defaultValue: defaultProps.layout, - controlType: 'radio', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'horizontal', value: 'horizontal' }, { label: 'vertical', value: 'vertical' }, @@ -124,28 +100,22 @@ const props: ChartProperty[] = [ for vertical layout and right instead of left for horizontal one. `, + flavors: ['svg'], type: 'boolean', required: false, defaultValue: defaultProps.reverse, - controlType: 'switch', - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', + control: { type: 'switch' }, }, { key: 'spacing', help: 'define spacing between items.', type: 'number', + flavors: ['svg'], required: false, defaultValue: defaultProps.spacing, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 100, @@ -156,10 +126,11 @@ const props: ChartProperty[] = [ help: 'define size of measure related to item size, expressed as a ratio.', type: 'number', required: false, + flavors: ['svg'], defaultValue: defaultProps.measureSize, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', min: 0, max: 1, step: 0.05, @@ -170,10 +141,11 @@ const props: ChartProperty[] = [ help: 'define size of markers related to item size, expressed as a ratio.', type: 'number', required: false, + flavors: ['svg'], defaultValue: defaultProps.markerSize, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', min: 0, max: 2, step: 0.05, @@ -190,9 +162,9 @@ const props: ChartProperty[] = [ [see dedicated documentation](self:/guides/colors). `, type: 'string | object | Function', - controlType: 'inheritedColor', required: false, defaultValue: defaultProps.rangeBorderColor, + control: { type: 'inheritedColor' }, }, { key: 'rangeBorderWidth', @@ -200,9 +172,9 @@ const props: ChartProperty[] = [ group: 'Style', help: 'Width of range border.', type: 'number', - controlType: 'lineWidth', required: false, defaultValue: defaultProps.rangeBorderWidth, + control: { type: 'lineWidth' }, }, { key: 'rangeComponent', @@ -221,11 +193,12 @@ const props: ChartProperty[] = [ \`greens\` or sequential form: \`seq:green\`. `, type: 'string | Function | string[]', + flavors: ['svg'], required: false, defaultValue: defaultProps.rangeColors, - controlType: 'colors', group: 'Style', - controlOptions: { + control: { + type: 'colors', includeSequential: true, }, }, @@ -239,9 +212,9 @@ const props: ChartProperty[] = [ [see dedicated documentation](self:/guides/colors). `, type: 'string | object | Function', - controlType: 'inheritedColor', required: false, defaultValue: defaultProps.measureBorderColor, + control: { type: 'inheritedColor' }, }, { key: 'measureBorderWidth', @@ -249,9 +222,9 @@ const props: ChartProperty[] = [ group: 'Style', help: 'Width of measure border.', type: 'number', - controlType: 'lineWidth', required: false, defaultValue: defaultProps.measureBorderWidth, + control: { type: 'lineWidth' }, }, { key: 'measureComponent', @@ -271,10 +244,11 @@ const props: ChartProperty[] = [ `, type: 'string | Function | string[]', required: false, + flavors: ['svg'], defaultValue: defaultProps.measureColors, - controlType: 'colors', group: 'Style', - controlOptions: { + control: { + type: 'colors', includeSequential: true, }, }, @@ -288,6 +262,7 @@ const props: ChartProperty[] = [ }, { key: 'markerColors', + flavors: ['svg'], help: 'Markers colors.', description: ` Defines colors for markers, @@ -297,9 +272,9 @@ const props: ChartProperty[] = [ type: 'string | Function| string[]', required: false, defaultValue: defaultProps.markerColors, - controlType: 'colors', group: 'Style', - controlOptions: { + control: { + type: 'colors', includeSequential: true, }, }, @@ -309,9 +284,10 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: defaultProps.axisPosition, - controlType: 'radio', + flavors: ['svg'], group: 'Axes', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'before', value: 'before' }, { label: 'after', value: 'after' }, @@ -324,9 +300,10 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: defaultProps.titlePosition, - controlType: 'radio', + flavors: ['svg'], group: 'Title', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'before', value: 'before' }, { label: 'after', value: 'after' }, @@ -339,9 +316,10 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: defaultProps.titleAlign, - controlType: 'choices', + flavors: ['svg'], group: 'Title', - controlOptions: { + control: { + type: 'choices', choices: [ { label: 'start', value: 'start' }, { label: 'middle', value: 'middle' }, @@ -354,10 +332,11 @@ const props: ChartProperty[] = [ help: 'title x offset from bullet edge.', type: 'number', required: false, - defaultValue: defaultProps.titleOffset, - controlType: 'range', + defaultValue: defaultProps.titleOffsetX, + flavors: ['svg'], group: 'Title', - controlOptions: { + control: { + type: 'range', min: -100, max: 100, unit: 'px', @@ -368,10 +347,11 @@ const props: ChartProperty[] = [ help: 'title y offset from bullet edge.', type: 'number', required: false, - defaultValue: defaultProps.titleOffset, - controlType: 'range', + defaultValue: defaultProps.titleOffsetY, + flavors: ['svg'], group: 'Title', - controlOptions: { + control: { + type: 'range', min: -100, max: 100, unit: 'px', @@ -383,9 +363,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaultProps.titleRotation, - controlType: 'angle', + flavors: ['svg'], group: 'Title', - controlOptions: { + control: { + type: 'angle', start: 90, min: -360, max: 360, diff --git a/website/src/data/components/bump/props.ts b/website/src/data/components/bump/props.ts index b550d542f7..1050f39418 100644 --- a/website/src/data/components/bump/props.ts +++ b/website/src/data/components/bump/props.ts @@ -1,17 +1,23 @@ +// @ts-ignore import { BumpDefaultProps as defaults } from '@nivo/bump' +import { themeProperty, motionProperties, groupProperties } from '../../../lib/componentProperties' import { - themeProperty, - motionProperties, - axesProperties, - groupProperties, -} from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' + chartDimensions, + ordinalColors, + chartGrid, + axes, + isInteractive, +} from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', help: 'Chart data.', + flavors: allFlavors, description: ` Chart data, which must conform to this structure: \`\`\` @@ -29,64 +35,17 @@ const props: ChartProperty[] = [ required: true, type: 'object[]', }, - { - key: 'width', - group: 'Base', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using - \`\`. - Also note that width does not include labels, - so you should add enough margin to display them. - `, - type: 'number', - required: true, - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - group: 'Base', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using - \`\`. - Also note that width does not include labels, - so you should add enough margin to display them. - `, - type: 'number', - required: true, - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'margin', - group: 'Base', - help: 'Chart margin.', - type: 'object', - controlType: 'margin', - }, + ...chartDimensions(allFlavors), { key: 'interpolation', group: 'Base', type: 'string', help: `Line interpolation.`, required: false, + flavors: ['svg'], defaultValue: defaults.interpolation, - controlType: 'radio', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'smooth', value: 'smooth' }, { label: 'linear', value: 'linear' }, @@ -99,8 +58,10 @@ const props: ChartProperty[] = [ type: 'number', help: 'X padding.', defaultValue: defaults.xPadding, - controlType: 'range', - controlOptions: { + flavors: ['svg'], + required: false, + control: { + type: 'range', min: 0, max: 1, step: 0.05, @@ -112,8 +73,10 @@ const props: ChartProperty[] = [ type: 'number', help: 'X outer padding.', defaultValue: defaults.xOuterPadding, - controlType: 'range', - controlOptions: { + flavors: ['svg'], + required: false, + control: { + type: 'range', min: 0, max: 1, step: 0.05, @@ -125,38 +88,39 @@ const props: ChartProperty[] = [ type: 'number', help: 'Y outer padding.', defaultValue: defaults.yOuterPadding, - controlType: 'range', - controlOptions: { + flavors: ['svg'], + required: false, + control: { + type: 'range', min: 0, max: 1, step: 0.05, }, }, themeProperty(['svg']), - { - key: 'colors', - help: 'Defines color range.', - type: 'string | Function | string[]', - required: false, + ordinalColors({ + flavors: allFlavors, defaultValue: defaults.colors, - controlType: 'ordinalColors', - group: 'Style', - }, + }), { key: 'lineWidth', group: 'Style', type: 'number | (serie: Serie) => number', help: 'Line width.', + flavors: ['svg'], + required: false, defaultValue: defaults.lineWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'activeLineWidth', group: 'Style', type: 'number | (serie: Serie) => number', help: 'Line width for active series.', + flavors: ['svg'], + required: false, defaultValue: defaults.activeLineWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'inactiveLineWidth', @@ -164,7 +128,9 @@ const props: ChartProperty[] = [ type: 'number | (serie: Serie) => number', help: 'Line width for inactive series.', defaultValue: defaults.inactiveLineWidth, - controlType: 'lineWidth', + flavors: ['svg'], + required: false, + control: { type: 'lineWidth' }, }, { key: 'opacity', @@ -172,7 +138,9 @@ const props: ChartProperty[] = [ type: 'number | (serie: Serie) => number', help: 'Opacity.', defaultValue: defaults.opacity, - controlType: 'opacity', + flavors: ['svg'], + required: false, + control: { type: 'opacity' }, }, { key: 'activeOpacity', @@ -180,7 +148,9 @@ const props: ChartProperty[] = [ type: 'number | (serie: Serie) => number', help: 'Opacity for active series.', defaultValue: defaults.activeOpacity, - controlType: 'opacity', + flavors: ['svg'], + required: false, + control: { type: 'opacity' }, }, { key: 'inactiveOpacity', @@ -188,21 +158,29 @@ const props: ChartProperty[] = [ type: 'number | (serie: Serie) => number', help: 'Opacity for inactive series.', defaultValue: defaults.inactiveOpacity, - controlType: 'opacity', + flavors: ['svg'], + required: false, + control: { type: 'opacity' }, }, { key: 'startLabel', + help: 'Start label.', group: 'Labels', type: 'false | string | (serie: Serie) => string', defaultValue: defaults.startLabel, + flavors: ['svg'], + required: false, }, { key: 'startLabelPadding', + help: 'Start label padding.', group: 'Labels', type: 'number', defaultValue: defaults.startLabelPadding, - controlType: 'range', - controlOptions: { + flavors: ['svg'], + required: false, + control: { + type: 'range', min: 0, max: 30, }, @@ -212,23 +190,30 @@ const props: ChartProperty[] = [ help: 'Method to compute start label text color.', type: 'string | object | Function', required: false, + flavors: ['svg'], defaultValue: defaults.startLabelTextColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Labels', }, { key: 'endLabel', + help: 'End label.', group: 'Labels', type: 'false | string | (serie: Serie) => string', defaultValue: defaults.endLabel, + flavors: ['svg'], + required: false, }, { key: 'endLabelPadding', + help: 'End label padding.', group: 'Labels', type: 'number', defaultValue: defaults.endLabelPadding, - controlType: 'range', - controlOptions: { + flavors: ['svg'], + required: false, + control: { + type: 'range', min: 0, max: 30, }, @@ -239,7 +224,8 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, defaultValue: defaults.endLabelTextColor, - controlType: 'inheritedColor', + flavors: ['svg'], + control: { type: 'inheritedColor' }, group: 'Labels', }, { @@ -248,8 +234,10 @@ const props: ChartProperty[] = [ help: 'Point size.', type: 'number | Function', defaultValue: defaults.pointSize, - controlType: 'range', - controlOptions: { + flavors: ['svg'], + required: false, + control: { + type: 'range', min: 0, max: 24, }, @@ -260,8 +248,10 @@ const props: ChartProperty[] = [ help: 'Point size for active series.', type: 'number | Function', defaultValue: defaults.activePointSize, - controlType: 'range', - controlOptions: { + flavors: ['svg'], + required: false, + control: { + type: 'range', min: 0, max: 24, }, @@ -272,8 +262,10 @@ const props: ChartProperty[] = [ help: 'Point size for inactive series.', type: 'number | Function', defaultValue: defaults.inactivePointSize, - controlType: 'range', - controlOptions: { + flavors: ['svg'], + required: false, + control: { + type: 'range', min: 0, max: 24, }, @@ -284,8 +276,10 @@ const props: ChartProperty[] = [ type: 'string | object | Function', help: 'Method to compute point fill color.', defaultValue: defaults.pointColor, - controlType: 'inheritedColor', - controlOptions: { + flavors: ['svg'], + required: false, + control: { + type: 'inheritedColor', inheritableProperties: ['serie.color'], }, }, @@ -295,7 +289,9 @@ const props: ChartProperty[] = [ help: 'Point border width.', type: 'number | Function', defaultValue: defaults.pointBorderWidth, - controlType: 'lineWidth', + flavors: ['svg'], + required: false, + control: { type: 'lineWidth' }, }, { key: 'activePointBorderWidth', @@ -303,7 +299,9 @@ const props: ChartProperty[] = [ help: 'Point border width for active series.', type: 'number | Function', defaultValue: defaults.activePointBorderWidth, - controlType: 'lineWidth', + flavors: ['svg'], + required: false, + control: { type: 'lineWidth' }, }, { key: 'inactivePointBorderWidth', @@ -311,7 +309,9 @@ const props: ChartProperty[] = [ help: 'Point border width for inactive series.', type: 'number | Function', defaultValue: defaults.inactivePointBorderWidth, - controlType: 'lineWidth', + flavors: ['svg'], + required: false, + control: { type: 'lineWidth' }, }, { key: 'pointBorderColor', @@ -319,45 +319,30 @@ const props: ChartProperty[] = [ type: 'string | object | Function', help: 'Method to compute point border color.', defaultValue: defaults.pointBorderColor, - controlType: 'inheritedColor', - controlOptions: { + flavors: ['svg'], + required: false, + control: { + type: 'inheritedColor', inheritableProperties: ['color', 'serie.color'], }, }, - { - key: 'enableGridX', - group: 'Grid & Axes', - help: 'Enable/disable x grid.', - type: 'boolean', - required: false, - defaultValue: defaults.enableGridX, - controlType: 'switch', - }, - { - key: 'enableGridY', - group: 'Grid & Axes', - help: 'Enable/disable y grid.', - type: 'boolean', - required: false, - defaultValue: defaults.enableGridY, - controlType: 'switch', - }, - ...axesProperties(), - { - key: 'isInteractive', - group: 'Interactivity', - type: 'boolean', - help: 'Enable/disable interactivity.', - required: false, + ...chartGrid({ + flavors: allFlavors, + xDefault: defaults.enableGridX, + yDefault: defaults.enableGridY, + }), + ...axes({ flavors: allFlavors }), + isInteractive({ + flavors: ['svg'], defaultValue: defaults.isInteractive, - controlType: 'switch', - }, + }), { key: 'onMouseEnter', group: 'Interactivity', type: '(serie, event) => void', help: 'onMouseEnter handler.', required: false, + flavors: ['svg'], }, { key: 'onMouseMove', @@ -365,6 +350,7 @@ const props: ChartProperty[] = [ type: '(serie, event) => void', help: 'onMouseMove handler.', required: false, + flavors: ['svg'], }, { key: 'onMouseLeave', @@ -372,6 +358,7 @@ const props: ChartProperty[] = [ type: '(serie, event) => void', help: 'onMouseLeave handler.', required: false, + flavors: ['svg'], }, { key: 'onClick', @@ -379,6 +366,7 @@ const props: ChartProperty[] = [ type: '(serie, event) => void', help: 'onClick handler.', required: false, + flavors: ['svg'], }, { key: 'tooltip', @@ -391,6 +379,7 @@ const props: ChartProperty[] = [ it must return a valid HTML element and will receive the series's data. `, + flavors: ['svg'], }, ...motionProperties(['svg'], defaults, 'react-spring'), ] diff --git a/website/src/data/components/calendar/props.ts b/website/src/data/components/calendar/props.ts index c5c5a5a46d..f196313806 100644 --- a/website/src/data/components/calendar/props.ts +++ b/website/src/data/components/calendar/props.ts @@ -1,7 +1,9 @@ -import { boxAlignments } from '@nivo/core' import { calendarDefaultProps as defaults } from '@nivo/calendar' import { themeProperty, groupProperties } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'canvas', 'api'] const props: ChartProperty[] = [ { @@ -21,6 +23,7 @@ const props: ChartProperty[] = [ `, type: 'object[]', required: true, + flavors: allFlavors, }, { key: 'from', @@ -28,6 +31,7 @@ const props: ChartProperty[] = [ help: 'start date', type: 'string | Date', required: true, + flavors: allFlavors, }, { key: 'to', @@ -35,81 +39,35 @@ const props: ChartProperty[] = [ help: 'end date', type: 'string | Date', required: true, + flavors: allFlavors, }, - { - key: 'width', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using responsive alternative of - the component \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using responsive alternative of - the component \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, + ...chartDimensions(allFlavors), { key: 'direction', help: 'defines calendar layout direction.', type: 'string', required: false, defaultValue: defaults.direction, - controlType: 'radio', + flavors: ['svg', 'canvas', 'api'], group: 'Base', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'horizontal', value: 'horizontal' }, { label: 'vertical', value: 'vertical' }, ], }, }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, { key: 'align', help: 'defines how calendar should be aligned inside chart container.', type: 'string', required: false, + flavors: ['svg', 'canvas', 'api'], defaultValue: defaults.align, - controlType: 'boxAnchor', group: 'Base', - controlOptions: { - choices: boxAlignments.map(align => ({ - label: align, - value: align, - })), + control: { + type: 'boxAnchor', }, }, { @@ -122,11 +80,12 @@ const props: ChartProperty[] = [ desired lower bound value. `, required: false, + flavors: ['svg', 'canvas', 'api'], defaultValue: defaults.minValue, type: `number | 'auto'`, - controlType: 'switchableRange', group: 'Base', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 0, min: -300, @@ -143,11 +102,12 @@ const props: ChartProperty[] = [ desired higher bound value. `, required: false, + flavors: ['svg', 'canvas', 'api'], defaultValue: defaults.maxValue, type: `number | 'auto'`, - controlType: 'switchableRange', group: 'Base', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 100, min: 0, @@ -167,6 +127,7 @@ const props: ChartProperty[] = [ `, type: 'string[]', required: false, + flavors: ['svg', 'canvas', 'api'], defaultValue: defaults.colors, }, { @@ -174,24 +135,11 @@ const props: ChartProperty[] = [ help: 'color to use to fill days without available value.', type: 'string', required: false, + flavors: ['svg', 'canvas', 'api'], defaultValue: defaults.emptyColor, - controlType: 'colorPicker', + control: { type: 'colorPicker' }, group: 'Style', }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, // Years { key: 'yearSpacing', @@ -199,9 +147,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaults.yearSpacing, - controlType: 'range', + flavors: ['svg', 'canvas', 'api'], group: 'Years', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 160, @@ -214,6 +163,7 @@ const props: ChartProperty[] = [ help: `can be used to customize years label, returns 'YYYY' by default.`, type: '(year: number) => string | number', required: false, + flavors: ['svg', 'canvas', 'api'], }, { key: 'yearLegendPosition', @@ -221,9 +171,10 @@ const props: ChartProperty[] = [ type: `'before' | 'after'`, required: false, defaultValue: defaults.yearLegendPosition, - controlType: 'radio', + flavors: ['svg', 'canvas', 'api'], group: 'Years', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'before', value: 'before' }, { label: 'after', value: 'after' }, @@ -236,9 +187,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaults.yearLegendOffset, - controlType: 'range', + flavors: ['svg', 'canvas', 'api'], group: 'Years', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 60, @@ -251,9 +203,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaults.monthSpacing, - controlType: 'range', + flavors: ['svg', 'canvas', 'api'], group: 'Months', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 160, @@ -267,7 +220,7 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaults.monthBorderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Months', }, { @@ -277,7 +230,7 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: defaults.monthBorderColor, - controlType: 'colorPicker', + control: { type: 'colorPicker' }, group: 'Months', }, { @@ -286,6 +239,7 @@ const props: ChartProperty[] = [ type: '(year: number, month: number, date: Date) => string | number', required: false, group: 'Months', + flavors: ['svg', 'canvas', 'api'], }, { key: 'monthLegendPosition', @@ -293,9 +247,10 @@ const props: ChartProperty[] = [ type: `'before' | 'after'`, required: false, defaultValue: defaults.monthLegendPosition, - controlType: 'radio', + flavors: ['svg', 'canvas', 'api'], group: 'Months', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'before', value: 'before' }, { label: 'after', value: 'after' }, @@ -308,9 +263,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaults.monthLegendOffset, - controlType: 'range', + flavors: ['svg', 'canvas', 'api'], group: 'Months', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 36, @@ -323,9 +279,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaults.daySpacing, - controlType: 'range', + flavors: ['svg', 'canvas', 'api'], group: 'Days', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 20, @@ -337,7 +294,8 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaults.dayBorderWidth, - controlType: 'lineWidth', + flavors: ['svg', 'canvas', 'api'], + control: { type: 'lineWidth' }, group: 'Days', }, { @@ -346,19 +304,14 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: defaults.dayBorderColor, - controlType: 'colorPicker', + flavors: ['svg', 'canvas', 'api'], + control: { type: 'colorPicker' }, group: 'Days', }, - { - key: 'isInteractive', + isInteractive({ flavors: ['svg', 'canvas'], - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: defaults.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'onClick', flavors: ['svg', 'canvas'], @@ -397,7 +350,8 @@ const props: ChartProperty[] = [ flavors: ['svg', 'canvas'], help: 'Showcase custom tooltip.', type: 'boolean', - controlType: 'switch', + required: false, + control: { type: 'switch' }, group: 'Interactivity', }, ] diff --git a/website/src/data/components/chord/props.ts b/website/src/data/components/chord/props.ts index f5a6285943..fc329f381b 100644 --- a/website/src/data/components/chord/props.ts +++ b/website/src/data/components/chord/props.ts @@ -1,3 +1,4 @@ +// @ts-ignore import { ChordDefaultProps as defaults } from '@nivo/chord' import { themeProperty, @@ -5,7 +6,10 @@ import { groupProperties, getLegendsProps, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions, ordinalColors, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'canvas', 'api'] const props: ChartProperty[] = [ { @@ -33,6 +37,7 @@ const props: ChartProperty[] = [ \`\`\` `, required: true, + flavors: allFlavors, type: 'string[]', }, { @@ -46,6 +51,7 @@ const props: ChartProperty[] = [ `, required: true, type: 'Array', + flavors: allFlavors, }, { key: 'valueFormat', @@ -53,80 +59,19 @@ const props: ChartProperty[] = [ type: 'string | Function', required: false, help: `Optional value formatter.`, + flavors: allFlavors, }, - { - key: 'width', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using - \`\`. - Also note that width does not include labels, - so you should add enough margin to display them. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using - \`\`. - Also note that width does not include labels, - so you should add enough margin to display them. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, + ...chartDimensions(allFlavors), { key: 'padAngle', help: 'Padding angle.', required: false, defaultValue: defaults.padAngle, type: 'number', - controlType: 'range', group: 'Base', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', min: 0, max: 1, step: 0.01, @@ -138,9 +83,10 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.innerRadiusRatio, type: 'number', - controlType: 'range', group: 'Base', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', min: 0, max: 1, step: 0.01, @@ -152,32 +98,29 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.innerRadiusOffset, type: 'number', - controlType: 'range', group: 'Base', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', min: 0, max: 1, step: 0.01, }, }, - themeProperty(['svg', 'canvas', 'api']), - { - key: 'colors', - help: 'Defines how to compute arc/ribbon color.', - type: 'string | Function | string[]', - required: false, + themeProperty(allFlavors), + ordinalColors({ + flavors: allFlavors, defaultValue: defaults.colors, - flavors: ['svg', 'canvas', 'api'], - controlType: 'ordinalColors', - group: 'Style', - }, + help: 'Defines how to compute arcs & ribbons color.', + }), { key: 'arcOpacity', help: 'Arcs opacity.', required: false, defaultValue: defaults.arcOpacity, type: 'number', - controlType: 'opacity', + flavors: allFlavors, + control: { type: 'opacity' }, group: 'Style', }, { @@ -186,7 +129,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.arcBorderWidth, type: 'number', - controlType: 'lineWidth', + flavors: allFlavors, + control: { type: 'lineWidth' }, group: 'Style', }, { @@ -194,8 +138,9 @@ const props: ChartProperty[] = [ help: 'Arcs border color.', required: false, defaultValue: defaults.arcBorderColor, + flavors: allFlavors, type: 'string | object | Function', - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, { @@ -204,7 +149,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.ribbonOpacity, type: 'number', - controlType: 'opacity', + flavors: allFlavors, + control: { type: 'opacity' }, group: 'Style', }, { @@ -213,7 +159,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.ribbonBorderWidth, type: 'number', - controlType: 'lineWidth', + control: { type: 'lineWidth' }, + flavors: allFlavors, group: 'Style', }, { @@ -222,7 +169,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.ribbonBorderColor, type: 'string | object | Function', - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, + flavors: allFlavors, group: 'Style', }, { @@ -231,7 +179,8 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, defaultValue: defaults.enableLabel, - controlType: 'switch', + control: { type: 'switch' }, + flavors: allFlavors, group: 'Labels', }, { @@ -240,9 +189,10 @@ const props: ChartProperty[] = [ type: 'string | Function', required: false, defaultValue: defaults.label, - controlType: 'choices', group: 'Labels', - controlOptions: { + flavors: allFlavors, + control: { + type: 'choices', choices: ['id', 'value', `d => \`\${d.id} [\${d.value}]\``].map(choice => ({ label: choice, value: choice, @@ -255,9 +205,10 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.labelOffset, type: 'number', - controlType: 'range', + flavors: allFlavors, group: 'Labels', - controlOptions: { + control: { + type: 'range', unit: 'px', min: -80, max: 80, @@ -269,9 +220,10 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.labelRotation, type: 'number', - controlType: 'angle', group: 'Labels', - controlOptions: { + flavors: allFlavors, + control: { + type: 'angle', min: -180, max: 180, step: 5, @@ -286,8 +238,9 @@ const props: ChartProperty[] = [ help: 'Method to compute label text color.', type: 'string | object | Function', required: false, + flavors: allFlavors, defaultValue: defaults.labelTextColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Labels', }, { @@ -311,20 +264,15 @@ const props: ChartProperty[] = [ modifications to the 2d context inside this function to avoid side effects. `, + flavors: allFlavors, required: false, type: 'Array', defaultValue: defaults.layers, }, - { - key: 'isInteractive', + isInteractive({ flavors: ['svg', 'canvas'], - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: defaults.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'arcHoverOpacity', flavors: ['svg', 'canvas'], @@ -332,7 +280,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.arcHoverOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Interactivity', }, { @@ -342,7 +290,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.arcHoverOthersOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Interactivity', }, { @@ -352,7 +300,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.ribbonHoverOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Interactivity', }, { @@ -362,7 +310,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.ribbonHoverOthersOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Interactivity', }, { @@ -461,13 +409,14 @@ const props: ChartProperty[] = [ type: 'object[]', help: `Optional chart's legends.`, group: 'Legends', - controlType: 'array', - controlOptions: { + required: false, + control: { + type: 'array', props: getLegendsProps(['svg', 'canvas']), shouldCreate: true, addLabel: 'add legend', shouldRemove: true, - getItemTitle: (index, legend) => + getItemTitle: (index, legend: any) => `legend[${index}]: ${legend.anchor}, ${legend.direction}`, defaults: { dataFrom: 'keys', @@ -481,8 +430,8 @@ const props: ChartProperty[] = [ itemsSpacing: 0, symbolSize: 20, itemDirection: 'left-to-right', - onClick: data => { - alert(JSON.stringify(data, null, ' ')) + onClick: (data: any) => { + console.log(JSON.stringify(data, null, ' ')) }, }, }, diff --git a/website/src/data/components/choropleth/props.ts b/website/src/data/components/choropleth/props.ts index d4d689b9ff..b4125a1f93 100644 --- a/website/src/data/components/choropleth/props.ts +++ b/website/src/data/components/choropleth/props.ts @@ -1,3 +1,4 @@ +// @ts-ignore import { GeoMapDefaultProps, ChoroplethDefaultProps } from '@nivo/geo' import { getLegendsProps, groupProperties } from '../../../lib/componentProperties' import { props as geoProps } from '../geo/props' @@ -10,6 +11,7 @@ const props: ChartProperty[] = [ group: 'Base', type: 'string | Function', required: false, + flavors: ['svg', 'canvas'], help: 'Label accessor.', description: ` Accessor to label, if a string is provided, @@ -24,6 +26,7 @@ const props: ChartProperty[] = [ group: 'Base', type: 'string | Function', required: false, + flavors: ['svg', 'canvas'], help: 'Value accessor.', description: ` Accessor to data value, if a string is provided, @@ -38,6 +41,7 @@ const props: ChartProperty[] = [ group: 'Base', type: 'string | Function', required: false, + flavors: ['svg', 'canvas'], help: 'Value formatter.', description: ` Optional formatting of values, if provided, it will @@ -61,31 +65,35 @@ const props: ChartProperty[] = [ `, type: 'number[]', required: true, + flavors: ['svg', 'canvas'], group: 'Base', }, { key: 'colors', + group: 'Style', help: 'Defines color range.', type: 'string | Function | string[]', required: false, + flavors: ['svg', 'canvas'], defaultValue: 'nivo', - controlType: 'quantizeColors', - group: 'Style', + control: { type: 'quantizeColors' }, }, { key: 'unknownColor', + group: 'Style', help: 'Defines the color to use for features without value.', type: 'string', required: false, + flavors: ['svg', 'canvas'], defaultValue: 'nivo', - controlType: 'colorPicker', - group: 'Style', + control: { type: 'colorPicker' }, }, { key: 'layers', group: 'Customization', type: `Array<'graticule' | 'features' | Function>`, required: false, + flavors: ['svg', 'canvas'], help: 'Defines the order of layers.', description: ` Defines the order of layers, available layers are: @@ -107,6 +115,7 @@ const props: ChartProperty[] = [ group: 'Interactivity', type: 'Function', required: false, + flavors: ['svg', 'canvas'], help: 'Custom tooltip component.', description: ` A function allowing complete tooltip customisation, @@ -116,20 +125,24 @@ const props: ChartProperty[] = [ }, { key: 'custom tooltip example', + group: 'Interactivity', excludeFromDoc: true, + required: false, help: 'Showcase custom tooltip.', type: 'boolean', - controlType: 'switch', - group: 'Interactivity', + flavors: ['svg', 'canvas'], + control: { type: 'switch' }, }, { key: 'legends', type: '{Array}', help: `Optional chart's legends.`, group: 'Legends', - controlType: 'array', - controlOptions: { - props: getLegendsProps(), + flavors: ['svg', 'canvas'], + required: false, + control: { + type: 'array', + props: getLegendsProps(['svg', 'canvas']), shouldCreate: true, addLabel: 'add legend', shouldRemove: true, @@ -145,8 +158,8 @@ const props: ChartProperty[] = [ symbolSize: 20, itemDirection: 'left-to-right', itemTextColor: '#777', - onClick: data => { - alert(JSON.stringify(data, null, ' ')) + onClick: (data: any) => { + console.log(JSON.stringify(data, null, ' ')) }, effects: [ { diff --git a/website/src/data/components/circle-packing/props.ts b/website/src/data/components/circle-packing/props.ts index 8973ce145d..d0a348d7e9 100644 --- a/website/src/data/components/circle-packing/props.ts +++ b/website/src/data/components/circle-packing/props.ts @@ -5,13 +5,17 @@ import { defsProperties, groupProperties, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions, ordinalColors, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'html', 'canvas', 'api'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', help: 'Chart data, which should be immutable.', + flavors: allFlavors, description: ` Chart data, which must conform to this structure if using the default \`id\` and \`value\` accessors: @@ -43,6 +47,7 @@ const props: ChartProperty[] = [ { key: 'id', group: 'Base', + flavors: allFlavors, help: 'Id accessor.', description: ` define id accessor, if string given, @@ -59,6 +64,7 @@ const props: ChartProperty[] = [ { key: 'value', group: 'Base', + flavors: allFlavors, help: 'Value accessor', description: ` define value accessor, if string given, @@ -75,6 +81,7 @@ const props: ChartProperty[] = [ { key: 'valueFormat', group: 'Base', + flavors: allFlavors, help: 'Optional formatter for values.', description: ` The formatted value can then be used for labels & tooltips. @@ -85,11 +92,12 @@ const props: ChartProperty[] = [ `, required: false, type: 'string | (value: number) => string | number', - controlType: 'valueFormat', + control: { type: 'valueFormat' }, }, { key: 'padding', help: 'Padding between each circle.', + flavors: allFlavors, description: ` Padding between adjacent circles. Please be aware that when zoomed @@ -100,9 +108,9 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaultProps.padding, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 32, @@ -111,85 +119,19 @@ const props: ChartProperty[] = [ { key: 'leavesOnly', help: 'Only render leaf nodes (skip parent nodes).', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultProps.leavesOnly, - controlType: 'switch', - group: 'Base', - }, - { - key: 'width', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', group: 'Base', + control: { type: 'switch' }, }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, + ...chartDimensions(allFlavors), themeProperty(['svg', 'html', 'canvas']), - { - key: 'colors', - help: 'Define how to compute node color.', - description: ` - colors used to colorize the circles, - [see dedicated documentation](self:/guides/colors). - `, - type: 'string | Function | string[]', - required: false, + ordinalColors({ + flavors: allFlavors, defaultValue: { scheme: 'nivo' }, - flavors: ['svg', 'html', 'canvas'], - controlType: 'ordinalColors', - group: 'Style', - }, + }), { key: 'colorBy', help: `Define the property to use to assign a color to circles.`, @@ -200,9 +142,10 @@ const props: ChartProperty[] = [ type: `'id' | 'depth'`, required: false, defaultValue: defaultProps.colorBy, - controlType: 'radio', + flavors: allFlavors, group: 'Style', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'id', value: 'id' }, { label: 'depth', value: 'depth' }, @@ -214,31 +157,35 @@ const props: ChartProperty[] = [ help: 'Inherit color from parent node starting from 2nd level.', type: 'boolean', required: false, + flavors: allFlavors, defaultValue: defaultProps.inheritColorFromParent, - controlType: 'switch', + control: { type: 'switch' }, group: 'Style', }, { key: 'childColor', help: 'Defines how to compute child nodes color, only used when inheritColorFromParent is enabled.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaultProps.childColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, { key: 'borderWidth', help: 'Width of circle border.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.borderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Style', }, { key: 'borderColor', help: 'Method to compute border color.', + flavors: allFlavors, description: ` how to compute border color, [see dedicated documentation](self:/guides/colors). @@ -246,28 +193,32 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, defaultValue: defaultProps.borderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, ...defsProperties('Style', ['svg']), { key: 'circleComponent', help: 'Custom circle component.', + type: 'Component', + flavors: ['svg'], group: 'Style', required: false, }, { key: 'enableLabels', help: 'Enable/disable labels.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultProps.enableLabels, - controlType: 'switch', + control: { type: 'switch' }, group: 'Labels', }, { key: 'label', help: 'Label accessor.', + flavors: allFlavors, description: ` Defines how to get label text, can be a string (used to access current node data property) @@ -276,9 +227,9 @@ const props: ChartProperty[] = [ type: 'string | Function', required: false, defaultValue: defaultProps.label, - controlType: 'choices', group: 'Labels', - controlOptions: { + control: { + type: 'choices', choices: ['id', 'value', 'formattedValue', `d => \`\${d.id}: \${d.value}\``].map( choice => ({ label: choice, @@ -290,6 +241,7 @@ const props: ChartProperty[] = [ { key: 'labelsFilter', help: 'Filter labels using custom conditions.', + flavors: allFlavors, description: ` Please note that at this stage, nodes are already excluded according to \`labelsSkipRadius\`. @@ -312,10 +264,11 @@ const props: ChartProperty[] = [ help: 'Skip label rendering if node radius is lower than given value, 0 to disable.', type: 'number', required: false, + flavors: allFlavors, defaultValue: defaultProps.labelsSkipRadius, - controlType: 'range', group: 'Labels', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 32, @@ -324,6 +277,7 @@ const props: ChartProperty[] = [ { key: 'labelTextColor', help: 'Method to compute label text color.', + flavors: allFlavors, description: ` how to compute label text color, [see dedicated documentation](self:/guides/colors). @@ -331,25 +285,21 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, defaultValue: defaultProps.labelTextColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Labels', }, { key: 'labelComponent', help: 'Custom label component.', + type: 'Component', + flavors: allFlavors, group: 'Labels', required: false, }, - { - key: 'isInteractive', + isInteractive({ flavors: ['svg', 'html', 'canvas'], - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: defaultProps.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'onMouseEnter', flavors: ['svg', 'html'], diff --git a/website/src/data/components/funnel/props.ts b/website/src/data/components/funnel/props.ts index 4b6aa898eb..e56995d263 100644 --- a/website/src/data/components/funnel/props.ts +++ b/website/src/data/components/funnel/props.ts @@ -1,6 +1,9 @@ import { svgDefaultProps as defaults } from '@nivo/funnel' import { themeProperty, groupProperties, motionProperties } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions, ordinalColors, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg'] const props: ChartProperty[] = [ { @@ -26,15 +29,7 @@ const props: ChartProperty[] = [ this for the \`colors\` property. `, }, - { - key: 'margin', - group: 'Base', - type: 'object', - required: false, - help: 'Chart margin.', - flavors: ['svg'], - controlType: 'margin', - }, + ...chartDimensions(allFlavors), { key: 'direction', group: 'Base', @@ -43,8 +38,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.direction, flavors: ['svg'], - controlType: 'radio', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'horizontal', value: 'horizontal' }, { label: 'vertical', value: 'vertical' }, @@ -59,8 +54,8 @@ const props: ChartProperty[] = [ help: `Part shape interpolation.`, defaultValue: defaults.interpolation, flavors: ['svg'], - controlType: 'radio', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'smooth', value: 'smooth' }, { label: 'linear', value: 'linear' }, @@ -75,8 +70,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.spacing, flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 30, unit: 'px', @@ -90,8 +85,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.shapeBlending, flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 1, step: 0.01, @@ -107,19 +102,13 @@ const props: ChartProperty[] = [ type: 'string | Function', required: false, flavors: ['svg'], - controlType: 'valueFormat', + control: { type: 'valueFormat' }, }, themeProperty(['svg']), - { - key: 'colors', - group: 'Style', - help: 'Defines how to compute parts color.', - type: 'string | Function | string[]', - required: false, + ordinalColors({ + flavors: allFlavors, defaultValue: defaults.colors, - flavors: ['svg'], - controlType: 'ordinalColors', - }, + }), { key: 'fillOpacity', group: 'Style', @@ -128,7 +117,7 @@ const props: ChartProperty[] = [ defaultValue: defaults.fillOpacity, type: 'number', flavors: ['svg'], - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'borderWidth', @@ -138,7 +127,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.borderWidth, flavors: ['svg'], - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'borderColor', @@ -152,7 +141,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.borderColor, flavors: ['svg'], - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'borderOpacity', @@ -162,7 +151,7 @@ const props: ChartProperty[] = [ defaultValue: defaults.borderOpacity, type: 'number', flavors: ['svg'], - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'enableLabel', @@ -175,7 +164,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.enableLabel, flavors: ['svg'], - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'labelColor', @@ -189,7 +178,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.labelColor, flavors: ['svg'], - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'enableBeforeSeparators', @@ -202,7 +191,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.enableBeforeSeparators, flavors: ['svg'], - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'beforeSeparatorLength', @@ -215,8 +204,8 @@ const props: ChartProperty[] = [ defaultValue: defaults.beforeSeparatorLength, type: 'number', flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 100, @@ -234,8 +223,8 @@ const props: ChartProperty[] = [ defaultValue: defaults.beforeSeparatorOffset, type: 'number', flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 100, @@ -252,7 +241,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.enableAfterSeparators, flavors: ['svg'], - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'afterSeparatorLength', @@ -265,8 +254,8 @@ const props: ChartProperty[] = [ defaultValue: defaults.afterSeparatorLength, type: 'number', flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 100, @@ -284,8 +273,8 @@ const props: ChartProperty[] = [ defaultValue: defaults.afterSeparatorOffset, type: 'number', flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 100, @@ -307,16 +296,10 @@ const props: ChartProperty[] = [ flavors: ['svg'], defaultValue: defaults.layers, }, - { - key: 'isInteractive', - group: 'Interactivity', - type: 'boolean', - help: 'Enable/disable interactivity.', - required: false, - defaultValue: defaults.isInteractive, + isInteractive({ flavors: ['svg'], - controlType: 'switch', - }, + defaultValue: defaults.isInteractive, + }), { key: 'currentPartSizeExtension', group: 'Interactivity', @@ -328,8 +311,8 @@ const props: ChartProperty[] = [ defaultValue: defaults.currentPartSizeExtension, type: 'number', flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 100, @@ -342,8 +325,8 @@ const props: ChartProperty[] = [ required: false, type: 'number', flavors: ['svg'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 100, diff --git a/website/src/data/components/geo/props.ts b/website/src/data/components/geo/props.ts index a69984b407..f69ff36e02 100644 --- a/website/src/data/components/geo/props.ts +++ b/website/src/data/components/geo/props.ts @@ -1,62 +1,23 @@ +// @ts-ignore import { GeoMapDefaultProps } from '@nivo/geo' import { themeProperty, defsProperties } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'canvas'] export const props: ChartProperty[] = [ - { - key: 'width', - group: 'Base', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using responsive alternative - of the component \`\`. - `, - type: 'number', - required: true, - }, - { - key: 'height', - group: 'Base', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using responsive alternative - of the component \`\`. - `, - type: 'number', - required: true, - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, + ...chartDimensions(allFlavors), { key: 'projectionType', + flavors: ['svg', 'canvas'], help: 'Defines the projection to use.', + type: 'string', required: false, defaultValue: GeoMapDefaultProps.projectionType, - controlType: 'choices', group: 'Projection', - controlOptions: { + control: { + type: 'choices', choices: [ { label: 'azimuthalEqualArea', value: 'azimuthalEqualArea' }, { label: 'azimuthalEquidistant', value: 'azimuthalEquidistant' }, @@ -73,26 +34,28 @@ export const props: ChartProperty[] = [ }, { key: 'projectionScale', + flavors: ['svg', 'canvas'], help: 'Projection scale.', required: false, defaultValue: GeoMapDefaultProps.projectionScale, type: 'number', - controlType: 'range', group: 'Projection', - controlOptions: { + control: { + type: 'range', min: 0, max: 400, }, }, { key: 'projectionTranslation', + flavors: ['svg', 'canvas'], type: '[number, number]', help: 'Projection x/y translation.', required: false, defaultValue: GeoMapDefaultProps.projectionTranslation, - controlType: 'numberArray', group: 'Projection', - controlOptions: { + control: { + type: 'numberArray', unit: 'px', items: [ { @@ -112,13 +75,14 @@ export const props: ChartProperty[] = [ }, { key: 'projectionRotation', + flavors: ['svg', 'canvas'], type: '[number, number, number]', help: 'Projection rotation.', required: false, defaultValue: GeoMapDefaultProps.projectionRotation, group: 'Projection', - controlType: 'numberArray', - controlOptions: { + control: { + type: 'numberArray', items: [ { label: 'lambda (λ)', @@ -141,67 +105,68 @@ export const props: ChartProperty[] = [ themeProperty(['svg', 'canvas']), { key: 'borderWidth', + flavors: ['svg', 'canvas'], help: 'Control border width.', type: 'number', required: false, defaultValue: GeoMapDefaultProps.borderWidth, group: 'Style', - controlType: 'lineWidth', - controlOptions: { + control: { + type: 'lineWidth', step: 0.5, }, }, { key: 'borderColor', + flavors: ['svg', 'canvas'], help: 'Method to compute border color.', type: 'string | object | Function', required: false, defaultValue: GeoMapDefaultProps.borderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, { key: 'enableGraticule', + flavors: ['svg', 'canvas'], help: 'Enable meridians and parallels, useful for showing projection distortion.', type: 'boolean', required: false, defaultValue: GeoMapDefaultProps.enableGraticule, - controlType: 'switch', + control: { type: 'switch' }, group: 'Graticule', }, { key: 'graticuleLineWidth', + flavors: ['svg', 'canvas'], help: 'Control meridians and parallel lines width.', type: 'number', required: false, defaultValue: GeoMapDefaultProps.graticuleLineWidth, - controlType: 'lineWidth', group: 'Graticule', - controlOptions: { + control: { + type: 'lineWidth', step: 0.5, }, }, { key: 'graticuleLineColor', + flavors: ['svg', 'canvas'], help: 'Control meridians and parallel lines color.', type: 'string', required: false, defaultValue: GeoMapDefaultProps.graticuleLineColor, - controlType: 'colorPicker', + control: { type: 'colorPicker' }, group: 'Graticule', }, ...defsProperties('Style', ['svg']), - { - key: 'isInteractive', - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, + isInteractive({ + flavors: ['svg', 'canvas'], defaultValue: GeoMapDefaultProps.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'onClick', + flavors: ['svg', 'canvas'], help: 'onClick handler, it receives clicked node data and style plus mouse event.', type: 'Function', required: false, diff --git a/website/src/data/components/heatmap/props.ts b/website/src/data/components/heatmap/props.ts index 4a4780a107..977d2acb2d 100644 --- a/website/src/data/components/heatmap/props.ts +++ b/website/src/data/components/heatmap/props.ts @@ -1,16 +1,16 @@ +// @ts-ignore import { HeatMapDefaultProps as defaults } from '@nivo/heatmap' -import { - themeProperty, - axesProperties, - motionProperties, - groupProperties, -} from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { themeProperty, motionProperties, groupProperties } from '../../../lib/componentProperties' +import { chartDimensions, chartGrid, axes, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'canvas', 'api'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', + flavors: allFlavors, help: 'Chart data.', type: 'object[]', required: true, @@ -18,6 +18,7 @@ const props: ChartProperty[] = [ { key: 'indexBy', group: 'Base', + flavors: allFlavors, help: 'Key to use to index the data.', description: ` Key to use to index the data, @@ -33,6 +34,7 @@ const props: ChartProperty[] = [ { key: 'keys', group: 'Base', + flavors: allFlavors, help: 'Keys to use to determine each serie.', type: 'string[]', required: false, @@ -41,6 +43,7 @@ const props: ChartProperty[] = [ { key: 'minValue', help: 'Minimum value.', + flavors: allFlavors, description: ` Minimum value. If 'auto', will pick the lowest value @@ -51,9 +54,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.minValue, type: `number | 'auto'`, - controlType: 'switchableRange', group: 'Base', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 0, min: -100, @@ -63,6 +66,7 @@ const props: ChartProperty[] = [ { key: 'maxValue', help: 'Maximum value.', + flavors: allFlavors, description: ` Maximum value. If 'auto', will pick the highest value in the provided data set. Should be overriden @@ -72,9 +76,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.maxValue, type: `number | 'auto'`, - controlType: 'switchableRange', group: 'Base', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 100, min: -100, @@ -84,22 +88,24 @@ const props: ChartProperty[] = [ { key: 'forceSquare', help: 'Force square cells (width = height).', + flavors: allFlavors, required: false, defaultValue: defaults.forceSquare, type: 'boolean', - controlType: 'switch', + control: { type: 'switch' }, group: 'Base', }, { key: 'sizeVariation', help: 'Cell size variation.', + flavors: allFlavors, description: `Size variation (0~1), if value is 0 size won't be affected. If you use for example the value 0.3, cell width/height will vary between 0.7~1 according to its corresponding value.`, required: false, defaultValue: defaults.sizeVariation, type: 'number', - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', min: 0, max: 1, step: 0.02, @@ -108,81 +114,24 @@ const props: ChartProperty[] = [ { key: 'padding', help: 'Padding.', + flavors: allFlavors, required: false, defaultValue: defaults.padding, type: 'number', - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', min: 0, max: 36, unit: 'px', }, }, - { - key: 'width', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using - \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1200, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using - \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1200, - step: 5, - }, - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, + ...chartDimensions(allFlavors), themeProperty(['svg', 'canvas', 'api']), { key: 'cellShape', help: `Cell shape/component.`, + flavors: allFlavors, description: ` Cell shape, can be one of: \`'rect'\`, \`'circle'\`, if a function is provided, it must return @@ -206,9 +155,9 @@ const props: ChartProperty[] = [ type: 'string | Function', required: false, defaultValue: defaults.cellShape, - controlType: 'choices', group: 'Style', - controlOptions: { + control: { + type: 'choices', choices: ['rect', 'circle', 'Custom(props) => (…)'].map(key => ({ label: key, value: key, @@ -218,33 +167,37 @@ const props: ChartProperty[] = [ { key: 'colors', help: 'Defines color range.', + flavors: allFlavors, type: 'string | Function | string[]', required: false, defaultValue: 'nivo', - controlType: 'quantizeColors', + control: { type: 'quantizeColors' }, group: 'Style', }, { key: 'cellOpacity', help: 'Cell opacity (0~1).', + flavors: allFlavors, required: false, defaultValue: defaults.cellOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Style', }, { key: 'cellBorderWidth', help: 'Cell border width.', + flavors: allFlavors, required: false, defaultValue: defaults.cellBorderWidth, type: 'number', - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Style', }, { key: 'cellBorderColor', help: 'Method to compute cell border color.', + flavors: allFlavors, description: ` how to compute cell border color, [see dedicated documentation](self:/guides/colors). @@ -252,21 +205,23 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, defaultValue: defaults.cellBorderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, { key: 'enableLabels', help: 'Enable/disable labels.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaults.enableLabels, - controlType: 'switch', + control: { type: 'switch' }, group: 'Labels', }, { key: 'labelTextColor', help: 'Method to compute label text color.', + flavors: allFlavors, description: ` how to compute label text color, [see dedicated documentation](self:/guides/colors). @@ -274,38 +229,19 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, defaultValue: defaults.labelTextColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Labels', }, - { - key: 'enableGridX', - help: 'Enable/disable x grid.', - type: 'boolean', - required: false, - defaultValue: defaults.enableGridX, - controlType: 'switch', - group: 'Grid & Axes', - }, - { - key: 'enableGridY', - help: 'Enable/disable y grid.', - type: 'boolean', - required: false, - defaultValue: defaults.enableGridY, - controlType: 'switch', - group: 'Grid & Axes', - }, - ...axesProperties(), - { - key: 'isInteractive', + ...chartGrid({ + flavors: allFlavors, + xDefault: defaults.enableGridX, + yDefault: defaults.enableGridY, + }), + ...axes({ flavors: allFlavors }), + isInteractive({ flavors: ['svg', 'canvas'], - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: defaults.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'onClick', flavors: ['svg', 'canvas'], @@ -347,9 +283,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.hoverTarget, type: 'string', - controlType: 'choices', group: 'Interactivity', - controlOptions: { + control: { + type: 'choices', choices: ['cell', 'row', 'column', 'rowColumn'].map(key => ({ label: key, value: key, @@ -363,7 +299,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.cellHoverOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Interactivity', }, { @@ -373,7 +309,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.cellHoverOthersOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Interactivity', }, ...motionProperties(['svg'], defaults, 'react-spring'), diff --git a/website/src/data/components/line/props.ts b/website/src/data/components/line/props.ts index e349f33642..daaed582f9 100644 --- a/website/src/data/components/line/props.ts +++ b/website/src/data/components/line/props.ts @@ -1,19 +1,31 @@ +// @ts-ignore import { lineCurvePropKeys } from '@nivo/core' +// @ts-ignore import { LineDefaultProps as defaults } from '@nivo/line' import { themeProperty, - axesProperties, motionProperties, getLegendsProps, groupProperties, defsProperties, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { + chartDimensions, + ordinalColors, + blendMode, + chartGrid, + axes, + isInteractive, +} from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'canvas', 'api'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', + flavors: allFlavors, help: 'Chart data.', description: ` Chart data, which must conform to this structure: @@ -33,17 +45,21 @@ const props: ChartProperty[] = [ { key: 'xScale', type: 'object', + flavors: allFlavors, group: 'Base', help: `X scale configuration.`, - controlType: 'object', - controlOptions: { + required: false, + control: { + type: 'object', props: [ { key: 'type', help: `Scale type.`, type: 'string', - controlType: 'choices', - controlOptions: { + required: true, + flavors: allFlavors, + control: { + type: 'choices', disabled: true, choices: ['linear', 'point'].map(v => ({ label: v, @@ -58,6 +74,7 @@ const props: ChartProperty[] = [ key: 'xFormat', group: 'Base', help: 'Optional formatter for x values.', + flavors: allFlavors, description: ` The formatted value can then be used for labels & tooltips. @@ -70,22 +87,26 @@ const props: ChartProperty[] = [ `, required: false, type: 'Function | string', - controlType: 'valueFormat', + control: { type: 'valueFormat' }, }, { key: 'yScale', type: 'object', help: `Y scale configuration.`, + flavors: allFlavors, group: 'Base', - controlType: 'object', - controlOptions: { + required: false, + control: { + type: 'object', props: [ { key: 'type', help: `Scale type.`, type: 'string', - controlType: 'choices', - controlOptions: { + flavors: allFlavors, + required: true, + control: { + type: 'choices', disabled: true, choices: ['linear', 'point'].map(v => ({ label: v, @@ -96,17 +117,19 @@ const props: ChartProperty[] = [ { key: 'stacked', help: 'Enable/disable stacked mode.', + flavors: allFlavors, type: 'boolean', required: false, - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'min', help: 'Minimum scale value.', + flavors: allFlavors, required: false, type: `number | 'auto'`, - controlType: 'switchableRange', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 0, min: -2000, @@ -116,10 +139,11 @@ const props: ChartProperty[] = [ { key: 'max', help: 'Maximum scale value.', + flavors: allFlavors, required: false, type: `number | 'auto'`, - controlType: 'switchableRange', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 1200, min: -2000, @@ -132,6 +156,7 @@ const props: ChartProperty[] = [ { key: 'yFormat', group: 'Base', + flavors: allFlavors, help: 'Optional formatter for y values.', description: ` The formatted value can then be used for labels & tooltips. @@ -145,58 +170,22 @@ const props: ChartProperty[] = [ `, required: false, type: 'Function | string', - controlType: 'valueFormat', - }, - { - key: 'width', - enableControlForFlavors: ['api'], - help: 'Chart width, not required when using responsive variant.', - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - help: 'Chart height, not required when using responsive variant.', - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', + control: { type: 'valueFormat' }, }, + ...chartDimensions(allFlavors), { key: 'curve', help: 'Curve interpolation.', + flavors: allFlavors, description: ` Defines the curve factory to use for the line generator. `, type: 'string', required: false, defaultValue: defaults.curve, - controlType: 'choices', group: 'Style', - controlOptions: { + control: { + type: 'choices', choices: lineCurvePropKeys.map((key: string) => ({ label: key, value: key, @@ -204,36 +193,34 @@ const props: ChartProperty[] = [ }, }, themeProperty(['svg', 'canvas', 'api']), - { - key: 'colors', - help: 'Defines color range.', - type: 'string | Function | string[]', - required: false, + ordinalColors({ + flavors: allFlavors, defaultValue: defaults.colors, - controlType: 'ordinalColors', - group: 'Style', - }, + }), { key: 'lineWidth', help: 'Line width.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.lineWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Style', }, { key: 'enableArea', help: 'Enable/disable area below each line.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaults.enableArea, - controlType: 'switch', + control: { type: 'switch' }, group: 'Style', }, { key: 'areaBaselineValue', help: 'Define the value to be used for area baseline.', + flavors: allFlavors, description: ` Define the value to be used for area baseline. Please note that this value isn't the @@ -243,9 +230,9 @@ const props: ChartProperty[] = [ type: 'number | string | Date', required: false, defaultValue: defaults.areaBaselineValue, - controlType: 'range', group: 'Style', - controlOptions: { + control: { + type: 'range', min: 0, max: 200, step: 10, @@ -254,31 +241,25 @@ const props: ChartProperty[] = [ { key: 'areaOpacity', help: 'Area opacity (0~1), depends on enableArea.', + flavors: allFlavors, required: false, defaultValue: defaults.areaOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Style', }, - { + blendMode({ key: 'areaBlendMode', + target: 'areas', flavors: ['svg'], - help: 'Defines CSS mix-blend-mode property.', - description: ` - Defines CSS \`mix-blend-mode\` property for areas, - see - [MDN documentation](https://developer.mozilla.org/fr/docs/Web/CSS/mix-blend-mode). - `, - type: 'string', - required: false, defaultValue: defaults.areaBlendMode, - controlType: 'blendMode', - group: 'Style', - }, + }), ...defsProperties('Style', ['svg']), { key: 'layers', group: 'Customization', + type: '(string | Component)[]', + flavors: allFlavors, help: 'Defines the order of layers and add custom layers.', description: ` You can also use this property to insert extra layers @@ -292,10 +273,11 @@ const props: ChartProperty[] = [ { key: 'enablePoints', help: 'Enable/disable points.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaults.enablePoints, - controlType: 'switch', + control: { type: 'switch' }, group: 'Points', }, { @@ -309,12 +291,13 @@ const props: ChartProperty[] = [ { key: 'pointSize', help: 'Size of the points.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.pointSize, group: 'Points', - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 2, max: 20, @@ -324,28 +307,31 @@ const props: ChartProperty[] = [ key: 'pointColor', help: 'Method to compute points color.', type: 'string | object | Function', + flavors: allFlavors, required: false, defaultValue: defaults.pointColor, group: 'Points', - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'pointBorderWidth', help: 'Width of the points border.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.pointBorderWidth, group: 'Points', - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'pointBorderColor', help: 'Method to compute points border color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaults.pointBorderColor, group: 'Points', - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'enablePointLabel', @@ -355,7 +341,7 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, defaultValue: defaults.enablePointLabel, - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'pointLabel', @@ -364,8 +350,8 @@ const props: ChartProperty[] = [ help: 'Property to use to determine point label. If a function is provided, it will receive current point data and should return the desired label.', type: 'string', required: false, - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: ['y', 'yFormatted', 'x', 'xFormatted', `d => \`\${d.x}: \${d.y}\``].map( choice => ({ label: choice, @@ -382,56 +368,24 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: -12, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: -24, max: 24, }, }, - { - key: 'enableGridX', - help: 'Enable/disable x grid.', - type: 'boolean', - required: false, - defaultValue: defaults.enableGridX, - controlType: 'switch', - group: 'Grid & Axes', - }, - { - key: 'gridXValues', - group: 'Grid & Axes', - help: 'Specify values to use for vertical grid lines.', - type: 'Array', - required: false, - }, - { - key: 'enableGridY', - help: 'Enable/disable y grid.', - type: 'boolean', - required: false, - defaultValue: defaults.enableGridY, - controlType: 'switch', - group: 'Grid & Axes', - }, - { - key: 'gridYValues', - group: 'Grid & Axes', - help: 'Specify values to use for horizontal grid lines.', - type: 'Array', - required: false, - }, - ...axesProperties(), - { - key: 'isInteractive', + ...chartGrid({ + flavors: allFlavors, + values: true, + xDefault: defaults.enableGridX, + yDefault: defaults.enableGridY, + }), + ...axes({ flavors: allFlavors }), + isInteractive({ flavors: ['svg', 'canvas'], - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: defaults.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'useMesh', flavors: ['svg'], @@ -439,7 +393,7 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, defaultValue: defaults.useMesh, - controlType: 'switch', + control: { type: 'switch' }, group: 'Interactivity', }, { @@ -449,7 +403,7 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, defaultValue: defaults.debugMesh, - controlType: 'switch', + control: { type: 'switch' }, group: 'Interactivity', }, { @@ -500,8 +454,8 @@ const props: ChartProperty[] = [ type: `'x' | 'y' | false`, required: false, defaultValue: defaults.enableSlicesTooltip, - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: [ { label: 'false', @@ -525,7 +479,7 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, defaultValue: defaults.debugSlices, - controlType: 'switch', + control: { type: 'switch' }, group: 'Interactivity', }, { @@ -543,7 +497,7 @@ const props: ChartProperty[] = [ help: 'Enable/disable crosshair.', type: 'boolean', required: false, - controlType: 'switch', + control: { type: 'switch' }, defaultValue: defaults.enableCrosshair, }, { @@ -554,8 +508,8 @@ const props: ChartProperty[] = [ defaultValue: defaults.crosshairType, help: `Crosshair type, forced to slices axis if enabled.`, type: 'string', - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', disabled: true, choices: [ 'x', @@ -581,13 +535,14 @@ const props: ChartProperty[] = [ type: 'object[]', help: `Optional chart's legends.`, group: 'Legends', - controlType: 'array', - controlOptions: { + required: false, + control: { + type: 'array', props: getLegendsProps(['svg', 'canvas']), shouldCreate: true, addLabel: 'add legend', shouldRemove: true, - getItemTitle: (index, legend) => + getItemTitle: (index, legend: any) => `legend[${index}]: ${legend.anchor}, ${legend.direction}`, defaults: { anchor: 'left', @@ -602,8 +557,8 @@ const props: ChartProperty[] = [ symbolShape: 'circle', itemDirection: 'left-to-right', itemTextColor: '#777', - onClick: data => { - alert(JSON.stringify(data, null, ' ')) + onClick: (data: any) => { + console.log(JSON.stringify(data, null, ' ')) }, effects: [ { diff --git a/website/src/data/components/marimekko/props.ts b/website/src/data/components/marimekko/props.ts index fc9af8a551..fef4e38cd3 100644 --- a/website/src/data/components/marimekko/props.ts +++ b/website/src/data/components/marimekko/props.ts @@ -1,18 +1,28 @@ import { defaultProps as defaults, offsetById } from '@nivo/marimekko' +import { OrdinalColorScaleConfig } from '@nivo/colors' import { themeProperty, defsProperties, groupProperties, getLegendsProps, motionProperties, - axesProperties, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { + chartDimensions, + ordinalColors, + chartGrid, + axes, + isInteractive, +} from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', + flavors: allFlavors, help: 'Chart data, which should be immutable.', description: ` The data doesn't have to conform to a specific schema, @@ -25,6 +35,7 @@ const props: ChartProperty[] = [ { key: 'id', group: 'Base', + flavors: allFlavors, help: 'ID accessor.', description: ` Define how to access the ID of each datum, @@ -36,6 +47,7 @@ const props: ChartProperty[] = [ { key: 'value', group: 'Base', + flavors: allFlavors, help: 'Value accessor.', description: ` Define how to access the value of each datum, @@ -48,6 +60,7 @@ const props: ChartProperty[] = [ { key: 'dimensions', group: 'Base', + flavors: allFlavors, help: 'Data dimensions configuration.', type: '{ id: string, value: string | (datum: RawDatum) => number }', required: true, @@ -55,6 +68,7 @@ const props: ChartProperty[] = [ { key: 'valueFormat', group: 'Base', + flavors: allFlavors, help: 'Optional formatter for values.', description: ` The formatted value can then be used for labels & tooltips. @@ -65,17 +79,18 @@ const props: ChartProperty[] = [ `, required: false, type: 'string | (value: number) => string | number', - controlType: 'valueFormat', + control: { type: 'valueFormat' }, }, { key: 'layout', help: `How to display bars.`, type: 'string', + flavors: allFlavors, required: false, defaultValue: defaults.layout, - controlType: 'radio', group: 'Base', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'horizontal', value: 'horizontal' }, { label: 'vertical', value: 'vertical' }, @@ -86,11 +101,12 @@ const props: ChartProperty[] = [ key: 'offset', help: 'Offset type.', type: 'OffsetId', + flavors: allFlavors, required: false, - controlType: 'choices', group: 'Base', defaultValue: defaults.offset, - controlOptions: { + control: { + type: 'choices', choices: Object.keys(offsetById).map(key => ({ label: key, value: key, @@ -100,12 +116,13 @@ const props: ChartProperty[] = [ { key: 'outerPadding', help: 'Space before the first bar and after the last one.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.outerPadding, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', min: 0, max: 20, unit: 'px', @@ -114,80 +131,30 @@ const props: ChartProperty[] = [ { key: 'innerPadding', help: 'Space between bars.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.innerPadding, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', min: 0, max: 20, unit: 'px', }, }, - { - key: 'width', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using - \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using - \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'margin', - group: 'Base', - type: 'object', - required: false, - help: 'Chart margin.', - flavors: ['svg', 'api'], - controlType: 'margin', - }, - themeProperty(['svg', 'api']), - { - key: 'colors', - group: 'Style', - type: 'string | Function | string[]', - required: false, - help: 'Defines color range.', - defaultValue: defaults.colors, - flavors: ['svg', 'api'], - controlType: 'ordinalColors', - }, - ...defsProperties('Style', ['svg', 'api']), + ...chartDimensions(allFlavors), + themeProperty(allFlavors), + ordinalColors({ + flavors: allFlavors, + defaultValue: defaults.colors as OrdinalColorScaleConfig, + }), + ...defsProperties('Style', allFlavors), { key: 'showcase pattern usage', flavors: ['svg'], help: 'Patterns.', + required: false, description: ` You can use \`defs\` and \`fill\` properties to use patterns, see @@ -195,64 +162,41 @@ const props: ChartProperty[] = [ for further information. `, type: 'boolean', - controlType: 'switch', + control: { type: 'switch' }, group: 'Style', }, { key: 'borderWidth', help: 'Slices border width.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.borderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Style', }, { key: 'borderColor', help: 'Method to compute border color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaults.borderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, - ...axesProperties(), - { - key: 'enableGridX', - help: 'Enable/disable x grid.', - type: 'boolean', - required: false, - defaultValue: defaults.enableGridX, - controlType: 'switch', - group: 'Grid & Axes', - }, - { - key: 'gridXValues', - group: 'Grid & Axes', - help: 'Specify values to use for vertical grid lines.', - type: 'number[]', - required: false, - }, - { - key: 'enableGridY', - help: 'Enable/disable y grid.', - type: 'boolean', - required: false, - defaultValue: defaults.enableGridY, - controlType: 'switch', - group: 'Grid & Axes', - }, - { - key: 'gridYValues', - group: 'Grid & Axes', - help: 'Specify values to use for horizontal grid lines.', - type: 'number[]', - required: false, - }, + ...chartGrid({ + flavors: allFlavors, + values: true, + xDefault: defaults.enableGridX, + yDefault: defaults.enableGridY, + }), + ...axes({ flavors: allFlavors }), { key: 'layers', group: 'Customization', help: 'Defines the order of layers and add custom layers.', + flavors: allFlavors, description: ` You can also use this to insert extra layers to the chart, the extra layer must be a component. @@ -276,16 +220,10 @@ const props: ChartProperty[] = [ type: 'Array', defaultValue: defaults.layers, }, - { - key: 'isInteractive', + isInteractive({ flavors: ['svg'], - group: 'Interactivity', - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: defaults.isInteractive, - controlType: 'switch', - }, + }), { key: 'onClick', flavors: ['svg'], @@ -321,6 +259,7 @@ const props: ChartProperty[] = [ { key: 'tooltip', group: 'Interactivity', + flavors: allFlavors, type: 'Component', required: false, help: 'Custom tooltip component', @@ -342,8 +281,10 @@ const props: ChartProperty[] = [ { key: 'custom tooltip example', help: 'Showcase custom tooltip.', + flavors: allFlavors, + required: false, type: 'boolean', - controlType: 'switch', + control: { type: 'switch' }, group: 'Interactivity', }, ...motionProperties(['svg'], defaults, 'react-spring'), @@ -353,13 +294,14 @@ const props: ChartProperty[] = [ type: 'Legend[]', help: `Optional chart's legends.`, group: 'Legends', - controlType: 'array', - controlOptions: { + required: false, + control: { + type: 'array', props: getLegendsProps(['svg']), shouldCreate: true, addLabel: 'add legend', shouldRemove: true, - getItemTitle: (index, legend) => + getItemTitle: (index, legend: any) => `legend[${index}]: ${legend.anchor}, ${legend.direction}`, defaults: { anchor: 'top-left', @@ -372,8 +314,8 @@ const props: ChartProperty[] = [ itemsSpacing: 0, symbolSize: 20, itemDirection: 'left-to-right', - onClick: data => { - alert(JSON.stringify(data, null, ' ')) + onClick: (data: any) => { + console.log(JSON.stringify(data, null, ' ')) }, }, }, diff --git a/website/src/data/components/network/props.ts b/website/src/data/components/network/props.ts index b8180bb682..bd802b3292 100644 --- a/website/src/data/components/network/props.ts +++ b/website/src/data/components/network/props.ts @@ -1,69 +1,13 @@ +// @ts-ignore import { NetworkDefaultProps } from '@nivo/network' import { motionProperties, groupProperties } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'canvas'] const props: ChartProperty[] = [ - { - key: 'width', - group: 'Base', - help: 'Chart width.', - description: ` - Not required if using responsive component. - `, - type: 'number', - required: true, - flavors: ['svg', 'canvas'], - enableControlForFlavors: ['api'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - group: 'Base', - help: 'Chart height.', - description: ` - Not required if using responsive component. - `, - type: 'number', - required: true, - flavors: ['svg', 'canvas'], - enableControlForFlavors: ['api'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - defaultValue: 'Depends on device', - type: `number`, - required: false, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, - { - key: 'margin', - group: 'Base', - type: 'object', - required: false, - help: 'Chart margin.', - flavors: ['svg', 'canvas'], - controlType: 'margin', - }, + ...chartDimensions(allFlavors), { key: 'linkDistance', group: 'Simulation', @@ -93,8 +37,8 @@ const props: ChartProperty[] = [ of \`distanceMin\` and \`distanceMax\`. `, flavors: ['svg', 'canvas'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 1, max: 100, }, @@ -130,8 +74,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: NetworkDefaultProps.iterations, flavors: ['svg', 'canvas'], - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 60, max: 260, }, @@ -152,7 +96,7 @@ const props: ChartProperty[] = [ help: `Control nodes' border width.`, defaultValue: NetworkDefaultProps.nodeBorderWidth, flavors: ['svg', 'canvas'], - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'nodeBorderColor', @@ -162,7 +106,7 @@ const props: ChartProperty[] = [ help: `Control nodes' border color.`, defaultValue: NetworkDefaultProps.nodeBorderColor, flavors: ['svg', 'canvas'], - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'linkThickness', @@ -173,7 +117,7 @@ const props: ChartProperty[] = [ help: `Control links' thickness.`, flavors: ['svg', 'canvas'], defaultValue: NetworkDefaultProps.linkThickness, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'linkColor', @@ -183,8 +127,8 @@ const props: ChartProperty[] = [ help: `Control links' color.`, defaultValue: NetworkDefaultProps.linkColor, flavors: ['svg', 'canvas'], - controlType: 'inheritedColor', - controlOptions: { + control: { + type: 'inheritedColor', inheritableProperties: ['source.color', 'target.color'], }, }, diff --git a/website/src/data/components/parallel-coordinates/props.ts b/website/src/data/components/parallel-coordinates/props.ts index 9f43136e4b..2ed492e6fe 100644 --- a/website/src/data/components/parallel-coordinates/props.ts +++ b/website/src/data/components/parallel-coordinates/props.ts @@ -1,11 +1,18 @@ +// @ts-ignore import { lineCurvePropKeys } from '@nivo/core' +// @ts-ignore import { commonDefaultProps as defaults } from '@nivo/parallel-coordinates' import { themeProperty, motionProperties, groupProperties } from '../../../lib/componentProperties' +import { chartDimensions, ordinalColors } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' -const props = [ +const allFlavors: Flavor[] = ['svg', 'canvas'] + +const props: ChartProperty[] = [ { key: 'data', group: 'Base', + flavors: allFlavors, help: 'Chart data.', type: 'Array', required: true, @@ -13,6 +20,7 @@ const props = [ { key: 'variables', type: 'object[]', + flavors: allFlavors, help: 'Variables configuration.', description: ` Variables configuration, define accessor (\`key\`) @@ -24,35 +32,44 @@ const props = [ discrete values such as gender. `, group: 'Variables', - controlType: 'array', - controlOptions: { + required: true, + control: { + type: 'array', shouldCreate: false, shouldRemove: false, - getItemTitle: (index, values) => `${values.key} (${values.type})`, + getItemTitle: (_index: number, values: any) => `${values.key} (${values.type})`, props: [ { key: 'key', help: 'Variable key, used to access to corresponding datum value.', - controlType: 'text', - controlOptions: { + flavors: allFlavors, + type: 'string', + required: true, + control: { + type: 'text', disabled: true, }, }, { key: 'type', help: `Variable type, must be one of: 'linear', 'point'.`, - controlType: 'text', - controlOptions: { + flavors: allFlavors, + type: `'linear' | 'point'`, + required: true, + control: { + type: 'text', disabled: true, }, }, { key: 'min', help: 'Min value of linear scale.', + flavors: allFlavors, type: `number | 'auto'`, - controlType: 'switchableRange', - controlOptions: { - when: ({ type }) => type === 'linear', + required: false, + when: ({ type }) => type === 'linear', + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 0, min: -100, @@ -62,10 +79,12 @@ const props = [ { key: 'max', help: 'Max value of linear scale.', + flavors: allFlavors, type: `number | 'auto'`, - controlType: 'switchableRange', - controlOptions: { - when: ({ type }) => type === 'linear', + required: false, + when: ({ type }) => type === 'linear', + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 1000, min: -100, @@ -90,12 +109,13 @@ const props = [ { key: 'layout', help: `Chart layout.`, + flavors: allFlavors, type: 'string', required: false, defaultValue: defaults.layout, - controlType: 'radio', group: 'Base', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'horizontal', value: 'horizontal' }, { label: 'vertical', value: 'vertical' }, @@ -105,16 +125,17 @@ const props = [ { key: 'curve', help: 'Curve interpolation.', + flavors: allFlavors, description: ` Defines the curve factory to use for the line generator. `, type: 'string', required: false, defaultValue: defaults.curve, - controlType: 'choices', group: 'Base', - controlOptions: { - choices: lineCurvePropKeys.map(key => ({ + control: { + type: 'choices', + choices: lineCurvePropKeys.map((key: string) => ({ label: key, value: key, })), @@ -123,12 +144,13 @@ const props = [ { key: 'axesPlan', help: `Axes plan.`, + flavors: allFlavors, type: `string`, required: false, defaultValue: defaults.axesPlan, - controlType: 'radio', group: 'Base', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'foreground', value: 'foreground' }, { label: 'background', value: 'background' }, @@ -138,104 +160,43 @@ const props = [ { key: 'axesTicksPosition', help: `Axes ticks position.`, + flavors: allFlavors, type: `string`, required: false, defaultValue: defaults.axesTicksPosition, - controlType: 'radio', group: 'Base', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'before', value: 'before' }, { label: 'after', value: 'after' }, ], }, }, - { - key: 'width', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using - \`ResponsiveParallelCoords\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using - \`ResponsiveParallelCoords\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, + ...chartDimensions(allFlavors), themeProperty(['svg', 'canvas']), - { - key: 'colors', - help: 'Defines color range.', - type: 'string | Function | string[]', - required: false, + ordinalColors({ + flavors: allFlavors, defaultValue: defaults.colors, - controlType: 'ordinalColors', - group: 'Style', - }, + }), { key: 'strokeWidth', help: 'Lines stroke width.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.strokeWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Style', }, { key: 'lineOpacity', help: 'Lines opacity.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.lineOpacity, - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Style', }, ...motionProperties(['svg'], defaults, 'react-spring'), diff --git a/website/src/data/components/parallel-coordinates/variables.js b/website/src/data/components/parallel-coordinates/variables.ts similarity index 100% rename from website/src/data/components/parallel-coordinates/variables.js rename to website/src/data/components/parallel-coordinates/variables.ts diff --git a/website/src/data/components/pie/props.ts b/website/src/data/components/pie/props.ts index 84fe9e7126..a46ee2d2d5 100644 --- a/website/src/data/components/pie/props.ts +++ b/website/src/data/components/pie/props.ts @@ -7,12 +7,16 @@ import { getLegendsProps, motionProperties, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions, ordinalColors, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'canvas', 'api'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', + flavors: allFlavors, help: 'Chart data, which should be immutable.', description: ` Chart data, which must conform to this structure @@ -40,6 +44,7 @@ const props: ChartProperty[] = [ { key: 'id', group: 'Base', + flavors: allFlavors, help: 'ID accessor which should return a unique value for the whole dataset.', description: ` Define how to access the ID of each datum, @@ -52,6 +57,7 @@ const props: ChartProperty[] = [ { key: 'value', group: 'Base', + flavors: allFlavors, help: 'Value accessor.', description: ` Define how to access the value of each datum, @@ -64,6 +70,7 @@ const props: ChartProperty[] = [ { key: 'valueFormat', group: 'Base', + flavors: allFlavors, help: 'Optional formatter for values.', description: ` The formatted value can then be used for labels & tooltips. @@ -74,70 +81,19 @@ const props: ChartProperty[] = [ `, required: false, type: 'string | (value: number) => string | number', - controlType: 'valueFormat', - }, - { - key: 'width', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using - \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using - \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, + control: { type: 'valueFormat' }, }, + ...chartDimensions(allFlavors), { key: 'startAngle', help: 'Start angle (in degrees), useful to make gauges for example.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.startAngle, group: 'Base', - controlType: 'angle', - controlOptions: { - unit: '°', + control: { + type: 'angle', min: -180, max: 360, step: 5, @@ -146,13 +102,13 @@ const props: ChartProperty[] = [ { key: 'endAngle', help: 'End angle (in degrees), useful to make gauges for example.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.endAngle, group: 'Base', - controlType: 'angle', - controlOptions: { - unit: '°', + control: { + type: 'angle', min: -360, max: 360, step: 5, @@ -161,21 +117,23 @@ const props: ChartProperty[] = [ { key: 'fit', help: `If 'true', pie will be optimized to occupy more space when using partial pie.`, + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultProps.fit, - controlType: 'switch', + control: { type: 'switch' }, group: 'Base', }, { key: 'innerRadius', help: `Donut chart if greater than 0. Value should be between 0~1 as it's a ratio from original radius.`, + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.innerRadius, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', min: 0, max: 0.95, step: 0.05, @@ -184,12 +142,13 @@ const props: ChartProperty[] = [ { key: 'padAngle', help: 'Padding between each pie slice.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.padAngle, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', unit: '°', min: 0, max: 45, @@ -199,12 +158,13 @@ const props: ChartProperty[] = [ { key: 'cornerRadius', help: 'Rounded slices.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.cornerRadius, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 45, @@ -214,30 +174,18 @@ const props: ChartProperty[] = [ { key: 'sortByValue', help: `If 'true', arcs will be ordered according to their associated value.`, + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultProps.sortByValue, - controlType: 'switch', + control: { type: 'switch' }, group: 'Base', }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, - themeProperty(['svg', 'canvas', 'api']), - { - key: 'colors', - help: 'Defines color range.', - type: 'string | Function | string[]', - required: false, + themeProperty(allFlavors), + ordinalColors({ + flavors: allFlavors, defaultValue: defaultProps.colors, - controlType: 'ordinalColors', - group: 'Style', - }, + }), ...defsProperties('Style', ['svg', 'api']), { key: 'showcase pattern usage', @@ -249,46 +197,51 @@ const props: ChartProperty[] = [ [dedicated guide](self:/guides/patterns) for further information. `, + required: false, type: 'boolean', - controlType: 'switch', + control: { type: 'switch' }, group: 'Style', }, { key: 'borderWidth', help: 'Slices border width.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.borderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Style', }, { key: 'borderColor', help: 'Method to compute border color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaultProps.borderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, { key: 'enableArcLabels', help: 'Enable/disable arc labels.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultProps.enableArcLabels, - controlType: 'switch', + control: { type: 'switch' }, group: 'Arc labels', }, { key: 'arcLabel', help: 'Defines how to get label text, can be a string (used to access current node data property) or a function which will receive the actual node data.', + flavors: allFlavors, type: 'string | Function', required: false, defaultValue: defaultProps.arcLabel, - controlType: 'choices', group: 'Arc labels', - controlOptions: { + control: { + type: 'choices', choices: ['id', 'value', 'formattedValue', `d => \`\${d.id} (\${d.value})\``].map( choice => ({ label: choice, @@ -303,12 +256,13 @@ const props: ChartProperty[] = [ Define the radius to use to determine the label position, starting from inner radius, this is expressed as a ratio. `, + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.arcLabelsRadiusOffset, - controlType: 'range', group: 'Arc labels', - controlOptions: { + control: { + type: 'range', min: 0, max: 2, step: 0.05, @@ -317,12 +271,13 @@ const props: ChartProperty[] = [ { key: 'arcLabelsSkipAngle', help: `Skip label if corresponding arc's angle is lower than provided value.`, + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.arcLabelsSkipAngle, - controlType: 'range', group: 'Arc labels', - controlOptions: { + control: { + type: 'range', unit: '°', min: 0, max: 45, @@ -332,24 +287,27 @@ const props: ChartProperty[] = [ { key: 'arcLabelsTextColor', help: 'Defines how to compute arc label text color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaultProps.arcLabelsTextColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Arc labels', }, { key: 'enableArcLinkLabels', help: 'Enable/disable arc link labels.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultProps.enableArcLinkLabels, - controlType: 'switch', + control: { type: 'switch' }, group: 'Arc link labels', }, { key: 'arcLinkLabel', help: 'Arc link label', + flavors: allFlavors, description: ` Defines how to get label text, can be a string (used to access current node data property) @@ -358,9 +316,9 @@ const props: ChartProperty[] = [ type: 'string | Function', required: false, defaultValue: defaultProps.arcLinkLabel, - controlType: 'choices', group: 'Arc link labels', - controlOptions: { + control: { + type: 'choices', choices: ['id', 'value', `d => \`\${d.id} (\${d.value})\``].map(choice => ({ label: choice, value: choice, @@ -370,12 +328,13 @@ const props: ChartProperty[] = [ { key: 'arcLinkLabelsSkipAngle', help: `Skip label if corresponding slice's angle is lower than provided value.`, + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.arcLinkLabelsSkipAngle, - controlType: 'range', group: 'Arc link labels', - controlOptions: { + control: { + type: 'range', unit: '°', min: 0, max: 45, @@ -385,12 +344,13 @@ const props: ChartProperty[] = [ { key: 'arcLinkLabelsOffset', help: `Link offset from pie outer radius, useful to have links overlapping pie slices.`, + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.arcLinkLabelsOffset, - controlType: 'range', group: 'Arc link labels', - controlOptions: { + control: { + type: 'range', unit: 'px', min: -24, max: 24, @@ -400,12 +360,13 @@ const props: ChartProperty[] = [ { key: 'arcLinkLabelsDiagonalLength', help: `Link diagonal length.`, + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.arcLinkLabelsDiagonalLength, - controlType: 'range', group: 'Arc link labels', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 36, @@ -415,12 +376,13 @@ const props: ChartProperty[] = [ { key: 'arcLinkLabelsStraightLength', help: `Length of the straight segment of the links.`, + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.arcLinkLabelsStraightLength, - controlType: 'range', group: 'Arc link labels', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 36, @@ -430,12 +392,13 @@ const props: ChartProperty[] = [ { key: 'arcLinkLabelsTextOffset', help: `X offset from links' end.`, + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.arcLinkLabelsTextOffset, - controlType: 'range', group: 'Arc link labels', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 36, @@ -445,34 +408,38 @@ const props: ChartProperty[] = [ { key: 'arcLinkLabelsThickness', help: 'Links stroke width.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.arcLinkLabelsThickness, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Arc link labels', }, { key: 'arcLinkLabelsTextColor', help: 'Defines how to compute arc link label text color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaultProps.arcLinkLabelsTextColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Arc link labels', }, { key: 'arcLinkLabelsColor', help: 'Defines how to compute arc link label link color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaultProps.arcLinkLabelsColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Arc link labels', }, { key: 'layers', group: 'Customization', help: 'Defines the order of layers and add custom layers.', + flavors: allFlavors, description: ` You can also use this to insert extra layers to the chart, the extra layer must be a function. @@ -507,16 +474,10 @@ const props: ChartProperty[] = [ type: 'Array', defaultValue: defaultProps.layers, }, - { - key: 'isInteractive', + isInteractive({ flavors: ['svg', 'canvas'], - group: 'Interactivity', - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: defaultProps.isInteractive, - controlType: 'switch', - }, + }), { key: 'activeInnerRadiusOffset', flavors: ['svg', 'canvas'], @@ -524,9 +485,9 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaultProps.activeInnerRadiusOffset, - controlType: 'range', group: 'Interactivity', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 50, @@ -539,9 +500,9 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaultProps.activeOuterRadiusOffset, - controlType: 'range', group: 'Interactivity', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 50, @@ -606,7 +567,8 @@ const props: ChartProperty[] = [ flavors: ['svg', 'canvas'], help: 'Showcase custom tooltip.', type: 'boolean', - controlType: 'switch', + required: false, + control: { type: 'switch' }, group: 'Interactivity', }, ...motionProperties(['svg'], defaultProps, 'react-spring'), @@ -617,9 +579,9 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: defaultProps.transitionMode, - controlType: 'choices', group: 'Motion', - controlOptions: { + control: { + type: 'choices', choices: arcTransitionModes.map(choice => ({ label: choice, value: choice, @@ -632,13 +594,14 @@ const props: ChartProperty[] = [ type: 'Legend[]', help: `Optional chart's legends.`, group: 'Legends', - controlType: 'array', - controlOptions: { + required: false, + control: { + type: 'array', props: getLegendsProps(['svg', 'canvas']), shouldCreate: true, addLabel: 'add legend', shouldRemove: true, - getItemTitle: (index, legend) => + getItemTitle: (index, legend: any) => `legend[${index}]: ${legend.anchor}, ${legend.direction}`, defaults: { anchor: 'top-left', @@ -651,8 +614,8 @@ const props: ChartProperty[] = [ itemsSpacing: 0, symbolSize: 20, itemDirection: 'left-to-right', - onClick: data => { - alert(JSON.stringify(data, null, ' ')) + onClick: (data: any) => { + console.log(JSON.stringify(data, null, ' ')) }, }, }, diff --git a/website/src/data/components/radar/props.ts b/website/src/data/components/radar/props.ts index c4782d539a..2de5cccfdb 100644 --- a/website/src/data/components/radar/props.ts +++ b/website/src/data/components/radar/props.ts @@ -6,7 +6,15 @@ import { groupProperties, defsProperties, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { + chartDimensions, + ordinalColors, + blendMode, + isInteractive, +} from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'api'] const props: ChartProperty[] = [ { @@ -31,7 +39,7 @@ const props: ChartProperty[] = [ skills for each user by language (3 layers and 4 dimensions). `, - flavors: ['svg', 'api'], + flavors: allFlavors, }, { key: 'indexBy', @@ -43,7 +51,7 @@ const props: ChartProperty[] = [ Key to use to index the data, this key must exist in each data item. `, - flavors: ['svg', 'api'], + flavors: allFlavors, }, { key: 'keys', @@ -55,7 +63,7 @@ const props: ChartProperty[] = [ Keys to use to determine each serie. Those keys should exist in each data item. `, - flavors: ['svg', 'api'], + flavors: allFlavors, }, { key: 'maxValue', @@ -68,10 +76,10 @@ const props: ChartProperty[] = [ will use max value from the provided data. `, - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.maxValue, - controlType: 'switchableRange', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 200, min: 0, @@ -91,8 +99,8 @@ const props: ChartProperty[] = [ please have a look at it for available formats, you can also pass a function which will receive the raw value and should return the formatted one. `, - flavors: ['svg', 'api'], - controlType: 'valueFormat', + flavors: allFlavors, + control: { type: 'valueFormat' }, }, { key: 'curve', @@ -105,104 +113,45 @@ const props: ChartProperty[] = [ for the line generator. `, defaultValue: svgDefaultProps.curve, - flavors: ['svg', 'api'], - controlType: 'choices', - controlOptions: { + flavors: allFlavors, + control: { + type: 'choices', choices: closedCurvePropKeys.map((key: string) => ({ label: key, value: key, })), }, }, - { - key: 'width', - group: 'Base', - type: 'number', - required: true, - help: 'Chart width.', - description: ` - not required if using - \`\`. - `, - flavors: ['svg', 'api'], - enableControlForFlavors: ['api'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - group: 'Base', - type: 'number', - required: true, - help: 'Chart height.', - description: ` - not required if using - \`\`. - `, - flavors: ['svg', 'api'], - enableControlForFlavors: ['api'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'margin', - group: 'Base', - help: 'Chart margin.', - type: 'object', - required: false, - flavors: ['svg', 'api'], - controlType: 'margin', - }, + ...chartDimensions(allFlavors), themeProperty(['svg', 'api']), - { - key: 'colors', - group: 'Style', - type: 'string | Function | string[]', - required: false, - help: 'Defines how to compute colors.', + ordinalColors({ + flavors: allFlavors, defaultValue: svgDefaultProps.colors, - flavors: ['svg', 'api'], - controlType: 'ordinalColors', - }, + }), { key: 'fillOpacity', group: 'Style', type: 'number', required: false, help: 'Shape fill opacity.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.fillOpacity, - controlType: 'opacity', + control: { type: 'opacity' }, }, - { - key: 'blendMode', - group: 'Style', - type: 'string', - required: false, - help: 'Defines CSS [mix-blend-mode](https://developer.mozilla.org/fr/docs/Web/CSS/mix-blend-mode) for shapes.', + blendMode({ + target: 'layers', flavors: ['svg'], defaultValue: svgDefaultProps.blendMode, - controlType: 'blendMode', - }, + }), { key: 'borderWidth', group: 'Style', type: 'number', required: false, help: 'Shape border width.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.borderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'borderColor', @@ -210,9 +159,9 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, help: 'Method to compute border color.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.borderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, ...defsProperties('Style', ['svg']), { @@ -221,10 +170,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, help: 'Number of levels to display for grid', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.gridLevels, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 1, max: 12, }, @@ -235,10 +184,10 @@ const props: ChartProperty[] = [ type: 'string', required: false, help: 'Determine shape of the grid.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.gridShape, - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: [ { label: 'circular', value: 'circular' }, { label: 'linear', value: 'linear' }, @@ -277,10 +226,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, help: 'Label offset from outer radius.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.gridLabelOffset, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 60, @@ -292,9 +241,9 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, help: 'Enable/disable dots.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.enableDots, - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'dotSymbol', @@ -316,10 +265,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, help: 'Size of the dots.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.dotSize, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 2, max: 64, @@ -330,9 +279,9 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, help: 'Method to compute dots color.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.dotColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Dots', }, { @@ -341,10 +290,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, help: 'Width of the dots border.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.dotBorderWidth, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 10, @@ -356,9 +305,9 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, help: 'Method to compute dots border color.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.dotBorderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'enableDotLabel', @@ -366,9 +315,9 @@ const props: ChartProperty[] = [ help: 'Enable/disable dots label.', type: 'boolean', required: false, - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.enableDotLabel, - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'dotLabel', @@ -380,8 +329,8 @@ const props: ChartProperty[] = [ 'Property to use to determine dot label. If a function is provided, it will receive current value and serie and must return a label.', flavors: ['svg'], defaultValue: svgDefaultProps.dotLabel, - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: [ 'value', 'formattedValue', @@ -401,10 +350,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, help: 'Label Y offset from dot shape.', - flavors: ['svg', 'api'], + flavors: allFlavors, defaultValue: svgDefaultProps.dotLabelYOffset, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: -24, max: 24, @@ -426,16 +375,10 @@ const props: ChartProperty[] = [ flavors: ['svg'], defaultValue: svgDefaultProps.layers, }, - { - key: 'isInteractive', - group: 'Interactivity', - type: 'boolean', - required: false, - help: 'Enable/disable interactivity.', + isInteractive({ flavors: ['svg'], defaultValue: svgDefaultProps.isInteractive, - controlType: 'switch', - }, + }), { key: 'sliceTooltip', group: 'Interactivity', diff --git a/website/src/data/components/radial-bar/props.ts b/website/src/data/components/radial-bar/props.ts index f924b2b99c..9554b8cdc2 100644 --- a/website/src/data/components/radial-bar/props.ts +++ b/website/src/data/components/radial-bar/props.ts @@ -7,7 +7,10 @@ import { getLegendsProps, polarAxisProperty, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions, ordinalColors, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg'] const props: ChartProperty[] = [ { @@ -69,7 +72,7 @@ const props: ChartProperty[] = [ You might read those values when adding an \`onClick\` handler for example, or when customizing the tooltip. `, - flavors: ['svg'], + flavors: allFlavors, }, { key: 'maxValue', @@ -77,7 +80,7 @@ const props: ChartProperty[] = [ type: `'auto' | number`, required: false, help: `If 'auto', the max value is derived from the data, otherwise use a static value.`, - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.maxValue, }, { @@ -93,68 +96,20 @@ const props: ChartProperty[] = [ please have a look at it for available formats, you can also pass a function which will receive the raw value and should return the formatted one. `, - flavors: ['svg'], - controlType: 'valueFormat', - }, - { - key: 'width', - group: 'Base', - type: 'number', - required: true, - help: 'Chart width.', - description: ` - not required if using - \`\`. - `, - flavors: ['svg', 'api'], - enableControlForFlavors: ['api'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - group: 'Base', - type: 'number', - required: true, - help: 'Chart height.', - description: ` - not required if using - \`\`. - `, - flavors: ['svg', 'api'], - enableControlForFlavors: ['api'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'margin', - group: 'Base', - help: 'Chart margin.', - type: 'object', - required: false, - flavors: ['svg'], - controlType: 'margin', + flavors: allFlavors, + control: { type: 'valueFormat' }, }, + ...chartDimensions(allFlavors), { key: 'startAngle', group: 'Base', type: 'number', required: false, help: 'Start angle (in degrees).', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.startAngle, - controlType: 'angle', - controlOptions: { + control: { + type: 'angle', min: -360, max: 360, step: 5, @@ -166,10 +121,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, help: 'End angle (in degrees).', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.endAngle, - controlType: 'angle', - controlOptions: { + control: { + type: 'angle', min: -360, max: 360, step: 5, @@ -181,10 +136,10 @@ const props: ChartProperty[] = [ help: `Donut if greater than 0. Value should be between 0~1 as it's a ratio from outer radius.`, type: 'number', required: false, - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.innerRadius, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 0.95, step: 0.05, @@ -196,10 +151,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, help: 'Padding between each ring (ratio).', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.padding, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 0.9, step: 0.05, @@ -211,10 +166,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, help: 'Padding between each bar.', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.padAngle, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: '°', min: 0, max: 45, @@ -227,10 +182,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, help: 'Rounded corners.', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.cornerRadius, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 45, @@ -238,25 +193,19 @@ const props: ChartProperty[] = [ }, }, themeProperty(['svg']), - { - key: 'colors', - group: 'Style', - type: 'string | Function | string[]', - required: false, - help: 'Defines how to compute colors.', - flavors: ['svg'], + ordinalColors({ + flavors: allFlavors, defaultValue: svgDefaultProps.colors, - controlType: 'ordinalColors', - }, + }), { key: 'borderWidth', group: 'Style', type: 'number', required: false, help: 'Bars border width.', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.borderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'borderColor', @@ -268,9 +217,9 @@ const props: ChartProperty[] = [ how to compute border color, [see dedicated documentation](self:/guides/colors). `, - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.borderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'enableTracks', @@ -278,9 +227,9 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, help: 'Enable/disable tracks.', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.enableTracks, - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'tracksColor', @@ -288,9 +237,9 @@ const props: ChartProperty[] = [ type: 'string', required: false, help: 'Define tracks color.', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.tracksColor, - controlType: 'colorPicker', + control: { type: 'colorPicker' }, }, { key: 'enableRadialGrid', @@ -298,9 +247,9 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, help: 'Enable radial grid (rays)', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.enableRadialGrid, - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'enableCircularGrid', @@ -308,28 +257,28 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, help: 'Enable circular grid (rings)', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.enableCircularGrid, - controlType: 'switch', + control: { type: 'switch' }, }, polarAxisProperty({ key: 'radialAxisStart', - flavors: ['svg'], + flavors: allFlavors, tickComponent: 'RadialAxisTickComponent', }), polarAxisProperty({ key: 'radialAxisEnd', - flavors: ['svg'], + flavors: allFlavors, tickComponent: 'RadialAxisTickComponent', }), polarAxisProperty({ key: 'circularAxisInner', - flavors: ['svg'], + flavors: allFlavors, tickComponent: 'CircularAxisTickComponent', }), polarAxisProperty({ key: 'circularAxisOuter', - flavors: ['svg'], + flavors: allFlavors, tickComponent: 'CircularAxisTickComponent', }), { @@ -338,9 +287,9 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, help: 'Enable/disable labels.', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.enableLabels, - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'label', @@ -348,10 +297,10 @@ const props: ChartProperty[] = [ type: 'string | (bar: ComputedBar) => string', required: false, help: 'Defines how to get label text, can be a string (used to access current bar property) or a function which will receive the actual bar data.', - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.label, - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: ['category', 'groupId', 'value', 'formattedValue'].map(choice => ({ label: choice, value: choice, @@ -364,10 +313,10 @@ const props: ChartProperty[] = [ type: 'number', required: false, help: `Skip label if corresponding arc's angle is lower than provided value.`, - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.labelsSkipAngle, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: '°', min: 0, max: 45, @@ -383,10 +332,10 @@ const props: ChartProperty[] = [ Define the radius to use to determine the label position, starting from inner radius, this is expressed as a ratio. Centered at 0.5 by default. `, - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.labelsRadiusOffset, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 2, step: 0.05, @@ -398,9 +347,9 @@ const props: ChartProperty[] = [ help: 'Defines how to compute label text color.', type: 'string | object | Function', required: false, - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.labelsTextColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'layers', @@ -416,26 +365,20 @@ const props: ChartProperty[] = [ the \`RadialBarCustomLayerProps\` interface and must return a valid SVG element. `, - flavors: ['svg'], + flavors: allFlavors, defaultValue: svgDefaultProps.layers, }, - { - key: 'isInteractive', - group: 'Interactivity', - type: 'boolean', - required: false, - help: 'Enable/disable interactivity.', - flavors: ['svg'], + isInteractive({ + flavors: allFlavors, defaultValue: svgDefaultProps.isInteractive, - controlType: 'switch', - }, + }), { key: 'tooltip', group: 'Interactivity', type: 'RadialBarTooltipComponent', required: false, help: 'Override default tooltip.', - flavors: ['svg'], + flavors: allFlavors, }, { key: 'onClick', @@ -443,7 +386,7 @@ const props: ChartProperty[] = [ type: '(bar: ComputedBar, event: MouseEvent) => void', required: false, help: 'onClick handler.', - flavors: ['svg'], + flavors: allFlavors, }, { key: 'onMouseEnter', @@ -451,7 +394,7 @@ const props: ChartProperty[] = [ type: '(bar: ComputedBar, event: MouseEvent) => void', required: false, help: 'onMouseEnter handler.', - flavors: ['svg'], + flavors: allFlavors, }, { key: 'onMouseMove', @@ -459,7 +402,7 @@ const props: ChartProperty[] = [ type: '(bar: ComputedBar, event: MouseEvent) => void', required: false, help: 'onMouseMove handler.', - flavors: ['svg'], + flavors: allFlavors, }, { key: 'onMouseLeave', @@ -467,7 +410,7 @@ const props: ChartProperty[] = [ type: '(bar: ComputedBar, event: MouseEvent) => void', required: false, help: 'onMouseLeave handler.', - flavors: ['svg'], + flavors: allFlavors, }, { key: 'legends', @@ -475,16 +418,16 @@ const props: ChartProperty[] = [ type: 'LegendProps[]', required: false, help: `Optional chart's legends.`, - flavors: ['svg'], - controlType: 'array', - controlOptions: { + flavors: allFlavors, + control: { + type: 'array', props: getLegendsProps(['svg']), shouldCreate: true, addLabel: 'add legend', shouldRemove: true, - getItemTitle: (index, legend) => + getItemTitle: (index, legend: any) => `legend[${index}]: ${legend.anchor}, ${legend.direction}`, - svgDefaultProps: { + defaults: { dataFrom: 'keys', anchor: 'top-left', direction: 'column', @@ -496,8 +439,8 @@ const props: ChartProperty[] = [ itemsSpacing: 0, symbolSize: 20, itemDirection: 'left-to-right', - onClick: data => { - alert(JSON.stringify(data, null, ' ')) + onClick: (data: any) => { + console.log(JSON.stringify(data, null, ' ')) }, }, }, @@ -508,7 +451,7 @@ const props: ChartProperty[] = [ type: 'string', required: false, help: 'Main element role attribute.', - flavors: ['svg'], + flavors: allFlavors, }, { key: 'ariaLabel', @@ -516,7 +459,7 @@ const props: ChartProperty[] = [ type: 'string', required: false, help: 'Main element [aria-label](https://www.w3.org/TR/wai-aria/#aria-label).', - flavors: ['svg'], + flavors: allFlavors, }, { key: 'ariaLabelledBy', @@ -524,7 +467,7 @@ const props: ChartProperty[] = [ type: 'string', required: false, help: 'Main element [aria-labelledby](https://www.w3.org/TR/wai-aria/#aria-labelledby).', - flavors: ['svg'], + flavors: allFlavors, }, { key: 'ariaDescribedBy', @@ -532,19 +475,19 @@ const props: ChartProperty[] = [ type: 'string', required: false, help: 'Main element [aria-describedby](https://www.w3.org/TR/wai-aria/#aria-describedby).', - flavors: ['svg'], + flavors: allFlavors, }, - ...motionProperties(['svg'], svgDefaultProps, 'react-spring'), + ...motionProperties(allFlavors, svgDefaultProps, 'react-spring'), { key: 'transitionMode', - flavors: ['svg'], + flavors: allFlavors, help: 'Define how transitions behave.', type: 'string', required: false, defaultValue: svgDefaultProps.transitionMode, - controlType: 'choices', group: 'Motion', - controlOptions: { + control: { + type: 'choices', choices: arcTransitionModes.map(choice => ({ label: choice, value: choice, diff --git a/website/src/data/components/sankey/props.ts b/website/src/data/components/sankey/props.ts index 0c0f74e474..ed9d07cea4 100644 --- a/website/src/data/components/sankey/props.ts +++ b/website/src/data/components/sankey/props.ts @@ -1,6 +1,14 @@ import { svgDefaultProps, sankeyAlignmentPropKeys } from '@nivo/sankey' import { themeProperty, motionProperties, groupProperties } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { + chartDimensions, + ordinalColors, + blendMode, + isInteractive, +} from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'api'] const props: ChartProperty[] = [ { @@ -9,7 +17,7 @@ const props: ChartProperty[] = [ type: '{ nodes: object[], links: object[] }', required: true, help: 'Chart data defining nodes and links.', - flavors: ['svg', 'api'], + flavors: allFlavors, description: ` Chart data, which must conform to this structure: @@ -40,8 +48,8 @@ const props: ChartProperty[] = [ please have a look at it for available formats, you can also pass a function which will receive the raw value and should return the formatted one. `, - flavors: ['svg', 'api'], - controlType: 'valueFormat', + flavors: allFlavors, + control: { type: 'valueFormat' }, }, { key: 'layout', @@ -50,9 +58,9 @@ const props: ChartProperty[] = [ required: false, help: `Control sankey layout direction.`, defaultValue: svgDefaultProps.layout, - flavors: ['svg', 'api'], - controlType: 'radio', - controlOptions: { + flavors: allFlavors, + control: { + type: 'radio', choices: [ { label: 'horizontal', value: 'horizontal' }, { label: 'vertical', value: 'vertical' }, @@ -72,9 +80,9 @@ const props: ChartProperty[] = [ for further information. `, defaultValue: svgDefaultProps.align, - flavors: ['svg', 'api'], - controlType: 'choices', - controlOptions: { + flavors: allFlavors, + control: { + type: 'choices', choices: sankeyAlignmentPropKeys.map((key: string) => ({ label: key, value: key, @@ -102,75 +110,21 @@ const props: ChartProperty[] = [ for further information. `, defaultValue: svgDefaultProps.sort, - flavors: ['svg', 'api'], - controlType: 'choices', - controlOptions: { + flavors: allFlavors, + control: { + type: 'choices', choices: ['auto', 'input', 'ascending', 'descending'].map(key => ({ label: key, value: key, })), }, }, - { - key: 'width', - group: 'Base', - type: 'number', - required: true, - help: 'Chart width.', - description: ` - not required if using - \`\`. - `, - flavors: ['svg', 'api'], - enableControlForFlavors: ['api'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1200, - step: 5, - }, - }, - { - key: 'height', - group: 'Base', - type: 'number', - required: true, - help: 'Chart height.', - description: ` - not required if using - \`\`. - `, - flavors: ['svg', 'api'], - enableControlForFlavors: ['api'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1200, - step: 5, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - group: 'Base', - flavors: ['svg', 'api'], - controlType: 'margin', - }, - themeProperty(['svg', 'api']), - { - key: 'colors', - group: 'Style', - type: 'string | Function | string[]', - required: false, - help: 'Defines how to compute nodes color.', + ...chartDimensions(allFlavors), + themeProperty(allFlavors), + ordinalColors({ + flavors: allFlavors, defaultValue: svgDefaultProps.colors, - flavors: ['svg', 'api'], - controlType: 'ordinalColors', - }, + }), { key: 'nodeThickness', group: 'Nodes', @@ -178,9 +132,9 @@ const props: ChartProperty[] = [ required: false, help: 'Node thickness.', defaultValue: svgDefaultProps.nodeThickness, - flavors: ['svg', 'api'], - controlType: 'range', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', unit: 'px', min: 2, max: 100, @@ -193,8 +147,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.nodeOpacity, type: 'number', - flavors: ['svg', 'api'], - controlType: 'opacity', + flavors: allFlavors, + control: { type: 'opacity' }, }, { key: 'nodeHoverOpacity', @@ -204,7 +158,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.nodeHoverOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'nodeHoverOthersOpacity', @@ -213,7 +167,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.nodeHoverOthersOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Nodes', }, { @@ -223,9 +177,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.nodeSpacing, type: 'number', - flavors: ['svg', 'api'], - controlType: 'range', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', unit: 'px', min: 0, max: 60, @@ -238,9 +192,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.nodeInnerPadding, type: 'number', - flavors: ['svg', 'api'], - controlType: 'range', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', unit: 'px', min: 0, max: 20, @@ -253,8 +207,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.nodeBorderWidth, type: 'number', - flavors: ['svg', 'api'], - controlType: 'lineWidth', + flavors: allFlavors, + control: { type: 'lineWidth' }, }, { key: 'nodeBorderColor', @@ -267,8 +221,8 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, defaultValue: svgDefaultProps.nodeBorderColor, - flavors: ['svg', 'api'], - controlType: 'inheritedColor', + flavors: allFlavors, + control: { type: 'inheritedColor' }, }, { key: 'nodeBorderRadius', @@ -277,9 +231,9 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: svgDefaultProps.nodeBorderRadius, - flavors: ['svg', 'api'], - controlType: 'range', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', unit: 'px', min: 0, max: 12, @@ -292,8 +246,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.linkOpacity, type: 'number', - flavors: ['svg', 'api'], - controlType: 'opacity', + flavors: allFlavors, + control: { type: 'opacity' }, }, { key: 'linkHoverOpacity', @@ -303,7 +257,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.linkHoverOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'linkHoverOthersOpacity', @@ -313,7 +267,7 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.linkHoverOthersOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'linkContract', @@ -322,24 +276,21 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.linkContract, type: 'number', - flavors: ['svg', 'api'], - controlType: 'range', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', unit: 'px', min: 0, max: 60, }, }, - { + blendMode({ key: 'linkBlendMode', + target: 'links', flavors: ['svg'], - help: 'Defines CSS [mix-blend-mode](https://developer.mozilla.org/fr/docs/Web/CSS/mix-blend-mode) property for links.', - type: 'string', - required: false, - defaultValue: svgDefaultProps.linkBlendMode, - controlType: 'blendMode', group: 'Links', - }, + defaultValue: svgDefaultProps.linkBlendMode, + }), { key: 'enableLinkGradient', group: 'Links', @@ -347,8 +298,8 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, defaultValue: svgDefaultProps.enableLinkGradient, - flavors: ['svg', 'api'], - controlType: 'switch', + flavors: allFlavors, + control: { type: 'switch' }, }, { key: 'enableLabels', @@ -357,8 +308,8 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, defaultValue: svgDefaultProps.enableLabels, - flavors: ['svg', 'api'], - controlType: 'switch', + flavors: allFlavors, + control: { type: 'switch' }, }, { key: 'labelPosition', @@ -367,9 +318,9 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: svgDefaultProps.labelPosition, - flavors: ['svg', 'api'], - controlType: 'radio', - controlOptions: { + flavors: allFlavors, + control: { + type: 'radio', choices: ['inside', 'outside'].map(key => ({ label: key, value: key, @@ -383,9 +334,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: svgDefaultProps.labelPadding, type: 'number', - flavors: ['svg', 'api'], - controlType: 'range', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', unit: 'px', min: 0, max: 60, @@ -402,8 +353,8 @@ const props: ChartProperty[] = [ type: 'string | object | Function', required: false, defaultValue: svgDefaultProps.labelTextColor, - flavors: ['svg', 'api'], - controlType: 'inheritedColor', + flavors: allFlavors, + control: { type: 'inheritedColor' }, }, { key: 'labelOrientation', @@ -412,25 +363,19 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: svgDefaultProps.labelOrientation, - flavors: ['svg', 'api'], - controlType: 'radio', - controlOptions: { + flavors: allFlavors, + control: { + type: 'radio', choices: ['horizontal', 'vertical'].map((key: string) => ({ label: key, value: key, })), }, }, - { - key: 'isInteractive', + isInteractive({ flavors: ['svg'], - group: 'Interactivity', - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: svgDefaultProps.isInteractive, - controlType: 'switch', - }, + }), { key: 'nodeTooltip', flavors: ['svg'], diff --git a/website/src/data/components/scatterplot/props.ts b/website/src/data/components/scatterplot/props.ts index da331a4bf2..848b9e4756 100644 --- a/website/src/data/components/scatterplot/props.ts +++ b/website/src/data/components/scatterplot/props.ts @@ -1,18 +1,29 @@ import { commonDefaultProps, svgDefaultProps } from '@nivo/scatterplot' import { themeProperty, - axesProperties, motionProperties, getLegendsProps, groupProperties, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { + chartDimensions, + ordinalColors, + blendMode, + chartGrid, + axes, + isInteractive, +} from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'canvas'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', help: 'Chart data.', + flavors: allFlavors, + type: 'Object[]', description: ` Chart data, which must conform to this structure: \`\`\` @@ -36,16 +47,20 @@ const props: ChartProperty[] = [ key: 'xScale', type: 'object', help: `X scale configuration.`, + flavors: allFlavors, group: 'Base', - controlType: 'object', - controlOptions: { + required: false, + control: { + type: 'object', props: [ { key: 'type', help: `Scale type, supports linear, point and time scales.`, type: 'string', - controlType: 'choices', - controlOptions: { + flavors: allFlavors, + required: true, + control: { + type: 'choices', disabled: true, choices: ['linear'].map(v => ({ label: v, @@ -56,10 +71,11 @@ const props: ChartProperty[] = [ { key: 'min', help: 'Minimum scale value.', + flavors: allFlavors, required: false, type: `number | 'auto'`, - controlType: 'switchableRange', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 0, min: -2000, @@ -69,10 +85,11 @@ const props: ChartProperty[] = [ { key: 'max', help: 'Maximum scale value.', + flavors: allFlavors, required: false, type: `number | 'auto'`, - controlType: 'switchableRange', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 1200, min: -2000, @@ -85,6 +102,8 @@ const props: ChartProperty[] = [ { key: 'xFormat', group: 'Base', + flavors: allFlavors, + required: false, type: 'string | Function', help: 'Optional formatter for x values.', description: ` @@ -97,22 +116,26 @@ const props: ChartProperty[] = [ please have a look at it for available formats, you can also pass a function which will receive the raw value and should return the formatted one. `, - controlType: 'valueFormat', + control: { type: 'valueFormat' }, }, { key: 'yScale', group: 'Base', + flavors: allFlavors, type: 'object', help: `Y scale configuration.`, - controlType: 'object', - controlOptions: { + required: false, + control: { + type: 'object', props: [ { key: 'type', help: `Scale type, supports linear, point and time scales.`, type: 'string', - controlType: 'choices', - controlOptions: { + flavors: allFlavors, + required: true, + control: { + type: 'choices', disabled: true, choices: ['linear'].map(v => ({ label: v, @@ -123,10 +146,11 @@ const props: ChartProperty[] = [ { key: 'min', help: 'Minimum scale value.', + flavors: allFlavors, required: false, type: `number | 'auto'`, - controlType: 'switchableRange', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 0, min: -2000, @@ -137,9 +161,10 @@ const props: ChartProperty[] = [ key: 'max', help: 'Maximum scale value.', required: false, + flavors: allFlavors, type: `number | 'auto'`, - controlType: 'switchableRange', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 1200, min: -2000, @@ -152,6 +177,8 @@ const props: ChartProperty[] = [ { key: 'yFormat', group: 'Base', + flavors: allFlavors, + required: false, type: 'string | Function', help: 'Optional formatter for y values.', description: ` @@ -164,11 +191,13 @@ const props: ChartProperty[] = [ please have a look at it for available formats, you can also pass a function which will receive the raw value and should return the formatted one. `, - controlType: 'valueFormat', + control: { type: 'valueFormat' }, }, { key: 'nodeId', group: 'Base', + flavors: allFlavors, + required: false, defaultValue: '(d) => `${d.serieId}.${d.index}`', type: 'string | (datum) => string', help: `ID accessor for the node.`, @@ -185,8 +214,10 @@ const props: ChartProperty[] = [ { key: 'nodeSize', group: 'Base', + flavors: allFlavors, defaultValue: commonDefaultProps.nodeSize, type: 'number | object | Function', + required: false, help: `How to compute node size, static or dynamic.`, description: ` If you provide a **number**, all nodes will have the same @@ -209,107 +240,30 @@ const props: ChartProperty[] = [ If you use a **custom function**, it will receive the current node and must **return a number**. `, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 2, max: 24, }, }, - { - key: 'width', - enableControlForFlavors: ['api'], - description: ` - Not required if using - \`Responsive*\` component. - Also note that width exclude left/right axes, - please add margin to make sure they're visible. - `, - help: 'Chart width.', - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - description: ` - Not required if using - \`Responsive*\` component. - Also note that width exclude top/bottom axes, - please add margin to make sure they're visible. - `, - help: 'Chart height.', - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, + ...chartDimensions(allFlavors), themeProperty(['svg', 'canvas']), - { - key: 'colors', - group: 'Style', - help: 'Defines color range.', - type: 'string | Function | string[]', - required: false, + ordinalColors({ + flavors: allFlavors, defaultValue: commonDefaultProps.colors, - controlType: 'ordinalColors', - }, - { - key: 'blendMode', - group: 'Style', + }), + blendMode({ flavors: ['svg'], - help: 'Defines CSS mix-blend-mode property.', - description: ` - Defines CSS \`mix-blend-mode\` property for nodes, - see - [MDN documentation](https://developer.mozilla.org/fr/docs/Web/CSS/mix-blend-mode). - `, - type: 'string', - required: false, - defaultValue: commonDefaultProps.blendMode, - controlType: 'blendMode', - }, + target: 'nodes', + defaultValue: 'normal', // commonDefaultProps.blendMode, + }), { key: 'layers', flavors: ['svg', 'canvas'], group: 'Customization', help: 'Defines the order of layers.', + type: '(string | Component)[]', description: ` Defines the order of layers, available layers are: \`grid\`, \`axes\`, \`points\`, \`markers\`, @@ -381,48 +335,17 @@ const props: ChartProperty[] = [ `, required: false, }, - { - key: 'enableGridX', - help: 'Enable/disable x grid.', - type: 'boolean', - required: false, - defaultValue: commonDefaultProps.enableGridX, - controlType: 'switch', - group: 'Grid & Axes', - }, - { - key: 'gridXValues', - group: 'Grid & Axes', - help: 'Specify values to use for vertical grid lines.', - type: 'Array', - required: false, - }, - { - key: 'enableGridY', - group: 'Grid & Axes', - help: 'Enable/disable y grid.', - type: 'boolean', - required: false, - defaultValue: commonDefaultProps.enableGridY, - controlType: 'switch', - }, - { - key: 'gridYValues', - group: 'Grid & Axes', - help: 'Specify values to use for horizontal grid lines.', - type: 'Array', - required: false, - }, - ...axesProperties(), - { - key: 'isInteractive', - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, + ...chartGrid({ + flavors: allFlavors, + values: true, + xDefault: commonDefaultProps.enableGridX, + yDefault: commonDefaultProps.enableGridY, + }), + ...axes({ flavors: allFlavors }), + isInteractive({ + flavors: ['svg', 'canvas'], defaultValue: commonDefaultProps.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'useMesh', group: 'Interactivity', @@ -430,16 +353,17 @@ const props: ChartProperty[] = [ help: 'Use a mesh to detect mouse interactions.', type: 'boolean', required: false, - defaultValue: commonDefaultProps.useMesh, - controlType: 'switch', + defaultValue: true, // commonDefaultProps.useMesh, + control: { type: 'switch' }, }, { key: 'debugMesh', help: 'Display mesh used to detect mouse interactions (voronoi cells).', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: commonDefaultProps.debugMesh, - controlType: 'switch', + control: { type: 'switch' }, group: 'Interactivity', }, { @@ -461,6 +385,7 @@ const props: ChartProperty[] = [ { key: 'onMouseEnter', group: 'Interactivity', + flavors: allFlavors, help: 'onMouseEnter handler, it receives target node data and mouse event.', type: '(node, event) => void', required: false, @@ -468,6 +393,7 @@ const props: ChartProperty[] = [ { key: 'onMouseMove', group: 'Interactivity', + flavors: allFlavors, help: 'onMouseMove handler, it receives target node data and mouse event.', type: '(node, event) => void', required: false, @@ -475,6 +401,7 @@ const props: ChartProperty[] = [ { key: 'onMouseLeave', group: 'Interactivity', + flavors: allFlavors, help: 'onMouseLeave handler, it receives target node data and mouse event.', type: '(node, event) => void', required: false, @@ -482,6 +409,7 @@ const props: ChartProperty[] = [ { key: 'onClick', group: 'Interactivity', + flavors: allFlavors, help: 'onClick handler, it receives target node data and mouse event.', type: '(node, event) => void', required: false, @@ -492,13 +420,14 @@ const props: ChartProperty[] = [ flavors: ['svg', 'canvas'], type: 'object[]', help: `Optional chart's legends.`, - controlType: 'array', - controlOptions: { + required: false, + control: { + type: 'array', props: getLegendsProps(['svg', 'canvas']), shouldCreate: true, addLabel: 'add legend', shouldRemove: true, - getItemTitle: (index, legend) => + getItemTitle: (index, legend: any) => `legend[${index}]: ${legend.anchor}, ${legend.direction}`, defaults: { anchor: 'top-left', @@ -511,8 +440,8 @@ const props: ChartProperty[] = [ itemsSpacing: 0, symbolSize: 20, itemDirection: 'left-to-right', - onClick: data => { - alert(JSON.stringify(data, null, ' ')) + onClick: (data: any) => { + console.log(JSON.stringify(data, null, ' ')) }, }, }, @@ -520,6 +449,7 @@ const props: ChartProperty[] = [ { key: 'annotations', group: 'Annotations', + flavors: allFlavors, help: 'Extra annotations.', type: 'object[]', required: false, diff --git a/website/src/data/components/stream/props.ts b/website/src/data/components/stream/props.ts index ed59bb9a25..8d6ad0739a 100644 --- a/website/src/data/components/stream/props.ts +++ b/website/src/data/components/stream/props.ts @@ -3,12 +3,20 @@ import { areaCurvePropKeys, stackOrderPropKeys, stackOffsetPropKeys } from '@niv import { defaultProps, svgDefaultProps } from '@nivo/stream' import { themeProperty, - axesProperties, motionProperties, defsProperties, groupProperties, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { + chartDimensions, + ordinalColors, + chartGrid, + axes, + isInteractive, +} from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg'] const props: ChartProperty[] = [ { @@ -76,7 +84,7 @@ const props: ChartProperty[] = [ which will receive the raw value and should return the formatted one. `, flavors: ['svg'], - controlType: 'valueFormat', + control: { type: 'valueFormat' }, }, { key: 'offsetType', @@ -85,8 +93,8 @@ const props: ChartProperty[] = [ required: false, help: 'Offset type.', flavors: ['svg'], - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: stackOffsetPropKeys.map((key: string) => ({ label: key, value: key, @@ -100,8 +108,8 @@ const props: ChartProperty[] = [ required: false, help: 'Layers order.', flavors: ['svg'], - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: stackOrderPropKeys.map((key: string) => ({ label: key, value: key, @@ -120,74 +128,20 @@ const props: ChartProperty[] = [ `, defaultValue: defaultProps.curve, flavors: ['svg'], - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: areaCurvePropKeys.map((key: string) => ({ label: key, value: key, })), }, }, - { - key: 'width', - group: 'Base', - type: '{number}', - required: true, - help: 'Chart width.', - description: ` - not required if using - \`\`. - `, - flavors: ['svg'], - enableControlForFlavors: ['api'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - group: 'Base', - type: '{number}', - required: true, - help: 'Chart height.', - description: ` - not required if using - \`\`. - `, - flavors: ['svg'], - enableControlForFlavors: ['api'], - controlType: 'range', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'margin', - group: 'Base', - type: 'object', - required: false, - help: 'Chart margin.', - flavors: ['svg'], - controlType: 'margin', - }, + ...chartDimensions(allFlavors), themeProperty(['svg']), - { - key: 'colors', - group: 'Style', - type: 'string | Function', - required: false, - help: 'Defines how to compute line color.', - flavors: ['svg'], + ordinalColors({ + flavors: allFlavors, defaultValue: defaultProps.colors, - controlType: 'ordinalColors', - }, + }), { key: 'fillOpacity', group: 'Style', @@ -196,7 +150,7 @@ const props: ChartProperty[] = [ help: 'Layers fill opacity.', flavors: ['svg'], defaultValue: defaultProps.fillOpacity, - controlType: 'opacity', + control: { type: 'opacity' }, }, { key: 'borderWidth', @@ -206,7 +160,7 @@ const props: ChartProperty[] = [ required: false, flavors: ['svg'], defaultValue: defaultProps.borderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'borderColor', @@ -220,7 +174,7 @@ const props: ChartProperty[] = [ `, flavors: ['svg'], defaultValue: defaultProps.borderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, ...defsProperties('Style', ['svg']), { @@ -240,27 +194,12 @@ const props: ChartProperty[] = [ flavors: ['svg'], defaultValue: svgDefaultProps.layers, }, - { - key: 'enableGridX', - group: 'Grid & Axes', - help: 'Enable/disable x grid.', - type: 'boolean', - required: false, - flavors: ['svg'], - defaultValue: defaultProps.enableGridX, - controlType: 'switch', - }, - { - key: 'enableGridY', - group: 'Grid & Axes', - help: 'Enable/disable y grid.', - type: 'boolean', - required: false, - flavors: ['svg'], - defaultValue: defaultProps.enableGridY, - controlType: 'switch', - }, - ...axesProperties(), + ...chartGrid({ + flavors: allFlavors, + xDefault: defaultProps.enableGridX, + yDefault: defaultProps.enableGridY, + }), + ...axes({ flavors: allFlavors }), { key: 'enableDots', group: 'Dots', @@ -269,7 +208,7 @@ const props: ChartProperty[] = [ required: false, flavors: ['svg'], defaultValue: defaultProps.enableDots, - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'renderDot', @@ -289,8 +228,8 @@ const props: ChartProperty[] = [ required: false, flavors: ['svg'], defaultValue: defaultProps.dotSize, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 2, max: 20, @@ -304,7 +243,7 @@ const props: ChartProperty[] = [ required: false, flavors: ['svg'], defaultValue: defaultProps.dotColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, { key: 'dotBorderWidth', @@ -316,7 +255,7 @@ const props: ChartProperty[] = [ required: false, flavors: ['svg'], defaultValue: defaultProps.dotBorderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, }, { key: 'dotBorderColor', @@ -326,18 +265,12 @@ const props: ChartProperty[] = [ required: false, flavors: ['svg'], defaultValue: defaultProps.dotBorderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, - { - key: 'isInteractive', + isInteractive({ flavors: ['svg'], - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: defaultProps.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'tooltip', flavors: ['svg'], @@ -376,7 +309,7 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, defaultValue: defaultProps.enableStackTooltip, - controlType: 'switch', + control: { type: 'switch' }, group: 'Interactivity', }, { diff --git a/website/src/data/components/sunburst/props.ts b/website/src/data/components/sunburst/props.ts index 7fec74eca2..afd39aed9a 100644 --- a/website/src/data/components/sunburst/props.ts +++ b/website/src/data/components/sunburst/props.ts @@ -6,12 +6,16 @@ import { motionProperties, themeProperty, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions, ordinalColors, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'api'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', + flavors: allFlavors, help: 'Chart data, which should be immutable.', description: ` Chart data, which must conform to this structure @@ -44,6 +48,7 @@ const props: ChartProperty[] = [ { key: 'id', group: 'Base', + flavors: allFlavors, help: 'Id accessor.', description: ` define id accessor, if string given, @@ -60,6 +65,7 @@ const props: ChartProperty[] = [ { key: 'value', group: 'Base', + flavors: allFlavors, help: 'Value accessor', description: ` define value accessor, if string given, @@ -76,6 +82,7 @@ const props: ChartProperty[] = [ { key: 'valueFormat', group: 'Base', + flavors: allFlavors, help: 'Optional formatter for values.', description: ` The formatted value can then be used for labels & tooltips. @@ -86,82 +93,34 @@ const props: ChartProperty[] = [ `, required: false, type: 'string | (value: number) => string | number', - controlType: 'valueFormat', + control: { type: 'valueFormat' }, }, { key: 'cornerRadius', help: 'Round node shape.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.cornerRadius, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 45, step: 1, }, }, - { - key: 'width', - enableControlForFlavors: ['api'], - description: ` - not required if using - \`\`. - `, - help: 'Chart width.', - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - description: ` - not required if using - \`\`. - `, - help: 'Chart height.', - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, + ...chartDimensions(allFlavors), themeProperty(['svg', 'api']), - { - key: 'colors', - help: 'Defines how to compute node color.', - required: false, + ordinalColors({ + flavors: allFlavors, defaultValue: defaultProps.colors, - controlType: 'ordinalColors', - type: 'string | Function | string[]', - group: 'Style', - }, + }), { key: 'colorBy', help: `Define the property to use to assign a color to arcs.`, + flavors: allFlavors, description: ` When using \`id\`, each node will get a new color, and when using \`depth\` the nodes' color will depend on their depth. @@ -169,9 +128,9 @@ const props: ChartProperty[] = [ type: `'id' | 'depth'`, required: false, defaultValue: defaultProps.colorBy, - controlType: 'radio', group: 'Style', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'id', value: 'id' }, { label: 'depth', value: 'depth' }, @@ -181,37 +140,41 @@ const props: ChartProperty[] = [ { key: 'inheritColorFromParent', help: 'Inherit color from parent node starting from 2nd level.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultProps.inheritColorFromParent, - controlType: 'switch', + control: { type: 'switch' }, group: 'Style', }, { key: 'childColor', help: 'Defines how to compute child nodes color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaultProps.childColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, { key: 'borderWidth', help: 'Node border width.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.borderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Style', }, { key: 'borderColor', help: 'Defines how to compute arcs color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaultProps.borderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, ...defsProperties('Style', ['svg', 'api']), @@ -225,28 +188,31 @@ const props: ChartProperty[] = [ [dedicated guide](self:/guides/patterns) for further information. `, + required: false, type: 'boolean', - controlType: 'switch', + control: { type: 'switch' }, group: 'Style', }, { key: 'enableArcLabels', help: 'Enable/disable arc labels.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultProps.enableArcLabels, - controlType: 'switch', + control: { type: 'switch' }, group: 'Arc labels', }, { key: 'arcLabel', help: 'Defines how to get label text, can be a string (used to access current node data property) or a function which will receive the actual node data.', + flavors: allFlavors, type: 'string | Function', required: false, defaultValue: defaultProps.arcLabel, - controlType: 'choices', group: 'Arc labels', - controlOptions: { + control: { + type: 'choices', choices: ['id', 'value', 'formattedValue', `d => \`\${d.id} (\${d.value})\``].map( choice => ({ label: choice, @@ -261,12 +227,13 @@ const props: ChartProperty[] = [ Define the radius to use to determine the label position, starting from inner radius, this is expressed as a ratio. `, + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.arcLabelsRadiusOffset, - controlType: 'range', group: 'Arc labels', - controlOptions: { + control: { + type: 'range', min: 0, max: 2, step: 0.05, @@ -275,12 +242,13 @@ const props: ChartProperty[] = [ { key: 'arcLabelsSkipAngle', help: `Skip label if corresponding arc's angle is lower than provided value.`, + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.arcLabelsSkipAngle, - controlType: 'range', group: 'Arc labels', - controlOptions: { + control: { + type: 'range', unit: '°', min: 0, max: 45, @@ -290,16 +258,18 @@ const props: ChartProperty[] = [ { key: 'arcLabelsTextColor', help: 'Defines how to compute arc label text color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaultProps.arcLabelsTextColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Arc labels', }, { key: 'layers', group: 'Customization', help: 'Defines the order of layers and add custom layers.', + flavors: ['svg'], description: ` You can also use this to insert extra layers to the chart, the extra layer must be a function. @@ -324,16 +294,10 @@ const props: ChartProperty[] = [ type: 'Array', defaultValue: defaultProps.layers, }, - { - key: 'isInteractive', + isInteractive({ flavors: ['svg'], - help: 'Enable/disable interactivity.', - type: '{boolean}', - required: false, defaultValue: defaultProps.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), ...motionProperties(['svg'], defaultProps, 'react-spring'), { key: 'transitionMode', @@ -342,9 +306,9 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: defaultProps.transitionMode, - controlType: 'choices', group: 'Motion', - controlOptions: { + control: { + type: 'choices', choices: arcTransitionModes.map(choice => ({ label: choice, value: choice, @@ -383,9 +347,10 @@ const props: ChartProperty[] = [ key: 'custom tooltip example', flavors: ['svg'], group: 'Interactivity', + required: false, help: 'Showcase custom tooltip component.', type: 'boolean', - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'onClick', diff --git a/website/src/data/components/swarmplot/props.ts b/website/src/data/components/swarmplot/props.ts index f07586c47a..9723caec48 100644 --- a/website/src/data/components/swarmplot/props.ts +++ b/website/src/data/components/swarmplot/props.ts @@ -1,16 +1,22 @@ import { defaultProps } from '@nivo/swarmplot' +import { OrdinalColorScaleConfig } from '@nivo/colors' +import { themeProperty, motionProperties, groupProperties } from '../../../lib/componentProperties' import { - themeProperty, - motionProperties, - axesProperties, - groupProperties, -} from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' + chartDimensions, + ordinalColors, + chartGrid, + axes, + isInteractive, +} from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'canvas'] const props: ChartProperty[] = [ { key: 'data', help: 'Chart data.', + flavors: allFlavors, description: ` This Chart's doesn't have a predefined structure, you must use a schema which match \`groupBy\`, @@ -23,6 +29,7 @@ const props: ChartProperty[] = [ { key: 'id', group: 'Base', + flavors: allFlavors, type: 'string | Function', required: false, help: `Property used to retrieve the node's unique identifier.`, @@ -41,6 +48,7 @@ const props: ChartProperty[] = [ { key: 'value', group: 'Base', + flavors: allFlavors, type: 'string | Function', required: false, help: `Property used to retrieve the node's value.`, @@ -49,6 +57,7 @@ const props: ChartProperty[] = [ { key: 'valueFormat', group: 'Base', + flavors: allFlavors, help: 'Optional formatter for values.', description: ` The formatted value can then be used for labels & tooltips. @@ -59,11 +68,12 @@ const props: ChartProperty[] = [ `, required: false, type: 'string | (value: number) => string | number', - controlType: 'valueFormat', + control: { type: 'valueFormat' }, }, { key: 'groups', group: 'Base', + flavors: allFlavors, type: 'string[]', required: true, help: 'Available groups.', @@ -71,6 +81,7 @@ const props: ChartProperty[] = [ { key: 'groupBy', group: 'Base', + flavors: allFlavors, type: 'string | Function', required: false, help: 'Propety used to group nodes, must return a group which is available in the groups property.', @@ -79,6 +90,7 @@ const props: ChartProperty[] = [ { key: 'size', group: 'Base', + flavors: allFlavors, type: 'number | object | Function', required: false, help: `How to compute node size, static or dynamic.`, @@ -108,66 +120,23 @@ const props: ChartProperty[] = [ { key: 'spacing', help: 'Spacing between nodes.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.spacing, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 20, }, }, - { - key: 'width', - enableControlForFlavors: ['api'], - group: 'Base', - help: 'Chart width.', - description: ` - not required if using responsive alternative - of the component \`\`. - `, - type: 'number', - required: true, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - group: 'Base', - help: 'Chart height.', - description: ` - not required if using responsive alternative - of the component \`\`. - `, - type: 'number', - required: true, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, + ...chartDimensions(allFlavors), { key: 'forceStrength', help: 'Force strength.', + flavors: allFlavors, description: ` This value determine the strength applied on the value axis, using lower value will result in a **more linear @@ -186,9 +155,9 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaultProps.forceStrength, - controlType: 'range', group: 'Simulation', - controlOptions: { + control: { + type: 'range', step: 0.2, min: 0.2, max: 9, @@ -197,6 +166,7 @@ const props: ChartProperty[] = [ { key: 'simulationIterations', help: 'Adjust the simulation quality.', + flavors: allFlavors, description: ` Increasing this number will result in a **more accurate simulation**, however it will also involve more computing. @@ -204,9 +174,9 @@ const props: ChartProperty[] = [ type: 'number', required: false, defaultValue: defaultProps.simulationIterations, - controlType: 'range', group: 'Simulation', - controlOptions: { + control: { + type: 'range', min: 60, max: 260, }, @@ -214,12 +184,13 @@ const props: ChartProperty[] = [ { key: 'layout', help: `Chart layout.`, + flavors: allFlavors, type: 'string', required: false, defaultValue: defaultProps.layout, - controlType: 'radio', group: 'Layout', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'horizontal', value: 'horizontal' }, { label: 'vertical', value: 'vertical' }, @@ -229,21 +200,22 @@ const props: ChartProperty[] = [ { key: 'gap', help: 'Gap between each serie.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultProps.gap, - controlType: 'range', group: 'Layout', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 100, }, }, - themeProperty(['svg', 'canvas']), - { - key: 'colors', - help: 'Defines how to compute node color.', + themeProperty(allFlavors), + ordinalColors({ + flavors: allFlavors, + defaultValue: defaultProps.colors as OrdinalColorScaleConfig, description: ` The colors property is used to determine the **ordinal color scale** to use to compute nodes' color, it use the serie id as a discriminator. @@ -273,16 +245,12 @@ const props: ChartProperty[] = [ If you pass a string, it will be **used as a color for each and every nodes**. `, - type: `Function | object | string`, - required: false, - defaultValue: defaultProps.colors, - controlType: 'ordinalColors', - group: 'Style', - }, + }), { key: 'colorBy', group: 'Style', help: 'Property or accessor function to be used with colors.', + flavors: allFlavors, description: ` When using a color scheme or an array of colors, you'll generate a color scale, this scale will @@ -297,8 +265,8 @@ const props: ChartProperty[] = [ type: `Function | string`, required: false, defaultValue: defaultProps.colorBy, - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: ['group', 'id'].map(key => ({ label: key, value: key, @@ -308,24 +276,27 @@ const props: ChartProperty[] = [ { key: 'borderWidth', help: 'Control node border width.', + flavors: allFlavors, type: 'number | Function', required: false, defaultValue: defaultProps.borderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Style', }, { key: 'borderColor', help: 'Control node border color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaultProps.borderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, { key: 'layers', group: 'Customization', + flavors: allFlavors, help: 'Defines the order of layers and add custom layers.', description: ` Defines the order of layers, available layers are: @@ -391,48 +362,17 @@ const props: ChartProperty[] = [ required: false, type: 'Function', }, - { - key: 'enableGridX', - group: 'Grid & Axes', - help: 'Enable/disable x grid.', - type: 'boolean', - required: false, - defaultValue: defaultProps.enableGridX, - controlType: 'switch', - }, - { - key: 'gridXValues', - group: 'Grid & Axes', - help: 'Specify values to use for vertical grid lines.', - type: 'Array', - required: false, - }, - { - key: 'enableGridY', - group: 'Grid & Axes', - help: 'Enable/disable y grid.', - type: 'boolean', - required: false, - defaultValue: defaultProps.enableGridY, - controlType: 'switch', - }, - { - key: 'gridYValues', - group: 'Grid & Axes', - help: 'Specify values to use for horizontal grid lines.', - type: 'Array', - required: false, - }, - ...axesProperties(), - { - key: 'isInteractive', - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, + ...chartGrid({ + flavors: allFlavors, + values: true, + xDefault: defaultProps.enableGridX, + yDefault: defaultProps.enableGridY, + }), + ...axes({ flavors: allFlavors }), + isInteractive({ + flavors: ['svg', 'canvas'], defaultValue: defaultProps.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'useMesh', help: 'Use a mesh to detect mouse interactions, always true for canvas.', @@ -440,21 +380,23 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, defaultValue: defaultProps.useMesh, - controlType: 'switch', + control: { type: 'switch' }, group: 'Interactivity', }, { key: 'debugMesh', help: 'Display the mesh used to detect mouse interactions (voronoi cells), depends on useMesh.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultProps.debugMesh, - controlType: 'switch', + control: { type: 'switch' }, group: 'Interactivity', }, { key: 'onMouseEnter', group: 'Interactivity', + flavors: allFlavors, help: 'onMouseEnter handler.', type: '(node, event) => void', required: false, @@ -462,6 +404,7 @@ const props: ChartProperty[] = [ { key: 'onMouseMove', group: 'Interactivity', + flavors: allFlavors, help: 'onMouseMove handler.', type: '(node, event) => void', required: false, @@ -469,6 +412,7 @@ const props: ChartProperty[] = [ { key: 'onMouseLeave', group: 'Interactivity', + flavors: allFlavors, help: 'onMouseLeave handler.', type: '(node, event) => void', required: false, @@ -476,6 +420,7 @@ const props: ChartProperty[] = [ { key: 'onClick', group: 'Interactivity', + flavors: allFlavors, help: 'onClick handler.', type: '(node, event) => void', required: false, @@ -483,6 +428,7 @@ const props: ChartProperty[] = [ { key: 'tooltip', group: 'Interactivity', + flavors: allFlavors, type: 'Function', required: false, help: 'Custom tooltip component.', diff --git a/website/src/data/components/time-range/props.ts b/website/src/data/components/time-range/props.ts index 90ec7f5777..55ec23cf1b 100644 --- a/website/src/data/components/time-range/props.ts +++ b/website/src/data/components/time-range/props.ts @@ -1,13 +1,16 @@ -import { boxAlignments } from '@nivo/core' import { timeRangeDefaultProps as defaults } from '@nivo/calendar' import { themeProperty, getLegendsProps, groupProperties } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', help: 'Chart data.', + flavors: allFlavors, description: ` Chart data, which must conform to this structure: \`\`\` @@ -25,6 +28,7 @@ const props: ChartProperty[] = [ { key: 'from', group: 'Base', + flavors: allFlavors, help: 'start date', type: 'string | Date', required: false, @@ -33,88 +37,43 @@ const props: ChartProperty[] = [ key: 'to', group: 'Base', help: 'end date', + flavors: allFlavors, type: 'string | Date', required: false, }, - { - key: 'width', - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using responsive alternative of - the component \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using responsive alternative of - the component \`\`. - `, - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, + ...chartDimensions(allFlavors), { key: 'direction', help: 'defines calendar layout direction.', + flavors: allFlavors, type: 'string', required: false, defaultValue: defaults.direction, - controlType: 'radio', group: 'Base', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'horizontal', value: 'horizontal' }, { label: 'vertical', value: 'vertical' }, ], }, }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, { key: 'align', help: 'defines how calendar should be aligned inside chart container.', + flavors: allFlavors, type: 'string', required: false, defaultValue: defaults.align, group: 'Base', - controlType: 'boxAnchor', - controlOptions: { - choices: boxAlignments.map((align: string) => ({ - label: align, - value: align, - })), + control: { + type: 'boxAnchor', }, }, { key: 'minValue', help: 'Minimum value.', + flavors: allFlavors, description: ` Minimum value. If 'auto', will pick the lowest value in the provided data set. @@ -124,9 +83,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.minValue, type: `number | 'auto'`, - controlType: 'switchableRange', group: 'Base', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 0, min: -300, @@ -136,6 +95,7 @@ const props: ChartProperty[] = [ { key: 'maxValue', help: 'Maximum value.', + flavors: allFlavors, description: ` Maximum value. If 'auto', will pick the highest value in the provided data set. @@ -145,9 +105,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.maxValue, type: `number | 'auto'`, - controlType: 'switchableRange', group: 'Base', - controlOptions: { + control: { + type: 'switchableRange', disabledValue: 'auto', defaultValue: 100, min: 0, @@ -158,6 +118,7 @@ const props: ChartProperty[] = [ { key: 'colors', group: 'Style', + flavors: allFlavors, help: 'Cell colors.', description: ` An array of colors to be used in conjunction with @@ -172,16 +133,18 @@ const props: ChartProperty[] = [ { key: 'emptyColor', help: 'color to use to fill days without available value.', + flavors: allFlavors, type: 'string', required: false, defaultValue: defaults.emptyColor, - controlType: 'colorPicker', + control: { type: 'colorPicker' }, group: 'Style', }, // Months { key: 'monthLegend', help: `can be used to customize months label, returns abbreviated month name (english) by default. This can be used to use a different language`, + flavors: allFlavors, type: '(year: number, month: number, date: Date) => string | number', required: false, group: 'Months', @@ -189,12 +152,13 @@ const props: ChartProperty[] = [ { key: 'monthLegendPosition', help: 'defines month legends position.', + flavors: allFlavors, type: `'before' | 'after'`, required: false, defaultValue: defaults.monthLegendPosition, - controlType: 'radio', group: 'Months', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'before', value: 'before' }, { label: 'after', value: 'after' }, @@ -204,12 +168,13 @@ const props: ChartProperty[] = [ { key: 'monthLegendOffset', help: 'define offset from month edge to its label.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.monthLegendOffset, - controlType: 'range', group: 'Months', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 36, @@ -219,12 +184,13 @@ const props: ChartProperty[] = [ { key: 'weekdayLegendOffset', help: 'define offset from weekday edge to its label.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.weekdayLegendOffset, - controlType: 'range', group: 'Weekday', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 100, @@ -233,7 +199,8 @@ const props: ChartProperty[] = [ { key: 'weekdayTicks', help: 'define weekday tickmarks to show', - type: 'Array<0 | 1 | 2 | 3 | 4 | 5 | 6>', + flavors: allFlavors, + type: '(0 | 1 | 2 | 3 | 4 | 5 | 6)[]', required: false, defaultValue: [1, 3, 5], group: 'Weekday', @@ -252,21 +219,23 @@ const props: ChartProperty[] = [ { key: 'square', help: 'force day cell into square shape', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaults.square, - controlType: 'switch', + control: { type: 'switch' }, group: 'Days', }, { key: 'dayRadius', help: 'define border radius of each day cell.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.dayRadius, - controlType: 'range', group: 'Days', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 20, @@ -275,12 +244,13 @@ const props: ChartProperty[] = [ { key: 'daySpacing', help: 'define spacing between each day cell.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.daySpacing, - controlType: 'range', group: 'Days', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 20, @@ -289,33 +259,31 @@ const props: ChartProperty[] = [ { key: 'dayBorderWidth', help: 'width of days border.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.dayBorderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Days', }, { key: 'dayBorderColor', help: 'color to use for days border.', + flavors: allFlavors, type: 'string', required: false, defaultValue: defaults.dayBorderColor, - controlType: 'colorPicker', + control: { type: 'colorPicker' }, group: 'Days', }, - { - key: 'isInteractive', - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, + isInteractive({ + flavors: ['svg'], defaultValue: defaults.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'onClick', group: 'Interactivity', + flavors: allFlavors, help: 'onClick handler, it receives clicked day data and mouse event.', type: '(day, event) => void', required: false, @@ -323,6 +291,7 @@ const props: ChartProperty[] = [ { key: 'tooltip', group: 'Interactivity', + flavors: allFlavors, type: 'Function', required: false, help: 'Custom tooltip component.', @@ -350,8 +319,10 @@ const props: ChartProperty[] = [ { key: 'custom tooltip example', help: 'Showcase custom tooltip.', + flavors: allFlavors, type: 'boolean', - controlType: 'switch', + required: false, + control: { type: 'switch' }, group: 'Interactivity', }, { @@ -360,13 +331,14 @@ const props: ChartProperty[] = [ type: 'LegendProps[]', help: `Optional chart's legends.`, group: 'Legends', - controlType: 'array', - controlOptions: { + required: false, + control: { + type: 'array', props: getLegendsProps(['svg']), shouldCreate: true, addLabel: 'add legend', shouldRemove: true, - getItemTitle: (index, legend) => + getItemTitle: (index, legend: any) => `legend[${index}]: ${legend.anchor}, ${legend.direction}`, defaults: { anchor: 'bottom-right', @@ -380,8 +352,8 @@ const props: ChartProperty[] = [ translateX: -85, translateY: -240, symbolSize: 20, - onClick: data => { - alert(JSON.stringify(data, null, ' ')) + onClick: (data: any) => { + console.log(JSON.stringify(data, null, ' ')) }, }, }, diff --git a/website/src/data/components/treemap/props.ts b/website/src/data/components/treemap/props.ts index 244cda858e..f2527fc805 100644 --- a/website/src/data/components/treemap/props.ts +++ b/website/src/data/components/treemap/props.ts @@ -1,6 +1,15 @@ +// @ts-ignore import { TreeMapDefaultProps } from '@nivo/treemap' -import { motionProperties, defsProperties, groupProperties } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { + motionProperties, + defsProperties, + groupProperties, + themeProperty, +} from '../../../lib/componentProperties' +import { chartDimensions, ordinalColors, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'html', 'canvas', 'api'] const defaults = TreeMapDefaultProps @@ -8,6 +17,7 @@ const props: ChartProperty[] = [ { key: 'data', group: 'Base', + flavors: allFlavors, help: 'The hierarchical data object.', type: 'object', required: true, @@ -15,6 +25,7 @@ const props: ChartProperty[] = [ { key: 'identity', group: 'Base', + flavors: allFlavors, help: 'The key or function to use to retrieve nodes identity.', type: 'string | Function', required: false, @@ -23,6 +34,7 @@ const props: ChartProperty[] = [ { key: 'value', group: 'Base', + flavors: allFlavors, help: 'The key or function to use to retrieve nodes value.', type: 'string | Function', required: false, @@ -34,14 +46,16 @@ const props: ChartProperty[] = [ Value format supporting d3-format notation, this formatted value will then be used for labels and tooltips. `, + flavors: allFlavors, type: 'string | Function', required: false, - controlType: 'valueFormat', + control: { type: 'valueFormat' }, group: 'Base', }, { key: 'tile', group: 'Base', + flavors: allFlavors, help: 'Strategy used to compute nodes.', description: ` Strategy used to compute nodes, see @@ -50,8 +64,8 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: 'squarify', - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: [ { label: 'binary', value: 'binary' }, { label: 'squarify', value: 'squarify' }, @@ -68,21 +82,23 @@ const props: ChartProperty[] = [ { key: 'leavesOnly', help: 'Only render leaf nodes (no parent).', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaults.leavesOnly, - controlType: 'switch', + control: { type: 'switch' }, group: 'Base', }, { key: 'innerPadding', help: 'Padding between parent and child node.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.innerPadding, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 32, @@ -91,121 +107,76 @@ const props: ChartProperty[] = [ { key: 'outerPadding', help: 'Padding between parent and child node.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.outerPadding, - controlType: 'range', group: 'Base', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 32, }, }, - { - key: 'width', - group: 'Base', - flavors: ['svg', 'canvas', 'html', 'api'], - enableControlForFlavors: ['api'], - help: 'Chart width.', - description: ` - not required if using responsive alternative - of the component \`\`. - `, - type: 'number', - required: true, - }, - { - key: 'height', - group: 'Base', - flavors: ['svg', 'canvas', 'html', 'api'], - enableControlForFlavors: ['api'], - help: 'Chart height.', - description: ` - not required if using responsive alternative - of the component \`\`. - `, - type: 'number', - required: true, - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, - { - key: 'colors', - help: 'Defines how to compute node color.', - type: 'string | Function | string[]', - required: false, + ...chartDimensions(allFlavors), + themeProperty(allFlavors), + ordinalColors({ + flavors: allFlavors, defaultValue: defaults.colors, - controlType: 'ordinalColors', - group: 'Style', - }, + }), { key: 'nodeOpacity', help: 'Node opacity (0~1).', + flavors: allFlavors, required: false, defaultValue: defaults.nodeOpacity, type: 'number', - controlType: 'opacity', + control: { type: 'opacity' }, group: 'Style', }, { key: 'borderWidth', help: 'Control node border width.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaults.borderWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Style', }, { key: 'borderColor', help: 'Method to compute border color.', + flavors: allFlavors, type: 'string | object | Function', required: false, defaultValue: defaults.borderColor, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Style', }, ...defsProperties('Style', ['svg']), { key: 'enableLabel', help: 'Enable/disable labels.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaults.enableLabel, - controlType: 'switch', + control: { type: 'switch' }, group: 'Labels', }, { key: 'label', help: 'Label accessor.', + flavors: allFlavors, description: 'Defines how to get label text, can be a string (used to access current node property) or a function which will receive the actual node and must return the desired label.', type: 'string | Function', required: false, - controlType: 'choices', group: 'Labels', - controlOptions: { + control: { + type: 'choices', choices: [ 'formattedValue', 'id', @@ -219,11 +190,12 @@ const props: ChartProperty[] = [ { key: 'labelSkipSize', help: 'Skip label rendering if node minimal side length is lower than given value, 0 to disable.', + flavors: allFlavors, type: 'number', required: false, - controlType: 'range', group: 'Labels', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 100, @@ -232,18 +204,20 @@ const props: ChartProperty[] = [ { key: 'orientLabel', help: 'Orient labels according to max node width/height.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaults.orientLabel, - controlType: 'switch', + control: { type: 'switch' }, group: 'Labels', }, { key: 'labelTextColor', help: 'Method to compute label text color.', + flavors: allFlavors, type: 'string | object | Function', required: false, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Labels', }, { @@ -253,7 +227,7 @@ const props: ChartProperty[] = [ type: 'boolean', required: false, defaultValue: defaults.enableParentLabel, - controlType: 'switch', + control: { type: 'switch' }, group: 'Labels', }, { @@ -264,9 +238,9 @@ const props: ChartProperty[] = [ 'Defines how to get parent label text, can be a string (used to access current node property) or a function which will receive the actual node and must return the desired label.', type: 'string | Function', required: false, - controlType: 'choices', group: 'Labels', - controlOptions: { + control: { + type: 'choices', choices: ['id', 'formattedValue', `node => node.pathComponents.join(' / ')`].map( prop => ({ label: prop, @@ -282,9 +256,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.parentLabelSize, type: `number`, - controlType: 'range', group: 'Labels', - controlOptions: { + control: { + type: 'range', min: 10, max: 40, }, @@ -295,10 +269,10 @@ const props: ChartProperty[] = [ help: 'Parent label position.', type: `'top' | 'right' | 'bottom' | 'left'`, required: false, - controlType: 'choices', group: 'Labels', defaultValue: defaults.parentLabelPosition, - controlOptions: { + control: { + type: 'choices', choices: ['top', 'right', 'bottom', 'left'].map(prop => ({ label: prop, value: prop, @@ -312,9 +286,9 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.parentLabelPadding, type: `number`, - controlType: 'range', group: 'Labels', - controlOptions: { + control: { + type: 'range', min: 0, max: 20, }, @@ -325,19 +299,13 @@ const props: ChartProperty[] = [ help: 'Method to compute parent label text color.', type: 'string | object | Function', required: false, - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, group: 'Labels', }, - { - key: 'isInteractive', + isInteractive({ flavors: ['svg', 'html', 'canvas'], - help: 'Enable/disable interactivity.', - type: 'boolean', - required: false, defaultValue: defaults.isInteractive, - controlType: 'switch', - group: 'Interactivity', - }, + }), { key: 'onMouseEnter', flavors: ['svg', 'html'], diff --git a/website/src/data/components/voronoi/props.ts b/website/src/data/components/voronoi/props.ts index 228b631b54..df814a7623 100644 --- a/website/src/data/components/voronoi/props.ts +++ b/website/src/data/components/voronoi/props.ts @@ -1,11 +1,15 @@ import { defaultVoronoiProps } from '@nivo/voronoi' import { groupProperties } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg'] const props: ChartProperty[] = [ { key: 'data', group: 'Base', + flavors: allFlavors, help: 'Chart data.', description: ` Chart data, which must conform to this structure: @@ -23,6 +27,7 @@ const props: ChartProperty[] = [ { key: 'xDomain', group: 'Base', + flavors: allFlavors, help: 'Defines the x values domain.', type: '[number, number]', required: false, @@ -31,61 +36,18 @@ const props: ChartProperty[] = [ { key: 'yDomain', group: 'Base', + flavors: allFlavors, help: 'Defines the y values domain.', type: '[number, number]', required: false, defaultValue: defaultVoronoiProps.yDomain, }, - { - key: 'width', - enableControlForFlavors: ['api'], - description: ` - not required if using - \`\`. - `, - help: 'Chart width.', - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'height', - enableControlForFlavors: ['api'], - description: ` - not required if using - \`\`. - `, - help: 'Chart height.', - type: 'number', - required: true, - controlType: 'range', - group: 'Base', - controlOptions: { - unit: 'px', - min: 100, - max: 1000, - step: 5, - }, - }, - { - key: 'margin', - help: 'Chart margin.', - type: 'object', - required: false, - controlType: 'margin', - group: 'Base', - }, + ...chartDimensions(allFlavors), { key: 'layers', - flavors: ['svg'], - group: 'Base', + flavors: allFlavors, + group: 'Customization', + type: 'string | Component', help: 'Defines the order of layers.', description: ` Defines the order of layers, available layers are: @@ -102,75 +64,83 @@ const props: ChartProperty[] = [ { key: 'enableLinks', help: 'Enable/disable links.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultVoronoiProps.enableLinks, - controlType: 'switch', + control: { type: 'switch' }, group: 'Links', }, { key: 'linkLineWidth', help: 'Links line width.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultVoronoiProps.linkLineWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Links', }, { key: 'linkLineColor', help: 'Links color.', + flavors: allFlavors, type: 'string', required: false, defaultValue: defaultVoronoiProps.linkLineColor, - controlType: 'colorPicker', + control: { type: 'colorPicker' }, group: 'Links', }, { key: 'enableCells', help: 'Enable/disable cells.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultVoronoiProps.enableCells, - controlType: 'switch', + control: { type: 'switch' }, group: 'Cells', }, { key: 'cellLineWidth', help: 'Border width for cells.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultVoronoiProps.cellLineWidth, - controlType: 'lineWidth', + control: { type: 'lineWidth' }, group: 'Cells', }, { key: 'cellLineColor', help: 'Border color for cells.', + flavors: allFlavors, type: 'string', required: false, defaultValue: defaultVoronoiProps.cellLineColor, - controlType: 'colorPicker', + control: { type: 'colorPicker' }, group: 'Cells', }, { key: 'enablePoints', help: 'Enable/disable points.', + flavors: allFlavors, type: 'boolean', required: false, defaultValue: defaultVoronoiProps.enablePoints, - controlType: 'switch', + control: { type: 'switch' }, group: 'Points', }, { key: 'pointSize', help: 'Size of points.', + flavors: allFlavors, type: 'number', required: false, defaultValue: defaultVoronoiProps.pointSize, - controlType: 'range', group: 'Points', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 12, @@ -180,10 +150,11 @@ const props: ChartProperty[] = [ { key: 'pointColor', help: 'Points color.', + flavors: allFlavors, type: 'string', required: false, defaultValue: defaultVoronoiProps.pointColor, - controlType: 'colorPicker', + control: { type: 'colorPicker' }, group: 'Points', }, ] diff --git a/website/src/data/components/waffle/props.ts b/website/src/data/components/waffle/props.ts index 98a5f9a075..93fdb7e1f3 100644 --- a/website/src/data/components/waffle/props.ts +++ b/website/src/data/components/waffle/props.ts @@ -1,3 +1,4 @@ +// @ts-ignore import { WaffleDefaultProps } from '@nivo/waffle' import { themeProperty, @@ -6,7 +7,10 @@ import { getLegendsProps, groupProperties, } from '../../../lib/componentProperties' -import { ChartProperty } from '../../../types' +import { chartDimensions, ordinalColors, isInteractive } from '../../../lib/chart-properties' +import { ChartProperty, Flavor } from '../../../types' + +const allFlavors: Flavor[] = ['svg', 'html', 'canvas'] const defaults = WaffleDefaultProps @@ -18,7 +22,7 @@ const props: ChartProperty[] = [ required: true, help: 'Max value.', description: 'Max value, ratio will be computed against this value for each datum.', - flavors: ['svg', 'html', 'canvas'], + flavors: allFlavors, }, { key: 'data', @@ -36,7 +40,7 @@ const props: ChartProperty[] = [ `, type: 'object[]', required: true, - flavors: ['svg', 'html', 'canvas'], + flavors: allFlavors, }, // { // key: 'hiddenIds', @@ -59,9 +63,9 @@ const props: ChartProperty[] = [ type: 'number', help: 'Number of rows.', required: true, - flavors: ['svg', 'html', 'canvas'], - controlType: 'range', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', min: 1, max: 100, }, @@ -72,9 +76,9 @@ const props: ChartProperty[] = [ type: 'number', help: 'Number of columns.', required: true, - flavors: ['svg', 'html', 'canvas'], - controlType: 'range', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', min: 1, max: 100, }, @@ -85,10 +89,10 @@ const props: ChartProperty[] = [ type: 'string', required: false, help: `How to fill the waffle.`, - flavors: ['svg', 'html', 'canvas'], + flavors: allFlavors, defaultValue: defaults.fillDirection, - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: [ { label: 'top', value: 'top' }, { label: 'right', value: 'right' }, @@ -103,65 +107,15 @@ const props: ChartProperty[] = [ type: 'number', help: 'Padding between each cell.', required: true, - flavors: ['svg', 'html', 'canvas'], - controlType: 'range', - controlOptions: { + flavors: allFlavors, + control: { + type: 'range', unit: 'px', min: 0, max: 10, }, }, - { - key: 'width', - group: 'Base', - enableControlForFlavors: ['api'], - flavors: ['svg', 'html', 'canvas'], - help: 'Chart width.', - description: ` - not required if using responsive alternative - of the component - \`\`. - `, - type: 'number', - required: true, - }, - { - key: 'height', - group: 'Base', - enableControlForFlavors: ['api'], - flavors: ['svg', 'html', 'canvas'], - help: 'Chart height.', - description: ` - not required if using responsive alternative - of the component - \`\`. - `, - type: 'number', - required: true, - }, - { - key: 'pixelRatio', - flavors: ['canvas'], - help: `Adjust pixel ratio, useful for HiDPI screens.`, - required: false, - defaultValue: 'Depends on device', - type: `number`, - controlType: 'range', - group: 'Base', - controlOptions: { - min: 1, - max: 2, - }, - }, - { - key: 'margin', - group: 'Base', - type: 'object', - required: false, - help: 'Chart margin.', - flavors: ['svg', 'html', 'canvas'], - controlType: 'margin', - }, + ...chartDimensions(allFlavors), themeProperty(['svg', 'html', 'canvas']), { key: 'cellComponent', @@ -169,25 +123,19 @@ const props: ChartProperty[] = [ help: 'Override default cell component.', type: 'Function', required: false, - controlType: 'choices', group: 'Style', - controlOptions: { + control: { + type: 'choices', choices: ['default', 'Custom(props) => (…)'].map(key => ({ label: key, value: key, })), }, }, - { - key: 'colors', - group: 'Style', - type: 'string | Function | string[]', - required: false, - help: 'Defines how to compute node color.', + ordinalColors({ + flavors: allFlavors, defaultValue: defaults.colors, - flavors: ['svg', 'html', 'canvas'], - controlType: 'ordinalColors', - }, + }), { key: 'emptyColor', group: 'Style', @@ -195,8 +143,8 @@ const props: ChartProperty[] = [ type: 'string', required: false, defaultValue: defaults.emptyColor, - flavors: ['svg', 'html', 'canvas'], - controlType: 'colorPicker', + flavors: allFlavors, + control: { type: 'colorPicker' }, }, { key: 'emptyOpacity', @@ -205,8 +153,8 @@ const props: ChartProperty[] = [ required: false, defaultValue: defaults.emptyOpacity, type: 'number', - flavors: ['svg', 'html', 'canvas'], - controlType: 'opacity', + flavors: allFlavors, + control: { type: 'opacity' }, }, { key: 'borderWidth', @@ -215,8 +163,8 @@ const props: ChartProperty[] = [ required: false, help: 'Control cell border width.', defaultValue: defaults.borderWidth, - flavors: ['svg', 'html', 'canvas'], - controlType: 'lineWidth', + flavors: allFlavors, + control: { type: 'lineWidth' }, }, { key: 'borderColor', @@ -226,19 +174,13 @@ const props: ChartProperty[] = [ help: 'Method to compute cell border color.', defaultValue: defaults.borderColor, flavors: ['svg', 'html', 'canvas'], - controlType: 'inheritedColor', + control: { type: 'inheritedColor' }, }, ...defsProperties('Style', ['svg']), - { - key: 'isInteractive', - group: 'Interactivity', - type: 'boolean', - required: false, - help: 'Enable/disable interactivity.', - defaultValue: defaults.isInteractive, + isInteractive({ flavors: ['svg', 'html', 'canvas'], - controlType: 'switch', - }, + defaultValue: defaults.isInteractive, + }), { key: 'onClick', group: 'Interactivity', @@ -253,7 +195,7 @@ const props: ChartProperty[] = [ type: 'Function', required: false, help: 'Custom tooltip component', - flavors: ['svg', 'html', 'canvas'], + flavors: allFlavors, description: ` A function allowing complete tooltip customisation, it must return a valid HTML element and will @@ -281,9 +223,9 @@ const props: ChartProperty[] = [ group: 'Interactivity', type: 'boolean', required: false, - controlType: 'switch', + control: { type: 'switch' }, help: 'Showcase custom tooltip.', - flavors: ['svg', 'html', 'canvas'], + flavors: allFlavors, }, { key: 'legends', @@ -292,8 +234,8 @@ const props: ChartProperty[] = [ required: false, help: `Optional chart's legends.`, flavors: ['svg', 'canvas'], - controlType: 'array', - controlOptions: { + control: { + type: 'array', props: getLegendsProps(['svg', 'canvas']), shouldCreate: true, addLabel: 'add legend', @@ -310,8 +252,8 @@ const props: ChartProperty[] = [ symbolSize: 20, itemDirection: 'left-to-right', itemTextColor: '#777', - onClick: data => { - alert(JSON.stringify(data, null, ' ')) + onClick: (data: any) => { + console.log(JSON.stringify(data, null, ' ')) }, effects: [ { diff --git a/website/src/lib/chart-properties/axes.ts b/website/src/lib/chart-properties/axes.ts new file mode 100644 index 0000000000..41335f5104 --- /dev/null +++ b/website/src/lib/chart-properties/axes.ts @@ -0,0 +1,113 @@ +import upperFirst from 'lodash/upperFirst' +import { ChartProperty, Flavor } from '../../types' + +const positions = [ + { + position: 'top', + orientations: ['top', 'bottom'], + }, + { + position: 'right', + orientations: ['left', 'right'], + }, + { + position: 'bottom', + orientations: ['top', 'bottom'], + }, + { + position: 'left', + orientations: ['left', 'right'], + }, +] + +export const axes = ({ + flavors, + exclude = [], +}: { + flavors: Flavor[] + exclude?: string[] +}): ChartProperty[] => + positions + .filter(axis => !exclude.includes(axis.position)) + .reduce((properties: any[], { position }) => { + const axisKey = upperFirst(position) + + return [ + ...properties, + { + key: `axis${axisKey}`, + flavors, + help: `${axisKey} axis configuration.`, + type: 'object', + required: false, + group: 'Grid & Axes', + control: { + type: 'object', + props: [ + { + key: `enable`, + flavors, + help: `enable ${axisKey} axis, it's not an actual prop (demo only).`, + control: { type: 'switch' }, + excludeFromDoc: true, + }, + { + key: `tickSize`, + flavors, + help: `${axisKey} axis tick size.`, + type: 'number', + control: { + type: 'range', + unit: 'px', + min: 0, + max: 20, + }, + }, + { + key: `tickPadding`, + flavors, + help: `${axisKey} axis tick padding.`, + type: 'number', + control: { + type: 'range', + unit: 'px', + min: 0, + max: 20, + }, + }, + { + key: `tickRotation`, + flavors, + help: `${axisKey} axis tick rotation.`, + type: 'number', + control: { + type: 'angle', + start: 90, + min: -90, + max: 90, + }, + }, + { + key: `legend`, + flavors, + help: `${axisKey} axis legend.`, + type: 'string', + control: { type: 'text' }, + }, + { + key: `legendOffset`, + flavors, + help: `${axisKey} axis legend offset from axis.`, + type: 'number', + control: { + type: 'range', + unit: 'px', + min: -60, + max: 60, + }, + }, + ], + }, + }, + ] + }, []) diff --git a/website/src/lib/chart-properties/chart-dimensions.ts b/website/src/lib/chart-properties/chart-dimensions.ts new file mode 100644 index 0000000000..cca6af768f --- /dev/null +++ b/website/src/lib/chart-properties/chart-dimensions.ts @@ -0,0 +1,84 @@ +import { ChartProperty, Flavor } from '../../types' + +export const chartWidth = (flavors: Flavor[]): ChartProperty => ({ + key: 'width', + group: 'Base', + type: 'number', + required: true, + help: 'Chart width.', + description: ` + Not required if using responsive component, \`\`. + + Also note that width does not include labels/axes, + so you should add enough margin to display them. + `, + flavors, + enableControlForFlavors: ['api'], + control: { + type: 'range', + unit: 'px', + min: 100, + max: 1000, + step: 5, + }, +}) + +export const chartHeight = (flavors: Flavor[]): ChartProperty => ({ + key: 'height', + group: 'Base', + type: 'number', + required: true, + help: 'Chart height.', + description: ` + Not required if using responsive component, \`\`. + + Also note that height does not include labels/axes, + so you should add enough margin to display them. + `, + flavors, + enableControlForFlavors: ['api'], + control: { + type: 'range', + unit: 'px', + min: 100, + max: 1000, + step: 5, + }, +}) + +export const chartMargin = (flavors: Flavor[]): ChartProperty => ({ + key: 'margin', + group: 'Base', + help: 'Chart margin.', + type: 'object', + required: false, + flavors, + control: { type: 'margin' }, +}) + +export const pixelRatio = (): ChartProperty => ({ + key: 'pixelRatio', + flavors: ['canvas'], + help: `Adjust pixel ratio, useful for HiDPI screens.`, + required: false, + defaultValue: 'Depends on device', + type: `number`, + group: 'Base', + control: { + type: 'range', + min: 1, + max: 2, + }, +}) + +export const chartDimensions = (flavors: Flavor[]): ChartProperty[] => { + const properties: ChartProperty[] = [chartWidth(flavors), chartHeight(flavors)] + + if (flavors.includes('canvas')) { + properties.push(pixelRatio()) + } + + properties.push(chartMargin(flavors)) + + return properties +} diff --git a/website/src/lib/chart-properties/colors.ts b/website/src/lib/chart-properties/colors.ts new file mode 100644 index 0000000000..f1564fca2c --- /dev/null +++ b/website/src/lib/chart-properties/colors.ts @@ -0,0 +1,57 @@ +import { CssMixBlendMode } from '@nivo/core' +import { OrdinalColorScaleConfig } from '@nivo/colors' +import { ChartProperty, Flavor } from '../../types' + +export const ordinalColors = ({ + key = 'colors', + group = 'Style', + flavors, + help = `Define chart's colors.`, + description = `Please see the [dedicated documentation](self:/guides/colors) for colors.`, + defaultValue, +}: { + key?: string + group?: string + flavors: Flavor[] + help?: string + description?: string + defaultValue: OrdinalColorScaleConfig +}): ChartProperty => ({ + key, + group, + type: 'OrdinalColorScaleConfig', + help, + description, + required: false, + defaultValue, + flavors, + control: { type: 'ordinalColors' }, +}) + +export const blendMode = ({ + key = 'blendMode', + target, + description, + group = 'Style', + flavors, + required = false, + defaultValue, +}: { + key?: string + target: string + description?: string + group?: string + flavors: Flavor[] + required?: boolean + defaultValue: CssMixBlendMode +}): ChartProperty => ({ + key, + group, + type: 'CssMixBlendMode', + help: `Define CSS [\`mix-blend-mode\`](https://developer.mozilla.org/fr/docs/Web/CSS/mix-blend-mode) for ${target}.`, + description, + required, + defaultValue, + flavors, + control: { type: 'blendMode' }, +}) diff --git a/website/src/lib/chart-properties/grid.ts b/website/src/lib/chart-properties/grid.ts new file mode 100644 index 0000000000..a92b5b3a83 --- /dev/null +++ b/website/src/lib/chart-properties/grid.ts @@ -0,0 +1,77 @@ +import { ChartProperty, Flavor } from '../../types' + +const defaultGroup = 'Grid & Axes' + +export const enableGridAxis = ({ + axis, + group = defaultGroup, + flavors, + defaultValue, +}: { + axis: 'x' | 'y' + group?: string + flavors: Flavor[] + defaultValue?: boolean +}): ChartProperty => ({ + key: `enableGrid${axis.toUpperCase()}`, + group, + flavors, + type: 'boolean', + required: false, + defaultValue, + help: `Enable/disable ${axis} grid.`, + control: { type: 'switch' }, +}) + +export const gridAxisValues = ({ + axis, + group = defaultGroup, + flavors, +}: { + axis: 'x' | 'y' + group?: string + flavors: Flavor[] +}): ChartProperty => ({ + key: `grid${axis.toUpperCase()}Values`, + group, + help: `Specify values to use for ${axis === 'x' ? 'vertical' : 'horizontal'} grid lines.`, + type: '(number | string)[]', + flavors, + required: false, +}) + +export const chartGrid = ({ + x = true, + xDefault, + y = true, + yDefault, + values = false, + group = defaultGroup, + flavors, +}: { + group?: string + x?: boolean + xDefault?: boolean + y?: boolean + yDefault?: boolean + values?: boolean + flavors: Flavor[] +}): ChartProperty[] => { + const properties: ChartProperty[] = [] + + if (x) { + properties.push(enableGridAxis({ axis: 'x', group, flavors, defaultValue: xDefault })) + if (values) { + properties.push(gridAxisValues({ axis: 'x', group, flavors })) + } + } + + if (y) { + properties.push(enableGridAxis({ axis: 'y', group, flavors, defaultValue: yDefault })) + if (values) { + properties.push(gridAxisValues({ axis: 'y', group, flavors })) + } + } + + return properties +} diff --git a/website/src/lib/chart-properties/index.ts b/website/src/lib/chart-properties/index.ts new file mode 100644 index 0000000000..ddf6ecc123 --- /dev/null +++ b/website/src/lib/chart-properties/index.ts @@ -0,0 +1,5 @@ +export * from './axes' +export * from './chart-dimensions' +export * from './colors' +export * from './grid' +export * from './interactivity' diff --git a/website/src/lib/chart-properties/interactivity.ts b/website/src/lib/chart-properties/interactivity.ts new file mode 100644 index 0000000000..01e472fe7d --- /dev/null +++ b/website/src/lib/chart-properties/interactivity.ts @@ -0,0 +1,18 @@ +import { ChartProperty, Flavor } from '../../types' + +export const isInteractive = ({ + flavors, + defaultValue, +}: { + flavors: Flavor[] + defaultValue: boolean +}): ChartProperty => ({ + key: 'isInteractive', + group: 'Interactivity', + type: 'boolean', + help: 'Enable/disable interactivity.', + required: false, + defaultValue, + flavors, + control: { type: 'switch' }, +}) diff --git a/website/src/lib/componentProperties.ts b/website/src/lib/componentProperties.ts index c019e7b3c8..a29ccdbe6c 100644 --- a/website/src/lib/componentProperties.ts +++ b/website/src/lib/componentProperties.ts @@ -1,4 +1,3 @@ -import upperFirst from 'lodash/upperFirst' import uniq from 'lodash/uniq' import { defaultAnimate, defaultMotionStiffness, defaultMotionDamping } from '@nivo/core' import { Flavor, ChartProperty } from '../types' @@ -58,7 +57,7 @@ export const motionProperties = ( type: 'boolean', required: false, defaultValue: defaults.animate !== undefined ? defaults.animate : defaultAnimate, - controlType: 'switch', + control: { type: 'switch' }, group: 'Motion', }, ] @@ -75,8 +74,8 @@ export const motionProperties = ( ? defaults.motionStiffness : defaultMotionStiffness, group: 'Motion', - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 300, step: 5, @@ -92,9 +91,9 @@ export const motionProperties = ( defaults.motionDamping !== undefined ? defaults.motionDamping : defaultMotionDamping, - controlType: 'range', group: 'Motion', - controlOptions: { + control: { + type: 'range', min: 0, max: 40, }, @@ -107,7 +106,7 @@ export const motionProperties = ( type: 'string | object', required: false, defaultValue: defaults.motionConfig, - controlType: 'motionConfig', + control: { type: 'motionConfig' }, group: 'Motion', }) } @@ -115,115 +114,6 @@ export const motionProperties = ( return props } -export const axesProperties = ({ - flavors, - exclude = [], -}: { - flavors?: Flavor[] - exclude?: string[] -} = {}): ChartProperty[] => - [ - { - position: 'top', - orientations: ['top', 'bottom'], - }, - { - position: 'right', - orientations: ['left', 'right'], - }, - { - position: 'bottom', - orientations: ['top', 'bottom'], - }, - { - position: 'left', - orientations: ['left', 'right'], - }, - ] - .filter(axis => !exclude.includes(axis.position)) - .reduce((properties: any[], { position }) => { - const axisKey = upperFirst(position) - - return [ - ...properties, - { - key: `axis${axisKey}`, - flavors, - help: `${axisKey} axis configuration.`, - type: 'object', - required: false, - group: 'Grid & Axes', - controlType: 'object', - controlOptions: { - props: [ - { - key: `enable`, - flavors, - help: `enable ${axisKey} axis, it's not an actual prop (demo only).`, - controlType: 'switch', - excludeFromDoc: true, - }, - { - key: `tickSize`, - flavors, - help: `${axisKey} axis tick size.`, - type: 'number', - controlType: 'range', - controlOptions: { - unit: 'px', - min: 0, - max: 20, - }, - }, - { - key: `tickPadding`, - flavors, - help: `${axisKey} axis tick padding.`, - type: 'number', - controlType: 'range', - controlOptions: { - unit: 'px', - min: 0, - max: 20, - }, - }, - { - key: `tickRotation`, - flavors, - help: `${axisKey} axis tick rotation.`, - type: 'number', - controlType: 'angle', - controlOptions: { - start: 90, - min: -90, - max: 90, - }, - }, - { - key: `legend`, - flavors, - help: `${axisKey} axis legend.`, - type: 'string', - controlType: 'text', - }, - { - key: `legendOffset`, - flavors, - help: `${axisKey} axis legend offset from axis.`, - type: 'number', - controlType: 'range', - controlOptions: { - unit: 'px', - min: -60, - max: 60, - }, - }, - ], - }, - }, - ] - }, []) - export const getLegendsProps = (flavors: Flavor[]): Omit[] => [ { key: 'anchor', @@ -231,7 +121,7 @@ export const getLegendsProps = (flavors: Flavor[]): Omit help: `Defines legend anchor relative to chart's viewport.`, type: 'string', required: false, - controlType: 'boxAnchor', + control: { type: 'boxAnchor' }, }, { key: 'direction', @@ -239,8 +129,8 @@ export const getLegendsProps = (flavors: Flavor[]): Omit help: `Legend direction, must be one of 'column', 'row'.`, type: `'column' | 'row'`, required: false, - controlType: 'radio', - controlOptions: { + control: { + type: 'radio', choices: [ { label: 'column', @@ -257,7 +147,7 @@ export const getLegendsProps = (flavors: Flavor[]): Omit key: 'justify', flavors, help: `Justify symbol and label.`, - controlType: 'switch', + control: { type: 'switch' }, type: 'boolean', required: false, }, @@ -267,8 +157,8 @@ export const getLegendsProps = (flavors: Flavor[]): Omit help: `Legend block x translation.`, type: `number`, required: false, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: -200, max: 200, unit: 'px', @@ -280,8 +170,8 @@ export const getLegendsProps = (flavors: Flavor[]): Omit help: `Legend block y translation.`, type: `number`, required: false, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: -200, max: 200, unit: 'px', @@ -293,8 +183,8 @@ export const getLegendsProps = (flavors: Flavor[]): Omit help: `Legend item width.`, type: `number`, required: true, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 10, max: 200, unit: 'px', @@ -306,8 +196,8 @@ export const getLegendsProps = (flavors: Flavor[]): Omit help: `Legend item height.`, type: `number`, required: true, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 10, max: 200, unit: 'px', @@ -319,8 +209,8 @@ export const getLegendsProps = (flavors: Flavor[]): Omit help: `Spacing between each item.`, type: `number`, required: false, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 0, max: 60, unit: 'px', @@ -332,8 +222,8 @@ export const getLegendsProps = (flavors: Flavor[]): Omit help: `Item symbol size.`, type: `number`, required: false, - controlType: 'range', - controlOptions: { + control: { + type: 'range', min: 2, max: 60, unit: 'px', @@ -345,8 +235,8 @@ export const getLegendsProps = (flavors: Flavor[]): Omit help: `Item layout direction.`, type: `string`, required: false, - controlType: 'choices', - controlOptions: { + control: { + type: 'choices', choices: ['left-to-right', 'right-to-left', 'top-to-bottom', 'bottom-to-top'].map( v => ({ label: v, @@ -407,8 +297,8 @@ export const polarAxisProperty = ({ type: 'object', required: false, flavors, - controlType: 'object', - controlOptions: { + control: { + type: 'object', props: [ { key: 'enable', @@ -417,7 +307,7 @@ export const polarAxisProperty = ({ help: `enable ${key} axis, it's not an actual prop (demo only).`, flavors, excludeFromDoc: true, - controlType: 'switch', + control: { type: 'switch' }, }, { key: 'tickSize', @@ -425,8 +315,8 @@ export const polarAxisProperty = ({ required: false, help: `${key} axis tick size.`, flavors, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 20, @@ -438,8 +328,8 @@ export const polarAxisProperty = ({ required: false, help: `${key} axis tick padding.`, flavors, - controlType: 'range', - controlOptions: { + control: { + type: 'range', unit: 'px', min: 0, max: 20, @@ -451,8 +341,8 @@ export const polarAxisProperty = ({ required: false, help: `${key} axis tick rotation.`, flavors, - controlType: 'angle', - controlOptions: { + control: { + type: 'angle', start: 90, min: -90, max: 90, diff --git a/website/src/pages/line/canvas.js b/website/src/pages/line/canvas.js index 763e31ab7a..302ba7cdb1 100644 --- a/website/src/pages/line/canvas.js +++ b/website/src/pages/line/canvas.js @@ -16,6 +16,8 @@ const initialProperties = { useMesh: true, debugMesh: false, curve: 'monotoneX', + pixelRatio: + typeof window !== 'undefined' && window.devicePixelRatio ? window.devicePixelRatio : 1, margin: { top: 50, right: 160, diff --git a/website/src/types.ts b/website/src/types.ts index 79f58dee50..76c1aebba0 100644 --- a/website/src/types.ts +++ b/website/src/types.ts @@ -1,4 +1,5 @@ export type Flavor = 'svg' | 'html' | 'canvas' | 'api' +import { ControlConfig } from './components/controls/types' export interface ChartMeta { package: string @@ -10,156 +11,19 @@ export interface ChartMeta { }[] } -export interface SwitchControlAttrs { - controlType: 'switch' +export interface ArrayPropertyControlAttrs { + props: ChartProperty[] + shouldCreate: boolean + addLabel: string + shouldRemove: boolean + removeLabel: string + defaults: object + getItemTitle: (index: number, item: unknown) => string } -export type SwitchProperty = BaseChartProperty & SwitchControlAttrs -export interface RangeControlAttrs { - controlType: 'range' - controlOptions: { - min: number - max: number - step?: number - unit?: 'px' | '°' - } -} -export type RangeProperty = BaseChartProperty & RangeControlAttrs - -export interface MotionConfigControlAttrs { - controlType: 'motionConfig' -} -export type MotionConfigProperty = BaseChartProperty & MotionConfigControlAttrs - -export interface BoxAnchorControlAttrs { - controlType: 'boxAnchor' -} -export type BoxAnchorProperty = BaseChartProperty & BoxAnchorControlAttrs - -export interface ChoicesControlAttrs { - controlType: 'choices' - controlOptions: { - choices: { - label: string - value: string - }[] - } -} -export type ChoicesProperty = BaseChartProperty & ChoicesControlAttrs - -export interface RadioControlAttrs { - controlType: 'radio' - controlOptions: { - choices: { - label: string - value: string - }[] - } -} -export type RadioProperty = BaseChartProperty & RadioControlAttrs - -export interface ValueFormatControlAttrs { - controlType: 'valueFormat' -} -export type ValueFormatProperty = BaseChartProperty & ValueFormatControlAttrs - -export interface MarginControlAttrs { - controlType: 'margin' -} -export type MarginProperty = BaseChartProperty & MarginControlAttrs - -export interface OpacityControlAttrs { - controlType: 'opacity' -} -export type OpacityChartProperty = BaseChartProperty & OpacityControlAttrs - -export interface LineWidthControlAttrs { - controlType: 'lineWidth' - controlOptions?: { - step?: number - } -} -export type LineWidthProperty = BaseChartProperty & LineWidthControlAttrs - -export interface BlendModeControlAttrs { - controlType: 'blendMode' -} -export type BlendModeProperty = BaseChartProperty & BlendModeControlAttrs - -export interface InheritedColorControlAttrs { - controlType: 'inheritedColor' - controlOptions?: { - inheritableProperties?: string[] - } -} -export type InheritedColorProperty = BaseChartProperty & InheritedColorControlAttrs - -export interface OrdinalColorsControlAttrs { - controlType: 'ordinalColors' -} -export type OrdinalColorsProperty = BaseChartProperty & OrdinalColorsControlAttrs - -export interface NumberArrayControlAttrs { - controlType: 'numberArray' - controlOptions: { - unit?: 'px' | '°' - items: { - label: string - min?: number - max?: number - step?: number - }[] - } -} -export type NumberArrayProperty = BaseChartProperty & NumberArrayControlAttrs - -export interface ColorPickerControlAttrs { - controlType: 'colorPicker' -} -export type ColorPickerProperty = BaseChartProperty & ColorPickerControlAttrs - -export interface QuantizeColorsControlAttrs { - controlType: 'quantizeColors' -} -export type QuantizeColorsProperty = BaseChartProperty & QuantizeColorsControlAttrs - -export interface SwitchableRangeControlAttrs { - controlType: 'switchableRange' - controlOptions: { - disabledValue: string - defaultValue: number - min: number - max: number - } -} -export type SwitchableRangeProperty = BaseChartProperty & SwitchableRangeControlAttrs - -export interface AngleControlAttrs { - controlType: 'angle' - controlOptions: { - start?: number - min?: number - max?: number - step?: number - } -} -export type AngleChartProperty = BaseChartProperty & AngleControlAttrs - -export interface ObjectControlAttrs { - controlType: 'object' - controlOptions: { - props: ( - | Omit - | Omit - | Omit - | Omit - )[] - } -} -export type ObjectChartProperty = BaseChartProperty & ObjectControlAttrs - -export interface BaseChartProperty { +export interface ChartProperty { key: string + name?: string group: string // type of the property, preferably expressed with TypeScript notation type: string @@ -178,26 +42,6 @@ export interface BaseChartProperty { // not used at the moment, indicate that a property is just used // for the demo and not part of the component props. excludeFromDoc?: boolean + control?: ControlConfig + when?: (settings: any) => boolean } - -export type ChartProperty = - | BaseChartProperty - | SwitchProperty - | RangeProperty - | MotionConfigProperty - | BoxAnchorProperty - | ChoicesProperty - | RadioProperty - | ValueFormatProperty - | MarginProperty - | OpacityChartProperty - | LineWidthProperty - | BlendModeProperty - | InheritedColorProperty - | OrdinalColorsProperty - | NumberArrayProperty - | ColorPickerProperty - | QuantizeColorsProperty - | SwitchableRangeProperty - | ObjectChartProperty - | AngleChartProperty diff --git a/website/tsconfig.json b/website/tsconfig.json index 126168a22a..31c5845395 100644 --- a/website/tsconfig.json +++ b/website/tsconfig.json @@ -2,6 +2,7 @@ "include": ["./src/**/*"], "exclude": ["node_modules"], "compilerOptions": { + "lib": ["ES2020", "DOM"], "target": "es5", "jsx": "react", "skipLibCheck": true,