@atlaskit/top-layer 0.1.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 (300) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +151 -0
  3. package/animations/package.json +17 -0
  4. package/arrow/package.json +17 -0
  5. package/create-close-event/package.json +17 -0
  6. package/dialog/package.json +17 -0
  7. package/dialog-scroll-lock/package.json +17 -0
  8. package/dist/cjs/animations/presets.js +199 -0
  9. package/dist/cjs/animations/types.js +5 -0
  10. package/dist/cjs/arrow/index.js +130 -0
  11. package/dist/cjs/arrow/types.js +5 -0
  12. package/dist/cjs/dialog/create-close-event.js +39 -0
  13. package/dist/cjs/dialog/dialog-content.compiled.css +14 -0
  14. package/dist/cjs/dialog/dialog-content.js +144 -0
  15. package/dist/cjs/dialog/index.js +19 -0
  16. package/dist/cjs/dialog/types.js +5 -0
  17. package/dist/cjs/dialog-scroll-lock/index.js +46 -0
  18. package/dist/cjs/entry-points/animations.js +36 -0
  19. package/dist/cjs/entry-points/arrow.js +12 -0
  20. package/dist/cjs/entry-points/create-close-event.js +19 -0
  21. package/dist/cjs/entry-points/dialog-scroll-lock.js +12 -0
  22. package/dist/cjs/entry-points/dialog.js +12 -0
  23. package/dist/cjs/entry-points/focus.js +24 -0
  24. package/dist/cjs/entry-points/placement-map.js +18 -0
  25. package/dist/cjs/entry-points/popover.js +12 -0
  26. package/dist/cjs/entry-points/popup-surface.js +12 -0
  27. package/dist/cjs/entry-points/popup.js +12 -0
  28. package/dist/cjs/entry-points/use-anchor-position.js +12 -0
  29. package/dist/cjs/entry-points/use-arrow-navigation.js +18 -0
  30. package/dist/cjs/entry-points/use-simple-light-dismiss.js +12 -0
  31. package/dist/cjs/focus/focus.js +115 -0
  32. package/dist/cjs/focus/index.js +24 -0
  33. package/dist/cjs/index.js +8 -0
  34. package/dist/cjs/internal/anchor-positioning-fallback.js +154 -0
  35. package/dist/cjs/internal/combine.js +29 -0
  36. package/dist/cjs/internal/ensure-preset-styles.js +34 -0
  37. package/dist/cjs/internal/reduced-motion.js +27 -0
  38. package/dist/cjs/internal/resolve-placement.js +24 -0
  39. package/dist/cjs/internal/role-types.js +66 -0
  40. package/dist/cjs/internal/set-style.js +42 -0
  41. package/dist/cjs/internal/slot.js +65 -0
  42. package/dist/cjs/internal/use-anchor-positioning.js +336 -0
  43. package/dist/cjs/internal/use-animated-visibility.js +169 -0
  44. package/dist/cjs/internal/use-animation-preset.js +24 -0
  45. package/dist/cjs/internal/use-focus-wrap.js +94 -0
  46. package/dist/cjs/internal/use-initial-focus.js +112 -0
  47. package/dist/cjs/internal/use-preset-styles.js +27 -0
  48. package/dist/cjs/placement-map/index.js +147 -0
  49. package/dist/cjs/popover/create-close-event.js +44 -0
  50. package/dist/cjs/popover/index.js +19 -0
  51. package/dist/cjs/popover/popover.compiled.css +13 -0
  52. package/dist/cjs/popover/popover.js +251 -0
  53. package/dist/cjs/popover/types.js +5 -0
  54. package/dist/cjs/popup/index.js +37 -0
  55. package/dist/cjs/popup/popup-content.js +201 -0
  56. package/dist/cjs/popup/popup-context.js +42 -0
  57. package/dist/cjs/popup/popup-surface.compiled.css +5 -0
  58. package/dist/cjs/popup/popup-surface.js +30 -0
  59. package/dist/cjs/popup/popup-trigger-function.js +74 -0
  60. package/dist/cjs/popup/popup-trigger.js +82 -0
  61. package/dist/cjs/popup/popup.js +70 -0
  62. package/dist/cjs/popup/types.js +5 -0
  63. package/dist/cjs/use-arrow-navigation/index.js +18 -0
  64. package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +245 -0
  65. package/dist/cjs/use-simple-light-dismiss/index.js +84 -0
  66. package/dist/es2019/animations/presets.js +375 -0
  67. package/dist/es2019/animations/types.js +1 -0
  68. package/dist/es2019/arrow/index.js +249 -0
  69. package/dist/es2019/arrow/types.js +1 -0
  70. package/dist/es2019/dialog/create-close-event.js +34 -0
  71. package/dist/es2019/dialog/dialog-content.compiled.css +14 -0
  72. package/dist/es2019/dialog/dialog-content.js +138 -0
  73. package/dist/es2019/dialog/index.js +2 -0
  74. package/dist/es2019/dialog/types.js +1 -0
  75. package/dist/es2019/dialog-scroll-lock/index.js +41 -0
  76. package/dist/es2019/entry-points/animations.js +1 -0
  77. package/dist/es2019/entry-points/arrow.js +1 -0
  78. package/dist/es2019/entry-points/create-close-event.js +2 -0
  79. package/dist/es2019/entry-points/dialog-scroll-lock.js +1 -0
  80. package/dist/es2019/entry-points/dialog.js +1 -0
  81. package/dist/es2019/entry-points/focus.js +1 -0
  82. package/dist/es2019/entry-points/placement-map.js +1 -0
  83. package/dist/es2019/entry-points/popover.js +1 -0
  84. package/dist/es2019/entry-points/popup-surface.js +1 -0
  85. package/dist/es2019/entry-points/popup.js +1 -0
  86. package/dist/es2019/entry-points/use-anchor-position.js +1 -0
  87. package/dist/es2019/entry-points/use-arrow-navigation.js +1 -0
  88. package/dist/es2019/entry-points/use-simple-light-dismiss.js +1 -0
  89. package/dist/es2019/focus/focus.js +107 -0
  90. package/dist/es2019/focus/index.js +1 -0
  91. package/dist/es2019/index.js +7 -0
  92. package/dist/es2019/internal/anchor-positioning-fallback.js +153 -0
  93. package/dist/es2019/internal/combine.js +18 -0
  94. package/dist/es2019/internal/ensure-preset-styles.js +29 -0
  95. package/dist/es2019/internal/reduced-motion.js +21 -0
  96. package/dist/es2019/internal/resolve-placement.js +19 -0
  97. package/dist/es2019/internal/role-types.js +61 -0
  98. package/dist/es2019/internal/set-style.js +39 -0
  99. package/dist/es2019/internal/slot.js +57 -0
  100. package/dist/es2019/internal/use-anchor-positioning.js +330 -0
  101. package/dist/es2019/internal/use-animated-visibility.js +159 -0
  102. package/dist/es2019/internal/use-animation-preset.js +18 -0
  103. package/dist/es2019/internal/use-focus-wrap.js +90 -0
  104. package/dist/es2019/internal/use-initial-focus.js +109 -0
  105. package/dist/es2019/internal/use-preset-styles.js +22 -0
  106. package/dist/es2019/placement-map/index.js +142 -0
  107. package/dist/es2019/popover/create-close-event.js +39 -0
  108. package/dist/es2019/popover/index.js +2 -0
  109. package/dist/es2019/popover/popover.compiled.css +13 -0
  110. package/dist/es2019/popover/popover.js +240 -0
  111. package/dist/es2019/popover/types.js +1 -0
  112. package/dist/es2019/popup/index.js +33 -0
  113. package/dist/es2019/popup/popup-content.js +192 -0
  114. package/dist/es2019/popup/popup-context.js +34 -0
  115. package/dist/es2019/popup/popup-surface.compiled.css +5 -0
  116. package/dist/es2019/popup/popup-surface.js +24 -0
  117. package/dist/es2019/popup/popup-trigger-function.js +69 -0
  118. package/dist/es2019/popup/popup-trigger.js +76 -0
  119. package/dist/es2019/popup/popup.js +56 -0
  120. package/dist/es2019/popup/types.js +1 -0
  121. package/dist/es2019/use-arrow-navigation/index.js +1 -0
  122. package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +238 -0
  123. package/dist/es2019/use-simple-light-dismiss/index.js +79 -0
  124. package/dist/esm/animations/presets.js +190 -0
  125. package/dist/esm/animations/types.js +1 -0
  126. package/dist/esm/arrow/index.js +123 -0
  127. package/dist/esm/arrow/types.js +1 -0
  128. package/dist/esm/dialog/create-close-event.js +33 -0
  129. package/dist/esm/dialog/dialog-content.compiled.css +14 -0
  130. package/dist/esm/dialog/dialog-content.js +135 -0
  131. package/dist/esm/dialog/index.js +2 -0
  132. package/dist/esm/dialog/types.js +1 -0
  133. package/dist/esm/dialog-scroll-lock/index.js +41 -0
  134. package/dist/esm/entry-points/animations.js +1 -0
  135. package/dist/esm/entry-points/arrow.js +1 -0
  136. package/dist/esm/entry-points/create-close-event.js +2 -0
  137. package/dist/esm/entry-points/dialog-scroll-lock.js +1 -0
  138. package/dist/esm/entry-points/dialog.js +1 -0
  139. package/dist/esm/entry-points/focus.js +1 -0
  140. package/dist/esm/entry-points/placement-map.js +1 -0
  141. package/dist/esm/entry-points/popover.js +1 -0
  142. package/dist/esm/entry-points/popup-surface.js +1 -0
  143. package/dist/esm/entry-points/popup.js +1 -0
  144. package/dist/esm/entry-points/use-anchor-position.js +1 -0
  145. package/dist/esm/entry-points/use-arrow-navigation.js +1 -0
  146. package/dist/esm/entry-points/use-simple-light-dismiss.js +1 -0
  147. package/dist/esm/focus/focus.js +107 -0
  148. package/dist/esm/focus/index.js +1 -0
  149. package/dist/esm/index.js +7 -0
  150. package/dist/esm/internal/anchor-positioning-fallback.js +147 -0
  151. package/dist/esm/internal/combine.js +23 -0
  152. package/dist/esm/internal/ensure-preset-styles.js +28 -0
  153. package/dist/esm/internal/reduced-motion.js +21 -0
  154. package/dist/esm/internal/resolve-placement.js +18 -0
  155. package/dist/esm/internal/role-types.js +60 -0
  156. package/dist/esm/internal/set-style.js +36 -0
  157. package/dist/esm/internal/slot.js +59 -0
  158. package/dist/esm/internal/use-anchor-positioning.js +323 -0
  159. package/dist/esm/internal/use-animated-visibility.js +162 -0
  160. package/dist/esm/internal/use-animation-preset.js +18 -0
  161. package/dist/esm/internal/use-focus-wrap.js +89 -0
  162. package/dist/esm/internal/use-initial-focus.js +107 -0
  163. package/dist/esm/internal/use-preset-styles.js +21 -0
  164. package/dist/esm/placement-map/index.js +141 -0
  165. package/dist/esm/popover/create-close-event.js +38 -0
  166. package/dist/esm/popover/index.js +2 -0
  167. package/dist/esm/popover/popover.compiled.css +13 -0
  168. package/dist/esm/popover/popover.js +242 -0
  169. package/dist/esm/popover/types.js +1 -0
  170. package/dist/esm/popup/index.js +33 -0
  171. package/dist/esm/popup/popup-content.js +192 -0
  172. package/dist/esm/popup/popup-context.js +34 -0
  173. package/dist/esm/popup/popup-surface.compiled.css +5 -0
  174. package/dist/esm/popup/popup-surface.js +23 -0
  175. package/dist/esm/popup/popup-trigger-function.js +69 -0
  176. package/dist/esm/popup/popup-trigger.js +74 -0
  177. package/dist/esm/popup/popup.js +61 -0
  178. package/dist/esm/popup/types.js +1 -0
  179. package/dist/esm/use-arrow-navigation/index.js +1 -0
  180. package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +238 -0
  181. package/dist/esm/use-simple-light-dismiss/index.js +78 -0
  182. package/dist/types/animations/presets.d.ts +94 -0
  183. package/dist/types/animations/types.d.ts +42 -0
  184. package/dist/types/arrow/index.d.ts +24 -0
  185. package/dist/types/arrow/types.d.ts +29 -0
  186. package/dist/types/dialog/create-close-event.d.ts +24 -0
  187. package/dist/types/dialog/dialog-content.d.ts +20 -0
  188. package/dist/types/dialog/index.d.ts +3 -0
  189. package/dist/types/dialog/types.d.ts +92 -0
  190. package/dist/types/dialog-scroll-lock/index.d.ts +24 -0
  191. package/dist/types/entry-points/animations.d.ts +2 -0
  192. package/dist/types/entry-points/arrow.d.ts +2 -0
  193. package/dist/types/entry-points/create-close-event.d.ts +4 -0
  194. package/dist/types/entry-points/dialog-scroll-lock.d.ts +1 -0
  195. package/dist/types/entry-points/dialog.d.ts +2 -0
  196. package/dist/types/entry-points/focus.d.ts +2 -0
  197. package/dist/types/entry-points/placement-map.d.ts +2 -0
  198. package/dist/types/entry-points/popover.d.ts +2 -0
  199. package/dist/types/entry-points/popup-surface.d.ts +2 -0
  200. package/dist/types/entry-points/popup.d.ts +2 -0
  201. package/dist/types/entry-points/use-anchor-position.d.ts +1 -0
  202. package/dist/types/entry-points/use-arrow-navigation.d.ts +2 -0
  203. package/dist/types/entry-points/use-simple-light-dismiss.d.ts +2 -0
  204. package/dist/types/focus/focus.d.ts +42 -0
  205. package/dist/types/focus/index.d.ts +2 -0
  206. package/dist/types/index.d.ts +0 -0
  207. package/dist/types/internal/anchor-positioning-fallback.d.ts +24 -0
  208. package/dist/types/internal/combine.d.ts +14 -0
  209. package/dist/types/internal/ensure-preset-styles.d.ts +6 -0
  210. package/dist/types/internal/reduced-motion.d.ts +14 -0
  211. package/dist/types/internal/resolve-placement.d.ts +16 -0
  212. package/dist/types/internal/role-types.d.ts +62 -0
  213. package/dist/types/internal/set-style.d.ts +28 -0
  214. package/dist/types/internal/slot.d.ts +29 -0
  215. package/dist/types/internal/use-anchor-positioning.d.ts +95 -0
  216. package/dist/types/internal/use-animated-visibility.d.ts +74 -0
  217. package/dist/types/internal/use-animation-preset.d.ts +11 -0
  218. package/dist/types/internal/use-focus-wrap.d.ts +20 -0
  219. package/dist/types/internal/use-initial-focus.d.ts +21 -0
  220. package/dist/types/internal/use-preset-styles.d.ts +15 -0
  221. package/dist/types/placement-map/index.d.ts +55 -0
  222. package/dist/types/popover/create-close-event.d.ts +26 -0
  223. package/dist/types/popover/index.d.ts +3 -0
  224. package/dist/types/popover/popover.d.ts +22 -0
  225. package/dist/types/popover/types.d.ts +153 -0
  226. package/dist/types/popup/index.d.ts +34 -0
  227. package/dist/types/popup/popup-content.d.ts +14 -0
  228. package/dist/types/popup/popup-context.d.ts +96 -0
  229. package/dist/types/popup/popup-surface.d.ts +16 -0
  230. package/dist/types/popup/popup-trigger-function.d.ts +108 -0
  231. package/dist/types/popup/popup-trigger.d.ts +23 -0
  232. package/dist/types/popup/popup.d.ts +14 -0
  233. package/dist/types/popup/types.d.ts +289 -0
  234. package/dist/types/use-arrow-navigation/index.d.ts +2 -0
  235. package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +136 -0
  236. package/dist/types/use-simple-light-dismiss/index.d.ts +45 -0
  237. package/dist/types-ts4.5/animations/presets.d.ts +94 -0
  238. package/dist/types-ts4.5/animations/types.d.ts +42 -0
  239. package/dist/types-ts4.5/arrow/index.d.ts +24 -0
  240. package/dist/types-ts4.5/arrow/types.d.ts +29 -0
  241. package/dist/types-ts4.5/dialog/create-close-event.d.ts +24 -0
  242. package/dist/types-ts4.5/dialog/dialog-content.d.ts +20 -0
  243. package/dist/types-ts4.5/dialog/index.d.ts +3 -0
  244. package/dist/types-ts4.5/dialog/types.d.ts +92 -0
  245. package/dist/types-ts4.5/dialog-scroll-lock/index.d.ts +24 -0
  246. package/dist/types-ts4.5/entry-points/animations.d.ts +2 -0
  247. package/dist/types-ts4.5/entry-points/arrow.d.ts +2 -0
  248. package/dist/types-ts4.5/entry-points/create-close-event.d.ts +4 -0
  249. package/dist/types-ts4.5/entry-points/dialog-scroll-lock.d.ts +1 -0
  250. package/dist/types-ts4.5/entry-points/dialog.d.ts +2 -0
  251. package/dist/types-ts4.5/entry-points/focus.d.ts +2 -0
  252. package/dist/types-ts4.5/entry-points/placement-map.d.ts +2 -0
  253. package/dist/types-ts4.5/entry-points/popover.d.ts +2 -0
  254. package/dist/types-ts4.5/entry-points/popup-surface.d.ts +2 -0
  255. package/dist/types-ts4.5/entry-points/popup.d.ts +2 -0
  256. package/dist/types-ts4.5/entry-points/use-anchor-position.d.ts +1 -0
  257. package/dist/types-ts4.5/entry-points/use-arrow-navigation.d.ts +2 -0
  258. package/dist/types-ts4.5/entry-points/use-simple-light-dismiss.d.ts +2 -0
  259. package/dist/types-ts4.5/focus/focus.d.ts +42 -0
  260. package/dist/types-ts4.5/focus/index.d.ts +2 -0
  261. package/dist/types-ts4.5/index.d.ts +0 -0
  262. package/dist/types-ts4.5/internal/anchor-positioning-fallback.d.ts +24 -0
  263. package/dist/types-ts4.5/internal/combine.d.ts +14 -0
  264. package/dist/types-ts4.5/internal/ensure-preset-styles.d.ts +6 -0
  265. package/dist/types-ts4.5/internal/reduced-motion.d.ts +14 -0
  266. package/dist/types-ts4.5/internal/resolve-placement.d.ts +16 -0
  267. package/dist/types-ts4.5/internal/role-types.d.ts +62 -0
  268. package/dist/types-ts4.5/internal/set-style.d.ts +28 -0
  269. package/dist/types-ts4.5/internal/slot.d.ts +29 -0
  270. package/dist/types-ts4.5/internal/use-anchor-positioning.d.ts +95 -0
  271. package/dist/types-ts4.5/internal/use-animated-visibility.d.ts +74 -0
  272. package/dist/types-ts4.5/internal/use-animation-preset.d.ts +11 -0
  273. package/dist/types-ts4.5/internal/use-focus-wrap.d.ts +20 -0
  274. package/dist/types-ts4.5/internal/use-initial-focus.d.ts +21 -0
  275. package/dist/types-ts4.5/internal/use-preset-styles.d.ts +15 -0
  276. package/dist/types-ts4.5/placement-map/index.d.ts +55 -0
  277. package/dist/types-ts4.5/popover/create-close-event.d.ts +26 -0
  278. package/dist/types-ts4.5/popover/index.d.ts +3 -0
  279. package/dist/types-ts4.5/popover/popover.d.ts +22 -0
  280. package/dist/types-ts4.5/popover/types.d.ts +153 -0
  281. package/dist/types-ts4.5/popup/index.d.ts +34 -0
  282. package/dist/types-ts4.5/popup/popup-content.d.ts +14 -0
  283. package/dist/types-ts4.5/popup/popup-context.d.ts +96 -0
  284. package/dist/types-ts4.5/popup/popup-surface.d.ts +16 -0
  285. package/dist/types-ts4.5/popup/popup-trigger-function.d.ts +108 -0
  286. package/dist/types-ts4.5/popup/popup-trigger.d.ts +23 -0
  287. package/dist/types-ts4.5/popup/popup.d.ts +14 -0
  288. package/dist/types-ts4.5/popup/types.d.ts +289 -0
  289. package/dist/types-ts4.5/use-arrow-navigation/index.d.ts +2 -0
  290. package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +136 -0
  291. package/dist/types-ts4.5/use-simple-light-dismiss/index.d.ts +45 -0
  292. package/focus/package.json +17 -0
  293. package/package.json +95 -0
  294. package/placement-map/package.json +17 -0
  295. package/popover/package.json +17 -0
  296. package/popup/package.json +17 -0
  297. package/popup-surface/package.json +17 -0
  298. package/use-anchor-position/package.json +17 -0
  299. package/use-arrow-navigation/package.json +17 -0
  300. package/use-simple-light-dismiss/package.json +17 -0
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Computes the base {top, left} position based on the primary edge,
3
+ * flipping to the opposite side when there is not enough space.
4
+ */
5
+ function computeEdgePosition({
6
+ axis,
7
+ edge,
8
+ triggerRect,
9
+ popoverWidth,
10
+ popoverHeight,
11
+ viewport,
12
+ offset
13
+ }) {
14
+ if (axis === 'block' && edge === 'end') {
15
+ // Below trigger
16
+ const spaceBelow = viewport.height - triggerRect.bottom;
17
+ const spaceAbove = triggerRect.top;
18
+ return {
19
+ top: spaceBelow >= popoverHeight + offset || spaceBelow >= spaceAbove ? triggerRect.bottom + offset : triggerRect.top - popoverHeight - offset,
20
+ left: triggerRect.left + triggerRect.width / 2 - popoverWidth / 2
21
+ };
22
+ }
23
+ if (axis === 'block' && edge === 'start') {
24
+ // Above trigger
25
+ const spaceAbove = triggerRect.top;
26
+ const spaceBelow = viewport.height - triggerRect.bottom;
27
+ return {
28
+ top: spaceAbove >= popoverHeight + offset || spaceAbove >= spaceBelow ? triggerRect.top - popoverHeight - offset : triggerRect.bottom + offset,
29
+ left: triggerRect.left + triggerRect.width / 2 - popoverWidth / 2
30
+ };
31
+ }
32
+ if (axis === 'inline' && edge === 'end') {
33
+ // Right of trigger
34
+ const spaceRight = viewport.width - triggerRect.right;
35
+ const spaceLeft = triggerRect.left;
36
+ return {
37
+ top: triggerRect.top + triggerRect.height / 2 - popoverHeight / 2,
38
+ left: spaceRight >= popoverWidth + offset || spaceRight >= spaceLeft ? triggerRect.right + offset : triggerRect.left - popoverWidth - offset
39
+ };
40
+ }
41
+ if (axis === 'inline' && edge === 'start') {
42
+ // Left of trigger
43
+ const spaceLeft = triggerRect.left;
44
+ const spaceRight = viewport.width - triggerRect.right;
45
+ return {
46
+ top: triggerRect.top + triggerRect.height / 2 - popoverHeight / 2,
47
+ left: spaceLeft >= popoverWidth + offset || spaceLeft >= spaceRight ? triggerRect.left - popoverWidth - offset : triggerRect.right + offset
48
+ };
49
+ }
50
+
51
+ // Unreachable for valid placements; defaults to below trigger
52
+ return {
53
+ top: triggerRect.bottom + offset,
54
+ left: triggerRect.left + triggerRect.width / 2 - popoverWidth / 2
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Adjusts the base (centered) position for non-center alignments.
60
+ *
61
+ * `align: 'start'` → popover start edge at trigger start edge
62
+ * `align: 'end'` → popover end edge at trigger end edge
63
+ */
64
+ function applyAlignment({
65
+ position,
66
+ axis,
67
+ align,
68
+ triggerRect,
69
+ popoverWidth,
70
+ popoverHeight
71
+ }) {
72
+ if (align === 'center') {
73
+ return position;
74
+ }
75
+ if (axis === 'block') {
76
+ // Block-axis placement → cross-axis is inline (left/right)
77
+ if (align === 'start') {
78
+ return {
79
+ ...position,
80
+ left: triggerRect.left
81
+ };
82
+ }
83
+ // align === 'end'
84
+ return {
85
+ ...position,
86
+ left: triggerRect.right - popoverWidth
87
+ };
88
+ }
89
+
90
+ // Inline-axis placement → cross-axis is block (top/bottom)
91
+ if (align === 'start') {
92
+ return {
93
+ ...position,
94
+ top: triggerRect.top
95
+ };
96
+ }
97
+ // align === 'end'
98
+ return {
99
+ ...position,
100
+ top: triggerRect.bottom - popoverHeight
101
+ };
102
+ }
103
+
104
+ /**
105
+ * JS fallback: compute popover position from trigger rect and viewport.
106
+ *
107
+ * Placement algorithm (from the document):
108
+ * - "block" placement: show above/below, picking the side with more space if flipping needed
109
+ * - "inline" placement: show left/right, picking the side with more space if flipping needed
110
+ * - "auto" placement: show on the edge with the most available space
111
+ *
112
+ * Re-runs on scroll (capture on window) and resize events.
113
+ */
114
+ export function computeFallbackPosition({
115
+ triggerRect,
116
+ popoverEl,
117
+ placement,
118
+ viewport,
119
+ offset
120
+ }) {
121
+ const {
122
+ axis,
123
+ edge,
124
+ align
125
+ } = placement;
126
+
127
+ // Measure popover dimensions (it might not have layout yet if just shown)
128
+ const popoverWidth = popoverEl.offsetWidth;
129
+ const popoverHeight = popoverEl.offsetHeight;
130
+ const basePosition = computeEdgePosition({
131
+ axis,
132
+ edge,
133
+ triggerRect,
134
+ popoverWidth,
135
+ popoverHeight,
136
+ viewport,
137
+ offset
138
+ });
139
+ const alignedPosition = applyAlignment({
140
+ position: basePosition,
141
+ axis,
142
+ align,
143
+ triggerRect,
144
+ popoverWidth,
145
+ popoverHeight
146
+ });
147
+
148
+ // Clamp to viewport so the popover is never offscreen
149
+ return {
150
+ top: Math.max(0, Math.min(alignedPosition.top, viewport.height - popoverHeight)),
151
+ left: Math.max(0, Math.min(alignedPosition.left, viewport.width - popoverWidth))
152
+ };
153
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Combine multiple cleanup functions into a single cleanup function.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * useEffect(() => {
7
+ * return combine(
8
+ * bind(window, { type: 'resize', listener: onResize }),
9
+ * bind(window, { type: 'scroll', listener: onScroll, options: { capture: true } }),
10
+ * );
11
+ * }, []);
12
+ * ```
13
+ */
14
+ export function combine(...cleanupFns) {
15
+ return function cleanup() {
16
+ cleanupFns.forEach(fn => fn === null || fn === void 0 ? void 0 : fn());
17
+ };
18
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Per-preset CSS injection.
3
+ *
4
+ * Each preset's CSS is injected at most once into `<head>`.
5
+ * Shared by both PopoverContent and DialogContent.
6
+ *
7
+ * Note: injected `<style>` elements and the tracking Set are append-only —
8
+ * they are never removed. This is intentional: the number of distinct
9
+ * presets is bounded (handful of animation + arrow presets), so the
10
+ * memory footprint is negligible. Removing styles would risk breaking
11
+ * other instances of the same preset that are still mounted.
12
+ *
13
+ * Decision (2026-03-17 audit): Accepted as a non-issue. The bounded
14
+ * preset count (~5 presets) makes cleanup unnecessary. We plan to move
15
+ * to a Compiled-based solution which will handle style injection and
16
+ * deduplication natively.
17
+ */
18
+ const injectedPresets = new Set();
19
+ export function ensurePresetStyles({
20
+ preset
21
+ }) {
22
+ if (injectedPresets.has(preset.name) || typeof document === 'undefined') {
23
+ return;
24
+ }
25
+ injectedPresets.add(preset.name);
26
+ const style = document.createElement('style');
27
+ style.textContent = preset.css;
28
+ document.head.appendChild(style);
29
+ }
@@ -0,0 +1,21 @@
1
+ import once from '@atlaskit/ds-lib/once';
2
+
3
+ /**
4
+ * Returns `true` when the user prefers reduced motion.
5
+ *
6
+ * Safe for SSR (returns `false` when `window` is unavailable).
7
+ *
8
+ * The result is cached after the first call via `once`. This avoids
9
+ * calling `matchMedia` on every render. The trade-off is that if a user
10
+ * toggles the OS reduced-motion setting mid-session, the change won't
11
+ * take effect until the next page load. This is acceptable because
12
+ * toggling this system-level preference mid-session is extremely rare,
13
+ * and a page refresh is a reasonable expectation for system accessibility
14
+ * settings to take effect.
15
+ */
16
+ export const prefersReducedMotion = once(() => {
17
+ if (typeof window === 'undefined' || !('matchMedia' in window)) {
18
+ return false;
19
+ }
20
+ return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
21
+ });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Fully-resolved placement (internal). All fields are required.
3
+ * Use getPlacement({ placement: partial }) to obtain from partial input.
4
+ */
5
+
6
+ /**
7
+ * Resolves a partial placement to its fully-specified form.
8
+ * Defaults: `axis: 'block'`, `edge: 'end'`, `align: 'center'`.
9
+ */
10
+ export function getPlacement({
11
+ placement
12
+ }) {
13
+ var _placement$axis, _placement$edge, _placement$align;
14
+ return {
15
+ axis: (_placement$axis = placement.axis) !== null && _placement$axis !== void 0 ? _placement$axis : 'block',
16
+ edge: (_placement$edge = placement.edge) !== null && _placement$edge !== void 0 ? _placement$edge : 'end',
17
+ align: (_placement$align = placement.align) !== null && _placement$align !== void 0 ? _placement$align : 'center'
18
+ };
19
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Valid values for the `aria-haspopup` attribute.
3
+ * Derived from the HTML spec — maps popover roles to what the trigger announces.
4
+ */
5
+
6
+ /**
7
+ * Roles that require an accessible name (`label` or `labelledBy`) per WCAG 4.1.2.
8
+ * Without a name, assistive technology cannot identify these landmarks.
9
+ */
10
+
11
+ /**
12
+ * Roles where the accessible name is derived from content or provided externally
13
+ * (e.g. a combobox labels its listbox, tooltip content IS the accessible name).
14
+ */
15
+
16
+ // ── Shared ARIA role discrimination types ──
17
+ //
18
+ // These encode the WCAG 4.1.2 constraint: roles like `dialog`, `alertdialog`,
19
+ // and `menu` MUST have an accessible name (either `label` or `labelledBy`).
20
+ // TypeScript enforces this at compile time via discriminated unions.
21
+
22
+ /**
23
+ * ARIA role props where a role is always required.
24
+ *
25
+ * Used by `TPopupContentProps` — popup content must always declare
26
+ * its role so assistive technology can identify the layer.
27
+ */
28
+
29
+ /**
30
+ * ARIA role props where a role is optional.
31
+ *
32
+ * Used by `TPopoverProps` — the low-level primitive allows omitting
33
+ * the role for cases where it is set externally or not needed.
34
+ */
35
+
36
+ /**
37
+ * Maps a popover content role to the correct `aria-haspopup` value
38
+ * for its trigger element.
39
+ */
40
+ export function roleToAriaHasPopup({
41
+ role
42
+ }) {
43
+ if (role === 'menu') {
44
+ return 'menu';
45
+ }
46
+ if (role === 'listbox') {
47
+ return 'listbox';
48
+ }
49
+ if (role === 'tree') {
50
+ return 'tree';
51
+ }
52
+ if (role === 'grid') {
53
+ return 'grid';
54
+ }
55
+ // Default: return 'dialog' for all unmapped roles (tooltip, alertdialog,
56
+ // note, status, alert, log, etc). This is a kinder API — rather than
57
+ // throwing on unknown roles, we fall back to the most common popup type.
58
+ // New roles that need specific aria-haspopup values should be added
59
+ // as explicit cases above.
60
+ return 'dialog';
61
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Sets inline styles on an element and returns a cleanup function
3
+ * that removes only the styles that were applied.
4
+ *
5
+ * Uses `style.setProperty()` / `style.removeProperty()` so that
6
+ * hyphenated CSS property names (e.g. `position-area`, `anchor-name`)
7
+ * work correctly. These newer properties do not have camelCase
8
+ * mappings in `CSSStyleDeclaration` yet.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const cleanup = setStyle({ el: popover, styles: [
13
+ * { property: 'position-anchor', value: '--my-anchor' },
14
+ * { property: 'position-area', value: 'block-end' },
15
+ * { property: 'margin', value: '0' },
16
+ * ] });
17
+ *
18
+ * // Later: removes all three properties
19
+ * cleanup();
20
+ * ```
21
+ */
22
+ export function setStyle({
23
+ el,
24
+ styles
25
+ }) {
26
+ styles.forEach(({
27
+ property,
28
+ value
29
+ }) => {
30
+ el.style.setProperty(property, value);
31
+ });
32
+ return function cleanup() {
33
+ styles.forEach(({
34
+ property
35
+ }) => {
36
+ el.style.removeProperty(property);
37
+ });
38
+ };
39
+ }
@@ -0,0 +1,57 @@
1
+ import { cloneElement, forwardRef, isValidElement } from 'react';
2
+ import mergeRefs from '@atlaskit/ds-lib/merge-refs';
3
+
4
+ /**
5
+ * Extra DOM/event props are passed through to the cloned child.
6
+ */
7
+
8
+ /**
9
+ * Single element child: merge the caller ref with `child.ref`.
10
+ *
11
+ * Do not read `child.props.ref`: React keeps a `ref` key on `props` for
12
+ * host elements but accessing it logs a warning and returns `undefined`
13
+ * (ref lives on the element as `child.ref`).
14
+ */
15
+
16
+ function isSlotChild(child) {
17
+ return /*#__PURE__*/isValidElement(child);
18
+ }
19
+
20
+ /**
21
+ * Merges props (including ref) onto a single React element child.
22
+ *
23
+ * A safer alternative to raw `cloneElement` that:
24
+ * 1. Guards with `isValidElement` — non-element children (strings,
25
+ * fragments, null) are returned as-is instead of crashing.
26
+ * 2. Merges refs via `mergeRefs` so both the caller's ref and the
27
+ * child's existing ref are honoured.
28
+ * 3. Spreads any additional props (ARIA attributes, event handlers, etc.)
29
+ * onto the child element.
30
+ *
31
+ * Event handlers (e.g. `onClick`) are **not** auto-merged — the caller's
32
+ * handler replaces the child's. Compose handlers before passing them in.
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * <Slot ref={triggerRef} onClick={handleClick} aria-expanded={isOpen}>
37
+ * <button>Open</button>
38
+ * </Slot>
39
+ * ```
40
+ */
41
+ export const Slot = /*#__PURE__*/forwardRef(function Slot(slotProps, ref) {
42
+ const {
43
+ children: rawChildren,
44
+ ...props
45
+ } = slotProps;
46
+ // `SlotProps` intersects `Record<string, unknown>`, so `children` is typed as `unknown`.
47
+ const children = rawChildren;
48
+ if (!isSlotChild(children)) {
49
+ return children;
50
+ }
51
+
52
+ // eslint-disable-next-line @repo/internal/react/no-clone-element -- Slot is a controlled wrapper around cloneElement with isValidElement guard
53
+ return /*#__PURE__*/cloneElement(children, {
54
+ ...props,
55
+ ref: mergeRefs([ref, children.ref])
56
+ });
57
+ });