@ioca/react 1.4.75 → 1.4.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/components/picker/dates/index.js +1 -1
- package/lib/cjs/components/picker/dates/index.js.map +1 -1
- package/lib/cjs/components/picker/time/index.js +1 -1
- package/lib/cjs/components/picker/time/index.js.map +1 -1
- package/lib/cjs/components/popconfirm/popconfirm.js +1 -1
- package/lib/cjs/components/popconfirm/popconfirm.js.map +1 -1
- package/lib/cjs/components/popup/content.js +5 -9
- package/lib/cjs/components/popup/content.js.map +1 -1
- package/lib/cjs/components/popup/popup.js +388 -157
- package/lib/cjs/components/popup/popup.js.map +1 -1
- package/lib/cjs/js/hooks.js +0 -4
- package/lib/cjs/js/hooks.js.map +1 -1
- package/lib/css/index.css +1 -1
- package/lib/css/index.css.map +1 -1
- package/lib/es/components/picker/dates/index.js +1 -1
- package/lib/es/components/picker/dates/index.js.map +1 -1
- package/lib/es/components/picker/time/index.js +1 -1
- package/lib/es/components/picker/time/index.js.map +1 -1
- package/lib/es/components/popconfirm/popconfirm.js +1 -1
- package/lib/es/components/popconfirm/popconfirm.js.map +1 -1
- package/lib/es/components/popup/content.js +6 -10
- package/lib/es/components/popup/content.js.map +1 -1
- package/lib/es/components/popup/popup.js +390 -159
- package/lib/es/components/popup/popup.js.map +1 -1
- package/lib/es/js/hooks.js +2 -5
- package/lib/es/js/hooks.js.map +1 -1
- package/lib/index.js +399 -175
- package/lib/types/components/popup/type.d.ts +0 -4
- package/package.json +100 -99
|
@@ -1,151 +1,322 @@
|
|
|
1
1
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { debounce } from 'radash';
|
|
3
|
+
import { useRef, useState, useMemo, useEffect, useLayoutEffect, Children, isValidElement, cloneElement } from 'react';
|
|
4
|
+
import { useResizeObserver, useMouseUp } from '../../js/hooks.js';
|
|
4
5
|
import { getPosition, getPointPosition } from '../../js/utils.js';
|
|
5
|
-
import ModalContext from '../modal/context.js';
|
|
6
6
|
import Content from './content.js';
|
|
7
7
|
|
|
8
8
|
function Popup(props) {
|
|
9
|
-
const { visible = false, content, trigger = "hover", gap = 12, offset = 8,
|
|
9
|
+
const { visible = false, content, trigger = "hover", gap = 12, offset = 8, position = "top", showDelay = 16, hideDelay = 12, touchable, arrow = true, align = "center", fitSize, disabled, style, className, children, onVisibleChange, } = props;
|
|
10
10
|
const triggerRef = useRef(null);
|
|
11
11
|
const contentRef = useRef(null);
|
|
12
12
|
const timerRef = useRef(null);
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
13
|
+
const afterHideTimerRef = useRef(null);
|
|
14
|
+
const rafRef = useRef(null);
|
|
15
|
+
const [show, setShow] = useState(false);
|
|
16
|
+
const showRef = useRef(false);
|
|
17
|
+
showRef.current = show;
|
|
18
|
+
const latestRef = useRef({
|
|
19
|
+
disabled,
|
|
20
|
+
trigger,
|
|
21
|
+
touchable,
|
|
22
|
+
showDelay,
|
|
23
|
+
hideDelay,
|
|
24
|
+
position,
|
|
25
|
+
gap,
|
|
26
|
+
offset,
|
|
27
|
+
align,
|
|
28
|
+
fitSize,
|
|
29
|
+
onVisibleChange,
|
|
30
30
|
});
|
|
31
|
+
latestRef.current = {
|
|
32
|
+
disabled,
|
|
33
|
+
trigger,
|
|
34
|
+
touchable,
|
|
35
|
+
showDelay,
|
|
36
|
+
hideDelay,
|
|
37
|
+
position,
|
|
38
|
+
gap,
|
|
39
|
+
offset,
|
|
40
|
+
align,
|
|
41
|
+
fitSize,
|
|
42
|
+
onVisibleChange,
|
|
43
|
+
};
|
|
44
|
+
const phaseRef = useRef("");
|
|
45
|
+
const lastPosRef = useRef(null);
|
|
46
|
+
const lastArrowRef = useRef(null);
|
|
47
|
+
const arrowElRef = useRef(null);
|
|
48
|
+
const pointRef = useRef(null);
|
|
31
49
|
const clearTimer = () => {
|
|
32
50
|
if (!timerRef.current)
|
|
33
51
|
return;
|
|
34
52
|
clearTimeout(timerRef.current);
|
|
35
53
|
timerRef.current = null;
|
|
36
|
-
|
|
54
|
+
phaseRef.current = "";
|
|
55
|
+
};
|
|
56
|
+
const clearAllTimers = () => {
|
|
57
|
+
clearTimer();
|
|
58
|
+
if (afterHideTimerRef.current) {
|
|
59
|
+
clearTimeout(afterHideTimerRef.current);
|
|
60
|
+
afterHideTimerRef.current = null;
|
|
61
|
+
}
|
|
62
|
+
if (rafRef.current !== null) {
|
|
63
|
+
cancelAnimationFrame(rafRef.current);
|
|
64
|
+
rafRef.current = null;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const setContentVisible = (visible) => {
|
|
68
|
+
const el = contentRef.current;
|
|
69
|
+
if (!el)
|
|
70
|
+
return;
|
|
71
|
+
el.style.opacity = visible ? "1" : "0";
|
|
72
|
+
el.style.transform = visible ? "none" : "translate(0, 2px)";
|
|
73
|
+
};
|
|
74
|
+
const ensureBaseStyle = () => {
|
|
75
|
+
const el = contentRef.current;
|
|
76
|
+
if (!el)
|
|
77
|
+
return;
|
|
78
|
+
const pos = "fixed";
|
|
79
|
+
if (el.style.position !== pos)
|
|
80
|
+
el.style.position = pos;
|
|
81
|
+
};
|
|
82
|
+
const applyFitSize = () => {
|
|
83
|
+
const o = latestRef.current;
|
|
84
|
+
const triggerEl = triggerRef.current;
|
|
85
|
+
const contentEl = contentRef.current;
|
|
86
|
+
if (!triggerEl || !contentEl)
|
|
87
|
+
return;
|
|
88
|
+
const vertical = ["top", "bottom"].includes(o.position);
|
|
89
|
+
const key = vertical ? "width" : "height";
|
|
90
|
+
if (!o.fitSize) {
|
|
91
|
+
contentEl.style[key] = "";
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const size = triggerEl[vertical ? "offsetWidth" : "offsetHeight"];
|
|
95
|
+
contentEl.style[key] =
|
|
96
|
+
typeof size === "number" ? `${size}px` : "";
|
|
97
|
+
};
|
|
98
|
+
const applyArrow = (arrowX, arrowY, arrowPos) => {
|
|
99
|
+
const contentEl = contentRef.current;
|
|
100
|
+
if (!contentEl)
|
|
101
|
+
return;
|
|
102
|
+
const arrowEl = arrowElRef.current ??
|
|
103
|
+
contentEl.querySelector(".i-popup-arrow");
|
|
104
|
+
arrowElRef.current = arrowEl;
|
|
105
|
+
if (!arrowEl)
|
|
106
|
+
return;
|
|
107
|
+
let left = arrowX ?? 0;
|
|
108
|
+
let top = arrowY ?? 0;
|
|
109
|
+
let transform = "";
|
|
110
|
+
switch (arrowPos) {
|
|
111
|
+
case "left":
|
|
112
|
+
left += 2;
|
|
113
|
+
transform = `translate(-100%, -50%) rotate(180deg)`;
|
|
114
|
+
break;
|
|
115
|
+
case "right":
|
|
116
|
+
left -= 2;
|
|
117
|
+
transform = `translate(0, -50%)`;
|
|
118
|
+
break;
|
|
119
|
+
case "top":
|
|
120
|
+
top -= 2;
|
|
121
|
+
transform = `translate(-50%, -50%) rotate(-90deg)`;
|
|
122
|
+
break;
|
|
123
|
+
case "bottom":
|
|
124
|
+
top += 2;
|
|
125
|
+
transform = `translate(-50%, -50%) rotate(90deg)`;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
const prev = lastArrowRef.current;
|
|
129
|
+
if (prev &&
|
|
130
|
+
prev.left === left &&
|
|
131
|
+
prev.top === top &&
|
|
132
|
+
prev.transform === transform) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
lastArrowRef.current = { left, top, transform };
|
|
136
|
+
arrowEl.style.left = `${left}px`;
|
|
137
|
+
arrowEl.style.top = `${top}px`;
|
|
138
|
+
arrowEl.style.transform = transform;
|
|
139
|
+
};
|
|
140
|
+
const applyLeftTop = (left, top) => {
|
|
141
|
+
const contentEl = contentRef.current;
|
|
142
|
+
if (!contentEl)
|
|
143
|
+
return;
|
|
144
|
+
const prev = lastPosRef.current;
|
|
145
|
+
if (prev && prev.left === left && prev.top === top)
|
|
146
|
+
return;
|
|
147
|
+
lastPosRef.current = { left, top };
|
|
148
|
+
contentEl.style.left = `${left}px`;
|
|
149
|
+
contentEl.style.top = `${top}px`;
|
|
150
|
+
};
|
|
151
|
+
const computeRelativePosition = () => {
|
|
152
|
+
const triggerEl = triggerRef.current;
|
|
153
|
+
const contentEl = contentRef.current;
|
|
154
|
+
if (!triggerEl || !contentEl)
|
|
155
|
+
return;
|
|
156
|
+
const o = latestRef.current;
|
|
157
|
+
applyFitSize();
|
|
158
|
+
const [left, top, { arrowX, arrowY, arrowPos }] = getPosition(triggerEl, contentEl, {
|
|
159
|
+
position: o.position,
|
|
160
|
+
gap: o.gap,
|
|
161
|
+
offset: o.offset,
|
|
162
|
+
align: o.align,
|
|
163
|
+
refWindow: true,
|
|
164
|
+
});
|
|
165
|
+
applyLeftTop(left, top);
|
|
166
|
+
applyArrow(arrowX, arrowY, arrowPos);
|
|
167
|
+
};
|
|
168
|
+
const computePointPosition = () => {
|
|
169
|
+
const contentEl = contentRef.current;
|
|
170
|
+
if (!contentEl)
|
|
171
|
+
return;
|
|
172
|
+
const point = pointRef.current;
|
|
173
|
+
if (!point)
|
|
174
|
+
return;
|
|
175
|
+
const [left, top] = getPointPosition(point, contentEl);
|
|
176
|
+
applyLeftTop(left, top);
|
|
177
|
+
};
|
|
178
|
+
const scheduleComputePosition = () => {
|
|
179
|
+
if (!showRef.current)
|
|
180
|
+
return;
|
|
181
|
+
if (rafRef.current !== null)
|
|
182
|
+
return;
|
|
183
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
184
|
+
rafRef.current = null;
|
|
185
|
+
if (!showRef.current)
|
|
186
|
+
return;
|
|
187
|
+
ensureBaseStyle();
|
|
188
|
+
if (latestRef.current.trigger === "contextmenu") {
|
|
189
|
+
computePointPosition();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
computeRelativePosition();
|
|
193
|
+
});
|
|
37
194
|
};
|
|
38
195
|
const handleShow = () => {
|
|
39
|
-
|
|
196
|
+
const opts = latestRef.current;
|
|
197
|
+
if (opts.disabled)
|
|
40
198
|
return;
|
|
41
|
-
|
|
42
|
-
|
|
199
|
+
clearAllTimers();
|
|
200
|
+
if (showRef.current &&
|
|
201
|
+
(opts.trigger !== "hover" ||
|
|
202
|
+
(opts.trigger === "hover" && !opts.touchable))) {
|
|
203
|
+
ensureBaseStyle();
|
|
204
|
+
computeRelativePosition();
|
|
205
|
+
setContentVisible(true);
|
|
43
206
|
return;
|
|
44
207
|
}
|
|
45
|
-
|
|
46
|
-
|
|
208
|
+
phaseRef.current = "showing";
|
|
209
|
+
if (!showRef.current) {
|
|
210
|
+
lastPosRef.current = null;
|
|
211
|
+
lastArrowRef.current = null;
|
|
212
|
+
arrowElRef.current = null;
|
|
213
|
+
setShow(true);
|
|
214
|
+
}
|
|
47
215
|
timerRef.current = setTimeout(() => {
|
|
48
|
-
if (
|
|
216
|
+
if (phaseRef.current !== "showing")
|
|
49
217
|
return;
|
|
50
|
-
requestAnimationFrame(() => {
|
|
51
|
-
|
|
218
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
219
|
+
rafRef.current = null;
|
|
220
|
+
if (phaseRef.current !== "showing")
|
|
52
221
|
return;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
left,
|
|
65
|
-
top,
|
|
66
|
-
};
|
|
67
|
-
state.arrowProps = {
|
|
68
|
-
left: arrowX,
|
|
69
|
-
top: arrowY,
|
|
70
|
-
pos: arrowPos,
|
|
71
|
-
};
|
|
72
|
-
onVisibleChange?.(true);
|
|
222
|
+
if (!contentRef.current)
|
|
223
|
+
return;
|
|
224
|
+
ensureBaseStyle();
|
|
225
|
+
if (opts.trigger === "contextmenu") {
|
|
226
|
+
computePointPosition();
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
computeRelativePosition();
|
|
230
|
+
}
|
|
231
|
+
setContentVisible(true);
|
|
232
|
+
opts.onVisibleChange?.(true);
|
|
73
233
|
clearTimer();
|
|
74
|
-
|
|
234
|
+
phaseRef.current = "";
|
|
75
235
|
});
|
|
76
|
-
}, showDelay);
|
|
236
|
+
}, opts.showDelay);
|
|
77
237
|
};
|
|
78
238
|
const handleHide = () => {
|
|
79
|
-
if (!
|
|
239
|
+
if (!showRef.current)
|
|
80
240
|
return;
|
|
81
|
-
|
|
241
|
+
clearAllTimers();
|
|
242
|
+
phaseRef.current = "hiding";
|
|
82
243
|
timerRef.current = setTimeout(() => {
|
|
83
|
-
if (
|
|
244
|
+
if (phaseRef.current !== "hiding") {
|
|
84
245
|
clearTimer();
|
|
85
246
|
return;
|
|
86
247
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
clearTimer();
|
|
95
|
-
onVisibleChange?.(false);
|
|
96
|
-
statusRef.current = "";
|
|
248
|
+
setContentVisible(false);
|
|
249
|
+
afterHideTimerRef.current = setTimeout(() => {
|
|
250
|
+
afterHideTimerRef.current = null;
|
|
251
|
+
setShow(false);
|
|
252
|
+
clearAllTimers();
|
|
253
|
+
latestRef.current.onVisibleChange?.(false);
|
|
254
|
+
phaseRef.current = "";
|
|
97
255
|
}, 160);
|
|
98
|
-
}, hideDelay);
|
|
256
|
+
}, latestRef.current.hideDelay);
|
|
99
257
|
};
|
|
100
258
|
const handleToggle = (action) => {
|
|
101
259
|
if (action !== undefined) {
|
|
102
260
|
action ? handleShow() : handleHide();
|
|
103
261
|
return;
|
|
104
262
|
}
|
|
105
|
-
|
|
106
|
-
};
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
timerRef.current = setTimeout(() => {
|
|
134
|
-
const [left, top] = getPointPosition(e, contentRef.current);
|
|
135
|
-
state.style = {
|
|
136
|
-
...state.style,
|
|
137
|
-
opacity: 1,
|
|
138
|
-
transform: "none",
|
|
139
|
-
left,
|
|
140
|
-
top,
|
|
263
|
+
showRef.current ? handleHide() : handleShow();
|
|
264
|
+
};
|
|
265
|
+
const hideRef = useRef(handleHide);
|
|
266
|
+
const toggleRef = useRef(handleToggle);
|
|
267
|
+
hideRef.current = handleHide;
|
|
268
|
+
toggleRef.current = handleToggle;
|
|
269
|
+
const doHide = useMemo(() => () => hideRef.current(), []);
|
|
270
|
+
const doToggle = useMemo(() => (action) => toggleRef.current(action), []);
|
|
271
|
+
const eventMaps = useMemo(() => {
|
|
272
|
+
return {
|
|
273
|
+
click: {
|
|
274
|
+
onClick: () => doToggle(true),
|
|
275
|
+
},
|
|
276
|
+
hover: {
|
|
277
|
+
onMouseEnter: () => doToggle(true),
|
|
278
|
+
onMouseLeave: () => doToggle(false),
|
|
279
|
+
},
|
|
280
|
+
focus: {
|
|
281
|
+
onFocus: () => doToggle(true),
|
|
282
|
+
onBlur: () => doToggle(false),
|
|
283
|
+
},
|
|
284
|
+
contextmenu: {
|
|
285
|
+
onContextMenu: (e) => {
|
|
286
|
+
e.preventDefault();
|
|
287
|
+
e.stopPropagation();
|
|
288
|
+
pointRef.current = {
|
|
289
|
+
pageX: e.pageX,
|
|
290
|
+
pageY: e.pageY,
|
|
141
291
|
};
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
292
|
+
if (showRef.current) {
|
|
293
|
+
ensureBaseStyle();
|
|
294
|
+
computePointPosition();
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
clearAllTimers();
|
|
298
|
+
phaseRef.current = "showing";
|
|
299
|
+
lastPosRef.current = null;
|
|
300
|
+
lastArrowRef.current = null;
|
|
301
|
+
arrowElRef.current = null;
|
|
302
|
+
setShow(true);
|
|
303
|
+
timerRef.current = setTimeout(() => {
|
|
304
|
+
if (phaseRef.current !== "showing")
|
|
305
|
+
return;
|
|
306
|
+
if (!contentRef.current)
|
|
307
|
+
return;
|
|
308
|
+
ensureBaseStyle();
|
|
309
|
+
computePointPosition();
|
|
310
|
+
setContentVisible(true);
|
|
311
|
+
clearTimer();
|
|
312
|
+
latestRef.current.onVisibleChange?.(true);
|
|
313
|
+
phaseRef.current = "";
|
|
314
|
+
}, latestRef.current.showDelay);
|
|
315
|
+
},
|
|
145
316
|
},
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
317
|
+
none: {},
|
|
318
|
+
};
|
|
319
|
+
}, [doToggle]);
|
|
149
320
|
const contentTouch = useMemo(() => {
|
|
150
321
|
if (!touchable)
|
|
151
322
|
return {};
|
|
@@ -158,72 +329,132 @@ function Popup(props) {
|
|
|
158
329
|
}
|
|
159
330
|
return events;
|
|
160
331
|
}, [touchable, trigger]);
|
|
161
|
-
const computePosition = () => {
|
|
162
|
-
if (!state.show)
|
|
163
|
-
return;
|
|
164
|
-
const [left, top, { arrowX, arrowY, arrowPos }] = getPosition(triggerRef.current, contentRef.current, {
|
|
165
|
-
position,
|
|
166
|
-
gap,
|
|
167
|
-
offset,
|
|
168
|
-
align,
|
|
169
|
-
refWindow,
|
|
170
|
-
});
|
|
171
|
-
Object.assign(state, {
|
|
172
|
-
style: { ...state.style, left, top },
|
|
173
|
-
arrowProps: { left: arrowX, top: arrowY, pos: arrowPos },
|
|
174
|
-
});
|
|
175
|
-
};
|
|
176
332
|
const { observe, unobserve, disconnect } = useResizeObserver();
|
|
177
333
|
useEffect(() => {
|
|
178
|
-
if (
|
|
179
|
-
return;
|
|
180
|
-
triggerRef.current && observe(triggerRef.current, computePosition);
|
|
181
|
-
if (!watchResize || !contentRef.current)
|
|
334
|
+
if (!observe)
|
|
182
335
|
return;
|
|
183
|
-
|
|
336
|
+
const triggerEl = triggerRef.current;
|
|
337
|
+
const contentEl = contentRef.current;
|
|
338
|
+
if (triggerEl)
|
|
339
|
+
observe(triggerEl, scheduleComputePosition);
|
|
340
|
+
if (contentEl)
|
|
341
|
+
observe(contentEl, scheduleComputePosition);
|
|
184
342
|
return () => {
|
|
185
|
-
if (
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
343
|
+
if (contentEl)
|
|
344
|
+
unobserve(contentEl);
|
|
345
|
+
if (triggerEl)
|
|
346
|
+
unobserve(triggerEl);
|
|
189
347
|
disconnect();
|
|
190
348
|
};
|
|
191
|
-
}, [
|
|
349
|
+
}, [trigger, observe, unobserve, disconnect, show]);
|
|
192
350
|
useLayoutEffect(() => {
|
|
193
|
-
if (!
|
|
351
|
+
if (!show)
|
|
194
352
|
return;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
353
|
+
ensureBaseStyle();
|
|
354
|
+
if (latestRef.current.trigger === "contextmenu") {
|
|
355
|
+
computePointPosition();
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
computeRelativePosition();
|
|
359
|
+
}
|
|
360
|
+
}, [show]);
|
|
199
361
|
useLayoutEffect(() => {
|
|
200
|
-
|
|
362
|
+
doToggle(visible);
|
|
201
363
|
}, [visible]);
|
|
202
364
|
useEffect(() => {
|
|
203
365
|
return () => {
|
|
204
|
-
|
|
366
|
+
clearAllTimers();
|
|
205
367
|
};
|
|
206
368
|
}, []);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
369
|
+
const mouseUpHandlerRef = useRef(() => { });
|
|
370
|
+
mouseUpHandlerRef.current = (e) => {
|
|
371
|
+
if (!showRef.current)
|
|
372
|
+
return;
|
|
373
|
+
const triggerEl = triggerRef.current;
|
|
374
|
+
const contentEl = contentRef.current;
|
|
375
|
+
if (!triggerEl || !contentEl)
|
|
376
|
+
return;
|
|
377
|
+
const tar = e.target;
|
|
378
|
+
if (triggerEl.contains(tar) || contentEl.contains(tar))
|
|
379
|
+
return;
|
|
380
|
+
doHide();
|
|
381
|
+
};
|
|
382
|
+
const onGlobalMouseUp = useMemo(() => (e) => mouseUpHandlerRef.current(e), []);
|
|
383
|
+
useMouseUp(onGlobalMouseUp);
|
|
384
|
+
useEffect(() => {
|
|
385
|
+
if (!show)
|
|
386
|
+
return;
|
|
387
|
+
if (typeof window === "undefined")
|
|
388
|
+
return;
|
|
389
|
+
const onScrollOrResize = debounce({ delay: 160 }, () => {
|
|
390
|
+
scheduleComputePosition();
|
|
391
|
+
});
|
|
392
|
+
window.addEventListener("scroll", onScrollOrResize, {
|
|
393
|
+
passive: true,
|
|
394
|
+
capture: true,
|
|
395
|
+
});
|
|
396
|
+
return () => {
|
|
397
|
+
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
398
|
+
};
|
|
399
|
+
}, [show]);
|
|
400
|
+
const mergeRefs = (...refs) => {
|
|
401
|
+
return (node) => {
|
|
402
|
+
for (const ref of refs) {
|
|
403
|
+
if (!ref)
|
|
404
|
+
continue;
|
|
405
|
+
if (typeof ref === "function") {
|
|
406
|
+
ref(node);
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
ref.current = node;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
};
|
|
414
|
+
return (jsxs(Fragment, { children: [(() => {
|
|
415
|
+
const events = eventMaps[trigger];
|
|
416
|
+
const items = Children.toArray(children);
|
|
417
|
+
const canAttachRef = (el) => {
|
|
418
|
+
if (!isValidElement(el))
|
|
419
|
+
return false;
|
|
420
|
+
const t = el.type;
|
|
421
|
+
if (typeof t === "string")
|
|
422
|
+
return true;
|
|
423
|
+
if (t?.prototype?.isReactComponent)
|
|
424
|
+
return true;
|
|
425
|
+
if (t?.$$typeof === Symbol.for("react.forward_ref"))
|
|
426
|
+
return true;
|
|
427
|
+
return false;
|
|
428
|
+
};
|
|
429
|
+
if (items.length !== 1) {
|
|
430
|
+
return (jsx("div", { ref: triggerRef, ...events, className: 'i-popup-trigger', style: { display: "inline-block" }, children: children }));
|
|
431
|
+
}
|
|
432
|
+
const only = items[0];
|
|
433
|
+
if (!isValidElement(only) || !canAttachRef(only)) {
|
|
434
|
+
return (jsx("div", { ref: triggerRef, ...events, className: 'i-popup-trigger', style: { display: "inline-block" }, children: only }));
|
|
435
|
+
}
|
|
436
|
+
const { className: childClassName, ...restProps } = only.props;
|
|
437
|
+
const nextProps = { ...restProps };
|
|
438
|
+
for (const evt of Object.keys(events)) {
|
|
439
|
+
const theirs = restProps[evt];
|
|
440
|
+
const ours = events[evt];
|
|
441
|
+
nextProps[evt] =
|
|
442
|
+
typeof theirs === "function"
|
|
443
|
+
? (e) => {
|
|
444
|
+
ours(e);
|
|
445
|
+
theirs(e);
|
|
446
|
+
}
|
|
447
|
+
: ours;
|
|
448
|
+
}
|
|
449
|
+
return cloneElement(only, {
|
|
450
|
+
ref: mergeRefs(only.ref, triggerRef),
|
|
451
|
+
className: childClassName,
|
|
452
|
+
...nextProps,
|
|
225
453
|
});
|
|
226
|
-
}),
|
|
454
|
+
})(), show && (jsx(Content, { ref: contentRef, arrow: arrow && trigger !== "contextmenu", style: {
|
|
455
|
+
...style,
|
|
456
|
+
position: "fixed",
|
|
457
|
+
}, className: className, ...contentTouch, trigger: triggerRef.current, children: content }))] }));
|
|
227
458
|
}
|
|
228
459
|
|
|
229
460
|
export { Popup as default };
|