/
AngleControl.tsx
94 lines (85 loc) · 2.88 KB
/
AngleControl.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import React, { memo, useCallback } from 'react'
import styled from 'styled-components'
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
const markerSize = 6
interface AngleControlProps {
id: string
property: ChartProperty
flavors: Flavor[]
currentFlavor: Flavor
value: number
config: AngleControlConfig
onChange: (value: number) => void
context?: any
}
export const AngleControl = memo(
({ 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 => {
onChange(Number(event.target.value))
},
[onChange]
)
return (
<Control
id={id}
description={property.description}
flavors={flavors}
currentFlavor={currentFlavor}
supportedFlavors={property.flavors}
>
<PropertyHeader id={id} {...property} />
<Row>
<TextInput
id={id}
value={value}
onChange={handleChange}
unit="°"
isNumber={true}
/>
<svg width={size} height={size}>
<Circle cx={center} cy={center} r={center - markerSize / 2} />
<g transform={`translate(${center},${center})`}>
<g transform={`rotate(${start + value})`}>
<Line y2={-size / 2 + markerSize / 2} />
<Marker r={markerSize / 4} />
<Marker cy={-size / 2 + markerSize / 2} r={markerSize / 2} />
</g>
</g>
</svg>
<input type="range" value={value} onChange={handleChange} min={min} max={max} />
</Row>
<Help>{property.help}</Help>
</Control>
)
}
)
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 Circle = styled.circle`
fill: ${({ theme }) => theme.colors.background};
stroke-width: 1px;
stroke: ${({ theme }) => theme.colors.border};
`
const Line = styled.line`
stroke: ${({ theme }) => theme.colors.accent};
`
const Marker = styled.circle`
fill: ${({ theme }) => theme.colors.accent};
`