UNPKG

wix-style-react

Version:
298 lines (296 loc) • 9.71 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _debounce = _interopRequireDefault(require("lodash/debounce")); var _shallowequal = _interopRequireDefault(require("shallowequal")); var _EllipsisSt = require("./Ellipsis.st.css"); var _Tooltip = _interopRequireDefault(require("../../Tooltip")); var _ZIndex = require("../../ZIndex"); var _TooltipCommon = require("../PropTypes/TooltipCommon"); var _jsxFileName = "/home/builduser/work/a9c1ac8876d5057c/packages/wix-style-react/dist/cjs/common/Ellipsis/Ellipsis.js"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var isTestEnv = process.env.NODE_ENV === 'test'; class TextComponent extends _react.default.PureComponent { constructor() { super(...arguments); this.requestedRecalculationMount = null; this.requestedRecalculationUpdate = []; this._getEllipsisClasses = () => { var { ellipsis, maxLines } = this.props; var ellipsisLines = maxLines > 1 ? 'multiline' : 'singleLine'; return className => ellipsis ? (0, _EllipsisSt.st)(_EllipsisSt.classes.text, { ellipsisLines }, className) : className; }; } componentDidMount() { if (!this.props.textRendered) { /** * The requestAnimationFrame implementation is meant for browser only race condition bug fix. * It does not get reproduced in test environment due JSDOM being not a browser. * So we skip the requestAnimationFrame part in order not to have delays in calculations. */ if (isTestEnv) { return this.props.onTextRendered(); } this.requestedRecalculationMount = requestAnimationFrame(() => { this.props.onTextRendered(); }); } } componentDidUpdate() { if (!this.props.textRendered) { /** * The requestAnimationFrame implementation is meant for browser only race condition bug fix. * It does not get reproduced in test environment due JSDOM being not a browser. * So we skip the requestAnimationFrame part in order not to have delays in calculations. */ if (isTestEnv) { return this.props.onTextRendered(); } this.requestedRecalculationUpdate.push(requestAnimationFrame(() => { this.props.onTextRendered(); })); } } componentWillUnmount() { if (this.requestedRecalculationMount) { cancelAnimationFrame(this.requestedRecalculationMount); } if (this.requestedRecalculationUpdate.length !== 0) { this.requestedRecalculationUpdate.forEach(id => cancelAnimationFrame(id)); } } render() { var { render, maxLines, textElementRef } = this.props; return render({ ref: textElementRef, ellipsisClasses: this._getEllipsisClasses(), ellipsisInlineStyle: { [_EllipsisSt.vars.maxLines]: maxLines } }); } } class Ellipsis extends _react.default.PureComponent { constructor(props) { super(props); /** * Once text component has rendered, * Update text content and tooltip active state * @private */ this._onTextRendered = () => { var { isActive, textContent } = this.state; var newState = { textRendered: true }; var newTextContent = this._getTextContent(); if (newTextContent !== textContent) { newState.textContent = newTextContent; } var shouldBeActive = this._checkShouldBeActive(); if (shouldBeActive !== isActive) { newState.isActive = shouldBeActive; } this.setState(newState); }; /** * An ellipsis is considered active when either the text's scroll width/height is wider than it's container or itself. * @private */ this._updateIsActive = () => { var { isActive } = this.state; var shouldBeActive = this._checkShouldBeActive(); if (shouldBeActive !== isActive) { this.setState({ isActive: shouldBeActive }); } }; this._getTextContent = () => { var { current: textElement } = this.ref; return textElement && textElement.textContent; }; this._checkShouldBeActive = () => this._isOverflowingHorizontally() || this._isOverflowingVertically(); this._isOverflowingHorizontally = () => { var { current: textElement } = this.ref; var { ellipsis } = this.props; return ellipsis && textElement && (textElement.scrollWidth - textElement.parentNode.offsetWidth > 1 || textElement.offsetWidth < textElement.scrollWidth); }; this._isOverflowingVertically = () => { var { current: textElement } = this.ref; var { ellipsis, maxLines } = this.props; return maxLines > 1 && ellipsis && textElement && (textElement.scrollHeight - textElement.parentNode.offsetHeight > 1 || textElement.offsetHeight < textElement.scrollHeight); }; /** * A callback for resizing the window, must be debounced in order to improve performance. * @private */ this._debouncedUpdate = (0, _debounce.default)(this._updateIsActive, 100); this.state = { isActive: false, textContent: null, textRendered: false }; this.ref = /*#__PURE__*/_react.default.createRef(); } componentDidMount() { window.addEventListener('resize', this._debouncedUpdate); } _renderText() { var { render, ellipsis, maxLines } = this.props; var { textRendered } = this.state; return /*#__PURE__*/_react.default.createElement(TextComponent, { render, ellipsis, maxLines, textRendered, onTextRendered: this._onTextRendered, textElementRef: this.ref, __self: this, __source: { fileName: _jsxFileName, lineNumber: 204, columnNumber: 7 } }); } render() { var { appendTo, wrapperClassName, disabled, enterDelay, exitDelay, fixed, flip, maxWidth, moveArrowTo, onHide, onShow, placement, showTooltip, textAlign, zIndex, size } = this.props; var { isActive, textContent } = this.state; return showTooltip && isActive ? /*#__PURE__*/_react.default.createElement(_Tooltip.default, { className: (0, _EllipsisSt.st)(_EllipsisSt.classes.tooltip, wrapperClassName), content: textContent, appendTo, disabled, enterDelay, exitDelay, fixed, flip, maxWidth, moveArrowTo, onHide, onShow, placement, textAlign, zIndex, size, __self: this, __source: { fileName: _jsxFileName, lineNumber: 234, columnNumber: 7 } }, this._renderText()) : this._renderText(); } static getDerivedStateFromProps(props, state) { var { render, ellipsis, maxLines } = props; var textPropsChanged = state.prevRender !== render || state.prevEllipsis !== ellipsis || state.prevMaxLines !== maxLines; if (!textPropsChanged) { return null; } // Text changed, initialize textRendered state return { textRendered: false, prevRender: render, prevEllipsis: ellipsis, prevMaxLines: maxLines }; } componentDidUpdate(prevProps) { var { textRendered } = this.state; if (textRendered && !(0, _shallowequal.default)(prevProps, this.props)) { this._updateIsActive(); } } componentWillUnmount() { this._debouncedUpdate.cancel(); window.removeEventListener('resize', this._debouncedUpdate); } } Ellipsis.propTypes = _objectSpread({ /** When true, text that is longer than it's container will be truncated to a single line followed by ellipsis. Otherwise the text will break into several lines. */ ellipsis: _propTypes.default.bool, /** True by default, set it to false in order to show ellipsis without a tooltip. */ showTooltip: _propTypes.default.bool, /** A className to be applied to the Ellipsis wrapper. */ wrapperClassName: _propTypes.default.string, /** The render function, use it to render a text you want to truncate with ellipsis. */ render: _propTypes.default.func, /** maxLines truncates text at a specific number of lines. */ maxLines: _propTypes.default.number }, _TooltipCommon.TooltipCommonProps); Ellipsis.defaultProps = { ellipsis: false, appendTo: 'window', flip: false, fixed: false, placement: 'top', zIndex: (0, _ZIndex.ZIndex)('Tooltip'), enterDelay: 0, exitDelay: 0, showTooltip: true }; var _default = exports.default = Ellipsis; //# sourceMappingURL=Ellipsis.js.map