UNPKG

@awsui/components-react

Version:

AWS UI is a collection of [React](https://reactjs.org/) components that help create intuitive, responsive, and accessible user experiences for web applications. It is developed by Amazon Web Services (AWS). This work is available under the terms of the [A

118 lines (117 loc) 6.84 kB
import { __assign, __rest } from "tslib"; import { getBaseProps } from '../../base-component'; import styles from './styles.css.js'; import clsx from 'clsx'; import React, { useCallback, useEffect, useImperativeHandle, useLayoutEffect, useRef } from 'react'; import { getDropdownPosition, focusPreservingScroll, getInteriorDropdownPosition } from './dropdown-fit-handler'; import { fireNonCancelableEvent, fireCancelableEvent } from '../../events'; var getMouseTarget = function (containerRef, e) { var element = e.target; do { if (element.dataset) { var mouseTarget = element.dataset.mouseTarget; if (mouseTarget) { return { mouseTarget: mouseTarget }; } } element = element.parentNode; } while (element && element !== containerRef.current); return {}; }; var Dropdown = React.forwardRef(function (_a, ref) { var _b, _c; var children = _a.children, trigger = _a.trigger, open = _a.open, _d = _a.hideOverflow, hideOverflow = _d === void 0 ? true : _d, onDropdownClose = _a.onDropdownClose, onMouseDown = _a.onMouseDown, onMouseMove = _a.onMouseMove, header = _a.header, footer = _a.footer, _e = _a.display, display = _e === void 0 ? 'block' : _e, dropdownId = _a.dropdownId, _f = _a.nativeAttributes, nativeAttributes = _f === void 0 ? {} : _f, _g = _a.stretchWidth, stretchWidth = _g === void 0 ? true : _g, _h = _a.stretchHeight, stretchHeight = _h === void 0 ? false : _h, _j = _a.prefersDownDirection, prefersDownDirection = _j === void 0 ? false : _j, _k = _a.interior, interior = _k === void 0 ? false : _k, restProps = __rest(_a, ["children", "trigger", "open", "hideOverflow", "onDropdownClose", "onMouseDown", "onMouseMove", "header", "footer", "display", "dropdownId", "nativeAttributes", "stretchWidth", "stretchHeight", "prefersDownDirection", "interior"]); var baseProps = getBaseProps(restProps); var triggerRef = useRef(null); var dropdownRef = useRef(null); var verticalContainerRef = useRef(null); var setDropdownPosition = function (position, target, verticalContainer, isInterior, entireWidth, entireHeight) { if (isInterior === void 0) { isInterior = false; } if (entireWidth === void 0) { entireWidth = false; } if (entireHeight === void 0) { entireHeight = false; } if (!entireHeight) { verticalContainer.style.maxHeight = position.height; } if (entireWidth) { target.classList.add(styles['occupy-entire-width']); } else { target.style.width = position.width; } var isInteriorPosition = function (position) { return position.bottom !== undefined; }; if (isInterior && isInteriorPosition(position)) { if (position.dropUp) { target.style.bottom = position.bottom; } else { target.style.top = position.top; } target.style.left = position.left; return; } if (position.dropUp) { target.classList.add(styles['dropdown-drop-up']); } else { target.classList.remove(styles['dropdown-drop-up']); } target.classList.add(position.dropLeft ? styles['dropdown-drop-left'] : styles['dropdown-drop-right']); }; useLayoutEffect(function () { if (open && dropdownRef.current && triggerRef.current && verticalContainerRef.current && hideOverflow) { verticalContainerRef.current.style.maxHeight = ''; dropdownRef.current.style.width = ''; dropdownRef.current.style.top = ''; dropdownRef.current.style.bottom = ''; dropdownRef.current.style.left = ''; dropdownRef.current.classList.remove(styles['dropdown-drop-left']); dropdownRef.current.classList.remove(styles['dropdown-drop-right']); dropdownRef.current.classList.remove(styles['dropdown-drop-up']); dropdownRef.current.classList.add(styles.nowrap); var position = interior ? getInteriorDropdownPosition(triggerRef.current, dropdownRef.current) : getDropdownPosition(triggerRef.current, dropdownRef.current, prefersDownDirection); setDropdownPosition(position, dropdownRef.current, verticalContainerRef.current, interior, !interior && stretchWidth, stretchHeight); dropdownRef.current.classList.remove(styles.nowrap); } }, [open, hideOverflow, dropdownRef, triggerRef, verticalContainerRef, interior, stretchWidth]); useImperativeHandle(ref, function () { return ({ focus: function () { if (dropdownRef.current) { focusPreservingScroll(dropdownRef.current); } } }); }, []); useEffect(function () { var clickListener = function (e) { if (dropdownRef.current && triggerRef.current && open) { if (!(dropdownRef.current.contains(e.target) || triggerRef.current.contains(e.target))) { fireNonCancelableEvent(onDropdownClose); } } }; document.addEventListener('click', clickListener); return function () { return document.removeEventListener('click', clickListener); }; }, [open, onDropdownClose]); var handleMouseDown = useCallback(function (e) { e.preventDefault(); fireCancelableEvent(onMouseDown, getMouseTarget(dropdownRef, e), e); }, [onMouseDown]); var handleMouseMove = useCallback(function (e) { fireCancelableEvent(onMouseMove, getMouseTarget(dropdownRef, e), e); }, [onMouseMove]); return (React.createElement("div", __assign({}, baseProps, { className: clsx(styles.root, styles["root-" + display], stretchWidth ? styles.stretch : interior ? styles.interior : styles['root-inline'], baseProps.className), ref: ref }, nativeAttributes), React.createElement("div", { ref: triggerRef, className: clsx(styles["trigger-" + display], (_b = {}, _b[styles['with-limited-width']] = !stretchWidth, _b)) }, trigger), React.createElement("div", { className: clsx(styles.dropdown, (_c = {}, _c[styles['extra-margin']] = display === 'inline', _c[styles.open] = open, _c[styles['with-limited-width']] = !stretchWidth, _c[styles['hide-upper-border']] = stretchWidth, _c[styles.interior] = interior, _c)), ref: dropdownRef, id: dropdownId, onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, "data-open": open }, React.createElement("div", { ref: verticalContainerRef, className: styles['ie11-wrapper'] }, header, children, footer)))); }); export default Dropdown;