@atlaskit/top-layer 0.12.2 → 0.14.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 (245) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +61 -34
  3. package/dist/cjs/animations/presets.js +4 -4
  4. package/dist/cjs/entry-points/focus.js +6 -4
  5. package/dist/cjs/entry-points/get-aria-for-trigger.js +12 -0
  6. package/dist/cjs/entry-points/popover-surface.js +12 -0
  7. package/dist/cjs/entry-points/use-anchor-position-at-point.js +12 -0
  8. package/dist/cjs/entry-points/use-popover-id.js +21 -0
  9. package/dist/cjs/focus/get-first-focusable.js +19 -0
  10. package/dist/cjs/focus/get-focusables.js +30 -0
  11. package/dist/cjs/focus/get-last-focusable.js +19 -0
  12. package/dist/cjs/focus/get-next-focusable.js +43 -0
  13. package/dist/cjs/focus/is-in-same-layer.js +23 -0
  14. package/dist/cjs/focus/is-nested-layer-focused.js +32 -0
  15. package/dist/cjs/focus/selectors.js +19 -0
  16. package/dist/cjs/focus/types.js +1 -0
  17. package/dist/cjs/internal/get-aria-for-trigger.js +88 -0
  18. package/dist/cjs/internal/role-to-aria-has-popup.js +37 -0
  19. package/dist/cjs/internal/role-types.js +2 -35
  20. package/dist/cjs/internal/should-focus-into-popover.js +19 -0
  21. package/dist/cjs/internal/slot.js +1 -1
  22. package/dist/cjs/internal/use-anchor-position-at-point.js +127 -0
  23. package/dist/cjs/internal/use-anchor-position.js +36 -16
  24. package/dist/cjs/internal/use-focus-wrap.js +8 -5
  25. package/dist/cjs/internal/use-initial-focus.js +4 -4
  26. package/dist/cjs/placement-map/index.js +2 -2
  27. package/dist/cjs/placement-map/legacy-placements.js +2 -101
  28. package/dist/cjs/placement-map/placement-mapping.js +103 -0
  29. package/dist/cjs/popover/popover.js +79 -80
  30. package/dist/cjs/popover-surface/index.js +12 -0
  31. package/dist/cjs/{popup/popup-surface.js → popover-surface/popover-surface.js} +9 -12
  32. package/dist/cjs/testing/polyfill.js +9 -6
  33. package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +7 -5
  34. package/dist/es2019/animations/presets.js +4 -4
  35. package/dist/es2019/entry-points/focus.js +3 -1
  36. package/dist/es2019/entry-points/get-aria-for-trigger.js +1 -0
  37. package/dist/es2019/entry-points/popover-surface.js +1 -0
  38. package/dist/es2019/entry-points/use-anchor-position-at-point.js +1 -0
  39. package/dist/es2019/entry-points/use-popover-id.js +15 -0
  40. package/dist/es2019/focus/get-first-focusable.js +14 -0
  41. package/dist/es2019/focus/get-focusables.js +19 -0
  42. package/dist/es2019/focus/get-last-focusable.js +14 -0
  43. package/dist/es2019/focus/get-next-focusable.js +38 -0
  44. package/dist/es2019/focus/is-in-same-layer.js +18 -0
  45. package/dist/es2019/focus/is-nested-layer-focused.js +28 -0
  46. package/dist/es2019/focus/selectors.js +11 -0
  47. package/dist/es2019/focus/types.js +0 -0
  48. package/dist/es2019/internal/get-aria-for-trigger.js +84 -0
  49. package/dist/es2019/internal/role-to-aria-has-popup.js +32 -0
  50. package/dist/es2019/internal/role-types.js +0 -33
  51. package/dist/es2019/internal/should-focus-into-popover.js +14 -0
  52. package/dist/es2019/internal/slot.js +1 -1
  53. package/dist/es2019/internal/use-anchor-position-at-point.js +122 -0
  54. package/dist/es2019/internal/use-anchor-position.js +21 -14
  55. package/dist/es2019/internal/use-focus-wrap.js +4 -1
  56. package/dist/es2019/internal/use-initial-focus.js +1 -1
  57. package/dist/es2019/placement-map/index.js +1 -1
  58. package/dist/es2019/placement-map/legacy-placements.js +1 -100
  59. package/dist/es2019/placement-map/placement-mapping.js +97 -0
  60. package/dist/es2019/popover/popover.js +79 -80
  61. package/dist/es2019/popover-surface/index.js +1 -0
  62. package/dist/es2019/popover-surface/popover-surface.js +27 -0
  63. package/dist/es2019/testing/polyfill.js +9 -6
  64. package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +3 -1
  65. package/dist/esm/animations/presets.js +4 -4
  66. package/dist/esm/entry-points/focus.js +3 -1
  67. package/dist/esm/entry-points/get-aria-for-trigger.js +1 -0
  68. package/dist/esm/entry-points/popover-surface.js +1 -0
  69. package/dist/esm/entry-points/use-anchor-position-at-point.js +1 -0
  70. package/dist/esm/entry-points/use-popover-id.js +15 -0
  71. package/dist/esm/focus/get-first-focusable.js +13 -0
  72. package/dist/esm/focus/get-focusables.js +24 -0
  73. package/dist/esm/focus/get-last-focusable.js +13 -0
  74. package/dist/esm/focus/get-next-focusable.js +37 -0
  75. package/dist/esm/focus/is-in-same-layer.js +17 -0
  76. package/dist/esm/focus/is-nested-layer-focused.js +27 -0
  77. package/dist/esm/focus/selectors.js +13 -0
  78. package/dist/esm/focus/types.js +0 -0
  79. package/dist/esm/internal/get-aria-for-trigger.js +83 -0
  80. package/dist/esm/internal/role-to-aria-has-popup.js +31 -0
  81. package/dist/esm/internal/role-types.js +2 -34
  82. package/dist/esm/internal/should-focus-into-popover.js +13 -0
  83. package/dist/esm/internal/slot.js +1 -1
  84. package/dist/esm/internal/use-anchor-position-at-point.js +122 -0
  85. package/dist/esm/internal/use-anchor-position.js +36 -16
  86. package/dist/esm/internal/use-focus-wrap.js +4 -1
  87. package/dist/esm/internal/use-initial-focus.js +1 -1
  88. package/dist/esm/placement-map/index.js +1 -1
  89. package/dist/esm/placement-map/legacy-placements.js +1 -100
  90. package/dist/esm/placement-map/placement-mapping.js +97 -0
  91. package/dist/esm/popover/popover.js +79 -80
  92. package/dist/esm/popover-surface/index.js +1 -0
  93. package/dist/esm/popover-surface/popover-surface.js +26 -0
  94. package/dist/esm/testing/polyfill.js +9 -6
  95. package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +3 -1
  96. package/dist/types/animations/presets.d.ts +4 -4
  97. package/dist/types/animations/types.d.ts +1 -1
  98. package/dist/types/dialog/types.d.ts +0 -8
  99. package/dist/types/entry-points/focus.d.ts +4 -2
  100. package/dist/types/entry-points/get-aria-for-trigger.d.ts +1 -0
  101. package/dist/types/entry-points/popover-surface.d.ts +2 -0
  102. package/dist/types/entry-points/popover.d.ts +1 -1
  103. package/dist/types/entry-points/use-anchor-position-at-point.d.ts +1 -0
  104. package/dist/types/entry-points/use-popover-id.d.ts +11 -0
  105. package/dist/types/focus/get-first-focusable.d.ts +8 -0
  106. package/dist/types/focus/get-focusables.d.ts +13 -0
  107. package/dist/types/focus/get-last-focusable.d.ts +8 -0
  108. package/dist/types/focus/get-next-focusable.d.ts +13 -0
  109. package/dist/types/focus/is-in-same-layer.d.ts +8 -0
  110. package/dist/types/focus/is-nested-layer-focused.d.ts +8 -0
  111. package/dist/types/focus/selectors.d.ts +4 -0
  112. package/dist/types/focus/types.d.ts +5 -0
  113. package/dist/types/internal/get-aria-for-trigger.d.ts +86 -0
  114. package/dist/types/internal/role-to-aria-has-popup.d.ts +13 -0
  115. package/dist/types/internal/role-types.d.ts +0 -12
  116. package/dist/types/internal/should-focus-into-popover.d.ts +8 -0
  117. package/dist/types/internal/slot.d.ts +2 -2
  118. package/dist/types/internal/use-anchor-position-at-point.d.ts +62 -0
  119. package/dist/types/internal/use-anchor-position.d.ts +6 -1
  120. package/dist/types/placement-map/index.d.ts +1 -1
  121. package/dist/types/placement-map/legacy-placements.d.ts +0 -12
  122. package/dist/types/placement-map/placement-mapping.d.ts +13 -0
  123. package/dist/types/popover/index.d.ts +1 -1
  124. package/dist/types/popover/popover.d.ts +6 -13
  125. package/dist/types/popover/types.d.ts +6 -5
  126. package/dist/types/popover-surface/index.d.ts +2 -0
  127. package/dist/types/popover-surface/popover-surface.d.ts +21 -0
  128. package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +1 -1
  129. package/dist/types-ts4.5/animations/presets.d.ts +4 -4
  130. package/dist/types-ts4.5/animations/types.d.ts +1 -1
  131. package/dist/types-ts4.5/dialog/types.d.ts +0 -8
  132. package/dist/types-ts4.5/entry-points/focus.d.ts +4 -2
  133. package/dist/types-ts4.5/entry-points/get-aria-for-trigger.d.ts +1 -0
  134. package/dist/types-ts4.5/entry-points/popover-surface.d.ts +2 -0
  135. package/dist/types-ts4.5/entry-points/popover.d.ts +1 -1
  136. package/dist/types-ts4.5/entry-points/use-anchor-position-at-point.d.ts +1 -0
  137. package/dist/types-ts4.5/entry-points/use-popover-id.d.ts +11 -0
  138. package/dist/types-ts4.5/focus/get-first-focusable.d.ts +8 -0
  139. package/dist/types-ts4.5/focus/get-focusables.d.ts +13 -0
  140. package/dist/types-ts4.5/focus/get-last-focusable.d.ts +8 -0
  141. package/dist/types-ts4.5/focus/get-next-focusable.d.ts +13 -0
  142. package/dist/types-ts4.5/focus/is-in-same-layer.d.ts +8 -0
  143. package/dist/types-ts4.5/focus/is-nested-layer-focused.d.ts +8 -0
  144. package/dist/types-ts4.5/focus/selectors.d.ts +4 -0
  145. package/dist/types-ts4.5/focus/types.d.ts +5 -0
  146. package/dist/types-ts4.5/internal/get-aria-for-trigger.d.ts +86 -0
  147. package/dist/types-ts4.5/internal/role-to-aria-has-popup.d.ts +13 -0
  148. package/dist/types-ts4.5/internal/role-types.d.ts +0 -12
  149. package/dist/types-ts4.5/internal/should-focus-into-popover.d.ts +8 -0
  150. package/dist/types-ts4.5/internal/slot.d.ts +2 -2
  151. package/dist/types-ts4.5/internal/use-anchor-position-at-point.d.ts +62 -0
  152. package/dist/types-ts4.5/internal/use-anchor-position.d.ts +6 -1
  153. package/dist/types-ts4.5/placement-map/index.d.ts +1 -1
  154. package/dist/types-ts4.5/placement-map/legacy-placements.d.ts +0 -12
  155. package/dist/types-ts4.5/placement-map/placement-mapping.d.ts +13 -0
  156. package/dist/types-ts4.5/popover/index.d.ts +1 -1
  157. package/dist/types-ts4.5/popover/popover.d.ts +6 -13
  158. package/dist/types-ts4.5/popover/types.d.ts +6 -5
  159. package/dist/types-ts4.5/popover-surface/index.d.ts +2 -0
  160. package/dist/types-ts4.5/popover-surface/popover-surface.d.ts +21 -0
  161. package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +1 -1
  162. package/get-aria-for-trigger/package.json +17 -0
  163. package/package.json +3 -3
  164. package/popover-surface/package.json +17 -0
  165. package/use-anchor-position-at-point/package.json +17 -0
  166. package/use-popover-id/package.json +17 -0
  167. package/dist/cjs/entry-points/popup-surface.js +0 -12
  168. package/dist/cjs/entry-points/popup.js +0 -12
  169. package/dist/cjs/focus/focus.js +0 -169
  170. package/dist/cjs/focus/index.js +0 -24
  171. package/dist/cjs/popup/index.js +0 -37
  172. package/dist/cjs/popup/popup-content.js +0 -214
  173. package/dist/cjs/popup/popup-context.js +0 -25
  174. package/dist/cjs/popup/popup-provider.js +0 -15
  175. package/dist/cjs/popup/popup-trigger-function.js +0 -80
  176. package/dist/cjs/popup/popup-trigger.js +0 -66
  177. package/dist/cjs/popup/popup.js +0 -81
  178. package/dist/cjs/popup/types.js +0 -5
  179. package/dist/cjs/popup/use-maybe-popup-context.js +0 -17
  180. package/dist/cjs/popup/use-popup-context.js +0 -20
  181. package/dist/es2019/entry-points/popup-surface.js +0 -1
  182. package/dist/es2019/entry-points/popup.js +0 -1
  183. package/dist/es2019/focus/focus.js +0 -158
  184. package/dist/es2019/focus/index.js +0 -1
  185. package/dist/es2019/popup/index.js +0 -33
  186. package/dist/es2019/popup/popup-content.js +0 -206
  187. package/dist/es2019/popup/popup-context.js +0 -20
  188. package/dist/es2019/popup/popup-provider.js +0 -10
  189. package/dist/es2019/popup/popup-surface.js +0 -30
  190. package/dist/es2019/popup/popup-trigger-function.js +0 -75
  191. package/dist/es2019/popup/popup-trigger.js +0 -61
  192. package/dist/es2019/popup/popup.js +0 -67
  193. package/dist/es2019/popup/types.js +0 -1
  194. package/dist/es2019/popup/use-maybe-popup-context.js +0 -12
  195. package/dist/es2019/popup/use-popup-context.js +0 -15
  196. package/dist/esm/entry-points/popup-surface.js +0 -1
  197. package/dist/esm/entry-points/popup.js +0 -1
  198. package/dist/esm/focus/focus.js +0 -160
  199. package/dist/esm/focus/index.js +0 -1
  200. package/dist/esm/popup/index.js +0 -33
  201. package/dist/esm/popup/popup-content.js +0 -206
  202. package/dist/esm/popup/popup-context.js +0 -20
  203. package/dist/esm/popup/popup-provider.js +0 -10
  204. package/dist/esm/popup/popup-surface.js +0 -29
  205. package/dist/esm/popup/popup-trigger-function.js +0 -75
  206. package/dist/esm/popup/popup-trigger.js +0 -59
  207. package/dist/esm/popup/popup.js +0 -72
  208. package/dist/esm/popup/types.js +0 -1
  209. package/dist/esm/popup/use-maybe-popup-context.js +0 -12
  210. package/dist/esm/popup/use-popup-context.js +0 -15
  211. package/dist/types/entry-points/popup-surface.d.ts +0 -2
  212. package/dist/types/entry-points/popup.d.ts +0 -2
  213. package/dist/types/focus/focus.d.ts +0 -50
  214. package/dist/types/focus/index.d.ts +0 -2
  215. package/dist/types/popup/index.d.ts +0 -34
  216. package/dist/types/popup/popup-content.d.ts +0 -14
  217. package/dist/types/popup/popup-context.d.ts +0 -96
  218. package/dist/types/popup/popup-provider.d.ts +0 -10
  219. package/dist/types/popup/popup-surface.d.ts +0 -22
  220. package/dist/types/popup/popup-trigger-function.d.ts +0 -112
  221. package/dist/types/popup/popup-trigger.d.ts +0 -14
  222. package/dist/types/popup/popup.d.ts +0 -14
  223. package/dist/types/popup/types.d.ts +0 -321
  224. package/dist/types/popup/use-maybe-popup-context.d.ts +0 -8
  225. package/dist/types/popup/use-popup-context.d.ts +0 -7
  226. package/dist/types-ts4.5/entry-points/popup-surface.d.ts +0 -2
  227. package/dist/types-ts4.5/entry-points/popup.d.ts +0 -2
  228. package/dist/types-ts4.5/focus/focus.d.ts +0 -50
  229. package/dist/types-ts4.5/focus/index.d.ts +0 -2
  230. package/dist/types-ts4.5/popup/index.d.ts +0 -34
  231. package/dist/types-ts4.5/popup/popup-content.d.ts +0 -14
  232. package/dist/types-ts4.5/popup/popup-context.d.ts +0 -96
  233. package/dist/types-ts4.5/popup/popup-provider.d.ts +0 -10
  234. package/dist/types-ts4.5/popup/popup-surface.d.ts +0 -22
  235. package/dist/types-ts4.5/popup/popup-trigger-function.d.ts +0 -112
  236. package/dist/types-ts4.5/popup/popup-trigger.d.ts +0 -14
  237. package/dist/types-ts4.5/popup/popup.d.ts +0 -14
  238. package/dist/types-ts4.5/popup/types.d.ts +0 -321
  239. package/dist/types-ts4.5/popup/use-maybe-popup-context.d.ts +0 -8
  240. package/dist/types-ts4.5/popup/use-popup-context.d.ts +0 -7
  241. package/popup/package.json +0 -17
  242. package/popup-surface/package.json +0 -17
  243. /package/dist/cjs/{popup/popup-surface.compiled.css → popover-surface/popover-surface.compiled.css} +0 -0
  244. /package/dist/es2019/{popup/popup-surface.compiled.css → popover-surface/popover-surface.compiled.css} +0 -0
  245. /package/dist/esm/{popup/popup-surface.compiled.css → popover-surface/popover-surface.compiled.css} +0 -0
