@gjermundgaraba-designs/pixel-paper 0.22.0 → 0.22.2

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/DESIGN.md CHANGED
@@ -216,6 +216,7 @@ spacing:
216
216
  reel-gutter: "16px"
217
217
  reel-column-min: "280px"
218
218
  reel-pane-min: "120px"
219
+ bench-work-min: "152px"
219
220
  components:
220
221
  button:
221
222
  backgroundColor: "{colors.paper}"
@@ -924,17 +925,17 @@ The Deck is one centred column, `max-width: 1160px` (`--deck`), padded 24px top,
924
925
 
925
926
  Frames with no surface of their own (Deck, Wall, Stage, Bench) are described here rather than among the components.
926
927
 
927
- **Bench:** a page whose work is the window: a task's terminals and editors side by side, which a reading column would cramp and a frame of its own would scroll twice. Fixed from the top bar's lower edge (hung from it by anchor positioning, like the stage and the rail) to the status bar, the window wide, or from the rail's edge beside a rail (a fixed box takes nothing from `.railed`'s padding, so the bench reads `--rail` itself and follows the reader's width), and from the left edge at 900px and under, where the rail is a drawer. It is a grid of two rows: the head (a PageHead, notices, the rail's open button first) at its own height, padded `24px 16px 0` with 24px between its parts, and the work in all the height left (`minmax(0, 1fr)`), where a reel takes 100% of it. The head's 16px is a reel's gutter (`--reel-gutter`), so the head's edge lines up with the windows' and the reel's own top gutter is the space between them. The page does not scroll: the work scrolls itself where it must (a reel's columns sideways, and down where a column is taller). The Deck stays the frame for pages that read; the Stage, for a canvas with no head.
928
+ **Bench:** a page whose work is the window: a task's terminals and editors side by side, which a reading column would cramp and a frame of its own would scroll twice. Fixed from the top bar's lower edge (hung from it by anchor positioning, like the stage and the rail) to the status bar, the window wide, or from the rail's edge beside a rail (a fixed box takes nothing from `.railed`'s padding, so the bench reads `--rail` itself and follows the reader's width), and from the left edge at 900px and under, where the rail is a drawer. It is a grid of two rows: the head (a PageHead, notices, the rail's open button first) at its own height, padded 24px at the top and 16px at the sides with 24px between its parts, and the work in all the height left, where a reel takes 100% of it. **The work keeps a floor:** `--bench-work-min` (152px, one pane at `--reel-pane-min` between a reel's gutters, the least a reel still shows a window in), whatever the head holds, or all of the bench but 64px on a window too short for both (a bench under 216px), the head's padding and a small button, so the head's first line, the rail's open button at 900px and under, never vanishes. A head taller than what the floor leaves it (a PageHead, a status and two notices on a landscape phone) stops there and scrolls itself, so all of it can be reached while the work stays where it is: the rows are `minmax(0, max-content) minmax(min(var(--bench-work-min), 100% - 64px), 1fr)`. That was chosen over scrolling the whole bench, which would scroll a page around a reel that scrolls itself (a wheel over the reel, held in it, would never reach the page) and push the work off the window to read the head: the head is read once, the work is what the reader keeps in view. A scroller clips what prints past it, so the head pads its foot by 6px (a button's 3px shadow, a focus ring's 4px) and hands the 6px back in a negative margin, the work starting where it would. A keyboard scrolls the head with the arrows from a control in it, and a screen reader reads it whole. The head's 16px is a reel's gutter (`--reel-gutter`), so the head's edge lines up with the windows' and the reel's own top gutter is the space between them. The page does not scroll: the work scrolls itself where it must (a reel's columns sideways, and down where a column is taller). While a dialog in its work is open the bench is lifted over the rail and the bars (see Dialog). The Deck stays the frame for pages that read; the Stage, for a canvas with no head.
928
929
 
929
- **Stage:** the ground itself for a canvas: fixed from the top bar's lower edge (it hangs from the bar by anchor positioning, so a phone's two-line bar fits) to the window's edges. It does not scroll; what is on it pans. Its floating tools sit 16px in from the left edge, centred (along the bottom, centred, on a phone); its bar sits 16px down from the top, centred, wrapping when narrow.
930
+ **Stage:** the ground itself for a canvas: fixed from the top bar's lower edge (it hangs from the bar by anchor positioning, so a phone's two-line bar fits) to the window's edges. It does not scroll; what is on it pans. A dialog in its canvas lifts it over the bars while it is open (see Dialog). Its floating tools sit 16px in from the left edge, centred (along the bottom, centred, on a phone); its bar sits 16px down from the top, centred, wrapping when narrow.
930
931
 
931
- Dialogs are native `<dialog>` elements that fill the viewport as a veil; the card centres in a 24px pad (or sits at 18vh for the command palette) at `min(680px, 100%)`, or `min(440px, 100%)` when narrow, capped at `calc(100vh - 48px)` with its body scrolling between a fixed title bar and a fixed action row. The Banner is fixed 16px above the bottom edge, centred, at most `min(680px, 100vw - 32px)`.
932
+ Dialogs are native `<dialog>` elements that fill the viewport as a veil, over everything on the page, from a Deck or from inside a Bench or a Stage alike; the card centres in a 24px pad (or sits at 18vh for the command palette) at `min(680px, 100%)`, or `min(440px, 100%)` when narrow, capped at `calc(100vh - 48px)` with its body scrolling between a fixed title bar and a fixed action row. The Banner is fixed 16px above the bottom edge, centred, at most `min(680px, 100vw - 32px)`.
932
933
 
933
934
  Breakpoints: 600px (phone; the page title steps to 18px, stats two across, the wall's corner joins the flow, toasts span the bottom), 900px (board columns stack, above it they stretch; a stat's figure steps to 22px).
934
935
 
935
936
  ### Named Rules
936
937
 
937
- **The Panel Scroll Rule.** The page scrolls; a panel does not, except a board column above 900px, a card body inside a dialog, the rail, a window's body (a window is sized by the canvas, not by its content), and a reel, which scrolls sideways, and down where a column is taller than it, its windows sized by its columns. A stage never scrolls, and nor does a bench, whose work scrolls itself. A wide table, a long code line or a run of bar columns scrolls horizontally inside its own panel and never widens the deck.
938
+ **The Panel Scroll Rule.** The page scrolls; a panel does not, except a board column above 900px, a card body inside a dialog, the rail, a window's body (a window is sized by the canvas, not by its content), and a reel, which scrolls sideways, and down where a column is taller than it, its windows sized by its columns. A stage never scrolls, and nor does a bench: its work scrolls itself, and its head scrolls only when the window leaves it less than it holds once the work has its floor. A wide table, a long code line or a run of bar columns scrolls horizontally inside its own panel and never widens the deck.
938
939
 
939
940
  **The 24px Target Rule.** Every target is at least 24px square. A control drawn smaller (a tab, a glyph-switch option, a filter chip, a row toggle, a clickable mark or tag, a text button, a crumb, an error-summary link) keeps its look and takes the pointer over an invisible 24px square centred on it; an icon button never gives up its 24px to a full line (a tag beside it clips first), and links in a list stand 24px apart so no two squares overlap.
940
941
 
@@ -1059,7 +1060,7 @@ The printed button: a paper rectangle in a 2px ink frame that casts a 3px shadow
1059
1060
  - **EmptyState** → `div.empty > h3.empty-title + p`: `headingLevel` is required and picks the title's element, which looks the same at every level. Where the empty state is a page's or a section's main content it is a heading, `3` inside a Panel (whose title is an `h2`), `1` for a gate or a missing page; `"Strong"` prints `strong.empty-title` where it is not (a chart with nothing to chart, a picture of the state). Centred, `26px 16px`, a 12px uppercase 0.08em (`--tracking-title`) headline, a muted 46ch sentence, an optional action 6px below.
1060
1061
  - **Wall** → `main.wall`, `Wall.markView` → `div.wall-mark` (a 30px ink-bordered glyph box beside the 22px wordmark). `Wall.cornerView` → `aside.wall-corner[aria-label]`, rendered just before the Wall: a paper slip in a 2px ink box on the 3px shadow, `6px 8px`, holding what a top bar would (see Layout).
1061
1062
  - **Banner** → `div.banner > span.glyph (.error, .ok, .quiet) + span`: a fixed paper slip on the 3px shadow with a 26px glyph box in the Notice's tones and a sentence that says what happens to the reader's work. It holds a state the whole interface is in, for as long as it lasts, one at a time. It is not a live region (it arrives already holding its sentence, which would go unheard): the application says the state once, when it begins, with the `Announcer.Announce` Command. `"Error"` (the default; red, bang): a state that stops work (offline). `"Warn"` (amber): a state that is passing (reconnecting). `"Ok"` (ink, check): the state just ended (back online), shown briefly and then taken away. `"Quiet"` (head, info): news. With the connection word it is one pair: LinkState `"Reconnecting"` beside a warn Banner, `"Offline"` beside an error Banner with a retry, then `"Online"` beside an ok Banner for a moment; `"Connecting"` takes none.
