@rc-component/trigger 1.0.0

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.
Files changed (51) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +321 -0
  3. package/assets/index/Mask.less +63 -0
  4. package/assets/index/Mobile.less +25 -0
  5. package/assets/index.css +133 -0
  6. package/assets/index.less +79 -0
  7. package/es/Popup/Arrow.d.ts +9 -0
  8. package/es/Popup/Arrow.js +47 -0
  9. package/es/Popup/Mask.d.ts +10 -0
  10. package/es/Popup/Mask.js +26 -0
  11. package/es/Popup/index.d.ts +39 -0
  12. package/es/Popup/index.js +149 -0
  13. package/es/TriggerWrapper.d.ts +8 -0
  14. package/es/TriggerWrapper.js +19 -0
  15. package/es/context.d.ts +6 -0
  16. package/es/context.js +3 -0
  17. package/es/hooks/useAction.d.ts +4 -0
  18. package/es/hooks/useAction.js +8 -0
  19. package/es/hooks/useAlign.d.ts +12 -0
  20. package/es/hooks/useAlign.js +275 -0
  21. package/es/hooks/useWatch.d.ts +1 -0
  22. package/es/hooks/useWatch.js +50 -0
  23. package/es/index.d.ts +61 -0
  24. package/es/index.js +448 -0
  25. package/es/interface.d.ts +122 -0
  26. package/es/interface.js +1 -0
  27. package/es/util.d.ts +7 -0
  28. package/es/util.js +47 -0
  29. package/lib/Popup/Arrow.d.ts +9 -0
  30. package/lib/Popup/Arrow.js +54 -0
  31. package/lib/Popup/Mask.d.ts +10 -0
  32. package/lib/Popup/Mask.js +33 -0
  33. package/lib/Popup/index.d.ts +39 -0
  34. package/lib/Popup/index.js +158 -0
  35. package/lib/TriggerWrapper.d.ts +8 -0
  36. package/lib/TriggerWrapper.js +27 -0
  37. package/lib/context.d.ts +6 -0
  38. package/lib/context.js +11 -0
  39. package/lib/hooks/useAction.d.ts +4 -0
  40. package/lib/hooks/useAction.js +14 -0
  41. package/lib/hooks/useAlign.d.ts +12 -0
  42. package/lib/hooks/useAlign.js +283 -0
  43. package/lib/hooks/useWatch.d.ts +1 -0
  44. package/lib/hooks/useWatch.js +57 -0
  45. package/lib/index.d.ts +61 -0
  46. package/lib/index.js +457 -0
  47. package/lib/interface.d.ts +122 -0
  48. package/lib/interface.js +5 -0
  49. package/lib/util.d.ts +7 -0
  50. package/lib/util.js +57 -0
  51. package/package.json +79 -0
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ import type { CSSMotionProps } from 'rc-motion';
3
+ export interface MaskProps {
4
+ prefixCls: string;
5
+ open?: boolean;
6
+ zIndex?: number;
7
+ mask?: boolean;
8
+ motion?: CSSMotionProps;
9
+ }
10
+ export default function Mask(props: MaskProps): JSX.Element;
@@ -0,0 +1,26 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import classNames from 'classnames';
3
+ import CSSMotion from 'rc-motion';
4
+ export default function Mask(props) {
5
+ var prefixCls = props.prefixCls,
6
+ open = props.open,
7
+ zIndex = props.zIndex,
8
+ mask = props.mask,
9
+ motion = props.motion;
10
+ if (!mask) {
11
+ return null;
12
+ }
13
+ return /*#__PURE__*/React.createElement(CSSMotion, _extends({}, motion, {
14
+ motionAppear: true,
15
+ visible: open,
16
+ removeOnLeave: true
17
+ }), function (_ref) {
18
+ var className = _ref.className;
19
+ return /*#__PURE__*/React.createElement("div", {
20
+ style: {
21
+ zIndex: zIndex
22
+ },
23
+ className: classNames("".concat(prefixCls, "-mask"), className)
24
+ });
25
+ });
26
+ }
@@ -0,0 +1,39 @@
1
+ import type { CSSMotionProps } from 'rc-motion';
2
+ import * as React from 'react';
3
+ import type { TriggerProps } from '../';
4
+ import type { AlignType } from '../interface';
5
+ export interface PopupProps {
6
+ prefixCls: string;
7
+ className?: string;
8
+ style?: React.CSSProperties;
9
+ popup?: TriggerProps['popup'];
10
+ target: HTMLElement;
11
+ onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
12
+ onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
13
+ zIndex?: number;
14
+ mask?: boolean;
15
+ onVisibleChanged: (visible: boolean) => void;
16
+ align?: AlignType;
17
+ arrow?: boolean;
18
+ arrowX?: number;
19
+ arrowY?: number;
20
+ open: boolean;
21
+ /** Tell Portal that should keep in screen. e.g. should wait all motion end */
22
+ keepDom: boolean;
23
+ onClick?: React.MouseEventHandler<HTMLDivElement>;
24
+ motion?: CSSMotionProps;
25
+ maskMotion?: CSSMotionProps;
26
+ forceRender?: boolean;
27
+ getPopupContainer?: TriggerProps['getPopupContainer'];
28
+ autoDestroy?: boolean;
29
+ ready: boolean;
30
+ offsetX: number;
31
+ offsetY: number;
32
+ onAlign: VoidFunction;
33
+ onPrepare: () => Promise<void>;
34
+ stretch?: string;
35
+ targetWidth?: number;
36
+ targetHeight?: number;
37
+ }
38
+ declare const Popup: React.ForwardRefExoticComponent<PopupProps & React.RefAttributes<HTMLDivElement>>;
39
+ export default Popup;
@@ -0,0 +1,149 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
3
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4
+ import Portal from '@rc-component/portal';
5
+ import classNames from 'classnames';
6
+ import CSSMotion from 'rc-motion';
7
+ import ResizeObserver from 'rc-resize-observer';
8
+ import useLayoutEffect from "rc-util/es/hooks/useLayoutEffect";
9
+ import * as React from 'react';
10
+ import Arrow from "./Arrow";
11
+ import Mask from "./Mask";
12
+ var Popup = /*#__PURE__*/React.forwardRef(function (props, ref) {
13
+ var popup = props.popup,
14
+ className = props.className,
15
+ prefixCls = props.prefixCls,
16
+ style = props.style,
17
+ target = props.target,
18
+ _onVisibleChanged = props.onVisibleChanged,
19
+ open = props.open,
20
+ keepDom = props.keepDom,
21
+ onClick = props.onClick,
22
+ mask = props.mask,
23
+ arrow = props.arrow,
24
+ align = props.align,
25
+ arrowX = props.arrowX,
26
+ arrowY = props.arrowY,
27
+ motion = props.motion,
28
+ maskMotion = props.maskMotion,
29
+ forceRender = props.forceRender,
30
+ getPopupContainer = props.getPopupContainer,
31
+ autoDestroy = props.autoDestroy,
32
+ zIndex = props.zIndex,
33
+ onMouseEnter = props.onMouseEnter,
34
+ onMouseLeave = props.onMouseLeave,
35
+ ready = props.ready,
36
+ offsetX = props.offsetX,
37
+ offsetY = props.offsetY,
38
+ onAlign = props.onAlign,
39
+ onPrepare = props.onPrepare,
40
+ stretch = props.stretch,
41
+ targetWidth = props.targetWidth,
42
+ targetHeight = props.targetHeight;
43
+ var childNode = typeof popup === 'function' ? popup() : popup;
44
+
45
+ // We can not remove holder only when motion finished.
46
+ var isNodeVisible = open || keepDom;
47
+
48
+ // ======================= Container ========================
49
+ var getPopupContainerNeedParams = (getPopupContainer === null || getPopupContainer === void 0 ? void 0 : getPopupContainer.length) > 0;
50
+ var _React$useState = React.useState(!getPopupContainer || !getPopupContainerNeedParams),
51
+ _React$useState2 = _slicedToArray(_React$useState, 2),
52
+ show = _React$useState2[0],
53
+ setShow = _React$useState2[1];
54
+
55
+ // Delay to show since `getPopupContainer` need target element
56
+ useLayoutEffect(function () {
57
+ if (!show && getPopupContainerNeedParams && target) {
58
+ setShow(true);
59
+ }
60
+ }, [show, getPopupContainerNeedParams, target]);
61
+
62
+ // ========================= Render =========================
63
+ if (!show) {
64
+ return null;
65
+ }
66
+
67
+ // >>>>> Offset
68
+ var offsetStyle = ready || !open ? {
69
+ left: offsetX,
70
+ top: offsetY
71
+ } : {
72
+ left: '-1000vw',
73
+ top: '-1000vh'
74
+ };
75
+
76
+ // >>>>> Misc
77
+ var miscStyle = {};
78
+ if (stretch) {
79
+ if (stretch.includes('height') && targetHeight) {
80
+ miscStyle.height = targetHeight;
81
+ } else if (stretch.includes('minHeight') && targetHeight) {
82
+ miscStyle.minHeight = targetHeight;
83
+ }
84
+ if (stretch.includes('width') && targetWidth) {
85
+ miscStyle.width = targetWidth;
86
+ } else if (stretch.includes('minWidth') && targetWidth) {
87
+ miscStyle.minWidth = targetWidth;
88
+ }
89
+ }
90
+ if (!open) {
91
+ miscStyle.pointerEvents = 'none';
92
+ }
93
+ return /*#__PURE__*/React.createElement(Portal, {
94
+ open: forceRender || isNodeVisible,
95
+ getContainer: getPopupContainer && function () {
96
+ return getPopupContainer(target);
97
+ },
98
+ autoDestroy: autoDestroy
99
+ }, /*#__PURE__*/React.createElement(Mask, {
100
+ prefixCls: prefixCls,
101
+ open: open,
102
+ zIndex: zIndex,
103
+ mask: mask,
104
+ motion: maskMotion
105
+ }), /*#__PURE__*/React.createElement(ResizeObserver, {
106
+ onResize: onAlign,
107
+ disabled: !open
108
+ }, /*#__PURE__*/React.createElement(CSSMotion, _extends({
109
+ motionAppear: true,
110
+ motionEnter: true,
111
+ motionLeave: true,
112
+ removeOnLeave: false,
113
+ forceRender: forceRender,
114
+ leavedClassName: "".concat(prefixCls, "-hidden")
115
+ }, motion, {
116
+ onAppearPrepare: onPrepare,
117
+ onEnterPrepare: onPrepare,
118
+ visible: open,
119
+ onVisibleChanged: function onVisibleChanged(nextVisible) {
120
+ var _motion$onVisibleChan;
121
+ motion === null || motion === void 0 ? void 0 : (_motion$onVisibleChan = motion.onVisibleChanged) === null || _motion$onVisibleChan === void 0 ? void 0 : _motion$onVisibleChan.call(motion, nextVisible);
122
+ _onVisibleChanged(nextVisible);
123
+ }
124
+ }), function (_ref) {
125
+ var motionClassName = _ref.className,
126
+ motionStyle = _ref.style;
127
+ var cls = classNames(prefixCls, motionClassName, className);
128
+ return /*#__PURE__*/React.createElement("div", {
129
+ ref: ref,
130
+ className: cls,
131
+ style: _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, offsetStyle), miscStyle), motionStyle), {}, {
132
+ boxSizing: 'border-box',
133
+ zIndex: zIndex
134
+ }, style),
135
+ onMouseEnter: onMouseEnter,
136
+ onMouseLeave: onMouseLeave,
137
+ onClick: onClick
138
+ }, arrow && /*#__PURE__*/React.createElement(Arrow, {
139
+ prefixCls: prefixCls,
140
+ align: align,
141
+ arrowX: arrowX,
142
+ arrowY: arrowY
143
+ }), childNode);
144
+ })));
145
+ });
146
+ if (process.env.NODE_ENV !== 'production') {
147
+ Popup.displayName = 'Popup';
148
+ }
149
+ export default Popup;
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ import type { TriggerProps } from '.';
3
+ export interface TriggerWrapperProps {
4
+ getTriggerDOMNode?: TriggerProps['getTriggerDOMNode'];
5
+ children: React.ReactElement;
6
+ }
7
+ declare const TriggerWrapper: React.ForwardRefExoticComponent<TriggerWrapperProps & React.RefAttributes<HTMLElement>>;
8
+ export default TriggerWrapper;
@@ -0,0 +1,19 @@
1
+ import { fillRef, useComposeRef } from "rc-util/es/ref";
2
+ import * as React from 'react';
3
+ var TriggerWrapper = /*#__PURE__*/React.forwardRef(function (props, ref) {
4
+ var children = props.children,
5
+ getTriggerDOMNode = props.getTriggerDOMNode;
6
+
7
+ // When use `getTriggerDOMNode`, we should do additional work to get the real dom
8
+ var setRef = React.useCallback(function (node) {
9
+ fillRef(ref, getTriggerDOMNode ? getTriggerDOMNode(node) : node);
10
+ }, [getTriggerDOMNode]);
11
+ var mergedRef = useComposeRef(setRef, children.ref);
12
+ return /*#__PURE__*/React.cloneElement(children, {
13
+ ref: mergedRef
14
+ });
15
+ });
16
+ if (process.env.NODE_ENV !== 'production') {
17
+ TriggerWrapper.displayName = 'TriggerWrapper';
18
+ }
19
+ export default TriggerWrapper;
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ export interface TriggerContextProps {
3
+ registerSubPopup: (id: string, node: HTMLElement) => void;
4
+ }
5
+ declare const TriggerContext: React.Context<TriggerContextProps>;
6
+ export default TriggerContext;
package/es/context.js ADDED
@@ -0,0 +1,3 @@
1
+ import * as React from 'react';
2
+ var TriggerContext = /*#__PURE__*/React.createContext(null);
3
+ export default TriggerContext;
@@ -0,0 +1,4 @@
1
+ import type { ActionType } from '../interface';
2
+ declare type ActionTypes = ActionType | ActionType[];
3
+ export default function useAction(action: ActionTypes, showAction?: ActionTypes, hideAction?: ActionTypes): [showAction: Set<ActionType>, hideAction: Set<ActionType>];
4
+ export {};
@@ -0,0 +1,8 @@
1
+ function toArray(val) {
2
+ return val ? Array.isArray(val) ? val : [val] : [];
3
+ }
4
+ export default function useAction(action, showAction, hideAction) {
5
+ var mergedShowAction = toArray(showAction !== null && showAction !== void 0 ? showAction : action);
6
+ var mergedHideAction = toArray(hideAction !== null && hideAction !== void 0 ? hideAction : action);
7
+ return [new Set(mergedShowAction), new Set(mergedHideAction)];
8
+ }
@@ -0,0 +1,12 @@
1
+ import type { AlignType } from '../interface';
2
+ export default function useAlign(open: boolean, popupEle: HTMLElement, target: HTMLElement | [x: number, y: number], placement: string, builtinPlacements: any, popupAlign?: AlignType): [
3
+ ready: boolean,
4
+ offsetX: number,
5
+ offsetY: number,
6
+ arrowX: number,
7
+ arrowY: number,
8
+ scaleX: number,
9
+ scaleY: number,
10
+ align: AlignType,
11
+ onAlign: VoidFunction
12
+ ];
@@ -0,0 +1,275 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3
+ import useEvent from "rc-util/es/hooks/useEvent";
4
+ import useLayoutEffect from "rc-util/es/hooks/useLayoutEffect";
5
+ import * as React from 'react';
6
+ import { getWin } from "../util";
7
+ function toNum(num) {
8
+ return Number.isNaN(num) ? 1 : num;
9
+ }
10
+ function splitPoints() {
11
+ var points = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
12
+ return [points[0], points[1]];
13
+ }
14
+ function getAlignPoint(rect, points) {
15
+ var topBottom = points[0];
16
+ var leftRight = points[1];
17
+ var x;
18
+ var y;
19
+
20
+ // Top & Bottom
21
+ if (topBottom === 't') {
22
+ y = rect.y;
23
+ } else if (topBottom === 'b') {
24
+ y = rect.y + rect.height;
25
+ } else {
26
+ y = rect.y + rect.height / 2;
27
+ }
28
+
29
+ // Left & Right
30
+ if (leftRight === 'l') {
31
+ x = rect.x;
32
+ } else if (leftRight === 'r') {
33
+ x = rect.x + rect.width;
34
+ } else {
35
+ x = rect.x + rect.width / 2;
36
+ }
37
+ return {
38
+ x: x,
39
+ y: y
40
+ };
41
+ }
42
+ function reversePoints(points, index) {
43
+ var reverseMap = {
44
+ t: 'b',
45
+ b: 't',
46
+ l: 'r',
47
+ r: 'l'
48
+ };
49
+ return points.map(function (point, i) {
50
+ if (i === index) {
51
+ return reverseMap[point] || 'c';
52
+ }
53
+ return point;
54
+ }).join('');
55
+ }
56
+ export default function useAlign(open, popupEle, target, placement, builtinPlacements, popupAlign) {
57
+ var _React$useState = React.useState({
58
+ ready: false,
59
+ offsetX: 0,
60
+ offsetY: 0,
61
+ arrowX: 0,
62
+ arrowY: 0,
63
+ scaleX: 1,
64
+ scaleY: 1,
65
+ align: builtinPlacements[placement] || {}
66
+ }),
67
+ _React$useState2 = _slicedToArray(_React$useState, 2),
68
+ offsetInfo = _React$useState2[0],
69
+ setOffsetInfo = _React$useState2[1];
70
+ var alignCountRef = React.useRef(0);
71
+ var onAlign = useEvent(function () {
72
+ if (popupEle && target && open) {
73
+ var popupElement = popupEle;
74
+ var originLeft = popupElement.style.left;
75
+ var originTop = popupElement.style.top;
76
+ var doc = popupElement.ownerDocument;
77
+ var win = getWin(popupElement);
78
+
79
+ // Reset first
80
+ popupElement.style.left = '0';
81
+ popupElement.style.top = '0';
82
+
83
+ // Calculate align style, we should consider `transform` case
84
+ var targetRect = Array.isArray(target) ? {
85
+ x: target[0],
86
+ y: target[1],
87
+ width: 0,
88
+ height: 0
89
+ } : target.getBoundingClientRect();
90
+ var popupRect = popupElement.getBoundingClientRect();
91
+ var _win$getComputedStyle = win.getComputedStyle(popupElement),
92
+ width = _win$getComputedStyle.width,
93
+ height = _win$getComputedStyle.height;
94
+ var _doc$documentElement = doc.documentElement,
95
+ clientWidth = _doc$documentElement.clientWidth,
96
+ clientHeight = _doc$documentElement.clientHeight;
97
+ var popupHeight = popupRect.height;
98
+ var popupWidth = popupRect.width;
99
+
100
+ // Reset back
101
+ popupElement.style.left = originLeft;
102
+ popupElement.style.top = originTop;
103
+
104
+ // Calculate scale
105
+ var _scaleX = toNum(Math.round(popupWidth / parseFloat(width) * 1000) / 1000);
106
+ var _scaleY = toNum(Math.round(popupHeight / parseFloat(height) * 1000) / 1000);
107
+
108
+ // Placement
109
+ var placementInfo = builtinPlacements[placement] || popupAlign || {};
110
+ var _ref = placementInfo.points || [],
111
+ _ref2 = _slicedToArray(_ref, 2),
112
+ popupPoint = _ref2[0],
113
+ targetPoint = _ref2[1];
114
+ var targetPoints = splitPoints(targetPoint);
115
+ var popupPoints = splitPoints(popupPoint);
116
+ var targetAlignPoint = getAlignPoint(targetRect, targetPoints);
117
+ var popupAlignPoint = getAlignPoint(popupRect, popupPoints);
118
+
119
+ // Real align info may not same as origin one
120
+ var nextAlignInfo = _objectSpread({}, placementInfo);
121
+
122
+ // Offset
123
+ var offset = placementInfo.offset;
124
+ var _ref3 = offset || [],
125
+ _ref4 = _slicedToArray(_ref3, 2),
126
+ _ref4$ = _ref4[0],
127
+ popupOffsetX = _ref4$ === void 0 ? 0 : _ref4$,
128
+ _ref4$2 = _ref4[1],
129
+ popupOffsetY = _ref4$2 === void 0 ? 0 : _ref4$2;
130
+
131
+ // Placement
132
+ var nextOffsetX = targetAlignPoint.x - popupAlignPoint.x + popupOffsetX;
133
+ var nextOffsetY = targetAlignPoint.y - popupAlignPoint.y + popupOffsetY;
134
+
135
+ // ================ Overflow =================
136
+ var targetAlignPointTL = getAlignPoint(targetRect, ['t', 'l']);
137
+ var popupAlignPointTL = getAlignPoint(popupRect, ['t', 'l']);
138
+ var targetAlignPointBR = getAlignPoint(targetRect, ['b', 'r']);
139
+ var popupAlignPointBR = getAlignPoint(popupRect, ['b', 'r']);
140
+ var overflow = placementInfo.overflow || {};
141
+ var adjustX = overflow.adjustX,
142
+ adjustY = overflow.adjustY,
143
+ shiftX = overflow.shiftX,
144
+ shiftY = overflow.shiftY;
145
+
146
+ // >>>>>>>>>> Top & Bottom
147
+ var nextPopupY = popupRect.y + nextOffsetY;
148
+ var nextPopupBottom = nextPopupY + popupHeight;
149
+ var needAdjustY = adjustY === true || adjustY >= 0;
150
+
151
+ // Bottom to Top
152
+ if (needAdjustY && popupPoints[0] === 't' && nextPopupBottom > clientHeight) {
153
+ nextOffsetY = targetAlignPointTL.y - popupAlignPointBR.y - popupOffsetY;
154
+ nextAlignInfo.points = [reversePoints(popupPoints, 0), reversePoints(targetPoints, 0)];
155
+ }
156
+
157
+ // Top to Bottom
158
+ if (needAdjustY && popupPoints[0] === 'b' && nextPopupY < 0) {
159
+ nextOffsetY = targetAlignPointBR.y - popupAlignPointTL.y - popupOffsetY;
160
+ nextAlignInfo.points = [reversePoints(popupPoints, 0), reversePoints(targetPoints, 0)];
161
+ }
162
+
163
+ // >>>>>>>>>> Left & Right
164
+ var nextPopupX = popupRect.x + nextOffsetX;
165
+ var nextPopupRight = nextPopupX + popupWidth;
166
+ var needAdjustX = adjustX === true || adjustX >= 0;
167
+
168
+ // >>>>> Flip
169
+ // Right to Left
170
+ if (needAdjustX && popupPoints[1] === 'l' && nextPopupRight > clientWidth) {
171
+ nextOffsetX = targetAlignPointTL.x - popupAlignPointBR.x - popupOffsetX;
172
+ nextAlignInfo.points = [reversePoints(popupPoints, 1), reversePoints(targetPoints, 1)];
173
+ }
174
+
175
+ // Left to Right
176
+ if (needAdjustX && popupPoints[1] === 'r' && nextPopupX < 0) {
177
+ nextOffsetX = targetAlignPointBR.x - popupAlignPointTL.x - popupOffsetX;
178
+ nextAlignInfo.points = [reversePoints(popupPoints, 1), reversePoints(targetPoints, 1)];
179
+ }
180
+
181
+ // >>>>> Shift
182
+ var numShiftX = shiftX === true ? 0 : shiftX;
183
+ if (typeof numShiftX === 'number') {
184
+ // Left
185
+ if (nextPopupX < 0) {
186
+ nextOffsetX -= nextPopupX;
187
+ if (targetRect.x + targetRect.width < numShiftX) {
188
+ nextOffsetX += targetRect.x + targetRect.width - numShiftX;
189
+ }
190
+ }
191
+
192
+ // Right
193
+ if (nextPopupRight > clientWidth) {
194
+ nextOffsetX -= nextPopupRight - clientWidth;
195
+ if (targetRect.x > clientWidth - numShiftX) {
196
+ nextOffsetX += targetRect.x - clientWidth + numShiftX;
197
+ }
198
+ }
199
+ }
200
+ var numShiftY = shiftY === true ? 0 : shiftY;
201
+ if (typeof numShiftY === 'number') {
202
+ // Top
203
+ if (nextPopupY < 0) {
204
+ nextOffsetY -= nextPopupY;
205
+ if (targetRect.y + targetRect.height < numShiftY) {
206
+ nextOffsetY += targetRect.y + targetRect.height - numShiftY;
207
+ }
208
+ }
209
+
210
+ // Bottom
211
+ if (nextPopupBottom > clientHeight) {
212
+ nextOffsetY -= nextPopupBottom - clientHeight;
213
+ if (targetRect.y > clientHeight - numShiftY) {
214
+ nextOffsetY += targetRect.y - clientHeight + numShiftY;
215
+ }
216
+ }
217
+ }
218
+
219
+ // Arrow center align
220
+ var popupLeft = popupRect.x + nextOffsetX;
221
+ var popupRight = popupLeft + popupWidth;
222
+ var popupTop = popupRect.y + nextOffsetY;
223
+ var popupBottom = popupTop + popupHeight;
224
+ var targetLeft = targetRect.x;
225
+ var targetRight = targetLeft + targetRect.width;
226
+ var targetTop = targetRect.y;
227
+ var targetBottom = targetTop + targetRect.height;
228
+ var maxLeft = Math.max(popupLeft, targetLeft);
229
+ var minRight = Math.min(popupRight, targetRight);
230
+ var xCenter = (maxLeft + minRight) / 2;
231
+ var nextArrowX = xCenter - popupLeft;
232
+ var maxTop = Math.max(popupTop, targetTop);
233
+ var minBottom = Math.min(popupBottom, targetBottom);
234
+ var yCenter = (maxTop + minBottom) / 2;
235
+ var nextArrowY = yCenter - popupTop;
236
+ setOffsetInfo({
237
+ ready: true,
238
+ offsetX: nextOffsetX / _scaleX,
239
+ offsetY: nextOffsetY / _scaleY,
240
+ arrowX: nextArrowX / _scaleX,
241
+ arrowY: nextArrowY / _scaleY,
242
+ scaleX: _scaleX,
243
+ scaleY: _scaleY,
244
+ align: nextAlignInfo
245
+ });
246
+ }
247
+ });
248
+ var triggerAlign = function triggerAlign() {
249
+ alignCountRef.current += 1;
250
+ var id = alignCountRef.current;
251
+
252
+ // Merge all align requirement into one frame
253
+ Promise.resolve().then(function () {
254
+ if (alignCountRef.current === id) {
255
+ onAlign();
256
+ }
257
+ });
258
+ };
259
+
260
+ // Reset ready status when placement & open changed
261
+ var resetReady = function resetReady() {
262
+ setOffsetInfo(function (ori) {
263
+ return _objectSpread(_objectSpread({}, ori), {}, {
264
+ ready: false
265
+ });
266
+ });
267
+ };
268
+ useLayoutEffect(resetReady, [placement]);
269
+ useLayoutEffect(function () {
270
+ if (!open) {
271
+ resetReady();
272
+ }
273
+ }, [open]);
274
+ return [offsetInfo.ready, offsetInfo.offsetX, offsetInfo.offsetY, offsetInfo.arrowX, offsetInfo.arrowY, offsetInfo.scaleX, offsetInfo.scaleY, offsetInfo.align, triggerAlign];
275
+ }
@@ -0,0 +1 @@
1
+ export default function useWatch(open: boolean, target: HTMLElement, popup: HTMLElement, onAlign: VoidFunction): void;
@@ -0,0 +1,50 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
2
+ import useLayoutEffect from "rc-util/es/hooks/useLayoutEffect";
3
+ import { getWin } from "../util";
4
+ function collectScroller(ele) {
5
+ var scrollerList = [];
6
+ var current = ele === null || ele === void 0 ? void 0 : ele.parentElement;
7
+ var scrollStyle = ['hidden', 'scroll', 'auto'];
8
+ while (current) {
9
+ var _getWin$getComputedSt = getWin(current).getComputedStyle(current),
10
+ overflowX = _getWin$getComputedSt.overflowX,
11
+ overflowY = _getWin$getComputedSt.overflowY;
12
+ if (scrollStyle.includes(overflowX) || scrollStyle.includes(overflowY)) {
13
+ scrollerList.push(current);
14
+ }
15
+ current = current.parentElement;
16
+ }
17
+ return scrollerList;
18
+ }
19
+ export default function useWatch(open, target, popup, onAlign) {
20
+ useLayoutEffect(function () {
21
+ if (open && target && popup) {
22
+ var targetElement = target;
23
+ var popupElement = popup;
24
+ var targetScrollList = collectScroller(targetElement);
25
+ var popupScrollList = collectScroller(popupElement);
26
+ var win = getWin(popupElement);
27
+ var mergedList = new Set([win].concat(_toConsumableArray(targetScrollList), _toConsumableArray(popupScrollList)));
28
+ function notifyScroll() {
29
+ onAlign();
30
+ }
31
+ mergedList.forEach(function (scroller) {
32
+ scroller.addEventListener('scroll', notifyScroll, {
33
+ passive: true
34
+ });
35
+ });
36
+ win.addEventListener('resize', notifyScroll, {
37
+ passive: true
38
+ });
39
+
40
+ // First time always do align
41
+ onAlign();
42
+ return function () {
43
+ mergedList.forEach(function (scroller) {
44
+ scroller.removeEventListener('scroll', notifyScroll);
45
+ win.removeEventListener('resize', notifyScroll);
46
+ });
47
+ };
48
+ }
49
+ }, [open, target, popup]);
50
+ }