@react-aria/overlays 3.19.0 → 3.20.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 (182) hide show
  1. package/dist/ar-AE.main.js +6 -0
  2. package/dist/ar-AE.main.js.map +1 -0
  3. package/dist/ar-AE.mjs +8 -0
  4. package/dist/ar-AE.module.js +8 -0
  5. package/dist/ar-AE.module.js.map +1 -0
  6. package/dist/bg-BG.main.js +6 -0
  7. package/dist/bg-BG.main.js.map +1 -0
  8. package/dist/bg-BG.mjs +8 -0
  9. package/dist/bg-BG.module.js +8 -0
  10. package/dist/bg-BG.module.js.map +1 -0
  11. package/dist/cs-CZ.main.js +6 -0
  12. package/dist/cs-CZ.main.js.map +1 -0
  13. package/dist/cs-CZ.mjs +8 -0
  14. package/dist/cs-CZ.module.js +8 -0
  15. package/dist/cs-CZ.module.js.map +1 -0
  16. package/dist/da-DK.main.js +6 -0
  17. package/dist/da-DK.main.js.map +1 -0
  18. package/dist/da-DK.mjs +8 -0
  19. package/dist/da-DK.module.js +8 -0
  20. package/dist/da-DK.module.js.map +1 -0
  21. package/dist/de-DE.main.js +6 -0
  22. package/dist/de-DE.main.js.map +1 -0
  23. package/dist/de-DE.mjs +8 -0
  24. package/dist/de-DE.module.js +8 -0
  25. package/dist/de-DE.module.js.map +1 -0
  26. package/dist/el-GR.main.js +6 -0
  27. package/dist/el-GR.main.js.map +1 -0
  28. package/dist/el-GR.mjs +8 -0
  29. package/dist/el-GR.module.js +8 -0
  30. package/dist/el-GR.module.js.map +1 -0
  31. package/dist/en-US.main.js +6 -0
  32. package/dist/en-US.main.js.map +1 -0
  33. package/dist/en-US.mjs +8 -0
  34. package/dist/en-US.module.js +8 -0
  35. package/dist/en-US.module.js.map +1 -0
  36. package/dist/es-ES.main.js +6 -0
  37. package/dist/es-ES.main.js.map +1 -0
  38. package/dist/es-ES.mjs +8 -0
  39. package/dist/es-ES.module.js +8 -0
  40. package/dist/es-ES.module.js.map +1 -0
  41. package/dist/et-EE.main.js +6 -0
  42. package/dist/et-EE.main.js.map +1 -0
  43. package/dist/et-EE.mjs +8 -0
  44. package/dist/et-EE.module.js +8 -0
  45. package/dist/et-EE.module.js.map +1 -0
  46. package/dist/fi-FI.main.js +6 -0
  47. package/dist/fi-FI.main.js.map +1 -0
  48. package/dist/fi-FI.mjs +8 -0
  49. package/dist/fi-FI.module.js +8 -0
  50. package/dist/fi-FI.module.js.map +1 -0
  51. package/dist/fr-FR.main.js +6 -0
  52. package/dist/fr-FR.main.js.map +1 -0
  53. package/dist/fr-FR.mjs +8 -0
  54. package/dist/fr-FR.module.js +8 -0
  55. package/dist/fr-FR.module.js.map +1 -0
  56. package/dist/he-IL.main.js +6 -0
  57. package/dist/he-IL.main.js.map +1 -0
  58. package/dist/he-IL.mjs +8 -0
  59. package/dist/he-IL.module.js +8 -0
  60. package/dist/he-IL.module.js.map +1 -0
  61. package/dist/hr-HR.main.js +6 -0
  62. package/dist/hr-HR.main.js.map +1 -0
  63. package/dist/hr-HR.mjs +8 -0
  64. package/dist/hr-HR.module.js +8 -0
  65. package/dist/hr-HR.module.js.map +1 -0
  66. package/dist/hu-HU.main.js +6 -0
  67. package/dist/hu-HU.main.js.map +1 -0
  68. package/dist/hu-HU.mjs +8 -0
  69. package/dist/hu-HU.module.js +8 -0
  70. package/dist/hu-HU.module.js.map +1 -0
  71. package/dist/import.mjs +85 -206
  72. package/dist/it-IT.main.js +6 -0
  73. package/dist/it-IT.main.js.map +1 -0
  74. package/dist/it-IT.mjs +8 -0
  75. package/dist/it-IT.module.js +8 -0
  76. package/dist/it-IT.module.js.map +1 -0
  77. package/dist/ja-JP.main.js +6 -0
  78. package/dist/ja-JP.main.js.map +1 -0
  79. package/dist/ja-JP.mjs +8 -0
  80. package/dist/ja-JP.module.js +8 -0
  81. package/dist/ja-JP.module.js.map +1 -0
  82. package/dist/ko-KR.main.js +6 -0
  83. package/dist/ko-KR.main.js.map +1 -0
  84. package/dist/ko-KR.mjs +8 -0
  85. package/dist/ko-KR.module.js +8 -0
  86. package/dist/ko-KR.module.js.map +1 -0
  87. package/dist/lt-LT.main.js +6 -0
  88. package/dist/lt-LT.main.js.map +1 -0
  89. package/dist/lt-LT.mjs +8 -0
  90. package/dist/lt-LT.module.js +8 -0
  91. package/dist/lt-LT.module.js.map +1 -0
  92. package/dist/lv-LV.main.js +6 -0
  93. package/dist/lv-LV.main.js.map +1 -0
  94. package/dist/lv-LV.mjs +8 -0
  95. package/dist/lv-LV.module.js +8 -0
  96. package/dist/lv-LV.module.js.map +1 -0
  97. package/dist/main.js +85 -206
  98. package/dist/main.js.map +1 -1
  99. package/dist/module.js +85 -206
  100. package/dist/module.js.map +1 -1
  101. package/dist/nb-NO.main.js +6 -0
  102. package/dist/nb-NO.main.js.map +1 -0
  103. package/dist/nb-NO.mjs +8 -0
  104. package/dist/nb-NO.module.js +8 -0
  105. package/dist/nb-NO.module.js.map +1 -0
  106. package/dist/nl-NL.main.js +6 -0
  107. package/dist/nl-NL.main.js.map +1 -0
  108. package/dist/nl-NL.mjs +8 -0
  109. package/dist/nl-NL.module.js +8 -0
  110. package/dist/nl-NL.module.js.map +1 -0
  111. package/dist/pl-PL.main.js +6 -0
  112. package/dist/pl-PL.main.js.map +1 -0
  113. package/dist/pl-PL.mjs +8 -0
  114. package/dist/pl-PL.module.js +8 -0
  115. package/dist/pl-PL.module.js.map +1 -0
  116. package/dist/pt-BR.main.js +6 -0
  117. package/dist/pt-BR.main.js.map +1 -0
  118. package/dist/pt-BR.mjs +8 -0
  119. package/dist/pt-BR.module.js +8 -0
  120. package/dist/pt-BR.module.js.map +1 -0
  121. package/dist/pt-PT.main.js +6 -0
  122. package/dist/pt-PT.main.js.map +1 -0
  123. package/dist/pt-PT.mjs +8 -0
  124. package/dist/pt-PT.module.js +8 -0
  125. package/dist/pt-PT.module.js.map +1 -0
  126. package/dist/ro-RO.main.js +6 -0
  127. package/dist/ro-RO.main.js.map +1 -0
  128. package/dist/ro-RO.mjs +8 -0
  129. package/dist/ro-RO.module.js +8 -0
  130. package/dist/ro-RO.module.js.map +1 -0
  131. package/dist/ru-RU.main.js +6 -0
  132. package/dist/ru-RU.main.js.map +1 -0
  133. package/dist/ru-RU.mjs +8 -0
  134. package/dist/ru-RU.module.js +8 -0
  135. package/dist/ru-RU.module.js.map +1 -0
  136. package/dist/sk-SK.main.js +6 -0
  137. package/dist/sk-SK.main.js.map +1 -0
  138. package/dist/sk-SK.mjs +8 -0
  139. package/dist/sk-SK.module.js +8 -0
  140. package/dist/sk-SK.module.js.map +1 -0
  141. package/dist/sl-SI.main.js +6 -0
  142. package/dist/sl-SI.main.js.map +1 -0
  143. package/dist/sl-SI.mjs +8 -0
  144. package/dist/sl-SI.module.js +8 -0
  145. package/dist/sl-SI.module.js.map +1 -0
  146. package/dist/sr-SP.main.js +6 -0
  147. package/dist/sr-SP.main.js.map +1 -0
  148. package/dist/sr-SP.mjs +8 -0
  149. package/dist/sr-SP.module.js +8 -0
  150. package/dist/sr-SP.module.js.map +1 -0
  151. package/dist/sv-SE.main.js +6 -0
  152. package/dist/sv-SE.main.js.map +1 -0
  153. package/dist/sv-SE.mjs +8 -0
  154. package/dist/sv-SE.module.js +8 -0
  155. package/dist/sv-SE.module.js.map +1 -0
  156. package/dist/tr-TR.main.js +6 -0
  157. package/dist/tr-TR.main.js.map +1 -0
  158. package/dist/tr-TR.mjs +8 -0
  159. package/dist/tr-TR.module.js +8 -0
  160. package/dist/tr-TR.module.js.map +1 -0
  161. package/dist/types.d.ts +7 -0
  162. package/dist/types.d.ts.map +1 -1
  163. package/dist/uk-UA.main.js +6 -0
  164. package/dist/uk-UA.main.js.map +1 -0
  165. package/dist/uk-UA.mjs +8 -0
  166. package/dist/uk-UA.module.js +8 -0
  167. package/dist/uk-UA.module.js.map +1 -0
  168. package/dist/zh-CN.main.js +6 -0
  169. package/dist/zh-CN.main.js.map +1 -0
  170. package/dist/zh-CN.mjs +8 -0
  171. package/dist/zh-CN.module.js +8 -0
  172. package/dist/zh-CN.module.js.map +1 -0
  173. package/dist/zh-TW.main.js +6 -0
  174. package/dist/zh-TW.main.js.map +1 -0
  175. package/dist/zh-TW.mjs +8 -0
  176. package/dist/zh-TW.module.js +8 -0
  177. package/dist/zh-TW.module.js.map +1 -0
  178. package/package.json +8 -8
  179. package/src/DismissButton.tsx +3 -2
  180. package/src/useOverlay.ts +1 -1
  181. package/src/usePopover.ts +13 -4
  182. package/src/usePreventScroll.ts +56 -41