1062
- - **Rail** (Submodel) → `div.railed > main.deck#main + aside.rail[popover="auto"][aria-label] + div.rail-resize` (a `main.bench#main` in the deck's place for a page whose work is the window): the rail's panels (a tree, places, filters) beside the deck's, after it in the markup so the page's main content and its h1 come first in reading order; the stylesheet fixes the rail at the left under the top bar. One element serves both layouts, so nothing in it renders twice or loses its state: at rest it stands there (its `popover` attribute is inert until opened), and at 900px and under it is hidden and `span.rail-open > button.btn.small[aria-expanded]` at the top of the deck opens it as a drawer: a slice of the dithered ground, `min(var(--rail-drawer), 100vw - 40px)` (320px) wide from the left edge, whatever width the reader gave the rail, closed by a 2px ink rule and the 8px card shadow, entering from the left in three steps over a veil. Its head (`div.rail-head`: the name in the label register and a close IconButton) shows only in the drawer. Opening focuses its first control; Escape, a click on the veil, the close glyph or focus leaving closes it, and all but the last return focus to the button. Widening the window past 900px closes it. The parent reads whether the drawer is open with `Rail.isOpen`, to hold its own page keys while the drawer covers the page. **Its width is the reader's:** after the aside, `div.rail-resize[role="separator"][aria-orientation="vertical"]` ("Width of <label>", `aria-controls` the rail, its width as `aria-valuenow` between `aria-valuemin` 220 and `aria-valuemax` 480 and as "300 pixels" in `aria-valuetext`) is a 12px strip from the rail's right edge outward, over the page's margin and never over the rail's own scrollbar, fixed beside the rail rather than in it (the rail scrolls, and the drawer's first Tab stop is its first control), a `col-resize` cursor showing a 2px ink line down the edge while hovered or focused, hidden with the rail at 900px and under. A pointer drags it, the rail printing the new width as it moves, and Escape or the browser's cancel puts it back; the side arrows, unmodified, step it 16px, a modified arrow being the application's. Let go where it changes the width, or stepped, it reports `ResizedRail` with the width in whole pixels within the bounds, and the parent keeps it and passes it back as `maybeWidth`: the rail holds no width of its own, as the reel holds no layout. The parent keeps it per client, as it keeps focus and scroll, since a width suits a window, not a task. The splitter's handlers are the reel's (`src/drag`), and the rail's Subscriptions, which follow a dragged splitter and take Escape, are lifted behind a key prefix of the parent's. A file tree flush in a rail panel (or any panel) drops its own border.
1063
+ - **Rail** (Submodel) → `div.railed > main.deck#main + aside.rail[popover="auto"][aria-label] + div.rail-resize` (a `main.bench#main` in the deck's place for a page whose work is the window): the rail's panels (a tree, places, filters) beside the deck's, after it in the markup so the page's main content and its h1 come first in reading order; the stylesheet fixes the rail at the left under the top bar. One element serves both layouts, so nothing in it renders twice or loses its state: at rest it stands there (its `popover` attribute is inert until opened), and at 900px and under it is hidden and `span.rail-open > button.btn.small[aria-expanded]` at the top of the deck opens it as a drawer: a slice of the dithered ground, `min(var(--rail-drawer), 100vw - 40px)` (320px) wide from the left edge, whatever width the reader gave the rail, closed by a 2px ink rule and the 8px card shadow, entering from the left in three steps over a veil. Its head (`div.rail-head`: the name in the label register and a close IconButton) shows only in the drawer. Opening focuses its first control; Escape, a click on the veil, the close glyph or focus leaving closes it, and all but the last return focus to the button. Widening the window past 900px closes it. The parent reads whether the drawer is open with `Rail.isOpen`, to hold its own page keys while the drawer covers the page. **Its width is the reader's:** after the aside, `div.rail-resize[role="separator"][aria-orientation="vertical"]` ("Width of <label>", `aria-controls` the rail, its width as `aria-valuenow` between `aria-valuemin` 220 and `aria-valuemax` 480 and as "300 pixels" in `aria-valuetext`) is a 12px strip from the rail's right edge outward, over the page's margin and never over the rail's own scrollbar, fixed beside the rail rather than in it (the rail scrolls, and the drawer's first Tab stop is its first control), a `col-resize` cursor showing a 2px ink line down the edge while hovered or focused, hidden with the rail at 900px and under. A pointer drags it, the rail printing the new width as it moves, and Escape or the browser's cancel puts it back; the side arrows, unmodified, step it 16px, a modified arrow being the application's. Let go where it changes the width, or stepped, it reports `ResizedRail` with the width in whole pixels within the bounds, and the parent keeps it and passes it back as `maybeWidth`: the rail holds no width of its own, as the reel holds no layout. Until one is given, the splitter says 272px, a copy of `--rail` in the component's code: the server render needs the number before anything is measured, and the package is compiled from `src/` by `tsc` alone, which the specimen's token scanner (a dev dependency, fed through Vite's `?raw`) cannot reach without a build step of its own. The parent keeps it per client, as it keeps focus and scroll, since a width suits a window, not a task. The splitter's handlers are the reel's (`src/drag`), and the rail's Subscriptions, which follow a dragged splitter and take Escape, are lifted behind a key prefix of the parent's. A file tree flush in a rail panel (or any panel) drops its own border.
1063
1064
  - **Stage** → `main.stage#main > div.stage-work > div.stage-canvas + div.stage-tools + div.stage-bar`: see Layout. `paused` (a Notice saying why: the link dropped, the page is read-only) veils the work when editing stops: `div.stage-paused[role="status"]` lays the dialog veil and its ink grain over everything and centres that Notice on the 3px button shadow, while the work beneath is `inert`. It lifts when `paused` is not given; the connection word says reconnecting meanwhile.
1064
1065
  - **Window** → `section.panel.window (.flush) > header.panel-tb + div.window-body + div.panel-foot`: a Panel for a stage or a reel, as tall and wide as whatever places it (and moved by it, if anything moves it). Its title bar is the panel's, trimmed to hold tools: 30px tall (`3px 3px 3px 10px`, its left trimmed to 3px under a `lead`), centred, with an optional `lead` (`span.panel-lead`, a quiet IconButton: a Reel's grip), an optional kind glyph, the title (clipped with an ellipsis), a status chip (its border turns paper so it reads on ink), tools and a close IconButton, both in the bar's paper. Tools a child Submodel hands back come as one element, `span.window-tools`, which is no box of its own (`display: contents`), so its buttons sit in the bar as the others do. The body scrolls inside (`16px`, a 14px grid); flush, what fills it (a code surface, a file tree, a diff) drops its border and fills it. A foot is a panel foot; a notice there takes the whole line.
1065
1066
  - **Loading** → `div.loading[role="status"]`: where content is on its way, centred like an EmptyState at `26px 16px`, a 12px uppercase 0.08em (`--tracking-title`) muted line ("loading the items") ending in the 6×11px working cursor. Its status element stays in the page and only its words change: with `isLoading` false it is `div.loading-idle[role="status"]`, empty and out of the flow (`position: absolute`, never `display: none`, which would drop the live region), so it takes no room and no gap at the top of a panel's or a card's body, and a screen reader hears the line when it arrives. The content or an EmptyState takes its place on screen; the line never prints beside either. It is not the page's live region (the Announcer's).
@@ -1072,7 +1073,7 @@ The printed button: a paper rectangle in a 2px ink frame that casts a 3px shadow
1072
1073
 
1073
1074
  ### Cards (dialogs)
1074
1075
 
1075
- **Dialog** is a Submodel over `@foldkit/ui`'s Dialog: a `<dialog class="veil">` that fills the viewport, opened with `show()` in place rather than `showModal()` in the top layer. That is a deliberate exception to the baseline's "prefer the platform" for overlays: Foldkit's Dialog (through `Dom.showDialog`) makes everything outside the dialog `inert` and `aria-hidden`, traps focus, handles Escape on the topmost dialog and returns focus on close, so the platform's modal behaviour is reproduced, not dropped; what is lost is the top layer and its `::backdrop`. The veil is therefore an element of its own, `div.veil-backdrop` (fixed, Veil with the ink checker grain, entering in 3 steps over 0.12s), under `div.veil-pad` (`.top` for the palette), which lets a press through everywhere but on the card it holds; a press on the veil, Escape, or a control given the `closeButton` group closes it and reports `Closed`. While its work must land in it (a save whose failure the reader has to see), the parent holds those three: its update passes `isCloseHeld` to the dialog's (`Dialog.update(model, message, { isCloseHeld })`, or `foldDialog`'s `isCloseHeld: (model) => model.isSaving`), read from its own state as each Message arrives, so the hold starts with the work, ends with it, and covers a key pressed before the next render: the dialog stays open and reports no `Closed`. Nothing is stored, so there is nothing to let go of. Opening and closing are the parent's, through `Dialog.open` and `Dialog.close` in its update, and a step the parent asked for reports nothing; `Dialog.foldDialog` lifts a dialog the parent always holds (its update, `open` and `close`) into the parent at once, `Closed` reported only where the parent maps it. The content is the parent's `toView`, which receives the attribute groups to spread (`title`, `description`, `initialFocus`, `closeButton`, `actionBar`). Focus starts on the element given the `initialFocus` group, else the first control. The Card inside names the dialog through its title (the `title` group, `aria-labelledby`); a dialog without a heading takes `label`, printed for screen readers only. `isAlert` makes it an `alertdialog`, and `hasDescription` points `aria-describedby` at the element given the `description` group. Because the page outside is inert and hidden, anything that must be heard or reached while it is open renders inside it: the topmost open dialog hosts the page's live region and the toast stack, both outside the card, through its `toLiveRegionView` (see Building components).
1076
+ **Dialog** is a Submodel over `@foldkit/ui`'s Dialog: a `<dialog class="veil">` that fills the viewport, opened with `show()` in place rather than `showModal()` in the top layer. That is a deliberate exception to the baseline's "prefer the platform" for overlays: Foldkit's Dialog (through `Dom.showDialog`) makes everything outside the dialog `inert` and `aria-hidden`, traps focus, handles Escape on the topmost dialog and returns focus on close, so the platform's modal behaviour is reproduced, not dropped; what is lost is the top layer and its `::backdrop`. **Out of the top layer, a dialog layers where it is rendered:** its inline z-index counts inside its nearest stacking context. In the page's flow (a Deck, a Wall) that is the page, and the veil prints over everything. A fixed frame, a Bench or a Stage, is a stacking context of its own, which the rail (fixed, later in the page) and the bars would print over, so while the frame holds an open dialog (`:is(.bench, .stage):has(dialog.veil[open])`) the stylesheet lifts the frame to `z-index: 250`: over the top bar and the status bar (40), the rail and its splitter, a Banner (150) and a menu's slip (200). It is lifted only then, because at rest the rail's splitter lies over the bench's edge and a slip opened from the head prints over the frame. So a dialog is rendered in the page, in a bench's work (`body`) or in a stage's canvas (`body`): never in the rail, whose column is fixed too and is hidden on a phone, nor in a stage's tools or bar, whose `translate` shrinks a fixed veil to their own box. A lifted frame still prints under a dialog in the page's flow, so a dialog in the page closes before one in a frame opens (a palette's command closes the palette first). The veil is therefore an element of its own, `div.veil-backdrop` (fixed, Veil with the ink checker grain, entering in 3 steps over 0.12s), under `div.veil-pad` (`.top` for the palette), which lets a press through everywhere but on the card it holds; a press on the veil, Escape, or a control given the `closeButton` group closes it and reports `Closed`. While its work must land in it (a save whose failure the reader has to see), the parent holds those three: its update passes `isCloseHeld` to the dialog's (`Dialog.update(model, message, { isCloseHeld })`, or `foldDialog`'s `isCloseHeld: (model) => model.isSaving`), read from its own state as each Message arrives, so the hold starts with the work, ends with it, and covers a key pressed before the next render: the dialog stays open and reports no `Closed`. Nothing is stored, so there is nothing to let go of. Opening and closing are the parent's, through `Dialog.open` and `Dialog.close` in its update, and a step the parent asked for reports nothing; `Dialog.foldDialog` lifts a dialog the parent always holds (its update, `open` and `close`) into the parent at once, `Closed` reported only where the parent maps it. The content is the parent's `toView`, which receives the attribute groups to spread (`title`, `description`, `initialFocus`, `closeButton`, `actionBar`). Focus starts on the element given the `initialFocus` group, else the first control. The Card inside names the dialog through its title (the `title` group, `aria-labelledby`); a dialog without a heading takes `label`, printed for screen readers only. `isAlert` makes it an `alertdialog`, and `hasDescription` points `aria-describedby` at the element given the `description` group. Because the page outside is inert and hidden, anything that must be heard or reached while it is open renders inside it: the topmost open dialog hosts the page's live region and the toast stack, both outside the card, through its `toLiveRegionView` (see Building components).
1076
1077
 
1077
1078
  **Card** → `div.card` (`.narrow`; `form.card` from `Card.formView`, named by its title (`aria-label`), so a form landmark; no role of its own, the Dialog around it is the dialog): a paper panel with the card shadow, `min(680px, 100%)` (440px narrow), entering in 3 steps over 0.14s from `scale(0.97)`. An inverted title bar `header.card-tb` (`6px 8px 6px 12px`, 13px uppercase 0.06em (`--tracking-head`), a close IconButton when it has `closeAttributes`, held by `Card.formView`'s `isBusy` while work the reader may not walk away from runs: `aria-disabled`, in the keyboard, its `closeAttributes` and so its handler dropped, faded to 0.6 on the bar, as a held button in a panel's title bar), a scrolling `div.card-body` (16px, 14px gap; a word longer than the card, a path or an id, breaks rather than widening it), and `div.card-actions` (`12px 16px`) over a 2px ink rule: `lead` first, then `span.card-acts` holding the actions at the right, which drop below the lead together when the bar wraps. Inside a Dialog, where the page's keys wait, the bar moves focus between its actions: `h` or ← to the one before, `l` or → to the one after, in the order they print, stopping at the ends, never pressing one (Enter, Space and Tab stay the browser's). The keys are bound by a Mount on the bar (`BindActionKeys`), which reads the real key event: only a key whose target is one of that bar's own buttons or links, unmodified, outside an IME and not already handled, and only when there is an action that way, moves focus and has its default prevented. A field, the title bar's close, a menu's items and a nested dialog's bar keep their keys. A disabled action is passed over; an `aria-disabled` one (held: busy, done or disabled) is still a stop and still ignores presses. **Card.formView** is the one way to make a form card: its `body` in one Fields group, then the action bar's `lead` (a form's own delete, before the push), cancel (`cancel`, closing through `closeAttributes`) and the primary default submit button (`submit`, its id `Card.submitId(id)`). One flag, `isBusy`, holds every way the form could change or leave while its work runs: the submit button prints busy and turns `type="button"`, the close glyph and cancel are held with their close attributes dropped, and the Fields group is natively disabled and `aria-busy`, so nothing changes under the send and nothing sends twice. In a Dialog, the state that sets `isBusy` is the `isCloseHeld` the parent passes the Dialog's update, so Escape and the veil are held with it, and a failed send frees both, the reason on the field (the specimen's rename refuses a name with a slash). `notices` print above the Fields group, outside the hold: what the page says while the form is open (a lost connection with its retry), whose controls stay live while it sends. `isSubmitDisabled` holds the submit button alone while there is nothing to send (a name unchanged), the fields and cancel live. The fields leave the keyboard as they are held, so the update moves focus to the submit button as it sends (`Focus.Focus({ id: Card.submitId(id) })`), and it still ignores `onSubmit` while busy, for an Enter that raced the render. A ConfirmDialog with `isDanger` still opens on cancel.
