@crewlethq/ui 0.29.0 → 0.31.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 (51) hide show
  1. package/README.md +28 -3
  2. package/dist/ArtifactBar/ArtifactBar.d.ts +13 -1
  3. package/dist/ArtifactBar/index.js +1 -1
  4. package/dist/{ArtifactBar-IBWB5POL.css → ArtifactBar-MLMJHWY6.css} +7 -0
  5. package/dist/ArtifactCover/index.js +2 -2
  6. package/dist/CommentThread/index.js +2 -2
  7. package/dist/DataView/index.js +2 -2
  8. package/dist/Document/Document.d.ts +8 -1
  9. package/dist/Document/index.js +1 -1
  10. package/dist/{Document-PQGXJHB7.css → Document-G3YTZIUL.css} +71 -0
  11. package/dist/EditingStatus/EditingStatus.d.ts +25 -0
  12. package/dist/EditingStatus/index.d.ts +3 -0
  13. package/dist/EditingStatus/index.js +2 -0
  14. package/dist/EditingStatus-NFADEPSX.css +53 -0
  15. package/dist/Editor-YZ7KG2RD.js +2099 -0
  16. package/dist/Markdown/grammar.d.ts +170 -0
  17. package/dist/Markdown/index.d.ts +2 -0
  18. package/dist/Markdown/index.js +1 -0
  19. package/dist/RichEditor/Editor.d.ts +17 -0
  20. package/dist/RichEditor/RichEditor.d.ts +26 -0
  21. package/dist/RichEditor/codec.d.ts +78 -0
  22. package/dist/RichEditor/commands.d.ts +89 -0
  23. package/dist/RichEditor/index.d.ts +4 -0
  24. package/dist/RichEditor/index.js +8 -0
  25. package/dist/RichEditor/keys.d.ts +16 -0
  26. package/dist/RichEditor/nodeviews.d.ts +60 -0
  27. package/dist/RichEditor/paste.d.ts +47 -0
  28. package/dist/RichEditor/plugins.d.ts +49 -0
  29. package/dist/RichEditor/roundtrip.d.ts +14 -0
  30. package/dist/RichEditor/schema.d.ts +23 -0
  31. package/dist/RichEditor/types.d.ts +140 -0
  32. package/dist/RichEditor-NPD2KAPS.css +419 -0
  33. package/dist/RichEditorMarkdown/index.d.ts +1 -0
  34. package/dist/RichEditorMarkdown/index.js +3 -0
  35. package/dist/chunk-3DPIU2Q7.js +28 -0
  36. package/dist/{chunk-XALUCIG5.js → chunk-6AH2XJ3Q.js} +1 -1
  37. package/dist/chunk-A4E5YLXO.js +85 -0
  38. package/dist/{chunk-FKULOLKG.js → chunk-GR55WT4R.js} +1 -1
  39. package/dist/chunk-IDBHX5SR.js +12 -0
  40. package/dist/{chunk-WI6K5M5X.js → chunk-M3LUNN7F.js} +1 -1
  41. package/dist/{chunk-QMBP23BL.js → chunk-P4BOXB6E.js} +17 -1
  42. package/dist/chunk-SKOYC2CF.js +288 -0
  43. package/dist/chunk-VOX3YRFO.js +76 -0
  44. package/dist/chunk-YFW4MTK4.js +749 -0
  45. package/dist/generated/index.d.ts +4 -0
  46. package/dist/generated/index.js +50 -44
  47. package/dist/index.js +50 -44
  48. package/dist/styles.css +558 -2
  49. package/package.json +13 -3
  50. package/dist/{chunk-IFNQKWUO.js → chunk-OC46246T.js} +0 -0
  51. package/dist/{chunk-RODMM35O.js → chunk-UVJ5FF5V.js} +1 -1
package/README.md CHANGED
@@ -41,11 +41,11 @@ import { Button } from '@crewlethq/ui/Button'; // 8 KB of CSS, not 182 KB
41
41
  | Area | Components |
42
42
  | ---- | ---------- |
