@octanejs/aria 0.0.46 → 0.0.48

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 (201) hide show
  1. package/README.md +7 -6
  2. package/UPSTREAM.md +58 -69
  3. package/package.json +11 -11
  4. package/src/calendar/useCalendarGrid.tsx +64 -62
  5. package/src/collections/Document.ts +3 -0
  6. package/src/color/useColorArea.tsx +95 -69
  7. package/src/color/useColorWheel.tsx +38 -37
  8. package/src/combobox/{useComboBox.ts → useComboBox.tsx} +243 -258
  9. package/src/components/ComboBox.ts +35 -2
  10. package/src/components/Dialog.ts +12 -1
  11. package/src/components/DropZone.tsx +3 -2
  12. package/src/components/FileTrigger.tsx +1 -0
  13. package/src/components/GridList.ts +11 -2
  14. package/src/components/ListBox.ts +1 -1
  15. package/src/components/Menu.ts +1 -0
  16. package/src/components/Meter.ts +3 -1
  17. package/src/components/Popover.ts +20 -8
  18. package/src/components/PreviewTrigger.tsx +101 -0
  19. package/src/components/ProgressBar.ts +10 -2
  20. package/src/components/Select.ts +1 -1
  21. package/src/components/Table.ts +26 -15
  22. package/src/components/TokenField.tsx +395 -0
  23. package/src/components/Tooltip.ts +4 -6
  24. package/src/components/Tree.ts +14 -7
  25. package/src/components/Virtualizer.tsx +30 -14
  26. package/src/components/index.ts +22 -0
  27. package/src/components/utils.ts +1 -1
  28. package/src/datepicker/useDateField.tsx +2 -11
  29. package/src/datepicker/useDatePickerGroup.tsx +44 -33
  30. package/src/datepicker/useDateSegment.tsx +31 -30
  31. package/src/dialog/useDialog.ts +8 -1
  32. package/src/dnd/DragManager.tsx +5 -1
  33. package/src/dnd/useDrag.tsx +2 -1
  34. package/src/focus/FocusScope.ts +2 -2
  35. package/src/grid/useGrid.ts +3 -0
  36. package/src/grid/{useGridCell.ts → useGridCell.tsx} +128 -66
  37. package/src/grid/utils.ts +1 -0
  38. package/src/gridlist/{useGridListItem.ts → useGridListItem.tsx} +154 -112
  39. package/src/index.ts +22 -0
  40. package/src/interactions/createEventHandler.ts +11 -8
  41. package/src/interactions/createKeyboardShortcutHandler.tsx +218 -0
  42. package/src/interactions/textSelection.ts +3 -3
  43. package/src/interactions/useContextMenu.tsx +125 -0
  44. package/src/interactions/useFocusVisible.ts +4 -4
  45. package/src/interactions/useKeyboard.ts +50 -2
  46. package/src/interactions/useLongPress.ts +33 -22
  47. package/src/interactions/useMove.ts +6 -6
  48. package/src/interactions/usePress.ts +8 -0
  49. package/src/interactions/utils.ts +10 -10
  50. package/src/intl/combobox/fi-FI.json +2 -2
  51. package/src/intl/previewtrigger/ar-AE.json +3 -0
  52. package/src/intl/previewtrigger/bg-BG.json +3 -0
  53. package/src/intl/previewtrigger/cs-CZ.json +3 -0
  54. package/src/intl/previewtrigger/da-DK.json +3 -0
  55. package/src/intl/previewtrigger/de-DE.json +3 -0
  56. package/src/intl/previewtrigger/el-GR.json +3 -0
  57. package/src/intl/previewtrigger/en-US.json +3 -0
  58. package/src/intl/previewtrigger/es-ES.json +3 -0
  59. package/src/intl/previewtrigger/et-EE.json +3 -0
  60. package/src/intl/previewtrigger/fi-FI.json +3 -0
  61. package/src/intl/previewtrigger/fr-FR.json +3 -0
  62. package/src/intl/previewtrigger/he-IL.json +3 -0
  63. package/src/intl/previewtrigger/hr-HR.json +3 -0
  64. package/src/intl/previewtrigger/hu-HU.json +3 -0
  65. package/src/intl/previewtrigger/index.ts +73 -0
  66. package/src/intl/previewtrigger/it-IT.json +3 -0
  67. package/src/intl/previewtrigger/ja-JP.json +3 -0
  68. package/src/intl/previewtrigger/ko-KR.json +3 -0
  69. package/src/intl/previewtrigger/lt-LT.json +3 -0
  70. package/src/intl/previewtrigger/lv-LV.json +3 -0
  71. package/src/intl/previewtrigger/nb-NO.json +3 -0
  72. package/src/intl/previewtrigger/nl-NL.json +3 -0
  73. package/src/intl/previewtrigger/pl-PL.json +3 -0
  74. package/src/intl/previewtrigger/pt-BR.json +3 -0
  75. package/src/intl/previewtrigger/pt-PT.json +3 -0
  76. package/src/intl/previewtrigger/ro-RO.json +3 -0
  77. package/src/intl/previewtrigger/ru-RU.json +3 -0
  78. package/src/intl/previewtrigger/sk-SK.json +3 -0
  79. package/src/intl/previewtrigger/sl-SI.json +3 -0
  80. package/src/intl/previewtrigger/sr-SP.json +3 -0
  81. package/src/intl/previewtrigger/sv-SE.json +3 -0
  82. package/src/intl/previewtrigger/tr-TR.json +3 -0
  83. package/src/intl/previewtrigger/uk-UA.json +3 -0
  84. package/src/intl/previewtrigger/zh-CN.json +3 -0
  85. package/src/intl/previewtrigger/zh-TW.json +3 -0
  86. package/src/intl/table/ar-AE.json +3 -3
  87. package/src/intl/table/bg-BG.json +3 -3
  88. package/src/intl/table/cs-CZ.json +3 -3
  89. package/src/intl/table/da-DK.json +3 -3
  90. package/src/intl/table/de-DE.json +3 -3
  91. package/src/intl/table/el-GR.json +3 -3
  92. package/src/intl/table/es-ES.json +3 -3
  93. package/src/intl/table/et-EE.json +3 -3
  94. package/src/intl/table/fi-FI.json +3 -3
  95. package/src/intl/table/fr-FR.json +3 -3
  96. package/src/intl/table/he-IL.json +3 -3
  97. package/src/intl/table/hr-HR.json +3 -3
  98. package/src/intl/table/hu-HU.json +3 -3
  99. package/src/intl/table/it-IT.json +3 -3
  100. package/src/intl/table/ja-JP.json +3 -3
  101. package/src/intl/table/ko-KR.json +3 -3
  102. package/src/intl/table/lt-LT.json +3 -3
  103. package/src/intl/table/lv-LV.json +3 -3
  104. package/src/intl/table/nb-NO.json +3 -3
  105. package/src/intl/table/nl-NL.json +3 -3
  106. package/src/intl/table/pl-PL.json +3 -3
  107. package/src/intl/table/pt-BR.json +3 -3
  108. package/src/intl/table/pt-PT.json +3 -3
  109. package/src/intl/table/ro-RO.json +3 -3
  110. package/src/intl/table/ru-RU.json +3 -3
  111. package/src/intl/table/sk-SK.json +3 -3
  112. package/src/intl/table/sl-SI.json +3 -3
  113. package/src/intl/table/sr-SP.json +3 -3
  114. package/src/intl/table/sv-SE.json +3 -3
  115. package/src/intl/table/tr-TR.json +3 -3
  116. package/src/intl/table/uk-UA.json +3 -3
  117. package/src/intl/table/zh-CN.json +4 -4
  118. package/src/intl/table/zh-TW.json +3 -3
  119. package/src/intl/tree/es-ES.json +1 -1
  120. package/src/link/useLink.ts +2 -0
  121. package/src/menu/useMenuItem.ts +33 -36
  122. package/src/menu/useMenuTrigger.tsx +222 -0
  123. package/src/menu/{useSubmenuTrigger.ts → useSubmenuTrigger.tsx} +116 -151
  124. package/src/numberfield/{useNumberField.ts → useNumberField.tsx} +188 -238
  125. package/src/overlays/Overlay.ts +5 -1
  126. package/src/overlays/ariaHideOutside.ts +6 -8
  127. package/src/overlays/useCloseOnScroll.ts +7 -5
  128. package/src/overlays/{useOverlay.ts → useOverlay.tsx} +76 -83
  129. package/src/overlays/usePopover.ts +10 -5
  130. package/src/overlays/usePreventScroll.ts +4 -4
  131. package/src/progress/useProgressBar.ts +2 -1
  132. package/src/radio/{useRadioGroup.ts → useRadioGroup.tsx} +87 -79
  133. package/src/searchfield/useSearchField.tsx +152 -0
  134. package/src/select/useSelect.ts +20 -20
  135. package/src/selection/useSelectableCollection.tsx +755 -0
  136. package/src/selection/useSelectableItem.ts +48 -11
  137. package/src/slider/{useSliderThumb.ts → useSliderThumb.tsx} +120 -158
  138. package/src/spinbutton/useSpinButton.tsx +335 -0
  139. package/src/stately/combobox/useComboBoxState.ts +1 -1
  140. package/src/stately/grid/useGridState.ts +9 -10
  141. package/src/stately/index.ts +11 -0
  142. package/src/stately/menu/useMenuTriggerState.ts +1 -1
  143. package/src/stately/menu/useSubmenuTriggerState.ts +2 -0
  144. package/src/stately/overlays/useOverlayTriggerState.ts +12 -1
  145. package/src/stately/radio/useRadioGroupState.ts +5 -1
  146. package/src/stately/table/TableUtils.ts +15 -1
  147. package/src/stately/table/useTableState.ts +7 -0
  148. package/src/stately/tokenfield/TokenFieldValue.tsx +440 -0
  149. package/src/stately/tokenfield/useTokenFieldState.tsx +57 -0
  150. package/src/stately/tooltip/useTooltipTriggerState.ts +16 -7
  151. package/src/stately/virtualizer/Layout.tsx +2 -0
  152. package/src/stately/virtualizer/ScrollAnchor.tsx +338 -0
  153. package/src/stately/virtualizer/Virtualizer.tsx +52 -1
  154. package/src/stately/virtualizer/types.tsx +2 -0
  155. package/src/table/useTableCell.ts +12 -0
  156. package/src/table/useTableColumnHeader.ts +8 -1
  157. package/src/table/useTableColumnResize.tsx +359 -0
  158. package/src/tag/useTag.ts +22 -15
  159. package/src/textfield/useTextField.ts +2 -0
  160. package/src/tokenfield/useToken.tsx +64 -0
  161. package/src/tokenfield/useTokenField.tsx +849 -0
  162. package/src/tooltip/usePreviewTrigger.tsx +266 -0
  163. package/src/tooltip/useSafeArea.tsx +171 -0
  164. package/src/upstream-exports/react-aria/mergeRefs.tsx +3 -0
  165. package/src/upstream-exports/react-aria/usePreviewTrigger.tsx +18 -0
  166. package/src/upstream-exports/react-aria/useTokenField.tsx +22 -0
  167. package/src/upstream-exports/react-stately/private/collections/getChildNodes.tsx +8 -0
  168. package/src/upstream-exports/react-stately/private/collections/getItemCount.tsx +2 -0
  169. package/src/upstream-exports/react-stately/private/grid/GridCollection.tsx +7 -0
  170. package/src/upstream-exports/react-stately/private/grid/useGridState.tsx +6 -0
  171. package/src/upstream-exports/react-stately/private/utils/number.tsx +2 -0
  172. package/src/upstream-exports/react-stately/useComboBoxState.tsx +23 -0
  173. package/src/upstream-exports/react-stately/useListState.tsx +15 -0
  174. package/src/upstream-exports/react-stately/useMenuTriggerState.tsx +26 -0
  175. package/src/upstream-exports/react-stately/useMultipleSelectionState.tsx +21 -0
  176. package/src/upstream-exports/react-stately/useNumberFieldState.tsx +20 -0
  177. package/src/upstream-exports/react-stately/useOverlayTriggerState.tsx +20 -0
  178. package/src/upstream-exports/react-stately/useRadioGroupState.tsx +16 -0
  179. package/src/upstream-exports/react-stately/useSearchFieldState.tsx +19 -0
  180. package/src/upstream-exports/react-stately/useSliderState.tsx +20 -0
  181. package/src/upstream-exports/react-stately/useTableState.tsx +45 -0
  182. package/src/upstream-exports/react-stately/useTokenFieldState.tsx +25 -0
  183. package/src/upstream-exports/react-stately/useTooltipTriggerState.tsx +20 -0
  184. package/src/upstream-exports/react-stately/useTreeState.tsx +14 -0
  185. package/src/utils/domHelpers.ts +74 -17
  186. package/src/utils/isVirtualEvent.ts +2 -1
  187. package/src/utils/openLink.ts +8 -3
  188. package/src/utils/platform.ts +7 -3
  189. package/src/utils/scrollIntoView.ts +4 -4
  190. package/src/utils/shadowdom/DOMFunctions.ts +42 -2
  191. package/src/utils/useId.ts +11 -2
  192. package/src/utils/useLoadMoreSentinel.ts +8 -3
  193. package/src/utils/useViewportSize.ts +3 -3
  194. package/src/virtualizer/ScrollView.tsx +13 -4
  195. package/src/virtualizer/VirtualizerItem.tsx +4 -1
  196. package/src/virtualizer/useVirtualizerItem.tsx +43 -3
  197. package/src/menu/useMenuTrigger.ts +0 -189
  198. package/src/searchfield/useSearchField.ts +0 -156
  199. package/src/selection/useSelectableCollection.ts +0 -750
  200. package/src/spinbutton/useSpinButton.ts +0 -380
  201. package/src/table/useTableColumnResize.ts +0 -374
@@ -1,12 +1,13 @@
1
1
  /** @jsxImportSource octane */
2
- // Ported from adobe/react-spectrum@1c84a49a1faf50b571c84e00bcf9c60b22ddd03e (packages/react-aria/src/datepicker/useDatePickerGroup.ts).
2
+ // Ported from adobe/react-spectrum@5ecb3333001313e83898cd07644227897e3bae1f (packages/react-aria/src/datepicker/useDatePickerGroup.ts).
3
3
  import { createFocusManager, getFocusableTreeWalker } from '../focus/FocusScope';
4
4
  import { DateFieldState } from '../upstream-exports/react-stately/useDateFieldState';
5
5
  import { DatePickerState } from '../upstream-exports/react-stately/useDatePickerState';
6
6
  import { DateRangePickerState } from '../upstream-exports/react-stately/useDateRangePickerState';
7
- import { DOMAttributes, FocusableElement, KeyboardEvent, RefObject } from '@react-types/shared';
8
- import { getEventTarget, nodeContains } from '../utils/shadowdom/DOMFunctions';
7
+ import { DOMAttributes, FocusableElement, RefObject } from '@react-types/shared';
8
+ import { getEventTarget } from '../utils/shadowdom/DOMFunctions';
9
9
  import { mergeProps } from '../utils/mergeProps';
