@jsenv/navi 0.29.91 → 0.29.93

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.
@@ -144,6 +144,15 @@ consistency across the app, not from any single call site.
144
144
  `signal` carrying something is an answer). Read it before a screen that
145
145
  modifies an existing resource (`pristineKey`), and before reaching for
146
146
  `canSendWhileUnchanged` because a submit "does nothing".
147
+ - `distributeChildStates` on a group — the way down asked once for ALL the
148
+ children, when they cannot be placed one at a time (four seats where who sits
149
+ down decides who moves). The mirror of `aggregateChildStates`; see
150
+ control_object.md. Read it before writing a `uiAction` whose only job is to
151
+ translate. Two neighbouring questions have answers already: a yes/no shown as
152
+ two rows needs no translation (`List.Item value={true}` beside
153
+ `value={false}` IS a boolean control), and a cross that means "back to the
154
+ usual answer" needs none either — clearing empties, and `placeholder` is
155
+ where that sentence is written (control_value.md).
147
156
  - `docs/control_object.md` — a value made of several controls: `<ControlGroup>`
148
157
  (the shape) vs `<Form>` (the shape plus a send), what a group's `name` does
149
158
  and what a nameless one merges, and what a `<Picker type="object">` needs in
package/docs/actions.md CHANGED
@@ -185,12 +185,12 @@ the event that caused it, and `findEvent(event, type)` walks that chain back:
185
185
  clearable
186
186
  uiAction={(value, event) => {
187
187
  if (findEvent(event, "navi_clear_ui_state")) {
188
- // the clear cross was pressed — for this row that means "back to the
189
- // profile level", not "empty"
190
- draft.level = profile.level;
188
+ // the cross was pressed — the row is empty because somebody emptied it,
189
+ // not because the last player left the list
190
+ askAgainLater();
191
191
  return;
192
192
  }
193
- draft.level = value;
193
+ draft.players = value;
194
194
  }}
195
195
  />
196
196
  ```
@@ -152,6 +152,18 @@ are not all there yet:
152
152
  group holds. Only a child controlled by a `value`/`checked` prop is left
153
153
  alone: its owner decides.
154
154
 
155
+ `distributeChildUIState` is asked child by child, which is fine while each child
156
+ can be placed on its own. When it cannot — four seats where who sits down
157
+ decides who moves, a row whose first answer changes what the others may show —
158
+ `distributeChildStates` is the same way down asked ONCE for all of them:
159
+
160
+ ```js
161
+ distributeChildStates: (groupValue, children) => new Map([[child, state], …])
162
+ ```
163
+
164
+ the mirror of `aggregateChildStates`, which already sees every child. A child
165
+ the Map does not name is left where it is. Given both, the plural one wins.
166
+
155
167
  A group with an `aggregateChildStates` of its own is outside all of this: what
156
168
  it returns is taken as the truth, `undefined` included. That is the one way such
157
169
  a group says **"I have nothing to say yet"** — return `undefined` while the
@@ -11,6 +11,8 @@ somewhere else in the app.
11
11
  - [Empty keeps the shape of the question](#empty-keeps-the-shape-of-the-question)
12
12
  - [Which controls take a `signal`](#which-controls-take-a-signal)
13
13
  - [The PROP is what controls, not its value](#the-prop-is-what-controls-not-its-value)
14
+ - [A yes/no shown as two rows](#a-yesno-shown-as-two-rows)
15
+ - [Clearing, resetting, and what is shown meanwhile](#clearing-resetting-and-what-is-shown-meanwhile)
14
16
  - [`value` and `signal` exclude each other](#value-and-signal-exclude-each-other)
15
17
  - [A `stateSignal` brings more than a value](#a-statesignal-brings-more-than-a-value)
16
18
 
@@ -183,6 +185,54 @@ Passing a prop the code knows will always be `undefined` is the same mistake
183
185
  written once instead of twice: leave it out. navi says so in dev when a group
184
186
  tries to place a child that has claimed itself this way.
185
187
 
188
+ ## A yes/no shown as two rows
189
+
190
+ A checkbox is one way to ask a yes/no; two rows one can compare — "Publique, we
191
+ propose it to players looking for this kind of game" against "Privée, it travels
192
+ only by the link you send" — is another, and it is the same value:
193
+
194
+ ```jsx
195
+ <Picker name="visibility" signal={isPublicSignal}>
196
+ <List selectable>
197
+ <List.Item value={true}>Publique …</List.Item>
198
+ <List.Item value={false}>Privée …</List.Item>
199
+ </List>
200
+ </Picker>
201
+ ```
202
+
203
+ Nothing translates: the row holds the boolean, the form carries the boolean.
204
+ What cannot be done is give a row `undefined` to mean "no value" — `undefined`
205
+ is what UNCHECKED means, here as in HTML, so such a row can never be ticked.
206
+ A value the control can hold is a value one can see; "nothing chosen" is the
207
+ absence of a row, not a row.
208
+
209
+ ## Clearing, resetting, and what is shown meanwhile
210
+
211
+ Three things that look alike and are not:
212
+
213
+ | gesture / prop | what it does |
214
+ | ------------------------- | ----------------------------------------------------------------------------------- |
215
+ | `--navi-clear`, the cross | the control holds its own empty — `""`, `[]`, `{}`, unchecked |
216
+ | `--navi-reset` | the control goes back to its `defaultValue` |
217
+ | `defaultValue` | where it starts, and where a reset goes back to — a real value, sent like any other |
218
+ | `placeholder` | what is SHOWN while it holds nothing, and never a value |
219
+
220
+ So a row whose cross means "back to the one from my profile" needs nothing of
221
+ its own: clearing empties it, and `placeholder` is where that sentence is
222
+ written.
223
+
224
+ ```jsx
225
+ <Picker clearable placeholder="Celui de mon profil" signal={sideSignal} />
226
+ ```
227
+
228
+ What the app then reads is `undefined` (or the empty of the row's type), which
229
+ is what "nothing chosen here, use the usual answer" already means everywhere
230
+ else — the same rule as an emptied signal falling back on its default.
231
+
232
+ A control that cannot show emptiness — a pair of wheels has no blank row to land
233
+ on — takes the same `placeholder` as a POSITION instead of a word (see
234
+ `TimeWheel`): shown, and still not an answer.
235
+
186
236
  ## `value` and `signal` exclude each other
187
237
 
188
238
  `value` (or `checked`) says "you hold it", `signal` says "the signal holds it".
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.91",
3
+ "version": "0.29.93",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {