@crewlethq/ui 0.17.0 → 0.18.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 (146) hide show
  1. package/README.md +36 -1
  2. package/dist/AccessDeniedCard/AccessDeniedCard.d.ts +39 -0
  3. package/dist/AccessDeniedCard/index.d.ts +3 -0
  4. package/dist/AccessDeniedCard/index.js +8 -0
  5. package/dist/AccessDeniedCard-WXM5DBDZ.css +8 -0
  6. package/dist/ArtifactCard/ArtifactCard.d.ts +61 -0
  7. package/dist/ArtifactCard/index.d.ts +3 -0
  8. package/dist/ArtifactCard/index.js +12 -0
  9. package/dist/ArtifactCard-EXVAEBV6.css +109 -0
  10. package/dist/AvatarPicker/index.js +4 -4
  11. package/dist/ChangeMark/ChangeMark.d.ts +26 -0
  12. package/dist/ChangeMark/index.d.ts +3 -0
  13. package/dist/ChangeMark/index.js +8 -0
  14. package/dist/ChangeMark-3VMTW7MT.css +22 -0
  15. package/dist/Combobox/index.js +1 -1
  16. package/dist/CommandPalette/index.js +3 -3
  17. package/dist/CursorFlag/CursorFlag.d.ts +34 -0
  18. package/dist/CursorFlag/index.d.ts +3 -0
  19. package/dist/CursorFlag/index.js +3 -0
  20. package/dist/CursorFlag-AJQJBUGY.css +61 -0
  21. package/dist/DataTable/index.js +6 -6
  22. package/dist/DataView/index.js +12 -12
  23. package/dist/DateTimePicker/index.js +2 -2
  24. package/dist/FollowBanner/FollowBanner.d.ts +35 -0
  25. package/dist/FollowBanner/index.d.ts +2 -0
  26. package/dist/FollowBanner/index.js +7 -0
  27. package/dist/FrameProtocol/index.d.ts +2 -0
  28. package/dist/FrameProtocol/index.js +2 -0
  29. package/dist/FrameProtocol/protocol.d.ts +164 -0
  30. package/dist/HuePicker/index.js +2 -2
  31. package/dist/LinkInterstitial/LinkInterstitial.d.ts +41 -0
  32. package/dist/LinkInterstitial/index.d.ts +3 -0
  33. package/dist/LinkInterstitial/index.js +11 -0
  34. package/dist/LinkInterstitial-ET4MSVSV.css +34 -0
  35. package/dist/ListInput/index.js +1 -1
  36. package/dist/LiveCursor/LiveCursor.d.ts +34 -0
  37. package/dist/LiveCursor/index.d.ts +3 -0
  38. package/dist/LiveCursor/index.js +4 -0
  39. package/dist/LiveCursor-DZHGIYWE.css +47 -0
  40. package/dist/MarkdownEditor/index.js +2 -2
  41. package/dist/Modal/index.js +2 -2
  42. package/dist/OrgTable/index.js +2 -2
  43. package/dist/PresenceModel/index.d.ts +2 -0
  44. package/dist/PresenceModel/index.js +3 -0
  45. package/dist/PresenceModel/presence.d.ts +80 -0
  46. package/dist/PresenceRing/PresenceRing.d.ts +31 -0
  47. package/dist/PresenceRing/index.d.ts +3 -0
  48. package/dist/PresenceRing/index.js +2 -0
  49. package/dist/PresenceRing-M4C22Q6U.css +68 -0
  50. package/dist/PresenceStack/PresenceStack.d.ts +36 -0
  51. package/dist/PresenceStack/index.d.ts +3 -0
  52. package/dist/PresenceStack/index.js +9 -0
  53. package/dist/PresenceStack-QSXQJND5.css +59 -0
  54. package/dist/PricingCard/index.js +2 -2
  55. package/dist/Principal/Principal.d.ts +35 -0
  56. package/dist/Principal/index.d.ts +2 -0
  57. package/dist/Principal/index.js +4 -0
  58. package/dist/PrincipalPicker/PrincipalPicker.d.ts +45 -0
  59. package/dist/PrincipalPicker/index.d.ts +3 -0
  60. package/dist/PrincipalPicker/index.js +12 -0
  61. package/dist/PrincipalPicker-7NNZTGUP.css +41 -0
  62. package/dist/SandboxedFrame/SandboxedFrame.d.ts +142 -0
  63. package/dist/SandboxedFrame/index.d.ts +3 -0
  64. package/dist/SandboxedFrame/index.js +8 -0
  65. package/dist/SandboxedFrame-L6HBQZCD.css +50 -0
  66. package/dist/ShareDialog/ShareDialog.d.ts +101 -0
  67. package/dist/ShareDialog/index.d.ts +5 -0
  68. package/dist/ShareDialog/index.js +19 -0
  69. package/dist/ShareDialog/roles.d.ts +10 -0
  70. package/dist/ShareDialog-YZ4F37MW.css +146 -0
  71. package/dist/SheetGrid/SheetGrid.d.ts +78 -0
  72. package/dist/SheetGrid/cells.d.ts +117 -0
  73. package/dist/SheetGrid/index.d.ts +5 -0
  74. package/dist/SheetGrid/index.js +18 -0
  75. package/dist/SheetGrid-4HOXDVIB.css +595 -0
  76. package/dist/SheetModel/clipboard.d.ts +37 -0
  77. package/dist/SheetModel/edits.d.ts +68 -0
  78. package/dist/SheetModel/index.d.ts +14 -0
  79. package/dist/SheetModel/index.js +3 -0
  80. package/dist/SheetModel/labels.d.ts +71 -0
  81. package/dist/SheetModel/navigation.d.ts +79 -0
  82. package/dist/SheetModel/options.d.ts +28 -0
  83. package/dist/SheetModel/types.d.ts +126 -0
  84. package/dist/SheetModel/values.d.ts +76 -0
  85. package/dist/SheetModel/view.d.ts +32 -0
  86. package/dist/Switcher/index.js +5 -5
  87. package/dist/Tag/Tag.d.ts +13 -0
  88. package/dist/Tag/index.js +1 -1
  89. package/dist/{Tag-4BRQS6GN.css → Tag-SRGTK5KI.css} +42 -0
  90. package/dist/TagsInput/index.js +2 -2
  91. package/dist/ThemeSwitcher/apply.d.ts +43 -0
  92. package/dist/ThemeSwitcher/index.d.ts +4 -2
  93. package/dist/ThemeSwitcher/index.js +3 -2
  94. package/dist/ThemeSwitcher/preferences.d.ts +2 -19
  95. package/dist/ThemeToggle/index.js +3 -2
  96. package/dist/TimeWindowPicker/index.js +3 -3
  97. package/dist/Timeline/Timeline.d.ts +7 -2
  98. package/dist/Timeline/index.js +1 -1
  99. package/dist/VersionTimeline/VersionTimeline.d.ts +76 -0
  100. package/dist/VersionTimeline/index.d.ts +3 -0
  101. package/dist/VersionTimeline/index.js +10 -0
  102. package/dist/VersionTimeline-EBJ6MIPJ.css +108 -0
  103. package/dist/{chunk-SBRE7IML.js → chunk-2ONWEDQT.js} +1 -1
  104. package/dist/chunk-2YR5ZPQ3.js +216 -0
  105. package/dist/chunk-3BYIWOTV.js +29 -0
  106. package/dist/chunk-3UAA4IWJ.js +98 -0
  107. package/dist/chunk-4KP4RC3O.js +25 -0
  108. package/dist/chunk-4U3GQ7D2.js +99 -0
  109. package/dist/chunk-5XACKNYR.js +53 -0
  110. package/dist/{chunk-RF5O4FYL.js → chunk-76FXDZAZ.js} +2 -2
  111. package/dist/chunk-A7EBCHEG.js +49 -0
  112. package/dist/{chunk-JCO3SIST.js → chunk-AQCV62K6.js} +1 -1
  113. package/dist/{chunk-O67VF5MS.js → chunk-AUQPBL4O.js} +2 -2
  114. package/dist/{chunk-HENOTGUV.js → chunk-BOW2VUCH.js} +2 -2
  115. package/dist/{chunk-UCYIRDND.js → chunk-DQSXWQMJ.js} +1 -1
  116. package/dist/chunk-ESKP3TXM.js +1 -0
  117. package/dist/chunk-F6V2PTN6.js +142 -0
  118. package/dist/chunk-FW7HN6AP.js +40 -0
  119. package/dist/chunk-FYXRWBJJ.js +1235 -0
  120. package/dist/{chunk-LOECRMHA.js → chunk-GFV4LJHH.js} +4 -3
  121. package/dist/chunk-I6POAB4V.js +20 -0
  122. package/dist/{chunk-PQ63NLFC.js → chunk-IFKBDRNJ.js} +1 -1
  123. package/dist/{chunk-XU4H6JQB.js → chunk-KVT3TJVG.js} +4 -4
  124. package/dist/chunk-LFZ45HV2.js +46 -0
  125. package/dist/{chunk-6TSZCBID.js → chunk-NP2C4Y4E.js} +1 -1
  126. package/dist/{chunk-FA2V2VT6.js → chunk-NZY77ZDU.js} +3 -3
  127. package/dist/chunk-PPAQFGS2.js +12 -0
  128. package/dist/chunk-S35G6PNC.js +80 -0
  129. package/dist/chunk-VYDFB6PJ.js +243 -0
  130. package/dist/chunk-WXAULPBH.js +135 -0
  131. package/dist/chunk-YM3GJHGW.js +69 -0
  132. package/dist/chunk-YYZRLLLY.js +822 -0
  133. package/dist/{chunk-K3OWD7BJ.js → chunk-Z24ZUSTX.js} +4 -19
  134. package/dist/chunk-ZXXDZJQN.js +36 -0
  135. package/dist/generated/index.d.ts +18 -0
  136. package/dist/generated/index.js +82 -62
  137. package/dist/index.js +82 -62
  138. package/dist/styles.css +1578 -149
  139. package/dist/utils/index.js +1 -1
  140. package/package.json +6 -6
  141. package/dist/{chunk-DEEVA6TV.js → chunk-2TZATTIU.js} +1 -1
  142. package/dist/{chunk-2UU5IGZI.js → chunk-5NVKTB6E.js} +1 -1
  143. package/dist/{chunk-CRVETI5L.js → chunk-CENOOTAV.js} +0 -0
  144. package/dist/{chunk-JF7X673Z.js → chunk-ERV5BUS3.js} +1 -1
  145. package/dist/{chunk-NXDEPUVG.js → chunk-PA4CYTBY.js} +1 -1
  146. package/dist/{chunk-77IEHFY4.js → chunk-QQGWES46.js} +1 -1
