@jsenv/navi 0.29.322 → 0.29.324

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.
@@ -159,11 +159,13 @@ to start when unsure which export solves a problem.
159
159
  `triggerNaviCommand` as the last resort, with the event forwarded and never
160
160
  invented; opening ON something; a press that opens and acts is a `Picker`,
161
161
  and its trigger wears the wait and the error (a card that lifts, `openOn`);
162
- Escape cancels; the close cross; a popup that loads data. Read before passing
163
- `open`, calling `triggerNaviCommand`, or writing a close button.
162
+ Escape cancels; the close cross; one panel fed by a slot (`createSlot`,
163
+ `open={isFilled}`); a popup that loads data. Read before passing `open`,
164
+ calling `triggerNaviCommand`, or writing a close button.
164
165
  - `popup_backdrop.md` — three independent questions: a wall or not
165
166
  (`backdrop={false}`), what an outside press does, how far the page withdraws;
166
- `data-navi-popup-outside`. Read before writing CSS for a backdrop.
167
+ `data-navi-popup-outside`, and `data-navi-popup-inside` for a box of the
168
+ page whose press is not a dismissal. Read before writing CSS for a backdrop.
167
169
  - `dialog_shape.md` — bounds rather than a width, the container ceiling, the
168
170
  centered box versus the bottom sheet, `marginWithContainer`. Read before
169
171
  deriving `smallTouchScreenSignal` in an app or writing CSS to make a dialog
@@ -167,6 +167,37 @@ Navi does not warn about a marked container: the column whose gaps must not
167
167
  dismiss and the row whose sides must are the same box from the outside, and
168
168
  only the caller knows which one it wrote.
169
169
 
170
+ ### A box of the page that is not outside
171
+
172
+ `data-navi-popup-inside` is the other direction: a box of the page the caller
173
+ says belongs to a popup, so that a press on it is not outside that popup even
174
+ though it lies beyond the border box. A board with one panel for all its cards
175
+ is the case: pressing another card is what changes what the panel shows, and a
176
+ panel that closes on that press then reopens on the click that follows is a
177
+ panel meant to stay open, blinking.
178
+
179
+ ```jsx
180
+ <SidePanel id="error_panel" closeOnClickOutside backdrop={false} open={isFilled}>
181
+ …
182
+ </SidePanel>
183
+
184
+ <Box data-navi-popup-inside="error_panel" interactions={{ click: openCard }}>
185
+ …
186
+ </Box>
187
+ ```
188
+
189
+ The value names the popup by `id`, the way `commandfor` does, and the exemption
190
+ is that popup's alone: a menu open beside the board still closes when a card is
191
+ pressed. Several popups are named with a space between the ids.
192
+
193
+ Unlike the outside marker, this one answers for its whole subtree: the outside
194
+ marker carves free space out of a surface whose controls stay surface, this one
195
+ adds a whole thing to the popup's ground — the card, its count, its buttons —
196
+ and nothing in it is a dismissal.
197
+
198
+ It reads a press the page hears, so it belongs with a popup that has no wall
199
+ (`backdrop={false}`, or a popover): behind a wall, no card is pressable.
200
+
170
201
  ### `pointer-events: none` and `inert` are not this
171
202
 
172
203
  Neither says "this is backdrop", and reaching for them here is the natural
@@ -862,6 +862,19 @@ changes. A popup is open on exactly one value: what varies while it is open (a
862
862
  tab inside it) is a param of its own, see
863
863
  [navigation.md](./navigation.md#places-inside-the-layer).
864
864
 
865
+ The other way round — ONE sheet showing whichever card the address names — is
866
+ the same signal with no `value`: a popup without one reads anything the signal
867
+ holds as open, except `false`, `null` and `undefined`. The panel's content reads
868
+ the id from the signal, a card's press writes it, and the popup never writes
869
+ over it: opening writes `true` only into a signal that reads closed, closing
870
+ writes `undefined` (or `false`, where the signal held `true`).
871
+
872
+ ```jsx
873
+ <SidePanel signal={errorOpenSignal} side="right">
874
+ <ErrorPanel /> {/* reads errorOpenSignal.value to know which card */}
875
+ </SidePanel>
876
+ ```
877
+
865
878
  ### `navState` — the history entry holds it
866
879
 
867
880
  ```jsx
@@ -899,6 +912,38 @@ afterwards. `defaultOpen="interaction"` means the mount _is_ the opening (the
899
912
  entrance animation plays); any other truthy value means it was already open when
900
913
  the page appeared (no entrance).
901
914
 
915
+ ### One panel, fed by a slot
916
+
917
+ A board with a detail pane wants one panel that stays open as long as something
918
+ asks to be shown in it, and whose content changes from one card to the next
919
+ without the panel closing and reopening. That is `open` driven by a slot:
920
+ `createSlot(Renderer)` keeps the renderer mounted whether or not anything fills
921
+ it, and hands it `isFilled`.
922
+
923
+ ```jsx
924
+ const Panel = ({ isFilled, children }) => (
925
+ <SidePanel
926
+ open={isFilled}
927
+ onClose={() => {
928
+ openCardIdSignal.value = null;
929
+ }}
930
+ >
931
+ {children}
932
+ </SidePanel>
933
+ );
934
+ const [PanelSlot, PanelSlotFill] = createSlot(Panel);
935
+ ```
936
+
937
+ `<PanelSlot />` sits once at the board level; the open card renders a
938
+ `<PanelSlotFill>` holding what the panel shows. The slot holds one filler, the
939
+ last to render: switching cards mounts the next fill in the render that unmounts
940
+ the previous one, and the leaver, unmounting after, leaves the slot to the
941
+ newcomer. `onClose` is the panel's own way out — the close cross, Escape, an
942
+ outside press — and clears the state that renders the fill; the panel follows.
943
+ A press on another card is not an outside press once the card names the panel
944
+ with `data-navi-popup-inside` (see [popup_backdrop.md](./popup_backdrop.md)).
945
+ The full example is `src/layout/demos/7_slot_demo.html`, "two side panels".
946
+
902
947
  ## A popup that loads data
903
948
 
904
949
  Being open is where the user is, and what a popup draws belongs to the screen
package/docs/scroll.md CHANGED
@@ -346,10 +346,12 @@ sheet, a handful of tabs. A collection whose size the caller does not decide
346
346
  The run draws only the rows inside the **render window** — `renderBudget` of
347
347
  them, 100 by default — and holds the room of the others with fillers, so the
348
348
  scrollbar says how long the collection is and the DOM says how many rows fit a
349
- screen and some. The window slides as the user scrolls, and moves only when
350
- what is on screen nears one of its edges: a row crossed is not a window
351
- rebuilt. Below 30 the list warns, because a window shorter than a tall screen
352
- shows blank fillers under the last row.
349
+ screen and some. The window slides as the user scrolls: it keeps three
350
+ quarters of its spare rows ahead of the direction the user goes, and moves
351
+ once those fall under half a screen — a row crossed is not a window rebuilt,
352
+ and a row reached is never a blank one. So the budget has to exceed what the
353
+ scroller shows at once, with room for that lookahead: the list warns below
354
+ 30, and when a budget leaves fewer than two rows beyond the screen.
353
355
 
354
356
  ### The first paint of a list that opens in a click
355
357
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.322",
3
+ "version": "0.29.324",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {