Skip to content

Commit

Permalink
fix: update versions and convert color picker to ts
Browse files Browse the repository at this point in the history
  • Loading branch information
dannyhw committed May 27, 2024
1 parent 9e1b8ee commit 304f40a
Show file tree
Hide file tree
Showing 16 changed files with 2,896 additions and 2,652 deletions.
9 changes: 9 additions & 0 deletions examples/expo-example/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// we use a config file because it resolves rootdir correctly

/** @type {import('jest').Config} */
const config = {
preset: 'jest-expo',
setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
};

module.exports = config;
32 changes: 13 additions & 19 deletions examples/expo-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
"test:ci": "jest --runInBand"
},
"dependencies": {
"@expo/metro-runtime": "~3.1.3",
"@expo/metro-runtime": "~3.2.1",
"@gorhom/bottom-sheet": "^4",
"@react-native-async-storage/async-storage": "1.21.0",
"@react-native-community/datetimepicker": "7.6.1",
"@react-native-community/slider": "4.4.2",
"@react-native-async-storage/async-storage": "1.23.1",
"@react-native-community/datetimepicker": "8.0.1",
"@react-native-community/slider": "4.5.2",
"@storybook/addon-essentials": "^8",
"@storybook/addon-interactions": "^8",
"@storybook/addon-links": "^8",
Expand All @@ -43,15 +43,15 @@
"@storybook/react-native-theming": "^8.0.0-alpha.4",
"@storybook/react-webpack5": "^8",
"@storybook/test": "^8",
"expo": "~50.0.14",
"expo": "~51.0.8",
"querystring": "^0.2.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.73.6",
"react-native-gesture-handler": "~2.14.1",
"react-native-reanimated": "~3.6.2",
"react-native-safe-area-context": "4.8.2",
"react-native-svg": "14.1.0",
"react-native": "0.74.1",
"react-native-gesture-handler": "~2.16.1",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.1",
"react-native-svg": "15.2.0",
"react-native-web": "~0.19.6",
"storybook": "^8",
"ws": "^8.16.0"
Expand All @@ -61,20 +61,14 @@
"@babel/plugin-proposal-export-namespace-from": "^7.18.9",
"@react-native/babel-preset": "^0.74.0",
"@testing-library/react-native": "12.4.3",
"@types/react": "~18.2.14",
"@types/react": "~18.2.79",
"@types/react-test-renderer": "18.0.7",
"@types/ws": "^8.5.10",
"babel-loader": "^9.1.3",
"babel-plugin-react-docgen-typescript": "^1.5.1",
"jest": "^29.7.0",
"jest-expo": "~50.0.4",
"jest-expo": "~51.0.2",
"metro-react-native-babel-preset": "^0.77.0",
"typescript": "^5.3.3"
},
"jest": {
"preset": "jest-expo",
"setupFilesAfterEnv": [
"<rootDir>/setup-jest.ts"
]
"typescript": "~5.3.3"
}
}
1 change: 1 addition & 0 deletions examples/expo-example/setup-jest.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
import '@testing-library/react-native/extend-expect';
import 'react-native-gesture-handler/jestSetup';
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
// credit to https://github.com/instea/react-native-color-picker
import React from 'react';
import PropTypes from 'prop-types';
import Slider from '@react-native-community/slider';
import { PureComponent, createRef } from 'react';
import {
I18nManager,
Image,
InteractionManager,
LayoutChangeEvent,
StyleSheet,
Text,
TouchableOpacity,
View,
Image,
StyleSheet,
InteractionManager,
I18nManager,
ViewStyle,
} from 'react-native';
import Slider from '@react-native-community/slider';
import tinycolor from 'tinycolor2';
import tinycolor, { ColorFormats } from 'tinycolor2';
import { createPanResponder } from './utils';

