@octanejs/aria 0.0.46 → 0.0.47
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.
- package/README.md +7 -6
- package/UPSTREAM.md +58 -69
- package/package.json +11 -11
- package/src/calendar/useCalendarGrid.tsx +64 -62
- package/src/collections/Document.ts +3 -0
- package/src/color/useColorArea.tsx +95 -69
- package/src/color/useColorWheel.tsx +38 -37
- package/src/combobox/{useComboBox.ts → useComboBox.tsx} +239 -259
- package/src/components/ComboBox.ts +35 -2
- package/src/components/Dialog.ts +12 -1
- package/src/components/DropZone.tsx +3 -2
- package/src/components/FileTrigger.tsx +1 -0
- package/src/components/GridList.ts +11 -2
- package/src/components/ListBox.ts +1 -1
- package/src/components/Menu.ts +1 -0
- package/src/components/Meter.ts +3 -1
- package/src/components/Popover.ts +20 -8
- package/src/components/PreviewTrigger.tsx +101 -0
- package/src/components/ProgressBar.ts +10 -2
- package/src/components/Select.ts +1 -1
- package/src/components/Table.ts +26 -15
- package/src/components/TokenField.tsx +395 -0
- package/src/components/Tooltip.ts +4 -6
- package/src/components/Tree.ts +14 -7
- package/src/components/Virtualizer.tsx +30 -14
- package/src/components/index.ts +22 -0
- package/src/components/utils.ts +1 -1
- package/src/datepicker/useDateField.tsx +2 -11
- package/src/datepicker/useDatePickerGroup.tsx +44 -33
- package/src/datepicker/useDateSegment.tsx +31 -30
- package/src/dialog/useDialog.ts +8 -1
- package/src/dnd/DragManager.tsx +5 -1
- package/src/dnd/useDrag.tsx +2 -1
- package/src/focus/FocusScope.ts +2 -2
- package/src/grid/useGrid.ts +3 -0
- package/src/grid/{useGridCell.ts → useGridCell.tsx} +121 -64
- package/src/grid/utils.ts +1 -0
- package/src/gridlist/{useGridListItem.ts → useGridListItem.tsx} +152 -111
- package/src/index.ts +22 -0
- package/src/interactions/createEventHandler.ts +11 -8
- package/src/interactions/createKeyboardShortcutHandler.tsx +218 -0
- package/src/interactions/textSelection.ts +3 -3
- package/src/interactions/useContextMenu.tsx +125 -0
- package/src/interactions/useFocusVisible.ts +4 -4
- package/src/interactions/useKeyboard.ts +50 -2
- package/src/interactions/useLongPress.ts +33 -22
- package/src/interactions/useMove.ts +6 -6
- package/src/interactions/usePress.ts +8 -0
- package/src/interactions/utils.ts +10 -10
- package/src/intl/combobox/fi-FI.json +2 -2
- package/src/intl/previewtrigger/ar-AE.json +3 -0
- package/src/intl/previewtrigger/bg-BG.json +3 -0
- package/src/intl/previewtrigger/cs-CZ.json +3 -0
- package/src/intl/previewtrigger/da-DK.json +3 -0
- package/src/intl/previewtrigger/de-DE.json +3 -0
- package/src/intl/previewtrigger/el-GR.json +3 -0
- package/src/intl/previewtrigger/en-US.json +3 -0
- package/src/intl/previewtrigger/es-ES.json +3 -0
- package/src/intl/previewtrigger/et-EE.json +3 -0
- package/src/intl/previewtrigger/fi-FI.json +3 -0
- package/src/intl/previewtrigger/fr-FR.json +3 -0
- package/src/intl/previewtrigger/he-IL.json +3 -0
- package/src/intl/previewtrigger/hr-HR.json +3 -0
- package/src/intl/previewtrigger/hu-HU.json +3 -0
- package/src/intl/previewtrigger/index.ts +73 -0
- package/src/intl/previewtrigger/it-IT.json +3 -0
- package/src/intl/previewtrigger/ja-JP.json +3 -0
- package/src/intl/previewtrigger/ko-KR.json +3 -0
- package/src/intl/previewtrigger/lt-LT.json +3 -0
- package/src/intl/previewtrigger/lv-LV.json +3 -0
- package/src/intl/previewtrigger/nb-NO.json +3 -0
- package/src/intl/previewtrigger/nl-NL.json +3 -0
- package/src/intl/previewtrigger/pl-PL.json +3 -0
- package/src/intl/previewtrigger/pt-BR.json +3 -0
- package/src/intl/previewtrigger/pt-PT.json +3 -0
- package/src/intl/previewtrigger/ro-RO.json +3 -0
- package/src/intl/previewtrigger/ru-RU.json +3 -0
- package/src/intl/previewtrigger/sk-SK.json +3 -0
- package/src/intl/previewtrigger/sl-SI.json +3 -0
- package/src/intl/previewtrigger/sr-SP.json +3 -0
- package/src/intl/previewtrigger/sv-SE.json +3 -0
- package/src/intl/previewtrigger/tr-TR.json +3 -0
- package/src/intl/previewtrigger/uk-UA.json +3 -0
- package/src/intl/previewtrigger/zh-CN.json +3 -0
- package/src/intl/previewtrigger/zh-TW.json +3 -0
- package/src/intl/table/ar-AE.json +3 -3
- package/src/intl/table/bg-BG.json +3 -3
- package/src/intl/table/cs-CZ.json +3 -3
- package/src/intl/table/da-DK.json +3 -3
- package/src/intl/table/de-DE.json +3 -3
- package/src/intl/table/el-GR.json +3 -3
- package/src/intl/table/es-ES.json +3 -3
- package/src/intl/table/et-EE.json +3 -3
- package/src/intl/table/fi-FI.json +3 -3
- package/src/intl/table/fr-FR.json +3 -3
- package/src/intl/table/he-IL.json +3 -3
- package/src/intl/table/hr-HR.json +3 -3
- package/src/intl/table/hu-HU.json +3 -3
- package/src/intl/table/it-IT.json +3 -3
- package/src/intl/table/ja-JP.json +3 -3
- package/src/intl/table/ko-KR.json +3 -3
- package/src/intl/table/lt-LT.json +3 -3
- package/src/intl/table/lv-LV.json +3 -3
- package/src/intl/table/nb-NO.json +3 -3
- package/src/intl/table/nl-NL.json +3 -3
- package/src/intl/table/pl-PL.json +3 -3
- package/src/intl/table/pt-BR.json +3 -3
- package/src/intl/table/pt-PT.json +3 -3
- package/src/intl/table/ro-RO.json +3 -3
- package/src/intl/table/ru-RU.json +3 -3
- package/src/intl/table/sk-SK.json +3 -3
- package/src/intl/table/sl-SI.json +3 -3
- package/src/intl/table/sr-SP.json +3 -3
- package/src/intl/table/sv-SE.json +3 -3
- package/src/intl/table/tr-TR.json +3 -3
- package/src/intl/table/uk-UA.json +3 -3
- package/src/intl/table/zh-CN.json +4 -4
- package/src/intl/table/zh-TW.json +3 -3
- package/src/intl/tree/es-ES.json +1 -1
- package/src/link/useLink.ts +2 -0
- package/src/menu/useMenuItem.ts +33 -36
- package/src/menu/useMenuTrigger.tsx +217 -0
- package/src/menu/{useSubmenuTrigger.ts → useSubmenuTrigger.tsx} +112 -152
- package/src/numberfield/{useNumberField.ts → useNumberField.tsx} +185 -239
- package/src/overlays/Overlay.ts +5 -1
- package/src/overlays/ariaHideOutside.ts +6 -8
- package/src/overlays/useCloseOnScroll.ts +7 -5
- package/src/overlays/{useOverlay.ts → useOverlay.tsx} +72 -84
- package/src/overlays/usePopover.ts +10 -5
- package/src/overlays/usePreventScroll.ts +4 -4
- package/src/progress/useProgressBar.ts +2 -1
- package/src/radio/{useRadioGroup.ts → useRadioGroup.tsx} +83 -80
- package/src/searchfield/useSearchField.tsx +147 -0
- package/src/select/useSelect.ts +20 -20
- package/src/selection/useSelectableCollection.tsx +751 -0
- package/src/selection/useSelectableItem.ts +48 -11
- package/src/slider/{useSliderThumb.ts → useSliderThumb.tsx} +116 -159
- package/src/spinbutton/useSpinButton.tsx +330 -0
- package/src/stately/combobox/useComboBoxState.ts +1 -1
- package/src/stately/grid/useGridState.ts +9 -10
- package/src/stately/index.ts +11 -0
- package/src/stately/menu/useMenuTriggerState.ts +1 -1
- package/src/stately/menu/useSubmenuTriggerState.ts +2 -0
- package/src/stately/overlays/useOverlayTriggerState.ts +12 -1
- package/src/stately/radio/useRadioGroupState.ts +5 -1
- package/src/stately/table/TableUtils.ts +15 -1
- package/src/stately/table/useTableState.ts +7 -0
- package/src/stately/tokenfield/TokenFieldValue.tsx +440 -0
- package/src/stately/tokenfield/useTokenFieldState.tsx +57 -0
- package/src/stately/tooltip/useTooltipTriggerState.ts +16 -7
- package/src/stately/virtualizer/Layout.tsx +2 -0
- package/src/stately/virtualizer/ScrollAnchor.tsx +338 -0
- package/src/stately/virtualizer/Virtualizer.tsx +52 -1
- package/src/stately/virtualizer/types.tsx +2 -0
- package/src/table/useTableCell.ts +12 -0
- package/src/table/useTableColumnHeader.ts +8 -1
- package/src/table/useTableColumnResize.tsx +354 -0
- package/src/tag/useTag.ts +22 -15
- package/src/textfield/useTextField.ts +2 -0
- package/src/tokenfield/useToken.tsx +64 -0
- package/src/tokenfield/useTokenField.tsx +849 -0
- package/src/tooltip/usePreviewTrigger.tsx +266 -0
- package/src/tooltip/useSafeArea.tsx +171 -0
- package/src/upstream-exports/react-aria/mergeRefs.tsx +3 -0
- package/src/upstream-exports/react-aria/usePreviewTrigger.tsx +18 -0
- package/src/upstream-exports/react-aria/useTokenField.tsx +22 -0
- package/src/upstream-exports/react-stately/private/collections/getChildNodes.tsx +8 -0
- package/src/upstream-exports/react-stately/private/collections/getItemCount.tsx +2 -0
- package/src/upstream-exports/react-stately/private/grid/GridCollection.tsx +7 -0
- package/src/upstream-exports/react-stately/private/grid/useGridState.tsx +6 -0
- package/src/upstream-exports/react-stately/private/utils/number.tsx +2 -0
- package/src/upstream-exports/react-stately/useComboBoxState.tsx +23 -0
- package/src/upstream-exports/react-stately/useListState.tsx +15 -0
- package/src/upstream-exports/react-stately/useMenuTriggerState.tsx +26 -0
- package/src/upstream-exports/react-stately/useMultipleSelectionState.tsx +21 -0
- package/src/upstream-exports/react-stately/useNumberFieldState.tsx +20 -0
- package/src/upstream-exports/react-stately/useOverlayTriggerState.tsx +20 -0
- package/src/upstream-exports/react-stately/useRadioGroupState.tsx +16 -0
- package/src/upstream-exports/react-stately/useSearchFieldState.tsx +19 -0
- package/src/upstream-exports/react-stately/useSliderState.tsx +20 -0
- package/src/upstream-exports/react-stately/useTableState.tsx +45 -0
- package/src/upstream-exports/react-stately/useTokenFieldState.tsx +25 -0
- package/src/upstream-exports/react-stately/useTooltipTriggerState.tsx +20 -0
- package/src/upstream-exports/react-stately/useTreeState.tsx +14 -0
- package/src/utils/domHelpers.ts +74 -17
- package/src/utils/isVirtualEvent.ts +2 -1
- package/src/utils/openLink.ts +8 -3
- package/src/utils/platform.ts +7 -3
- package/src/utils/scrollIntoView.ts +4 -4
- package/src/utils/shadowdom/DOMFunctions.ts +42 -2
- package/src/utils/useId.ts +11 -2
- package/src/utils/useLoadMoreSentinel.ts +8 -3
- package/src/utils/useViewportSize.ts +3 -3
- package/src/virtualizer/ScrollView.tsx +13 -4
- package/src/virtualizer/VirtualizerItem.tsx +3 -1
- package/src/virtualizer/useVirtualizerItem.tsx +43 -3
- package/src/menu/useMenuTrigger.ts +0 -189
- package/src/searchfield/useSearchField.ts +0 -156
- package/src/selection/useSelectableCollection.ts +0 -750
- package/src/spinbutton/useSpinButton.ts +0 -380
- package/src/table/useTableColumnResize.ts +0 -374
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/** @jsxImportSource octane */
|
|
2
|
-
// Ported from adobe/react-spectrum@
|
|
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,
|
|
8
|
-
import { getEventTarget
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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@
|
|
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
|
|
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
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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:
|
|
419
|
+
onPointerDown(e: PointerEvent) {
|
|
419
420
|
e.stopPropagation();
|
|
420
421
|
},
|
|
421
|
-
onMouseDown(e:
|
|
422
|
+
onMouseDown(e: MouseEvent) {
|
|
422
423
|
e.stopPropagation();
|
|
423
424
|
},
|
|
424
425
|
}),
|
package/src/dialog/useDialog.ts
CHANGED
|
@@ -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();
|
|
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']
|
|
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
|
},
|
package/src/dnd/DragManager.tsx
CHANGED
|
@@ -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 {
|
package/src/dnd/useDrag.tsx
CHANGED
|
@@ -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 {
|
package/src/focus/FocusScope.ts
CHANGED
|
@@ -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
|
|
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
|
|
499
|
+
focusElement(focusedNode.current);
|
|
500
500
|
} else if (activeScope.current) {
|
|
501
501
|
focusFirstInScope(activeScope.current);
|
|
502
502
|
}
|
package/src/grid/useGrid.ts
CHANGED
|
@@ -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
|
|
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
/** @jsxImportSource octane */
|
|
2
|
+
type DOMAttributes = Record<string, any>;
|
|
3
|
+
// Ported from adobe/react-spectrum@5ecb3333001313e83898cd07644227897e3bae1f (packages/react-aria/src/grid/useGridCell.ts).
|
|
4
|
+
/*
|
|
5
|
+
* Copyright 2020 Adobe. All rights reserved.
|
|
6
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
8
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
11
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
12
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
13
|
+
* governing permissions and limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { FocusableElement, Key, RefObject } from '@react-types/shared';
|
|
12
17
|
import { focusSafely } from '../interactions/focusSafely';
|
|
13
18
|
import {
|
|
14
19
|
getActiveElement,
|
|
@@ -17,23 +22,21 @@ import {
|
|
|
17
22
|
nodeContains,
|
|
18
23
|
} from '../utils/shadowdom/DOMFunctions';
|
|
19
24
|
import { getFocusableTreeWalker } from '../focus/FocusScope';
|
|
25
|
+
import { getOwnerDocument } from '../utils/domHelpers';
|
|
20
26
|
import { getScrollParent } from '../utils/getScrollParent';
|
|
21
|
-
import
|
|
27
|
+
import {
|
|
28
|
+
IGridCollection as GridCollection,
|
|
29
|
+
GridNode,
|
|
30
|
+
} from '../upstream-exports/react-stately/private/grid/GridCollection';
|
|
22
31
|
import { gridMap } from './utils';
|
|
23
|
-
import
|
|
32
|
+
import { GridState } from '../upstream-exports/react-stately/private/grid/useGridState';
|
|
24
33
|
import { isFocusVisible } from '../interactions/useFocusVisible';
|
|
25
34
|
import { mergeProps } from '../utils/mergeProps';
|
|
26
|
-
import { useRef } from '
|
|
35
|
+
import { KeyboardEvent as ReactKeyboardEvent, useRef } from '../compat/react';
|
|
27
36
|
import { scrollIntoViewport } from '../utils/scrollIntoView';
|
|
28
37
|
import { useLocale } from '../i18n/I18nProvider';
|
|
29
38
|
import { useSelectableItem } from '../selection/useSelectableItem';
|
|
30
39
|
|
|
31
|
-
import { S, splitSlot, subSlot } from '../internal';
|
|
32
|
-
|
|
33
|
-
// octane adaptation: minimal structural DOMAttributes (upstream's drags React's synthetic
|
|
34
|
-
// handler types along).
|
|
35
|
-
type DOMAttributes = Record<string, any>;
|
|
36
|
-
|
|
37
40
|
export interface GridCellProps {
|
|
38
41
|
/**
|
|
39
42
|
* An object representing the grid cell. Contains all the relevant information that makes up the
|
|
@@ -44,9 +47,16 @@ export interface GridCellProps {
|
|
|
44
47
|
isVirtualized?: boolean;
|
|
45
48
|
/**
|
|
46
49
|
* Whether the cell or its first focusable child element should be focused when the grid cell is
|
|
47
|
-
* focused.
|
|
50
|
+
* focused. Defaults to 'child' in arrow keyboard navigation mode and 'cell' in
|
|
51
|
+
* tab keyboard navigation mode.
|
|
48
52
|
*/
|
|
49
53
|
focusMode?: 'child' | 'cell';
|
|
54
|
+
/**
|
|
55
|
+
* Whether the cell should support arrow key navigation even when the containing collection uses
|
|
56
|
+
* tab keyboard navigation. Allows users to navigate between rows and cells with arrow keys while
|
|
57
|
+
* focus is on an interactive child element within the cell.
|
|
58
|
+
*/
|
|
59
|
+
allowsArrowNavigation?: boolean;
|
|
50
60
|
/** Whether selection should occur on press up instead of press down. */
|
|
51
61
|
shouldSelectOnPressUp?: boolean;
|
|
52
62
|
/** Indicates how many columns the data cell spans. */
|
|
@@ -77,32 +87,28 @@ export function useGridCell<T, C extends GridCollection<T>>(
|
|
|
77
87
|
props: GridCellProps,
|
|
78
88
|
state: GridState<T, C>,
|
|
79
89
|
ref: RefObject<FocusableElement | null>,
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const slot = slotArg ?? S('useGridCell');
|
|
91
|
-
const props = user[0] as GridCellProps;
|
|
92
|
-
const state = user[1] as GridState<any, GridCollection<any>>;
|
|
93
|
-
const ref = user[2] as RefObject<FocusableElement | null>;
|
|
94
|
-
|
|
95
|
-
let { node, isVirtualized, focusMode = 'child', shouldSelectOnPressUp, onAction } = props;
|
|
90
|
+
_slot?: symbol,
|
|
91
|
+
): GridCellAria {
|
|
92
|
+
let {
|
|
93
|
+
node,
|
|
94
|
+
isVirtualized,
|
|
95
|
+
focusMode: focusModeProp,
|
|
96
|
+
allowsArrowNavigation,
|
|
97
|
+
shouldSelectOnPressUp,
|
|
98
|
+
onAction,
|
|
99
|
+
} = props;
|
|
96
100
|
|
|
97
|
-
let { direction } = useLocale(
|
|
101
|
+
let { direction } = useLocale();
|
|
98
102
|
let {
|
|
99
103
|
keyboardDelegate,
|
|
100
104
|
actions: { onCellAction },
|
|
105
|
+
keyboardNavigationBehavior,
|
|
101
106
|
} = gridMap.get(state)!;
|
|
107
|
+
let focusMode = focusModeProp ?? (keyboardNavigationBehavior === 'tab' ? 'cell' : 'child');
|
|
102
108
|
|
|
103
109
|
// We need to track the key of the item at the time it was last focused so that we force
|
|
104
110
|
// focus to go to the item when the DOM node is reused for a different item in a virtualizer.
|
|
105
|
-
let keyWhenFocused = useRef<Key | null>(null
|
|
111
|
+
let keyWhenFocused = useRef<Key | null>(null);
|
|
106
112
|
|
|
107
113
|
// Handles focusing the cell. If there is a focusable child,
|
|
108
114
|
// it is focused, otherwise the cell itself is focused.
|
|
@@ -111,7 +117,10 @@ export function useGridCell(...args: any[]): GridCellAria {
|
|
|
111
117
|
let treeWalker = getFocusableTreeWalker(ref.current);
|
|
112
118
|
if (focusMode === 'child') {
|
|
113
119
|
// If focus is already on a focusable child within the cell, early return so we don't shift focus
|
|
114
|
-
if (
|
|
120
|
+
if (
|
|
121
|
+
isFocusWithin(ref.current) &&
|
|
122
|
+
ref.current !== getActiveElement(getOwnerDocument(ref.current))
|
|
123
|
+
) {
|
|
115
124
|
return;
|
|
116
125
|
}
|
|
117
126
|
|
|
@@ -134,24 +143,21 @@ export function useGridCell(...args: any[]): GridCellAria {
|
|
|
134
143
|
}
|
|
135
144
|
};
|
|
136
145
|
|
|
137
|
-
let { itemProps, isPressed } = useSelectableItem(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
},
|
|
148
|
-
subSlot(slot, 'selectableItem'),
|
|
149
|
-
);
|
|
146
|
+
let { itemProps, isPressed } = useSelectableItem({
|
|
147
|
+
selectionManager: state.selectionManager,
|
|
148
|
+
key: node.key,
|
|
149
|
+
ref,
|
|
150
|
+
isVirtualized,
|
|
151
|
+
focus,
|
|
152
|
+
shouldSelectOnPressUp,
|
|
153
|
+
onAction: onCellAction ? () => onCellAction(node.key) : onAction,
|
|
154
|
+
isDisabled: state.collection.size === 0,
|
|
155
|
+
});
|
|
150
156
|
|
|
151
|
-
let onKeyDownCapture = (e:
|
|
152
|
-
let activeElement = getActiveElement();
|
|
157
|
+
let onKeyDownCapture = (e: ReactKeyboardEvent) => {
|
|
158
|
+
let activeElement = getActiveElement(getOwnerDocument(ref.current));
|
|
153
159
|
if (
|
|
154
|
-
!nodeContains(e.currentTarget as
|
|
160
|
+
!nodeContains(e.currentTarget as Node, getEventTarget(e) as Element) ||
|
|
155
161
|
state.isKeyboardNavigationDisabled ||
|
|
156
162
|
!ref.current ||
|
|
157
163
|
!activeElement
|
|
@@ -191,7 +197,6 @@ export function useGridCell(...args: any[]): GridCellAria {
|
|
|
191
197
|
// We prevent the capturing event from reaching children of the cell, e.g. pickers.
|
|
192
198
|
// We want arrow keys to navigate to the next cell instead. We need to re-dispatch
|
|
193
199
|
// the event from a higher parent so it still bubbles and gets handled by useSelectableCollection.
|
|
194
|
-
// octane adaptation: the native event IS `e.nativeEvent`.
|
|
195
200
|
ref.current.parentElement?.dispatchEvent(new KeyboardEvent(e.type, e));
|
|
196
201
|
break;
|
|
197
202
|
}
|
|
@@ -232,7 +237,6 @@ export function useGridCell(...args: any[]): GridCellAria {
|
|
|
232
237
|
// We prevent the capturing event from reaching children of the cell, e.g. pickers.
|
|
233
238
|
// We want arrow keys to navigate to the next cell instead. We need to re-dispatch
|
|
234
239
|
// the event from a higher parent so it still bubbles and gets handled by useSelectableCollection.
|
|
235
|
-
// octane adaptation: the native event IS `e.nativeEvent`.
|
|
236
240
|
ref.current.parentElement?.dispatchEvent(new KeyboardEvent(e.type, e));
|
|
237
241
|
break;
|
|
238
242
|
}
|
|
@@ -260,13 +264,47 @@ export function useGridCell(...args: any[]): GridCellAria {
|
|
|
260
264
|
if (!e.altKey && nodeContains(ref.current, getEventTarget(e) as Element)) {
|
|
261
265
|
e.stopPropagation();
|
|
262
266
|
e.preventDefault();
|
|
263
|
-
// octane adaptation: the native event IS `e.nativeEvent`.
|
|
264
267
|
ref.current.parentElement?.dispatchEvent(new KeyboardEvent(e.type, e));
|
|
265
268
|
}
|
|
266
269
|
break;
|
|
267
270
|
}
|
|
268
271
|
};
|
|
269
272
|
|
|
273
|
+
let onKeyDown = (e: ReactKeyboardEvent) => {
|
|
274
|
+
let activeElement = getActiveElement(getOwnerDocument(ref.current));
|
|
275
|
+
if (
|
|
276
|
+
!nodeContains(e.currentTarget as Node, getEventTarget(e) as Element) ||
|
|
277
|
+
state.isKeyboardNavigationDisabled ||
|
|
278
|
+
!ref.current ||
|
|
279
|
+
!activeElement
|
|
280
|
+
) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (keyboardNavigationBehavior === 'tab') {
|
|
285
|
+
if (getEventTarget(e) !== ref.current && e.key !== 'Tab') {
|
|
286
|
+
e.stopPropagation();
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
switch (e.key) {
|
|
292
|
+
case 'Tab': {
|
|
293
|
+
if (keyboardNavigationBehavior === 'tab') {
|
|
294
|
+
// If there is another focusable element within this item, stop propagation so the tab key
|
|
295
|
+
// is handled by the browser and not by useSelectableCollection (which would take us out of the list).
|
|
296
|
+
let walker = getFocusableTreeWalker(ref.current, { tabbable: true });
|
|
297
|
+
walker.currentNode = activeElement;
|
|
298
|
+
let next = e.shiftKey ? walker.previousNode() : walker.nextNode();
|
|
299
|
+
|
|
300
|
+
if (next) {
|
|
301
|
+
e.stopPropagation();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
|
|
270
308
|
// Grid cells can have focusable elements inside them. In this case, focus should
|
|
271
309
|
// be marshalled to that element rather than focusing the cell itself.
|
|
272
310
|
let onFocus = (e: FocusEvent) => {
|
|
@@ -284,22 +322,41 @@ export function useGridCell(...args: any[]): GridCellAria {
|
|
|
284
322
|
return;
|
|
285
323
|
}
|
|
286
324
|
|
|
287
|
-
//
|
|
325
|
+
// if focus goes back to cell from child, make sure we don't refocus the cell if we are in focusMode=child
|
|
326
|
+
// since that would be a focus trap
|
|
327
|
+
if (
|
|
328
|
+
focusMode === 'child' &&
|
|
329
|
+
e.relatedTarget &&
|
|
330
|
+
nodeContains(ref.current, e.relatedTarget as Element)
|
|
331
|
+
) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// If the cell itself is focused, wait a frame so that focus finishes propagating
|
|
288
336
|
// up to the tree, and move focus to a focusable child if possible.
|
|
289
337
|
requestAnimationFrame(() => {
|
|
290
|
-
if (
|
|
338
|
+
if (
|
|
339
|
+
focusMode === 'child' &&
|
|
340
|
+
getActiveElement(getOwnerDocument(ref.current)) === ref.current
|
|
341
|
+
) {
|
|
291
342
|
focus();
|
|
292
343
|
}
|
|
293
344
|
});
|
|
294
345
|
};
|
|
295
346
|
|
|
347
|
+
// oxlint-disable-next-line react/react-compiler
|
|
296
348
|
let gridCellProps: DOMAttributes = mergeProps(itemProps, {
|
|
297
349
|
role: 'gridcell',
|
|
298
|
-
onKeyDownCapture
|
|
350
|
+
onKeyDownCapture:
|
|
351
|
+
keyboardNavigationBehavior !== 'tab' || allowsArrowNavigation ? onKeyDownCapture : undefined,
|
|
352
|
+
onKeyDown: keyboardNavigationBehavior === 'tab' ? onKeyDown : undefined,
|
|
299
353
|
'aria-colspan': node.colSpan,
|
|
300
354
|
'aria-colindex': node.colIndex != null ? node.colIndex + 1 : undefined, // aria-colindex is 1-based
|
|
301
355
|
colSpan: isVirtualized ? undefined : node.colSpan,
|
|
302
356
|
onFocus,
|
|
357
|
+
// make sure shift tabbing from a child of a cell doesnt move focus back to cell if focusMode="child" and in tab nav
|
|
358
|
+
// consistent with arrow nav and focusMode="child" since you can't go back to the cell there either
|
|
359
|
+
...(focusMode === 'child' && keyboardNavigationBehavior === 'tab' ? { tabIndex: -1 } : {}),
|
|
303
360
|
});
|
|
304
361
|
|
|
305
362
|
if (isVirtualized) {
|
|
@@ -315,8 +372,8 @@ export function useGridCell(...args: any[]): GridCellAria {
|
|
|
315
372
|
gridCellProps.tabIndex != null &&
|
|
316
373
|
gridCellProps.onPointerDown == null
|
|
317
374
|
) {
|
|
318
|
-
gridCellProps.onPointerDown = (e: PointerEvent) => {
|
|
319
|
-
let el = e.currentTarget
|
|
375
|
+
gridCellProps.onPointerDown = (e: import('octane').PointerEvent<HTMLElement>) => {
|
|
376
|
+
let el = e.currentTarget;
|
|
320
377
|
let tabindex = el.getAttribute('tabindex');
|
|
321
378
|
el.removeAttribute('tabindex');
|
|
322
379
|
requestAnimationFrame(() => {
|