@crewlethq/ui 0.38.0 → 0.40.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.
Files changed (157) hide show
  1. package/README.md +79 -3
  2. package/dist/AgentHandoffPanel/index.js +3 -3
  3. package/dist/AppShell/AppShell.d.ts +13 -2
  4. package/dist/AppShell/index.js +1 -1
  5. package/dist/{AppShell-NDU4XMGF.css → AppShell-NPSWZ3XW.css} +45 -4
  6. package/dist/ArtifactBar/index.js +6 -5
  7. package/dist/{ArtifactBar-FWPBBKQ5.css → ArtifactBar-6PGWGKN2.css} +13 -1
  8. package/dist/ArtifactCard/index.js +2 -2
  9. package/dist/AuthLayout/index.js +2 -2
  10. package/dist/AvatarPicker/index.js +10 -6
  11. package/dist/Card/Card.d.ts +14 -2
  12. package/dist/Card/index.js +1 -1
  13. package/dist/{Card-G2ZGT5Z6.css → Card-JR2UPQH7.css} +20 -0
  14. package/dist/CatalogTile/CatalogTile.d.ts +47 -0
  15. package/dist/CatalogTile/index.d.ts +3 -0
  16. package/dist/CatalogTile/index.js +3 -0
  17. package/dist/CatalogTile-XL4XLFUH.css +135 -0
  18. package/dist/CharacterPicker/index.js +2 -2
  19. package/dist/Charts/Histogram.d.ts +71 -0
  20. package/dist/Charts/index.d.ts +2 -0
  21. package/dist/Charts/index.js +1 -1
  22. package/dist/{Charts-MBJG72BS.css → Charts-TZ744HT6.css} +118 -0
  23. package/dist/CodeBlock/index.js +1 -1
  24. package/dist/{CodeBlock-GYNJ2HI6.css → CodeBlock-N5ETJF24.css} +13 -0
  25. package/dist/CommandPalette/index.js +3 -3
  26. package/dist/CommentThread/index.js +3 -3
  27. package/dist/Composer/index.js +2 -2
  28. package/dist/DataGrid/DataGrid.d.ts +267 -0
  29. package/dist/DataGrid/index.d.ts +3 -0
  30. package/dist/DataGrid/index.js +7 -0
  31. package/dist/DataGrid-AQKPJD7W.css +482 -0
  32. package/dist/DataTable/index.js +2 -2
  33. package/dist/DataView/index.js +4 -4
  34. package/dist/DatasetSource/DatasetSource.d.ts +7 -1
  35. package/dist/DatasetSource/index.js +1 -1
  36. package/dist/HuePicker/index.js +11 -4
  37. package/dist/LayersList/index.js +2 -2
  38. package/dist/LinkInterstitial/index.js +2 -2
  39. package/dist/List/List.d.ts +8 -0
  40. package/dist/List/index.js +1 -1
  41. package/dist/{List-MYJIV6MP.css → List-YHLIZFK4.css} +46 -0
  42. package/dist/ListInput/ListInput.d.ts +9 -1
  43. package/dist/ListInput/index.js +2 -2
  44. package/dist/LockedLabel/LockedLabel.d.ts +34 -0
  45. package/dist/LockedLabel/index.d.ts +3 -0
  46. package/dist/LockedLabel/index.js +3 -0
  47. package/dist/LockedLabel-VQEGEB7G.css +16 -0
  48. package/dist/MarkdownEditor/index.js +8 -5
  49. package/dist/MergeConflicts/index.js +11 -5
  50. package/dist/Modal/index.js +1 -1
  51. package/dist/{Modal-7MWRCWAI.css → Modal-TOEWHDCQ.css} +5 -0
  52. package/dist/ObjectHeader/index.js +1 -1
  53. package/dist/{ObjectHeader-D7GU7QNI.css → ObjectHeader-ZOS22FKX.css} +7 -8
  54. package/dist/PageNote/PageNote.d.ts +14 -0
  55. package/dist/PageNote/index.d.ts +3 -0
  56. package/dist/PageNote/index.js +2 -0
  57. package/dist/PageNote-RHLXH3ML.css +12 -0
  58. package/dist/PropertyList/PropertyList.d.ts +88 -0
  59. package/dist/PropertyList/index.d.ts +3 -0
  60. package/dist/PropertyList/index.js +7 -0
  61. package/dist/PropertyList-SCYM66LL.css +96 -0
  62. package/dist/RelatedRow/RelatedRow.d.ts +27 -0
  63. package/dist/RelatedRow/index.d.ts +3 -0
  64. package/dist/RelatedRow/index.js +9 -0
  65. package/dist/RelatedRow-2FVS6QQA.css +6 -0
  66. package/dist/RichEditor/index.js +1 -1
  67. package/dist/SectionFrame/SectionFrame.d.ts +76 -0
  68. package/dist/SectionFrame/index.d.ts +3 -0
  69. package/dist/SectionFrame/index.js +7 -0
  70. package/dist/SectionFrame-M62UUVFQ.css +164 -0
  71. package/dist/SegmentedControl/index.js +11 -4
  72. package/dist/SettingsTable/SettingsTable.d.ts +66 -0
  73. package/dist/SettingsTable/index.d.ts +3 -0
  74. package/dist/SettingsTable/index.js +3 -0
  75. package/dist/SettingsTable-6DUFAFXG.css +160 -0
  76. package/dist/ShareDialog/index.js +2 -2
  77. package/dist/SheetColumnEditor/index.js +7 -6
  78. package/dist/SheetGrid/index.js +3 -3
  79. package/dist/SidebarNav/SidebarNav.d.ts +35 -2
  80. package/dist/SidebarNav/index.js +2 -1
  81. package/dist/{SidebarNav-7SGUZYKK.css → SidebarNav-YI74SPDC.css} +10 -0
  82. package/dist/StatCard/index.js +1 -1
  83. package/dist/{StatCard-4T7TMWMN.css → StatCard-HAA3F5GX.css} +8 -3
  84. package/dist/StatGroup/index.js +1 -1
  85. package/dist/{StatGroup-DOFHX5QJ.css → StatGroup-ZMW7VQWP.css} +27 -0
  86. package/dist/Switcher/index.js +2 -2
  87. package/dist/Tabs/Tabs.d.ts +55 -1
  88. package/dist/Tabs/fold.d.ts +54 -0
  89. package/dist/Tabs/index.d.ts +1 -1
  90. package/dist/Tabs/index.js +9 -2
  91. package/dist/Tabs/roving.d.ts +3 -3
  92. package/dist/{Tabs-WIF7457H.css → Tabs-S7F4RWAN.css} +77 -0
  93. package/dist/TagsInput/index.js +1 -1
  94. package/dist/ThemeGallery/index.js +2 -2
  95. package/dist/ThemeSwitcher/index.js +12 -5
  96. package/dist/TileGrid/TileGrid.d.ts +33 -0
  97. package/dist/TileGrid/index.d.ts +3 -0
  98. package/dist/TileGrid/index.js +2 -0
  99. package/dist/TileGrid-I6LNYD2H.css +52 -0
  100. package/dist/VersionCompare/index.js +12 -5
  101. package/dist/{chunk-B5J23C73.js → chunk-2PEXZ7L4.js} +1 -1
  102. package/dist/{chunk-S27UBCVX.js → chunk-2VOHUGUA.js} +2 -2
  103. package/dist/{chunk-XBURIXHO.js → chunk-3TXY3PJZ.js} +1 -1
  104. package/dist/{chunk-2QZ2VPHR.js → chunk-4OK4DX3V.js} +2 -2
  105. package/dist/chunk-4RKTZSEW.js +64 -0
  106. package/dist/{chunk-ECGGQX2H.js → chunk-A44YHLCQ.js} +2 -2
  107. package/dist/{chunk-F4LPQA4E.js → chunk-BA32AVKS.js} +1 -1
  108. package/dist/chunk-CV4NES3P.js +9 -0
  109. package/dist/{chunk-PPHTIKZO.js → chunk-E4BOVKNJ.js} +1 -1
  110. package/dist/{chunk-W7PAIVAP.js → chunk-E7QLG3PG.js} +30 -9
  111. package/dist/{chunk-RKKO7QHH.js → chunk-EGMQURBR.js} +5 -4
  112. package/dist/{chunk-GMW4ZHST.js → chunk-EX22Q5SH.js} +2 -2
  113. package/dist/{chunk-A23KDROH.js → chunk-FXBGEANQ.js} +1 -1
  114. package/dist/{chunk-4L2BWSHR.js → chunk-GFYQKMQZ.js} +2 -2
  115. package/dist/{chunk-HG5VF3TZ.js → chunk-HMVQQEHW.js} +91 -2
  116. package/dist/{chunk-IPWU6ERC.js → chunk-HQJ24WPM.js} +4 -2
  117. package/dist/{chunk-SVGARBDY.js → chunk-IAGYPTEJ.js} +2 -2
  118. package/dist/{chunk-ZK3VYY7L.js → chunk-INHXF2CL.js} +24 -11
  119. package/dist/chunk-INVSUFJK.js +71 -0
  120. package/dist/{chunk-6NNY5WBF.js → chunk-JKAGN4V4.js} +1 -1
  121. package/dist/{chunk-4LRAJXHL.js → chunk-JSWOXRRE.js} +1 -1
  122. package/dist/{chunk-DYB66CNM.js → chunk-KKNHMXTE.js} +6 -3
  123. package/dist/{chunk-UWRBD2YO.js → chunk-KNHUBHFX.js} +1 -1
  124. package/dist/{chunk-ZMDYQ2HH.js → chunk-KWWP3D7M.js} +1 -1
  125. package/dist/{chunk-46RL3E54.js → chunk-M6NQ4XGK.js} +1 -1
  126. package/dist/{chunk-PT6WKXKW.js → chunk-MMPKN7WV.js} +1 -1
  127. package/dist/{chunk-NRBAXRWE.js → chunk-N3TFYBN3.js} +1 -1
  128. package/dist/chunk-NNTO3TNC.js +9 -0
  129. package/dist/{chunk-DS2C73RJ.js → chunk-NZWX27J7.js} +2 -2
  130. package/dist/{chunk-VGE3G3T4.js → chunk-ODOJJGXH.js} +1 -1
  131. package/dist/chunk-OHGH7O6T.js +19 -0
  132. package/dist/{chunk-4ISUIS6F.js → chunk-OOC7Q67K.js} +1 -1
  133. package/dist/{chunk-BT5H2THK.js → chunk-OUD75UB2.js} +1 -1
  134. package/dist/chunk-PCT47E7O.js +48 -0
  135. package/dist/{chunk-X3UYTAOG.js → chunk-PFZOFAQ6.js} +1 -1
  136. package/dist/{chunk-YQG4PZGC.js → chunk-QRKT4XTT.js} +2 -2
  137. package/dist/{chunk-BJI3RFXG.js → chunk-S4DREXGM.js} +1 -1
  138. package/dist/{chunk-GDDE4UM7.js → chunk-SEC2GR2V.js} +1 -1
  139. package/dist/{chunk-YEVG2X5R.js → chunk-SNQRGH4A.js} +1 -1
  140. package/dist/chunk-T6MXORP5.js +116 -0
  141. package/dist/{chunk-OTCXRJ7D.js → chunk-U2XAJONO.js} +1 -1
  142. package/dist/{chunk-3ZUINC7C.js → chunk-WYYCPV46.js} +6 -1
  143. package/dist/chunk-X4IXXLWM.js +306 -0
  144. package/dist/{chunk-PAQXOP2M.js → chunk-XGBUUQDU.js} +2 -2
  145. package/dist/chunk-XIDD7PJO.js +416 -0
  146. package/dist/{chunk-XO7PUL4F.js → chunk-YPTTSJPM.js} +1 -1
  147. package/dist/chunk-ZUTUI27P.js +21 -0
  148. package/dist/generated/index.d.ts +9 -0
  149. package/dist/generated/index.js +83 -74
  150. package/dist/index.js +83 -74
  151. package/dist/styles.css +1627 -104
  152. package/package.json +3 -3
  153. package/dist/chunk-7SDUKCNW.js +0 -141
  154. package/dist/{Editor-QV4JP242.js → Editor-IRDQ3JDZ.js} +1 -1
  155. package/dist/{chunk-JZPK4IXR.js → chunk-3PR65I3H.js} +2 -2
  156. package/dist/{chunk-ETVEGR2Y.js → chunk-ISA2O2BK.js} +1 -1
  157. /package/dist/{chunk-4QQ3MND5.js → chunk-S3QTFUJX.js} +0 -0
