@ledvance/base 1.3.66 → 1.3.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,266 +0,0 @@
1
- import React, { Component } from 'react';
2
- import _ from 'lodash';
3
- import { View, ViewStyle, StyleProp } from 'react-native';
4
- import RectPicker, { ValidBound, Point, defaultProps as baseDefault } from './RectPicker';
5
- import Slider, { IBrightOption } from './Slider';
6
- import ColorUtils from './utils/color';
7
-
8
-
9
- export const rectGradientBg = [
10
- {
11
- colors: [
12
- { offset: '0%', stopColor: '#FF0000', stopOpacity: 1 },
13
- { offset: '8%', stopColor: '#FF7F00', stopOpacity: 1 },
14
- { offset: '20%', stopColor: '#FFFF00', stopOpacity: 1 },
15
- { offset: '25%', stopColor: '#7FFF00', stopOpacity: 1 },
16
- { offset: '33%', stopColor: '#00FF00', stopOpacity: 1 },
17
- { offset: '42%', stopColor: '#00FF7F', stopOpacity: 1 },
18
- { offset: '50%', stopColor: '#00FFFF', stopOpacity: 1 },
19
- { offset: '58%', stopColor: '#007FFF', stopOpacity: 1 },
20
- { offset: '66%', stopColor: '#0000FF', stopOpacity: 1 },
21
- { offset: '75%', stopColor: '#7F00FF', stopOpacity: 1 },
22
- { offset: '83%', stopColor: '#FF00FF', stopOpacity: 1 },
23
- { offset: '92%', stopColor: '#FF007F', stopOpacity: 1 },
24
- { offset: '100%', stopColor: '#FF0000', stopOpacity: 1 },
25
- ],
26
- },
27
- {
28
- x2: '0%',
29
- y2: '100%',
30
- colors: [
31
- { offset: '0%', stopColor: '#fff', stopOpacity: 1 },
32
- { offset: '16%', stopColor: '#fff', stopOpacity: 0.9 },
33
- { offset: '100%', stopColor: '#fff', stopOpacity: 0 },
34
- ],
35
- },
36
- ];
37
-
38
- export interface IHsv {
39
- hue: number;
40
- saturation: number;
41
- value: number;
42
- }
43
-
44
- const defaultProps = {
45
- ...baseDefault,
46
- /**
47
- * 值
48
- */
49
- value: { hue: 0, saturation: 1000, value: 1000 } as IHsv,
50
- /**
51
- * 色度偏量
52
- */
53
- hueOffset: 1,
54
- /**
55
- * 亮度配置
56
- */
57
- brightOption: {} as IBrightOption,
58
- /**
59
- * 是否隐藏亮度调节
60
- */
61
- hideBright: false,
62
- /**
63
- * 失去焦点时的亮度滑动条颜色
64
- */
65
- lossSliderColor: 'rgba(255,255,255,0.4)',
66
- /**
67
- * 背景渐变配置
68
- */
69
- bgs: rectGradientBg,
70
- /**
71
- * 滑动开始事件
72
- * @param _v
73
- * @param _option
74
- */
75
- onGrant(_v: any, _option?: { isChangeBright: boolean }) {},
76
- /**
77
- * 滑动过程事件
78
- * @param _v
79
- * @param _option
80
- */
81
- onMove(_v: any, _option?: { isChangeBright: boolean }) {},
82
- /**
83
- * 滑动结束事件
84
- * @param _v
85
- * @param _option
86
- */
87
- onRelease(_v: any, _option?: { isChangeBright: boolean }) {},
88
- /**
89
- * 点击事件
90
- * @param _v
91
- * @param _option
92
- * @version ^0.3.0
93
- */
94
- onPress(_v: any, _option?: { isChangeBright: boolean }) {},
95
- };
96
-
97
- type DefaultProps = Readonly<typeof defaultProps>;
98
-
99
- type ColourProps = {
100
- /**
101
- * 组件的样式
102
- */
103
- style?: StyleProp<ViewStyle>;
104
- /**
105
- * 颜色选择区的样式
106
- */
107
- rectStyle?: StyleProp<ViewStyle>;
108
- } & DefaultProps;
109
-
110
- type IState = IHsv;
111
-
112
- export default class ColourPicker extends Component<ColourProps, IState> {
113
- static defaultProps: DefaultProps = defaultProps;
114
- constructor(props: ColourProps) {
115
- super(props);
116
- this.state = { ...this.props.value };
117
- }
118
-
119
- // eslint-disable-next-line react/no-deprecated
120
- componentWillReceiveProps(nextProps: ColourProps) {
121
- if (!_.isEqual(nextProps.value, this.props.value)) {
122
- this.setState({ ...nextProps.value });
123
- }
124
- }
125
-
126
- shouldComponentUpdate(nextProps: ColourProps, nextState: IState) {
127
- return !_.isEqual(nextProps, this.props) || !_.isEqual(nextState, this.state);
128
- }
129
-
130
- onBrightGrant = () => {
131
- const { hue, saturation, value } = this.state;
132
- this.firPropsEvent(this.props.onGrant, { hue, saturation, value }, { isChangeBright: true });
133
- };
134
-
135
- onBrightMove = (value: number) => {
136
- const { hue, saturation } = this.state;
137
- this.firPropsEvent(this.props.onMove, { hue, saturation, value }, { isChangeBright: true });
138
- };
139
-
140
- onBrightRelease = (value: number) => {
141
- const { hue, saturation } = this.state;
142
- this.setState({ value });
143
- this.firPropsEvent(this.props.onRelease, { hue, saturation, value }, { isChangeBright: true });
144
- };
145
-
146
- onBrightPress = (value: number) => {
147
- const { hue, saturation } = this.state;
148
- this.setState({ value });
149
- this.firPropsEvent(this.props.onPress, { hue, saturation, value }, { isChangeBright: true });
150
- };
151
-
152
- coorToValue = ({ x, y }: Point, validBound: ValidBound) => {
153
- const { hueOffset } = this.props;
154
- const { width, height, x: validStartX, y: validStartY } = validBound;
155
- const { value } = this.state;
156
- let hue = Math.round(((x - validStartX) / width) * 360 + hueOffset) % 360;
157
- const saturation = Math.round(((y - validStartY) / height) * 1000);
158
-
159
- // hueOffset 不等于0时,最左边与最右边的值一样,为确保不会滑到最左边时跳到最右边
160
- // 滑到最左边时,hue + 1;
161
- if (hueOffset !== 0) {
162
- if (Math.abs(x - validStartX) < 1) {
163
- hue += 1;
164
- }
165
- }
166
-
167
- return { hue, saturation, value };
168
- };
169
-
170
- valueToCoor = (hsv: IHsv, _origin: Point, validBound: ValidBound): Point => {
171
- const { hueOffset } = this.props;
172
- const { width, height, x: validStartX, y: validStartY } = validBound;
173
- const { hue, saturation } = hsv;
174
- let x = ((hue - hueOffset) / 360) * width;
175
- if (x <= 0) {
176
- x = width + x;
177
- }
178
- const y = (saturation / 1000) * height;
179
-
180
- return { x: x + validStartX, y: y + validStartY };
181
- };
182
-
183
- valueToColor = (hsv: IHsv): string => {
184
- const { hue, saturation, value } = hsv;
185
- return ColorUtils.hsv2rgba(hue!, saturation, value) || 'transparent';
186
- };
187
-
188
- firPropsEvent(cb: (params?: any) => void, ...args: any[]) {
189
- typeof cb === 'function' && cb(...args);
190
- }
191
-
192
- handlePickerGrant = () => {
193
- const { hue, saturation, value } = this.state;
194
- this.firPropsEvent(this.props.onGrant, { hue, saturation, value });
195
- };
196
-
197
- handlePickerMove = (hsv: IHsv) => {
198
- this.firPropsEvent(this.props.onMove, hsv);
199
- };
200
-
201
- handlePickerRelease = (hsv: IHsv) => {
202
- this.setState({ ...hsv });
203
- this.firPropsEvent(this.props.onRelease, hsv);
204
- };
205
-
206
- handlePickerPress = (hsv: IHsv) => {
207
- this.setState({ ...hsv });
208
- this.firPropsEvent(this.props.onPress, hsv);
209
- };
210
-
211
- initData = async () => {};
212
- render() {
213
- const {
214
- style,
215
- rectStyle,
216
- brightOption,
217
- lossShow,
218
- lossSliderColor,
219
- clickEnabled,
220
- hideBright,
221
- opacityAnimationValue,
222
- opacityAnimationDuration,
223
- ...pickerProps
224
- } = this.props;
225
- const { hue, saturation, value: bright } = this.state;
226
- const sliderProps: any = {};
227
- if (lossShow) {
228
- sliderProps.activeColor = lossSliderColor;
229
- }
230
- return (
231
- <View style={[{ flex: 1 }, style]}>
232
- <RectPicker
233
- coorToValue={this.coorToValue}
234
- valueToColor={this.valueToColor}
235
- valueToCoor={this.valueToCoor}
236
- value={{ hue, saturation, value: bright }}
237
- lossShow={lossShow}
238
- clickEnabled={clickEnabled}
239
- opacityAnimationValue={opacityAnimationValue}
240
- opacityAnimationDuration={opacityAnimationDuration}
241
- {...pickerProps}
242
- style={rectStyle}
243
- onGrant={this.handlePickerGrant}
244
- onMove={this.handlePickerMove}
245
- onRelease={this.handlePickerRelease}
246
- onPress={this.handlePickerPress}
247
- initData={this.initData}
248
- />
249
- {!hideBright && (
250
- <Slider
251
- opacityAnimationValue={opacityAnimationValue}
252
- opacityAnimationDuration={opacityAnimationDuration}
253
- {...brightOption}
254
- {...sliderProps}
255
- value={bright}
256
- clickEnabled={clickEnabled}
257
- onGrant={this.onBrightGrant}
258
- onMove={this.onBrightMove}
259
- onRelease={this.onBrightRelease}
260
- onPress={this.onBrightPress}
261
- />
262
- )}
263
- </View>
264
- );
265
- }
266
- }
@@ -1,398 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
- /* eslint-disable react/no-array-index-key */
3
- import React, { Component } from 'react';
4
- import {
5
- View,
6
- PanResponder,
7
- GestureResponderEvent,
8
- LayoutChangeEvent,
9
- PanResponderGestureState,
10
- PanResponderInstance,
11
- Animated,
12
- StyleProp,
13
- ViewStyle,
14
- } from 'react-native';
15
- import _ from 'lodash';
16
- import { Svg, Rect, Defs, LinearGradient, Stop } from 'react-native-svg';
17
- import Thumb from './Thumb';
18
- import Res from './res';
19
-
20
- export interface Point {
21
- x: number;
22
- y: number;
23
- }
24
-
25
- /**
26
- * thumb 的有效区域
27
- */
28
- export interface ValidBound {
29
- width: number;
30
- height: number;
31
- x: number;
32
- y: number;
33
- }
34
-
35
- export interface ILinearColors {
36
- offset: string;
37
- stopColor: string;
38
- stopOpacity: number;
39
- }
40
-
41
- export interface ILinear {
42
- x1?: string | number;
43
- x2?: string | number;
44
- y1?: string | number;
45
- y2?: string | number;
46
- colors: ILinearColors[];
47
- }
48
-
49
- export const defaultProps = {
50
- bgs: [] as ILinear[],
51
- thumbComponent: Thumb,
52
- disabled: false,
53
- thumbSize: 38,
54
- touchThumbSize: 60,
55
- showThumbWhenDisabled: true,
56
- clickEnabled: true, // 是否可以点击选择
57
- lossShow: false, // 数据未在设备生效处理,若为true,则loassColor 启效,并thumb及亮度调节会变成指定颜色
58
- lossColor: 'rgba(0,0,0,0.2)',
59
- // eslint-disable-next-line import/no-unresolved
60
- thumbImg: Res.thumbMask,
61
- onGrant(_v: any) {},
62
- onMove(_v: any) {},
63
- onRelease(_v: any) {},
64
- onPress(_v: any) {},
65
- /**
66
- * 背景透明度动画值
67
- */
68
- opacityAnimationValue: 1,
69
- /**
70
- * 背景透明度动画时间
71
- */
72
- opacityAnimationDuration: 150,
73
- };
74
-
75
- type DefaultProps = Readonly<typeof defaultProps>;
76
-
77
- interface IProps extends DefaultProps {
78
- value: any;
79
- style?: StyleProp<ViewStyle>;
80
- pickerStyle?: StyleProp<ViewStyle>;
81
- coorToValue: (coor: Point, validBound: ValidBound) => any;
82
- valueToCoor: (value: any, originCoor?: Point, validBound?: ValidBound) => Point;
83
- valueToColor: (value: any) => string;
84
- initData: (validBound?: ValidBound) => void;
85
- }
86
-
87
- interface IState {
88
- value: any;
89
- }
90
-
91
- let idIndex = 0;
92
-
93
- export default class RectPicker extends Component<IProps, IState> {
94
- static defaultProps = defaultProps;
95
-
96
- constructor(props: IProps) {
97
- super(props);
98
- this.state = { value: this.props.value };
99
- this.bgOpacityAnim = new Animated.Value(this.props.opacityAnimationValue);
100
- // rn的坑,需要在此赋值才有效果
101
- this._panResponder = PanResponder.create({
102
- onStartShouldSetPanResponder: this.handleSetResponder,
103
- onPanResponderTerminationRequest: () => !this.locked,
104
- onPanResponderGrant: this.handleGrant,
105
- onPanResponderMove: this.handleMove,
106
- onPanResponderRelease: this.handleRelease,
107
- });
108
- }
109
-
110
- // eslint-disable-next-line react/no-deprecated
111
- componentWillReceiveProps(nextProps: IProps) {
112
- if (!_.isEqual(nextProps.value, this.props.value)) {
113
- this.setState({ value: nextProps.value });
114
- const position = this.valueToCoor(nextProps.value);
115
- const color = this.valueToColor(nextProps.value);
116
- this.updateThumbPosition(position, color, true);
117
- }
118
- if (nextProps.lossShow !== this.props.lossShow) {
119
- const color = this.valueToColor(nextProps.value);
120
- this.updateThumbPosition(
121
- this.thumbPosition,
122
- nextProps.lossShow ? nextProps.lossColor : color,
123
- true
124
- );
125
- }
126
- if (nextProps.thumbSize !== this.props.thumbSize) {
127
- this.handleViewBoxChange(nextProps.thumbSize);
128
- }
129
- if (this.props.opacityAnimationValue !== nextProps.opacityAnimationValue) {
130
- Animated.timing(this.bgOpacityAnim, {
131
- toValue: nextProps.opacityAnimationValue,
132
- duration: nextProps.opacityAnimationDuration,
133
- useNativeDriver: true,
134
- }).start();
135
- }
136
- }
137
-
138
- shouldComponentUpdate() {
139
- return !this.locked;
140
- }
141
-
142
- private _panResponder: PanResponderInstance;
143
- private thumbPosition: Point = { x: 0, y: 0 };
144
- private color = 'red';
145
- private showPicker = false;
146
- private pickerWidth = 200;
147
- private pickerHeight = 200;
148
- private validBound: ValidBound = { x: 0, y: 0, width: 0, height: 0 };
149
- private locked = false; // 是否锁定组件,锁定后,组件接受react正常更新
150
- private thumbRef: Thumb;
151
- private isThumbFocus = false;
152
- private grantTime = 0;
153
- private linearGradientId = `rectPicker_${idIndex++}`;
154
- private bgOpacityAnim: Animated.Value = new Animated.Value(1);
155
-
156
- coorToValue(point: Point) {
157
- const { coorToValue } = this.props;
158
- if (typeof coorToValue === 'function') {
159
- return coorToValue(point, this.validBound);
160
- }
161
- return point;
162
- }
163
-
164
- valueToCoor(value: any, originCoor?: Point): Point {
165
- const { valueToCoor } = this.props;
166
-
167
- // 是否有显示区, 无显示区直接返回原点坐标
168
- const { width, height } = this.validBound;
169
- if (width === 0 || height === 0) {
170
- return { x: 0, y: 0 };
171
- }
172
- if (typeof valueToCoor === 'function') {
173
- return valueToCoor(value, originCoor, this.validBound);
174
- }
175
- return originCoor || { x: 0, y: 0 };
176
- }
177
-
178
- valueToColor(value: any): string {
179
- const { valueToColor } = this.props;
180
- if (typeof valueToColor === 'function') {
181
- return valueToColor(value);
182
- }
183
- return 'transparent';
184
- }
185
-
186
- firPropsEvent(cb: (params?: any) => void, ...args: any[]) {
187
- cb && cb(...args);
188
- }
189
-
190
- handleSetResponder = (e: GestureResponderEvent) => {
191
- if (this.props.disabled) {
192
- return false;
193
- }
194
- // 是否点中标记
195
- const { locationX, locationY } = e.nativeEvent;
196
- const { thumbSize, touchThumbSize, clickEnabled } = this.props;
197
- let validRadius = thumbSize / 2;
198
- if (touchThumbSize) {
199
- validRadius = touchThumbSize / 2;
200
- }
201
- const { x, y } = this.thumbPosition;
202
- const length = Math.sqrt((locationX - x) ** 2 + (locationY - y) ** 2);
203
- if (length <= validRadius) {
204
- this.isThumbFocus = true;
205
- return true;
206
- }
207
- this.isThumbFocus = false;
208
- this.grantTime = +new Date();
209
- return clickEnabled;
210
- };
211
-
212
- handleGrant = () => {
213
- if (this.isThumbFocus) {
214
- this.locked = true;
215
- this.firPropsEvent(this.props.onGrant, this.state.value);
216
- }
217
- };
218
-
219
- handleMove = (_e: GestureResponderEvent, gesture: PanResponderGestureState) => {
220
- if (this.isThumbFocus) {
221
- const value = this.handleGestureMove(gesture);
222
- this.firPropsEvent(this.props.onMove, value);
223
- }
224
- };
225
-
226
- handleRelease = (e: GestureResponderEvent, gesture: PanResponderGestureState) => {
227
- if (this.isThumbFocus) {
228
- this.locked = false;
229
- const value = this.handleGestureMove(gesture, true);
230
- this.setState({ value });
231
- this.firPropsEvent(this.props.onRelease, value);
232
- } else if (this.props.clickEnabled) {
233
- // 点击选择颜色
234
- const now = +new Date();
235
- if (Math.abs(gesture.dx) < 4 && Math.abs(gesture.dy) < 4 && now - this.grantTime < 300) {
236
- // 点击位置
237
- const { locationX, locationY } = e.nativeEvent;
238
- const { x: newX, y: newY } = this.formatCoor(locationX, locationY);
239
- const value = this.coorToValue({ x: newX, y: newY });
240
- const coor = this.valueToCoor(value, { x: newX, y: newY });
241
- const color = this.valueToColor(value);
242
- this.updateThumbPosition(coor, color, true);
243
-
244
- this.firPropsEvent(this.props.onPress, value);
245
- }
246
- }
247
- };
248
-
249
- handleGestureMove(e: PanResponderGestureState, isEnd = false) {
250
- const { dx, dy } = e;
251
- const { x, y } = this.thumbPosition;
252
- // 边界处理
253
- const { x: newX, y: newY } = this.formatCoor(x + dx, y + dy);
254
-
255
- // 转为实际值,再转回成坐标
256
- const value = this.coorToValue({ x: newX, y: newY });
257
- const coor = this.valueToCoor(value, { x: newX, y: newY });
258
- const color = this.valueToColor(value);
259
- this.updateThumbPosition(coor, color, isEnd);
260
- return value;
261
- }
262
-
263
- formatCoor(x: number, y: number) {
264
- const {
265
- width: validWidth,
266
- height: validHeight,
267
- x: validStartX,
268
- y: validStartY,
269
- } = this.validBound;
270
- let newX = x;
271
- let newY = y;
272
- // 边界处理
273
- if (newX < validStartX) {
274
- newX = validStartX;
275
- } else if (newX > validWidth + validStartX) {
276
- newX = validWidth + validStartX;
277
- }
278
- if (newY < validStartY) {
279
- newY = validStartY;
280
- } else if (newY > validHeight + validStartY) {
281
- newY = validHeight + validStartY;
282
- }
283
-
284
- return { x: newX, y: newY };
285
- }
286
-
287
- updateThumbPosition(coor: Point, color: string, isEnd: boolean) {
288
- this.thumbRef && this.thumbRef.setNativeProps({ color, ...coor });
289
- if (isEnd) {
290
- this.color = color;
291
- this.thumbPosition = coor;
292
- }
293
- }
294
-
295
- handleViewBoxChange = async (thumbSize: number) => {
296
- this.validBound = {
297
- width: this.pickerWidth - thumbSize,
298
- height: this.pickerHeight - thumbSize,
299
- x: thumbSize / 2,
300
- y: thumbSize / 2,
301
- };
302
- await this.props.initData(this.validBound);
303
- this.thumbPosition = this.valueToCoor(this.props.value);
304
- this.forceUpdate();
305
- };
306
-
307
- handlePickerLayout = async (e: LayoutChangeEvent) => {
308
- const { thumbSize, lossColor, lossShow } = this.props;
309
- const { width, height } = e.nativeEvent.layout;
310
- if (width !== this.pickerWidth || height !== this.pickerHeight) {
311
- this.pickerWidth = width || 10; // svg 尺寸不能为0,此处确保值大于0
312
- this.pickerHeight = height || 10; // svg 尺寸不能为0,此处确保值大于0
313
- if (!this.showPicker) {
314
- this.showPicker = true;
315
- this.color = lossShow ? lossColor : this.valueToColor(this.props.value);
316
- }
317
- await this.handleViewBoxChange(thumbSize);
318
- }
319
- };
320
-
321
- render() {
322
- const {
323
- style,
324
- pickerStyle,
325
- bgs,
326
- thumbComponent: ThumbView,
327
- disabled,
328
- thumbSize,
329
- thumbImg,
330
- } = this.props;
331
- const { showPicker, pickerHeight, pickerWidth, thumbPosition } = this;
332
- return (
333
- <View
334
- style={[{ flex: 1 }, style]}
335
- {...this._panResponder.panHandlers}
336
- pointerEvents="box-only"
337
- onLayout={this.handlePickerLayout}
338
- >
339
- {showPicker && (
340
- <Animated.View
341
- style={[
342
- {
343
- opacity: this.bgOpacityAnim,
344
- },
345
- pickerStyle,
346
- ]}
347
- >
348
- <Svg
349
- height={pickerHeight}
350
- width={pickerWidth}
351
- viewBox={`0 0 ${pickerWidth} ${pickerHeight}`}
352
- >
353
- <Defs>
354
- {bgs.map(({ x1 = '0%', x2 = '100%', y1 = '0%', y2 = '0%', colors }, index) => (
355
- <LinearGradient
356
- key={index}
357
- id={`${this.linearGradientId}_${index}`}
358
- x1={x1}
359
- x2={x2}
360
- y1={y1}
361
- y2={y2}
362
- >
363
- {colors.map((color, i) => (
364
- <Stop key={i} {...color} />
365
- ))}
366
- </LinearGradient>
367
- ))}
368
- </Defs>
369
- {bgs.map((_bg, index) => (
370
- <Rect
371
- key={index}
372
- fill={`url(#${this.linearGradientId}_${index})`}
373
- x="0"
374
- y="0"
375
- width={pickerWidth}
376
- height={pickerHeight}
377
- />
378
- ))}
379
- </Svg>
380
- </Animated.View>
381
- )}
382
- {/* render thumb */}
383
- {showPicker && (
384
- <ThumbView
385
- ref={(ref: Thumb) => {
386
- this.thumbRef = ref;
387
- }}
388
- {...thumbPosition}
389
- img={thumbImg}
390
- size={thumbSize}
391
- color={this.color}
392
- disabled={disabled}
393
- />
394
- )}
395
- </View>
396
- );
397
- }
398
- }