@jsenv/navi 0.29.9 → 0.29.10

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.
@@ -1663,6 +1663,11 @@ const generateSignalId = () => {
1663
1663
  * @param {"string" | "number" | "boolean" | "object"} [options.type="string"] - Type for localStorage serialization/deserialization
1664
1664
  * @param {number} [options.step] - For number type: step size for precision. Values will be rounded to nearest multiple of step.
1665
1665
  * @param {Array} [options.oneOf] - Array of valid values for validation. Signal will be marked invalid if value is not in this array
1666
+ * @param {boolean} [options.weak=false] - The param qualifies one visit, not the screen: it is written into a
1667
+ * url only when explicitly named (`routeParams={{ edit: id }}`), never inherited from the signal's current
1668
+ * value, and it goes back to the default value when the route stops matching. Use it for params like an
1669
+ * "edit this one" id, where every other link to the screen must lead to the plain screen.
1670
+ * Incompatible with `persists` (throws).
1666
1671
  * @param {boolean} [options.debug=false] - Enable debug logging for this signal's operations
1667
1672
  * @returns {import("@preact/signals").Signal} A signal that can be synchronized with a source signal and/or persisted in localStorage. The signal includes a `validity` property for validation state.
1668
1673
  *
@@ -1735,8 +1740,15 @@ const stateSignal = (defaultValue, options = {}) => {
1735
1740
  default: staticFallback,
1736
1741
  ignoreArrayOrder,
1737
1742
  autoFix,
1743
+ weak = false,
1738
1744
  } = options;
1739
1745
 
1746
+ if (weak && persists) {
1747
+ throw new TypeError(
1748
+ `stateSignal "${id}": weak and persists are contradictory — a weak param qualifies one visit, it cannot be restored from a previous session.`,
1749
+ );
1750
+ }
1751
+
1740
1752
  // Check if defaultValue is a signal (dynamic default) or static value
1741
1753
  const isDynamicDefault =
1742
1754
  defaultValue &&
@@ -2099,6 +2111,23 @@ setBaseUrl(
2099
2111
  : window.location.origin,
2100
2112
  );
2101
2113
 
2114
+ /**
2115
+ * The single place where "this param was not provided, take the signal value"
2116
+ * happens while building a url. A weak param qualifies one visit, not the
2117
+ * screen: it enters a url only when the caller names it (or when it is already
2118
+ * in the url being preserved), so here it always reads as absent.
2119
+ * Not reading the signal also keeps the built url from depending on it.
2120
+ */
2121
+ const readSignalForUrlBuild = (connection) => {
2122
+ if (!connection || !connection.signal) {
2123
+ return undefined;
2124
+ }
2125
+ if (connection.weak) {
2126
+ return undefined;
2127
+ }
2128
+ return connection.signal.value;
2129
+ };
2130
+
2102
2131
  /**
2103
2132
  * Creates a custom route pattern matcher
2104
2133
  */
@@ -2173,7 +2202,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2173
2202
  // Parameter was explicitly provided - always respect explicit parameters
2174
2203
  continue;
2175
2204
  }
2176
- const signalValue = connection.signal.value;
2205
+ const signalValue = readSignalForUrlBuild(connection);
2177
2206
  if (signalValue !== undefined) {
2178
2207
  // Parameter was not provided, check signal value
2179
2208
  resolvedParams[paramName] = signalValue;
@@ -2186,7 +2215,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2186
2215
  // Parameter was explicitly provided - always respect explicit parameters
2187
2216
  continue;
2188
2217
  }
2189
- const signalValue = connection.signal.value;
2218
+ const signalValue = readSignalForUrlBuild(connection);
2190
2219
  if (signalValue !== undefined) {
2191
2220
  // Parameter was not provided, check signal value
2192
2221
  resolvedParams[paramName] = signalValue;
@@ -2229,7 +2258,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2229
2258
  continue;
2230
2259
  }
2231
2260
 