@@ -0,0 +1,83 @@
1
+ import { roleToAriaHasPopup } from './role-to-aria-has-popup';
2
+
3
+ /**
4
+ * Roles accepted by `getAriaForTrigger`.
5
+ *
6
+ * Excludes tooltip-family roles (`tooltip`, `note`, `status`, `alert`, `log`)
7
+ * because the correct trigger wiring for those is `aria-describedby`, not
8
+ * `aria-haspopup` / `aria-expanded` / `aria-controls`. Use `aria-describedby`
9
+ * manually for tooltip triggers.
10
+ */
11
+
12
+ /**
13
+ * Non-undefined subset of `TAriaHasPopupValue`. Every role accepted by
14
+ * `getAriaForTrigger` maps to a concrete `aria-haspopup` string, so the
15
+ * trigger always receives a defined attribute value.
16
+ */
17
+
18
+ /**
19
+ * Returns the ARIA attributes to spread onto a click-activated popover trigger.
20
+ *
21
+ * Centralises three attributes that are easy to forget or get wrong individually:
22
+ *
23
+ * - `aria-haspopup` - derived from the popover's role (e.g. `dialog → "dialog"`,
24
+ * `menu → "menu"`, `tooltip → undefined`). React omits the attribute when
25
+ * the value is `undefined`.
26
+ * - `aria-expanded` - reflects the current open state.
27
+ * - `aria-controls` - references the popover element by its id, even
28
+ * while the popover is closed. The relationship is stable; `aria-expanded`
29
+ * carries the current visibility state.
30
+ *
31
+ * **This function is for click/keyboard-activated popovers only.** For
32
+ * hover-driven tooltips, the trigger should use `aria-describedby` instead.
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * import { getAriaForTrigger } from '@atlaskit/top-layer/get-aria-for-trigger';
37
+ * import { usePopoverId } from '@atlaskit/top-layer/use-popover-id';
38
+ *
39
+ * const popoverId = usePopoverId();
40
+ * const [isOpen, setIsOpen] = useState(false);
41
+ *
42
+ * return (
43
+ * <>
44
+ * <button
45
+ * ref={triggerRef}
46
+ * onClick={() => setIsOpen((previous) => !previous)}
47
+ * {...getAriaForTrigger({ role: 'dialog', isOpen, popoverId })}
48
+ * >
49
+ * Open
50
+ * </button>
51
+ * <Popover
52
+ * id={popoverId}
53
+ * role="dialog"
54
+ * label="My dialog"
55
+ * isOpen={isOpen}
56
+ * triggerRef={triggerRef}
57
+ * onClose={() => setIsOpen(false)}
58
+ * >
59
+ * …
60
+ * </Popover>
61
+ * </>
62
+ * );
63
+ * ```
64
+ */
65
+ export function getAriaForTrigger(_ref) {
66
+ var role = _ref.role,
67
+ isOpen = _ref.isOpen,
68
+ popoverId = _ref.popoverId;
69
+ // `roleToAriaHasPopup` accepts a wider role union (including tooltip-family
70
+ // roles that map to `undefined`). `TAriaForTriggerRole` excludes those, so
71
+ // the returned value is guaranteed to be a defined string. The cast narrows
72
+ // the wider helper signature to match.
73
+ var ariaHasPopup = roleToAriaHasPopup({
74
+ role: role
75
+ });
76
+ return {
77
+ 'aria-haspopup': ariaHasPopup,
78
+ 'aria-expanded': isOpen,
79
+ // Keep the trigger-to-popover relationship stable. `aria-expanded`
80
+ // tells assistive technology whether the controlled popover is visible.
81
+ 'aria-controls': popoverId
82
+ };
83
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Maps a popover content role to the correct `aria-haspopup` value
3
+ * for its trigger element.
4
+ *
5
+ * Returns `undefined` for roles that are not popups in the ARIA sense
6
+ * (`tooltip`, `note`, `status`, `alert`, `log`). Triggers for those roles
7
+ * should not announce a popup at all - emitting `aria-haspopup="dialog"`
8
+ * on a tooltip trigger would mislead assistive technology.
9
+ */
10
+ export function roleToAriaHasPopup(_ref) {
11
+ var role = _ref.role;
12
+ if (role === 'menu') {
13
+ return 'menu';
14
+ }
15
+ if (role === 'listbox') {
16
+ return 'listbox';
17
+ }
18
+ if (role === 'tree') {
19
+ return 'tree';
20
+ }
21
+ if (role === 'grid') {
22
+ return 'grid';
23
+ }
24
+ if (role === 'dialog' || role === 'alertdialog') {
25
+ return 'dialog';
26
+ }
27
+ // Non-popup roles (tooltip, note, status, alert, log) and the
28
+ // no-role case: omit `aria-haspopup` entirely. React drops the
29
+ // attribute when the value is `undefined`.
30
+ return undefined;
31
+ }
@@ -42,38 +42,6 @@
42
42
  * the role for cases where it is set externally or not needed.
43
43
  */
44
44
 
45
- /**
46
- * Maps a popover content role to the correct `aria-haspopup` value
47
- * for its trigger element.
48
- *
49
- * Returns `undefined` for roles that are not popups in the ARIA sense
50
- * (`tooltip`, `note`, `status`, `alert`, `log`). Triggers for those roles
51
- * should not announce a popup at all - emitting `aria-haspopup="dialog"`
52
- * on a tooltip trigger would mislead assistive technology.
53
- */
54
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
55
- export function roleToAriaHasPopup(_ref) {
56
- var role = _ref.role;
57
- if (role === 'menu') {
58
- return 'menu';
59
- }
60
- if (role === 'listbox') {
61
- return 'listbox';
62
- }
63
- if (role === 'tree') {
64
- return 'tree';
65
- }
66
- if (role === 'grid') {
67
- return 'grid';
68
- }
69
- if (role === 'dialog' || role === 'alertdialog') {
70
- return 'dialog';
71
- }
72
- // Non-popup roles (tooltip, note, status, alert, log) and the
73
- // no-role case: omit `aria-haspopup` entirely. React drops the
74
- // attribute when the value is `undefined`.
75
- return undefined;
76
- }
77
45
  var rolesThatMoveFocus = new Set(['dialog', 'alertdialog', 'menu', 'listbox', 'tree', 'grid']);
78
46
 
79
47
  /**
@@ -81,8 +49,8 @@ var rolesThatMoveFocus = new Set(['dialog', 'alertdialog', 'menu', 'listbox', 't
81
49
  * on open, and `false` otherwise (including when `role` is `undefined`).
82
50
  */
83
51
  // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
84
- export function shouldFocusIntoPopover(_ref2) {
85
- var role = _ref2.role;
52
+ export function shouldFocusIntoPopover(_ref) {
53
+ var role = _ref.role;
86
54
  if (!role) {
87
55
  return false;
88
56
  }
@@ -0,0 +1,13 @@
1
+ var rolesThatMoveFocus = new Set(['dialog', 'alertdialog', 'menu', 'listbox', 'tree', 'grid']);
2
+
3
+ /**
4
+ * Returns `true` when the given popover role moves focus into the popover
5
+ * on open, and `false` otherwise (including when `role` is `undefined`).
6
+ */
7
+ export function shouldFocusIntoPopover(_ref) {
8
+ var role = _ref.role;
9
+ if (!role) {
10
+ return false;
11
+ }
12
+ return rolesThatMoveFocus.has(role);
13
+ }
@@ -46,7 +46,7 @@ function isSlotChild(child) {
46
46
  export var Slot = /*#__PURE__*/forwardRef(function Slot(slotProps, ref) {
47
47
  var rawChildren = slotProps.children,
48
48
  props = _objectWithoutProperties(slotProps, _excluded);
49
- // `TSlotProps` intersects `Record<string, unknown>`, so `children` is typed as `unknown`.
49
+ // `SlotProps` intersects `Record<string, unknown>`, so `children` is typed as `unknown`.
50
50
  var children = rawChildren;
51
51
  if (!isSlotChild(children)) {
52
52
  return children;
@@ -0,0 +1,122 @@
1
+ import { useLayoutEffect, useRef } from 'react';
2
+ import { useAnchorPosition } from './use-anchor-position';
3
+
4
+ /**
5
+ * A point in viewport coordinates (CSS pixels) at which the synthetic
6
+ * anchor should be placed.
7
+ *
8
+ * Axis-named (`x`/`y`) rather than edge-named (`left`/`top`) so the
9
+ * shape is unambiguous in RTL writing modes — there is no ambiguity
10
+ * about whether a coordinate is logical (`inline-start`/`block-start`)
11
+ * or physical (`left`/`top`). Viewport coordinates are always
12
+ * physical, so we name them with the physical axis labels.
13
+ */
14
+
15
+ /**
16
+ * Styles the synthetic anchor as an invisible, zero-size point.
17
+ * Dynamic `inset-*` overrides are written by the positioning effect.
18
+ *
19
+ * Uses `Object.assign` rather than Compiled CSS (element is outside the React tree)
20
+ * or the internal `setStyle` helper (we own this element entirely — it is created
21
+ * and removed by this hook — so the snapshot/restore semantics `setStyle`
22
+ * provides for caller-owned elements would be dead work here).
23
+ */
24
+ function applyStaticAnchorStyles(el) {
25
+ Object.assign(el.style, {
26
+ position: 'fixed',
27
+ // `top`/`left` rather than `inset-block-start`/`inset-inline-start`
28
+ // for consistency with the dynamic positioning effect below, which
29
+ // uses physical properties (see comment there for the rationale).
30
+ top: '0',
31
+ left: '0',
32
+ // Zero size — placement decides which side the popover sits on.
33
+ width: '0',
34
+ height: '0',
35
+ // Prevent the overlay from intercepting pointer events.
36
+ pointerEvents: 'none'
37
+ });
38
+ }
39
+
40
+ // `useAnchorPosition` requires a real DOM element. When the caller only
41
+ // has a viewport coordinate (e.g. cursor at hover time), this hook
42
+ // manages a hidden `<div>` at that point and delegates the rest.
43
+ //
44
+ // The `<div>` is appended directly to `document.body` to escape any
45
+ // transformed ancestor, which would otherwise break `position: fixed`
46
+ // viewport-relative resolution.
47
+
48
+ /**
49
+ * Positions a popover at a consumer-supplied viewport coordinate using a
50
+ * hidden synthetic anchor.
51
+ *
52
+ * @example
53
+ * ```tsx
54
+ * function PointPositionedPopover({ popoverRef, placement, mousePos }) {
55
+ * useAnchorPositionAtPoint({
56
+ * popoverRef,
57
+ * placement,
58
+ * isEnabled: Boolean(mousePos),
59
+ * getPoint: () => {
60
+ * if (!mousePos) return null;
61
+ * return { x: mousePos.clientX, y: mousePos.clientY };
62
+ * },
63
+ * });
64
+ * return <Popover ref={popoverRef}>...</Popover>;
65
+ * }
66
+ * ```
67
+ */
68
+ export function useAnchorPositionAtPoint(_ref) {
69
+ var popoverRef = _ref.popoverRef,
70
+ placement = _ref.placement,
71
+ getPoint = _ref.getPoint,
72
+ _ref$isEnabled = _ref.isEnabled,
73
+ isEnabled = _ref$isEnabled === void 0 ? true : _ref$isEnabled;
74
+ var syntheticAnchorRef = useRef(null);
75
+
76
+ // `getPoint` is kept in a ref so the layout effect can call the
77
+ // latest version without listing it as a dep — that would re-fire
78
+ // on every render and re-latch the point.
79
+ var getPointRef = useRef(getPoint);
80
+ getPointRef.current = getPoint;
81
+
82
+ // Lazy element creation: the `<div>` is only created when both
83
+ // `isEnabled` is true AND `getPoint()` returns a non-null point.
84
+ // `useLayoutEffect` ensures the element exists before the inner
85
+ // `useAnchorPosition` (also a layout effect) reads the ref.
86
+ useLayoutEffect(function () {
87
+ if (!isEnabled) {
88
+ return;
89
+ }
90
+ var point = getPointRef.current();
91
+ if (!point) {
92
+ return;
93
+ }
94
+ var anchor = document.createElement('div');
95
+ anchor.setAttribute('aria-hidden', 'true');
96
+ applyStaticAnchorStyles(anchor);
97
+ // `point.x`/`y` are physical viewport coordinates (from
98
+ // `MouseEvent.clientX/Y`), so map directly onto physical
99
+ // `left`/`top`. This is RTL-safe: `position: fixed` + physical
100
+ // insets is direction-independent. Using logical
101
+ // `inset-inline-start` would need `viewportWidth - point.x` in
102
+ // RTL to land at the same physical pixel.
103
+ anchor.style.top = "".concat(point.y, "px");
104
+ anchor.style.left = "".concat(point.x, "px");
105
+ document.body.appendChild(anchor);
106
+ syntheticAnchorRef.current = anchor;
107
+ return function cleanup() {
108
+ anchor.remove();
109
+ syntheticAnchorRef.current = null;
110
+ };
111
+ }, [isEnabled]);
112
+
113
+ // Mirror `isEnabled` so both hooks stay in sync — when disabled,
114
+ // neither this hook nor the inner one touches the popover, leaving
115
+ // any other positioning the consumer has set up free to take effect.
116
+ useAnchorPosition({
117
+ anchorRef: syntheticAnchorRef,
118
+ popoverRef: popoverRef,
119
+ placement: placement,
120
+ isEnabled: isEnabled
121
+ });
122
+ }
@@ -1,3 +1,5 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
1
3
  /**
2
4
  * Anchor positioning for top-layer popovers. See
3
5
  * `notes/architecture/positioning.md` for the full model.
@@ -28,15 +30,25 @@ import { setStyle } from './set-style';
28
30
  // from `./resolve-placement` so search-and-jump lands at the source of truth.
29
31
 
30
32
  /**
31
- * Module-scope no-op `ResizeObserver` stub used in non-DOM jest environments where
33
+ * Module-scope no-op `ResizeObserver` used in non-DOM jest environments where
32
34
  * `ResizeObserver` is `undefined`. Hoisted out of the effect to avoid
33
- * re-allocating on every run.
35
+ * allocating a new class declaration on every run.
34
36
  */
35
- var noopResizeObserver = {
36
- observe: function observe() {},
37
- unobserve: function unobserve() {},
38
- disconnect: function disconnect() {}
39
- };
37
+ var NoopResizeObserver = /*#__PURE__*/function () {
38
+ function NoopResizeObserver() {
39
+ _classCallCheck(this, NoopResizeObserver);
40
+ }
41
+ return _createClass(NoopResizeObserver, [{
42
+ key: "observe",
43
+ value: function observe() {}
44
+ }, {
45
+ key: "unobserve",
46
+ value: function unobserve() {}
47
+ }, {
48
+ key: "disconnect",
49
+ value: function disconnect() {}
50
+ }]);
51
+ }();
40
52
 
41
53
  /**
42
54
  * Returns true when the popover is currently open. Wrapped because the
@@ -200,12 +212,17 @@ export function useAnchorPosition(_ref3) {
200
212
  _ref3$placement = _ref3.placement,
201
213
  placement = _ref3$placement === void 0 ? {} : _ref3$placement,
202
214
  _ref3$forceFallbackPo = _ref3.forceFallbackPositioning,
203
- forceFallbackPositioning = _ref3$forceFallbackPo === void 0 ? false : _ref3$forceFallbackPo;
215
+ forceFallbackPositioning = _ref3$forceFallbackPo === void 0 ? false : _ref3$forceFallbackPo,
216
+ _ref3$isEnabled = _ref3.isEnabled,
217
+ isEnabled = _ref3$isEnabled === void 0 ? true : _ref3$isEnabled;
204
218
  var id = useId();
205
219
  // Stabilize `placement` object so the same object literal
206
220
  // value returns an object with the same reference
207
221
  var stablePlacement = useStablePlacement(placement);
208
222
  useLayoutEffect(function () {
223
+ if (!isEnabled) {
224
+ return;
225
+ }
209
226
  var trigger = anchorRef.current;
210
227
  var popover = popoverRef.current;
211
228
  if (!trigger || !popover) {
@@ -395,17 +412,20 @@ export function useAnchorPosition(_ref3) {
395
412
  // Self-disconnects after one valid measurement; ongoing
396
413
  // scroll/resize is handled by the window listeners below.
397
414
  // `ResizeObserver` is missing in some non-DOM jest environments
398
- // (e.g. post-office's `node` environment). Fall back to the
399
- // module-scope `noopResizeObserver` stub there. The scroll/resize
400
- // listeners below still keep the popover positioned in the rare
401
- // case the consumer also polyfilled `showPopover` but not
402
- // `ResizeObserver`. Real browsers always have it.
403
- var resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(function () {
415
+ // (e.g. post-office's `node` environment). Fall back to a no-op
416
+ // observer there. The scroll/resize listeners below still keep
417
+ // the popover positioned in the rare case the consumer also
418
+ // polyfilled `showPopover` but not `ResizeObserver`. Real
419
+ // browsers always have it. The `NoopResizeObserver` class is
420
+ // hoisted to module scope (see top of file) so we do not allocate
421
+ // a new constructor on every effect run.
422
+ var ResizeObserverImpl = typeof ResizeObserver !== 'undefined' ? ResizeObserver : NoopResizeObserver;
423
+ var resizeObserver = new ResizeObserverImpl(function () {
404
424
  if (popover.offsetWidth > 0 && popover.offsetHeight > 0) {
405
425
  update();
406
426
  resizeObserver.disconnect();
407
427
  }
408
- }) : noopResizeObserver;
428
+ });
409
429
 
410
430
  // If the popover is already open by the time this effect runs (for
411
431
  // example, the parent `useAnchorPosition` effect runs after the child
@@ -454,5 +474,5 @@ export function useAnchorPosition(_ref3) {
454
474
  popover.style.removeProperty('opacity');
455
475
  });
456
476
  return undoPositioning;
457
- }, [anchorRef, popoverRef, stablePlacement, forceFallbackPositioning, id]);
477
+ }, [anchorRef, popoverRef, stablePlacement, forceFallbackPositioning, isEnabled, id]);
458
478
  }
@@ -1,6 +1,9 @@
1
1
  import { useEffect } from 'react';
2
2
  import { bind } from 'bind-event-listener';
3
- import { getFirstFocusable, getLastFocusable, getNextFocusable, isNestedLayerFocused } from '../focus/focus';
3
+ import { getFirstFocusable } from '../focus/get-first-focusable';
4
+ import { getLastFocusable } from '../focus/get-last-focusable';
5
+ import { getNextFocusable } from '../focus/get-next-focusable';
6
+ import { isNestedLayerFocused } from '../focus/is-nested-layer-focused';
4
7
 
5
8
  /**
6
9
  * Roles that require focus wrapping per WAI-ARIA APG.
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useRef } from 'react';
2
- import { getFirstFocusable } from '../focus/focus';
2
+ import { getFirstFocusable } from '../focus/get-first-focusable';
3
3
 
4
4
  /**
5
5
  * Determines the correct element to receive initial focus within a popover,
@@ -2,7 +2,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
4
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
- import { placementMapping } from './legacy-placements';
5
+ import { placementMapping } from './placement-mapping';
6
6
 
7
7
  /**
8
8
  * Maps legacy Popper.js placement values to the new object-based
@@ -5,103 +5,4 @@
5
5
  * to enumerate every placement (e.g. for a settings dropdown). New code
6
6
  * should use the object-based `TPlacementOptions` directly.
7
7
  */
8
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
9
- export var LEGACY_PLACEMENTS = ['auto', 'auto-start', 'auto-end', 'top', 'top-start', 'top-center', 'top-end', 'bottom', 'bottom-start', 'bottom-center', 'bottom-end', 'right', 'right-start', 'right-end', 'left', 'left-start', 'left-end'];
10
- /**
11
- * The full mapping record. Internal - use `fromLegacyPlacement` from the
12
- * public entry-point so the offset-tuple translation is applied consistently.
13
- *
14
- * Note: `auto`, `auto-start`, `auto-end` map to `block-end` placements. This
15
- * is a reduction in expressiveness vs Popper.js (which picked the best
16
- * placement at runtime). CSS `position-try-fallbacks` flips at the edge but
17
- * the initial placement is fixed. Migration consumers who relied on Popper's
18
- * dynamic auto-flip should pick an explicit placement instead.
19
- */
20
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
21
- export var placementMapping = {
22
- top: {
23
- axis: 'block',
24
- edge: 'start',
25
- align: 'center'
26
- },
27
- 'top-start': {
28
- axis: 'block',
29
- edge: 'start',
30
- align: 'start'
31
- },
32
- 'top-center': {
33
- axis: 'block',
34
- edge: 'start',
35
- align: 'center'
36
- },
37
- 'top-end': {
38
- axis: 'block',
39
- edge: 'start',
40
- align: 'end'
41
- },
42
- bottom: {
43
- axis: 'block',
44
- edge: 'end',
45
- align: 'center'
46
- },
47
- 'bottom-start': {
48
- axis: 'block',
49
- edge: 'end',
50
- align: 'start'
51
- },
52
- 'bottom-center': {
53
- axis: 'block',
54
- edge: 'end',
55
- align: 'center'
56
- },
57
- 'bottom-end': {
58
- axis: 'block',
59
- edge: 'end',
60
- align: 'end'
61
- },
62
- right: {
63
- axis: 'inline',
64
- edge: 'end',
65
- align: 'center'
66
- },
67
- 'right-start': {
68
- axis: 'inline',
69
- edge: 'end',
70
- align: 'start'
71
- },
72
- 'right-end': {
73
- axis: 'inline',
74
- edge: 'end',
75
- align: 'end'
76
- },
77
- left: {
78
- axis: 'inline',
79
- edge: 'start',
80
- align: 'center'
81
- },
82
- 'left-start': {
83
- axis: 'inline',
84
- edge: 'start',
85
- align: 'start'
86
- },
87
- 'left-end': {
88
- axis: 'inline',
89
- edge: 'start',
90
- align: 'end'
91
- },
92
- auto: {
93
- axis: 'block',
94
- edge: 'end',
95
- align: 'center'
96
- },
97
- 'auto-start': {
98
- axis: 'block',
99
- edge: 'end',
100
- align: 'start'
101
- },
102
- 'auto-end': {
103
- axis: 'block',
104
- edge: 'end',
105
- align: 'end'
106
- }
107
- };
8
+ export var LEGACY_PLACEMENTS = ['auto', 'auto-start', 'auto-end', 'top', 'top-start', 'top-center', 'top-end', 'bottom', 'bottom-start', 'bottom-center', 'bottom-end', 'right', 'right-start', 'right-end', 'left', 'left-start', 'left-end'];
@@ -0,0 +1,97 @@
1
+ /**
2
+ * The full mapping record. Internal - use `fromLegacyPlacement` from the
3
+ * public entry-point so the offset-tuple translation is applied consistently.
4
+ *
5
+ * Note: `auto`, `auto-start`, `auto-end` map to `block-end` placements. This
6
+ * is a reduction in expressiveness vs Popper.js (which picked the best
7
+ * placement at runtime). CSS `position-try-fallbacks` flips at the edge but
8
+ * the initial placement is fixed. Migration consumers who relied on Popper's
9
+ * dynamic auto-flip should pick an explicit placement instead.
10
+ */
11
+ export var placementMapping = {
12
+ top: {
13
+ axis: 'block',
14
+ edge: 'start',
15
+ align: 'center'
16
+ },
17
+ 'top-start': {
18
+ axis: 'block',
19
+ edge: 'start',
20
+ align: 'start'
21
+ },
22
+ 'top-center': {
23
+ axis: 'block',
24
+ edge: 'start',
25
+ align: 'center'
26
+ },
27
+ 'top-end': {
28
+ axis: 'block',
29
+ edge: 'start',
30
+ align: 'end'
31
+ },
32
+ bottom: {
33
+ axis: 'block',
34
+ edge: 'end',
35
+ align: 'center'
36
+ },
37
+ 'bottom-start': {
38
+ axis: 'block',
39
+ edge: 'end',
40
+ align: 'start'
41
+ },
42
+ 'bottom-center': {
43
+ axis: 'block',
44
+ edge: 'end',
45
+ align: 'center'
46
+ },
47
+ 'bottom-end': {
48
+ axis: 'block',
49
+ edge: 'end',
50
+ align: 'end'
51
+ },
52
+ right: {
53
+ axis: 'inline',
54
+ edge: 'end',
55
+ align: 'center'
56
+ },
57
+ 'right-start': {
58
+ axis: 'inline',
59
+ edge: 'end',
60
+ align: 'start'
61
+ },
62
+ 'right-end': {
63
+ axis: 'inline',
64
+ edge: 'end',
65
+ align: 'end'
66
+ },
67
+ left: {
68
+ axis: 'inline',
69
+ edge: 'start',
70
+ align: 'center'
71
+ },
72
+ 'left-start': {
73
+ axis: 'inline',
74
+ edge: 'start',
75
+ align: 'start'
76
+ },
77
+ 'left-end': {
78
+ axis: 'inline',
79
+ edge: 'start',
80
+ align: 'end'
81
+ },
82
+ auto: {
83
+ axis: 'block',
84
+ edge: 'end',
85
+ align: 'center'
86
+ },
87
+ 'auto-start': {
88
+ axis: 'block',
89
+ edge: 'end',
90
+ align: 'start'
91
+ },
92
+ 'auto-end': {
93
+ axis: 'block',
94
+ edge: 'end',
95
+ align: 'end'
96
+ }
97
+ };