@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 +8 -7
- package/dist/src/bench/bench.d.ts +7 -4
- package/dist/src/bench/bench.d.ts.map +1 -1
- package/dist/src/bench/bench.js +3 -2
- package/dist/src/chip/chip.d.ts.map +1 -1
- package/dist/src/chip/chip.js +1 -8
- package/dist/src/drag/drag.d.ts +0 -3
- package/dist/src/drag/drag.d.ts.map +1 -1
- package/dist/src/drag/drag.js +1 -1
- package/dist/src/rail/rail.js +1 -1
- package/dist/src/reel/layout.d.ts.map +1 -1
- package/dist/src/reel/layout.js +2 -2
- package/dist/src/reel/reel.d.ts.map +1 -1
- package/dist/src/reel/reel.js +11 -9
- package/dist/src/sortable/sortable.d.ts +1 -9
- package/dist/src/sortable/sortable.d.ts.map +1 -1
- package/dist/src/sortable/sortable.js +28 -24
- package/package.json +1 -1
- package/src/bench/bench.ts +7 -4
- package/src/chip/chip.ts +1 -9
- package/src/drag/drag.ts +1 -1
- package/src/pixel-paper.css +21 -5
- package/src/rail/rail.ts +1 -1
- package/src/reel/layout.ts +6 -8
- package/src/reel/reel.ts +14 -14
- package/src/sortable/sortable.ts +7 -9
- package/src/tokens.css +3 -0
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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"}
|
package/dist/src/bench/bench.js
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/src/chip/chip.js
CHANGED
|
@@ -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(
|
|
28
|
+
h.Class(`chip-dot${TONE_CLASS[tone]}`),
|
|
36
29
|
])), "@gjermundgaraba-designs/pixel-paper/src/chip/chip.js#dotView");
|
|
37
30
|
};
|
package/dist/src/drag/drag.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/src/drag/drag.js
CHANGED
|
@@ -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
|
-
|
|
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) => {
|
package/dist/src/rail/rail.js
CHANGED
|
@@ -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:
|
|
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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"}
|
package/dist/src/reel/layout.js
CHANGED
|
@@ -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.
|
|
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
|
-
})
|
|
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":"AAAA,OAAO,EAAS,MAAM,EAAwB,MAAM,EAAS,MAAM,EAAkB,MAAM,QAAQ,CAAC;AACpG,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAa,IAAI,EAAe,MAAM,cAAc,CAAC;AAEjE,OAAO,KAAK,KAAK,MAAM,eAAe,CAAC;AAKvC,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,KAAK,MAAM,MAAM,gBAAgB,CAAC;AAiB9C,OAAO,EAGL,KAAK,MAAM,EACX,UAAU,EACV,KAAK,IAAI,EA2BV,MAAM,aAAa,CAAC;AA8DrB;+DAC+D;AAC/D,eAAO,MAAM,KAAK;;;;;;;;;;;gBA/Bd,SAAS;gBACT,MAAM;gBACN,MAAM;gBACN,CAAC;gBACD,CAAC;gBACD,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BZ,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAC;AAWtC,gDAAgD;AAChD,eAAO,MAAM,OAAO;;QAEhB,MAAM;QACN,SAAS;QACT,OAAO;QACP,OAAO;;;QAES,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAIT,IAAI;;;;;;QAIJ,MAAM;;;QAEnB,QAAQ;;;;;;;;QACR,SAAS;QACT,OAAO;QACP,OAAO;;;QAEQ,KAAK;;;QACF,KAAK;;;;QAEH,QAAQ;;;;;;;;QAAY,KAAK;;;;;;;EAM/C,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAC;AAI1C;6CAC6C;AAC7C,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAElD,0EAA0E;AAC1E,eAAO,MAAM,IAAI,WAAY,UAAU,KAAG,KAKxC,CAAC;AAmBH;6FAC6F;AAC7F,eAAO,MAAM,aAAa,UAAW,KAAK,UAAU,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CACjB,CAAC;
|
|
1
|
+
{"version":3,"file":"reel.d.ts","sourceRoot":"","sources":["../../../src/reel/reel.ts"],"names":[],"mappings":"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"}
|
package/dist/src/reel/reel.js
CHANGED
|
@@ -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
|
|
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((
|
|
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((
|
|
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:
|
|
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((
|
|
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((
|
|
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:
|
|
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([], [
|
|
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
|
|
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":"AACA,OAAO,EAAS,MAAM,EAAS,MAAM,EAAE,MAAM,
|
|
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,
|
|
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
|
-
|
|
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~
|
|
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~
|
|
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~
|
|
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~
|
|
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~
|
|
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~
|
|
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~
|
|
389
|
-
const others = Array.filter(held.items, (item) => __foldkitBrandViewResult((item.id !== held.item.id), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
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~
|
|
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~
|
|
397
|
-
}))), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
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~
|
|
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~
|
|
410
|
-
const maybeSlot = pipe(model.maybeHeld, Option.filter(() => __foldkitBrandViewResult((phaseOf(model.dragAndDrop) === "KeyboardDragging"), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~
|
|
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~
|
|
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~
|
|
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~
|
|
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~
|
|
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~
|
|
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~
|
|
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~
|
|
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~
|
|
483
|
+
])), "@gjermundgaraba-designs/pixel-paper/src/sortable/sortable.js#anonymous~56");
|
|
480
484
|
});
|
package/package.json
CHANGED
package/src/bench/bench.ts
CHANGED
|
@@ -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
|
|
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
|
|
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(
|
|
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
|
-
|
|
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) =>
|
package/src/pixel-paper.css
CHANGED
|
@@ -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
|
|
5190
|
-
|
|
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:
|
|
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
|
-
|
|
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:
|
|
459
|
+
Message.PressedSplitterKey({ width: width + direction * WIDTH.step }),
|
|
460
460
|
},
|
|
461
461
|
h,
|
|
462
462
|
),
|
package/src/reel/layout.ts
CHANGED
|
@@ -343,14 +343,12 @@ export const requestOf = (
|
|
|
343
343
|
paneId: string,
|
|
344
344
|
target: Target,
|
|
345
345
|
): Option.Option<OutMessage> =>
|
|
346
|
-
Option.
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
() =>
|
|
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
|
-
() =>
|
|
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:
|
|
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([], [
|
|
1404
|
+
h.h2([], [heldLabel(layout, held)]),
|
|
1405
1405
|
],
|
|
1406
1406
|
),
|
|
1407
1407
|
],
|
package/src/sortable/sortable.ts
CHANGED
|
@@ -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
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
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
|
|