react-native-animateable-text
Version:
A fork of React Native's <Text/> component that supports Animated Values
276 lines (221 loc) • 8.08 kB
JavaScript
/**
* 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() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const DeprecatedTextPropTypes = require('deprecated-react-native-prop-types/DeprecatedTextPropTypes');
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');
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,
numberOfLines: true,
ellipsizeMode: true,
allowFontScaling: true,
maxFontSizeMultiplier: true,
disabled: true,
selectable: true,
selectionColor: true,
adjustsFontSizeToFit: true,
minimumFontScale: true,
textBreakStrategy: true,
onTextLayout: true,
onInlineViewLayout: true,
dataDetectorType: true,
android_hyphenationFrequency: 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 {
constructor(...args) {
super(...args);
_defineProperty(this, "touchableGetPressRectOffset", void 0);
_defineProperty(this, "touchableHandleActivePressIn", void 0);
_defineProperty(this, "touchableHandleActivePressOut", void 0);
_defineProperty(this, "touchableHandleLongPress", void 0);
_defineProperty(this, "touchableHandlePress", void 0);
_defineProperty(this, "touchableHandleResponderGrant", void 0);
_defineProperty(this, "touchableHandleResponderMove", void 0);
_defineProperty(this, "touchableHandleResponderRelease", void 0);
_defineProperty(this, "touchableHandleResponderTerminate", void 0);
_defineProperty(this, "touchableHandleResponderTerminationRequest", void 0);
_defineProperty(this, "state", { ...Touchable.Mixin.touchableGetInitialState(),
isHighlighted: false,
createResponderHandlers: this._createResponseHandlers.bind(this),
responseHandlers: null
});
}
static getDerivedStateFromProps(nextProps, prevState) {
return prevState.responseHandlers == null && isTouchable(nextProps) ? {
responseHandlers: prevState.createResponderHandlers()
} : null;
}
render() {
let props = this.props;
if (isTouchable(props)) {
props = { ...props,
...this.state.responseHandlers,
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;
}
}
_defineProperty(TouchableText, "defaultProps", {
accessible: true,
allowFontScaling: true,
ellipsizeMode: 'tail'
});
_defineProperty(TouchableText, "viewConfig", viewConfig);
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. */
TextToExport.propTypes = DeprecatedTextPropTypes;
export const AnimateableText = TextToExport;
//# sourceMappingURL=AnimateableText.js.map