@jsenv/navi 0.29.168 → 0.29.170

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.
@@ -34483,7 +34483,12 @@ const GROUP_DEFAULTS = {
34483
34483
  }
34484
34484
  // Merged in on the way up (see above), so on the way down it takes the
34485
34485
  // whole object and picks out its own keys — the same value it produced.
34486
- if (isNamelessGrouping(child, child.uiState)) {
34486
+ // Only for a child with no name of its own: the same condition the
34487
+ // aggregate applies before merging. A NAMED child holding an object (a
34488
+ // `type="object"` picker, say) answers for one key, and the object it is
34489
+ // not mentioned in says nothing about it — handing it the whole value
34490
+ // would make it hold the group.
34491
+ if (!childName && isNamelessGrouping(child, child.uiState)) {
34487
34492
  return newUIState;
34488
34493
  }
34489
34494
  if (
@@ -34771,7 +34776,20 @@ const useUIGroupStateController = (
34771
34776
  e,
34772
34777
  `${controlType}.getUIState -> ${JSON.stringify(groupUIState)}`,
34773
34778
  );
34774
- if (notifyExternal === true) {
34779
+ if (notifyExternal === true || notifyExternal === "if-it-moves") {
34780
+ if (
34781
+ notifyExternal === "if-it-moves" &&
34782
+ compareTwoJsValues(groupUIState, controller.announcedUIState)
34783
+ ) {
34784
+ // A child confirming what it already shows, to a group that has
34785
+ // already said it: the value arrived while the popup was open and
34786
+ // the group reacted then. One trip through a picker is one answer,
34787
+ // so there is nothing left to say here. Measured against what was
34788
+ // announced rather than against what the group holds — a picker
34789
+ // mounting into a form folds its suggestion into that silently, and
34790
+ // a value nobody was ever told is not one that has been said.
34791
+ return;
34792
+ }
34775
34793
  // Somebody answered: what the group is worth is what its children say
34776
34794
  // between them, from here on.
34777
34795
  controller.stateGivenFromAbove = false;
@@ -34858,6 +34876,11 @@ const useUIGroupStateController = (
34858
34876
  const { controller } = s;
34859
34877
  const currentUIState = controller.uiState;
34860
34878
  controller.uiState = newUIState;
34879
+ // What the outside was last told, which is not what the group is worth:
34880
+ // a child mounting into a group that derived its own value moves that
34881
+ // value through syncInternalState, deliberately without telling anybody
34882
+ // (see onChange). Only what goes through here has been said out loud.
34883
+ controller.announcedUIState = newUIState;
34861
34884
  uiStateSignal.value = newUIState;
34862
34885
  debugUIGroup(
34863
34886
  e,
@@ -34890,6 +34913,7 @@ const useUIGroupStateController = (
34890
34913
  hasDefaultValueProp,
34891
34914
  props,
34892
34915
  uiState: stateInitial,
34916
+ announcedUIState: stateInitial,
34893
34917
  // Whether what the group holds was HANDED to it (a parent distributing,
34894
34918
  // a picker filling its popup, a value prop) rather than worked out from
34895
34919
  // its children. What it protects is read in onChange.
@@ -35085,7 +35109,7 @@ const useUIGroupStateController = (
35085
35109
  onChildUIAction: (
35086
35110
  childUIStateController,
35087
35111
  e,
35088
- { stateChanged, silent },
35112
+ { stateChanged, silent, onlyIfGroupValueMoves },
35089
35113
  ) => {
35090
35114
  const delegatedTo = delegatedChildrenRef.current.get(
35091
35115
  childUIStateController,
@@ -35094,6 +35118,7 @@ const useUIGroupStateController = (
35094
35118
  delegatedTo.onChildUIAction(childUIStateController, e, {
35095
35119
  stateChanged,
35096
35120
  silent,
35121
+ onlyIfGroupValueMoves,
35097
35122
  });
35098
35123
  return;
35099
35124
  }
@@ -35108,7 +35133,11 @@ const useUIGroupStateController = (
35108
35133
  );
35109
35134
  if (stateChanged) {
35110
35135
  onChange(e, {
35111
- notifyExternal: silent ? "silent" : true,
35136
+ notifyExternal: silent
35137
+ ? "silent"
35138
+ : onlyIfGroupValueMoves
35139
+ ? "if-it-moves"
35140
+ : true,
35112
35141
  actingChild: childUIStateController,
35113
35142
  });
35114
35143
  } else {
@@ -41920,10 +41949,8 @@ const css$W = /* css */`@layer navi {
41920
41949
  }
41921
41950
  }
41922
41951
 
41923
- &[data-expand-x] {
41924
- flex-grow: 1;
41925
-
41926
- &:not([data-vertical]):not([data-scrollable]) .navi_link {
41952
+ &[data-expand-x]:not([data-vertical]):not([data-scrollable]) {
41953
+ & .navi_link {
41927
41954
  flex: 1;
41928
41955
  justify-content: center;
41929
41956
  }
@@ -51839,6 +51866,17 @@ const isUIStateHeld = (controller) => {
51839
51866
  * `command` on a control is its reaction to being used, and this is a
51840
51867
  * confirmation happening elsewhere, whose own command (the picker's) is already
51841
51868
  * running.
51869
+ *
51870
+ * And up one, to the group the control answers to: a picker inside a form is
51871
+ * one of its fields, and a form is worth what its fields say. What the popup
51872
+ * put there arrived through a mount sync, which is deliberately silent — a
51873
+ * popup opening is nobody answering (see onChange in ui_state_controller.js) —
51874
+ * so this is the first moment the form can be told.
51875
+ *
51876
+ * That group only hears about it when it moves: a value the user picked in the
51877
+ * popup reached it already, and one trip through a picker is one answer. Down
51878
+ * the subtree the reaction re-runs either way — a control saying again what it
51879
+ * holds says the same thing, and it is where a signal is written.
51842
51880
  */
51843
51881
  const commitUIStateAsAnswer = (controller, e) => {
51844
51882
  if (!controller) {
@@ -51846,6 +51884,10 @@ const commitUIStateAsAnswer = (controller, e) => {
51846
51884
  }
51847
51885
  const answering = controller.facadeChild || controller;
51848
51886
  commitSubtree(answering, e);
51887
+ controller.parentUIStateController?.onChildUIAction(controller, e, {
51888
+ stateChanged: true,
51889
+ onlyIfGroupValueMoves: true,
51890
+ });
51849
51891
  };
51850
51892
  const commitSubtree = (controller, e) => {
51851
51893
  controller.onUIAction?.(e, { skipCommand: true });