@crewlethq/ui 0.18.0 → 0.19.0
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/README.md +19 -2
- package/dist/AccessDeniedCard/index.js +2 -2
- package/dist/AppShell/index.js +2 -2
- package/dist/ArrangeBoard/ArrangeBoard.d.ts +32 -0
- package/dist/ArrangeBoard/index.d.ts +3 -0
- package/dist/ArrangeBoard/index.js +2 -0
- package/dist/ArrangeBoard-MQE35P6Z.css +80 -0
- package/dist/ArrangeFrame/ArrangeFrame.d.ts +82 -0
- package/dist/ArrangeFrame/index.d.ts +5 -0
- package/dist/ArrangeFrame/index.js +5 -0
- package/dist/ArrangeFrame/useGridResize.d.ts +66 -0
- package/dist/ArrangeFrame-3PLZAG22.css +329 -0
- package/dist/ArrangeGroup/ArrangeGroup.d.ts +42 -0
- package/dist/ArrangeGroup/index.d.ts +3 -0
- package/dist/ArrangeGroup/index.js +4 -0
- package/dist/ArrangeGroup-SHFHA7BE.css +170 -0
- package/dist/ArrangeList/ArrangeList.d.ts +64 -0
- package/dist/ArrangeList/index.d.ts +3 -0
- package/dist/ArrangeList/index.js +10 -0
- package/dist/ArrangeList-NNRTDFI5.css +94 -0
- package/dist/ArtifactCard/index.js +2 -2
- package/dist/AuthLayout/index.js +2 -2
- package/dist/AvatarPicker/index.js +4 -4
- package/dist/Canvas/index.js +2 -2
- package/dist/Card/index.js +1 -1
- package/dist/Checkbox/index.js +3 -3
- package/dist/Combobox/index.js +4 -4
- package/dist/CommandPalette/index.js +6 -6
- package/dist/Composer/index.js +3 -3
- package/dist/ConfirmField/index.js +3 -3
- package/dist/DataTable/index.js +8 -8
- package/dist/DataView/index.js +13 -13
- package/dist/DateTimePicker/index.js +3 -3
- package/dist/Divider/Divider.d.ts +15 -0
- package/dist/Divider/index.d.ts +3 -0
- package/dist/Divider/index.js +2 -0
- package/dist/Divider-3Z77ZAJH.css +37 -0
- package/dist/HuePicker/HuePicker.d.ts +16 -4
- package/dist/HuePicker/index.js +2 -2
- package/dist/{HuePicker-5QIUR6L7.css → HuePicker-PAIGH6LR.css} +6 -0
- package/dist/IconTile/IconTile.d.ts +23 -0
- package/dist/IconTile/index.d.ts +3 -0
- package/dist/IconTile/index.js +2 -0
- package/dist/IconTile-4GNWTLAW.css +30 -0
- package/dist/Input/index.js +2 -2
- package/dist/LinkInterstitial/index.js +4 -4
- package/dist/ListInput/index.js +5 -5
- package/dist/MarkdownEditor/index.js +2 -2
- package/dist/Menu/index.js +2 -2
- package/dist/Modal/Modal.d.ts +20 -0
- package/dist/Modal/index.js +3 -3
- package/dist/{Modal-RQAYGG4L.css → Modal-XOSV6FAH.css} +14 -0
- package/dist/Note/Note.d.ts +23 -0
- package/dist/Note/index.d.ts +3 -0
- package/dist/Note/index.js +2 -0
- package/dist/Note-RT4L6VUT.css +58 -0
- package/dist/OrgTable/index.js +5 -5
- package/dist/PinTile/PinTile.d.ts +37 -0
- package/dist/PinTile/index.d.ts +3 -0
- package/dist/PinTile/index.js +4 -0
- package/dist/PinTile-IIA25MNZ.css +141 -0
- package/dist/PresenceStack/index.js +1 -1
- package/dist/PrincipalPicker/index.js +5 -5
- package/dist/Reorder/index.d.ts +2 -0
- package/dist/Reorder/index.js +4 -0
- package/dist/Reorder/useReorder.d.ts +138 -0
- package/dist/ShareDialog/index.js +7 -7
- package/dist/SheetGrid/index.js +4 -4
- package/dist/StatGroup/StatGroup.d.ts +7 -1
- package/dist/StatGroup/index.js +1 -1
- package/dist/{StatGroup-HVG6O62W.css → StatGroup-PADTJCUQ.css} +7 -0
- package/dist/Switcher/index.js +8 -8
- package/dist/TagsInput/index.js +3 -3
- package/dist/TimeWindowPicker/index.js +5 -5
- package/dist/TreeCanvas/index.js +3 -3
- package/dist/TreeGrid/index.js +2 -2
- package/dist/chunk-35XVR5JQ.js +81 -0
- package/dist/chunk-63WJLRB2.js +24 -0
- package/dist/{chunk-L4ZLXYPO.js → chunk-6A7P6II6.js} +1 -1
- package/dist/chunk-6KWNXIDE.js +18 -0
- package/dist/chunk-6MIXD6IW.js +49 -0
- package/dist/{chunk-NZY77ZDU.js → chunk-7FQEUNHX.js} +4 -4
- package/dist/{chunk-2TZATTIU.js → chunk-7IJARUIF.js} +18 -5
- package/dist/chunk-AIVZVKYZ.js +126 -0
- package/dist/{chunk-76FXDZAZ.js → chunk-AJESMWJS.js} +4 -4
- package/dist/chunk-DEJHAOC5.js +279 -0
- package/dist/{chunk-ERV5BUS3.js → chunk-EIGEIT4O.js} +3 -3
- package/dist/chunk-FFMCMSJB.js +1 -0
- package/dist/{chunk-LFZ45HV2.js → chunk-G3EEUNZQ.js} +1 -1
- package/dist/{chunk-2YR5ZPQ3.js → chunk-HTCJSUIZ.js} +3 -3
- package/dist/{chunk-75CLJNDQ.js → chunk-I6NZKJGK.js} +1 -1
- package/dist/chunk-IXJHTFXG.js +17 -0
- package/dist/{chunk-3UAA4IWJ.js → chunk-JEDWC3GI.js} +1 -1
- package/dist/{chunk-QVAFL2LE.js → chunk-JXRI5YD2.js} +3 -3
- package/dist/{chunk-ZFH7H7GS.js → chunk-LOLELDBW.js} +1 -1
- package/dist/{chunk-KVT3TJVG.js → chunk-OIMAK5AE.js} +6 -6
- package/dist/chunk-QO7QEQKV.js +24 -0
- package/dist/{chunk-A7EBCHEG.js → chunk-RT323I4I.js} +1 -1
- package/dist/{chunk-BOW2VUCH.js → chunk-T7ICFXEC.js} +1 -1
- package/dist/{chunk-2OLCUNG7.js → chunk-TBIZSQHB.js} +1 -1
- package/dist/{chunk-4U3GQ7D2.js → chunk-TODND5AD.js} +1 -1
- package/dist/{chunk-IFKBDRNJ.js → chunk-UXELEORU.js} +3 -3
- package/dist/{chunk-6NIMZ5XC.js → chunk-VJLYGPPE.js} +1 -1
- package/dist/{chunk-7QFAORCY.js → chunk-WHZFDS62.js} +1 -1
- package/dist/chunk-XJ2QEBMM.js +277 -0
- package/dist/{chunk-PA4CYTBY.js → chunk-XU4ZUGLE.js} +19 -4
- package/dist/{chunk-T3ZWBZ65.js → chunk-YSJYWQSP.js} +2 -2
- package/dist/{chunk-CXBAIVYZ.js → chunk-YSY6UJ4F.js} +1 -1
- package/dist/{chunk-EG6NYWVK.js → chunk-YZCJ63JF.js} +1 -1
- package/dist/generated/index.d.ts +9 -0
- package/dist/generated/index.js +80 -71
- package/dist/index.js +80 -71
- package/dist/styles.css +993 -3
- package/package.json +3 -3
- package/dist/chunk-EXHQ2QVW.js +0 -1
- package/dist/{chunk-ESKP3TXM.js → chunk-4Z7PW3L6.js} +0 -0
- package/dist/{chunk-AQCV62K6.js → chunk-7ZNKEPLN.js} +1 -1
- package/dist/{chunk-OYOQU7O5.js → chunk-EDGCPVVD.js} +1 -1
- package/dist/{chunk-NS7BVLL3.js → chunk-JULMZNGT.js} +1 -1
- package/dist/{chunk-5NVKTB6E.js → chunk-L4H7SSWF.js} +1 -1
- package/dist/{chunk-FYXRWBJJ.js → chunk-PUQY4WXR.js} +2 -2
- package/dist/{chunk-4GB57WIT.js → chunk-Q55TXPA3.js} +1 -1
- package/dist/{chunk-B2Z2CDM5.js → chunk-T5TFZ2JB.js} +1 -1
- package/dist/{chunk-AMH67MLM.js → chunk-TXAFKH2A.js} +1 -1
package/README.md
CHANGED
|
@@ -41,15 +41,16 @@ import { Button } from '@crewlethq/ui/Button'; // 8 KB of CSS, not 182 KB
|
|
|
41
41
|
| Area | Components |
|
|
42
42
|
| ---- | ---------- |
|
|
43
43
|
| Actions | `Button` and `ButtonLink` (variants `primary`, `secondary`, `outline`, `ghost`, `accent`, `danger`; sizes `small`, `medium`, `large`; shapes `square`, `pill`), `IconButton`, `Menu`, `Link`, `Copyable`, `CopyButton`, `DownloadButton`, `Kbd` |
|
|
44
|
-
| Content and text | `Text` (the eight registers and `inherit`), `Prose`, `Document` and `DocumentTitle`, `Highlight`, `InlineCode`, `List` and `ListItem`, `DescriptionList`, `Timeline`, `RelativeTime` |
|
|
44
|
+
| Content and text | `Text` (the eight registers and `inherit`), `Prose`, `Document` and `DocumentTitle`, `Highlight`, `InlineCode`, `List` and `ListItem`, `DescriptionList`, `Timeline`, `RelativeTime`, `Note`, `Divider` |
|
|
45
45
|
| Forms | `Input`, `Textarea`, `Label`, `FormField`, `FormRow`, `Checkbox`, `CheckboxGroup`, `ConfirmField`, `Select`, `Tag`, `TagsInput`, `DateTimePicker`, `TimeWindowPicker`, `ImageUpload`, `CharacterPicker`, `HuePicker`, `AvatarPicker`, `FactList`, `ChoiceList`, `Composer`, `MarkdownEditor` |
|
|
46
|
-
| Data display | `DataTable`, `CopyableCell`, `Table`, `StatCard`, `Meter`, `SegmentedMeter`, `Stepper`, `PricingCard`, `Avatar`, `AvatarStack`, `EntityChip`, `CodeBlock`, `QrCode`, `ObjectHeader`, `FactLine`, `SetByLine`, `Skeleton`, `Eyebrow` |
|
|
46
|
+
| Data display | `DataTable`, `CopyableCell`, `Table`, `StatCard`, `Meter`, `SegmentedMeter`, `Stepper`, `PricingCard`, `Avatar`, `AvatarStack`, `EntityChip`, `CodeBlock`, `QrCode`, `ObjectHeader`, `FactLine`, `SetByLine`, `Skeleton`, `Eyebrow`, `StatGroup`, `PinTile`, `IconTile` |
|
|
47
47
|
| List screens | `DataView`, and its parts on their own: `DataViewToolbar`, `FilterAxisBar`, `FilterAxisChip`, plus the filter model (`filterDefsFromColumns`, `applyColumnFilters`, `filterPredicate`, `blankFilterValue`) |
|
|
48
48
|
| Feedback and overlays | `Callout`, `Toaster`, `Modal` (with `variant="sheet"`), `ConfirmModal`, `CommandPalette`, `Tooltip`, `Popover`, `Announcer` |
|
|
49
49
|
| Charts | `Legend`, `BarList`, `StackedBar`, `StackedColumns`, `ActivityStrip`, `TimeSeries`, `Sparkline`, the reading layer they share (`ChartTooltip`, `useChartHover`), and the ramp (`DATA_COLORS`, `DATA_COLOR_OTHER`, `dataColor`) |
|
|
50
50
|
| Marks | `Count`, `StatusDot`, `EmptyValue`, `VisuallyHidden` |
|
|
51
51
|
| Hooks and seams | `useModalLayer`, `usePopupLayer`, `LayerHost`, `useListbox`, `useOptionKeys`, `useHighlightRest` and `HIGHLIGHT_REST_MS`, `useClipboard`, `useDownload`, `downloadText`, `safeFilename`, `useOutcome`, `useAnnouncer`, `useNow`, `formatRelative`, `HeadingLevelProvider`, `cx`, the node hues (`NODE_HUES`, `NODE_HUE_NAMES`, `isNodeHue`) |
|
|
52
52
|
| Layout | `Container`, `Section`, `Card`, `Tabs`, `Accordion`, `Disclosure`, `Outline` (with `useActiveHeading` and `scrollToHeading`), `TreeGrid` |
|
|
53
|
+
| Arranging a page | `ArrangeBoard`, `ArrangeFrame` (with `useGridResize`), `ArrangeGroup`, `ArrangeList`, and the reorder hooks under them (`useReorder`, `useReorderLists`, `moveKey`) |
|
|
53
54
|
| Application shell | `AppShell` with `AppShell.Rail`, `AppShell.Topbar`, `AppShell.AccountRow` and `useAppShell`, `AuthLayout`, `SidebarNav` and `NavItem`, `BrandLockup`, `SearchTrigger`, `PageHeader`, `Toolbar`, `Stack`, `Inline`, `Spacer`, `AutoGrid`, `ErrorBoundary`, `useShortcut`, `useFullscreen` |
|
|
54
55
|
| Preferences | `ThemeToggle`, `ThemeSwitcher`, `DensitySwitcher`, `ThemeGallery`, `ThemeSwatch`, `useThemePreference`, `useDensityPreference`, `useSystemTheme`, `resolveTheme`, `applyStoredPreferences`, and the framework-free `applyTheme`, `applyPalette`, `applyDensity` with `THEME_PREFERENCES`, `DENSITY_PREFERENCES` and their guards |
|
|
55
56
|
| Artifacts | `SandboxedFrame`, `LinkInterstitial` and `openExternal`, `VersionTimeline`, `ShareDialog` with the role ladder (`ARTIFACT_ROLES`, `SHAREABLE_ROLES`, `roleAtLeast`), `PrincipalPicker`, `Principal` and `PrincipalAvatar`, `ArtifactCard` and `ArtifactKindGlyph`, `AccessDeniedCard`, and `FrameProtocol` (the wire between a host page and an embedded artifact, with no React in it) |
|
|
@@ -201,6 +202,22 @@ places:
|
|
|
201
202
|
- A surface that pans or zooms dispatches `LAYER_REPOSITION_EVENT` on its host
|
|
202
203
|
when the content beneath it moves, and every panel anchored inside follows.
|
|
203
204
|
|
|
205
|
+
## Changes in 0.19.0
|
|
206
|
+
|
|
207
|
+
0.19.0 adds what a page needs to be arranged by its reader: blocks they move, resize and group on a board, the layout pieces they add between them, and the tray those come from. The engine console's Home is built from it.
|
|
208
|
+
|
|
209
|
+
**`useReorder` and `useReorderLists`** put items in order within one list or across several (a page and the groups on it), by drag, by keyboard and by command. The handle is a named control the arrow keys move from. Another list shows where a dragged item will land (`data-reorder-target`, with `data-reorder-line` saying whether the mark runs beside the item or across it) and the move is made on the drop. Every move is announced and glides unless the reader asked for reduced motion. `accepts` refuses a drop (a group inside a group), `moveTo` moves an item to another list by command, and `moveKey` is exported.
|
|
210
|
+
|
|
211
|
+
**`ArrangeBoard`** is the ground an arranged page stands on: a fine hatch at rest, and the page's columns as lanes while a block is carried or resized. Its hatch is the new **`--color-border-hatch` token** in `@crewlethq/tokens`, measured in every theme, and a `Note` on the board shows it through its paper. **`ArrangeFrame`** is one block on it: layout only at rest; while editing, the block is its own move handle, one accent ring is drawn over its edge on hover or focus, and its toolbar (an `actions` slot and Remove) and resize grips sit on that ring. **`useGridResize`** snaps a resize to twelve columns and 16px rows, from the corner or, for width alone, the edge, by pointer and by keyboard. **`ArrangeGroup`** is a titled band that holds blocks and folds away, its title edited in place, and **`ArrangeList`** is a list a reader orders and switches on and off.
|
|
212
|
+
|
|
213
|
+
**`Note`** is words on coloured paper, in any node hue or plain. **`Divider`** is a rule between parts of a page, with an optional label. **`PinTile`** is something a reader pinned, with the one or two facts that make opening it unnecessary. **`IconTile`** is a glyph on a hue-tinted square, what a choice in a catalog is told apart by before its name is read.
|
|
214
|
+
|
|
215
|
+
**`Modal` takes `onBack` and `backLabel`**, a step back that leads the head for a surface reached from another, and **`backdrop="clear"`**, for a sheet that edits the page beside it. **`StatGroup` takes `flush`**, for a row of figures inside another card. **`HuePicker` takes `none`**, which offers no hue first under the name you give it ("Plain") and then reports `"none"`.
|
|
216
|
+
|
|
217
|
+
**A `Card` with `asChild` holds its child's own content.** With no header slots it used to draw the child again inside its own clone: a link inside a link, a button inside a button.
|
|
218
|
+
|
|
219
|
+
What to change: nothing, unless code extends `HuePickerProps` as an interface; it is a type now, so intersect it instead. Everything else is new.
|
|
220
|
+
|
|
204
221
|
## Changes in 0.18.0
|
|
205
222
|
|
|
206
223
|
0.18.0 adds the pieces the engine dashboard's Artifacts workspace is built from: the frame an artifact runs in, its versions, who it is shared with, and the card and refusal that stand for it elsewhere; the editable sheet; and the marks that show who else is in an artifact.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { ACCESS_DENIED_REASONS, AccessDeniedCard } from '../chunk-
|
|
1
|
+
export { ACCESS_DENIED_REASONS, AccessDeniedCard } from '../chunk-G3EEUNZQ.js';
|
|
2
2
|
import '../chunk-RA2ULG6H.js';
|
|
3
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-YZCJ63JF.js';
|
|
4
4
|
import '../chunk-AV2DXAEL.js';
|
|
5
5
|
import '../chunk-PQADV6P6.js';
|
|
6
6
|
import '../chunk-BHHIIK3M.js';
|
package/dist/AppShell/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { AccountRow, AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from '../chunk-
|
|
1
|
+
export { AccountRow, AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from '../chunk-EDGCPVVD.js';
|
|
2
2
|
import '../chunk-IG75YMUN.js';
|
|
3
|
-
import '../chunk-4FQT6ZAY.js';
|
|
4
3
|
import '../chunk-HMPFGIWM.js';
|
|
5
4
|
import '../chunk-R25RGPUB.js';
|
|
5
|
+
import '../chunk-4FQT6ZAY.js';
|
|
6
6
|
import '../chunk-BZFWDIV6.js';
|
|
7
7
|
import '../chunk-ODEQTPFM.js';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface ArrangeBoardProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Whether the page is being arranged. */
|
|
4
|
+
editing: boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Columns of the page grid the blocks snap to, shown as lanes while a block
|
|
7
|
+
* is carried or resized. The grid's gap is read from
|
|
8
|
+
* `--crewlet-arrange-board-gap` (one `--spacing-4` unless set).
|
|
9
|
+
*/
|
|
10
|
+
columns?: number | undefined;
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The ground a page's blocks stand on while it is arranged.
|
|
15
|
+
*
|
|
16
|
+
* A FINE HATCH SAYS "ARRANGING" AT REST. While editing, the blocks keep their
|
|
17
|
+
* own look and light up only when hovered, so something has to say the page
|
|
18
|
+
* is in a different mode before anything is touched. The ground under them
|
|
19
|
+
* does it: diagonal hairlines, the drafting mark for a surface under
|
|
20
|
+
* construction, with no frame of its own, so it adds no border to the borders
|
|
21
|
+
* already on the page. Most of it sits under the blocks, and in the gaps
|
|
22
|
+
* between them it reads as a cutting mat.
|
|
23
|
+
*
|
|
24
|
+
* THE COLUMNS SHOW WHILE A BLOCK MOVES. Carried or resized, the page's columns
|
|
25
|
+
* appear as lanes on the ground, as wide as the grid exactly, so a lane is
|
|
26
|
+
* the column a block will snap to; at rest they are gone.
|
|
27
|
+
*
|
|
28
|
+
* IT TAKES NO WIDTH FROM THE BLOCKS. The ground reaches a step past the blocks
|
|
29
|
+
* on each side rather than padding them inward, so entering editing never
|
|
30
|
+
* reflows a card to a narrower width.
|
|
31
|
+
*/
|
|
32
|
+
export declare function ArrangeBoard({ editing, columns, className, style, children, ...rest }: ArrangeBoardProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ArrangeBoard: the ground under a page being arranged. Two layers, both
|
|
3
|
+
* under every block (the board is its own stacking context, so they sit above
|
|
4
|
+
* its background and below its content): the hatch on `::after`, and the
|
|
5
|
+
* column lanes on `::before`, shown only while a block is carried or resized.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.crewlet-arrange-board {
|
|
9
|
+
--crewlet-arrange-board-gap: var(--spacing-4);
|
|
10
|
+
/* The hatch, as one value: the ground below and the notes standing on it
|
|
11
|
+
draw the same lines. */
|
|
12
|
+
--crewlet-arrange-board-hatch: repeating-linear-gradient(
|
|
13
|
+
-45deg,
|
|
14
|
+
var(--color-border-hatch) 0 1px,
|
|
15
|
+
transparent 1px var(--spacing-2)
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
min-width: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.crewlet-arrange-board.is-editing {
|
|
22
|
+
position: relative;
|
|
23
|
+
isolation: isolate;
|
|
24
|
+
margin-inline: calc(var(--spacing-3) * -1);
|
|
25
|
+
padding: var(--spacing-5) var(--spacing-3);
|
|
26
|
+
border-radius: var(--radius-xl);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Room to land below the last block while one is carried out of a group:
|
|
30
|
+
a page made only of groups otherwise has no bare stretch of its own. */
|
|
31
|
+
.crewlet-arrange-board.is-editing:has(.crewlet-arrange-group__body [data-reorder='dragging']) {
|
|
32
|
+
padding-bottom: var(--spacing-11);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* The hatch: its own ink, the strong hairline's held back to 60%, one
|
|
36
|
+
diagonal every half step, so the cards standing on it stay the loudest
|
|
37
|
+
thing on the page. */
|
|
38
|
+
.crewlet-arrange-board.is-editing::after {
|
|
39
|
+
content: '';
|
|
40
|
+
position: absolute;
|
|
41
|
+
inset: 0;
|
|
42
|
+
z-index: -1;
|
|
43
|
+
border-radius: inherit;
|
|
44
|
+
background: var(--crewlet-arrange-board-hatch);
|
|
45
|
+
pointer-events: none;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* A note is an annotation on the ground, not a card on it: while the page is
|
|
49
|
+
arranged its paper shows the hatch through, inside a group as well, where
|
|
50
|
+
the group's own surface hides the ground. */
|
|
51
|
+
.crewlet-arrange-board.is-editing .crewlet-note {
|
|
52
|
+
background: var(--crewlet-arrange-board-hatch), var(--crewlet-note-paper);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* The lanes: one tile per column and its gap, as wide as the grid, so the
|
|
56
|
+
twelfth tile's gap falls outside the board and is not drawn. */
|
|
57
|
+
.crewlet-arrange-board.is-editing::before {
|
|
58
|
+
content: '';
|
|
59
|
+
position: absolute;
|
|
60
|
+
inset: 0 var(--spacing-3);
|
|
61
|
+
background: linear-gradient(
|
|
62
|
+
to right,
|
|
63
|
+
var(--color-brand-accent-soft) 0 calc(100% - var(--crewlet-arrange-board-gap)),
|
|
64
|
+
transparent 0
|
|
65
|
+
)
|
|
66
|
+
0 0 / calc((100% + var(--crewlet-arrange-board-gap)) / var(--crewlet-arrange-board-columns)) 100%
|
|
67
|
+
repeat-x;
|
|
68
|
+
opacity: 0;
|
|
69
|
+
pointer-events: none;
|
|
70
|
+
transition: opacity var(--motion-duration-base) var(--motion-easing-default);
|
|
71
|
+
}
|
|
72
|
+
.crewlet-arrange-board.is-editing:has([data-reorder='dragging'], .crewlet-arrange-frame.is-resizing)::before {
|
|
73
|
+
opacity: 1;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@media (prefers-reduced-motion: reduce) {
|
|
77
|
+
.crewlet-arrange-board.is-editing::before {
|
|
78
|
+
transition: none;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
import type { ReorderHandleProps } from '../Reorder/index.js';
|
|
3
|
+
import { type GridSize } from './useGridResize.js';
|
|
4
|
+
export interface ArrangeFrameResize {
|
|
5
|
+
minColumns?: number | undefined;
|
|
6
|
+
maxColumns?: number | undefined;
|
|
7
|
+
minRows?: number | undefined;
|
|
8
|
+
maxRows?: number | undefined;
|
|
9
|
+
/** False for a block whose height is always its content's: width only. */
|
|
10
|
+
vertical?: boolean | undefined;
|
|
11
|
+
onResize: (next: GridSize) => void;
|
|
12
|
+
}
|
|
13
|
+
export interface ArrangeFrameProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
14
|
+
/** What the block is called: every control's name. */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Whether the page is being arranged. Off, the frame draws its child only. */
|
|
17
|
+
editing: boolean;
|
|
18
|
+
/** Columns of the page grid the block spans. */
|
|
19
|
+
columns: number;
|
|
20
|
+
/** Rows tall, or null for its content's height. */
|
|
21
|
+
rows?: number | null | undefined;
|
|
22
|
+
/** One row's height in pixels. */
|
|
23
|
+
rowHeight?: number | undefined;
|
|
24
|
+
/** The handle's props from `useReorder`, spread on the block itself; left out, it does not move. */
|
|
25
|
+
handle?: ReorderHandleProps | undefined;
|
|
26
|
+
/** Resize by the corner or the edge; left out, the block keeps its size. */
|
|
27
|
+
resize?: ArrangeFrameResize | undefined;
|
|
28
|
+
/** Controls of the block's own on its toolbar: settings, a menu. */
|
|
29
|
+
actions?: ReactNode;
|
|
30
|
+
/** Take the block off the page; left out, it cannot be removed. */
|
|
31
|
+
onRemove?: (() => void) | undefined;
|
|
32
|
+
/** Why the block cannot be removed, said on the button that would. */
|
|
33
|
+
fixed?: string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* A block that holds other blocks (a group). Its content stays operable
|
|
36
|
+
* while arranging, because the blocks inside are arranged in place and
|
|
37
|
+
* each makes its own content inert; a press on its fields types rather
|
|
38
|
+
* than moves it.
|
|
39
|
+
*/
|
|
40
|
+
container?: boolean | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* A block with no surface of its own (a heading, a divider): its ring is
|
|
43
|
+
* drawn a step outside it, so the words are not pressed against it.
|
|
44
|
+
*/
|
|
45
|
+
bare?: boolean | undefined;
|
|
46
|
+
/** The block whose settings are open: ringed until they close. */
|
|
47
|
+
selected?: boolean | undefined;
|
|
48
|
+
/** Drawn once with the accent, for a block the reader just added. */
|
|
49
|
+
fresh?: boolean | undefined;
|
|
50
|
+
children: ReactNode;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* One block of a page the reader is arranging: moved by its grip or its
|
|
54
|
+
* surface, sized from its corner or its edge, taken off from its toolbar.
|
|
55
|
+
*
|
|
56
|
+
* ONE BOUNDARY, THE BLOCK'S OWN. A card already draws its edge, and a second
|
|
57
|
+
* outline around it read as two borders. At rest a block being arranged looks
|
|
58
|
+
* exactly as it does on the page. Hovered or focused, ONE accent ring is drawn
|
|
59
|
+
* over its own edge (on the innermost block only, so a card inside a group
|
|
60
|
+
* does not light the group as well), with its toolbar and its resize handle.
|
|
61
|
+
*
|
|
62
|
+
* THE CHROME NEVER COVERS THE BLOCK'S CONTROLS. The toolbar sits on the
|
|
63
|
+
* block's top edge, half outside it, clear of a card's own header links; the
|
|
64
|
+
* corner bracket follows the card's own radius.
|
|
65
|
+
*
|
|
66
|
+
* TWO HANDLES FOR TWO RESIZES. A block that may be sized both ways carries a
|
|
67
|
+
* corner bracket; one whose height is always its content's (a heading, a
|
|
68
|
+
* figure, a group) carries a grip on its right edge, the handle of a column
|
|
69
|
+
* splitter, so the handle says which way it moves before it is touched.
|
|
70
|
+
*
|
|
71
|
+
* THE GRID SHOWS WHILE RESIZING, measured from the grid the block sits on
|
|
72
|
+
* (the page's, or a group's), so the columns drawn are the ones it snaps to.
|
|
73
|
+
*
|
|
74
|
+
* THE BLOCK IS ITS OWN HANDLE. A block's content is inert while arranging,
|
|
75
|
+
* so a press on it can mean nothing but "move this": the whole block is the
|
|
76
|
+
* drag source, and focused it moves with the arrow keys, so the toolbar
|
|
77
|
+
* carries no grip. A container (a group) is moved the same way, by its header
|
|
78
|
+
* or its edge, except from a field, where a press types or selects.
|
|
79
|
+
*
|
|
80
|
+
* A FIXED HEIGHT SCROLLS ITS CONTENT rather than cutting it off.
|
|
81
|
+
*/
|
|
82
|
+
export declare const ArrangeFrame: import("react").ForwardRefExoticComponent<ArrangeFrameProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import './ArrangeFrame.css';
|
|
2
|
+
export { ArrangeFrame } from './ArrangeFrame.js';
|
|
3
|
+
export type { ArrangeFrameProps, ArrangeFrameResize } from './ArrangeFrame.js';
|
|
4
|
+
export { useGridResize } from './useGridResize.js';
|
|
5
|
+
export type { GridResizeHandleProps, GridResizeOptions, GridSize } from './useGridResize.js';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type KeyboardEvent, type PointerEvent, type RefObject } from 'react';
|
|
2
|
+
/** A block's size on a page grid: columns it spans, and rows tall or null for its content's height. */
|
|
3
|
+
export interface GridSize {
|
|
4
|
+
columns: number;
|
|
5
|
+
rows: number | null;
|
|
6
|
+
}
|
|
7
|
+
export interface GridResizeOptions {
|
|
8
|
+
/** What the block is called, for the handle's name and the announcement. */
|
|
9
|
+
name: string;
|
|
10
|
+
size: GridSize;
|
|
11
|
+
/** One row's height in pixels: the step a height snaps to. */
|
|
12
|
+
rowHeight: number;
|
|
13
|
+
minColumns?: number | undefined;
|
|
14
|
+
/** Left out, the grid's own column count. */
|
|
15
|
+
maxColumns?: number | undefined;
|
|
16
|
+
minRows?: number | undefined;
|
|
17
|
+
maxRows?: number | undefined;
|
|
18
|
+
/** False for a block whose height is always its content's (a group): width only. */
|
|
19
|
+
vertical?: boolean | undefined;
|
|
20
|
+
/** A finished resize: a pointer released, a key pressed, or the height fitted. */
|
|
21
|
+
onResize: (next: GridSize) => void;
|
|
22
|
+
}
|
|
23
|
+
export interface GridResizeHandleProps {
|
|
24
|
+
'aria-label': string;
|
|
25
|
+
'aria-keyshortcuts': string;
|
|
26
|
+
onPointerDown: (event: PointerEvent<HTMLElement>) => void;
|
|
27
|
+
onPointerMove: (event: PointerEvent<HTMLElement>) => void;
|
|
28
|
+
onPointerUp: (event: PointerEvent<HTMLElement>) => void;
|
|
29
|
+
onPointerCancel: () => void;
|
|
30
|
+
onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
|
|
31
|
+
onDoubleClick: () => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Where the grid's columns fall, measured from the block's own left edge, so
|
|
35
|
+
* a block can draw the guides of the grid it sits on (the page's, or a
|
|
36
|
+
* group's) while it is being resized.
|
|
37
|
+
*/
|
|
38
|
+
export interface GridGuides {
|
|
39
|
+
left: number;
|
|
40
|
+
width: number;
|
|
41
|
+
columns: number;
|
|
42
|
+
gap: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resizing a block on a page grid by its corner, snapped to whole columns
|
|
46
|
+
* across and whole rows down, with the keyboard doing the same.
|
|
47
|
+
*
|
|
48
|
+
* SNAPPED AS IT MOVES. The block follows the pointer in steps of the grid it
|
|
49
|
+
* sits on, so what the reader sees while dragging is exactly where it will
|
|
50
|
+
* land; nothing reflows after the release. The release reports once, and
|
|
51
|
+
* Escape puts the block back.
|
|
52
|
+
*
|
|
53
|
+
* WIDTH ALONE LEAVES THE HEIGHT TO THE CONTENT. A block whose height fits its
|
|
54
|
+
* content keeps doing so until the pointer has moved down or up by half a
|
|
55
|
+
* row; a sideways drag is a width change and nothing else. A double press on
|
|
56
|
+
* the handle (or Enter) fits the height to the content again.
|
|
57
|
+
*
|
|
58
|
+
* THE ARROW KEYS ON THE HANDLE resize by one column or one row, and every
|
|
59
|
+
* change is said, because a corner that only a pointer can drag is a control
|
|
60
|
+
* nobody on a keyboard has.
|
|
61
|
+
*/
|
|
62
|
+
export declare function useGridResize(frame: RefObject<HTMLElement | null>, { name, size, rowHeight, minColumns, maxColumns, minRows, maxRows, vertical, onResize }: GridResizeOptions): {
|
|
63
|
+
live: GridSize | null;
|
|
64
|
+
guides: GridGuides | null;
|
|
65
|
+
handleProps: GridResizeHandleProps;
|
|
66
|
+
};
|