@jsenv/navi 0.29.38 → 0.29.40

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.
@@ -23708,13 +23708,13 @@ const useUIGroupStateController = (
23708
23708
  );
23709
23709
  }
23710
23710
  const parentUIStateController = useContext(ParentUIStateControllerContext);
23711
- const hasValueProp = Object.hasOwn(props, "value");
23712
- const hasOwnDefaultValueProp = Object.hasOwn(props, "defaultValue");
23713
23711
  // A bound signal seeds the group the way `defaultValue` does — uncontrolled,
23714
23712
  // with the signal's current value as what it starts on. Write-back is handled
23715
23713
  // by applyState's own boundSignal; the read half is below: children are
23716
23714
  // placed from it when they register, and again whenever it moves.
23717
- const boundSignal = hasValueProp ? undefined : props.signal;
23715
+ const boundSignal = props.signal;
23716
+ const hasValueProp = !boundSignal && Object.hasOwn(props, "value");
23717
+ const hasOwnDefaultValueProp = Object.hasOwn(props, "defaultValue");
23718
23718
  const hasDefaultValueProp = hasOwnDefaultValueProp || Boolean(boundSignal);
23719
23719
  const { id, name, value, uiAction } = props;
23720
23720
  // A signal holding something wins over `defaultValue`: the default is a
@@ -24124,6 +24124,11 @@ const useUIGroupStateController = (
24124
24124
  parentUIStateController,
24125
24125
  uiAction,
24126
24126
  uiActionInternal,
24127
+ // `props` is what writeBoundSignal reads to find the bound `signal`.
24128
+ // Missing here, a group whose component never re-renders between mount
24129
+ // and the first choice wrote nothing back into its signal — and said
24130
+ // nothing about it: the list showed the choice, the signal stayed empty.
24131
+ props,
24127
24132
  };
24128
24133
  },
24129
24134
  // ── update: runs every render after the first ─────────────────────────