package/README.md CHANGED
@@ -43,16 +43,16 @@ import { Button } from '@crewlethq/ui/Button'; // 8 KB of CSS, not 182 KB
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
44
  | Content and text | `Text` (the eight registers and `inherit`), `Prose`, `Document`, `DocumentTitle` and `DocumentTitleField`, the Markdown grammar (`parseMarkdown`, `parseMarkdownSpans`, `markdownInline`, `safeHref` and the line readers, with no React in it), `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`, `RichEditor` (with `preloadRichEditor`, and the round trip `roundTripMarkdown` and `canonicalMarkdown` from `@crewlethq/ui/RichEditorMarkdown`) |
46
- | Data display | `DataTable`, `CopyableCell`, `Table`, the read-only table cells (`TableKeyCell`, `TableNumberCell`, `TableDateCell`, `TableEntityCell`, `TableStatusCell`, `TableTagsCell`, `TableTextCell`), `StatCard`, `Meter`, `SegmentedMeter`, `Stepper`, `PricingCard`, `Avatar`, `AvatarStack`, `EntityChip`, `CodeBlock`, `QrCode`, `ObjectHeader`, `FactLine`, `SetByLine`, `Skeleton`, `Eyebrow`, `StatGroup`, `PinTile`, `IconTile` |
46
+ | Data display | `DataTable`, `CopyableCell`, `Table`, the read-only table cells (`TableKeyCell`, `TableNumberCell`, `TableDateCell`, `TableEntityCell`, `TableStatusCell`, `TableTagsCell`, `TableTextCell`), `StatCard`, `Meter`, `SegmentedMeter`, `Stepper`, `PricingCard`, `Avatar`, `AvatarStack`, `EntityChip`, `CodeBlock`, `QrCode`, `ObjectHeader`, `FactLine`, `SetByLine`, `Skeleton`, `Eyebrow`, `StatGroup`, `PinTile`, `IconTile`, `SettingsTable` (with `SettingsTable.Row`), `CatalogTile` |
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`, `ConflictNote`, `EditingStatus`, `Toaster`, `Modal` (with `variant="sheet"`), `ConfirmModal`, `CommandPalette`, `Tooltip`, `Popover`, `Announcer` |
49
49
  | Documents and review | `DiffView` and `DiffSummary` with the line diff they draw (`diffLines`, `diffStat`, `collapseDiff`, `firstChangedLines`, `splitLines`, `MAX_DIFF_LINES`, with no React in it), `DiffList`, `VersionCompare`, `CommentThread` |
50
50
  | Charts | `Legend`, `BarList`, `StackedBar`, `StackedColumns`, `ActivityStrip`, `TimeSeries`, `Sparkline`, the reading layer they share (`ChartTooltip`, `useChartHover`), and the ramp (`DATA_COLORS`, `DATA_COLOR_OTHER`, `dataColor`) |
51
51
  | Marks | `Count`, `StatusDot`, `EmptyValue`, `VisuallyHidden` |
52
52
  | Hooks and seams | `useModalLayer`, `usePopupLayer`, `LayerHost`, `useListbox`, `useOptionKeys`, `useHighlightRest` and `HIGHLIGHT_REST_MS`, `useClipboard`, `useDownload`, `downloadText`, `downloadBlob`, `safeFilename`, `toCsv`, `elementToPng` and `ElementToPngError`, `useOutcome`, `useAnnouncer`, `useNow`, `formatRelative`, `HeadingLevelProvider`, `cx`, the node hues (`NODE_HUES`, `NODE_HUE_NAMES`, `isNodeHue`) |
53
- | Layout | `Container`, `Section`, `Card`, `Tabs`, `Accordion`, `Disclosure`, `Outline` (with `useActiveHeading` and `scrollToHeading`), `TreeGrid` |
53
+ | Layout | `Container`, `Section`, `Card`, `TileGrid`, `Tabs`, `Accordion`, `Disclosure`, `Outline` (with `useActiveHeading` and `scrollToHeading`), `TreeGrid` |
54
54
  | Arranging a page | `ArrangeBoard`, `ArrangeGrid`, `ArrangeFrame` (with `useGridResize`), `ArrangeGroup`, `ArrangeList`, and the reorder hooks under them (`useReorder`, `useReorderLists`, `moveKey`) |
55
- | 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`, `useIdle`, `useMediaMatch` |
55
+ | Application shell | `AppShell` with `AppShell.Rail`, `SectionFrame` (with `SectionFrame.Nav` and `SectionFrame.Body`), `LockedLabel`, `AppShell.Topbar`, `AppShell.AccountRow` and `useAppShell`, `AuthLayout`, `SidebarNav` and `NavItem`, `BrandLockup`, `SearchTrigger`, `PageHeader`, `Toolbar`, `Stack`, `Inline`, `Spacer`, `AutoGrid`, `ErrorBoundary`, `useShortcut`, `useFullscreen`, `useIdle`, `useMediaMatch` |
56
56
  | 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 |
