downshift 5.2.1 → 5.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "downshift",
3
- "version": "5.2.1",
3
+ "version": "5.2.2",
4
4
  "description": "A set of primitives to build simple, flexible, WAI-ARIA compliant React autocomplete components",
5
5
  "main": "dist/downshift.cjs.js",
6
6
  "react-native": "dist/downshift.native.cjs.js",
@@ -2231,25 +2231,26 @@ function useSelect(userProps) {
2231
2231
 
2232
2232
  var toggleButtonRef = preact.useRef(null);
2233
2233
  var menuRef = preact.useRef(null);
2234
- var isInitialMount = preact.useRef(true);
2235
- var shouldScroll = preact.useRef(true);
2236
- var clearTimeout = preact.useRef(null);
2237
- var mouseAndTouchTrackers = preact.useRef({
2234
+ var isInitialMountRef = preact.useRef(true);
2235
+ var shouldScrollRef = preact.useRef(true);
2236
+ var shouldBlurRef = preact.useRef(true);
2237
+ var clearTimeoutRef = preact.useRef(null);
2238
+ var mouseAndTouchTrackersRef = preact.useRef({
2238
2239
  isMouseDown: false,
2239
2240
  isTouchMove: false
2240
2241
  });
2241
- var elementIds = preact.useRef(getElementIds(props));
2242
+ var elementIdsRef = preact.useRef(getElementIds(props));
2242
2243
  var previousResultCountRef = preact.useRef(); // Some utils.
2243
2244
 
2244
2245
  var getItemNodeFromIndex = function (index) {
2245
- return environment.document.getElementById(elementIds.current.getItemId(index));
2246
+ return environment.document.getElementById(elementIdsRef.current.getItemId(index));
2246
2247
  }; // Effects.
2247
2248
 
2248
2249
  /* Sets a11y status message on changes in state. */
2249
2250
 
2250
2251
 
2251
2252
  preact.useEffect(function () {
2252
- if (isInitialMount.current) {
2253
+ if (isInitialMountRef.current) {
2253
2254
  return;
2254
2255
  }
2255
2256
 
@@ -2270,7 +2271,7 @@ function useSelect(userProps) {
2270
2271
  /* Sets a11y status message on changes in selectedItem. */
2271
2272
 
2272
2273
  preact.useEffect(function () {
2273
- if (isInitialMount.current) {
2274
+ if (isInitialMountRef.current) {
2274
2275
  return;
2275
2276
  }
2276
2277
 
@@ -2292,8 +2293,8 @@ function useSelect(userProps) {
2292
2293
 
2293
2294
  preact.useEffect(function () {
2294
2295
  // init the clean function here as we need access to dispatch.
2295
- if (isInitialMount.current) {
2296
- clearTimeout.current = debounce(function (outerDispatch) {
2296
+ if (isInitialMountRef.current) {
2297
+ clearTimeoutRef.current = debounce(function (outerDispatch) {
2297
2298
  outerDispatch({
2298
2299
  type: FunctionSetInputValue,
2299
2300
  inputValue: ''
@@ -2305,13 +2306,13 @@ function useSelect(userProps) {
2305
2306
  return;
2306
2307
  }
2307
2308
 
2308
- clearTimeout.current(dispatch); // eslint-disable-next-line react-hooks/exhaustive-deps
2309
+ clearTimeoutRef.current(dispatch); // eslint-disable-next-line react-hooks/exhaustive-deps
2309
2310
  }, [inputValue]);
2310
2311
  /* Controls the focus on the menu or the toggle button. */
2311
2312
 
2312
2313
  preact.useEffect(function () {
2313
2314
  // Don't focus menu on first render.
2314
- if (isInitialMount.current) {
2315
+ if (isInitialMountRef.current) {
2315
2316
  // Unless it was initialised as open.
2316
2317
  if ((initialIsOpen || defaultIsOpen || isOpen) && menuRef.current) {
2317
2318
  menuRef.current.focus();
@@ -2319,13 +2320,23 @@ function useSelect(userProps) {
2319
2320
 
2320
2321
  return;
2321
2322
  } // Focus menu on open.
2322
- // istanbul ignore next
2323
2323
 
2324
2324
 
2325
- if (isOpen && menuRef.current) {
2326
- menuRef.current.focus(); // Focus toggleButton on close.
2327
- } else if (environment.document.activeElement === menuRef.current && toggleButtonRef.current) {
2328
- toggleButtonRef.current.focus();
2325
+ if (isOpen) {
2326
+ // istanbul ignore else
2327
+ if (menuRef.current) {
2328
+ menuRef.current.focus();
2329
+ return;
2330
+ }
2331
+ } // Focus toggleButton on close, but on if was closed with (Shift+)Tab.
2332
+
2333
+
2334
+ if (environment.document.activeElement === menuRef.current) {
2335
+ // istanbul ignore else
2336
+ if (toggleButtonRef.current) {
2337
+ shouldBlurRef.current = false;
2338
+ toggleButtonRef.current.focus();
2339
+ }
2329
2340
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2330
2341
 
2331
2342
  }, [isOpen]);
@@ -2336,15 +2347,15 @@ function useSelect(userProps) {
2336
2347
  return;
2337
2348
  }
2338
2349
 
2339
- if (shouldScroll.current === false) {
2340
- shouldScroll.current = true;
2350
+ if (shouldScrollRef.current === false) {
2351
+ shouldScrollRef.current = true;
2341
2352
  } else {
2342
2353
  scrollIntoView(getItemNodeFromIndex(highlightedIndex), menuRef.current);
2343
2354
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2344
2355
 
2345
2356
  }, [highlightedIndex]);
2346
2357
  preact.useEffect(function () {
2347
- if (isInitialMount.current) {
2358
+ if (isInitialMountRef.current) {
2348
2359
  return;
2349
2360
  }
2350
2361
 
@@ -2353,7 +2364,7 @@ function useSelect(userProps) {
2353
2364
  /* Make initial ref false. */
2354
2365
 
2355
2366
  preact.useEffect(function () {
2356
- isInitialMount.current = false;
2367
+ isInitialMountRef.current = false;
2357
2368
  }, []);
2358
2369
  /* Add mouse/touch events to document. */
2359
2370
 
@@ -2361,11 +2372,11 @@ function useSelect(userProps) {
2361
2372
  // The same strategy for checking if a click occurred inside or outside downsift
2362
2373
  // as in downshift.js.
2363
2374
  var onMouseDown = function () {
2364
- mouseAndTouchTrackers.current.isMouseDown = true;
2375
+ mouseAndTouchTrackersRef.current.isMouseDown = true;
2365
2376
  };
2366
2377
 
2367
2378
  var onMouseUp = function (event) {
2368
- mouseAndTouchTrackers.current.isMouseDown = false;
2379
+ mouseAndTouchTrackersRef.current.isMouseDown = false;
2369
2380
 
2370
2381
  if (isOpen && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document)) {
2371
2382
  dispatch({
@@ -2375,15 +2386,15 @@ function useSelect(userProps) {
2375
2386
  };
2376
2387
 
2377
2388
  var onTouchStart = function () {
2378
- mouseAndTouchTrackers.current.isTouchMove = false;
2389
+ mouseAndTouchTrackersRef.current.isTouchMove = false;
2379
2390
  };
2380
2391
 
2381
2392
  var onTouchMove = function () {
2382
- mouseAndTouchTrackers.current.isTouchMove = true;
2393
+ mouseAndTouchTrackersRef.current.isTouchMove = true;
2383
2394
  };
2384
2395
 
2385
2396
  var onTouchEnd = function (event) {
2386
- if (isOpen && !mouseAndTouchTrackers.current.isTouchMove && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document, false)) {
2397
+ if (isOpen && !mouseAndTouchTrackersRef.current.isTouchMove && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document, false)) {
2387
2398
  dispatch({
2388
2399
  type: MenuBlur
2389
2400
  });
@@ -2487,7 +2498,13 @@ function useSelect(userProps) {
2487
2498
  };
2488
2499
 
2489
2500
  var menuHandleBlur = function () {
2490
- var shouldBlur = !mouseAndTouchTrackers.current.isMouseDown;
2501
+ // if the blur was a result of selection, we don't trigger this action.
2502
+ if (shouldBlurRef.current === false) {
2503
+ shouldBlurRef.current = true;
2504
+ return;
2505
+ }
2506
+
2507
+ var shouldBlur = !mouseAndTouchTrackersRef.current.isMouseDown;
2491
2508
  /* istanbul ignore else */
2492
2509
 
2493
2510
  if (shouldBlur) {
@@ -2528,7 +2545,7 @@ function useSelect(userProps) {
2528
2545
  return;
2529
2546
  }
2530
2547
 
2531
- shouldScroll.current = false;
2548
+ shouldScrollRef.current = false;
2532
2549
  dispatch({
2533
2550
  type: ItemMouseMove,
2534
2551
  index: index
@@ -2558,7 +2575,7 @@ function useSelect(userProps) {
2558
2575
 
2559
2576
  var toggleProps = _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (toggleButtonNode) {
2560
2577
  toggleButtonRef.current = toggleButtonNode;
2561
- }), _extends3.id = elementIds.current.toggleButtonId, _extends3['aria-haspopup'] = 'listbox', _extends3['aria-expanded'] = isOpen, _extends3['aria-labelledby'] = elementIds.current.labelId + " " + elementIds.current.toggleButtonId, _extends3), rest);
2578
+ }), _extends3.id = elementIdsRef.current.toggleButtonId, _extends3['aria-haspopup'] = 'listbox', _extends3['aria-expanded'] = isOpen, _extends3['aria-labelledby'] = elementIdsRef.current.labelId + " " + elementIdsRef.current.toggleButtonId, _extends3), rest);
2562
2579
 
2563
2580
  if (!rest.disabled) {
2564
2581
  toggleProps.onClick = callAllEventHandlers(onClick, toggleButtonHandleClick);
@@ -2569,8 +2586,8 @@ function useSelect(userProps) {
2569
2586
  },
2570
2587
  getLabelProps: function getLabelProps(labelProps) {
2571
2588
  return _extends({
2572
- id: elementIds.current.labelId,
2573
- htmlFor: elementIds.current.toggleButtonId
2589
+ id: elementIdsRef.current.labelId,
2590
+ htmlFor: elementIdsRef.current.toggleButtonId
2574
2591
  }, labelProps);
2575
2592
  },
2576
2593
  getMenuProps: function getMenuProps(_temp) {
@@ -2587,8 +2604,8 @@ function useSelect(userProps) {
2587
2604
 
2588
2605
  return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, function (menuNode) {
2589
2606
  menuRef.current = menuNode;
2590
- }), _extends2.id = elementIds.current.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = elementIds.current.labelId, _extends2.tabIndex = -1, _extends2), isOpen && highlightedIndex > -1 && {
2591
- 'aria-activedescendant': elementIds.current.getItemId(highlightedIndex)
2607
+ }), _extends2.id = elementIdsRef.current.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = elementIdsRef.current.labelId, _extends2.tabIndex = -1, _extends2), isOpen && highlightedIndex > -1 && {
2608
+ 'aria-activedescendant': elementIdsRef.current.getItemId(highlightedIndex)
2592
2609
  }, {
2593
2610
  onMouseLeave: callAllEventHandlers(onMouseLeave, menuHandleMouseLeave),
2594
2611
  onKeyDown: callAllEventHandlers(onKeyDown, menuHandleKeyDown),
@@ -2612,7 +2629,7 @@ function useSelect(userProps) {
2612
2629
  var itemProps = _extends({
2613
2630
  role: 'option',
2614
2631
  'aria-selected': "" + (itemIndex === highlightedIndex),
2615
- id: elementIds.current.getItemId(itemIndex)
2632
+ id: elementIdsRef.current.getItemId(itemIndex)
2616
2633
  }, rest);
2617
2634
 
2618
2635
  if (!rest.disabled) {
@@ -2225,25 +2225,26 @@ function useSelect(userProps) {
2225
2225
 
2226
2226
  var toggleButtonRef = useRef(null);
2227
2227
  var menuRef = useRef(null);
2228
- var isInitialMount = useRef(true);
2229
- var shouldScroll = useRef(true);
2230
- var clearTimeout = useRef(null);
2231
- var mouseAndTouchTrackers = useRef({
2228
+ var isInitialMountRef = useRef(true);
2229
+ var shouldScrollRef = useRef(true);
2230
+ var shouldBlurRef = useRef(true);
2231
+ var clearTimeoutRef = useRef(null);
2232
+ var mouseAndTouchTrackersRef = useRef({
2232
2233
  isMouseDown: false,
2233
2234
  isTouchMove: false
2234
2235
  });
2235
- var elementIds = useRef(getElementIds(props));
2236
+ var elementIdsRef = useRef(getElementIds(props));
2236
2237
  var previousResultCountRef = useRef(); // Some utils.
2237
2238
 
2238
2239
  var getItemNodeFromIndex = function (index) {
2239
- return environment.document.getElementById(elementIds.current.getItemId(index));
2240
+ return environment.document.getElementById(elementIdsRef.current.getItemId(index));
2240
2241
  }; // Effects.
2241
2242
 
2242
2243
  /* Sets a11y status message on changes in state. */
2243
2244
 
2244
2245
 
2245
2246
  useEffect(function () {
2246
- if (isInitialMount.current) {
2247
+ if (isInitialMountRef.current) {
2247
2248
  return;
2248
2249
  }
2249
2250
 
@@ -2264,7 +2265,7 @@ function useSelect(userProps) {
2264
2265
  /* Sets a11y status message on changes in selectedItem. */
2265
2266
 
2266
2267
  useEffect(function () {
2267
- if (isInitialMount.current) {
2268
+ if (isInitialMountRef.current) {
2268
2269
  return;
2269
2270
  }
2270
2271
 
@@ -2286,8 +2287,8 @@ function useSelect(userProps) {
2286
2287
 
2287
2288
  useEffect(function () {
2288
2289
  // init the clean function here as we need access to dispatch.
2289
- if (isInitialMount.current) {
2290
- clearTimeout.current = debounce(function (outerDispatch) {
2290
+ if (isInitialMountRef.current) {
2291
+ clearTimeoutRef.current = debounce(function (outerDispatch) {
2291
2292
  outerDispatch({
2292
2293
  type: FunctionSetInputValue,
2293
2294
  inputValue: ''
@@ -2299,13 +2300,13 @@ function useSelect(userProps) {
2299
2300
  return;
2300
2301
  }
2301
2302
 
2302
- clearTimeout.current(dispatch); // eslint-disable-next-line react-hooks/exhaustive-deps
2303
+ clearTimeoutRef.current(dispatch); // eslint-disable-next-line react-hooks/exhaustive-deps
2303
2304
  }, [inputValue]);
2304
2305
  /* Controls the focus on the menu or the toggle button. */
2305
2306
 
2306
2307
  useEffect(function () {
2307
2308
  // Don't focus menu on first render.
2308
- if (isInitialMount.current) {
2309
+ if (isInitialMountRef.current) {
2309
2310
  // Unless it was initialised as open.
2310
2311
  if ((initialIsOpen || defaultIsOpen || isOpen) && menuRef.current) {
2311
2312
  menuRef.current.focus();
@@ -2313,13 +2314,23 @@ function useSelect(userProps) {
2313
2314
 
2314
2315
  return;
2315
2316
  } // Focus menu on open.
2316
- // istanbul ignore next
2317
2317
 
2318
2318
 
2319
- if (isOpen && menuRef.current) {
2320
- menuRef.current.focus(); // Focus toggleButton on close.
2321
- } else if (environment.document.activeElement === menuRef.current && toggleButtonRef.current) {
2322
- toggleButtonRef.current.focus();
2319
+ if (isOpen) {
2320
+ // istanbul ignore else
2321
+ if (menuRef.current) {
2322
+ menuRef.current.focus();
2323
+ return;
2324
+ }
2325
+ } // Focus toggleButton on close, but on if was closed with (Shift+)Tab.
2326
+
2327
+
2328
+ if (environment.document.activeElement === menuRef.current) {
2329
+ // istanbul ignore else
2330
+ if (toggleButtonRef.current) {
2331
+ shouldBlurRef.current = false;
2332
+ toggleButtonRef.current.focus();
2333
+ }
2323
2334
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2324
2335
 
2325
2336
  }, [isOpen]);
@@ -2330,15 +2341,15 @@ function useSelect(userProps) {
2330
2341
  return;
2331
2342
  }
2332
2343
 
2333
- if (shouldScroll.current === false) {
2334
- shouldScroll.current = true;
2344
+ if (shouldScrollRef.current === false) {
2345
+ shouldScrollRef.current = true;
2335
2346
  } else {
2336
2347
  scrollIntoView(getItemNodeFromIndex(highlightedIndex), menuRef.current);
2337
2348
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2338
2349
 
2339
2350
  }, [highlightedIndex]);
2340
2351
  useEffect(function () {
2341
- if (isInitialMount.current) {
2352
+ if (isInitialMountRef.current) {
2342
2353
  return;
2343
2354
  }
2344
2355
 
@@ -2347,7 +2358,7 @@ function useSelect(userProps) {
2347
2358
  /* Make initial ref false. */
2348
2359
 
2349
2360
  useEffect(function () {
2350
- isInitialMount.current = false;
2361
+ isInitialMountRef.current = false;
2351
2362
  }, []);
2352
2363
  /* Add mouse/touch events to document. */
2353
2364
 
@@ -2355,11 +2366,11 @@ function useSelect(userProps) {
2355
2366
  // The same strategy for checking if a click occurred inside or outside downsift
2356
2367
  // as in downshift.js.
2357
2368
  var onMouseDown = function () {
2358
- mouseAndTouchTrackers.current.isMouseDown = true;
2369
+ mouseAndTouchTrackersRef.current.isMouseDown = true;
2359
2370
  };
2360
2371
 
2361
2372
  var onMouseUp = function (event) {
2362
- mouseAndTouchTrackers.current.isMouseDown = false;
2373
+ mouseAndTouchTrackersRef.current.isMouseDown = false;
2363
2374
 
2364
2375
  if (isOpen && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document)) {
2365
2376
  dispatch({
@@ -2369,15 +2380,15 @@ function useSelect(userProps) {
2369
2380
  };
2370
2381
 
2371
2382
  var onTouchStart = function () {
2372
- mouseAndTouchTrackers.current.isTouchMove = false;
2383
+ mouseAndTouchTrackersRef.current.isTouchMove = false;
2373
2384
  };
2374
2385
 
2375
2386
  var onTouchMove = function () {
2376
- mouseAndTouchTrackers.current.isTouchMove = true;
2387
+ mouseAndTouchTrackersRef.current.isTouchMove = true;
2377
2388
  };
2378
2389
 
2379
2390
  var onTouchEnd = function (event) {
2380
- if (isOpen && !mouseAndTouchTrackers.current.isTouchMove && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document, false)) {
2391
+ if (isOpen && !mouseAndTouchTrackersRef.current.isTouchMove && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document, false)) {
2381
2392
  dispatch({
2382
2393
  type: MenuBlur
2383
2394
  });
@@ -2481,7 +2492,13 @@ function useSelect(userProps) {
2481
2492
  };
2482
2493
 
2483
2494
  var menuHandleBlur = function () {
2484
- var shouldBlur = !mouseAndTouchTrackers.current.isMouseDown;
2495
+ // if the blur was a result of selection, we don't trigger this action.
2496
+ if (shouldBlurRef.current === false) {
2497
+ shouldBlurRef.current = true;
2498
+ return;
2499
+ }
2500
+
2501
+ var shouldBlur = !mouseAndTouchTrackersRef.current.isMouseDown;
2485
2502
  /* istanbul ignore else */
2486
2503
 
2487
2504
  if (shouldBlur) {
@@ -2522,7 +2539,7 @@ function useSelect(userProps) {
2522
2539
  return;
2523
2540
  }
2524
2541
 
2525
- shouldScroll.current = false;
2542
+ shouldScrollRef.current = false;
2526
2543
  dispatch({
2527
2544
  type: ItemMouseMove,
2528
2545
  index: index
@@ -2552,7 +2569,7 @@ function useSelect(userProps) {
2552
2569
 
2553
2570
  var toggleProps = _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (toggleButtonNode) {
2554
2571
  toggleButtonRef.current = toggleButtonNode;
2555
- }), _extends3.id = elementIds.current.toggleButtonId, _extends3['aria-haspopup'] = 'listbox', _extends3['aria-expanded'] = isOpen, _extends3['aria-labelledby'] = elementIds.current.labelId + " " + elementIds.current.toggleButtonId, _extends3), rest);
2572
+ }), _extends3.id = elementIdsRef.current.toggleButtonId, _extends3['aria-haspopup'] = 'listbox', _extends3['aria-expanded'] = isOpen, _extends3['aria-labelledby'] = elementIdsRef.current.labelId + " " + elementIdsRef.current.toggleButtonId, _extends3), rest);
2556
2573
 
2557
2574
  if (!rest.disabled) {
2558
2575
  toggleProps.onClick = callAllEventHandlers(onClick, toggleButtonHandleClick);
@@ -2563,8 +2580,8 @@ function useSelect(userProps) {
2563
2580
  },
2564
2581
  getLabelProps: function getLabelProps(labelProps) {
2565
2582
  return _extends({
2566
- id: elementIds.current.labelId,
2567
- htmlFor: elementIds.current.toggleButtonId
2583
+ id: elementIdsRef.current.labelId,
2584
+ htmlFor: elementIdsRef.current.toggleButtonId
2568
2585
  }, labelProps);
2569
2586
  },
2570
2587
  getMenuProps: function getMenuProps(_temp) {
@@ -2581,8 +2598,8 @@ function useSelect(userProps) {
2581
2598
 
2582
2599
  return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, function (menuNode) {
2583
2600
  menuRef.current = menuNode;
2584
- }), _extends2.id = elementIds.current.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = elementIds.current.labelId, _extends2.tabIndex = -1, _extends2), isOpen && highlightedIndex > -1 && {
2585
- 'aria-activedescendant': elementIds.current.getItemId(highlightedIndex)
2601
+ }), _extends2.id = elementIdsRef.current.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = elementIdsRef.current.labelId, _extends2.tabIndex = -1, _extends2), isOpen && highlightedIndex > -1 && {
2602
+ 'aria-activedescendant': elementIdsRef.current.getItemId(highlightedIndex)
2586
2603
  }, {
2587
2604
  onMouseLeave: callAllEventHandlers(onMouseLeave, menuHandleMouseLeave),
2588
2605
  onKeyDown: callAllEventHandlers(onKeyDown, menuHandleKeyDown),
@@ -2606,7 +2623,7 @@ function useSelect(userProps) {
2606
2623
  var itemProps = _extends({
2607
2624
  role: 'option',
2608
2625
  'aria-selected': "" + (itemIndex === highlightedIndex),
2609
- id: elementIds.current.getItemId(itemIndex)
2626
+ id: elementIdsRef.current.getItemId(itemIndex)
2610
2627
  }, rest);
2611
2628
 
2612
2629
  if (!rest.disabled) {
@@ -2667,25 +2667,26 @@
2667
2667
 
2668
2668
  var toggleButtonRef = preact.useRef(null);
2669
2669
  var menuRef = preact.useRef(null);
2670
- var isInitialMount = preact.useRef(true);
2671
- var shouldScroll = preact.useRef(true);
2672
- var clearTimeout = preact.useRef(null);
2673
- var mouseAndTouchTrackers = preact.useRef({
2670
+ var isInitialMountRef = preact.useRef(true);
2671
+ var shouldScrollRef = preact.useRef(true);
2672
+ var shouldBlurRef = preact.useRef(true);
2673
+ var clearTimeoutRef = preact.useRef(null);
2674
+ var mouseAndTouchTrackersRef = preact.useRef({
2674
2675
  isMouseDown: false,
2675
2676
  isTouchMove: false
2676
2677
  });
2677
- var elementIds = preact.useRef(getElementIds(props));
2678
+ var elementIdsRef = preact.useRef(getElementIds(props));
2678
2679
  var previousResultCountRef = preact.useRef(); // Some utils.
2679
2680
 
2680
2681
  var getItemNodeFromIndex = function (index) {
2681
- return environment.document.getElementById(elementIds.current.getItemId(index));
2682
+ return environment.document.getElementById(elementIdsRef.current.getItemId(index));
2682
2683
  }; // Effects.
2683
2684
 
2684
2685
  /* Sets a11y status message on changes in state. */
2685
2686
 
2686
2687
 
2687
2688
  preact.useEffect(function () {
2688
- if (isInitialMount.current) {
2689
+ if (isInitialMountRef.current) {
2689
2690
  return;
2690
2691
  }
2691
2692
 
@@ -2706,7 +2707,7 @@
2706
2707
  /* Sets a11y status message on changes in selectedItem. */
2707
2708
 
2708
2709
  preact.useEffect(function () {
2709
- if (isInitialMount.current) {
2710
+ if (isInitialMountRef.current) {
2710
2711
  return;
2711
2712
  }
2712
2713
 
@@ -2728,8 +2729,8 @@
2728
2729
 
2729
2730
  preact.useEffect(function () {
2730
2731
  // init the clean function here as we need access to dispatch.
2731
- if (isInitialMount.current) {
2732
- clearTimeout.current = debounce(function (outerDispatch) {
2732
+ if (isInitialMountRef.current) {
2733
+ clearTimeoutRef.current = debounce(function (outerDispatch) {
2733
2734
  outerDispatch({
2734
2735
  type: FunctionSetInputValue,
2735
2736
  inputValue: ''
@@ -2741,13 +2742,13 @@
2741
2742
  return;
2742
2743
  }
2743
2744
 
2744
- clearTimeout.current(dispatch); // eslint-disable-next-line react-hooks/exhaustive-deps
2745
+ clearTimeoutRef.current(dispatch); // eslint-disable-next-line react-hooks/exhaustive-deps
2745
2746
  }, [inputValue]);
2746
2747
  /* Controls the focus on the menu or the toggle button. */
2747
2748
 
2748
2749
  preact.useEffect(function () {
2749
2750
  // Don't focus menu on first render.
2750
- if (isInitialMount.current) {
2751
+ if (isInitialMountRef.current) {
2751
2752
  // Unless it was initialised as open.
2752
2753
  if ((initialIsOpen || defaultIsOpen || isOpen) && menuRef.current) {
2753
2754
  menuRef.current.focus();
@@ -2755,13 +2756,23 @@
2755
2756
 
2756
2757
  return;
2757
2758
  } // Focus menu on open.
2758
- // istanbul ignore next
2759
2759
 
2760
2760
 
2761
- if (isOpen && menuRef.current) {
2762
- menuRef.current.focus(); // Focus toggleButton on close.
2763
- } else if (environment.document.activeElement === menuRef.current && toggleButtonRef.current) {
2764
- toggleButtonRef.current.focus();
2761
+ if (isOpen) {
2762
+ // istanbul ignore else
2763
+ if (menuRef.current) {
2764
+ menuRef.current.focus();
2765
+ return;
2766
+ }
2767
+ } // Focus toggleButton on close, but on if was closed with (Shift+)Tab.
2768
+
2769
+
2770
+ if (environment.document.activeElement === menuRef.current) {
2771
+ // istanbul ignore else
2772
+ if (toggleButtonRef.current) {
2773
+ shouldBlurRef.current = false;
2774
+ toggleButtonRef.current.focus();
2775
+ }
2765
2776
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2766
2777
 
2767
2778
  }, [isOpen]);
@@ -2772,15 +2783,15 @@
2772
2783
  return;
2773
2784
  }
2774
2785
 
2775
- if (shouldScroll.current === false) {
2776
- shouldScroll.current = true;
2786
+ if (shouldScrollRef.current === false) {
2787
+ shouldScrollRef.current = true;
2777
2788
  } else {
2778
2789
  scrollIntoView(getItemNodeFromIndex(highlightedIndex), menuRef.current);
2779
2790
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2780
2791
 
2781
2792
  }, [highlightedIndex]);
2782
2793
  preact.useEffect(function () {
2783
- if (isInitialMount.current) {
2794
+ if (isInitialMountRef.current) {
2784
2795
  return;
2785
2796
  }
2786
2797
 
@@ -2789,7 +2800,7 @@
2789
2800
  /* Make initial ref false. */
2790
2801
 
2791
2802
  preact.useEffect(function () {
2792
- isInitialMount.current = false;
2803
+ isInitialMountRef.current = false;
2793
2804
  }, []);
2794
2805
  /* Add mouse/touch events to document. */
2795
2806
 
@@ -2797,11 +2808,11 @@
2797
2808
  // The same strategy for checking if a click occurred inside or outside downsift
2798
2809
  // as in downshift.js.
2799
2810
  var onMouseDown = function () {
2800
- mouseAndTouchTrackers.current.isMouseDown = true;
2811
+ mouseAndTouchTrackersRef.current.isMouseDown = true;
2801
2812
  };
2802
2813
 
2803
2814
  var onMouseUp = function (event) {
2804
- mouseAndTouchTrackers.current.isMouseDown = false;
2815
+ mouseAndTouchTrackersRef.current.isMouseDown = false;
2805
2816
 
2806
2817
  if (isOpen && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document)) {
2807
2818
  dispatch({
@@ -2811,15 +2822,15 @@
2811
2822
  };
2812
2823
 
2813
2824
  var onTouchStart = function () {
2814
- mouseAndTouchTrackers.current.isTouchMove = false;
2825
+ mouseAndTouchTrackersRef.current.isTouchMove = false;
2815
2826
  };
2816
2827
 
2817
2828
  var onTouchMove = function () {
2818
- mouseAndTouchTrackers.current.isTouchMove = true;
2829
+ mouseAndTouchTrackersRef.current.isTouchMove = true;
2819
2830
  };
2820
2831
 
2821
2832
  var onTouchEnd = function (event) {
2822
- if (isOpen && !mouseAndTouchTrackers.current.isTouchMove && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document, false)) {
2833
+ if (isOpen && !mouseAndTouchTrackersRef.current.isTouchMove && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document, false)) {
2823
2834
  dispatch({
2824
2835
  type: MenuBlur
2825
2836
  });
@@ -2923,7 +2934,13 @@
2923
2934
  };
2924
2935
 
2925
2936
  var menuHandleBlur = function () {
2926
- var shouldBlur = !mouseAndTouchTrackers.current.isMouseDown;
2937
+ // if the blur was a result of selection, we don't trigger this action.
2938
+ if (shouldBlurRef.current === false) {
2939
+ shouldBlurRef.current = true;
2940
+ return;
2941
+ }
2942
+
2943
+ var shouldBlur = !mouseAndTouchTrackersRef.current.isMouseDown;
2927
2944
  /* istanbul ignore else */
2928
2945
 
2929
2946
  if (shouldBlur) {
@@ -2964,7 +2981,7 @@
2964
2981
  return;
2965
2982
  }
2966
2983
 
2967
- shouldScroll.current = false;
2984
+ shouldScrollRef.current = false;
2968
2985
  dispatch({
2969
2986
  type: ItemMouseMove,
2970
2987
  index: index
@@ -2994,7 +3011,7 @@
2994
3011
 
2995
3012
  var toggleProps = _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (toggleButtonNode) {
2996
3013
  toggleButtonRef.current = toggleButtonNode;
2997
- }), _extends3.id = elementIds.current.toggleButtonId, _extends3['aria-haspopup'] = 'listbox', _extends3['aria-expanded'] = isOpen, _extends3['aria-labelledby'] = elementIds.current.labelId + " " + elementIds.current.toggleButtonId, _extends3), rest);
3014
+ }), _extends3.id = elementIdsRef.current.toggleButtonId, _extends3['aria-haspopup'] = 'listbox', _extends3['aria-expanded'] = isOpen, _extends3['aria-labelledby'] = elementIdsRef.current.labelId + " " + elementIdsRef.current.toggleButtonId, _extends3), rest);
2998
3015
 
2999
3016
  if (!rest.disabled) {
3000
3017
  toggleProps.onClick = callAllEventHandlers(onClick, toggleButtonHandleClick);
@@ -3005,8 +3022,8 @@
3005
3022
  },
3006
3023
  getLabelProps: function getLabelProps(labelProps) {
3007
3024
  return _extends({
3008
- id: elementIds.current.labelId,
3009
- htmlFor: elementIds.current.toggleButtonId
3025
+ id: elementIdsRef.current.labelId,
3026
+ htmlFor: elementIdsRef.current.toggleButtonId
3010
3027
  }, labelProps);
3011
3028
  },
3012
3029
  getMenuProps: function getMenuProps(_temp) {
@@ -3023,8 +3040,8 @@
3023
3040
 
3024
3041
  return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, function (menuNode) {
3025
3042
  menuRef.current = menuNode;
3026
- }), _extends2.id = elementIds.current.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = elementIds.current.labelId, _extends2.tabIndex = -1, _extends2), isOpen && highlightedIndex > -1 && {
3027
- 'aria-activedescendant': elementIds.current.getItemId(highlightedIndex)
3043
+ }), _extends2.id = elementIdsRef.current.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = elementIdsRef.current.labelId, _extends2.tabIndex = -1, _extends2), isOpen && highlightedIndex > -1 && {
3044
+ 'aria-activedescendant': elementIdsRef.current.getItemId(highlightedIndex)
3028
3045
  }, {
3029
3046
  onMouseLeave: callAllEventHandlers(onMouseLeave, menuHandleMouseLeave),
3030
3047
  onKeyDown: callAllEventHandlers(onKeyDown, menuHandleKeyDown),
@@ -3048,7 +3065,7 @@
3048
3065
  var itemProps = _extends({
3049
3066
  role: 'option',
3050
3067
  'aria-selected': "" + (itemIndex === highlightedIndex),
3051
- id: elementIds.current.getItemId(itemIndex)
3068
+ id: elementIdsRef.current.getItemId(itemIndex)
3052
3069
  }, rest);
3053
3070
 
3054
3071
  if (!rest.disabled) {