10
+ import { useKeyboard } from '../interactions/useKeyboard';
10
11
  import { useLocale } from '../i18n/I18nProvider';
11
12
  import { useMemo } from '../compat/react';
12
13
  import { usePress } from '../interactions/usePress';
@@ -17,59 +18,68 @@ export function useDatePickerGroup(
17
18
  disableArrowNavigation?: boolean,
18
19
  ): DOMAttributes<FocusableElement> {
19
20
  let { direction } = useLocale();
21
+ // oxlint-disable-next-line react/react-compiler
20
22
  let focusManager = useMemo(() => createFocusManager(ref), [ref]);
21
23
 
22
- // Open the popover on alt + arrow down
23
- let onKeyDown = (e: KeyboardEvent) => {
24
- if (!nodeContains(e.currentTarget, getEventTarget(e as unknown as Event) as Element)) {
25
- return;
26
- }
27
-
28
- if (e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp') && 'setOpen' in state) {
29
- e.preventDefault();
30
- e.stopPropagation();
31
- state.setOpen(true);
32
- }
33
-
34
- if (disableArrowNavigation) {
35
- return;
36
- }
37
-
38
- switch (e.key) {
39
- case 'ArrowLeft':
40
- e.preventDefault();
41
- e.stopPropagation();
24
+ let { keyboardProps } = useKeyboard({
25
+ shortcuts: {
26
+ 'Alt+ArrowDown': () => {
27
+ if ('setOpen' in state) {
28
+ state.setOpen(true);
29
+ return;
30
+ }
31
+ return false;
32
+ },
33
+ 'Alt+ArrowUp': () => {
34
+ if ('setOpen' in state) {
35
+ state.setOpen(true);
36
+ return;
37
+ }
38
+ return false;
39
+ },
40
+ ArrowLeft: (e) => {
41
+ if (disableArrowNavigation) {
42
+ return false;
43
+ }
42
44
  if (direction === 'rtl') {
43
45
  if (ref.current) {
44
- let target = getEventTarget(e as unknown as Event) as FocusableElement;
46
+ let target = getEventTarget(e) as FocusableElement;
45
47
  let prev = findNextSegment(ref.current, target.getBoundingClientRect().left, -1);
46
48
 
47
49
  if (prev) {
48
50
  prev.focus();
51
+ return;
49
52
  }
50
53
  }
51
54
  } else {
52
55
  focusManager.focusPrevious();
56
+ return;
57
+ }
58
+ return false;
59
+ },
60
+ ArrowRight: (e) => {
61
+ if (disableArrowNavigation) {
62
+ return false;
53
63
  }
54
- break;
55
- case 'ArrowRight':
56
- e.preventDefault();
57
- e.stopPropagation();
58
64
  if (direction === 'rtl') {
59
65
  if (ref.current) {
60
- let target = getEventTarget(e as unknown as Event) as FocusableElement;
66
+ let target = getEventTarget(e) as FocusableElement;
61
67
  let next = findNextSegment(ref.current, target.getBoundingClientRect().left, 1);
62
68
 
63
69
  if (next) {
64
70
  next.focus();
71
+ return;
65
72
  }
66
73
  }
67
74
  } else {
68
75
  focusManager.focusNext();
76
+ return;
69
77
  }
70
- break;
71
- }
72
- };
78
+ return false;
79
+ },
80
+ },
81
+ allowRepeats: true,
82
+ });
73
83
 
74
84
  // Focus the first placeholder segment from the end on mouse down/touch up in the field.
75
85
  let focusLast = () => {
@@ -125,7 +135,8 @@ export function useDatePickerGroup(
125
135
  },
126
136
  });