43
43
  | Actions | `Button` and `ButtonLink` (variants `primary`, `secondary`, `outline`, `ghost`, `accent`, `danger`; sizes `small`, `medium`, `large`; shapes `square`, `pill`), `IconButton`, `Menu`, `Link`, `Copyable`, `CopyButton`, `DownloadButton`, `Kbd` |
44
- | Content and text | `Text` (the eight registers and `inherit`), `Prose`, `Document` and `DocumentTitle`, `Highlight`, `InlineCode`, `List` and `ListItem`, `DescriptionList`, `Timeline`, `RelativeTime`, `Note`, `Divider` |
45
- | Forms | `Input`, `Textarea`, `Label`, `FormField`, `FormRow`, `Checkbox`, `CheckboxGroup`, `ConfirmField`, `Select`, `Tag`, `TagsInput`, `DateTimePicker`, `TimeWindowPicker`, `ImageUpload`, `CharacterPicker`, `HuePicker`, `AvatarPicker`, `FactList`, `ChoiceList`, `Composer`, `MarkdownEditor` |
44
+ | Content and text | `Text` (the eight registers and `inherit`), `Prose`, `Document` and `DocumentTitle`, 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
+ | 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
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` |
47
47
  | List screens | `DataView`, and its parts on their own: `DataViewToolbar`, `FilterAxisBar`, `FilterAxisChip`, plus the filter model (`filterDefsFromColumns`, `applyColumnFilters`, `filterPredicate`, `blankFilterValue`) |
48
- | Feedback and overlays | `Callout`, `ConflictNote`, `Toaster`, `Modal` (with `variant="sheet"`), `ConfirmModal`, `CommandPalette`, `Tooltip`, `Popover`, `Announcer` |
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` |
@@ -204,6 +204,31 @@ 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.31.0
208
+
209
+ **`ArtifactBar` carries an editing state**: a `status` slot said before the kind's tools (an `EditingStatus` while a doc is edited), never folded away, and a tool's `emphasis: 'primary'`, drawn as the primary button with its word kept at every width, for the one action the state turns on, such as Save.
210
+
211
+ ## Changes in 0.30.0
212
+
213
+ **`RichEditor` edits Markdown in place, as the document it reads as.** The editable element is set by `Document`, so a page looks the same while it is edited as when it is read, and there is no separate preview. It is built on ProseMirror and loaded lazily: the component is a shell that fetches the editor's code with `import()` the first time one is drawn, so a screen that only reads pays for none of it, and `preloadRichEditor()` starts that fetch from a press that is about to open an editor.
214
+
215
+ - **Blocks**: headings, bulleted, numbered and task lists, quotes, callouts, code blocks with their language, tables, links, pictures and dividers.
216
+ - **A slash menu**: type `/` at the start of a line or after a space, filter by name, move with the arrows and choose with Enter. An application adds entries of its own (`commands`), each opening a panel it draws ("Link to a page").
217
+ - **A selection toolbar**: heading levels, bold, italic, strikethrough, inline code and a link, reached from the keyboard with Alt+F10.
218
+ - **Markdown typed as Markdown** becomes the block or the format it spells (`# `, `- `, `1. `, `[ ] `, `> `, three backticks and a language, `---`, `**bold**`, `*em*`, `~~struck~~`, `` `code` ``, `[text](address)`), and Backspace right after gives back what was typed. The shortcuts are the ones every editor shares, and Command or Control with Enter is the caller's `onSubmit`.
219
+ - **A paste of Markdown or HTML converts cleanly, under Trusted Types.** ProseMirror reads pasted HTML by assigning it to `innerHTML` behind a pass-through policy of its own, which a page enforcing `trusted-types 'none'` refuses and a page allowing it should not want. The editor takes paste and drop itself and reads HTML with a tokenizer that builds elements one by one in an inert document, keeping only the elements and attributes it has a meaning for, and copy writes Markdown as the plain text.
220
+ - **A load and a save with no edit change no byte.** Every top-level block remembers the lines it was read from and is written back as them until it is edited; a changed block is written in the spelling it was read with (its bullet, its fence, `*` or `_`), checked by reading it back. `@crewlethq/ui/RichEditorMarkdown` exports the round trip (`roundTripMarkdown`, `canonicalMarkdown`) for an application to hold its own bodies to.
221
+
222
+ **The Markdown grammar is part of the package** (`parseMarkdown`, `parseMarkdownSpans`, `markdownInline`, `safeHref`, `markdownHeadingOf`, `markdownFenceOf`, `markdownClosesFence`), so an application's renderer and `RichEditor` read a body by one grammar and cannot disagree about it. It reads what the Crewlet engine's renderer read, plus three things that renderer did not: backslash escapes (`\*` is an asterisk), an escaped pipe inside a table cell, and a link label holding an escaped bracket. It also reads **callouts** in GitHub's alert syntax, `> [!NOTE]`, `> [!TIP]`, `> [!IMPORTANT]`, `> [!WARNING]` and `> [!CAUTION]`.
223
+
224
+ **`Document` sets a callout and a cell aligned by `data-align`.** A renderer emits an element with `data-callout="<tone>"`, the tone's name in an element with `data-callout-label` and the blocks in one with `data-callout-body`; each tone is drawn from the same three steps `Callout` paints with.
225
+
226
+ **`EditingStatus` says a page is being edited**: "Editing", and an accent dot with "Unsaved changes" once anything differs from what was opened (or "Saving" while a save is in flight), announced politely. It sits in a page bar beside the caller's own Cancel and Save, and on a phone the words fold away behind the dot.
227
+
228
+ **`@crewlethq/icons` carries the editor's glyphs**: `heading-1`, `type`, `strikethrough`, `text-quote`, `square-code`, `unlink`, and `text-align-start`, `text-align-center` and `text-align-end`.
229
+
230
+ What to change: nothing. An application that renders Markdown itself may read it through `parseMarkdown` and `markdownInline` instead, and draws a callout by the shape above.
231
+
207
232
  ## Changes in 0.29.0
