downshift 7.0.0-beta.0 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/dist/downshift.cjs.js +264 -651
- package/dist/downshift.esm.js +264 -651
- package/dist/downshift.native.cjs.js +265 -650
- package/dist/downshift.umd.js +262 -646
- package/dist/downshift.umd.js.map +1 -1
- package/dist/downshift.umd.min.js +1 -1
- package/dist/downshift.umd.min.js.map +1 -1
- package/dist/src/hooks/utils.d.ts +1 -1
- package/package.json +1 -1
- package/preact/dist/downshift.cjs.js +264 -648
- package/preact/dist/downshift.esm.js +264 -648
- package/preact/dist/downshift.umd.js +262 -643
- package/preact/dist/downshift.umd.js.map +1 -1
- package/preact/dist/downshift.umd.min.js +1 -1
- package/preact/dist/downshift.umd.min.js.map +1 -1
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;
|
|
655
576
|
|
|
656
|
-
|
|
577
|
+
// Your own function that could modify the state that will be set.
|
|
578
|
+
newStateToSet = this.props.stateReducer(state, newStateToSet);
|
|
579
|
+
|
|
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,16 +2423,12 @@ function useSelect(userProps) {
|
|
|
2699
2423
|
});
|
|
2700
2424
|
}
|
|
2701
2425
|
},
|
|
2702
|
-
|
|
2703
2426
|
Enter(event) {
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
});
|
|
2709
|
-
}
|
|
2427
|
+
event.preventDefault();
|
|
2428
|
+
dispatch({
|
|
2429
|
+
type: latest.current.state.isOpen ? ToggleButtonKeyDownEnter : ToggleButtonClick$1
|
|
2430
|
+
});
|
|
2710
2431
|
},
|
|
2711
|
-
|
|
2712
2432
|
PageUp(event) {
|
|
2713
2433
|
if (latest.current.state.isOpen) {
|
|
2714
2434
|
event.preventDefault();
|
|
@@ -2718,7 +2438,6 @@ function useSelect(userProps) {
|
|
|
2718
2438
|
});
|
|
2719
2439
|
}
|
|
2720
2440
|
},
|
|
2721
|
-
|
|
2722
2441
|
PageDown(event) {
|
|
2723
2442
|
if (latest.current.state.isOpen) {
|
|
2724
2443
|
event.preventDefault();
|
|
@@ -2728,18 +2447,15 @@ function useSelect(userProps) {
|
|
|
2728
2447
|
});
|
|
2729
2448
|
}
|
|
2730
2449
|
},
|
|
2731
|
-
|
|
2732
2450
|
' '(event) {
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
});
|
|
2738
|
-
}
|
|
2451
|
+
event.preventDefault();
|
|
2452
|
+
dispatch({
|
|
2453
|
+
type: latest.current.state.isOpen ? ToggleButtonKeyDownSpaceButton : ToggleButtonClick$1
|
|
2454
|
+
});
|
|
2739
2455
|
}
|
|
2456
|
+
}), [dispatch, getItemNodeFromIndex, latest]);
|
|
2740
2457
|
|
|
2741
|
-
|
|
2742
|
-
|
|
2458
|
+
// Action functions.
|
|
2743
2459
|
const toggleMenu = react.useCallback(() => {
|
|
2744
2460
|
dispatch({
|
|
2745
2461
|
type: FunctionToggleMenu$1
|
|
@@ -2777,8 +2493,8 @@ function useSelect(userProps) {
|
|
|
2777
2493
|
type: FunctionSetInputValue$1,
|
|
2778
2494
|
inputValue: newInputValue
|
|
2779
2495
|
});
|
|
2780
|
-
}, [dispatch]);
|
|
2781
|
-
|
|
2496
|
+
}, [dispatch]);
|
|
2497
|
+
// Getter functions.
|
|
2782
2498
|
const getLabelProps = react.useCallback(labelProps => ({
|
|
2783
2499
|
id: elementIds.labelId,
|
|
2784
2500
|
htmlFor: elementIds.toggleButtonId,
|
|
@@ -2796,13 +2512,11 @@ function useSelect(userProps) {
|
|
|
2796
2512
|
let {
|
|
2797
2513
|
suppressRefError = false
|
|
2798
2514
|
} = _temp2 === void 0 ? {} : _temp2;
|
|
2799
|
-
|
|
2800
2515
|
const menuHandleMouseLeave = () => {
|
|
2801
2516
|
dispatch({
|
|
2802
2517
|
type: MenuMouseLeave$1
|
|
2803
2518
|
});
|
|
2804
2519
|
};
|
|
2805
|
-
|
|
2806
2520
|
setGetterPropCallInfo('getMenuProps', suppressRefError, refKey, menuRef);
|
|
2807
2521
|
return {
|
|
2808
2522
|
[refKey]: handleRefs(ref, menuNode => {
|
|
@@ -2829,13 +2543,11 @@ function useSelect(userProps) {
|
|
|
2829
2543
|
suppressRefError = false
|
|
2830
2544
|
} = _temp4 === void 0 ? {} : _temp4;
|
|
2831
2545
|
const latestState = latest.current.state;
|
|
2832
|
-
|
|
2833
2546
|
const toggleButtonHandleClick = () => {
|
|
2834
2547
|
dispatch({
|
|
2835
2548
|
type: ToggleButtonClick$1
|
|
2836
2549
|
});
|
|
2837
2550
|
};
|
|
2838
|
-
|
|
2839
2551
|
const toggleButtonHandleBlur = () => {
|
|
2840
2552
|
if (latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
|
|
2841
2553
|
dispatch({
|
|
@@ -2843,10 +2555,8 @@ function useSelect(userProps) {
|
|
|
2843
2555
|
});
|
|
2844
2556
|
}
|
|
2845
2557
|
};
|
|
2846
|
-
|
|
2847
2558
|
const toggleButtonHandleKeyDown = event => {
|
|
2848
2559
|
const key = normalizeArrowKey(event);
|
|
2849
|
-
|
|
2850
2560
|
if (key && toggleButtonKeyDownHandlers[key]) {
|
|
2851
2561
|
toggleButtonKeyDownHandlers[key](event);
|
|
2852
2562
|
} else if (isAcceptedCharacterKey(key)) {
|
|
@@ -2857,7 +2567,6 @@ function useSelect(userProps) {
|
|
|
2857
2567
|
});
|
|
2858
2568
|
}
|
|
2859
2569
|
};
|
|
2860
|
-
|
|
2861
2570
|
const toggleProps = {
|
|
2862
2571
|
[refKey]: handleRefs(ref, toggleButtonNode => {
|
|
2863
2572
|
toggleButtonRef.current = toggleButtonNode;
|
|
@@ -2873,12 +2582,10 @@ function useSelect(userProps) {
|
|
|
2873
2582
|
onBlur: callAllEventHandlers(onBlur, toggleButtonHandleBlur),
|
|
2874
2583
|
...rest
|
|
2875
2584
|
};
|
|
2876
|
-
|
|
2877
2585
|
if (!rest.disabled) {
|
|
2878
2586
|
toggleProps.onClick = callAllEventHandlers(onClick, toggleButtonHandleClick);
|
|
2879
2587
|
toggleProps.onKeyDown = callAllEventHandlers(onKeyDown, toggleButtonHandleKeyDown);
|
|
2880
2588
|
}
|
|
2881
|
-
|
|
2882
2589
|
setGetterPropCallInfo('getToggleButtonProps', suppressRefError, refKey, toggleButtonRef);
|
|
2883
2590
|
return toggleProps;
|
|
2884
2591
|
}, [latest, elementIds, setGetterPropCallInfo, dispatch, mouseAndTouchTrackersRef, toggleButtonKeyDownHandlers, getItemNodeFromIndex]);
|
|
@@ -2899,12 +2606,10 @@ function useSelect(userProps) {
|
|
|
2899
2606
|
} = latest.current;
|
|
2900
2607
|
const item = itemProp ?? items[indexProp];
|
|
2901
2608
|
const index = getItemIndex(indexProp, item, latestProps.items);
|
|
2902
|
-
|
|
2903
2609
|
const itemHandleMouseMove = () => {
|
|
2904
2610
|
if (index === latestState.highlightedIndex) {
|
|
2905
2611
|
return;
|
|
2906
2612
|
}
|
|
2907
|
-
|
|
2908
2613
|
shouldScrollRef.current = false;
|
|
2909
2614
|
dispatch({
|
|
2910
2615
|
type: ItemMouseMove$1,
|
|
@@ -2912,20 +2617,16 @@ function useSelect(userProps) {
|
|
|
2912
2617
|
disabled
|
|
2913
2618
|
});
|
|
2914
2619
|
};
|
|
2915
|
-
|
|
2916
2620
|
const itemHandleClick = () => {
|
|
2917
2621
|
dispatch({
|
|
2918
2622
|
type: ItemClick$1,
|
|
2919
2623
|
index
|
|
2920
2624
|
});
|
|
2921
2625
|
};
|
|
2922
|
-
|
|
2923
2626
|
const itemIndex = getItemIndex(index, item, latestProps.items);
|
|
2924
|
-
|
|
2925
2627
|
if (itemIndex < 0) {
|
|
2926
2628
|
throw new Error('Pass either item or item index in getItemProps!');
|
|
2927
2629
|
}
|
|
2928
|
-
|
|
2929
2630
|
const itemProps = {
|
|
2930
2631
|
disabled,
|
|
2931
2632
|
role: 'option',
|
|
@@ -2938,11 +2639,9 @@ function useSelect(userProps) {
|
|
|
2938
2639
|
}),
|
|
2939
2640
|
...rest
|
|
2940
2641
|
};
|
|
2941
|
-
|
|
2942
2642
|
if (!disabled) {
|
|
2943
2643
|
itemProps.onClick = callAllEventHandlers(onClick, itemHandleClick);
|
|
2944
2644
|
}
|
|
2945
|
-
|
|
2946
2645
|
itemProps.onMouseMove = callAllEventHandlers(onMouseMove, itemHandleMouseMove);
|
|
2947
2646
|
return itemProps;
|
|
2948
2647
|
}, [latest, items, selectedItem, elementIds, shouldScrollRef, dispatch]);
|
|
@@ -3027,16 +2726,14 @@ function getInitialState$1(props) {
|
|
|
3027
2726
|
let {
|
|
3028
2727
|
inputValue
|
|
3029
2728
|
} = initialState;
|
|
3030
|
-
|
|
3031
2729
|
if (inputValue === '' && selectedItem && props.defaultInputValue === undefined && props.initialInputValue === undefined && props.inputValue === undefined) {
|
|
3032
2730
|
inputValue = props.itemToString(selectedItem);
|
|
3033
2731
|
}
|
|
3034
|
-
|
|
3035
|
-
|
|
2732
|
+
return {
|
|
2733
|
+
...initialState,
|
|
3036
2734
|
inputValue
|
|
3037
2735
|
};
|
|
3038
2736
|
}
|
|
3039
|
-
|
|
3040
2737
|
const propTypes$1 = {
|
|
3041
2738
|
items: PropTypes__default["default"].array.isRequired,
|
|
3042
2739
|
itemToString: PropTypes__default["default"].func,
|
|
@@ -3076,6 +2773,7 @@ const propTypes$1 = {
|
|
|
3076
2773
|
})
|
|
3077
2774
|
})
|
|
3078
2775
|
};
|
|
2776
|
+
|
|
3079
2777
|
/**
|
|
3080
2778
|
* The useCombobox version of useControlledReducer, which also
|
|
3081
2779
|
* checks if the controlled prop selectedItem changed between
|
|
@@ -3088,11 +2786,11 @@ const propTypes$1 = {
|
|
|
3088
2786
|
* @param {Object} props The hook props.
|
|
3089
2787
|
* @returns {Array} An array with the state and an action dispatcher.
|
|
3090
2788
|
*/
|
|
3091
|
-
|
|
3092
2789
|
function useControlledReducer(reducer, initialState, props) {
|
|
3093
2790
|
const previousSelectedItemRef = react.useRef();
|
|
3094
|
-
const [state, dispatch] = useEnhancedReducer(reducer, initialState, props);
|
|
2791
|
+
const [state, dispatch] = useEnhancedReducer(reducer, initialState, props);
|
|
3095
2792
|
|
|
2793
|
+
// ToDo: if needed, make same approach as selectedItemChanged from Downshift.
|
|
3096
2794
|
react.useEffect(() => {
|
|
3097
2795
|
if (isControlledProp(props, 'selectedItem')) {
|
|
3098
2796
|
if (previousSelectedItemRef.current !== props.selectedItem) {
|
|
@@ -3101,29 +2799,26 @@ function useControlledReducer(reducer, initialState, props) {
|
|
|
3101
2799
|
inputValue: props.itemToString(props.selectedItem)
|
|
3102
2800
|
});
|
|
3103
2801
|
}
|
|
3104
|
-
|
|
3105
2802
|
previousSelectedItemRef.current = state.selectedItem === previousSelectedItemRef.current ? props.selectedItem : state.selectedItem;
|
|
3106
2803
|
}
|
|
3107
2804
|
});
|
|
3108
2805
|
return [getState(state, props), dispatch];
|
|
3109
|
-
}
|
|
3110
|
-
|
|
2806
|
+
}
|
|
3111
2807
|
|
|
2808
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
3112
2809
|
let validatePropTypes$1 = noop;
|
|
3113
2810
|
/* istanbul ignore next */
|
|
3114
|
-
|
|
3115
2811
|
if (process.env.NODE_ENV !== 'production') {
|
|
3116
2812
|
validatePropTypes$1 = (options, caller) => {
|
|
3117
2813
|
PropTypes__default["default"].checkPropTypes(propTypes$1, options, 'prop', caller.name);
|
|
3118
2814
|
};
|
|
3119
2815
|
}
|
|
3120
|
-
|
|
3121
|
-
|
|
2816
|
+
const defaultProps$1 = {
|
|
2817
|
+
...defaultProps$3,
|
|
3122
2818
|
getA11yStatusMessage: getA11yStatusMessage$1
|
|
3123
2819
|
};
|
|
3124
2820
|
|
|
3125
2821
|
/* eslint-disable complexity */
|
|
3126
|
-
|
|
3127
2822
|
function downshiftUseComboboxReducer(state, action) {
|
|
3128
2823
|
const {
|
|
3129
2824
|
type,
|
|
@@ -3131,7 +2826,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3131
2826
|
altKey
|
|
3132
2827
|
} = action;
|
|
3133
2828
|
let changes;
|
|
3134
|
-
|
|
3135
2829
|
switch (type) {
|
|
3136
2830
|
case ItemClick:
|
|
3137
2831
|
changes = {
|
|
@@ -3141,7 +2835,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3141
2835
|
inputValue: props.itemToString(props.items[action.index])
|
|
3142
2836
|
};
|
|
3143
2837
|
break;
|
|
3144
|
-
|
|
3145
2838
|
case InputKeyDownArrowDown:
|
|
3146
2839
|
if (state.isOpen) {
|
|
3147
2840
|
changes = {
|
|
@@ -3153,9 +2846,7 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3153
2846
|
isOpen: props.items.length >= 0
|
|
3154
2847
|
};
|
|
3155
2848
|
}
|
|
3156
|
-
|
|
3157
2849
|
break;
|
|
3158
|
-
|
|
3159
2850
|
case InputKeyDownArrowUp:
|
|
3160
2851
|
if (state.isOpen) {
|
|
3161
2852
|
if (altKey) {
|
|
@@ -3178,9 +2869,7 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3178
2869
|
isOpen: props.items.length >= 0
|
|
3179
2870
|
};
|
|
3180
2871
|
}
|
|
3181
|
-
|
|
3182
2872
|
break;
|
|
3183
|
-
|
|
3184
2873
|
case InputKeyDownEnter:
|
|
3185
2874
|
changes = {
|
|
3186
2875
|
isOpen: getDefaultValue$1(props, 'isOpen'),
|
|
@@ -3191,7 +2880,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3191
2880
|
})
|
|
3192
2881
|
};
|
|
3193
2882
|
break;
|
|
3194
|
-
|
|
3195
2883
|
case InputKeyDownEscape:
|
|
3196
2884
|
changes = {
|
|
3197
2885
|
isOpen: false,
|
|
@@ -3202,31 +2890,26 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3202
2890
|
})
|
|
3203
2891
|
};
|
|
3204
2892
|
break;
|
|
3205
|
-
|
|
3206
2893
|
case InputKeyDownPageUp:
|
|
3207
2894
|
changes = {
|
|
3208
2895
|
highlightedIndex: getNextWrappingIndex(-10, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false)
|
|
3209
2896
|
};
|
|
3210
2897
|
break;
|
|
3211
|
-
|
|
3212
2898
|
case InputKeyDownPageDown:
|
|
3213
2899
|
changes = {
|
|
3214
2900
|
highlightedIndex: getNextWrappingIndex(10, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, false)
|
|
3215
2901
|
};
|
|
3216
2902
|
break;
|
|
3217
|
-
|
|
3218
2903
|
case InputKeyDownHome:
|
|
3219
2904
|
changes = {
|
|
3220
2905
|
highlightedIndex: getNextNonDisabledIndex(1, 0, props.items.length, action.getItemNodeFromIndex, false)
|
|
3221
2906
|
};
|
|
3222
2907
|
break;
|
|
3223
|
-
|
|
3224
2908
|
case InputKeyDownEnd:
|
|
3225
2909
|
changes = {
|
|
3226
2910
|
highlightedIndex: getNextNonDisabledIndex(-1, props.items.length - 1, props.items.length, action.getItemNodeFromIndex, false)
|
|
3227
2911
|
};
|
|
3228
2912
|
break;
|
|
3229
|
-
|
|
3230
2913
|
case InputBlur:
|
|
3231
2914
|
changes = {
|
|
3232
2915
|
isOpen: false,
|
|
@@ -3237,7 +2920,6 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3237
2920
|
})
|
|
3238
2921
|
};
|
|
3239
2922
|
break;
|
|
3240
|
-
|
|
3241
2923
|
case InputChange:
|
|
3242
2924
|
changes = {
|
|
3243
2925
|
isOpen: true,
|
|
@@ -3245,32 +2927,28 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3245
2927
|
inputValue: action.inputValue
|
|
3246
2928
|
};
|
|
3247
2929
|
break;
|
|
3248
|
-
|
|
3249
2930
|
case InputFocus:
|
|
3250
2931
|
changes = {
|
|
3251
2932
|
isOpen: true,
|
|
3252
2933
|
highlightedIndex: getHighlightedIndexOnOpen(props, state, 0)
|
|
3253
2934
|
};
|
|
3254
2935
|
break;
|
|
3255
|
-
|
|
3256
2936
|
case FunctionSelectItem:
|
|
3257
2937
|
changes = {
|
|
3258
2938
|
selectedItem: action.selectedItem,
|
|
3259
2939
|
inputValue: props.itemToString(action.selectedItem)
|
|
3260
2940
|
};
|
|
3261
2941
|
break;
|
|
3262
|
-
|
|
3263
2942
|
case ControlledPropUpdatedSelectedItem:
|
|
3264
2943
|
changes = {
|
|
3265
2944
|
inputValue: action.inputValue
|
|
3266
2945
|
};
|
|
3267
2946
|
break;
|
|
3268
|
-
|
|
3269
2947
|
default:
|
|
3270
2948
|
return downshiftCommonReducer(state, action, stateChangeTypes$1);
|
|
3271
2949
|
}
|
|
3272
|
-
|
|
3273
|
-
|
|
2950
|
+
return {
|
|
2951
|
+
...state,
|
|
3274
2952
|
...changes
|
|
3275
2953
|
};
|
|
3276
2954
|
}
|
|
@@ -3278,15 +2956,14 @@ function downshiftUseComboboxReducer(state, action) {
|
|
|
3278
2956
|
|
|
3279
2957
|
/* eslint-disable max-statements */
|
|
3280
2958
|
useCombobox.stateChangeTypes = stateChangeTypes$1;
|
|
3281
|
-
|
|
3282
2959
|
function useCombobox(userProps) {
|
|
3283
2960
|
if (userProps === void 0) {
|
|
3284
2961
|
userProps = {};
|
|
3285
2962
|
}
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
2963
|
+
validatePropTypes$1(userProps, useCombobox);
|
|
2964
|
+
// Props defaults and destructuring.
|
|
2965
|
+
const props = {
|
|
2966
|
+
...defaultProps$1,
|
|
3290
2967
|
...userProps
|
|
3291
2968
|
};
|
|
3292
2969
|
const {
|
|
@@ -3298,8 +2975,8 @@ function useCombobox(userProps) {
|
|
|
3298
2975
|
getA11yStatusMessage,
|
|
3299
2976
|
getA11ySelectionMessage,
|
|
3300
2977
|
itemToString
|
|
3301
|
-
} = props;
|
|
3302
|
-
|
|
2978
|
+
} = props;
|
|
2979
|
+
// Initial state depending on controlled props.
|
|
3303
2980
|
const initialState = getInitialState$1(props);
|
|
3304
2981
|
const [state, dispatch] = useControlledReducer(downshiftUseComboboxReducer, initialState, props);
|
|
3305
2982
|
const {
|
|
@@ -3307,25 +2984,27 @@ function useCombobox(userProps) {
|
|
|
3307
2984
|
highlightedIndex,
|
|
3308
2985
|
selectedItem,
|
|
3309
2986
|
inputValue
|
|
3310
|
-
} = state;
|
|
2987
|
+
} = state;
|
|
3311
2988
|
|
|
2989
|
+
// Element refs.
|
|
3312
2990
|
const menuRef = react.useRef(null);
|
|
3313
2991
|
const itemRefs = react.useRef({});
|
|
3314
2992
|
const inputRef = react.useRef(null);
|
|
3315
2993
|
const toggleButtonRef = react.useRef(null);
|
|
3316
|
-
const isInitialMountRef = react.useRef(true);
|
|
3317
|
-
|
|
3318
|
-
const elementIds = useElementIds(props);
|
|
3319
|
-
|
|
3320
|
-
const previousResultCountRef = react.useRef();
|
|
3321
|
-
|
|
2994
|
+
const isInitialMountRef = react.useRef(true);
|
|
2995
|
+
// prevent id re-generation between renders.
|
|
2996
|
+
const elementIds = useElementIds(props);
|
|
2997
|
+
// used to keep track of how many items we had on previous cycle.
|
|
2998
|
+
const previousResultCountRef = react.useRef();
|
|
2999
|
+
// utility callback to get item element.
|
|
3322
3000
|
const latest = useLatestRef({
|
|
3323
3001
|
state,
|
|
3324
3002
|
props
|
|
3325
3003
|
});
|
|
3326
|
-
const getItemNodeFromIndex = react.useCallback(index => itemRefs.current[elementIds.getItemId(index)], [elementIds]);
|
|
3327
|
-
// Sets a11y status message on changes in state.
|
|
3004
|
+
const getItemNodeFromIndex = react.useCallback(index => itemRefs.current[elementIds.getItemId(index)], [elementIds]);
|
|
3328
3005
|
|
|
3006
|
+
// Effects.
|
|
3007
|
+
// Sets a11y status message on changes in state.
|
|
3329
3008
|
useA11yMessageSetter(getA11yStatusMessage, [isOpen, highlightedIndex, inputValue, items], {
|
|
3330
3009
|
isInitialMount: isInitialMountRef.current,
|
|
3331
3010
|
previousResultCount: previousResultCountRef.current,
|
|
@@ -3333,8 +3012,8 @@ function useCombobox(userProps) {
|
|
|
3333
3012
|
environment,
|
|
3334
3013
|
itemToString,
|
|
3335
3014
|
...state
|
|
3336
|
-
});
|
|
3337
|
-
|
|
3015
|
+
});
|
|
3016
|
+
// Sets a11y status message on changes in selectedItem.
|
|
3338
3017
|
useA11yMessageSetter(getA11ySelectionMessage, [selectedItem], {
|
|
3339
3018
|
isInitialMount: isInitialMountRef.current,
|
|
3340
3019
|
previousResultCount: previousResultCountRef.current,
|
|
@@ -3342,8 +3021,8 @@ function useCombobox(userProps) {
|
|
|
3342
3021
|
environment,
|
|
3343
3022
|
itemToString,
|
|
3344
3023
|
...state
|
|
3345
|
-
});
|
|
3346
|
-
|
|
3024
|
+
});
|
|
3025
|
+
// Scroll on highlighted item if change comes from keyboard.
|
|
3347
3026
|
const shouldScrollRef = useScrollIntoView({
|
|
3348
3027
|
menuElement: menuRef.current,
|
|
3349
3028
|
highlightedIndex,
|
|
@@ -3356,47 +3035,44 @@ function useCombobox(userProps) {
|
|
|
3356
3035
|
isInitialMount: isInitialMountRef.current,
|
|
3357
3036
|
props,
|
|
3358
3037
|
state
|
|
3359
|
-
});
|
|
3360
|
-
|
|
3038
|
+
});
|
|
3039
|
+
// Focus the input on first render if required.
|
|
3361
3040
|
react.useEffect(() => {
|
|
3362
3041
|
const focusOnOpen = initialIsOpen || defaultIsOpen || isOpen;
|
|
3363
|
-
|
|
3364
3042
|
if (focusOnOpen && inputRef.current) {
|
|
3365
3043
|
inputRef.current.focus();
|
|
3366
|
-
}
|
|
3367
|
-
|
|
3044
|
+
}
|
|
3045
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3368
3046
|
}, []);
|
|
3369
3047
|
react.useEffect(() => {
|
|
3370
3048
|
if (isInitialMountRef.current) {
|
|
3371
3049
|
return;
|
|
3372
3050
|
}
|
|
3373
|
-
|
|
3374
3051
|
previousResultCountRef.current = items.length;
|
|
3375
|
-
});
|
|
3376
|
-
|
|
3052
|
+
});
|
|
3053
|
+
// Add mouse/touch events to document.
|
|
3377
3054
|
const mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [inputRef, menuRef, toggleButtonRef], environment, () => {
|
|
3378
3055
|
dispatch({
|
|
3379
3056
|
type: InputBlur,
|
|
3380
3057
|
selectItem: false
|
|
3381
3058
|
});
|
|
3382
3059
|
});
|
|
3383
|
-
const setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getMenuProps');
|
|
3384
|
-
|
|
3060
|
+
const setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getMenuProps');
|
|
3061
|
+
// Make initial ref false.
|
|
3385
3062
|
react.useEffect(() => {
|
|
3386
3063
|
isInitialMountRef.current = false;
|
|
3387
|
-
}, []);
|
|
3388
|
-
|
|
3064
|
+
}, []);
|
|
3065
|
+
// Reset itemRefs on close.
|
|
3389
3066
|
react.useEffect(() => {
|
|
3390
3067
|
if (!isOpen) {
|
|
3391
3068
|
itemRefs.current = {};
|
|
3392
3069
|
} else if (document.activeElement !== inputRef.current) {
|
|
3393
3070
|
var _inputRef$current;
|
|
3394
|
-
|
|
3395
3071
|
inputRef == null ? void 0 : (_inputRef$current = inputRef.current) == null ? void 0 : _inputRef$current.focus();
|
|
3396
3072
|
}
|
|
3397
3073
|
}, [isOpen]);
|
|
3398
|
-
/* Event handler functions */
|
|
3399
3074
|
|
|
3075
|
+
/* Event handler functions */
|
|
3400
3076
|
const inputKeyDownHandlers = react.useMemo(() => ({
|
|
3401
3077
|
ArrowDown(event) {
|
|
3402
3078
|
event.preventDefault();
|
|
@@ -3406,7 +3082,6 @@ function useCombobox(userProps) {
|
|
|
3406
3082
|
getItemNodeFromIndex
|
|
3407
3083
|
});
|
|
3408
3084
|
},
|
|
3409
|
-
|
|
3410
3085
|
ArrowUp(event) {
|
|
3411
3086
|
event.preventDefault();
|
|
3412
3087
|
dispatch({
|
|
@@ -3415,34 +3090,28 @@ function useCombobox(userProps) {
|
|
|
3415
3090
|
getItemNodeFromIndex
|
|
3416
3091
|
});
|
|
3417
3092
|
},
|
|
3418
|
-
|
|
3419
3093
|
Home(event) {
|
|
3420
3094
|
if (!latest.current.state.isOpen) {
|
|
3421
3095
|
return;
|
|
3422
3096
|
}
|
|
3423
|
-
|
|
3424
3097
|
event.preventDefault();
|
|
3425
3098
|
dispatch({
|
|
3426
3099
|
type: InputKeyDownHome,
|
|
3427
3100
|
getItemNodeFromIndex
|
|
3428
3101
|
});
|
|
3429
3102
|
},
|
|
3430
|
-
|
|
3431
3103
|
End(event) {
|
|
3432
3104
|
if (!latest.current.state.isOpen) {
|
|
3433
3105
|
return;
|
|
3434
3106
|
}
|
|
3435
|
-
|
|
3436
3107
|
event.preventDefault();
|
|
3437
3108
|
dispatch({
|
|
3438
3109
|
type: InputKeyDownEnd,
|
|
3439
3110
|
getItemNodeFromIndex
|
|
3440
3111
|
});
|
|
3441
3112
|
},
|
|
3442
|
-
|
|
3443
3113
|
Escape(event) {
|
|
3444
3114
|
const latestState = latest.current.state;
|
|
3445
|
-
|
|
3446
3115
|
if (latestState.isOpen || latestState.inputValue || latestState.selectedItem || latestState.highlightedIndex > -1) {
|
|
3447
3116
|
event.preventDefault();
|
|
3448
3117
|
dispatch({
|
|
@@ -3450,22 +3119,19 @@ function useCombobox(userProps) {
|
|
|
3450
3119
|
});
|
|
3451
3120
|
}
|
|
3452
3121
|
},
|
|
3453
|
-
|
|
3454
3122
|
Enter(event) {
|
|
3455
|
-
const latestState = latest.current.state;
|
|
3456
|
-
|
|
3123
|
+
const latestState = latest.current.state;
|
|
3124
|
+
// if closed or no highlighted index, do nothing.
|
|
3457
3125
|
if (!latestState.isOpen || event.which === 229 // if IME composing, wait for next Enter keydown event.
|
|
3458
3126
|
) {
|
|
3459
3127
|
return;
|
|
3460
3128
|
}
|
|
3461
|
-
|
|
3462
3129
|
event.preventDefault();
|
|
3463
3130
|
dispatch({
|
|
3464
3131
|
type: InputKeyDownEnter,
|
|
3465
3132
|
getItemNodeFromIndex
|
|
3466
3133
|
});
|
|
3467
3134
|
},
|
|
3468
|
-
|
|
3469
3135
|
PageUp(event) {
|
|
3470
3136
|
if (latest.current.state.isOpen) {
|
|
3471
3137
|
event.preventDefault();
|
|
@@ -3475,7 +3141,6 @@ function useCombobox(userProps) {
|
|
|
3475
3141
|
});
|
|
3476
3142
|
}
|
|
3477
3143
|
},
|
|
3478
|
-
|
|
3479
3144
|
PageDown(event) {
|
|
3480
3145
|
if (latest.current.state.isOpen) {
|
|
3481
3146
|
event.preventDefault();
|
|
@@ -3485,9 +3150,9 @@ function useCombobox(userProps) {
|
|
|
3485
3150
|
});
|
|
3486
3151
|
}
|
|
3487
3152
|
}
|
|
3153
|
+
}), [dispatch, latest, getItemNodeFromIndex]);
|
|
3488
3154
|
|
|
3489
|
-
|
|
3490
|
-
|
|
3155
|
+
// Getter props.
|
|
3491
3156
|
const getLabelProps = react.useCallback(labelProps => ({
|
|
3492
3157
|
id: elementIds.labelId,
|
|
3493
3158
|
htmlFor: elementIds.inputId,
|
|
@@ -3537,19 +3202,15 @@ function useCombobox(userProps) {
|
|
|
3537
3202
|
state: latestState
|
|
3538
3203
|
} = latest.current;
|
|
3539
3204
|
const itemIndex = getItemIndex(index, item, latestProps.items);
|
|
3540
|
-
|
|
3541
3205
|
if (itemIndex < 0) {
|
|
3542
3206
|
throw new Error('Pass either item or item index in getItemProps!');
|
|
3543
3207
|
}
|
|
3544
|
-
|
|
3545
3208
|
const onSelectKey = 'onClick';
|
|
3546
3209
|
const customClickHandler = onClick;
|
|
3547
|
-
|
|
3548
3210
|
const itemHandleMouseMove = () => {
|
|
3549
3211
|
if (index === latestState.highlightedIndex) {
|
|
3550
3212
|
return;
|
|
3551
3213
|
}
|
|
3552
|
-
|
|
3553
3214
|
shouldScrollRef.current = false;
|
|
3554
3215
|
dispatch({
|
|
3555
3216
|
type: ItemMouseMove,
|
|
@@ -3557,16 +3218,13 @@ function useCombobox(userProps) {
|
|
|
3557
3218
|
disabled
|
|
3558
3219
|
});
|
|
3559
3220
|
};
|
|
3560
|
-
|
|
3561
3221
|
const itemHandleClick = () => {
|
|
3562
3222
|
dispatch({
|
|
3563
3223
|
type: ItemClick,
|
|
3564
3224
|
index
|
|
3565
3225
|
});
|
|
3566
3226
|
};
|
|
3567
|
-
|
|
3568
3227
|
const itemHandleMouseDown = e => e.preventDefault();
|
|
3569
|
-
|
|
3570
3228
|
return {
|
|
3571
3229
|
[refKey]: handleRefs(ref, itemNode => {
|
|
3572
3230
|
if (itemNode) {
|
|
@@ -3594,13 +3252,11 @@ function useCombobox(userProps) {
|
|
|
3594
3252
|
...rest
|
|
3595
3253
|
} = _temp4 === void 0 ? {} : _temp4;
|
|
3596
3254
|
const latestState = latest.current.state;
|
|
3597
|
-
|
|
3598
3255
|
const toggleButtonHandleClick = () => {
|
|
3599
3256
|
dispatch({
|
|
3600
3257
|
type: ToggleButtonClick
|
|
3601
3258
|
});
|
|
3602
3259
|
};
|
|
3603
|
-
|
|
3604
3260
|
return {
|
|
3605
3261
|
[refKey]: handleRefs(ref, toggleButtonNode => {
|
|
3606
3262
|
toggleButtonRef.current = toggleButtonNode;
|
|
@@ -3609,7 +3265,8 @@ function useCombobox(userProps) {
|
|
|
3609
3265
|
'aria-expanded': latestState.isOpen,
|
|
3610
3266
|
id: elementIds.toggleButtonId,
|
|
3611
3267
|
tabIndex: -1,
|
|
3612
|
-
...(!rest.disabled && {
|
|
3268
|
+
...(!rest.disabled && {
|
|
3269
|
+
...({
|
|
3613
3270
|
onClick: callAllEventHandlers(onClick, toggleButtonHandleClick)
|
|
3614
3271
|
})
|
|
3615
3272
|
}),
|
|
@@ -3633,22 +3290,18 @@ function useCombobox(userProps) {
|
|
|
3633
3290
|
} = _temp6 === void 0 ? {} : _temp6;
|
|
3634
3291
|
setGetterPropCallInfo('getInputProps', suppressRefError, refKey, inputRef);
|
|
3635
3292
|
const latestState = latest.current.state;
|
|
3636
|
-
|
|
3637
3293
|
const inputHandleKeyDown = event => {
|
|
3638
3294
|
const key = normalizeArrowKey(event);
|
|
3639
|
-
|
|
3640
3295
|
if (key && inputKeyDownHandlers[key]) {
|
|
3641
3296
|
inputKeyDownHandlers[key](event);
|
|
3642
3297
|
}
|
|
3643
3298
|
};
|
|
3644
|
-
|
|
3645
3299
|
const inputHandleChange = event => {
|
|
3646
3300
|
dispatch({
|
|
3647
3301
|
type: InputChange,
|
|
3648
3302
|
inputValue: event.target.value
|
|
3649
3303
|
});
|
|
3650
3304
|
};
|
|
3651
|
-
|
|
3652
3305
|
const inputHandleBlur = () => {
|
|
3653
3306
|
/* istanbul ignore else */
|
|
3654
3307
|
if (latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
|
|
@@ -3658,7 +3311,6 @@ function useCombobox(userProps) {
|
|
|
3658
3311
|
});
|
|
3659
3312
|
}
|
|
3660
3313
|
};
|
|
3661
|
-
|
|
3662
3314
|
const inputHandleFocus = () => {
|
|
3663
3315
|
if (!latestState.isOpen) {
|
|
3664
3316
|
dispatch({
|
|
@@ -3666,12 +3318,10 @@ function useCombobox(userProps) {
|
|
|
3666
3318
|
});
|
|
3667
3319
|
}
|
|
3668
3320
|
};
|
|
3669
|
-
/* istanbul ignore next (preact) */
|
|
3670
|
-
|
|
3671
3321
|
|
|
3322
|
+
/* istanbul ignore next (preact) */
|
|
3672
3323
|
const onChangeKey = 'onChange';
|
|
3673
3324
|
let eventHandlers = {};
|
|
3674
|
-
|
|
3675
3325
|
if (!rest.disabled) {
|
|
3676
3326
|
eventHandlers = {
|
|
3677
3327
|
[onChangeKey]: callAllEventHandlers(onChange, onInput, inputHandleChange),
|
|
@@ -3680,7 +3330,6 @@ function useCombobox(userProps) {
|
|
|
3680
3330
|
onFocus: callAllEventHandlers(onFocus, inputHandleFocus)
|
|
3681
3331
|
};
|
|
3682
3332
|
}
|
|
3683
|
-
|
|
3684
3333
|
return {
|
|
3685
3334
|
[refKey]: handleRefs(ref, inputNode => {
|
|
3686
3335
|
inputRef.current = inputNode;
|
|
@@ -3699,8 +3348,9 @@ function useCombobox(userProps) {
|
|
|
3699
3348
|
...eventHandlers,
|
|
3700
3349
|
...rest
|
|
3701
3350
|
};
|
|
3702
|
-
}, [dispatch, inputKeyDownHandlers, latest, mouseAndTouchTrackersRef, setGetterPropCallInfo, elementIds]);
|
|
3351
|
+
}, [dispatch, inputKeyDownHandlers, latest, mouseAndTouchTrackersRef, setGetterPropCallInfo, elementIds]);
|
|
3703
3352
|
|
|
3353
|
+
// returns
|
|
3704
3354
|
const toggleMenu = react.useCallback(() => {
|
|
3705
3355
|
dispatch({
|
|
3706
3356
|
type: FunctionToggleMenu
|
|
@@ -3766,6 +3416,7 @@ const defaultStateValues = {
|
|
|
3766
3416
|
activeIndex: -1,
|
|
3767
3417
|
selectedItems: []
|
|
3768
3418
|
};
|
|
3419
|
+
|
|
3769
3420
|
/**
|
|
3770
3421
|
* Returns the initial value for a state key in the following order:
|
|
3771
3422
|
* 1. controlled prop, 2. initial prop, 3. default prop, 4. default
|
|
@@ -3775,10 +3426,10 @@ const defaultStateValues = {
|
|
|
3775
3426
|
* @param {string} propKey Props key to generate the value for.
|
|
3776
3427
|
* @returns {any} The initial value for that prop.
|
|
3777
3428
|
*/
|
|
3778
|
-
|
|
3779
3429
|
function getInitialValue(props, propKey) {
|
|
3780
3430
|
return getInitialValue$1(props, propKey, defaultStateValues);
|
|
3781
3431
|
}
|
|
3432
|
+
|
|
3782
3433
|
/**
|
|
3783
3434
|
* Returns the default value for a state key in the following order:
|
|
3784
3435
|
* 1. controlled prop, 2. default prop, 3. default value from Downshift.
|
|
@@ -3787,11 +3438,10 @@ function getInitialValue(props, propKey) {
|
|
|
3787
3438
|
* @param {string} propKey Props key to generate the value for.
|
|
3788
3439
|
* @returns {any} The initial value for that prop.
|
|
3789
3440
|
*/
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
3441
|
function getDefaultValue(props, propKey) {
|
|
3793
3442
|
return getDefaultValue$1(props, propKey, defaultStateValues);
|
|
3794
3443
|
}
|
|
3444
|
+
|
|
3795
3445
|
/**
|
|
3796
3446
|
* Gets the initial state based on the provided props. It uses initial, default
|
|
3797
3447
|
* and controlled props related to state in order to compute the initial value.
|
|
@@ -3799,8 +3449,6 @@ function getDefaultValue(props, propKey) {
|
|
|
3799
3449
|
* @param {Object} props Props passed to the hook.
|
|
3800
3450
|
* @returns {Object} The initial state.
|
|
3801
3451
|
*/
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
3452
|
function getInitialState(props) {
|
|
3805
3453
|
const activeIndex = getInitialValue(props, 'activeIndex');
|
|
3806
3454
|
const selectedItems = getInitialValue(props, 'selectedItems');
|
|
@@ -3809,6 +3457,7 @@ function getInitialState(props) {
|
|
|
3809
3457
|
selectedItems
|
|
3810
3458
|
};
|
|
3811
3459
|
}
|
|
3460
|
+
|
|
3812
3461
|
/**
|
|
3813
3462
|
* Returns true if dropdown keydown operation is permitted. Should not be
|
|
3814
3463
|
* allowed on keydown with modifier keys (ctrl, alt, shift, meta), on
|
|
@@ -3818,32 +3467,28 @@ function getInitialState(props) {
|
|
|
3818
3467
|
* @param {KeyboardEvent} event The event from keydown.
|
|
3819
3468
|
* @returns {boolean} Whether the operation is allowed.
|
|
3820
3469
|
*/
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
3470
|
function isKeyDownOperationPermitted(event) {
|
|
3824
3471
|
if (event.shiftKey || event.metaKey || event.ctrlKey || event.altKey) {
|
|
3825
3472
|
return false;
|
|
3826
3473
|
}
|
|
3827
|
-
|
|
3828
3474
|
const element = event.target;
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
element.value !== '' && (
|
|
3475
|
+
if (element instanceof HTMLInputElement &&
|
|
3476
|
+
// if element is a text input
|
|
3477
|
+
element.value !== '' && (
|
|
3478
|
+
// and we have text in it
|
|
3832
3479
|
// and cursor is either not at the start or is currently highlighting text.
|
|
3833
3480
|
element.selectionStart !== 0 || element.selectionEnd !== 0)) {
|
|
3834
3481
|
return false;
|
|
3835
3482
|
}
|
|
3836
|
-
|
|
3837
3483
|
return true;
|
|
3838
3484
|
}
|
|
3485
|
+
|
|
3839
3486
|
/**
|
|
3840
3487
|
* Returns a message to be added to aria-live region when item is removed.
|
|
3841
3488
|
*
|
|
3842
3489
|
* @param {Object} selectionParameters Parameters required to build the message.
|
|
3843
3490
|
* @returns {string} The a11y message.
|
|
3844
3491
|
*/
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
3492
|
function getA11yRemovalMessage(selectionParameters) {
|
|
3848
3493
|
const {
|
|
3849
3494
|
removedSelectedItem,
|
|
@@ -3851,7 +3496,6 @@ function getA11yRemovalMessage(selectionParameters) {
|
|
|
3851
3496
|
} = selectionParameters;
|
|
3852
3497
|
return `${itemToStringLocal(removedSelectedItem)} has been removed.`;
|
|
3853
3498
|
}
|
|
3854
|
-
|
|
3855
3499
|
const propTypes = {
|
|
3856
3500
|
selectedItems: PropTypes__default["default"].array,
|
|
3857
3501
|
initialSelectedItems: PropTypes__default["default"].array,
|
|
@@ -3883,11 +3527,11 @@ const defaultProps = {
|
|
|
3883
3527
|
getA11yRemovalMessage,
|
|
3884
3528
|
keyNavigationNext: 'ArrowRight',
|
|
3885
3529
|
keyNavigationPrevious: 'ArrowLeft'
|
|
3886
|
-
};
|
|
3530
|
+
};
|
|
3887
3531
|
|
|
3532
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
3888
3533
|
let validatePropTypes = noop;
|
|
3889
3534
|
/* istanbul ignore next */
|
|
3890
|
-
|
|
3891
3535
|
if (process.env.NODE_ENV !== 'production') {
|
|
3892
3536
|
validatePropTypes = (options, caller) => {
|
|
3893
3537
|
PropTypes__default["default"].checkPropTypes(propTypes, options, 'prop', caller.name);
|
|
@@ -3926,7 +3570,6 @@ var stateChangeTypes = /*#__PURE__*/Object.freeze({
|
|
|
3926
3570
|
});
|
|
3927
3571
|
|
|
3928
3572
|
/* eslint-disable complexity */
|
|
3929
|
-
|
|
3930
3573
|
function downshiftMultipleSelectionReducer(state, action) {
|
|
3931
3574
|
const {
|
|
3932
3575
|
type,
|
|
@@ -3939,37 +3582,31 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
3939
3582
|
selectedItems
|
|
3940
3583
|
} = state;
|
|
3941
3584
|
let changes;
|
|
3942
|
-
|
|
3943
3585
|
switch (type) {
|
|
3944
3586
|
case SelectedItemClick:
|
|
3945
3587
|
changes = {
|
|
3946
3588
|
activeIndex: index
|
|
3947
3589
|
};
|
|
3948
3590
|
break;
|
|
3949
|
-
|
|
3950
3591
|
case SelectedItemKeyDownNavigationPrevious:
|
|
3951
3592
|
changes = {
|
|
3952
3593
|
activeIndex: activeIndex - 1 < 0 ? 0 : activeIndex - 1
|
|
3953
3594
|
};
|
|
3954
3595
|
break;
|
|
3955
|
-
|
|
3956
3596
|
case SelectedItemKeyDownNavigationNext:
|
|
3957
3597
|
changes = {
|
|
3958
3598
|
activeIndex: activeIndex + 1 >= selectedItems.length ? -1 : activeIndex + 1
|
|
3959
3599
|
};
|
|
3960
3600
|
break;
|
|
3961
|
-
|
|
3962
3601
|
case SelectedItemKeyDownBackspace:
|
|
3963
3602
|
case SelectedItemKeyDownDelete:
|
|
3964
3603
|
{
|
|
3965
3604
|
let newActiveIndex = activeIndex;
|
|
3966
|
-
|
|
3967
3605
|
if (selectedItems.length === 1) {
|
|
3968
3606
|
newActiveIndex = -1;
|
|
3969
3607
|
} else if (activeIndex === selectedItems.length - 1) {
|
|
3970
3608
|
newActiveIndex = selectedItems.length - 2;
|
|
3971
3609
|
}
|
|
3972
|
-
|
|
3973
3610
|
changes = {
|
|
3974
3611
|
selectedItems: [...selectedItems.slice(0, activeIndex), ...selectedItems.slice(activeIndex + 1)],
|
|
3975
3612
|
...{
|
|
@@ -3978,52 +3615,43 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
3978
3615
|
};
|
|
3979
3616
|
break;
|
|
3980
3617
|
}
|
|
3981
|
-
|
|
3982
3618
|
case DropdownKeyDownNavigationPrevious:
|
|
3983
3619
|
changes = {
|
|
3984
3620
|
activeIndex: selectedItems.length - 1
|
|
3985
3621
|
};
|
|
3986
3622
|
break;
|
|
3987
|
-
|
|
3988
3623
|
case DropdownKeyDownBackspace:
|
|
3989
3624
|
changes = {
|
|
3990
3625
|
selectedItems: selectedItems.slice(0, selectedItems.length - 1)
|
|
3991
3626
|
};
|
|
3992
3627
|
break;
|
|
3993
|
-
|
|
3994
3628
|
case FunctionAddSelectedItem:
|
|
3995
3629
|
changes = {
|
|
3996
3630
|
selectedItems: [...selectedItems, selectedItem]
|
|
3997
3631
|
};
|
|
3998
3632
|
break;
|
|
3999
|
-
|
|
4000
3633
|
case DropdownClick:
|
|
4001
3634
|
changes = {
|
|
4002
3635
|
activeIndex: -1
|
|
4003
3636
|
};
|
|
4004
3637
|
break;
|
|
4005
|
-
|
|
4006
3638
|
case FunctionRemoveSelectedItem:
|
|
4007
3639
|
{
|
|
4008
3640
|
let newActiveIndex = activeIndex;
|
|
4009
3641
|
const selectedItemIndex = selectedItems.indexOf(selectedItem);
|
|
4010
|
-
|
|
4011
3642
|
if (selectedItemIndex >= 0) {
|
|
4012
3643
|
if (selectedItems.length === 1) {
|
|
4013
3644
|
newActiveIndex = -1;
|
|
4014
3645
|
} else if (selectedItemIndex === selectedItems.length - 1) {
|
|
4015
3646
|
newActiveIndex = selectedItems.length - 2;
|
|
4016
3647
|
}
|
|
4017
|
-
|
|
4018
3648
|
changes = {
|
|
4019
3649
|
selectedItems: [...selectedItems.slice(0, selectedItemIndex), ...selectedItems.slice(selectedItemIndex + 1)],
|
|
4020
3650
|
activeIndex: newActiveIndex
|
|
4021
3651
|
};
|
|
4022
3652
|
}
|
|
4023
|
-
|
|
4024
3653
|
break;
|
|
4025
3654
|
}
|
|
4026
|
-
|
|
4027
3655
|
case FunctionSetSelectedItems:
|
|
4028
3656
|
{
|
|
4029
3657
|
const {
|
|
@@ -4034,7 +3662,6 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
4034
3662
|
};
|
|
4035
3663
|
break;
|
|
4036
3664
|
}
|
|
4037
|
-
|
|
4038
3665
|
case FunctionSetActiveIndex:
|
|
4039
3666
|
{
|
|
4040
3667
|
const {
|
|
@@ -4045,33 +3672,30 @@ function downshiftMultipleSelectionReducer(state, action) {
|
|
|
4045
3672
|
};
|
|
4046
3673
|
break;
|
|
4047
3674
|
}
|
|
4048
|
-
|
|
4049
3675
|
case FunctionReset:
|
|
4050
3676
|
changes = {
|
|
4051
3677
|
activeIndex: getDefaultValue(props, 'activeIndex'),
|
|
4052
3678
|
selectedItems: getDefaultValue(props, 'selectedItems')
|
|
4053
3679
|
};
|
|
4054
3680
|
break;
|
|
4055
|
-
|
|
4056
3681
|
default:
|
|
4057
3682
|
throw new Error('Reducer called without proper action type.');
|
|
4058
3683
|
}
|
|
4059
|
-
|
|
4060
|
-
|
|
3684
|
+
return {
|
|
3685
|
+
...state,
|
|
4061
3686
|
...changes
|
|
4062
3687
|
};
|
|
4063
3688
|
}
|
|
4064
3689
|
|
|
4065
3690
|
useMultipleSelection.stateChangeTypes = stateChangeTypes;
|
|
4066
|
-
|
|
4067
3691
|
function useMultipleSelection(userProps) {
|
|
4068
3692
|
if (userProps === void 0) {
|
|
4069
3693
|
userProps = {};
|
|
4070
3694
|
}
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
3695
|
+
validatePropTypes(userProps, useMultipleSelection);
|
|
3696
|
+
// Props defaults and destructuring.
|
|
3697
|
+
const props = {
|
|
3698
|
+
...defaultProps,
|
|
4075
3699
|
...userProps
|
|
4076
3700
|
};
|
|
4077
3701
|
const {
|
|
@@ -4080,14 +3704,16 @@ function useMultipleSelection(userProps) {
|
|
|
4080
3704
|
environment,
|
|
4081
3705
|
keyNavigationNext,
|
|
4082
3706
|
keyNavigationPrevious
|
|
4083
|
-
} = props;
|
|
3707
|
+
} = props;
|
|
4084
3708
|
|
|
3709
|
+
// Reducer init.
|
|
4085
3710
|
const [state, dispatch] = useControlledReducer$1(downshiftMultipleSelectionReducer, getInitialState(props), props);
|
|
4086
3711
|
const {
|
|
4087
3712
|
activeIndex,
|
|
4088
3713
|
selectedItems
|
|
4089
|
-
} = state;
|
|
3714
|
+
} = state;
|
|
4090
3715
|
|
|
3716
|
+
// Refs.
|
|
4091
3717
|
const isInitialMountRef = react.useRef(true);
|
|
4092
3718
|
const dropdownRef = react.useRef(null);
|
|
4093
3719
|
const previousSelectedItemsRef = react.useRef(selectedItems);
|
|
@@ -4096,15 +3722,14 @@ function useMultipleSelection(userProps) {
|
|
|
4096
3722
|
const latest = useLatestRef({
|
|
4097
3723
|
state,
|
|
4098
3724
|
props
|
|
4099
|
-
});
|
|
3725
|
+
});
|
|
4100
3726
|
|
|
3727
|
+
// Effects.
|
|
4101
3728
|
/* Sets a11y status message on changes in selectedItem. */
|
|
4102
|
-
|
|
4103
3729
|
react.useEffect(() => {
|
|
4104
3730
|
if (isInitialMountRef.current) {
|
|
4105
3731
|
return;
|
|
4106
3732
|
}
|
|
4107
|
-
|
|
4108
3733
|
if (selectedItems.length < previousSelectedItemsRef.current.length) {
|
|
4109
3734
|
const removedSelectedItem = previousSelectedItemsRef.current.find(item => selectedItems.indexOf(item) < 0);
|
|
4110
3735
|
setStatus(getA11yRemovalMessage({
|
|
@@ -4115,15 +3740,15 @@ function useMultipleSelection(userProps) {
|
|
|
4115
3740
|
activeSelectedItem: selectedItems[activeIndex]
|
|
4116
3741
|
}), environment.document);
|
|
4117
3742
|
}
|
|
3743
|
+
previousSelectedItemsRef.current = selectedItems;
|
|
4118
3744
|
|
|
4119
|
-
|
|
4120
|
-
}, [selectedItems.length]);
|
|
4121
|
-
|
|
3745
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3746
|
+
}, [selectedItems.length]);
|
|
3747
|
+
// Sets focus on active item.
|
|
4122
3748
|
react.useEffect(() => {
|
|
4123
3749
|
if (isInitialMountRef.current) {
|
|
4124
3750
|
return;
|
|
4125
3751
|
}
|
|
4126
|
-
|
|
4127
3752
|
if (activeIndex === -1 && dropdownRef.current) {
|
|
4128
3753
|
dropdownRef.current.focus();
|
|
4129
3754
|
} else if (selectedItemRefs.current[activeIndex]) {
|
|
@@ -4135,37 +3760,34 @@ function useMultipleSelection(userProps) {
|
|
|
4135
3760
|
props,
|
|
4136
3761
|
state
|
|
4137
3762
|
});
|
|
4138
|
-
const setGetterPropCallInfo = useGetterPropsCalledChecker('getDropdownProps');
|
|
4139
|
-
|
|
3763
|
+
const setGetterPropCallInfo = useGetterPropsCalledChecker('getDropdownProps');
|
|
3764
|
+
// Make initial ref false.
|
|
4140
3765
|
react.useEffect(() => {
|
|
4141
3766
|
isInitialMountRef.current = false;
|
|
4142
|
-
}, []);
|
|
3767
|
+
}, []);
|
|
4143
3768
|
|
|
3769
|
+
// Event handler functions.
|
|
4144
3770
|
const selectedItemKeyDownHandlers = react.useMemo(() => ({
|
|
4145
3771
|
[keyNavigationPrevious]() {
|
|
4146
3772
|
dispatch({
|
|
4147
3773
|
type: SelectedItemKeyDownNavigationPrevious
|
|
4148
3774
|
});
|
|
4149
3775
|
},
|
|
4150
|
-
|
|
4151
3776
|
[keyNavigationNext]() {
|
|
4152
3777
|
dispatch({
|
|
4153
3778
|
type: SelectedItemKeyDownNavigationNext
|
|
4154
3779
|
});
|
|
4155
3780
|
},
|
|
4156
|
-
|
|
4157
3781
|
Delete() {
|
|
4158
3782
|
dispatch({
|
|
4159
3783
|
type: SelectedItemKeyDownDelete
|
|
4160
3784
|
});
|
|
4161
3785
|
},
|
|
4162
|
-
|
|
4163
3786
|
Backspace() {
|
|
4164
3787
|
dispatch({
|
|
4165
3788
|
type: SelectedItemKeyDownBackspace
|
|
4166
3789
|
});
|
|
4167
3790
|
}
|
|
4168
|
-
|
|
4169
3791
|
}), [dispatch, keyNavigationNext, keyNavigationPrevious]);
|
|
4170
3792
|
const dropdownKeyDownHandlers = react.useMemo(() => ({
|
|
4171
3793
|
[keyNavigationPrevious](event) {
|
|
@@ -4175,7 +3797,6 @@ function useMultipleSelection(userProps) {
|
|
|
4175
3797
|
});
|
|
4176
3798
|
}
|
|
4177
3799
|
},
|
|
4178
|
-
|
|
4179
3800
|
Backspace(event) {
|
|
4180
3801
|
if (isKeyDownOperationPermitted(event)) {
|
|
4181
3802
|
dispatch({
|
|
@@ -4183,9 +3804,9 @@ function useMultipleSelection(userProps) {
|
|
|
4183
3804
|
});
|
|
4184
3805
|
}
|
|
4185
3806
|
}
|
|
3807
|
+
}), [dispatch, keyNavigationPrevious]);
|
|
4186
3808
|
|
|
4187
|
-
|
|
4188
|
-
|
|
3809
|
+
// Getter props.
|
|
4189
3810
|
const getSelectedItemProps = react.useCallback(function (_temp) {
|
|
4190
3811
|
let {
|
|
4191
3812
|
refKey = 'ref',
|
|
@@ -4200,26 +3821,21 @@ function useMultipleSelection(userProps) {
|
|
|
4200
3821
|
state: latestState
|
|
4201
3822
|
} = latest.current;
|
|
4202
3823
|
const itemIndex = getItemIndex(index, selectedItem, latestState.selectedItems);
|
|
4203
|
-
|
|
4204
3824
|
if (itemIndex < 0) {
|
|
4205
3825
|
throw new Error('Pass either selectedItem or index in getSelectedItemProps!');
|
|
4206
3826
|
}
|
|
4207
|
-
|
|
4208
3827
|
const selectedItemHandleClick = () => {
|
|
4209
3828
|
dispatch({
|
|
4210
3829
|
type: SelectedItemClick,
|
|
4211
3830
|
index
|
|
4212
3831
|
});
|
|
4213
3832
|
};
|
|
4214
|
-
|
|
4215
3833
|
const selectedItemHandleKeyDown = event => {
|
|
4216
3834
|
const key = normalizeArrowKey(event);
|
|
4217
|
-
|
|
4218
3835
|
if (key && selectedItemKeyDownHandlers[key]) {
|
|
4219
3836
|
selectedItemKeyDownHandlers[key](event);
|
|
4220
3837
|
}
|
|
4221
3838
|
};
|
|
4222
|
-
|
|
4223
3839
|
return {
|
|
4224
3840
|
[refKey]: handleRefs(ref, selectedItemNode => {
|
|
4225
3841
|
if (selectedItemNode) {
|
|
@@ -4245,21 +3861,17 @@ function useMultipleSelection(userProps) {
|
|
|
4245
3861
|
suppressRefError = false
|
|
4246
3862
|
} = _temp3 === void 0 ? {} : _temp3;
|
|
4247
3863
|
setGetterPropCallInfo('getDropdownProps', suppressRefError, refKey, dropdownRef);
|
|
4248
|
-
|
|
4249
3864
|
const dropdownHandleKeyDown = event => {
|
|
4250
3865
|
const key = normalizeArrowKey(event);
|
|
4251
|
-
|
|
4252
3866
|
if (key && dropdownKeyDownHandlers[key]) {
|
|
4253
3867
|
dropdownKeyDownHandlers[key](event);
|
|
4254
3868
|
}
|
|
4255
3869
|
};
|
|
4256
|
-
|
|
4257
3870
|
const dropdownHandleClick = () => {
|
|
4258
3871
|
dispatch({
|
|
4259
3872
|
type: DropdownClick
|
|
4260
3873
|
});
|
|
4261
3874
|
};
|
|
4262
|
-
|
|
4263
3875
|
return {
|
|
4264
3876
|
[refKey]: handleRefs(ref, dropdownNode => {
|
|
4265
3877
|
if (dropdownNode) {
|
|
@@ -4272,8 +3884,9 @@ function useMultipleSelection(userProps) {
|
|
|
4272
3884
|
}),
|
|
4273
3885
|
...rest
|
|
4274
3886
|
};
|
|
4275
|
-
}, [dispatch, dropdownKeyDownHandlers, setGetterPropCallInfo]);
|
|
3887
|
+
}, [dispatch, dropdownKeyDownHandlers, setGetterPropCallInfo]);
|
|
4276
3888
|
|
|
3889
|
+
// returns
|
|
4277
3890
|
const addSelectedItem = react.useCallback(selectedItem => {
|
|
4278
3891
|
dispatch({
|
|
4279
3892
|
type: FunctionAddSelectedItem,
|