57
57
  | Artifacts | `SandboxedFrame` (with `SandboxedFramePlaceholder` and `SandboxedFrameNotice`), `LinkInterstitial` and `openExternal`, `VersionTimeline`, `ShareDialog` with the role ladder (`ARTIFACT_ROLES`, `SHAREABLE_ROLES`, `roleAtLeast`), `PrincipalPicker`, `Principal` and `PrincipalAvatar`, `ArtifactCard`, `ArtifactKindGlyph` and `ArtifactPreviewGlyph` (the preview a card draws with no cover, for a cover with nothing to draw), `ArtifactBar` and `ArtifactVersionChip` (an open artifact's one slim bar), `ArtifactPanel` and `ArtifactWorkspace` (the panels it opens beside or over the artifact), `CanvasBoard` (a design's artboards and notes on a `Canvas`, with the visibility budget `liveBoards`), `CanvasToolbar` (a canvas's tool palette, with `toolForKey`), `LayersList` (the list of a canvas's items beside it, marked by the canvas's selection), `CanvasSchematic` (a design's cover, drawn from its boards' frames), `AccessDeniedCard`, `ArtifactIcon` (with `artifactIconGlyph` and `ARTIFACT_ICON_WORDS`), the native gallery covers (`DocCover`, `SheetCover`, `DashboardCover`), `MergeConflicts`, the dashboard pieces (`WidgetFrame`, `DatasetSource` and `DatasetSourceList`), and `FrameProtocol` (the wire between a host page and an embedded artifact, with no React in it), `ArtifactNameCell` and `ArtifactAccessLabel` (with `ArtifactAccessGlyph`) for a list of artifacts |
58
58
  | 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) |
@@ -204,6 +204,82 @@ places:
204
204
  - A surface that pans or zooms dispatches `LAYER_REPOSITION_EVENT` on its host
205
205
  when the content beneath it moves, and every panel anchored inside follows.
206
206
 
