@jsenv/navi 0.29.150 → 0.29.152

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.
@@ -15,6 +15,45 @@ import { parseDuration, durationContainsNaN, compareTwoDurations, durationToSeco
15
15
  export { compareTwoDurations, durationContainsNaN, durationToHours, durationToISOString, durationToMinutes, durationToNumber, durationToSeconds, durationToString, parseDuration } from "@jsenv/validity";
16
16
  import { Suspense, createPortal, forwardRef } from "preact/compat";
17
17
 
18
+ /**
19
+ * One page, one navi.
20
+ *
21
+ * navi keeps contexts, registries and singletons at module scope, so a second
22
+ * copy of the library in the same page is a second of each, and nothing
23
+ * crosses between them. Every symptom of that lands far from the cause and
24
+ * reads as an app bug: a <Loading> mounted by one copy is invisible to the
25
+ * hook reading the other's context and reports itself missing, an action
26
+ * registered in one is unknown to the other, focus and z-index each get a
27
+ * second owner. So the copies are detected here, when the second one is
28
+ * imported, and that import fails — the first thing that goes wrong says what
29
+ * is wrong.
30
+ *
31
+ * A copy is a module evaluation, which is what the object added to the set
32
+ * stands for; the urls are only there to tell the reader which two files to
33
+ * compare. Two urls for one file on disk is the usual shape (a dev server
34
+ * stamping a package version into specifiers, a bundle embedding navi next to
35
+ * a copy resolved separately); two versions installed in node_modules is the
36
+ * other.
37
+ *
38
+ * This module must stay in the entry chunk: the whole point is that it is
39
+ * evaluated once per copy of navi, and a shared chunk would be evaluated once
40
+ * for both.
41
+ */
42
+
43
+ // Symbol.for so the set is the same one across copies — a copy cannot see the
44
+ // other's module scope, which is the very thing being detected.
45
+ const NAVI_INSTANCE_SET = Symbol.for("navi_instance_set");
46
+
47
+ const instanceSet = globalThis[NAVI_INSTANCE_SET] || new Set();
48
+ globalThis[NAVI_INSTANCE_SET] = instanceSet;
49
+ instanceSet.add({ url: import.meta.url });
50
+ if (instanceSet.size > 1) {
51
+ const urlList = Array.from(instanceSet, ({ url }) => `- ${url}`).join("\n");
52
+ throw new Error(`@jsenv/navi is loaded ${instanceSet.size} times in this page:
53
+ ${urlList}
54
+ Each one builds its own contexts, stores and registries, so what one holds is invisible to the components using another.`);
55
+ }
56
+
18
57
  installImportMetaCssBuild(import.meta);/**
19
58
  * Every z-index navi can be seen competing on, in one place, ordered.
20
59
  *
@@ -5596,8 +5635,19 @@ const CLICK_SELECTOR = selfInteractionSelector("click");
5596
5635
  * The closest element CLAIMING THE PRESS wins, not the closest one claiming
5597
5636
  * anything: an affordance that took only the drag is transparent here, exactly
5598
5637
  * as it is to the drag readers when it took only the click.
5638
+ *
5639
+ * @param {Event} event The gesture being arbitrated.
5640
+ * @param {Element} controlHost The control asking whether the press is its own.
5641
+ * @param {Element} [requester] Who asked this control to act, when someone did
5642
+ * — the source of a command, typically. The claim answers "was this press
5643
+ * yours or the affordance's"; it says nothing about a request that affordance
5644
+ * is making, and the answer there is always yes.
5599
5645
  */
5600
- const isAimedAtSelfInteractionsBelow = (event, controlHost) => {
5646
+ const isAimedAtSelfInteractionsBelow = (
5647
+ event,
5648
+ controlHost,
5649
+ requester,
5650
+ ) => {
5601
5651
  const target = event?.target;
5602
5652
  if (!target || typeof target.closest !== "function") {
5603
5653
  return false;
@@ -5611,6 +5661,13 @@ const isAimedAtSelfInteractionsBelow = (event, controlHost) => {
5611
5661
  if (claimer === controlHost || claimer.contains(controlHost)) {
5612
5662
  return false;
5613
5663
  }
5664
+ // The claimer is the one asking. Its claim took the press so IT would decide
5665
+ // what the press means, and this is that decision arriving — a clear cross
5666
+ // sending "--navi-clear" to the field it sits in. Stepping back here would be
5667
+ // the control refusing the very request the claim exists to let through.
5668
+ if (requester && (claimer === requester || claimer.contains(requester))) {
5669
+ return false;
5670
+ }
5614
5671
  // From the root rather than the host: a layered control (a picker holding an
5615
5672
  // input) has its gate on the input, and what the application drew sits beside
5616
5673
  // it, not in it.
@@ -9802,12 +9859,21 @@ const createControlInteraction = (
9802
9859
 
9803
9860
  const dispatchRequestInteraction = (
9804
9861
  element,
9805
- { event, name = "", prevented, allowed, always, ...detailRest } = {},
9862
+ {
9863
+ event,
9864
+ name = "",
9865
+ requester,
9866
+ prevented,
9867
+ allowed,
9868
+ always,
9869
+ ...detailRest
9870
+ } = {},
9806
9871
  ) => {
9807
9872
  const controlHost = findControlHost(element) || element;
9808
9873
  return dispatchInternalCustomEvent(controlHost, "navi_request_interaction", {
9809
9874
  event,
9810
9875
  name,
9876
+ requester,
9811
9877
  prevented,
9812
9878
  allowed,
9813
9879
  always,
@@ -9829,6 +9895,9 @@ const onRequestInteraction = (
9829
9895
  // through (see READONLY_CONSTRAINT).
9830
9896
  intent = "write",
9831
9897
  bypassInteractivity = false,
9898
+ // Who asked, when the control is not answering the gesture on its own —
9899
+ // the source of a command (see the self-interactions step-back below).
9900
+ requester,
9832
9901
  prevented,
9833
9902
  allowed,
9834
9903
  always,
@@ -9862,7 +9931,9 @@ const onRequestInteraction = (
9862
9931
  // reaction never happened, so its `prevented`/`always` (an
9863
9932
  // `e.preventDefault()`, for most of them) have nothing to undo and would take
9864
9933
  // the press from the affordance itself.
9865
- if (isAimedAtSelfInteractionsBelow(event, controlHost)) {
9934
+ // Unless that element is the one asking: what it took the press to decide is
9935
+ // arriving here, and it is this control's to answer.
9936
+ if (isAimedAtSelfInteractionsBelow(event, controlHost, requester)) {
9866
9937
  debugInteraction(
9867
9938
  event,
9868
9939
  `"${name}" is for a self-interactions element below`,
@@ -9947,6 +10018,11 @@ const dispatchRequestAction = (
9947
10018
  return dispatchRequestInteraction(element, {
9948
10019
  event,
9949
10020
  name,
10021
+ // The gate needs it as much as the action does: the requester may be an
10022
+ // affordance that claimed the press to ask for this very action, and the
10023
+ // control must not read that claim as "this press was not for me" — see
10024
+ // isAimedAtSelfInteractionsBelow.
10025
+ requester: actionOptions.requester,
9950
10026
  prevented,
9951
10027
  allowed: () => {
9952
10028
  allowed?.();
@@ -30132,16 +30208,40 @@ const anyMatchingRouteSignal = (routes) => {
30132
30208
  };
30133
30209
 
30134
30210
  /**
30211
+ * Runs a navi command from JS. It is the LAST RESORT: the attributes say the
30212
+ * same thing declaratively and go through this very function, so a press that
30213
+ * opens, closes, sends, updates or travels needs none of this.
30214
+ *
30215
+ * ```html
30216
+ * <button command="--navi-open" commandfor="note-dialog" value="42">
30217
+ * ```
30218
+ *
30219
+ * `command` names it (`--navi-x:argument` when it needs an argument),
30220
+ * `commandfor` / `navi-command-target` says to whom, the source's own `value`
30221
+ * says what it is about (`command-value` when the source has a value meaning
30222
+ * something else). Reach for `triggerNaviCommand` only when what decides is not
30223
+ * a press on the element carrying those attributes: a long press, the end of a
30224
+ * drag, a double-click, a keyboard shortcut, a server answer, an observer.
30225
+ *
30135
30226
  * @param {Element} element The element asking — the command's source, and the
30136
30227
  * anchor a popup opens on unless `anchor` says otherwise.
30137
30228
  * @param {string} command
30138
30229
  * @param {Event} event What caused this. Mandatory: it is what makes a command
30139
30230
  * traceable back to its origin — the debug panel groups everything a gesture
30140
30231
  * set off under it, and the gates below read it to know whether the default
30141
- * was already prevented and which mouse button was pressed. When nothing was
30142
- * handed over — a timer firing, an action settling, a signal changing — build
30143
- * a `CustomEvent` that names what happened and chain it to whatever preceded
30144
- * it, rather than leaving the origin unsaid:
30232
+ * was already prevented and which mouse button was pressed.
30233
+ *
30234
+ * **Forward the event you were handed**, down through every function between
30235
+ * the handler and this call, so what arrives here is the real gesture. Almost
30236
+ * every command has one: a person did something to the page, or the browser
30237
+ * did. Building a `CustomEvent` at the call site instead of taking `event` as
30238
+ * a parameter looks like it satisfies the requirement, and throws away
30239
+ * exactly what makes it useful — the chain a popup reads to give the focus
30240
+ * back, the button that was pressed, a default already prevented.
30241
+ *
30242
+ * The `CustomEvent` is for the genuinely originless case — a timer firing, an
30243
+ * action settling, a signal changing — and even there it names what happened
30244
+ * and chains to whatever preceded it:
30145
30245
  * const expiredEvent = new CustomEvent("session_expired");
30146
30246
  * chainEvent(expiredEvent, causeEvent); // when something did precede it
30147
30247
  * triggerNaviCommand(dialogEl, "--navi-open", expiredEvent);
@@ -30163,7 +30263,7 @@ const triggerNaviCommand = (
30163
30263
  ) => {
30164
30264
  if (!event) {
30165
30265
  throw new Error(
30166
- `"${command}" triggered without an event: it is mandatory, a command must say what caused it. Pass the gesture, or a CustomEvent naming the cause when no gesture did — see triggerNaviCommand's jsdoc.`,
30266
+ `"${command}" triggered without an event: it is mandatory, a command must say what caused it. Forward the gesture that led here, or a CustomEvent naming the cause when no gesture did — see triggerNaviCommand's jsdoc.`,
30167
30267
  );
30168
30268
  }
30169
30269
  const naviCommand =
@@ -30404,6 +30504,9 @@ registerNaviCommand("--navi-update", (source, event, { argument }) => {
30404
30504
  dispatchRequestInteraction(target, {
30405
30505
  event,
30406
30506
  name: "--navi-update",
30507
+ // The source may have claimed the press to send this very command — see
30508
+ // the requester in onRequestInteraction.
30509
+ requester: source,
30407
30510
  prevented: () => event.preventDefault(),
30408
30511
  allowed: () => {
30409
30512
  const commandValue = resolveCommandValue(source, event);
@@ -30442,6 +30545,9 @@ registerNaviCommand("--navi-clear", (source, event) => {
30442
30545
  dispatchRequestInteraction(target, {
30443
30546
  event: clearEvent,
30444
30547
  name: "--navi-clear",
30548
+ // The source may have claimed the press to send this very command — see
30549
+ // the requester in onRequestInteraction.
30550
+ requester: source,
30445
30551
  prevented: () => clearEvent.preventDefault(),
30446
30552
  allowed: () => {
30447
30553
  // What the control holds, before it holds nothing: the clear is
@@ -30529,6 +30635,9 @@ registerNaviCommand("--navi-reset", (source, event) => {
30529
30635
  dispatchRequestInteraction(target, {
30530
30636
  event,
30531
30637
  name: "--navi-reset",
30638
+ // The source may have claimed the press to send this very command — see
30639
+ // the requester in onRequestInteraction.
30640
+ requester: source,
30532
30641
  prevented: () => event.preventDefault(),
30533
30642
  allowed: () => dispatchRequestResetUIState(target, event),
30534
30643
  });
@@ -44206,7 +44315,7 @@ installImportMetaCssBuild(import.meta);const css$P = /* css */`@layer navi {
44206
44315
  --button-color: currentColor;
44207
44316
  --button-cursor: pointer;
44208
44317
  --button-font-size: var(--navi-control-font-size);
44209
- --button-font-family: var(--navi-control-font-family);
44318
+ --button-font-family: var(--navi-control-font-family, inherit);
44210
44319
  --button-border-color-hover: color-mix(in srgb,
44211
44320
  var(--button-border-color) 70%,
44212
44321
  black);
@@ -44453,37 +44562,30 @@ a.navi_button {
44453
44562
  }
44454
44563
 
44455
44564
  &[data-cta] {
44456
- --x-button-background-color: var(--button-cta-background-color);
44457
- --x-button-border-color: var(--button-cta-background-color);
44458
- --x-button-color: white;
44459
-
44460
- &[data-hover] {
44461
- --x-button-background-color: color-mix(in srgb,
44462
- var(--button-cta-background-color) 85%,
44463
- white);
44464
- --x-button-border-color: color-mix(in srgb,
44465
- var(--button-cta-background-color) 85%,
44466
- white);
44467
- }
44468
-
44469
- &[data-readonly] {
44470
- --x-button-background-color: color-mix(in srgb,
44471
- var(--button-cta-background-color) 50%,
44472
- white);
44473
- --x-button-border-color: color-mix(in srgb,
44474
- var(--button-cta-background-color) 50%,
44475
- white);
44476
- }
44477
-
44478
- &[data-disabled] {
44479
- --x-button-background-color: color-mix(in srgb,
44480
- var(--button-cta-background-color) 40%,
44481
- white);
44482
- --x-button-border-color: color-mix(in srgb,
44483
- var(--button-cta-background-color) 40%,
44484
- white);
44485
- --x-button-color: #fff9;
44486
- }
44565
+ --button-background-color: var(--button-background, var(--button-cta-background-color));
44566
+ --button-border-color: var(--button-cta-background-color);
44567
+ --button-color: white;
44568
+ --button-background-color-hover: color-mix(in srgb,
44569
+ var(--button-background-color) 85%,
44570
+ white);
44571
+ --button-border-color-hover: color-mix(in srgb,
44572
+ var(--button-border-color) 85%,
44573
+ white);
44574
+ --button-background-color-readonly: color-mix(in srgb,
44575
+ var(--button-background-color) 50%,
44576
+ white);
44577
+ --button-border-color-readonly: color-mix(in srgb,
44578
+ var(--button-border-color) 50%,
44579
+ white);
44580
+ --button-background-color-disabled: color-mix(in srgb,
44581
+ var(--button-background-color) 40%,
44582
+ white);
44583
+ --button-border-color-disabled: color-mix(in srgb,
44584
+ var(--button-border-color) 40%,
44585
+ white);
44586
+ --button-color-disabled: color-mix(in srgb,
44587
+ var(--button-color) 60%,
44588
+ transparent);
44487
44589
  }
44488
44590
  }
44489
44591
  `;
@@ -45426,7 +45528,7 @@ installImportMetaCssBuild(import.meta);const css$M = /* css */`@layer navi {
45426
45528
  --outline-color: var(--navi-focus-outline-color);
45427
45529
  --margin: 3px 3px 3px 4px;
45428
45530
  --font-size: var(--navi-control-font-size);
45429
- --font-family: var(--navi-control-font-family);
45531
+ --font-family: var(--navi-control-font-family, inherit);
45430
45532
  --width: round(1em, 1px);
45431
45533
  --height: round(1em, 1px);
45432
45534
  --loader-color: var(--navi-loader-color);
@@ -46132,7 +46234,7 @@ installImportMetaCssBuild(import.meta);const css$K = /* css */`@layer navi {
46132
46234
  --border-color-checked: var(--accent-color);
46133
46235
  --cursor: pointer;
46134
46236
  --font-size: var(--navi-control-font-size);
46135
- --font-family: var(--navi-control-font-family);
46237
+ --font-family: var(--navi-control-font-family, inherit);
46136
46238
  --border-color-hover: color-mix(in srgb, var(--border-color) 60%, black);
46137
46239
  --border-color-hover-checked: color-mix(in srgb,
46138
46240
  var(--border-color-checked) 80%,
@@ -46579,7 +46681,7 @@ installImportMetaCssBuild(import.meta);const css$J = /* css */`@layer navi {
46579
46681
  --thumb-border-radius: 100%;
46580
46682
  --thumb-cursor: pointer;
46581
46683
  --font-size: var(--navi-control-font-size);
46582
- --font-family: var(--navi-control-font-family);
46684
+ --font-family: var(--navi-control-font-family, inherit);
46583
46685
  --loader-color: var(--navi-loader-color);
46584
46686
  --accent-color: var(--navi-control-accent-color);
46585
46687
  --color-mix-light: black;
@@ -46927,7 +47029,7 @@ const inputCss = /* css */`@layer navi {
46927
47029
  --outline-offset: calc(-.5 * var(--outline-width));
46928
47030
  --outline-color: var(--navi-focus-outline-color);
46929
47031
  --font-size: var(--navi-control-font-size);
46930
- --font-family: var(--navi-control-font-family);
47032
+ --font-family: var(--navi-control-font-family, inherit);
46931
47033
  --loader-color: var(--navi-loader-color);
46932
47034
  --border-color: var(--navi-control-border-color);
46933
47035
  --background-color: var(--navi-surface-color);
@@ -47142,13 +47244,24 @@ const inputCss = /* css */`@layer navi {
47142
47244
  }
47143
47245
 
47144
47246
  &[data-variant="text"] {
47145
- --x-background-color: transparent;
47146
- --x-border-color: transparent;
47247
+ --background-color: transparent;
47248
+ --background-color-hover: var(--background-color);
47249
+ --background-color-focus: var(--background-color);
47250
+ --background-color-readonly: var(--background-color);
47251
+ --background-color-disabled: var(--background-color);
47252
+ --border-color: transparent;
47253
+ --border-color-hover: var(--border-color);
47254
+ --border-color-readonly: var(--border-color);
47255
+ --border-color-disabled: var(--border-color);
47147
47256
  cursor: inherit;
47148
47257
  }
47149
47258
 
47150
47259
  &[data-variant="underline"] {
47151
- --x-background-color: transparent;
47260
+ --background-color: transparent;
47261
+ --background-color-hover: var(--background-color);
47262
+ --background-color-focus: var(--background-color);
47263
+ --background-color-readonly: var(--background-color);
47264
+ --background-color-disabled: var(--background-color);
47152
47265
  border: none;
47153
47266
  border-radius: 0;
47154
47267
  padding-left: 0;
@@ -47170,12 +47283,7 @@ const inputCss = /* css */`@layer navi {
47170
47283
  position: absolute;
47171
47284
  }
47172
47285
 
47173
- &[data-hover] {
47174
- --x-background-color: transparent;
47175
- }
47176
-
47177
47286
  &[data-focus-visible] {
47178
- --x-background-color: transparent;
47179
47287
  outline-style: none;
47180
47288
 
47181
47289
  & .navi_input_underline {
@@ -47183,10 +47291,6 @@ const inputCss = /* css */`@layer navi {
47183
47291
  height: 2px;
47184
47292
  }
47185
47293
  }
47186
-
47187
- &[data-readonly], &[data-disabled] {
47188
- --x-background-color: transparent;
47189
- }
47190
47294
  }
47191
47295
  }
47192
47296
  `;
@@ -59395,7 +59499,12 @@ const PickerConfirmResolver = props => {
59395
59499
  return jsx(Next, {
59396
59500
  ...props,
59397
59501
  type: "navi_js",
59398
- allowNameless: true,
59502
+ allowNameless: true
59503
+ // No chevron, no clear cross, whatever variant the trigger is drawn in:
59504
+ // both announce a value, and a question holds none.
59505
+ ,
59506
+
59507
+ picksNothing: true,
59399
59508
  variant: variant,
59400
59509
  mode: mode,
59401
59510
  focusCapture: focusCapture,
@@ -60264,7 +60373,7 @@ installImportMetaCssBuild(import.meta);const css$y = /* css */`@layer navi {
60264
60373
  --x-list-item-cursor: default;
60265
60374
  --x-list-item-border-color: var(--list-item-border-color);
60266
60375
  font-size: var(--navi-control-font-size);
60267
- font-family: var(--navi-control-font-family);
60376
+ font-family: var(--navi-control-font-family, inherit);
60268
60377
  line-height: var(--navi-control-line-height);
60269
60378
  position: relative;
60270
60379
  }
@@ -66707,7 +66816,7 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`@layer navi {
66707
66816
  --picker-padding-x-default: var(--navi-picker-padding-x-default);
66708
66817
  --picker-padding-y-default: var(--navi-picker-padding-y-default);
66709
66818
  --picker-font-size: var(--navi-control-font-size);
66710
- --picker-font-family: var(--navi-control-font-family);
66819
+ --picker-font-family: var(--navi-control-font-family, inherit);
66711
66820
  --picker-loader-color: var(--navi-loader-color);
66712
66821
  --picker-border-color: var(--navi-control-border-color);
66713
66822
  --picker-background-color: white;
@@ -66807,6 +66916,7 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`@layer navi {
66807
66916
  padding-bottom: var(--x-picker-padding-bottom);
66808
66917
  padding-left: var(--x-picker-padding-left);
66809
66918
  justify-content: inherit;
66919
+ text-align: var(--picker-align-x, var(--picker-text-align-default));
66810
66920
  pointer-events: none;
66811
66921
  user-select: none;
66812
66922
  flex-grow: 1;
@@ -66965,7 +67075,7 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`@layer navi {
66965
67075
  --picker-background-color-hover: var(--picker-background-color);
66966
67076
  --picker-background-color-readonly: var(--picker-background-color);
66967
67077
  --picker-background-color-disabled: var(--picker-background-color);
66968
- --x-picker-icon-color: currentColor;
67078
+ --picker-icon-color: currentColor;
66969
67079
 
66970
67080
  & .navi_picker_value {
66971
67081
  flex-grow: 0;
@@ -66998,7 +67108,7 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`@layer navi {
66998
67108
  --picker-background-color-hover: var(--picker-background-color);
66999
67109
  --picker-background-color-readonly: var(--picker-background-color);
67000
67110
  --picker-background-color-disabled: var(--picker-background-color);
67001
- --x-picker-icon-color: currentColor;
67111
+ --picker-icon-color: currentColor;
67002
67112
 
67003
67113
  & .navi_picker_box {
67004
67114
  z-index: -1;
@@ -67020,7 +67130,7 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`@layer navi {
67020
67130
  --picker-background-color-hover: var(--picker-background-color);
67021
67131
  --picker-background-color-readonly: var(--picker-background-color);
67022
67132
  --picker-background-color-disabled: var(--picker-background-color);
67023
- --x-picker-icon-color: currentColor;
67133
+ --picker-icon-color: currentColor;
67024
67134
  font-size: inherit;
67025
67135
  font-family: inherit;
67026
67136
  line-height: inherit;
@@ -67045,7 +67155,7 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`@layer navi {
67045
67155
  --picker-border-color-disabled: var(--picker-border-color-readonly);
67046
67156
  --picker-background-color-disabled: var(--picker-background-color-readonly);
67047
67157
  --picker-color-disabled: var(--picker-color-readonly);
67048
- text-align: center;
67158
+ --picker-text-align-default: center;
67049
67159
  }
67050
67160
 
67051
67161
  &[data-variant="text"] {
@@ -67111,6 +67221,11 @@ const PickerButton = props => {
67111
67221
  // not come back. The cross is then a confirm picker (see
67112
67222
  // picker_confirm.jsx), and the clear only goes out on yes.
67113
67223
  clearConfirm,
67224
+ // Nothing is picked here: the popup asks a question rather than holding an
67225
+ // answer, so the trigger draws a label and never a value. Set by the
67226
+ // confirm resolver (see picker_confirm.jsx), which is the picker that is
67227
+ // one — a caller whose popup is a menu of actions says it for themselves.
67228
+ picksNothing,
67114
67229
  readOnly,
67115
67230
  error
67116
67231
  } = props;
@@ -67124,17 +67239,19 @@ const PickerButton = props => {
67124
67239
  const isSingleLine = maxLines === 1;
67125
67240
  // Same rule as the root: phrasing content inside a sentence.
67126
67241
  const ContentTag = variant === "text" ? "span" : "div";
67127
- // Which variants get the right slot — the chevron saying "this opens", and
67128
- // the cross replacing it once there is something to clear.
67129
- // Not the ones that draw no value beside it: an icon picker IS its icon, a
67130
- // headless one draws nothing, a button says what it opens with its label, a
67242
+ // Who gets the right slot — the chevron saying "this opens", and the cross
67243
+ // replacing it once there is something to clear. Both are about a value, so
67244
+ // the slot follows the value and not the drawing: `picksNothing` has none to
67245
+ // announce and none to take back, whatever variant it is drawn in.
67246
+ // Then the variants that draw no value beside it: an icon picker IS its icon,
67247
+ // a headless one draws nothing, a button says what it opens with its label, a
67131
67248
  // word in a sentence has no room for furniture. Nor a picker rendering the
67132
67249
  // browser's own control ("default").
67133
67250
  // Nor a bare one: the picker is that drawing's box to the pixel, so anything
67134
67251
  // navi adds beside it either grows the box or covers what the caller drew.
67135
67252
  // The pieces are the caller's to place there instead — a <Picker.Clear /> in
67136
67253
  // their own layout (see warnOnClearableWithoutSlot).
67137
- const hasRightSlot = variant !== "icon" && variant !== "headless" && variant !== "button" && variant !== "text" && variant !== "bare" && ui !== "default";
67254
+ const hasRightSlot = !picksNothing && variant !== "icon" && variant !== "headless" && variant !== "button" && variant !== "text" && variant !== "bare" && ui !== "default";
67138
67255
  const inputRef = useRef(null);
67139
67256
  const [pickerRemainingProps, inputProps, facadeChildrenProps] = useControlFacadeProps({
67140
67257
  ...props,
@@ -67213,6 +67330,7 @@ const PickerButton = props => {
67213
67330
  rightSlotIconSize: undefined,
67214
67331
  rightSlot: undefined,
67215
67332
  clearConfirm: undefined,
67333
+ picksNothing: undefined,
67216
67334
  openWhileReadOnly: undefined,
67217
67335
  ui: undefined,
67218
67336
  maxLines: undefined,
@@ -67765,7 +67883,7 @@ const css$s = /* css */`@layer navi {
67765
67883
  --x-picker-spin-padding-bottom: var(--picker-spin-padding-bottom, var(--picker-spin-padding-y, var(--picker-spin-padding, var(--picker-spin-padding-y-default))));
67766
67884
  --x-picker-spin-padding-left: var(--picker-spin-padding-left, var(--picker-spin-padding-x, var(--picker-spin-padding, var(--picker-spin-padding-x-default))));
67767
67885
  font-size: var(--navi-control-font-size);
67768
- font-family: var(--navi-control-font-family);
67886
+ font-family: var(--navi-control-font-family, inherit);
67769
67887
  border: var(--navi-control-border-width) solid
67770
67888
  var(--navi-control-border-color);
67771
67889
  border-top-left-radius: var(--x-corner-top-left-radius, var(--navi-control-border-radius));
@@ -67915,7 +68033,7 @@ const css$s = /* css */`@layer navi {
67915
68033
 
67916
68034
  .navi_spin_group {
67917
68035
  font-size: var(--navi-control-font-size);
67918
- font-family: var(--navi-control-font-family);
68036
+ font-family: var(--navi-control-font-family, inherit);
67919
68037
  border: var(--navi-control-border-width) solid
67920
68038
  var(--navi-control-border-color);
67921
68039
  border-top-left-radius: var(--x-corner-top-left-radius, var(--navi-control-border-radius));
@@ -70813,7 +70931,7 @@ const css$m = /* css */`.navi_wheel_container {
70813
70931
  transparent);
70814
70932
  color: var(--wheel-color);
70815
70933
  font-size: var(--navi-control-font-size);
70816
- font-family: var(--navi-control-font-family);
70934
+ font-family: var(--navi-control-font-family, inherit);
70817
70935
  border: var(--navi-control-border-width) solid
70818
70936
  var(--navi-control-border-color);
70819
70937
  border-radius: var(--navi-control-border-radius);
@@ -71103,7 +71221,7 @@ const css$m = /* css */`.navi_wheel_container {
71103
71221
  color: var(--wheel-color, light-dark(#111, #eee));
71104
71222
  font-weight: 600;
71105
71223
  font-size: var(--navi-control-font-size);
71106
- font-family: var(--navi-control-font-family);
71224
+ font-family: var(--navi-control-font-family, inherit);
71107
71225
  white-space: nowrap;
71108
71226
  user-select: none;
71109
71227
  justify-content: center;
@@ -75864,7 +75982,6 @@ const css$g = /* css */`.navi_table_root {
75864
75982
 
75865
75983
  .navi_table {
75866
75984
  --editing-border-color: #a8c7fa;
75867
- font-family: Arial;
75868
75985
  font-size: 16px;
75869
75986
  }
75870
75987