UNPKG

react-native-skia-responsive-text

Version:

A library providing a wrapper for the React Native Skia Text component, offering features like user-friendly text alignment, efficient multiline text management, and straightforward text truncation.

131 lines (126 loc) 5.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _reactNativeSkia = require("@shopify/react-native-skia"); var _react = require("react"); var _reactNativeReanimated = require("react-native-reanimated"); var _hooks = require("../hooks"); var _utils = require("../utils"); var _TextLine = _interopRequireDefault(require("./TextLine")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _extends() { _extends = Object.assign ? Object.assign.bind() : 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); } const LINE_HEIGHT_MULTIPLIER = 1.5; function ResponsiveText(_ref) { let { animationSettings: animationSettingsProp, backgroundColor: backgroundColorProp, children, ellipsizeMode, font, height: heightProp, horizontalAlignment: horizontalAlignmentProp = 'left', lineHeight: lineHeightProp, numberOfLines, onMeasure, overflow = 'visible', text = '', verticalAlignment: verticalAlignmentProp = 'top', width: widthProp, x: xProp = 0, y: yProp = 0, ...rest } = _ref; const fontSize = font.getSize(); const width = widthProp ?? font.getTextWidth(text); // Update animation settings if they are provided const animationSettings = (0, _react.useMemo)(() => { if (!animationSettingsProp) return undefined; const { duration, easing, onComplete } = animationSettingsProp; if (!duration && !easing) return undefined; if (!duration) return { easing, onComplete }; if (!easing) return { duration, onComplete }; return { duration, easing, onComplete }; }, [animationSettingsProp]); // Create shared values from animatable props const x = (0, _hooks.useAnimatableValue)(xProp); const y = (0, _hooks.useAnimatableValue)(yProp); const backgroundColor = (0, _hooks.useAnimatableValue)(backgroundColorProp ?? 'transparent'); const lineHeight = (0, _hooks.useAnimatableValue)(lineHeightProp ?? LINE_HEIGHT_MULTIPLIER * fontSize); const horizontalAlignment = (0, _hooks.useAnimatableValue)(horizontalAlignmentProp); const verticalAlignment = (0, _hooks.useAnimatableValue)(verticalAlignmentProp); const textChunks = (0, _react.useMemo)(() => (0, _utils.getTextChunks)(text), [text]); // Divide text into lines const textLines = (0, _react.useMemo)(() => (0, _utils.wrapText)(textChunks, font, width, numberOfLines, ellipsizeMode), [textChunks, font, width, numberOfLines, ellipsizeMode]); // Calculate remaining values const horizontalAlignmentOffsets = (0, _reactNativeReanimated.useDerivedValue)(() => { const alignments = (0, _utils.getTextLinesAlignment)(textLines, width, horizontalAlignment.value); const textWidth = textLines.reduce((acc, _ref2) => { let { width: w } = _ref2; return Math.max(acc, w); }, 0); const textHeight = textLines.length * lineHeight.value; if (onMeasure) { (0, _reactNativeReanimated.runOnJS)(onMeasure)(textWidth, textHeight); } return alignments; }, [textLines]); const textHeight = (0, _reactNativeReanimated.useDerivedValue)(() => textLines.length * lineHeight.value - (lineHeight.value - LINE_HEIGHT_MULTIPLIER * fontSize)); const backgroundHeight = (0, _reactNativeReanimated.useDerivedValue)(() => heightProp ?? textHeight.value); const verticalAlignmentOffset = (0, _reactNativeReanimated.useDerivedValue)(() => (0, _utils.getVerticalAlignmentOffset)(textHeight.value, heightProp, verticalAlignment.value)); const backgroundComponent = backgroundColorProp && /*#__PURE__*/React.createElement(_reactNativeSkia.Rect, { color: backgroundColor, height: backgroundHeight, width: width, y: 0 }); const textComponent = /*#__PURE__*/React.createElement(React.Fragment, null, textLines.map((line, i) => /*#__PURE__*/React.createElement(_TextLine.default, _extends({}, rest, { animationSettings: animationSettings, font: font, fontSize: fontSize, horizontalAlignmentOffsets: horizontalAlignmentOffsets, index: i, key: i, lineHeight: lineHeight, text: line.text, verticalAlignmentOffset: verticalAlignmentOffset }), children))); const maskElement = (0, _react.useMemo)(() => /*#__PURE__*/React.createElement(_reactNativeSkia.Rect, { color: "white", height: backgroundHeight, width: width }), [backgroundHeight, width]); const groupTransform = (0, _reactNativeReanimated.useDerivedValue)(() => [{ translateX: x.value }, { translateY: y.value }]); return /*#__PURE__*/React.createElement(_reactNativeSkia.Group, { transform: groupTransform }, overflow === 'hidden' ? /*#__PURE__*/React.createElement(React.Fragment, null, backgroundComponent && /*#__PURE__*/React.createElement(_reactNativeSkia.Mask, { mask: maskElement, mode: "luminance" }, backgroundComponent), /*#__PURE__*/React.createElement(_reactNativeSkia.Mask, { mask: maskElement, mode: "luminance" }, textComponent)) : /*#__PURE__*/React.createElement(React.Fragment, null, backgroundComponent, textComponent)); } var _default = exports.default = /*#__PURE__*/(0, _react.memo)(ResponsiveText); //# sourceMappingURL=ResponsiveText.js.map