@crewlethq/ui 0.17.1 → 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 +55 -3
- package/dist/AccessDeniedCard/AccessDeniedCard.d.ts +39 -0
- package/dist/AccessDeniedCard/index.d.ts +3 -0
- package/dist/AccessDeniedCard/index.js +8 -0
- package/dist/AccessDeniedCard-WXM5DBDZ.css +8 -0
- 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/ArtifactCard.d.ts +61 -0
- package/dist/ArtifactCard/index.d.ts +3 -0
- package/dist/ArtifactCard/index.js +12 -0
- package/dist/ArtifactCard-EXVAEBV6.css +109 -0
- package/dist/AuthLayout/index.js +2 -2
- package/dist/AvatarPicker/index.js +5 -5
- package/dist/Canvas/index.js +2 -2
- package/dist/Card/index.js +1 -1
- package/dist/ChangeMark/ChangeMark.d.ts +26 -0
- package/dist/ChangeMark/index.d.ts +3 -0
- package/dist/ChangeMark/index.js +8 -0
- package/dist/ChangeMark-3VMTW7MT.css +22 -0
- package/dist/Checkbox/index.js +3 -3
- package/dist/Combobox/index.js +3 -3
- package/dist/CommandPalette/index.js +5 -5
- package/dist/Composer/index.js +3 -3
- package/dist/ConfirmField/index.js +3 -3
- package/dist/CursorFlag/CursorFlag.d.ts +34 -0
- package/dist/CursorFlag/index.d.ts +3 -0
- package/dist/CursorFlag/index.js +3 -0
- package/dist/CursorFlag-AJQJBUGY.css +61 -0
- package/dist/DataTable/index.js +7 -7
- package/dist/DataView/index.js +13 -13
- package/dist/DateTimePicker/index.js +2 -2
- 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/FollowBanner/FollowBanner.d.ts +35 -0
- package/dist/FollowBanner/index.d.ts +2 -0
- package/dist/FollowBanner/index.js +7 -0
- package/dist/FrameProtocol/index.d.ts +2 -0
- package/dist/FrameProtocol/index.js +2 -0
- package/dist/FrameProtocol/protocol.d.ts +164 -0
- package/dist/HuePicker/HuePicker.d.ts +16 -4
- package/dist/HuePicker/index.js +3 -3
- 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/LinkInterstitial.d.ts +41 -0
- package/dist/LinkInterstitial/index.d.ts +3 -0
- package/dist/LinkInterstitial/index.js +11 -0
- package/dist/LinkInterstitial-ET4MSVSV.css +34 -0
- package/dist/ListInput/index.js +4 -4
- package/dist/LiveCursor/LiveCursor.d.ts +34 -0
- package/dist/LiveCursor/index.d.ts +3 -0
- package/dist/LiveCursor/index.js +4 -0
- package/dist/LiveCursor-DZHGIYWE.css +47 -0
- package/dist/MarkdownEditor/index.js +3 -3
- package/dist/Menu/index.js +2 -2
- package/dist/Modal/Modal.d.ts +20 -0
- package/dist/Modal/index.js +2 -2
- 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/PresenceModel/index.d.ts +2 -0
- package/dist/PresenceModel/index.js +3 -0
- package/dist/PresenceModel/presence.d.ts +80 -0
- package/dist/PresenceRing/PresenceRing.d.ts +31 -0
- package/dist/PresenceRing/index.d.ts +3 -0
- package/dist/PresenceRing/index.js +2 -0
- package/dist/PresenceRing-M4C22Q6U.css +68 -0
- package/dist/PresenceStack/PresenceStack.d.ts +36 -0
- package/dist/PresenceStack/index.d.ts +3 -0
- package/dist/PresenceStack/index.js +9 -0
- package/dist/PresenceStack-QSXQJND5.css +59 -0
- package/dist/PricingCard/index.js +2 -2
- package/dist/Principal/Principal.d.ts +35 -0
- package/dist/Principal/index.d.ts +2 -0
- package/dist/Principal/index.js +4 -0
- package/dist/PrincipalPicker/PrincipalPicker.d.ts +45 -0
- package/dist/PrincipalPicker/index.d.ts +3 -0
- package/dist/PrincipalPicker/index.js +12 -0
- package/dist/PrincipalPicker-7NNZTGUP.css +41 -0
- 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/SandboxedFrame/SandboxedFrame.d.ts +142 -0
- package/dist/SandboxedFrame/index.d.ts +3 -0
- package/dist/SandboxedFrame/index.js +8 -0
- package/dist/SandboxedFrame-L6HBQZCD.css +50 -0
- package/dist/ShareDialog/ShareDialog.d.ts +101 -0
- package/dist/ShareDialog/index.d.ts +5 -0
- package/dist/ShareDialog/index.js +19 -0
- package/dist/ShareDialog/roles.d.ts +10 -0
- package/dist/ShareDialog-YZ4F37MW.css +146 -0
- package/dist/SheetGrid/SheetGrid.d.ts +78 -0
- package/dist/SheetGrid/cells.d.ts +117 -0
- package/dist/SheetGrid/index.d.ts +5 -0
- package/dist/SheetGrid/index.js +18 -0
- package/dist/SheetGrid-4HOXDVIB.css +595 -0
- package/dist/SheetModel/clipboard.d.ts +37 -0
- package/dist/SheetModel/edits.d.ts +68 -0
- package/dist/SheetModel/index.d.ts +14 -0
- package/dist/SheetModel/index.js +3 -0
- package/dist/SheetModel/labels.d.ts +71 -0
- package/dist/SheetModel/navigation.d.ts +79 -0
- package/dist/SheetModel/options.d.ts +28 -0
- package/dist/SheetModel/types.d.ts +126 -0
- package/dist/SheetModel/values.d.ts +76 -0
- package/dist/SheetModel/view.d.ts +32 -0
- 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/Tag/Tag.d.ts +13 -0
- package/dist/Tag/index.js +1 -1
- package/dist/{Tag-4BRQS6GN.css → Tag-SRGTK5KI.css} +42 -0
- package/dist/TagsInput/index.js +4 -4
- package/dist/ThemeSwitcher/apply.d.ts +43 -0
- package/dist/ThemeSwitcher/index.d.ts +4 -2
- package/dist/ThemeSwitcher/index.js +3 -2
- package/dist/ThemeSwitcher/preferences.d.ts +2 -19
- package/dist/ThemeToggle/index.js +3 -2
- package/dist/TimeWindowPicker/index.js +4 -4
- package/dist/Timeline/Timeline.d.ts +7 -2
- package/dist/Timeline/index.js +1 -1
- package/dist/TreeCanvas/index.js +3 -3
- package/dist/TreeGrid/index.js +2 -2
- package/dist/VersionTimeline/VersionTimeline.d.ts +76 -0
- package/dist/VersionTimeline/index.d.ts +3 -0
- package/dist/VersionTimeline/index.js +10 -0
- package/dist/VersionTimeline-EBJ6MIPJ.css +108 -0
- package/dist/{chunk-SBRE7IML.js → chunk-2ONWEDQT.js} +1 -1
- package/dist/chunk-35XVR5JQ.js +81 -0
- package/dist/chunk-3BYIWOTV.js +29 -0
- package/dist/chunk-4KP4RC3O.js +25 -0
- package/dist/chunk-5XACKNYR.js +53 -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-FA2V2VT6.js → chunk-7FQEUNHX.js} +4 -4
- package/dist/{chunk-DEEVA6TV.js → chunk-7IJARUIF.js} +17 -4
- package/dist/{chunk-JCO3SIST.js → chunk-7ZNKEPLN.js} +2 -2
- package/dist/chunk-AIVZVKYZ.js +126 -0
- package/dist/{chunk-FSKTOIYC.js → chunk-AJESMWJS.js} +5 -5
- package/dist/{chunk-O67VF5MS.js → chunk-AUQPBL4O.js} +2 -2
- package/dist/chunk-CENOOTAV.js +1 -0
- package/dist/chunk-DEJHAOC5.js +279 -0
- package/dist/{chunk-UCYIRDND.js → chunk-DQSXWQMJ.js} +1 -1
- package/dist/{chunk-JF7X673Z.js → chunk-EIGEIT4O.js} +2 -2
- package/dist/chunk-F6V2PTN6.js +142 -0
- package/dist/chunk-FFMCMSJB.js +1 -0
- package/dist/chunk-FW7HN6AP.js +40 -0
- package/dist/chunk-G3EEUNZQ.js +46 -0
- package/dist/{chunk-LOECRMHA.js → chunk-GFV4LJHH.js} +4 -3
- package/dist/chunk-HTCJSUIZ.js +216 -0
- package/dist/{chunk-75CLJNDQ.js → chunk-I6NZKJGK.js} +1 -1
- package/dist/chunk-I6POAB4V.js +20 -0
- package/dist/chunk-IXJHTFXG.js +17 -0
- package/dist/chunk-JEDWC3GI.js +98 -0
- package/dist/{chunk-QVAFL2LE.js → chunk-JXRI5YD2.js} +3 -3
- package/dist/{chunk-ZFH7H7GS.js → chunk-LOLELDBW.js} +1 -1
- package/dist/{chunk-6TSZCBID.js → chunk-NP2C4Y4E.js} +1 -1
- package/dist/{chunk-6NN2F7GM.js → chunk-OIMAK5AE.js} +6 -6
- package/dist/chunk-PPAQFGS2.js +12 -0
- package/dist/chunk-PUQY4WXR.js +1235 -0
- package/dist/chunk-QO7QEQKV.js +24 -0
- package/dist/chunk-RT323I4I.js +49 -0
- package/dist/chunk-S35G6PNC.js +80 -0
- package/dist/{chunk-HENOTGUV.js → chunk-T7ICFXEC.js} +2 -2
- package/dist/{chunk-2OLCUNG7.js → chunk-TBIZSQHB.js} +1 -1
- package/dist/chunk-TODND5AD.js +99 -0
- package/dist/{chunk-PQ63NLFC.js → chunk-UXELEORU.js} +3 -3
- package/dist/{chunk-6NIMZ5XC.js → chunk-VJLYGPPE.js} +1 -1
- package/dist/chunk-VYDFB6PJ.js +243 -0
- package/dist/{chunk-7QFAORCY.js → chunk-WHZFDS62.js} +1 -1
- package/dist/chunk-WXAULPBH.js +135 -0
- package/dist/chunk-XJ2QEBMM.js +277 -0
- package/dist/{chunk-NXDEPUVG.js → chunk-XU4ZUGLE.js} +20 -5
- package/dist/chunk-YM3GJHGW.js +69 -0
- package/dist/{chunk-T3ZWBZ65.js → chunk-YSJYWQSP.js} +2 -2
- package/dist/{chunk-CXBAIVYZ.js → chunk-YSY6UJ4F.js} +1 -1
- package/dist/chunk-YYZRLLLY.js +822 -0
- package/dist/{chunk-EG6NYWVK.js → chunk-YZCJ63JF.js} +1 -1
- package/dist/{chunk-K3OWD7BJ.js → chunk-Z24ZUSTX.js} +4 -19
- package/dist/chunk-ZXXDZJQN.js +36 -0
- package/dist/generated/index.d.ts +27 -0
- package/dist/generated/index.js +98 -69
- package/dist/index.js +98 -69
- package/dist/styles.css +13625 -11206
- package/dist/utils/index.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-EXHQ2QVW.js +0 -1
- package/dist/{chunk-CRVETI5L.js → chunk-4Z7PW3L6.js} +0 -0
- package/dist/{chunk-OYOQU7O5.js → chunk-EDGCPVVD.js} +1 -1
- package/dist/{chunk-NS7BVLL3.js → chunk-JULMZNGT.js} +1 -1
- package/dist/{chunk-2UU5IGZI.js → chunk-L4H7SSWF.js} +1 -1
- package/dist/{chunk-4GB57WIT.js → chunk-Q55TXPA3.js} +1 -1
- package/dist/{chunk-77IEHFY4.js → chunk-QQGWES46.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,17 +41,21 @@ 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
|
-
| Preferences | `ThemeToggle`, `ThemeSwitcher`, `DensitySwitcher`, `ThemeGallery`, `ThemeSwatch`, `useThemePreference`, `useDensityPreference`, `useSystemTheme`, `resolveTheme`, `applyStoredPreferences` |
|
|
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 |
|
|
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) |
|
|
57
|
+
| Sheets | `SheetGrid`, the cells on their own (`CheckboxCell`, `TextCell`, `LongTextCell`, `NumberCell`, `SelectCell`, `MultiSelectCell`, `PersonCell`, `StatusCell`, `DateCell`, `UrlCell`, `RatingCell`, and `SheetCell` for any type), `ChangeMark`, and `SheetModel` (every rule a sheet is drawn from, with no React in it: values, parsing, the keyboard model, TSV, the pending edits of D23) |
|
|
58
|
+
| Presence | `PresenceStack`, `PresenceRing` and `presenceHueClass`, `CursorFlag`, `LiveCursor`, `FollowBanner`, and `PresenceModel` (the roster order, one entry per person, the session hues, with no React in it) |
|
|
55
59
|
|
|
56
60
|
Storybook stories live under `apps/storybook/src/stories`.
|
|
57
61
|
|
|
@@ -198,6 +202,54 @@ places:
|
|
|
198
202
|
- A surface that pans or zooms dispatches `LAYER_REPOSITION_EVENT` on its host
|
|
199
203
|
when the content beneath it moves, and every panel anchored inside follows.
|
|
200
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
|
+
|
|
221
|
+
## Changes in 0.18.0
|
|
222
|
+
|
|
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.
|
|
224
|
+
|
|
225
|
+
**`SandboxedFrame`** embeds an artifact's document with the engine's `sandbox` and `allow` attributes set verbatim, after a second check that refuses any token the host never sets: there is no `allow-popups` at all, and `allow-same-origin` only when the artifact has an origin of its own. A hello is accepted only from the iframe's own window, carrying the nonce minted with its ticket, and per artifact from the artifact's origin; only then is one `MessagePort` transferred, in the same task, to the window that was checked. The reader's appearance travels in the URL fragment for the first paint and on the port afterwards. A document that does not announce itself is torn down (`failed`, or `navigated` when it replaced one that did), a runtime with no common bridge version is `outdated`, and each refusal reaches `onRefusal`. The frame never opens a window: an external link reaches `onOpenLink`. A port message asking for focus back moves focus to the frame's region, or to `onFocusExit`.
|
|
226
|
+
|
|
227
|
+
**`FrameProtocol`** is that wire, written once for both ends and free of React, so the engine's runtime and `@crewlethq/artifact-kit`'s `theme.js` import it: `FRAME_MESSAGE`, `frameFragment` and `parseFrameFragment`, `readFrameHello`, `negotiateBridge`, `checkFrameSandbox`, `readFrameTheme` and `applyFrameTheme`, and `externalUrl`, which admits absolute https, http and mailto links only and never one carrying a user name or password.
|
|
228
|
+
|
|
229
|
+
**`LinkInterstitial`** is the stop between an artifact's link and the open web: the host in large type (the parser's ASCII form, so a look-alike name shows as the `xn--` name it is), the whole address, a warning on plain http, and **`openExternal`**, which opens with `noopener` and `noreferrer`.
|
|
230
|
+
|
|
231
|
+
**`VersionTimeline`** lists versions newest first on the `Timeline` ledger with the one on show current, Compare as a toggle, Restore (never on the newest) and Name, glyphs and words for schema, capability and restore versions, and a line for versions past retention. **`Timeline.Item` takes `label={false}`** for an item whose content already says what it is.
|
|
232
|
+
|
|
233
|
+
**`ShareDialog`** is who can open an artifact on the engine's five-role ladder (viewer, commenter, contributor, editor, owner): a grantee search slot handed the role chosen beside it, direct shares with a role control and a remove, effective access with what it is through and no control, company access in words, and Copy link. Changes are confirmed rather than optimistic, a refusal is said on its row, no control offers owner, and a reader who cannot share sees the same audience in words with the reason. **`PrincipalPicker`** is the search the slot usually holds, grouped people, agents and teams. **`Principal`** and **`PrincipalAvatar`** draw a person, an agent or a team one way everywhere.
|
|
234
|
+
|
|
235
|
+
**`ArtifactCard`** is one real link named by the artifact's title and described by its facts, with a natively drawn preview or the kind's glyph (**`ArtifactKindGlyph`**), and a compact row. **`AccessDeniedCard`** is the refusal an artifact's place shows; "not found" says both things the engine means by it and never names an owner.
|
|
236
|
+
|
|
237
|
+
**The appearance attributes have a module of their own.** `applyTheme` and `applyDensity` take an optional root element, **`applyPalette`** is new (the default theme removes the attribute, as `system` and `normal` do), and `THEME_PREFERENCES`, `DENSITY_PREFERENCES`, `PALETTE_ID` and their guards are exported.
|
|
238
|
+
|
|
239
|
+
**`SheetGrid`** is the editable, virtualised grid of a sheet artifact, and the grid `@crewlethq/artifact-kit` draws for a page's `<crewlet-sheet>`. It is an ARIA grid with one tab stop and a spreadsheet's keys: the arrows, Enter or F2 to edit, Escape to cancel, Tab across (leaving the grid at a row's edge), Space on a checkbox, typing to start an edit with that character, Mod+C, Mod+X and Mod+V for ranges as tab-separated values, Delete to clear, Mod+Z and Mod+Shift+Z handed to the host's `onUndo` and `onRedo`, and Mod+Alt+H for a cell's history (`onShowHistory`, also a control on the active cell). Every one of the eleven column types is drawn and edited (text, long text, number, checkbox, select, multi-select, status, person, date, URL, rating); frozen columns lead and stay in view; headers sort; only the rows in view are in the document, so ten thousand rows cost what forty do. Edits reach the host as one batch through `onEdit`: the host draws the value at once and lists the field in the row's `pending` until the engine confirms it, which the grid draws as Saving (the honest instant edit, D23), and a refusal arrives in the row's `refused` and is said on the cell. A value that does not fit its column is refused on the cell before it is sent, with the reason. A remote change landing under the editor keeps it open and names the writer, with Keep yours and Use theirs. Collaborators on cells (`presence`) wear a ring in their presence hue and a name flag, cells changed since the reader looked (`changed`) wear a **`ChangeMark`**, and the focused cell's description says all of it in words. `onActiveCellChange` and `onEditingChange` hand the host the reader's own cell for its presence frames, and `sync` drives the strip that says Saved, Saving, Offline or Could not save with Retry.
|
|
240
|
+
|
|
241
|
+
**The cells stand on their own.** `CheckboxCell`, `TextCell`, `LongTextCell`, `NumberCell`, `SelectCell`, `MultiSelectCell`, `PersonCell`, `StatusCell`, `DateCell`, `UrlCell` and `RatingCell` (and `SheetCell` with a `type`) draw the same display and editors as a field in a form: a checkbox is a real checkbox, every other type a button that says its column and value and opens its editor in place.
|
|
242
|
+
|
|
243
|
+
**`SheetModel`** holds every rule the sheet is drawn from, with no React and no stylesheet, so the artifact kit and any host share it: the column, row and edit shapes, mirroring the engine's datastore schema; `normalizeValue`, `displayText`, `editText` and `parseText` for each type, with the reason a value is refused; `optionHue` and `statusTone`; the keyboard model (`moveFrom`, `rangeOf`) and the row window (`visibleRows`); `toTSV`, `parseTSV`, `planPaste` and `planClear`; **`SheetPendingEdits`**, the bookkeeping of which cells wait on the engine and which were refused, with `refusalText`; and `cellDescription`, the words a focused cell is described by.
|
|
244
|
+
|
|
245
|
+
**Presence** is drawn in the narrow presence colour exception (D22): a collaborator's node hue, on a cursor, a selection ring, a cell outline and a name flag only, always beside the name. **`PresenceStack`** is who is here, people editing first, each present badge ringed in its hue and an idle one faded, one image named "You and 3 others are here", or a button per badge with `onSelect`. **`PresenceRing`** is the inset ring in a hue, dashed when idle; **`presenceHueClass`** sets the one hue variable every presence mark reads. **`CursorFlag`** is the name on its hue, in the new `--color-presence-flag-text`. **`LiveCursor`** is a pointer and its flag at a point, fading after five seconds still and hidden after thirty, jumping rather than gliding under a reduced-motion preference. **`FollowBanner`** is the follow mode strip, which Escape ends from anywhere. Every mark is decorative to assistive technology, because the same facts are said in words. **`PresenceModel`** holds the roster order (`presenceOrder`), one entry per person (`collapseSessions`), the session hues (`assignPresenceHues`: an agent keeps its chosen hue, a person takes the first hue nobody present wears) and the words.
|
|
246
|
+
|
|
247
|
+
**`Tag` takes `hue`**, a node hue an author chose for a value (a select option's colour), drawn in the node steps; a hue is never a state, so with one the variant colours nothing.
|
|
248
|
+
|
|
249
|
+
`@crewlethq/icons` adds `share-2`, `rotate-ccw-clock` (Lucide's canonical name for the drawing it once called `history`), `upload`, `file-code`, `image`, and `mouse-pointer-2` (fillable, for the live cursor). `@crewlethq/tokens` adds `--color-presence-flag-text`, `--color-change-mark`, `--shadow-cursor`, `--z-index-presence` and `--size-sheet-row`.
|
|
250
|
+
|
|
251
|
+
What to change: nothing. Every addition is new, and `applyTheme` and `applyDensity` keep their one-argument form.
|
|
252
|
+
|
|
201
253
|
## Changes in 0.17.0
|
|
202
254
|
|
|
203
255
|
**`Avatar` takes `mark`**, a glyph on the lower-right corner that says how a principal is present rather than what it is doing: a seat's badge acting through an API token keeps its own initials and wears a key there. It sits in the notch a status uses, drawn quiet in the neutral badge's raised fill, strong hairline and secondary ink, and a `status` wins over it. **`markLabel`** is said after the name by a badge that names itself (`Miles avatar, signed in with an API token`); a decorative one says nothing. A marked badge, like one with a status, is drawn inside a `.crewlet-avatar-frame` and draws no ring. What to change: nothing.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { HeadingLevel } from '../utils/headingLevel.js';
|
|
3
|
+
/**
|
|
4
|
+
* Why an artifact cannot be shown.
|
|
5
|
+
*
|
|
6
|
+
* `not-found` is what the engine answers for an artifact the reader has no
|
|
7
|
+
* relation to, as much as for one that does not exist: telling the two apart
|
|
8
|
+
* would tell anybody holding a link that the artifact is there. So it says
|
|
9
|
+
* both, and it says them together. `no-access` is for a reader the engine has
|
|
10
|
+
* told plainly (a member of the company opening a private artifact through a
|
|
11
|
+
* surface that already named it). `revoked` is access that ended while the
|
|
12
|
+
* reader had it open. `app-locked` is a reader whose role does not open the
|
|
13
|
+
* Artifacts app at all.
|
|
14
|
+
*/
|
|
15
|
+
export type AccessDeniedReason = 'not-found' | 'no-access' | 'revoked' | 'app-locked';
|
|
16
|
+
export declare const ACCESS_DENIED_REASONS: readonly ["not-found", "no-access", "revoked", "app-locked"];
|
|
17
|
+
export interface AccessDeniedCardLabels {
|
|
18
|
+
titles: Record<AccessDeniedReason, string>;
|
|
19
|
+
/** The line under the title, given the owner's name when the caller knows it. */
|
|
20
|
+
descriptions: Record<AccessDeniedReason, (owner: string | undefined) => string>;
|
|
21
|
+
}
|
|
22
|
+
export interface AccessDeniedCardProps {
|
|
23
|
+
reason: AccessDeniedReason;
|
|
24
|
+
/** The owner's name, where the reader is allowed to know it, so the request names a person. */
|
|
25
|
+
owner?: string | undefined;
|
|
26
|
+
/** What the reader can do next: "Back to artifacts", "Request access". */
|
|
27
|
+
action?: ReactNode;
|
|
28
|
+
headingLevel?: HeadingLevel | 'none' | undefined;
|
|
29
|
+
className?: string | undefined;
|
|
30
|
+
labels?: Partial<AccessDeniedCardLabels> | undefined;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The card an artifact's place shows when the reader may not open it.
|
|
34
|
+
*
|
|
35
|
+
* IT SAYS WHAT THE READER CAN DO, never what the artifact is. A title, a
|
|
36
|
+
* kind or an owner the engine has not shown this reader stays unsaid, so the
|
|
37
|
+
* card is safe to draw from nothing but the engine's refusal.
|
|
38
|
+
*/
|
|
39
|
+
export declare function AccessDeniedCard({ reason, owner, action, headingLevel, className, labels }: AccessDeniedCardProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { ACCESS_DENIED_REASONS, AccessDeniedCard } from '../chunk-G3EEUNZQ.js';
|
|
2
|
+
import '../chunk-RA2ULG6H.js';
|
|
3
|
+
import '../chunk-YZCJ63JF.js';
|
|
4
|
+
import '../chunk-AV2DXAEL.js';
|
|
5
|
+
import '../chunk-PQADV6P6.js';
|
|
6
|
+
import '../chunk-BHHIIK3M.js';
|
|
7
|
+
import '../chunk-BZFWDIV6.js';
|
|
8
|
+
import '../chunk-ODEQTPFM.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
|
+
};
|