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
package/dist/downshift.cjs.js
CHANGED
|
@@ -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 = {
|
|
929
818
|
onClick: callAllEventHandlers(onClick, _this.buttonHandleClick),
|
|
930
819
|
onKeyDown: callAllEventHandlers(onKeyDown, _this.buttonHandleKeyDown),
|
|
@@ -942,33 +831,27 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
942
831
|
...rest
|
|
943
832
|
};
|
|
944
833
|
};
|
|
945
|
-
|
|
946
834
|
this.buttonHandleKeyUp = event => {
|
|
947
835
|
// Prevent click event from emitting in Firefox
|
|
948
836
|
event.preventDefault();
|
|
949
837
|
};
|
|
950
|
-
|
|
951
838
|
this.buttonHandleKeyDown = event => {
|
|
952
839
|
const key = normalizeArrowKey(event);
|
|
953
|
-
|
|
954
840
|
if (this.buttonKeyDownHandlers[key]) {
|
|
955
841
|
this.buttonKeyDownHandlers[key].call(this, event);
|
|
956
842
|
}
|
|
957
843
|
};
|
|
958
|
-
|
|
959
844
|
this.buttonHandleClick = event => {
|
|
960
|
-
event.preventDefault();
|
|
845
|
+
event.preventDefault();
|
|
846
|
+
// handle odd case for Safari and Firefox which
|
|
961
847
|
// don't give the button the focus properly.
|
|
962
|
-
|
|
963
848
|
/* istanbul ignore if (can't reasonably test this) */
|
|
964
|
-
|
|
965
849
|
if (this.props.environment.document.activeElement === this.props.environment.document.body) {
|
|
966
850
|
event.target.focus();
|
|
967
|
-
}
|
|
851
|
+
}
|
|
852
|
+
// to simplify testing components that use downshift, we'll not wrap this in a setTimeout
|
|
968
853
|
// if the NODE_ENV is test. With the proper build system, this should be dead code eliminated
|
|
969
854
|
// when building for production and should therefore have no impact on production code.
|
|
970
|
-
|
|
971
|
-
|
|
972
855
|
if (process.env.NODE_ENV === 'test') {
|
|
973
856
|
this.toggleMenu({
|
|
974
857
|
type: clickButton
|
|
@@ -980,11 +863,9 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
980
863
|
}));
|
|
981
864
|
}
|
|
982
865
|
};
|
|
983
|
-
|
|
984
866
|
this.buttonHandleBlur = event => {
|
|
985
867
|
const blurTarget = event.target; // Save blur target for comparison with activeElement later
|
|
986
868
|
// Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not body element
|
|
987
|
-
|
|
988
869
|
this.internalSetTimeout(() => {
|
|
989
870
|
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)
|
|
990
871
|
) {
|
|
@@ -994,7 +875,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
994
875
|
}
|
|
995
876
|
});
|
|
996
877
|
};
|
|
997
|
-
|
|
998
878
|
this.getLabelProps = props => {
|
|
999
879
|
return {
|
|
1000
880
|
htmlFor: this.inputId,
|
|
@@ -1002,7 +882,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1002
882
|
...props
|
|
1003
883
|
};
|
|
1004
884
|
};
|
|
1005
|
-
|
|
1006
885
|
this.getInputProps = function (_temp4) {
|
|
1007
886
|
let {
|
|
1008
887
|
onKeyDown,
|
|
@@ -1014,18 +893,16 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1014
893
|
} = _temp4 === void 0 ? {} : _temp4;
|
|
1015
894
|
let onChangeKey;
|
|
1016
895
|
let eventHandlers = {};
|
|
1017
|
-
/* istanbul ignore next (preact) */
|
|
1018
896
|
|
|
897
|
+
/* istanbul ignore next (preact) */
|
|
1019
898
|
{
|
|
1020
899
|
onChangeKey = 'onChange';
|
|
1021
900
|
}
|
|
1022
|
-
|
|
1023
901
|
const {
|
|
1024
902
|
inputValue,
|
|
1025
903
|
isOpen,
|
|
1026
904
|
highlightedIndex
|
|
1027
905
|
} = _this.getState();
|
|
1028
|
-
|
|
1029
906
|
if (!rest.disabled) {
|
|
1030
907
|
eventHandlers = {
|
|
1031
908
|
[onChangeKey]: callAllEventHandlers(onChange, onInput, _this.inputHandleChange),
|
|
@@ -1033,7 +910,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1033
910
|
onBlur: callAllEventHandlers(onBlur, _this.inputHandleBlur)
|
|
1034
911
|
};
|
|
1035
912
|
}
|
|
1036
|
-
|
|
1037
913
|
return {
|
|
1038
914
|
'aria-autocomplete': 'list',
|
|
1039
915
|
'aria-activedescendant': isOpen && typeof highlightedIndex === 'number' && highlightedIndex >= 0 ? _this.getItemId(highlightedIndex) : null,
|
|
@@ -1048,15 +924,12 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1048
924
|
...rest
|
|
1049
925
|
};
|
|
1050
926
|
};
|
|
1051
|
-
|
|
1052
927
|
this.inputHandleKeyDown = event => {
|
|
1053
928
|
const key = normalizeArrowKey(event);
|
|
1054
|
-
|
|
1055
929
|
if (key && this.inputKeyDownHandlers[key]) {
|
|
1056
930
|
this.inputKeyDownHandlers[key].call(this, event);
|
|
1057
931
|
}
|
|
1058
932
|
};
|
|
1059
|
-
|
|
1060
933
|
this.inputHandleChange = event => {
|
|
1061
934
|
this.internalSetState({
|
|
1062
935
|
type: changeInput,
|
|
@@ -1065,12 +938,10 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1065
938
|
highlightedIndex: this.props.defaultHighlightedIndex
|
|
1066
939
|
});
|
|
1067
940
|
};
|
|
1068
|
-
|
|
1069
941
|
this.inputHandleBlur = () => {
|
|
1070
942
|
// Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not the body element
|
|
1071
943
|
this.internalSetTimeout(() => {
|
|
1072
944
|
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);
|
|
1073
|
-
|
|
1074
945
|
if (!this.isMouseDown && !downshiftButtonIsActive) {
|
|
1075
946
|
this.reset({
|
|
1076
947
|
type: blurInput
|
|
@@ -1078,11 +949,9 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1078
949
|
}
|
|
1079
950
|
});
|
|
1080
951
|
};
|
|
1081
|
-
|
|
1082
952
|
this.menuRef = node => {
|
|
1083
953
|
this._menuNode = node;
|
|
1084
954
|
};
|
|
1085
|
-
|
|
1086
955
|
this.getMenuProps = function (_temp5, _temp6) {
|
|
1087
956
|
let {
|
|
1088
957
|
refKey = 'ref',
|
|
@@ -1103,7 +972,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1103
972
|
...props
|
|
1104
973
|
};
|
|
1105
974
|
};
|
|
1106
|
-
|
|
1107
975
|
this.getItemProps = function (_temp7) {
|
|
1108
976
|
let {
|
|
1109
977
|
onMouseMove,
|
|
@@ -1111,20 +979,15 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1111
979
|
onClick,
|
|
1112
980
|
onPress,
|
|
1113
981
|
index,
|
|
1114
|
-
item = process.env.NODE_ENV === 'production' ?
|
|
1115
|
-
/* istanbul ignore next */
|
|
1116
|
-
undefined : requiredProp('getItemProps', 'item'),
|
|
982
|
+
item = process.env.NODE_ENV === 'production' ? /* istanbul ignore next */undefined : requiredProp('getItemProps', 'item'),
|
|
1117
983
|
...rest
|
|
1118
984
|
} = _temp7 === void 0 ? {} : _temp7;
|
|
1119
|
-
|
|
1120
985
|
if (index === undefined) {
|
|
1121
986
|
_this.items.push(item);
|
|
1122
|
-
|
|
1123
987
|
index = _this.items.indexOf(item);
|
|
1124
988
|
} else {
|
|
1125
989
|
_this.items[index] = item;
|
|
1126
990
|
}
|
|
1127
|
-
|
|
1128
991
|
const onSelectKey = 'onClick';
|
|
1129
992
|
const customClickHandler = onClick;
|
|
1130
993
|
const enabledEventHandlers = {
|
|
@@ -1135,17 +998,15 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1135
998
|
if (index === _this.getState().highlightedIndex) {
|
|
1136
999
|
return;
|
|
1137
1000
|
}
|
|
1138
|
-
|
|
1139
1001
|
_this.setHighlightedIndex(index, {
|
|
1140
1002
|
type: itemMouseEnter
|
|
1141
|
-
});
|
|
1003
|
+
});
|
|
1004
|
+
|
|
1005
|
+
// We never want to manually scroll when changing state based
|
|
1142
1006
|
// on `onMouseMove` because we will be moving the element out
|
|
1143
1007
|
// from under the user which is currently scrolling/moving the
|
|
1144
1008
|
// cursor
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
1009
|
_this.avoidScrolling = true;
|
|
1148
|
-
|
|
1149
1010
|
_this.internalSetTimeout(() => _this.avoidScrolling = false, 250);
|
|
1150
1011
|
}),
|
|
1151
1012
|
onMouseDown: callAllEventHandlers(onMouseDown, event => {
|
|
@@ -1159,9 +1020,10 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1159
1020
|
type: clickItem
|
|
1160
1021
|
});
|
|
1161
1022
|
})
|
|
1162
|
-
};
|
|
1163
|
-
// of the activeElement if clicking on disabled items
|
|
1023
|
+
};
|
|
1164
1024
|
|
|
1025
|
+
// Passing down the onMouseDown handler to prevent redirect
|
|
1026
|
+
// of the activeElement if clicking on disabled items
|
|
1165
1027
|
const eventHandlers = rest.disabled ? {
|
|
1166
1028
|
onMouseDown: enabledEventHandlers.onMouseDown
|
|
1167
1029
|
} : enabledEventHandlers;
|
|
@@ -1173,18 +1035,14 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1173
1035
|
...rest
|
|
1174
1036
|
};
|
|
1175
1037
|
};
|
|
1176
|
-
|
|
1177
1038
|
this.clearItems = () => {
|
|
1178
1039
|
this.items = [];
|
|
1179
1040
|
};
|
|
1180
|
-
|
|
1181
1041
|
this.reset = function (otherStateToSet, cb) {
|
|
1182
1042
|
if (otherStateToSet === void 0) {
|
|
1183
1043
|
otherStateToSet = {};
|
|
1184
1044
|
}
|
|
1185
|
-
|
|
1186
1045
|
otherStateToSet = pickState(otherStateToSet);
|
|
1187
|
-
|
|
1188
1046
|
_this.internalSetState(_ref => {
|
|
1189
1047
|
let {
|
|
1190
1048
|
selectedItem
|
|
@@ -1197,14 +1055,11 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1197
1055
|
};
|
|
1198
1056
|
}, cb);
|
|
1199
1057
|
};
|
|
1200
|
-
|
|
1201
1058
|
this.toggleMenu = function (otherStateToSet, cb) {
|
|
1202
1059
|
if (otherStateToSet === void 0) {
|
|
1203
1060
|
otherStateToSet = {};
|
|
1204
1061
|
}
|
|
1205
|
-
|
|
1206
1062
|
otherStateToSet = pickState(otherStateToSet);
|
|
1207
|
-
|
|
1208
1063
|
_this.internalSetState(_ref2 => {
|
|
1209
1064
|
let {
|
|
1210
1065
|
isOpen
|
|
@@ -1221,29 +1076,24 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1221
1076
|
isOpen,
|
|
1222
1077
|
highlightedIndex
|
|
1223
1078
|
} = _this.getState();
|
|
1224
|
-
|
|
1225
1079
|
if (isOpen) {
|
|
1226
1080
|
if (_this.getItemCount() > 0 && typeof highlightedIndex === 'number') {
|
|
1227
1081
|
_this.setHighlightedIndex(highlightedIndex, otherStateToSet);
|
|
1228
1082
|
}
|
|
1229
1083
|
}
|
|
1230
|
-
|
|
1231
1084
|
cbToCb(cb)();
|
|
1232
1085
|
});
|
|
1233
1086
|
};
|
|
1234
|
-
|
|
1235
1087
|
this.openMenu = cb => {
|
|
1236
1088
|
this.internalSetState({
|
|
1237
1089
|
isOpen: true
|
|
1238
1090
|
}, cb);
|
|
1239
1091
|
};
|
|
1240
|
-
|
|
1241
1092
|
this.closeMenu = cb => {
|
|
1242
1093
|
this.internalSetState({
|
|
1243
1094
|
isOpen: false
|
|
1244
1095
|
}, cb);
|
|
1245
1096
|
};
|
|
1246
|
-
|
|
1247
1097
|
this.updateStatus = debounce(() => {
|
|
1248
1098
|
const state = this.getState();
|
|
1249
1099
|
const item = this.items[state.highlightedIndex];
|
|
@@ -1269,21 +1119,17 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1269
1119
|
initialInputValue: _inputValue = '',
|
|
1270
1120
|
initialSelectedItem: _selectedItem = null
|
|
1271
1121
|
} = this.props;
|
|
1272
|
-
|
|
1273
1122
|
const _state = this.getState({
|
|
1274
1123
|
highlightedIndex: _highlightedIndex,
|
|
1275
1124
|
isOpen: _isOpen,
|
|
1276
1125
|
inputValue: _inputValue,
|
|
1277
1126
|
selectedItem: _selectedItem
|
|
1278
1127
|
});
|
|
1279
|
-
|
|
1280
1128
|
if (_state.selectedItem != null && this.props.initialInputValue === undefined) {
|
|
1281
1129
|
_state.inputValue = this.props.itemToString(_state.selectedItem);
|
|
1282
1130
|
}
|
|
1283
|
-
|
|
1284
1131
|
this.state = _state;
|
|
1285
1132
|
}
|
|
1286
|
-
|
|
1287
1133
|
/**
|
|
1288
1134
|
* Clear all running timeouts
|
|
1289
1135
|
*/
|
|
@@ -1293,6 +1139,7 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1293
1139
|
});
|
|
1294
1140
|
this.timeoutIds = [];
|
|
1295
1141
|
}
|
|
1142
|
+
|
|
1296
1143
|
/**
|
|
1297
1144
|
* Gets the state based on internal state or props
|
|
1298
1145
|
* If a state value is passed via props, then that
|
|
@@ -1302,36 +1149,28 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1302
1149
|
* @param {Object} stateToMerge defaults to this.state
|
|
1303
1150
|
* @return {Object} the state
|
|
1304
1151
|
*/
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
1152
|
getState(stateToMerge) {
|
|
1308
1153
|
if (stateToMerge === void 0) {
|
|
1309
1154
|
stateToMerge = this.state;
|
|
1310
1155
|
}
|
|
1311
|
-
|
|
1312
1156
|
return getState(stateToMerge, this.props);
|
|
1313
1157
|
}
|
|
1314
|
-
|
|
1315
1158
|
getItemCount() {
|
|
1316
1159
|
// things read better this way. They're in priority order:
|
|
1317
1160
|
// 1. `this.itemCount`
|
|
1318
1161
|
// 2. `this.props.itemCount`
|
|
1319
1162
|
// 3. `this.items.length`
|
|
1320
1163
|
let itemCount = this.items.length;
|
|
1321
|
-
|
|
1322
1164
|
if (this.itemCount != null) {
|
|
1323
1165
|
itemCount = this.itemCount;
|
|
1324
1166
|
} else if (this.props.itemCount !== undefined) {
|
|
1325
1167
|
itemCount = this.props.itemCount;
|
|
1326
1168
|
}
|
|
1327
|
-
|
|
1328
1169
|
return itemCount;
|
|
1329
1170
|
}
|
|
1330
|
-
|
|
1331
1171
|
getItemNodeFromIndex(index) {
|
|
1332
1172
|
return this.props.environment.document.getElementById(this.getItemId(index));
|
|
1333
1173
|
}
|
|
1334
|
-
|
|
1335
1174
|
scrollHighlightedItemIntoView() {
|
|
1336
1175
|
/* istanbul ignore else (react-native) */
|
|
1337
1176
|
{
|
|
@@ -1339,19 +1178,16 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1339
1178
|
this.props.scrollIntoView(node, this._menuNode);
|
|
1340
1179
|
}
|
|
1341
1180
|
}
|
|
1342
|
-
|
|
1343
1181
|
moveHighlightedIndex(amount, otherStateToSet) {
|
|
1344
1182
|
const itemCount = this.getItemCount();
|
|
1345
1183
|
const {
|
|
1346
1184
|
highlightedIndex
|
|
1347
1185
|
} = this.getState();
|
|
1348
|
-
|
|
1349
1186
|
if (itemCount > 0) {
|
|
1350
1187
|
const nextHighlightedIndex = getNextWrappingIndex(amount, highlightedIndex, itemCount, index => this.getItemNodeFromIndex(index));
|
|
1351
1188
|
this.setHighlightedIndex(nextHighlightedIndex, otherStateToSet);
|
|
1352
1189
|
}
|
|
1353
1190
|
}
|
|
1354
|
-
|
|
1355
1191
|
getStateAndHelpers() {
|
|
1356
1192
|
const {
|
|
1357
1193
|
highlightedIndex,
|
|
@@ -1418,17 +1254,17 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1418
1254
|
isOpen,
|
|
1419
1255
|
selectedItem
|
|
1420
1256
|
};
|
|
1421
|
-
}
|
|
1257
|
+
}
|
|
1422
1258
|
|
|
1259
|
+
//////////////////////////// ROOT
|
|
1423
1260
|
|
|
1424
1261
|
componentDidMount() {
|
|
1425
1262
|
/* istanbul ignore if (react-native) */
|
|
1426
1263
|
if (process.env.NODE_ENV !== 'production' && !false && this.getMenuProps.called && !this.getMenuProps.suppressRefError) {
|
|
1427
1264
|
validateGetMenuPropsCalledCorrectly(this._menuNode, this.getMenuProps);
|
|
1428
1265
|
}
|
|
1429
|
-
/* istanbul ignore if (react-native) */
|
|
1430
|
-
|
|
1431
1266
|
|
|
1267
|
+
/* istanbul ignore if (react-native) */
|
|
1432
1268
|
{
|
|
1433
1269
|
// this.isMouseDown helps us track whether the mouse is currently held down.
|
|
1434
1270
|
// This is useful when the user clicks on an item in the list, but holds the mouse
|
|
@@ -1438,44 +1274,37 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1438
1274
|
const onMouseDown = () => {
|
|
1439
1275
|
this.isMouseDown = true;
|
|
1440
1276
|
};
|
|
1441
|
-
|
|
1442
1277
|
const onMouseUp = event => {
|
|
1443
|
-
this.isMouseDown = false;
|
|
1278
|
+
this.isMouseDown = false;
|
|
1279
|
+
// if the target element or the activeElement is within a downshift node
|
|
1444
1280
|
// then we don't want to reset downshift
|
|
1445
|
-
|
|
1446
1281
|
const contextWithinDownshift = targetWithinDownshift(event.target, [this._rootNode, this._menuNode], this.props.environment);
|
|
1447
|
-
|
|
1448
1282
|
if (!contextWithinDownshift && this.getState().isOpen) {
|
|
1449
1283
|
this.reset({
|
|
1450
1284
|
type: mouseUp
|
|
1451
1285
|
}, () => this.props.onOuterClick(this.getStateAndHelpers()));
|
|
1452
1286
|
}
|
|
1453
|
-
};
|
|
1287
|
+
};
|
|
1288
|
+
// Touching an element in iOS gives focus and hover states, but touching out of
|
|
1454
1289
|
// the element will remove hover, and persist the focus state, resulting in the
|
|
1455
1290
|
// blur event not being triggered.
|
|
1456
1291
|
// this.isTouchMove helps us track whether the user is tapping or swiping on a touch screen.
|
|
1457
1292
|
// If the user taps outside of Downshift, the component should be reset,
|
|
1458
1293
|
// but not if the user is swiping
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
1294
|
const onTouchStart = () => {
|
|
1462
1295
|
this.isTouchMove = false;
|
|
1463
1296
|
};
|
|
1464
|
-
|
|
1465
1297
|
const onTouchMove = () => {
|
|
1466
1298
|
this.isTouchMove = true;
|
|
1467
1299
|
};
|
|
1468
|
-
|
|
1469
1300
|
const onTouchEnd = event => {
|
|
1470
1301
|
const contextWithinDownshift = targetWithinDownshift(event.target, [this._rootNode, this._menuNode], this.props.environment, false);
|
|
1471
|
-
|
|
1472
1302
|
if (!this.isTouchMove && !contextWithinDownshift && this.getState().isOpen) {
|
|
1473
1303
|
this.reset({
|
|
1474
1304
|
type: touchEnd
|
|
1475
1305
|
}, () => this.props.onOuterClick(this.getStateAndHelpers()));
|
|
1476
1306
|
}
|
|
1477
1307
|
};
|
|
1478
|
-
|
|
1479
1308
|
const {
|
|
1480
1309
|
environment
|
|
1481
1310
|
} = this.props;
|
|
@@ -1484,7 +1313,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1484
1313
|
environment.addEventListener('touchstart', onTouchStart);
|
|
1485
1314
|
environment.addEventListener('touchmove', onTouchMove);
|
|
1486
1315
|
environment.addEventListener('touchend', onTouchEnd);
|
|
1487
|
-
|
|
1488
1316
|
this.cleanup = () => {
|
|
1489
1317
|
this.internalClearTimeouts();
|
|
1490
1318
|
this.updateStatus.cancel();
|
|
@@ -1496,7 +1324,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1496
1324
|
};
|
|
1497
1325
|
}
|
|
1498
1326
|
}
|
|
1499
|
-
|
|
1500
1327
|
shouldScroll(prevState, prevProps) {
|
|
1501
1328
|
const {
|
|
1502
1329
|
highlightedIndex: currentHighlightedIndex
|
|
@@ -1508,93 +1335,81 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1508
1335
|
const scrollWhenNavigating = currentHighlightedIndex !== prevHighlightedIndex;
|
|
1509
1336
|
return scrollWhenOpen || scrollWhenNavigating;
|
|
1510
1337
|
}
|
|
1511
|
-
|
|
1512
1338
|
componentDidUpdate(prevProps, prevState) {
|
|
1513
1339
|
if (process.env.NODE_ENV !== 'production') {
|
|
1514
1340
|
validateControlledUnchanged(this.state, prevProps, this.props);
|
|
1515
1341
|
/* istanbul ignore if (react-native) */
|
|
1516
|
-
|
|
1517
1342
|
if (this.getMenuProps.called && !this.getMenuProps.suppressRefError) {
|
|
1518
1343
|
validateGetMenuPropsCalledCorrectly(this._menuNode, this.getMenuProps);
|
|
1519
1344
|
}
|
|
1520
1345
|
}
|
|
1521
|
-
|
|
1522
1346
|
if (isControlledProp(this.props, 'selectedItem') && this.props.selectedItemChanged(prevProps.selectedItem, this.props.selectedItem)) {
|
|
1523
1347
|
this.internalSetState({
|
|
1524
1348
|
type: controlledPropUpdatedSelectedItem,
|
|
1525
1349
|
inputValue: this.props.itemToString(this.props.selectedItem)
|
|
1526
1350
|
});
|
|
1527
1351
|
}
|
|
1528
|
-
|
|
1529
1352
|
if (!this.avoidScrolling && this.shouldScroll(prevState, prevProps)) {
|
|
1530
1353
|
this.scrollHighlightedItemIntoView();
|
|
1531
1354
|
}
|
|
1532
|
-
/* istanbul ignore else (react-native) */
|
|
1533
|
-
|
|
1534
1355
|
|
|
1356
|
+
/* istanbul ignore else (react-native) */
|
|
1535
1357
|
{
|
|
1536
1358
|
this.updateStatus();
|
|
1537
1359
|
}
|
|
1538
1360
|
}
|
|
1539
|
-
|
|
1540
1361
|
componentWillUnmount() {
|
|
1541
1362
|
this.cleanup(); // avoids memory leak
|
|
1542
1363
|
}
|
|
1543
1364
|
|
|
1544
1365
|
render() {
|
|
1545
|
-
const children = unwrapArray(this.props.children, noop);
|
|
1366
|
+
const children = unwrapArray(this.props.children, noop);
|
|
1367
|
+
// because the items are rerendered every time we call the children
|
|
1546
1368
|
// we clear this out each render and it will be populated again as
|
|
1547
1369
|
// getItemProps is called.
|
|
1548
|
-
|
|
1549
|
-
|
|
1370
|
+
this.clearItems();
|
|
1371
|
+
// we reset this so we know whether the user calls getRootProps during
|
|
1550
1372
|
// this render. If they do then we don't need to do anything,
|
|
1551
1373
|
// if they don't then we need to clone the element they return and
|
|
1552
1374
|
// apply the props for them.
|
|
1553
|
-
|
|
1554
1375
|
this.getRootProps.called = false;
|
|
1555
1376
|
this.getRootProps.refKey = undefined;
|
|
1556
|
-
this.getRootProps.suppressRefError = undefined;
|
|
1557
|
-
|
|
1377
|
+
this.getRootProps.suppressRefError = undefined;
|
|
1378
|
+
// we do something similar for getMenuProps
|
|
1558
1379
|
this.getMenuProps.called = false;
|
|
1559
1380
|
this.getMenuProps.refKey = undefined;
|
|
1560
|
-
this.getMenuProps.suppressRefError = undefined;
|
|
1561
|
-
|
|
1562
|
-
this.getLabelProps.called = false;
|
|
1563
|
-
|
|
1381
|
+
this.getMenuProps.suppressRefError = undefined;
|
|
1382
|
+
// we do something similar for getLabelProps
|
|
1383
|
+
this.getLabelProps.called = false;
|
|
1384
|
+
// and something similar for getInputProps
|
|
1564
1385
|
this.getInputProps.called = false;
|
|
1565
1386
|
const element = unwrapArray(children(this.getStateAndHelpers()));
|
|
1566
|
-
|
|
1567
1387
|
if (!element) {
|
|
1568
1388
|
return null;
|
|
1569
1389
|
}
|
|
1570
|
-
|
|
1571
1390
|
if (this.getRootProps.called || this.props.suppressRefError) {
|
|
1572
1391
|
if (process.env.NODE_ENV !== 'production' && !this.getRootProps.suppressRefError && !this.props.suppressRefError) {
|
|
1573
1392
|
validateGetRootPropsCalledCorrectly(element, this.getRootProps);
|
|
1574
1393
|
}
|
|
1575
|
-
|
|
1576
1394
|
return element;
|
|
1577
1395
|
} else if (isDOMElement(element)) {
|
|
1578
1396
|
// they didn't apply the root props, but we can clone
|
|
1579
1397
|
// this and apply the props ourselves
|
|
1580
1398
|
return /*#__PURE__*/react.cloneElement(element, this.getRootProps(getElementProps(element)));
|
|
1581
1399
|
}
|
|
1582
|
-
/* istanbul ignore else */
|
|
1583
|
-
|
|
1584
1400
|
|
|
1401
|
+
/* istanbul ignore else */
|
|
1585
1402
|
if (process.env.NODE_ENV !== 'production') {
|
|
1586
1403
|
// they didn't apply the root props, but they need to
|
|
1587
1404
|
// otherwise we can't query around the autocomplete
|
|
1405
|
+
|
|
1588
1406
|
throw new Error('downshift: If you return a non-DOM element, you must apply the getRootProps function');
|
|
1589
1407
|
}
|
|
1590
|
-
/* istanbul ignore next */
|
|
1591
|
-
|
|
1592
1408
|
|
|
1409
|
+
/* istanbul ignore next */
|
|
1593
1410
|
return undefined;
|
|
1594
1411
|
}
|
|
1595
|
-
|
|
1596
1412
|
}
|
|
1597
|
-
|
|
1598
1413
|
Downshift.defaultProps = {
|
|
1599
1414
|
defaultHighlightedIndex: null,
|
|
1600
1415
|
defaultIsOpen: false,
|
|
@@ -1603,12 +1418,10 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1603
1418
|
if (i == null) {
|
|
1604
1419
|
return '';
|
|
1605
1420
|
}
|
|
1606
|
-
|
|
1607
1421
|
if (process.env.NODE_ENV !== 'production' && isPlainObject(i) && !i.hasOwnProperty('toString')) {
|
|
1608
1422
|
// eslint-disable-next-line no-console
|
|
1609
1423
|
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);
|
|
1610
1424
|
}
|
|
1611
|
-
|
|
1612
1425
|
return String(i);
|
|
1613
1426
|
},
|
|
1614
1427
|
onStateChange: noop,
|
|
@@ -1618,8 +1431,7 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1618
1431
|
onSelect: noop,
|
|
1619
1432
|
onOuterClick: noop,
|
|
1620
1433
|
selectedItemChanged: (prevItem, item) => prevItem !== item,
|
|
1621
|
-
environment:
|
|
1622
|
-
/* istanbul ignore next (ssr) */
|
|
1434
|
+
environment: /* istanbul ignore next (ssr) */
|
|
1623
1435
|
typeof window === 'undefined' ? {} : window,
|
|
1624
1436
|
stateReducer: (state, stateToSet) => stateToSet,
|
|
1625
1437
|
suppressRefError: false,
|
|
@@ -1628,7 +1440,6 @@ const Downshift = /*#__PURE__*/(() => {
|
|
|
1628
1440
|
Downshift.stateChangeTypes = stateChangeTypes$3;
|
|
1629
1441
|
return Downshift;
|
|
1630
1442
|
})();
|
|
1631
|
-
|
|
1632
1443
|
process.env.NODE_ENV !== "production" ? Downshift.propTypes = {
|
|
1633
1444
|
children: PropTypes__default["default"].func,
|
|
1634
1445
|
defaultHighlightedIndex: PropTypes__default["default"].number,
|
|
@@ -1662,7 +1473,6 @@ process.env.NODE_ENV !== "production" ? Downshift.propTypes = {
|
|
|
1662
1473
|
scrollIntoView: PropTypes__default["default"].func,
|
|
1663
1474
|
// things we keep in state for uncontrolled components
|
|
1664
1475
|
// but can accept as props for controlled components
|
|
1665
|
-
|
|
1666
1476
|
/* eslint-disable react/no-unused-prop-types */
|
|
1667
1477
|
selectedItem: PropTypes__default["default"].any,
|
|
1668
1478
|
isOpen: PropTypes__default["default"].bool,
|
|
@@ -1673,28 +1483,23 @@ process.env.NODE_ENV !== "production" ? Downshift.propTypes = {
|
|
|
1673
1483
|
menuId: PropTypes__default["default"].string,
|
|
1674
1484
|
getItemId: PropTypes__default["default"].func
|
|
1675
1485
|
/* eslint-enable react/no-unused-prop-types */
|
|
1676
|
-
|
|
1677
1486
|
} : void 0;
|
|
1678
1487
|
var Downshift$1 = Downshift;
|
|
1679
|
-
|
|
1680
1488
|
function validateGetMenuPropsCalledCorrectly(node, _ref3) {
|
|
1681
1489
|
let {
|
|
1682
1490
|
refKey
|
|
1683
1491
|
} = _ref3;
|
|
1684
|
-
|
|
1685
1492
|
if (!node) {
|
|
1686
1493
|
// eslint-disable-next-line no-console
|
|
1687
1494
|
console.error(`downshift: The ref prop "${refKey}" from getMenuProps was not applied correctly on your menu element.`);
|
|
1688
1495
|
}
|
|
1689
1496
|
}
|
|
1690
|
-
|
|
1691
1497
|
function validateGetRootPropsCalledCorrectly(element, _ref4) {
|
|
1692
1498
|
let {
|
|
1693
1499
|
refKey
|
|
1694
1500
|
} = _ref4;
|
|
1695
1501
|
const refKeySpecified = refKey !== 'ref';
|
|
1696
1502
|
const isComposite = !isDOMElement(element);
|
|
1697
|
-
|
|
1698
1503
|
if (isComposite && !refKeySpecified && !reactIs.isForwardRef(element)) {
|
|
1699
1504
|
// eslint-disable-next-line no-console
|
|
1700
1505
|
console.error('downshift: You returned a non-DOM element. You must specify a refKey in getRootProps');
|
|
@@ -1702,7 +1507,6 @@ function validateGetRootPropsCalledCorrectly(element, _ref4) {
|
|
|
1702
1507
|
// eslint-disable-next-line no-console
|
|
1703
1508
|
console.error(`downshift: You returned a DOM element. You should not specify a refKey in getRootProps. You specified "${refKey}"`);
|
|
1704
1509
|
}
|
|
1705
|
-
|
|
1706
1510
|
if (!reactIs.isForwardRef(element) && !getElementProps(element)[refKey]) {
|
|
1707
1511
|
// eslint-disable-next-line no-console
|
|
1708
1512
|
console.error(`downshift: You must apply the ref prop "${refKey}" from getRootProps onto your root element.`);
|
|
@@ -1715,7 +1519,6 @@ const dropdownDefaultStateValues = {
|
|
|
1715
1519
|
selectedItem: null,
|
|
1716
1520
|
inputValue: ''
|
|
1717
1521
|
};
|
|
1718
|
-
|
|
1719
1522
|
function callOnChangeProps(action, state, newState) {
|
|
1720
1523
|
const {
|
|
1721
1524
|
props,
|
|
@@ -1724,12 +1527,10 @@ function callOnChangeProps(action, state, newState) {
|
|
|
1724
1527
|
const changes = {};
|
|
1725
1528
|
Object.keys(state).forEach(key => {
|
|
1726
1529
|
invokeOnChangeHandler(key, action, state, newState);
|
|
1727
|
-
|
|
1728
1530
|
if (newState[key] !== state[key]) {
|
|
1729
1531
|
changes[key] = newState[key];
|
|
1730
1532
|
}
|
|
1731
1533
|
});
|
|
1732
|
-
|
|
1733
1534
|
if (props.onStateChange && Object.keys(changes).length) {
|
|
1734
1535
|
props.onStateChange({
|
|
1735
1536
|
type,
|
|
@@ -1737,14 +1538,12 @@ function callOnChangeProps(action, state, newState) {
|
|
|
1737
1538
|
});
|
|
1738
1539
|
}
|
|
1739
1540
|
}
|
|
1740
|
-
|
|
1741
1541
|
function invokeOnChangeHandler(key, action, state, newState) {
|
|
1742
1542
|
const {
|
|
1743
1543
|
props,
|
|
1744
1544
|
type
|
|
1745
1545
|
} = action;
|
|
1746
1546
|
const handler = `on${capitalizeString(key)}Change`;
|
|
1747
|
-
|
|
1748
1547
|
if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
|
|
1749
1548
|
props[handler]({
|
|
1750
1549
|
type,
|
|
@@ -1752,6 +1551,7 @@ function invokeOnChangeHandler(key, action, state, newState) {
|
|
|
1752
1551
|
});
|
|
1753
1552
|
}
|
|
1754
1553
|
}
|
|
1554
|
+
|
|
1755
1555
|
/**
|
|
1756
1556
|
* Default state reducer that returns the changes.
|
|
1757
1557
|
*
|
|
@@ -1759,19 +1559,16 @@ function invokeOnChangeHandler(key, action, state, newState) {
|
|
|
1759
1559
|
* @param {Object} a action with changes.
|
|
1760
1560
|
* @returns {Object} changes.
|
|
1761
1561
|
*/
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
1562
|
function stateReducer(s, a) {
|
|
1765
1563
|
return a.changes;
|
|
1766
1564
|
}
|
|
1565
|
+
|
|
1767
1566
|
/**
|
|
1768
1567
|
* Returns a message to be added to aria-live region when item is selected.
|
|
1769
1568
|
*
|
|
1770
1569
|
* @param {Object} selectionParameters Parameters required to build the message.
|
|
1771
1570
|
* @returns {string} The a11y message.
|
|
1772
1571
|
*/
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
1572
|
function getA11ySelectionMessage(selectionParameters) {
|
|
1776
1573
|
const {
|
|
1777
1574
|
selectedItem,
|
|
@@ -1779,17 +1576,16 @@ function getA11ySelectionMessage(selectionParameters) {
|
|
|
1779
1576
|
} = selectionParameters;
|
|
1780
1577
|
return selectedItem ? `${itemToStringLocal(selectedItem)} has been selected.` : '';
|
|
1781
1578
|
}
|
|
1579
|
+
|
|
1782
1580
|
/**
|
|
1783
1581
|
* Debounced call for updating the a11y message.
|
|
1784
1582
|
*/
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
1583
|
const updateA11yStatus = debounce((getA11yMessage, document) => {
|
|
1788
1584
|
setStatus(getA11yMessage(), document);
|
|
1789
|
-
}, 200);
|
|
1585
|
+
}, 200);
|
|
1790
1586
|
|
|
1587
|
+
// istanbul ignore next
|
|
1791
1588
|
const useIsomorphicLayoutEffect = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined' ? react.useLayoutEffect : react.useEffect;
|
|
1792
|
-
|
|
1793
1589
|
function useElementIds(_ref) {
|
|
1794
1590
|
let {
|
|
1795
1591
|
id = `downshift-${generateId()}`,
|
|
@@ -1808,41 +1604,35 @@ function useElementIds(_ref) {
|
|
|
1808
1604
|
});
|
|
1809
1605
|
return elementIdsRef.current;
|
|
1810
1606
|
}
|
|
1811
|
-
|
|
1812
1607
|
function getItemIndex(index, item, items) {
|
|
1813
1608
|
if (index !== undefined) {
|
|
1814
1609
|
return index;
|
|
1815
1610
|
}
|
|
1816
|
-
|
|
1817
1611
|
if (items.length === 0) {
|
|
1818
1612
|
return -1;
|
|
1819
1613
|
}
|
|
1820
|
-
|
|
1821
1614
|
return items.indexOf(item);
|
|
1822
1615
|
}
|
|
1823
|
-
|
|
1824
1616
|
function itemToString(item) {
|
|
1825
1617
|
return item ? String(item) : '';
|
|
1826
1618
|
}
|
|
1827
|
-
|
|
1828
1619
|
function isAcceptedCharacterKey(key) {
|
|
1829
1620
|
return /^\S{1}$/.test(key);
|
|
1830
1621
|
}
|
|
1831
|
-
|
|
1832
1622
|
function capitalizeString(string) {
|
|
1833
1623
|
return `${string.slice(0, 1).toUpperCase()}${string.slice(1)}`;
|
|
1834
1624
|
}
|
|
1835
|
-
|
|
1836
1625
|
function useLatestRef(val) {
|
|
1837
|
-
const ref = react.useRef(val);
|
|
1626
|
+
const ref = react.useRef(val);
|
|
1627
|
+
// technically this is not "concurrent mode safe" because we're manipulating
|
|
1838
1628
|
// the value during render (so it's not idempotent). However, the places this
|
|
1839
1629
|
// hook is used is to support memoizing callbacks which will be called
|
|
1840
1630
|
// *during* render, so we need the latest values *during* render.
|
|
1841
1631
|
// If not for this, then we'd probably want to use useLayoutEffect instead.
|
|
1842
|
-
|
|
1843
1632
|
ref.current = val;
|
|
1844
1633
|
return ref;
|
|
1845
1634
|
}
|
|
1635
|
+
|
|
1846
1636
|
/**
|
|
1847
1637
|
* Computes the controlled state using a the previous state, props,
|
|
1848
1638
|
* two reducers, one from downshift and an optional one from the user.
|
|
@@ -1853,8 +1643,6 @@ function useLatestRef(val) {
|
|
|
1853
1643
|
* @param {Object} props The hook props.
|
|
1854
1644
|
* @returns {Array} An array with the state and an action dispatcher.
|
|
1855
1645
|
*/
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
1646
|
function useEnhancedReducer(reducer, initialState, props) {
|
|
1859
1647
|
const prevStateRef = react.useRef();
|
|
1860
1648
|
const actionRef = react.useRef();
|
|
@@ -1862,7 +1650,8 @@ function useEnhancedReducer(reducer, initialState, props) {
|
|
|
1862
1650
|
actionRef.current = action;
|
|
1863
1651
|
state = getState(state, action.props);
|
|
1864
1652
|
const changes = reducer(state, action);
|
|
1865
|
-
const newState = action.props.stateReducer(state, {
|
|
1653
|
+
const newState = action.props.stateReducer(state, {
|
|
1654
|
+
...action,
|
|
1866
1655
|
changes
|
|
1867
1656
|
});
|
|
1868
1657
|
return newState;
|
|
@@ -1878,11 +1667,11 @@ function useEnhancedReducer(reducer, initialState, props) {
|
|
|
1878
1667
|
if (action && prevStateRef.current && prevStateRef.current !== state) {
|
|
1879
1668
|
callOnChangeProps(action, getState(prevStateRef.current, action.props), state);
|
|
1880
1669
|
}
|
|
1881
|
-
|
|
1882
1670
|
prevStateRef.current = state;
|
|
1883
1671
|
}, [state, props, action]);
|
|
1884
1672
|
return [state, dispatchWithProps];
|
|
1885
1673
|
}
|
|
1674
|
+
|
|
1886
1675
|
/**
|
|
1887
1676
|
* Wraps the useEnhancedReducer and applies the controlled prop values before
|
|
1888
1677
|
* returning the new state.
|
|
@@ -1892,57 +1681,42 @@ function useEnhancedReducer(reducer, initialState, props) {
|
|
|
1892
1681
|
* @param {Object} props The hook props.
|
|
1893
1682
|
* @returns {Array} An array with the state and an action dispatcher.
|
|
1894
1683
|
*/
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
1684
|
function useControlledReducer$1(reducer, initialState, props) {
|
|
1898
1685
|
const [state, dispatch] = useEnhancedReducer(reducer, initialState, props);
|
|
1899
1686
|
return [getState(state, props), dispatch];
|
|
1900
1687
|
}
|
|
1901
|
-
|
|
1902
1688
|
const defaultProps$3 = {
|
|
1903
1689
|
itemToString,
|
|
1904
1690
|
stateReducer,
|
|
1905
1691
|
getA11ySelectionMessage,
|
|
1906
1692
|
scrollIntoView,
|
|
1907
|
-
environment:
|
|
1908
|
-
/* istanbul ignore next (ssr) */
|
|
1693
|
+
environment: /* istanbul ignore next (ssr) */
|
|
1909
1694
|
typeof window === 'undefined' ? {} : window
|
|
1910
1695
|
};
|
|
1911
|
-
|
|
1912
1696
|
function getDefaultValue$1(props, propKey, defaultStateValues) {
|
|
1913
1697
|
if (defaultStateValues === void 0) {
|
|
1914
1698
|
defaultStateValues = dropdownDefaultStateValues;
|
|
1915
1699
|
}
|
|
1916
|
-
|
|
1917
1700
|
const defaultValue = props[`default${capitalizeString(propKey)}`];
|
|
1918
|
-
|
|
1919
1701
|
if (defaultValue !== undefined) {
|
|
1920
1702
|
return defaultValue;
|
|
1921
1703
|
}
|
|
1922
|
-
|
|
1923
1704
|
return defaultStateValues[propKey];
|
|
1924
1705
|
}
|
|
1925
|
-
|
|
1926
1706
|
function getInitialValue$1(props, propKey, defaultStateValues) {
|
|
1927
1707
|
if (defaultStateValues === void 0) {
|
|
1928
1708
|
defaultStateValues = dropdownDefaultStateValues;
|
|
1929
1709
|
}
|
|
1930
|
-
|
|
1931
1710
|
const value = props[propKey];
|
|
1932
|
-
|
|
1933
1711
|
if (value !== undefined) {
|
|
1934
1712
|
return value;
|
|
1935
1713
|
}
|
|
1936
|
-
|
|
1937
1714
|
const initialValue = props[`initial${capitalizeString(propKey)}`];
|
|
1938
|
-
|
|
1939
1715
|
if (initialValue !== undefined) {
|
|
1940
1716
|
return initialValue;
|
|
1941
1717
|
}
|
|
1942
|
-
|
|
1943
1718
|
return getDefaultValue$1(props, propKey, defaultStateValues);
|
|
1944
1719
|
}
|
|
1945
|
-
|
|
1946
1720
|
function getInitialState$2(props) {
|
|
1947
1721
|
const selectedItem = getInitialValue$1(props, 'selectedItem');
|
|
1948
1722
|
const isOpen = getInitialValue$1(props, 'isOpen');
|
|
@@ -1955,7 +1729,6 @@ function getInitialState$2(props) {
|
|
|
1955
1729
|
inputValue
|
|
1956
1730
|
};
|
|
1957
1731
|
}
|
|
1958
|
-
|
|
1959
1732
|
function getHighlightedIndexOnOpen(props, state, offset) {
|
|
1960
1733
|
const {
|
|
1961
1734
|
items,
|
|
@@ -1966,30 +1739,26 @@ function getHighlightedIndexOnOpen(props, state, offset) {
|
|
|
1966
1739
|
selectedItem,
|
|
1967
1740
|
highlightedIndex
|
|
1968
1741
|
} = state;
|
|
1969
|
-
|
|
1970
1742
|
if (items.length === 0) {
|
|
1971
1743
|
return -1;
|
|
1972
|
-
}
|
|
1973
|
-
|
|
1744
|
+
}
|
|
1974
1745
|
|
|
1746
|
+
// initialHighlightedIndex will give value to highlightedIndex on initial state only.
|
|
1975
1747
|
if (initialHighlightedIndex !== undefined && highlightedIndex === initialHighlightedIndex) {
|
|
1976
1748
|
return initialHighlightedIndex;
|
|
1977
1749
|
}
|
|
1978
|
-
|
|
1979
1750
|
if (defaultHighlightedIndex !== undefined) {
|
|
1980
1751
|
return defaultHighlightedIndex;
|
|
1981
1752
|
}
|
|
1982
|
-
|
|
1983
1753
|
if (selectedItem) {
|
|
1984
1754
|
return items.indexOf(selectedItem);
|
|
1985
1755
|
}
|
|
1986
|
-
|
|
1987
1756
|
if (offset === 0) {
|
|
1988
1757
|
return -1;
|
|
1989
1758
|
}
|
|
1990
|
-
|
|
1991
1759
|
return offset < 0 ? items.length - 1 : 0;
|
|
1992
1760
|
}
|
|
1761
|
+
|
|
1993
1762
|
/**
|
|
1994
1763
|
* Reuse the movement tracking of mouse and touch events.
|
|
1995
1764
|
*
|
|
@@ -1999,8 +1768,6 @@ function getHighlightedIndexOnOpen(props, state, offset) {
|
|
|
1999
1768
|
* @param {Function} handleBlur Handler on blur from mouse or touch.
|
|
2000
1769
|
* @returns {Object} Ref containing whether mouseDown or touchMove event is happening
|
|
2001
1770
|
*/
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
1771
|
function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, handleBlur) {
|
|
2005
1772
|
const mouseAndTouchTrackersRef = react.useRef({
|
|
2006
1773
|
isMouseDown: false,
|
|
@@ -2012,29 +1779,23 @@ function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, hand
|
|
|
2012
1779
|
const onMouseDown = () => {
|
|
2013
1780
|
mouseAndTouchTrackersRef.current.isMouseDown = true;
|
|
2014
1781
|
};
|
|
2015
|
-
|
|
2016
1782
|
const onMouseUp = event => {
|
|
2017
1783
|
mouseAndTouchTrackersRef.current.isMouseDown = false;
|
|
2018
|
-
|
|
2019
1784
|
if (isOpen && !targetWithinDownshift(event.target, downshiftElementRefs.map(ref => ref.current), environment)) {
|
|
2020
1785
|
handleBlur();
|
|
2021
1786
|
}
|
|
2022
1787
|
};
|
|
2023
|
-
|
|
2024
1788
|
const onTouchStart = () => {
|
|
2025
1789
|
mouseAndTouchTrackersRef.current.isTouchMove = false;
|
|
2026
1790
|
};
|
|
2027
|
-
|
|
2028
1791
|
const onTouchMove = () => {
|
|
2029
1792
|
mouseAndTouchTrackersRef.current.isTouchMove = true;
|
|
2030
1793
|
};
|
|
2031
|
-
|
|
2032
1794
|
const onTouchEnd = event => {
|
|
2033
1795
|
if (isOpen && !mouseAndTouchTrackersRef.current.isTouchMove && !targetWithinDownshift(event.target, downshiftElementRefs.map(ref => ref.current), environment, false)) {
|
|
2034
1796
|
handleBlur();
|
|
2035
1797
|
}
|
|
2036
1798
|
};
|
|
2037
|
-
|
|
2038
1799
|
environment.addEventListener('mousedown', onMouseDown);
|
|
2039
1800
|
environment.addEventListener('mouseup', onMouseUp);
|
|
2040
1801
|
environment.addEventListener('touchstart', onTouchStart);
|
|
@@ -2046,14 +1807,14 @@ function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, hand
|
|
|
2046
1807
|
environment.removeEventListener('touchstart', onTouchStart);
|
|
2047
1808
|
environment.removeEventListener('touchmove', onTouchMove);
|
|
2048
1809
|
environment.removeEventListener('touchend', onTouchEnd);
|
|
2049
|
-
};
|
|
1810
|
+
};
|
|
1811
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2050
1812
|
}, [isOpen, environment]);
|
|
2051
1813
|
return mouseAndTouchTrackersRef;
|
|
2052
1814
|
}
|
|
1815
|
+
|
|
2053
1816
|
/* istanbul ignore next */
|
|
2054
1817
|
// eslint-disable-next-line import/no-mutable-exports
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
1818
|
let useGetterPropsCalledChecker = () => noop;
|
|
2058
1819
|
/**
|
|
2059
1820
|
* Custom hook that checks if getter props are called correctly.
|
|
@@ -2061,18 +1822,13 @@ let useGetterPropsCalledChecker = () => noop;
|
|
|
2061
1822
|
* @param {...any} propKeys Getter prop names to be handled.
|
|
2062
1823
|
* @returns {Function} Setter function called inside getter props to set call information.
|
|
2063
1824
|
*/
|
|
2064
|
-
|
|
2065
1825
|
/* istanbul ignore next */
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
1826
|
if (process.env.NODE_ENV !== 'production') {
|
|
2069
1827
|
useGetterPropsCalledChecker = function () {
|
|
2070
1828
|
const isInitialMountRef = react.useRef(true);
|
|
2071
|
-
|
|
2072
1829
|
for (var _len = arguments.length, propKeys = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
2073
1830
|
propKeys[_key] = arguments[_key];
|
|
2074
1831
|
}
|
|
2075
|
-
|
|
2076
1832
|
const getterPropsCalledRef = react.useRef(propKeys.reduce((acc, propKey) => {
|
|
2077
1833
|
acc[propKey] = {};
|
|
2078
1834
|
return acc;
|
|
@@ -2080,7 +1836,6 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
2080
1836
|
react.useEffect(() => {
|
|
2081
1837
|
Object.keys(getterPropsCalledRef.current).forEach(propKey => {
|
|
2082
1838
|
const propCallInfo = getterPropsCalledRef.current[propKey];
|
|
2083
|
-
|
|
2084
1839
|
if (isInitialMountRef.current) {
|
|
2085
1840
|
if (!Object.keys(propCallInfo).length) {
|
|
2086
1841
|
// eslint-disable-next-line no-console
|
|
@@ -2088,13 +1843,11 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
2088
1843
|
return;
|
|
2089
1844
|
}
|
|
2090
1845
|
}
|
|
2091
|
-
|
|
2092
1846
|
const {
|
|
2093
1847
|
suppressRefError,
|
|
2094
1848
|
refKey,
|
|
2095
1849
|
elementRef
|
|
2096
1850
|
} = propCallInfo;
|
|
2097
|
-
|
|
2098
1851
|
if ((!elementRef || !elementRef.current) && !suppressRefError) {
|
|
2099
1852
|
// eslint-disable-next-line no-console
|
|
2100
1853
|
console.error(`downshift: The ref prop "${refKey}" from ${propKey} was not applied correctly on your element.`);
|
|
@@ -2112,7 +1865,6 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
2112
1865
|
return setGetterPropCallInfo;
|
|
2113
1866
|
};
|
|
2114
1867
|
}
|
|
2115
|
-
|
|
2116
1868
|
function useA11yMessageSetter(getA11yMessage, dependencyArray, _ref2) {
|
|
2117
1869
|
let {
|
|
2118
1870
|
isInitialMount,
|
|
@@ -2126,16 +1878,15 @@ function useA11yMessageSetter(getA11yMessage, dependencyArray, _ref2) {
|
|
|
2126
1878
|
if (isInitialMount || false) {
|
|
2127
1879
|
return;
|
|
2128
1880
|
}
|
|
2129
|
-
|
|
2130
1881
|
updateA11yStatus(() => getA11yMessage({
|
|
2131
1882
|
highlightedIndex,
|
|
2132
1883
|
highlightedItem: items[highlightedIndex],
|
|
2133
1884
|
resultCount: items.length,
|
|
2134
1885
|
...rest
|
|
2135
|
-
}), environment.document);
|
|
1886
|
+
}), environment.document);
|
|
1887
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2136
1888
|
}, dependencyArray);
|
|
2137
1889
|
}
|
|
2138
|
-
|
|
2139
1890
|
function useScrollIntoView(_ref3) {
|
|
2140
1891
|
let {
|
|
2141
1892
|
highlightedIndex,
|
|
@@ -2146,27 +1897,25 @@ function useScrollIntoView(_ref3) {
|
|
|
2146
1897
|
scrollIntoView: scrollIntoViewProp
|
|
2147
1898
|
} = _ref3;
|
|
2148
1899
|
// used not to scroll on highlight by mouse.
|
|
2149
|
-
const shouldScrollRef = react.useRef(true);
|
|
2150
|
-
|
|
1900
|
+
const shouldScrollRef = react.useRef(true);
|
|
1901
|
+
// Scroll on highlighted item if change comes from keyboard.
|
|
2151
1902
|
useIsomorphicLayoutEffect(() => {
|
|
2152
1903
|
if (highlightedIndex < 0 || !isOpen || !Object.keys(itemRefs.current).length) {
|
|
2153
1904
|
return;
|
|
2154
1905
|
}
|
|
2155
|
-
|
|
2156
1906
|
if (shouldScrollRef.current === false) {
|
|
2157
1907
|
shouldScrollRef.current = true;
|
|
2158
1908
|
} else {
|
|
2159
1909
|
scrollIntoViewProp(getItemNodeFromIndex(highlightedIndex), menuElement);
|
|
2160
|
-
}
|
|
2161
|
-
|
|
1910
|
+
}
|
|
1911
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2162
1912
|
}, [highlightedIndex]);
|
|
2163
1913
|
return shouldScrollRef;
|
|
2164
|
-
}
|
|
2165
|
-
|
|
1914
|
+
}
|
|
2166
1915
|
|
|
1916
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
2167
1917
|
let useControlPropsValidator = noop;
|
|
2168
1918
|
/* istanbul ignore next */
|
|
2169
|
-
|
|
2170
1919
|
if (process.env.NODE_ENV !== 'production') {
|
|
2171
1920
|
useControlPropsValidator = _ref4 => {
|
|
2172
1921
|
let {
|
|
@@ -2180,7 +1929,6 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
2180
1929
|
if (isInitialMount) {
|
|
2181
1930
|
return;
|
|
2182
1931
|
}
|
|
2183
|
-
|
|
2184
1932
|
validateControlledUnchanged(state, prevPropsRef.current, props);
|
|
2185
1933
|
prevPropsRef.current = props;
|
|
2186
1934
|
}, [state, props, isInitialMount]);
|
|
@@ -2193,20 +1941,17 @@ function downshiftCommonReducer(state, action, stateChangeTypes) {
|
|
|
2193
1941
|
props
|
|
2194
1942
|
} = action;
|
|
2195
1943
|
let changes;
|
|
2196
|
-
|
|
2197
1944
|
switch (type) {
|
|
2198
1945
|
case stateChangeTypes.ItemMouseMove:
|
|
2199
1946
|
changes = {
|
|
2200
1947
|
highlightedIndex: action.disabled ? -1 : action.index
|
|
2201
1948
|
};
|
|
2202
1949
|
break;
|
|
2203
|
-
|
|
2204
1950
|
case stateChangeTypes.MenuMouseLeave:
|
|
2205
1951
|
changes = {
|
|
2206
1952
|
highlightedIndex: -1
|
|
2207
1953
|
};
|
|
2208
1954
|
break;
|
|
2209
|
-
|
|
2210
1955
|
case stateChangeTypes.ToggleButtonClick:
|
|
2211
1956
|
case stateChangeTypes.FunctionToggleMenu:
|
|
2212
1957
|
changes = {
|
|
@@ -2214,32 +1959,27 @@ function downshiftCommonReducer(state, action, stateChangeTypes) {
|
|
|
2214
1959
|
highlightedIndex: state.isOpen ? -1 : getHighlightedIndexOnOpen(props, state, 0)
|
|
2215
1960
|
};
|
|
2216
1961
|
break;
|
|
2217
|
-
|
|
2218
1962
|
case stateChangeTypes.FunctionOpenMenu:
|
|
2219
1963
|
changes = {
|
|
2220
1964
|
isOpen: true,
|
|
2221
1965
|
highlightedIndex: getHighlightedIndexOnOpen(props, state, 0)
|
|
2222
1966
|
};
|
|
2223
1967
|
break;
|
|
2224
|
-
|
|
2225
1968
|
case stateChangeTypes.FunctionCloseMenu:
|
|
2226
1969
|
changes = {
|
|
2227
1970
|
isOpen: false
|
|
2228
1971
|
};
|
|
2229
1972
|
break;
|
|
2230
|
-
|
|
2231
1973
|
case stateChangeTypes.FunctionSetHighlightedIndex:
|
|
2232
1974
|
changes = {
|
|
2233
1975
|
highlightedIndex: action.highlightedIndex
|
|
2234
1976
|
};
|
|
2235
1977
|
break;
|
|
2236
|
-
|
|
2237
1978
|
case stateChangeTypes.FunctionSetInputValue:
|
|
2238
1979
|
changes = {
|
|
2239
1980
|
inputValue: action.inputValue
|
|
2240
1981
|
};
|
|
2241
1982
|
break;
|
|
2242
|
-
|
|
2243
1983
|
case stateChangeTypes.FunctionReset:
|
|
2244
1984
|
changes = {
|
|
2245
1985
|
highlightedIndex: getDefaultValue$1(props, 'highlightedIndex'),
|
|
@@ -2248,12 +1988,11 @@ function downshiftCommonReducer(state, action, stateChangeTypes) {
|
|
|
2248
1988
|
inputValue: getDefaultValue$1(props, 'inputValue')
|
|
2249
1989
|
};
|
|
2250
1990
|
break;
|
|
2251
|
-
|
|
2252
1991
|
default:
|
|
2253
1992
|
throw new Error('Reducer called without proper action type.');
|
|
2254
1993
|
}
|
|
2255
|
-
|
|
2256
|
-
|
|
1994
|
+
return {
|
|
1995
|
+
...state,
|
|
2257
1996
|
...changes
|
|
2258
1997
|
};
|
|
2259
1998
|
}
|
|
@@ -2392,7 +2131,6 @@ var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
|
|
|
2392
2131
|
});
|
|
2393
2132
|
|
|
2394
2133
|
/* eslint-disable complexity */
|
|
2395
|
-
|
|
2396
2134
|
function downshiftSelectReducer(state, action) {
|
|
2397
2135
|
const {
|
|
2398
2136
|
type,
|
|
@@ -2400,7 +2138,6 @@ function downshiftSelectReducer(state, action) {
|
|
|
2400
2138
|
altKey
|
|
2401
2139
|
} = action;
|
|
2402
2140
|
let changes;
|
|
2403
|
-
|
|
2404
2141
|
switch (type) {
|
|
2405
2142
|
case ItemClick$1:
|
|
2406
2143
|
changes = {
|
|
@@ -2409,7 +2146,6 @@ function downshiftSelectReducer(state, action) {
|
|
|
2409
2146
|
selectedItem: props.items[action.index]
|
|
2410
2147
|
};
|
|
2411
2148
|
break;
|
|
2412
|
-
|
|
2413
2149
|
case ToggleButtonKeyDownCharacter:
|
|
2414
2150
|
{
|
|
2415
2151
|
const lowercasedKey = action.key;
|
|
@@ -2429,7 +2165,6 @@ function downshiftSelectReducer(state, action) {
|
|
|
2429
2165
|
};
|
|
2430
2166
|
}
|
|
2431
2167
|
break;
|
|
2432
|
-
|
|
2433
2168
|
case ToggleButtonKeyDownArrowDown:
|
|
2434
2169
|
{
|
|
2435
2170
|
const highlightedIndex = state.isOpen ? getNextWrappingIndex(1, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false) : altKey && state.selectedItem == null ? -1 : getHighlightedIndexOnOpen(props, state, 1);
|
|
@@ -2439,7 +2174,6 @@ function downshiftSelectReducer(state, action) {
|
|
|
2439
2174
|
};
|
|
2440
2175
|
}
|
|
2441
2176
|
break;
|
|
2442
|
-
|
|
2443
2177
|
case ToggleButtonKeyDownArrowUp:
|
|
2444
2178
|
if (state.isOpen && altKey) {
|
|
2445
2179
|
changes = {
|
|
@@ -2456,10 +2190,8 @@ function downshiftSelectReducer(state, action) {
|
|
|
2456
2190
|
isOpen: true
|
|
2457
2191
|
};
|
|
2458
2192
|
}
|
|
2459
|
-
|
|
2460
2193
|
break;
|
|
2461
2194
|
// only triggered when menu is open.
|
|
2462
|
-
|
|
2463
2195
|
case ToggleButtonKeyDownEnter:
|
|
2464
2196
|
case ToggleButtonKeyDownSpaceButton:
|
|
2465
2197
|
changes = {
|
|
@@ -2470,40 +2202,34 @@ function downshiftSelectReducer(state, action) {
|
|
|
2470
2202
|
})
|
|
2471
2203
|
};
|
|
2472
2204
|
break;
|
|
2473
|
-
|
|
2474
2205
|
case ToggleButtonKeyDownHome:
|
|
2475
2206
|
changes = {
|
|
2476
2207
|
highlightedIndex: getNextNonDisabledIndex(1, 0, props.items.length, action.getItemNodeFromIndex, false),
|
|
2477
2208
|
isOpen: true
|
|
2478
2209
|
};
|
|
2479
2210
|
break;
|
|
2480
|
-
|
|
2481
2211
|
case ToggleButtonKeyDownEnd:
|
|
2482
2212
|
changes = {
|
|
2483
2213
|
highlightedIndex: getNextNonDisabledIndex(-1, props.items.length - 1, props.items.length, action.getItemNodeFromIndex, false),
|
|
2484
2214
|
isOpen: true
|
|
2485
2215
|
};
|
|
2486
2216
|
break;
|
|
2487
|
-
|
|
2488
2217
|
case ToggleButtonKeyDownPageUp:
|
|
2489
2218
|
changes = {
|
|
2490
2219
|
highlightedIndex: getNextWrappingIndex(-10, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false)
|
|
2491
2220
|
};
|
|
2492
2221
|
break;
|
|
2493
|
-
|
|
2494
2222
|
case ToggleButtonKeyDownPageDown:
|
|
2495
2223
|
changes = {
|
|
2496
2224
|
highlightedIndex: getNextWrappingIndex(10, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false)
|
|
2497
2225
|
};
|
|
2498
2226
|
break;
|
|
2499
|
-
|
|
2500
2227
|
case ToggleButtonKeyDownEscape:
|
|
2501
2228
|
changes = {
|
|
2502
2229
|
isOpen: false,
|
|
2503
2230
|
highlightedIndex: -1
|
|
2504
2231
|
};
|
|
2505
2232
|
break;
|
|
2506
|
-
|
|
2507
2233
|
case ToggleButtonBlur:
|
|
2508
2234
|
changes = {
|
|
2509
2235
|
isOpen: false,
|
|
@@ -2513,33 +2239,30 @@ function downshiftSelectReducer(state, action) {
|
|
|
2513
2239
|
})
|
|
2514
2240
|
};
|
|
2515
2241
|
break;
|
|
2516
|
-
|
|
2517
2242
|
case FunctionSelectItem$1:
|
|
2518
2243
|
changes = {
|
|
2519
2244
|
selectedItem: action.selectedItem
|
|
2520
2245
|
};
|
|
2521
2246
|
break;
|
|
2522
|
-
|
|
2523
2247
|
default:
|
|
2524
2248
|
return downshiftCommonReducer(state, action, stateChangeTypes$2);
|
|
2525
2249
|
}
|
|
2526
|
-
|
|
2527
|
-
|
|
2250
|
+
return {
|
|
2251
|
+
...state,
|
|
2528
2252
|
...changes
|
|
2529
2253
|
};
|
|
2530
2254
|
}
|
|
2531
2255
|
/* eslint-enable complexity */
|
|
2532
2256
|
|
|
2533
2257
|
useSelect.stateChangeTypes = stateChangeTypes$2;
|
|
2534
|
-
|
|
2535
2258
|
function useSelect(userProps) {
|
|
2536
2259
|
if (userProps === void 0) {
|
|
2537
2260
|
userProps = {};
|
|
2538
2261
|
}
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2262
|
+
validatePropTypes$2(userProps, useSelect);
|
|
2263
|
+
// Props defaults and destructuring.
|
|
2264
|
+
const props = {
|
|
2265
|
+
...defaultProps$2,
|
|
2543
2266
|
...userProps
|
|
2544
2267
|
};
|
|
2545
2268
|
const {
|
|
@@ -2549,8 +2272,8 @@ function useSelect(userProps) {
|
|
|
2549
2272
|
itemToString,
|
|
2550
2273
|
getA11ySelectionMessage,
|
|
2551
2274
|
getA11yStatusMessage
|
|
2552
|
-
} = props;
|
|
2553
|
-
|
|
2275
|
+
} = props;
|
|
2276
|
+
// Initial state depending on controlled props.
|
|
2554
2277
|
const initialState = getInitialState$2(props);
|
|
2555
2278
|
const [state, dispatch] = useControlledReducer$1(downshiftSelectReducer, initialState, props);
|
|
2556
2279
|
const {
|
|
@@ -2558,27 +2281,30 @@ function useSelect(userProps) {
|
|
|
2558
2281
|
highlightedIndex,
|
|
2559
2282
|
selectedItem,
|
|
2560
2283
|
inputValue
|
|
2561
|
-
} = state;
|
|
2284
|
+
} = state;
|
|
2562
2285
|
|
|
2286
|
+
// Element efs.
|
|
2563
2287
|
const toggleButtonRef = react.useRef(null);
|
|
2564
2288
|
const menuRef = react.useRef(null);
|
|
2565
|
-
const itemRefs = react.useRef({});
|
|
2566
|
-
|
|
2567
|
-
const clearTimeoutRef = react.useRef(null);
|
|
2568
|
-
|
|
2569
|
-
const elementIds = useElementIds(props);
|
|
2570
|
-
|
|
2289
|
+
const itemRefs = react.useRef({});
|
|
2290
|
+
// used to keep the inputValue clearTimeout object between renders.
|
|
2291
|
+
const clearTimeoutRef = react.useRef(null);
|
|
2292
|
+
// prevent id re-generation between renders.
|
|
2293
|
+
const elementIds = useElementIds(props);
|
|
2294
|
+
// used to keep track of how many items we had on previous cycle.
|
|
2571
2295
|
const previousResultCountRef = react.useRef();
|
|
2572
|
-
const isInitialMountRef = react.useRef(true);
|
|
2573
|
-
|
|
2296
|
+
const isInitialMountRef = react.useRef(true);
|
|
2297
|
+
// utility callback to get item element.
|
|
2574
2298
|
const latest = useLatestRef({
|
|
2575
2299
|
state,
|
|
2576
2300
|
props
|
|
2577
|
-
});
|
|
2301
|
+
});
|
|
2578
2302
|
|
|
2579
|
-
|
|
2580
|
-
|
|
2303
|
+
// Some utils.
|
|
2304
|
+
const getItemNodeFromIndex = react.useCallback(index => itemRefs.current[elementIds.getItemId(index)], [elementIds]);
|
|
2581
2305
|
|
|
2306
|
+
// Effects.
|
|
2307
|
+
// Sets a11y status message on changes in state.
|
|
2582
2308
|
useA11yMessageSetter(getA11yStatusMessage, [isOpen, highlightedIndex, inputValue, items], {
|
|
2583
2309
|
isInitialMount: isInitialMountRef.current,
|
|
2584
2310
|
previousResultCount: previousResultCountRef.current,
|
|
@@ -2586,8 +2312,8 @@ function useSelect(userProps) {
|
|
|
2586
2312
|
environment,
|
|
2587
2313
|
itemToString,
|
|
2588
2314
|
...state
|
|
2589
|
-
});
|
|
2590
|
-
|
|
2315
|
+
});
|
|
2316
|
+
// Sets a11y status message on changes in selectedItem.
|
|
2591
2317
|
useA11yMessageSetter(getA11ySelectionMessage, [selectedItem], {
|
|
2592
2318
|
isInitialMount: isInitialMountRef.current,
|
|
2593
2319
|
previousResultCount: previousResultCountRef.current,
|
|
@@ -2595,8 +2321,8 @@ function useSelect(userProps) {
|
|
|
2595
2321
|
environment,
|
|
2596
2322
|
itemToString,
|
|
2597
2323
|
...state
|
|
2598
|
-
});
|
|
2599
|
-
|
|
2324
|
+
});
|
|
2325
|
+
// Scroll on highlighted item if change comes from keyboard.
|
|
2600
2326
|
const shouldScrollRef = useScrollIntoView({
|
|
2601
2327
|
menuElement: menuRef.current,
|
|
2602
2328
|
highlightedIndex,
|
|
@@ -2604,8 +2330,9 @@ function useSelect(userProps) {
|
|
|
2604
2330
|
itemRefs,
|
|
2605
2331
|
scrollIntoView,
|
|
2606
2332
|
getItemNodeFromIndex
|
|
2607
|
-
});
|
|
2333
|
+
});
|
|
2608
2334
|
|
|
2335
|
+
// Sets cleanup for the keysSoFar callback, debounded after 500ms.
|
|
2609
2336
|
react.useEffect(() => {
|
|
2610
2337
|
// init the clean function here as we need access to dispatch.
|
|
2611
2338
|
clearTimeoutRef.current = debounce(outerDispatch => {
|
|
@@ -2613,18 +2340,19 @@ function useSelect(userProps) {
|
|
|
2613
2340
|
type: FunctionSetInputValue$1,
|
|
2614
2341
|
inputValue: ''
|
|
2615
2342
|
});
|
|
2616
|
-
}, 500);
|
|
2343
|
+
}, 500);
|
|
2617
2344
|
|
|
2345
|
+
// Cancel any pending debounced calls on mount
|
|
2618
2346
|
return () => {
|
|
2619
2347
|
clearTimeoutRef.current.cancel();
|
|
2620
2348
|
};
|
|
2621
|
-
}, []);
|
|
2349
|
+
}, []);
|
|
2622
2350
|
|
|
2351
|
+
// Invokes the keysSoFar callback set up above.
|
|
2623
2352
|
react.useEffect(() => {
|
|
2624
2353
|
if (!inputValue) {
|
|
2625
2354
|
return;
|
|
2626
2355
|
}
|
|
2627
|
-
|
|
2628
2356
|
clearTimeoutRef.current(dispatch);
|
|
2629
2357
|
}, [dispatch, inputValue]);
|
|
2630
2358
|
useControlPropsValidator({
|
|
@@ -2636,27 +2364,27 @@ function useSelect(userProps) {
|
|
|
2636
2364
|
if (isInitialMountRef.current) {
|
|
2637
2365
|
return;
|
|
2638
2366
|
}
|
|
2639
|
-
|
|
2640
2367
|
previousResultCountRef.current = items.length;
|
|
2641
|
-
});
|
|
2642
|
-
|
|
2368
|
+
});
|
|
2369
|
+
// Add mouse/touch events to document.
|
|
2643
2370
|
const mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [menuRef, toggleButtonRef], environment, () => {
|
|
2644
2371
|
dispatch({
|
|
2645
2372
|
type: ToggleButtonBlur
|
|
2646
2373
|
});
|
|
2647
2374
|
});
|
|
2648
|
-
const setGetterPropCallInfo = useGetterPropsCalledChecker('getMenuProps', 'getToggleButtonProps');
|
|
2649
|
-
|
|
2375
|
+
const setGetterPropCallInfo = useGetterPropsCalledChecker('getMenuProps', 'getToggleButtonProps');
|
|
2376
|
+
// Make initial ref false.
|
|
2650
2377
|
react.useEffect(() => {
|
|
2651
2378
|
isInitialMountRef.current = false;
|
|
2652
|
-
}, []);
|
|
2653
|
-
|
|
2379
|
+
}, []);
|
|
2380
|
+
// Reset itemRefs on close.
|
|
2654
2381
|
react.useEffect(() => {
|
|
2655
2382
|
if (!isOpen) {
|
|
2656
2383
|
itemRefs.current = {};
|
|
2657
2384
|
}
|
|
2658
|
-
}, [isOpen]);
|
|
2385
|
+
}, [isOpen]);
|
|
2659
2386
|
|
|
2387
|
+
// Event handler functions.
|
|
2660
2388
|
const toggleButtonKeyDownHandlers = react.useMemo(() => ({
|
|
2661
2389
|
ArrowDown(event) {
|
|
2662
2390
|
event.preventDefault();
|
|
@@ -2666,7 +2394,6 @@ function useSelect(userProps) {
|
|
|
2666
2394
|
altKey: event.altKey
|
|
2667
2395
|
});
|
|
2668
2396
|
},
|
|
2669
|
-
|
|
2670
2397
|
ArrowUp(event) {
|
|
2671
2398
|
event.preventDefault();
|
|
2672
2399
|
dispatch({
|
|
@@ -2675,7 +2402,6 @@ function useSelect(userProps) {
|
|
|
2675
2402
|
altKey: event.altKey
|
|
2676
2403
|
});
|
|
2677
2404
|
},
|
|
2678
|
-
|
|
2679
2405
|
Home(event) {
|
|
2680
2406
|
event.preventDefault();
|
|
2681
2407
|
dispatch({
|
|
@@ -2683,7 +2409,6 @@ function useSelect(userProps) {
|
|
|
2683
2409
|
getItemNodeFromIndex
|
|
2684
2410
|
});
|
|
2685
2411
|
},
|
|
2686
|
-
|
|
2687
2412
|
End(event) {
|
|
2688
2413
|
event.preventDefault();
|
|
2689
2414
|
dispatch({
|
|
@@ -2691,7 +2416,6 @@ function useSelect(userProps) {
|
|
|
2691
2416
|
getItemNodeFromIndex
|
|
2692
2417
|
});
|
|
2693
2418
|
},
|
|
2694
|
-
|
|
2695
2419
|
Escape() {
|
|
2696
2420
|
if (latest.current.state.isOpen) {
|
|
2697
2421
|
dispatch({
|
|
@@ -2699,7 +2423,6 @@ function useSelect(userProps) {
|
|
|
2699
2423
|
});
|
|
2700
2424
|
}
|
|
2701
2425
|
},
|
|
2702
|
-
|
|
2703
2426
|
Enter(event) {
|
|
2704
2427
|
if (latest.current.state.isOpen) {
|
|
2705
2428
|
event.preventDefault();
|
|
@@ -2708,7 +2431,6 @@ function useSelect(userProps) {
|
|
|
2708
2431
|
});
|
|
2709
2432
|
}
|
|
2710
2433
|
},
|
|
2711
|
-
|
|
2712
2434
|
PageUp(event) {
|
|
2713
2435
|
if (latest.current.state.isOpen) {
|
|
2714
2436
|
event.preventDefault();
|
|
@@ -2718,7 +2440,6 @@ function useSelect(userProps) {
|
|
|
2718
2440
|
});
|
|
2719
2441
|
}
|
|
2720
2442
|
},
|
|
2721
|
-
|
|
2722
2443
|
PageDown(event) {
|
|
2723
2444
|
if (latest.current.state.isOpen) {
|
|
2724
2445
|
event.preventDefault();
|
|
@@ -2728,7 +2449,6 @@ function useSelect(userProps) {
|
|
|
2728
2449
|
});
|
|
2729
2450
|
}
|
|
2730
2451
|
},
|
|
2731
|
-
|
|
2732
2452
|
' '(event) {
|
|
2733
2453
|
if (latest.current.state.isOpen) {
|
|
2734
2454
|
event.preventDefault();
|
|
@@ -2737,9 +2457,9 @@ function useSelect(userProps) {
|
|
|
2737
2457
|
});
|
|
2738
2458
|
}
|
|
2739
2459
|
}
|
|
2460
|
+
}), [dispatch, getItemNodeFromIndex, latest]);
|
|
2740
2461
|
|
|
2741
|
-
|
|
2742
|
-
|
|
2462
|
+
// Action functions.
|
|
2743
2463
|
const toggleMenu = react.useCallback(() => {
|
|
2744
2464
|
dispatch({
|
|
2745
2465
|
type: FunctionToggleMenu$1
|
|
@@ -2777,8 +2497,8 @@ function useSelect(userProps) {
|
|
|
2777
2497
|
type: FunctionSetInputValue$1,
|
|
2778
2498
|
inputValue: newInputValue
|
|
2779
2499
|
});
|
|
2780
|
-
}, [dispatch]);
|
|
2781
|
-
|
|
2500
|
+
}, [dispatch]);
|
|
2501
|
+
// Getter functions.
|
|
2782
2502
|
const getLabelProps = react.useCallback(labelProps => ({
|
|
2783
2503
|
id: elementIds.labelId,
|
|
2784
2504
|
htmlFor: elementIds.toggleButtonId,
|
|
@@ -2796,13 +2516,11 @@ function useSelect(userProps) {
|
|
|
2796
2516
|
let {
|
|
2797
2517
|
suppressRefError = false
|
|
2798
2518
|
} = _temp2 === void 0 ? {} : _temp2;
|
|
2799
|
-
|
|
2800
2519
|
const menuHandleMouseLeave = () => {
|
|
2801
2520
|
dispatch({
|
|
2802
2521
|
type: MenuMouseLeave$1
|
|
2803
2522
|
});
|
|
2804
2523
|
};
|
|
2805
|
-
|
|
2806
2524
|
setGetterPropCallInfo('getMenuProps', suppressRefError, refKey, menuRef);
|
|
2807
2525
|
return {
|
|
2808
2526
|
[refKey]: handleRefs(ref, menuNode => {
|
|
@@ -2829,13 +2547,11 @@ function useSelect(userProps) {
|
|
|
2829
2547
|
suppressRefError = false
|
|
2830
2548
|
} = _temp4 === void 0 ? {} : _temp4;
|
|
2831
2549
|
const latestState = latest.current.state;
|
|
2832
|
-
|
|
2833
2550
|
const toggleButtonHandleClick = () => {
|
|
2834
2551
|
dispatch({
|
|
2835
2552
|
type: ToggleButtonClick$1
|
|
2836
2553
|
});
|
|
2837
2554
|
};
|
|
2838
|
-
|
|
2839
2555
|
const toggleButtonHandleBlur = () => {
|
|
2840
2556
|
if (latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
|
|
2841
2557
|
dispatch({
|
|
@@ -2843,10 +2559,8 @@ function useSelect(userProps) {
|
|
|
2843
2559
|
});
|
|
2844
2560
|
}
|
|
2845
2561
|
};
|
|
2846
|
-
|
|
2847
2562
|
const toggleButtonHandleKeyDown = event => {
|
|
2848
2563
|
const key = normalizeArrowKey(event);
|
|
2849
|
-
|
|
2850
2564
|
if (key && toggleButtonKeyDownHandlers[key]) {
|
|
2851
2565
|
toggleButtonKeyDownHandlers[key](event);
|
|
2852
2566
|
} else if (isAcceptedCharacterKey(key)) {
|
|
@@ -2857,7 +2571,6 @@ function useSelect(userProps) {
|
|
|
2857
2571
|
});
|
|
2858
2572
|
}
|
|
2859
2573
|
};
|
|
2860
|
-
|
|
2861
2574
|
const toggleProps = {
|
|
2862
2575
|
[refKey]: handleRefs(ref, toggleButtonNode => {
|
|
2863
2576
|
toggleButtonRef.current = toggleButtonNode;
|
|
@@ -2873,12 +2586,10 @@ function useSelect(userProps) {
|
|
|
2873
2586
|
onBlur: callAllEventHandlers(onBlur, toggleButtonHandleBlur),
|
|
2874
2587
|
...rest
|
|
2875
2588
|
};
|
|
2876
|
-
|
|
2877
2589
|
if (!rest.disabled) {
|
|
2878
2590
|
toggleProps.onClick = callAllEventHandlers(onClick, toggleButtonHandleClick);
|
|
2879
2591
|
toggleProps.onKeyDown = callAllEventHandlers(onKeyDown, toggleButtonHandleKeyDown);
|
|
2880
2592
|
}
|
|
2881
|
-
|
|
2882
2593
|
setGetterPropCallInfo('getToggleButtonProps', suppressRefError, refKey, toggleButtonRef);
|
|
2883
2594
|
return toggleProps;
|
|
2884
2595
|
}, [latest, elementIds, setGetterPropCallInfo, dispatch, mouseAndTouchTrackersRef, toggleButtonKeyDownHandlers, getItemNodeFromIndex]);
|
|
@@ -2899,12 +2610,10 @@ function useSelect(userProps) {
|
|
|
2899
2610
|
} = latest.current;
|
|
2900
2611
|
const item = itemProp ?? items[indexProp];
|
|
2901
2612
|
const index = getItemIndex(indexProp, item, latestProps.items);
|
|
2902
|
-
|
|
2903
2613
|
const itemHandleMouseMove = () => {
|
|
2904
2614
|
if (index === latestState.highlightedIndex) {
|
|
2905
2615
|
return;
|
|
2906
2616
|
}
|
|
2907
|
-
|
|
2908
2617
|
shouldScrollRef.current = false;
|
|
2909
2618
|
dispatch({
|
|
2910
2619
|
type: ItemMouseMove$1,
|
|
@@ -2912,20 +2621,16 @@ function useSelect(userProps) {
|
|
|
2912
2621
|
disabled
|
|
2913
2622
|
});
|
|
2914
2623
|
};
|
|
2915
|
-
|
|
2916
2624
|
const itemHandleClick = () => {
|
|
2917
2625
|
dispatch({
|
|
2918
2626
|
type: ItemClick$1,
|
|
2919
2627
|
index
|
|
2920
2628
|
});
|
|
2921
2629
|
};
|
|
2922
|
-
|
|
2923
2630
|
const itemIndex = getItemIndex(index, item, latestProps.items);
|
|
2924
|
-
|
|
2925
2631
|
if (itemIndex < 0) {
|
|
2926
2632
|
throw new Error('Pass either item or item index in getItemProps!');
|
|
2927
2633
|
}
|
|
2928
|
-
|
|
2929
2634
|
const itemProps = {
|
|
2930
2635
|
disabled,
|
|
2931
2636
|
role: 'option',
|
|
@@ -2938,11 +2643,9 @@ function useSelect(userProps) {
|
|
|
2938
2643
|
}),
|
|
2939
2644
|
...rest
|
|
2940
2645
|
};
|
|
2941
|
-
|
|
2942
2646
|
if (!disabled) {
|
|
2943
2647
|
itemProps.onClick = callAllEventHandlers(onClick, itemHandleClick);
|
|
2944
2648
|
}
|
|
2945
|
-
|
|
2946
2649
|
itemProps.onMouseMove = callAllEventHandlers(onMouseMove, itemHandleMouseMove);
|
|
2947
2650
|
return itemProps;
|
|
2948
2651
|
}, [latest, items, selectedItem, elementIds, shouldScrollRef, dispatch]);
|
|
@@ -3027,16 +2730,14 @@ function getInitialState$1(props) {
|
|
|
3027
2730
|
let {
|
|
3028
2731
|
inputValue
|
|
3029
2732
|
} = initialState;
|
|
3030
|
-
|
|
3031
2733
|
if (inputValue === '' && selectedItem && props.defaultInputValue === undefined && props.initialInputValue === undefined && props.inputValue === undefined) {
|
|
3032
2734
|
inputValue = props.itemToString(selectedItem);
|
|
3033
2735
|
}
|
|
3034
|
-
|
|
3035
|
-
|
|
2736
|
+
return {
|
|
2737
|
+
...initialState,
|
|
3036
2738
|
inputValue
|
|
3037
2739
|
};
|
|
3038
2740
|
}
|
|
3039
|
-
|
|
3040
2741
|
const propTypes$1 = {
|
|
3041
2742
|
items: PropTypes__default["default"].array.isRequired,
|
|
3042
2743
|
itemToString: PropTypes__default["default"].func,
|
|
@@ -3076,6 +2777,7 @@ const propTypes$1 = {
|
|
|
3076
2777
|
})
|
|
3077
2778
|
})
|
|
3078
2779
|
};
|
|
2780
|
+
|
|
3079
2781
|
/**
|
|
3080
2782
|
* The useCombobox version of useControlledReducer, which also
|
|
3081
2783
|
* checks if the controlled prop selectedItem changed between
|
|
@@ -3088,11 +2790,11 @@ const propTypes$1 = {
|
|
|
3088
2790
|
* @param {Object} props The hook props.
|
|
3089
2791
|
* @returns {Array} An array with the state and an action dispatcher.
|
|
3090
2792
|
*/
|
|
3091
|
-
|
|
3092
2793
|
function useControlledReducer(reducer, initialState, props) {
|
|
3093
2794
|
const previousSelectedItemRef = react.useRef();
|
|
3094
|
-
const [state, dispatch] = useEnhancedReducer(reducer, initialState, props);
|
|
2795
|
+
const [state, dispatch] = useEnhancedReducer(reducer, initialState, props);
|
|
3095
2796
|
|
|
2797
|
+
// ToDo: if needed, make same approach as selectedItemChanged from Downshift.
|
|
3096
2798
|
react.useEffect(() => {
|
|
3097
2799
|
if (isControlledProp(props, 'selectedItem')) {
|
|
3098
2800
|
if (previousSelectedItemRef.current !== props.selectedItem) {
|
|
@@ -3101,29 +2803,26 @@ function useControlledReducer(reducer, initialState, props) {
|
|
|
3101
2803
|
inputValue: props.itemToString(props.selectedItem)
|
|
3102
2804
|
});
|
|
3103
2805
|
}
|
|
3104
|
-
|
|
3105
2806
|
previousSelectedItemRef.current = state.selectedItem === previousSelectedItemRef.current ? props.selectedItem : state.selectedItem;
|
|
3106
2807
|
}
|
|
3107
2808
|
});
|
|
3108
2809
|
return [getState(state, props), dispatch];
|
|
3109
|
-
}
|
|
3110
|
-
|
|
2810
|
+
}
|
|
3111
2811
|
|
|
2812
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
3112
2813
|
let validatePropTypes$1 = noop;
|
|
3113
2814
|
/* istanbul ignore next */
|
|
3114
|
-
|
|
3115
2815
|
if (process.env.NODE_ENV !== 'production') {
|
|
3116
2816
|
validatePropTypes$1 = (options, caller) => {
|
|
3117
2817
|
PropTypes__default["default"].checkPropTypes(propTypes$1, options, 'prop', caller.name);
|
|
3118
2818
|
};
|
|
3119
2819
|
}
|
|
3120
|
-
|
|
3121
|
-
|
|
2820
|
+
const defaultProps$1 = {
|
|
2821
|
+
...defaultProps$3,
|
|
3122
2822
|
getA11yStatusMessage: getA11yStatusMessage$1
|
|
3123
2823
|
};
|
|
3124
2824
|
|
|
3125
2825
|
/* eslint-disable complexity */
|
|
3126
|
-
|
|
3127
2826
|
function downshiftUseComboboxReducer(state, action) {
|
|
3128
2827
|
const {
|
|
3129
2828
|
type,
|
|
@@ -3131,7 +2830,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3131
2830
|
altKey
|
|
3132
2831
|
} = action;
|
|
3133
2832
|
let changes;
|
|
3134
|
-
|
|
3135
2833
|
switch (type) {
|
|
3136
2834
|
case ItemClick:
|
|
3137
2835
|
changes = {
|
|
@@ -3141,7 +2839,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3141
2839
|
inputValue: props.itemToString(props.items[action.index])
|
|
3142
2840
|
};
|
|
3143
2841
|
break;
|
|
3144
|
-
|
|
3145
2842
|
case InputKeyDownArrowDown:
|
|
3146
2843
|
if (state.isOpen) {
|
|
3147
2844
|
changes = {
|
|
@@ -3153,9 +2850,7 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3153
2850
|
isOpen: props.items.length >= 0
|
|
3154
2851
|
};
|
|
3155
2852
|
}
|
|
3156
|
-
|
|
3157
2853
|
break;
|
|
3158
|
-
|
|
3159
2854
|
case InputKeyDownArrowUp:
|
|
3160
2855
|
if (state.isOpen) {
|
|
3161
2856
|
if (altKey) {
|
|
@@ -3178,9 +2873,7 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3178
2873
|
isOpen: props.items.length >= 0
|
|
3179
2874
|
};
|
|
3180
2875
|
}
|
|
3181
|
-
|
|
3182
2876
|
break;
|
|
3183
|
-
|
|
3184
2877
|
case InputKeyDownEnter:
|
|
3185
2878
|
changes = {
|
|
3186
2879
|
isOpen: getDefaultValue$1(props, 'isOpen'),
|
|
@@ -3191,7 +2884,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3191
2884
|
})
|
|
3192
2885
|
};
|
|
3193
2886
|
break;
|
|
3194
|
-
|
|
3195
2887
|
case InputKeyDownEscape:
|
|
3196
2888
|
changes = {
|
|
3197
2889
|
isOpen: false,
|
|
@@ -3202,31 +2894,26 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3202
2894
|
})
|
|
3203
2895
|
};
|
|
3204
2896
|
break;
|
|
3205
|
-
|
|
3206
2897
|
case InputKeyDownPageUp:
|
|
3207
2898
|
changes = {
|
|
3208
2899
|
highlightedIndex: getNextWrappingIndex(-10, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false)
|
|
3209
2900
|
};
|
|
3210
2901
|
break;
|
|
3211
|
-
|
|
3212
2902
|
case InputKeyDownPageDown:
|
|
3213
2903
|
changes = {
|
|
3214
2904
|
highlightedIndex: getNextWrappingIndex(10, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false)
|
|
3215
2905
|
};
|
|
3216
2906
|
break;
|
|
3217
|
-
|
|
3218
2907
|
case InputKeyDownHome:
|
|
3219
2908
|
changes = {
|
|
3220
2909
|
highlightedIndex: getNextNonDisabledIndex(1, 0, props.items.length, action.getItemNodeFromIndex, false)
|
|
3221
2910
|
};
|
|
3222
2911
|
break;
|
|
3223
|
-
|
|
3224
2912
|
case InputKeyDownEnd:
|
|
3225
2913
|
changes = {
|
|
3226
2914
|
highlightedIndex: getNextNonDisabledIndex(-1, props.items.length - 1, props.items.length, action.getItemNodeFromIndex, false)
|
|
3227
2915
|
};
|
|
3228
2916
|
break;
|
|
3229
|
-
|
|
3230
2917
|
case InputBlur:
|
|
3231
2918
|
changes = {
|
|
3232
2919
|
isOpen: false,
|
|
@@ -3237,7 +2924,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3237
2924
|
})
|
|
3238
2925
|
};
|
|
3239
2926
|
break;
|
|
3240
|
-
|
|
3241
2927
|
case InputChange:
|
|
3242
2928
|
changes = {
|
|
3243
2929
|
isOpen: true,
|
|
@@ -3245,32 +2931,28 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3245
2931
|
inputValue: action.inputValue
|
|
3246
2932
|
};
|
|
3247
2933
|
break;
|
|
3248
|
-
|
|
3249
2934
|
case InputFocus:
|
|
3250
2935
|
changes = {
|
|
3251
2936
|
isOpen: true,
|
|
3252
2937
|
highlightedIndex: getHighlightedIndexOnOpen(props, state, 0)
|
|
3253
2938
|
};
|
|
3254
2939
|
break;
|
|
3255
|
-
|
|
3256
2940
|
case FunctionSelectItem:
|
|
3257
2941
|
changes = {
|
|
3258
2942
|
selectedItem: action.selectedItem,
|
|
3259
2943
|
inputValue: props.itemToString(action.selectedItem)
|
|
3260
2944
|
};
|
|
3261
2945
|
break;
|
|
3262
|
-
|
|
3263
2946
|
case ControlledPropUpdatedSelectedItem:
|
|
3264
2947
|
changes = {
|
|
3265
2948
|
inputValue: action.inputValue
|
|
3266
2949
|
};
|
|
3267
2950
|
break;
|
|
3268
|
-
|
|
3269
2951
|
default:
|
|
3270
2952
|
return downshiftCommonReducer(state, action, stateChangeTypes$1);
|
|
3271
2953
|
}
|
|
3272
|
-
|
|
3273
|
-
|
|
2954
|
+
return {
|
|
2955
|
+
...state,
|
|
3274
2956
|
...changes
|
|
3275
2957
|
};
|
|
3276
2958
|
}
|
|
@@ -3278,15 +2960,14 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3278
2960
|
|
|
3279
2961
|
/* eslint-disable max-statements */
|
|
3280
2962
|
useCombobox.stateChangeTypes = stateChangeTypes$1;
|
|
3281
|
-
|
|
3282
2963
|
function useCombobox(userProps) {
|
|
3283
2964
|
if (userProps === void 0) {
|
|
3284
2965
|
userProps = {};
|
|
3285
2966
|
}
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
2967
|
+
validatePropTypes$1(userProps, useCombobox);
|
|
2968
|
+
// Props defaults and destructuring.
|
|
2969
|
+
const props = {
|
|
2970
|
+
...defaultProps$1,
|
|
3290
2971
|
...userProps
|
|
3291
2972
|
};
|
|
3292
2973
|
const {
|
|
@@ -3298,8 +2979,8 @@ function useCombobox(userProps) {
|
|
|
3298
2979
|
getA11yStatusMessage,
|
|
3299
2980
|
getA11ySelectionMessage,
|
|
3300
2981
|
itemToString
|
|
3301
|
-
} = props;
|
|
3302
|
-
|
|
2982
|
+
} = props;
|
|
2983
|
+
// Initial state depending on controlled props.
|
|
3303
2984
|
const initialState = getInitialState$1(props);
|
|
3304
2985
|
const [state, dispatch] = useControlledReducer(downshiftUseComboboxReducer, initialState, props);
|
|
3305
2986
|
const {
|
|
@@ -3307,25 +2988,27 @@ function useCombobox(userProps) {
|
|
|
3307
2988
|
highlightedIndex,
|
|
3308
2989
|
selectedItem,
|
|
3309
2990
|
inputValue
|
|
3310
|
-
} = state;
|
|
2991
|
+
} = state;
|
|
3311
2992
|
|
|
2993
|
+
// Element refs.
|
|
3312
2994
|
const menuRef = react.useRef(null);
|
|
3313
2995
|
const itemRefs = react.useRef({});
|
|
3314
2996
|
const inputRef = react.useRef(null);
|
|
3315
2997
|
const toggleButtonRef = react.useRef(null);
|
|
3316
|
-
const isInitialMountRef = react.useRef(true);
|
|
3317
|
-
|
|
3318
|
-
const elementIds = useElementIds(props);
|
|
3319
|
-
|
|
3320
|
-
const previousResultCountRef = react.useRef();
|
|
3321
|
-
|
|
2998
|
+
const isInitialMountRef = react.useRef(true);
|
|
2999
|
+
// prevent id re-generation between renders.
|
|
3000
|
+
const elementIds = useElementIds(props);
|
|
3001
|
+
// used to keep track of how many items we had on previous cycle.
|
|
3002
|
+
const previousResultCountRef = react.useRef();
|
|
3003
|
+
// utility callback to get item element.
|
|
3322
3004
|
const latest = useLatestRef({
|
|
3323
3005
|
state,
|
|
3324
3006
|
props
|
|
3325
3007
|
});
|
|
3326
|
-
const getItemNodeFromIndex = react.useCallback(index => itemRefs.current[elementIds.getItemId(index)], [elementIds]);
|
|
3327
|
-
// Sets a11y status message on changes in state.
|
|
3008
|
+
const getItemNodeFromIndex = react.useCallback(index => itemRefs.current[elementIds.getItemId(index)], [elementIds]);
|
|
3328
3009
|
|
|
3010
|
+
// Effects.
|
|
3011
|
+
// Sets a11y status message on changes in state.
|
|
3329
3012
|
useA11yMessageSetter(getA11yStatusMessage, [isOpen, highlightedIndex, inputValue, items], {
|
|
3330
3013
|
isInitialMount: isInitialMountRef.current,
|
|
3331
3014
|
previousResultCount: previousResultCountRef.current,
|
|
@@ -3333,8 +3016,8 @@ function useCombobox(userProps) {
|
|
|
3333
3016
|
environment,
|
|
3334
3017
|
itemToString,
|
|
3335
3018
|
...state
|
|
3336
|
-
});
|
|
3337
|
-
|
|
3019
|
+
});
|
|
3020
|
+
// Sets a11y status message on changes in selectedItem.
|
|
3338
3021
|
useA11yMessageSetter(getA11ySelectionMessage, [selectedItem], {
|
|
3339
3022
|
isInitialMount: isInitialMountRef.current,
|
|
3340
3023
|
previousResultCount: previousResultCountRef.current,
|
|
@@ -3342,8 +3025,8 @@ function useCombobox(userProps) {
|
|
|
3342
3025
|
environment,
|
|
3343
3026
|
itemToString,
|
|
3344
3027
|
...state
|
|
3345
|
-
});
|
|
3346
|
-
|
|
3028
|
+
});
|
|
3029
|
+
// Scroll on highlighted item if change comes from keyboard.
|
|
3347
3030
|
const shouldScrollRef = useScrollIntoView({
|
|
3348
3031
|
menuElement: menuRef.current,
|
|
3349
3032
|
highlightedIndex,
|
|
@@ -3356,47 +3039,44 @@ function useCombobox(userProps) {
|
|
|
3356
3039
|
isInitialMount: isInitialMountRef.current,
|
|
3357
3040
|
props,
|
|
3358
3041
|
state
|
|
3359
|
-
});
|
|
3360
|
-
|
|
3042
|
+
});
|
|
3043
|
+
// Focus the input on first render if required.
|
|
3361
3044
|
react.useEffect(() => {
|
|
3362
3045
|
const focusOnOpen = initialIsOpen || defaultIsOpen || isOpen;
|
|
3363
|
-
|
|
3364
3046
|
if (focusOnOpen && inputRef.current) {
|
|
3365
3047
|
inputRef.current.focus();
|
|
3366
|
-
}
|
|
3367
|
-
|
|
3048
|
+
}
|
|
3049
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3368
3050
|
}, []);
|
|
3369
3051
|
react.useEffect(() => {
|
|
3370
3052
|
if (isInitialMountRef.current) {
|
|
3371
3053
|
return;
|
|
3372
3054
|
}
|
|
3373
|
-
|
|
3374
3055
|
previousResultCountRef.current = items.length;
|
|
3375
|
-
});
|
|
3376
|
-
|
|
3056
|
+
});
|
|
3057
|
+
// Add mouse/touch events to document.
|
|
3377
3058
|
const mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [inputRef, menuRef, toggleButtonRef], environment, () => {
|
|
3378
3059
|
dispatch({
|
|
3379
3060
|
type: InputBlur,
|
|
3380
3061
|
selectItem: false
|
|
3381
3062
|
});
|
|
3382
3063
|
});
|
|
3383
|
-
const setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getMenuProps');
|
|
3384
|
-
|
|
3064
|
+
const setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getMenuProps');
|
|
3065
|
+
// Make initial ref false.
|
|
3385
3066
|
react.useEffect(() => {
|
|
3386
3067
|
isInitialMountRef.current = false;
|
|
3387
|
-
}, []);
|
|
3388
|
-
|
|
3068
|
+
}, []);
|
|
3069
|
+
// Reset itemRefs on close.
|
|
3389
3070
|
react.useEffect(() => {
|
|
3390
3071
|
if (!isOpen) {
|
|
3391
3072
|
itemRefs.current = {};
|
|
3392
3073
|
} else if (document.activeElement !== inputRef.current) {
|
|
3393
3074
|
var _inputRef$current;
|
|
3394
|
-
|
|
3395
3075
|
inputRef == null ? void 0 : (_inputRef$current = inputRef.current) == null ? void 0 : _inputRef$current.focus();
|
|
3396
3076
|
}
|
|
3397
3077
|
}, [isOpen]);
|
|
3398
|
-
/* Event handler functions */
|
|
3399
3078
|
|
|
3079
|
+
/* Event handler functions */
|
|
3400
3080
|
const inputKeyDownHandlers = react.useMemo(() => ({
|
|
3401
3081
|
ArrowDown(event) {
|
|
3402
3082
|
event.preventDefault();
|
|
@@ -3406,7 +3086,6 @@ function useCombobox(userProps) {
|
|
|
3406
3086
|
getItemNodeFromIndex
|
|
3407
3087
|
});
|
|
3408
3088
|
},
|
|
3409
|
-
|
|
3410
3089
|
ArrowUp(event) {
|
|
3411
3090
|
event.preventDefault();
|
|
3412
3091
|
dispatch({
|
|
@@ -3415,34 +3094,28 @@ function useCombobox(userProps) {
|
|
|
3415
3094
|
getItemNodeFromIndex
|
|
3416
3095
|
});
|
|
3417
3096
|
},
|
|
3418
|
-
|
|
3419
3097
|
Home(event) {
|
|
3420
3098
|
if (!latest.current.state.isOpen) {
|
|
3421
3099
|
return;
|
|
3422
3100
|
}
|
|
3423
|
-
|
|
3424
3101
|
event.preventDefault();
|
|
3425
3102
|
dispatch({
|
|
3426
3103
|
type: InputKeyDownHome,
|
|
3427
3104
|
getItemNodeFromIndex
|
|
3428
3105
|
});
|
|
3429
3106
|
},
|
|
3430
|
-
|
|
3431
3107
|
End(event) {
|
|
3432
3108
|
if (!latest.current.state.isOpen) {
|
|
3433
3109
|
return;
|
|
3434
3110
|
}
|
|
3435
|
-
|
|
3436
3111
|
event.preventDefault();
|
|
3437
3112
|
dispatch({
|
|
3438
3113
|
type: InputKeyDownEnd,
|
|
3439
3114
|
getItemNodeFromIndex
|
|
3440
3115
|
});
|
|
3441
3116
|
},
|
|
3442
|
-
|
|
3443
3117
|
Escape(event) {
|
|
3444
3118
|
const latestState = latest.current.state;
|
|
3445
|
-
|
|
3446
3119
|
if (latestState.isOpen || latestState.inputValue || latestState.selectedItem || latestState.highlightedIndex > -1) {
|
|
3447
3120
|
event.preventDefault();
|
|
3448
3121
|
dispatch({
|
|
@@ -3450,22 +3123,19 @@ function useCombobox(userProps) {
|
|
|
3450
3123
|
});
|
|
3451
3124
|
}
|
|
3452
3125
|
},
|
|
3453
|
-
|
|
3454
3126
|
Enter(event) {
|
|
3455
|
-
const latestState = latest.current.state;
|
|
3456
|
-
|
|
3127
|
+
const latestState = latest.current.state;
|
|
3128
|
+
// if closed or no highlighted index, do nothing.
|
|
3457
3129
|
if (!latestState.isOpen || event.which === 229 // if IME composing, wait for next Enter keydown event.
|
|
3458
3130
|
) {
|
|
3459
3131
|
return;
|
|
3460
3132
|
}
|
|
3461
|
-
|
|
3462
3133
|
event.preventDefault();
|
|
3463
3134
|
dispatch({
|
|
3464
3135
|
type: InputKeyDownEnter,
|
|
3465
3136
|
getItemNodeFromIndex
|
|
3466
3137
|
});
|
|
3467
3138
|
},
|
|
3468
|
-
|
|
3469
3139
|
PageUp(event) {
|
|
3470
3140
|
if (latest.current.state.isOpen) {
|
|
3471
3141
|
event.preventDefault();
|
|
@@ -3475,7 +3145,6 @@ function useCombobox(userProps) {
|
|
|
3475
3145
|
});
|
|
3476
3146
|
}
|
|
3477
3147
|
},
|
|
3478
|
-
|
|
3479
3148
|
PageDown(event) {
|
|
3480
3149
|
if (latest.current.state.isOpen) {
|
|
3481
3150
|
event.preventDefault();
|
|
@@ -3485,9 +3154,9 @@ function useCombobox(userProps) {
|
|
|
3485
3154
|
});
|
|
3486
3155
|
}
|
|
3487
3156
|
}
|
|
3157
|
+
}), [dispatch, latest, getItemNodeFromIndex]);
|
|
3488
3158
|
|
|
3489
|
-
|
|
3490
|
-
|
|
3159
|
+
// Getter props.
|
|
3491
3160
|
const getLabelProps = react.useCallback(labelProps => ({
|
|
3492
3161
|
id: elementIds.labelId,
|
|
3493
3162
|
htmlFor: elementIds.inputId,
|
|
@@ -3537,19 +3206,15 @@ function useCombobox(userProps) {
|
|
|
3537
3206
|
state: latestState
|
|
3538
3207
|
} = latest.current;
|
|
3539
3208
|
const itemIndex = getItemIndex(index, item, latestProps.items);
|
|
3540
|
-
|
|
3541
3209
|
if (itemIndex < 0) {
|
|
3542
3210
|
throw new Error('Pass either item or item index in getItemProps!');
|
|
3543
3211
|
}
|
|
3544
|
-
|
|
3545
3212
|
const onSelectKey = 'onClick';
|
|
3546
3213
|
const customClickHandler = onClick;
|
|
3547
|
-
|
|
3548
3214
|
const itemHandleMouseMove = () => {
|
|
3549
3215
|
if (index === latestState.highlightedIndex) {
|
|
3550
3216
|
return;
|
|
3551
3217
|
}
|
|
3552
|
-
|
|
3553
3218
|
shouldScrollRef.current = false;
|
|
3554
3219
|
dispatch({
|
|
3555
3220
|
type: ItemMouseMove,
|
|
@@ -3557,16 +3222,13 @@ function useCombobox(userProps) {
|
|
|
3557
3222
|
disabled
|
|
3558
3223
|
});
|
|
3559
3224
|
};
|
|
3560
|
-
|
|
3561
3225
|
const itemHandleClick = () => {
|
|
3562
3226
|
dispatch({
|
|
3563
3227
|
type: ItemClick,
|
|
3564
3228
|
index
|
|
3565
3229
|
});
|
|
3566
3230
|
};
|
|
3567
|
-
|
|
3568
3231
|
const itemHandleMouseDown = e => e.preventDefault();
|
|
3569
|
-
|
|
3570
3232
|
return {
|
|
3571
3233
|
[refKey]: handleRefs(ref, itemNode => {
|
|
3572
3234
|
if (itemNode) {
|
|
@@ -3594,13 +3256,11 @@ function useCombobox(userProps) {
|
|
|
3594
3256
|
...rest
|
|
3595
3257
|
} = _temp4 === void 0 ? {} : _temp4;
|
|
3596
3258
|
const latestState = latest.current.state;
|
|
3597
|
-
|
|
3598
3259
|
const toggleButtonHandleClick = () => {
|
|
3599
3260
|
dispatch({
|
|
3600
3261
|
type: ToggleButtonClick
|
|
3601
3262
|
});
|
|
3602
3263
|
};
|
|
3603
|
-
|
|
3604
3264
|
return {
|
|
3605
3265
|
[refKey]: handleRefs(ref, toggleButtonNode => {
|
|
3606
3266
|
toggleButtonRef.current = toggleButtonNode;
|
|
@@ -3609,7 +3269,8 @@ function useCombobox(userProps) {
|
|
|
3609
3269
|
'aria-expanded': latestState.isOpen,
|
|
3610
3270
|
id: elementIds.toggleButtonId,
|
|
3611
3271
|
tabIndex: -1,
|
|
3612
|
-
...(!rest.disabled && {
|
|
3272
|
+
...(!rest.disabled && {
|
|
3273
|
+
...({
|
|
3613
3274
|
onClick: callAllEventHandlers(onClick, toggleButtonHandleClick)
|
|
3614
3275
|
})
|
|
3615
3276
|
}),
|
|
@@ -3633,22 +3294,18 @@ function useCombobox(userProps) {
|
|
|
3633
3294
|
} = _temp6 === void 0 ? {} : _temp6;
|
|
3634
3295
|
setGetterPropCallInfo('getInputProps', suppressRefError, refKey, inputRef);
|
|
3635
3296
|
const latestState = latest.current.state;
|
|
3636
|
-
|
|
3637
3297
|
const inputHandleKeyDown = event => {
|
|
3638
3298
|
const key = normalizeArrowKey(event);
|
|
3639
|
-
|
|
3640
3299
|
if (key && inputKeyDownHandlers[key]) {
|
|
3641
3300
|
inputKeyDownHandlers[key](event);
|
|
3642
3301
|
}
|
|
3643
3302
|
};
|
|
3644
|
-
|
|
3645
3303
|
const inputHandleChange = event => {
|
|
3646
3304
|
dispatch({
|
|
3647
3305
|
type: InputChange,
|
|
3648
3306
|
inputValue: event.target.value
|
|
3649
3307
|
});
|
|
3650
3308
|
};
|
|
3651
|
-
|
|
3652
3309
|
const inputHandleBlur = () => {
|
|
3653
3310
|
/* istanbul ignore else */
|
|
3654
3311
|
if (latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
|
|
@@ -3658,7 +3315,6 @@ function useCombobox(userProps) {
|
|
|
3658
3315
|
});
|
|
3659
3316
|
}
|
|
3660
3317
|
};
|
|
3661
|
-
|
|
3662
3318
|
const inputHandleFocus = () => {
|
|
3663
3319
|
if (!latestState.isOpen) {
|
|
3664
3320
|
dispatch({
|
|
@@ -3666,12 +3322,10 @@ function useCombobox(userProps) {
|
|
|
3666
3322
|
});
|
|
3667
3323
|
}
|
|
3668
3324
|
};
|
|
3669
|
-
/* istanbul ignore next (preact) */
|
|
3670
|
-
|
|
3671
3325
|
|
|
3326
|
+
/* istanbul ignore next (preact) */
|
|
3672
3327
|
const onChangeKey = 'onChange';
|
|
3673
3328
|
let eventHandlers = {};
|
|
3674
|
-
|
|
3675
3329
|
if (!rest.disabled) {
|
|
3676
3330
|
eventHandlers = {
|
|
3677
3331
|
[onChangeKey]: callAllEventHandlers(onChange, onInput, inputHandleChange),
|
|
@@ -3680,7 +3334,6 @@ function useCombobox(userProps) {
|
|
|
3680
3334
|
onFocus: callAllEventHandlers(onFocus, inputHandleFocus)
|
|
3681
3335
|
};
|
|
3682
3336
|
}
|
|
3683
|
-
|
|
3684
3337
|
return {
|
|
3685
3338
|
[refKey]: handleRefs(ref, inputNode => {
|
|
3686
3339
|
inputRef.current = inputNode;
|
|
@@ -3699,8 +3352,9 @@ function useCombobox(userProps) {
|
|
|
3699
3352
|
...eventHandlers,
|
|
3700
3353
|
...rest
|
|
3701
3354
|
};
|
|
3702
|
-
}, [dispatch, inputKeyDownHandlers, latest, mouseAndTouchTrackersRef, setGetterPropCallInfo, elementIds]);
|
|
3355
|
+
}, [dispatch, inputKeyDownHandlers, latest, mouseAndTouchTrackersRef, setGetterPropCallInfo, elementIds]);
|
|
3703
3356
|
|
|
3357
|
+
// returns
|
|
3704
3358
|
const toggleMenu = react.useCallback(() => {
|
|
3705
3359
|
dispatch({
|
|
3706
3360
|
type: FunctionToggleMenu
|
|
@@ -3766,6 +3420,7 @@ const defaultStateValues = {
|
|
|
3766
3420
|
activeIndex: -1,
|
|
3767
3421
|
selectedItems: []
|
|
3768
3422
|
};
|
|
3423
|
+
|
|
3769
3424
|
/**
|
|
3770
3425
|
* Returns the initial value for a state key in the following order:
|
|
3771
3426
|
* 1. controlled prop, 2. initial prop, 3. default prop, 4. default
|
|
@@ -3775,10 +3430,10 @@ const defaultStateValues = {
|
|
|
3775
3430
|
* @param {string} propKey Props key to generate the value for.
|
|
3776
3431
|
* @returns {any} The initial value for that prop.
|
|
3777
3432
|
*/
|
|
3778
|
-
|
|
3779
3433
|
function getInitialValue(props, propKey) {
|
|
3780
3434
|
return getInitialValue$1(props, propKey, defaultStateValues);
|
|
3781
3435
|
}
|
|
3436
|
+
|
|
3782
3437
|
/**
|
|
3783
3438
|
* Returns the default value for a state key in the following order:
|
|
3784
3439
|
* 1. controlled prop, 2. default prop, 3. default value from Downshift.
|
|
@@ -3787,11 +3442,10 @@ function getInitialValue(props, propKey) {
|
|
|
3787
3442
|
* @param {string} propKey Props key to generate the value for.
|
|
3788
3443
|
* @returns {any} The initial value for that prop.
|
|
3789
3444
|
*/
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
3445
|
function getDefaultValue(props, propKey) {
|
|
3793
3446
|
return getDefaultValue$1(props, propKey, defaultStateValues);
|
|
3794
3447
|
}
|
|
3448
|
+
|
|
3795
3449
|
/**
|
|
3796
3450
|
* Gets the initial state based on the provided props. It uses initial, default
|
|
3797
3451
|
* and controlled props related to state in order to compute the initial value.
|
|
@@ -3799,8 +3453,6 @@ function getDefaultValue(props, propKey) {
|
|
|
3799
3453
|
* @param {Object} props Props passed to the hook.
|
|
3800
3454
|
* @returns {Object} The initial state.
|
|
3801
3455
|
*/
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
3456
|
function getInitialState(props) {
|
|
3805
3457
|
const activeIndex = getInitialValue(props, 'activeIndex');
|
|
3806
3458
|
const selectedItems = getInitialValue(props, 'selectedItems');
|
|
@@ -3809,6 +3461,7 @@ function getInitialState(props) {
|
|
|
3809
3461
|
selectedItems
|
|
3810
3462
|
};
|
|
3811
3463
|
}
|
|
3464
|
+
|
|
3812
3465
|
/**
|
|
3813
3466
|
* Returns true if dropdown keydown operation is permitted. Should not be
|
|
3814
3467
|
* allowed on keydown with modifier keys (ctrl, alt, shift, meta), on
|
|
@@ -3818,32 +3471,28 @@ function getInitialState(props) {
|
|
|
3818
3471
|
* @param {KeyboardEvent} event The event from keydown.
|
|
3819
3472
|
* @returns {boolean} Whether the operation is allowed.
|
|
3820
3473
|
*/
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
3474
|
function isKeyDownOperationPermitted(event) {
|
|
3824
3475
|
if (event.shiftKey || event.metaKey || event.ctrlKey || event.altKey) {
|
|
3825
3476
|
return false;
|
|
3826
3477
|
}
|
|
3827
|
-
|
|
3828
3478
|
const element = event.target;
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
element.value !== '' && (
|
|
3479
|
+
if (element instanceof HTMLInputElement &&
|
|
3480
|
+
// if element is a text input
|
|
3481
|
+
element.value !== '' && (
|
|
3482
|
+
// and we have text in it
|
|
3832
3483
|
// and cursor is either not at the start or is currently highlighting text.
|
|
3833
3484
|
element.selectionStart !== 0 || element.selectionEnd !== 0)) {
|
|
3834
3485
|
return false;
|
|
3835
3486
|
}
|
|
3836
|
-
|
|
3837
3487
|
return true;
|
|
3838
3488
|
}
|
|
3489
|
+
|
|
3839
3490
|
/**
|
|
3840
3491
|
* Returns a message to be added to aria-live region when item is removed.
|
|
3841
3492
|
*
|
|
3842
3493
|
* @param {Object} selectionParameters Parameters required to build the message.
|
|
3843
3494
|
* @returns {string} The a11y message.
|
|
3844
3495
|
*/
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
3496
|
function getA11yRemovalMessage(selectionParameters) {
|
|
3848
3497
|
const {
|
|
3849
3498
|
removedSelectedItem,
|
|
@@ -3851,7 +3500,6 @@ function getA11yRemovalMessage(selectionParameters) {
|
|
|
3851
3500
|
} = selectionParameters;
|
|
3852
3501
|
return `${itemToStringLocal(removedSelectedItem)} has been removed.`;
|
|
3853
3502
|
}
|
|
3854
|
-
|
|
3855
3503
|
const propTypes = {
|
|
3856
3504
|
selectedItems: PropTypes__default["default"].array,
|
|
3857
3505
|
initialSelectedItems: PropTypes__default["default"].array,
|
|
@@ -3883,11 +3531,11 @@ const defaultProps = {
|
|
|
3883
3531
|
getA11yRemovalMessage,
|
|
3884
3532
|
keyNavigationNext: 'ArrowRight',
|
|
3885
3533
|
keyNavigationPrevious: 'ArrowLeft'
|
|
3886
|
-
};
|
|
3534
|
+
};
|
|
3887
3535
|
|
|
3536
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
3888
3537
|
let validatePropTypes = noop;
|
|
3889
3538
|
/* istanbul ignore next */
|
|
3890
|
-
|
|
3891
3539
|
if (process.env.NODE_ENV !== 'production') {
|
|
3892
3540
|
validatePropTypes = (options, caller) => {
|
|
3893
3541
|
PropTypes__default["default"].checkPropTypes(propTypes, options, 'prop', caller.name);
|
|
@@ -3926,7 +3574,6 @@ var stateChangeTypes = /*#__PURE__*/Object.freeze({
|
|
|
3926
3574
|
});
|
|
3927
3575
|
|
|
3928
3576
|
/* eslint-disable complexity */
|
|
3929
|
-
|
|
3930
3577
|
function downshiftMultipleSelectionReducer(state, action) {
|
|
3931
3578
|
const {
|
|
3932
3579
|
type,
|
|
@@ -3939,37 +3586,31 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
3939
3586
|
selectedItems
|
|
3940
3587
|
} = state;
|
|
3941
3588
|
let changes;
|
|
3942
|
-
|
|
3943
3589
|
switch (type) {
|
|
3944
3590
|
case SelectedItemClick:
|
|
3945
3591
|
changes = {
|
|
3946
3592
|
activeIndex: index
|
|
3947
3593
|
};
|
|
3948
3594
|
break;
|
|
3949
|
-
|
|
3950
3595
|
case SelectedItemKeyDownNavigationPrevious:
|
|
3951
3596
|
changes = {
|
|
3952
3597
|
activeIndex: activeIndex - 1 < 0 ? 0 : activeIndex - 1
|
|
3953
3598
|
};
|
|
3954
3599
|
break;
|
|
3955
|
-
|
|
3956
3600
|
case SelectedItemKeyDownNavigationNext:
|
|
3957
3601
|
changes = {
|
|
3958
3602
|
activeIndex: activeIndex + 1 >= selectedItems.length ? -1 : activeIndex + 1
|
|
3959
3603
|
};
|
|
3960
3604
|
break;
|
|
3961
|
-
|
|
3962
3605
|
case SelectedItemKeyDownBackspace:
|
|
3963
3606
|
case SelectedItemKeyDownDelete:
|
|
3964
3607
|
{
|
|
3965
3608
|
let newActiveIndex = activeIndex;
|
|
3966
|
-
|
|
3967
3609
|
if (selectedItems.length === 1) {
|
|
3968
3610
|
newActiveIndex = -1;
|
|
3969
3611
|
} else if (activeIndex === selectedItems.length - 1) {
|
|
3970
3612
|
newActiveIndex = selectedItems.length - 2;
|
|
3971
3613
|
}
|
|
3972
|
-
|
|
3973
3614
|
changes = {
|
|
3974
3615
|
selectedItems: [...selectedItems.slice(0, activeIndex), ...selectedItems.slice(activeIndex + 1)],
|
|
3975
3616
|
...{
|
|
@@ -3978,52 +3619,43 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
3978
3619
|
};
|
|
3979
3620
|
break;
|
|
3980
3621
|
}
|
|
3981
|
-
|
|
3982
3622
|
case DropdownKeyDownNavigationPrevious:
|
|
3983
3623
|
changes = {
|
|
3984
3624
|
activeIndex: selectedItems.length - 1
|
|
3985
3625
|
};
|
|
3986
3626
|
break;
|
|
3987
|
-
|
|
3988
3627
|
case DropdownKeyDownBackspace:
|
|
3989
3628
|
changes = {
|
|
3990
3629
|
selectedItems: selectedItems.slice(0, selectedItems.length - 1)
|
|
3991
3630
|
};
|
|
3992
3631
|
break;
|
|
3993
|
-
|
|
3994
3632
|
case FunctionAddSelectedItem:
|
|
3995
3633
|
changes = {
|
|
3996
3634
|
selectedItems: [...selectedItems, selectedItem]
|
|
3997
3635
|
};
|
|
3998
3636
|
break;
|
|
3999
|
-
|
|
4000
3637
|
case DropdownClick:
|
|
4001
3638
|
changes = {
|
|
4002
3639
|
activeIndex: -1
|
|
4003
3640
|
};
|
|
4004
3641
|
break;
|
|
4005
|
-
|
|
4006
3642
|
case FunctionRemoveSelectedItem:
|
|
4007
3643
|
{
|
|
4008
3644
|
let newActiveIndex = activeIndex;
|
|
4009
3645
|
const selectedItemIndex = selectedItems.indexOf(selectedItem);
|
|
4010
|
-
|
|
4011
3646
|
if (selectedItemIndex >= 0) {
|
|
4012
3647
|
if (selectedItems.length === 1) {
|
|
4013
3648
|
newActiveIndex = -1;
|
|
4014
3649
|
} else if (selectedItemIndex === selectedItems.length - 1) {
|
|
4015
3650
|
newActiveIndex = selectedItems.length - 2;
|
|
4016
3651
|
}
|
|
4017
|
-
|
|
4018
3652
|
changes = {
|
|
4019
3653
|
selectedItems: [...selectedItems.slice(0, selectedItemIndex), ...selectedItems.slice(selectedItemIndex + 1)],
|
|
4020
3654
|
activeIndex: newActiveIndex
|
|
4021
3655
|
};
|
|
4022
3656
|
}
|
|
4023
|
-
|
|
4024
3657
|
break;
|
|
4025
3658
|
}
|
|
4026
|
-
|
|
4027
3659
|
case FunctionSetSelectedItems:
|
|
4028
3660
|
{
|
|
4029
3661
|
const {
|
|
@@ -4034,7 +3666,6 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
4034
3666
|
};
|
|
4035
3667
|
break;
|
|
4036
3668
|
}
|
|
4037
|
-
|
|
4038
3669
|
case FunctionSetActiveIndex:
|
|
4039
3670
|
{
|
|
4040
3671
|
const {
|
|
@@ -4045,33 +3676,30 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
4045
3676
|
};
|
|
4046
3677
|
break;
|
|
4047
3678
|
}
|
|
4048
|
-
|
|
4049
3679
|
case FunctionReset:
|
|
4050
3680
|
changes = {
|
|
4051
3681
|
activeIndex: getDefaultValue(props, 'activeIndex'),
|
|
4052
3682
|
selectedItems: getDefaultValue(props, 'selectedItems')
|
|
4053
3683
|
};
|
|
4054
3684
|
break;
|
|
4055
|
-
|
|
4056
3685
|
default:
|
|
4057
3686
|
throw new Error('Reducer called without proper action type.');
|
|
4058
3687
|
}
|
|
4059
|
-
|
|
4060
|
-
|
|
3688
|
+
return {
|
|
3689
|
+
...state,
|
|
4061
3690
|
...changes
|
|
4062
3691
|
};
|
|
4063
3692
|
}
|
|
4064
3693
|
|
|
4065
3694
|
useMultipleSelection.stateChangeTypes = stateChangeTypes;
|
|
4066
|
-
|
|
4067
3695
|
function useMultipleSelection(userProps) {
|
|
4068
3696
|
if (userProps === void 0) {
|
|
4069
3697
|
userProps = {};
|
|
4070
3698
|
}
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
3699
|
+
validatePropTypes(userProps, useMultipleSelection);
|
|
3700
|
+
// Props defaults and destructuring.
|
|
3701
|
+
const props = {
|
|
3702
|
+
...defaultProps,
|
|
4075
3703
|
...userProps
|
|
4076
3704
|
};
|
|
4077
3705
|
const {
|
|
@@ -4080,14 +3708,16 @@ function useMultipleSelection(userProps) {
|
|
|
4080
3708
|
environment,
|
|
4081
3709
|
keyNavigationNext,
|
|
4082
3710
|
keyNavigationPrevious
|
|
4083
|
-
} = props;
|
|
3711
|
+
} = props;
|
|
4084
3712
|
|
|
3713
|
+
// Reducer init.
|
|
4085
3714
|
const [state, dispatch] = useControlledReducer$1(downshiftMultipleSelectionReducer, getInitialState(props), props);
|
|
4086
3715
|
const {
|
|
4087
3716
|
activeIndex,
|
|
4088
3717
|
selectedItems
|
|
4089
|
-
} = state;
|
|
3718
|
+
} = state;
|
|
4090
3719
|
|
|
3720
|
+
// Refs.
|
|
4091
3721
|
const isInitialMountRef = react.useRef(true);
|
|
4092
3722
|
const dropdownRef = react.useRef(null);
|
|
4093
3723
|
const previousSelectedItemsRef = react.useRef(selectedItems);
|
|
@@ -4096,15 +3726,14 @@ function useMultipleSelection(userProps) {
|
|
|
4096
3726
|
const latest = useLatestRef({
|
|
4097
3727
|
state,
|
|
4098
3728
|
props
|
|
4099
|
-
});
|
|
3729
|
+
});
|
|
4100
3730
|
|
|
3731
|
+
// Effects.
|
|
4101
3732
|
/* Sets a11y status message on changes in selectedItem. */
|
|
4102
|
-
|
|
4103
3733
|
react.useEffect(() => {
|
|
4104
3734
|
if (isInitialMountRef.current) {
|
|
4105
3735
|
return;
|
|
4106
3736
|
}
|
|
4107
|
-
|
|
4108
3737
|
if (selectedItems.length < previousSelectedItemsRef.current.length) {
|
|
4109
3738
|
const removedSelectedItem = previousSelectedItemsRef.current.find(item => selectedItems.indexOf(item) < 0);
|
|
4110
3739
|
setStatus(getA11yRemovalMessage({
|
|
@@ -4115,15 +3744,15 @@ function useMultipleSelection(userProps) {
|
|
|
4115
3744
|
activeSelectedItem: selectedItems[activeIndex]
|
|
4116
3745
|
}), environment.document);
|
|
4117
3746
|
}
|
|
3747
|
+
previousSelectedItemsRef.current = selectedItems;
|
|
4118
3748
|
|
|
4119
|
-
|
|
4120
|
-
}, [selectedItems.length]);
|
|
4121
|
-
|
|
3749
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3750
|
+
}, [selectedItems.length]);
|
|
3751
|
+
// Sets focus on active item.
|
|
4122
3752
|
react.useEffect(() => {
|
|
4123
3753
|
if (isInitialMountRef.current) {
|
|
4124
3754
|
return;
|
|
4125
3755
|
}
|
|
4126
|
-
|
|
4127
3756
|
if (activeIndex === -1 && dropdownRef.current) {
|
|
4128
3757
|
dropdownRef.current.focus();
|
|
4129
3758
|
} else if (selectedItemRefs.current[activeIndex]) {
|
|
@@ -4135,37 +3764,34 @@ function useMultipleSelection(userProps) {
|
|
|
4135
3764
|
props,
|
|
4136
3765
|
state
|
|
4137
3766
|
});
|
|
4138
|
-
const setGetterPropCallInfo = useGetterPropsCalledChecker('getDropdownProps');
|
|
4139
|
-
|
|
3767
|
+
const setGetterPropCallInfo = useGetterPropsCalledChecker('getDropdownProps');
|
|
3768
|
+
// Make initial ref false.
|
|
4140
3769
|
react.useEffect(() => {
|
|
4141
3770
|
isInitialMountRef.current = false;
|
|
4142
|
-
}, []);
|
|
3771
|
+
}, []);
|
|
4143
3772
|
|
|
3773
|
+
// Event handler functions.
|
|
4144
3774
|
const selectedItemKeyDownHandlers = react.useMemo(() => ({
|
|
4145
3775
|
[keyNavigationPrevious]() {
|
|
4146
3776
|
dispatch({
|
|
4147
3777
|
type: SelectedItemKeyDownNavigationPrevious
|
|
4148
3778
|
});
|
|
4149
3779
|
},
|
|
4150
|
-
|
|
4151
3780
|
[keyNavigationNext]() {
|
|
4152
3781
|
dispatch({
|
|
4153
3782
|
type: SelectedItemKeyDownNavigationNext
|
|
4154
3783
|
});
|
|
4155
3784
|
},
|
|
4156
|
-
|
|
4157
3785
|
Delete() {
|
|
4158
3786
|
dispatch({
|
|
4159
3787
|
type: SelectedItemKeyDownDelete
|
|
4160
3788
|
});
|
|
4161
3789
|
},
|
|
4162
|
-
|
|
4163
3790
|
Backspace() {
|
|
4164
3791
|
dispatch({
|
|
4165
3792
|
type: SelectedItemKeyDownBackspace
|
|
4166
3793
|
});
|
|
4167
3794
|
}
|
|
4168
|
-
|
|
4169
3795
|
}), [dispatch, keyNavigationNext, keyNavigationPrevious]);
|
|
4170
3796
|
const dropdownKeyDownHandlers = react.useMemo(() => ({
|
|
4171
3797
|
[keyNavigationPrevious](event) {
|
|
@@ -4175,7 +3801,6 @@ function useMultipleSelection(userProps) {
|
|
|
4175
3801
|
});
|
|
4176
3802
|
}
|
|
4177
3803
|
},
|
|
4178
|
-
|
|
4179
3804
|
Backspace(event) {
|
|
4180
3805
|
if (isKeyDownOperationPermitted(event)) {
|
|
4181
3806
|
dispatch({
|
|
@@ -4183,9 +3808,9 @@ function useMultipleSelection(userProps) {
|
|
|
4183
3808
|
});
|
|
4184
3809
|
}
|
|
4185
3810
|
}
|
|
3811
|
+
}), [dispatch, keyNavigationPrevious]);
|
|
4186
3812
|
|
|
4187
|
-
|
|
4188
|
-
|
|
3813
|
+
// Getter props.
|
|
4189
3814
|
const getSelectedItemProps = react.useCallback(function (_temp) {
|
|
4190
3815
|
let {
|
|
4191
3816
|
refKey = 'ref',
|
|
@@ -4200,26 +3825,21 @@ function useMultipleSelection(userProps) {
|
|
|
4200
3825
|
state: latestState
|
|
4201
3826
|
} = latest.current;
|
|
4202
3827
|
const itemIndex = getItemIndex(index, selectedItem, latestState.selectedItems);
|
|
4203
|
-
|
|
4204
3828
|
if (itemIndex < 0) {
|
|
4205
3829
|
throw new Error('Pass either selectedItem or index in getSelectedItemProps!');
|
|
4206
3830
|
}
|
|
4207
|
-
|
|
4208
3831
|
const selectedItemHandleClick = () => {
|
|
4209
3832
|
dispatch({
|
|
4210
3833
|
type: SelectedItemClick,
|
|
4211
3834
|
index
|
|
4212
3835
|
});
|
|
4213
3836
|
};
|
|
4214
|
-
|
|
4215
3837
|
const selectedItemHandleKeyDown = event => {
|
|
4216
3838
|
const key = normalizeArrowKey(event);
|
|
4217
|
-
|
|
4218
3839
|
if (key && selectedItemKeyDownHandlers[key]) {
|
|
4219
3840
|
selectedItemKeyDownHandlers[key](event);
|
|
4220
3841
|
}
|
|
4221
3842
|
};
|
|
4222
|
-
|
|
4223
3843
|
return {
|
|
4224
3844
|
[refKey]: handleRefs(ref, selectedItemNode => {
|
|
4225
3845
|
if (selectedItemNode) {
|
|
@@ -4245,21 +3865,17 @@ function useMultipleSelection(userProps) {
|
|
|
4245
3865
|
suppressRefError = false
|
|
4246
3866
|
} = _temp3 === void 0 ? {} : _temp3;
|
|
4247
3867
|
setGetterPropCallInfo('getDropdownProps', suppressRefError, refKey, dropdownRef);
|
|
4248
|
-
|
|
4249
3868
|
const dropdownHandleKeyDown = event => {
|
|
4250
3869
|
const key = normalizeArrowKey(event);
|
|
4251
|
-
|
|
4252
3870
|
if (key && dropdownKeyDownHandlers[key]) {
|
|
4253
3871
|
dropdownKeyDownHandlers[key](event);
|
|
4254
3872
|
}
|
|
4255
3873
|
};
|
|
4256
|
-
|
|
4257
3874
|
const dropdownHandleClick = () => {
|
|
4258
3875
|
dispatch({
|
|
4259
3876
|
type: DropdownClick
|
|
4260
3877
|
});
|
|
4261
3878
|
};
|
|
4262
|
-
|
|
4263
3879
|
return {
|
|
4264
3880
|
[refKey]: handleRefs(ref, dropdownNode => {
|
|
4265
3881
|
if (dropdownNode) {
|
|
@@ -4272,8 +3888,9 @@ function useMultipleSelection(userProps) {
|
|
|
4272
3888
|
}),
|
|
4273
3889
|
...rest
|
|
4274
3890
|
};
|
|
4275
|
-
}, [dispatch, dropdownKeyDownHandlers, setGetterPropCallInfo]);
|
|
3891
|
+
}, [dispatch, dropdownKeyDownHandlers, setGetterPropCallInfo]);
|
|
4276
3892
|
|
|
3893
|
+
// returns
|
|
4277
3894
|
const addSelectedItem = react.useCallback(selectedItem => {
|
|
4278
3895
|
dispatch({
|
|
4279
3896
|
type: FunctionAddSelectedItem,
|