@helpscout/hsds-react
Version:
React component library for Help Scout's Design System
292 lines (229 loc) • 9.64 kB
JavaScript
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;
;