UNPKG

reanimated-color-picker

Version:
158 lines (150 loc) 4.39 kB
import React from 'react'; import { useAnimatedStyle, useDerivedValue, useSharedValue } from 'react-native-reanimated'; import colorKit from '../../colorKit/index'; import usePickerContext from '../../AppContext'; import { styles } from '../../styles'; import BuiltinThumbs from './BuiltinThumbs/index'; export default function Thumb({ handleStyle, innerStyle, style, thumbColor, renderThumb: RenderThumb, thumbShape = 'ring', thumbSize, vertical = false, adaptSpectrum, channel, overrideHSV, }) { const { width, height, borderRadius } = { width: thumbSize, height: thumbSize, borderRadius: thumbSize / 2, }; const { hueValue, saturationValue, brightnessValue, alphaValue, value } = usePickerContext(); const hue = (overrideHSV === null || overrideHSV === void 0 ? void 0 : overrideHSV.hue) ?? hueValue, saturation = (overrideHSV === null || overrideHSV === void 0 ? void 0 : overrideHSV.saturation) ?? saturationValue, brightness = (overrideHSV === null || overrideHSV === void 0 ? void 0 : overrideHSV.brightness) ?? brightnessValue, alpha = (overrideHSV === null || overrideHSV === void 0 ? void 0 : overrideHSV.alpha) ?? alphaValue; const resultColor = useSharedValue('#ffffff'); const solidColor = useAnimatedStyle( () => ({ backgroundColor: thumbColor ?? resultColor.value, }), [resultColor], ); const adaptiveColor = useSharedValue('#ffffff'); /** * Get the current color and calculate its contrast ratio against white or black, depending on the channel and whether * 'adaptSpectrum' is enabled */ const getColorForAdaptiveColor = () => { 'worklet'; if (adaptSpectrum) { if (channel === 'a') { if (alpha.value > 0.5) return { h: hue.value, s: saturation.value, v: brightness.value, }; return { h: 0, s: 0, v: 70, }; } return { h: hue.value, s: saturation.value, v: brightness.value, }; } if (channel === 'h') return { h: hue.value, s: 100, v: 100, }; if (channel === 'v') return { h: hue.value, s: 100, v: brightness.value, }; if (channel === 's') return { h: hue.value, s: saturation.value, v: 70, }; if (channel === 'a') return { h: hue.value, s: alpha.value * 100, v: 70, }; return { h: hue.value, s: saturation.value, v: brightness.value, }; }; // When the values of channels change useDerivedValue(() => { alpha.value; // to track alpha changes too; resultColor.value = colorKit.runOnUI().HEX({ h: hue.value, s: saturation.value, v: brightness.value, }); // calculate the contrast ratio const compareColor1 = getColorForAdaptiveColor(); const compareColor2 = adaptiveColor.value === '#000000' ? { h: 0, s: 0, v: 0, } : { h: 0, s: 0, v: 100, }; const contrast = colorKit.runOnUI().contrastRatio(compareColor1, compareColor2); const reversedColor = adaptiveColor.value === '#ffffff' ? '#000000' : '#ffffff'; adaptiveColor.value = contrast < 4.5 ? reversedColor : adaptiveColor.value; }, [alpha, hue, saturation, brightness]); const thumbProps = { width, height, borderRadius, vertical, solidColor, adaptiveColor, handleStyle, innerStyle, style, thumbColor, }; // render a custom thumb if (RenderThumb) return /*#__PURE__*/ React.createElement(RenderThumb, { positionStyle: [styles.handle, handleStyle], width: width, height: height, initialColor: value, currentColor: resultColor, adaptiveColor: adaptiveColor, }); // normalize 'thumbShape' string to match 'BuiltinThumbs' keys. const thumb_Shape = thumbShape.toLowerCase().charAt(0).toUpperCase() + thumbShape.slice(1); if (thumb_Shape in BuiltinThumbs) { const SelectedThumb = BuiltinThumbs[thumb_Shape]; return /*#__PURE__*/ React.createElement(SelectedThumb, thumbProps); } // default to the 'Ring' thumb return /*#__PURE__*/ React.createElement(BuiltinThumbs.Ring, thumbProps); }