package/README.md CHANGED
@@ -51,7 +51,10 @@ import { Button } from '@crewlethq/ui/Button'; // 8 KB of CSS, not 182 KB
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
53
  | 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` |
54
+ | Preferences | `ThemeToggle`, `ThemeSwitcher`, `DensitySwitcher`, `ThemeGallery`, `ThemeSwatch`, `useThemePreference`, `useDensityPreference`, `useSystemTheme`, `resolveTheme`, `applyStoredPreferences`, and the framework-free `applyTheme`, `applyPalette`, `applyDensity` with `THEME_PREFERENCES`, `DENSITY_PREFERENCES` and their guards |
55
+ | 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) |
56
+ | 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) |
57
+ | 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
58
 
56
59
  Storybook stories live under `apps/storybook/src/stories`.
57
60
 
@@ -198,6 +201,38 @@ places:
198
201
  - A surface that pans or zooms dispatches `LAYER_REPOSITION_EVENT` on its host
199
202
  when the content beneath it moves, and every panel anchored inside follows.
200
203
 
204
+ ## Changes in 0.18.0
205
+
206
+ 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.
207
+
208
+ **`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`.
209
+
210
+ **`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.
211
+
212
+ **`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`.
213
+
214
+ **`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.
215
+
216
+ **`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.
217
+
218
+ **`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.
219
+
220
+ **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.
221
+
222
+ **`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.
223
+
224
+ **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.
225
+
226
+ **`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.
227
+
228
+ **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.
229
+
230
+ **`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.
231
+
232
+ `@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`.
233
+
234
+ What to change: nothing. Every addition is new, and `applyTheme` and `applyDensity` keep their one-argument form.
235
+
201
236
  ## Changes in 0.17.0
