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
JavaScript
"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