UNPKG

@helpscout/hsds-react

Version:

React component library for Help Scout's Design System

292 lines (229 loc) 9.64 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = exports.Overflow = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _reactDom = _interopRequireDefault(require("react-dom")); var _getValidProps = _interopRequireDefault(require("@helpscout/react-utils/dist/getValidProps")); var _EventListener = _interopRequireDefault(require("../EventListener")); var _classnames = _interopRequireDefault(require("classnames")); var _Overflow = require("./Overflow.utils"); var _smoothScroll = require("../../utilities/smoothScroll"); var _scrollFade = require("../../utilities/scrollFade"); var _Overflow2 = require("./Overflow.css"); var _jsxRuntime = require("react/jsx-runtime"); function noop() {} var Overflow = /*#__PURE__*/function (_React$PureComponent) { (0, _inheritsLoose2.default)(Overflow, _React$PureComponent); function Overflow() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _React$PureComponent.call.apply(_React$PureComponent, [this].concat(args)) || this; _this.state = { shouldFadeOnMount: false }; _this._isMounted = false; _this.faderSize = 32; _this.scrollAmount = 0.7; _this.smoothScrollDuration = 200; _this.componentDidMount = function () { _this._isMounted = true; _this.setNodes(); _this.handleOnResize(); _this.bindPropMethods(); }; _this.componentWillUnmount = function () { _this._isMounted = false; }; _this.setNodes = function () { if (_this.node || !_this._isMounted) return; _this.node = _reactDom.default.findDOMNode((0, _assertThisInitialized2.default)(_this)); }; _this.bindPropMethods = function () { _this.props.refApplyFade(_this.handleOnResize); _this.props.refScrollToEnd(_this.scrollToEnd); }; _this.adjustHeight = function () { if (!_this._isMounted || !_this.node) return; var containerNode = _this.containerNode; var height = containerNode && containerNode.clientHeight; var heightOffset = 20; _this.setState({ shouldFadeOnMount: (0, _Overflow.hasContentOverflowX)(containerNode) }); // JSDOM does not provide node.clientHeight, which prevents // us from testing this calculation _this.node.style.height = height ? height - heightOffset + "px" : null; }; _this.applyFadeStyles = function (event) { var isScrollable = _this.props.isScrollable; var offset = _this.faderSize; if (!isScrollable) return; var transformLeft = (0, _scrollFade.getFadeLeftStyles)(event, offset); var transformRight = (0, _scrollFade.getFadeRightStyles)(event, offset); requestAnimationFrame(function () { _this.faderNodeLeft.style.transform = transformLeft; _this.faderNodeRight.style.transform = transformRight; }); }; _this.handleOnScroll = function (event) { var onScroll = _this.props.onScroll; _this.applyFadeStyles(event); onScroll(event); }; _this.handleOnResize = function () { // Initial adjustHeight has been tested. Ignoring due to fragility // of JSDOM + timeouts. requestAnimationFrame(function () { _this.adjustHeight(); _this.applyFadeStyles({ currentTarget: _this.containerNode }); }); }; _this.remapScrollDirections = function (event) { if (_this.props.remapScrollDirections) { (0, _Overflow.remapScrollingPlane)(event); } _this.props.onWheel(event); }; _this.scrollLeft = function () { if (!_this.props.scrollOnClickFade) return; var currentScrollAmount = _this.containerNode.scrollLeft; var scrollAmount = _this.containerNode.clientWidth * _this.scrollAmount; var scrollValue = currentScrollAmount - scrollAmount; _this.scrollContainerView(scrollValue); }; _this.scrollRight = function () { if (!_this.props.scrollOnClickFade) return; var currentScrollAmount = _this.containerNode.scrollLeft; var scrollAmount = _this.containerNode.clientWidth * _this.scrollAmount; var scrollValue = currentScrollAmount + scrollAmount; _this.scrollContainerView(scrollValue); }; _this.scrollToEnd = function () { if (!_this.containerNode) return; var scrollValue = _this.containerNode.scrollWidth; _this.scrollContainerView(scrollValue); }; _this.scrollContainerView = function (amount) { if (amount === void 0) { amount = 0; } if (!_this.containerNode) return; // Cannot be reliably + neatly tested in JSDOM. (0, _smoothScroll.smoothScrollTo)({ node: _this.containerNode, position: amount, direction: 'x', duration: _this.smoothScrollDuration, callback: undefined }); }; return _this; } var _proto = Overflow.prototype; _proto.render = function render() { var _this2 = this; var _this$props = this.props, backgroundColor = _this$props.backgroundColor, className = _this$props.className, children = _this$props.children, refApplyFade = _this$props.refApplyFade, refScrollToEnd = _this$props.refScrollToEnd, initialHeightAdjustDelay = _this$props.initialHeightAdjustDelay, isScrollable = _this$props.isScrollable, onScroll = _this$props.onScroll, remapScrollDirections = _this$props.remapScrollDirections, scrollableRef = _this$props.scrollableRef, scrollOnClickFade = _this$props.scrollOnClickFade, onWheel = _this$props.onWheel, rest = (0, _objectWithoutPropertiesLoose2.default)(_this$props, ["backgroundColor", "className", "children", "refApplyFade", "refScrollToEnd", "initialHeightAdjustDelay", "isScrollable", "onScroll", "remapScrollDirections", "scrollableRef", "scrollOnClickFade", "onWheel"]); var shouldFadeOnMount = this.state.shouldFadeOnMount; var componentClassName = (0, _classnames.default)('c-Overflow', shouldFadeOnMount && 'is-faded', isScrollable && 'is-scrollable', className); var faderLeftMarkup = /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: "c-Overflow__fader is-left", ref: function ref(node) { return _this2.faderNodeLeft = node; }, onClick: this.scrollLeft, role: "presentation", style: { color: backgroundColor } }); var faderRightMarkup = /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: "c-Overflow__fader is-right", onClick: this.scrollRight, ref: function ref(node) { return _this2.faderNodeRight = node; }, role: "presentation", style: { color: backgroundColor, transform: shouldFadeOnMount ? 'scaleX(1)' : 'scaleX(0)' } }); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Overflow2.OverflowUI, (0, _extends2.default)({}, (0, _getValidProps.default)(rest), { className: componentClassName, children: [faderLeftMarkup, /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: "c-Overflow__container", ref: function ref(node) { _this2.containerNode = node; scrollableRef(node); }, onScroll: this.handleOnScroll, onWheel: this.remapScrollDirections, children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: "c-Overflow__content", children: children }) }), faderRightMarkup, /*#__PURE__*/(0, _jsxRuntime.jsx)(_EventListener.default, { event: "resize", handler: this.handleOnResize })] })); }; return Overflow; }(_react.default.PureComponent); exports.Overflow = Overflow; Overflow.defaultProps = { 'data-cy': 'Overflow', initialHeightAdjustDelay: 30, isScrollable: true, onScroll: noop, onWheel: noop, refApplyFade: noop, refScrollToEnd: noop, remapScrollDirections: false, scrollableRef: noop, scrollOnClickFade: true }; Overflow.propTypes = { /** Background color for the fade elements. */ backgroundColor: _propTypes.default.string, /** Custom class names to be added to the component. */ className: _propTypes.default.string, /** Amount of time (`ms`) to re-calculate the height on mount. Default `60`. */ initialHeightAdjustDelay: _propTypes.default.number, /** Enables horizontal scrolling on overflow. Default is `true`. */ isScrollable: _propTypes.default.bool, /** Callback function when component is scrolled. */ onScroll: _propTypes.default.func, /** Retrieves the scrollable node. */ scrollableRef: _propTypes.default.func, refApplyFade: _propTypes.default.func, refScrollToEnd: _propTypes.default.func, onWheel: _propTypes.default.func, remapScrollDirections: _propTypes.default.bool, scrollOnClickFade: _propTypes.default.bool, /** Data attr for Cypress tests. */ 'data-cy': _propTypes.default.string }; var _default = Overflow; exports.default = _default;