downshift 7.0.0-alpha.1 → 7.0.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/CHANGELOG.md +5 -0
- package/README.md +8 -0
- package/dist/downshift.cjs.js +256 -639
- package/dist/downshift.esm.js +256 -639
- package/dist/downshift.native.cjs.js +257 -638
- package/dist/downshift.umd.js +254 -634
- package/dist/downshift.umd.js.map +1 -1
- package/dist/downshift.umd.min.js.map +1 -1
- package/dist/src/hooks/utils.d.ts +1 -1
- package/flow-typed/npm/downshift_v2.x.x.js.flow +2 -2
- package/package.json +1 -1
- package/preact/dist/downshift.cjs.js +256 -636
- package/preact/dist/downshift.esm.js +256 -636
- package/preact/dist/downshift.umd.js +254 -631
- package/preact/dist/downshift.umd.js.map +1 -1
- package/preact/dist/downshift.umd.min.js.map +1 -1
- package/typings/index.d.ts +3 -3
|
@@ -14,6 +14,7 @@ var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
|
|
|
14
14
|
var computeScrollIntoView__default = /*#__PURE__*/_interopDefaultLegacy(computeScrollIntoView);
|
|
15
15
|
|
|
16
16
|
let idCounter = 0;
|
|
17
|
+
|
|
17
18
|
/**
|
|
18
19
|
* Accepts a parameter and returns it if it's a function
|
|
19
20
|
* or a noop function if it's not. This allows us to
|
|
@@ -22,24 +23,20 @@ let idCounter = 0;
|
|
|
22
23
|
* @param {Function} cb the callback
|
|
23
24
|
* @return {Function} a function
|
|
24
25
|
*/
|
|
25
|
-
|
|
26
26
|
function cbToCb(cb) {
|
|
27
27
|
return typeof cb === 'function' ? cb : noop;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
29
|
function noop() {}
|
|
30
|
+
|
|
31
31
|
/**
|
|
32
32
|
* Scroll node into view if necessary
|
|
33
33
|
* @param {HTMLElement} node the element that should scroll into view
|
|
34
34
|
* @param {HTMLElement} menuNode the menu element of the component
|
|
35
35
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
38
36
|
function scrollIntoView(node, menuNode) {
|
|
39
37
|
if (!node) {
|
|
40
38
|
return;
|
|
41
39
|
}
|
|
42
|
-
|
|
43
40
|
const actions = computeScrollIntoView__default["default"](node, {
|
|
44
41
|
boundary: menuNode,
|
|
45
42
|
block: 'nearest',
|
|
@@ -55,18 +52,18 @@ function scrollIntoView(node, menuNode) {
|
|
|
55
52
|
el.scrollLeft = left;
|
|
56
53
|
});
|
|
57
54
|
}
|
|
55
|
+
|
|
58
56
|
/**
|
|
59
57
|
* @param {HTMLElement} parent the parent node
|
|
60
58
|
* @param {HTMLElement} child the child node
|
|
61
59
|
* @param {Window} environment The window context where downshift renders.
|
|
62
60
|
* @return {Boolean} whether the parent is the child or the child is in the parent
|
|
63
61
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
62
|
function isOrContainsNode(parent, child, environment) {
|
|
67
63
|
const result = parent === child || child instanceof environment.Node && parent.contains && parent.contains(child);
|
|
68
64
|
return result;
|
|
69
65
|
}
|
|
66
|
+
|
|
70
67
|
/**
|
|
71
68
|
* Simple debounce implementation. Will call the given
|
|
72
69
|
* function once after the time given has passed since
|
|
@@ -75,32 +72,27 @@ function isOrContainsNode(parent, child, environment) {
|
|
|
75
72
|
* @param {Number} time the time to wait
|
|
76
73
|
* @return {Function} the debounced function
|
|
77
74
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
80
75
|
function debounce(fn, time) {
|
|
81
76
|
let timeoutId;
|
|
82
|
-
|
|
83
77
|
function cancel() {
|
|
84
78
|
if (timeoutId) {
|
|
85
79
|
clearTimeout(timeoutId);
|
|
86
80
|
}
|
|
87
81
|
}
|
|
88
|
-
|
|
89
82
|
function wrapper() {
|
|
90
83
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
91
84
|
args[_key] = arguments[_key];
|
|
92
85
|
}
|
|
93
|
-
|
|
94
86
|
cancel();
|
|
95
87
|
timeoutId = setTimeout(() => {
|
|
96
88
|
timeoutId = null;
|
|
97
89
|
fn(...args);
|
|
98
90
|
}, time);
|
|
99
91
|
}
|
|
100
|
-
|
|
101
92
|
wrapper.cancel = cancel;
|
|
102
93
|
return wrapper;
|
|
103
94
|
}
|
|
95
|
+
|
|
104
96
|
/**
|
|
105
97
|
* This is intended to be used to compose event handlers.
|
|
106
98
|
* They are executed in order until one of them sets
|
|
@@ -108,33 +100,26 @@ function debounce(fn, time) {
|
|
|
108
100
|
* @param {...Function} fns the event handler functions
|
|
109
101
|
* @return {Function} the event handler to add to an element
|
|
110
102
|
*/
|
|
111
|
-
|
|
112
|
-
|
|
113
103
|
function callAllEventHandlers() {
|
|
114
104
|
for (var _len2 = arguments.length, fns = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
115
105
|
fns[_key2] = arguments[_key2];
|
|
116
106
|
}
|
|
117
|
-
|
|
118
107
|
return function (event) {
|
|
119
108
|
for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
|
|
120
109
|
args[_key3 - 1] = arguments[_key3];
|
|
121
110
|
}
|
|
122
|
-
|
|
123
111
|
return fns.some(fn => {
|
|
124
112
|
if (fn) {
|
|
125
113
|
fn(event, ...args);
|
|
126
114
|
}
|
|
127
|
-
|
|
128
115
|
return event.preventDownshiftDefault || event.hasOwnProperty('nativeEvent') && event.nativeEvent.preventDownshiftDefault;
|
|
129
116
|
});
|
|
130
117
|
};
|
|
131
118
|
}
|
|
132
|
-
|
|
133
119
|
function handleRefs() {
|
|
134
120
|
for (var _len4 = arguments.length, refs = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
|
|
135
121
|
refs[_key4] = arguments[_key4];
|
|
136
122
|
}
|
|
137
|
-
|
|
138
123
|
return node => {
|
|
139
124
|
refs.forEach(ref => {
|
|
140
125
|
if (typeof ref === 'function') {
|
|
@@ -145,23 +130,22 @@ function handleRefs() {
|
|
|
145
130
|
});
|
|
146
131
|
};
|
|
147
132
|
}
|
|
133
|
+
|
|
148
134
|
/**
|
|
149
135
|
* This generates a unique ID for an instance of Downshift
|
|
150
136
|
* @return {String} the unique ID
|
|
151
137
|
*/
|
|
152
|
-
|
|
153
|
-
|
|
154
138
|
function generateId() {
|
|
155
139
|
return String(idCounter++);
|
|
156
140
|
}
|
|
141
|
+
|
|
157
142
|
/**
|
|
158
143
|
* Resets idCounter to 0. Used for SSR.
|
|
159
144
|
*/
|
|
160
|
-
|
|
161
|
-
|
|
162
145
|
function resetIdCounter() {
|
|
163
146
|
idCounter = 0;
|
|
164
147
|
}
|
|
148
|
+
|
|
165
149
|
/**
|
|
166
150
|
* Default implementation for status message. Only added when menu is open.
|
|
167
151
|
* Will specify if there are results in the list, and if so, how many,
|
|
@@ -170,29 +154,24 @@ function resetIdCounter() {
|
|
|
170
154
|
* @param {Object} param the downshift state and other relevant properties
|
|
171
155
|
* @return {String} the a11y status message
|
|
172
156
|
*/
|
|
173
|
-
|
|
174
|
-
|
|
175
157
|
function getA11yStatusMessage$1(_ref2) {
|
|
176
158
|
let {
|
|
177
159
|
isOpen,
|
|
178
160
|
resultCount,
|
|
179
161
|
previousResultCount
|
|
180
162
|
} = _ref2;
|
|
181
|
-
|
|
182
163
|
if (!isOpen) {
|
|
183
164
|
return '';
|
|
184
165
|
}
|
|
185
|
-
|
|
186
166
|
if (!resultCount) {
|
|
187
167
|
return 'No results are available.';
|
|
188
168
|
}
|
|
189
|
-
|
|
190
169
|
if (resultCount !== previousResultCount) {
|
|
191
170
|
return `${resultCount} result${resultCount === 1 ? ' is' : 's are'} available, use up and down arrow keys to navigate. Press Enter key to select.`;
|
|
192
171
|
}
|
|
193
|
-
|
|
194
172
|
return '';
|
|
195
173
|
}
|
|
174
|
+
|
|
196
175
|
/**
|
|
197
176
|
* Takes an argument and if it's an array, returns the first item in the array
|
|
198
177
|
* otherwise returns the argument
|
|
@@ -200,64 +179,52 @@ function getA11yStatusMessage$1(_ref2) {
|
|
|
200
179
|
* @param {*} defaultValue the value if arg is falsey not defined
|
|
201
180
|
* @return {*} the arg or it's first item
|
|
202
181
|
*/
|
|
203
|
-
|
|
204
|
-
|
|
205
182
|
function unwrapArray(arg, defaultValue) {
|
|
206
|
-
arg = Array.isArray(arg) ?
|
|
207
|
-
/* istanbul ignore next (preact) */
|
|
208
|
-
arg[0] : arg;
|
|
209
|
-
|
|
183
|
+
arg = Array.isArray(arg) ? /* istanbul ignore next (preact) */arg[0] : arg;
|
|
210
184
|
if (!arg && defaultValue) {
|
|
211
185
|
return defaultValue;
|
|
212
186
|
} else {
|
|
213
187
|
return arg;
|
|
214
188
|
}
|
|
215
189
|
}
|
|
190
|
+
|
|
216
191
|
/**
|
|
217
192
|
* @param {Object} element (P)react element
|
|
218
193
|
* @return {Boolean} whether it's a DOM element
|
|
219
194
|
*/
|
|
220
|
-
|
|
221
|
-
|
|
222
195
|
function isDOMElement(element) {
|
|
223
196
|
|
|
224
|
-
|
|
197
|
+
// then we assume this is react
|
|
225
198
|
return typeof element.type === 'string';
|
|
226
199
|
}
|
|
200
|
+
|
|
227
201
|
/**
|
|
228
202
|
* @param {Object} element (P)react element
|
|
229
203
|
* @return {Object} the props
|
|
230
204
|
*/
|
|
231
|
-
|
|
232
|
-
|
|
233
205
|
function getElementProps(element) {
|
|
234
|
-
|
|
235
206
|
return element.props;
|
|
236
207
|
}
|
|
208
|
+
|
|
237
209
|
/**
|
|
238
210
|
* Throws a helpful error message for required properties. Useful
|
|
239
211
|
* to be used as a default in destructuring or object params.
|
|
240
212
|
* @param {String} fnName the function name
|
|
241
213
|
* @param {String} propName the prop name
|
|
242
214
|
*/
|
|
243
|
-
|
|
244
|
-
|
|
245
215
|
function requiredProp(fnName, propName) {
|
|
246
216
|
// eslint-disable-next-line no-console
|
|
247
217
|
console.error(`The property "${propName}" is required in "${fnName}"`);
|
|
248
218
|
}
|
|
249
|
-
|
|
250
219
|
const stateKeys = ['highlightedIndex', 'inputValue', 'isOpen', 'selectedItem', 'type'];
|
|
251
220
|
/**
|
|
252
221
|
* @param {Object} state the state object
|
|
253
222
|
* @return {Object} state that is relevant to downshift
|
|
254
223
|
*/
|
|
255
|
-
|
|
256
224
|
function pickState(state) {
|
|
257
225
|
if (state === void 0) {
|
|
258
226
|
state = {};
|
|
259
227
|
}
|
|
260
|
-
|
|
261
228
|
const result = {};
|
|
262
229
|
stateKeys.forEach(k => {
|
|
263
230
|
if (state.hasOwnProperty(k)) {
|
|
@@ -266,6 +233,7 @@ function pickState(state) {
|
|
|
266
233
|
});
|
|
267
234
|
return result;
|
|
268
235
|
}
|
|
236
|
+
|
|
269
237
|
/**
|
|
270
238
|
* This will perform a shallow merge of the given state object
|
|
271
239
|
* with the state coming from props
|
|
@@ -277,14 +245,13 @@ function pickState(state) {
|
|
|
277
245
|
* @param {Object} props The props that may contain controlled values.
|
|
278
246
|
* @returns {Object} The merged controlled state.
|
|
279
247
|
*/
|
|
280
|
-
|
|
281
|
-
|
|
282
248
|
function getState(state, props) {
|
|
283
249
|
return Object.keys(state).reduce((prevState, key) => {
|
|
284
250
|
prevState[key] = isControlledProp(props, key) ? props[key] : state[key];
|
|
285
251
|
return prevState;
|
|
286
252
|
}, {});
|
|
287
253
|
}
|
|
254
|
+
|
|
288
255
|
/**
|
|
289
256
|
* This determines whether a prop is a "controlled prop" meaning it is
|
|
290
257
|
* state which is controlled by the outside of this component rather
|
|
@@ -294,41 +261,36 @@ function getState(state, props) {
|
|
|
294
261
|
* @param {String} key the key to check
|
|
295
262
|
* @return {Boolean} whether it is a controlled controlled prop
|
|
296
263
|
*/
|
|
297
|
-
|
|
298
|
-
|
|
299
264
|
function isControlledProp(props, key) {
|
|
300
265
|
return props[key] !== undefined;
|
|
301
266
|
}
|
|
267
|
+
|
|
302
268
|
/**
|
|
303
269
|
* Normalizes the 'key' property of a KeyboardEvent in IE/Edge
|
|
304
270
|
* @param {Object} event a keyboardEvent object
|
|
305
271
|
* @return {String} keyboard key
|
|
306
272
|
*/
|
|
307
|
-
|
|
308
|
-
|
|
309
273
|
function normalizeArrowKey(event) {
|
|
310
274
|
const {
|
|
311
275
|
key,
|
|
312
276
|
keyCode
|
|
313
277
|
} = event;
|
|
314
278
|
/* istanbul ignore next (ie) */
|
|
315
|
-
|
|
316
279
|
if (keyCode >= 37 && keyCode <= 40 && key.indexOf('Arrow') !== 0) {
|
|
317
280
|
return `Arrow${key}`;
|
|
318
281
|
}
|
|
319
|
-
|
|
320
282
|
return key;
|
|
321
283
|
}
|
|
284
|
+
|
|
322
285
|
/**
|
|
323
286
|
* Simple check if the value passed is object literal
|
|
324
287
|
* @param {*} obj any things
|
|
325
288
|
* @return {Boolean} whether it's object literal
|
|
326
289
|
*/
|
|
327
|
-
|
|
328
|
-
|
|
329
290
|
function isPlainObject(obj) {
|
|
330
291
|
return Object.prototype.toString.call(obj) === '[object Object]';
|
|
331
292
|
}
|
|
293
|
+
|
|
332
294
|
/**
|
|
333
295
|
* Returns the new index in the list, in a circular way. If next value is out of bonds from the total,
|
|
334
296
|
* it will wrap to either 0 or itemCount - 1.
|
|
@@ -340,39 +302,30 @@ function isPlainObject(obj) {
|
|
|
340
302
|
* @param {boolean} circular Specify if navigation is circular. Default is true.
|
|
341
303
|
* @returns {number} The new index after the move.
|
|
342
304
|
*/
|
|
343
|
-
|
|
344
|
-
|
|
345
305
|
function getNextWrappingIndex(moveAmount, baseIndex, itemCount, getItemNodeFromIndex, circular) {
|
|
346
306
|
if (circular === void 0) {
|
|
347
307
|
circular = true;
|
|
348
308
|
}
|
|
349
|
-
|
|
350
309
|
if (itemCount === 0) {
|
|
351
310
|
return -1;
|
|
352
311
|
}
|
|
353
|
-
|
|
354
312
|
const itemsLastIndex = itemCount - 1;
|
|
355
|
-
|
|
356
313
|
if (typeof baseIndex !== 'number' || baseIndex < 0 || baseIndex >= itemCount) {
|
|
357
314
|
baseIndex = moveAmount > 0 ? -1 : itemsLastIndex + 1;
|
|
358
315
|
}
|
|
359
|
-
|
|
360
316
|
let newIndex = baseIndex + moveAmount;
|
|
361
|
-
|
|
362
317
|
if (newIndex < 0) {
|
|
363
318
|
newIndex = circular ? itemsLastIndex : 0;
|
|
364
319
|
} else if (newIndex > itemsLastIndex) {
|
|
365
320
|
newIndex = circular ? 0 : itemsLastIndex;
|
|
366
321
|
}
|
|
367
|
-
|
|
368
322
|
const nonDisabledNewIndex = getNextNonDisabledIndex(moveAmount, newIndex, itemCount, getItemNodeFromIndex, circular);
|
|
369
|
-
|
|
370
323
|
if (nonDisabledNewIndex === -1) {
|
|
371
324
|
return baseIndex >= itemCount ? -1 : baseIndex;
|
|
372
325
|
}
|
|
373
|
-
|
|
374
326
|
return nonDisabledNewIndex;
|
|
375
327
|
}
|
|
328
|
+
|
|
376
329
|
/**
|
|
377
330
|
* Returns the next index in the list of an item that is not disabled.
|
|
378
331
|
*
|
|
@@ -383,15 +336,11 @@ function getNextWrappingIndex(moveAmount, baseIndex, itemCount, getItemNodeFromI
|
|
|
383
336
|
* @param {boolean} circular Specify if navigation is circular. Default is true.
|
|
384
337
|
* @returns {number} The new index. Returns baseIndex if item is not disabled. Returns next non-disabled item otherwise. If no non-disabled found it will return -1.
|
|
385
338
|
*/
|
|
386
|
-
|
|
387
|
-
|
|
388
339
|
function getNextNonDisabledIndex(moveAmount, baseIndex, itemCount, getItemNodeFromIndex, circular) {
|
|
389
340
|
const currentElementNode = getItemNodeFromIndex(baseIndex);
|
|
390
|
-
|
|
391
341
|
if (!currentElementNode || !currentElementNode.hasAttribute('disabled')) {
|
|
392
342
|
return baseIndex;
|
|
393
343
|
}
|
|
394
|
-
|
|
395
344
|
if (moveAmount > 0) {
|
|
396
345
|
for (let index = baseIndex + 1; index < itemCount; index++) {
|
|
397
346
|
if (!getItemNodeFromIndex(index).hasAttribute('disabled')) {
|
|
@@ -405,13 +354,12 @@ function getNextNonDisabledIndex(moveAmount, baseIndex, itemCount, getItemNodeFr
|
|
|
405
354
|
}
|
|
406
355
|
}
|
|
407
356
|
}
|
|
408
|
-
|
|
409
357
|
if (circular) {
|
|
410
358
|
return moveAmount > 0 ? getNextNonDisabledIndex(1, 0, itemCount, getItemNodeFromIndex, false) : getNextNonDisabledIndex(-1, itemCount - 1, itemCount, getItemNodeFromIndex, false);
|
|
411
359
|
}
|
|
412
|
-
|
|
413
360
|
return -1;
|
|
414
361
|
}
|
|
362
|
+
|
|
415
363
|
/**
|
|
416
364
|
* Checks if event target is within the downshift elements.
|
|
417
365
|
*
|
|
@@ -422,20 +370,16 @@ function getNextNonDisabledIndex(moveAmount, baseIndex, itemCount, getItemNodeFr
|
|
|
422
370
|
*
|
|
423
371
|
* @returns {boolean} Whether or not the target is within downshift elements.
|
|
424
372
|
*/
|
|
425
|
-
|
|
426
|
-
|
|
427
373
|
function targetWithinDownshift(target, downshiftElements, environment, checkActiveElement) {
|
|
428
374
|
if (checkActiveElement === void 0) {
|
|
429
375
|
checkActiveElement = true;
|
|
430
376
|
}
|
|
431
|
-
|
|
432
377
|
return downshiftElements.some(contextNode => contextNode && (isOrContainsNode(contextNode, target, environment) || checkActiveElement && isOrContainsNode(contextNode, environment.document.activeElement, environment)));
|
|
433
|
-
}
|
|
434
|
-
|
|
378
|
+
}
|
|
435
379
|
|
|
380
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
436
381
|
let validateControlledUnchanged = noop;
|
|
437
382
|
/* istanbul ignore next */
|
|
438
|
-
|
|
439
383
|
if (process.env.NODE_ENV !== 'production') {
|
|
440
384
|
validateControlledUnchanged = (state, prevProps, nextProps) => {
|
|
441
385
|
const warningDescription = `This prop should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled Downshift element for the lifetime of the component. More info: https://github.com/downshift-js/downshift#control-props`;
|
|
@@ -454,39 +398,33 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
454
398
|
const cleanupStatus = debounce(documentProp => {
|
|
455
399
|
getStatusDiv(documentProp).textContent = '';
|
|
456
400
|
}, 500);
|
|
401
|
+
|
|
457
402
|
/**
|
|
458
403
|
* @param {String} status the status message
|
|
459
404
|
* @param {Object} documentProp document passed by the user.
|
|
460
405
|
*/
|
|
461
|
-
|
|
462
406
|
function setStatus(status, documentProp) {
|
|
463
407
|
const div = getStatusDiv(documentProp);
|
|
464
|
-
|
|
465
408
|
if (!status) {
|
|
466
409
|
return;
|
|
467
410
|
}
|
|
468
|
-
|
|
469
411
|
div.textContent = status;
|
|
470
412
|
cleanupStatus(documentProp);
|
|
471
413
|
}
|
|
414
|
+
|
|
472
415
|
/**
|
|
473
416
|
* Get the status node or create it if it does not already exist.
|
|
474
417
|
* @param {Object} documentProp document passed by the user.
|
|
475
418
|
* @return {HTMLElement} the status node.
|
|
476
419
|
*/
|
|
477
|
-
|
|
478
|
-
|
|
479
420
|
function getStatusDiv(documentProp) {
|
|
480
421
|
if (documentProp === void 0) {
|
|
481
422
|
documentProp = document;
|
|
482
423
|
}
|
|
483
|
-
|
|
484
424
|
let statusDiv = documentProp.getElementById('a11y-status-message');
|
|
485
|
-
|
|
486
425
|
if (statusDiv) {
|
|
487
426
|
return statusDiv;
|
|
488
427
|
}
|
|
489
|
-
|
|
490
428
|
statusDiv = documentProp.createElement('div');
|
|
491
429
|
statusDiv.setAttribute('id', 'a11y-status-message');
|
|
492
430
|
statusDiv.setAttribute('role', 'status');
|
|
@@ -546,27 +484,22 @@ var stateChangeTypes$3 = /*#__PURE__*/Object.freeze({
|
|
|
546
484
|
});
|
|
547
485
|
|
|
548
486
|
/* eslint camelcase:0 */
|
|
549
|
-
|
|
550
487
|
const Downshift = /*#__PURE__*/(() => {
|
|
551
488
|
class Downshift extends react.Component {
|
|
552
489
|
constructor(_props) {
|
|
553
490
|
var _this;
|
|
554
|
-
|
|
555
491
|
super(_props);
|
|
556
492
|
_this = this;
|
|
557
493
|
this.id = this.props.id || `downshift-${generateId()}`;
|
|
558
494
|
this.menuId = this.props.menuId || `${this.id}-menu`;
|
|
559
495
|
this.labelId = this.props.labelId || `${this.id}-label`;
|
|
560
496
|
this.inputId = this.props.inputId || `${this.id}-input`;
|
|
561
|
-
|
|
562
497
|
this.getItemId = this.props.getItemId || (index => `${this.id}-item-${index}`);
|
|
563
|
-
|
|
564
498
|
this.input = null;
|
|
565
499
|
this.items = [];
|
|
566
500
|
this.itemCount = null;
|
|
567
501
|
this.previousResultCount = 0;
|
|
568
502
|
this.timeoutIds = [];
|
|
569
|
-
|
|
570
503
|
this.internalSetTimeout = (fn, time) => {
|
|
571
504
|
const id = setTimeout(() => {
|
|
572
505
|
this.timeoutIds = this.timeoutIds.filter(i => i !== id);
|
|
@@ -574,32 +507,25 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
574
507
|
}, time);
|
|
575
508
|
this.timeoutIds.push(id);
|
|
576
509
|
};
|
|
577
|
-
|
|
578
510
|
this.setItemCount = count => {
|
|
579
511
|
this.itemCount = count;
|
|
580
512
|
};
|
|
581
|
-
|
|
582
513
|
this.unsetItemCount = () => {
|
|
583
514
|
this.itemCount = null;
|
|
584
515
|
};
|
|
585
|
-
|
|
586
516
|
this.setHighlightedIndex = function (highlightedIndex, otherStateToSet) {
|
|
587
517
|
if (highlightedIndex === void 0) {
|
|
588
518
|
highlightedIndex = _this.props.defaultHighlightedIndex;
|
|
589
519
|
}
|
|
590
|
-
|
|
591
520
|
if (otherStateToSet === void 0) {
|
|
592
521
|
otherStateToSet = {};
|
|
593
522
|
}
|
|
594
|
-
|
|
595
523
|
otherStateToSet = pickState(otherStateToSet);
|
|
596
|
-
|
|
597
524
|
_this.internalSetState({
|
|
598
525
|
highlightedIndex,
|
|
599
526
|
...otherStateToSet
|
|
600
527
|
});
|
|
601
528
|
};
|
|
602
|
-
|
|
603
529
|
this.clearSelection = cb => {
|
|
604
530
|
this.internalSetState({
|
|
605
531
|
selectedItem: null,
|
|
@@ -608,7 +534,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
608
534
|
isOpen: this.props.defaultIsOpen
|
|
609
535
|
}, cb);
|
|
610
536
|
};
|
|
611
|
-
|
|
612
537
|
this.selectItem = (item, otherStateToSet, cb) => {
|
|
613
538
|
otherStateToSet = pickState(otherStateToSet);
|
|
614
539
|
this.internalSetState({
|
|
@@ -619,114 +544,105 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
619
544
|
...otherStateToSet
|
|
620
545
|
}, cb);
|
|
621
546
|
};
|
|
622
|
-
|
|
623
547
|
this.selectItemAtIndex = (itemIndex, otherStateToSet, cb) => {
|
|
624
548
|
const item = this.items[itemIndex];
|
|
625
|
-
|
|
626
549
|
if (item == null) {
|
|
627
550
|
return;
|
|
628
551
|
}
|
|
629
|
-
|
|
630
552
|
this.selectItem(item, otherStateToSet, cb);
|
|
631
553
|
};
|
|
632
|
-
|
|
633
554
|
this.selectHighlightedItem = (otherStateToSet, cb) => {
|
|
634
555
|
return this.selectItemAtIndex(this.getState().highlightedIndex, otherStateToSet, cb);
|
|
635
556
|
};
|
|
636
|
-
|
|
637
557
|
this.internalSetState = (stateToSet, cb) => {
|
|
638
558
|
let isItemSelected, onChangeArg;
|
|
639
559
|
const onStateChangeArg = {};
|
|
640
|
-
const isStateToSetFunction = typeof stateToSet === 'function';
|
|
560
|
+
const isStateToSetFunction = typeof stateToSet === 'function';
|
|
561
|
+
|
|
562
|
+
// we want to call `onInputValueChange` before the `setState` call
|
|
641
563
|
// so someone controlling the `inputValue` state gets notified of
|
|
642
564
|
// the input change as soon as possible. This avoids issues with
|
|
643
565
|
// preserving the cursor position.
|
|
644
566
|
// See https://github.com/downshift-js/downshift/issues/217 for more info.
|
|
645
|
-
|
|
646
567
|
if (!isStateToSetFunction && stateToSet.hasOwnProperty('inputValue')) {
|
|
647
|
-
this.props.onInputValueChange(stateToSet.inputValue, {
|
|
568
|
+
this.props.onInputValueChange(stateToSet.inputValue, {
|
|
569
|
+
...this.getStateAndHelpers(),
|
|
648
570
|
...stateToSet
|
|
649
571
|
});
|
|
650
572
|
}
|
|
651
|
-
|
|
652
573
|
return this.setState(state => {
|
|
653
574
|
state = this.getState(state);
|
|
654
|
-
let newStateToSet = isStateToSetFunction ? stateToSet(state) : stateToSet;
|
|
575
|
+
let newStateToSet = isStateToSetFunction ? stateToSet(state) : stateToSet;
|
|
576
|
+
|
|
577
|
+
// Your own function that could modify the state that will be set.
|
|
578
|
+
newStateToSet = this.props.stateReducer(state, newStateToSet);
|
|
655
579
|
|
|
656
|
-
|
|
580
|
+
// checks if an item is selected, regardless of if it's different from
|
|
657
581
|
// what was selected before
|
|
658
582
|
// used to determine if onSelect and onChange callbacks should be called
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
583
|
+
isItemSelected = newStateToSet.hasOwnProperty('selectedItem');
|
|
584
|
+
// this keeps track of the object we want to call with setState
|
|
585
|
+
const nextState = {};
|
|
586
|
+
// we need to call on change if the outside world is controlling any of our state
|
|
663
587
|
// and we're trying to update that state. OR if the selection has changed and we're
|
|
664
588
|
// trying to update the selection
|
|
665
|
-
|
|
666
589
|
if (isItemSelected && newStateToSet.selectedItem !== state.selectedItem) {
|
|
667
590
|
onChangeArg = newStateToSet.selectedItem;
|
|
668
591
|
}
|
|
669
|
-
|
|
670
592
|
newStateToSet.type = newStateToSet.type || unknown;
|
|
671
593
|
Object.keys(newStateToSet).forEach(key => {
|
|
672
594
|
// onStateChangeArg should only have the state that is
|
|
673
595
|
// actually changing
|
|
674
596
|
if (state[key] !== newStateToSet[key]) {
|
|
675
597
|
onStateChangeArg[key] = newStateToSet[key];
|
|
676
|
-
}
|
|
598
|
+
}
|
|
599
|
+
// the type is useful for the onStateChangeArg
|
|
677
600
|
// but we don't actually want to set it in internal state.
|
|
678
601
|
// this is an undocumented feature for now... Not all internalSetState
|
|
679
602
|
// calls support it and I'm not certain we want them to yet.
|
|
680
603
|
// But it enables users controlling the isOpen state to know when
|
|
681
604
|
// the isOpen state changes due to mouseup events which is quite handy.
|
|
682
|
-
|
|
683
|
-
|
|
684
605
|
if (key === 'type') {
|
|
685
606
|
return;
|
|
686
607
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
608
|
+
newStateToSet[key];
|
|
609
|
+
// if it's coming from props, then we don't care to set it internally
|
|
690
610
|
if (!isControlledProp(this.props, key)) {
|
|
691
611
|
nextState[key] = newStateToSet[key];
|
|
692
612
|
}
|
|
693
|
-
});
|
|
694
|
-
// earlier, so we'll call it now that we know what the inputValue state will be.
|
|
613
|
+
});
|
|
695
614
|
|
|
615
|
+
// if stateToSet is a function, then we weren't able to call onInputValueChange
|
|
616
|
+
// earlier, so we'll call it now that we know what the inputValue state will be.
|
|
696
617
|
if (isStateToSetFunction && newStateToSet.hasOwnProperty('inputValue')) {
|
|
697
|
-
this.props.onInputValueChange(newStateToSet.inputValue, {
|
|
618
|
+
this.props.onInputValueChange(newStateToSet.inputValue, {
|
|
619
|
+
...this.getStateAndHelpers(),
|
|
698
620
|
...newStateToSet
|
|
699
621
|
});
|
|
700
622
|
}
|
|
701
|
-
|
|
702
623
|
return nextState;
|
|
703
624
|
}, () => {
|
|
704
625
|
// call the provided callback if it's a function
|
|
705
|
-
cbToCb(cb)();
|
|
706
|
-
// we have relevant information to pass them.
|
|
626
|
+
cbToCb(cb)();
|
|
707
627
|
|
|
628
|
+
// only call the onStateChange and onChange callbacks if
|
|
629
|
+
// we have relevant information to pass them.
|
|
708
630
|
const hasMoreStateThanType = Object.keys(onStateChangeArg).length > 1;
|
|
709
|
-
|
|
710
631
|
if (hasMoreStateThanType) {
|
|
711
632
|
this.props.onStateChange(onStateChangeArg, this.getStateAndHelpers());
|
|
712
633
|
}
|
|
713
|
-
|
|
714
634
|
if (isItemSelected) {
|
|
715
635
|
this.props.onSelect(stateToSet.selectedItem, this.getStateAndHelpers());
|
|
716
636
|
}
|
|
717
|
-
|
|
718
637
|
if (onChangeArg !== undefined) {
|
|
719
638
|
this.props.onChange(onChangeArg, this.getStateAndHelpers());
|
|
720
|
-
}
|
|
639
|
+
}
|
|
640
|
+
// this is currently undocumented and therefore subject to change
|
|
721
641
|
// We'll try to not break it, but just be warned.
|
|
722
|
-
|
|
723
|
-
|
|
724
642
|
this.props.onUserAction(onStateChangeArg, this.getStateAndHelpers());
|
|
725
643
|
});
|
|
726
644
|
};
|
|
727
|
-
|
|
728
645
|
this.rootRef = node => this._rootNode = node;
|
|
729
|
-
|
|
730
646
|
this.getRootProps = function (_temp, _temp2) {
|
|
731
647
|
let {
|
|
732
648
|
refKey = 'ref',
|
|
@@ -741,11 +657,9 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
741
657
|
_this.getRootProps.called = true;
|
|
742
658
|
_this.getRootProps.refKey = refKey;
|
|
743
659
|
_this.getRootProps.suppressRefError = suppressRefError;
|
|
744
|
-
|
|
745
660
|
const {
|
|
746
661
|
isOpen
|
|
747
662
|
} = _this.getState();
|
|
748
|
-
|
|
749
663
|
return {
|
|
750
664
|
[refKey]: handleRefs(ref, _this.rootRef),
|
|
751
665
|
role: 'combobox',
|
|
@@ -756,11 +670,9 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
756
670
|
...rest
|
|
757
671
|
};
|
|
758
672
|
};
|
|
759
|
-
|
|
760
673
|
this.keyDownHandlers = {
|
|
761
674
|
ArrowDown(event) {
|
|
762
675
|
event.preventDefault();
|
|
763
|
-
|
|
764
676
|
if (this.getState().isOpen) {
|
|
765
677
|
const amount = event.shiftKey ? 5 : 1;
|
|
766
678
|
this.moveHighlightedIndex(amount, {
|
|
@@ -772,7 +684,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
772
684
|
type: keyDownArrowDown
|
|
773
685
|
}, () => {
|
|
774
686
|
const itemCount = this.getItemCount();
|
|
775
|
-
|
|
776
687
|
if (itemCount > 0) {
|
|
777
688
|
const {
|
|
778
689
|
highlightedIndex
|
|
@@ -785,10 +696,8 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
785
696
|
});
|
|
786
697
|
}
|
|
787
698
|
},
|
|
788
|
-
|
|
789
699
|
ArrowUp(event) {
|
|
790
700
|
event.preventDefault();
|
|
791
|
-
|
|
792
701
|
if (this.getState().isOpen) {
|
|
793
702
|
const amount = event.shiftKey ? -5 : -1;
|
|
794
703
|
this.moveHighlightedIndex(amount, {
|
|
@@ -800,7 +709,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
800
709
|
type: keyDownArrowUp
|
|
801
710
|
}, () => {
|
|
802
711
|
const itemCount = this.getItemCount();
|
|
803
|
-
|
|
804
712
|
if (itemCount > 0) {
|
|
805
713
|
const {
|
|
806
714
|
highlightedIndex
|
|
@@ -813,32 +721,26 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
813
721
|
});
|
|
814
722
|
}
|
|
815
723
|
},
|
|
816
|
-
|
|
817
724
|
Enter(event) {
|
|
818
725
|
if (event.which === 229) {
|
|
819
726
|
return;
|
|
820
727
|
}
|
|
821
|
-
|
|
822
728
|
const {
|
|
823
729
|
isOpen,
|
|
824
730
|
highlightedIndex
|
|
825
731
|
} = this.getState();
|
|
826
|
-
|
|
827
732
|
if (isOpen && highlightedIndex != null) {
|
|
828
733
|
event.preventDefault();
|
|
829
734
|
const item = this.items[highlightedIndex];
|
|
830
735
|
const itemNode = this.getItemNodeFromIndex(highlightedIndex);
|
|
831
|
-
|
|
832
736
|
if (item == null || itemNode && itemNode.hasAttribute('disabled')) {
|
|
833
737
|
return;
|
|
834
738
|
}
|
|
835
|
-
|
|
836
739
|
this.selectHighlightedItem({
|
|
837
740
|
type: keyDownEnter
|
|
838
741
|
});
|
|
839
742
|
}
|
|
840
743
|
},
|
|
841
|
-
|
|
842
744
|
Escape(event) {
|
|
843
745
|
event.preventDefault();
|
|
844
746
|
this.reset({
|
|
@@ -849,68 +751,57 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
849
751
|
})
|
|
850
752
|
});
|
|
851
753
|
}
|
|
852
|
-
|
|
853
754
|
};
|
|
854
|
-
this.buttonKeyDownHandlers = {
|
|
855
|
-
|
|
755
|
+
this.buttonKeyDownHandlers = {
|
|
756
|
+
...this.keyDownHandlers,
|
|
856
757
|
' '(event) {
|
|
857
758
|
event.preventDefault();
|
|
858
759
|
this.toggleMenu({
|
|
859
760
|
type: keyDownSpaceButton
|
|
860
761
|
});
|
|
861
762
|
}
|
|
862
|
-
|
|
863
763
|
};
|
|
864
|
-
this.inputKeyDownHandlers = {
|
|
865
|
-
|
|
764
|
+
this.inputKeyDownHandlers = {
|
|
765
|
+
...this.keyDownHandlers,
|
|
866
766
|
Home(event) {
|
|
867
767
|
const {
|
|
868
768
|
isOpen
|
|
869
769
|
} = this.getState();
|
|
870
|
-
|
|
871
770
|
if (!isOpen) {
|
|
872
771
|
return;
|
|
873
772
|
}
|
|
874
|
-
|
|
875
773
|
event.preventDefault();
|
|
876
774
|
const itemCount = this.getItemCount();
|
|
877
|
-
|
|
878
775
|
if (itemCount <= 0 || !isOpen) {
|
|
879
776
|
return;
|
|
880
|
-
}
|
|
881
|
-
|
|
777
|
+
}
|
|
882
778
|
|
|
779
|
+
// get next non-disabled starting downwards from 0 if that's disabled.
|
|
883
780
|
const newHighlightedIndex = getNextNonDisabledIndex(1, 0, itemCount, index => this.getItemNodeFromIndex(index), false);
|
|
884
781
|
this.setHighlightedIndex(newHighlightedIndex, {
|
|
885
782
|
type: keyDownHome
|
|
886
783
|
});
|
|
887
784
|
},
|
|
888
|
-
|
|
889
785
|
End(event) {
|
|
890
786
|
const {
|
|
891
787
|
isOpen
|
|
892
788
|
} = this.getState();
|
|
893
|
-
|
|
894
789
|
if (!isOpen) {
|
|
895
790
|
return;
|
|
896
791
|
}
|
|
897
|
-
|
|
898
792
|
event.preventDefault();
|
|
899
793
|
const itemCount = this.getItemCount();
|
|
900
|
-
|
|
901
794
|
if (itemCount <= 0 || !isOpen) {
|
|
902
795
|
return;
|
|
903
|
-
}
|
|
904
|
-
|
|
796
|
+
}
|
|
905
797
|
|
|
798
|
+
// get next non-disabled starting upwards from last index if that's disabled.
|
|
906
799
|
const newHighlightedIndex = getNextNonDisabledIndex(-1, itemCount - 1, itemCount, index => this.getItemNodeFromIndex(index), false);
|
|
907
800
|
this.setHighlightedIndex(newHighlightedIndex, {
|
|
908
801
|
type: keyDownEnd
|
|
909
802
|
});
|
|
910
803
|
}
|
|
911
|
-
|
|
912
804
|
};
|
|
913
|
-
|
|
914
805
|
this.getToggleButtonProps = function (_temp3) {
|
|
915
806
|
let {
|
|
916
807
|
onClick,
|
|
@@ -920,11 +811,9 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
920
811
|
onBlur,
|
|
921
812
|
...rest
|
|
922
813
|
} = _temp3 === void 0 ? {} : _temp3;
|
|
923
|
-
|
|
924
814
|
const {
|
|
925
815
|
isOpen
|
|
926
816
|
} = _this.getState();
|
|
927
|
-
|
|
928
817
|
const enabledEventHandlers = /* istanbul ignore next (react-native) */
|
|
929
818
|
{
|
|
930
819
|
onPress: callAllEventHandlers(onPress, _this.buttonHandleClick)
|
|
@@ -940,26 +829,21 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
940
829
|
...rest
|
|
941
830
|
};
|
|
942
831
|
};
|
|
943
|
-
|
|
944
832
|
this.buttonHandleKeyUp = event => {
|
|
945
833
|
// Prevent click event from emitting in Firefox
|
|
946
834
|
event.preventDefault();
|
|
947
835
|
};
|
|
948
|
-
|
|
949
836
|
this.buttonHandleKeyDown = event => {
|
|
950
837
|
const key = normalizeArrowKey(event);
|
|
951
|
-
|
|
952
838
|
if (this.buttonKeyDownHandlers[key]) {
|
|
953
839
|
this.buttonKeyDownHandlers[key].call(this, event);
|
|
954
840
|
}
|
|
955
841
|
};
|
|
956
|
-
|
|
957
842
|
this.buttonHandleClick = event => {
|
|
958
|
-
event.preventDefault();
|
|
843
|
+
event.preventDefault();
|
|
844
|
+
// to simplify testing components that use downshift, we'll not wrap this in a setTimeout
|
|
959
845
|
// if the NODE_ENV is test. With the proper build system, this should be dead code eliminated
|
|
960
846
|
// when building for production and should therefore have no impact on production code.
|
|
961
|
-
|
|
962
|
-
|
|
963
847
|
if (process.env.NODE_ENV === 'test') {
|
|
964
848
|
this.toggleMenu({
|
|
965
849
|
type: clickButton
|
|
@@ -971,11 +855,9 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
971
855
|
}));
|
|
972
856
|
}
|
|
973
857
|
};
|
|
974
|
-
|
|
975
858
|
this.buttonHandleBlur = event => {
|
|
976
859
|
const blurTarget = event.target; // Save blur target for comparison with activeElement later
|
|
977
860
|
// Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not body element
|
|
978
|
-
|
|
979
861
|
this.internalSetTimeout(() => {
|
|
980
862
|
if (!this.isMouseDown && (this.props.environment.document.activeElement == null || this.props.environment.document.activeElement.id !== this.inputId) && this.props.environment.document.activeElement !== blurTarget // Do nothing if we refocus the same element again (to solve issue in Safari on iOS)
|
|
981
863
|
) {
|
|
@@ -985,7 +867,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
985
867
|
}
|
|
986
868
|
});
|
|
987
869
|
};
|
|
988
|
-
|
|
989
870
|
this.getLabelProps = props => {
|
|
990
871
|
return {
|
|
991
872
|
htmlFor: this.inputId,
|
|
@@ -993,7 +874,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
993
874
|
...props
|
|
994
875
|
};
|
|
995
876
|
};
|
|
996
|
-
|
|
997
877
|
this.getInputProps = function (_temp4) {
|
|
998
878
|
let {
|
|
999
879
|
onKeyDown,
|
|
@@ -1005,18 +885,16 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1005
885
|
} = _temp4 === void 0 ? {} : _temp4;
|
|
1006
886
|
let onChangeKey;
|
|
1007
887
|
let eventHandlers = {};
|
|
1008
|
-
/* istanbul ignore next (preact) */
|
|
1009
888
|
|
|
889
|
+
/* istanbul ignore next (preact) */
|
|
1010
890
|
{
|
|
1011
891
|
onChangeKey = 'onChange';
|
|
1012
892
|
}
|
|
1013
|
-
|
|
1014
893
|
const {
|
|
1015
894
|
inputValue,
|
|
1016
895
|
isOpen,
|
|
1017
896
|
highlightedIndex
|
|
1018
897
|
} = _this.getState();
|
|
1019
|
-
|
|
1020
898
|
if (!rest.disabled) {
|
|
1021
899
|
eventHandlers = {
|
|
1022
900
|
[onChangeKey]: callAllEventHandlers(onChange, onInput, _this.inputHandleChange),
|
|
@@ -1024,9 +902,8 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1024
902
|
onBlur: callAllEventHandlers(onBlur, _this.inputHandleBlur)
|
|
1025
903
|
};
|
|
1026
904
|
}
|
|
1027
|
-
/* istanbul ignore if (react-native) */
|
|
1028
|
-
|
|
1029
905
|
|
|
906
|
+
/* istanbul ignore if (react-native) */
|
|
1030
907
|
{
|
|
1031
908
|
eventHandlers = {
|
|
1032
909
|
onChange: callAllEventHandlers(onChange, onInput, _this.inputHandleChange),
|
|
@@ -1038,7 +915,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1038
915
|
onBlur: callAllEventHandlers(onBlur, _this.inputHandleBlur)
|
|
1039
916
|
};
|
|
1040
917
|
}
|
|
1041
|
-
|
|
1042
918
|
return {
|
|
1043
919
|
'aria-autocomplete': 'list',
|
|
1044
920
|
'aria-activedescendant': isOpen && typeof highlightedIndex === 'number' && highlightedIndex >= 0 ? _this.getItemId(highlightedIndex) : null,
|
|
@@ -1053,30 +929,24 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1053
929
|
...rest
|
|
1054
930
|
};
|
|
1055
931
|
};
|
|
1056
|
-
|
|
1057
932
|
this.inputHandleKeyDown = event => {
|
|
1058
933
|
const key = normalizeArrowKey(event);
|
|
1059
|
-
|
|
1060
934
|
if (key && this.inputKeyDownHandlers[key]) {
|
|
1061
935
|
this.inputKeyDownHandlers[key].call(this, event);
|
|
1062
936
|
}
|
|
1063
937
|
};
|
|
1064
|
-
|
|
1065
938
|
this.inputHandleChange = event => {
|
|
1066
939
|
this.internalSetState({
|
|
1067
940
|
type: changeInput,
|
|
1068
941
|
isOpen: true,
|
|
1069
|
-
inputValue: /* istanbul ignore next (react-native) */
|
|
1070
|
-
event.nativeEvent.text ,
|
|
942
|
+
inputValue: /* istanbul ignore next (react-native) */event.nativeEvent.text ,
|
|
1071
943
|
highlightedIndex: this.props.defaultHighlightedIndex
|
|
1072
944
|
});
|
|
1073
945
|
};
|
|
1074
|
-
|
|
1075
946
|
this.inputHandleBlur = () => {
|
|
1076
947
|
// Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not the body element
|
|
1077
948
|
this.internalSetTimeout(() => {
|
|
1078
949
|
const downshiftButtonIsActive = this.props.environment.document && !!this.props.environment.document.activeElement && !!this.props.environment.document.activeElement.dataset && this.props.environment.document.activeElement.dataset.toggle && this._rootNode && this._rootNode.contains(this.props.environment.document.activeElement);
|
|
1079
|
-
|
|
1080
950
|
if (!this.isMouseDown && !downshiftButtonIsActive) {
|
|
1081
951
|
this.reset({
|
|
1082
952
|
type: blurInput
|
|
@@ -1084,11 +954,9 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1084
954
|
}
|
|
1085
955
|
});
|
|
1086
956
|
};
|
|
1087
|
-
|
|
1088
957
|
this.menuRef = node => {
|
|
1089
958
|
this._menuNode = node;
|
|
1090
959
|
};
|
|
1091
|
-
|
|
1092
960
|
this.getMenuProps = function (_temp5, _temp6) {
|
|
1093
961
|
let {
|
|
1094
962
|
refKey = 'ref',
|
|
@@ -1109,7 +977,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1109
977
|
...props
|
|
1110
978
|
};
|
|
1111
979
|
};
|
|
1112
|
-
|
|
1113
980
|
this.getItemProps = function (_temp7) {
|
|
1114
981
|
let {
|
|
1115
982
|
onMouseMove,
|
|
@@ -1117,24 +984,17 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1117
984
|
onClick,
|
|
1118
985
|
onPress,
|
|
1119
986
|
index,
|
|
1120
|
-
item = process.env.NODE_ENV === 'production' ?
|
|
1121
|
-
/* istanbul ignore next */
|
|
1122
|
-
undefined : requiredProp('getItemProps', 'item'),
|
|
987
|
+
item = process.env.NODE_ENV === 'production' ? /* istanbul ignore next */undefined : requiredProp('getItemProps', 'item'),
|
|
1123
988
|
...rest
|
|
1124
989
|
} = _temp7 === void 0 ? {} : _temp7;
|
|
1125
|
-
|
|
1126
990
|
if (index === undefined) {
|
|
1127
991
|
_this.items.push(item);
|
|
1128
|
-
|
|
1129
992
|
index = _this.items.indexOf(item);
|
|
1130
993
|
} else {
|
|
1131
994
|
_this.items[index] = item;
|
|
1132
995
|
}
|
|
1133
|
-
|
|
1134
|
-
const
|
|
1135
|
-
'onPress' ;
|
|
1136
|
-
const customClickHandler = /* istanbul ignore next (react-native) */
|
|
1137
|
-
onPress ;
|
|
996
|
+
const onSelectKey = /* istanbul ignore next (react-native) */'onPress' ;
|
|
997
|
+
const customClickHandler = /* istanbul ignore next (react-native) */onPress ;
|
|
1138
998
|
const enabledEventHandlers = {
|
|
1139
999
|
// onMouseMove is used over onMouseEnter here. onMouseMove
|
|
1140
1000
|
// is only triggered on actual mouse movement while onMouseEnter
|
|
@@ -1143,17 +1003,15 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1143
1003
|
if (index === _this.getState().highlightedIndex) {
|
|
1144
1004
|
return;
|
|
1145
1005
|
}
|
|
1146
|
-
|
|
1147
1006
|
_this.setHighlightedIndex(index, {
|
|
1148
1007
|
type: itemMouseEnter
|
|
1149
|
-
});
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
// We never want to manually scroll when changing state based
|
|
1150
1011
|
// on `onMouseMove` because we will be moving the element out
|
|
1151
1012
|
// from under the user which is currently scrolling/moving the
|
|
1152
1013
|
// cursor
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
1014
|
_this.avoidScrolling = true;
|
|
1156
|
-
|
|
1157
1015
|
_this.internalSetTimeout(() => _this.avoidScrolling = false, 250);
|
|
1158
1016
|
}),
|
|
1159
1017
|
onMouseDown: callAllEventHandlers(onMouseDown, event => {
|
|
@@ -1167,9 +1025,10 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1167
1025
|
type: clickItem
|
|
1168
1026
|
});
|
|
1169
1027
|
})
|
|
1170
|
-
};
|
|
1171
|
-
// of the activeElement if clicking on disabled items
|
|
1028
|
+
};
|
|
1172
1029
|
|
|
1030
|
+
// Passing down the onMouseDown handler to prevent redirect
|
|
1031
|
+
// of the activeElement if clicking on disabled items
|
|
1173
1032
|
const eventHandlers = rest.disabled ? {
|
|
1174
1033
|
onMouseDown: enabledEventHandlers.onMouseDown
|
|
1175
1034
|
} : enabledEventHandlers;
|
|
@@ -1181,18 +1040,14 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1181
1040
|
...rest
|
|
1182
1041
|
};
|
|
1183
1042
|
};
|
|
1184
|
-
|
|
1185
1043
|
this.clearItems = () => {
|
|
1186
1044
|
this.items = [];
|
|
1187
1045
|
};
|
|
1188
|
-
|
|
1189
1046
|
this.reset = function (otherStateToSet, cb) {
|
|
1190
1047
|
if (otherStateToSet === void 0) {
|
|
1191
1048
|
otherStateToSet = {};
|
|
1192
1049
|
}
|
|
1193
|
-
|
|
1194
1050
|
otherStateToSet = pickState(otherStateToSet);
|
|
1195
|
-
|
|
1196
1051
|
_this.internalSetState(_ref => {
|
|
1197
1052
|
let {
|
|
1198
1053
|
selectedItem
|
|
@@ -1205,14 +1060,11 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1205
1060
|
};
|
|
1206
1061
|
}, cb);
|
|
1207
1062
|
};
|
|
1208
|
-
|
|
1209
1063
|
this.toggleMenu = function (otherStateToSet, cb) {
|
|
1210
1064
|
if (otherStateToSet === void 0) {
|
|
1211
1065
|
otherStateToSet = {};
|
|
1212
1066
|
}
|
|
1213
|
-
|
|
1214
1067
|
otherStateToSet = pickState(otherStateToSet);
|
|
1215
|
-
|
|
1216
1068
|
_this.internalSetState(_ref2 => {
|
|
1217
1069
|
let {
|
|
1218
1070
|
isOpen
|
|
@@ -1229,29 +1081,24 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1229
1081
|
isOpen,
|
|
1230
1082
|
highlightedIndex
|
|
1231
1083
|
} = _this.getState();
|
|
1232
|
-
|
|
1233
1084
|
if (isOpen) {
|
|
1234
1085
|
if (_this.getItemCount() > 0 && typeof highlightedIndex === 'number') {
|
|
1235
1086
|
_this.setHighlightedIndex(highlightedIndex, otherStateToSet);
|
|
1236
1087
|
}
|
|
1237
1088
|
}
|
|
1238
|
-
|
|
1239
1089
|
cbToCb(cb)();
|
|
1240
1090
|
});
|
|
1241
1091
|
};
|
|
1242
|
-
|
|
1243
1092
|
this.openMenu = cb => {
|
|
1244
1093
|
this.internalSetState({
|
|
1245
1094
|
isOpen: true
|
|
1246
1095
|
}, cb);
|
|
1247
1096
|
};
|
|
1248
|
-
|
|
1249
1097
|
this.closeMenu = cb => {
|
|
1250
1098
|
this.internalSetState({
|
|
1251
1099
|
isOpen: false
|
|
1252
1100
|
}, cb);
|
|
1253
1101
|
};
|
|
1254
|
-
|
|
1255
1102
|
this.updateStatus = debounce(() => {
|
|
1256
1103
|
const state = this.getState();
|
|
1257
1104
|
const item = this.items[state.highlightedIndex];
|
|
@@ -1277,21 +1124,17 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1277
1124
|
initialInputValue: _inputValue = '',
|
|
1278
1125
|
initialSelectedItem: _selectedItem = null
|
|
1279
1126
|
} = this.props;
|
|
1280
|
-
|
|
1281
1127
|
const _state = this.getState({
|
|
1282
1128
|
highlightedIndex: _highlightedIndex,
|
|
1283
1129
|
isOpen: _isOpen,
|
|
1284
1130
|
inputValue: _inputValue,
|
|
1285
1131
|
selectedItem: _selectedItem
|
|
1286
1132
|
});
|
|
1287
|
-
|
|
1288
1133
|
if (_state.selectedItem != null && this.props.initialInputValue === undefined) {
|
|
1289
1134
|
_state.inputValue = this.props.itemToString(_state.selectedItem);
|
|
1290
1135
|
}
|
|
1291
|
-
|
|
1292
1136
|
this.state = _state;
|
|
1293
1137
|
}
|
|
1294
|
-
|
|
1295
1138
|
/**
|
|
1296
1139
|
* Clear all running timeouts
|
|
1297
1140
|
*/
|
|
@@ -1301,6 +1144,7 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1301
1144
|
});
|
|
1302
1145
|
this.timeoutIds = [];
|
|
1303
1146
|
}
|
|
1147
|
+
|
|
1304
1148
|
/**
|
|
1305
1149
|
* Gets the state based on internal state or props
|
|
1306
1150
|
* If a state value is passed via props, then that
|
|
@@ -1310,51 +1154,40 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1310
1154
|
* @param {Object} stateToMerge defaults to this.state
|
|
1311
1155
|
* @return {Object} the state
|
|
1312
1156
|
*/
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
1157
|
getState(stateToMerge) {
|
|
1316
1158
|
if (stateToMerge === void 0) {
|
|
1317
1159
|
stateToMerge = this.state;
|
|
1318
1160
|
}
|
|
1319
|
-
|
|
1320
1161
|
return getState(stateToMerge, this.props);
|
|
1321
1162
|
}
|
|
1322
|
-
|
|
1323
1163
|
getItemCount() {
|
|
1324
1164
|
// things read better this way. They're in priority order:
|
|
1325
1165
|
// 1. `this.itemCount`
|
|
1326
1166
|
// 2. `this.props.itemCount`
|
|
1327
1167
|
// 3. `this.items.length`
|
|
1328
1168
|
let itemCount = this.items.length;
|
|
1329
|
-
|
|
1330
1169
|
if (this.itemCount != null) {
|
|
1331
1170
|
itemCount = this.itemCount;
|
|
1332
1171
|
} else if (this.props.itemCount !== undefined) {
|
|
1333
1172
|
itemCount = this.props.itemCount;
|
|
1334
1173
|
}
|
|
1335
|
-
|
|
1336
1174
|
return itemCount;
|
|
1337
1175
|
}
|
|
1338
|
-
|
|
1339
1176
|
getItemNodeFromIndex(index) {
|
|
1340
1177
|
return this.props.environment.document.getElementById(this.getItemId(index));
|
|
1341
1178
|
}
|
|
1342
|
-
|
|
1343
1179
|
scrollHighlightedItemIntoView() {
|
|
1344
1180
|
}
|
|
1345
|
-
|
|
1346
1181
|
moveHighlightedIndex(amount, otherStateToSet) {
|
|
1347
1182
|
const itemCount = this.getItemCount();
|
|
1348
1183
|
const {
|
|
1349
1184
|
highlightedIndex
|
|
1350
1185
|
} = this.getState();
|
|
1351
|
-
|
|
1352
1186
|
if (itemCount > 0) {
|
|
1353
1187
|
const nextHighlightedIndex = getNextWrappingIndex(amount, highlightedIndex, itemCount, index => this.getItemNodeFromIndex(index));
|
|
1354
1188
|
this.setHighlightedIndex(nextHighlightedIndex, otherStateToSet);
|
|
1355
1189
|
}
|
|
1356
1190
|
}
|
|
1357
|
-
|
|
1358
1191
|
getStateAndHelpers() {
|
|
1359
1192
|
const {
|
|
1360
1193
|
highlightedIndex,
|
|
@@ -1421,24 +1254,23 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1421
1254
|
isOpen,
|
|
1422
1255
|
selectedItem
|
|
1423
1256
|
};
|
|
1424
|
-
}
|
|
1257
|
+
}
|
|
1425
1258
|
|
|
1259
|
+
//////////////////////////// ROOT
|
|
1426
1260
|
|
|
1427
1261
|
componentDidMount() {
|
|
1428
1262
|
/* istanbul ignore if (react-native) */
|
|
1429
1263
|
if (process.env.NODE_ENV !== 'production' && !true && this.getMenuProps.called && !this.getMenuProps.suppressRefError) {
|
|
1430
1264
|
validateGetMenuPropsCalledCorrectly(this._menuNode, this.getMenuProps);
|
|
1431
1265
|
}
|
|
1432
|
-
/* istanbul ignore if (react-native) */
|
|
1433
|
-
|
|
1434
1266
|
|
|
1267
|
+
/* istanbul ignore if (react-native) */
|
|
1435
1268
|
{
|
|
1436
1269
|
this.cleanup = () => {
|
|
1437
1270
|
this.internalClearTimeouts();
|
|
1438
1271
|
};
|
|
1439
1272
|
}
|
|
1440
1273
|
}
|
|
1441
|
-
|
|
1442
1274
|
shouldScroll(prevState, prevProps) {
|
|
1443
1275
|
const {
|
|
1444
1276
|
highlightedIndex: currentHighlightedIndex
|
|
@@ -1450,82 +1282,72 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1450
1282
|
const scrollWhenNavigating = currentHighlightedIndex !== prevHighlightedIndex;
|
|
1451
1283
|
return scrollWhenOpen || scrollWhenNavigating;
|
|
1452
1284
|
}
|
|
1453
|
-
|
|
1454
1285
|
componentDidUpdate(prevProps, prevState) {
|
|
1455
1286
|
if (process.env.NODE_ENV !== 'production') {
|
|
1456
1287
|
validateControlledUnchanged(this.state, prevProps, this.props);
|
|
1457
1288
|
}
|
|
1458
|
-
|
|
1459
1289
|
if (isControlledProp(this.props, 'selectedItem') && this.props.selectedItemChanged(prevProps.selectedItem, this.props.selectedItem)) {
|
|
1460
1290
|
this.internalSetState({
|
|
1461
1291
|
type: controlledPropUpdatedSelectedItem,
|
|
1462
1292
|
inputValue: this.props.itemToString(this.props.selectedItem)
|
|
1463
1293
|
});
|
|
1464
1294
|
}
|
|
1465
|
-
|
|
1466
1295
|
if (!this.avoidScrolling && this.shouldScroll(prevState, prevProps)) {
|
|
1467
1296
|
this.scrollHighlightedItemIntoView();
|
|
1468
1297
|
}
|
|
1469
1298
|
}
|
|
1470
|
-
|
|
1471
1299
|
componentWillUnmount() {
|
|
1472
1300
|
this.cleanup(); // avoids memory leak
|
|
1473
1301
|
}
|
|
1474
1302
|
|
|
1475
1303
|
render() {
|
|
1476
|
-
const children = unwrapArray(this.props.children, noop);
|
|
1304
|
+
const children = unwrapArray(this.props.children, noop);
|
|
1305
|
+
// because the items are rerendered every time we call the children
|
|
1477
1306
|
// we clear this out each render and it will be populated again as
|
|
1478
1307
|
// getItemProps is called.
|
|
1479
|
-
|
|
1480
|
-
|
|
1308
|
+
this.clearItems();
|
|
1309
|
+
// we reset this so we know whether the user calls getRootProps during
|
|
1481
1310
|
// this render. If they do then we don't need to do anything,
|
|
1482
1311
|
// if they don't then we need to clone the element they return and
|
|
1483
1312
|
// apply the props for them.
|
|
1484
|
-
|
|
1485
1313
|
this.getRootProps.called = false;
|
|
1486
1314
|
this.getRootProps.refKey = undefined;
|
|
1487
|
-
this.getRootProps.suppressRefError = undefined;
|
|
1488
|
-
|
|
1315
|
+
this.getRootProps.suppressRefError = undefined;
|
|
1316
|
+
// we do something similar for getMenuProps
|
|
1489
1317
|
this.getMenuProps.called = false;
|
|
1490
1318
|
this.getMenuProps.refKey = undefined;
|
|
1491
|
-
this.getMenuProps.suppressRefError = undefined;
|
|
1492
|
-
|
|
1493
|
-
this.getLabelProps.called = false;
|
|
1494
|
-
|
|
1319
|
+
this.getMenuProps.suppressRefError = undefined;
|
|
1320
|
+
// we do something similar for getLabelProps
|
|
1321
|
+
this.getLabelProps.called = false;
|
|
1322
|
+
// and something similar for getInputProps
|
|
1495
1323
|
this.getInputProps.called = false;
|
|
1496
1324
|
const element = unwrapArray(children(this.getStateAndHelpers()));
|
|
1497
|
-
|
|
1498
1325
|
if (!element) {
|
|
1499
1326
|
return null;
|
|
1500
1327
|
}
|
|
1501
|
-
|
|
1502
1328
|
if (this.getRootProps.called || this.props.suppressRefError) {
|
|
1503
1329
|
if (process.env.NODE_ENV !== 'production' && !this.getRootProps.suppressRefError && !this.props.suppressRefError) {
|
|
1504
1330
|
validateGetRootPropsCalledCorrectly(element, this.getRootProps);
|
|
1505
1331
|
}
|
|
1506
|
-
|
|
1507
1332
|
return element;
|
|
1508
1333
|
} else if (isDOMElement(element)) {
|
|
1509
1334
|
// they didn't apply the root props, but we can clone
|
|
1510
1335
|
// this and apply the props ourselves
|
|
1511
1336
|
return /*#__PURE__*/react.cloneElement(element, this.getRootProps(getElementProps(element)));
|
|
1512
1337
|
}
|
|
1513
|
-
/* istanbul ignore else */
|
|
1514
|
-
|
|
1515
1338
|
|
|
1339
|
+
/* istanbul ignore else */
|
|
1516
1340
|
if (process.env.NODE_ENV !== 'production') {
|
|
1517
1341
|
// they didn't apply the root props, but they need to
|
|
1518
1342
|
// otherwise we can't query around the autocomplete
|
|
1343
|
+
|
|
1519
1344
|
throw new Error('downshift: If you return a non-DOM element, you must apply the getRootProps function');
|
|
1520
1345
|
}
|
|
1521
|
-
/* istanbul ignore next */
|
|
1522
|
-
|
|
1523
1346
|
|
|
1347
|
+
/* istanbul ignore next */
|
|
1524
1348
|
return undefined;
|
|
1525
1349
|
}
|
|
1526
|
-
|
|
1527
1350
|
}
|
|
1528
|
-
|
|
1529
1351
|
Downshift.defaultProps = {
|
|
1530
1352
|
defaultHighlightedIndex: null,
|
|
1531
1353
|
defaultIsOpen: false,
|
|
@@ -1534,12 +1356,10 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1534
1356
|
if (i == null) {
|
|
1535
1357
|
return '';
|
|
1536
1358
|
}
|
|
1537
|
-
|
|
1538
1359
|
if (process.env.NODE_ENV !== 'production' && isPlainObject(i) && !i.hasOwnProperty('toString')) {
|
|
1539
1360
|
// eslint-disable-next-line no-console
|
|
1540
1361
|
console.warn('downshift: An object was passed to the default implementation of `itemToString`. You should probably provide your own `itemToString` implementation. Please refer to the `itemToString` API documentation.', 'The object that was passed:', i);
|
|
1541
1362
|
}
|
|
1542
|
-
|
|
1543
1363
|
return String(i);
|
|
1544
1364
|
},
|
|
1545
1365
|
onStateChange: noop,
|
|
@@ -1549,8 +1369,7 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1549
1369
|
onSelect: noop,
|
|
1550
1370
|
onOuterClick: noop,
|
|
1551
1371
|
selectedItemChanged: (prevItem, item) => prevItem !== item,
|
|
1552
|
-
environment:
|
|
1553
|
-
/* istanbul ignore next (ssr) */
|
|
1372
|
+
environment: /* istanbul ignore next (ssr) */
|
|
1554
1373
|
typeof window === 'undefined' ? {} : window,
|
|
1555
1374
|
stateReducer: (state, stateToSet) => stateToSet,
|
|
1556
1375
|
suppressRefError: false,
|
|
@@ -1559,7 +1378,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1559
1378
|
Downshift.stateChangeTypes = stateChangeTypes$3;
|
|
1560
1379
|
return Downshift;
|
|
1561
1380
|
})();
|
|
1562
|
-
|
|
1563
1381
|
process.env.NODE_ENV !== "production" ? Downshift.propTypes = {
|
|
1564
1382
|
children: PropTypes__default["default"].func,
|
|
1565
1383
|
defaultHighlightedIndex: PropTypes__default["default"].number,
|
|
@@ -1593,7 +1411,6 @@ process.env.NODE_ENV !== "production" ? Downshift.propTypes = {
|
|
|
1593
1411
|
scrollIntoView: PropTypes__default["default"].func,
|
|
1594
1412
|
// things we keep in state for uncontrolled components
|
|
1595
1413
|
// but can accept as props for controlled components
|
|
1596
|
-
|
|
1597
1414
|
/* eslint-disable react/no-unused-prop-types */
|
|
1598
1415
|
selectedItem: PropTypes__default["default"].any,
|
|
1599
1416
|
isOpen: PropTypes__default["default"].bool,
|
|
@@ -1604,28 +1421,23 @@ process.env.NODE_ENV !== "production" ? Downshift.propTypes = {
|
|
|
1604
1421
|
menuId: PropTypes__default["default"].string,
|
|
1605
1422
|
getItemId: PropTypes__default["default"].func
|
|
1606
1423
|
/* eslint-enable react/no-unused-prop-types */
|
|
1607
|
-
|
|
1608
1424
|
} : void 0;
|
|
1609
1425
|
var Downshift$1 = Downshift;
|
|
1610
|
-
|
|
1611
1426
|
function validateGetMenuPropsCalledCorrectly(node, _ref3) {
|
|
1612
1427
|
let {
|
|
1613
1428
|
refKey
|
|
1614
1429
|
} = _ref3;
|
|
1615
|
-
|
|
1616
1430
|
if (!node) {
|
|
1617
1431
|
// eslint-disable-next-line no-console
|
|
1618
1432
|
console.error(`downshift: The ref prop "${refKey}" from getMenuProps was not applied correctly on your menu element.`);
|
|
1619
1433
|
}
|
|
1620
1434
|
}
|
|
1621
|
-
|
|
1622
1435
|
function validateGetRootPropsCalledCorrectly(element, _ref4) {
|
|
1623
1436
|
let {
|
|
1624
1437
|
refKey
|
|
1625
1438
|
} = _ref4;
|
|
1626
1439
|
const refKeySpecified = refKey !== 'ref';
|
|
1627
1440
|
const isComposite = !isDOMElement(element);
|
|
1628
|
-
|
|
1629
1441
|
if (isComposite && !refKeySpecified && !reactIs.isForwardRef(element)) {
|
|
1630
1442
|
// eslint-disable-next-line no-console
|
|
1631
1443
|
console.error('downshift: You returned a non-DOM element. You must specify a refKey in getRootProps');
|
|
@@ -1633,7 +1445,6 @@ function validateGetRootPropsCalledCorrectly(element, _ref4) {
|
|
|
1633
1445
|
// eslint-disable-next-line no-console
|
|
1634
1446
|
console.error(`downshift: You returned a DOM element. You should not specify a refKey in getRootProps. You specified "${refKey}"`);
|
|
1635
1447
|
}
|
|
1636
|
-
|
|
1637
1448
|
if (!reactIs.isForwardRef(element) && !getElementProps(element)[refKey]) {
|
|
1638
1449
|
// eslint-disable-next-line no-console
|
|
1639
1450
|
console.error(`downshift: You must apply the ref prop "${refKey}" from getRootProps onto your root element.`);
|
|
@@ -1646,7 +1457,6 @@ const dropdownDefaultStateValues = {
|
|
|
1646
1457
|
selectedItem: null,
|
|
1647
1458
|
inputValue: ''
|
|
1648
1459
|
};
|
|
1649
|
-
|
|
1650
1460
|
function callOnChangeProps(action, state, newState) {
|
|
1651
1461
|
const {
|
|
1652
1462
|
props,
|
|
@@ -1655,12 +1465,10 @@ function callOnChangeProps(action, state, newState) {
|
|
|
1655
1465
|
const changes = {};
|
|
1656
1466
|
Object.keys(state).forEach(key => {
|
|
1657
1467
|
invokeOnChangeHandler(key, action, state, newState);
|
|
1658
|
-
|
|
1659
1468
|
if (newState[key] !== state[key]) {
|
|
1660
1469
|
changes[key] = newState[key];
|
|
1661
1470
|
}
|
|
1662
1471
|
});
|
|
1663
|
-
|
|
1664
1472
|
if (props.onStateChange && Object.keys(changes).length) {
|
|
1665
1473
|
props.onStateChange({
|
|
1666
1474
|
type,
|
|
@@ -1668,14 +1476,12 @@ function callOnChangeProps(action, state, newState) {
|
|
|
1668
1476
|
});
|
|
1669
1477
|
}
|
|
1670
1478
|
}
|
|
1671
|
-
|
|
1672
1479
|
function invokeOnChangeHandler(key, action, state, newState) {
|
|
1673
1480
|
const {
|
|
1674
1481
|
props,
|
|
1675
1482
|
type
|
|
1676
1483
|
} = action;
|
|
1677
1484
|
const handler = `on${capitalizeString(key)}Change`;
|
|
1678
|
-
|
|
1679
1485
|
if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
|
|
1680
1486
|
props[handler]({
|
|
1681
1487
|
type,
|
|
@@ -1683,6 +1489,7 @@ function invokeOnChangeHandler(key, action, state, newState) {
|
|
|
1683
1489
|
});
|
|
1684
1490
|
}
|
|
1685
1491
|
}
|
|
1492
|
+
|
|
1686
1493
|
/**
|
|
1687
1494
|
* Default state reducer that returns the changes.
|
|
1688
1495
|
*
|
|
@@ -1690,19 +1497,16 @@ function invokeOnChangeHandler(key, action, state, newState) {
|
|
|
1690
1497
|
* @param {Object} a action with changes.
|
|
1691
1498
|
* @returns {Object} changes.
|
|
1692
1499
|
*/
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
1500
|
function stateReducer(s, a) {
|
|
1696
1501
|
return a.changes;
|
|
1697
1502
|
}
|
|
1503
|
+
|
|
1698
1504
|
/**
|
|
1699
1505
|
* Returns a message to be added to aria-live region when item is selected.
|
|
1700
1506
|
*
|
|
1701
1507
|
* @param {Object} selectionParameters Parameters required to build the message.
|
|
1702
1508
|
* @returns {string} The a11y message.
|
|
1703
1509
|
*/
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
1510
|
function getA11ySelectionMessage(selectionParameters) {
|
|
1707
1511
|
const {
|
|
1708
1512
|
selectedItem,
|
|
@@ -1710,17 +1514,16 @@ function getA11ySelectionMessage(selectionParameters) {
|
|
|
1710
1514
|
} = selectionParameters;
|
|
1711
1515
|
return selectedItem ? `${itemToStringLocal(selectedItem)} has been selected.` : '';
|
|
1712
1516
|
}
|
|
1517
|
+
|
|
1713
1518
|
/**
|
|
1714
1519
|
* Debounced call for updating the a11y message.
|
|
1715
1520
|
*/
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
1521
|
const updateA11yStatus = debounce((getA11yMessage, document) => {
|
|
1719
1522
|
setStatus(getA11yMessage(), document);
|
|
1720
|
-
}, 200);
|
|
1523
|
+
}, 200);
|
|
1721
1524
|
|
|
1525
|
+
// istanbul ignore next
|
|
1722
1526
|
const useIsomorphicLayoutEffect = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined' ? react.useLayoutEffect : react.useEffect;
|
|
1723
|
-
|
|
1724
1527
|
function useElementIds(_ref) {
|
|
1725
1528
|
let {
|
|
1726
1529
|
id = `downshift-${generateId()}`,
|
|
@@ -1739,41 +1542,35 @@ function useElementIds(_ref) {
|
|
|
1739
1542
|
});
|
|
1740
1543
|
return elementIdsRef.current;
|
|
1741
1544
|
}
|
|
1742
|
-
|
|
1743
1545
|
function getItemIndex(index, item, items) {
|
|
1744
1546
|
if (index !== undefined) {
|
|
1745
1547
|
return index;
|
|
1746
1548
|
}
|
|
1747
|
-
|
|
1748
1549
|
if (items.length === 0) {
|
|
1749
1550
|
return -1;
|
|
1750
1551
|
}
|
|
1751
|
-
|
|
1752
1552
|
return items.indexOf(item);
|
|
1753
1553
|
}
|
|
1754
|
-
|
|
1755
1554
|
function itemToString(item) {
|
|
1756
1555
|
return item ? String(item) : '';
|
|
1757
1556
|
}
|
|
1758
|
-
|
|
1759
1557
|
function isAcceptedCharacterKey(key) {
|
|
1760
1558
|
return /^\S{1}$/.test(key);
|
|
1761
1559
|
}
|
|
1762
|
-
|
|
1763
1560
|
function capitalizeString(string) {
|
|
1764
1561
|
return `${string.slice(0, 1).toUpperCase()}${string.slice(1)}`;
|
|
1765
1562
|
}
|
|
1766
|
-
|
|
1767
1563
|
function useLatestRef(val) {
|
|
1768
|
-
const ref = react.useRef(val);
|
|
1564
|
+
const ref = react.useRef(val);
|
|
1565
|
+
// technically this is not "concurrent mode safe" because we're manipulating
|
|
1769
1566
|
// the value during render (so it's not idempotent). However, the places this
|
|
1770
1567
|
// hook is used is to support memoizing callbacks which will be called
|
|
1771
1568
|
// *during* render, so we need the latest values *during* render.
|
|
1772
1569
|
// If not for this, then we'd probably want to use useLayoutEffect instead.
|
|
1773
|
-
|
|
1774
1570
|
ref.current = val;
|
|
1775
1571
|
return ref;
|
|
1776
1572
|
}
|
|
1573
|
+
|
|
1777
1574
|
/**
|
|
1778
1575
|
* Computes the controlled state using a the previous state, props,
|
|
1779
1576
|
* two reducers, one from downshift and an optional one from the user.
|
|
@@ -1784,8 +1581,6 @@ function useLatestRef(val) {
|
|
|
1784
1581
|
* @param {Object} props The hook props.
|
|
1785
1582
|
* @returns {Array} An array with the state and an action dispatcher.
|
|
1786
1583
|
*/
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
1584
|
function useEnhancedReducer(reducer, initialState, props) {
|
|
1790
1585
|
const prevStateRef = react.useRef();
|
|
1791
1586
|
const actionRef = react.useRef();
|
|
@@ -1793,7 +1588,8 @@ function useEnhancedReducer(reducer, initialState, props) {
|
|
|
1793
1588
|
actionRef.current = action;
|
|
1794
1589
|
state = getState(state, action.props);
|
|
1795
1590
|
const changes = reducer(state, action);
|
|
1796
|
-
const newState = action.props.stateReducer(state, {
|
|
1591
|
+
const newState = action.props.stateReducer(state, {
|
|
1592
|
+
...action,
|
|
1797
1593
|
changes
|
|
1798
1594
|
});
|
|
1799
1595
|
return newState;
|
|
@@ -1809,11 +1605,11 @@ function useEnhancedReducer(reducer, initialState, props) {
|
|
|
1809
1605
|
if (action && prevStateRef.current && prevStateRef.current !== state) {
|
|
1810
1606
|
callOnChangeProps(action, getState(prevStateRef.current, action.props), state);
|
|
1811
1607
|
}
|
|
1812
|
-
|
|
1813
1608
|
prevStateRef.current = state;
|
|
1814
1609
|
}, [state, props, action]);
|
|
1815
1610
|
return [state, dispatchWithProps];
|
|
1816
1611
|
}
|
|
1612
|
+
|
|
1817
1613
|
/**
|
|
1818
1614
|
* Wraps the useEnhancedReducer and applies the controlled prop values before
|
|
1819
1615
|
* returning the new state.
|
|
@@ -1823,57 +1619,42 @@ function useEnhancedReducer(reducer, initialState, props) {
|
|
|
1823
1619
|
* @param {Object} props The hook props.
|
|
1824
1620
|
* @returns {Array} An array with the state and an action dispatcher.
|
|
1825
1621
|
*/
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
1622
|
function useControlledReducer$1(reducer, initialState, props) {
|
|
1829
1623
|
const [state, dispatch] = useEnhancedReducer(reducer, initialState, props);
|
|
1830
1624
|
return [getState(state, props), dispatch];
|
|
1831
1625
|
}
|
|
1832
|
-
|
|
1833
1626
|
const defaultProps$3 = {
|
|
1834
1627
|
itemToString,
|
|
1835
1628
|
stateReducer,
|
|
1836
1629
|
getA11ySelectionMessage,
|
|
1837
1630
|
scrollIntoView,
|
|
1838
|
-
environment:
|
|
1839
|
-
/* istanbul ignore next (ssr) */
|
|
1631
|
+
environment: /* istanbul ignore next (ssr) */
|
|
1840
1632
|
typeof window === 'undefined' ? {} : window
|
|
1841
1633
|
};
|
|
1842
|
-
|
|
1843
1634
|
function getDefaultValue$1(props, propKey, defaultStateValues) {
|
|
1844
1635
|
if (defaultStateValues === void 0) {
|
|
1845
1636
|
defaultStateValues = dropdownDefaultStateValues;
|
|
1846
1637
|
}
|
|
1847
|
-
|
|
1848
1638
|
const defaultValue = props[`default${capitalizeString(propKey)}`];
|
|
1849
|
-
|
|
1850
1639
|
if (defaultValue !== undefined) {
|
|
1851
1640
|
return defaultValue;
|
|
1852
1641
|
}
|
|
1853
|
-
|
|
1854
1642
|
return defaultStateValues[propKey];
|
|
1855
1643
|
}
|
|
1856
|
-
|
|
1857
1644
|
function getInitialValue$1(props, propKey, defaultStateValues) {
|
|
1858
1645
|
if (defaultStateValues === void 0) {
|
|
1859
1646
|
defaultStateValues = dropdownDefaultStateValues;
|
|
1860
1647
|
}
|
|
1861
|
-
|
|
1862
1648
|
const value = props[propKey];
|
|
1863
|
-
|
|
1864
1649
|
if (value !== undefined) {
|
|
1865
1650
|
return value;
|
|
1866
1651
|
}
|
|
1867
|
-
|
|
1868
1652
|
const initialValue = props[`initial${capitalizeString(propKey)}`];
|
|
1869
|
-
|
|
1870
1653
|
if (initialValue !== undefined) {
|
|
1871
1654
|
return initialValue;
|
|
1872
1655
|
}
|
|
1873
|
-
|
|
1874
1656
|
return getDefaultValue$1(props, propKey, defaultStateValues);
|
|
1875
1657
|
}
|
|
1876
|
-
|
|
1877
1658
|
function getInitialState$2(props) {
|
|
1878
1659
|
const selectedItem = getInitialValue$1(props, 'selectedItem');
|
|
1879
1660
|
const isOpen = getInitialValue$1(props, 'isOpen');
|
|
@@ -1886,7 +1667,6 @@ function getInitialState$2(props) {
|
|
|
1886
1667
|
inputValue
|
|
1887
1668
|
};
|
|
1888
1669
|
}
|
|
1889
|
-
|
|
1890
1670
|
function getHighlightedIndexOnOpen(props, state, offset) {
|
|
1891
1671
|
const {
|
|
1892
1672
|
items,
|
|
@@ -1897,30 +1677,26 @@ function getHighlightedIndexOnOpen(props, state, offset) {
|
|
|
1897
1677
|
selectedItem,
|
|
1898
1678
|
highlightedIndex
|
|
1899
1679
|
} = state;
|
|
1900
|
-
|
|
1901
1680
|
if (items.length === 0) {
|
|
1902
1681
|
return -1;
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1682
|
+
}
|
|
1905
1683
|
|
|
1684
|
+
// initialHighlightedIndex will give value to highlightedIndex on initial state only.
|
|
1906
1685
|
if (initialHighlightedIndex !== undefined && highlightedIndex === initialHighlightedIndex) {
|
|
1907
1686
|
return initialHighlightedIndex;
|
|
1908
1687
|
}
|
|
1909
|
-
|
|
1910
1688
|
if (defaultHighlightedIndex !== undefined) {
|
|
1911
1689
|
return defaultHighlightedIndex;
|
|
1912
1690
|
}
|
|
1913
|
-
|
|
1914
1691
|
if (selectedItem) {
|
|
1915
1692
|
return items.indexOf(selectedItem);
|
|
1916
1693
|
}
|
|
1917
|
-
|
|
1918
1694
|
if (offset === 0) {
|
|
1919
1695
|
return -1;
|
|
1920
1696
|
}
|
|
1921
|
-
|
|
1922
1697
|
return offset < 0 ? items.length - 1 : 0;
|
|
1923
1698
|
}
|
|
1699
|
+
|
|
1924
1700
|
/**
|
|
1925
1701
|
* Reuse the movement tracking of mouse and touch events.
|
|
1926
1702
|
*
|
|
@@ -1930,8 +1706,6 @@ function getHighlightedIndexOnOpen(props, state, offset) {
|
|
|
1930
1706
|
* @param {Function} handleBlur Handler on blur from mouse or touch.
|
|
1931
1707
|
* @returns {Object} Ref containing whether mouseDown or touchMove event is happening
|
|
1932
1708
|
*/
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
1709
|
function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, handleBlur) {
|
|
1936
1710
|
const mouseAndTouchTrackersRef = react.useRef({
|
|
1937
1711
|
isMouseDown: false,
|
|
@@ -1943,29 +1717,23 @@ function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, hand
|
|
|
1943
1717
|
const onMouseDown = () => {
|
|
1944
1718
|
mouseAndTouchTrackersRef.current.isMouseDown = true;
|
|
1945
1719
|
};
|
|
1946
|
-
|
|
1947
1720
|
const onMouseUp = event => {
|
|
1948
1721
|
mouseAndTouchTrackersRef.current.isMouseDown = false;
|
|
1949
|
-
|
|
1950
1722
|
if (isOpen && !targetWithinDownshift(event.target, downshiftElementRefs.map(ref => ref.current), environment)) {
|
|
1951
1723
|
handleBlur();
|
|
1952
1724
|
}
|
|
1953
1725
|
};
|
|
1954
|
-
|
|
1955
1726
|
const onTouchStart = () => {
|
|
1956
1727
|
mouseAndTouchTrackersRef.current.isTouchMove = false;
|
|
1957
1728
|
};
|
|
1958
|
-
|
|
1959
1729
|
const onTouchMove = () => {
|
|
1960
1730
|
mouseAndTouchTrackersRef.current.isTouchMove = true;
|
|
1961
1731
|
};
|
|
1962
|
-
|
|
1963
1732
|
const onTouchEnd = event => {
|
|
1964
1733
|
if (isOpen && !mouseAndTouchTrackersRef.current.isTouchMove && !targetWithinDownshift(event.target, downshiftElementRefs.map(ref => ref.current), environment, false)) {
|
|
1965
1734
|
handleBlur();
|
|
1966
1735
|
}
|
|
1967
1736
|
};
|
|
1968
|
-
|
|
1969
1737
|
environment.addEventListener('mousedown', onMouseDown);
|
|
1970
1738
|
environment.addEventListener('mouseup', onMouseUp);
|
|
1971
1739
|
environment.addEventListener('touchstart', onTouchStart);
|
|
@@ -1977,14 +1745,14 @@ function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, hand
|
|
|
1977
1745
|
environment.removeEventListener('touchstart', onTouchStart);
|
|
1978
1746
|
environment.removeEventListener('touchmove', onTouchMove);
|
|
1979
1747
|
environment.removeEventListener('touchend', onTouchEnd);
|
|
1980
|
-
};
|
|
1748
|
+
};
|
|
1749
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1981
1750
|
}, [isOpen, environment]);
|
|
1982
1751
|
return mouseAndTouchTrackersRef;
|
|
1983
1752
|
}
|
|
1753
|
+
|
|
1984
1754
|
/* istanbul ignore next */
|
|
1985
1755
|
// eslint-disable-next-line import/no-mutable-exports
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
1756
|
let useGetterPropsCalledChecker = () => noop;
|
|
1989
1757
|
/**
|
|
1990
1758
|
* Custom hook that checks if getter props are called correctly.
|
|
@@ -1992,18 +1760,13 @@ let useGetterPropsCalledChecker = () => noop;
|
|
|
1992
1760
|
* @param {...any} propKeys Getter prop names to be handled.
|
|
1993
1761
|
* @returns {Function} Setter function called inside getter props to set call information.
|
|
1994
1762
|
*/
|
|
1995
|
-
|
|
1996
1763
|
/* istanbul ignore next */
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
1764
|
if (process.env.NODE_ENV !== 'production') {
|
|
2000
1765
|
useGetterPropsCalledChecker = function () {
|
|
2001
1766
|
const isInitialMountRef = react.useRef(true);
|
|
2002
|
-
|
|
2003
1767
|
for (var _len = arguments.length, propKeys = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
2004
1768
|
propKeys[_key] = arguments[_key];
|
|
2005
1769
|
}
|
|
2006
|
-
|
|
2007
1770
|
const getterPropsCalledRef = react.useRef(propKeys.reduce((acc, propKey) => {
|
|
2008
1771
|
acc[propKey] = {};
|
|
2009
1772
|
return acc;
|
|
@@ -2011,7 +1774,6 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
2011
1774
|
react.useEffect(() => {
|
|
2012
1775
|
Object.keys(getterPropsCalledRef.current).forEach(propKey => {
|
|
2013
1776
|
const propCallInfo = getterPropsCalledRef.current[propKey];
|
|
2014
|
-
|
|
2015
1777
|
if (isInitialMountRef.current) {
|
|
2016
1778
|
if (!Object.keys(propCallInfo).length) {
|
|
2017
1779
|
// eslint-disable-next-line no-console
|
|
@@ -2019,13 +1781,11 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
2019
1781
|
return;
|
|
2020
1782
|
}
|
|
2021
1783
|
}
|
|
2022
|
-
|
|
2023
1784
|
const {
|
|
2024
1785
|
suppressRefError,
|
|
2025
1786
|
refKey,
|
|
2026
1787
|
elementRef
|
|
2027
1788
|
} = propCallInfo;
|
|
2028
|
-
|
|
2029
1789
|
if ((!elementRef || !elementRef.current) && !suppressRefError) {
|
|
2030
1790
|
// eslint-disable-next-line no-console
|
|
2031
1791
|
console.error(`downshift: The ref prop "${refKey}" from ${propKey} was not applied correctly on your element.`);
|
|
@@ -2043,7 +1803,6 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
2043
1803
|
return setGetterPropCallInfo;
|
|
2044
1804
|
};
|
|
2045
1805
|
}
|
|
2046
|
-
|
|
2047
1806
|
function useA11yMessageSetter(getA11yMessage, dependencyArray, _ref2) {
|
|
2048
1807
|
let {
|
|
2049
1808
|
isInitialMount,
|
|
@@ -2057,16 +1816,15 @@ function useA11yMessageSetter(getA11yMessage, dependencyArray, _ref2) {
|
|
|
2057
1816
|
if (isInitialMount || true) {
|
|
2058
1817
|
return;
|
|
2059
1818
|
}
|
|
2060
|
-
|
|
2061
1819
|
updateA11yStatus(() => getA11yMessage({
|
|
2062
1820
|
highlightedIndex,
|
|
2063
1821
|
highlightedItem: items[highlightedIndex],
|
|
2064
1822
|
resultCount: items.length,
|
|
2065
1823
|
...rest
|
|
2066
|
-
}), environment.document);
|
|
1824
|
+
}), environment.document);
|
|
1825
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2067
1826
|
}, dependencyArray);
|
|
2068
1827
|
}
|
|
2069
|
-
|
|
2070
1828
|
function useScrollIntoView(_ref3) {
|
|
2071
1829
|
let {
|
|
2072
1830
|
highlightedIndex,
|
|
@@ -2077,27 +1835,25 @@ function useScrollIntoView(_ref3) {
|
|
|
2077
1835
|
scrollIntoView: scrollIntoViewProp
|
|
2078
1836
|
} = _ref3;
|
|
2079
1837
|
// used not to scroll on highlight by mouse.
|
|
2080
|
-
const shouldScrollRef = react.useRef(true);
|
|
2081
|
-
|
|
1838
|
+
const shouldScrollRef = react.useRef(true);
|
|
1839
|
+
// Scroll on highlighted item if change comes from keyboard.
|
|
2082
1840
|
useIsomorphicLayoutEffect(() => {
|
|
2083
1841
|
if (highlightedIndex < 0 || !isOpen || !Object.keys(itemRefs.current).length) {
|
|
2084
1842
|
return;
|
|
2085
1843
|
}
|
|
2086
|
-
|
|
2087
1844
|
if (shouldScrollRef.current === false) {
|
|
2088
1845
|
shouldScrollRef.current = true;
|
|
2089
1846
|
} else {
|
|
2090
1847
|
scrollIntoViewProp(getItemNodeFromIndex(highlightedIndex), menuElement);
|
|
2091
|
-
}
|
|
2092
|
-
|
|
1848
|
+
}
|
|
1849
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2093
1850
|
}, [highlightedIndex]);
|
|
2094
1851
|
return shouldScrollRef;
|
|
2095
|
-
}
|
|
2096
|
-
|
|
1852
|
+
}
|
|
2097
1853
|
|
|
1854
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
2098
1855
|
let useControlPropsValidator = noop;
|
|
2099
1856
|
/* istanbul ignore next */
|
|
2100
|
-
|
|
2101
1857
|
if (process.env.NODE_ENV !== 'production') {
|
|
2102
1858
|
useControlPropsValidator = _ref4 => {
|
|
2103
1859
|
let {
|
|
@@ -2111,7 +1867,6 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
2111
1867
|
if (isInitialMount) {
|
|
2112
1868
|
return;
|
|
2113
1869
|
}
|
|
2114
|
-
|
|
2115
1870
|
validateControlledUnchanged(state, prevPropsRef.current, props);
|
|
2116
1871
|
prevPropsRef.current = props;
|
|
2117
1872
|
}, [state, props, isInitialMount]);
|
|
@@ -2124,20 +1879,17 @@ function downshiftCommonReducer(state, action, stateChangeTypes) {
|
|
|
2124
1879
|
props
|
|
2125
1880
|
} = action;
|
|
2126
1881
|
let changes;
|
|
2127
|
-
|
|
2128
1882
|
switch (type) {
|
|
2129
1883
|
case stateChangeTypes.ItemMouseMove:
|
|
2130
1884
|
changes = {
|
|
2131
1885
|
highlightedIndex: action.disabled ? -1 : action.index
|
|
2132
1886
|
};
|
|
2133
1887
|
break;
|
|
2134
|
-
|
|
2135
1888
|
case stateChangeTypes.MenuMouseLeave:
|
|
2136
1889
|
changes = {
|
|
2137
1890
|
highlightedIndex: -1
|
|
2138
1891
|
};
|
|
2139
1892
|
break;
|
|
2140
|
-
|
|
2141
1893
|
case stateChangeTypes.ToggleButtonClick:
|
|
2142
1894
|
case stateChangeTypes.FunctionToggleMenu:
|
|
2143
1895
|
changes = {
|
|
@@ -2145,32 +1897,27 @@ function downshiftCommonReducer(state, action, stateChangeTypes) {
|
|
|
2145
1897
|
highlightedIndex: state.isOpen ? -1 : getHighlightedIndexOnOpen(props, state, 0)
|
|
2146
1898
|
};
|
|
2147
1899
|
break;
|
|
2148
|
-
|
|
2149
1900
|
case stateChangeTypes.FunctionOpenMenu:
|
|
2150
1901
|
changes = {
|
|
2151
1902
|
isOpen: true,
|
|
2152
1903
|
highlightedIndex: getHighlightedIndexOnOpen(props, state, 0)
|
|
2153
1904
|
};
|
|
2154
1905
|
break;
|
|
2155
|
-
|
|
2156
1906
|
case stateChangeTypes.FunctionCloseMenu:
|
|
2157
1907
|
changes = {
|
|
2158
1908
|
isOpen: false
|
|
2159
1909
|
};
|
|
2160
1910
|
break;
|
|
2161
|
-
|
|
2162
1911
|
case stateChangeTypes.FunctionSetHighlightedIndex:
|
|
2163
1912
|
changes = {
|
|
2164
1913
|
highlightedIndex: action.highlightedIndex
|
|
2165
1914
|
};
|
|
2166
1915
|
break;
|
|
2167
|
-
|
|
2168
1916
|
case stateChangeTypes.FunctionSetInputValue:
|
|
2169
1917
|
changes = {
|
|
2170
1918
|
inputValue: action.inputValue
|
|
2171
1919
|
};
|
|
2172
1920
|
break;
|
|
2173
|
-
|
|
2174
1921
|
case stateChangeTypes.FunctionReset:
|
|
2175
1922
|
changes = {
|
|
2176
1923
|
highlightedIndex: getDefaultValue$1(props, 'highlightedIndex'),
|
|
@@ -2179,12 +1926,11 @@ function downshiftCommonReducer(state, action, stateChangeTypes) {
|
|
|
2179
1926
|
inputValue: getDefaultValue$1(props, 'inputValue')
|
|
2180
1927
|
};
|
|
2181
1928
|
break;
|
|
2182
|
-
|
|
2183
1929
|
default:
|
|
2184
1930
|
throw new Error('Reducer called without proper action type.');
|
|
2185
1931
|
}
|
|
2186
|
-
|
|
2187
|
-
|
|
1932
|
+
return {
|
|
1933
|
+
...state,
|
|
2188
1934
|
...changes
|
|
2189
1935
|
};
|
|
2190
1936
|
}
|
|
@@ -2323,7 +2069,6 @@ var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
|
|
|
2323
2069
|
});
|
|
2324
2070
|
|
|
2325
2071
|
/* eslint-disable complexity */
|
|
2326
|
-
|
|
2327
2072
|
function downshiftSelectReducer(state, action) {
|
|
2328
2073
|
const {
|
|
2329
2074
|
type,
|
|
@@ -2331,7 +2076,6 @@ function downshiftSelectReducer(state, action) {
|
|
|
2331
2076
|
altKey
|
|
2332
2077
|
} = action;
|
|
2333
2078
|
let changes;
|
|
2334
|
-
|
|
2335
2079
|
switch (type) {
|
|
2336
2080
|
case ItemClick$1:
|
|
2337
2081
|
changes = {
|
|
@@ -2340,7 +2084,6 @@ function downshiftSelectReducer(state, action) {
|
|
|
2340
2084
|
selectedItem: props.items[action.index]
|
|
2341
2085
|
};
|
|
2342
2086
|
break;
|
|
2343
|
-
|
|
2344
2087
|
case ToggleButtonKeyDownCharacter:
|
|
2345
2088
|
{
|
|
2346
2089
|
const lowercasedKey = action.key;
|
|
@@ -2360,7 +2103,6 @@ function downshiftSelectReducer(state, action) {
|
|
|
2360
2103
|
};
|
|
2361
2104
|
}
|
|
2362
2105
|
break;
|
|
2363
|
-
|
|
2364
2106
|
case ToggleButtonKeyDownArrowDown:
|
|
2365
2107
|
{
|
|
2366
2108
|
const highlightedIndex = state.isOpen ? getNextWrappingIndex(1, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false) : altKey && state.selectedItem == null ? -1 : getHighlightedIndexOnOpen(props, state, 1);
|
|
@@ -2370,7 +2112,6 @@ function downshiftSelectReducer(state, action) {
|
|
|
2370
2112
|
};
|
|
2371
2113
|
}
|
|
2372
2114
|
break;
|
|
2373
|
-
|
|
2374
2115
|
case ToggleButtonKeyDownArrowUp:
|
|
2375
2116
|
if (state.isOpen && altKey) {
|
|
2376
2117
|
changes = {
|
|
@@ -2387,10 +2128,8 @@ function downshiftSelectReducer(state, action) {
|
|
|
2387
2128
|
isOpen: true
|
|
2388
2129
|
};
|
|
2389
2130
|
}
|
|
2390
|
-
|
|
2391
2131
|
break;
|
|
2392
2132
|
// only triggered when menu is open.
|
|
2393
|
-
|
|
2394
2133
|
case ToggleButtonKeyDownEnter:
|
|
2395
2134
|
case ToggleButtonKeyDownSpaceButton:
|
|
2396
2135
|
changes = {
|
|
@@ -2401,40 +2140,34 @@ function downshiftSelectReducer(state, action) {
|
|
|
2401
2140
|
})
|
|
2402
2141
|
};
|
|
2403
2142
|
break;
|
|
2404
|
-
|
|
2405
2143
|
case ToggleButtonKeyDownHome:
|
|
2406
2144
|
changes = {
|
|
2407
2145
|
highlightedIndex: getNextNonDisabledIndex(1, 0, props.items.length, action.getItemNodeFromIndex, false),
|
|
2408
2146
|
isOpen: true
|
|
2409
2147
|
};
|
|
2410
2148
|
break;
|
|
2411
|
-
|
|
2412
2149
|
case ToggleButtonKeyDownEnd:
|
|
2413
2150
|
changes = {
|
|
2414
2151
|
highlightedIndex: getNextNonDisabledIndex(-1, props.items.length - 1, props.items.length, action.getItemNodeFromIndex, false),
|
|
2415
2152
|
isOpen: true
|
|
2416
2153
|
};
|
|
2417
2154
|
break;
|
|
2418
|
-
|
|
2419
2155
|
case ToggleButtonKeyDownPageUp:
|
|
2420
2156
|
changes = {
|
|
2421
2157
|
highlightedIndex: getNextWrappingIndex(-10, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false)
|
|
2422
2158
|
};
|
|
2423
2159
|
break;
|
|
2424
|
-
|
|
2425
2160
|
case ToggleButtonKeyDownPageDown:
|
|
2426
2161
|
changes = {
|
|
2427
2162
|
highlightedIndex: getNextWrappingIndex(10, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false)
|
|
2428
2163
|
};
|
|
2429
2164
|
break;
|
|
2430
|
-
|
|
2431
2165
|
case ToggleButtonKeyDownEscape:
|
|
2432
2166
|
changes = {
|
|
2433
2167
|
isOpen: false,
|
|
2434
2168
|
highlightedIndex: -1
|
|
2435
2169
|
};
|
|
2436
2170
|
break;
|
|
2437
|
-
|
|
2438
2171
|
case ToggleButtonBlur:
|
|
2439
2172
|
changes = {
|
|
2440
2173
|
isOpen: false,
|
|
@@ -2444,33 +2177,30 @@ function downshiftSelectReducer(state, action) {
|
|
|
2444
2177
|
})
|
|
2445
2178
|
};
|
|
2446
2179
|
break;
|
|
2447
|
-
|
|
2448
2180
|
case FunctionSelectItem$1:
|
|
2449
2181
|
changes = {
|
|
2450
2182
|
selectedItem: action.selectedItem
|
|
2451
2183
|
};
|
|
2452
2184
|
break;
|
|
2453
|
-
|
|
2454
2185
|
default:
|
|
2455
2186
|
return downshiftCommonReducer(state, action, stateChangeTypes$2);
|
|
2456
2187
|
}
|
|
2457
|
-
|
|
2458
|
-
|
|
2188
|
+
return {
|
|
2189
|
+
...state,
|
|
2459
2190
|
...changes
|
|
2460
2191
|
};
|
|
2461
2192
|
}
|
|
2462
2193
|
/* eslint-enable complexity */
|
|
2463
2194
|
|
|
2464
2195
|
useSelect.stateChangeTypes = stateChangeTypes$2;
|
|
2465
|
-
|
|
2466
2196
|
function useSelect(userProps) {
|
|
2467
2197
|
if (userProps === void 0) {
|
|
2468
2198
|
userProps = {};
|
|
2469
2199
|
}
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2200
|
+
validatePropTypes$2(userProps, useSelect);
|
|
2201
|
+
// Props defaults and destructuring.
|
|
2202
|
+
const props = {
|
|
2203
|
+
...defaultProps$2,
|
|
2474
2204
|
...userProps
|
|
2475
2205
|
};
|
|
2476
2206
|
const {
|
|
@@ -2480,8 +2210,8 @@ function useSelect(userProps) {
|
|
|
2480
2210
|
itemToString,
|
|
2481
2211
|
getA11ySelectionMessage,
|
|
2482
2212
|
getA11yStatusMessage
|
|
2483
|
-
} = props;
|
|
2484
|
-
|
|
2213
|
+
} = props;
|
|
2214
|
+
// Initial state depending on controlled props.
|
|
2485
2215
|
const initialState = getInitialState$2(props);
|
|
2486
2216
|
const [state, dispatch] = useControlledReducer$1(downshiftSelectReducer, initialState, props);
|
|
2487
2217
|
const {
|
|
@@ -2489,27 +2219,30 @@ function useSelect(userProps) {
|
|
|
2489
2219
|
highlightedIndex,
|
|
2490
2220
|
selectedItem,
|
|
2491
2221
|
inputValue
|
|
2492
|
-
} = state;
|
|
2222
|
+
} = state;
|
|
2493
2223
|
|
|
2224
|
+
// Element efs.
|
|
2494
2225
|
const toggleButtonRef = react.useRef(null);
|
|
2495
2226
|
const menuRef = react.useRef(null);
|
|
2496
|
-
const itemRefs = react.useRef({});
|
|
2497
|
-
|
|
2498
|
-
const clearTimeoutRef = react.useRef(null);
|
|
2499
|
-
|
|
2500
|
-
const elementIds = useElementIds(props);
|
|
2501
|
-
|
|
2227
|
+
const itemRefs = react.useRef({});
|
|
2228
|
+
// used to keep the inputValue clearTimeout object between renders.
|
|
2229
|
+
const clearTimeoutRef = react.useRef(null);
|
|
2230
|
+
// prevent id re-generation between renders.
|
|
2231
|
+
const elementIds = useElementIds(props);
|
|
2232
|
+
// used to keep track of how many items we had on previous cycle.
|
|
2502
2233
|
const previousResultCountRef = react.useRef();
|
|
2503
|
-
const isInitialMountRef = react.useRef(true);
|
|
2504
|
-
|
|
2234
|
+
const isInitialMountRef = react.useRef(true);
|
|
2235
|
+
// utility callback to get item element.
|
|
2505
2236
|
const latest = useLatestRef({
|
|
2506
2237
|
state,
|
|
2507
2238
|
props
|
|
2508
|
-
});
|
|
2239
|
+
});
|
|
2509
2240
|
|
|
2510
|
-
|
|
2511
|
-
|
|
2241
|
+
// Some utils.
|
|
2242
|
+
const getItemNodeFromIndex = react.useCallback(index => itemRefs.current[elementIds.getItemId(index)], [elementIds]);
|
|
2512
2243
|
|
|
2244
|
+
// Effects.
|
|
2245
|
+
// Sets a11y status message on changes in state.
|
|
2513
2246
|
useA11yMessageSetter(getA11yStatusMessage, [isOpen, highlightedIndex, inputValue, items], {
|
|
2514
2247
|
isInitialMount: isInitialMountRef.current,
|
|
2515
2248
|
previousResultCount: previousResultCountRef.current,
|
|
@@ -2517,8 +2250,8 @@ function useSelect(userProps) {
|
|
|
2517
2250
|
environment,
|
|
2518
2251
|
itemToString,
|
|
2519
2252
|
...state
|
|
2520
|
-
});
|
|
2521
|
-
|
|
2253
|
+
});
|
|
2254
|
+
// Sets a11y status message on changes in selectedItem.
|
|
2522
2255
|
useA11yMessageSetter(getA11ySelectionMessage, [selectedItem], {
|
|
2523
2256
|
isInitialMount: isInitialMountRef.current,
|
|
2524
2257
|
previousResultCount: previousResultCountRef.current,
|
|
@@ -2526,8 +2259,8 @@ function useSelect(userProps) {
|
|
|
2526
2259
|
environment,
|
|
2527
2260
|
itemToString,
|
|
2528
2261
|
...state
|
|
2529
|
-
});
|
|
2530
|
-
|
|
2262
|
+
});
|
|
2263
|
+
// Scroll on highlighted item if change comes from keyboard.
|
|
2531
2264
|
const shouldScrollRef = useScrollIntoView({
|
|
2532
2265
|
menuElement: menuRef.current,
|
|
2533
2266
|
highlightedIndex,
|
|
@@ -2535,8 +2268,9 @@ function useSelect(userProps) {
|
|
|
2535
2268
|
itemRefs,
|
|
2536
2269
|
scrollIntoView,
|
|
2537
2270
|
getItemNodeFromIndex
|
|
2538
|
-
});
|
|
2271
|
+
});
|
|
2539
2272
|
|
|
2273
|
+
// Sets cleanup for the keysSoFar callback, debounded after 500ms.
|
|
2540
2274
|
react.useEffect(() => {
|
|
2541
2275
|
// init the clean function here as we need access to dispatch.
|
|
2542
2276
|
clearTimeoutRef.current = debounce(outerDispatch => {
|
|
@@ -2544,18 +2278,19 @@ function useSelect(userProps) {
|
|
|
2544
2278
|
type: FunctionSetInputValue$1,
|
|
2545
2279
|
inputValue: ''
|
|
2546
2280
|
});
|
|
2547
|
-
}, 500);
|
|
2281
|
+
}, 500);
|
|
2548
2282
|
|
|
2283
|
+
// Cancel any pending debounced calls on mount
|
|
2549
2284
|
return () => {
|
|
2550
2285
|
clearTimeoutRef.current.cancel();
|
|
2551
2286
|
};
|
|
2552
|
-
}, []);
|
|
2287
|
+
}, []);
|
|
2553
2288
|
|
|
2289
|
+
// Invokes the keysSoFar callback set up above.
|
|
2554
2290
|
react.useEffect(() => {
|
|
2555
2291
|
if (!inputValue) {
|
|
2556
2292
|
return;
|
|
2557
2293
|
}
|
|
2558
|
-
|
|
2559
2294
|
clearTimeoutRef.current(dispatch);
|
|
2560
2295
|
}, [dispatch, inputValue]);
|
|
2561
2296
|
useControlPropsValidator({
|
|
@@ -2567,27 +2302,27 @@ function useSelect(userProps) {
|
|
|
2567
2302
|
if (isInitialMountRef.current) {
|
|
2568
2303
|
return;
|
|
2569
2304
|
}
|
|
2570
|
-
|
|
2571
2305
|
previousResultCountRef.current = items.length;
|
|
2572
|
-
});
|
|
2573
|
-
|
|
2306
|
+
});
|
|
2307
|
+
// Add mouse/touch events to document.
|
|
2574
2308
|
const mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [menuRef, toggleButtonRef], environment, () => {
|
|
2575
2309
|
dispatch({
|
|
2576
2310
|
type: ToggleButtonBlur
|
|
2577
2311
|
});
|
|
2578
2312
|
});
|
|
2579
|
-
const setGetterPropCallInfo = useGetterPropsCalledChecker('getMenuProps', 'getToggleButtonProps');
|
|
2580
|
-
|
|
2313
|
+
const setGetterPropCallInfo = useGetterPropsCalledChecker('getMenuProps', 'getToggleButtonProps');
|
|
2314
|
+
// Make initial ref false.
|
|
2581
2315
|
react.useEffect(() => {
|
|
2582
2316
|
isInitialMountRef.current = false;
|
|
2583
|
-
}, []);
|
|
2584
|
-
|
|
2317
|
+
}, []);
|
|
2318
|
+
// Reset itemRefs on close.
|
|
2585
2319
|
react.useEffect(() => {
|
|
2586
2320
|
if (!isOpen) {
|
|
2587
2321
|
itemRefs.current = {};
|
|
2588
2322
|
}
|
|
2589
|
-
}, [isOpen]);
|
|
2323
|
+
}, [isOpen]);
|
|
2590
2324
|
|
|
2325
|
+
// Event handler functions.
|
|
2591
2326
|
const toggleButtonKeyDownHandlers = react.useMemo(() => ({
|
|
2592
2327
|
ArrowDown(event) {
|
|
2593
2328
|
event.preventDefault();
|
|
@@ -2597,7 +2332,6 @@ function useSelect(userProps) {
|
|
|
2597
2332
|
altKey: event.altKey
|
|
2598
2333
|
});
|
|
2599
2334
|
},
|
|
2600
|
-
|
|
2601
2335
|
ArrowUp(event) {
|
|
2602
2336
|
event.preventDefault();
|
|
2603
2337
|
dispatch({
|
|
@@ -2606,7 +2340,6 @@ function useSelect(userProps) {
|
|
|
2606
2340
|
altKey: event.altKey
|
|
2607
2341
|
});
|
|
2608
2342
|
},
|
|
2609
|
-
|
|
2610
2343
|
Home(event) {
|
|
2611
2344
|
event.preventDefault();
|
|
2612
2345
|
dispatch({
|
|
@@ -2614,7 +2347,6 @@ function useSelect(userProps) {
|
|
|
2614
2347
|
getItemNodeFromIndex
|
|
2615
2348
|
});
|
|
2616
2349
|
},
|
|
2617
|
-
|
|
2618
2350
|
End(event) {
|
|
2619
2351
|
event.preventDefault();
|
|
2620
2352
|
dispatch({
|
|
@@ -2622,7 +2354,6 @@ function useSelect(userProps) {
|
|
|
2622
2354
|
getItemNodeFromIndex
|
|
2623
2355
|
});
|
|
2624
2356
|
},
|
|
2625
|
-
|
|
2626
2357
|
Escape() {
|
|
2627
2358
|
if (latest.current.state.isOpen) {
|
|
2628
2359
|
dispatch({
|
|
@@ -2630,7 +2361,6 @@ function useSelect(userProps) {
|
|
|
2630
2361
|
});
|
|
2631
2362
|
}
|
|
2632
2363
|
},
|
|
2633
|
-
|
|
2634
2364
|
Enter(event) {
|
|
2635
2365
|
if (latest.current.state.isOpen) {
|
|
2636
2366
|
event.preventDefault();
|
|
@@ -2639,7 +2369,6 @@ function useSelect(userProps) {
|
|
|
2639
2369
|
});
|
|
2640
2370
|
}
|
|
2641
2371
|
},
|
|
2642
|
-
|
|
2643
2372
|
PageUp(event) {
|
|
2644
2373
|
if (latest.current.state.isOpen) {
|
|
2645
2374
|
event.preventDefault();
|
|
@@ -2649,7 +2378,6 @@ function useSelect(userProps) {
|
|
|
2649
2378
|
});
|
|
2650
2379
|
}
|
|
2651
2380
|
},
|
|
2652
|
-
|
|
2653
2381
|
PageDown(event) {
|
|
2654
2382
|
if (latest.current.state.isOpen) {
|
|
2655
2383
|
event.preventDefault();
|
|
@@ -2659,7 +2387,6 @@ function useSelect(userProps) {
|
|
|
2659
2387
|
});
|
|
2660
2388
|
}
|
|
2661
2389
|
},
|
|
2662
|
-
|
|
2663
2390
|
' '(event) {
|
|
2664
2391
|
if (latest.current.state.isOpen) {
|
|
2665
2392
|
event.preventDefault();
|
|
@@ -2668,9 +2395,9 @@ function useSelect(userProps) {
|
|
|
2668
2395
|
});
|
|
2669
2396
|
}
|
|
2670
2397
|
}
|
|
2398
|
+
}), [dispatch, getItemNodeFromIndex, latest]);
|
|
2671
2399
|
|
|
2672
|
-
|
|
2673
|
-
|
|
2400
|
+
// Action functions.
|
|
2674
2401
|
const toggleMenu = react.useCallback(() => {
|
|
2675
2402
|
dispatch({
|
|
2676
2403
|
type: FunctionToggleMenu$1
|
|
@@ -2708,8 +2435,8 @@ function useSelect(userProps) {
|
|
|
2708
2435
|
type: FunctionSetInputValue$1,
|
|
2709
2436
|
inputValue: newInputValue
|
|
2710
2437
|
});
|
|
2711
|
-
}, [dispatch]);
|
|
2712
|
-
|
|
2438
|
+
}, [dispatch]);
|
|
2439
|
+
// Getter functions.
|
|
2713
2440
|
const getLabelProps = react.useCallback(labelProps => ({
|
|
2714
2441
|
id: elementIds.labelId,
|
|
2715
2442
|
htmlFor: elementIds.toggleButtonId,
|
|
@@ -2727,13 +2454,11 @@ function useSelect(userProps) {
|
|
|
2727
2454
|
let {
|
|
2728
2455
|
suppressRefError = false
|
|
2729
2456
|
} = _temp2 === void 0 ? {} : _temp2;
|
|
2730
|
-
|
|
2731
2457
|
const menuHandleMouseLeave = () => {
|
|
2732
2458
|
dispatch({
|
|
2733
2459
|
type: MenuMouseLeave$1
|
|
2734
2460
|
});
|
|
2735
2461
|
};
|
|
2736
|
-
|
|
2737
2462
|
setGetterPropCallInfo('getMenuProps', suppressRefError, refKey, menuRef);
|
|
2738
2463
|
return {
|
|
2739
2464
|
[refKey]: handleRefs(ref, menuNode => {
|
|
@@ -2760,13 +2485,11 @@ function useSelect(userProps) {
|
|
|
2760
2485
|
suppressRefError = false
|
|
2761
2486
|
} = _temp4 === void 0 ? {} : _temp4;
|
|
2762
2487
|
const latestState = latest.current.state;
|
|
2763
|
-
|
|
2764
2488
|
const toggleButtonHandleClick = () => {
|
|
2765
2489
|
dispatch({
|
|
2766
2490
|
type: ToggleButtonClick$1
|
|
2767
2491
|
});
|
|
2768
2492
|
};
|
|
2769
|
-
|
|
2770
2493
|
const toggleButtonHandleBlur = () => {
|
|
2771
2494
|
if (latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
|
|
2772
2495
|
dispatch({
|
|
@@ -2774,10 +2497,8 @@ function useSelect(userProps) {
|
|
|
2774
2497
|
});
|
|
2775
2498
|
}
|
|
2776
2499
|
};
|
|
2777
|
-
|
|
2778
2500
|
const toggleButtonHandleKeyDown = event => {
|
|
2779
2501
|
const key = normalizeArrowKey(event);
|
|
2780
|
-
|
|
2781
2502
|
if (key && toggleButtonKeyDownHandlers[key]) {
|
|
2782
2503
|
toggleButtonKeyDownHandlers[key](event);
|
|
2783
2504
|
} else if (isAcceptedCharacterKey(key)) {
|
|
@@ -2788,7 +2509,6 @@ function useSelect(userProps) {
|
|
|
2788
2509
|
});
|
|
2789
2510
|
}
|
|
2790
2511
|
};
|
|
2791
|
-
|
|
2792
2512
|
const toggleProps = {
|
|
2793
2513
|
[refKey]: handleRefs(ref, toggleButtonNode => {
|
|
2794
2514
|
toggleButtonRef.current = toggleButtonNode;
|
|
@@ -2804,12 +2524,10 @@ function useSelect(userProps) {
|
|
|
2804
2524
|
onBlur: callAllEventHandlers(onBlur, toggleButtonHandleBlur),
|
|
2805
2525
|
...rest
|
|
2806
2526
|
};
|
|
2807
|
-
|
|
2808
2527
|
if (!rest.disabled) {
|
|
2809
2528
|
toggleProps.onClick = callAllEventHandlers(onClick, toggleButtonHandleClick);
|
|
2810
2529
|
toggleProps.onKeyDown = callAllEventHandlers(onKeyDown, toggleButtonHandleKeyDown);
|
|
2811
2530
|
}
|
|
2812
|
-
|
|
2813
2531
|
setGetterPropCallInfo('getToggleButtonProps', suppressRefError, refKey, toggleButtonRef);
|
|
2814
2532
|
return toggleProps;
|
|
2815
2533
|
}, [latest, elementIds, setGetterPropCallInfo, dispatch, mouseAndTouchTrackersRef, toggleButtonKeyDownHandlers, getItemNodeFromIndex]);
|
|
@@ -2830,12 +2548,10 @@ function useSelect(userProps) {
|
|
|
2830
2548
|
} = latest.current;
|
|
2831
2549
|
const item = itemProp ?? items[indexProp];
|
|
2832
2550
|
const index = getItemIndex(indexProp, item, latestProps.items);
|
|
2833
|
-
|
|
2834
2551
|
const itemHandleMouseMove = () => {
|
|
2835
2552
|
if (index === latestState.highlightedIndex) {
|
|
2836
2553
|
return;
|
|
2837
2554
|
}
|
|
2838
|
-
|
|
2839
2555
|
shouldScrollRef.current = false;
|
|
2840
2556
|
dispatch({
|
|
2841
2557
|
type: ItemMouseMove$1,
|
|
@@ -2843,20 +2559,16 @@ function useSelect(userProps) {
|
|
|
2843
2559
|
disabled
|
|
2844
2560
|
});
|
|
2845
2561
|
};
|
|
2846
|
-
|
|
2847
2562
|
const itemHandleClick = () => {
|
|
2848
2563
|
dispatch({
|
|
2849
2564
|
type: ItemClick$1,
|
|
2850
2565
|
index
|
|
2851
2566
|
});
|
|
2852
2567
|
};
|
|
2853
|
-
|
|
2854
2568
|
const itemIndex = getItemIndex(index, item, latestProps.items);
|
|
2855
|
-
|
|
2856
2569
|
if (itemIndex < 0) {
|
|
2857
2570
|
throw new Error('Pass either item or item index in getItemProps!');
|
|
2858
2571
|
}
|
|
2859
|
-
|
|
2860
2572
|
const itemProps = {
|
|
2861
2573
|
disabled,
|
|
2862
2574
|
role: 'option',
|
|
@@ -2869,11 +2581,9 @@ function useSelect(userProps) {
|
|
|
2869
2581
|
}),
|
|
2870
2582
|
...rest
|
|
2871
2583
|
};
|
|
2872
|
-
|
|
2873
2584
|
if (!disabled) {
|
|
2874
2585
|
itemProps.onClick = callAllEventHandlers(onClick, itemHandleClick);
|
|
2875
2586
|
}
|
|
2876
|
-
|
|
2877
2587
|
itemProps.onMouseMove = callAllEventHandlers(onMouseMove, itemHandleMouseMove);
|
|
2878
2588
|
return itemProps;
|
|
2879
2589
|
}, [latest, items, selectedItem, elementIds, shouldScrollRef, dispatch]);
|
|
@@ -2958,16 +2668,14 @@ function getInitialState$1(props) {
|
|
|
2958
2668
|
let {
|
|
2959
2669
|
inputValue
|
|
2960
2670
|
} = initialState;
|
|
2961
|
-
|
|
2962
2671
|
if (inputValue === '' && selectedItem && props.defaultInputValue === undefined && props.initialInputValue === undefined && props.inputValue === undefined) {
|
|
2963
2672
|
inputValue = props.itemToString(selectedItem);
|
|
2964
2673
|
}
|
|
2965
|
-
|
|
2966
|
-
|
|
2674
|
+
return {
|
|
2675
|
+
...initialState,
|
|
2967
2676
|
inputValue
|
|
2968
2677
|
};
|
|
2969
2678
|
}
|
|
2970
|
-
|
|
2971
2679
|
const propTypes$1 = {
|
|
2972
2680
|
items: PropTypes__default["default"].array.isRequired,
|
|
2973
2681
|
itemToString: PropTypes__default["default"].func,
|
|
@@ -3007,6 +2715,7 @@ const propTypes$1 = {
|
|
|
3007
2715
|
})
|
|
3008
2716
|
})
|
|
3009
2717
|
};
|
|
2718
|
+
|
|
3010
2719
|
/**
|
|
3011
2720
|
* The useCombobox version of useControlledReducer, which also
|
|
3012
2721
|
* checks if the controlled prop selectedItem changed between
|
|
@@ -3019,11 +2728,11 @@ const propTypes$1 = {
|
|
|
3019
2728
|
* @param {Object} props The hook props.
|
|
3020
2729
|
* @returns {Array} An array with the state and an action dispatcher.
|
|
3021
2730
|
*/
|
|
3022
|
-
|
|
3023
2731
|
function useControlledReducer(reducer, initialState, props) {
|
|
3024
2732
|
const previousSelectedItemRef = react.useRef();
|
|
3025
|
-
const [state, dispatch] = useEnhancedReducer(reducer, initialState, props);
|
|
2733
|
+
const [state, dispatch] = useEnhancedReducer(reducer, initialState, props);
|
|
3026
2734
|
|
|
2735
|
+
// ToDo: if needed, make same approach as selectedItemChanged from Downshift.
|
|
3027
2736
|
react.useEffect(() => {
|
|
3028
2737
|
if (isControlledProp(props, 'selectedItem')) {
|
|
3029
2738
|
if (previousSelectedItemRef.current !== props.selectedItem) {
|
|
@@ -3032,29 +2741,26 @@ function useControlledReducer(reducer, initialState, props) {
|
|
|
3032
2741
|
inputValue: props.itemToString(props.selectedItem)
|
|
3033
2742
|
});
|
|
3034
2743
|
}
|
|
3035
|
-
|
|
3036
2744
|
previousSelectedItemRef.current = state.selectedItem === previousSelectedItemRef.current ? props.selectedItem : state.selectedItem;
|
|
3037
2745
|
}
|
|
3038
2746
|
});
|
|
3039
2747
|
return [getState(state, props), dispatch];
|
|
3040
|
-
}
|
|
3041
|
-
|
|
2748
|
+
}
|
|
3042
2749
|
|
|
2750
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
3043
2751
|
let validatePropTypes$1 = noop;
|
|
3044
2752
|
/* istanbul ignore next */
|
|
3045
|
-
|
|
3046
2753
|
if (process.env.NODE_ENV !== 'production') {
|
|
3047
2754
|
validatePropTypes$1 = (options, caller) => {
|
|
3048
2755
|
PropTypes__default["default"].checkPropTypes(propTypes$1, options, 'prop', caller.name);
|
|
3049
2756
|
};
|
|
3050
2757
|
}
|
|
3051
|
-
|
|
3052
|
-
|
|
2758
|
+
const defaultProps$1 = {
|
|
2759
|
+
...defaultProps$3,
|
|
3053
2760
|
getA11yStatusMessage: getA11yStatusMessage$1
|
|
3054
2761
|
};
|
|
3055
2762
|
|
|
3056
2763
|
/* eslint-disable complexity */
|
|
3057
|
-
|
|
3058
2764
|
function downshiftUseComboboxReducer(state, action) {
|
|
3059
2765
|
const {
|
|
3060
2766
|
type,
|
|
@@ -3062,7 +2768,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3062
2768
|
altKey
|
|
3063
2769
|
} = action;
|
|
3064
2770
|
let changes;
|
|
3065
|
-
|
|
3066
2771
|
switch (type) {
|
|
3067
2772
|
case ItemClick:
|
|
3068
2773
|
changes = {
|
|
@@ -3072,7 +2777,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3072
2777
|
inputValue: props.itemToString(props.items[action.index])
|
|
3073
2778
|
};
|
|
3074
2779
|
break;
|
|
3075
|
-
|
|
3076
2780
|
case InputKeyDownArrowDown:
|
|
3077
2781
|
if (state.isOpen) {
|
|
3078
2782
|
changes = {
|
|
@@ -3084,9 +2788,7 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3084
2788
|
isOpen: props.items.length >= 0
|
|
3085
2789
|
};
|
|
3086
2790
|
}
|
|
3087
|
-
|
|
3088
2791
|
break;
|
|
3089
|
-
|
|
3090
2792
|
case InputKeyDownArrowUp:
|
|
3091
2793
|
if (state.isOpen) {
|
|
3092
2794
|
if (altKey) {
|
|
@@ -3109,9 +2811,7 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3109
2811
|
isOpen: props.items.length >= 0
|
|
3110
2812
|
};
|
|
3111
2813
|
}
|
|
3112
|
-
|
|
3113
2814
|
break;
|
|
3114
|
-
|
|
3115
2815
|
case InputKeyDownEnter:
|
|
3116
2816
|
changes = {
|
|
3117
2817
|
isOpen: getDefaultValue$1(props, 'isOpen'),
|
|
@@ -3122,7 +2822,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3122
2822
|
})
|
|
3123
2823
|
};
|
|
3124
2824
|
break;
|
|
3125
|
-
|
|
3126
2825
|
case InputKeyDownEscape:
|
|
3127
2826
|
changes = {
|
|
3128
2827
|
isOpen: false,
|
|
@@ -3133,31 +2832,26 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3133
2832
|
})
|
|
3134
2833
|
};
|
|
3135
2834
|
break;
|
|
3136
|
-
|
|
3137
2835
|
case InputKeyDownPageUp:
|
|
3138
2836
|
changes = {
|
|
3139
2837
|
highlightedIndex: getNextWrappingIndex(-10, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false)
|
|
3140
2838
|
};
|
|
3141
2839
|
break;
|
|
3142
|
-
|
|
3143
2840
|
case InputKeyDownPageDown:
|
|
3144
2841
|
changes = {
|
|
3145
2842
|
highlightedIndex: getNextWrappingIndex(10, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false)
|
|
3146
2843
|
};
|
|
3147
2844
|
break;
|
|
3148
|
-
|
|
3149
2845
|
case InputKeyDownHome:
|
|
3150
2846
|
changes = {
|
|
3151
2847
|
highlightedIndex: getNextNonDisabledIndex(1, 0, props.items.length, action.getItemNodeFromIndex, false)
|
|
3152
2848
|
};
|
|
3153
2849
|
break;
|
|
3154
|
-
|
|
3155
2850
|
case InputKeyDownEnd:
|
|
3156
2851
|
changes = {
|
|
3157
2852
|
highlightedIndex: getNextNonDisabledIndex(-1, props.items.length - 1, props.items.length, action.getItemNodeFromIndex, false)
|
|
3158
2853
|
};
|
|
3159
2854
|
break;
|
|
3160
|
-
|
|
3161
2855
|
case InputBlur:
|
|
3162
2856
|
changes = {
|
|
3163
2857
|
isOpen: false,
|
|
@@ -3168,7 +2862,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3168
2862
|
})
|
|
3169
2863
|
};
|
|
3170
2864
|
break;
|
|
3171
|
-
|
|
3172
2865
|
case InputChange:
|
|
3173
2866
|
changes = {
|
|
3174
2867
|
isOpen: true,
|
|
@@ -3176,32 +2869,28 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3176
2869
|
inputValue: action.inputValue
|
|
3177
2870
|
};
|
|
3178
2871
|
break;
|
|
3179
|
-
|
|
3180
2872
|
case InputFocus:
|
|
3181
2873
|
changes = {
|
|
3182
2874
|
isOpen: true,
|
|
3183
2875
|
highlightedIndex: getHighlightedIndexOnOpen(props, state, 0)
|
|
3184
2876
|
};
|
|
3185
2877
|
break;
|
|
3186
|
-
|
|
3187
2878
|
case FunctionSelectItem:
|
|
3188
2879
|
changes = {
|
|
3189
2880
|
selectedItem: action.selectedItem,
|
|
3190
2881
|
inputValue: props.itemToString(action.selectedItem)
|
|
3191
2882
|
};
|
|
3192
2883
|
break;
|
|
3193
|
-
|
|
3194
2884
|
case ControlledPropUpdatedSelectedItem:
|
|
3195
2885
|
changes = {
|
|
3196
2886
|
inputValue: action.inputValue
|
|
3197
2887
|
};
|
|
3198
2888
|
break;
|
|
3199
|
-
|
|
3200
2889
|
default:
|
|
3201
2890
|
return downshiftCommonReducer(state, action, stateChangeTypes$1);
|
|
3202
2891
|
}
|
|
3203
|
-
|
|
3204
|
-
|
|
2892
|
+
return {
|
|
2893
|
+
...state,
|
|
3205
2894
|
...changes
|
|
3206
2895
|
};
|
|
3207
2896
|
}
|
|
@@ -3209,15 +2898,14 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3209
2898
|
|
|
3210
2899
|
/* eslint-disable max-statements */
|
|
3211
2900
|
useCombobox.stateChangeTypes = stateChangeTypes$1;
|
|
3212
|
-
|
|
3213
2901
|
function useCombobox(userProps) {
|
|
3214
2902
|
if (userProps === void 0) {
|
|
3215
2903
|
userProps = {};
|
|
3216
2904
|
}
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
2905
|
+
validatePropTypes$1(userProps, useCombobox);
|
|
2906
|
+
// Props defaults and destructuring.
|
|
2907
|
+
const props = {
|
|
2908
|
+
...defaultProps$1,
|
|
3221
2909
|
...userProps
|
|
3222
2910
|
};
|
|
3223
2911
|
const {
|
|
@@ -3229,8 +2917,8 @@ function useCombobox(userProps) {
|
|
|
3229
2917
|
getA11yStatusMessage,
|
|
3230
2918
|
getA11ySelectionMessage,
|
|
3231
2919
|
itemToString
|
|
3232
|
-
} = props;
|
|
3233
|
-
|
|
2920
|
+
} = props;
|
|
2921
|
+
// Initial state depending on controlled props.
|
|
3234
2922
|
const initialState = getInitialState$1(props);
|
|
3235
2923
|
const [state, dispatch] = useControlledReducer(downshiftUseComboboxReducer, initialState, props);
|
|
3236
2924
|
const {
|
|
@@ -3238,25 +2926,27 @@ function useCombobox(userProps) {
|
|
|
3238
2926
|
highlightedIndex,
|
|
3239
2927
|
selectedItem,
|
|
3240
2928
|
inputValue
|
|
3241
|
-
} = state;
|
|
2929
|
+
} = state;
|
|
3242
2930
|
|
|
2931
|
+
// Element refs.
|
|
3243
2932
|
const menuRef = react.useRef(null);
|
|
3244
2933
|
const itemRefs = react.useRef({});
|
|
3245
2934
|
const inputRef = react.useRef(null);
|
|
3246
2935
|
const toggleButtonRef = react.useRef(null);
|
|
3247
|
-
const isInitialMountRef = react.useRef(true);
|
|
3248
|
-
|
|
3249
|
-
const elementIds = useElementIds(props);
|
|
3250
|
-
|
|
3251
|
-
const previousResultCountRef = react.useRef();
|
|
3252
|
-
|
|
2936
|
+
const isInitialMountRef = react.useRef(true);
|
|
2937
|
+
// prevent id re-generation between renders.
|
|
2938
|
+
const elementIds = useElementIds(props);
|
|
2939
|
+
// used to keep track of how many items we had on previous cycle.
|
|
2940
|
+
const previousResultCountRef = react.useRef();
|
|
2941
|
+
// utility callback to get item element.
|
|
3253
2942
|
const latest = useLatestRef({
|
|
3254
2943
|
state,
|
|
3255
2944
|
props
|
|
3256
2945
|
});
|
|
3257
|
-
const getItemNodeFromIndex = react.useCallback(index => itemRefs.current[elementIds.getItemId(index)], [elementIds]);
|
|
3258
|
-
// Sets a11y status message on changes in state.
|
|
2946
|
+
const getItemNodeFromIndex = react.useCallback(index => itemRefs.current[elementIds.getItemId(index)], [elementIds]);
|
|
3259
2947
|
|
|
2948
|
+
// Effects.
|
|
2949
|
+
// Sets a11y status message on changes in state.
|
|
3260
2950
|
useA11yMessageSetter(getA11yStatusMessage, [isOpen, highlightedIndex, inputValue, items], {
|
|
3261
2951
|
isInitialMount: isInitialMountRef.current,
|
|
3262
2952
|
previousResultCount: previousResultCountRef.current,
|
|
@@ -3264,8 +2954,8 @@ function useCombobox(userProps) {
|
|
|
3264
2954
|
environment,
|
|
3265
2955
|
itemToString,
|
|
3266
2956
|
...state
|
|
3267
|
-
});
|
|
3268
|
-
|
|
2957
|
+
});
|
|
2958
|
+
// Sets a11y status message on changes in selectedItem.
|
|
3269
2959
|
useA11yMessageSetter(getA11ySelectionMessage, [selectedItem], {
|
|
3270
2960
|
isInitialMount: isInitialMountRef.current,
|
|
3271
2961
|
previousResultCount: previousResultCountRef.current,
|
|
@@ -3273,8 +2963,8 @@ function useCombobox(userProps) {
|
|
|
3273
2963
|
environment,
|
|
3274
2964
|
itemToString,
|
|
3275
2965
|
...state
|
|
3276
|
-
});
|
|
3277
|
-
|
|
2966
|
+
});
|
|
2967
|
+
// Scroll on highlighted item if change comes from keyboard.
|
|
3278
2968
|
const shouldScrollRef = useScrollIntoView({
|
|
3279
2969
|
menuElement: menuRef.current,
|
|
3280
2970
|
highlightedIndex,
|
|
@@ -3287,47 +2977,44 @@ function useCombobox(userProps) {
|
|
|
3287
2977
|
isInitialMount: isInitialMountRef.current,
|
|
3288
2978
|
props,
|
|
3289
2979
|
state
|
|
3290
|
-
});
|
|
3291
|
-
|
|
2980
|
+
});
|
|
2981
|
+
// Focus the input on first render if required.
|
|
3292
2982
|
react.useEffect(() => {
|
|
3293
2983
|
const focusOnOpen = initialIsOpen || defaultIsOpen || isOpen;
|
|
3294
|
-
|
|
3295
2984
|
if (focusOnOpen && inputRef.current) {
|
|
3296
2985
|
inputRef.current.focus();
|
|
3297
|
-
}
|
|
3298
|
-
|
|
2986
|
+
}
|
|
2987
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3299
2988
|
}, []);
|
|
3300
2989
|
react.useEffect(() => {
|
|
3301
2990
|
if (isInitialMountRef.current) {
|
|
3302
2991
|
return;
|
|
3303
2992
|
}
|
|
3304
|
-
|
|
3305
2993
|
previousResultCountRef.current = items.length;
|
|
3306
|
-
});
|
|
3307
|
-
|
|
2994
|
+
});
|
|
2995
|
+
// Add mouse/touch events to document.
|
|
3308
2996
|
const mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [inputRef, menuRef, toggleButtonRef], environment, () => {
|
|
3309
2997
|
dispatch({
|
|
3310
2998
|
type: InputBlur,
|
|
3311
2999
|
selectItem: false
|
|
3312
3000
|
});
|
|
3313
3001
|
});
|
|
3314
|
-
const setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getMenuProps');
|
|
3315
|
-
|
|
3002
|
+
const setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getMenuProps');
|
|
3003
|
+
// Make initial ref false.
|
|
3316
3004
|
react.useEffect(() => {
|
|
3317
3005
|
isInitialMountRef.current = false;
|
|
3318
|
-
}, []);
|
|
3319
|
-
|
|
3006
|
+
}, []);
|
|
3007
|
+
// Reset itemRefs on close.
|
|
3320
3008
|
react.useEffect(() => {
|
|
3321
3009
|
if (!isOpen) {
|
|
3322
3010
|
itemRefs.current = {};
|
|
3323
3011
|
} else if (document.activeElement !== inputRef.current) {
|
|
3324
3012
|
var _inputRef$current;
|
|
3325
|
-
|
|
3326
3013
|
inputRef == null ? void 0 : (_inputRef$current = inputRef.current) == null ? void 0 : _inputRef$current.focus();
|
|
3327
3014
|
}
|
|
3328
3015
|
}, [isOpen]);
|
|
3329
|
-
/* Event handler functions */
|
|
3330
3016
|
|
|
3017
|
+
/* Event handler functions */
|
|
3331
3018
|
const inputKeyDownHandlers = react.useMemo(() => ({
|
|
3332
3019
|
ArrowDown(event) {
|
|
3333
3020
|
event.preventDefault();
|
|
@@ -3337,7 +3024,6 @@ function useCombobox(userProps) {
|
|
|
3337
3024
|
getItemNodeFromIndex
|
|
3338
3025
|
});
|
|
3339
3026
|
},
|
|
3340
|
-
|
|
3341
3027
|
ArrowUp(event) {
|
|
3342
3028
|
event.preventDefault();
|
|
3343
3029
|
dispatch({
|
|
@@ -3346,34 +3032,28 @@ function useCombobox(userProps) {
|
|
|
3346
3032
|
getItemNodeFromIndex
|
|
3347
3033
|
});
|
|
3348
3034
|
},
|
|
3349
|
-
|
|
3350
3035
|
Home(event) {
|
|
3351
3036
|
if (!latest.current.state.isOpen) {
|
|
3352
3037
|
return;
|
|
3353
3038
|
}
|
|
3354
|
-
|
|
3355
3039
|
event.preventDefault();
|
|
3356
3040
|
dispatch({
|
|
3357
3041
|
type: InputKeyDownHome,
|
|
3358
3042
|
getItemNodeFromIndex
|
|
3359
3043
|
});
|
|
3360
3044
|
},
|
|
3361
|
-
|
|
3362
3045
|
End(event) {
|
|
3363
3046
|
if (!latest.current.state.isOpen) {
|
|
3364
3047
|
return;
|
|
3365
3048
|
}
|
|
3366
|
-
|
|
3367
3049
|
event.preventDefault();
|
|
3368
3050
|
dispatch({
|
|
3369
3051
|
type: InputKeyDownEnd,
|
|
3370
3052
|
getItemNodeFromIndex
|
|
3371
3053
|
});
|
|
3372
3054
|
},
|
|
3373
|
-
|
|
3374
3055
|
Escape(event) {
|
|
3375
3056
|
const latestState = latest.current.state;
|
|
3376
|
-
|
|
3377
3057
|
if (latestState.isOpen || latestState.inputValue || latestState.selectedItem || latestState.highlightedIndex > -1) {
|
|
3378
3058
|
event.preventDefault();
|
|
3379
3059
|
dispatch({
|
|
@@ -3381,22 +3061,19 @@ function useCombobox(userProps) {
|
|
|
3381
3061
|
});
|
|
3382
3062
|
}
|
|
3383
3063
|
},
|
|
3384
|
-
|
|
3385
3064
|
Enter(event) {
|
|
3386
|
-
const latestState = latest.current.state;
|
|
3387
|
-
|
|
3065
|
+
const latestState = latest.current.state;
|
|
3066
|
+
// if closed or no highlighted index, do nothing.
|
|
3388
3067
|
if (!latestState.isOpen || event.which === 229 // if IME composing, wait for next Enter keydown event.
|
|
3389
3068
|
) {
|
|
3390
3069
|
return;
|
|
3391
3070
|
}
|
|
3392
|
-
|
|
3393
3071
|
event.preventDefault();
|
|
3394
3072
|
dispatch({
|
|
3395
3073
|
type: InputKeyDownEnter,
|
|
3396
3074
|
getItemNodeFromIndex
|
|
3397
3075
|
});
|
|
3398
3076
|
},
|
|
3399
|
-
|
|
3400
3077
|
PageUp(event) {
|
|
3401
3078
|
if (latest.current.state.isOpen) {
|
|
3402
3079
|
event.preventDefault();
|
|
@@ -3406,7 +3083,6 @@ function useCombobox(userProps) {
|
|
|
3406
3083
|
});
|
|
3407
3084
|
}
|
|
3408
3085
|
},
|
|
3409
|
-
|
|
3410
3086
|
PageDown(event) {
|
|
3411
3087
|
if (latest.current.state.isOpen) {
|
|
3412
3088
|
event.preventDefault();
|
|
@@ -3416,9 +3092,9 @@ function useCombobox(userProps) {
|
|
|
3416
3092
|
});
|
|
3417
3093
|
}
|
|
3418
3094
|
}
|
|
3095
|
+
}), [dispatch, latest, getItemNodeFromIndex]);
|
|
3419
3096
|
|
|
3420
|
-
|
|
3421
|
-
|
|
3097
|
+
// Getter props.
|
|
3422
3098
|
const getLabelProps = react.useCallback(labelProps => ({
|
|
3423
3099
|
id: elementIds.labelId,
|
|
3424
3100
|
htmlFor: elementIds.inputId,
|
|
@@ -3468,21 +3144,15 @@ function useCombobox(userProps) {
|
|
|
3468
3144
|
state: latestState
|
|
3469
3145
|
} = latest.current;
|
|
3470
3146
|
const itemIndex = getItemIndex(index, item, latestProps.items);
|
|
3471
|
-
|
|
3472
3147
|
if (itemIndex < 0) {
|
|
3473
3148
|
throw new Error('Pass either item or item index in getItemProps!');
|
|
3474
3149
|
}
|
|
3475
|
-
|
|
3476
|
-
const
|
|
3477
|
-
'onPress' ;
|
|
3478
|
-
const customClickHandler = /* istanbul ignore next (react-native) */
|
|
3479
|
-
onPress ;
|
|
3480
|
-
|
|
3150
|
+
const onSelectKey = /* istanbul ignore next (react-native) */'onPress' ;
|
|
3151
|
+
const customClickHandler = /* istanbul ignore next (react-native) */onPress ;
|
|
3481
3152
|
const itemHandleMouseMove = () => {
|
|
3482
3153
|
if (index === latestState.highlightedIndex) {
|
|
3483
3154
|
return;
|
|
3484
3155
|
}
|
|
3485
|
-
|
|
3486
3156
|
shouldScrollRef.current = false;
|
|
3487
3157
|
dispatch({
|
|
3488
3158
|
type: ItemMouseMove,
|
|
@@ -3490,16 +3160,13 @@ function useCombobox(userProps) {
|
|
|
3490
3160
|
disabled
|
|
3491
3161
|
});
|
|
3492
3162
|
};
|
|
3493
|
-
|
|
3494
3163
|
const itemHandleClick = () => {
|
|
3495
3164
|
dispatch({
|
|
3496
3165
|
type: ItemClick,
|
|
3497
3166
|
index
|
|
3498
3167
|
});
|
|
3499
3168
|
};
|
|
3500
|
-
|
|
3501
3169
|
const itemHandleMouseDown = e => e.preventDefault();
|
|
3502
|
-
|
|
3503
3170
|
return {
|
|
3504
3171
|
[refKey]: handleRefs(ref, itemNode => {
|
|
3505
3172
|
if (itemNode) {
|
|
@@ -3527,13 +3194,11 @@ function useCombobox(userProps) {
|
|
|
3527
3194
|
...rest
|
|
3528
3195
|
} = _temp4 === void 0 ? {} : _temp4;
|
|
3529
3196
|
const latestState = latest.current.state;
|
|
3530
|
-
|
|
3531
3197
|
const toggleButtonHandleClick = () => {
|
|
3532
3198
|
dispatch({
|
|
3533
3199
|
type: ToggleButtonClick
|
|
3534
3200
|
});
|
|
3535
3201
|
};
|
|
3536
|
-
|
|
3537
3202
|
return {
|
|
3538
3203
|
[refKey]: handleRefs(ref, toggleButtonNode => {
|
|
3539
3204
|
toggleButtonRef.current = toggleButtonNode;
|
|
@@ -3542,8 +3207,8 @@ function useCombobox(userProps) {
|
|
|
3542
3207
|
'aria-expanded': latestState.isOpen,
|
|
3543
3208
|
id: elementIds.toggleButtonId,
|
|
3544
3209
|
tabIndex: -1,
|
|
3545
|
-
...(!rest.disabled && {
|
|
3546
|
-
{
|
|
3210
|
+
...(!rest.disabled && {
|
|
3211
|
+
...(/* istanbul ignore next (react-native) */{
|
|
3547
3212
|
onPress: callAllEventHandlers(onPress, toggleButtonHandleClick)
|
|
3548
3213
|
} )
|
|
3549
3214
|
}),
|
|
@@ -3567,23 +3232,18 @@ function useCombobox(userProps) {
|
|
|
3567
3232
|
} = _temp6 === void 0 ? {} : _temp6;
|
|
3568
3233
|
setGetterPropCallInfo('getInputProps', suppressRefError, refKey, inputRef);
|
|
3569
3234
|
const latestState = latest.current.state;
|
|
3570
|
-
|
|
3571
3235
|
const inputHandleKeyDown = event => {
|
|
3572
3236
|
const key = normalizeArrowKey(event);
|
|
3573
|
-
|
|
3574
3237
|
if (key && inputKeyDownHandlers[key]) {
|
|
3575
3238
|
inputKeyDownHandlers[key](event);
|
|
3576
3239
|
}
|
|
3577
3240
|
};
|
|
3578
|
-
|
|
3579
3241
|
const inputHandleChange = event => {
|
|
3580
3242
|
dispatch({
|
|
3581
3243
|
type: InputChange,
|
|
3582
|
-
inputValue: /* istanbul ignore next (react-native) */
|
|
3583
|
-
event.nativeEvent.text
|
|
3244
|
+
inputValue: /* istanbul ignore next (react-native) */event.nativeEvent.text
|
|
3584
3245
|
});
|
|
3585
3246
|
};
|
|
3586
|
-
|
|
3587
3247
|
const inputHandleBlur = () => {
|
|
3588
3248
|
/* istanbul ignore else */
|
|
3589
3249
|
if (latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
|
|
@@ -3593,7 +3253,6 @@ function useCombobox(userProps) {
|
|
|
3593
3253
|
});
|
|
3594
3254
|
}
|
|
3595
3255
|
};
|
|
3596
|
-
|
|
3597
3256
|
const inputHandleFocus = () => {
|
|
3598
3257
|
if (!latestState.isOpen) {
|
|
3599
3258
|
dispatch({
|
|
@@ -3601,12 +3260,10 @@ function useCombobox(userProps) {
|
|
|
3601
3260
|
});
|
|
3602
3261
|
}
|
|
3603
3262
|
};
|
|
3604
|
-
/* istanbul ignore next (preact) */
|
|
3605
|
-
|
|
3606
3263
|
|
|
3264
|
+
/* istanbul ignore next (preact) */
|
|
3607
3265
|
const onChangeKey = 'onChange';
|
|
3608
3266
|
let eventHandlers = {};
|
|
3609
|
-
|
|
3610
3267
|
if (!rest.disabled) {
|
|
3611
3268
|
eventHandlers = {
|
|
3612
3269
|
[onChangeKey]: callAllEventHandlers(onChange, onInput, inputHandleChange),
|
|
@@ -3615,9 +3272,8 @@ function useCombobox(userProps) {
|
|
|
3615
3272
|
onFocus: callAllEventHandlers(onFocus, inputHandleFocus)
|
|
3616
3273
|
};
|
|
3617
3274
|
}
|
|
3618
|
-
/* istanbul ignore if (react-native) */
|
|
3619
|
-
|
|
3620
3275
|
|
|
3276
|
+
/* istanbul ignore if (react-native) */
|
|
3621
3277
|
{
|
|
3622
3278
|
eventHandlers.onChange = callAllEventHandlers(onChange, onInput, inputHandleChange);
|
|
3623
3279
|
eventHandlers.onChangeText = callAllEventHandlers(onChangeText, onInput, text => {
|
|
@@ -3628,7 +3284,6 @@ function useCombobox(userProps) {
|
|
|
3628
3284
|
});
|
|
3629
3285
|
});
|
|
3630
3286
|
}
|
|
3631
|
-
|
|
3632
3287
|
return {
|
|
3633
3288
|
[refKey]: handleRefs(ref, inputNode => {
|
|
3634
3289
|
inputRef.current = inputNode;
|
|
@@ -3647,8 +3302,9 @@ function useCombobox(userProps) {
|
|
|
3647
3302
|
...eventHandlers,
|
|
3648
3303
|
...rest
|
|
3649
3304
|
};
|
|
3650
|
-
}, [dispatch, inputKeyDownHandlers, latest, mouseAndTouchTrackersRef, setGetterPropCallInfo, elementIds]);
|
|
3305
|
+
}, [dispatch, inputKeyDownHandlers, latest, mouseAndTouchTrackersRef, setGetterPropCallInfo, elementIds]);
|
|
3651
3306
|
|
|
3307
|
+
// returns
|
|
3652
3308
|
const toggleMenu = react.useCallback(() => {
|
|
3653
3309
|
dispatch({
|
|
3654
3310
|
type: FunctionToggleMenu
|
|
@@ -3714,6 +3370,7 @@ const defaultStateValues = {
|
|
|
3714
3370
|
activeIndex: -1,
|
|
3715
3371
|
selectedItems: []
|
|
3716
3372
|
};
|
|
3373
|
+
|
|
3717
3374
|
/**
|
|
3718
3375
|
* Returns the initial value for a state key in the following order:
|
|
3719
3376
|
* 1. controlled prop, 2. initial prop, 3. default prop, 4. default
|
|
@@ -3723,10 +3380,10 @@ const defaultStateValues = {
|
|
|
3723
3380
|
* @param {string} propKey Props key to generate the value for.
|
|
3724
3381
|
* @returns {any} The initial value for that prop.
|
|
3725
3382
|
*/
|
|
3726
|
-
|
|
3727
3383
|
function getInitialValue(props, propKey) {
|
|
3728
3384
|
return getInitialValue$1(props, propKey, defaultStateValues);
|
|
3729
3385
|
}
|
|
3386
|
+
|
|
3730
3387
|
/**
|
|
3731
3388
|
* Returns the default value for a state key in the following order:
|
|
3732
3389
|
* 1. controlled prop, 2. default prop, 3. default value from Downshift.
|
|
@@ -3735,11 +3392,10 @@ function getInitialValue(props, propKey) {
|
|
|
3735
3392
|
* @param {string} propKey Props key to generate the value for.
|
|
3736
3393
|
* @returns {any} The initial value for that prop.
|
|
3737
3394
|
*/
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
3395
|
function getDefaultValue(props, propKey) {
|
|
3741
3396
|
return getDefaultValue$1(props, propKey, defaultStateValues);
|
|
3742
3397
|
}
|
|
3398
|
+
|
|
3743
3399
|
/**
|
|
3744
3400
|
* Gets the initial state based on the provided props. It uses initial, default
|
|
3745
3401
|
* and controlled props related to state in order to compute the initial value.
|
|
@@ -3747,8 +3403,6 @@ function getDefaultValue(props, propKey) {
|
|
|
3747
3403
|
* @param {Object} props Props passed to the hook.
|
|
3748
3404
|
* @returns {Object} The initial state.
|
|
3749
3405
|
*/
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
3406
|
function getInitialState(props) {
|
|
3753
3407
|
const activeIndex = getInitialValue(props, 'activeIndex');
|
|
3754
3408
|
const selectedItems = getInitialValue(props, 'selectedItems');
|
|
@@ -3757,6 +3411,7 @@ function getInitialState(props) {
|
|
|
3757
3411
|
selectedItems
|
|
3758
3412
|
};
|
|
3759
3413
|
}
|
|
3414
|
+
|
|
3760
3415
|
/**
|
|
3761
3416
|
* Returns true if dropdown keydown operation is permitted. Should not be
|
|
3762
3417
|
* allowed on keydown with modifier keys (ctrl, alt, shift, meta), on
|
|
@@ -3766,32 +3421,28 @@ function getInitialState(props) {
|
|
|
3766
3421
|
* @param {KeyboardEvent} event The event from keydown.
|
|
3767
3422
|
* @returns {boolean} Whether the operation is allowed.
|
|
3768
3423
|
*/
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
3424
|
function isKeyDownOperationPermitted(event) {
|
|
3772
3425
|
if (event.shiftKey || event.metaKey || event.ctrlKey || event.altKey) {
|
|
3773
3426
|
return false;
|
|
3774
3427
|
}
|
|
3775
|
-
|
|
3776
3428
|
const element = event.target;
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
element.value !== '' && (
|
|
3429
|
+
if (element instanceof HTMLInputElement &&
|
|
3430
|
+
// if element is a text input
|
|
3431
|
+
element.value !== '' && (
|
|
3432
|
+
// and we have text in it
|
|
3780
3433
|
// and cursor is either not at the start or is currently highlighting text.
|
|
3781
3434
|
element.selectionStart !== 0 || element.selectionEnd !== 0)) {
|
|
3782
3435
|
return false;
|
|
3783
3436
|
}
|
|
3784
|
-
|
|
3785
3437
|
return true;
|
|
3786
3438
|
}
|
|
3439
|
+
|
|
3787
3440
|
/**
|
|
3788
3441
|
* Returns a message to be added to aria-live region when item is removed.
|
|
3789
3442
|
*
|
|
3790
3443
|
* @param {Object} selectionParameters Parameters required to build the message.
|
|
3791
3444
|
* @returns {string} The a11y message.
|
|
3792
3445
|
*/
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
3446
|
function getA11yRemovalMessage(selectionParameters) {
|
|
3796
3447
|
const {
|
|
3797
3448
|
removedSelectedItem,
|
|
@@ -3799,7 +3450,6 @@ function getA11yRemovalMessage(selectionParameters) {
|
|
|
3799
3450
|
} = selectionParameters;
|
|
3800
3451
|
return `${itemToStringLocal(removedSelectedItem)} has been removed.`;
|
|
3801
3452
|
}
|
|
3802
|
-
|
|
3803
3453
|
const propTypes = {
|
|
3804
3454
|
selectedItems: PropTypes__default["default"].array,
|
|
3805
3455
|
initialSelectedItems: PropTypes__default["default"].array,
|
|
@@ -3831,11 +3481,11 @@ const defaultProps = {
|
|
|
3831
3481
|
getA11yRemovalMessage,
|
|
3832
3482
|
keyNavigationNext: 'ArrowRight',
|
|
3833
3483
|
keyNavigationPrevious: 'ArrowLeft'
|
|
3834
|
-
};
|
|
3484
|
+
};
|
|
3835
3485
|
|
|
3486
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
3836
3487
|
let validatePropTypes = noop;
|
|
3837
3488
|
/* istanbul ignore next */
|
|
3838
|
-
|
|
3839
3489
|
if (process.env.NODE_ENV !== 'production') {
|
|
3840
3490
|
validatePropTypes = (options, caller) => {
|
|
3841
3491
|
PropTypes__default["default"].checkPropTypes(propTypes, options, 'prop', caller.name);
|
|
@@ -3874,7 +3524,6 @@ var stateChangeTypes = /*#__PURE__*/Object.freeze({
|
|
|
3874
3524
|
});
|
|
3875
3525
|
|
|
3876
3526
|
/* eslint-disable complexity */
|
|
3877
|
-
|
|
3878
3527
|
function downshiftMultipleSelectionReducer(state, action) {
|
|
3879
3528
|
const {
|
|
3880
3529
|
type,
|
|
@@ -3887,37 +3536,31 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
3887
3536
|
selectedItems
|
|
3888
3537
|
} = state;
|
|
3889
3538
|
let changes;
|
|
3890
|
-
|
|
3891
3539
|
switch (type) {
|
|
3892
3540
|
case SelectedItemClick:
|
|
3893
3541
|
changes = {
|
|
3894
3542
|
activeIndex: index
|
|
3895
3543
|
};
|
|
3896
3544
|
break;
|
|
3897
|
-
|
|
3898
3545
|
case SelectedItemKeyDownNavigationPrevious:
|
|
3899
3546
|
changes = {
|
|
3900
3547
|
activeIndex: activeIndex - 1 < 0 ? 0 : activeIndex - 1
|
|
3901
3548
|
};
|
|
3902
3549
|
break;
|
|
3903
|
-
|
|
3904
3550
|
case SelectedItemKeyDownNavigationNext:
|
|
3905
3551
|
changes = {
|
|
3906
3552
|
activeIndex: activeIndex + 1 >= selectedItems.length ? -1 : activeIndex + 1
|
|
3907
3553
|
};
|
|
3908
3554
|
break;
|
|
3909
|
-
|
|
3910
3555
|
case SelectedItemKeyDownBackspace:
|
|
3911
3556
|
case SelectedItemKeyDownDelete:
|
|
3912
3557
|
{
|
|
3913
3558
|
let newActiveIndex = activeIndex;
|
|
3914
|
-
|
|
3915
3559
|
if (selectedItems.length === 1) {
|
|
3916
3560
|
newActiveIndex = -1;
|
|
3917
3561
|
} else if (activeIndex === selectedItems.length - 1) {
|
|
3918
3562
|
newActiveIndex = selectedItems.length - 2;
|
|
3919
3563
|
}
|
|
3920
|
-
|
|
3921
3564
|
changes = {
|
|
3922
3565
|
selectedItems: [...selectedItems.slice(0, activeIndex), ...selectedItems.slice(activeIndex + 1)],
|
|
3923
3566
|
...{
|
|
@@ -3926,52 +3569,43 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
3926
3569
|
};
|
|
3927
3570
|
break;
|
|
3928
3571
|
}
|
|
3929
|
-
|
|
3930
3572
|
case DropdownKeyDownNavigationPrevious:
|
|
3931
3573
|
changes = {
|
|
3932
3574
|
activeIndex: selectedItems.length - 1
|
|
3933
3575
|
};
|
|
3934
3576
|
break;
|
|
3935
|
-
|
|
3936
3577
|
case DropdownKeyDownBackspace:
|
|
3937
3578
|
changes = {
|
|
3938
3579
|
selectedItems: selectedItems.slice(0, selectedItems.length - 1)
|
|
3939
3580
|
};
|
|
3940
3581
|
break;
|
|
3941
|
-
|
|
3942
3582
|
case FunctionAddSelectedItem:
|
|
3943
3583
|
changes = {
|
|
3944
3584
|
selectedItems: [...selectedItems, selectedItem]
|
|
3945
3585
|
};
|
|
3946
3586
|
break;
|
|
3947
|
-
|
|
3948
3587
|
case DropdownClick:
|
|
3949
3588
|
changes = {
|
|
3950
3589
|
activeIndex: -1
|
|
3951
3590
|
};
|
|
3952
3591
|
break;
|
|
3953
|
-
|
|
3954
3592
|
case FunctionRemoveSelectedItem:
|
|
3955
3593
|
{
|
|
3956
3594
|
let newActiveIndex = activeIndex;
|
|
3957
3595
|
const selectedItemIndex = selectedItems.indexOf(selectedItem);
|
|
3958
|
-
|
|
3959
3596
|
if (selectedItemIndex >= 0) {
|
|
3960
3597
|
if (selectedItems.length === 1) {
|
|
3961
3598
|
newActiveIndex = -1;
|
|
3962
3599
|
} else if (selectedItemIndex === selectedItems.length - 1) {
|
|
3963
3600
|
newActiveIndex = selectedItems.length - 2;
|
|
3964
3601
|
}
|
|
3965
|
-
|
|
3966
3602
|
changes = {
|
|
3967
3603
|
selectedItems: [...selectedItems.slice(0, selectedItemIndex), ...selectedItems.slice(selectedItemIndex + 1)],
|
|
3968
3604
|
activeIndex: newActiveIndex
|
|
3969
3605
|
};
|
|
3970
3606
|
}
|
|
3971
|
-
|
|
3972
3607
|
break;
|
|
3973
3608
|
}
|
|
3974
|
-
|
|
3975
3609
|
case FunctionSetSelectedItems:
|
|
3976
3610
|
{
|
|
3977
3611
|
const {
|
|
@@ -3982,7 +3616,6 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
3982
3616
|
};
|
|
3983
3617
|
break;
|
|
3984
3618
|
}
|
|
3985
|
-
|
|
3986
3619
|
case FunctionSetActiveIndex:
|
|
3987
3620
|
{
|
|
3988
3621
|
const {
|
|
@@ -3993,33 +3626,30 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
3993
3626
|
};
|
|
3994
3627
|
break;
|
|
3995
3628
|
}
|
|
3996
|
-
|
|
3997
3629
|
case FunctionReset:
|
|
3998
3630
|
changes = {
|
|
3999
3631
|
activeIndex: getDefaultValue(props, 'activeIndex'),
|
|
4000
3632
|
selectedItems: getDefaultValue(props, 'selectedItems')
|
|
4001
3633
|
};
|
|
4002
3634
|
break;
|
|
4003
|
-
|
|
4004
3635
|
default:
|
|
4005
3636
|
throw new Error('Reducer called without proper action type.');
|
|
4006
3637
|
}
|
|
4007
|
-
|
|
4008
|
-
|
|
3638
|
+
return {
|
|
3639
|
+
...state,
|
|
4009
3640
|
...changes
|
|
4010
3641
|
};
|
|
4011
3642
|
}
|
|
4012
3643
|
|
|
4013
3644
|
useMultipleSelection.stateChangeTypes = stateChangeTypes;
|
|
4014
|
-
|
|
4015
3645
|
function useMultipleSelection(userProps) {
|
|
4016
3646
|
if (userProps === void 0) {
|
|
4017
3647
|
userProps = {};
|
|
4018
3648
|
}
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
3649
|
+
validatePropTypes(userProps, useMultipleSelection);
|
|
3650
|
+
// Props defaults and destructuring.
|
|
3651
|
+
const props = {
|
|
3652
|
+
...defaultProps,
|
|
4023
3653
|
...userProps
|
|
4024
3654
|
};
|
|
4025
3655
|
const {
|
|
@@ -4028,14 +3658,16 @@ function useMultipleSelection(userProps) {
|
|
|
4028
3658
|
environment,
|
|
4029
3659
|
keyNavigationNext,
|
|
4030
3660
|
keyNavigationPrevious
|
|
4031
|
-
} = props;
|
|
3661
|
+
} = props;
|
|
4032
3662
|
|
|
3663
|
+
// Reducer init.
|
|
4033
3664
|
const [state, dispatch] = useControlledReducer$1(downshiftMultipleSelectionReducer, getInitialState(props), props);
|
|
4034
3665
|
const {
|
|
4035
3666
|
activeIndex,
|
|
4036
3667
|
selectedItems
|
|
4037
|
-
} = state;
|
|
3668
|
+
} = state;
|
|
4038
3669
|
|
|
3670
|
+
// Refs.
|
|
4039
3671
|
const isInitialMountRef = react.useRef(true);
|
|
4040
3672
|
const dropdownRef = react.useRef(null);
|
|
4041
3673
|
const previousSelectedItemsRef = react.useRef(selectedItems);
|
|
@@ -4044,15 +3676,14 @@ function useMultipleSelection(userProps) {
|
|
|
4044
3676
|
const latest = useLatestRef({
|
|
4045
3677
|
state,
|
|
4046
3678
|
props
|
|
4047
|
-
});
|
|
3679
|
+
});
|
|
4048
3680
|
|
|
3681
|
+
// Effects.
|
|
4049
3682
|
/* Sets a11y status message on changes in selectedItem. */
|
|
4050
|
-
|
|
4051
3683
|
react.useEffect(() => {
|
|
4052
3684
|
if (isInitialMountRef.current) {
|
|
4053
3685
|
return;
|
|
4054
3686
|
}
|
|
4055
|
-
|
|
4056
3687
|
if (selectedItems.length < previousSelectedItemsRef.current.length) {
|
|
4057
3688
|
const removedSelectedItem = previousSelectedItemsRef.current.find(item => selectedItems.indexOf(item) < 0);
|
|
4058
3689
|
setStatus(getA11yRemovalMessage({
|
|
@@ -4063,15 +3694,15 @@ function useMultipleSelection(userProps) {
|
|
|
4063
3694
|
activeSelectedItem: selectedItems[activeIndex]
|
|
4064
3695
|
}), environment.document);
|
|
4065
3696
|
}
|
|
3697
|
+
previousSelectedItemsRef.current = selectedItems;
|
|
4066
3698
|
|
|
4067
|
-
|
|
4068
|
-
}, [selectedItems.length]);
|
|
4069
|
-
|
|
3699
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3700
|
+
}, [selectedItems.length]);
|
|
3701
|
+
// Sets focus on active item.
|
|
4070
3702
|
react.useEffect(() => {
|
|
4071
3703
|
if (isInitialMountRef.current) {
|
|
4072
3704
|
return;
|
|
4073
3705
|
}
|
|
4074
|
-
|
|
4075
3706
|
if (activeIndex === -1 && dropdownRef.current) {
|
|
4076
3707
|
dropdownRef.current.focus();
|
|
4077
3708
|
} else if (selectedItemRefs.current[activeIndex]) {
|
|
@@ -4083,37 +3714,34 @@ function useMultipleSelection(userProps) {
|
|
|
4083
3714
|
props,
|
|
4084
3715
|
state
|
|
4085
3716
|
});
|
|
4086
|
-
const setGetterPropCallInfo = useGetterPropsCalledChecker('getDropdownProps');
|
|
4087
|
-
|
|
3717
|
+
const setGetterPropCallInfo = useGetterPropsCalledChecker('getDropdownProps');
|
|
3718
|
+
// Make initial ref false.
|
|
4088
3719
|
react.useEffect(() => {
|
|
4089
3720
|
isInitialMountRef.current = false;
|
|
4090
|
-
}, []);
|
|
3721
|
+
}, []);
|
|
4091
3722
|
|
|
3723
|
+
// Event handler functions.
|
|
4092
3724
|
const selectedItemKeyDownHandlers = react.useMemo(() => ({
|
|
4093
3725
|
[keyNavigationPrevious]() {
|
|
4094
3726
|
dispatch({
|
|
4095
3727
|
type: SelectedItemKeyDownNavigationPrevious
|
|
4096
3728
|
});
|
|
4097
3729
|
},
|
|
4098
|
-
|
|
4099
3730
|
[keyNavigationNext]() {
|
|
4100
3731
|
dispatch({
|
|
4101
3732
|
type: SelectedItemKeyDownNavigationNext
|
|
4102
3733
|
});
|
|
4103
3734
|
},
|
|
4104
|
-
|
|
4105
3735
|
Delete() {
|
|
4106
3736
|
dispatch({
|
|
4107
3737
|
type: SelectedItemKeyDownDelete
|
|
4108
3738
|
});
|
|
4109
3739
|
},
|
|
4110
|
-
|
|
4111
3740
|
Backspace() {
|
|
4112
3741
|
dispatch({
|
|
4113
3742
|
type: SelectedItemKeyDownBackspace
|
|
4114
3743
|
});
|
|
4115
3744
|
}
|
|
4116
|
-
|
|
4117
3745
|
}), [dispatch, keyNavigationNext, keyNavigationPrevious]);
|
|
4118
3746
|
const dropdownKeyDownHandlers = react.useMemo(() => ({
|
|
4119
3747
|
[keyNavigationPrevious](event) {
|
|
@@ -4123,7 +3751,6 @@ function useMultipleSelection(userProps) {
|
|
|
4123
3751
|
});
|
|
4124
3752
|
}
|
|
4125
3753
|
},
|
|
4126
|
-
|
|
4127
3754
|
Backspace(event) {
|
|
4128
3755
|
if (isKeyDownOperationPermitted(event)) {
|
|
4129
3756
|
dispatch({
|
|
@@ -4131,9 +3758,9 @@ function useMultipleSelection(userProps) {
|
|
|
4131
3758
|
});
|
|
4132
3759
|
}
|
|
4133
3760
|
}
|
|
3761
|
+
}), [dispatch, keyNavigationPrevious]);
|
|
4134
3762
|
|
|
4135
|
-
|
|
4136
|
-
|
|
3763
|
+
// Getter props.
|
|
4137
3764
|
const getSelectedItemProps = react.useCallback(function (_temp) {
|
|
4138
3765
|
let {
|
|
4139
3766
|
refKey = 'ref',
|
|
@@ -4148,26 +3775,21 @@ function useMultipleSelection(userProps) {
|
|
|
4148
3775
|
state: latestState
|
|
4149
3776
|
} = latest.current;
|
|
4150
3777
|
const itemIndex = getItemIndex(index, selectedItem, latestState.selectedItems);
|
|
4151
|
-
|
|
4152
3778
|
if (itemIndex < 0) {
|
|
4153
3779
|
throw new Error('Pass either selectedItem or index in getSelectedItemProps!');
|
|
4154
3780
|
}
|
|
4155
|
-
|
|
4156
3781
|
const selectedItemHandleClick = () => {
|
|
4157
3782
|
dispatch({
|
|
4158
3783
|
type: SelectedItemClick,
|
|
4159
3784
|
index
|
|
4160
3785
|
});
|
|
4161
3786
|
};
|
|
4162
|
-
|
|
4163
3787
|
const selectedItemHandleKeyDown = event => {
|
|
4164
3788
|
const key = normalizeArrowKey(event);
|
|
4165
|
-
|
|
4166
3789
|
if (key && selectedItemKeyDownHandlers[key]) {
|
|
4167
3790
|
selectedItemKeyDownHandlers[key](event);
|
|
4168
3791
|
}
|
|
4169
3792
|
};
|
|
4170
|
-
|
|
4171
3793
|
return {
|
|
4172
3794
|
[refKey]: handleRefs(ref, selectedItemNode => {
|
|
4173
3795
|
if (selectedItemNode) {
|
|
@@ -4193,21 +3815,17 @@ function useMultipleSelection(userProps) {
|
|
|
4193
3815
|
suppressRefError = false
|
|
4194
3816
|
} = _temp3 === void 0 ? {} : _temp3;
|
|
4195
3817
|
setGetterPropCallInfo('getDropdownProps', suppressRefError, refKey, dropdownRef);
|
|
4196
|
-
|
|
4197
3818
|
const dropdownHandleKeyDown = event => {
|
|
4198
3819
|
const key = normalizeArrowKey(event);
|
|
4199
|
-
|
|
4200
3820
|
if (key && dropdownKeyDownHandlers[key]) {
|
|
4201
3821
|
dropdownKeyDownHandlers[key](event);
|
|
4202
3822
|
}
|
|
4203
3823
|
};
|
|
4204
|
-
|
|
4205
3824
|
const dropdownHandleClick = () => {
|
|
4206
3825
|
dispatch({
|
|
4207
3826
|
type: DropdownClick
|
|
4208
3827
|
});
|
|
4209
3828
|
};
|
|
4210
|
-
|
|
4211
3829
|
return {
|
|
4212
3830
|
[refKey]: handleRefs(ref, dropdownNode => {
|
|
4213
3831
|
if (dropdownNode) {
|
|
@@ -4220,8 +3838,9 @@ function useMultipleSelection(userProps) {
|
|
|
4220
3838
|
}),
|
|
4221
3839
|
...rest
|
|
4222
3840
|
};
|
|
4223
|
-
}, [dispatch, dropdownKeyDownHandlers, setGetterPropCallInfo]);
|
|
3841
|
+
}, [dispatch, dropdownKeyDownHandlers, setGetterPropCallInfo]);
|
|
4224
3842
|
|
|
3843
|
+
// returns
|
|
4225
3844
|
const addSelectedItem = react.useCallback(selectedItem => {
|
|
4226
3845
|
dispatch({
|
|
4227
3846
|
type: FunctionAddSelectedItem,
|