1
1
import _ from 'lodash' ;
2
2
import tinycolor from 'tinycolor2' ;
3
- import React , { Component } from 'react' ;
3
+ import React , { useCallback , useEffect , useState } from 'react' ;
4
4
import { StyleProp , ViewStyle } from 'react-native' ;
5
5
import { Colors } from '../../style' ;
6
6
import { asBaseComponent , forwardRef , ForwardRefInjectedProps } from '../../commons/new' ;
@@ -19,7 +19,10 @@ export enum GradientSliderTypes {
19
19
SATURATION = 'saturation'
20
20
}
21
21
22
- export type GradientSliderProps = Omit < SliderProps , 'onValueChange' > & {
22
+ export type GradientSliderProps = Omit <
23
+ SliderProps ,
24
+ 'onValueChange' | 'value' | 'minimumValue' | 'maximumValue' | 'step' | 'thumbHitSlop' | 'useGap'
25
+ > & {
23
26
/**
24
27
* The gradient color
25
28
*/
@@ -48,196 +51,166 @@ export type GradientSliderProps = Omit<SliderProps, 'onValueChange'> & {
48
51
* If true the Slider will be disabled and will appear in disabled color
49
52
*/
50
53
disabled ?: boolean ;
51
- } ;
54
+ } & Partial < Pick < SliderProps , 'value' | 'minimumValue' | 'maximumValue' | 'step' | 'thumbHitSlop' | 'useGap' > > ; // Fixes typing errors with the old slider.
52
55
53
56
type GradientSliderComponentProps = {
54
57
/**
55
58
* Context of the slider group
56
59
*/
57
60
sliderContext : SliderContextProps ;
58
- } & GradientSliderProps &
59
- typeof defaultProps ;
61
+ } & GradientSliderProps ;
60
62
61
63
type Props = GradientSliderComponentProps & ForwardRefInjectedProps ;
62
64
63
- interface GradientSliderState {
64
- color : tinycolor . ColorFormats . HSLA ;
65
- initialColor : tinycolor . ColorFormats . HSLA ;
66
- prevColor : string | undefined ;
67
- }
68
-
69
- const defaultProps = {
70
- type : GradientSliderTypes . DEFAULT ,
71
- gradientSteps : 120 ,
72
- color : Colors . $backgroundPrimaryHeavy
73
- } ;
74
-
75
65
/**
76
66
* @description : A Gradient Slider component
77
67
* @example : https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/SliderScreen.tsx
78
68
* @gif : https://github.com/wix/react-native-ui-lib/blob/master/demo/showcase/GradientSlider/GradientSlider.gif?raw=true
79
69
*/
80
- class GradientSlider extends Component < Props , GradientSliderState > {
81
- static displayName = 'GradientSlider' ;
82
-
83
- static defaultProps = defaultProps ;
84
-
85
- static types = GradientSliderTypes ;
86
-
87
- constructor ( props : Props ) {
88
- super ( props ) ;
89
-
90
- this . state = {
91
- prevColor : props . color ,
92
- initialColor : Colors . getHSL ( props . color ) ,
93
- color : Colors . getHSL ( props . color )
94
- } ;
95
- }
96
-
97
- static getDerivedStateFromProps ( nextProps : Props , prevState : GradientSliderState ) {
98
- if ( prevState . prevColor !== nextProps . color ) {
99
- return {
100
- color : Colors . getHSL ( nextProps . color ) ,
101
- prevColor : Colors . getHSL ( nextProps . color )
102
- } ;
103
- }
104
- return null ;
105
- }
106
-
107
- slider = React . createRef ( ) ;
108
-
109
- reset = ( ) => {
110
- this . updateColor ( this . state . initialColor ) ;
111
- } ;
112
-
113
- getColor ( ) {
114
- const { color} = this . state ;
115
- const { value} = this . props . sliderContext ;
116
-
117
- return value || color ;
118
- }
119
-
120
- getStepColor = ( i : number ) => {
121
- const color = this . getColor ( ) ;
122
- return tinycolor ( { ...color , a : i } ) . toHslString ( ) ;
123
- } ;
124
-
125
- renderDefaultGradient = ( ) => {
126
- const color = this . getColor ( ) ;
127
- const { gradientSteps} = this . props ;
70
+ const GradientSlider = ( props : Props ) => {
71
+ const {
72
+ type = GradientSliderTypes . DEFAULT ,
73
+ gradientSteps = 120 ,
74
+ color : propsColors = Colors . $backgroundPrimaryHeavy ,
75
+ sliderContext,
76
+ onValueChange : _onValueChange ,
77
+ migrate,
78
+ containerStyle,
79
+ disabled,
80
+ accessible,
81
+ forwardedRef,
82
+ ...others
83
+ } = props ;
84
+
85
+ const [ initialColor ] = useState ( Colors . getHSL ( propsColors ) ) ;
86
+ const [ color , setColor ] = useState ( Colors . getHSL ( propsColors ) ) ;
87
+
88
+ useEffect ( ( ) => {
89
+ setColor ( Colors . getHSL ( propsColors ) ) ;
90
+ } , [ propsColors ] ) ;
91
+
92
+ const getColor = useCallback ( ( ) => {
93
+ return color || sliderContext . value ;
94
+ } , [ color , sliderContext . value ] ) ;
95
+
96
+ const renderDefaultGradient = useCallback ( ( ) => {
97
+ const color = getColor ( ) ;
128
98
129
99
return < Gradient color = { color } numberOfSteps = { gradientSteps } /> ;
130
- } ;
131
-
132
- renderHueGradient = ( ) => {
133
- const { gradientSteps} = this . props ;
100
+ } , [ getColor , gradientSteps ] ) ;
134
101
102
+ const renderHueGradient = useCallback ( ( ) => {
135
103
return < Gradient type = { Gradient . types . HUE } numberOfSteps = { gradientSteps } /> ;
136
- } ;
137
-
138
- renderLightnessGradient = ( ) => {
139
- const color = this . getColor ( ) ;
140
- const { gradientSteps} = this . props ;
104
+ } , [ gradientSteps ] ) ;
141
105
106
+ const renderLightnessGradient = useCallback ( ( ) => {
107
+ const color = getColor ( ) ;
142
108
return < Gradient type = { Gradient . types . LIGHTNESS } color = { color } numberOfSteps = { gradientSteps } /> ;
143
- } ;
144
-
145
- renderSaturationGradient = ( ) => {
146
- const color = this . getColor ( ) ;
147
- const { gradientSteps} = this . props ;
109
+ } , [ getColor , gradientSteps ] ) ;
148
110
111
+ const renderSaturationGradient = useCallback ( ( ) => {
112
+ const color = getColor ( ) ;
149
113
return < Gradient type = { Gradient . types . SATURATION } color = { color } numberOfSteps = { gradientSteps } /> ;
150
- } ;
114
+ } , [ getColor , gradientSteps ] ) ;
151
115
152
- onValueChange = ( value : string , alpha : number ) => {
116
+ const onValueChange = useCallback ( ( value : string , alpha : number ) => {
153
117
// alpha returns for type.DEFAULT
154
- this . props . onValueChange ?.( value , alpha ) ;
155
- } ;
118
+ _onValueChange ?.( value , alpha ) ;
119
+ } ,
120
+ [ _onValueChange ] ) ;
156
121
157
- updateColor ( color : tinycolor . ColorFormats . HSLA ) {
158
- if ( ! _ . isEmpty ( this . props . sliderContext ) ) {
159
- this . props . sliderContext . setValue ?.( color ) ;
122
+ const updateColor = useCallback ( ( color : tinycolor . ColorFormats . HSLA ) => {
123
+ if ( ! _ . isEmpty ( sliderContext ) ) {
124
+ sliderContext . setValue ?.( color ) ;
160
125
} else {
161
- this . setState ( { color} ) ;
126
+ setColor ( color ) ;
162
127
const hex = Colors . getHexString ( color ) ;
163
- this . onValueChange ( hex , color . a ) ;
128
+ onValueChange ( hex , color . a ) ;
164
129
}
130
+ } ,
131
+ [ sliderContext , onValueChange ] ) ;
132
+
133
+ const reset = useCallback ( ( ) => {
134
+ updateColor ( initialColor ) ;
135
+ } , [ initialColor , updateColor ] ) ;
136
+
137
+ const updateAlpha = useCallback ( ( a : number ) => {
138
+ const color = getColor ( ) ;
139
+ updateColor ( { ...color , a} ) ;
140
+ } ,
141
+ [ getColor , updateColor ] ) ;
142
+
143
+ const updateHue = useCallback ( ( h : number ) => {
144
+ const color = getColor ( ) ;
145
+ updateColor ( { ...color , h} ) ;
146
+ } ,
147
+ [ getColor , updateColor ] ) ;
148
+
149
+ const updateLightness = useCallback ( ( l : number ) => {
150
+ const color = getColor ( ) ;
151
+ updateColor ( { ...color , l} ) ;
152
+ } ,
153
+ [ getColor , updateColor ] ) ;
154
+
155
+ const updateSaturation = useCallback ( ( s : number ) => {
156
+ const color = getColor ( ) ;
157
+ updateColor ( { ...color , s} ) ;
158
+ } ,
159
+ [ getColor , updateColor ] ) ;
160
+
161
+ const _color = getColor ( ) ;
162
+ const thumbTintColor = Colors . getHexString ( _color ) ;
163
+ let step = 0.01 ;
164
+ let maximumValue = 1 ;
165
+ let value = color . a ;
166
+ let renderTrack = renderDefaultGradient ;
167
+ let sliderOnValueChange = updateAlpha ;
168
+
169
+ switch ( type ) {
170
+ case GradientSliderTypes . HUE :
171
+ step = 1 ;
172
+ maximumValue = 359 ;
173
+ value = initialColor . h ;
174
+ renderTrack = renderHueGradient ;
175
+ sliderOnValueChange = updateHue ;
176
+ break ;
177
+ case GradientSliderTypes . LIGHTNESS :
178
+ value = initialColor . l ;
179
+ renderTrack = renderLightnessGradient ;
180
+ sliderOnValueChange = updateLightness ;
181
+ break ;
182
+ case GradientSliderTypes . SATURATION :
183
+ value = initialColor . s ;
184
+ renderTrack = renderSaturationGradient ;
185
+ sliderOnValueChange = updateSaturation ;
186
+ break ;
187
+ default :
188
+ break ;
165
189
}
190
+ const SliderComponent = migrate ? NewSlider : Slider ;
191
+
192
+ return (
193
+ < SliderComponent
194
+ { ...others }
195
+ //@ts -expect-error
196
+ ref = { forwardedRef }
197
+ onReset = { reset }
198
+ renderTrack = { renderTrack }
199
+ step = { step }
200
+ maximumValue = { maximumValue }
201
+ value = { value }
202
+ thumbTintColor = { thumbTintColor }
203
+ onValueChange = { sliderOnValueChange }
204
+ containerStyle = { containerStyle }
205
+ disabled = { disabled }
206
+ accessible = { accessible }
207
+ useRange = { false }
208
+ />
209
+ ) ;
210
+ } ;
166
211
167
- updateAlpha = ( a : number ) => {
168
- const color = this . getColor ( ) ;
169
- this . updateColor ( { ...color , a} ) ;
170
- } ;
171
-
172
- updateHue = ( h : number ) => {
173
- const color = this . getColor ( ) ;
174
- this . updateColor ( { ...color , h} ) ;
175
- } ;
176
-
177
- updateLightness = ( l : number ) => {
178
- const color = this . getColor ( ) ;
179
- this . updateColor ( { ...color , l} ) ;
180
- } ;
181
-
182
- updateSaturation = ( s : number ) => {
183
- const color = this . getColor ( ) ;
184
- this . updateColor ( { ...color , s} ) ;
185
- } ;
186
-
187
- render ( ) {
188
- const { type, containerStyle, disabled, accessible, forwardedRef, migrate, ...others } = this . props ;
189
- const initialColor = this . state . initialColor ;
190
- const color = this . getColor ( ) ;
191
- const thumbTintColor = Colors . getHexString ( color ) ;
192
- let step = 0.01 ;
193
- let maximumValue = 1 ;
194
- let value = color . a ;
195
- let renderTrack = this . renderDefaultGradient ;
196
- let onValueChange = this . updateAlpha ;
197
-
198
- switch ( type ) {
199
- case GradientSliderTypes . HUE :
200
- step = 1 ;
201
- maximumValue = 359 ;
202
- value = initialColor . h ;
203
- renderTrack = this . renderHueGradient ;
204
- onValueChange = this . updateHue ;
205
- break ;
206
- case GradientSliderTypes . LIGHTNESS :
207
- value = initialColor . l ;
208
- renderTrack = this . renderLightnessGradient ;
209
- onValueChange = this . updateLightness ;
210
- break ;
211
- case GradientSliderTypes . SATURATION :
212
- value = initialColor . s ;
213
- renderTrack = this . renderSaturationGradient ;
214
- onValueChange = this . updateSaturation ;
215
- break ;
216
- default :
217
- break ;
218
- }
219
-
220
- const SliderComponent = migrate ? NewSlider : Slider ;
221
-
222
- return (
223
- < SliderComponent
224
- { ...others }
225
- //@ts -expect-error
226
- ref = { forwardedRef }
227
- onReset = { this . reset }
228
- renderTrack = { renderTrack }
229
- step = { step }
230
- maximumValue = { maximumValue }
231
- value = { value }
232
- thumbTintColor = { thumbTintColor }
233
- onValueChange = { onValueChange }
234
- containerStyle = { containerStyle }
235
- disabled = { disabled }
236
- accessible = { accessible }
237
- useRange = { false }
238
- />
239
- ) ;
240
- }
241
- }
212
+ GradientSlider . displayName = 'GradientSlider' ;
213
+ GradientSlider . types = GradientSliderTypes ;
242
214
243
- export default asBaseComponent < GradientSliderComponentProps , typeof GradientSlider > ( forwardRef ( asSliderGroupChild ( GradientSlider ) ) ) ;
215
+ // eslint-disable-next-line max-len
216
+ export default asBaseComponent < GradientSliderProps , typeof GradientSlider > ( forwardRef ( asSliderGroupChild ( forwardRef ( GradientSlider ) ) ) ) ;
0 commit comments