@@ -25322,22 +25327,25 @@ const createControlInfo = (props, {
25322
25327
  defaultStatePropName = "defaultChecked";
25323
25328
  value = props.value || "on";
25324
25329
  signalHoldsChecked = true;
25325
- if (Object.hasOwn(props, "checked")) {
25330
+ if (signal) {
25331
+ if (props.defaultChecked) {
25332
+ // resolveInputProps may seed defaultChecked from a bound signal's
25333
+ // default: the control stays uncontrolled and follows the signal
25334
+ // through stateFromSignal.
25335
+ hasStateProp = false;
25336
+ stateInitial = value;
25337
+ stateFromSignal = signal.value ? value : undefined;
25338
+ } else {
25339
+ // A bound signal with no resolved default: its live value seeds state.
25340
+ hasStateProp = true;
25341
+ stateInitial = signal.value ? value : undefined;
25342
+ }
25343
+ } else if (Object.hasOwn(props, "checked")) {
25326
25344
  hasStateProp = true;
25327
25345
  stateInitial = props.checked ? value : undefined;
25328
25346
  } else if (props.defaultChecked) {
25329
- // resolveInputProps may seed defaultChecked from a bound signal's
25330
- // default: the control stays uncontrolled and follows the signal
25331
- // through stateFromSignal.
25332
25347
  hasStateProp = false;
25333
25348
  stateInitial = value;
25334
- if (signal) {
25335
- stateFromSignal = signal.value ? value : undefined;
25336
- }
25337
- } else if (signal) {
25338
- // A bound signal with no resolved default: its live value seeds state.
25339
- hasStateProp = true;
25340
- stateInitial = signal.value ? value : undefined;
25341
25349
  } else {
25342
25350
  hasStateProp = false;
25343
25351
  stateInitial = undefined;
@@ -25345,30 +25353,33 @@ const createControlInfo = (props, {
25345
25353
  } else {
25346
25354
  statePropName = "value";
25347
25355
  defaultStatePropName = "defaultValue";
25348
- if (Object.hasOwn(props, "value")) {
25356
+ if (signal) {
25357
+ if (Object.hasOwn(props, "defaultValue")) {
25358
+ // resolveInputProps seeds defaultValue from a bound signal's default,
25359
+ // so an input+signal is uncontrolled-with-default; the signal only
25360
+ // receives write-backs (onUIAction).
25361
+ hasStateProp = false;
25362
+ // A signal holding something wins over the default: `defaultValue` is
25363
+ // a suggestion of what to start from (and what a reset goes back to),
25364
+ // not an answer — while the signal's value IS the answer, restored
25365
+ // from the url or set by whoever owns it. Taking the default here
25366
+ // would show a suggestion in place of the value on every reload.
25367
+ stateInitial = signal.value !== undefined ? signal.value : props.defaultValue;
25368
+ stateFromSignal = stateInitial;
25369
+ } else {
25370
+ // A plain bound signal with no default (e.g. Wheel): its live value
25371
+ // seeds and controls the state.
25372
+ hasStateProp = true;
25373
+ value = signal.value;
25374
+ stateInitial = value;
25375
+ }
25376
+ } else if (Object.hasOwn(props, "value")) {
25349
25377
  hasStateProp = true;
25350
25378
  value = props.value;
25351
25379
  stateInitial = value;
25352
25380
  } else if (Object.hasOwn(props, "defaultValue")) {
25353
- // resolveInputProps seeds defaultValue from a bound signal's default,
25354
- // so an input+signal is uncontrolled-with-default; the signal only
25355
- // receives write-backs (onUIAction).
25356
25381
  hasStateProp = false;
25357
- // A signal holding something wins over the default: `defaultValue` is a
25358
- // suggestion of what to start from (and what a reset goes back to), not
25359
- // an answer — while the signal's value IS the answer, restored from the
25360
- // url or set by whoever owns it. Taking the default here would show a
25361
- // suggestion in place of the value on every reload.
25362
- stateInitial = signal && signal.value !== undefined ? signal.value : props.defaultValue;
25363
- if (signal) {
25364
- stateFromSignal = stateInitial;
25365
- }
25366
- } else if (signal) {
25367
- // A plain bound signal with no default (e.g. Wheel): its live value
25368
- // seeds and controls the state.
25369
- hasStateProp = true;
25370
- value = signal.value;
25371
- stateInitial = value;
25382
+ stateInitial = props.defaultValue;
25372
25383
  } else {
25373
25384
  hasStateProp = false;
25374
25385
  stateInitial = undefined;
@@ -25388,20 +25399,23 @@ const createControlInfo = (props, {
25388
25399
  } else if (controlType === "picker" || controlType === "select") {
25389
25400
  statePropName = "value";
25390
25401
  defaultStatePropName = "defaultValue";
25391
- if (Object.hasOwn(props, "value")) {
25402
+ if (signal) {
25403
+ if (Object.hasOwn(props, "defaultValue")) {
25404
+ hasStateProp = false;
25405
+ // The signal's value is the answer, defaultValue only the suggestion to
25406
+ // start from.
25407
+ stateInitial = signal.value !== undefined ? signal.value : props.defaultValue;
25408
+ stateFromSignal = stateInitial;
25409
+ } else {
25410
+ hasStateProp = true;
25411
+ stateInitial = signal.value;
25412
+ }
25413
+ } else if (Object.hasOwn(props, "value")) {
25392
25414
  hasStateProp = true;
25393
25415
  stateInitial = props.value;
25394
25416
  } else if (Object.hasOwn(props, "defaultValue")) {
25395
25417
  hasStateProp = false;
25396
- // Same precedence as an input above: the signal's value is the answer,
25397
- // defaultValue only the suggestion to start from.
25398
- stateInitial = signal && signal.value !== undefined ? signal.value : props.defaultValue;
25399
- if (signal) {
25400
- stateFromSignal = stateInitial;
25401
- }
25402
- } else if (signal) {
25403
- hasStateProp = true;
25404
- stateInitial = signal.value;
25418
+ stateInitial = props.defaultValue;
25405
25419
  } else {
25406
25420
  hasStateProp = false;
25407
25421
  stateInitial = undefined;
@@ -46878,7 +46892,10 @@ const resolveInputProps = (props) => {
46878
46892
  if (Object.hasOwn(props, "defaultChecked")) ; else {
46879
46893
  // If no explicit defaultChecked, derive it from the signal's default
46880
46894
  // value so that resetUIState restores to the original default.
46881
- const defaultVal = signal.options.getDefaultValue(false);
46895
+ // Only a stateSignal carries a default of its own; a plain signal has
46896
+ // no `options` at all, and asking it for one used to throw on mount —
46897
+ // the same optional read every other branch here already does.
46898
+ const defaultVal = signalOptions?.getDefaultValue(false);
46882
46899
  if (defaultVal === undefined) ; else if (props.type === "radio") {
46883
46900
  if (defaultVal === true) {
46884
46901
  props.defaultChecked = true;
@@ -58928,10 +58945,15 @@ const PickerFirstResolver = props => {
58928
58945
  * picker. "cancel" puts back the value the picker had at open, and a dialog
58929
58946
  * picker also goes back in history — so anything written to the url while it
58930
58947
  * was open (a route `stateSignal`, a search param) goes back with it. "close"
58931
- * makes Escape say what clicking outside says: keep what was chosen, close.
58948
+ * makes Escape say what clicking outside says: keep what was chosen, close
58949
+ * a last resort, see docs/popup_open.md ("Escape cancels, the other gestures
58950
+ * keep") for why Escape should go on meaning cancel, and for what the value
58951
+ * at open is on the picker's very first open.
58932
58952
  * @param {"close"|"cancel"|"capture"} [pointerInteractionOutsideEffect="close"]
58933
58953
  * What a click outside the popup does: close and keep ("close"), close and
58934
- * put back the value at open ("cancel"), or nothing at all ("capture").
58954
+ * put back the value at open ("cancel"), or nothing at all ("capture"). The
58955
+ * default is what gives a popup with no confirm button its way out that
58956
+ * keeps — see the same section.
58935
58957
  * @param {number|string} [marginWithContainer] Minimum gap kept between the
58936
58958
  * popup and the edges of what contains it (the viewport, or the picker's own
58937
58959
  * positioned ancestor for `popupLayer="local"`). Caps the popup's size as