@@ -92,8 +92,9 @@ function preventScrollStandard() {
92
92
  //
93
93
  // 1. Prevent default on `touchmove` events that are not in a scrollable element. This prevents touch scrolling
94
94
  // on the window.
95
- // 2. Prevent default on `touchmove` events inside a scrollable element when the scroll position is at the
96
- // top or bottom. This avoids the whole page scrolling instead, but does prevent overscrolling.
95
+ // 2. Set `overscroll-behavior: contain` on nested scrollable regions so they do not scroll the page when at
96
+ // the top or bottom. Work around a bug where this does not work when the element does not actually overflow
97
+ // by preventing default in a `touchmove` event.
97
98
  // 3. Prevent default on `touchend` events on input elements and handle focusing the element ourselves.
98
99
  // 4. When focusing an input, apply a transform to trick Safari into thinking the input is at the top
99
100
  // of the page, which prevents it from scrolling the page. After the input is focused, scroll the element
@@ -105,15 +106,20 @@ function preventScrollStandard() {
105
106
  // to navigate to an input with the next/previous buttons that's outside a modal.
106
107
  function preventScrollMobileSafari() {
107
108
  let scrollable: Element;
108
- let lastY = 0;
109
+ let restoreScrollableStyles;
109
110
  let onTouchStart = (e: TouchEvent) => {
110
111
  // Store the nearest scrollable parent element from the element that the user touched.
111
- scrollable = getScrollParent(e.target as Element);
112
+ scrollable = getScrollParent(e.target as Element, true);
112
113
  if (scrollable === document.documentElement && scrollable === document.body) {
113
114
  return;
114
115
  }
115
116
 
116
- lastY = e.changedTouches[0].pageY;
117
+ // Prevent scrolling up when at the top and scrolling down when at the bottom
118
+ // of a nested scrollable area, otherwise mobile Safari will start scrolling
119
+ // the window instead.
120
+ if (scrollable instanceof HTMLElement && window.getComputedStyle(scrollable).overscrollBehavior === 'auto') {
121
+ restoreScrollableStyles = setStyle(scrollable, 'overscrollBehavior', 'contain');
122
+ }
117
123
  };
118
124
 
119
125
  let onTouchMove = (e: TouchEvent) => {
@@ -123,23 +129,15 @@ function preventScrollMobileSafari() {
123
129
  return;
124
130
  }
125
131
 
126
- // Prevent scrolling up when at the top and scrolling down when at the bottom
127
- // of a nested scrollable area, otherwise mobile Safari will start scrolling
128
- // the window instead. Unfortunately, this disables bounce scrolling when at
129
- // the top but it's the best we can do.
130
- let y = e.changedTouches[0].pageY;
131
- let scrollTop = scrollable.scrollTop;
132
- let bottom = scrollable.scrollHeight - scrollable.clientHeight;
133
-
134
- if (bottom === 0) {
135
- return;
136
- }
137
-
138
- if ((scrollTop <= 0 && y > lastY) || (scrollTop >= bottom && y < lastY)) {
132
+ // overscroll-behavior should prevent scroll chaining, but currently does not
133
+ // if the element doesn't actually overflow. https://bugs.webkit.org/show_bug.cgi?id=243452
134
+ // This checks that both the width and height do not overflow, otherwise we might
135
+ // block horizontal scrolling too. In that case, adding `touch-action: pan-x` to
136
+ // the element will prevent vertical page scrolling. We can't add that automatically
137
+ // because it must be set before the touchstart event.
138
+ if (scrollable.scrollHeight === scrollable.clientHeight && scrollable.scrollWidth === scrollable.clientWidth) {
139
139
  e.preventDefault();
140
140
  }
141
-
142
- lastY = y;
143
141
  };
144
142
 
145
143
  let onTouchEnd = (e: TouchEvent) => {
@@ -148,6 +146,7 @@ function preventScrollMobileSafari() {
148
146
  // Apply this change if we're not already focused on the target element
149
147
  if (willOpenKeyboard(target) && target !== document.activeElement) {
150
148
  e.preventDefault();
149
+ setupStyles();
151
150
 
152
151
  // Apply a transform to trick Safari into thinking the input is at the top of the page
153
152
  // so it doesn't try to scroll it into view. When tapping on an input, this needs to
@@ -158,11 +157,17 @@ function preventScrollMobileSafari() {
158
157
  target.style.transform = '';
159
158
  });
160
159
  }
160
+
161
+ if (restoreScrollableStyles) {
162
+ restoreScrollableStyles();
163
+ }
161
164
  };
162
165
 
163
166
  let onFocus = (e: FocusEvent) => {
164
167
  let target = e.target as HTMLElement;
165
168
  if (willOpenKeyboard(target)) {
169
+ setupStyles();
170
+
166
171
  // Transform also needs to be applied in the focus event in cases where focus moves
167
172
  // other than tapping on an input directly, e.g. the next/previous buttons in the
168
173
  // software keyboard. In these cases, it seems applying the transform in the focus event
@@ -190,40 +195,50 @@ function preventScrollMobileSafari() {
190
195
  }
191
196
  };
192
197
 
193
- let onWindowScroll = () => {
194
- // Last resort. If the window scrolled, scroll it back to the top.
195
- // It should always be at the top because the body will have a negative margin (see below).
196
- window.scrollTo(0, 0);
197
- };
198
+ let restoreStyles = null;
199
+ let setupStyles = () => {
200
+ if (restoreStyles) {
201
+ return;
202
+ }
198
203
 
199
- // Record the original scroll position so we can restore it.
200
- // Then apply a negative margin to the body to offset it by the scroll position. This will
201
- // enable us to scroll the window to the top, which is required for the rest of this to work.
202
- let scrollX = window.pageXOffset;
203
- let scrollY = window.pageYOffset;
204
+ let onWindowScroll = () => {
205
+ // Last resort. If the window scrolled, scroll it back to the top.
206
+ // It should always be at the top because the body will have a negative margin (see below).
207
+ window.scrollTo(0, 0);
208
+ };
204
209
 
205
- let restoreStyles = chain(
206
- setStyle(document.documentElement, 'paddingRight', `${window.innerWidth - document.documentElement.clientWidth}px`),
207
- setStyle(document.documentElement, 'overflow', 'hidden'),
208
- setStyle(document.body, 'marginTop', `-${scrollY}px`)
209
- );
210
+ // Record the original scroll position so we can restore it.
211
+ // Then apply a negative margin to the body to offset it by the scroll position. This will
212
+ // enable us to scroll the window to the top, which is required for the rest of this to work.
213
+ let scrollX = window.pageXOffset;
214
+ let scrollY = window.pageYOffset;
215
+
216
+ restoreStyles = chain(
217
+ addEvent(window, 'scroll', onWindowScroll),
218
+ setStyle(document.documentElement, 'paddingRight', `${window.innerWidth - document.documentElement.clientWidth}px`),
219
+ setStyle(document.documentElement, 'overflow', 'hidden'),
220
+ setStyle(document.body, 'marginTop', `-${scrollY}px`),
221
+ () => {
222
+ window.scrollTo(scrollX, scrollY);
223
+ }
224
+ );
210
225
 
211
- // Scroll to the top. The negative margin on the body will make this appear the same.
212
- window.scrollTo(0, 0);
226
+ // Scroll to the top. The negative margin on the body will make this appear the same.
227
+ window.scrollTo(0, 0);
228
+ };
213
229
 
214
230
  let removeEvents = chain(
215
231
  addEvent(document, 'touchstart', onTouchStart, {passive: false, capture: true}),
216
232
  addEvent(document, 'touchmove', onTouchMove, {passive: false, capture: true}),
217
233
  addEvent(document, 'touchend', onTouchEnd, {passive: false, capture: true}),
218
- addEvent(document, 'focus', onFocus, true),
219
- addEvent(window, 'scroll', onWindowScroll)
234
+ addEvent(document, 'focus', onFocus, true)
220
235
  );
221
236
 
222
237
  return () => {
223
238
  // Restore styles and scroll the page back to where it was.
224
- restoreStyles();
239
+ restoreScrollableStyles?.();
240
+ restoreStyles?.();
225
241
  removeEvents();
226
- window.scrollTo(scrollX, scrollY);
227
242
  };
228
243
  }
229
244