@react-aria/grid 3.11.1 → 3.12.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.
- package/dist/GridKeyboardDelegate.main.js +19 -10
- package/dist/GridKeyboardDelegate.main.js.map +1 -1
- package/dist/GridKeyboardDelegate.mjs +20 -11
- package/dist/GridKeyboardDelegate.module.js +20 -11
- package/dist/GridKeyboardDelegate.module.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/useGrid.main.js +3 -2
- package/dist/useGrid.main.js.map +1 -1
- package/dist/useGrid.mjs +3 -2
- package/dist/useGrid.module.js +3 -2
- package/dist/useGrid.module.js.map +1 -1
- package/dist/useGridCell.main.js +12 -9
- package/dist/useGridCell.main.js.map +1 -1
- package/dist/useGridCell.mjs +5 -2
- package/dist/useGridCell.module.js +5 -2
- package/dist/useGridCell.module.js.map +1 -1
- package/dist/useGridSelectionAnnouncement.main.js +13 -4
- package/dist/useGridSelectionAnnouncement.main.js.map +1 -1
- package/dist/useGridSelectionAnnouncement.mjs +13 -4
- package/dist/useGridSelectionAnnouncement.module.js +13 -4
- package/dist/useGridSelectionAnnouncement.module.js.map +1 -1
- package/package.json +13 -13
- package/src/GridKeyboardDelegate.ts +34 -11
- package/src/useGrid.ts +8 -1
- package/src/useGridCell.ts +7 -2
- package/src/useGridSelectionAnnouncement.ts +14 -4
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import {Direction, DisabledBehavior, Key, KeyboardDelegate, LayoutDelegate, Node, Rect, RefObject, Size} from '@react-types/shared';
|
|
14
14
|
import {DOMLayoutDelegate} from '@react-aria/selection';
|
|
15
15
|
import {getChildNodes, getFirstItem, getLastItem, getNthItem} from '@react-stately/collections';
|
|
16
|
-
import {GridCollection} from '@react-types/grid';
|
|
16
|
+
import {GridCollection, GridNode} from '@react-types/grid';
|
|
17
17
|
|
|
18
18
|
export interface GridKeyboardDelegateOptions<C> {
|
|
19
19
|
collection: C,
|
|
@@ -103,6 +103,35 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
103
103
|
return null;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
protected getKeyForItemInRowByIndex(key: Key, index: number = 0): Key | null {
|
|
107
|
+
if (index < 0) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let item = this.collection.getItem(key);
|
|
112
|
+
if (!item) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let i = 0;
|
|
117
|
+
for (let child of getChildNodes(item, this.collection) as Iterable<GridNode<T>>) {
|
|
118
|
+
if (child.colSpan && child.colSpan + i > index) {
|
|
119
|
+
return child.key ?? null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (child.colSpan) {
|
|
123
|
+
i = i + child.colSpan - 1;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (i === index) {
|
|
127
|
+
return child.key ?? null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
i++;
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
|
|
106
135
|
getKeyBelow(fromKey: Key) {
|
|
107
136
|
let key: Key | null = fromKey;
|
|
108
137
|
let startItem = this.collection.getItem(key);
|
|
@@ -123,11 +152,8 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
123
152
|
if (key != null) {
|
|
124
153
|
// If focus was on a cell, focus the cell with the same index in the next row.
|
|
125
154
|
if (this.isCell(startItem)) {
|
|
126
|
-
let
|
|
127
|
-
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
130
|
-
return getNthItem(getChildNodes(item, this.collection), startItem.index ?? 0)?.key ?? null;
|
|
155
|
+
let startIndex = startItem.colIndex ? startItem.colIndex : startItem.index;
|
|
156
|
+
return this.getKeyForItemInRowByIndex(key, startIndex);
|
|
131
157
|
}
|
|
132
158
|
|
|
133
159
|
// Otherwise, focus the next row
|
|
@@ -158,11 +184,8 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
158
184
|
if (key != null) {
|
|
159
185
|
// If focus was on a cell, focus the cell with the same index in the previous row.
|
|
160
186
|
if (this.isCell(startItem)) {
|
|
161
|
-
let
|
|
162
|
-
|
|
163
|
-
return null;
|
|
164
|
-
}
|
|
165
|
-
return getNthItem(getChildNodes(item, this.collection), startItem.index ?? 0)?.key || null;
|
|
187
|
+
let startIndex = startItem.colIndex ? startItem.colIndex : startItem.index;
|
|
188
|
+
return this.getKeyForItemInRowByIndex(key, startIndex);
|
|
166
189
|
}
|
|
167
190
|
|
|
168
191
|
// Otherwise, focus the previous row
|
package/src/useGrid.ts
CHANGED
|
@@ -26,6 +26,11 @@ import {useSelectableCollection} from '@react-aria/selection';
|
|
|
26
26
|
export interface GridProps extends DOMProps, AriaLabelingProps {
|
|
27
27
|
/** Whether the grid uses virtual scrolling. */
|
|
28
28
|
isVirtualized?: boolean,
|
|
29
|
+
/**
|
|
30
|
+
* Whether typeahead navigation is disabled.
|
|
31
|
+
* @default false
|
|
32
|
+
*/
|
|
33
|
+
disallowTypeAhead?: boolean,
|
|
29
34
|
/**
|
|
30
35
|
* An optional keyboard delegate implementation for type to select,
|
|
31
36
|
* to override the default.
|
|
@@ -66,6 +71,7 @@ export interface GridAria {
|
|
|
66
71
|
export function useGrid<T>(props: GridProps, state: GridState<T, GridCollection<T>>, ref: RefObject<HTMLElement | null>): GridAria {
|
|
67
72
|
let {
|
|
68
73
|
isVirtualized,
|
|
74
|
+
disallowTypeAhead,
|
|
69
75
|
keyboardDelegate,
|
|
70
76
|
focusMode,
|
|
71
77
|
scrollRef,
|
|
@@ -99,7 +105,8 @@ export function useGrid<T>(props: GridProps, state: GridState<T, GridCollection<
|
|
|
99
105
|
selectionManager: manager,
|
|
100
106
|
keyboardDelegate: delegate,
|
|
101
107
|
isVirtualized,
|
|
102
|
-
scrollRef
|
|
108
|
+
scrollRef,
|
|
109
|
+
disallowTypeAhead
|
|
103
110
|
});
|
|
104
111
|
|
|
105
112
|
let id = useId(props.id);
|
package/src/useGridCell.ts
CHANGED
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import {DOMAttributes, FocusableElement, Key, RefObject} from '@react-types/shared';
|
|
14
|
-
import {focusSafely,
|
|
14
|
+
import {focusSafely, isFocusVisible} from '@react-aria/interactions';
|
|
15
|
+
import {getFocusableTreeWalker} from '@react-aria/focus';
|
|
15
16
|
import {getScrollParent, mergeProps, scrollIntoViewport} from '@react-aria/utils';
|
|
16
17
|
import {GridCollection, GridNode} from '@react-types/grid';
|
|
17
18
|
import {gridMap} from './utils';
|
|
18
19
|
import {GridState} from '@react-stately/grid';
|
|
19
|
-
import {isFocusVisible} from '@react-aria/interactions';
|
|
20
20
|
import {KeyboardEvent as ReactKeyboardEvent, useRef} from 'react';
|
|
21
21
|
import {useLocale} from '@react-aria/i18n';
|
|
22
22
|
import {useSelectableItem} from '@react-aria/selection';
|
|
@@ -30,6 +30,8 @@ export interface GridCellProps {
|
|
|
30
30
|
focusMode?: 'child' | 'cell',
|
|
31
31
|
/** Whether selection should occur on press up instead of press down. */
|
|
32
32
|
shouldSelectOnPressUp?: boolean,
|
|
33
|
+
/** Indicates how many columns the data cell spans. */
|
|
34
|
+
colSpan?: number,
|
|
33
35
|
/**
|
|
34
36
|
* Handler that is called when a user performs an action on the cell.
|
|
35
37
|
* Please use onCellAction at the collection level instead.
|
|
@@ -251,6 +253,9 @@ export function useGridCell<T, C extends GridCollection<T>>(props: GridCellProps
|
|
|
251
253
|
let gridCellProps: DOMAttributes = mergeProps(itemProps, {
|
|
252
254
|
role: 'gridcell',
|
|
253
255
|
onKeyDownCapture,
|
|
256
|
+
'aria-colspan': node.colSpan,
|
|
257
|
+
'aria-colindex': node.colIndex != null ? node.colIndex + 1 : undefined, // aria-colindex is 1-based
|
|
258
|
+
colSpan: isVirtualized ? undefined : node.colSpan,
|
|
254
259
|
onFocus
|
|
255
260
|
});
|
|
256
261
|
|
|
@@ -15,9 +15,9 @@ import {Collection, Key, Node, Selection} from '@react-types/shared';
|
|
|
15
15
|
// @ts-ignore
|
|
16
16
|
import intlMessages from '../intl/*.json';
|
|
17
17
|
import {SelectionManager} from '@react-stately/selection';
|
|
18
|
+
import {useEffectEvent, useUpdateEffect} from '@react-aria/utils';
|
|
18
19
|
import {useLocalizedStringFormatter} from '@react-aria/i18n';
|
|
19
20
|
import {useRef} from 'react';
|
|
20
|
-
import {useUpdateEffect} from '@react-aria/utils';
|
|
21
21
|
|
|
22
22
|
export interface GridSelectionAnnouncementProps {
|
|
23
23
|
/**
|
|
@@ -46,8 +46,8 @@ export function useGridSelectionAnnouncement<T>(props: GridSelectionAnnouncement
|
|
|
46
46
|
// We do this using an ARIA live region.
|
|
47
47
|
let selection = state.selectionManager.rawSelection;
|
|
48
48
|
let lastSelection = useRef(selection);
|
|
49
|
-
|
|
50
|
-
if (!state.selectionManager.isFocused) {
|
|
49
|
+
let announceSelectionChange = useEffectEvent(() => {
|
|
50
|
+
if (!state.selectionManager.isFocused || selection === lastSelection.current) {
|
|
51
51
|
lastSelection.current = selection;
|
|
52
52
|
|
|
53
53
|
return;
|
|
@@ -96,7 +96,17 @@ export function useGridSelectionAnnouncement<T>(props: GridSelectionAnnouncement
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
lastSelection.current = selection;
|
|
99
|
-
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
useUpdateEffect(() => {
|
|
102
|
+
if (state.selectionManager.isFocused) {
|
|
103
|
+
announceSelectionChange();
|
|
104
|
+
} else {
|
|
105
|
+
// Wait a frame in case the collection is about to become focused (e.g. on mouse down).
|
|
106
|
+
let raf = requestAnimationFrame(announceSelectionChange);
|
|
107
|
+
return () => cancelAnimationFrame(raf);
|
|
108
|
+
}
|
|
109
|
+
}, [selection, state.selectionManager.isFocused]);
|
|
100
110
|
}
|
|
101
111
|
|
|
102
112
|
function diffSelection(a: Selection, b: Selection): Set<Key> {
|