New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

react-native-wheel-color-picker

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-wheel-color-picker - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

439

ColorPicker.js

@@ -14,2 +14,3 @@ // @flow

Text,
ActivityIndicator,
} = require('react-native')

@@ -129,3 +130,3 @@

const hex2Rgb = (hex) => {
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
let result = (/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i).exec(hex)
return result ? {

@@ -153,7 +154,13 @@ r: parseInt(result[1], 16),

const flipInterpolationConfig = {
inputRange: [1, 10],
outputRange: [-1, -10],
extrapolate: 'extend', // a string such as 'extend', 'identity', or 'clamp'
}
module.exports = class ColorPicker extends Component {
// testData = {}
// testView = {forceUpdate(){}}
color = {h:0,s:0,v:100}
color = { h: 0, s: 0, v: 100 }
slideX = new Animated.Value(0)

@@ -174,4 +181,4 @@ slideY = new Animated.Value(0)

gapSize: 16, // size of gap between slider and wheel
discrete: false, // use swatchs of shades instead of slider
discreteLength: 10, // number of swatchs of shades
discrete: false, // use swatches of shades instead of slider
discreteLength: 10, // number of swatches of shades, should be > 1
sliderHidden: false, // if true the slider is hidden

@@ -187,12 +194,21 @@ swatches: true, // show color swatches

autoResetSlider: false, // if true the slider thumb is reset to 0 value when wheel thumb is moved
onInteractionStart: () => {}, // callback function triggered when user begins dragging slider/wheel
onColorChange: () => {}, // callback function providing current color while user is actively dragging slider/wheel
onColorChangeComplete: () => {}, // callback function providing final color when user stops dragging slider/wheel
onInteractionStart: () => { }, // callback function triggered when user begins dragging slider/wheel
onColorChange: () => { }, // callback function providing current color while user is actively dragging slider/wheel
onColorChangeComplete: () => { }, // callback function providing final color when user stops dragging slider/wheel
wheelLoadingIndicator: null, // wheel image loading component eg: <ActivityIndicator />
sliderLoadingIndicator: null, // slider image loading component eg: <ActivityIndicator />
useNativeDriver: false, // to use useNativeDriver for animations
useNativeLayout: false, // to use onLayoutEvent.nativeEvent.layout instead of measureInWindow for x, y, width, height values for wheel and slider measurements which may be useful to prevent some layout problems
disabled: false, // disable all interactions
flipTouchX: false, // flip touch positioning on X axis, might be useful in UI with RTL support
flipTouchY: false, // flip touch positioning on Y axis, might be useful in UI with RTL support
wheelHidden: false, // if true the wheel is hidden, does not work with sliderHidden = true
}
wheelPanResponder = PanResponder.create({
onStartShouldSetPanResponderCapture: (event, gestureState) => {
const {nativeEvent} = event
if (this.props.disabled) return false;
const { nativeEvent } = event
if (this.outOfWheel(nativeEvent)) return
this.wheelMovement(event, gestureState)
this.updateHueSaturation({nativeEvent})
this.updateHueSaturation({ nativeEvent })
return true

@@ -203,2 +219,3 @@ },

onPanResponderGrant: (event, gestureState) => {
if (this.props.disabled) return;
const { locationX, locationY } = event.nativeEvent

@@ -213,4 +230,5 @@ const { moveX, moveY, x0, y0 } = gestureState

onPanResponderMove: (event, gestureState) => {
if(event && event.nativeEvent && typeof event.nativeEvent.preventDefault == 'function') event.nativeEvent.preventDefault()
if(event && event.nativeEvent && typeof event.nativeEvent.stopPropagation == 'function') event.nativeEvent.stopPropagation()
if (this.props.disabled) return;
if (event && event.nativeEvent && typeof event.nativeEvent.preventDefault == 'function') event.nativeEvent.preventDefault()
if (event && event.nativeEvent && typeof event.nativeEvent.stopPropagation == 'function') event.nativeEvent.stopPropagation()
if (this.outOfWheel(event.nativeEvent) || this.outOfBox(this.wheelMeasure, gestureState)) return;

@@ -221,10 +239,11 @@ this.wheelMovement(event, gestureState)

onPanResponderRelease: (event, gestureState) => {
const {nativeEvent} = event
const {radius} = this.polar(nativeEvent)
const {hsv} = this.state
const {h,s,v} = hsv
if (this.props.disabled) return;
const { nativeEvent } = event
const { radius } = this.polar(nativeEvent)
const { hsv } = this.state
const { h, s, v } = hsv
if (!this.props.noSnap && radius <= 0.10 && radius >= 0) this.animate('#ffffff', 'hs', false, true)
if (!this.props.noSnap && radius >= 0.95 && radius <= 1) this.animate(this.state.currentColor, 'hs', true)
if (this.props.onColorChangeComplete) this.props.onColorChangeComplete(hsv2Hex(hsv))
this.setState({currentColor:this.state.currentColor}, x=>this.renderDiscs())
this.setState({ currentColor: this.state.currentColor }, x => this.renderDiscs())
},

@@ -234,6 +253,7 @@ })

onStartShouldSetPanResponderCapture: (event, gestureState) => {
const {nativeEvent} = event
if (this.props.disabled) return false;
const { nativeEvent } = event
if (this.outOfSlider(nativeEvent)) return
this.sliderMovement(event, gestureState)
this.updateValue({nativeEvent})
this.updateValue({ nativeEvent })
return true

@@ -244,2 +264,3 @@ },

onPanResponderGrant: (event, gestureState) => {
if (this.props.disabled) return;
const { locationX, locationY } = event.nativeEvent

@@ -254,4 +275,5 @@ const { moveX, moveY, x0, y0 } = gestureState

onPanResponderMove: (event, gestureState) => {
if(event && event.nativeEvent && typeof event.nativeEvent.preventDefault == 'function') event.nativeEvent.preventDefault()
if(event && event.nativeEvent && typeof event.nativeEvent.stopPropagation == 'function') event.nativeEvent.stopPropagation()
if (this.props.disabled) return;
if (event && event.nativeEvent && typeof event.nativeEvent.preventDefault == 'function') event.nativeEvent.preventDefault()
if (event && event.nativeEvent && typeof event.nativeEvent.stopPropagation == 'function') event.nativeEvent.stopPropagation()
if (this.outOfSlider(event.nativeEvent) || this.outOfBox(this.sliderMeasure, gestureState)) return;

@@ -262,5 +284,6 @@ this.sliderMovement(event, gestureState)

onPanResponderRelease: (event, gestureState) => {
const {nativeEvent} = event
const {hsv} = this.state
const {h,s,v} = hsv
if (this.props.disabled) return;
const { nativeEvent } = event
const { hsv } = this.state
const { h, s, v } = hsv
const ratio = this.ratio(nativeEvent)

@@ -272,11 +295,20 @@ if (!this.props.noSnap && ratio <= 0.05 && ratio >= 0) this.animate(this.state.currentColor, 'v', false)

})
constructor (props) {
constructor(props) {
super(props)
this.mounted = false
this.swatchesUpdatedAt = 0
this.discsUpdatedAt = 0
this.state = {
wheelOpacity: 0,
sliderOpacity: 0,
hueSaturation: hsv2Hex(this.color.h,this.color.s,100),
hueSaturation: hsv2Hex(this.color.h, this.color.s, 100),
currentColor: props.color,
hsv: {h:0,s:0,v:100},
hsv: { h: 0, s: 0, v: 100 },
wheelImageLoaded: false,
sliderImageLoaded: false,
palette: props.palette,
discreteLength: props.discreteLength,
swatchesHitSlop: props.swatchesHitSlop,
swatchesUpdatedAt: 0,
discsUpdatedAt: 0,
}

@@ -294,3 +326,3 @@ this.wheelMovement = new Animated.event(

{
useNativeDriver: false,
useNativeDriver: !!props.useNativeDriver,
listener: this.updateHueSaturation

@@ -310,8 +342,8 @@ }

{
useNativeDriver: false,
useNativeDriver: !!props.useNativeDriver,
listener: this.updateValue
}
)
this.swatchAnim = props.palette.map((c,i) => (new Animated.Value(0)))
this.discAnim = (`1`).repeat(props.discreteLength).split('').map((c,i) => (new Animated.Value(0)))
this.initSwatchAnimatedValues(props)
this.initDiscAnimatedValues(props)
this.renderSwatches()

@@ -326,9 +358,10 @@ this.renderDiscs()

}
onSwatchPress = (c,i) => {
onSwatchPress = (c, i) => {
if (this.props.disabled) return;
this.swatchAnim[i].stopAnimation()
Animated.timing(this.swatchAnim[i], {
toValue: 1,
useNativeDriver: false,
useNativeDriver: !!this.props.useNativeDriver,
duration: 500,
}).start(x=>{
}).start(x => {
this.swatchAnim[i].setValue(0)

@@ -338,81 +371,101 @@ })

}
onDiscPress = (c,i) => {
onDiscPress = (c, i) => {
if (this.props.disabled) return;
this.discAnim[i].stopAnimation()
Animated.timing(this.discAnim[i], {
toValue: 1,
useNativeDriver: false,
useNativeDriver: !!this.props.useNativeDriver,
duration: 500,
}).start(x=>{
}).start(x => {
this.discAnim[i].setValue(0)
})
const val = i>=9?100:11*i
this.updateValue({nativeEvent:null}, val)
this.animate({h:this.color.h,s:this.color.s,v:val}, 'v')
const val = i >= 9 ? 100 : 11 * i
this.updateValue({ nativeEvent: null }, val)
this.animate({ h: this.color.h, s: this.color.s, v: val }, 'v')
}
onSquareLayout = (e) => {
let {x, y, width, height} = e.nativeEvent.layout
let { x, y, width, height } = e.nativeEvent.layout
this.wheelWidth = Math.min(width, height)
this.tryForceUpdate()
}
onWheelImageLoad = (e) => {
this.setState({ wheelImageLoaded: true })
}
onSliderImageLoad = (e) => {
this.setState({ sliderImageLoaded: true })
}
onWheelLayout = (e) => {
/*
* const {x, y, width, height} = nativeEvent.layout
* onlayout values are different than measureInWindow
* onLayout values are different than measureInWindow
* x and y are the distances to its previous element
* but in measureInWindow they are relative to the window
*/
this.wheel.measureInWindow((x, y, width, height) => {
this.wheelMeasure = {x, y, width, height}
this.wheelSize = width
// this.panX.setOffset(-width/2)
// this.panY.setOffset(-width/2)
this.update(this.state.currentColor)
this.setState({wheelOpacity:1})
})
if (!!this.props.useNativeLayout) {
let {x, y, width, height} = e.nativeEvent.layout
this.setWheelMeasure(x, y, width, height)
} else {
this.wheel.measureInWindow(this.setWheelMeasure)
}
}
onSliderLayout = (e) => {
this.slider.measureInWindow((x, y, width, height) => {
this.sliderMeasure = {x, y, width, height}
this.sliderLength = this.props.row ? height-width : width-height
// this.slideX.setOffset(-width/2)
// this.slideY.setOffset(-width/2)
this.update(this.state.currentColor)
this.setState({sliderOpacity:1})
})
if (!!this.props.useNativeLayout) {
let {x, y, width, height} = e.nativeEvent.layout
this.setSliderMeasure(x, y, width, height)
} else {
this.slider.measureInWindow(this.setSliderMeasure)
}
}
outOfBox (measure, gestureState) {
setWheelMeasure = (x, y, width, height) => {
this.wheelMeasure = { x, y, width, height }
this.wheelSize = width
// this.panX.setOffset(-width/2)
// this.panY.setOffset(-width/2)
this.update(this.state.currentColor)
this.setState({ wheelOpacity: 1 })
}
setSliderMeasure = (x, y, width, height) => {
this.sliderMeasure = { x, y, width, height }
this.sliderLength = this.props.row ? height - width : width - height
// this.slideX.setOffset(-width/2)
// this.slideY.setOffset(-width/2)
this.update(this.state.currentColor)
this.setState({ sliderOpacity: 1 })
}
outOfBox(measure, gestureState) {
const { x, y, width, height } = measure
const { moveX, moveY, x0, y0 } = gestureState
// console.log(`${moveX} , ${moveY} / ${x} , ${y} / ${locationX} , ${locationY}`);
return !(moveX >= x && moveX <= x+width && moveY >= y && moveY <= y+height)
return !(moveX >= x && moveX <= x + width && moveY >= y && moveY <= y + height)
}
outOfWheel (nativeEvent) {
const {radius} = this.polar(nativeEvent)
outOfWheel(nativeEvent) {
const { radius } = this.polar(nativeEvent)
return radius > 1
}
outOfSlider (nativeEvent) {
outOfSlider(nativeEvent) {
const row = this.props.row
const loc = row ? nativeEvent.locationY : nativeEvent.locationX
const {width,height} = this.sliderMeasure
return (loc > (row ? height-width : width-height))
const { width, height } = this.sliderMeasure
return (loc > (row ? height - width : width - height))
}
val (v) {
const d = this.props.discrete, r = 11*Math.round(v/11)
return d ? (r>=99?100:r) : v
val(v) {
const d = this.props.discrete, r = 11 * Math.round(v / 11)
return d ? (r >= 99 ? 100 : r) : v
}
ratio (nativeEvent) {
ratio(nativeEvent) {
const row = this.props.row
const loc = row ? nativeEvent.locationY : nativeEvent.locationX
const {width,height} = this.sliderMeasure
return 1 - (loc / (row ? height-width : width-height))
const { width, height } = this.sliderMeasure
return 1 - (loc / (row ? height - width : width - height))
}
polar (nativeEvent) {
polar(nativeEvent) {
const lx = nativeEvent.locationX, ly = nativeEvent.locationY
const [x, y] = [lx - this.wheelSize/2, ly - this.wheelSize/2]
const [x, y] = [lx - this.wheelSize / 2, ly - this.wheelSize / 2]
return {
deg: Math.atan2(y, x) * (-180 / Math.PI),
radius: Math.sqrt(y * y + x * x) / (this.wheelSize / 2),
// radius: Math.min(1, Math.max(0, Math.sqrt(y * y + x * x) / (this.wheelSize / 2))), // not working well
}
}
cartesian (deg, radius) {
cartesian(deg, radius) {
const r = radius * this.wheelSize / 2 // was normalized

@@ -427,7 +480,7 @@ const rad = Math.PI * deg / 180

}
updateHueSaturation = ({nativeEvent}) => {
const {deg, radius} = this.polar(nativeEvent), h = deg, s = 100 * radius, v = this.color.v
updateHueSaturation = ({ nativeEvent }) => {
const { deg, radius } = this.polar(nativeEvent), h = deg, s = Math.max(0, Math.min(100, 100 * radius)), v = this.color.v
// if(radius > 1 ) return
const hsv = {h,s,v}// v: 100} // causes bug
if(this.props.autoResetSlider === true) {
const hsv = { h, s, v }// v: 100} // causes bug
if (this.props.autoResetSlider === true) {
this.slideX.setValue(0)

@@ -439,3 +492,3 @@ this.slideY.setValue(0)

this.color = hsv
this.setState({hsv, currentColor, hueSaturation: hsv2Hex(this.color.h,this.color.s,100)})
this.setState({ hsv, currentColor, hueSaturation: hsv2Hex(this.color.h, this.color.s, 100) })
this.props.onColorChange(hsv2Hex(hsv))

@@ -448,8 +501,8 @@ // this.testData.deg = deg

}
updateValue = ({nativeEvent}, val) => {
const {h,s} = this.color, v = (typeof val == 'number') ? val : 100 * this.ratio(nativeEvent)
const hsv = {h,s,v}
updateValue = ({ nativeEvent }, val) => {
const { h, s } = this.color, v = (typeof val == 'number') ? val : 100 * this.ratio(nativeEvent)
const hsv = { h, s, v }
const currentColor = hsv2Hex(hsv)
this.color = hsv
this.setState({hsv, currentColor, hueSaturation: hsv2Hex(this.color.h,this.color.s,100)})
this.setState({ hsv, currentColor, hueSaturation: hsv2Hex(this.color.h, this.color.s, 100) })
this.props.onColorChange(hsv2Hex(hsv))

@@ -461,25 +514,25 @@ }

color = expandColor(color);
const specific = (typeof who == 'string'), who_hs = (who=='hs'), who_v = (who=='v')
let {h, s, v} = (typeof color == 'string') ? hex2Hsv(color) : color, stt = {}
h = (who_hs||!specific) ? h : this.color.h
s = (who_hs && max) ? 100 : (who_hs && max===false) ? 0 : (who_hs||!specific) ? s : this.color.s
v = (who_v && max) ? 100 : (who_v && max===false) ? 0 : (who_v||!specific) ? v : this.color.v
const specific = (typeof who == 'string'), who_hs = (who == 'hs'), who_v = (who == 'v')
let { h, s, v } = (typeof color == 'string') ? hex2Hsv(color) : color, stt = {}
h = (who_hs || !specific) ? h : this.color.h
s = (who_hs && max) ? 100 : (who_hs && max === false) ? 0 : (who_hs || !specific) ? s : this.color.s
v = (who_v && max) ? 100 : (who_v && max === false) ? 0 : (who_v || !specific) ? v : this.color.v
const range = (100 - v) / 100 * this.sliderLength
const {left, top} = this.cartesian(h, s / 100)
const hsv = {h,s,v}
if(!specific||force) {
const { left, top } = this.cartesian(h, s / 100)
const hsv = { h, s, v }
if (!specific || force) {
this.color = hsv
stt.hueSaturation = hsv2Hex(this.color.h,this.color.s,100)
stt.hueSaturation = hsv2Hex(this.color.h, this.color.s, 100)
// this.setState({hueSaturation: hsv2Hex(this.color.h,this.color.s,100)})
}
stt.currentColor = hsv2Hex(hsv)
this.setState(stt, x=>{ this.tryForceUpdate(); this.renderDiscs(); })
this.setState(stt, x => { this.tryForceUpdate(); this.renderDiscs(); })
// this.setState({currentColor:hsv2Hex(hsv)}, x=>this.tryForceUpdate())
this.props.onColorChange(hsv2Hex(hsv))
if (this.props.onColorChangeComplete) this.props.onColorChangeComplete(hsv2Hex(hsv))
if(who_hs||!specific) {
if (who_hs || !specific) {
this.panY.setValue(top)// - this.props.thumbSize / 2)
this.panX.setValue(left)// - this.props.thumbSize / 2)
}
if(who_v||!specific) {
if (who_v || !specific) {
this.slideX.setValue(range)

@@ -490,19 +543,21 @@ this.slideY.setValue(range)

animate = (color, who, max, force) => {
const isHex = /^#(([0-9a-f]{2}){3}|([0-9a-f]){3})$/i
if (!isHex.test(color)) color = '#ffffff'
color = expandColor(color);
const specific = (typeof who == 'string'), who_hs = (who=='hs'), who_v = (who=='v')
let {h, s, v} = (typeof color == 'string') ? hex2Hsv(color) : color, stt = {}
h = (who_hs||!specific) ? h : this.color.h
s = (who_hs && max) ? 100 : (who_hs && max===false) ? 0 : (who_hs||!specific) ? s : this.color.s
v = (who_v && max) ? 100 : (who_v && max===false) ? 0 : (who_v||!specific) ? v : this.color.v
const specific = (typeof who == 'string'), who_hs = (who == 'hs'), who_v = (who == 'v')
let { h, s, v } = (typeof color == 'string') ? hex2Hsv(color) : color, stt = {}
h = (who_hs || !specific) ? h : this.color.h
s = (who_hs && max) ? 100 : (who_hs && max === false) ? 0 : (who_hs || !specific) ? s : this.color.s
v = (who_v && max) ? 100 : (who_v && max === false) ? 0 : (who_v || !specific) ? v : this.color.v
const range = (100 - v) / 100 * this.sliderLength
const {left, top} = this.cartesian(h, s / 100)
const hsv = {h,s,v}
const { left, top } = this.cartesian(h, s / 100)
const hsv = { h, s, v }
// console.log(hsv);
if(!specific||force) {
if (!specific || force) {
this.color = hsv
stt.hueSaturation = hsv2Hex(this.color.h,this.color.s,100)
stt.hueSaturation = hsv2Hex(this.color.h, this.color.s, 100)
// this.setState({hueSaturation: hsv2Hex(this.color.h,this.color.s,100)})
}
stt.currentColor = hsv2Hex(hsv)
this.setState(stt, x=>{ this.tryForceUpdate(); this.renderDiscs(); })
this.setState(stt, x => { this.tryForceUpdate(); this.renderDiscs(); })
// this.setState({currentColor:hsv2Hex(hsv)}, x=>this.tryForceUpdate())

@@ -512,31 +567,59 @@ this.props.onColorChange(hsv2Hex(hsv))

let anims = []
if(who_hs||!specific) anims.push(//{//
Animated.spring(this.panX, { toValue: left, useNativeDriver: false, friction: 90 }),//.start()//
Animated.spring(this.panY, { toValue: top, useNativeDriver: false, friction: 90 }),//.start()//
if (who_hs || !specific) anims.push(//{//
Animated.spring(this.panX, { toValue: left, useNativeDriver: !!this.props.useNativeDriver, friction: 90 }),//.start()//
Animated.spring(this.panY, { toValue: top, useNativeDriver: !!this.props.useNativeDriver, friction: 90 }),//.start()//
)//}//
if(who_v||!specific) anims.push(//{//
Animated.spring(this.slideX, { toValue: range, useNativeDriver: false, friction: 90 }),//.start()//
Animated.spring(this.slideY, { toValue: range, useNativeDriver: false, friction: 90 }),//.start()//
if (who_v || !specific) anims.push(//{//
Animated.spring(this.slideX, { toValue: range, useNativeDriver: !!this.props.useNativeDriver, friction: 90 }),//.start()//
Animated.spring(this.slideY, { toValue: range, useNativeDriver: !!this.props.useNativeDriver, friction: 90 }),//.start()//
)//}//
Animated.parallel(anims).start()
}
// componentWillReceiveProps(nextProps) {
// componentWillReceiveProps(nextProps) { // DEPRICATED
// const { color } = nextProps
// if(color !== this.props.color) this.animate(color)
// }
static getDerivedStateFromProps(nextProps, prevState) {
const { palette, discreteLength, swatchesHitSlop } = nextProps
const now = Date.now()
const payload = {}
if (
(Array.isArray(palette) && Array.isArray(prevState.palette) && palette.join('-') !== prevState.palette.join('-'))
|| swatchesHitSlop !== prevState.swatchesHitSlop
) {
payload.palette = palette
payload.swatchesHitSlop = swatchesHitSlop
payload.swatchesUpdatedAt = now
}
if (discreteLength !== prevState.discreteLength || swatchesHitSlop !== prevState.swatchesHitSlop) {
payload.discreteLength = discreteLength
payload.swatchesHitSlop = swatchesHitSlop
payload.discsUpdatedAt = now
}
return Object.keys(payload).length > 0 ? payload : null
}
componentDidUpdate(prevProps) {
const { color } = this.props
if(color !== prevProps.color) this.animate(color)
if (color !== prevProps.color) this.animate(color)
}
revert() {
if(this.mounted) this.animate(this.props.color)
if (this.mounted) this.animate(this.props.color)
}
tryForceUpdate () {
if(this.mounted) this.forceUpdate()
tryForceUpdate() {
if (this.mounted) this.forceUpdate()
}
renderSwatches () {
this.swatches = this.props.palette.map((c,i) => (
<View style={[ss.swatch,{backgroundColor:c}]} key={'S'+i} hitSlop={this.props.swatchesHitSlop}>
<TouchableWithoutFeedback onPress={x=>this.onSwatchPress(c,i)} hitSlop={this.props.swatchesHitSlop}>
<Animated.View style={[ss.swatchTouch,{backgroundColor:c,transform:[{scale:this.swatchAnim[i].interpolate({inputRange:[0,0.5,1],outputRange:[0.666,1,0.666]})}]}]} />
initSwatchAnimatedValues(props) {
this.swatchAnim = props.palette.map((c, i) => (new Animated.Value(0)))
}
initDiscAnimatedValues(props) {
const length = Math.max(props.discreteLength, 2)
this.discAnim = (`1`).repeat(length).split('').map((c, i) => (new Animated.Value(0)))
}
renderSwatches() {
// console.log('RENDER SWATCHES >>', this.props.palette)
this.swatchesUpdatedAt = this.state.swatchesUpdatedAt
this.swatches = this.props.palette.map((c, i) => (
<View style={[ss.swatch, { backgroundColor: c }]} key={'S' + i} hitSlop={this.props.swatchesHitSlop}>
<TouchableWithoutFeedback onPress={x => this.onSwatchPress(c, i)} hitSlop={this.props.swatchesHitSlop}>
<Animated.View style={[ss.swatchTouch, { backgroundColor: c, transform: [{ scale: this.swatchAnim[i].interpolate({ inputRange: [0, 0.5, 1], outputRange: [0.666, 1, 0.666] }) }] }]} />
</TouchableWithoutFeedback>

@@ -546,8 +629,10 @@ </View>

}
renderDiscs () {
this.disc = (`1`).repeat(this.props.discreteLength).split('').map((c,i) => (
<View style={[ss.swatch,{backgroundColor:this.state.hueSaturation}]} key={'D'+i} hitSlop={this.props.swatchesHitSlop}>
<TouchableWithoutFeedback onPress={x=>this.onDiscPress(c,i)} hitSlop={this.props.swatchesHitSlop}>
<Animated.View style={[ss.swatchTouch,{backgroundColor:this.state.hueSaturation,transform:[{scale:this.discAnim[i].interpolate({inputRange:[0,0.5,1],outputRange:[0.666,1,0.666]})}]}]}>
<View style={[ss.wheelImg,{backgroundColor:'#000',opacity:1-(i>=9?1:(i*11/100))}]}></View>
renderDiscs() {
this.discsUpdatedAt = this.state.discsUpdatedAt
const length = Math.max(this.props.discreteLength, 2)
this.disc = (`1`).repeat(length).split('').map((c, i) => (
<View style={[ss.swatch, { backgroundColor: this.state.hueSaturation }]} key={'D' + i} hitSlop={this.props.swatchesHitSlop}>
<TouchableWithoutFeedback onPress={x => this.onDiscPress(c, i)} hitSlop={this.props.swatchesHitSlop}>
<Animated.View style={[ss.swatchTouch, { backgroundColor: this.state.hueSaturation, transform: [{ scale: this.discAnim[i].interpolate({ inputRange: [0, 0.5, 1], outputRange: [0.666, 1, 0.666] }) }] }]}>
<View style={[ss.wheelImg, { backgroundColor: '#000', opacity: 1 - (i >= (length-1) ? 1 : (i * 1/(length-1))) }]}></View>
</Animated.View>

@@ -559,3 +644,3 @@ </TouchableWithoutFeedback>

}
render () {
render() {
const {

@@ -571,5 +656,6 @@ style,

row,
wheelHidden,
} = this.props
const swatches = !!(this.props.swatches || swatchesOnly)
const hsv = hsv2Hex(this.color), hex = hsv2Hex(this.color.h,this.color.s,100)
const hsv = hsv2Hex(this.color), hex = hsv2Hex(this.color.h, this.color.s, 100)
const wheelPanHandlers = this.wheelPanResponder && this.wheelPanResponder.panHandlers || {}

@@ -583,6 +669,6 @@ const sliderPanHandlers = this.sliderPanResponder && this.sliderPanResponder.panHandlers || {}

borderRadius: thumbSize / 2,
backgroundColor: this.props.shadeWheelThumb === true ? hsv: hex,
transform: [{translateX:-thumbSize/2},{translateY:-thumbSize/2}],
left: this.panX,
top: this.panY,
backgroundColor: this.props.shadeWheelThumb === true ? hsv : hex,
transform: [{ translateX: (!!this.props.flipTouchX ? 1 : -1) * thumbSize / 2 }, { translateY: (!!this.props.flipTouchY ? 1 : -1) * thumbSize / 2 }],
[!!this.props.flipTouchX ? 'right' : 'left']: this.panX,
[!!this.props.flipTouchY ? 'bottom' : 'top']: this.panY,
opacity,

@@ -596,7 +682,7 @@ ////

const sliderThumbStyle = {
left: row?0:this.slideX,
top: row?this.slideY:0,
[!!this.props.flipTouchX ? 'right' : 'left']: row ? 0 : this.slideX,
[!!this.props.flipTouchY ? 'bottom' : 'top']: row ? this.slideY : 0,
// transform: [row?{translateX:8}:{translateY:8}],
backgroundColor: this.props.shadeSliderThumb === true ? hsv: hex,
borderRadius: sliderSize/2,
backgroundColor: this.props.shadeSliderThumb === true ? hsv : hex,
borderRadius: sliderSize / 2,
height: sliderSize,

@@ -607,42 +693,57 @@ width: sliderSize,

const sliderStyle = {
width:row?sliderSize:'100%',
height:row?'100%':sliderSize,
marginLeft:row?gapSize:0,
marginTop:row?0:gapSize,
borderRadius:sliderSize/2,
width: row ? sliderSize : '100%',
height: row ? '100%' : sliderSize,
marginLeft: row ? gapSize : 0,
marginTop: row ? 0 : gapSize,
borderRadius: sliderSize / 2,
}
const swatchStyle = {
flexDirection:row?'column':'row',
width:row?20:'100%',
height:row?'100%':20,
marginLeft:row?margin:0,
marginTop:row?0:margin,
flexDirection: row ? 'column' : 'row',
width: row ? 20 : '100%',
height: row ? '100%' : 20,
marginLeft: row ? margin : 0,
marginTop: row ? 0 : margin,
}
const swatchFirstStyle = {
marginTop:0,
marginLeft:0,
marginRight:row?margin:0,
marginBottom:row?0:margin,
marginTop: 0,
marginLeft: 0,
marginRight: row ? margin : 0,
marginBottom: row ? 0 : margin,
}
if (this.state.swatchesUpdatedAt !== this.swatchesUpdatedAt) {
this.initSwatchAnimatedValues(this.props)
this.renderSwatches()
}
if (this.state.discsUpdatedAt !== this.discsUpdatedAt) {
this.initDiscAnimatedValues(this.props)
this.renderDiscs()
}
// console.log('RENDER >>',row,thumbSize,sliderSize)
return (
<View style={[ss.root,row?{flexDirection:'row'}:{},style]}>
{ swatches && !swatchesLast && <View style={[ss.swatches,swatchStyle,swatchFirstStyle]} key={'SW'}>{ this.swatches }</View> }
{ !swatchesOnly && <View style={[ss.wheel]} key={'$1'} onLayout={this.onSquareLayout}>
{ this.wheelWidth>0 && <View style={[{padding:thumbSize/2,width:this.wheelWidth,height:this.wheelWidth}]}>
<View style={[ss.root, row ? { flexDirection: 'row' } : {}, style]}>
{swatches && !swatchesLast && <View style={[ss.swatches, swatchStyle, swatchFirstStyle]} key={'SW'}>{this.swatches}</View>}
{!swatchesOnly && !(wheelHidden && !sliderHidden) && <View style={[ss.wheel]} key={'$1'} onLayout={this.onSquareLayout}>
{this.wheelWidth > 0 && <View style={[{ padding: thumbSize / 2, width: this.wheelWidth, height: this.wheelWidth }]} key={'$1$1'}>
<View style={[ss.wheelWrap]}>
<Image style={ss.wheelImg} source={srcWheel} />
<Animated.View style={[ss.wheelThumb,wheelThumbStyle,Elevations[4],{pointerEvents:'none'}]} />
<View style={[ss.cover]} onLayout={this.onWheelLayout} {...wheelPanHandlers} ref={r => { this.wheel = r }}></View>
<Image style={[ss.wheelImg, { opacity: !this.props.wheelLoadingIndicator || this.state.wheelImageLoaded ? 1 : 0 }]} key={'$1$1$1'} source={srcWheel} onLoad={this.onWheelImageLoad} />
{(this.props.wheelLoadingIndicator ? this.state.wheelImageLoaded : true) && <Animated.View style={[ss.wheelThumb, wheelThumbStyle, Elevations[4], { pointerEvents: 'none' }]} key={'$1$1$2'} />}
<View style={[ss.cover]} key={'$1$1$3'} onLayout={this.onWheelLayout} {...wheelPanHandlers} ref={r => { this.wheel = r }}>
{!!this.props.wheelLoadingIndicator && !this.state.wheelImageLoaded && this.props.wheelLoadingIndicator}
</View>
</View>
</View> }
</View> }
{ !swatchesOnly && !sliderHidden && (discrete ? <View style={[ss.swatches,swatchStyle]} key={'$2'}>{ this.disc }</View> : <View style={[ss.slider,sliderStyle]} key={'$2'}>
<View style={[ss.grad,{backgroundColor:hex}]}>
<Image style={ss.sliderImg} source={row?srcSliderRotated:srcSlider} resizeMode="stretch" />
</View>}
</View>}
{!swatchesOnly && !sliderHidden && (discrete
? <View style={[ss.swatches, swatchStyle]} key={'$2'}>{this.disc}</View>
: <View style={[ss.slider, sliderStyle]} key={'$2'}>
<View style={[ss.grad, { backgroundColor: hex }]} key={'$2$1'}>
<Image style={[ss.sliderImg, { opacity: !this.props.sliderLoadingIndicator || this.state.sliderImageLoaded ? 1 : 0 }]} source={row ? srcSliderRotated : srcSlider} onLoad={this.onSliderImageLoad} resizeMode="stretch" />
</View>
{(this.props.sliderLoadingIndicator ? this.state.sliderImageLoaded : true) && <Animated.View style={[ss.sliderThumb, sliderThumbStyle, Elevations[4], { pointerEvents: 'none' }]} key={'$2$2'} />}
<View style={[ss.cover]} key={'$2$3'} onLayout={this.onSliderLayout} {...sliderPanHandlers} ref={r => { this.slider = r }}>
{!!this.props.sliderLoadingIndicator && !this.state.sliderImageLoaded && this.props.sliderLoadingIndicator}
</View>
</View>
<Animated.View style={[ss.sliderThumb,sliderThumbStyle,Elevations[4],{pointerEvents:'none'}]} />
<View style={[ss.cover]} onLayout={this.onSliderLayout} {...sliderPanHandlers} ref={r => { this.slider = r }}></View>
</View>) }
{ swatches && swatchesLast && <View style={[ss.swatches,swatchStyle]} key={'SW'}>{ this.swatches }</View> }
)}
{swatches && swatchesLast && <View style={[ss.swatches, swatchStyle]} key={'SW'}>{this.swatches}</View>}
</View>

@@ -692,3 +793,3 @@ )

shadowColor: 'rgb(46, 48, 58)',
shadowOffset: {width: 0, height: 2},
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.8,

@@ -704,2 +805,4 @@ shadowRadius: 2,

// backgroundColor: '#ccccff88',
alignItems: 'center',
justifyContent: 'center',
},

@@ -721,4 +824,2 @@ slider: {

position: 'absolute',
top: 0,
left: 0,
borderWidth: 2,

@@ -725,0 +826,0 @@ borderColor: '#EEEEEE',

{
"name": "react-native-wheel-color-picker",
"version": "1.2.0",
"version": "1.3.0",
"description": "A color picker component for react native",

@@ -5,0 +5,0 @@ "main": "ColorPicker.js",

@@ -26,3 +26,3 @@ # React Native Wheel Color Picker

import { Component } from 'react'
import { View, Text } from 'react-native'
import { View, Text, ActivityIndicator } from 'react-native'

@@ -32,23 +32,27 @@ import ColorPicker from 'react-native-wheel-color-picker'

class App extends Component {
render() {
return (
<View style={[]}>
<ColorPicker
ref={r => { this.picker = r }}
color={this.state.currentColor}
swatchesOnly={this.state.swatchesOnly}
onColorChange={this.onColorChange}
onColorChangeComplete={this.onColorChangeComplete}
thumbSize={40}
sliderSize={40}
noSnap={true}
row={false}
swatchesLast={this.state.swatchesLast}
swatches={this.state.swatchesEnabled}
discrete={this.state.disc}
/>
<SomeButton onPress={() => this.picker.revert()} />
</View>
)
}
render() {
return (
<View style={[]}>
<ColorPicker
ref={r => { this.picker = r }}
color={this.state.currentColor}
swatchesOnly={this.state.swatchesOnly}
onColorChange={this.onColorChange}
onColorChangeComplete={this.onColorChangeComplete}
thumbSize={40}
sliderSize={40}
noSnap={true}
row={false}
swatchesLast={this.state.swatchesLast}
swatches={this.state.swatchesEnabled}
discrete={this.state.disc}
wheelLodingIndicator={<ActivityIndicator size={40} />}
sliderLodingIndicator={<ActivityIndicator size={20} />}
useNativeDriver={false}
useNativeLayout={false}
/>
<SomeButton onPress={() => this.picker.revert()} />
</View>
)
}
}

@@ -59,7 +63,36 @@

## Changelog
### 1.3.0
- added changelog section to README.md
- prop added: `wheelLoadingIndicator`
- prop added: `sliderLoadingIndicator`
- prop added: `useNativeDriver`
- prop added: `useNativeLayout`
- prop added: `disabled`
- prop added: `flipTouchX`
- prop added: `flipTouchY`
- prop added: `wheelHidden`
- fixed a bug related to `discreteLength` prop
- no breaking changes
### 1.2.0
- prop added: `gapSize`
- prop added: `discreteLength`
- prop added: `swatchesHitSlop`
- prop added: `palette`
- prop added: `onInteractionStart`
- no breaking changes
### 1.1.0
- prop added: `shadeWheelThumb`
- prop added: `shadeSliderThumb`
- prop added: `autoResetSlider`
- no breaking changes
## API
## ***ColorPicker***
### ***ColorPicker***
## Component props and default values
### Component props and default values
`row: false` use row or vertical layout

@@ -75,5 +108,5 @@

`discrete: false` use swatchs of shades instead of slider
`discrete: false` use swatches of shades instead of slider
`discreteLength: 10` number of swatchs of shades
`discreteLength: 10` number of swatches of shades, should be > 1

@@ -106,3 +139,19 @@ `sliderHidden: false` if true the slider is hidden

## Instance methods
`wheelLoadingIndicator: null` wheel image loading component eg: <ActivityIndicator />
`sliderLoadingIndicator: null` slider image loading component eg: <ActivityIndicator />
`useNativeDriver: false` to use useNativeDriver for animations
`useNativeLayout: false` to use onLayoutEvent.nativeEvent.layout instead of measureInWindow for x, y, width, height values for wheel and slider measurements which may be useful to prevent some layout problems
`disabled: false` disable all interactions
`flipTouchX: false` flip touch positioning on X axis, might be useful in UI with RTL support
`flipTouchY: false` flip touch positioning on Y axis, might be useful in UI with RTL support
`wheelHidden: false` if true the wheel is hidden, does not work with sliderHidden = true
### Instance methods
`revert()` reverts the color to the one provided in the color prop

@@ -113,3 +162,3 @@

Copyright (c) 2021 Md. Naeemur Rahman (https://naeemur.github.io)
Copyright (c) 2020-2024 Md. Naeemur Rahman (https://naeemur.github.io)

@@ -116,0 +165,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy

@@ -14,5 +14,5 @@ import * as React from 'react';

gapSize?: number,
/** Use swatchs of shades instead of slider */
/** Use swatches of shades instead of slider */
discrete?: boolean,
/** Number of swatchs of shades */
/** Number of swatches of shades, should be > 1 */
discreteLength?: number,

@@ -45,2 +45,18 @@ /** If true the slider is hidden */

onColorChangeComplete?: (color: string) => void,
/** Wheel image loading component eg: <ActivityIndicator /> */
wheelLoadingIndicator?: React.ReactNode,
/** Slider image loading component eg: <ActivityIndicator /> */
sliderLoadingIndicator?: React.ReactNode,
/** To use useNativeDriver for animations */
useNativeDriver?: boolean,
/** To use onLayoutEvent.nativeEvent.layout instead of measureInWindow for x, y, width, height values for wheel and slider measurements which may be useful to prevent some layout problems */
useNativeLayout?: boolean,
/** Disable all interactions */
disabled?: boolean,
/** Flip touch positioning on X axis, might be useful in UI with RTL support */
flipTouchX?: boolean,
/** Flip touch positioning on Y axis, might be useful in UI with RTL support */
flipTouchY?: boolean,
/** If true the wheel is hidden, does not work with sliderHidden = true */
wheelHidden?: boolean,
}

@@ -47,0 +63,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc