@fluentui/react-positioning 9.0.0-alpha.6 → 9.0.0-alpha.60

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 (118) hide show
  1. package/CHANGELOG.json +1116 -1
  2. package/CHANGELOG.md +520 -2
  3. package/dist/react-positioning.d.ts +72 -27
  4. package/lib/createVirtualElementFromClick.d.ts +6 -0
  5. package/lib/createVirtualElementFromClick.js +24 -0
  6. package/lib/createVirtualElementFromClick.js.map +1 -0
  7. package/lib/index.d.ts +3 -0
  8. package/lib/index.js +4 -0
  9. package/lib/index.js.map +1 -1
  10. package/lib/tsdoc-metadata.json +1 -1
  11. package/lib/types.d.ts +22 -27
  12. package/lib/types.js +1 -0
  13. package/lib/types.js.map +1 -1
  14. package/lib/usePopper.d.ts +21 -1
  15. package/lib/usePopper.js +67 -29
  16. package/lib/usePopper.js.map +1 -1
  17. package/lib/usePopperMouseTarget.d.ts +11 -0
  18. package/lib/usePopperMouseTarget.js +34 -0
  19. package/lib/usePopperMouseTarget.js.map +1 -0
  20. package/lib/utils/getBasePlacement.d.ts +8 -0
  21. package/lib/utils/getBasePlacement.js +10 -0
  22. package/lib/utils/getBasePlacement.js.map +1 -0
  23. package/lib/utils/getBoundary.d.ts +1 -1
  24. package/lib/utils/getBoundary.js +2 -3
  25. package/lib/utils/getBoundary.js.map +1 -1
  26. package/lib/utils/getReactFiberFromNode.js.map +1 -1
  27. package/lib/utils/getScrollParent.js.map +1 -1
  28. package/lib/utils/index.d.ts +5 -3
  29. package/lib/utils/index.js +5 -3
  30. package/lib/utils/index.js.map +1 -1
  31. package/lib/utils/mergeArrowOffset.d.ts +10 -0
  32. package/lib/utils/mergeArrowOffset.js +37 -0
  33. package/lib/utils/mergeArrowOffset.js.map +1 -0
  34. package/lib/utils/positioningHelper.d.ts +2 -2
  35. package/lib/utils/positioningHelper.js.map +1 -1
  36. package/lib/utils/resolvePositioningShorthand.d.ts +2 -0
  37. package/lib/utils/resolvePositioningShorthand.js +25 -0
  38. package/lib/utils/resolvePositioningShorthand.js.map +1 -0
  39. package/lib/utils/useCallbackRef.js.map +1 -1
  40. package/lib-commonjs/createVirtualElementFromClick.d.ts +6 -0
  41. package/lib-commonjs/createVirtualElementFromClick.js +28 -0
  42. package/lib-commonjs/createVirtualElementFromClick.js.map +1 -0
  43. package/lib-commonjs/index.d.ts +3 -0
  44. package/lib-commonjs/index.js +7 -0
  45. package/lib-commonjs/index.js.map +1 -1
  46. package/lib-commonjs/types.d.ts +22 -27
  47. package/lib-commonjs/types.js.map +1 -1
  48. package/lib-commonjs/usePopper.d.ts +21 -1
  49. package/lib-commonjs/usePopper.js +67 -28
  50. package/lib-commonjs/usePopper.js.map +1 -1
  51. package/lib-commonjs/usePopperMouseTarget.d.ts +11 -0
  52. package/lib-commonjs/usePopperMouseTarget.js +38 -0
  53. package/lib-commonjs/usePopperMouseTarget.js.map +1 -0
  54. package/lib-commonjs/utils/getBasePlacement.d.ts +8 -0
  55. package/lib-commonjs/utils/getBasePlacement.js +14 -0
  56. package/lib-commonjs/utils/getBasePlacement.js.map +1 -0
  57. package/lib-commonjs/utils/getBoundary.d.ts +1 -1
  58. package/lib-commonjs/utils/getBoundary.js +3 -3
  59. package/lib-commonjs/utils/getBoundary.js.map +1 -1
  60. package/lib-commonjs/utils/getReactFiberFromNode.js +1 -0
  61. package/lib-commonjs/utils/getReactFiberFromNode.js.map +1 -1
  62. package/lib-commonjs/utils/getScrollParent.js +5 -2
  63. package/lib-commonjs/utils/getScrollParent.js.map +1 -1
  64. package/lib-commonjs/utils/index.d.ts +5 -3
  65. package/lib-commonjs/utils/index.js +5 -3
  66. package/lib-commonjs/utils/index.js.map +1 -1
  67. package/lib-commonjs/utils/mergeArrowOffset.d.ts +10 -0
  68. package/lib-commonjs/utils/mergeArrowOffset.js +41 -0
  69. package/lib-commonjs/utils/mergeArrowOffset.js.map +1 -0
  70. package/lib-commonjs/utils/positioningHelper.d.ts +2 -2
  71. package/lib-commonjs/utils/positioningHelper.js +5 -2
  72. package/lib-commonjs/utils/positioningHelper.js.map +1 -1
  73. package/lib-commonjs/utils/resolvePositioningShorthand.d.ts +2 -0
  74. package/lib-commonjs/utils/resolvePositioningShorthand.js +29 -0
  75. package/lib-commonjs/utils/resolvePositioningShorthand.js.map +1 -0
  76. package/lib-commonjs/utils/useCallbackRef.js +1 -0
  77. package/lib-commonjs/utils/useCallbackRef.js.map +1 -1
  78. package/package.json +11 -8
  79. package/NOTICE.txt +0 -0
  80. package/config/api-extractor.json +0 -3
  81. package/etc/react-positioning.api.md +0 -69
  82. package/just.config.ts +0 -3
  83. package/lib/utils/isBrowser.d.ts +0 -1
  84. package/lib/utils/isBrowser.js +0 -4
  85. package/lib/utils/isBrowser.js.map +0 -1
  86. package/lib-amd/index.d.ts +0 -2
  87. package/lib-amd/index.js +0 -6
  88. package/lib-amd/index.js.map +0 -1
  89. package/lib-amd/types.d.ts +0 -73
  90. package/lib-amd/types.js +0 -5
  91. package/lib-amd/types.js.map +0 -1
  92. package/lib-amd/usePopper.d.ts +0 -15
  93. package/lib-amd/usePopper.js +0 -280
  94. package/lib-amd/usePopper.js.map +0 -1
  95. package/lib-amd/utils/getBoundary.d.ts +0 -6
  96. package/lib-amd/utils/getBoundary.js +0 -23
  97. package/lib-amd/utils/getBoundary.js.map +0 -1
  98. package/lib-amd/utils/getReactFiberFromNode.d.ts +0 -109
  99. package/lib-amd/utils/getReactFiberFromNode.js +0 -47
  100. package/lib-amd/utils/getReactFiberFromNode.js.map +0 -1
  101. package/lib-amd/utils/getScrollParent.d.ts +0 -12
  102. package/lib-amd/utils/getScrollParent.js +0 -55
  103. package/lib-amd/utils/getScrollParent.js.map +0 -1
  104. package/lib-amd/utils/index.d.ts +0 -6
  105. package/lib-amd/utils/index.js +0 -11
  106. package/lib-amd/utils/index.js.map +0 -1
  107. package/lib-amd/utils/isBrowser.d.ts +0 -1
  108. package/lib-amd/utils/isBrowser.js +0 -8
  109. package/lib-amd/utils/isBrowser.js.map +0 -1
  110. package/lib-amd/utils/positioningHelper.d.ts +0 -7
  111. package/lib-amd/utils/positioningHelper.js +0 -45
  112. package/lib-amd/utils/positioningHelper.js.map +0 -1
  113. package/lib-amd/utils/useCallbackRef.d.ts +0 -19
  114. package/lib-amd/utils/useCallbackRef.js +0 -54
  115. package/lib-amd/utils/useCallbackRef.js.map +0 -1
  116. package/lib-commonjs/utils/isBrowser.d.ts +0 -1
  117. package/lib-commonjs/utils/isBrowser.js +0 -6
  118. package/lib-commonjs/utils/isBrowser.js.map +0 -1
@@ -1,10 +1,28 @@
1
1
  import * as PopperJs from '@popperjs/core';
2
- import * as React from 'react';
2
+ import * as React_2 from 'react';
3
3
 
4
4
  export declare type Alignment = 'top' | 'bottom' | 'start' | 'end' | 'center';
5
5
 
6
+ export declare type AutoSize = 'height' | 'height-always' | 'width' | 'width-always' | 'always' | boolean;
7
+
6
8
  export declare type Boundary = PopperJs.Boundary | 'scrollParent' | 'window';
7
9
 
10
+ /**
11
+ * Creates a virtual element based on the position of a click event
12
+ * Can be used as a target for popper in scenarios such as context menus
13
+ */
14
+ export declare function createVirtualElementFromClick(nativeEvent: MouseEvent): PopperVirtualElement;
15
+
16
+ /**
17
+ * Generally when adding an arrow to popper, it's necessary to offset the position of the popper by the
18
+ * height of the arrow. A simple utility to merge a provided offset with an arrow height to return the final offset
19
+ *
20
+ * @param userOffset - The offset provided by the user
21
+ * @param arrowHeight - The height of the arrow in px
22
+ * @returns User offset augmented with arrow height
23
+ */
24
+ export declare function mergeArrowOffset(userOffset: Offset | undefined | null, arrowHeight: number): Offset;
25
+
8
26
  export declare type Offset = OffsetFunction | [number | null | undefined, number | null | undefined];
9
27
 
10
28
  export declare type OffsetFunction = (param: OffsetFunctionParam) => [number | null | undefined, number | null | undefined];
@@ -15,36 +33,42 @@ export declare type OffsetFunctionParam = {
15
33
  placement: PopperJs.Placement;
16
34
  };
17
35
 
18
- export declare interface PopperOptions extends PositioningProps {
36
+ declare interface PopperOptions extends PositioningProps {
19
37
  /**
20
38
  * If false, delays Popper's creation.
21
39
  * @default true
22
40
  */
23
41
  enabled?: boolean;
42
+ onStateUpdate?: (state: Partial<PopperJs.State>) => void;
24
43
  /**
25
- * Array of conditions to be met in order to trigger a subsequent render to reposition the elements.
44
+ * Enables the Popper box to position itself in 'fixed' mode (default value is position: 'absolute')
45
+ * @default false
26
46
  */
27
- positioningDependencies?: React.DependencyList;
28
- onStateUpdate?: (state: Partial<PopperJs.State>) => void;
47
+ positionFixed?: boolean;
48
+ /**
49
+ * When the reference element or the viewport is outside viewport allows a popper element to be fully in viewport.
50
+ * "all" enables this behavior for all axis.
51
+ */
52
+ unstable_disableTether?: boolean | 'all';
29
53
  }
30
54
 
31
55
  export declare type PopperRefHandle = {
32
56
  updatePosition: () => void;
33
57
  };
34
58
 
59
+ export declare type PopperVirtualElement = PopperJs.VirtualElement;
60
+
35
61
  export declare type Position = 'above' | 'below' | 'before' | 'after';
36
62
 
37
63
  export declare interface PositioningProps {
38
- /**
39
- * Alignment for the component.
40
- */
64
+ /** Alignment for the component. Only has an effect if used with the @see position option */
41
65
  align?: Alignment;
42
66
  /** The element which will define the boundaries of the popper position for the flip behavior. */
43
67
  flipBoundary?: Boundary;
44
68
  /** The element which will define the boundaries of the popper position for the overflow behavior. */
45
69
  overflowBoundary?: Boundary;
46
70
  /** An imperative handle to Popper methods. */
47
- containerRef?: React.Ref<PopperRefHandle>;
71
+ popperRef?: React_2.Ref<PopperRefHandle>;
48
72
  /**
49
73
  * Position for the component. Position has higher priority than align. If position is vertical ('above' | 'below')
50
74
  * and align is also vertical ('top' | 'bottom') or if both position and align are horizontal ('before' | 'after'
@@ -52,11 +76,6 @@ export declare interface PositioningProps {
52
76
  * then provided value for 'align' will be ignored and 'center' will be used instead.
53
77
  */
54
78
  position?: Position;
55
- /**
56
- * Enables the Popper box to position itself in 'fixed' mode (default value is position: 'absolute')
57
- * @default false
58
- */
59
- positionFixed?: boolean;
60
79
  /**
61
80
  * Lets you displace a popper element from its reference element.
62
81
  * This can be useful if you need to apply some margin between them or if you need to fine tune the
@@ -64,23 +83,39 @@ export declare interface PositioningProps {
64
83
  */
65
84
  offset?: Offset;
66
85
  /**
67
- * When the reference element or the viewport is outside viewport allows a popper element to be fully in viewport.
68
- * "all" enables this behavior for all axis.
86
+ * Defines padding between the corner of the popup element and the arrow.
87
+ * Use to prevent the arrow from overlapping a rounded corner, for example.
69
88
  */
70
- unstable_disableTether?: boolean | 'all';
89
+ arrowPadding?: number;
71
90
  /**
72
- * Disables automatic repositioning of the component; it will always be placed according to the values of `align` and
73
- * `position` props, regardless of the size of the component, the reference element or the viewport.
91
+ * Applies max-height and max-width on popper to fit it within the available space in viewport.
92
+ * true enables this for both width and height when overflow happens.
93
+ * 'always' applies `max-height`/`max-width` regardless of overflow.
94
+ * 'height' applies `max-height` when overflow happens, and 'width' for `max-width`
95
+ * `height-always` applies `max-height` regardless of overflow, and 'width-always' for always applying `max-width`
74
96
  */
75
- unstable_pinned?: boolean;
97
+ autoSize?: AutoSize;
76
98
  /**
77
- * Applies max-height and max-width on popper to fit it within the available space in viewport.
78
- * true enables this for both width and height.
79
- * 'height' applies only `max-height` and 'width' for `max-width`
99
+ * Manual override for popper target. Useful for scenarios where a component accepts user prop to override target
100
+ */
101
+ target?: HTMLElement | PopperVirtualElement | null;
102
+ /**
103
+ * Modifies position and alignment to cover the target
104
+ */
105
+ coverTarget?: boolean;
106
+ /**
107
+ * Disables automatic repositioning of the component; it will always be placed according to the values of `align` and
108
+ * `position` props, regardless of the size of the component, the reference element or the viewport.
80
109
  */
81
- autoSize?: 'height' | 'width' | boolean;
110
+ pinned?: boolean;
82
111
  }
83
112
 
113
+ export declare type PositioningShorthand = PositioningProps | PositioningShorthandValue;
114
+
115
+ export declare type PositioningShorthandValue = 'above' | 'above-start' | 'above-end' | 'below' | 'below-start' | 'below-end' | 'before' | 'before-top' | 'before-bottom' | 'after' | 'after-top' | 'after-bottom';
116
+
117
+ export declare function resolvePositioningShorthand(shorthand: PositioningShorthand | undefined | null): Readonly<PositioningProps>;
118
+
84
119
  /**
85
120
  * Exposes Popper positioning API via React hook. Contains few important differences between an official "react-popper"
86
121
  * package:
@@ -90,9 +125,19 @@ export declare interface PositioningProps {
90
125
  * to avoid focus jumps
91
126
  */
92
127
  export declare function usePopper(options?: PopperOptions): {
93
- targetRef: React.MutableRefObject<any>;
94
- containerRef: React.MutableRefObject<any>;
95
- arrowRef: React.MutableRefObject<any>;
128
+ targetRef: React_2.MutableRefObject<any>;
129
+ containerRef: React_2.MutableRefObject<any>;
130
+ arrowRef: React_2.MutableRefObject<any>;
96
131
  };
97
132
 
133
+ /**
134
+ * A state hook that manages a popper virtual element from mouseevents.
135
+ * Useful for scenarios where a component needs to be positioned by mouse click (e.g. contextmenu)
136
+ * React synthetic events are not persisted by this hook
137
+ *
138
+ * @param initialState - initializes a user provided state similare to useState
139
+ * @returns state and dispatcher for a Popper virtual element that uses native/synthetic mouse events
140
+ */
141
+ export declare const usePopperMouseTarget: (initialState?: PopperJs.VirtualElement | (() => PopperJs.VirtualElement) | undefined) => readonly [PopperJs.VirtualElement | undefined, (event: React_2.MouseEvent | MouseEvent | undefined | null) => void];
142
+
98
143
  export { }
@@ -0,0 +1,6 @@
1
+ import type { PopperVirtualElement } from './types';
2
+ /**
3
+ * Creates a virtual element based on the position of a click event
4
+ * Can be used as a target for popper in scenarios such as context menus
5
+ */
6
+ export declare function createVirtualElementFromClick(nativeEvent: MouseEvent): PopperVirtualElement;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Creates a virtual element based on the position of a click event
3
+ * Can be used as a target for popper in scenarios such as context menus
4
+ */
5
+ export function createVirtualElementFromClick(nativeEvent) {
6
+ var left = nativeEvent.clientX;
7
+ var top = nativeEvent.clientY;
8
+ var right = left + 1;
9
+ var bottom = top + 1;
10
+ function getBoundingClientRect() {
11
+ return {
12
+ left: left,
13
+ top: top,
14
+ right: right,
15
+ bottom: bottom,
16
+ height: 1,
17
+ width: 1,
18
+ };
19
+ }
20
+ return {
21
+ getBoundingClientRect: getBoundingClientRect,
22
+ };
23
+ }
24
+ //# sourceMappingURL=createVirtualElementFromClick.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createVirtualElementFromClick.js","sourceRoot":"","sources":["../src/createVirtualElementFromClick.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAAC,WAAuB;IACnE,IAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC;IACjC,IAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC;IAChC,IAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC;IACvB,IAAM,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC;IAEvB,SAAS,qBAAqB;QAC5B,OAAO;YACL,IAAI,MAAA;YACJ,GAAG,KAAA;YACH,KAAK,OAAA;YACL,MAAM,QAAA;YAEN,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,CAAC;SACT,CAAC;IACJ,CAAC;IAED,OAAO;QACL,qBAAqB,uBAAA;KACtB,CAAC;AACJ,CAAC"}
package/lib/index.d.ts CHANGED
@@ -1,2 +1,5 @@
1
1
  export * from './usePopper';
2
+ export * from './createVirtualElementFromClick';
3
+ export * from './usePopperMouseTarget';
4
+ export { resolvePositioningShorthand, mergeArrowOffset } from './utils/index';
2
5
  export * from './types';
package/lib/index.js CHANGED
@@ -1,2 +1,6 @@
1
1
  export * from './usePopper';
2
+ export * from './createVirtualElementFromClick';
3
+ export * from './usePopperMouseTarget';
4
+ export { resolvePositioningShorthand, mergeArrowOffset } from './utils/index';
5
+ export * from './types';
2
6
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"../src/","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC","sourcesContent":["export * from './usePopper';\nexport * from './types';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,OAAO,EAAE,2BAA2B,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC9E,cAAc,SAAS,CAAC"}
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.7.1"
8
+ "packageVersion": "7.18.1"
9
9
  }
10
10
  ]
11
11
  }
package/lib/types.d.ts CHANGED
@@ -9,21 +9,21 @@ export declare type OffsetFunction = (param: OffsetFunctionParam) => [number | n
9
9
  export declare type Offset = OffsetFunction | [number | null | undefined, number | null | undefined];
10
10
  export declare type Position = 'above' | 'below' | 'before' | 'after';
11
11
  export declare type Alignment = 'top' | 'bottom' | 'start' | 'end' | 'center';
12
+ export declare type AutoSize = 'height' | 'height-always' | 'width' | 'width-always' | 'always' | boolean;
12
13
  export declare type Boundary = PopperJs.Boundary | 'scrollParent' | 'window';
13
14
  export declare type PopperRefHandle = {
14
15
  updatePosition: () => void;
15
16
  };
17
+ export declare type PopperVirtualElement = PopperJs.VirtualElement;
16
18
  export interface PositioningProps {
17
- /**
18
- * Alignment for the component.
19
- */
19
+ /** Alignment for the component. Only has an effect if used with the @see position option */
20
20
  align?: Alignment;
21
21
  /** The element which will define the boundaries of the popper position for the flip behavior. */
22
22
  flipBoundary?: Boundary;
23
23
  /** The element which will define the boundaries of the popper position for the overflow behavior. */
24
24
  overflowBoundary?: Boundary;
25
25
  /** An imperative handle to Popper methods. */
26
- containerRef?: React.Ref<PopperRefHandle>;
26
+ popperRef?: React.Ref<PopperRefHandle>;
27
27
  /**
28
28
  * Position for the component. Position has higher priority than align. If position is vertical ('above' | 'below')
29
29
  * and align is also vertical ('top' | 'bottom') or if both position and align are horizontal ('before' | 'after'
@@ -31,11 +31,6 @@ export interface PositioningProps {
31
31
  * then provided value for 'align' will be ignored and 'center' will be used instead.
32
32
  */
33
33
  position?: Position;
34
- /**
35
- * Enables the Popper box to position itself in 'fixed' mode (default value is position: 'absolute')
36
- * @default false
37
- */
38
- positionFixed?: boolean;
39
34
  /**
40
35
  * Lets you displace a popper element from its reference element.
41
36
  * This can be useful if you need to apply some margin between them or if you need to fine tune the
@@ -43,31 +38,31 @@ export interface PositioningProps {
43
38
  */
44
39
  offset?: Offset;
45
40
  /**
46
- * When the reference element or the viewport is outside viewport allows a popper element to be fully in viewport.
47
- * "all" enables this behavior for all axis.
41
+ * Defines padding between the corner of the popup element and the arrow.
42
+ * Use to prevent the arrow from overlapping a rounded corner, for example.
48
43
  */
49
- unstable_disableTether?: boolean | 'all';
44
+ arrowPadding?: number;
50
45
  /**
51
- * Disables automatic repositioning of the component; it will always be placed according to the values of `align` and
52
- * `position` props, regardless of the size of the component, the reference element or the viewport.
46
+ * Applies max-height and max-width on popper to fit it within the available space in viewport.
47
+ * true enables this for both width and height when overflow happens.
48
+ * 'always' applies `max-height`/`max-width` regardless of overflow.
49
+ * 'height' applies `max-height` when overflow happens, and 'width' for `max-width`
50
+ * `height-always` applies `max-height` regardless of overflow, and 'width-always' for always applying `max-width`
53
51
  */
54
- unstable_pinned?: boolean;
52
+ autoSize?: AutoSize;
55
53
  /**
56
- * Applies max-height and max-width on popper to fit it within the available space in viewport.
57
- * true enables this for both width and height.
58
- * 'height' applies only `max-height` and 'width' for `max-width`
54
+ * Manual override for popper target. Useful for scenarios where a component accepts user prop to override target
59
55
  */
60
- autoSize?: 'height' | 'width' | boolean;
61
- }
62
- export interface PopperOptions extends PositioningProps {
56
+ target?: HTMLElement | PopperVirtualElement | null;
63
57
  /**
64
- * If false, delays Popper's creation.
65
- * @default true
58
+ * Modifies position and alignment to cover the target
66
59
  */
67
- enabled?: boolean;
60
+ coverTarget?: boolean;
68
61
  /**
69
- * Array of conditions to be met in order to trigger a subsequent render to reposition the elements.
62
+ * Disables automatic repositioning of the component; it will always be placed according to the values of `align` and
63
+ * `position` props, regardless of the size of the component, the reference element or the viewport.
70
64
  */
71
- positioningDependencies?: React.DependencyList;
72
- onStateUpdate?: (state: Partial<PopperJs.State>) => void;
65
+ pinned?: boolean;
73
66
  }
67
+ export declare type PositioningShorthandValue = 'above' | 'above-start' | 'above-end' | 'below' | 'below-start' | 'below-end' | 'before' | 'before-top' | 'before-bottom' | 'after' | 'after-top' | 'after-bottom';
68
+ export declare type PositioningShorthand = PositioningProps | PositioningShorthandValue;
package/lib/types.js CHANGED
@@ -1 +1,2 @@
1
+ export {};
1
2
  //# sourceMappingURL=types.js.map
package/lib/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"../src/","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import * as PopperJs from '@popperjs/core';\nimport * as React from 'react';\n\nexport type OffsetFunctionParam = {\n popper: PopperJs.Rect;\n reference: PopperJs.Rect;\n placement: PopperJs.Placement;\n};\n\nexport type OffsetFunction = (param: OffsetFunctionParam) => [number | null | undefined, number | null | undefined];\n\nexport type Offset = OffsetFunction | [number | null | undefined, number | null | undefined];\n\nexport type Position = 'above' | 'below' | 'before' | 'after';\nexport type Alignment = 'top' | 'bottom' | 'start' | 'end' | 'center';\n\nexport type Boundary = PopperJs.Boundary | 'scrollParent' | 'window';\n\nexport type PopperRefHandle = { updatePosition: () => void };\n\nexport interface PositioningProps {\n /**\n * Alignment for the component.\n */\n align?: Alignment;\n\n /** The element which will define the boundaries of the popper position for the flip behavior. */\n flipBoundary?: Boundary;\n\n /** The element which will define the boundaries of the popper position for the overflow behavior. */\n overflowBoundary?: Boundary;\n\n /** An imperative handle to Popper methods. */\n containerRef?: React.Ref<PopperRefHandle>;\n\n /**\n * Position for the component. Position has higher priority than align. If position is vertical ('above' | 'below')\n * and align is also vertical ('top' | 'bottom') or if both position and align are horizontal ('before' | 'after'\n * and 'start' | 'end' respectively),\n * then provided value for 'align' will be ignored and 'center' will be used instead.\n */\n position?: Position;\n\n /**\n * Enables the Popper box to position itself in 'fixed' mode (default value is position: 'absolute')\n * @default false\n */\n positionFixed?: boolean;\n\n /**\n * Lets you displace a popper element from its reference element.\n * This can be useful if you need to apply some margin between them or if you need to fine tune the\n * position according to some custom logic.\n */\n offset?: Offset;\n\n /**\n * When the reference element or the viewport is outside viewport allows a popper element to be fully in viewport.\n * \"all\" enables this behavior for all axis.\n */\n // eslint-disable-next-line @typescript-eslint/naming-convention\n unstable_disableTether?: boolean | 'all';\n\n /**\n * Disables automatic repositioning of the component; it will always be placed according to the values of `align` and\n * `position` props, regardless of the size of the component, the reference element or the viewport.\n */\n // eslint-disable-next-line @typescript-eslint/naming-convention\n unstable_pinned?: boolean;\n\n /**\n * Applies max-height and max-width on popper to fit it within the available space in viewport.\n * true enables this for both width and height.\n * 'height' applies only `max-height` and 'width' for `max-width`\n */\n autoSize?: 'height' | 'width' | boolean;\n}\n\nexport interface PopperOptions extends PositioningProps {\n /**\n * If false, delays Popper's creation.\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Array of conditions to be met in order to trigger a subsequent render to reposition the elements.\n */\n positioningDependencies?: React.DependencyList;\n\n onStateUpdate?: (state: Partial<PopperJs.State>) => void;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -1,5 +1,24 @@
1
+ import * as PopperJs from '@popperjs/core';
1
2
  import * as React from 'react';
2
- import { PopperOptions } from './types';
3
+ import type { PositioningProps } from './types';
4
+ interface PopperOptions extends PositioningProps {
5
+ /**
6
+ * If false, delays Popper's creation.
7
+ * @default true
8
+ */
9
+ enabled?: boolean;
10
+ onStateUpdate?: (state: Partial<PopperJs.State>) => void;
11
+ /**
12
+ * Enables the Popper box to position itself in 'fixed' mode (default value is position: 'absolute')
13
+ * @default false
14
+ */
15
+ positionFixed?: boolean;
16
+ /**
17
+ * When the reference element or the viewport is outside viewport allows a popper element to be fully in viewport.
18
+ * "all" enables this behavior for all axis.
19
+ */
20
+ unstable_disableTether?: boolean | 'all';
21
+ }
3
22
  /**
4
23
  * Exposes Popper positioning API via React hook. Contains few important differences between an official "react-popper"
5
24
  * package:
@@ -13,3 +32,4 @@ export declare function usePopper(options?: PopperOptions): {
13
32
  containerRef: React.MutableRefObject<any>;
14
33
  arrowRef: React.MutableRefObject<any>;
15
34
  };
35
+ export {};
package/lib/usePopper.js CHANGED
@@ -1,6 +1,6 @@
1
- import { useEventCallback, useIsomorphicLayoutEffect, useFirstMount } from '@fluentui/react-utilities';
2
- import { useFluent } from '@fluentui/react-provider';
3
- import { isBrowser, getScrollParent, applyRtlToOffset, getPlacement, getReactFiberFromNode, getBoundary, useCallbackRef, } from './utils/index';
1
+ import { useEventCallback, useIsomorphicLayoutEffect, useFirstMount, canUseDOM } from '@fluentui/react-utilities';
2
+ import { useFluent } from '@fluentui/react-shared-contexts';
3
+ import { getScrollParent, applyRtlToOffset, getPlacement, getReactFiberFromNode, getBoundary, useCallbackRef, getBasePlacement, } from './utils/index';
4
4
  import * as PopperJs from '@popperjs/core';
5
5
  import * as React from 'react';
6
6
  //
@@ -33,11 +33,9 @@ function hasAutofocusFilter(node) {
33
33
  * that can't be resolved properly during an initial rendering.
34
34
  */
35
35
  function usePopperOptions(options, popperOriginalPositionRef) {
36
- var autoSize = options.autoSize, flipBoundary = options.flipBoundary, offset = options.offset, onStateUpdate = options.onStateUpdate, overflowBoundary = options.overflowBoundary,
36
+ var arrowPadding = options.arrowPadding, autoSize = options.autoSize, coverTarget = options.coverTarget, flipBoundary = options.flipBoundary, offset = options.offset, onStateUpdate = options.onStateUpdate, overflowBoundary = options.overflowBoundary,
37
37
  // eslint-disable-next-line @typescript-eslint/naming-convention
38
- unstable_disableTether = options.unstable_disableTether,
39
- // eslint-disable-next-line @typescript-eslint/naming-convention
40
- unstable_pinned = options.unstable_pinned;
38
+ unstable_disableTether = options.unstable_disableTether, pinned = options.pinned;
41
39
  var isRtl = useFluent().dir === 'rtl';
42
40
  var placement = getPlacement(options.align, options.position, isRtl);
43
41
  var strategy = options.positionFixed ? 'fixed' : 'absolute';
@@ -85,12 +83,12 @@ function usePopperOptions(options, popperOriginalPositionRef) {
85
83
  },
86
84
  { name: 'flip', options: { flipVariations: true } },
87
85
  /**
88
- * unstable_pinned disables the flip modifier by setting flip.enabled to false; this
86
+ * pinned disables the flip modifier by setting flip.enabled to false; this
89
87
  * disables automatic repositioning of the popper box; it will always be placed according to
90
88
  * the values of `align` and `position` props, regardless of the size of the component, the
91
89
  * reference element or the viewport.
92
90
  */
93
- unstable_pinned && { name: 'flip', enabled: false },
91
+ pinned && { name: 'flip', enabled: false },
94
92
  /**
95
93
  * When the popper box is placed in the context of a scrollable element, we need to set
96
94
  * preventOverflow.escapeWithReference to true and flip.boundariesElement to 'scrollParent'
@@ -129,12 +127,12 @@ function usePopperOptions(options, popperOriginalPositionRef) {
129
127
  phase: 'afterWrite',
130
128
  fn: handleStateUpdate,
131
129
  },
132
- autoSize && {
130
+ {
133
131
  // Similar code as popper-maxsize-modifier: https://github.com/atomiks/popper.js/blob/master/src/modifiers/maxSize.js
134
132
  // popper-maxsize-modifier only calculates the max sizes.
135
- // This modifier applies the max sizes when overflow is detected
133
+ // This modifier can apply max sizes always, or apply the max sizes only when overflow is detected
136
134
  name: 'applyMaxSize',
137
- enabled: true,
135
+ enabled: !!autoSize,
138
136
  phase: 'beforeWrite',
139
137
  requiresIfExists: ['offset', 'preventOverflow', 'flip'],
140
138
  options: {
@@ -146,13 +144,19 @@ function usePopperOptions(options, popperOriginalPositionRef) {
146
144
  var overflow = PopperJs.detectOverflow(state, modifierOptions);
147
145
  var _b = state.modifiersData.preventOverflow || { x: 0, y: 0 }, x = _b.x, y = _b.y;
148
146
  var _c = state.rects.popper, width = _c.width, height = _c.height;
149
- var basePlacement = state.placement.split('-')[0];
147
+ var basePlacement = getBasePlacement(state.placement);
150
148
  var widthProp = basePlacement === 'left' ? 'left' : 'right';
151
149
  var heightProp = basePlacement === 'top' ? 'top' : 'bottom';
152
- if (overflow[widthProp] > 0 && (autoSize === true || autoSize === 'width')) {
150
+ var applyMaxWidth = autoSize === 'always' ||
151
+ autoSize === 'width-always' ||
152
+ (overflow[widthProp] > 0 && (autoSize === true || autoSize === 'width'));
153
+ var applyMaxHeight = autoSize === 'always' ||
154
+ autoSize === 'height-always' ||
155
+ (overflow[heightProp] > 0 && (autoSize === true || autoSize === 'height'));
156
+ if (applyMaxWidth) {
153
157
  state.styles.popper.maxWidth = width - overflow[widthProp] - x + "px";
154
158
  }
155
- if (overflow[heightProp] > 0 && (autoSize === true || autoSize === 'height')) {
159
+ if (applyMaxHeight) {
156
160
  state.styles.popper.maxHeight = height - overflow[heightProp] - y + "px";
157
161
  }
158
162
  },
@@ -164,7 +168,34 @@ function usePopperOptions(options, popperOriginalPositionRef) {
164
168
  {
165
169
  name: 'arrow',
166
170
  enabled: !!arrow,
167
- options: { element: arrow },
171
+ options: { element: arrow, padding: arrowPadding },
172
+ },
173
+ /**
174
+ * Modifies popper offsets to cover the reference rect, but still keep edge alignment
175
+ */
176
+ {
177
+ name: 'coverTarget',
178
+ enabled: !!coverTarget,
179
+ phase: 'main',
180
+ requiresIfExists: ['offset', 'preventOverflow', 'flip'],
181
+ fn: function (_a) {
182
+ var state = _a.state;
183
+ var basePlacement = getBasePlacement(state.placement);
184
+ switch (basePlacement) {
185
+ case 'bottom':
186
+ state.modifiersData.popperOffsets.y -= state.rects.reference.height;
187
+ break;
188
+ case 'top':
189
+ state.modifiersData.popperOffsets.y += state.rects.reference.height;
190
+ break;
191
+ case 'left':
192
+ state.modifiersData.popperOffsets.x += state.rects.reference.width;
193
+ break;
194
+ case 'right':
195
+ state.modifiersData.popperOffsets.x -= state.rects.reference.width;
196
+ break;
197
+ }
198
+ },
168
199
  },
169
200
  ].filter(Boolean); // filter boolean conditional spreading values
170
201
  var popperOptions = {
@@ -175,14 +206,16 @@ function usePopperOptions(options, popperOriginalPositionRef) {
175
206
  };
176
207
  return popperOptions;
177
208
  }, [
209
+ arrowPadding,
178
210
  autoSize,
211
+ coverTarget,
179
212
  flipBoundary,
180
213
  offsetModifier,
181
214
  overflowBoundary,
182
215
  placement,
183
216
  strategy,
184
217
  unstable_disableTether,
185
- unstable_pinned,
218
+ pinned,
186
219
  // These can be skipped from deps as they will not ever change
187
220
  handleStateUpdate,
188
221
  popperOriginalPositionRef,
@@ -207,10 +240,11 @@ export function usePopper(options) {
207
240
  var _a;
208
241
  (_a = popperInstanceRef.current) === null || _a === void 0 ? void 0 : _a.destroy();
209
242
  popperInstanceRef.current = null;
243
+ var _b = options.target, target = _b === void 0 ? targetRef.current : _b;
210
244
  var popperInstance = null;
211
- if (isBrowser() && enabled) {
212
- if (targetRef.current && containerRef.current) {
213
- popperInstance = PopperJs.createPopper(targetRef.current, containerRef.current, resolvePopperOptions(targetRef.current, containerRef.current, arrowRef.current));
245
+ if (canUseDOM() && enabled) {
246
+ if (target && containerRef.current) {
247
+ popperInstance = PopperJs.createPopper(target, containerRef.current, resolvePopperOptions(target, containerRef.current, arrowRef.current));
214
248
  }
215
249
  }
216
250
  if (popperInstance) {
@@ -221,8 +255,7 @@ export function usePopper(options) {
221
255
  var originalForceUpdate_1 = popperInstance.forceUpdate;
222
256
  popperInstance.isFirstRun = true;
223
257
  popperInstance.forceUpdate = function () {
224
- var _a;
225
- if ((_a = popperInstance) === null || _a === void 0 ? void 0 : _a.isFirstRun) {
258
+ if (popperInstance === null || popperInstance === void 0 ? void 0 : popperInstance.isFirstRun) {
226
259
  popperInstance.state.elements.popper.style.position = popperOriginalPositionRef.current;
227
260
  popperInstance.isFirstRun = false;
228
261
  }
@@ -254,7 +287,7 @@ export function usePopper(options) {
254
287
  var targetRef = useCallbackRef(null, handlePopperUpdate, true);
255
288
  var containerRef = useCallbackRef(null, handlePopperUpdate, true);
256
289
  var arrowRef = useCallbackRef(null, handlePopperUpdate, true);
257
- React.useImperativeHandle(options.containerRef, function () { return ({
290
+ React.useImperativeHandle(options.popperRef, function () { return ({
258
291
  updatePosition: function () {
259
292
  var _a;
260
293
  (_a = popperInstanceRef.current) === null || _a === void 0 ? void 0 : _a.update();
@@ -267,25 +300,30 @@ export function usePopper(options) {
267
300
  (_a = popperInstanceRef.current) === null || _a === void 0 ? void 0 : _a.destroy();
268
301
  popperInstanceRef.current = null;
269
302
  };
270
- }, [options.enabled]);
303
+ }, [handlePopperUpdate, options.enabled, options.target]);
271
304
  useIsomorphicLayoutEffect(function () {
272
305
  var _a;
273
306
  if (!isFirstMount) {
274
- (_a = popperInstanceRef.current) === null || _a === void 0 ? void 0 : _a.setOptions(resolvePopperOptions(targetRef.current, containerRef.current, arrowRef.current));
307
+ (_a = popperInstanceRef.current) === null || _a === void 0 ? void 0 : _a.setOptions(resolvePopperOptions(options.target || targetRef.current, containerRef.current, arrowRef.current));
275
308
  }
276
- }, [resolvePopperOptions]);
309
+ },
310
+ // Missing deps:
311
+ // options.target - The useIsomorphicLayoutEffect before this will create a new popper instance if target changes
312
+ // isFirstMount - Should never change after mount
313
+ // arrowRef, containerRef, targetRef - Stable between renders
314
+ // eslint-disable-next-line react-hooks/exhaustive-deps
315
+ [resolvePopperOptions]);
277
316
  if (process.env.NODE_ENV !== 'production') {
278
317
  // This checked should run only in development mode
279
318
  // eslint-disable-next-line react-hooks/rules-of-hooks
280
319
  React.useEffect(function () {
281
- var _a, _b;
320
+ var _a;
282
321
  if (containerRef.current) {
283
322
  var contentNode = containerRef.current;
284
- // eslint-disable-next-line deprecation/deprecation
285
323
  var treeWalker = (_a = contentNode.ownerDocument) === null || _a === void 0 ? void 0 : _a.createTreeWalker(contentNode, NodeFilter.SHOW_ELEMENT, {
286
324
  acceptNode: hasAutofocusFilter,
287
325
  });
288
- while ((_b = treeWalker) === null || _b === void 0 ? void 0 : _b.nextNode()) {
326
+ while (treeWalker === null || treeWalker === void 0 ? void 0 : treeWalker.nextNode()) {
289
327
  var node = treeWalker.currentNode;
290
328
  // eslint-disable-next-line no-console
291
329
  console.warn('<Popper>:', node);