// TODO: Raise PR at react-native-color-picker with these fixes
interface HoloColorPickerProps {
color?: string | ColorFormats.HSV;
defaultColor?: string;
oldColor?: string;
onColorChange?: (color: ColorFormats.HSV) => void;
onColorSelected?: (color: string) => void;
onOldColorSelected?: (color: string) => void;
hideSliders?: boolean;
style?: ViewStyle;
}

interface HoloColorPickerState {
color: ColorFormats.HSV;
pickerSize: number | null;
}

export class HoloColorPicker extends PureComponent<HoloColorPickerProps, HoloColorPickerState> {
private _layout: { width: number; height: number; x: number; y: number };
private _pageX: number;
private _pageY: number;
private _isRTL: boolean;
private _pickerResponder: any;
private pickerContainer = createRef<View>();

export class HoloColorPicker extends React.PureComponent {
constructor(props, ctx) {
super(props, ctx);
const state = {
constructor(props: HoloColorPickerProps) {
super(props);
const state: HoloColorPickerState = {
color: { h: 0, s: 1, v: 1 },
pickerSize: null,
};
Expand All @@ -33,105 +54,94 @@ export class HoloColorPicker extends React.PureComponent {
this._layout = { width: 0, height: 0, x: 0, y: 0 };
this._pageX = 0;
this._pageY = 0;
this._onLayout = this._onLayout.bind(this);
this._onSValueChange = this._onSValueChange.bind(this);
this._onVValueChange = this._onVValueChange.bind(this);
this._onColorSelected = this._onColorSelected.bind(this);
this._onOldColorSelected = this._onOldColorSelected.bind(this);
this._isRTL = I18nManager.isRTL;
this._pickerResponder = createPanResponder({
onStart: this._handleColorChange,
onMove: this._handleColorChange,
});

this.pickerContainer = React.createRef();
}

getColor() {
return tinycolor(this._getColor()).toHexString();
}

_handleColorChange = ({ x, y }) => {
_handleColorChange = ({ x, y }: { x: number; y: number }) => {
const { s, v } = this._getColor();
const marginLeft = (this._layout.width - this.state.pickerSize) / 2;
const marginTop = (this._layout.height - this.state.pickerSize) / 2;
const marginLeft = (this._layout.width - (this.state.pickerSize ?? 0)) / 2;
const marginTop = (this._layout.height - (this.state.pickerSize ?? 0)) / 2;
const relativeX = x - this._pageX - marginLeft;
const relativeY = y - this._pageY - marginTop;
const h = this._computeHValue(relativeX, relativeY);
this._onColorChange({ h, s, v });
};

_onSValueChange(s) {
_onSValueChange = (s: number) => {
const { h, v } = this._getColor();
this._onColorChange({ h, s, v });
}
};

_onVValueChange(v) {
_onVValueChange = (v: number) => {
const { h, s } = this._getColor();
this._onColorChange({ h, s, v });
}
};

_onColorChange(color) {
_onColorChange = (color: ColorFormats.HSV) => {
this.setState({ color });
if (this.props.onColorChange) {
this.props.onColorChange(color);
}
}
};

_onLayout(l) {
_onLayout = (l: LayoutChangeEvent) => {
this._layout = l.nativeEvent.layout;
const { width, height } = this._layout;
const pickerSize = Math.min(width, height);
if (this.state.pickerSize !== pickerSize) {
this.setState({ pickerSize });
}
// layout.x, layout.y is always 0
// we always measure because layout is the same even though picker is moved on the page
InteractionManager.runAfterInteractions(
() =>
// measure only after (possible) animation ended
this.pickerContainer.current &&
InteractionManager.runAfterInteractions(() => {
if (this.pickerContainer.current) {
this.pickerContainer.current.measure((_x, _y, _width, _height, pageX, pageY) => {
// picker position in the screen
this._pageX = pageX;
this._pageY = pageY;
})
);
}
});
}
});
};

_getColor() {
const passedColor =
typeof this.props.color === 'string' ? tinycolor(this.props.color).toHsv() : this.props.color;
return passedColor || this.state.color;
}

_onColorSelected() {
_onColorSelected = () => {
const { onColorSelected } = this.props;
const color = tinycolor(this._getColor()).toHexString();
if (onColorSelected) {
onColorSelected(color);
}
}
};

_onOldColorSelected() {
_onOldColorSelected = () => {
const { oldColor, onOldColorSelected } = this.props;
const color = tinycolor(oldColor);
const color = tinycolor(oldColor!);
this.setState({ color: color.toHsv() });
if (onOldColorSelected) {
onOldColorSelected(color.toHexString());
}
}
};

_computeHValue(x, y) {
const mx = this.state.pickerSize / 2;
const my = this.state.pickerSize / 2;
_computeHValue(x: number, y: number) {
const mx = (this.state.pickerSize ?? 0) / 2;
const my = (this.state.pickerSize ?? 0) / 2;
const dx = x - mx;
const dy = y - my;
const rad = Math.atan2(dx, dy) + Math.PI + Math.PI / 2;
return ((rad * 180) / Math.PI) % 360;
}

_hValueToRad(deg) {
_hValueToRad(deg: number) {
const rad = (deg * Math.PI) / 180;
return rad - Math.PI - Math.PI / 2;
}
Expand All @@ -145,7 +155,7 @@ export class HoloColorPicker extends React.PureComponent {
const selectedColor = tinycolor(color).toHexString();
const indicatorColor = tinycolor({ h, s: 1, v: 1 }).toHexString();
const computed = makeComputedStyles({
pickerSize,
pickerSize: pickerSize ?? 0,
selectedColor,
indicatorColor,
oldColor,
Expand All @@ -159,7 +169,7 @@ export class HoloColorPicker extends React.PureComponent {
<View>
<View
{...this._pickerResponder.panHandlers}
style={[styles.picker, computed.picker]}
style={[computed.picker]}
collapsable={false}
>
<Image
Expand Down Expand Up @@ -206,34 +216,23 @@ export class HoloColorPicker extends React.PureComponent {
}
}

HoloColorPicker.propTypes = {
color: PropTypes.oneOfType([
PropTypes.string,
PropTypes.shape({
h: PropTypes.number,
s: PropTypes.number,
v: PropTypes.number,
}),
]),
defaultColor: PropTypes.string,
oldColor: PropTypes.string,
onColorChange: PropTypes.func,
onColorSelected: PropTypes.func,
onOldColorSelected: PropTypes.func,
hideSliders: PropTypes.bool,
style: PropTypes.any,
};

const makeComputedStyles = ({
indicatorColor,
selectedColor,
oldColor,
angle,
pickerSize,
isRTL,
}: {
indicatorColor: string;
selectedColor: string;
oldColor?: string;
angle: number;
pickerSize: number;
isRTL: boolean;
}) => {
const summarySize = 0.5 * pickerSize;
const indicatorPickerRatio = 42 / 510; // computed from picker image
const indicatorPickerRatio = 42 / 510;
const indicatorSize = indicatorPickerRatio * pickerSize;
const pickerPadding = indicatorSize / 3;
const indicatorRadius = pickerSize / 2 - indicatorSize / 2 - pickerPadding;
Expand Down Expand Up @@ -292,18 +291,15 @@ const styles = StyleSheet.create({
},
pickerImage: {
flex: 1,
width: null,
height: null,
width: undefined,
height: undefined,
},
pickerIndicator: {
position: 'absolute',
// Shadow only works on iOS.
shadowColor: 'black',
shadowOpacity: 0.3,
shadowOffset: { width: 3, height: 3 },
shadowRadius: 4,

// This will elevate the view on Android, causing shadow to be drawn.
elevation: 5,
},
selectedPreview: {
Expand Down
Loading

0 comments on commit 304f40a

Please sign in to comment.