127
137
 
128
- return mergeProps(pressProps, { onKeyDown });
138
+ // oxlint-disable-next-line react/react-compiler
139
+ return mergeProps(pressProps, keyboardProps);
129
140
  }
130
141
 
131
142
  function findNextSegment(group: Element, fromX: number, direction: number) {
@@ -1,5 +1,5 @@
1
1
  /** @jsxImportSource octane */
2
- // Ported from adobe/react-spectrum@1c84a49a1faf50b571c84e00bcf9c60b22ddd03e (packages/react-aria/src/datepicker/useDateSegment.ts).
2
+ // Ported from adobe/react-spectrum@5ecb3333001313e83898cd07644227897e3bae1f (packages/react-aria/src/datepicker/useDateSegment.ts).
3
3
  /*
4
4
  * Copyright 2020 Adobe. All rights reserved.
5
5
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,7 @@ import { DateFieldState, DateSegment } from '../upstream-exports/react-stately/u
17
17
  import { getActiveElement, nodeContains } from '../utils/shadowdom/DOMFunctions';
18
18
  import { getScrollParent } from '../utils/getScrollParent';
19
19
  import { hookData } from './useDateField';
20
- import { isIOS, isMac } from '../utils/platform';
20
+ import { isIOS } from '../utils/platform';
21
21
  import { mergeProps } from '../utils/mergeProps';
22
22
  import { NumberParser } from '@internationalized/number';
23
23
  import React, { CSSProperties, useMemo, useRef } from '../compat/react';
@@ -28,6 +28,7 @@ import { useDisplayNames } from './useDisplayNames';
28
28
  import { useEvent } from '../utils/useEvent';
29
29
  import { useFilter } from '../i18n/useFilter';
30
30
  import { useId } from '../utils/useId';
31
+ import { useKeyboard } from '../interactions/useKeyboard';
31
32
  import { useLabels } from '../utils/useLabels';
32
33
  import { useLayoutEffect } from '../utils/useLayoutEffect';
33
34
  import { useLocale } from '../i18n/I18nProvider';
@@ -127,28 +128,21 @@ export function useDateSegment(
127
128
  }
128
129
  };
129
130
 
130
- let onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
131
- // Firefox does not fire selectstart for Ctrl/Cmd + A
132
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1742153
133
- if (e.key === 'a' && (isMac() ? e.metaKey : e.ctrlKey)) {
134
- e.preventDefault();
135
- }
136
-
137
- if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) {
138
- return;
139
- }
140
-
141
- switch (e.key) {
142
- case 'Backspace':
143
- case 'Delete': {
144
- // Safari on iOS does not fire beforeinput for the backspace key because the cursor is at the start.
145
- e.preventDefault();
146
- e.stopPropagation();
131
+ let { keyboardProps } = useKeyboard({
132
+ shortcuts: {
133
+ Backspace: () => {
147
134
  backspace();
148
- break;
149
- }
150
- }
151
- };
135
+ },
136
+ Delete: () => {
137
+ backspace();
138
+ },
139
+ 'Mod+a': () => {
140
+ // Firefox does not fire selectstart for Ctrl/Cmd + A
141
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1742153
142
+ },
143
+ },
144
+ allowRepeats: true,
145
+ });
152
146
 
153
147
  // Safari dayPeriod option doesn't work...
154
148
  let { startsWith } = useFilter({ sensitivity: 'base' });
@@ -273,7 +267,13 @@ export function useDateSegment(
273
267
  // Otherwise, when tapping on a segment in Android Chrome and then entering text,
274
268
  // composition events will be fired that break the DOM structure and crash the page.
275
269
  let selection = window.getSelection();
276
- if (selection?.anchorNode && nodeContains(ref.current, selection?.anchorNode)) {
270
+ // Only collapse while focused, otherwise a stale anchor left in the segment (e.g. on Firefox)
271
+ // steals focus back into it on selectionchange. See #10259.
272
+ if (
273
+ selection?.anchorNode &&
274
+ nodeContains(ref.current, selection?.anchorNode) &&
275
+ getActiveElement() === ref.current
276
+ ) {
277
277
  selection.collapse(ref.current);
278
278
  }
279
279
  });
@@ -393,32 +393,33 @@ export function useDateSegment(
393
393
  }
394
394
 
395
395
  return {
396
+ // oxlint-disable-next-line react/react-compiler
396
397
  segmentProps: mergeProps(spinButtonProps, labelProps, {
397
398
  id,
398
399
  ...touchPropOverrides,
400
+ ...keyboardProps,
399
401
  'aria-invalid': state.isInvalid ? 'true' : undefined,
400
402
  'aria-describedby': ariaDescribedBy,
401
403
  'aria-readonly': state.isReadOnly || !segment.isEditable ? 'true' : undefined,
402
404
  'data-placeholder': segment.isPlaceholder || undefined,
403
405
  contentEditable: isEditable,
404
406
  suppressContentEditableWarning: isEditable,
405
- spellCheck: isEditable ? 'false' : undefined,
407
+ spellCheck: isEditable ? ('false' as const) : undefined,
406
408
  autoCorrect: isEditable ? 'off' : undefined,
407
- // Octane uses the modern DOM property name regardless of its package version.
409
+ // Capitalization was changed in React 17...
408
410
  enterKeyHint: isEditable ? 'next' : undefined,
409
411
  inputMode:
410
412
  state.isDisabled || segment.type === 'dayPeriod' || segment.type === 'era' || !isEditable
411
413
  ? undefined
412
- : 'numeric',
414
+ : ('numeric' as const),
413
415
  tabIndex: state.isDisabled ? undefined : 0,
414
- onKeyDown,
415
416
  onFocus,
416
417
  style: segmentStyle,
417
418
  // Prevent pointer events from reaching useDatePickerGroup, and allow native browser behavior to focus the segment.
418
- onPointerDown(e: React.PointerEvent<HTMLDivElement>) {
419
+ onPointerDown(e: PointerEvent) {
419
420
  e.stopPropagation();
420
421
  },
421
- onMouseDown(e: React.MouseEvent<HTMLDivElement>) {
422
+ onMouseDown(e: MouseEvent) {
422
423
  e.stopPropagation();
423
424
  },
424
425
  }),
@@ -34,6 +34,7 @@ export interface DialogAria {
34
34
 
35
35
  /** Props for the dialog title element. */
36
36
  titleProps: DOMAttributes;
37
+ contentProps: DOMAttributes;
37
38
  }
