├── .github └── workflows │ └── npmpublish.yml ├── .gitignore ├── README.md ├── index.js ├── package.json ├── react-native-touchable-scale.d.ts └── src └── TouchableScale.js /.github/workflows/npmpublish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | publish-npm: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions/setup-node@v1 16 | with: 17 | node-version: 12 18 | registry-url: https://registry.npmjs.org/ 19 | - run: npm install 20 | - run: npm publish 21 | env: 22 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 23 | 24 | publish-gpr: 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/checkout@v2 28 | - uses: actions/setup-node@v1 29 | with: 30 | node-version: 12 31 | registry-url: https://npm.pkg.github.com/ 32 | - run: npm install 33 | - run: npm publish 34 | env: 35 | NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Animated touchable component. 2 | 3 | 4 | 5 | | Props | Required | Default Value | 6 | | ------------- | ------------- | ------------- | 7 | | [TouchableWithoutFeedback props...](https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html#props) 8 | | **style** style | No | | 9 | | **defaultScale** number | No | 1 | 10 | | **activeScale** number | No | 0.9 | 11 | | **tension** number | No | 150 | 12 | | **friction** number | No | 3 | 13 | | **pressInTension** number | No | | 14 | | **pressInFriction** number | No | | 15 | | **pressOutTension** number | No | | 16 | | **pressOutFriction** number | No | | 17 | | **useNativeDriver** boolean | No | true | 18 | 19 | ## Install 20 | 21 | ``` 22 | npm install --save react-native-touchable-scale 23 | ``` 24 | 25 | ## Usage 26 | 27 | ```js 28 | import TouchableScale from 'react-native-touchable-scale'; 29 | 30 | const Button = function(props) { 31 | return ( 32 | 37 | {props.children} 38 | 39 | ); 40 | }; 41 | ``` 42 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import TouchableScale from './src/TouchableScale'; 2 | 3 | export default TouchableScale; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-touchable-scale", 3 | "version": "2.2.0", 4 | "description": "Like TouchableOpacity, but scale.", 5 | "main": "index.js", 6 | "types": "react-native-touchable-scale.d.ts", 7 | "peerDependencies": { 8 | "react": ">=0.13.2 || ^0.14 || ^15.0.0", 9 | "react-native": ">=0.19.0" 10 | }, 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/kohver/react-native-touchable-scale.git" 17 | }, 18 | "keywords": [ 19 | "react", 20 | "react-native" 21 | ], 22 | "author": "Artyom Kohver ", 23 | "license": "ISC", 24 | "bugs": { 25 | "url": "https://github.com/kohver/react-native-touchable-scale/issues" 26 | }, 27 | "homepage": "https://github.com/kohver/react-native-touchable-scale#readme", 28 | "dependencies": { 29 | "prop-types": "^15.6.0", 30 | "deprecated-react-native-prop-types": "^2.3.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /react-native-touchable-scale.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'react-native-touchable-scale' { 2 | import React from 'react'; 3 | import { TouchableWithoutFeedbackProps } from 'react-native'; 4 | 5 | export interface TouchableScaleProps extends TouchableWithoutFeedbackProps { 6 | defaultScale?: number; 7 | activeScale?: number; 8 | tension?: number; 9 | friction?: number; 10 | pressInTension?: number; 11 | pressInFriction?: number; 12 | pressOutTension?: number; 13 | pressOutFriction?: number; 14 | useNativeDriver?: boolean; 15 | } 16 | 17 | export default class TouchableScale extends React.Component {} 18 | } 19 | -------------------------------------------------------------------------------- /src/TouchableScale.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { TouchableWithoutFeedback, Animated } from 'react-native'; 4 | import { ViewPropTypes } from 'deprecated-react-native-prop-types'; 5 | 6 | /** 7 | * @typedef {Object} TouchableWithoutFeedbackProps 8 | * @property {Object} children 9 | * @property {Object} [accessibilityComponentType] 10 | * @property {boolean} [accessibilityTraits] 11 | * @property {boolean} [accessible] 12 | * @property {number} [delayLongPress] 13 | * @property {number} [delayPressIn] 14 | * @property {number} [delayPressOut] 15 | * @property {boolean} [disabled] 16 | * @property {Object} [hitSlop] 17 | * @property {{top: number, left: number, bottom: number, right: number}} [hitSlop] 18 | * @property {Function} [onLayout] 19 | * @property {Function} [onLongPress] 20 | * @property {Function} [onPress] 21 | * @property {Function} [onPressIn] 22 | * @property {Function} [onPressOut] 23 | * @property {{top: number, left: number, bottom: number, right: number}} [pressRetentionOffset] 24 | */ 25 | 26 | /** 27 | * @typedef {TouchableWithoutFeedbackProps} TouchableScaleProps 28 | * @property {Object} [style] 29 | * @property {number} [defaultScale=1] 30 | * @property {number} [activeScale=0.9] 31 | * @property {number} [tension=150] 32 | * @property {number} [friction=3] 33 | * @property {number} [pressInTension] 34 | * @property {number} [pressInFriction] 35 | * @property {number} [pressOutTension] 36 | * @property {number} [pressOutFriction] 37 | * @property {boolean} [useNativeDriver] 38 | */ 39 | export default class TouchableScale extends React.Component { 40 | constructor(...args) { 41 | super(...args); 42 | /** @type {TouchableScaleProps} */ 43 | const props = this.props; 44 | 45 | this.onPressIn = this.onPressIn.bind(this); 46 | this.onPressOut = this.onPressOut.bind(this); 47 | this.scaleAnimation = new Animated.Value(props.defaultScale); 48 | } 49 | 50 | render() { 51 | /** @type {TouchableScaleProps} */ 52 | const props = this.props; 53 | 54 | return ( 55 | 61 | 68 | {props.children} 69 | 70 | 71 | ); 72 | } 73 | 74 | onPressIn(...args) { 75 | /** @type {TouchableScaleProps} */ 76 | const props = this.props; 77 | const tension = typeof props.pressInTension !== 'undefined' ? props.pressInTension : props.tension; 78 | const friction = typeof props.pressInFriction !== 'undefined' ? props.pressInFriction : props.friction; 79 | 80 | Animated.spring(this.scaleAnimation, { 81 | toValue: props.activeScale, 82 | tension: tension, 83 | friction: friction, 84 | useNativeDriver: props.useNativeDriver, 85 | }).start(); 86 | 87 | if (props.onPressIn) { 88 | props.onPressIn(...args); 89 | } 90 | } 91 | 92 | onPressOut(...args) { 93 | /** @type {TouchableScaleProps} */ 94 | const props = this.props; 95 | const tension = typeof props.pressOutTension !== 'undefined' ? props.pressOutTension : props.tension; 96 | const friction = typeof props.pressOutFriction !== 'undefined' ? props.pressOutFriction : props.friction; 97 | 98 | Animated.spring(this.scaleAnimation, { 99 | toValue: props.defaultScale, 100 | tension: tension, 101 | friction: friction, 102 | useNativeDriver: props.useNativeDriver, 103 | }).start(); 104 | 105 | if (props.onPressOut) { 106 | props.onPressOut(...args); 107 | } 108 | } 109 | } 110 | 111 | TouchableScale.propTypes = { 112 | ...TouchableWithoutFeedback.propTypes, 113 | style: ViewPropTypes.style, 114 | defaultScale: PropTypes.number.isRequired, 115 | activeScale: PropTypes.number.isRequired, 116 | tension: PropTypes.number.isRequired, 117 | friction: PropTypes.number.isRequired, 118 | pressInTension: PropTypes.number, 119 | pressInFriction: PropTypes.number, 120 | pressOutTension: PropTypes.number, 121 | pressOutFriction: PropTypes.number, 122 | useNativeDriver: PropTypes.bool, 123 | }; 124 | 125 | TouchableScale.defaultProps = { 126 | defaultScale: 1, 127 | activeScale: 0.9, 128 | tension: 150, 129 | friction: 3, 130 | useNativeDriver: true, 131 | }; 132 | --------------------------------------------------------------------------------