@react-aria/grid 3.10.5 → 3.11.1
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 +104 -43
- package/dist/GridKeyboardDelegate.main.js.map +1 -1
- package/dist/GridKeyboardDelegate.mjs +104 -43
- package/dist/GridKeyboardDelegate.module.js +104 -43
- package/dist/GridKeyboardDelegate.module.js.map +1 -1
- package/dist/ar-AE.main.js.map +1 -1
- package/dist/ar-AE.module.js.map +1 -1
- package/dist/bg-BG.main.js.map +1 -1
- package/dist/bg-BG.module.js.map +1 -1
- package/dist/cs-CZ.main.js.map +1 -1
- package/dist/cs-CZ.module.js.map +1 -1
- package/dist/da-DK.main.js.map +1 -1
- package/dist/da-DK.module.js.map +1 -1
- package/dist/de-DE.main.js.map +1 -1
- package/dist/de-DE.module.js.map +1 -1
- package/dist/el-GR.main.js.map +1 -1
- package/dist/el-GR.module.js.map +1 -1
- package/dist/en-US.main.js.map +1 -1
- package/dist/en-US.module.js.map +1 -1
- package/dist/es-ES.main.js.map +1 -1
- package/dist/es-ES.module.js.map +1 -1
- package/dist/et-EE.main.js.map +1 -1
- package/dist/et-EE.module.js.map +1 -1
- package/dist/fi-FI.main.js.map +1 -1
- package/dist/fi-FI.module.js.map +1 -1
- package/dist/fr-FR.main.js.map +1 -1
- package/dist/fr-FR.module.js.map +1 -1
- package/dist/he-IL.main.js.map +1 -1
- package/dist/he-IL.module.js.map +1 -1
- package/dist/hr-HR.main.js.map +1 -1
- package/dist/hr-HR.module.js.map +1 -1
- package/dist/hu-HU.main.js.map +1 -1
- package/dist/hu-HU.module.js.map +1 -1
- package/dist/it-IT.main.js.map +1 -1
- package/dist/it-IT.module.js.map +1 -1
- package/dist/ja-JP.main.js.map +1 -1
- package/dist/ja-JP.module.js.map +1 -1
- package/dist/ko-KR.main.js.map +1 -1
- package/dist/ko-KR.module.js.map +1 -1
- package/dist/lt-LT.main.js.map +1 -1
- package/dist/lt-LT.module.js.map +1 -1
- package/dist/lv-LV.main.js.map +1 -1
- package/dist/lv-LV.module.js.map +1 -1
- package/dist/nb-NO.main.js.map +1 -1
- package/dist/nb-NO.module.js.map +1 -1
- package/dist/nl-NL.main.js.map +1 -1
- package/dist/nl-NL.module.js.map +1 -1
- package/dist/pl-PL.main.js.map +1 -1
- package/dist/pl-PL.module.js.map +1 -1
- package/dist/pt-BR.main.js.map +1 -1
- package/dist/pt-BR.module.js.map +1 -1
- package/dist/pt-PT.main.js.map +1 -1
- package/dist/pt-PT.module.js.map +1 -1
- package/dist/ro-RO.main.js.map +1 -1
- package/dist/ro-RO.module.js.map +1 -1
- package/dist/ru-RU.main.js.map +1 -1
- package/dist/ru-RU.module.js.map +1 -1
- package/dist/sk-SK.main.js.map +1 -1
- package/dist/sk-SK.module.js.map +1 -1
- package/dist/sl-SI.main.js.map +1 -1
- package/dist/sl-SI.module.js.map +1 -1
- package/dist/sr-SP.main.js.map +1 -1
- package/dist/sr-SP.module.js.map +1 -1
- package/dist/sv-SE.main.js.map +1 -1
- package/dist/sv-SE.module.js.map +1 -1
- package/dist/tr-TR.main.js.map +1 -1
- package/dist/tr-TR.module.js.map +1 -1
- package/dist/types.d.ts +12 -12
- package/dist/types.d.ts.map +1 -1
- package/dist/uk-UA.main.js.map +1 -1
- package/dist/uk-UA.module.js.map +1 -1
- package/dist/useGrid.main.js +1 -1
- package/dist/useGrid.main.js.map +1 -1
- package/dist/useGrid.mjs +1 -1
- package/dist/useGrid.module.js +1 -1
- package/dist/useGrid.module.js.map +1 -1
- package/dist/useGridCell.main.js +27 -20
- package/dist/useGridCell.main.js.map +1 -1
- package/dist/useGridCell.mjs +27 -20
- package/dist/useGridCell.module.js +27 -20
- package/dist/useGridCell.module.js.map +1 -1
- package/dist/useGridRow.main.js +4 -1
- package/dist/useGridRow.main.js.map +1 -1
- package/dist/useGridRow.mjs +4 -1
- package/dist/useGridRow.module.js +4 -1
- package/dist/useGridRow.module.js.map +1 -1
- package/dist/useGridSelectionAnnouncement.main.js.map +1 -1
- package/dist/useGridSelectionAnnouncement.module.js.map +1 -1
- package/dist/useHighlightSelectionDescription.main.js +1 -1
- package/dist/useHighlightSelectionDescription.main.js.map +1 -1
- package/dist/useHighlightSelectionDescription.mjs +1 -1
- package/dist/useHighlightSelectionDescription.module.js +1 -1
- package/dist/useHighlightSelectionDescription.module.js.map +1 -1
- package/dist/utils.main.js.map +1 -1
- package/dist/utils.module.js.map +1 -1
- package/dist/zh-CN.main.js.map +1 -1
- package/dist/zh-CN.module.js.map +1 -1
- package/dist/zh-TW.main.js.map +1 -1
- package/dist/zh-TW.module.js.map +1 -1
- package/package.json +16 -16
- package/src/GridKeyboardDelegate.ts +120 -53
- package/src/useGrid.ts +1 -1
- package/src/useGridCell.ts +37 -33
- package/src/useGridRow.ts +2 -2
- package/src/useGridSelectionAnnouncement.ts +1 -1
- package/src/useHighlightSelectionDescription.ts +1 -1
- package/src/utils.ts +2 -2
package/dist/zh-TW.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";AAAA,4BAAiB;IAAG,kBAAkB,CAAC,OAAS,CAAC,gCAAI,EAAE,KAAK,IAAI,CAAC,gBAAE,CAAC;IAClE,qBAAqB,CAAC,gFAAU,CAAC;IACjC,UAAU,CAAC,gBAAE,CAAC;IACd,eAAe,CAAC,gEAAQ,CAAC;IACzB,iBAAiB,CAAC,MAAM,YAAc,
|
|
1
|
+
{"mappings":";AAAA,4BAAiB;IAAG,kBAAkB,CAAC,OAAS,CAAC,gCAAI,EAAE,KAAK,IAAI,CAAC,gBAAE,CAAC;IAClE,qBAAqB,CAAC,gFAAU,CAAC;IACjC,UAAU,CAAC,gBAAE,CAAC;IACd,eAAe,CAAC,gEAAQ,CAAC;IACzB,iBAAiB,CAAC,MAAM,YAAc,GAAG,UAAU,MAAM,CAAC,KAAK,KAAK,EAAE;YAAC,MAAM,CAAC,wDAAO,CAAC;YAAE,KAAK,IAAM,CAAC,yBAAI,EAAE,UAAU,MAAM,CAAC,KAAK,KAAK,EAAE,yBAAI,CAAC;YAAE,OAAO,IAAM,CAAC,yBAAI,EAAE,UAAU,MAAM,CAAC,KAAK,KAAK,EAAE,yBAAI,CAAC;QAAA,GAAG,QAAC,CAAC;IACzM,gBAAgB,CAAC,OAAS,CAAC,gCAAI,EAAE,KAAK,IAAI,CAAC,gBAAE,CAAC;AAChD","sources":["packages/@react-aria/grid/intl/zh-TW.json"],"sourcesContent":["{\n \"deselectedItem\": \"未選取「{item}」。\",\n \"longPressToSelect\": \"長按以進入選擇模式。\",\n \"select\": \"選取\",\n \"selectedAll\": \"已選取所有項目。\",\n \"selectedCount\": \"{count, plural, =0 {未選取任何項目} one {已選取 # 個項目} other {已選取 # 個項目}}。\",\n \"selectedItem\": \"已選取「{item}」。\"\n}\n"],"names":[],"version":3,"file":"zh-TW.module.js.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-aria/grid",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.1",
|
|
4
4
|
"description": "Spectrum UI components in React",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -22,26 +22,26 @@
|
|
|
22
22
|
"url": "https://github.com/adobe/react-spectrum"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@react-aria/focus": "^3.
|
|
26
|
-
"@react-aria/i18n": "^3.12.
|
|
27
|
-
"@react-aria/interactions": "^3.
|
|
28
|
-
"@react-aria/live-announcer": "^3.4.
|
|
29
|
-
"@react-aria/selection": "^3.
|
|
30
|
-
"@react-aria/utils": "^3.
|
|
31
|
-
"@react-stately/collections": "^3.
|
|
32
|
-
"@react-stately/grid": "^3.
|
|
33
|
-
"@react-stately/selection": "^3.
|
|
34
|
-
"@react-types/checkbox": "^3.
|
|
35
|
-
"@react-types/grid": "^3.2.
|
|
36
|
-
"@react-types/shared": "^3.
|
|
25
|
+
"@react-aria/focus": "^3.19.1",
|
|
26
|
+
"@react-aria/i18n": "^3.12.5",
|
|
27
|
+
"@react-aria/interactions": "^3.23.0",
|
|
28
|
+
"@react-aria/live-announcer": "^3.4.1",
|
|
29
|
+
"@react-aria/selection": "^3.22.0",
|
|
30
|
+
"@react-aria/utils": "^3.27.0",
|
|
31
|
+
"@react-stately/collections": "^3.12.1",
|
|
32
|
+
"@react-stately/grid": "^3.10.1",
|
|
33
|
+
"@react-stately/selection": "^3.19.0",
|
|
34
|
+
"@react-types/checkbox": "^3.9.1",
|
|
35
|
+
"@react-types/grid": "^3.2.11",
|
|
36
|
+
"@react-types/shared": "^3.27.0",
|
|
37
37
|
"@swc/helpers": "^0.5.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0",
|
|
41
|
-
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0"
|
|
40
|
+
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
|
|
41
|
+
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
|
|
42
42
|
},
|
|
43
43
|
"publishConfig": {
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "09e7f44bebdc9d89122926b2b439a0a38a2814ea"
|
|
47
47
|
}
|
|
@@ -33,7 +33,7 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
33
33
|
protected disabledKeys: Set<Key>;
|
|
34
34
|
protected disabledBehavior: DisabledBehavior;
|
|
35
35
|
protected direction: Direction;
|
|
36
|
-
protected collator: Intl.Collator;
|
|
36
|
+
protected collator: Intl.Collator | undefined;
|
|
37
37
|
protected layoutDelegate: LayoutDelegate;
|
|
38
38
|
protected focusMode;
|
|
39
39
|
|
|
@@ -43,7 +43,10 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
43
43
|
this.disabledBehavior = options.disabledBehavior || 'all';
|
|
44
44
|
this.direction = options.direction;
|
|
45
45
|
this.collator = options.collator;
|
|
46
|
-
|
|
46
|
+
if (!options.layout && !options.ref) {
|
|
47
|
+
throw new Error('Either a layout or a ref must be specified.');
|
|
48
|
+
}
|
|
49
|
+
this.layoutDelegate = options.layoutDelegate || (options.layout ? new DeprecatedLayoutDelegate(options.layout) : new DOMLayoutDelegate(options.ref!));
|
|
47
50
|
this.focusMode = options.focusMode || 'row';
|
|
48
51
|
}
|
|
49
52
|
|
|
@@ -66,12 +69,16 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
66
69
|
|
|
67
70
|
while (key != null) {
|
|
68
71
|
let item = this.collection.getItem(key);
|
|
72
|
+
if (!item) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
69
75
|
if (!this.isDisabled(item) && (!pred || pred(item))) {
|
|
70
76
|
return key;
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
key = this.collection.getKeyBefore(key);
|
|
74
80
|
}
|
|
81
|
+
return null;
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
protected findNextKey(fromKey?: Key, pred?: (item: Node<T>) => boolean) {
|
|
@@ -81,23 +88,34 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
81
88
|
|
|
82
89
|
while (key != null) {
|
|
83
90
|
let item = this.collection.getItem(key);
|
|
91
|
+
if (!item) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
84
94
|
if (!this.isDisabled(item) && (!pred || pred(item))) {
|
|
85
95
|
return key;
|
|
86
96
|
}
|
|
87
97
|
|
|
88
98
|
key = this.collection.getKeyAfter(key);
|
|
99
|
+
if (key == null) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
89
102
|
}
|
|
103
|
+
return null;
|
|
90
104
|
}
|
|
91
105
|
|
|
92
|
-
getKeyBelow(
|
|
106
|
+
getKeyBelow(fromKey: Key) {
|
|
107
|
+
let key: Key | null = fromKey;
|
|
93
108
|
let startItem = this.collection.getItem(key);
|
|
94
109
|
if (!startItem) {
|
|
95
|
-
return;
|
|
110
|
+
return null;
|
|
96
111
|
}
|
|
97
112
|
|
|
98
113
|
// If focus was on a cell, start searching from the parent row
|
|
99
114
|
if (this.isCell(startItem)) {
|
|
100
|
-
key = startItem.parentKey;
|
|
115
|
+
key = startItem.parentKey ?? null;
|
|
116
|
+
}
|
|
117
|
+
if (key == null) {
|
|
118
|
+
return null;
|
|
101
119
|
}
|
|
102
120
|
|
|
103
121
|
// Find the next item
|
|
@@ -106,7 +124,10 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
106
124
|
// If focus was on a cell, focus the cell with the same index in the next row.
|
|
107
125
|
if (this.isCell(startItem)) {
|
|
108
126
|
let item = this.collection.getItem(key);
|
|
109
|
-
|
|
127
|
+
if (!item) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return getNthItem(getChildNodes(item, this.collection), startItem.index ?? 0)?.key ?? null;
|
|
110
131
|
}
|
|
111
132
|
|
|
112
133
|
// Otherwise, focus the next row
|
|
@@ -114,17 +135,22 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
114
135
|
return key;
|
|
115
136
|
}
|
|
116
137
|
}
|
|
138
|
+
return null;
|
|
117
139
|
}
|
|
118
140
|
|
|
119
|
-
getKeyAbove(
|
|
141
|
+
getKeyAbove(fromKey: Key) {
|
|
142
|
+
let key: Key | null = fromKey;
|
|
120
143
|
let startItem = this.collection.getItem(key);
|
|
121
144
|
if (!startItem) {
|
|
122
|
-
return;
|
|
145
|
+
return null;
|
|
123
146
|
}
|
|
124
147
|
|
|
125
148
|
// If focus is on a cell, start searching from the parent row
|
|
126
149
|
if (this.isCell(startItem)) {
|
|
127
|
-
key = startItem.parentKey;
|
|
150
|
+
key = startItem.parentKey ?? null;
|
|
151
|
+
}
|
|
152
|
+
if (key == null) {
|
|
153
|
+
return null;
|
|
128
154
|
}
|
|
129
155
|
|
|
130
156
|
// Find the previous item
|
|
@@ -133,7 +159,10 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
133
159
|
// If focus was on a cell, focus the cell with the same index in the previous row.
|
|
134
160
|
if (this.isCell(startItem)) {
|
|
135
161
|
let item = this.collection.getItem(key);
|
|
136
|
-
|
|
162
|
+
if (!item) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return getNthItem(getChildNodes(item, this.collection), startItem.index ?? 0)?.key || null;
|
|
137
166
|
}
|
|
138
167
|
|
|
139
168
|
// Otherwise, focus the previous row
|
|
@@ -141,141 +170,165 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
141
170
|
return key;
|
|
142
171
|
}
|
|
143
172
|
}
|
|
173
|
+
return null;
|
|
144
174
|
}
|
|
145
175
|
|
|
146
176
|
getKeyRightOf(key: Key) {
|
|
147
177
|
let item = this.collection.getItem(key);
|
|
148
178
|
if (!item) {
|
|
149
|
-
return;
|
|
179
|
+
return null;
|
|
150
180
|
}
|
|
151
181
|
|
|
152
182
|
// If focus is on a row, focus the first child cell.
|
|
153
183
|
if (this.isRow(item)) {
|
|
154
184
|
let children = getChildNodes(item, this.collection);
|
|
155
|
-
return this.direction === 'rtl'
|
|
156
|
-
? getLastItem(children)
|
|
157
|
-
: getFirstItem(children)
|
|
185
|
+
return (this.direction === 'rtl'
|
|
186
|
+
? getLastItem(children)?.key
|
|
187
|
+
: getFirstItem(children)?.key) ?? null;
|
|
158
188
|
}
|
|
159
189
|
|
|
160
190
|
// If focus is on a cell, focus the next cell if any,
|
|
161
191
|
// otherwise focus the parent row.
|
|
162
|
-
if (this.isCell(item)) {
|
|
192
|
+
if (this.isCell(item) && item.parentKey != null) {
|
|
163
193
|
let parent = this.collection.getItem(item.parentKey);
|
|
194
|
+
if (!parent) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
164
197
|
let children = getChildNodes(parent, this.collection);
|
|
165
|
-
let next = this.direction === 'rtl'
|
|
198
|
+
let next = (this.direction === 'rtl'
|
|
166
199
|
? getNthItem(children, item.index - 1)
|
|
167
|
-
: getNthItem(children, item.index + 1);
|
|
200
|
+
: getNthItem(children, item.index + 1)) ?? null;
|
|
168
201
|
|
|
169
202
|
if (next) {
|
|
170
|
-
return next.key;
|
|
203
|
+
return next.key ?? null;
|
|
171
204
|
}
|
|
172
205
|
|
|
173
206
|
// focus row only if focusMode is set to row
|
|
174
207
|
if (this.focusMode === 'row') {
|
|
175
|
-
return item.parentKey;
|
|
208
|
+
return item.parentKey ?? null;
|
|
176
209
|
}
|
|
177
210
|
|
|
178
|
-
return this.direction === 'rtl' ? this.getFirstKey(key) : this.getLastKey(key);
|
|
211
|
+
return (this.direction === 'rtl' ? this.getFirstKey(key) : this.getLastKey(key)) ?? null;
|
|
179
212
|
}
|
|
213
|
+
return null;
|
|
180
214
|
}
|
|
181
215
|
|
|
182
216
|
getKeyLeftOf(key: Key) {
|
|
183
217
|
let item = this.collection.getItem(key);
|
|
184
218
|
if (!item) {
|
|
185
|
-
return;
|
|
219
|
+
return null;
|
|
186
220
|
}
|
|
187
221
|
|
|
188
222
|
// If focus is on a row, focus the last child cell.
|
|
189
223
|
if (this.isRow(item)) {
|
|
190
224
|
let children = getChildNodes(item, this.collection);
|
|
191
|
-
return this.direction === 'rtl'
|
|
192
|
-
? getFirstItem(children)
|
|
193
|
-
: getLastItem(children)
|
|
225
|
+
return (this.direction === 'rtl'
|
|
226
|
+
? getFirstItem(children)?.key
|
|
227
|
+
: getLastItem(children)?.key) ?? null;
|
|
194
228
|
}
|
|
195
229
|
|
|
196
230
|
// If focus is on a cell, focus the previous cell if any,
|
|
197
231
|
// otherwise focus the parent row.
|
|
198
|
-
if (this.isCell(item)) {
|
|
232
|
+
if (this.isCell(item) && item.parentKey != null) {
|
|
199
233
|
let parent = this.collection.getItem(item.parentKey);
|
|
234
|
+
if (!parent) {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
200
237
|
let children = getChildNodes(parent, this.collection);
|
|
201
|
-
let prev = this.direction === 'rtl'
|
|
238
|
+
let prev = (this.direction === 'rtl'
|
|
202
239
|
? getNthItem(children, item.index + 1)
|
|
203
|
-
: getNthItem(children, item.index - 1);
|
|
240
|
+
: getNthItem(children, item.index - 1)) ?? null;
|
|
204
241
|
|
|
205
242
|
if (prev) {
|
|
206
|
-
return prev.key;
|
|
243
|
+
return prev.key ?? null;
|
|
207
244
|
}
|
|
208
245
|
|
|
209
246
|
// focus row only if focusMode is set to row
|
|
210
247
|
if (this.focusMode === 'row') {
|
|
211
|
-
return item.parentKey;
|
|
248
|
+
return item.parentKey ?? null;
|
|
212
249
|
}
|
|
213
250
|
|
|
214
|
-
return this.direction === 'rtl' ? this.getLastKey(key) : this.getFirstKey(key);
|
|
251
|
+
return (this.direction === 'rtl' ? this.getLastKey(key) : this.getFirstKey(key)) ?? null;
|
|
215
252
|
}
|
|
253
|
+
return null;
|
|
216
254
|
}
|
|
217
255
|
|
|
218
|
-
getFirstKey(
|
|
219
|
-
let
|
|
256
|
+
getFirstKey(fromKey?: Key, global?: boolean) {
|
|
257
|
+
let key: Key | null = fromKey ?? null;
|
|
258
|
+
let item: Node<T> | undefined | null;
|
|
220
259
|
if (key != null) {
|
|
221
260
|
item = this.collection.getItem(key);
|
|
222
261
|
if (!item) {
|
|
223
|
-
return;
|
|
262
|
+
return null;
|
|
224
263
|
}
|
|
225
264
|
|
|
226
265
|
// If global flag is not set, and a cell is currently focused,
|
|
227
266
|
// move focus to the first cell in the parent row.
|
|
228
|
-
if (this.isCell(item) && !global) {
|
|
267
|
+
if (this.isCell(item) && !global && item.parentKey != null) {
|
|
229
268
|
let parent = this.collection.getItem(item.parentKey);
|
|
230
|
-
|
|
269
|
+
if (!parent) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
return getFirstItem(getChildNodes(parent, this.collection))?.key ?? null;
|
|
231
273
|
}
|
|
232
274
|
}
|
|
233
275
|
|
|
234
276
|
// Find the first row
|
|
235
|
-
key = this.findNextKey(
|
|
277
|
+
key = this.findNextKey(undefined, item => item.type === 'item');
|
|
236
278
|
|
|
237
279
|
// If global flag is set (or if focus mode is cell), focus the first cell in the first row.
|
|
238
|
-
if (
|
|
280
|
+
if (key != null && ((item && this.isCell(item) && global) || this.focusMode === 'cell')) {
|
|
239
281
|
let item = this.collection.getItem(key);
|
|
240
|
-
|
|
282
|
+
if (!item) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
key = getFirstItem(getChildNodes(item, this.collection))?.key ?? null;
|
|
241
286
|
}
|
|
242
287
|
|
|
243
288
|
// Otherwise, focus the row itself.
|
|
244
289
|
return key;
|
|
245
290
|
}
|
|
246
291
|
|
|
247
|
-
getLastKey(
|
|
248
|
-
let
|
|
292
|
+
getLastKey(fromKey?: Key, global?: boolean) {
|
|
293
|
+
let key: Key | null = fromKey ?? null;
|
|
294
|
+
let item: Node<T> | undefined | null;
|
|
249
295
|
if (key != null) {
|
|
250
296
|
item = this.collection.getItem(key);
|
|
251
297
|
if (!item) {
|
|
252
|
-
return;
|
|
298
|
+
return null;
|
|
253
299
|
}
|
|
254
300
|
|
|
255
301
|
// If global flag is not set, and a cell is currently focused,
|
|
256
302
|
// move focus to the last cell in the parent row.
|
|
257
|
-
if (this.isCell(item) && !global) {
|
|
303
|
+
if (this.isCell(item) && !global && item.parentKey != null) {
|
|
258
304
|
let parent = this.collection.getItem(item.parentKey);
|
|
305
|
+
if (!parent) {
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
259
308
|
let children = getChildNodes(parent, this.collection);
|
|
260
|
-
return getLastItem(children)
|
|
309
|
+
return getLastItem(children)?.key ?? null;
|
|
261
310
|
}
|
|
262
311
|
}
|
|
263
312
|
|
|
264
313
|
// Find the last row
|
|
265
|
-
key = this.findPreviousKey(
|
|
314
|
+
key = this.findPreviousKey(undefined, item => item.type === 'item');
|
|
266
315
|
|
|
267
316
|
// If global flag is set (or if focus mode is cell), focus the last cell in the last row.
|
|
268
|
-
if (
|
|
317
|
+
if (key != null && ((item && this.isCell(item) && global) || this.focusMode === 'cell')) {
|
|
269
318
|
let item = this.collection.getItem(key);
|
|
319
|
+
if (!item) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
270
322
|
let children = getChildNodes(item, this.collection);
|
|
271
|
-
key = getLastItem(children)
|
|
323
|
+
key = getLastItem(children)?.key ?? null;
|
|
272
324
|
}
|
|
273
325
|
|
|
274
326
|
// Otherwise, focus the row itself.
|
|
275
327
|
return key;
|
|
276
328
|
}
|
|
277
329
|
|
|
278
|
-
getKeyPageAbove(
|
|
330
|
+
getKeyPageAbove(fromKey: Key) {
|
|
331
|
+
let key: Key | null = fromKey;
|
|
279
332
|
let itemRect = this.layoutDelegate.getItemRect(key);
|
|
280
333
|
if (!itemRect) {
|
|
281
334
|
return null;
|
|
@@ -283,15 +336,19 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
283
336
|
|
|
284
337
|
let pageY = Math.max(0, itemRect.y + itemRect.height - this.layoutDelegate.getVisibleRect().height);
|
|
285
338
|
|
|
286
|
-
while (itemRect && itemRect.y > pageY) {
|
|
287
|
-
key = this.getKeyAbove(key);
|
|
339
|
+
while (itemRect && itemRect.y > pageY && key != null) {
|
|
340
|
+
key = this.getKeyAbove(key) ?? null;
|
|
341
|
+
if (key == null) {
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
288
344
|
itemRect = this.layoutDelegate.getItemRect(key);
|
|
289
345
|
}
|
|
290
346
|
|
|
291
347
|
return key;
|
|
292
348
|
}
|
|
293
349
|
|
|
294
|
-
getKeyPageBelow(
|
|
350
|
+
getKeyPageBelow(fromKey: Key) {
|
|
351
|
+
let key: Key | null = fromKey;
|
|
295
352
|
let itemRect = this.layoutDelegate.getItemRect(key);
|
|
296
353
|
|
|
297
354
|
if (!itemRect) {
|
|
@@ -316,29 +373,39 @@ export class GridKeyboardDelegate<T, C extends GridCollection<T>> implements Key
|
|
|
316
373
|
}
|
|
317
374
|
|
|
318
375
|
getKeyForSearch(search: string, fromKey?: Key) {
|
|
376
|
+
let key: Key | null = fromKey ?? null;
|
|
319
377
|
if (!this.collator) {
|
|
320
378
|
return null;
|
|
321
379
|
}
|
|
322
380
|
|
|
323
381
|
let collection = this.collection;
|
|
324
|
-
|
|
382
|
+
key = fromKey ?? this.getFirstKey();
|
|
383
|
+
if (key == null) {
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
325
386
|
|
|
326
387
|
// If the starting key is a cell, search from its parent row.
|
|
327
388
|
let startItem = collection.getItem(key);
|
|
389
|
+
if (!startItem) {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
328
392
|
if (startItem.type === 'cell') {
|
|
329
|
-
key = startItem.parentKey;
|
|
393
|
+
key = startItem.parentKey ?? null;
|
|
330
394
|
}
|
|
331
395
|
|
|
332
396
|
let hasWrapped = false;
|
|
333
397
|
while (key != null) {
|
|
334
398
|
let item = collection.getItem(key);
|
|
399
|
+
if (!item) {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
335
402
|
|
|
336
403
|
// check row text value for match
|
|
337
404
|
if (item.textValue) {
|
|
338
405
|
let substring = item.textValue.slice(0, search.length);
|
|
339
406
|
if (this.collator.compare(substring, search) === 0) {
|
|
340
407
|
if (this.isRow(item) && this.focusMode === 'cell') {
|
|
341
|
-
return getFirstItem(getChildNodes(item, this.collection))
|
|
408
|
+
return getFirstItem(getChildNodes(item, this.collection))?.key ?? null;
|
|
342
409
|
}
|
|
343
410
|
|
|
344
411
|
return item.key;
|
package/src/useGrid.ts
CHANGED
|
@@ -149,7 +149,7 @@ export function useGrid<T>(props: GridProps, state: GridState<T, GridCollection<
|
|
|
149
149
|
},
|
|
150
150
|
state.isKeyboardNavigationDisabled ? navDisabledHandlers : collectionProps,
|
|
151
151
|
// If collection is empty, make sure the grid is tabbable unless there is a child tabbable element.
|
|
152
|
-
state.collection.size === 0 && {tabIndex: hasTabbableChild ? -1 : 0},
|
|
152
|
+
(state.collection.size === 0 && {tabIndex: hasTabbableChild ? -1 : 0}) || undefined,
|
|
153
153
|
descriptionProps
|
|
154
154
|
);
|
|
155
155
|
|
package/src/useGridCell.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {DOMAttributes, FocusableElement, RefObject} from '@react-types/shared';
|
|
13
|
+
import {DOMAttributes, FocusableElement, Key, RefObject} from '@react-types/shared';
|
|
14
14
|
import {focusSafely, getFocusableTreeWalker} from '@react-aria/focus';
|
|
15
15
|
import {getScrollParent, mergeProps, scrollIntoViewport} from '@react-aria/utils';
|
|
16
16
|
import {GridCollection, GridNode} from '@react-types/grid';
|
|
@@ -60,36 +60,38 @@ export function useGridCell<T, C extends GridCollection<T>>(props: GridCellProps
|
|
|
60
60
|
} = props;
|
|
61
61
|
|
|
62
62
|
let {direction} = useLocale();
|
|
63
|
-
let {keyboardDelegate, actions: {onCellAction}} = gridMap.get(state)
|
|
63
|
+
let {keyboardDelegate, actions: {onCellAction}} = gridMap.get(state)!;
|
|
64
64
|
|
|
65
65
|
// We need to track the key of the item at the time it was last focused so that we force
|
|
66
66
|
// focus to go to the item when the DOM node is reused for a different item in a virtualizer.
|
|
67
|
-
let keyWhenFocused = useRef(null);
|
|
67
|
+
let keyWhenFocused = useRef<Key | null>(null);
|
|
68
68
|
|
|
69
69
|
// Handles focusing the cell. If there is a focusable child,
|
|
70
70
|
// it is focused, otherwise the cell itself is focused.
|
|
71
71
|
let focus = () => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
if (ref.current) {
|
|
73
|
+
let treeWalker = getFocusableTreeWalker(ref.current);
|
|
74
|
+
if (focusMode === 'child') {
|
|
75
|
+
// If focus is already on a focusable child within the cell, early return so we don't shift focus
|
|
76
|
+
if (ref.current.contains(document.activeElement) && ref.current !== document.activeElement) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
let focusable = state.selectionManager.childFocusStrategy === 'last'
|
|
81
|
+
? last(treeWalker)
|
|
82
|
+
: treeWalker.firstChild() as FocusableElement;
|
|
83
|
+
if (focusable) {
|
|
84
|
+
focusSafely(focusable);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
85
87
|
}
|
|
86
|
-
}
|
|
87
88
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
if (
|
|
90
|
+
(keyWhenFocused.current != null && node.key !== keyWhenFocused.current) ||
|
|
91
|
+
!ref.current.contains(document.activeElement)
|
|
92
|
+
) {
|
|
93
|
+
focusSafely(ref.current);
|
|
94
|
+
}
|
|
93
95
|
}
|
|
94
96
|
};
|
|
95
97
|
|
|
@@ -105,7 +107,7 @@ export function useGridCell<T, C extends GridCollection<T>>(props: GridCellProps
|
|
|
105
107
|
});
|
|
106
108
|
|
|
107
109
|
let onKeyDownCapture = (e: ReactKeyboardEvent) => {
|
|
108
|
-
if (!e.currentTarget.contains(e.target as Element) || state.isKeyboardNavigationDisabled) {
|
|
110
|
+
if (!e.currentTarget.contains(e.target as Element) || state.isKeyboardNavigationDisabled || !ref.current || !document.activeElement) {
|
|
109
111
|
return;
|
|
110
112
|
}
|
|
111
113
|
|
|
@@ -115,7 +117,7 @@ export function useGridCell<T, C extends GridCollection<T>>(props: GridCellProps
|
|
|
115
117
|
switch (e.key) {
|
|
116
118
|
case 'ArrowLeft': {
|
|
117
119
|
// Find the next focusable element within the cell.
|
|
118
|
-
let focusable = direction === 'rtl'
|
|
120
|
+
let focusable: FocusableElement | null = direction === 'rtl'
|
|
119
121
|
? walker.nextNode() as FocusableElement
|
|
120
122
|
: walker.previousNode() as FocusableElement;
|
|
121
123
|
|
|
@@ -135,12 +137,12 @@ export function useGridCell<T, C extends GridCollection<T>>(props: GridCellProps
|
|
|
135
137
|
// of this one, only one column, and the grid doesn't focus rows, then the next key will be the
|
|
136
138
|
// same as this one. In that case we need to handle focusing either the cell or the first/last
|
|
137
139
|
// child, depending on the focus mode.
|
|
138
|
-
let prev = keyboardDelegate.getKeyLeftOf(node.key);
|
|
140
|
+
let prev = keyboardDelegate.getKeyLeftOf?.(node.key);
|
|
139
141
|
if (prev !== node.key) {
|
|
140
142
|
// We prevent the capturing event from reaching children of the cell, e.g. pickers.
|
|
141
143
|
// We want arrow keys to navigate to the next cell instead. We need to re-dispatch
|
|
142
144
|
// the event from a higher parent so it still bubbles and gets handled by useSelectableCollection.
|
|
143
|
-
ref.current.parentElement
|
|
145
|
+
ref.current.parentElement?.dispatchEvent(
|
|
144
146
|
new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)
|
|
145
147
|
);
|
|
146
148
|
break;
|
|
@@ -163,7 +165,7 @@ export function useGridCell<T, C extends GridCollection<T>>(props: GridCellProps
|
|
|
163
165
|
break;
|
|
164
166
|
}
|
|
165
167
|
case 'ArrowRight': {
|
|
166
|
-
let focusable = direction === 'rtl'
|
|
168
|
+
let focusable: FocusableElement | null = direction === 'rtl'
|
|
167
169
|
? walker.previousNode() as FocusableElement
|
|
168
170
|
: walker.nextNode() as FocusableElement;
|
|
169
171
|
|
|
@@ -177,12 +179,12 @@ export function useGridCell<T, C extends GridCollection<T>>(props: GridCellProps
|
|
|
177
179
|
focusSafely(focusable);
|
|
178
180
|
scrollIntoViewport(focusable, {containingElement: getScrollParent(ref.current)});
|
|
179
181
|
} else {
|
|
180
|
-
let next = keyboardDelegate.getKeyRightOf(node.key);
|
|
182
|
+
let next = keyboardDelegate.getKeyRightOf?.(node.key);
|
|
181
183
|
if (next !== node.key) {
|
|
182
184
|
// We prevent the capturing event from reaching children of the cell, e.g. pickers.
|
|
183
185
|
// We want arrow keys to navigate to the next cell instead. We need to re-dispatch
|
|
184
186
|
// the event from a higher parent so it still bubbles and gets handled by useSelectableCollection.
|
|
185
|
-
ref.current.parentElement
|
|
187
|
+
ref.current.parentElement?.dispatchEvent(
|
|
186
188
|
new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)
|
|
187
189
|
);
|
|
188
190
|
break;
|
|
@@ -212,7 +214,7 @@ export function useGridCell<T, C extends GridCollection<T>>(props: GridCellProps
|
|
|
212
214
|
if (!e.altKey && ref.current.contains(e.target as Element)) {
|
|
213
215
|
e.stopPropagation();
|
|
214
216
|
e.preventDefault();
|
|
215
|
-
ref.current.parentElement
|
|
217
|
+
ref.current.parentElement?.dispatchEvent(
|
|
216
218
|
new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)
|
|
217
219
|
);
|
|
218
220
|
}
|
|
@@ -266,7 +268,9 @@ export function useGridCell<T, C extends GridCollection<T>>(props: GridCellProps
|
|
|
266
268
|
let tabindex = el.getAttribute('tabindex');
|
|
267
269
|
el.removeAttribute('tabindex');
|
|
268
270
|
requestAnimationFrame(() => {
|
|
269
|
-
|
|
271
|
+
if (tabindex != null) {
|
|
272
|
+
el.setAttribute('tabindex', tabindex);
|
|
273
|
+
}
|
|
270
274
|
});
|
|
271
275
|
};
|
|
272
276
|
}
|
|
@@ -278,10 +282,10 @@ export function useGridCell<T, C extends GridCollection<T>>(props: GridCellProps
|
|
|
278
282
|
}
|
|
279
283
|
|
|
280
284
|
function last(walker: TreeWalker) {
|
|
281
|
-
let next: FocusableElement;
|
|
282
|
-
let last: FocusableElement;
|
|
285
|
+
let next: FocusableElement | null = null;
|
|
286
|
+
let last: FocusableElement | null = null;
|
|
283
287
|
do {
|
|
284
|
-
last = walker.lastChild() as FocusableElement;
|
|
288
|
+
last = walker.lastChild() as FocusableElement | null;
|
|
285
289
|
if (last) {
|
|
286
290
|
next = last;
|
|
287
291
|
}
|
package/src/useGridRow.ts
CHANGED
|
@@ -52,8 +52,8 @@ export function useGridRow<T, C extends GridCollection<T>, S extends GridState<T
|
|
|
52
52
|
onAction
|
|
53
53
|
} = props;
|
|
54
54
|
|
|
55
|
-
let {actions} = gridMap.get(state)
|
|
56
|
-
let onRowAction = actions.onRowAction ? () => actions.onRowAction(node.key) : onAction;
|
|
55
|
+
let {actions} = gridMap.get(state)!;
|
|
56
|
+
let onRowAction = actions.onRowAction ? () => actions.onRowAction?.(node.key) : onAction;
|
|
57
57
|
let {itemProps, ...states} = useSelectableItem({
|
|
58
58
|
selectionManager: state.selectionManager,
|
|
59
59
|
key: node.key,
|
|
@@ -58,7 +58,7 @@ export function useGridSelectionAnnouncement<T>(props: GridSelectionAnnouncement
|
|
|
58
58
|
|
|
59
59
|
// If adding or removing a single row from the selection, announce the name of that item.
|
|
60
60
|
let isReplace = state.selectionManager.selectionBehavior === 'replace';
|
|
61
|
-
let messages = [];
|
|
61
|
+
let messages: string[] = [];
|
|
62
62
|
|
|
63
63
|
if ((state.selectionManager.selectedKeys.size === 1 && isReplace)) {
|
|
64
64
|
if (state.collection.getItem(state.selectionManager.selectedKeys.keys().next().value)) {
|
|
@@ -39,7 +39,7 @@ export function useHighlightSelectionDescription(props: HighlightSelectionDescri
|
|
|
39
39
|
let selectionMode = props.selectionManager.selectionMode;
|
|
40
40
|
let selectionBehavior = props.selectionManager.selectionBehavior;
|
|
41
41
|
|
|
42
|
-
let message
|
|
42
|
+
let message: string | undefined;
|
|
43
43
|
if (shouldLongPress) {
|
|
44
44
|
message = stringFormatter.format('longPressToSelect');
|
|
45
45
|
}
|
package/src/utils.ts
CHANGED
|
@@ -17,8 +17,8 @@ import type {Key, KeyboardDelegate} from '@react-types/shared';
|
|
|
17
17
|
interface GridMapShared {
|
|
18
18
|
keyboardDelegate: KeyboardDelegate,
|
|
19
19
|
actions: {
|
|
20
|
-
onRowAction
|
|
21
|
-
onCellAction
|
|
20
|
+
onRowAction?: (key: Key) => void,
|
|
21
|
+
onCellAction?: (key: Key) => void
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|