1078
1079
 
@@ -1120,7 +1121,7 @@ One keyboard for the page, Vim first, with the arrows beside the letters. The ke
1120
1121
 
1121
1122
  **Reel** (Submodel, holding its own drag state rather than `@foldkit/ui`'s DragAndDrop, whose targets are positions in a list and whose pointer reads the items under it; for a workspace of windows side by side: terminals, an editor, a browser, a canvas, in columns the reader arranges) → `div.reel[role="group"][aria-label][data-reel]` holding the scroller `div.reel-view`, whose `div.reel-track` holds, in order, `div.reel-gap` (the gap before the first column), then per column `div.reel-column[data-reel-column]` (the column's id; its share in `--reel-width`) with a `div.reel-slot` per pane (`--reel-weight`, `--reel-anchor`) and between two slots `div.reel-split[role="separator"][aria-orientation="horizontal"]` ("Height of <pane>", `data-reel-split` the id of the pane above it), and after each column `div.reel-gap.reel-resize[role="separator"][aria-orientation="vertical"]` ("Width of column 2", its share as `aria-valuenow` and in words as `aria-valuetext`, `data-reel-resize` its column's id), then `div.reel-panes` with a `div.reel-pane[data-reel-pane][tabindex="-1"]` per pane, each the parent's Window with the pane's grip as its `lead`; after the scroller, the grips' keyboard help in a `p.sr-only` and, while a pointer carries a pane, `div.reel-lift` with its copy. The reel takes its height from whatever holds it. The layout is the parent's (`Reel.Layout`: columns, each an id, a width and its panes, each an id, a label and a weight), passed to the view and, as `{ layout }`, to `update`, so the reel never holds a copy that could go stale. Whenever the parent changes the layout (a request it applied, another client's, a pane it closed), it calls `Reel.reconcile` with the layout as it is now.
1122
1123
 
1123
- **A column has no head.** It is its panes and nothing else: no grip, no width mark, no bar above them, so the only title bars in a reel are its windows'. A head read as a second header over each pane, and its mark (`1/2`) said what the width splitter already says (`aria-valuetext`) and `CycleWidth` says aloud. This holds for every reel, not as an option: the adopters it serves both want the columns bare, and an input for a head nobody asks for would be API for a hypothetical adopter. What the head did is done elsewhere: a pane's grip drags it into another column, between two of its panes or into a gap as a column of its own; a column is sized by the splitter after it and by `CycleWidth`; and a column moves by the application's keys (`MoveColumnLeft`, `MoveColumnRight`), not by a pointer. The live region's words still count columns ("Notes, 2 of 2 in column 2 of 3.", "Width of column 2"), which a reader counts from the left without a head to read the number from.
1124
+ **A column has no head.** It is its panes and nothing else, so the only title bars in a reel are its windows'. That was chosen over a head above each column, which read as a second title bar over its panes and printed what the width splitter already says.
1124
1125
 
1125
1126
  **The Pane Order Rule.** The panes are in the page in one order, by id, whatever their layout, and each is drawn over its slot by anchor positioning (`anchor-name` on the slot, `position-anchor` and `anchor()` insets on the pane; the track is the containing block and the pane layer is `display: contents`). A move changes where a pane is drawn and never its place in the page, so a terminal, a video or an embedded browser keeps its focus, its scroll and its state through any move, and a new pane is inserted among the others without moving them. So Tab follows ids, not columns: give panes ids that sort by when they were made (ULID, UUIDv7) and the reading order is the order they were opened; the keys below move by place.
1126
1127
 
@@ -1,14 +1,17 @@
1
1
  import type { Html, HtmlBuilder } from "foldkit/html";
2
2
  /** Configuration for rendering a bench with `view`. */
3
3
  export type ViewConfig = Readonly<{
4
- /** Above the work, at its own height: a PageHead, notices, and a Rail's open button first. */
4
+ /** Above the work, at its own height while the work keeps its floor, past which it scrolls:
5
+ * a PageHead, notices, and a Rail's open button first. */
5
6
  head: ReadonlyArray<Html | string>;
6
- /** The work, taking the rest of the window's height: a Reel, which fills it. */
7
+ /** The work, taking the rest of the window's height and never less than
8
+ * `--bench-work-min`: a Reel, which fills it, and the page's dialogs. */
7
9
  body: ReadonlyArray<Html | string>;
8
10
  }>;