207
+ ## Changes in 0.40.0
208
+
209
+ The engine dashboard's own lists, page parts and navigation pieces, moved into the kit so every application draws them from one place.
210
+
211
+ ### Lists and pages
212
+
213
+ **`DataGrid` draws a list as columns.** One track list on the grid, which every row adopts (`subgrid`), so a value always sits under the head that names it. The sort (`sort`, `onSortChange`, as `key` or `-key`) and the column set (`cols`, `onColsChange`, `key,key`, empty for the default set) are controlled, so an application keeps them wherever it keeps state (the engine keeps them in the address). A column gives way rather than starving its neighbours: `shrink` sizes it to its content up to a share of the grid, `floor` keeps the column that is the point of the list readable, and a grid that cannot fit drops columns by their `drop` rank rather than cutting them off, saying which in its foot ("Hidden to fit"). An `optional` column is off until the column set names it. A row links (`rowHref`, an overlay over the row, so a cell's own link or button still takes its own click) or activates (`onRowActivate`); `handleRef` steps and opens rows from an application's own keymap. Bands (`bands`) draw a grouped answer with each group's count, a sticky head sticks at `--crewlet-data-grid-sticky-top`, an empty grid draws `empty` as an `EmptyState`, and a grid inside a `Card` gives up its own edge. Below 640px each row is a labelled card, or one compact line with `phoneRows="compact"`. It is announced as a table, with `aria-sort` on its sortable column heads.
214
+
215
+ **`ColumnChooser` and `ChooserList`** are the checklist a reader picks what a view shows with. `ColumnChooser` takes a grid's own columns (`columnChoicesOf`) and writes the column set in declaration order; `ChooserList` is the plain checklist under it, for any set of facts a view shows (a card's fields). Both are one group named by their heading.
216
+
217
+ **`PropertyList` draws an object's facts in sections on one column**: every section's terms in one column (`--crewlet-description-list-term`, which `DescriptionList` reads too, so a page lines a list up with its key-value cards), the four kinds of absent value, a section with nothing filled in said once (`whenAllAbsent`), and one "set by" line under the last of the rows one change set (`setBy`, `change`). `headings` is `eyebrow` or `sentence`.
218
+
219
+ **`Tabs` take `overflow="menu"`**: what does not fit folds into a More menu (`moreLabel`, `moreMenuLabel`) instead of being cut, a tab with work in flight carries a pulsing mark and says so (`live`), and `note` is a sentence after the tabs that steps aside before any tab folds. Folded tabs stay measured and the arrow keys skip them. Link tabs spread `foldProps` on their link.
220
+
221
+ **`Histogram` draws where in a window things happened** (in `Charts`): one bar per bucket with its failed part inside the fill, a floor so a bucket with one event is still drawn, a date axis (`formatTick`) and the total said once (`summary`). With `onSelect` each bar is a button that narrows the window.
222
+
223
+ **`PageNote` is a screen's one quiet sentence** under its title, at the reading measure, with no word alone on its last line and no margin of its own. **`RelatedRow` is the one related place a page points at**: a quiet linked card under the page's content, its glyph and words on the card heads' columns, the whole row the link, in a `nav` named "Related".
224
+
225
+ **`NamedGlyph` draws a glyph from its name** (`@crewlethq/icons/glyphs/registry`, with `glyphFor`), for a place whose glyph is data, such as a list's empty state or a navigation entry.
226
+
227
+ ### Fixes
228
+
229
+ **Every catalogue tile's name stands on one line across a row** (`CatalogTile`). A tile without a status tag centred its name against its mark, 13px under its tagged neighbours; the name now starts at the top of the head whatever the tag.
230
+
231
+ ### Navigation
232
+
233
+ **`LockedLabel` draws a place the reader may not open**: its words with the key after them, the reason (`reason`, "Needs Admin access") as the pointer's title and read after the name, and nothing but the words where nothing is missing. A place is locked, never hidden. `mark={false}` keeps the reason and drops the key, for a place under a heading that already carries it.
234
+
235
+ **`SidebarNav.Item` takes `locked`, `title` and `onPrefetch`.** `locked` draws the row's words as a `LockedLabel`, and the row stays a link. `title` is the row's hint. `onPrefetch` is called when the pointer reaches the row and when it takes focus, on the kit's anchor and on a router's (`renderLink` is handed `title`, `onPointerEnter` and `onFocus`), so an application needs no wrapper of its own to start fetching where a row leads.
236
+
237
+ **A wholly locked group draws its key once** (`SidebarNav.Group` `locked`). The key and the reason go on the group's label, and its rows stay links in the quiet ink with no key each, still saying their own reason. A reader holding none of a column's access met a key on every row of it. A mixed group, and a run with no label to carry the key, keep it on each locked row.
238
+
239
+ **`SectionFrame` draws a workspace's sections as a column beside the screen** (`SectionFrame.Nav`, `SectionFrame.Body`). The column sticks at the view's height while the section scrolls and keeps the wheel at its ends; with `folded` (the application's decision, from its own arithmetic of what a section beside the column needs) it becomes one row naming the section the reader is on ("Settings Section: People"), which unfolds the list, folds again on a pick, and opens on an arrival the caller asks it to (`openOnArrival`). The frame takes the content column's padding back and gives it to the body, which takes the phone's 16px under 640px.
240
+
241
+ ### Application shell
242
+
243
+ **The rail has a field slot and a head that takes its width** (`AppShell.Rail`). `search` is drawn first in the rail's middle, on the nav's gutter with its glyph on the nav rows' glyph column; the head's first child takes the head's width, so a long name truncates. Both were an application's own wrapper and rule.
244
+
245
+ **The scroller is a size container** (`.crewlet-app-shell__main`, `container-type: size`), so a box inside a screen can be as tall as the view it scrolls in (`100cqb`), as `SectionFrame`'s column is.
246
+
247
+ **A fill screen keeps the reserved scrollbar gutter.** The top bar's end inset counts the gutter, so a fill screen that reserved none put the bar's controls a gutter further out than on its neighbour: with classic scrollbars they moved 11px between an org chart and its roster. An application that restated `scrollbar-gutter: auto` for a fill screen drops it.
248
+
249
+ ## Changes in 0.39.0
250
+
251
+ These come from a production polish of the engine dashboard's Settings › Limits, Company › Integrations and Company › Policies, and the same patterns everywhere else it draws them.
252
+
253
+ ### New
254
+
255
+ **`SettingsTable` draws a read-only table of settings** (with `SettingsTable.Row`). Each row is the setting's name with its key in the document it is written in under it (`settingKey`, in the monospace face, quiet), the value in force in tabular figures, and where the value comes from (`source`). A value that is the default says so as a quiet word; a row marked `changed` carries a mark before its source, the one row in a table a reader scanning it came to find. The tracks are fractions of the table's width (`--crewlet-settings-table-columns`), so a page that stacks a table per group in cards of one width puts every value and every source on one line down the page, which a term column sized to its own longest term never did. It is announced as a table with Setting, Value and Source column headers (drawn with `header`, renamed with `columns`) and each setting's name as its row's header. In a `Card` (with `padding="none"`) it gives up its own edge and corner, as `StatGroup` does; under 32rem of table the name takes the row's first line and the value and its source share the second.
256
+
257
+ **`TileGrid` lays tiles out on a fixed track count that folds by its own width.** Two sections of tiles each on a track count of its own put their edges in different places, and an `auto-fill` grid left a hole at the end of a short section. `columns` is the count at full width: `3` (the default) folds straight to one under 40rem of grid, never to two, so a set of three or six never strands a tile; `4` folds to two under 56rem; every count is one track under 28rem. `as="ul"` makes the track the list.
258
+
259
+ **`CatalogTile` is one entry in a catalogue**: the mark in a well of one size and ground for every tile, the name as a heading at the level its place gives it, a `status` only when the state carries meaning (On, Connected, Needs attention, Coming soon), one sentence, and a foot with a quiet `meta` fact and one `action`, drawn only when there is something to put in it. A tile in its resting state carries no pill, and its name stands centred beside its mark; `quiet` puts a tile that is available but not set up on the page's own ground rather than draining its mark, because a drained vendor mark (Datadog's white plate on grey) read as a placeholder image. The sentence reserves two lines in a row of tiles so their feet line up, and reserves nothing once the grid is one track.
260
+
261
+ **`List` takes `variant="numbered-divided"`**: an `ol` whose numbers stand in a column of their own, in tabular figures, with a hairline between rows at a card's inset and the body's leading. For statements a reader cites by number, such as a company's standing policies, each of which may run to several lines and wraps under its own first word. The drawn number is the list's counter and is not read a second time.
262
+
263
+ **`ListInput` takes `focusOnMount`**, as `TagsInput` does: the focus goes to the new-item box when the list mounts, once, so a form opened to change that one list (an "Edit policies" link) lands where the next item is written. It is taken during mount, so a dialog the list opens in keeps it rather than moving focus to its own first control.
264
+
265
+ ### Fixes
266
+
267
+ **A card header's plain words are its title** (`Card.Header`). A header given a string or a number drew it as a bare text node at the regular weight with no heading element, beside cards whose `Card.Title` was a semibold heading: two title treatments on one page (Models, People, Nodes and a dozen more beside Limits and Sign-in policy), and the plain ones missing from the document outline. Plain words are now drawn as `Card.Title`. **A count of zero is not drawn**: the card's own empty state already says there is nothing, and "Models 0" said it twice.
268
+
269
+ **A card head can stack its subtitle at every width** (`Card.Header` `subtitlePlacement="below"`), for a row of cards of different widths whose heads must stand at one height: by default a wide card keeps its subtitle beside the title while a narrow one stacks it, so one row drew heads of 48 and 68px. **A code block that is a card's content is that card's surface** (`CodeBlock`): placed straight in a `Card` with `padding="none"` it gives up its own edge, corner and ground, so there is no box inside a box; in a padded body it stays a well.
270
+
271
+ **A dataset source can leave out its kind** (`DatasetSource` `kind` is optional): a list whose every entry reads from one place, grouped under list labels of its own, draws no kind tag on every row.
272
+
273
+ **A catalogue tile's fact-only foot stands as tall as one with a button** (`CatalogTile`), so the rules of a row's feet sit on one line.
274
+
275
+ **A dialog's title is its `h1`** (`Modal`). It was a paragraph while the body's headings started at level 2, so the outline a screen reader walks had no top; it keeps its register (the text face at the dialog's size), and still names the dialog.
276
+
277
+ **An object header's eyebrow and fact labels keep the words as written** (`ObjectHeader`, `FactLine`). They were the uppercase, tracked-open micro-caps of a table's column head, so a unit's page read "UNIT" over its name and TYPE, LEAD and SEATS under it, like a form. They are sentence case at the caption step now, as `StatCard`'s label already is.
278
+
279
+ **A row of stat tiles shares its lines** (`StatGroup`). Each tile in a row is a subgrid over the row's three lines (label, number, sub), so a label that wraps no longer pushes its own figure below the others; and a label stands on its number, one gap above it, where another label in the row takes two lines. **A stat tile's sub wraps** (`StatCard`), balanced, rather than ending in an ellipsis: its end is the half that says what the number means, and a grid of tiles gives every tile in a row one height anyway. These were the engine dashboard's own rules over the components; an application that restated them drops them.
280
+
281
+ **The artifact bar takes the shell top bar's inset** (`ArtifactBar`): 20px, 16px under the shell's breakpoint, plus the scroller's gutter at its end, since it stands in that bar's place. At a 12px inset of its own a create page's controls ended past the content under them.
282
+
207
283
  ## Changes in 0.38.0
208
284
 
209
285
  ### Icons
@@ -1,11 +1,11 @@
1
- export { AGENT_HANDOFF_LABELS, AgentHandoffPanel } from '../chunk-XBURIXHO.js';
1
+ export { AGENT_HANDOFF_LABELS, AgentHandoffPanel } from '../chunk-3TXY3PJZ.js';
2
2
  import '../chunk-AUQPBL4O.js';
3
3
  import '../chunk-3TFDQLW3.js';
4
4
  import '../chunk-OGXHZHRX.js';
5
- import '../chunk-ETVEGR2Y.js';
5
+ import '../chunk-ISA2O2BK.js';
6
6
  import '../chunk-Y5BD4MTE.js';
7
- import '../chunk-SMBKXWML.js';
8
7
  import '../chunk-TYONQSOK.js';
8
+ import '../chunk-SMBKXWML.js';
9
9
  import '../chunk-FZVJDJFN.js';
10
10
  import '../chunk-BHHIIK3M.js';
11
11
  import '../chunk-PQADV6P6.js';
@@ -108,8 +108,19 @@ export declare namespace AppShell {
108
108
  var AccountRow: typeof import("./AccountRow.js").AccountRow;
109
109
  }
110
110
  export interface AppShellRailProps {
111
- /** The head of the rail, drawn at the top bar's own height. */
111
+ /**
112
+ * The head of the rail, drawn at the top bar's own height. Its first child
113
+ * takes the head's width, so a long name (a company's, in a lockup)
114
+ * truncates rather than wrapping.
115
+ */
112
116
  header?: ReactNode;
117
+ /**
118
+ * The rail's field, first in its scrolling middle: a `SearchTrigger` with
119
+ * `variant="rail"`. The slot stands it on the nav's own gutter with its
120
+ * glyph on the nav rows' glyph column, so the field needs no inset of its
121
+ * application's own.
122
+ */
123
+ search?: ReactNode;
113
124
  /**
114
125
  * The foot: what the engine is doing, the theme and density controls. An
115
126
  * `<AppShell.RailRow>` puts a line there on the rail's own insets, so its
@@ -120,7 +131,7 @@ export interface AppShellRailProps {
120
131
  children?: ReactNode;
121
132
  }
122
133
  /** The rail's three regions: a head, a scrolling middle, and a foot. */
123
- export declare function AppShellRail({ header, footer, className, children }: AppShellRailProps): import("react").JSX.Element;
134
+ export declare function AppShellRail({ header, search, footer, className, children }: AppShellRailProps): import("react").JSX.Element;
124
135
  /**
125
136
  * A figure at the end of a row in the foot, and what it counts.
126
137
  *
@@ -1,4 +1,4 @@
1
- export { AccountRow, AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from '../chunk-DYB66CNM.js';
1
+ export { AccountRow, AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from '../chunk-KKNHMXTE.js';
2
2
  import '../chunk-RTPQDNW3.js';
3
3
  import '../chunk-D6FEHY5G.js';
4
4
  import '../chunk-OMV5W53A.js';
@@ -130,6 +130,8 @@
130
130
  .crewlet-app-shell__rail-head {
131
131
  display: flex;
132
132
  align-items: center;
133
+ gap: var(--spacing-2);
134
+ min-width: 0;
133
135
  flex: none;
134
136
  box-sizing: border-box;
135
137
  min-height: calc(var(--size-shell-inset) + var(--crewlet-app-shell-topbar));
@@ -143,6 +145,31 @@
143
145
  scrollbar-color: var(--color-scrollbar) transparent;
144
146
  }
145
147
 
148
+ /*
149
+ * THE HEAD'S FIRST CHILD TAKES ITS WIDTH: a lockup alone on its line, whose
150
+ * name truncates at the rail's edge rather than wrapping or pushing the head
151
+ * wider. It was every application's own wrapper and rule.
152
+ */
153
+ .crewlet-app-shell__rail-head > :first-child {
154
+ flex: 1 1 auto;
155
+ min-width: 0;
156
+ }
157
+
158
+ /*
159
+ * THE RAIL'S FIELD ON THE NAV'S COLUMNS. It stands on the nav's gutter, so
160
+ * its right edge is where every row's background ends; and its glyph stands
161
+ * on the nav's glyph column: a row's glyph is the gutter and the row's pad
162
+ * in, the field's is the gutter, its own 1px edge and its pad
163
+ * (`SearchTrigger`'s two steps and a half), so the inset at its start makes
164
+ * up the difference from those measures.
165
+ */
166
+ .crewlet-app-shell__rail-search {
167
+ padding: 0 var(--size-nav-gutter) var(--spacing-3);
168
+ padding-inline-start: calc(
169
+ var(--size-nav-gutter) + var(--size-nav-row-pad) - (var(--spacing-2) + var(--spacing-1) / 2) - 1px
170
+ );
171
+ }
172
+
146
173
  /* The same gutter the nav takes, so what the foot says lines up with the rows
147
174
  above it rather than sitting further out. */
148
175
  .crewlet-app-shell__rail-foot {
@@ -488,6 +515,15 @@
488
515
  overflow-y: auto;
489
516
  overflow-x: hidden;
490
517
  scrollbar-gutter: stable;
518
+ /*
519
+ * A SIZE CONTAINER, so a box inside the screen can be as tall as the view
520
+ * it scrolls in (`100cqb`): a column that sticks beside the screen
521
+ * (`SectionFrame`), a record bounded by the window. The scroller's size is
522
+ * the shell's, never its content's, so containing it costs nothing. A box
523
+ * inside an inline-size container (a card, a stat row) reaches past it to
524
+ * this one for the block axis.
525
+ */
526
+ container-type: size;
491
527
  }
492
528
 
493
529
  /* No focus rule of its own: `main` takes focus only from the skip link, and a
@@ -505,12 +541,17 @@
505
541
  }
506
542
 
507
543
  /* A screen that draws to the bottom of the window: the scroller stops
508
- scrolling and the content column takes the height that is left. It
509
- reserves no scrollbar gutter either, since nothing in it scrolls: the
510
- reserved strip was a dead band down the screen's end edge. */
544
+ scrolling and the content column takes the height that is left.
545
+
546
+ IT KEEPS THE GUTTER RESERVED, like every other screen. The top bar's end
547
+ inset counts the scroller's gutter (`--crewlet-app-shell-gutter`, measured
548
+ by the shell), so a fill screen that reserved none put the bar's controls
549
+ one gutter further out than on the screen beside it: with classic
550
+ scrollbars, Add seat moved 11px between an org chart and its roster, two
551
+ tabs of one page. A strip at the end edge of a full-screen canvas is the
552
+ smaller cost than a bar that moves under the pointer. */
511
553
  .crewlet-app-shell--fill .crewlet-app-shell__main {
512
554
  overflow: hidden;
513
- scrollbar-gutter: auto;
514
555
  }
515
556
 
516
557
  .crewlet-app-shell--fill .crewlet-app-shell__content {
@@ -1,8 +1,9 @@
1
- export { ARTIFACT_BAR_LABELS, ArtifactBar, ArtifactVersionChip } from '../chunk-S27UBCVX.js';
2
- import '../chunk-4ISUIS6F.js';
3
- import '../chunk-2QZ2VPHR.js';
4
- import '../chunk-7SDUKCNW.js';
5
- import '../chunk-RKKO7QHH.js';
1
+ export { ARTIFACT_BAR_LABELS, ArtifactBar, ArtifactVersionChip } from '../chunk-2VOHUGUA.js';
2
+ import '../chunk-OOC7Q67K.js';
3
+ import '../chunk-4OK4DX3V.js';
4
+ import '../chunk-X4IXXLWM.js';
5
+ import '../chunk-WIATRXEJ.js';
6
+ import '../chunk-EGMQURBR.js';
6
7
  import '../chunk-I33UIUZD.js';
7
8
  import '../chunk-ILDNJHRU.js';
8
9
  import '../chunk-CE2THTQR.js';
@@ -29,7 +29,12 @@
29
29
  its place, and at a row's height of its own the line under it jumped by
30
30
  three pixels between the gallery and the artifact opened from it. */
31
31
  height: calc(var(--size-shell-topbar) - 1px);
32
- padding: 0 var(--spacing-3);
32
+ /* THE SHELL TOP BAR'S INSET, the scroller's gutter at its end included: the
33
+ bar stands in that bar's place, and at a 12px inset of its own a create
34
+ page's controls ended 19px past the content under them, where every other
35
+ page's end over it. The same two steps as the top bar, 20px wide and 16px
36
+ under the shell's breakpoint (below). */
37
+ padding: 0 calc(var(--spacing-5) + var(--crewlet-app-shell-gutter, 0px)) 0 var(--spacing-5);
33
38
  min-width: 0;
34
39
  }
35
40
 
@@ -413,3 +418,10 @@
413
418
  transition: none;
414
419
  }
