UNPKG

@retailmenot/anchor

Version:

A React UI Library by RetailMeNot

284 lines (257 loc) 10.8 kB
import { f as _classCallCheck, g as _createClass, h as _inherits, i as _createSuper, a as _taggedTemplateLiteral } from './anchor-chunk-7b9d8557.js'; import { a as __rest } from './anchor-chunk-27f34e54.js'; import { a as get } from './anchor-chunk-6ebffda8.js'; import { a as PositionContainer } from './anchor-chunk-9ff4257f.js'; import { fromEvent, merge } from 'rxjs'; import { filter, map, mapTo, distinctUntilChanged, throttleTime } from 'rxjs/operators'; import { forwardRef, createElement, useContext, useState, Children, Fragment, useEffect, useRef, createRef, Component, cloneElement, useReducer, PureComponent, isValidElement, createContext, useImperativeHandle } from 'react'; import classNames from 'classnames'; import styled, { css } from '@xstyled/styled-components'; import { space } from '@xstyled/system'; function _templateObject() { var data = _taggedTemplateLiteral(["\n box-sizing: border-box;\n font-family: base;\n position: relative;\n cursor: pointer;\n display: inline-flex;\n justify-content: center;\n align-items: center;\n min-height: 1rem;\n min-width: 1rem;\n\n ", ";\n\n ", "\n"]); _templateObject = function _templateObject() { return data; }; return data; } var StyledDropDown = styled('div')(_templateObject(), function (_ref) { var position = _ref.position, spacing = _ref.spacing; if (!spacing) { return null; } switch (position) { case 'bottom': case 'bottomStart': case 'bottomEnd': return css({ paddingBottom: spacing, // this won't work for a negative spacing values. if we fix // these we could allow negative values marginBottom: "-".concat(spacing) }); case 'right': case 'rightStart': case 'rightEnd': return css({ paddingRight: spacing, marginRight: "-".concat(spacing) }); case 'left': case 'leftStart': case 'leftEnd': return css({ paddingLeft: spacing, marginLeft: "-".concat(spacing) }); case 'top': case 'topStart': case 'topEnd': return css({ paddingTop: spacing, marginTop: "-".concat(spacing) }); } return null; }, space); var DropDown = /*#__PURE__*/function (_React$Component) { _inherits(DropDown, _React$Component); var _super = _createSuper(DropDown); function DropDown() { var _this; _classCallCheck(this, DropDown); _this = _super.apply(this, arguments); // State _this.state = { hovered: false, clicked: false }; // Instance Reference _this.dropDownReference = createRef(); _this.containerReference = createRef(); return _this; } _createClass(DropDown, [{ key: "isOpen", value: function isOpen() { var _this$props = this.props, open = _this$props.open, _this$props$trigger = _this$props.trigger, trigger = _this$props$trigger === void 0 ? 'both' : _this$props$trigger; var _this$state = this.state, clicked = _this$state.clicked, hovered = _this$state.hovered; return open !== undefined ? open : trigger === 'click' && clicked || trigger === 'hover' && hovered || trigger === 'both' && (hovered || clicked); } }, { key: "componentDidMount", value: function componentDidMount() { var _this2 = this; var dropDown = this.dropDownReference.current; var container = this.containerReference.current; this.setState({ height: get(dropDown, 'clientHeight', 0), width: get(dropDown, 'clientWidth', 0), containerHeight: get(container, 'clientHeight', 0), containerWidth: get(container, 'clientWidth', 0) }); // Dropdown Instance this.rootElement = dropDown && dropDown.getRootNode ? dropDown.getRootNode() : document; var outsideClick$ = merge(fromEvent(this.rootElement, 'click'), fromEvent(this.rootElement, 'touchstart')).pipe(filter(function () { return _this2.isOpen(); }), filter(function (_ref2) { var target = _ref2.target; return !dropDown.contains(target); }), throttleTime(500)); var dropDownClick$ = merge(fromEvent(dropDown, 'click'), fromEvent(dropDown, 'touchstart')).pipe(throttleTime(500)); var escapeKey$ = fromEvent(this.rootElement, 'keyup').pipe(filter(function () { return _this2.isOpen(); }), filter(function (keyEvent) { return keyEvent.key === 'Escape'; })); var mouseEnter$ = fromEvent(dropDown, 'mouseenter'); var mouseLeave$ = fromEvent(dropDown, 'mouseleave'); this.clickedSub = merge(outsideClick$.pipe(mapTo(false)), escapeKey$.pipe(mapTo(false)), dropDownClick$.pipe(map(function () { return !_this2.state.clicked; }))).subscribe(function (clicked) { _this2.setState(function (_ref3) { var height = _ref3.height, width = _ref3.width; return { clicked: clicked, height: clicked ? get(dropDown, 'clientHeight', 0) : height, width: clicked ? get(dropDown, 'clientWidth', 0) : width }; }); if (_this2.props.onTriggered) { _this2.props.onTriggered(clicked, 'click'); } }); this.escapeSub = escapeKey$.subscribe(function (event) { if (_this2.props.onEscapeKey) { _this2.props.onEscapeKey(event); } }); this.outsideClickSub = outsideClick$.subscribe(function (event) { if (_this2.props.onOutsideClick) { _this2.props.onOutsideClick(event); } }); this.hoveredSub = merge(mouseEnter$.pipe(mapTo(true)), mouseLeave$.pipe(mapTo(false)), escapeKey$.pipe(mapTo(false)), dropDownClick$.pipe(mapTo(false))).pipe(filter(function () { return _this2.props.trigger === 'hover' || _this2.props.trigger === 'both'; }), distinctUntilChanged()).subscribe(function (hovered) { _this2.setState(function (_ref4) { var height = _ref4.height, width = _ref4.width; return { hovered: hovered, height: hovered ? get(dropDown, 'clientHeight', 0) : height, width: hovered ? get(dropDown, 'clientWidth', 0) : width }; }); if (_this2.props.onTriggered) { _this2.props.onTriggered(hovered, 'hover'); } }); } }, { key: "componentWillUnmount", value: function componentWillUnmount() { this.hoveredSub.unsubscribe(); this.clickedSub.unsubscribe(); this.escapeSub.unsubscribe(); this.outsideClickSub.unsubscribe(); } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var prevShowArrow = prevProps.showArrow, prevPosition = prevProps.position, prevSpacing = prevProps.spacing; var _this$props2 = this.props, showArrow = _this$props2.showArrow, position = _this$props2.position, spacing = _this$props2.spacing; if (showArrow !== prevShowArrow || position !== prevPosition || spacing !== prevSpacing) { var dropDown = this.dropDownReference.current; var container = this.containerReference.current; if (container) { this.setState({ height: get(dropDown, 'clientHeight', 0), width: get(dropDown, 'clientWidth', 0), containerHeight: get(container, 'clientHeight', 0), containerWidth: get(container, 'clientWidth', 0) }); } } } }, { key: "render", value: function render() { var _a = this.props, children = _a.children, className = _a.className, overlay = _a.overlay, spacing = _a.spacing, arrowSize = _a.arrowSize, debug = _a.debug, _a$trigger = _a.trigger, arrowIndent = _a.arrowIndent, _a$showArrow = _a.showArrow, showArrow = _a$showArrow === void 0 ? true : _a$showArrow, _a$position = _a.position, position = _a$position === void 0 ? 'bottom' : _a$position, _a$shadow = _a.shadow, shadow = _a$shadow === void 0 ? '0 0 0.5rem 0 rgba(0,0,0,0.2)' : _a$shadow, _a$border = _a.border, border = _a$border === void 0 ? 'light' : _a$border, _a$borderRadius = _a.borderRadius, borderRadius = _a$borderRadius === void 0 ? 'base' : _a$borderRadius, _a$background = _a.background, background = _a$background === void 0 ? 'white' : _a$background, _a$onTriggered = _a.onTriggered, _a$onEscapeKey = _a.onEscapeKey, _a$onOutsideClick = _a.onOutsideClick, props = __rest(_a, ["children", "className", "overlay", "spacing", "arrowSize", "debug", "trigger", "arrowIndent", "showArrow", "position", "shadow", "border", "borderRadius", "background", "onTriggered", "onEscapeKey", "onOutsideClick"]); var _this$state2 = this.state, _this$state2$height = _this$state2.height, height = _this$state2$height === void 0 ? 0 : _this$state2$height, _this$state2$width = _this$state2.width, width = _this$state2$width === void 0 ? 0 : _this$state2$width, _this$state2$containe = _this$state2.containerHeight, containerHeight = _this$state2$containe === void 0 ? 0 : _this$state2$containe, _this$state2$containe2 = _this$state2.containerWidth, containerWidth = _this$state2$containe2 === void 0 ? 0 : _this$state2$containe2; var showDropdown = this.isOpen(); // if they don't specify a spacing then we'll default // based on whether the arrow is there or not var spacingWithDefault = typeof spacing === 'undefined' ? showArrow ? '0.75rem' : '0' : spacing; return createElement(StyledDropDown, Object.assign({ ref: this.dropDownReference, className: classNames('anchor-drop-down', className), showArrow: showArrow, shadow: shadow, position: position, spacing: spacingWithDefault }, props), children, createElement(PositionContainer, { ref: this.containerReference, active: showDropdown, arrowIndent: arrowIndent, arrowSize: arrowSize, background: background, border: border, borderRadius: borderRadius, children: overlay, className: "anchor-drop-down-container", containerHeight: containerHeight, containerWidth: containerWidth, height: height, width: width, position: position, shadow: shadow, showArrow: showArrow, debug: debug })); } }]); return DropDown; }(Component); export { DropDown }; //# sourceMappingURL=dropdown.js.map