38
39
 
39
40
  /**
@@ -60,6 +61,9 @@ export function useDialog(...args: any[]): DialogAria {
60
61
  let titleId: string | undefined = useSlotId(undefined, subSlot(slot, 'title'));
61
62
  titleId = props['aria-label'] ? undefined : titleId;
62
63
 
64
+ let contentId: string | undefined = useSlotId(undefined, subSlot(slot, 'content'));
65
+ contentId = role === 'alertdialog' && !props['aria-describedby'] ? contentId : undefined;
66
+
63
67
  let isRefocusing = useRef(false, subSlot(slot, 'refocusing'));
64
68
 
65
69
  // Focus the dialog itself on mount, unless a child element is already focused.
@@ -125,12 +129,14 @@ export function useDialog(...args: any[]): DialogAria {
125
129
  // See https://bugs.webkit.org/show_bug.cgi?id=211934.
126
130
  // useModal sets aria-hidden on all elements outside the dialog, so the dialog will behave as a modal
127
131
  // even without aria-modal on the dialog itself.
132
+ let ariaDescribedby = props['aria-describedby'] ?? contentId;
128
133
  return {
129
134
  dialogProps: {
130
135
  ...filterDOMProps(props, { labelable: true }),
131
136
  role,
132
137
  tabIndex: -1,
133
- 'aria-labelledby': props['aria-labelledby'] || titleId,
138
+ 'aria-labelledby': props['aria-labelledby'] ?? titleId,
139
+ 'aria-describedby': ariaDescribedby,
134
140
  // Prevent blur events from reaching useOverlay, which may cause
135
141
  // popovers to close. Since focus is contained within the dialog,
136
142
  // we don't want this to occur due to the above useEffect.
@@ -140,6 +146,7 @@ export function useDialog(...args: any[]): DialogAria {
140
146
  }
141
147
  },
142
148
  },
149
+ contentProps: { id: contentId },
143
150
  titleProps: {
144
151
  id: titleId,
145
152
  },
@@ -532,8 +532,12 @@ class DragSession {
532
532
 
533
533
  let minDistance = Infinity;
534
534
  let nearest = -1;
535
+ let ancestor = -1;
535
536
  for (let i = 0; i < this.validDropTargets.length; i++) {
536
537
  let dropTarget = this.validDropTargets[i];
538
+ if (ancestor < 0 && nodeContains(dropTarget.element, this.dragTarget.element)) {
539
+ ancestor = i;
540
+ }
537
541
  let rect = dropTarget.element.getBoundingClientRect();
538
542
  let dx = rect.left - dragTargetRect.left;
539
543
  let dy = rect.top - dragTargetRect.top;
@@ -544,7 +548,7 @@ class DragSession {
544
548
  }
545
549
  }
546
550
 
547
- return nearest;
551
+ return ancestor >= 0 ? ancestor : nearest;
548
552
  }
549
553
 
550
554
  setCurrentDropTarget(dropTarget: DropTarget | null, item?: DroppableItem): void {
@@ -1,4 +1,5 @@
1
1
  /** @jsxImportSource octane */