415
420
  }
421
+
422
+ /* The shell's breakpoint, where its top bar and content take 16px. */
423
+ @media (width < 1024px) {
424
+ .crewlet-artifact-bar__row {
425
+ padding: 0 calc(var(--spacing-4) + var(--crewlet-app-shell-gutter, 0px)) 0 var(--spacing-4);
426
+ }
427
+ }
@@ -1,10 +1,10 @@
1
- export { ArtifactCard, ArtifactCardSkeleton, ArtifactPreviewGlyph } from '../chunk-OTCXRJ7D.js';
1
+ export { ArtifactCard, ArtifactCardSkeleton, ArtifactPreviewGlyph } from '../chunk-U2XAJONO.js';
2
2
  import '../chunk-TEUQWOWZ.js';
3
3
  import '../chunk-CI3VPIJN.js';
4
4
  import '../chunk-3CZ7XAVY.js';
5
5
  import '../chunk-EUCC37WY.js';
6
6
  import '../chunk-UBZDYOCA.js';
7
- import '../chunk-ZK3VYY7L.js';
7
+ import '../chunk-INHXF2CL.js';
8
8
  import '../chunk-AV2DXAEL.js';
9
9
  import '../chunk-5AQBPHZD.js';
10
10
  import '../chunk-PZKHBB7D.js';
