7.18 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
4
5var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
6
7exports.__esModule = true;
8exports.useDropdownMenu = useDropdownMenu;
9exports["default"] = void 0;
10
11var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
12
13var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
14
15var _propTypes = _interopRequireDefault(require("prop-types"));
16
17var _react = _interopRequireWildcard(require("react"));
18
19var _useCallbackRef2 = _interopRequireDefault(require("@restart/hooks/useCallbackRef"));
20
21var _DropdownContext = _interopRequireDefault(require("./DropdownContext"));
22
23var _usePopper = _interopRequireDefault(require("./usePopper"));
24
25var _useRootClose = _interopRequireDefault(require("./useRootClose"));
26
27var _mergeOptionsWithPopperConfig = _interopRequireDefault(require("./mergeOptionsWithPopperConfig"));
28
29var noop = function noop() {};
30/**
31 * @memberOf Dropdown
32 * @param {object} options
33 * @param {boolean} options.flip Automatically adjust the menu `drop` position based on viewport edge detection
34 * @param {[number, number]} options.offset Define an offset distance between the Menu and the Toggle
35 * @param {boolean} options.show Display the menu manually, ignored in the context of a `Dropdown`
36 * @param {boolean} options.usePopper opt in/out of using PopperJS to position menus. When disabled you must position it yourself.
37 * @param {string} options.rootCloseEvent The pointer event to listen for when determining "clicks outside" the menu for triggering a close.
38 * @param {object} options.popperConfig Options passed to the [`usePopper`](/api/usePopper) hook.
39 */
40
41
42function useDropdownMenu(options) {
43 if (options === void 0) {
44 options = {};
45 }
46
47 var context = (0, _react.useContext)(_DropdownContext["default"]);
48
49 var _useCallbackRef = (0, _useCallbackRef2["default"])(),
50 arrowElement = _useCallbackRef[0],
51 attachArrowRef = _useCallbackRef[1];
52
53 var hasShownRef = (0, _react.useRef)(false);
54 var _options = options,
55 flip = _options.flip,
56 offset = _options.offset,
57 rootCloseEvent = _options.rootCloseEvent,
58 _options$fixed = _options.fixed,
59 fixed = _options$fixed === void 0 ? false : _options$fixed,
60 _options$popperConfig = _options.popperConfig,
61 popperConfig = _options$popperConfig === void 0 ? {} : _options$popperConfig,
62 _options$usePopper = _options.usePopper,
63 shouldUsePopper = _options$usePopper === void 0 ? !!context : _options$usePopper;
64 var show = (context == null ? void 0 : context.show) == null ? !!options.show : context.show;
65 var alignEnd = (context == null ? void 0 : context.alignEnd) == null ? options.alignEnd : context.alignEnd;
66
67 if (show && !hasShownRef.current) {
68 hasShownRef.current = true;
69 }
70
71 var handleClose = function handleClose(e) {
72 context == null ? void 0 : context.toggle(false, e);
73 };
74
75 var _ref = context || {},
76 drop = _ref.drop,
77 setMenu = _ref.setMenu,
78 menuElement = _ref.menuElement,
79 toggleElement = _ref.toggleElement;
80
81 var placement = alignEnd ? 'bottom-end' : 'bottom-start';
82 if (drop === 'up') placement = alignEnd ? 'top-end' : 'top-start';else if (drop === 'right') placement = alignEnd ? 'right-end' : 'right-start';else if (drop === 'left') placement = alignEnd ? 'left-end' : 'left-start';
83 var popper = (0, _usePopper["default"])(toggleElement, menuElement, (0, _mergeOptionsWithPopperConfig["default"])({
84 placement: placement,
85 enabled: !!(shouldUsePopper && show),
86 enableEvents: show,
87 offset: offset,
88 flip: flip,
89 fixed: fixed,
90 arrowElement: arrowElement,
91 popperConfig: popperConfig
92 }));
93 var menuProps = (0, _extends2["default"])({
94 ref: setMenu || noop,
95 'aria-labelledby': toggleElement == null ? void 0 : toggleElement.id
96 }, popper.attributes.popper, {
97 style: popper.styles.popper
98 });
99 var metadata = {
100 show: show,
101 alignEnd: alignEnd,
102 hasShown: hasShownRef.current,
103 toggle: context == null ? void 0 : context.toggle,
104 popper: shouldUsePopper ? popper : null,
105 arrowProps: shouldUsePopper ? (0, _extends2["default"])({
106 ref: attachArrowRef
107 }, popper.attributes.arrow, {
108 style: popper.styles.arrow
109 }) : {}
110 };
111 (0, _useRootClose["default"])(menuElement, handleClose, {
112 clickTrigger: rootCloseEvent,
113 disabled: !show
114 });
115 return [menuProps, metadata];
116}
117
118var propTypes = {
119 /**
120 * A render prop that returns a Menu element. The `props`
121 * argument should spread through to **a component that can accept a ref**.
122 *
123 * @type {Function ({
124 * show: boolean,
125 * alignEnd: boolean,
126 * close: (?SyntheticEvent) => void,
127 * placement: Placement,
128 * update: () => void,
129 * forceUpdate: () => void,
130 * props: {
131 * ref: (?HTMLElement) => void,
132 * style: { [string]: string | number },
133 * aria-labelledby: ?string
134 * },
135 * arrowProps: {
136 * ref: (?HTMLElement) => void,
137 * style: { [string]: string | number },
138 * },
139 * }) => React.Element}
140 */
141 children: _propTypes["default"].func.isRequired,
142
143 /**
144 * Controls the visible state of the menu, generally this is
145 * provided by the parent `Dropdown` component,
146 * but may also be specified as a prop directly.
147 */
148 show: _propTypes["default"].bool,
149
150 /**
151 * Aligns the dropdown menu to the 'end' of it's placement position.
152 * Generally this is provided by the parent `Dropdown` component,
153 * but may also be specified as a prop directly.
154 */
155 alignEnd: _propTypes["default"].bool,
156
157 /**
158 * Enables the Popper.js `flip` modifier, allowing the Dropdown to
159 * automatically adjust it's placement in case of overlap with the viewport or toggle.
160 * Refer to the [flip docs](https://popper.js.org/popper-documentation.html#modifiers..flip.enabled) for more info
161 */
162 flip: _propTypes["default"].bool,
163 usePopper: _propTypes["default"].oneOf([true, false]),
164
165 /**
166 * A set of popper options and props passed directly to react-popper's Popper component.
167 */
168 popperConfig: _propTypes["default"].object,
169
170 /**
171 * Override the default event used by RootCloseWrapper.
172 */
173 rootCloseEvent: _propTypes["default"].string
174};
175var defaultProps = {
176 usePopper: true
177};
178
179/**
180 * Also exported as `<Dropdown.Menu>` from `Dropdown`.
181 *
182 * @displayName DropdownMenu
183 * @memberOf Dropdown
184 */
185function DropdownMenu(_ref2) {
186 var children = _ref2.children,
187 options = (0, _objectWithoutPropertiesLoose2["default"])(_ref2, ["children"]);
188
189 var _useDropdownMenu = useDropdownMenu(options),
190 props = _useDropdownMenu[0],
191 meta = _useDropdownMenu[1];
192
193 return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, meta.hasShown ? children(props, meta) : null);
194}
195
196DropdownMenu.displayName = 'ReactOverlaysDropdownMenu';
197DropdownMenu.propTypes = propTypes;
198DropdownMenu.defaultProps = defaultProps;
199/** @component */
200
201var _default = DropdownMenu;
202exports["default"] = _default;
\No newline at end of file