UNPKG

6.35 kBJavaScriptView Raw
1import _extends from "@babel/runtime/helpers/esm/extends";
2import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4import useSafeState from '@restart/hooks/useSafeState';
5import { createPopper } from './popper';
6
7var initialPopperStyles = function initialPopperStyles(position) {
8 return {
9 position: position,
10 top: '0',
11 left: '0',
12 opacity: '0',
13 pointerEvents: 'none'
14 };
15};
16
17var disabledApplyStylesModifier = {
18 name: 'applyStyles',
19 enabled: false
20}; // until docjs supports type exports...
21
22var ariaDescribedByModifier = {
23 name: 'ariaDescribedBy',
24 enabled: true,
25 phase: 'afterWrite',
26 effect: function effect(_ref) {
27 var state = _ref.state;
28 return function () {
29 var _state$elements = state.elements,
30 reference = _state$elements.reference,
31 popper = _state$elements.popper;
32
33 if ('removeAttribute' in reference) {
34 var ids = (reference.getAttribute('aria-describedby') || '').split(',').filter(function (id) {
35 return id.trim() !== popper.id;
36 });
37 if (!ids.length) reference.removeAttribute('aria-describedby');else reference.setAttribute('aria-describedby', ids.join(','));
38 }
39 };
40 },
41 fn: function fn(_ref2) {
42 var _popper$getAttribute;
43
44 var state = _ref2.state;
45 var _state$elements2 = state.elements,
46 popper = _state$elements2.popper,
47 reference = _state$elements2.reference;
48 var role = (_popper$getAttribute = popper.getAttribute('role')) == null ? void 0 : _popper$getAttribute.toLowerCase();
49
50 if (popper.id && role === 'tooltip' && 'setAttribute' in reference) {
51 var ids = reference.getAttribute('aria-describedby');
52
53 if (ids && ids.split(',').indexOf(popper.id) !== -1) {
54 return;
55 }
56
57 reference.setAttribute('aria-describedby', ids ? ids + "," + popper.id : popper.id);
58 }
59 }
60};
61var EMPTY_MODIFIERS = [];
62/**
63 * Position an element relative some reference element using Popper.js
64 *
65 * @param referenceElement
66 * @param popperElement
67 * @param {object} options
68 * @param {object=} options.modifiers Popper.js modifiers
69 * @param {boolean=} options.enabled toggle the popper functionality on/off
70 * @param {string=} options.placement The popper element placement relative to the reference element
71 * @param {string=} options.strategy the positioning strategy
72 * @param {boolean=} options.eventsEnabled have Popper listen on window resize events to reposition the element
73 * @param {function=} options.onCreate called when the popper is created
74 * @param {function=} options.onUpdate called when the popper is updated
75 *
76 * @returns {UsePopperState} The popper state
77 */
78
79function usePopper(referenceElement, popperElement, _temp) {
80 var _ref3 = _temp === void 0 ? {} : _temp,
81 _ref3$enabled = _ref3.enabled,
82 enabled = _ref3$enabled === void 0 ? true : _ref3$enabled,
83 _ref3$placement = _ref3.placement,
84 placement = _ref3$placement === void 0 ? 'bottom' : _ref3$placement,
85 _ref3$strategy = _ref3.strategy,
86 strategy = _ref3$strategy === void 0 ? 'absolute' : _ref3$strategy,
87 _ref3$modifiers = _ref3.modifiers,
88 modifiers = _ref3$modifiers === void 0 ? EMPTY_MODIFIERS : _ref3$modifiers,
89 config = _objectWithoutPropertiesLoose(_ref3, ["enabled", "placement", "strategy", "modifiers"]);
90
91 var popperInstanceRef = useRef();
92 var update = useCallback(function () {
93 var _popperInstanceRef$cu;
94
95 (_popperInstanceRef$cu = popperInstanceRef.current) == null ? void 0 : _popperInstanceRef$cu.update();
96 }, []);
97 var forceUpdate = useCallback(function () {
98 var _popperInstanceRef$cu2;
99
100 (_popperInstanceRef$cu2 = popperInstanceRef.current) == null ? void 0 : _popperInstanceRef$cu2.forceUpdate();
101 }, []);
102
103 var _useSafeState = useSafeState(useState({
104 placement: placement,
105 update: update,
106 forceUpdate: forceUpdate,
107 attributes: {},
108 styles: {
109 popper: initialPopperStyles(strategy),
110 arrow: {}
111 }
112 })),
113 popperState = _useSafeState[0],
114 setState = _useSafeState[1];
115
116 var updateModifier = useMemo(function () {
117 return {
118 name: 'updateStateModifier',
119 enabled: true,
120 phase: 'write',
121 requires: ['computeStyles'],
122 fn: function fn(_ref4) {
123 var state = _ref4.state;
124 var styles = {};
125 var attributes = {};
126 Object.keys(state.elements).forEach(function (element) {
127 styles[element] = state.styles[element];
128 attributes[element] = state.attributes[element];
129 });
130 setState({
131 state: state,
132 styles: styles,
133 attributes: attributes,
134 update: update,
135 forceUpdate: forceUpdate,
136 placement: state.placement
137 });
138 }
139 };
140 }, [update, forceUpdate, setState]);
141 useEffect(function () {
142 if (!popperInstanceRef.current || !enabled) return;
143 popperInstanceRef.current.setOptions({
144 placement: placement,
145 strategy: strategy,
146 modifiers: [].concat(modifiers, [updateModifier, disabledApplyStylesModifier])
147 }); // intentionally NOT re-running on new modifiers
148 // eslint-disable-next-line react-hooks/exhaustive-deps
149 }, [strategy, placement, updateModifier, enabled]);
150 useEffect(function () {
151 if (!enabled || referenceElement == null || popperElement == null) {
152 return undefined;
153 }
154
155 popperInstanceRef.current = createPopper(referenceElement, popperElement, _extends({}, config, {
156 placement: placement,
157 strategy: strategy,
158 modifiers: [].concat(modifiers, [ariaDescribedByModifier, updateModifier])
159 }));
160 return function () {
161 if (popperInstanceRef.current != null) {
162 popperInstanceRef.current.destroy();
163 popperInstanceRef.current = undefined;
164 setState(function (s) {
165 return _extends({}, s, {
166 attributes: {},
167 styles: {
168 popper: initialPopperStyles(strategy)
169 }
170 });
171 });
172 }
173 }; // This is only run once to _create_ the popper
174 // eslint-disable-next-line react-hooks/exhaustive-deps
175 }, [enabled, referenceElement, popperElement]);
176 return popperState;
177}
178
179export default usePopper;
\No newline at end of file