@rc-component/trigger 1.14.3 → 1.15.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.
@@ -1,4 +1,4 @@
1
1
  import type { ActionType } from '../interface';
2
- declare type ActionTypes = ActionType | ActionType[];
2
+ type ActionTypes = ActionType | ActionType[];
3
3
  export default function useAction(mobile: boolean, action: ActionTypes, showAction?: ActionTypes, hideAction?: ActionTypes): [showAction: Set<ActionType>, hideAction: Set<ActionType>];
4
4
  export {};
@@ -413,7 +413,7 @@ export default function useAlign(open, popupEle, target, placement, builtinPlace
413
413
  if (typeof numShiftY === 'number') {
414
414
  // Top
415
415
  if (nextPopupY < visibleRegionArea.top) {
416
- nextOffsetY -= nextPopupY - visibleRegionArea.top;
416
+ nextOffsetY -= nextPopupY - visibleRegionArea.top + popupOffsetY;
417
417
  if (targetRect.y + targetHeight < visibleRegionArea.top + numShiftY) {
418
418
  nextOffsetY += targetRect.y - visibleRegionArea.top + targetHeight - numShiftY;
419
419
  }
@@ -421,7 +421,7 @@ export default function useAlign(open, popupEle, target, placement, builtinPlace
421
421
 
422
422
  // Bottom
423
423
  if (nextPopupBottom > visibleRegionArea.bottom) {
424
- nextOffsetY -= nextPopupBottom - visibleRegionArea.bottom;
424
+ nextOffsetY -= nextPopupBottom - visibleRegionArea.bottom - popupOffsetY;
425
425
  if (targetRect.y > visibleRegionArea.bottom - numShiftY) {
426
426
  nextOffsetY += targetRect.y - visibleRegionArea.bottom + numShiftY;
427
427
  }
package/es/index.js CHANGED
@@ -12,6 +12,7 @@ import useId from "rc-util/es/hooks/useId";
12
12
  import useLayoutEffect from "rc-util/es/hooks/useLayoutEffect";
13
13
  import isMobile from "rc-util/es/isMobile";
14
14
  import * as React from 'react';
15
+ import { flushSync } from 'react-dom';
15
16
  import TriggerContext from "./context";
16
17
  import useAction from "./hooks/useAction";
17
18
  import useAlign from "./hooks/useAlign";
@@ -159,10 +160,14 @@ export function generateTrigger() {
159
160
  var openRef = React.useRef(mergedOpen);
160
161
  openRef.current = mergedOpen;
161
162
  var internalTriggerOpen = useEvent(function (nextOpen) {
162
- if (mergedOpen !== nextOpen) {
163
- setMergedOpen(nextOpen);
164
- onPopupVisibleChange === null || onPopupVisibleChange === void 0 ? void 0 : onPopupVisibleChange(nextOpen);
165
- }
163
+ // Enter or Pointer will both trigger open state change
164
+ // We only need take one to avoid duplicated change event trigger
165
+ flushSync(function () {
166
+ if (mergedOpen !== nextOpen) {
167
+ setMergedOpen(nextOpen);
168
+ onPopupVisibleChange === null || onPopupVisibleChange === void 0 ? void 0 : onPopupVisibleChange(nextOpen);
169
+ }
170
+ });
166
171
  });
167
172
 
168
173
  // Trigger for delay
@@ -294,8 +299,10 @@ export function generateTrigger() {
294
299
  showActions = _useAction2[0],
295
300
  hideActions = _useAction2[1];
296
301
 
297
- // Util wrapper for trigger action
298
- var wrapperAction = function wrapperAction(eventName, nextOpen, delay, preEvent) {
302
+ /**
303
+ * Util wrapper for trigger action
304
+ */
305
+ function wrapperAction(eventName, nextOpen, delay, preEvent) {
299
306
  cloneProps[eventName] = function (event) {
300
307
  var _originChildProps$eve;
301
308
  preEvent === null || preEvent === void 0 ? void 0 : preEvent(event);
@@ -307,7 +314,7 @@ export function generateTrigger() {
307
314
  }
308
315
  (_originChildProps$eve = originChildProps[eventName]) === null || _originChildProps$eve === void 0 ? void 0 : _originChildProps$eve.call.apply(_originChildProps$eve, [originChildProps, event].concat(args));
309
316
  };
310
- };
317
+ }
311
318
 
312
319
  // ======================= Action: Click ========================
313
320
  var clickToShow = showActions.has('click');
@@ -339,9 +346,13 @@ export function generateTrigger() {
339
346
  var onPopupMouseEnter;
340
347
  var onPopupMouseLeave;
341
348
  if (hoverToShow) {
349
+ // Compatible with old browser which not support pointer event
342
350
  wrapperAction('onMouseEnter', true, mouseEnterDelay, function (event) {
343
351
  setMousePosByEvent(event);
344
352
  });
353
+ wrapperAction('onPointerEnter', true, mouseEnterDelay, function (event) {
354
+ setMousePosByEvent(event);
355
+ });
345
356
  onPopupMouseEnter = function onPopupMouseEnter() {
346
357
  // Only trigger re-open when popup is visible
347
358
  if (mergedOpen || inMotion) {
@@ -360,6 +371,7 @@ export function generateTrigger() {
360
371
  }
361
372
  if (hoverToHide) {
362
373
  wrapperAction('onMouseLeave', false, mouseLeaveDelay);
374
+ wrapperAction('onPointerLeave', false, mouseLeaveDelay);
363
375
  onPopupMouseLeave = function onPopupMouseLeave() {
364
376
  triggerOpen(false, mouseLeaveDelay);
365
377
  };
package/es/interface.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  /// <reference types="react" />
2
2
  import type { CSSMotionProps } from 'rc-motion';
3
- export declare type Placement = 'top' | 'left' | 'right' | 'bottom' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom';
4
- export declare type AlignPointTopBottom = 't' | 'b' | 'c';
5
- export declare type AlignPointLeftRight = 'l' | 'r' | 'c';
3
+ export type Placement = 'top' | 'left' | 'right' | 'bottom' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom';
4
+ export type AlignPointTopBottom = 't' | 'b' | 'c';
5
+ export type AlignPointLeftRight = 'l' | 'r' | 'c';
6
6
  /** Two char of 't' 'b' 'c' 'l' 'r'. Example: 'lt' */
7
- export declare type AlignPoint = `${AlignPointTopBottom}${AlignPointLeftRight}`;
8
- export declare type OffsetType = number | `${number}%`;
7
+ export type AlignPoint = `${AlignPointTopBottom}${AlignPointLeftRight}`;
8
+ export type OffsetType = number | `${number}%`;
9
9
  export interface AlignType {
10
10
  /**
11
11
  * move point of source node to align with point of target node.
@@ -75,15 +75,15 @@ export interface ArrowTypeOuter {
75
75
  className?: string;
76
76
  content?: React.ReactNode;
77
77
  }
78
- export declare type ArrowPos = {
78
+ export type ArrowPos = {
79
79
  x?: number;
80
80
  y?: number;
81
81
  };
82
- export declare type BuildInPlacements = Record<string, AlignType>;
83
- export declare type StretchType = string;
84
- export declare type ActionType = 'hover' | 'focus' | 'click' | 'contextMenu';
85
- export declare type AnimationType = string;
86
- export declare type TransitionNameType = string;
82
+ export type BuildInPlacements = Record<string, AlignType>;
83
+ export type StretchType = string;
84
+ export type ActionType = 'hover' | 'focus' | 'click' | 'contextMenu';
85
+ export type AnimationType = string;
86
+ export type TransitionNameType = string;
87
87
  export interface Point {
88
88
  pageX: number;
89
89
  pageY: number;
@@ -1,4 +1,4 @@
1
1
  import type { ActionType } from '../interface';
2
- declare type ActionTypes = ActionType | ActionType[];
2
+ type ActionTypes = ActionType | ActionType[];
3
3
  export default function useAction(mobile: boolean, action: ActionTypes, showAction?: ActionTypes, hideAction?: ActionTypes): [showAction: Set<ActionType>, hideAction: Set<ActionType>];
4
4
  export {};
@@ -421,7 +421,7 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
421
421
  if (typeof numShiftY === 'number') {
422
422
  // Top
423
423
  if (nextPopupY < visibleRegionArea.top) {
424
- nextOffsetY -= nextPopupY - visibleRegionArea.top;
424
+ nextOffsetY -= nextPopupY - visibleRegionArea.top + popupOffsetY;
425
425
  if (targetRect.y + targetHeight < visibleRegionArea.top + numShiftY) {
426
426
  nextOffsetY += targetRect.y - visibleRegionArea.top + targetHeight - numShiftY;
427
427
  }
@@ -429,7 +429,7 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
429
429
 
430
430
  // Bottom
431
431
  if (nextPopupBottom > visibleRegionArea.bottom) {
432
- nextOffsetY -= nextPopupBottom - visibleRegionArea.bottom;
432
+ nextOffsetY -= nextPopupBottom - visibleRegionArea.bottom - popupOffsetY;
433
433
  if (targetRect.y > visibleRegionArea.bottom - numShiftY) {
434
434
  nextOffsetY += targetRect.y - visibleRegionArea.bottom + numShiftY;
435
435
  }
package/lib/index.js CHANGED
@@ -20,6 +20,7 @@ var _useId = _interopRequireDefault(require("rc-util/lib/hooks/useId"));
20
20
  var _useLayoutEffect = _interopRequireDefault(require("rc-util/lib/hooks/useLayoutEffect"));
21
21
  var _isMobile = _interopRequireDefault(require("rc-util/lib/isMobile"));
22
22
  var React = _interopRequireWildcard(require("react"));
23
+ var _reactDom = require("react-dom");
23
24
  var _context = _interopRequireDefault(require("./context"));
24
25
  var _useAction3 = _interopRequireDefault(require("./hooks/useAction"));
25
26
  var _useAlign3 = _interopRequireDefault(require("./hooks/useAlign"));
@@ -169,10 +170,14 @@ function generateTrigger() {
169
170
  var openRef = React.useRef(mergedOpen);
170
171
  openRef.current = mergedOpen;
171
172
  var internalTriggerOpen = (0, _useEvent.default)(function (nextOpen) {
172
- if (mergedOpen !== nextOpen) {
173
- setMergedOpen(nextOpen);
174
- onPopupVisibleChange === null || onPopupVisibleChange === void 0 ? void 0 : onPopupVisibleChange(nextOpen);
175
- }
173
+ // Enter or Pointer will both trigger open state change
174
+ // We only need take one to avoid duplicated change event trigger
175
+ (0, _reactDom.flushSync)(function () {
176
+ if (mergedOpen !== nextOpen) {
177
+ setMergedOpen(nextOpen);
178
+ onPopupVisibleChange === null || onPopupVisibleChange === void 0 ? void 0 : onPopupVisibleChange(nextOpen);
179
+ }
180
+ });
176
181
  });
177
182
 
178
183
  // Trigger for delay
@@ -304,8 +309,10 @@ function generateTrigger() {
304
309
  showActions = _useAction2[0],
305
310
  hideActions = _useAction2[1];
306
311
 
307
- // Util wrapper for trigger action
308
- var wrapperAction = function wrapperAction(eventName, nextOpen, delay, preEvent) {
312
+ /**
313
+ * Util wrapper for trigger action
314
+ */
315
+ function wrapperAction(eventName, nextOpen, delay, preEvent) {
309
316
  cloneProps[eventName] = function (event) {
310
317
  var _originChildProps$eve;
311
318
  preEvent === null || preEvent === void 0 ? void 0 : preEvent(event);
@@ -317,7 +324,7 @@ function generateTrigger() {
317
324
  }
318
325
  (_originChildProps$eve = originChildProps[eventName]) === null || _originChildProps$eve === void 0 ? void 0 : _originChildProps$eve.call.apply(_originChildProps$eve, [originChildProps, event].concat(args));
319
326
  };
320
- };
327
+ }
321
328
 
322
329
  // ======================= Action: Click ========================
323
330
  var clickToShow = showActions.has('click');
@@ -349,9 +356,13 @@ function generateTrigger() {
349
356
  var onPopupMouseEnter;
350
357
  var onPopupMouseLeave;
351
358
  if (hoverToShow) {
359
+ // Compatible with old browser which not support pointer event
352
360
  wrapperAction('onMouseEnter', true, mouseEnterDelay, function (event) {
353
361
  setMousePosByEvent(event);
354
362
  });
363
+ wrapperAction('onPointerEnter', true, mouseEnterDelay, function (event) {
364
+ setMousePosByEvent(event);
365
+ });
355
366
  onPopupMouseEnter = function onPopupMouseEnter() {
356
367
  // Only trigger re-open when popup is visible
357
368
  if (mergedOpen || inMotion) {
@@ -370,6 +381,7 @@ function generateTrigger() {
370
381
  }
371
382
  if (hoverToHide) {
372
383
  wrapperAction('onMouseLeave', false, mouseLeaveDelay);
384
+ wrapperAction('onPointerLeave', false, mouseLeaveDelay);
373
385
  onPopupMouseLeave = function onPopupMouseLeave() {
374
386
  triggerOpen(false, mouseLeaveDelay);
375
387
  };
@@ -1,11 +1,11 @@
1
1
  /// <reference types="react" />
2
2
  import type { CSSMotionProps } from 'rc-motion';
3
- export declare type Placement = 'top' | 'left' | 'right' | 'bottom' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom';
4
- export declare type AlignPointTopBottom = 't' | 'b' | 'c';
5
- export declare type AlignPointLeftRight = 'l' | 'r' | 'c';
3
+ export type Placement = 'top' | 'left' | 'right' | 'bottom' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom';
4
+ export type AlignPointTopBottom = 't' | 'b' | 'c';
5
+ export type AlignPointLeftRight = 'l' | 'r' | 'c';
6
6
  /** Two char of 't' 'b' 'c' 'l' 'r'. Example: 'lt' */
7
- export declare type AlignPoint = `${AlignPointTopBottom}${AlignPointLeftRight}`;
8
- export declare type OffsetType = number | `${number}%`;
7
+ export type AlignPoint = `${AlignPointTopBottom}${AlignPointLeftRight}`;
8
+ export type OffsetType = number | `${number}%`;
9
9
  export interface AlignType {
10
10
  /**
11
11
  * move point of source node to align with point of target node.
@@ -75,15 +75,15 @@ export interface ArrowTypeOuter {
75
75
  className?: string;
76
76
  content?: React.ReactNode;
77
77
  }
78
- export declare type ArrowPos = {
78
+ export type ArrowPos = {
79
79
  x?: number;
80
80
  y?: number;
81
81
  };
82
- export declare type BuildInPlacements = Record<string, AlignType>;
83
- export declare type StretchType = string;
84
- export declare type ActionType = 'hover' | 'focus' | 'click' | 'contextMenu';
85
- export declare type AnimationType = string;
86
- export declare type TransitionNameType = string;
82
+ export type BuildInPlacements = Record<string, AlignType>;
83
+ export type StretchType = string;
84
+ export type ActionType = 'hover' | 'focus' | 'click' | 'contextMenu';
85
+ export type AnimationType = string;
86
+ export type TransitionNameType = string;
87
87
  export interface Point {
88
88
  pageX: number;
89
89
  pageY: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rc-component/trigger",
3
- "version": "1.14.3",
3
+ "version": "1.15.0",
4
4
  "description": "base abstract trigger component for react",
5
5
  "engines": {
6
6
  "node": ">=8.x"