2232
- const ancestorSignalValue = ancestorConnection.signal.value;
2261
+ const ancestorSignalValue = readSignalForUrlBuild(ancestorConnection);
2233
2262
  if (
2234
2263
  ancestorSignalValue !== undefined &&
2235
2264
  ancestorSignalValue !== ancestorConnection.getDefaultValue()
@@ -2307,7 +2336,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2307
2336
  if (childParam in resolvedParams) {
2308
2337
  continue;
2309
2338
  }
2310
- const childSignalValue = childConnection.signal.value;
2339
+ const childSignalValue = readSignalForUrlBuild(childConnection);
2311
2340
  // Only include if not already resolved and is non-default
2312
2341
  if (
2313
2342
  childSignalValue !== undefined &&
@@ -2349,7 +2378,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2349
2378
  }
2350
2379
  } else {
2351
2380
  // Parameter not provided but signal has a value
2352
- const signalValue = connection.signal.value;
2381
+ const signalValue = readSignalForUrlBuild(connection);
2353
2382
  if (connection.isCustomValue(signalValue)) {
2354
2383
  // Only include custom values
2355
2384
  filtered[paramName] = signalValue;
@@ -2368,7 +2397,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2368
2397
  }
2369
2398
  } else {
2370
2399
  // Parameter not provided but signal has a value
2371
- const signalValue = connection.signal.value;
2400
+ const signalValue = readSignalForUrlBuild(connection);
2372
2401
  if (connection.isCustomValue(signalValue)) {
2373
2402
  // Only include custom values
2374
2403
  filtered[paramName] = signalValue;
@@ -2385,7 +2414,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2385
2414
  const canReachLiteralValue = (literalValue, params, literalPosition) => {
2386
2415
  // Check parent's own parameters (signals and user params)
2387
2416
  const parentCanProvide = connections.some((conn) => {
2388
- const signalValue = conn.signal.value;
2417
+ const signalValue = readSignalForUrlBuild(conn);
2389
2418
  const userValue = params[conn.paramName];
2390
2419
  const effectiveValue = userValue !== undefined ? userValue : signalValue;
2391
2420
  return (
@@ -2414,7 +2443,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2414
2443
  return false;
2415
2444
  }
2416
2445
  return connsAtPosition.some((conn) => {
2417
- const signalValue = conn.signal.value;
2446
+ const signalValue = readSignalForUrlBuild(conn);
2418
2447
  return signalValue === literalValue && conn.isCustomValue(signalValue);
2419
2448
  });
2420
2449
  };
@@ -2469,7 +2498,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2469
2498
  pathConnectionMap.get(paramName) ||
2470
2499
  queryConnectionMap.get(paramName);
2471
2500
  if (parentConnection) {
2472
- parentParamValue = parentConnection.signal.value;
2501
+ parentParamValue = readSignalForUrlBuild(parentConnection);
2473
2502
  }
2474
2503
  }
2475
2504
 
@@ -2554,7 +2583,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2554
2583
  paramValue = item.userValue;
2555
2584
  } else {
2556
2585
  paramName = item.paramName;
2557
- paramValue = item.signal.value;
2586
+ paramValue = readSignalForUrlBuild(item);
2558
2587
  // Only include custom parent signal values (not using defaults)
2559
2588
  if (paramValue === undefined || !item.isCustomValue(paramValue)) {
2560
2589
  return { isCompatible: true, shouldInclude: false };
@@ -2661,7 +2690,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2661
2690
  if (!siblingConnection) {
2662
2691
  continue;
2663
2692
  }
2664
- const siblingSignalValue = siblingConnection.signal.value;
2693
+ const siblingSignalValue = readSignalForUrlBuild(siblingConnection);
2665
2694
  if (siblingSignalValue === undefined) {
2666
2695
  continue;
2667
2696
  }
@@ -2705,7 +2734,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2705
2734
  const explicitValue = params[paramName];
2706
2735
  const connection =
2707
2736
  pathConnectionMap.get(paramName) || queryConnectionMap.get(paramName);
2708
- const signalValue = connection ? connection.signal.value : undefined;
2737
+ const signalValue = readSignalForUrlBuild(connection);
2709
2738
 
2710
2739
  // Check if the parameter has the required value
2711
2740
  if (
@@ -2759,7 +2788,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2759
2788
  hasActiveParams = true;
2760
2789
  }
2761
2790
  } else {
2762
- const signalValue = connection.signal.value;
2791
+ const signalValue = readSignalForUrlBuild(connection);
2763
2792
  if (signalValue !== undefined) {
2764
2793
  // No explicit override - use signal value
2765
2794
  childParams[paramName] = signalValue;
@@ -2976,7 +3005,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
2976
3005
  }
2977
3006
  // If explicitly undefined, don't include it (which means don't use child route)
2978
3007
  } else {
2979
- const signalValue = connection.signal.value;
3008
+ const signalValue = readSignalForUrlBuild(connection);
2980
3009
  if (
2981
3010
  signalValue !== undefined &&
2982
3011
  connection.isCustomValue(signalValue)
@@ -3016,7 +3045,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
3016
3045
  continue; // Already have this parameter
3017
3046
  }
3018
3047
 
3019
- const signalValue = connection.signal.value;
3048
+ const signalValue = readSignalForUrlBuild(connection);
3020
3049
  // Only include custom signal values (not using defaults)
3021
3050
  if (
3022
3051
  signalValue !== undefined &&
@@ -3198,7 +3227,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
3198
3227
  paramName,
3199
3228
  connection,
3200
3229
  ] of childPatternObj.pathConnectionMap) {
3201
- const signalValue = connection.signal.value;
3230
+ const signalValue = readSignalForUrlBuild(connection);
3202
3231
  if (
3203
3232
  signalValue !== undefined &&
3204
3233
  connection.isCustomValue(signalValue)
@@ -3220,7 +3249,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
3220
3249
  paramName,
3221
3250
  connection,
3222
3251
  ] of childPatternObj.queryConnectionMap) {
3223
- const signalValue = connection.signal.value;
3252
+ const signalValue = readSignalForUrlBuild(connection);
3224
3253
  if (
3225
3254
  signalValue !== undefined &&
3226
3255
  connection.isCustomValue(signalValue)
@@ -3840,7 +3869,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
3840
3869
  );
3841
3870
  for (const conn of targetAncestor.connections) {
3842
3871
  console.debug(
3843
- `[${pattern}] tryDirectOptimization: Target connection ${conn.paramName}: value=${conn.signal.value}, isCustom=${conn.isCustomValue(conn.signal.value)}`,
3872
+ `[${pattern}] tryDirectOptimization: Target connection ${conn.paramName}: value=${readSignalForUrlBuild(conn)}, isCustom=${conn.isCustomValue(readSignalForUrlBuild(conn))}`,
3844
3873
  );
3845
3874
  }
3846
3875
  }
@@ -3857,7 +3886,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
3857
3886
  }
3858
3887
 
3859
3888
  // Only include if not already processed and has custom value (not default)
3860
- const signalValue = connection.signal.value;
3889
+ const signalValue = readSignalForUrlBuild(connection);
3861
3890
  if (signalValue !== undefined) {
3862
3891
  // Don't include path parameters that correspond to literal segments we're optimizing away
3863
3892
  const targetParam = targetParams.find((p) => p.name === paramName);
@@ -3903,7 +3932,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
3903
3932
  }
3904
3933
 
3905
3934
  // Only inherit custom values (not defaults) that we don't already have
3906
- const signalValue = connection.signal.value;
3935
+ const signalValue = readSignalForUrlBuild(connection);
3907
3936
  if (
3908
3937
  signalValue !== undefined &&
3909
3938
  connection.isCustomValue(signalValue)
@@ -3989,7 +4018,7 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
3989
4018
  }
3990
4019
 
3991
4020
  // Only inherit if we don't have this param and parent has custom value (not default)
3992
- const parentSignalValue = parentConnection.signal.value;
4021
+ const parentSignalValue = readSignalForUrlBuild(parentConnection);
3993
4022
  if (
3994
4023
  parentSignalValue !== undefined &&
3995
4024
  parentConnection.isCustomValue(parentSignalValue)
@@ -4075,7 +4104,36 @@ const createRoutePattern = (pattern, { searchParams = {} } = {}) => {
4075
4104
  // search params are updated. When buildMostPreciseUrl performs an ancestor
4076
4105
  // optimisation (e.g. "/map/isochrone/compare" → "/map/isochrone") it is trusted
4077
4106
  // as-is because the built pathname will differ from the route's own base pathname.
4107
+ // Weak params are never inherited from their signal, but a url that already
4108
+ // carries one keeps it: staying on the same screen while another param
4109
+ // changes must not end the visit this param qualifies.
4110
+ const carryOverWeakParams = (currentUrl, params) => {
4111
+ let paramsWithWeak = params;
4112
+ for (const [paramName, connection] of [
4113
+ ...pathConnectionMap,
4114
+ ...queryConnectionMap,
4115
+ ]) {
4116
+ if (!connection.weak || paramName in paramsWithWeak) {
4117
+ continue;
4118
+ }
4119
+ const currentValue = connection.signal.peek();
4120
+ if (currentValue === undefined) {
4121
+ continue;
4122
+ }
4123
+ const currentParams = applyOn(currentUrl);
4124
+ if (!currentParams || currentParams[paramName] === undefined) {
4125
+ continue;
4126
+ }
4127
+ if (paramsWithWeak === params) {
4128
+ paramsWithWeak = { ...params };
4129
+ }
4130
+ paramsWithWeak[paramName] = currentParams[paramName];
4131
+ }
4132
+ return paramsWithWeak;
4133
+ };
4134
+
4078
4135
  const buildUrlPreservingPath = (currentUrl, params = {}) => {
4136
+ params = carryOverWeakParams(currentUrl, params);
4079
4137
  const relativeBuiltUrl = buildMostPreciseUrl(params);
4080
4138
  if (!currentUrl) {
4081
4139
  return resolveRouteUrl(relativeBuiltUrl);
@@ -4332,7 +4390,7 @@ const parsePattern = (pattern, { pathConnectionMap, queryConnectionMap }) => {
4332
4390
  if (
4333
4391
  connection &&
4334
4392
  connection.signal &&
4335
- connection.signal.value === undefined &&
4393
+ readSignalForUrlBuild(connection) === undefined &&
4336
4394
  !hasDefault
4337
4395
  ) {
4338
4396
  isOptional = true;
@@ -5516,7 +5574,10 @@ const route = (pattern, { searchParams } = {}) => {
5516
5574
  });
5517
5575
  };
5518
5576
  route.matchesParams = (providedParams) => {
5519
- const currentParams = route.params;
5577
+ // paramsSignal (not route.params) so a component calling this during render
5578
+ // subscribes to param changes: a navigation from /games/me/a to /games/me/b
5579
+ // leaves matchingSignal untouched, only the params change.
5580
+ const currentParams = route.paramsSignal.value;
5520
5581
  const resolvedParams = routePattern.resolveParams({
5521
5582
  ...currentParams,
5522
5583
  ...providedParams,
@@ -5883,6 +5944,22 @@ This prevents cross-test pollution and ensures clean state.`,
5883
5944
  }
5884
5945
  }
5885
5946
 
5947
+ // A weak param qualifies one visit: leaving the route ends it,
5948
+ // whatever the family and whatever the default. Coming back by a
5949
+ // url that does not carry the param comes back to a blank screen.
5950
+ if (connection.weak) {
5951
+ if (!parameterExtractedByMatchingRoute) {
5952
+ const defaultValue = connection.getDefaultValue();
5953
+ if (debug) {
5954
+ console.debug(
5955
+ `[route] weak param ${paramName}: route no longer matching, back to ${defaultValue}`,
5956
+ );
5957
+ }
5958
+ paramSignal.value = defaultValue;
5959
+ }
5960
+ continue;
5961
+ }
5962
+
5886
5963
  // Only reset signal if:
5887
5964
  // 1. We're navigating within the same route family (not to completely unrelated routes)
5888
5965
  // 2. AND no matching route extracts this parameter from URL
@@ -31360,6 +31437,15 @@ const useActionAsyncData = (action, {
31360
31437
  return [staleData, true, undefined];
31361
31438
  }
31362
31439
 
31440
+ // An action without params has nothing to run and no one to start it: this is
31441
+ // where a route action lands when its params getter returns false. It is not a
31442
+ // load in progress, so there is nothing to wait for — suspending here would
31443
+ // throw a promise that never settles, and the whole <Loading> subtree would
31444
+ // stay hidden for good, silently.
31445
+ if (runningState !== RUNNING && action.paramsSignal.peek() === undefined) {
31446
+ return [action.dataSignal.peek(), false, undefined];
31447
+ }
31448
+
31363
31449
  // IDLE or RUNNING with loadingEffect: "delegate" — suspend
31364
31450
  const reason = runningState === RUNNING ? "loading" : "idle";
31365
31451
  loadingRef.current = {
@@ -33534,11 +33620,12 @@ const collectBranches = children => {
33534
33620
  type: "container",
33535
33621
  node: child
33536
33622
  };
33623
+ const guardMatching = route ? route.matchingSignal.value : false;
33537
33624
  if (!matchingBranch) {
33538
33625
  if (matchingChild) {
33539
33626
  // Real leaf match inside — always select this container
33540
33627
  matchingBranch = branch;
33541
- } else if (route && route.matchingSignal.value) {
33628
+ } else if (guardMatching) {
33542
33629
  // No leaf match but an explicit route guard matches — select this
33543
33630
  // container so it can render its own fallback inside its layout
33544
33631
  matchingBranch = branch;
@@ -33556,7 +33643,12 @@ const collectBranches = children => {
33556
33643
  type: "leaf",
33557
33644
  node: child
33558
33645
  };
33559
- if (!matchingBranch && route.matchingSignal.value && (!routeParams || route.matchesParams(routeParams))) {
33646
+ // every signal is read even once a match is found: reading is what
33647
+ // subscribes the container to it, and a branch that is skipped today is
33648
+ // the one that must wake the container up tomorrow
33649
+ const matching = route.matchingSignal.value;
33650
+ const paramsMatching = routeParams ? route.matchesParams(routeParams) : true;
33651
+ if (!matchingBranch && matching && paramsMatching) {
33560
33652
  matchingBranch = branch;
33561
33653
  }
33562
33654
  }
@@ -52047,6 +52139,10 @@ const css$p = /* css */`
52047
52139
  keyboard here (see navi-focus-delegate below). */
52048
52140
  outline-color: var(--navi-focus-outline-color);
52049
52141
  outline-offset: 0px;
52142
+ /* No grey flash under a finger: what a press does is said by the chevron's
52143
+ own background, and the browser's rectangle is drawn square over corners
52144
+ that are round. Inherited, so the three pieces inside get it too. */
52145
+ -webkit-tap-highlight-color: var(--navi-control-tap-highlight-color);
52050
52146
  }
52051
52147
  /* The middle holds the keyboard, and this box wears its ring: whatever is in
52052
52148
  there fills it, so a ring of its own would be drawn a pixel inside this
@@ -52173,7 +52269,12 @@ const css$p = /* css */`
52173
52269
  border-radius: 0;
52174
52270
  cursor: pointer;
52175
52271
  }
52176
- .navi_picker_spin > .navi_picker_spin_way_out:hover {
52272
+ /* Said as data-hover rather than :hover: a touch browser synthesizes the
52273
+ enter and never the leave, so a CSS :hover would stay grey under the last
52274
+ chevron pressed until something else was touched. What tracks it (see
52275
+ pseudo_styles.js) knows there is no hover on such a device and simply does
52276
+ not set the attribute. */
52277
+ .navi_picker_spin > .navi_picker_spin_way_out[data-hover] {
52177
52278
  background: color-mix(in srgb, currentColor 8%, transparent);
52178
52279
  }
52179
52280
  /* Nothing that way: still there, still pressable — pressing it is how one
@@ -52199,22 +52300,28 @@ const css$p = /* css */`
52199
52300
  of a rounded spin is rounded there too, and nowhere else — the two corners
52200
52301
  it does not own stay at the 0 above. Said with inherit rather than clipped
52201
52302
  away with overflow, which would cut the focus ring of the very button it
52202
- rounds. */
52303
+ rounds.
52304
+ Which chevron is which is asked of the chevron itself (data-way-out) rather
52305
+ than of its place among its siblings: the loading outline is a <span> too
52306
+ and it is written first, so :first-of-type named IT and the chevron at the
52307
+ start went unrounded. */
52203
52308
  .navi_picker_spin:not([data-vertical])
52204
- > .navi_picker_spin_way_out:first-of-type {
52309
+ > .navi_picker_spin_way_out[data-way-out="start"] {
52205
52310
  border-start-start-radius: inherit;
52206
52311
  border-end-start-radius: inherit;
52207
52312
  }
52208
52313
  .navi_picker_spin:not([data-vertical])
52209
- > .navi_picker_spin_way_out:last-of-type {
52314
+ > .navi_picker_spin_way_out[data-way-out="end"] {
52210
52315
  border-start-end-radius: inherit;
52211
52316
  border-end-end-radius: inherit;
52212
52317
  }
52213
- .navi_picker_spin[data-vertical] > .navi_picker_spin_way_out:first-of-type {
52318
+ .navi_picker_spin[data-vertical]
52319
+ > .navi_picker_spin_way_out[data-way-out="start"] {
52214
52320
  border-start-start-radius: inherit;
52215
52321
  border-start-end-radius: inherit;
52216
52322
  }
52217
- .navi_picker_spin[data-vertical] > .navi_picker_spin_way_out:last-of-type {
52323
+ .navi_picker_spin[data-vertical]
52324
+ > .navi_picker_spin_way_out[data-way-out="end"] {
52218
52325
  border-end-end-radius: inherit;
52219
52326
  border-end-start-radius: inherit;
52220
52327
  }
@@ -52455,6 +52562,7 @@ const Spin = ({
52455
52562
  const wayOut = atStart => {
52456
52563
  const isNext = atStart ? startIsNext : !startIsNext;
52457
52564
  return jsx(WayOut, {
52565
+ atStart: atStart,
52458
52566
  unavailableMessage: wayOutMessage(atStart ? startAllowed : endAllowed, isNext ? "spin.nothing_after" : "spin.nothing_before"),
52459
52567
  label: isNext ? nextLabel ?? naviI18n("spin.next") : previousLabel ?? naviI18n("spin.previous"),
52460
52568
  onPress: e => {
@@ -52632,6 +52740,7 @@ const Spin = ({
52632
52740
  // the container's own tabIndex, or the field's), where the arrows already mean
52633
52741
  // this.
52634
52742
  const WayOut = ({
52743
+ atStart,
52635
52744
  commandFor,
52636
52745
  unavailableMessage,
52637
52746
  label,
@@ -52640,6 +52749,17 @@ const WayOut = ({
52640
52749
  }) => jsx(Box, {
52641
52750
  as: "span",
52642
52751
  baseClassName: "navi_picker_spin_way_out"
52752
+ // Which end of the box it sits in, said by the chevron rather than read
52753
+ // from its place among its siblings: that is what the corners it is
52754
+ // rounded by are keyed on (see the CSS above).
52755
+ ,
52756
+
52757
+ "data-way-out": atStart ? "start" : "end"
52758
+ // Tracked rather than left to CSS :hover, which stays on after a tap on a
52759
+ // touch device (see the CSS above).
52760
+ ,
52761
+
52762
+ pseudoClasses: WAY_OUT_PSEUDO_CLASSES
52643
52763
  // Announced as a button because that is what it is to whoever cannot see
52644
52764
  // the chevron — and marked unavailable rather than removed when there is
52645
52765
  // nothing that way, so it keeps its place.
@@ -52691,6 +52811,7 @@ const WayOut = ({
52691
52811
  })
52692
52812
  });
52693
52813
  const PICKER_SPIN_PSEUDO_CLASSES = [":hover", ":focus-visible"];
52814
+ const WAY_OUT_PSEUDO_CLASSES = [":hover"];
52694
52815
 
52695
52816
  // A padding written on this box would sit between its border and the chevrons,
52696
52817
  // which are meant to reach the corners they are rounded by — so each padding