9
11
  /** A page whose work is the window: its head at its own height, then the work in all the
10
12
  * height left, from under the top bar to the window's bottom and edge to edge (beside a Rail,
11
- * from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll;
12
- * the work scrolls itself where it must (a reel's columns, sideways). */
13
+ * from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll:
14
+ * the work scrolls itself where it must (a reel's columns, sideways), and on a short window
15
+ * the head scrolls in what the work's floor leaves it. */
13
16
  export declare const view: <Message>(config: ViewConfig, h: HtmlBuilder<Message>) => Html;
14
17
  //# sourceMappingURL=bench.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bench.d.ts","sourceRoot":"","sources":["../../../src/bench/bench.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAItD,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,8FAA8F;IAC9F,IAAI,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACnC,gFAAgF;IAChF,IAAI,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;CACpC,CAAC,CAAC;AAEH;;;0EAG0E;AAC1E,eAAO,MAAM,IAAI,GAAI,OAAO,UAAU,UAAU,KAAK,WAAW,CAAC,OAAO,CAAC,KAAG,IAO3E,CAAC"}
1
+ {"version":3,"file":"bench.d.ts","sourceRoot":"","sources":["../../../src/bench/bench.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAItD,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC;+DAC2D;IAC3D,IAAI,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACnC;8EAC0E;IAC1E,IAAI,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;CACpC,CAAC,CAAC;AAEH;;;;2DAI2D;AAC3D,eAAO,MAAM,IAAI,GAAI,OAAO,UAAU,UAAU,KAAK,WAAW,CAAC,OAAO,CAAC,KAAG,IAO3E,CAAC"}
@@ -1,8 +1,9 @@
1
1
  import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
2
2
  /** A page whose work is the window: its head at its own height, then the work in all the
3
3
  * height left, from under the top bar to the window's bottom and edge to edge (beside a Rail,
4
- * from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll;
5
- * the work scrolls itself where it must (a reel's columns, sideways). */
4
+ * from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll:
5
+ * the work scrolls itself where it must (a reel's columns, sideways), and on a short window
6
+ * the head scrolls in what the work's floor leaves it. */
6
7
  export const view = (config, h) => {
7
8
  const { head, body } = config;
8
9
  return __foldkitBrandViewResult((h.main([h.Id("main"), h.Class("bench")], [h.div([h.Class("bench-head")], head), h.div([h.Class("bench-work")], body)])), "@gjermundgaraba-designs/pixel-paper/src/bench/bench.js#view");
@@ -1 +1 @@
1
- {"version":3,"file":"chip.d.ts","sourceRoot":"","sources":["../../../src/chip/chip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAItD;wEACwE;AACxE,eAAO,MAAM,IAAI,sEAA8D,CAAC;AAChF,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAC;AAIpC,sDAAsD;AACtD,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ;8CAC0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC,CAAC;AAUH,0FAA0F;AAC1F,eAAO,MAAM,IAAI,GAAI,OAAO,UAAU,UAAU,KAAK,WAAW,CAAC,OAAO,CAAC,KAAG,IAO3E,CAAC;AAIF,wDAAwD;AACxD,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;IAC/B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;CACb,CAAC,CAAC;AAUH;;yDAEyD;AACzD,eAAO,MAAM,OAAO,GAAI,OAAO,UAAU,SAAS,KAAK,WAAW,CAAC,OAAO,CAAC,KAAG,IAS7E,CAAC"}
1
+ {"version":3,"file":"chip.d.ts","sourceRoot":"","sources":["../../../src/chip/chip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAItD;wEACwE;AACxE,eAAO,MAAM,IAAI,sEAA8D,CAAC;AAChF,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAC;AAIpC,sDAAsD;AACtD,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ;8CAC0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC,CAAC;AAUH,0FAA0F;AAC1F,eAAO,MAAM,IAAI,GAAI,OAAO,UAAU,UAAU,KAAK,WAAW,CAAC,OAAO,CAAC,KAAG,IAO3E,CAAC;AAIF,wDAAwD;AACxD,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;IAC/B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;CACb,CAAC,CAAC;AAEH;;yDAEyD;AACzD,eAAO,MAAM,OAAO,GAAI,OAAO,UAAU,SAAS,KAAK,WAAW,CAAC,OAAO,CAAC,KAAG,IAS7E,CAAC"}
@@ -16,13 +16,6 @@ export const view = (config, h) => {
16
16
  const { label, tone = "Plain", isBusy = false } = config;
17
17
  return __foldkitBrandViewResult((h.span([...(isBusy ? [h.AriaBusy(true)] : []), h.Class(`chip${TONE_CLASS[tone]}`)], [label, ...(isBusy ? [h.span([h.Class("cursor"), h.AriaHidden(true)])] : [])])), "@gjermundgaraba-designs/pixel-paper/src/chip/chip.js#view");
18
18
  };
19
- const DOT_CLASS = {
20
- Plain: "chip-dot",
21
- Go: "chip-dot go",
22
- Warn: "chip-dot warn",
23
- Blocked: "chip-dot blocked",
24
- Done: "chip-dot done",
25
- };
26
19
  /** A chip as a 10px cell in its tone, where a word would take the room a title needs (a task
27
20
  * row's status, before its title). It is an image (`role="img"`) named by the word, which its
28
21
  * tip shows, so the state never rests on its colour. */
@@ -32,6 +25,6 @@ export const dotView = (config, h) => {
32
25
  h.Role("img"),
33
26
  h.AriaLabel(label),
34
27
  h.DataAttribute("tip", label),
35
- h.Class(DOT_CLASS[tone]),
28
+ h.Class(`chip-dot${TONE_CLASS[tone]}`),
36
29
  ])), "@gjermundgaraba-designs/pixel-paper/src/chip/chip.js#dotView");
37
30
  };
@@ -22,9 +22,6 @@ export declare const innerControls: (liftingButtons: string) => string;
22
22
  export declare const takeEscape: <Message>(event: KeyboardEvent, message: Message) => Option.Option<Message>;
23
23
  /** Escape on the window, in the capture phase, as `message`. */
24
24
  export declare const escapeKeys: <Message>(message: Message) => Stream.Stream<Message>;
25
- /** The moves, release and cancel of the pointer `pointerId`, on the document; another
26
- * pointer's are not the drag's. */
27
- export declare const pressingPointer: (pointerId: number) => Stream.Stream<PointerEvent>;
28
25
  /** What the pressing pointer `pointerId` does, as Messages: each move, the release and the
29
26
  * browser's cancel. */
30
27
  export declare const pointerMessages: <Message>(pointerId: number, toMessage: Readonly<{
@@ -1 +1 @@
1
- {"version":3,"file":"drag.d.ts","sourceRoot":"","sources":["../../../src/drag/drag.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,IAAI,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAiB,MAAM,EAAS,MAAM,EAAQ,MAAM,QAAQ,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAM3D;+BAC+B;AAC/B,KAAK,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAKzE,eAAO,MAAM,OAAO,gBAAiB,aAAa,CAAC,KAAK,KAAG,KAU1D,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,UAAU,UAAW,KAAK,KAAG,OACmB,CAAC;AAQ9D,eAAO,MAAM,gBAAgB,WACnB,UAAU,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KACnE,aAAa,CAAC,OAE+B,CAAC;AAEjD,eAAO,MAAM,qBAAqB,WACxB,UAAU,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,KACxE,aAAa,CAAC,OAEoC,CAAC;AAEtD,eAAO,MAAM,YAAY,WACf,UAAU,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAC/D,aAAa,CAAC,OAE2B,CAAC;AAE7C,eAAO,MAAM,eAAe,QAAO,aAAa,CAAC,OAER,CAAC;AAE1C,eAAO,MAAM,aAAa,QAAO,aAAa,CAAC,OAER,CAAC;AAIxC,sDAAsD;AACtD,eAAO,MAAM,WAAW,IAAI,CAAC;AAE7B;4FAC4F;AAC5F,eAAO,MAAM,aAAa,mBAAoB,MAAM,KAAG,MASzC,CAAC;AAMf;4CAC4C;AAC5C,eAAO,MAAM,UAAU,GAAI,OAAO,SACzB,aAAa,WACX,OAAO,KACf,MAAM,CAAC,MAAM,CAAC,OAAO,CAQvB,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,UAAU,GAAI,OAAO,WAAW,OAAO,KAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAMxE,CAAC;AAIL;oCACoC;AACpC,eAAO,MAAM,eAAe,cAAe,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAS3E,CAAC;AAEJ;wBACwB;AACxB,eAAO,MAAM,eAAe,GAAI,OAAO,aAC1B,MAAM,aACN,QAAQ,CAAC;IAClB,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC;IACxC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC;IAC3C,SAAS,EAAE,MAAM,OAAO,CAAC;CAC1B,CAAC,KACD,MAAM,CAAC,MAAM,CAAC,OAAO,CASpB,CAAC;AAIL;;;4EAG4E;AAC5E,eAAO,MAAM,kBAAkB,GAAI,OAAO,UAChC,QAAQ,CAAC;IACf,WAAW,EAAE,UAAU,GAAG,YAAY,CAAC;IACvC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1E,MAAM,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC;CACxC,CAAC,KACC,WAAW,CAAC,OAAO,CAAC,KACtB,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAmBlC,CAAC;AAIF;6CAC6C;AAC7C,eAAO,MAAM,WAAW,YACb,OAAO,kBACA,MAAM,UACd,MAAM,UACN,MAAM,KACb,IAQF,CAAC;AAoBF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,cACd,OAAO,UACV,MAAM,WACL,MAAM,WACN,MAAM,KACd,MA+BF,CAAC;AAMF;;8DAE8D;AAC9D,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAK7C,CAAC"}
1
+ {"version":3,"file":"drag.d.ts","sourceRoot":"","sources":["../../../src/drag/drag.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,IAAI,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAiB,MAAM,EAAS,MAAM,EAAQ,MAAM,QAAQ,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAM3D;+BAC+B;AAC/B,KAAK,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAKzE,eAAO,MAAM,OAAO,gBAAiB,aAAa,CAAC,KAAK,KAAG,KAU1D,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,UAAU,UAAW,KAAK,KAAG,OACmB,CAAC;AAQ9D,eAAO,MAAM,gBAAgB,WACnB,UAAU,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KACnE,aAAa,CAAC,OAE+B,CAAC;AAEjD,eAAO,MAAM,qBAAqB,WACxB,UAAU,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,KACxE,aAAa,CAAC,OAEoC,CAAC;AAEtD,eAAO,MAAM,YAAY,WACf,UAAU,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAC/D,aAAa,CAAC,OAE2B,CAAC;AAE7C,eAAO,MAAM,eAAe,QAAO,aAAa,CAAC,OAER,CAAC;AAE1C,eAAO,MAAM,aAAa,QAAO,aAAa,CAAC,OAER,CAAC;AAIxC,sDAAsD;AACtD,eAAO,MAAM,WAAW,IAAI,CAAC;AAE7B;4FAC4F;AAC5F,eAAO,MAAM,aAAa,mBAAoB,MAAM,KAAG,MASzC,CAAC;AAMf;4CAC4C;AAC5C,eAAO,MAAM,UAAU,GAAI,OAAO,SACzB,aAAa,WACX,OAAO,KACf,MAAM,CAAC,MAAM,CAAC,OAAO,CAQvB,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,UAAU,GAAI,OAAO,WAAW,OAAO,KAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAMxE,CAAC;AAiBL;wBACwB;AACxB,eAAO,MAAM,eAAe,GAAI,OAAO,aAC1B,MAAM,aACN,QAAQ,CAAC;IAClB,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC;IACxC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC;IAC3C,SAAS,EAAE,MAAM,OAAO,CAAC;CAC1B,CAAC,KACD,MAAM,CAAC,MAAM,CAAC,OAAO,CASpB,CAAC;AAIL;;;4EAG4E;AAC5E,eAAO,MAAM,kBAAkB,GAAI,OAAO,UAChC,QAAQ,CAAC;IACf,WAAW,EAAE,UAAU,GAAG,YAAY,CAAC;IACvC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1E,MAAM,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC;CACxC,CAAC,KACC,WAAW,CAAC,OAAO,CAAC,KACtB,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAmBlC,CAAC;AAIF;6CAC6C;AAC7C,eAAO,MAAM,WAAW,YACb,OAAO,kBACA,MAAM,UACd,MAAM,UACN,MAAM,KACb,IAQF,CAAC;AAoBF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,cACd,OAAO,UACV,MAAM,WACL,MAAM,WACN,MAAM,KACd,MA+BF,CAAC;AAMF;;8DAE8D;AAC9D,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAK7C,CAAC"}
@@ -84,7 +84,7 @@ export const escapeKeys = (message) => __foldkitBrandViewResult((Dom.streamFromE
84
84
  // POINTER
85
85
  /** The moves, release and cancel of the pointer `pointerId`, on the document; another
86
86
  * pointer's are not the drag's. */
87
- export const pressingPointer = (pointerId) => __foldkitBrandViewResult((Stream.filter(Stream.mergeAll(Array.map(["pointermove", "pointerup", "pointercancel"], (type) => __foldkitBrandViewResult((Stream.fromEventListener(document, type)), "@gjermundgaraba-designs/pixel-paper/src/drag/drag.js#anonymous")), { concurrency: "unbounded" }), (event) => __foldkitBrandViewResult((event.pointerId === pointerId), "@gjermundgaraba-designs/pixel-paper/src/drag/drag.js#anonymous~2"))), "@gjermundgaraba-designs/pixel-paper/src/drag/drag.js#pressingPointer");
87
+ const pressingPointer = (pointerId) => __foldkitBrandViewResult((Stream.filter(Stream.mergeAll(Array.map(["pointermove", "pointerup", "pointercancel"], (type) => __foldkitBrandViewResult((Stream.fromEventListener(document, type)), "@gjermundgaraba-designs/pixel-paper/src/drag/drag.js#anonymous")), { concurrency: "unbounded" }), (event) => __foldkitBrandViewResult((event.pointerId === pointerId), "@gjermundgaraba-designs/pixel-paper/src/drag/drag.js#anonymous~2"))), "@gjermundgaraba-designs/pixel-paper/src/drag/drag.js#pressingPointer");
88
88
  /** What the pressing pointer `pointerId` does, as Messages: each move, the release and the
89
89
  * browser's cancel. */
90
90
  export const pointerMessages = (pointerId, toMessage) => __foldkitBrandViewResult((Stream.map(pressingPointer(pointerId), (event) => {
@@ -292,7 +292,7 @@ export const view = defineView((model, viewInputs, h) => {
292
292
  orientation: "vertical",
293
293
  isIdle: Option.isNone(model.maybeResizing),
294
294
  onPress: (pointerId, clientX) => __foldkitBrandViewResult((Message.PressedSplitter({ pointerId, clientX, width })), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#onPress"),
295
- onStep: (direction) => __foldkitBrandViewResult((Message.PressedSplitterKey({ width: bounded(width + direction * WIDTH.step) })), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#onStep"),
295
+ onStep: (direction) => __foldkitBrandViewResult((Message.PressedSplitterKey({ width: width + direction * WIDTH.step })), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#onStep"),
296
296
  }, h),
297
297
  ]),
298
298
  ])), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~13");
@@ -1 +1 @@
1
- {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/reel/layout.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/reel/layout.ts"],"names":[],"mappings":"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"}
@@ -213,10 +213,10 @@ export const whereWords = (layout, subject) => __foldkitBrandViewResult((Subject
213
213
  export const originOf = (layout, paneId) => __foldkitBrandViewResult((Option.map(placeOf(layout, paneId), ({ column, row }) => __foldkitBrandViewResult((Target.Into({ columnId: column.id, index: row })), "@gjermundgaraba-designs/pixel-paper/src/reel/layout.js#anonymous~28"))), "@gjermundgaraba-designs/pixel-paper/src/reel/layout.js#originOf");
214
214
  /** What dropping the pane `paneId` at `target` asks of the layout: none where it would
215
215
  * change nothing (where it is, or a target whose column is gone). */
216
- export const requestOf = (layout, paneId, target) => __foldkitBrandViewResult((Option.filter(Option.some(Target.match(target, {
216
+ export const requestOf = (layout, paneId, target) => __foldkitBrandViewResult((Option.liftPredicate(Target.match(target, {
217
217
  Into: ({ columnId, index }) => __foldkitBrandViewResult((OutMessage.MovedPane({ paneId, toColumnId: columnId, toIndex: index })), "@gjermundgaraba-designs/pixel-paper/src/reel/layout.js#Into"),
218
218
  Gap: ({ maybeBeforeColumnId }) => __foldkitBrandViewResult((OutMessage.PulledOutPane({ paneId, maybeBeforeColumnId })), "@gjermundgaraba-designs/pixel-paper/src/reel/layout.js#Gap"),
219
- })), (request) => __foldkitBrandViewResult((!Equal.equals(apply(layout, request), layout)), "@gjermundgaraba-designs/pixel-paper/src/reel/layout.js#anonymous~29"))), "@gjermundgaraba-designs/pixel-paper/src/reel/layout.js#requestOf");
219
+ }), (request) => __foldkitBrandViewResult((!Equal.equals(apply(layout, request), layout)), "@gjermundgaraba-designs/pixel-paper/src/reel/layout.js#anonymous~29"))), "@gjermundgaraba-designs/pixel-paper/src/reel/layout.js#requestOf");
220
220
  /** Where the pane `paneId` would be once dropped at `target`, in words. */
221
221
  export const landingWords = (layout, paneId, target) => __foldkitBrandViewResult((Option.match(requestOf(layout, paneId, target), {
222
222
  onNone: () => __foldkitBrandViewResult((WHERE_IT_WAS), "@gjermundgaraba-designs/pixel-paper/src/reel/layout.js#onNone~7"),
@@ -1 +1 @@
1
- {"version":3,"file":"reel.d.ts","sourceRoot":"","sources":["../../../src/reel/reel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reel.d.ts","sourceRoot":"","sources":["../../../src/reel/reel.ts"],"names":[],"mappings":"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"}
@@ -132,6 +132,8 @@ const focusedPlace = (model, layout) => __foldkitBrandViewResult((Option.orElse(
132
132
  * now nearest its place; the first pane before any is focused. None for an empty layout. */
133
133
  export const focusedPaneId = (model, layout) => __foldkitBrandViewResult((Option.map(focusedPlace(model, layout), ({ pane }) => __foldkitBrandViewResult((pane.id), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~4"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#focusedPaneId");
134
134
  const isHolding = (model) => __foldkitBrandViewResult((Option.isSome(model.maybeHeld)), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#isHolding");
135
+ /** Whether nothing is held and no splitter is dragged: a grip or a splitter may be pressed. */
136
+ const isIdle = (model) => __foldkitBrandViewResult((!isHolding(model) && Option.isNone(model.maybeResizing)), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#isIdle");
135
137
  /** Whether `held` is carried: by the keyboard, or by a pointer past the threshold. */
136
138
  const isCarried = (held) => __foldkitBrandViewResult((By.match(held.by, { Pointer: ({ isCarrying }) => __foldkitBrandViewResult((isCarrying), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#Pointer"), Keyboard: () => __foldkitBrandViewResult((true), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#Keyboard") })), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#isCarried");
137
139
  // DOM HOOKS
@@ -206,7 +208,8 @@ const focusOn = (model, place) => __foldkitBrandViewResult((modifyFields(model,
206
208
  maybeFocus: () => __foldkitBrandViewResult((Option.some({ paneId: place.pane.id, column: place.columnIndex, row: place.row })), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#maybeFocus"),
207
209
  })), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#focusOn");
208
210
  const announce = (text) => __foldkitBrandViewResult((AnnounceReel({ text })), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#announce");
209
- const heldWords = (layout, held) => __foldkitBrandViewResult((String.capitalize(Option.getOrElse(subjectWords(layout, Subject.Pane({ paneId: held.paneId })), () => __foldkitBrandViewResult((""), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~13")))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#heldWords");
211
+ const heldLabel = (layout, held) => __foldkitBrandViewResult((Option.getOrElse(subjectWords(layout, Subject.Pane({ paneId: held.paneId })), () => __foldkitBrandViewResult((""), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~13"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#heldLabel");
212
+ const heldWords = (layout, held) => __foldkitBrandViewResult((String.capitalize(heldLabel(layout, held))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#heldWords");
210
213
  const scrollToTarget = (model, layout, target) => __foldkitBrandViewResult((Array.fromOption(Option.map(columnOfTarget(layout, target), (columnId) => __foldkitBrandViewResult((ScrollIntoView({ hook: columnHook(model, columnId) })), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~14")))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#scrollToTarget");
211
214
  /** Lets go of the held pane: dropped at its target when it is carried and the drop changes
212
215
  * something (reported as the request), put back otherwise, said in `putBack`'s words. */
@@ -235,7 +238,7 @@ const letGo = (model, layout, held, putBack) => {
235
238
  })), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#letGo");
236
239
  };
237
240
  const cancel = (model, layout, held) => __foldkitBrandViewResult((letGo(model, layout, { ...held, maybeTarget: Option.none() }, COPY.cancelled)), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#cancel");
238
- const lift = (model, layout, paneId, by) => __foldkitBrandViewResult((Option.match(Option.filter(originOf(layout, paneId), () => __foldkitBrandViewResult((!isHolding(model) && Option.isNone(model.maybeResizing)), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~17")), {
241
+ const lift = (model, layout, paneId, by) => __foldkitBrandViewResult((Option.match(Option.filter(originOf(layout, paneId), () => __foldkitBrandViewResult((isIdle(model)), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~17")), {
239
242
  onNone: () => (__foldkitBrandViewResult(({ model }), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#onNone~3")),
240
243
  onSome: (origin) => {
241
244
  const held = { paneId, by, maybeTarget: Option.some(origin) };
@@ -330,7 +333,7 @@ export const update = (model, message, context) => {
330
333
  onNone: () => (__foldkitBrandViewResult(({ model }), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#onNone~8")),
331
334
  onSome: (place) => (__foldkitBrandViewResult(({ model: focusOn(model, place) }), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#onSome~7")),
332
335
  })), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#FocusedPane"),
333
- PressedSplitter: ({ splitter, pointerId, clientX, clientY }) => __foldkitBrandViewResult((isHolding(model) || Option.isSome(model.maybeResizing) || !isSplitterPresent(layout, splitter)
336
+ PressedSplitter: ({ splitter, pointerId, clientX, clientY }) => __foldkitBrandViewResult((!isIdle(model) || !isSplitterPresent(layout, splitter)
334
337
  ? { model }
335
338
  : {
336
339
  model: withResizing(model, Option.some({
@@ -640,7 +643,7 @@ const reelSubscriptions = Subscription.make()((entry) => (__foldkitBrandViewResu
640
643
  }),
641
644
  escape: entry({ isHolding: Schema.Boolean }, {
642
645
  modelToDependencies: (model) => (__foldkitBrandViewResult(({
643
- isHolding: isHolding(model) || Option.isSome(model.maybeResizing),
646
+ isHolding: !isIdle(model),
644
647
  }), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#modelToDependencies~4")),
645
648
  dependenciesToStream: ({ isHolding: isHoldingNow }) => __foldkitBrandViewResult((isHoldingNow ? escapeKeys(Message.PressedEscape()) : Stream.empty), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#dependenciesToStream~4"),
646
649
  }),
@@ -681,7 +684,6 @@ const byId = Order.mapInput(Order.String, (pane) => __foldkitBrandViewResult((pa
681
684
  const markOf = (model, layout) => __foldkitBrandViewResult((Option.flatMap(Option.filter(model.maybeHeld, isCarried), (held) => __foldkitBrandViewResult((Option.filter(held.maybeTarget, (target) => __foldkitBrandViewResult((Option.isSome(requestOf(layout, held.paneId, target))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~82"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~81"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#markOf");
682
685
  const carriedIdOf = (model) => __foldkitBrandViewResult((Option.map(Option.filter(model.maybeHeld, isCarried), ({ paneId }) => __foldkitBrandViewResult((paneId), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~83"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#carriedIdOf");
683
686
  const gripView = (model, pane, h) => {
684
- const isIdleNow = !isHolding(model) && Option.isNone(model.maybeResizing);
685
687
  const maybeHeldHere = Option.filter(model.maybeHeld, (held) => __foldkitBrandViewResult((held.paneId === pane.id), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~84"));
686
688
  const isHeld = Option.exists(maybeHeldHere, isCarried);
687
689
  const isKeyboardHeld = Option.exists(maybeHeldHere, (held) => __foldkitBrandViewResult((held.by._tag === "Keyboard"), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~85"));
@@ -697,10 +699,10 @@ const gripView = (model, pane, h) => {
697
699
  : Option.map(Option.fromNullishOr(HELD_STEPS[key]), (step) => __foldkitBrandViewResult((Message.SteppedHeld({ step })), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~87"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~86");
698
700
  }
699
701
  else {
700
- return __foldkitBrandViewResult((Option.liftPredicate(Message.PressedGripKey({ paneId: pane.id }), () => __foldkitBrandViewResult((isIdleNow && isDropKey(key)), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~88"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~86");
702
+ return __foldkitBrandViewResult((Option.liftPredicate(Message.PressedGripKey({ paneId: pane.id }), () => __foldkitBrandViewResult((isIdle(model) && isDropKey(key)), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~88"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~86");
701
703
  }
702
704
  });
703
- const onGripPress = h.OnPointerDown((_pointerType, button, _screenX, _screenY, _time, clientX, clientY, pointerId) => __foldkitBrandViewResult((Option.liftPredicate(Message.PressedGrip({ paneId: pane.id, pointerId, clientX, clientY }), () => __foldkitBrandViewResult((isIdleNow && button === LEFT_BUTTON), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~90"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~89"));
705
+ const onGripPress = h.OnPointerDown((_pointerType, button, _screenX, _screenY, _time, clientX, clientY, pointerId) => __foldkitBrandViewResult((Option.liftPredicate(Message.PressedGrip({ paneId: pane.id, pointerId, clientX, clientY }), () => __foldkitBrandViewResult((isIdle(model) && button === LEFT_BUTTON), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~90"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~89"));
704
706
  return __foldkitBrandViewResult((IconButton.view({
705
707
  glyph: "grip",
706
708
  label: fill(COPY.paneGrip, { pane: pane.label }),
@@ -719,7 +721,7 @@ const gripView = (model, pane, h) => {
719
721
  /** A splitter's handlers: a pointer drags it, and its arrows step it by `SPLITTER_STEP`. */
720
722
  const reelSplitterAttributes = (model, splitter, h) => __foldkitBrandViewResult((splitterAttributes({
721
723
  orientation: splitter._tag === "Width" ? "vertical" : "horizontal",
722
- isIdle: !isHolding(model) && Option.isNone(model.maybeResizing),
724
+ isIdle: isIdle(model),
723
725
  onPress: (pointerId, clientX, clientY) => __foldkitBrandViewResult((Message.PressedSplitter({ splitter, pointerId, clientX, clientY })), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#onPress"),
724
726
  onStep: (direction) => __foldkitBrandViewResult((Message.PressedSplitterKey({ splitter, share: direction * SPLITTER_STEP })), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#onStep"),
725
727
  }, h)), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#reelSplitterAttributes");
@@ -818,7 +820,7 @@ const liftedCopyView = (info, h) => {
818
820
  h.div([h.Class("panel window")], [
819
821
  h.div([h.Class("panel-tb")], [
820
822
  h.span([h.Class("panel-lead")], [h.span([h.Class("iconbtn quiet")], [Glyph.view({ name: "grip" }, h)])]),
821
- h.h2([], [heldWords(layout, held)]),
823
+ h.h2([], [heldLabel(layout, held)]),
822
824
  ]),
823
825
  ]),
824
826
  ]), () => __foldkitBrandViewResult((isCarrying), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#anonymous~105"))), "@gjermundgaraba-designs/pixel-paper/src/reel/reel.js#Pointer~4"),
@@ -1,4 +1,4 @@
1
- import { Effect, Option, Schema, Stream } from "effect";
1
+ import { Effect, Option, Schema } from "effect";
2
2
  import * as Command from "foldkit/command";
3
3
  import type { Html } from "foldkit/html";
4
4
  import * as Mount from "foldkit/mount";
@@ -340,14 +340,6 @@ export declare const update: (model: Model, message: Message) => Readonly<{
340
340
  /** Lets items move, or stops them: while work runs, nothing moves. Stopping cancels an item
341
341
  * that is pressed or held, so no `Moved` arrives for it. */
342
342
  export declare const setMovable: (model: Model, isMovable: boolean) => UpdateReturn;
343
- declare const PointerHold: Schema.Struct<{
344
- readonly listId: Schema.String;
345
- readonly heldHook: Schema.String;
346
- readonly pointerId: Schema.Number;
347
- }>;
348
- type PointerHold = typeof PointerHold.Type;
349
- /** The pressing pointer's moves, release and cancel; another pointer's are not the list's. */
350
- export declare const pointerMessages: (hold: PointerHold) => Stream.Stream<Message>;
351
343
  /** A held item follows the pointer, the arrows and Space move and drop it, Escape puts it back
352
344
  * and the page scrolls near its edges, from listeners that run only while an item is pressed
353
345
  * or held. Lift them into the application's Subscriptions, once per list, behind a key prefix
@@ -1 +1 @@
1
- {"version":3,"file":"sortable.d.ts","sourceRoot":"","sources":["../../../src/sortable/sortable.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sortable.d.ts","sourceRoot":"","sources":["../../../src/sortable/sortable.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@ import * as Subscription from "foldkit/subscription";
10
10
  import * as Update from "foldkit/update";
11
11
  import * as Announcer from "../announcer/announcer.js";
12
12
  import * as Button from "../button/button.js";
13
- import { LEFT_BUTTON, activatedKeyboardDrag, cancelledDrag, escapeKeys, insertionIndex, isCarrying, markDragging, measureLift, movedPointer, phaseOf, pressedDraggable, pressingPointer, releasedPointer, } from "../drag/drag.js";
13
+ import { LEFT_BUTTON, activatedKeyboardDrag, cancelledDrag, escapeKeys, insertionIndex, isCarrying, markDragging, measureLift, movedPointer, phaseOf, pointerMessages as dragMessages, pressedDraggable, releasedPointer, } from "../drag/drag.js";
14
14
  import * as Glyph from "../glyph/glyph.js";
15
15
  import * as IconButton from "../iconButton/iconButton.js";
16
16
  import { LOCALE } from "../locale/locale.js";
@@ -289,7 +289,11 @@ const pointerAt = (hold, event) => (__foldkitBrandViewResult(({
289
289
  maybeIndex: pointerIndex(hold.listId, hold.heldHook, event.clientX, event.clientY),
290
290
  }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#pointerAt"));
291
291
  /** The pressing pointer's moves, release and cancel; another pointer's are not the list's. */
292
- export const pointerMessages = (hold) => __foldkitBrandViewResult((Stream.map(pressingPointer(hold.pointerId), (event) => __foldkitBrandViewResult((Match.value(event.type).pipe(Match.when("pointermove", () => __foldkitBrandViewResult((Message.MovedPointer(pointerAt(hold, event))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~26")), Match.when("pointerup", () => __foldkitBrandViewResult((Message.ReleasedPointer(pointerAt(hold, event))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~27")), Match.orElse(() => __foldkitBrandViewResult((Message.CancelledPointer()), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~28")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~25"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#pointerMessages");
292
+ const pointerMessages = (hold) => __foldkitBrandViewResult((dragMessages(hold.pointerId, {
293
+ moved: (event) => __foldkitBrandViewResult((Message.MovedPointer(pointerAt(hold, event))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#moved"),
294
+ released: (event) => __foldkitBrandViewResult((Message.ReleasedPointer(pointerAt(hold, event))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#released"),
295
+ cancelled: () => __foldkitBrandViewResult((Message.CancelledPointer()), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#cancelled"),
296
+ })), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#pointerMessages");
293
297
  const ownSubscriptions = Subscription.make()((entry) => (__foldkitBrandViewResult(({
294
298
  pointer: entry({ maybeHold: Schema.Option(PointerHold) }, {
295
299
  modelToDependencies: (model) => (__foldkitBrandViewResult(({
@@ -297,9 +301,9 @@ const ownSubscriptions = Subscription.make()((entry) => (__foldkitBrandViewResul
297
301
  listId: id(model),
298
302
  heldHook: itemHook(model, item.id),
299
303
  pointerId,
300
- }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~31")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~30")), () => {
304
+ }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~27")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~26")), () => {
301
305
  const phase = phaseOf(model.dragAndDrop);
302
- return __foldkitBrandViewResult((phase === "Pressed" || phase === "PointerDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~32");
306
+ return __foldkitBrandViewResult((phase === "Pressed" || phase === "PointerDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~28");
303
307
  }),
304
308
  }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#modelToDependencies")),
305
309
  dependenciesToStream: ({ maybeHold }) => __foldkitBrandViewResult((Option.match(maybeHold, {
@@ -311,7 +315,7 @@ const ownSubscriptions = Subscription.make()((entry) => (__foldkitBrandViewResul
311
315
  modelToDependencies: (model) => (__foldkitBrandViewResult(({ isHolding: isHolding(model) }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#modelToDependencies~2")),
312
316
  dependenciesToStream: ({ isHolding: isHoldingNow }) => __foldkitBrandViewResult((isHoldingNow ? escapeKeys(Message.PressedEscape()) : Stream.empty), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#dependenciesToStream~2"),
313
317
  }),
314
- }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~29")));
318
+ }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~25")));
315
319
  // NOTE: @foldkit/ui gap: DragAndDrop's Subscription keys are fixed, so two of its users on a
316
320
  // page would share them. The list lifts the ones it uses under its own names, behind the
317
321
  // parent's prefix.
@@ -337,7 +341,7 @@ export const SizeLiftedItem = Mount.define("SizeLiftedItem", {
337
341
  messages: [Message.CompletedSizeLiftedItem],
338
342
  execute: ({ element, itemHook: hook, pressX, pressY }) => __foldkitBrandViewResult((Effect.sync(() => {
339
343
  measureLift(element, `[data-sortable-id="${CSS.escape(hook)}"]`, pressX, pressY);
340
- return __foldkitBrandViewResult((Message.CompletedSizeLiftedItem()), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~33");
344
+ return __foldkitBrandViewResult((Message.CompletedSizeLiftedItem()), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~29");
341
345
  })), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#execute~2"),
342
346
  });
343
347
  const helpId = (model) => __foldkitBrandViewResult((`${id(model)}-grip-help`), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#helpId");
@@ -354,7 +358,7 @@ const liftedView = (info, item, h) => __foldkitBrandViewResult((h.div([h.Class("
354
358
  const gripView = (info, item, h) => {
355
359
  const { model, isMovable, items } = info;
356
360
  const isIdleNow = phaseOf(model.dragAndDrop) === "Idle";
357
- const onGripKey = h.OnKeyDownPreventDefault((key) => __foldkitBrandViewResult((Option.liftPredicate(Message.PressedGripKey({ itemId: item.id, items }), () => __foldkitBrandViewResult((isIdleNow && (key === " " || key === "Enter")), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~35"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~34"));
361
+ const onGripKey = h.OnKeyDownPreventDefault((key) => __foldkitBrandViewResult((Option.liftPredicate(Message.PressedGripKey({ itemId: item.id, items }), () => __foldkitBrandViewResult((isIdleNow && (key === " " || key === "Enter")), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~31"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~30"));
358
362
  const onGripPress = h.OnPointerDown((_pointerType, button, screenX, screenY, _time, clientX, clientY, pointerId) => __foldkitBrandViewResult((Option.liftPredicate(Message.PressedItem({
359
363
  itemId: item.id,
360
364
  pointerId,
@@ -363,7 +367,7 @@ const gripView = (info, item, h) => {
363
367
  clientX,
364
368
  clientY,
365
369
  items,
366
- }), () => __foldkitBrandViewResult((isIdleNow && button === LEFT_BUTTON), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~37"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~36"));
370
+ }), () => __foldkitBrandViewResult((isIdleNow && button === LEFT_BUTTON), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~33"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~32"));
367
371
  // NOTE: @foldkit/ui gap: DragAndDrop's `draggable` bundle forces `role="option"`, which a
368
372
  // plain list's items are not. So the grip carries the ui's `data-draggable-id` by hand, and
369
373
  // FocusItem finds the grip by it. While moves are held the grip stays, held, so the focus
@@ -385,17 +389,17 @@ const gripView = (info, item, h) => {
385
389
  };
386
390
  /** Where a pointer would drop the held item, marked on the item it would land beside: before
387
391
  * the other item at its target, or after the last. None where it already was. */
388
- const dropMarkOf = (model) => __foldkitBrandViewResult((pipe(model.maybeHeld, Option.filter(() => __foldkitBrandViewResult((phaseOf(model.dragAndDrop) === "PointerDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~38")), Option.flatMap((held) => __foldkitBrandViewResult((pipe(targetIndex(model, held), Option.filter((index) => __foldkitBrandViewResult((!Option.contains(indexOf(held.items, held.item.id), index)), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~40")), Option.flatMap((index) => {
389
- const others = Array.filter(held.items, (item) => __foldkitBrandViewResult((item.id !== held.item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~42"));
392
+ const dropMarkOf = (model) => __foldkitBrandViewResult((pipe(model.maybeHeld, Option.filter(() => __foldkitBrandViewResult((phaseOf(model.dragAndDrop) === "PointerDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~34")), Option.flatMap((held) => __foldkitBrandViewResult((pipe(targetIndex(model, held), Option.filter((index) => __foldkitBrandViewResult((!Option.contains(indexOf(held.items, held.item.id), index)), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~36")), Option.flatMap((index) => {
393
+ const others = Array.filter(held.items, (item) => __foldkitBrandViewResult((item.id !== held.item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~38"));
390
394
  return __foldkitBrandViewResult((Option.orElse(Option.map(Array.get(others, index), (item) => (__foldkitBrandViewResult(({
391
395
  itemId: item.id,
392
396
  side: "Before",
393
- }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~43"))), () => __foldkitBrandViewResult((Option.map(Array.last(others), (item) => (__foldkitBrandViewResult(({
397
+ }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~39"))), () => __foldkitBrandViewResult((Option.map(Array.last(others), (item) => (__foldkitBrandViewResult(({
394
398
  itemId: item.id,
395
399
  side: "After",
396
- }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~45")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~44"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~41");
397
- }))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~39")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#dropMarkOf");
398
- const dropClass = (info, item) => __foldkitBrandViewResult((Option.match(Option.filter(info.maybeDropMark, ({ itemId }) => __foldkitBrandViewResult((itemId === item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~46")), {
400
+ }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~41")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~40"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~37");
401
+ }))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~35")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#dropMarkOf");
402
+ const dropClass = (info, item) => __foldkitBrandViewResult((Option.match(Option.filter(info.maybeDropMark, ({ itemId }) => __foldkitBrandViewResult((itemId === item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~42")), {
399
403
  onNone: () => __foldkitBrandViewResult((""), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onNone~5"),
400
404
  onSome: ({ side }) => (__foldkitBrandViewResult((side === "Before" ? " drop-before" : " drop-after"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onSome~5")),
401
405
  })), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#dropClass");
@@ -406,17 +410,17 @@ const itemView = (info, item, h) => __foldkitBrandViewResult((h.keyed("li")(item
406
410
  * counted as an item. */
407
411
  const itemsView = (info, h) => {
408
412
  const { model, items } = info;
409
- const rows = Array.map(items, (item) => (__foldkitBrandViewResult(({ item, html: itemView(info, item, h) }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~47")));
410
- const maybeSlot = pipe(model.maybeHeld, Option.filter(() => __foldkitBrandViewResult((phaseOf(model.dragAndDrop) === "KeyboardDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~48")), Option.flatMap((held) => __foldkitBrandViewResult((Option.map(targetIndex(model, held), (index) => (__foldkitBrandViewResult(({ held, index }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~50")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~49")));
413
+ const rows = Array.map(items, (item) => (__foldkitBrandViewResult(({ item, html: itemView(info, item, h) }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~43")));
414
+ const maybeSlot = pipe(model.maybeHeld, Option.filter(() => __foldkitBrandViewResult((phaseOf(model.dragAndDrop) === "KeyboardDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~44")), Option.flatMap((held) => __foldkitBrandViewResult((Option.map(targetIndex(model, held), (index) => (__foldkitBrandViewResult(({ held, index }), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~46")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~45")));
411
415
  return __foldkitBrandViewResult((Option.match(maybeSlot, {
412
- onNone: () => __foldkitBrandViewResult((Array.map(rows, ({ html }) => __foldkitBrandViewResult((html), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~51"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onNone~6"),
416
+ onNone: () => __foldkitBrandViewResult((Array.map(rows, ({ html }) => __foldkitBrandViewResult((html), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~47"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onNone~6"),
413
417
  onSome: ({ held, index }) => {
414
418
  const slot = h.keyed("li")("sortable-slot", [h.Class("sortable-slot"), h.AriaHidden(true), h.Inert(true)], [liftedView(info, held.item, h)]);
415
- const others = Array.filter(rows, ({ item }) => __foldkitBrandViewResult((item.id !== held.item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~52"));
419
+ const others = Array.filter(rows, ({ item }) => __foldkitBrandViewResult((item.id !== held.item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~48"));
416
420
  const maybeBefore = Array.get(others, index);
417
421
  return __foldkitBrandViewResult((Option.match(maybeBefore, {
418
- onNone: () => __foldkitBrandViewResult(([...Array.map(rows, ({ html }) => __foldkitBrandViewResult((html), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~53")), slot]), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onNone~7"),
419
- onSome: (before) => __foldkitBrandViewResult((Array.flatMap(rows, ({ item, html }) => __foldkitBrandViewResult((item.id === before.item.id ? [slot, html] : [html]), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~54"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onSome~7"),
422
+ onNone: () => __foldkitBrandViewResult(([...Array.map(rows, ({ html }) => __foldkitBrandViewResult((html), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~49")), slot]), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onNone~7"),
423
+ onSome: (before) => __foldkitBrandViewResult((Array.flatMap(rows, ({ item, html }) => __foldkitBrandViewResult((item.id === before.item.id ? [slot, html] : [html]), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~50"))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onSome~7"),
420
424
  })), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#onSome~6");
421
425
  },
422
426
  })), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#itemsView");
@@ -426,7 +430,7 @@ const liftedCopyView = (info, h) => {
426
430
  const maybeLifted = Option.all({
427
431
  style: UiDragAndDrop.ghostStyle(model.dragAndDrop),
428
432
  held: model.maybeHeld,
429
- press: Option.flatMap(model.maybeHeld, ({ maybePress }) => __foldkitBrandViewResult((maybePress), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~55")),
433
+ press: Option.flatMap(model.maybeHeld, ({ maybePress }) => __foldkitBrandViewResult((maybePress), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~51")),
430
434
  });
431
435
  return __foldkitBrandViewResult((Array.fromOption(Option.map(maybeLifted, ({ style, held, press }) => __foldkitBrandViewResult((h.div([
432
436
  h.Class("sortable-lift"),
@@ -438,9 +442,9 @@ const liftedCopyView = (info, h) => {
438
442
  pressX: press.clientX,
439
443
  pressY: press.clientY,
440
444
  })),
441
- ], [liftedView(info, held.item, h)])), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~56")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#liftedCopyView");
445
+ ], [liftedView(info, held.item, h)])), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~52")))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#liftedCopyView");
442
446
  };
443
- const layoutClass = (layout) => __foldkitBrandViewResult((Match.value(layout).pipe(Match.withReturnType(), Match.when("List", () => __foldkitBrandViewResult(("sortable"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~57")), Match.when("Grid", () => __foldkitBrandViewResult(("sortable grid"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~58")), Match.when("Panels", () => __foldkitBrandViewResult(("sortable panels"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~59")), Match.exhaustive)), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#layoutClass");
447
+ const layoutClass = (layout) => __foldkitBrandViewResult((Match.value(layout).pipe(Match.withReturnType(), Match.when("List", () => __foldkitBrandViewResult(("sortable"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~53")), Match.when("Grid", () => __foldkitBrandViewResult(("sortable grid"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~54")), Match.when("Panels", () => __foldkitBrandViewResult(("sortable panels"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~55")), Match.exhaustive)), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#layoutClass");
444
448
  /**
445
449
  * Items the reader puts in order, as rows, as tiles or as panels, built on `@foldkit/ui`'s
446
450
  * DragAndDrop: `div.sortable` holding `ul.sortable-items` (named by `label`) of
@@ -476,5 +480,5 @@ export const view = defineView((model, viewInputs, h) => {
476
480
  ], itemsView(info, h)),
477
481
  h.p([h.Id(helpId(model)), h.Class("sr-only")], [COPY.gripHelp]),
478
482
  ...liftedCopyView(info, h),
479
- ])), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~60");
483
+ ])), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~56");
480
484
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjermundgaraba-designs/pixel-paper",
3
- "version": "0.22.0",
3
+ "version": "0.22.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -4,16 +4,19 @@ import type { Html, HtmlBuilder } from "foldkit/html";
4
4
 
5
5
  /** Configuration for rendering a bench with `view`. */
6
6
  export type ViewConfig = Readonly<{
7
- /** Above the work, at its own height: a PageHead, notices, and a Rail's open button first. */
7
+ /** Above the work, at its own height while the work keeps its floor, past which it scrolls:
8
+ * a PageHead, notices, and a Rail's open button first. */
8
9
  head: ReadonlyArray<Html | string>;
9
- /** The work, taking the rest of the window's height: a Reel, which fills it. */
10
+ /** The work, taking the rest of the window's height and never less than
11
+ * `--bench-work-min`: a Reel, which fills it, and the page's dialogs. */
10
12
  body: ReadonlyArray<Html | string>;
11
13
  }>;
12
14
 
13
15
  /** A page whose work is the window: its head at its own height, then the work in all the
14
16
  * height left, from under the top bar to the window's bottom and edge to edge (beside a Rail,
15
- * from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll;
16
- * the work scrolls itself where it must (a reel's columns, sideways). */
17
+ * from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll:
18
+ * the work scrolls itself where it must (a reel's columns, sideways), and on a short window
19
+ * the head scrolls in what the work's floor leaves it. */
17
20
  export const view = <Message>(config: ViewConfig, h: HtmlBuilder<Message>): Html => {
18
21
  const { head, body } = config;
19
22
 
package/src/chip/chip.ts CHANGED
@@ -47,14 +47,6 @@ export type DotConfig = Readonly<{
47
47
  tone?: Tone;
48
48
  }>;
49
49
 
50
- const DOT_CLASS: Readonly<Record<Tone, string>> = {
51
- Plain: "chip-dot",
52
- Go: "chip-dot go",
53
- Warn: "chip-dot warn",
54
- Blocked: "chip-dot blocked",
55
- Done: "chip-dot done",
56
- };
57
-
58
50
  /** A chip as a 10px cell in its tone, where a word would take the room a title needs (a task
59
51
  * row's status, before its title). It is an image (`role="img"`) named by the word, which its
60
52
  * tip shows, so the state never rests on its colour. */
@@ -65,6 +57,6 @@ export const dotView = <Message>(config: DotConfig, h: HtmlBuilder<Message>): Ht
65
57
  h.Role("img"),
66
58
  h.AriaLabel(label),
67
59
  h.DataAttribute("tip", label),
68
- h.Class(DOT_CLASS[tone]),
60
+ h.Class(`chip-dot${TONE_CLASS[tone]}`),
69
61
  ]);
70
62
  };
package/src/drag/drag.ts CHANGED
@@ -118,7 +118,7 @@ export const escapeKeys = <Message>(message: Message): Stream.Stream<Message> =>
118
118
 
119
119
  /** The moves, release and cancel of the pointer `pointerId`, on the document; another
120
120
  * pointer's are not the drag's. */
121
- export const pressingPointer = (pointerId: number): Stream.Stream<PointerEvent> =>
121
+ const pressingPointer = (pointerId: number): Stream.Stream<PointerEvent> =>
122
122
  Stream.filter(
123
123
  Stream.mergeAll(
124
124
  Array.map(["pointermove", "pointerup", "pointercancel"] as const, (type) =>
@@ -2732,6 +2732,15 @@ dialog.veil:focus {
2732
2732
  outline: none;
2733
2733
  }
2734
2734
 
2735
+ /* out of the top layer, a dialog's z-index counts inside its nearest stacking context, and a
2736
+ fixed frame is one: while a bench or a stage holds an open dialog the frame itself is lifted,
2737
+ over the bars (40), the rail and its splitter, a banner (150) and a slip (200), as a dialog
2738
+ in the page's flow already prints over them. Lifted only then: at rest the rail's splitter
2739
+ lies over the frame's edge and a slip from its head prints over it */
2740
+ :is(.bench, .stage):has(dialog.veil[open]) {
2741
+ z-index: 250;
2742
+ }
2743
+
2735
2744
  .veil-pad {
2736
2745
  position: relative;
2737
2746
  min-height: 100%;
@@ -5186,8 +5195,10 @@ dialog.veil:focus {
5186
5195
 
5187
5196
  /* hung from the top bar's lower edge like the stage, down to the status bar, edge to edge, or
5188
5197
  from the rail's edge beside one (a fixed box takes nothing from .railed's padding). The head
5189
- takes its own height; the work takes the rest and lays out what fills it (a reel's height
5190
- is 100% of it). The page does not scroll */
5198
+ takes its own height while the work keeps at least --bench-work-min, or all but the head's
5199
+ first 64px (its padding and a small button: the rail's open button) on a window too short
5200
+ for both; past that the head scrolls itself. The work takes the rest and lays out what
5201
+ fills it (a reel's height is 100% of it). The page does not scroll */
5191
5202
  .bench {
5192
5203
  position: fixed;
5193
5204
  top: anchor(--topbar bottom, 0px);
@@ -5195,7 +5206,7 @@ dialog.veil:focus {
5195
5206
  bottom: var(--statusbar-h, 0px);
5196
5207
  left: 0;
5197
5208
  display: grid;
5198
- grid-template-rows: auto minmax(0, 1fr);
5209
+ grid-template-rows: minmax(0, max-content) minmax(min(var(--bench-work-min), 100% - 64px), 1fr);
5199
5210
  }
5200
5211
 
5201
5212
  .railed > .bench {
@@ -5203,11 +5214,16 @@ dialog.veil:focus {
5203
5214
  }
5204
5215
 
5205
5216
  /* the head lines up with a reel's windows, a reel's gutter in from the edge; the reel's own
5206
- gutter is the space between the head and the windows */
5217
+ gutter is the space between the head and the windows. A scroller clips at its padding, so
5218
+ the head pads its foot by the ink a control prints past its box (a 3px shadow, a 4px focus
5219
+ ring) and hands that back to the work, which starts where it would */
5207
5220
  .bench-head {
5208
5221
  display: grid;
5222
+ align-content: start;
5209
5223
  gap: var(--gap);
5210
- padding: var(--gap) var(--reel-gutter) 0;
5224
+ margin-bottom: -6px;
5225
+ padding: var(--gap) var(--reel-gutter) 6px;
5226
+ overflow-y: auto;
5211
5227
  }
5212
5228
 
5213
5229
  .bench-head > *,
package/src/rail/rail.ts CHANGED
@@ -456,7 +456,7 @@ export const view = defineView<Model, Message, ViewInputs>((model, viewInputs, h
456
456
  isIdle: Option.isNone(model.maybeResizing),
457
457
  onPress: (pointerId, clientX) => Message.PressedSplitter({ pointerId, clientX, width }),
458
458
  onStep: (direction) =>
459
- Message.PressedSplitterKey({ width: bounded(width + direction * WIDTH.step) }),
459
+ Message.PressedSplitterKey({ width: width + direction * WIDTH.step }),
460
460
  },
461
461
  h,
462
462
  ),
@@ -343,14 +343,12 @@ export const requestOf = (
343
343
  paneId: string,
344
344
  target: Target,
345
345
  ): Option.Option<OutMessage> =>
346
- Option.filter(
347
- Option.some(
348
- Target.match(target, {
349
- Into: ({ columnId, index }) =>
350
- OutMessage.MovedPane({ paneId, toColumnId: columnId, toIndex: index }),
351
- Gap: ({ maybeBeforeColumnId }) => OutMessage.PulledOutPane({ paneId, maybeBeforeColumnId }),
352
- }),
353
- ),
346
+ Option.liftPredicate(
347
+ Target.match(target, {
348
+ Into: ({ columnId, index }) =>
349
+ OutMessage.MovedPane({ paneId, toColumnId: columnId, toIndex: index }),
350
+ Gap: ({ maybeBeforeColumnId }) => OutMessage.PulledOutPane({ paneId, maybeBeforeColumnId }),
351
+ }),
354
352
  (request) => !Equal.equals(apply(layout, request), layout),
355
353
  );
356
354
 
package/src/reel/reel.ts CHANGED
@@ -211,6 +211,9 @@ export const focusedPaneId = (model: Model, layout: Layout): Option.Option<strin
211
211
 
212
212
  const isHolding = (model: Model): boolean => Option.isSome(model.maybeHeld);
213
213
 
214
+ /** Whether nothing is held and no splitter is dragged: a grip or a splitter may be pressed. */
215
+ const isIdle = (model: Model): boolean => !isHolding(model) && Option.isNone(model.maybeResizing);
216
+
214
217
  /** Whether `held` is carried: by the keyboard, or by a pointer past the threshold. */
215
218
  const isCarried = (held: Held): boolean =>
216
219
  By.match(held.by, { Pointer: ({ isCarrying }) => isCarrying, Keyboard: () => true });
@@ -332,10 +335,11 @@ const focusOn = (model: Model, place: Place): Model =>
332
335
 
333
336
  const announce = (text: string) => AnnounceReel({ text });
334
337
 
338
+ const heldLabel = (layout: Layout, held: Held): string =>
339
+ Option.getOrElse(subjectWords(layout, Subject.Pane({ paneId: held.paneId })), () => "");
340
+
335
341
  const heldWords = (layout: Layout, held: Held): string =>
336
- String.capitalize(
337
- Option.getOrElse(subjectWords(layout, Subject.Pane({ paneId: held.paneId })), () => ""),
338
- );
342
+ String.capitalize(heldLabel(layout, held));
339
343
 
340
344
  const scrollToTarget = (model: Model, layout: Layout, target: Target) =>
341
345
  Array.fromOption(
@@ -385,10 +389,7 @@ const cancel = (model: Model, layout: Layout, held: Held): UpdateReturn =>
385
389
 
386
390
  const lift = (model: Model, layout: Layout, paneId: string, by: By): UpdateReturn =>
387
391
  Option.match(
388
- Option.filter(
389
- originOf(layout, paneId),
390
- () => !isHolding(model) && Option.isNone(model.maybeResizing),
391
- ),
392
+ Option.filter(originOf(layout, paneId), () => isIdle(model)),
392
393
  {
393
394
  onNone: () => ({ model }),
394
395
  onSome: (origin) => {
@@ -539,7 +540,7 @@ export const update = (model: Model, message: Message, context: UpdateContext):
539
540
  },
540
541
  ),
541
542
  PressedSplitter: ({ splitter, pointerId, clientX, clientY }) =>
542
- isHolding(model) || Option.isSome(model.maybeResizing) || !isSplitterPresent(layout, splitter)
543
+ !isIdle(model) || !isSplitterPresent(layout, splitter)
543
544
  ? { model }
544
545
  : {
545
546
  model: withResizing(
@@ -1059,7 +1060,7 @@ const reelSubscriptions = Subscription.make<Model, Message>()((entry) => ({
1059
1060
  { isHolding: Schema.Boolean },
1060
1061
  {
1061
1062
  modelToDependencies: (model) => ({
1062
- isHolding: isHolding(model) || Option.isSome(model.maybeResizing),
1063
+ isHolding: !isIdle(model),
1063
1064
  }),
1064
1065
  dependenciesToStream: ({ isHolding: isHoldingNow }) =>
1065
1066
  isHoldingNow ? escapeKeys(Message.PressedEscape()) : Stream.empty,
@@ -1155,7 +1156,6 @@ const carriedIdOf = (model: Model): Option.Option<string> =>
1155
1156
  Option.map(Option.filter(model.maybeHeld, isCarried), ({ paneId }) => paneId);
1156
1157
 
1157
1158
  const gripView = (model: Model, pane: Pane, h: HtmlBuilder<Message>): Html => {
1158
- const isIdleNow = !isHolding(model) && Option.isNone(model.maybeResizing);
1159
1159
  const maybeHeldHere = Option.filter(model.maybeHeld, (held) => held.paneId === pane.id);
1160
1160
  const isHeld = Option.exists(maybeHeldHere, isCarried);
1161
1161
  const isKeyboardHeld = Option.exists(maybeHeldHere, (held) => held.by._tag === "Keyboard");
@@ -1174,7 +1174,7 @@ const gripView = (model: Model, pane: Pane, h: HtmlBuilder<Message>): Html => {
1174
1174
  } else {
1175
1175
  return Option.liftPredicate(
1176
1176
  Message.PressedGripKey({ paneId: pane.id }),
1177
- () => isIdleNow && isDropKey(key),
1177
+ () => isIdle(model) && isDropKey(key),
1178
1178
  );
1179
1179
  }
1180
1180
  });
@@ -1183,7 +1183,7 @@ const gripView = (model: Model, pane: Pane, h: HtmlBuilder<Message>): Html => {
1183
1183
  (_pointerType, button, _screenX, _screenY, _time, clientX, clientY, pointerId) =>
1184
1184
  Option.liftPredicate(
1185
1185
  Message.PressedGrip({ paneId: pane.id, pointerId, clientX, clientY }),
1186
- () => isIdleNow && button === LEFT_BUTTON,
1186
+ () => isIdle(model) && button === LEFT_BUTTON,
1187
1187
  ),
1188
1188
  );
1189
1189
 
@@ -1215,7 +1215,7 @@ const reelSplitterAttributes = (
1215
1215
  splitterAttributes(
1216
1216
  {
1217
1217
  orientation: splitter._tag === "Width" ? "vertical" : "horizontal",
1218
- isIdle: !isHolding(model) && Option.isNone(model.maybeResizing),
1218
+ isIdle: isIdle(model),
1219
1219
  onPress: (pointerId, clientX, clientY) =>
1220
1220
  Message.PressedSplitter({ splitter, pointerId, clientX, clientY }),
1221
1221
  onStep: (direction) =>
@@ -1401,7 +1401,7 @@ const liftedCopyView = (info: ReelInfo, h: HtmlBuilder<Message>): ReadonlyArray<
1401
1401
  [h.Class("panel-lead")],
1402
1402
  [h.span([h.Class("iconbtn quiet")], [Glyph.view({ name: "grip" }, h)])],
1403
1403
  ),
1404
- h.h2([], [heldWords(layout, held)]),
1404
+ h.h2([], [heldLabel(layout, held)]),
1405
1405
  ],
1406
1406
  ),
1407
1407
  ],
@@ -22,8 +22,8 @@ import {
22
22
  measureLift,
23
23
  movedPointer,
24
24
  phaseOf,
25
+ pointerMessages as dragMessages,
25
26
  pressedDraggable,
26
- pressingPointer,
27
27
  releasedPointer,
28
28
  } from "../drag/drag.ts";
29
29
  import * as Glyph from "../glyph/glyph.ts";
@@ -473,14 +473,12 @@ const pointerAt = (hold: PointerHold, event: PointerEvent): PointerAt => ({
473
473
  });
474
474
 
475
475
  /** The pressing pointer's moves, release and cancel; another pointer's are not the list's. */
476
- export const pointerMessages = (hold: PointerHold): Stream.Stream<Message> =>
477
- Stream.map(pressingPointer(hold.pointerId), (event) =>
478
- Match.value(event.type).pipe(
479
- Match.when("pointermove", () => Message.MovedPointer(pointerAt(hold, event))),
480
- Match.when("pointerup", () => Message.ReleasedPointer(pointerAt(hold, event))),
481
- Match.orElse(() => Message.CancelledPointer()),
482
- ),
483
- );
476
+ const pointerMessages = (hold: PointerHold): Stream.Stream<Message> =>
477
+ dragMessages<Message>(hold.pointerId, {
478
+ moved: (event) => Message.MovedPointer(pointerAt(hold, event)),
479
+ released: (event) => Message.ReleasedPointer(pointerAt(hold, event)),
480
+ cancelled: () => Message.CancelledPointer(),
481
+ });
484
482
 
485
483
  const ownSubscriptions = Subscription.make<Model, Message>()((entry) => ({
486
484
  pointer: entry(
package/src/tokens.css CHANGED
@@ -145,6 +145,9 @@
145
145
  --reel-column-min: 280px; /* the narrowest a column prints, whatever its width */
146
146
  --reel-pane-min: 120px; /* the shortest a pane prints */
147
147
 
148
+ /* ---------- the bench: a page whose work is the window ---------- */
149
+ --bench-work-min: 152px; /* the least of its height the work keeps: a 120px pane, 16px gutters */
150
+
148
151
  /* ---------- charts ---------- */
149
152
  --chart-plot: 160px; /* a line chart's plot, between its top line and its axis */
150
153