@retailmenot/anchor
Version:
A React UI Library by RetailMeNot
284 lines (257 loc) • 10.8 kB
JavaScript
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