@@ -1,6 +1,6 @@
1
- export { AuthLayout } from '../chunk-BJI3RFXG.js';
1
+ export { AuthLayout } from '../chunk-S4DREXGM.js';
2
2
  import '../chunk-7KBNFFM3.js';
3
- import '../chunk-ZK3VYY7L.js';
3
+ import '../chunk-INHXF2CL.js';
4
4
  import '../chunk-AV2DXAEL.js';
5
5
  import '../chunk-BHHIIK3M.js';
6
6
  import '../chunk-PQADV6P6.js';
@@ -1,16 +1,20 @@
1
- export { AvatarPicker } from '../chunk-ECGGQX2H.js';
2
- import '../chunk-F4LPQA4E.js';
1
+ export { AvatarPicker } from '../chunk-A44YHLCQ.js';
2
+ import '../chunk-BA32AVKS.js';
3
3
  import '../chunk-KHJIEPZV.js';
4
4
  import '../chunk-AYKXMIOR.js';
5
- import '../chunk-YEVG2X5R.js';
6
- import '../chunk-2QZ2VPHR.js';
7
- import '../chunk-7SDUKCNW.js';
8
- import '../chunk-RKKO7QHH.js';
5
+ import '../chunk-SNQRGH4A.js';
6
+ import '../chunk-4OK4DX3V.js';
7
+ import '../chunk-X4IXXLWM.js';
8
+ import '../chunk-WIATRXEJ.js';
9
+ import '../chunk-EGMQURBR.js';
9
10
  import '../chunk-PZKHBB7D.js';