202
237
 
203
238
  **`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,3 @@
1
+ import './AccessDeniedCard.css';
2
+ export { ACCESS_DENIED_REASONS, AccessDeniedCard } from './AccessDeniedCard.js';
3
+ export type { AccessDeniedCardLabels, AccessDeniedCardProps, AccessDeniedReason } from './AccessDeniedCard.js';
@@ -0,0 +1,8 @@
1
+ export { ACCESS_DENIED_REASONS, AccessDeniedCard } from '../chunk-LFZ45HV2.js';
2
+ import '../chunk-RA2ULG6H.js';
3
+ import '../chunk-EG6NYWVK.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';
@@ -0,0 +1,8 @@
1
+ /* The card holds one empty state and nothing else, at a reading width, so a
2
+ refusal in a wide viewer body reads as one sentence rather than a banner. */
3
+
4
+ .crewlet-access-denied-card {
5
+ width: 100%;
6
+ max-width: var(--size-measure);
7
+ margin-inline: auto;
8
+ }
@@ -0,0 +1,61 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type GlyphSize } from '@crewlethq/icons/glyphs';
3
+ import { type AvatarStackMember } from '../Avatar/index.js';
4
+ import { type Principal } from '../Principal/index.js';
5
+ import { type TimeValue } from '../RelativeTime/index.js';
6
+ /** What an artifact is, as the engine names it (`artifacts.Kind`), which decides how it is drawn. */
7
+ export type ArtifactKind = 'html' | 'markdown' | 'sheet';
8
+ export declare const ARTIFACT_KINDS: readonly ["html", "markdown", "sheet"];
9
+ /** The glyph a kind is drawn with, wherever a kind is drawn, at a glyph size step or in px. */
10
+ export declare function ArtifactKindGlyph({ kind, size }: {
11
+ kind: ArtifactKind;
12
+ size?: GlyphSize | undefined;
13
+ }): import("react").JSX.Element;
14
+ export type ArtifactCardSize = 'card' | 'compact';
15
+ export interface ArtifactCardLabels {
16
+ kinds: Record<ArtifactKind, string>;
17
+ pinned: string;
18
+ version: (version: number) => string;
19
+ changes: (count: number) => string;
20
+ present: (count: number) => string;
21
+ updated: string;
22
+ }
23
+ export interface ArtifactCardProps {
24
+ title: string;
25
+ kind: ArtifactKind;
26
+ /** Where the card goes: the artifact's viewer. The whole card is one real link. */
27
+ href: string;
28
+ /**
29
+ * A thumbnail drawn natively: a sheet's first rows, an author's cover image.
30
+ * Never a screenshot. The kind's glyph stands in when there is none.
31
+ */
32
+ preview?: ReactNode;
33
+ owner?: Principal | undefined;
34
+ updatedAt: TimeValue;
35
+ /** Who made the latest change, when it is worth saying ("Maya"). */
36
+ updatedBy?: string | undefined;
37
+ /** Who has it open now. */
38
+ presence?: readonly AvatarStackMember[] | undefined;
39
+ /** Changes since this reader last opened it. Nothing is drawn for none or for never opened. */
40
+ changes?: number | undefined;
41
+ pinned?: boolean | undefined;
42
+ version?: number | undefined;
43
+ /** The project or task it belongs to, as its key ("OPS", "ENG-412"). */
44
+ project?: string | undefined;
45
+ /** `compact` is a row for a narrow rail or a phone, with no preview. */
46
+ size?: ArtifactCardSize | undefined;
47
+ className?: string | undefined;
48
+ /** Overrides the shared clock, for a story or a suite. */
49
+ now?: number | undefined;
50
+ labels?: Partial<ArtifactCardLabels> | undefined;
51
+ }
52
+ /**
53
+ * One artifact, as a card in a gallery, a row in a task's rail or an embed.
54
+ *
55
+ * THE WHOLE CARD IS ONE LINK, named by the title alone and described by the
56
+ * rest, so a reader moving through a gallery by link hears "Vendor scorecard"
57
+ * and then, if they wait, what it is and who changed it. Nothing inside is a
58
+ * second control: a pin or a menu inside a link is a control nobody can reach
59
+ * without opening the artifact. Those live on the gallery row's own menu.
60
+ */
61
+ export declare function ArtifactCard({ title, kind, href, preview, owner, updatedAt, updatedBy, presence, changes, pinned, version, project, size, className, now, labels, }: ArtifactCardProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import './ArtifactCard.css';
2
+ export { ARTIFACT_KINDS, ArtifactCard, ArtifactKindGlyph } from './ArtifactCard.js';
3
+ export type { ArtifactCardLabels, ArtifactCardProps, ArtifactCardSize, ArtifactKind } from './ArtifactCard.js';
@@ -0,0 +1,12 @@
1
+ export { ARTIFACT_KINDS, ArtifactCard, ArtifactKindGlyph } from '../chunk-4U3GQ7D2.js';
2
+ import '../chunk-4KP4RC3O.js';
3
+ import '../chunk-3CZ7XAVY.js';
4
+ import '../chunk-EUCC37WY.js';
5
+ import '../chunk-UAN5NE7M.js';
6
+ import '../chunk-5OM447RW.js';
7
+ import '../chunk-EG6NYWVK.js';
8
+ import '../chunk-AV2DXAEL.js';
9
+ import '../chunk-PQADV6P6.js';
10
+ import '../chunk-BHHIIK3M.js';
11
+ import '../chunk-BZFWDIV6.js';
12
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,109 @@
1
+ /*
2
+ * A card in a gallery: the preview on top at a fixed ratio, so a grid of them
3
+ * lines up whatever each preview is, then the title and up to three lines of
4
+ * facts. `compact` is a row with the kind's glyph in place of the preview.
5
+ */
6
+
7
+ .crewlet-artifact-card {
8
+ display: flex;
9
+ flex-direction: column;
10
+ min-width: 0;
11
+ overflow: hidden;
12
+ color: inherit;
13
+ text-decoration: none;
14
+ }
15
+
16
+ .crewlet-artifact-card--compact {
17
+ flex-direction: row;
18
+ align-items: flex-start;
19
+ gap: var(--spacing-3);
20
+ padding: var(--spacing-3);
21
+ }
22
+
23
+ .crewlet-artifact-card__preview {
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ aspect-ratio: 16 / 9;
28
+ overflow: hidden;
29
+ border-bottom: 1px solid var(--color-border-default);
30
+ background: var(--color-surface-inset);
31
+ color: var(--color-text-tertiary);
32
+ }
33
+
34
+ .crewlet-artifact-card__glyph {
35
+ display: inline-flex;
36
+ color: var(--color-text-tertiary);
37
+ }
38
+
39
+ .crewlet-artifact-card__glyph--compact {
40
+ flex: none;
41
+ align-items: center;
42
+ justify-content: center;
43
+ width: var(--size-control-md);
44
+ height: var(--size-control-md);
45
+ border-radius: var(--radius-md);
46
+ background: var(--color-surface-inset);
47
+ }
48
+
49
+ .crewlet-artifact-card__body {
50
+ display: flex;
51
+ flex-direction: column;
52
+ gap: var(--spacing-1);
53
+ min-width: 0;
54
+ padding: var(--spacing-3);
55
+ }
56
+
57
+ .crewlet-artifact-card--compact .crewlet-artifact-card__body {
58
+ padding: 0;
59
+ }
60
+
61
+ .crewlet-artifact-card__title-row {
62
+ display: flex;
63
+ align-items: center;
64
+ gap: var(--spacing-1);
65
+ min-width: 0;
66
+ }
67
+
68
+ .crewlet-artifact-card__title {
69
+ overflow: hidden;
70
+ color: var(--color-text-primary);
71
+ font-weight: var(--font-weight-semibold);
72
+ text-overflow: ellipsis;
73
+ white-space: nowrap;
74
+ }
75
+
76
+ .crewlet-artifact-card__pin {
77
+ display: inline-flex;
78
+ flex: none;
79
+ color: var(--color-text-tertiary);
80
+ }
81
+
82
+ .crewlet-artifact-card__facts {
83
+ display: flex;
84
+ flex-direction: column;
85
+ gap: var(--spacing-1);
86
+ color: var(--color-text-tertiary);
87
+ font-size: var(--font-size-xs);
88
+ }
89
+
90
+ .crewlet-artifact-card__line {
91
+ display: flex;
92
+ flex-wrap: wrap;
93
+ align-items: center;
94
+ gap: var(--spacing-1) var(--spacing-2);
95
+ min-width: 0;
96
+ }
97
+
98
+ .crewlet-artifact-card__owner,
99
+ .crewlet-artifact-card__presence {
100
+ display: inline-flex;
101
+ align-items: center;
102
+ gap: var(--spacing-1);
103
+ min-width: 0;
104
+ }
105
+
106
+ .crewlet-artifact-card__changes {
107
+ color: var(--color-text-secondary);
108
+ font-weight: var(--font-weight-medium);
109
+ }
@@ -1,14 +1,14 @@
1
- export { AvatarPicker } from '../chunk-HENOTGUV.js';
2
- import '../chunk-NXDEPUVG.js';
3
- import '../chunk-AYKXMIOR.js';
1
+ export { AvatarPicker } from '../chunk-BOW2VUCH.js';
2
+ import '../chunk-PA4CYTBY.js';
4
3
  import '../chunk-26PEPONN.js';
5
4
  import '../chunk-4LDTQWS7.js';
6
5
  import '../chunk-BWRGFKJP.js';
6
+ import '../chunk-AYKXMIOR.js';
7
7
  import '../chunk-5PSXBL73.js';
8
8
  import '../chunk-CBOICT64.js';
9
9
  import '../chunk-HMPFGIWM.js';
10
10
  import '../chunk-R25RGPUB.js';
11
+ import '../chunk-5OM447RW.js';
11
12
  import '../chunk-BHHIIK3M.js';
12
13
  import '../chunk-BZFWDIV6.js';
13
- import '../chunk-5OM447RW.js';
14
14
  import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,26 @@
1
+ import { type SheetChange, type SheetLabels } from '../SheetModel/index.js';
2
+ export interface ChangeMarkProps {
3
+ /** Who changed it, by display name. */
4
+ by: string;
5
+ at: SheetChange['at'];
6
+ /** The value before the change, already written for a reader ("6.8"), or null to say nothing of it. */
7
+ previous?: string | null | undefined;
8
+ /** A BCP 47 tag for the time; the reader's own locale when absent. */
9
+ locale?: string | undefined;
10
+ className?: string | undefined;
11
+ labels?: Pick<Partial<SheetLabels>, 'changed'> | undefined;
12
+ }
13
+ /**
14
+ * The corner mark on a cell or an element that changed since the reader last
15
+ * looked, with a tooltip that says who changed it, when, and what it was:
16
+ * "Changed by Maya Ortiz, 10:42. Was 6.8."
17
+ *
18
+ * A SHAPE AND WORDS, never colour alone: the mark is a corner notch in
19
+ * `--color-change-mark`, and the tooltip is the meaning. The mark itself is
20
+ * decorative to assistive technology, because the element it sits on carries
21
+ * the same sentence in its description (SheetGrid writes it into every focused
22
+ * cell's), and a mark read out on top of that would say it twice. A host
23
+ * drawing the mark on an element of its own says the sentence the same way,
24
+ * with `changeText` from the sheet model.
25
+ */
26
+ export declare function ChangeMark({ by, at, previous, locale, className, labels }: ChangeMarkProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import './ChangeMark.css';
2
+ export { ChangeMark } from './ChangeMark.js';
3
+ export type { ChangeMarkProps } from './ChangeMark.js';
@@ -0,0 +1,8 @@
1
+ export { ChangeMark } from '../chunk-PPAQFGS2.js';
2
+ import '../chunk-YYZRLLLY.js';
3
+ import '../chunk-S35G6PNC.js';
4
+ import '../chunk-QWOPX2MN.js';
5
+ import '../chunk-AYKXMIOR.js';
6
+ import '../chunk-HMPFGIWM.js';
7
+ import '../chunk-R25RGPUB.js';
8
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,22 @@
1
+ /*
2
+ * A change mark (ChangeMark.tsx): a notch in the top end corner of whatever
3
+ * it sits on, which is the nearest positioned ancestor. A triangle drawn by
4
+ * two borders, so it is a shape at any zoom and needs no glyph.
5
+ */
6
+
7
+ .crewlet-change-mark {
8
+ position: absolute;
9
+ top: 0;
10
+ inset-inline-end: 0;
11
+ width: 0;
12
+ height: 0;
13
+ border-top: var(--spacing-2) solid var(--color-change-mark);
14
+ border-inline-start: var(--spacing-2) solid transparent;
15
+ pointer-events: auto;
16
+ }
17
+
18
+ @media (forced-colors: active) {
19
+ .crewlet-change-mark {
20
+ border-top-color: CanvasText;
21
+ }
22
+ }
@@ -2,7 +2,7 @@ export { Combobox } from '../chunk-ZFH7H7GS.js';
2
2
  import '../chunk-F73MC7EZ.js';
3
3
  import '../chunk-4GB57WIT.js';
4
4
  import '../chunk-4FQT6ZAY.js';
5
- import '../chunk-PQADV6P6.js';
6
5
  import '../chunk-R25RGPUB.js';
6
+ import '../chunk-PQADV6P6.js';
7
7
  import '../chunk-BZFWDIV6.js';
8
8
  import '../chunk-ODEQTPFM.js';
@@ -1,13 +1,13 @@
1
- export { CommandPalette } from '../chunk-PQ63NLFC.js';
2
- import '../chunk-DEEVA6TV.js';
1
+ export { CommandPalette } from '../chunk-IFKBDRNJ.js';
2
+ import '../chunk-2TZATTIU.js';
3
3
  import '../chunk-F73MC7EZ.js';
4
4
  import '../chunk-SMBKXWML.js';
5
5
  import '../chunk-4GB57WIT.js';
6
6
  import '../chunk-OG6CL3EB.js';
7
7
  import '../chunk-4FQT6ZAY.js';
8
- import '../chunk-PQADV6P6.js';
9
8
  import '../chunk-HMPFGIWM.js';
10
9
  import '../chunk-R25RGPUB.js';
10
+ import '../chunk-PQADV6P6.js';
11
11
  import '../chunk-BHHIIK3M.js';
12
12
  import '../chunk-BZFWDIV6.js';
13
13
  import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,34 @@
1
+ import type { HTMLAttributes } from 'react';
2
+ import type { NodeHue } from '../utils/nodeHue.js';
3
+ /**
4
+ * Where a flag stands against the element it labels: above its end edge, below
5
+ * it, or in the flow for a component that places it itself (a live cursor).
6
+ */
7
+ export type CursorFlagPlacement = 'top-end' | 'bottom-end' | 'inline';
8
+ export interface CursorFlagProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'children'> {
9
+ /** The name, or several when more than one collaborator is on the same element ("Maya, @pm"). */
10
+ name: string | readonly string[];
11
+ hue: NodeHue;
12
+ /** A person's flag is a pill, an agent's a squircle, as their badges are. */
13
+ kind?: 'human' | 'agent' | undefined;
14
+ /** The collaborator is editing rather than looking: a pencil leads the name. */
15
+ editing?: boolean | undefined;
16
+ placement?: CursorFlagPlacement | undefined;
17
+ }
18
+ /**
19
+ * The name flag pinned to a collaborator's mark: a cell they are on, a cursor,
20
+ * a selection.
21
+ *
22
+ * THE NAME IS ALWAYS ON IT. A flag is the half of the presence colour
23
+ * exception (D22) that makes the hue mean somebody: a ring in a hue with no
24
+ * name beside it would be colour carrying identity on its own. The name is
25
+ * drawn in `--color-presence-flag-text`, which the palette suite holds at
26
+ * 4.5:1 on each of the six hues in every theme, and a long name is truncated
27
+ * rather than wrapped, so a flag never covers the row under it.
28
+ *
29
+ * DECORATIVE TO ASSISTIVE TECHNOLOGY. A flag moves with somebody else's
30
+ * attention, and announcing it would read the room out loud. The same fact is
31
+ * said in words wherever presence is listed, and in the focused element's
32
+ * description.
33
+ */
34
+ export declare function CursorFlag({ name, hue, kind, editing, placement, className, ...rest }: CursorFlagProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import './CursorFlag.css';
2
+ export { CursorFlag } from './CursorFlag.js';
3
+ export type { CursorFlagPlacement, CursorFlagProps } from './CursorFlag.js';
@@ -0,0 +1,3 @@
1
+ export { CursorFlag } from '../chunk-3BYIWOTV.js';
2
+ import '../chunk-I6POAB4V.js';
3
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,61 @@
1
+ /*
2
+ * A collaborator's name flag (CursorFlag.tsx): the name on a plate of their
3
+ * presence hue, in the ink the palette suite holds at 4.5:1 on every hue.
4
+ */
5
+
6
+ .crewlet-cursor-flag {
7
+ display: inline-flex;
8
+ align-items: center;
9
+ gap: var(--spacing-1);
10
+ box-sizing: border-box;
11
+ max-width: 16em;
12
+ padding: 0 calc(var(--spacing-1) * 1.5);
13
+ border-radius: var(--radius-pill);
14
+ background: var(--crewlet-presence-hue);
15
+ box-shadow: var(--shadow-cursor);
16
+ color: var(--color-presence-flag-text);
17
+ font-family: var(--font-family-sans);
18
+ font-size: var(--font-size-2xs);
19
+ font-weight: var(--font-weight-semibold);
20
+ line-height: var(--font-line-height-normal);
21
+ white-space: nowrap;
22
+ pointer-events: none;
23
+ user-select: none;
24
+ }
25
+
26
+ .crewlet-cursor-flag--agent {
27
+ border-radius: var(--radius-xs);
28
+ }
29
+
30
+ .crewlet-cursor-flag__name {
31
+ overflow: hidden;
32
+ text-overflow: ellipsis;
33
+ }
34
+
35
+ .crewlet-cursor-flag__glyph {
36
+ flex: none;
37
+ }
38
+
39
+ /* Pinned to the element it labels, which is the nearest positioned ancestor. */
40
+ .crewlet-cursor-flag--top-end,
41
+ .crewlet-cursor-flag--bottom-end {
42
+ position: absolute;
43
+ inset-inline-end: 0;
44
+ z-index: var(--z-index-presence);
45
+ }
46
+
47
+ .crewlet-cursor-flag--top-end {
48
+ bottom: 100%;
49
+ }
50
+
51
+ .crewlet-cursor-flag--bottom-end {
52
+ top: 100%;
53
+ }
54
+
55
+ @media (forced-colors: active) {
56
+ .crewlet-cursor-flag {
57
+ border: 1px solid CanvasText;
58
+ background: Canvas;
59
+ color: CanvasText;
60
+ }
61
+ }
@@ -1,16 +1,16 @@
1
- export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-RF5O4FYL.js';
1
+ export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-76FXDZAZ.js';
2
2
  import '../chunk-NS7BVLL3.js';
3
- import '../chunk-EUCC37WY.js';
3
+ import '../chunk-2TZATTIU.js';
4
4
  import '../chunk-75CLJNDQ.js';
5
+ import '../chunk-4GB57WIT.js';
5
6
  import '../chunk-STJ7QBC3.js';
6
7
  import '../chunk-DTIW4CHZ.js';
7
- import '../chunk-DEEVA6TV.js';
8
- import '../chunk-4GB57WIT.js';
9
8
  import '../chunk-OG6CL3EB.js';
10
9
  import '../chunk-4FQT6ZAY.js';
11
- import '../chunk-AV2DXAEL.js';
12
- import '../chunk-PQADV6P6.js';
13
10
  import '../chunk-HMPFGIWM.js';
14
11
  import '../chunk-R25RGPUB.js';
12
+ import '../chunk-EUCC37WY.js';
13
+ import '../chunk-AV2DXAEL.js';
14
+ import '../chunk-PQADV6P6.js';
15
15
  import '../chunk-BZFWDIV6.js';
16
16
  import '../chunk-ODEQTPFM.js';
@@ -1,26 +1,26 @@
1
- export { DATA_VIEW_TOOLBAR_LABELS, DataView, DataViewToolbar, FILTER_AXIS_LABELS, FilterAxisBar, FilterAxisChip, applyColumnFilters, applyFilters, blankFilterValue, defaultOperator, filterDefsFromColumns, filterHasValue, filterPredicate, formatFilterValue, operatorOf, tableColumns } from '../chunk-XU4H6JQB.js';
2
- import '../chunk-3CZ7XAVY.js';
1
+ export { DATA_VIEW_TOOLBAR_LABELS, DataView, DataViewToolbar, FILTER_AXIS_LABELS, FilterAxisBar, FilterAxisChip, applyColumnFilters, applyFilters, blankFilterValue, defaultOperator, filterDefsFromColumns, filterHasValue, filterPredicate, formatFilterValue, operatorOf, tableColumns } from '../chunk-KVT3TJVG.js';
3
2
  import '../chunk-HOXGBLEY.js';
4
3
  import '../chunk-PGRPNDWM.js';
5
- import '../chunk-RF5O4FYL.js';
4
+ import '../chunk-76FXDZAZ.js';
6
5
  import '../chunk-NS7BVLL3.js';
7
- import '../chunk-EUCC37WY.js';
8
- import '../chunk-2UU5IGZI.js';
9
- import '../chunk-75CLJNDQ.js';
10
- import '../chunk-STJ7QBC3.js';
11
- import '../chunk-DTIW4CHZ.js';
12
- import '../chunk-DEEVA6TV.js';
6
+ import '../chunk-5NVKTB6E.js';
7
+ import '../chunk-2TZATTIU.js';
13
8
  import '../chunk-F73MC7EZ.js';
14
9
  import '../chunk-SMBKXWML.js';
10
+ import '../chunk-75CLJNDQ.js';
15
11
  import '../chunk-4GB57WIT.js';
12
+ import '../chunk-STJ7QBC3.js';
13
+ import '../chunk-DTIW4CHZ.js';
14
+ import '../chunk-BWRGFKJP.js';
16
15
  import '../chunk-GXQ3B46I.js';
17
16
  import '../chunk-OG6CL3EB.js';
18
17
  import '../chunk-4FQT6ZAY.js';
19
- import '../chunk-AV2DXAEL.js';
20
- import '../chunk-PQADV6P6.js';
21
- import '../chunk-BWRGFKJP.js';
22
18
  import '../chunk-HMPFGIWM.js';
23
19
  import '../chunk-R25RGPUB.js';
20
+ import '../chunk-3CZ7XAVY.js';
21
+ import '../chunk-EUCC37WY.js';
22
+ import '../chunk-AV2DXAEL.js';
23
+ import '../chunk-PQADV6P6.js';
24
24
  import '../chunk-BHHIIK3M.js';
25
25
  import '../chunk-BZFWDIV6.js';
26
26
  import '../chunk-ODEQTPFM.js';
@@ -1,8 +1,8 @@
1
- export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from '../chunk-2UU5IGZI.js';
1
+ export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from '../chunk-5NVKTB6E.js';
2
+ import '../chunk-BWRGFKJP.js';
2
3
  import '../chunk-GXQ3B46I.js';
3
4
  import '../chunk-OG6CL3EB.js';
4
5
  import '../chunk-4FQT6ZAY.js';
5
- import '../chunk-BWRGFKJP.js';
6
6
  import '../chunk-HMPFGIWM.js';
7
7
  import '../chunk-R25RGPUB.js';
8
8
  import '../chunk-BZFWDIV6.js';
@@ -0,0 +1,35 @@
1
+ /** Following somebody, or the moment they left and following stopped. */
2
+ export type FollowBannerState = 'following' | 'left';
3
+ export interface FollowBannerLabels {
4
+ following: (name: string) => string;
5
+ left: (name: string) => string;
6
+ stop: string;
7
+ dismiss: string;
8
+ }
9
+ export interface FollowBannerProps {
10
+ /** The followed collaborator's full name in the sentence: "Maya Ortiz", or the first name once they left. */
11
+ name: string;
12
+ state?: FollowBannerState | undefined;
13
+ /** Stop following: the Stop control, or Escape anywhere in the document while following. */
14
+ onStop: () => void;
15
+ /** Takes the banner down once it has said the followed person left. */
16
+ onDismiss?: (() => void) | undefined;
17
+ className?: string | undefined;
18
+ labels?: Partial<FollowBannerLabels> | undefined;
19
+ }
20
+ /**
21
+ * The strip across the top of an artifact while its reader follows somebody:
22
+ * the view moves with theirs (tab, version, scroll, active cell) until the
23
+ * reader takes it back.
24
+ *
25
+ * ESCAPE STOPS IT FROM ANYWHERE, because following moves the reader's view
26
+ * under them and the way out has to be one key wherever focus happens to be.
27
+ * A key a composition is using, and one a nearer surface (an open menu, a
28
+ * dialog) already handled, are left alone. Scrolling or any own move of the
29
+ * view stops it too; that is the host's to call `onStop` for, since only the
30
+ * host knows which scroll is the reader's and which is the follow.
31
+ *
32
+ * ANNOUNCED POLITELY when it appears and when its sentence changes, so a
33
+ * screen reader user is told they are following and told when it stopped.
34
+ */
35
+ export declare function FollowBanner({ name, state, onStop, onDismiss, className, labels }: FollowBannerProps): import("react").JSX.Element;