@jsenv/navi 0.29.85 → 0.29.87
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.
- package/dist/jsenv_navi.js +489 -129
- package/dist/jsenv_navi.js.map +34 -14
- package/docs/autofocus.md +20 -12
- package/docs/control_object.md +34 -0
- package/docs/control_value.md +28 -1
- package/docs/form_changed.md +4 -1
- package/package.json +1 -1
package/docs/autofocus.md
CHANGED
|
@@ -82,17 +82,24 @@ itself.
|
|
|
82
82
|
|
|
83
83
|
## On a touch device: the surface is what one arrives on
|
|
84
84
|
|
|
85
|
-
Where the keyboard is a virtual one — anything answering `pointer: coarse` —
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
the
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
85
|
+
Where the keyboard is a virtual one — anything answering `pointer: coarse` — an
|
|
86
|
+
arrival drops step 3 of the ladder entirely: the focus goes where something
|
|
87
|
+
ASKED for it, and otherwise to the surface itself.
|
|
88
|
+
|
|
89
|
+
Every arrival, not just a popup opening. A slide travelling in (so a
|
|
90
|
+
`RouteTravel` screen too) hands out the focus the same way and loses the same
|
|
91
|
+
thing by landing on the first focusable — more of it, even, a screen having more
|
|
92
|
+
above the fold than a popup. Its surface is the `SlideContainer` box, which is
|
|
93
|
+
what takes the keyboard when the slide holds nothing that can, so the arrows
|
|
94
|
+
keep working from there.
|
|
95
|
+
|
|
96
|
+
The condition is the device, not the shape of what arrives and not the gesture
|
|
97
|
+
that brought it. A virtual keyboard is a fact about the screen: it costs a third
|
|
98
|
+
of the height whatever raised it, and an arrival with no pointer in it at all —
|
|
99
|
+
a popup opened by the page loading, a travel asked for by code — is exactly the
|
|
100
|
+
one that must not be answered "no keyboard here". Docking only makes the cost
|
|
101
|
+
more visible (a bottom sheet is short, so there is less room to lose before the
|
|
102
|
+
title goes), it is not what creates it.
|
|
96
103
|
|
|
97
104
|
Withdrawing only the FIELDS would not be enough either. The first focusable is
|
|
98
105
|
wherever the content happens to put it — and in a popup that explains before it
|
|
@@ -105,7 +112,8 @@ Nothing to pass, and nothing to remember per call site.
|
|
|
105
112
|
|
|
106
113
|
### Opting a field back in
|
|
107
114
|
|
|
108
|
-
Some popups really are opened to type in: one comment box,
|
|
115
|
+
Some popups — and some screens — really are opened to type in: one comment box,
|
|
116
|
+
one rename field.
|
|
109
117
|
There, the field says so itself, and that beats the device — step 2 of the
|
|
110
118
|
ladder comes before step 3 was ever skipped.
|
|
111
119
|
|
package/docs/control_object.md
CHANGED
|
@@ -11,6 +11,7 @@ whose value is an object needs in its popup.
|
|
|
11
11
|
- [`<Form>`: the shape, plus a send](#form-the-shape-plus-a-send)
|
|
12
12
|
- [Naming, and what a nameless group does](#naming-and-what-a-nameless-group-does)
|
|
13
13
|
- [A picker whose value is an object](#a-picker-whose-value-is-an-object)
|
|
14
|
+
- [One line, one key](#one-line-one-key)
|
|
14
15
|
- [A settings sheet](#a-settings-sheet)
|
|
15
16
|
- [`Group` is not `ControlGroup`](#group-is-not-controlgroup)
|
|
16
17
|
|
|
@@ -113,6 +114,39 @@ Two things to get right:
|
|
|
113
114
|
kind a scalar type and there is no group to distribute anything — the whole
|
|
114
115
|
object lands on one control, which is how `"[object Object]"` ends up in a
|
|
115
116
|
url.
|
|
117
|
+
- **A control that helps FIND the answer is not the answer.** A search box above
|
|
118
|
+
a long list, a "select all" beside it: they are tools, and a tool says so with
|
|
119
|
+
`allowNameless`. The picker then walks past it and talks to the list, which is
|
|
120
|
+
what a popup made of one choice and the means to reach it needs.
|
|
121
|
+
|
|
122
|
+
```jsx
|
|
123
|
+
<Picker name="place_ids" type="array">
|
|
124
|
+
<Input allowNameless placeholder="chercher" navi-list="places" />
|
|
125
|
+
<List id="places" selectable multiple>
|
|
126
|
+
…
|
|
127
|
+
</List>
|
|
128
|
+
</Picker>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## One line, one key
|
|
132
|
+
|
|
133
|
+
A row that opens a popup is one control, so what it answers arrives under its
|
|
134
|
+
one name. A row answering two questions at once — where the level comes from
|
|
135
|
+
AND which levels, when it starts AND when it ends — hands back a sub-object:
|
|
136
|
+
|
|
137
|
+
```jsx
|
|
138
|
+
<Picker name="level" type="object"> // { level: { level_mode, levels } }
|
|
139
|
+
<Picker name="hours" type="object"> // { hours: { from_minute, to_minute } }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Flattening those into the sent object is the caller's business
|
|
143
|
+
(`{ ...value.level, ...value.hours }`), and it is the only reasonable place for
|
|
144
|
+
it: a picker with no name of its own could not be collected, and one merging its
|
|
145
|
+
keys into the object around it would take the row's own identity away — nothing
|
|
146
|
+
would say which row a key came from, nor which row to put an incoming value
|
|
147
|
+
back on. A `<ControlGroup>` with no name IS that merge, and it exists for the
|
|
148
|
+
case where there is no row: several controls in one screen, no door between
|
|
149
|
+
them.
|
|
116
150
|
|
|
117
151
|
## A settings sheet
|
|
118
152
|
|
package/docs/control_value.md
CHANGED
|
@@ -8,6 +8,7 @@ somewhere else in the app.
|
|
|
8
8
|
- [A bound signal works in both directions](#a-bound-signal-works-in-both-directions)
|
|
9
9
|
- [`signal` + `defaultValue`: the answer and where it starts](#signal--defaultvalue-the-answer-and-where-it-starts)
|
|
10
10
|
- [What a signal holds, control by control](#what-a-signal-holds-control-by-control)
|
|
11
|
+
- [Empty keeps the shape of the question](#empty-keeps-the-shape-of-the-question)
|
|
11
12
|
- [Which controls take a `signal`](#which-controls-take-a-signal)
|
|
12
13
|
- [`value` and `signal` exclude each other](#value-and-signal-exclude-each-other)
|
|
13
14
|
- [A `stateSignal` brings more than a value](#a-statesignal-brings-more-than-a-value)
|
|
@@ -117,6 +118,31 @@ writes it, and what they change is written back into it. One signal for a screen
|
|
|
117
118
|
whose values arrive together — see
|
|
118
119
|
[create_and_edit.md](./create_and_edit.md#two-screens-two-states).
|
|
119
120
|
|
|
121
|
+
## Empty keeps the shape of the question
|
|
122
|
+
|
|
123
|
+
What a control is worth when it holds nothing has the type of what it holds when
|
|
124
|
+
it holds something. A list of days nobody picked is `[]`, not `""`:
|
|
125
|
+
|
|
126
|
+
| control | empty is |
|
|
127
|
+
| ------------------------------------------------- | -------- |
|
|
128
|
+
| `Picker type="array"`, `List selectable multiple` | `[]` |
|
|
129
|
+
| `Picker type="object"` | `{}` |
|
|
130
|
+
| text/number/date `Input`, `Select` | `""` |
|
|
131
|
+
| `Input type="checkbox" value={true}` | `false` |
|
|
132
|
+
| radio, checkbox holding a value of its own | absent |
|
|
133
|
+
|
|
134
|
+
This is what a clear (`--navi-clear`, a row's cross) leaves behind and what the
|
|
135
|
+
object around it carries, so the conversion nobody writes — `value.days || []` —
|
|
136
|
+
is not needed, and not needed only after having watched the wrong shape reach
|
|
137
|
+
the server.
|
|
138
|
+
|
|
139
|
+
A checkbox is a member of a set, the way HTML has it: checked it carries its
|
|
140
|
+
`value` (`"on"` when it was given none), unchecked it carries nothing at all —
|
|
141
|
+
which is what lets several checkboxes sharing a name aggregate into an array. A
|
|
142
|
+
checkbox that is a yes/no rather than a member says so with `value={true}`, and
|
|
143
|
+
is then `true` or `false`. Its bound `signal` holds the boolean either way (see
|
|
144
|
+
the table above): what a signal on a checkbox is about is whether it is checked.
|
|
145
|
+
|
|
120
146
|
## Which controls take a `signal`
|
|
121
147
|
|
|
122
148
|
All of them: `Input` (every type), `Picker`, `Select`, `Wheel`, `Spin`,
|
|
@@ -131,7 +157,8 @@ something else read where the slides are — or move them by writing it.
|
|
|
131
157
|
Inside a `List selectable` you can bind the list, or give each `List.Item` its
|
|
132
158
|
own `selected` — but not expect the two to arbitrate. An item that declares
|
|
133
159
|
`selected` is answering for itself, and the list's signal does not reposition
|
|
134
|
-
it.
|
|
160
|
+
it. On screen that reads as a list where clicking does nothing, so navi says it
|
|
161
|
+
in dev the moment the two claims meet: bind one end or the other, not both.
|
|
135
162
|
|
|
136
163
|
## `value` and `signal` exclude each other
|
|
137
164
|
|
package/docs/form_changed.md
CHANGED
|
@@ -168,7 +168,10 @@ row whose value is carried by a hidden input beside it) says so with
|
|
|
168
168
|
<Picker allowNameless ui={…}>
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
It is then neither collected nor complained about
|
|
171
|
+
It is then neither collected nor complained about — and inside a picker's popup
|
|
172
|
+
it is not the control the picker talks to either, which is what lets a search
|
|
173
|
+
box sit above the list that IS the answer (see
|
|
174
|
+
[control_object.md](./control_object.md#a-picker-whose-value-is-an-object)).
|
|
172
175
|
|
|
173
176
|
## See also
|
|
174
177
|
|