10
11
  import '../chunk-BHHIIK3M.js';
12
+ import '../chunk-D6FEHY5G.js';
11
13
  import '../chunk-OMV5W53A.js';
12
14
  import '../chunk-H5XTJ7GJ.js';
13
15
  import '../chunk-2YTOOH3A.js';
16
+ import '../chunk-OG6CL3EB.js';
17
+ import '../chunk-4FQT6ZAY.js';
14
18
  import '../chunk-NUZHC6MM.js';
15
19
  import '../chunk-BZFWDIV6.js';
16
20
  import '../chunk-ODEQTPFM.js';
@@ -105,10 +105,22 @@ export interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {
105
105
  divided?: boolean | undefined;
106
106
  /** A glyph before the title. Decoration: the title carries the meaning. */
107
107
  icon?: ReactNode;
108
- /** How many of something the card is about. */
108
+ /**
109
+ * How many of something the card is about. A count of zero is not drawn:
110
+ * the card's own empty state says there is nothing, and a "0" badge beside
111
+ * the title said it a second time.
112
+ */
109
113
  count?: number | string | undefined;
110
114
  /** A second line under the title. It truncates; a title does not. */
111
115
  subtitle?: ReactNode;
116
+ /**
117
+ * Where the subtitle stands. `beside` (the default) keeps the head one line
118
+ * and moves the subtitle under the title only on a card narrower than
119
+ * 480px; `below` always puts it under the title, for a row of cards of
120
+ * different widths (a wide card beside a narrow one) whose heads must stand
121
+ * at one height.
122
+ */
123
+ subtitlePlacement?: 'beside' | 'below' | undefined;
112
124
  /** The card's own controls, at the end of the header row. */
113
125
  actions?: ReactNode;
114
126
  }
@@ -159,7 +171,7 @@ export interface CardTitleProps extends HTMLAttributes<HTMLHeadingElement> {
159
171
  truncate?: boolean | undefined;
160
172
  }
161
173
  export declare const Card: (({ variant, padding, interactive, rail, selected, as, href, asChild, className, children, ...rest }: CardProps) => import("react").JSX.Element) & {
162
- Header: ({ divided, icon, count, subtitle, actions, className, children, ...rest }: CardHeaderProps) => import("react").JSX.Element;
174
+ Header: ({ divided, icon, count, subtitle, subtitlePlacement, actions, className, children, ...rest }: CardHeaderProps) => import("react").JSX.Element;
163
175
  Body: ({ padding, className, children, ...rest }: CardSectionProps) => import("react").JSX.Element;
164
176
  Footer: ({ variant, padding, className, children, ...rest }: CardFooterProps) => import("react").JSX.Element;
165
177
  Title: ({ as, truncate, className, children, ...rest }: CardTitleProps) => import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- export { Card } from '../chunk-ZK3VYY7L.js';
1
+ export { Card } from '../chunk-INHXF2CL.js';
2
2
  export { useCardHeaderSlot } from '../chunk-AV2DXAEL.js';
3
3
  import '../chunk-BHHIIK3M.js';
4
4
  import '../chunk-PQADV6P6.js';
@@ -495,6 +495,26 @@
495
495
  }
496
496
  }
497
497
 