2
+ import { isIOS, isWebKit } from '../utils/platform';
2
3
  // Ported from adobe/react-spectrum@1c84a49a1faf50b571c84e00bcf9c60b22ddd03e (packages/react-aria/src/dnd/useDrag.ts).
3
4
  /*
4
5
  * Copyright 2020 Adobe. All rights reserved.
@@ -368,7 +369,7 @@ export function useDrag(options: DragOptions): DragResult {
368
369
  modalityOnPointerDown.current = isVirtualPointerEvent(e) ? 'virtual' : e.pointerType;
369
370
 
370
371
  // Try to detect virtual drag passthrough gestures.
371
- if (e.width < 1 && e.height < 1) {
372
+ if (e.width < 1 && e.height < 1 && isIOS() && isWebKit()) {
372
373
  // iOS VoiceOver.
373
374
  modalityOnPointerDown.current = 'virtual';
374
375
  } else {
@@ -462,7 +462,7 @@ function useFocusContainment(
462
462
  // If a focus event occurs outside the active scope (e.g. user tabs from browser location bar),
463
463
  // restore focus to the previously focused node or the first tabbable element in the active scope.
464
464
  if (focusedNode.current) {
465
- focusedNode.current.focus();
465
+ focusElement(focusedNode.current);
466
466
  } else if (activeScope && activeScope.current) {
467
467
  focusFirstInScope(activeScope.current);
468
468
  }
@@ -496,7 +496,7 @@ function useFocusContainment(
496
496
  let target = getEventTarget(e) as FocusableElement;
497
497
  if (target && target.isConnected) {
498
498
  focusedNode.current = target;
499
- focusedNode.current?.focus();
499
+ focusElement(focusedNode.current);
500
500
  } else if (activeScope.current) {
501
501
  focusFirstInScope(activeScope.current);
502
502
  }
@@ -85,6 +85,7 @@ export interface GridProps extends DOMProps, AriaLabelingProps {
85
85
  escapeKeyBehavior?: 'clearSelection' | 'none';
86
86
  /** Whether selection should occur on press up instead of press down. */
87
87
  shouldSelectOnPressUp?: boolean;
88
+ keyboardNavigationBehavior?: 'arrow' | 'tab';
88
89
  }
89
90
 
90
91
  export interface GridAria {
@@ -130,6 +131,7 @@ export function useGrid(...args: any[]): GridAria {
130
131
  onRowAction,
131
132
  onCellAction,
132
133
  escapeKeyBehavior = 'clearSelection',
134
+ keyboardNavigationBehavior = 'arrow',
133
135
  shouldSelectOnPressUp,
134
136
  } = props;
135
137
  let { selectionManager: manager } = state;
@@ -185,6 +187,7 @@ export function useGrid(...args: any[]): GridAria {
185
187
  gridMap.set(state, {
186
188
  keyboardDelegate: delegate,
187
189
  actions: { onRowAction, onCellAction },
190
+ keyboardNavigationBehavior,
188
191
  shouldSelectOnPressUp,
189
192
  });
190
193