208
233
 
209
234
  0.29.0 adds the chrome an open artifact sits in: one slim bar over the artifact, and one panel at its side, so a host can give the artifact the screen and open everything else on demand.
@@ -33,6 +33,12 @@ export interface ArtifactBarTool {
33
33
  * or a kind's primary action such as a doc's Edit.
34
34
  */
35
35
  labelled?: boolean | undefined;
36
+ /**
37
+ * `primary`: the one action a kind's state turns on, such as Save while a
38
+ * doc is edited. Drawn as the primary button, labelled, and its word kept at
39
+ * every width, because a glyph alone does not say what a press commits.
40
+ */
41
+ emphasis?: 'primary' | undefined;
36
42
  }
37
43
  /** The ways a kind draws itself, as one choice: a deck's Edit, Grid and Present. */
38
44
  export interface ArtifactBarModes {
@@ -86,6 +92,12 @@ export interface ArtifactBarProps {
86
92
  modes?: ArtifactBarModes | undefined;
87
93
  /** Who else is here, such as a presence stack. Folded away first on a narrower bar. */
88
94
  presence?: ReactNode;
95
+ /**
96
+ * What the kind is doing now, said before its tools: an `EditingStatus`
97
+ * while a doc is edited. Never folded away; a status that has words to
98
+ * spare folds them itself.
99
+ */
100
+ status?: ReactNode;
89
101
  /** The kind's own controls, before the panels: a doc's Edit. */
90
102
  kindTools?: readonly ArtifactBarTool[] | undefined;
91
103
  /** The panels and actions every artifact has: details, history, people, share. */
@@ -121,7 +133,7 @@ export interface ArtifactBarProps {
121
133
  * the stylesheet shows one, so no control is ever in two places a reader can
122
134
  * see at once and nothing is measured in script.
123
135
  */
124
- export declare function ArtifactBar({ title, kind, icon, kindLabel, back, start, onRename, renaming, onRenamingChange, version, modes, presence, kindTools, tools, menu, as, headingLevel, pending, labels, className, }: ArtifactBarProps): import("react").JSX.Element;
136
+ export declare function ArtifactBar({ title, kind, icon, kindLabel, back, start, onRename, renaming, onRenamingChange, version, modes, presence, status, kindTools, tools, menu, as, headingLevel, pending, labels, className, }: ArtifactBarProps): import("react").JSX.Element;
125
137
  export interface ArtifactVersionChipProps {
126
138
  /** The version on show. */
127
139
  version: number;
@@ -1,4 +1,4 @@
1
- export { ARTIFACT_BAR_LABELS, ArtifactBar, ArtifactVersionChip } from '../chunk-QMBP23BL.js';
1
+ export { ARTIFACT_BAR_LABELS, ArtifactBar, ArtifactVersionChip } from '../chunk-P4BOXB6E.js';
2
2
  import '../chunk-FQCLKD7U.js';
3
3
  import '../chunk-SMBKXWML.js';
4
4
  import '../chunk-QWOPX2MN.js';
@@ -192,6 +192,13 @@
192
192
  margin-inline-start: var(--spacing-1);
193
193
  }
194
194
 
195
+ .crewlet-artifact-bar__status {
196
+ display: inline-flex;
197
+ align-items: center;
198
+ min-width: 0;
199
+ margin-inline-end: var(--spacing-2);
200
+ }
201
+
195
202
  .crewlet-artifact-bar__presence {
196
203
  display: inline-flex;
197
204
  align-items: center;
@@ -1,5 +1,5 @@
1
- export { DashboardCover, DocCover, SHEET_COVER_COLUMNS, SHEET_COVER_ROWS, SheetCover } from '../chunk-XALUCIG5.js';
2
- import '../chunk-WI6K5M5X.js';
1
+ export { DashboardCover, DocCover, SHEET_COVER_COLUMNS, SHEET_COVER_ROWS, SheetCover } from '../chunk-6AH2XJ3Q.js';
2
+ import '../chunk-M3LUNN7F.js';
3
3
  import '../chunk-GOSQXEZU.js';
4
4
  import '../chunk-4KP4RC3O.js';
5
5
  import '../chunk-3CZ7XAVY.js';
@@ -1,8 +1,8 @@
1
- export { COMMENT_THREAD_LABELS, CommentThread } from '../chunk-FKULOLKG.js';
1
+ export { COMMENT_THREAD_LABELS, CommentThread } from '../chunk-GR55WT4R.js';
2
2
  import '../chunk-7DZDSSJS.js';
3
3
  import '../chunk-6QFAK2WV.js';
4
4
  import '../chunk-SMBKXWML.js';
5
- import '../chunk-WI6K5M5X.js';
5
+ import '../chunk-M3LUNN7F.js';
6
6
  import '../chunk-4KP4RC3O.js';
7
7
  import '../chunk-3CZ7XAVY.js';
8
8
  import '../chunk-EUCC37WY.js';
@@ -1,8 +1,8 @@
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-RODMM35O.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-UVJ5FF5V.js';
2
2
  import '../chunk-HOXGBLEY.js';
3
3
  import '../chunk-PGRPNDWM.js';
4
- import '../chunk-Y5NQ2LMS.js';
5
4
  import '../chunk-EBJREOKS.js';
5
+ import '../chunk-Y5NQ2LMS.js';
6
6
  import '../chunk-STJ7QBC3.js';
7
7
  import '../chunk-DTIW4CHZ.js';
8
8
  import '../chunk-I3KKZ2O3.js';
@@ -21,7 +21,7 @@ export interface DocumentProps extends HTMLAttributes<HTMLElement> {
21
21
  }
22
22
  /**
23
23
  * Rendered markdown, set as a document: headings, paragraphs, lists and task
24
- * lists, quotes, code, tables, rules, links and images.
24
+ * lists, quotes, callouts, code, tables, rules, links and images.
25
25
  *
26
26
  * A STYLESHEET OVER ELEMENTS, NOT A RENDERER. What a body may contain (which
27
27
  * link schemes are safe, whether raw HTML is text) is a decision about the
@@ -37,6 +37,13 @@ export interface DocumentProps extends HTMLAttributes<HTMLElement> {
37
37
  * gives that element `tabIndex={0}`, a `region` role and a name, because a
38
38
  * scroller no keyboard can reach is a table no keyboard can read to its end.
39
39
  *
40
+ * A CALLOUT is recognised the same way: an element with `data-callout` set
41
+ * to its tone (`note`, `tip`, `important`, `warning`, `caution`), the tone's
42
+ * name in an element with `data-callout-label` and its blocks in one with
43
+ * `data-callout-body`. A table cell aligned by `data-align` is set as one
44
+ * aligned by a style, so an editor that may write no style attribute sets a
45
+ * column exactly as the reader's renderer does.
46
+ *
40
47
  * THE TITLE IS NOT PART OF IT. A page's title is its address and its `h1`, set
41
48
  * above the body by `DocumentTitle`, so a renderer draws the body's own
42
49
  * headings from `h2` down and the outline of the page starts there.
@@ -1,2 +1,2 @@
1
- export { Document, DocumentTitle } from '../chunk-WI6K5M5X.js';
1
+ export { Document, DocumentTitle } from '../chunk-M3LUNN7F.js';
2
2
  import '../chunk-ODEQTPFM.js';
@@ -286,3 +286,74 @@
286
286
  color: var(--color-text-primary);
287
287
  overflow-wrap: anywhere;
288
288
  }
289
+
290
+ /*
291
+ * A TABLE CELL'S ALIGNMENT, read off `data-align` as well as off a style: an
292
+ * editor that may not write a style attribute under a strict policy marks a
293
+ * column this way, and the cell is set as the reader's is.
294
+ */
295
+ .crewlet-document :where(th, td)[data-align='center'] {
296
+ text-align: center;
297
+ }
298
+
299
+ .crewlet-document :where(th, td)[data-align='right'] {
300
+ text-align: end;
301
+ }
302
+
303
+ /*
304
+ * A CALLOUT (`> [!NOTE]` and its four siblings): a tinted block with its tone
305
+ * named on a line of its own, read by its shape as everything here is. A
306
+ * renderer emits an element with `data-callout="<tone>"` and `role="note"`,
307
+ * the tone's name in an element with `data-callout-label`, and the blocks in
308
+ * one with `data-callout-body`. The fill, the ink and the line are each tone's
309
+ * declared steps, the same three `Callout` paints with.
310
+ */
311
+ .crewlet-document [data-callout] {
312
+ --crewlet-document-callout-fill: var(--color-feedback-info-soft);
313
+ --crewlet-document-callout-ink: var(--color-feedback-info-ink);
314
+ --crewlet-document-callout-line: var(--color-feedback-info-line);
315
+ padding: var(--spacing-3) var(--spacing-4);
316
+ border-inline-start: 3px solid var(--crewlet-document-callout-line);
317
+ border-radius: var(--radius-sm);
318
+ background: var(--crewlet-document-callout-fill);
319
+ }
320
+
321
+ .crewlet-document [data-callout='tip'] {
322
+ --crewlet-document-callout-fill: var(--color-feedback-success-soft);
323
+ --crewlet-document-callout-ink: var(--color-feedback-success-ink);
324
+ --crewlet-document-callout-line: var(--color-feedback-success-line);
325
+ }
326
+
327
+ .crewlet-document [data-callout='important'] {
328
+ --crewlet-document-callout-fill: var(--color-brand-accent-soft);
329
+ --crewlet-document-callout-ink: var(--color-brand-accent-ink);
330
+ --crewlet-document-callout-line: var(--color-brand-accent);
331
+ }
332
+
333
+ .crewlet-document [data-callout='warning'] {
334
+ --crewlet-document-callout-fill: var(--color-feedback-warning-soft);
335
+ --crewlet-document-callout-ink: var(--color-feedback-warning-ink);
336
+ --crewlet-document-callout-line: var(--color-feedback-warning-line);
337
+ }
338
+
339
+ .crewlet-document [data-callout='caution'] {
340
+ --crewlet-document-callout-fill: var(--color-feedback-danger-soft);
341
+ --crewlet-document-callout-ink: var(--color-feedback-danger-ink);
342
+ --crewlet-document-callout-line: var(--color-feedback-danger-line);
343
+ }
344
+
345
+ .crewlet-document [data-callout-label] {
346
+ margin: 0 0 var(--spacing-1);
347
+ color: var(--crewlet-document-callout-ink);
348
+ font-size: var(--font-size-xs);
349
+ font-weight: var(--font-weight-semibold);
350
+ line-height: var(--font-line-height-snug);
351
+ }
352
+
353
+ .crewlet-document [data-callout-body] {
354
+ color: var(--color-text-primary);
355
+ }
356
+
357
+ .crewlet-document [data-callout-body] > * + * {
358
+ margin-block-start: var(--crewlet-document-gap);
359
+ }
@@ -0,0 +1,25 @@
1
+ /** Every string the status draws. */
2
+ export interface EditingStatusLabels {
3
+ editing: string;
4
+ unsaved: string;
5
+ saving: string;
6
+ }
7
+ export interface EditingStatusProps {
8
+ /** Whether anything differs from what was opened. */
9
+ dirty: boolean;
10
+ /** Whether a save is in flight. */
11
+ saving?: boolean | undefined;
12
+ labels?: Partial<EditingStatusLabels> | undefined;
13
+ className?: string | undefined;
14
+ }
15
+ /**
16
+ * The quiet state a page is in while somebody edits it: "Editing", and a dot
17
+ * with "Unsaved changes" once anything differs from what was opened.
18
+ *
19
+ * It sits in the bar beside Save and Cancel, which are the caller's: what a
20
+ * save sends and what Cancel discards are decisions about the caller's own
21
+ * record. A STATUS, announced politely, so a screen reader hears the change
22
+ * from saved to unsaved without being interrupted. On a narrow bar the words
23
+ * fold away and the dot stays, named by the same words.
24
+ */
25
+ export declare function EditingStatus({ dirty, saving, labels, className }: EditingStatusProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import './EditingStatus.css';
2
+ export { EditingStatus } from './EditingStatus.js';
3
+ export type { EditingStatusLabels, EditingStatusProps } from './EditingStatus.js';
@@ -0,0 +1,2 @@
1
+ export { EditingStatus } from '../chunk-3DPIU2Q7.js';
2
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,53 @@
1
+ /*
2
+ * The editing status (EditingStatus.tsx): a word and a dot, in the bar's own
3
+ * small step, quiet until something is unsaved.
4
+ */
5
+
6
+ .crewlet-editing-status {
7
+ display: inline-flex;
8
+ align-items: center;
9
+ gap: var(--spacing-2);
10
+ min-width: 0;
11
+ color: var(--color-text-secondary);
12
+ font-family: var(--font-family-sans);
13
+ font-size: var(--font-size-compact);
14
+ white-space: nowrap;
15
+ }
16
+
17
+ .crewlet-editing-status__dot {
18
+ flex: none;
19
+ width: var(--spacing-2);
20
+ height: var(--spacing-2);
21
+ border-radius: var(--radius-circle);
22
+ background: var(--color-text-tertiary);
23
+ }
24
+
25
+ .crewlet-editing-status--dirty .crewlet-editing-status__dot {
26
+ background: var(--color-brand-accent);
27
+ }
28
+
29
+ .crewlet-editing-status__label {
30
+ color: var(--color-text-primary);
31
+ font-weight: var(--font-weight-medium);
32
+ }
33
+
34
+ .crewlet-editing-status__state {
35
+ overflow: hidden;
36
+ color: var(--color-text-tertiary);
37
+ text-overflow: ellipsis;
38
+ }
39
+
40
+ .crewlet-editing-status__state::before {
41
+ content: '\00b7';
42
+ margin-right: var(--spacing-2);
43
+ }
44
+
45
+ @media (width < 480px) {
46
+ .crewlet-editing-status__state {
47
+ position: absolute;
48
+ width: 1px;
49
+ height: 1px;
50
+ overflow: hidden;
51
+ clip-path: inset(50%);
52
+ }
53
+ }