498
+ /*
499
+ * STACKED, ASKED FOR: the subtitle under the title at every width, the shape
500
+ * the narrow step above draws, for a row of cards of different widths whose
501
+ * heads have to stand at one height rather than one inline and one stacked.
502
+ */
503
+ .crewlet-card__header--stacked {
504
+ flex-wrap: wrap;
505
+ row-gap: var(--spacing-1);
506
+ }
507
+
508
+ .crewlet-card__header--stacked > .crewlet-card__header-main {
509
+ flex: 1 1 0;
510
+ }
511
+
512
+ .crewlet-card__header--stacked > .crewlet-card__subtitle {
513
+ order: 1;
514
+ flex: 1 1 100%;
515
+ white-space: normal;
516
+ }
517
+
498
518
  .crewlet-card__description {
499
519
  margin: 0;
500
520
  font-size: var(--font-size-compact);
@@ -0,0 +1,47 @@
1
+ import { type HTMLAttributes, type ReactNode } from 'react';
2
+ import { type HeadingLevel } from '../utils/headingLevel.js';
3
+ export type CatalogTileElement = 'article' | 'li' | 'div';
4
+ export interface CatalogTileProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
5
+ /** The element the tile is: an `li` in a `TileGrid as="ul"`. */
6
+ as?: CatalogTileElement | undefined;
7
+ /**
8
+ * What the entry is told apart by before its name is read: a `VendorMark`,
9
+ * a glyph. Drawn in the tile's mark well, at one size and on one ground for
10
+ * every tile, and hidden from assistive technology: the name is what is read.
11
+ */
12
+ mark: ReactNode;
13
+ /** The entry's name, as the tile's heading. */
14
+ title: ReactNode;
15
+ /** Overrides the level the name is rendered at. */
16
+ headingLevel?: HeadingLevel | undefined;
17
+ /**
18
+ * The entry's state, as a `Tag`, ONLY when the state is worth reading: On,
19
+ * Connected, Needs attention, Coming soon. An entry in its resting state
20
+ * (available, not set up) carries none, and its name stands centred beside
21
+ * its mark; a pill under every name is a column a reader learns to skip.
22
+ */
23
+ status?: ReactNode;
24
+ /** One sentence: what the entry is for, or what is owed when something is. */
25
+ description?: ReactNode;
26
+ /** A quiet fact at the foot (`2 agents · 14 deliveries`). */
27
+ meta?: ReactNode;
28
+ /** The tile's one control, at the foot's end. */
29
+ action?: ReactNode;
30
+ /**
31
+ * Available but not set up: the tile sits one rung lower, on the page's own
32
+ * ground, rather than on the card's. Its text and its mark keep their
33
+ * strength, because a tile not yet set up is the one a reader came to set up.
34
+ */
35
+ quiet?: boolean | undefined;
36
+ }
37
+ /**
38
+ * One entry in a catalogue: its mark, its name, its state when it has one, a
39
+ * sentence, and a foot with a quiet fact and one action.
40
+ *
41
+ * EVERY TILE IN A ROW IS ONE SHAPE. The sentence reserves two lines and takes
42
+ * what is left of the tile's height, so tiles stretched to one row height in a
43
+ * `TileGrid` keep their feet on one line; a tile with neither a fact nor an
44
+ * action draws no foot at all, since a rule with nothing under it reads as a
45
+ * missing control.
46
+ */
47
+ export declare function CatalogTile({ as: Element, mark, title, headingLevel, status, description, meta, action, quiet, className, ...rest }: CatalogTileProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import './CatalogTile.css';
2
+ export { CatalogTile } from './CatalogTile.js';
3
+ export type { CatalogTileElement, CatalogTileProps } from './CatalogTile.js';
@@ -0,0 +1,3 @@
1
+ export { CatalogTile } from '../chunk-PCT47E7O.js';
2
+ import '../chunk-PQADV6P6.js';
3
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,135 @@
1
+ /*
2
+ * CatalogTile: mark, name and state, one sentence, and a foot with a quiet
3
+ * fact and one action.
4
+ *
5
+ * ONE WELL FOR EVERY MARK. A vendor's mark is drawn in the vendor's colours,
6
+ * so the box it stands in is the one thing a catalogue can hold constant: the
7
+ * same size, the same raised ground and the same hairline for every tile,
8
+ * set up or not. A drained mark on a grey box read as a placeholder image
9
+ * (a white plate on grey is not a logo), so a tile not yet set up says so by
10
+ * its ground, never by its mark.
11
+ */
12
+
13
+ .crewlet-catalog-tile {
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: var(--spacing-3);
17
+ min-width: 0;
18
+ padding: var(--spacing-4);
19
+ background: var(--color-surface-subtle);
20
+ border: 1px solid var(--color-border-default);
21
+ border-radius: var(--radius-lg);
22
+ color: var(--color-text-primary);
23
+ }
24
+
25
+ .crewlet-catalog-tile--quiet {
26
+ background: var(--color-surface-background);
27
+ }
28
+
29
+ .crewlet-catalog-tile__head {
30
+ display: flex;
31
+ align-items: flex-start;
32
+ gap: var(--spacing-3);
33
+ min-width: 0;
34
+ }
35
+
36
+ .crewlet-catalog-tile__mark {
37
+ display: inline-flex;
38
+ flex: none;
39
+ align-items: center;
40
+ justify-content: center;
41
+ width: var(--size-row-lg);
42
+ height: var(--size-row-lg);
43
+ border-radius: var(--radius-md);
44
+ background: var(--color-surface-elevated);
45
+ border: 1px solid var(--color-border-default);
46
+ color: var(--color-text-primary);
47
+ }
48
+
49
+ /* The name, and under it the state when there is one. THE NAME STANDS ON ONE
50
+ LINE ACROSS A ROW whether or not a tile has a state: centred on the mark, a
51
+ name with a pill under it rose 13px above its stateless neighbour's, so the
52
+ names of one row stood at two heights. It starts one step below the mark's
53
+ top edge in every tile instead. */
54
+ .crewlet-catalog-tile__title {
55
+ display: flex;
56
+ flex-direction: column;
57
+ align-items: flex-start;
58
+ justify-content: flex-start;
59
+ padding-top: var(--spacing-1);
60
+ gap: var(--spacing-1);
61
+ min-width: 0;
62
+ }
63
+
64
+ .crewlet-catalog-tile__name {
65
+ margin: 0;
66
+ font-family: var(--font-family-sans);
67
+ font-size: var(--font-size-sm);
68
+ font-weight: var(--font-weight-semibold);
69
+ line-height: var(--font-line-height-snug);
70
+ color: var(--color-text-primary);
71
+ overflow-wrap: anywhere;
72
+ }
73
+
74
+ .crewlet-catalog-tile__status {
75
+ display: inline-flex;
76
+ }
77
+
78
+ .crewlet-catalog-tile__description {
79
+ flex: 1;
80
+ margin: 0;
81
+ /* Two lines reserved, so a tile saying what it is for and one saying what
82
+ is owed keep their feet on one line in a row. */
83
+ min-height: calc(2em * var(--font-line-height-body));
84
+ font-size: var(--font-size-compact);
85
+ line-height: var(--font-line-height-body);
86
+ color: var(--color-text-secondary);
87
+ }
88
+
89
+ .crewlet-catalog-tile__foot {
90
+ display: flex;
91
+ align-items: center;
92
+ gap: var(--spacing-2);
93
+ /* A SMALL CONTROL'S HEIGHT OF CONTENT, under the rule and the padding: a
94
+ foot holding only a fact stands as tall as one holding a button, so the
95
+ rules of every foot in a row sit on one line. Measured on the content
96
+ box, since under border-box sizing the padding spent the floor and a
97
+ fact-only foot stood 8px shorter. */
98
+ box-sizing: content-box;
99
+ min-height: var(--size-control-sm);
100
+ padding-top: var(--spacing-3);
101
+ border-top: 1px solid var(--color-border-default);
102
+ }
103
+
104
+ .crewlet-catalog-tile__meta {
105
+ flex: 1;
106
+ min-width: 0;
107
+ overflow: hidden;
108
+ text-overflow: ellipsis;
109
+ white-space: nowrap;
110
+ font-size: var(--font-size-xs);
111
+ color: var(--color-text-tertiary);
112
+ }
113
+
114
+ .crewlet-catalog-tile__action {
115
+ display: inline-flex;
116
+ flex: none;
117
+ }
118
+
119
+ /*
120
+ * ONE TILE A ROW RESERVES NOTHING. The two reserved lines exist to keep the
121
+ * feet of tiles side by side on one line; a grid folded to one track has no
122
+ * neighbours to line up with, and on a phone the reserve was a blank line in
123
+ * every short tile.
124
+ */
125
+ @container crewlet-tile-grid (width < 40rem) {
126
+ .crewlet-tile-grid[data-columns='3'] .crewlet-catalog-tile__description {
127
+ min-height: 0;
128
+ }
129
+ }
130
+
131
+ @container crewlet-tile-grid (width < 28rem) {
132
+ .crewlet-tile-grid .crewlet-catalog-tile__description {
133
+ min-height: 0;
134
+ }
135
+ }
@@ -1,5 +1,5 @@
1
1
  import '../chunk-3L5NHASN.js';
2
- export { CHARACTER_PICKER_COLUMNS, CharacterPicker } from '../chunk-YEVG2X5R.js';
3
- import '../chunk-RKKO7QHH.js';
2
+ export { CHARACTER_PICKER_COLUMNS, CharacterPicker } from '../chunk-SNQRGH4A.js';
3
+ import '../chunk-EGMQURBR.js';
4
4
  import '../chunk-PZKHBB7D.js';
5
5
  import '../chunk-ODEQTPFM.js';