UNPKG

react-native-animateable-text

Version:

A fork of React Native's `<Text/> component that supports Reanimated Shared Values as text!

219 lines (213 loc) 6.85 kB
/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * * @format */ 'use strict'; function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } const React = require('react'); const ReactNativeViewAttributes = require('react-native/Libraries/Components/View/ReactNativeViewAttributes'); const Touchable = require('react-native/Libraries/Components/Touchable/Touchable'); const createReactNativeComponentClass = require('react-native/Libraries/Renderer/shims/createReactNativeComponentClass').default; const nullthrows = require('nullthrows'); const processColor = require('react-native/Libraries/StyleSheet/processColor'); const PRESS_RECT_OFFSET = { top: 20, left: 20, right: 20, bottom: 30 }; const viewConfig = { validAttributes: { ...ReactNativeViewAttributes.UIView, isHighlighted: true, isPressable: true, numberOfLines: true, ellipsizeMode: true, allowFontScaling: true, dynamicTypeRamp: true, maxFontSizeMultiplier: true, disabled: true, selectable: true, selectionColor: true, adjustsFontSizeToFit: true, minimumFontScale: true, textBreakStrategy: true, onTextLayout: true, onInlineViewLayout: true, dataDetectorType: true, android_hyphenationFrequency: true, lineBreakStrategyIOS: true, text: true }, directEventTypes: { topTextLayout: { registrationName: 'onTextLayout' }, topInlineViewLayout: { registrationName: 'onInlineViewLayout' } }, uiViewClassName: 'JBAnimatedText' }; /** * A React component for displaying text. * * See https://reactnative.dev/docs/text.html */ class TouchableText extends React.Component { static defaultProps = { accessible: true, allowFontScaling: true, ellipsizeMode: 'tail' }; state = { isHighlighted: false, createResponderHandlers: this._createResponseHandlers.bind(this), responseHandlers: null }; static getDerivedStateFromProps(nextProps, prevState) { return prevState.responseHandlers == null && isTouchable(nextProps) ? { responseHandlers: prevState.createResponderHandlers() } : null; } static viewConfig = viewConfig; render() { let props = this.props; if (isTouchable(props)) { props = { ...props, isHighlighted: this.state.isHighlighted }; } if (props.selectionColor != null) { props = { ...props, selectionColor: processColor(props.selectionColor) }; } if (__DEV__) { if (Touchable.TOUCH_TARGET_DEBUG && props.onPress != null) { props = { ...props, style: [props.style, { color: 'magenta' }] }; } } return /*#__PURE__*/React.createElement(RCTText, _extends({}, props, { ref: props.forwardedRef })); } _createResponseHandlers() { return { onStartShouldSetResponder: () => { const { onStartShouldSetResponder } = this.props; const shouldSetResponder = (onStartShouldSetResponder == null ? false : onStartShouldSetResponder()) || isTouchable(this.props); if (shouldSetResponder) { this._attachTouchHandlers(); } return shouldSetResponder; }, onResponderGrant: event => { nullthrows(this.touchableHandleResponderGrant)(event); if (this.props.onResponderGrant != null) { this.props.onResponderGrant.call(this, event); } }, onResponderMove: event => { nullthrows(this.touchableHandleResponderMove)(event); if (this.props.onResponderMove != null) { this.props.onResponderMove.call(this, event); } }, onResponderRelease: event => { nullthrows(this.touchableHandleResponderRelease)(event); if (this.props.onResponderRelease != null) { this.props.onResponderRelease.call(this, event); } }, onResponderTerminate: event => { nullthrows(this.touchableHandleResponderTerminate)(event); if (this.props.onResponderTerminate != null) { this.props.onResponderTerminate.call(this, event); } }, onResponderTerminationRequest: () => { const { onResponderTerminationRequest } = this.props; if (!nullthrows(this.touchableHandleResponderTerminationRequest)()) { return false; } if (onResponderTerminationRequest == null) { return true; } return onResponderTerminationRequest(); } }; } /** * Lazily attaches Touchable.Mixin handlers. */ _attachTouchHandlers() { if (this.touchableGetPressRectOffset != null) { return; } for (const key in Touchable.Mixin) { if (typeof Touchable.Mixin[key] === 'function') { this[key] = Touchable.Mixin[key].bind(this); } } this.touchableHandleActivePressIn = () => { if (!this.props.suppressHighlighting && isTouchable(this.props)) { this.setState({ isHighlighted: true }); } }; this.touchableHandleActivePressOut = () => { if (!this.props.suppressHighlighting && isTouchable(this.props)) { this.setState({ isHighlighted: false }); } }; this.touchableHandlePress = event => { if (this.props.onPress != null) { this.props.onPress(event); } }; this.touchableHandleLongPress = event => { if (this.props.onLongPress != null) { this.props.onLongPress(event); } }; this.touchableGetPressRectOffset = () => this.props.pressRetentionOffset == null ? PRESS_RECT_OFFSET : this.props.pressRetentionOffset; } } const isTouchable = props => props.onPress != null || props.onLongPress != null || // @ts-expect-error props.onStartShouldSetResponder != null; const RCTText = createReactNativeComponentClass(viewConfig.uiViewClassName, () => viewConfig); const Text = (props, forwardedRef) => { // @ts-expect-error return /*#__PURE__*/React.createElement(TouchableText, _extends({}, props, { forwardedRef: forwardedRef })); }; const TextToExport = React.forwardRef(Text); TextToExport.displayName = 'Animateable'; // TODO: Deprecate this. /* $FlowFixMe(>=0.89.0 site=react_native_fb) This comment suppresses an error * found when Flow v0.89 was deployed. To see the error, delete this comment * and run Flow. */ export const AnimateableText = TextToExport; //# sourceMappingURL=AnimateableText.js.map