UNPKG

reblend-ui

Version:

Utilities for creating robust overlay components

146 lines (143 loc) 5.33 kB
"use strict"; exports.__esModule = true; exports.default = void 0; exports.useDropdownMenu = useDropdownMenu; var _reblendjs = require("reblendjs"); var _reblendHooks = require("reblend-hooks"); var _DropdownContext = require("./DropdownContext"); var _usePopper = require("./usePopper"); var _useClickOutside = require("./useClickOutside"); var _mergeOptionsWithPopperConfig = require("./mergeOptionsWithPopperConfig"); const noop = () => {}; /** * @memberOf Dropdown * @param {object} options * @param {boolean} options.flip Automatically adjust the menu `drop` position based on viewport edge detection * @param {[number, number]} options.offset Define an offset distance between the Menu and the Toggle * @param {boolean} options.show Display the menu manually, ignored in the context of a `Dropdown` * @param {boolean} options.usePopper opt in/out of using PopperJS to position menus. When disabled you must position it yourself. * @param {string} options.rootCloseEvent The pointer event to listen for when determining "clicks outside" the menu for triggering a close. * @param {object} options.popperConfig Options passed to the [`usePopper`](/api/usePopper) hook. */ function useDropdownMenu(options = {}) { const [context] = _reblendjs.useContext.bind(this)(_DropdownContext.default, "context"); this.state.context = context; const elementRef = _reblendHooks.useCallbackRef.bind(this)(); this.state.elementRef = elementRef; const hasShownRef = _reblendjs.useRef.bind(this)(false); this.state.hasShownRef = hasShownRef; const { flip, offset, rootCloseEvent, fixed = false, placement: placementOverride, popperConfig = {}, enableEventListeners = true, usePopper: shouldUsePopper = !!this.state.context } = options; this.state.flip = flip; this.state.offset = offset; this.state.rootCloseEvent = rootCloseEvent; this.state.fixed = fixed; this.state.placementOverride = placementOverride; this.state.popperConfig = popperConfig; this.state.enableEventListeners = enableEventListeners; this.state.shouldUsePopper = shouldUsePopper; const show = this.state.context?.show == null ? !!options.show : this.state.context.show; this.state.show = show; if (this.state.show && !this.state.hasShownRef.current) { this.state.hasShownRef.current = true; } const handleClose = e => { this.state.context?.toggle(false, e); }; this.state.handleClose = handleClose; const { placement, setMenu, menuElement, toggleElement } = this.state.context || {}; this.state.placement = placement; this.state.setMenu = setMenu; this.state.menuElement = menuElement; this.state.toggleElement = toggleElement; const popper = _usePopper.default.bind(this)(this.state.toggleElement, this.state.menuElement, (0, _mergeOptionsWithPopperConfig.default)({ placement: this.state.placementOverride || this.state.placement || 'bottom-start', enabled: this.state.shouldUsePopper, enableEvents: this.state.enableEventListeners == null ? this.state.show : this.state.enableEventListeners, offset: this.state.offset, flip: this.state.flip, fixed: this.state.fixed, arrowElement: this.state.elementRef.item, popperConfig: this.state.popperConfig })); this.state.popper = popper; const menuProps = { ref: this.state.setMenu || noop, 'aria-labelledby': this.state.toggleElement?.id, ...this.state.popper.attributes.popper, style: this.state.popper.styles.popper }; this.state.menuProps = menuProps; const metadata = { show: this.state.show, placement: this.state.placement, hasShown: this.state.hasShownRef.current, toggle: this.state.context?.toggle, popper: this.state.shouldUsePopper ? this.state.popper : null, arrowProps: this.state.shouldUsePopper ? { ref: this.state.elementRef.ref, ...this.state.popper.attributes.arrow, style: this.state.popper.styles.arrow } : {} }; this.state.metadata = metadata; _useClickOutside.default.bind(this)(this.state.menuElement, this.state.handleClose, { clickTrigger: this.state.rootCloseEvent, disabled: !this.state.show }); return [this.state.menuProps, this.state.metadata]; } /* @Reblend: Transformed from function to class */ /** * Also exported as `<Dropdown.Menu>` from `Dropdown`. * * @displayName DropdownMenu * @memberOf Dropdown */ class DropdownMenu extends _reblendjs.default { static ELEMENT_NAME = "DropdownMenu"; constructor() { super(); } async initState() { const [props, meta] = useDropdownMenu.bind(this)({ ...this.props, usePopper: this.props.usePopperProp }); this.state.props = props; this.state.meta = meta; } async initProps({ children, usePopper: usePopperProp = true, ...options }) { this.props = {}; this.props.children = children; this.props.usePopperProp = usePopperProp; this.props = { ...this.props, ...options }; } async html() { return _reblendjs.default.construct.bind(this)(_reblendjs.default, null, this.props.children.map(child => child(this.state.props, this.state.meta))); } } /* @Reblend: Transformed from function to class */ DropdownMenu.displayName = 'DropdownMenu'; /** @component */ var _default = exports.default = DropdownMenu;