@crewlethq/ui 0.28.0 → 0.30.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 (95) hide show
  1. package/README.md +45 -4
  2. package/dist/AccessDeniedCard/index.js +3 -3
  3. package/dist/Accordion/index.js +3 -3
  4. package/dist/AppShell/index.js +1 -1
  5. package/dist/{AppShell-APHZKJYH.css → AppShell-GCM4TDVY.css} +4 -1
  6. package/dist/ArtifactBar/ArtifactBar.d.ts +143 -0
  7. package/dist/ArtifactBar/index.d.ts +3 -0
  8. package/dist/ArtifactBar/index.js +25 -0
  9. package/dist/ArtifactBar-IBWB5POL.css +358 -0
  10. package/dist/ArtifactCard/index.js +3 -3
  11. package/dist/ArtifactCover/index.js +5 -5
  12. package/dist/ArtifactIcon/index.js +4 -4
  13. package/dist/ArtifactPanel/ArtifactPanel.d.ts +81 -0
  14. package/dist/ArtifactPanel/index.d.ts +3 -0
  15. package/dist/ArtifactPanel/index.js +5 -0
  16. package/dist/ArtifactPanel-YFXT5O77.css +132 -0
  17. package/dist/AuthLayout/index.js +3 -3
  18. package/dist/AvatarPicker/index.js +4 -4
  19. package/dist/Card/index.js +2 -2
  20. package/dist/ChangeMark/index.js +1 -1
  21. package/dist/CommandPalette/index.js +3 -3
  22. package/dist/CommentThread/index.js +5 -5
  23. package/dist/Composer/index.js +2 -2
  24. package/dist/DataView/index.js +4 -4
  25. package/dist/Disclosure/index.js +3 -3
  26. package/dist/Document/Document.d.ts +8 -1
  27. package/dist/Document/index.js +1 -1
  28. package/dist/{Document-PQGXJHB7.css → Document-G3YTZIUL.css} +71 -0
  29. package/dist/EditingStatus/EditingStatus.d.ts +25 -0
  30. package/dist/EditingStatus/index.d.ts +3 -0
  31. package/dist/EditingStatus/index.js +2 -0
  32. package/dist/EditingStatus-NFADEPSX.css +53 -0
  33. package/dist/Editor-YZ7KG2RD.js +2099 -0
  34. package/dist/HuePicker/index.js +2 -2
  35. package/dist/ListInput/index.js +2 -2
  36. package/dist/Markdown/grammar.d.ts +170 -0
  37. package/dist/Markdown/index.d.ts +2 -0
  38. package/dist/Markdown/index.js +1 -0
  39. package/dist/MarkdownEditor/index.js +1 -1
  40. package/dist/PeopleRail/PeopleRail.d.ts +8 -1
  41. package/dist/PeopleRail/index.js +1 -1
  42. package/dist/{PeopleRail-R64WVOSH.css → PeopleRail-SZGHZXVT.css} +8 -0
  43. package/dist/RichEditor/Editor.d.ts +17 -0
  44. package/dist/RichEditor/RichEditor.d.ts +26 -0
  45. package/dist/RichEditor/codec.d.ts +78 -0
  46. package/dist/RichEditor/commands.d.ts +89 -0
  47. package/dist/RichEditor/index.d.ts +4 -0
  48. package/dist/RichEditor/index.js +8 -0
  49. package/dist/RichEditor/keys.d.ts +16 -0
  50. package/dist/RichEditor/nodeviews.d.ts +60 -0
  51. package/dist/RichEditor/paste.d.ts +47 -0
  52. package/dist/RichEditor/plugins.d.ts +49 -0
  53. package/dist/RichEditor/roundtrip.d.ts +14 -0
  54. package/dist/RichEditor/schema.d.ts +23 -0
  55. package/dist/RichEditor/types.d.ts +140 -0
  56. package/dist/RichEditor-NPD2KAPS.css +419 -0
  57. package/dist/RichEditorMarkdown/index.d.ts +1 -0
  58. package/dist/RichEditorMarkdown/index.js +3 -0
  59. package/dist/SheetGrid/index.js +1 -1
  60. package/dist/ThemeSwitcher/index.js +1 -1
  61. package/dist/VersionCompare/index.js +2 -2
  62. package/dist/chunk-3DPIU2Q7.js +28 -0
  63. package/dist/{chunk-V2Z24W2Z.js → chunk-4JUKWWUD.js} +1 -1
  64. package/dist/{chunk-MQEEQVG6.js → chunk-6AH2XJ3Q.js} +2 -2
  65. package/dist/chunk-A4E5YLXO.js +85 -0
  66. package/dist/{chunk-WENCSQ47.js → chunk-EBNI36UQ.js} +1 -1
  67. package/dist/{chunk-6J35F334.js → chunk-GOSQXEZU.js} +1 -1
  68. package/dist/{chunk-M2VJGNCD.js → chunk-GR55WT4R.js} +3 -3
  69. package/dist/chunk-I3BSQUKN.js +121 -0
  70. package/dist/chunk-IDBHX5SR.js +12 -0
  71. package/dist/{chunk-WI6K5M5X.js → chunk-M3LUNN7F.js} +1 -1
  72. package/dist/{chunk-S4RCG44T.js → chunk-MICH6QSJ.js} +1 -1
  73. package/dist/chunk-QMBP23BL.js +347 -0
  74. package/dist/{chunk-G2AVKPSL.js → chunk-RIAZM6L3.js} +1 -1
  75. package/dist/chunk-SKOYC2CF.js +288 -0
  76. package/dist/{chunk-PRNX5AFE.js → chunk-TGYDROIB.js} +1 -1
  77. package/dist/{chunk-G3EEUNZQ.js → chunk-UB7TJEKZ.js} +1 -1
  78. package/dist/chunk-UQHKFF2N.js +106 -0
  79. package/dist/{chunk-WHZFDS62.js → chunk-VDPJGP4Q.js} +1 -1
  80. package/dist/chunk-VOX3YRFO.js +76 -0
  81. package/dist/chunk-YFW4MTK4.js +749 -0
  82. package/dist/generated/index.d.ts +6 -0
  83. package/dist/generated/index.js +83 -75
  84. package/dist/index.js +83 -75
  85. package/dist/styles.css +8849 -7793
  86. package/package.json +13 -3
  87. package/dist/chunk-FVLCTCMV.js +0 -96
  88. package/dist/{chunk-RIEDQSA4.js → chunk-7DZDSSJS.js} +1 -1
  89. package/dist/{chunk-YZCJ63JF.js → chunk-ACA27MZH.js} +1 -1
  90. package/dist/{chunk-ENJUPIND.js → chunk-FZVJDJFN.js} +1 -1
  91. package/dist/{chunk-SGIQCI6Y.js → chunk-LIXSV5YI.js} +1 -1
  92. package/dist/{chunk-NWW4IQJU.js → chunk-OC46246T.js} +0 -0
  93. package/dist/{chunk-VOMYRJV5.js → chunk-RODMM35O.js} +2 -2
  94. package/dist/{chunk-HCKJGBQH.js → chunk-VVRL27HM.js} +1 -1
  95. package/dist/{chunk-D5JZN3ML.js → chunk-Z6VW6CXX.js} +1 -1
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The editor's Markdown round trip, as plain functions: what a load and a
3
+ * save with no edit write, and the spelling a changed block is written in.
4
+ * An application holds its own bodies to them (a Knowledge page's fixtures, a
5
+ * doc's), so a body the editor would rewrite is found by a test rather than
6
+ * by somebody's diff.
7
+ *
8
+ * Importing these brings the document model with them; the editor's shell
9
+ * does not, so a screen that only draws `RichEditor` pays for neither.
10
+ */
11
+ /** The body a load and a save with no edit write: the body itself, byte for byte. */
12
+ export declare function roundTripMarkdown(markdown: string): string;
13
+ /** The body as the editor writes it when every block has changed. */
14
+ export declare function canonicalMarkdown(markdown: string): string;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The document model `RichEditor` edits: exactly what the Markdown grammar
3
+ * (`../Markdown`) reads, and nothing it cannot write back.
4
+ *
5
+ * EVERY NODE DRAWS WHAT THE READER SEES. The editor's DOM is the element shape
6
+ * an application's renderer emits for the same block (an `h2` for a `#`
7
+ * heading, a list item whose first child is a checkbox, a table inside a
8
+ * scrolling wrapper), inside `Document`, so the page looks the same while it
9
+ * is edited as when it is read, and one stylesheet sets both.
10
+ *
11
+ * A NODE CARRIES THE SPELLING IT WAS READ WITH (a bullet's character, a
12
+ * fence's marker, emphasis by `*` or `_`), so a block somebody edits is
13
+ * written back in the hand it was written in rather than in the editor's.
14
+ *
15
+ * NO STYLE ATTRIBUTE IS EVER WRITTEN. A strict Content-Security-Policy refuses
16
+ * `style-src 'unsafe-inline'`, which covers a `style` attribute set through
17
+ * `setAttribute`, so a cell's alignment is a data attribute the stylesheet
18
+ * reads.
19
+ */
20
+ import { Schema } from 'prosemirror-model';
21
+ /** A heading's element: a body's `#` is an `h2`, because the page's title is its `h1`. */
22
+ export declare function headingTag(level: number): string;
23
+ export declare const schema: Schema<"blockquote" | "table" | "image" | "text" | "heading" | "doc" | "paragraph" | "callout" | "code_block" | "horizontal_rule" | "bullet_list" | "ordered_list" | "list_item" | "table_row" | "table_header" | "table_cell" | "hard_break", "code" | "em" | "link" | "strong" | "strike">;
@@ -0,0 +1,140 @@
1
+ /**
2
+ * The props, the handle and the words of `RichEditor`, apart from the engine,
3
+ * so the shell that loads the engine lazily carries none of it.
4
+ */
5
+ import type { ReactNode } from 'react';
6
+ import type { DocumentSize } from '../Document/index.js';
7
+ import { type MarkdownCalloutTone } from '../Markdown/index.js';
8
+ /** What an entry of the caller's own in the slash menu may do to the document. */
9
+ export interface RichEditorPanelApi {
10
+ /** Inserts `text` linked to `href` where the slash was typed, and closes the panel. */
11
+ insertLink(text: string, href: string): void;
12
+ /** Closes the panel and gives the editor its focus back. */
13
+ close(): void;
14
+ }
15
+ /**
16
+ * An entry of the caller's own in the slash menu: "Link to a page", say. It
17
+ * opens a panel the caller draws where the slash was typed, and the panel
18
+ * inserts through the API it is handed.
19
+ */
20
+ export interface RichEditorCommand {
21
+ key: string;
22
+ label: string;
23
+ description?: string | undefined;
24
+ icon?: ReactNode;
25
+ /** Words the menu's filter also matches, beyond the label. */
26
+ keywords?: readonly string[] | undefined;
27
+ panel: (api: RichEditorPanelApi) => ReactNode;
28
+ }
29
+ export interface RichEditorHandle {
30
+ focus(): void;
31
+ }
32
+ export interface RichEditorProps {
33
+ /** The Markdown being edited. */
34
+ value: string;
35
+ /** Called with the body as Markdown after every change. */
36
+ onChange: (value: string) => void;
37
+ /** The field's accessible name: "The body of Runbook". */
38
+ label: string;
39
+ /** What an empty body says. */
40
+ placeholder?: string | undefined;
41
+ /** Draws the document read only, as during a merge the writer has to settle first. */
42
+ disabled?: boolean | undefined;
43
+ autoFocus?: boolean | undefined;
44
+ /**
45
+ * Where a picture's address is shown from, in place of the address itself,
46
+ * or null for one that is not shown (it reads as its alt text). Without it a
47
+ * picture is shown only from an address a reader may follow (`safeHref`).
48
+ * The same rule the application's renderer reads with, so a picture shows
49
+ * while it is edited exactly where it shows to a reader.
50
+ */
51
+ resolveImage?: ((src: string) => string | null) | undefined;
52
+ /**
53
+ * Changes when what `resolveImage` can answer has changed (a picture
54
+ * finished loading), so every picture is drawn again.
55
+ */
56
+ imageVersion?: unknown;
57
+ /** Command+Enter (Control+Enter elsewhere): the shortcut every composer saves on. */
58
+ onSubmit?: (() => void) | undefined;
59
+ /** Escape with no menu or panel open: the writer leaving the editor. */
60
+ onEscape?: (() => void) | undefined;
61
+ /** Entries of the caller's own, listed after the blocks in the slash menu. */
62
+ commands?: readonly RichEditorCommand[] | undefined;
63
+ /** The document's size, as `Document` takes it. */
64
+ size?: DocumentSize | undefined;
65
+ /** Drawn while the editor's code loads, in place of a skeleton: the body as it reads. */
66
+ fallback?: ReactNode;
67
+ labels?: RichEditorLabelOverrides | undefined;
68
+ className?: string | undefined;
69
+ }
70
+ export type RichEditorBlock = 'paragraph' | 'heading1' | 'heading2' | 'heading3' | 'bullet' | 'ordered' | 'task' | 'quote' | 'callout' | 'code' | 'table' | 'divider' | 'image';
71
+ /** Every string the editor draws on its own. */
72
+ export interface RichEditorLabels {
73
+ /** Read to a screen reader after the field's name: how to reach the menus. */
74
+ description: string;
75
+ /** What an empty body says, when the caller gives no placeholder. */
76
+ placeholder: string;
77
+ /** What an empty line says while the caret is on it. */
78
+ emptyLine: string;
79
+ slashMenu: string;
80
+ slashEmpty: string;
81
+ slashGroupBlocks: string;
82
+ slashGroupInsert: string;
83
+ blocks: Record<RichEditorBlock, {
84
+ label: string;
85
+ description: string;
86
+ }>;
87
+ toolbar: string;
88
+ bold: string;
89
+ italic: string;
90
+ strike: string;
91
+ code: string;
92
+ link: string;
93
+ heading: (level: number) => string;
94
+ linkPanel: string;
95
+ linkAddress: string;
96
+ linkText: string;
97
+ linkApply: string;
98
+ linkRemove: string;
99
+ linkOpen: string;
100
+ linkEdit: string;
101
+ linkInvalid: string;
102
+ linkRefused: string;
103
+ imagePanel: string;
104
+ imageAddress: string;
105
+ imageAlt: string;
106
+ imageAltHelp: string;
107
+ imageInsert: string;
108
+ imageEdit: string;
109
+ imageRemove: string;
110
+ tableBar: string;
111
+ tableRow: string;
112
+ tableColumn: string;
113
+ rowAbove: string;
114
+ rowBelow: string;
115
+ rowDelete: string;
116
+ columnLeft: string;
117
+ columnRight: string;
118
+ columnDelete: string;
119
+ alignStart: string;
120
+ alignCenter: string;
121
+ alignEnd: string;
122
+ tableDelete: string;
123
+ codeLanguage: string;
124
+ codeLanguagePlaceholder: string;
125
+ calloutTone: string;
126
+ calloutRemove: string;
127
+ tones: Record<MarkdownCalloutTone, string>;
128
+ taskDone: string;
129
+ taskNotDone: string;
130
+ loading: string;
131
+ failed: string;
132
+ failedDetail: string;
133
+ retry: string;
134
+ }
135
+ export type RichEditorLabelOverrides = Partial<Omit<RichEditorLabels, 'blocks' | 'tones'>> & {
136
+ blocks?: Partial<RichEditorLabels['blocks']> | undefined;
137
+ tones?: Partial<RichEditorLabels['tones']> | undefined;
138
+ };
139
+ export declare const RICH_EDITOR_LABELS: RichEditorLabels;
140
+ export declare function richEditorLabels(overrides?: RichEditorLabelOverrides): RichEditorLabels;
@@ -0,0 +1,419 @@
1
+ /*
2
+ * The rich editor (RichEditor.tsx).
3
+ *
4
+ * THE DOCUMENT IS SET BY `Document`'s stylesheet, not by this one: the
5
+ * editable element carries `crewlet-document`, so a heading, a list, a quote
6
+ * or a table looks the same while it is edited as when it is read. What is
7
+ * here is only what editing adds: the caret's world (ProseMirror's own
8
+ * required rules, the placeholder, a selected node), the controls a block
9
+ * draws in its slot, and the surfaces that float over the page (the slash
10
+ * menu, the selection toolbar, the link and picture panels, the table bar).
11
+ */
12
+
13
+ .crewlet-rich-editor {
14
+ position: relative;
15
+ min-width: 0;
16
+ }
17
+
18
+ /* ── the editable document ─────────────────────────────────────────────── */
19
+
20
+ /*
21
+ * ProseMirror's own required rules: whitespace is preserved as typed (the
22
+ * view maps it to positions one to one), and ligatures are off so a caret
23
+ * never lands inside one.
24
+ */
25
+ .crewlet-rich-editor__content {
26
+ position: relative;
27
+ min-height: calc(var(--spacing-10) * 3);
28
+ outline: none;
29
+ white-space: pre-wrap;
30
+ white-space: break-spaces;
31
+ word-wrap: break-word;
32
+ font-variant-ligatures: none;
33
+ font-feature-settings: 'liga' 0;
34
+ caret-color: var(--color-brand-accent);
35
+ }
36
+
37
+ .crewlet-rich-editor__content pre {
38
+ white-space: pre-wrap;
39
+ }
40
+
41
+ .crewlet-rich-editor__content li {
42
+ position: relative;
43
+ }
44
+
45
+ .crewlet-rich-editor__content [draggable][contenteditable='false'] {
46
+ user-select: text;
47
+ }
48
+
49
+ .crewlet-rich-editor__content.ProseMirror-hideselection *::selection {
50
+ background: transparent;
51
+ }
52
+
53
+ .crewlet-rich-editor__content.ProseMirror-hideselection {
54
+ caret-color: transparent;
55
+ }
56
+
57
+ .crewlet-rich-editor__content img.ProseMirror-separator {
58
+ display: inline !important;
59
+ border: none !important;
60
+ margin: 0 !important;
61
+ }
62
+
63
+ /* A selected block (a picture, a rule) is outlined, as a focused control is. */
64
+ .crewlet-rich-editor__content .ProseMirror-selectednode {
65
+ outline: 2px solid var(--color-focus);
66
+ outline-offset: 2px;
67
+ border-radius: var(--radius-xs);
68
+ }
69
+
70
+ /* The caret between two blocks nobody can type into (two tables, say). */
71
+ .crewlet-rich-editor__content .ProseMirror-gapcursor {
72
+ display: none;
73
+ position: absolute;
74
+ pointer-events: none;
75
+ }
76
+
77
+ .crewlet-rich-editor__content .ProseMirror-gapcursor::after {
78
+ content: '';
79
+ display: block;
80
+ position: absolute;
81
+ top: calc(var(--spacing-2) * -1);
82
+ width: var(--spacing-5);
83
+ border-top: 1px solid var(--color-text-primary);
84
+ animation: crewlet-rich-editor-caret calc(var(--motion-duration-breath) / 2) steps(2, start) infinite;
85
+ }
86
+
87
+ @keyframes crewlet-rich-editor-caret {
88
+ to {
89
+ visibility: hidden;
90
+ }
91
+ }
92
+
93
+ .crewlet-rich-editor__content.ProseMirror-focused .ProseMirror-gapcursor {
94
+ display: block;
95
+ }
96
+
97
+ /*
98
+ * The placeholder and the empty line's hint: a decoration's attribute, drawn
99
+ * here, so neither is text in the document. Floated with no height, so the
100
+ * caret stands at the start of the line rather than after the words.
101
+ */
102
+ .crewlet-rich-editor__content .is-empty::before {
103
+ content: attr(data-placeholder);
104
+ float: left;
105
+ height: 0;
106
+ color: var(--color-text-tertiary);
107
+ pointer-events: none;
108
+ }
109
+
110
+ /* The slash and the word after it, while the menu is open. */
111
+ .crewlet-rich-editor__slash {
112
+ border-radius: var(--radius-xs);
113
+ background: var(--color-brand-accent-soft);
114
+ color: var(--color-brand-accent-ink);
115
+ }
116
+
117
+ /* An EMPTY table cell keeps a width a pointer can land in; one with text is
118
+ sized as the reader's is, so the columns do not move when editing starts. */
119
+ .crewlet-rich-editor__content :where(th, td):has(> br.ProseMirror-trailingBreak:only-child) {
120
+ min-width: calc(var(--spacing-10) * 1.5);
121
+ }
122
+
123
+ /* A task's box is pressed here, where a reader's is only read. */
124
+ .crewlet-rich-editor__content li > input[type='checkbox'] {
125
+ cursor: pointer;
126
+ }
127
+
128
+ /* A picture the page cannot show reads as its alt text, set apart as a chip. */
129
+ .crewlet-rich-editor__image-alt {
130
+ display: inline-flex;
131
+ align-items: center;
132
+ padding: 0 var(--spacing-2);
133
+ border: 1px dashed var(--color-border-strong);
134
+ border-radius: var(--radius-sm);
135
+ color: var(--color-text-tertiary);
136
+ font-size: var(--font-size-xs);
137
+ }
138
+
139
+ .crewlet-rich-editor--disabled .crewlet-rich-editor__content {
140
+ caret-color: transparent;
141
+ }
142
+
143
+ /* ── a block's controls ─────────────────────────────────────────────────── */
144
+
145
+ .crewlet-rich-editor__code {
146
+ position: relative;
147
+ }
148
+
149
+ /*
150
+ * A code block's language: a quiet field at the block's top right, read as
151
+ * the language's name and turning into a field under the pointer or the
152
+ * keyboard. An empty one shows only while the block is pointed at.
153
+ */
154
+ .crewlet-rich-editor__code-bar {
155
+ position: absolute;
156
+ top: var(--spacing-1);
157
+ right: var(--spacing-1);
158
+ z-index: var(--z-index-raised);
159
+ }
160
+
161
+ .crewlet-rich-editor__lang {
162
+ width: 12ch;
163
+ height: var(--size-control-sm);
164
+ padding: 0 var(--spacing-2);
165
+ border: 1px solid transparent;
166
+ border-radius: var(--radius-sm);
167
+ background: transparent;
168
+ color: var(--color-text-tertiary);
169
+ font-family: var(--font-family-mono);
170
+ font-size: var(--font-size-2xs);
171
+ text-align: right;
172
+ }
173
+
174
+ .crewlet-rich-editor__lang::placeholder {
175
+ color: var(--color-text-tertiary);
176
+ }
177
+
178
+ .crewlet-rich-editor__lang:placeholder-shown {
179
+ opacity: 0;
180
+ }
181
+
182
+ .crewlet-rich-editor__code:hover .crewlet-rich-editor__lang,
183
+ .crewlet-rich-editor__lang:focus {
184
+ opacity: 1;
185
+ border-color: var(--color-border-default);
186
+ background: var(--color-surface-elevated);
187
+ text-align: left;
188
+ }
189
+
190
+ .crewlet-rich-editor__lang:focus-visible {
191
+ outline: 2px solid var(--color-focus);
192
+ outline-offset: 0;
193
+ }
194
+
195
+ /* A callout's tone, drawn as its label, and a menu under it. */
196
+ .crewlet-rich-editor__tone {
197
+ display: inline-flex;
198
+ align-items: center;
199
+ gap: var(--spacing-1);
200
+ margin: 0;
201
+ padding: 0;
202
+ border: none;
203
+ border-radius: var(--radius-xs);
204
+ background: transparent;
205
+ color: inherit;
206
+ font: inherit;
207
+ cursor: pointer;
208
+ }
209
+
210
+ .crewlet-rich-editor__tone > svg {
211
+ opacity: 0;
212
+ }
213
+
214
+ .crewlet-rich-editor__tone:hover > svg,
215
+ .crewlet-rich-editor__tone:focus-visible > svg,
216
+ .crewlet-rich-editor__tone[aria-expanded='true'] > svg {
217
+ opacity: 1;
218
+ }
219
+
220
+ .crewlet-rich-editor__tone:hover {
221
+ text-decoration: underline;
222
+ text-underline-offset: 2px;
223
+ }
224
+
225
+ .crewlet-rich-editor__tone:focus-visible {
226
+ outline: 2px solid var(--color-focus);
227
+ outline-offset: 2px;
228
+ }
229
+
230
+ /* ── the floating surfaces ───────────────────────────────────────────────── */
231
+
232
+ /* Every one is the menu's surface: the same ground, line, radius and shadow. */
233
+ .crewlet-rich-editor__menu,
234
+ .crewlet-rich-editor__bar,
235
+ .crewlet-rich-editor__bubble,
236
+ .crewlet-rich-editor__panel {
237
+ position: fixed;
238
+ z-index: var(--z-index-popover);
239
+ border: 1px solid var(--color-border-default);
240
+ border-radius: var(--radius-md);
241
+ background: var(--color-surface-subtle);
242
+ box-shadow: var(--shadow-xl);
243
+ font-family: var(--font-family-sans);
244
+ animation: crewlet-rich-editor-in var(--motion-duration-fast) var(--motion-easing-emphasized);
245
+ }
246
+
247
+ @keyframes crewlet-rich-editor-in {
248
+ from {
249
+ opacity: 0;
250
+ transform: translateY(var(--spacing-1));
251
+ }
252
+ }
253
+
254
+ .crewlet-rich-editor__bar,
255
+ .crewlet-rich-editor__bubble {
256
+ display: flex;
257
+ align-items: center;
258
+ padding: var(--spacing-1);
259
+ box-shadow: var(--shadow-lg);
260
+ }
261
+
262
+ .crewlet-rich-editor__group {
263
+ display: inline-flex;
264
+ align-items: center;
265
+ gap: calc(var(--spacing-1) / 2);
266
+ }
267
+
268
+ .crewlet-rich-editor__group + .crewlet-rich-editor__group {
269
+ margin-left: var(--spacing-1);
270
+ padding-left: var(--spacing-1);
271
+ border-left: 1px solid var(--color-border-default);
272
+ }
273
+
274
+ /* The slash menu: a block's glyph on a tile, its name, and what it is. */
275
+ .crewlet-rich-editor__menu {
276
+ width: min(300px, calc(100vw - var(--spacing-8)));
277
+ max-height: min(360px, 50vh);
278
+ overflow-y: auto;
279
+ overscroll-behavior: contain;
280
+ padding: var(--spacing-1);
281
+ }
282
+
283
+ .crewlet-rich-editor__group-heading {
284
+ padding: var(--spacing-2) var(--spacing-2) var(--spacing-1);
285
+ color: var(--color-text-tertiary);
286
+ font-size: var(--font-size-2xs);
287
+ font-weight: var(--font-weight-semibold);
288
+ letter-spacing: var(--font-letter-spacing-wide);
289
+ text-transform: uppercase;
290
+ }
291
+
292
+ .crewlet-rich-editor__option {
293
+ display: flex;
294
+ align-items: center;
295
+ gap: var(--spacing-3);
296
+ padding: var(--spacing-1) var(--spacing-2);
297
+ border-radius: var(--radius-sm);
298
+ color: var(--color-text-primary);
299
+ cursor: pointer;
300
+ }
301
+
302
+ .crewlet-rich-editor__option.is-active {
303
+ background: var(--color-surface-hover);
304
+ }
305
+
306
+ .crewlet-rich-editor__option-icon {
307
+ display: inline-flex;
308
+ align-items: center;
309
+ justify-content: center;
310
+ flex: none;
311
+ width: var(--size-control-md);
312
+ height: var(--size-control-md);
313
+ border: 1px solid var(--color-border-default);
314
+ border-radius: var(--radius-sm);
315
+ background: var(--color-surface-elevated);
316
+ color: var(--color-text-secondary);
317
+ }
318
+
319
+ .crewlet-rich-editor__option-text {
320
+ display: flex;
321
+ flex-direction: column;
322
+ min-width: 0;
323
+ flex: 1;
324
+ }
325
+
326
+ .crewlet-rich-editor__option-label {
327
+ font-size: var(--font-size-compact);
328
+ line-height: var(--font-line-height-snug);
329
+ }
330
+
331
+ .crewlet-rich-editor__option-description {
332
+ overflow: hidden;
333
+ color: var(--color-text-tertiary);
334
+ font-size: var(--font-size-xs);
335
+ line-height: var(--font-line-height-snug);
336
+ text-overflow: ellipsis;
337
+ white-space: nowrap;
338
+ }
339
+
340
+ .crewlet-rich-editor__option-hint {
341
+ flex: none;
342
+ color: var(--color-text-tertiary);
343
+ font-family: var(--font-family-mono);
344
+ font-size: var(--font-size-2xs);
345
+ }
346
+
347
+ .crewlet-rich-editor__empty {
348
+ margin: 0;
349
+ padding: var(--spacing-2);
350
+ color: var(--color-text-tertiary);
351
+ font-size: var(--font-size-compact);
352
+ }
353
+
354
+ /* The link under the caret: where it goes, and what can be done with it. */
355
+ .crewlet-rich-editor__bubble-link {
356
+ display: inline-flex;
357
+ align-items: center;
358
+ gap: var(--spacing-1);
359
+ max-width: min(260px, calc(100vw - 160px));
360
+ padding: 0 var(--spacing-2);
361
+ color: var(--color-brand-accent-ink);
362
+ font-size: var(--font-size-compact);
363
+ text-decoration: none;
364
+ }
365
+
366
+ .crewlet-rich-editor__bubble-link:hover {
367
+ text-decoration: underline;
368
+ text-underline-offset: 2px;
369
+ }
370
+
371
+ .crewlet-rich-editor__bubble-link:focus-visible {
372
+ outline: 2px solid var(--color-focus);
373
+ outline-offset: 0;
374
+ border-radius: var(--radius-xs);
375
+ }
376
+
377
+ .crewlet-rich-editor__bubble-href {
378
+ overflow: hidden;
379
+ text-overflow: ellipsis;
380
+ white-space: nowrap;
381
+ }
382
+
383
+ .crewlet-rich-editor__bubble-refused {
384
+ padding: 0 var(--spacing-2);
385
+ color: var(--color-feedback-warning-ink);
386
+ font-size: var(--font-size-xs);
387
+ }
388
+
389
+ /* A panel: the link's address, a picture's address and alt text, a caller's own. */
390
+ .crewlet-rich-editor__panel {
391
+ width: min(320px, calc(100vw - var(--spacing-8)));
392
+ padding: var(--spacing-3);
393
+ }
394
+
395
+ .crewlet-rich-editor__form {
396
+ display: flex;
397
+ flex-direction: column;
398
+ gap: var(--spacing-3);
399
+ margin: 0;
400
+ }
401
+
402
+ .crewlet-rich-editor__form-actions {
403
+ display: flex;
404
+ justify-content: flex-end;
405
+ gap: var(--spacing-2);
406
+ }
407
+
408
+ @media (prefers-reduced-motion: reduce) {
409
+ .crewlet-rich-editor__content .ProseMirror-gapcursor::after {
410
+ animation: none;
411
+ }
412
+
413
+ .crewlet-rich-editor__menu,
414
+ .crewlet-rich-editor__bar,
415
+ .crewlet-rich-editor__bubble,
416
+ .crewlet-rich-editor__panel {
417
+ animation: none;
418
+ }
419
+ }
@@ -0,0 +1 @@
1
+ export { canonicalMarkdown, roundTripMarkdown } from '../RichEditor/roundtrip.js';
@@ -0,0 +1,3 @@
1
+ export { canonicalMarkdown, roundTripMarkdown } from '../chunk-IDBHX5SR.js';
2
+ import '../chunk-YFW4MTK4.js';
3
+ import '../chunk-SKOYC2CF.js';
@@ -8,8 +8,8 @@ import '../chunk-WIATRXEJ.js';
8
8
  import '../chunk-YEKYVJQR.js';
9
9
  import '../chunk-NHBP2XS5.js';
10
10
  import '../chunk-Z7JYG5TF.js';
11
- import '../chunk-QWOPX2MN.js';
12
11
  import '../chunk-AYKXMIOR.js';
12
+ import '../chunk-QWOPX2MN.js';
13
13
  import '../chunk-UAN5NE7M.js';
14
14
  import '../chunk-5OM447RW.js';
15
15
  import '../chunk-2HIOJ4YZ.js';
@@ -1,7 +1,7 @@
1
1
  export { DensitySwitcher, ThemeSwitcher } from '../chunk-WJDQ7XQA.js';
2
2
  export { applyStoredPreferences, resolveTheme, useDensityPreference, useSystemTheme, useThemePreference } from '../chunk-Z24ZUSTX.js';
3
- import '../chunk-FQCLKD7U.js';
4
3
  export { DENSITY_PREFERENCES, PALETTE_ID, THEME_PREFERENCES, applyDensity, applyPalette, applyTheme, isDensityPreference, isPaletteId, isThemePreference } from '../chunk-ZXXDZJQN.js';
4
+ import '../chunk-FQCLKD7U.js';
5
5
  import '../chunk-RCQXUT5K.js';
6
6
  import '../chunk-HJEVSQN6.js';
7
7
  import '../chunk-RKKO7QHH.js';
@@ -1,11 +1,11 @@
1
1
  export { VERSION_COMPARE_LABELS, VERSION_COMPARE_LENSES, VersionCompare } from '../chunk-EHQTPVV4.js';
2
- import '../chunk-FQCLKD7U.js';
3
2
  import '../chunk-BVWSLXTY.js';
3
+ import '../chunk-FQCLKD7U.js';
4
4
  import '../chunk-RCQXUT5K.js';
5
5
  import '../chunk-HJEVSQN6.js';
6
6
  import '../chunk-RKKO7QHH.js';
7
7
  import '../chunk-RA2ULG6H.js';
8
- import '../chunk-PQADV6P6.js';
9
8
  import '../chunk-BHHIIK3M.js';
9
+ import '../chunk-PQADV6P6.js';
10
10
  import '../chunk-BZFWDIV6.js';
11
11
  import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,28 @@
1
+ import { cx } from './chunk-ODEQTPFM.js';
2
+ import './EditingStatus-NFADEPSX.css';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+
5
+ var LABELS = {
6
+ editing: "Editing",
7
+ unsaved: "Unsaved changes",
8
+ saving: "Saving"
9
+ };
10
+ function EditingStatus({ dirty, saving = false, labels, className }) {
11
+ const text = { ...LABELS, ...labels };
12
+ const state = saving ? text.saving : dirty ? text.unsaved : null;
13
+ return /* @__PURE__ */ jsxs(
14
+ "span",
15
+ {
16
+ role: "status",
17
+ "aria-live": "polite",
18
+ className: cx("crewlet-editing-status", dirty && "crewlet-editing-status--dirty", className),
19
+ children: [
20
+ /* @__PURE__ */ jsx("span", { className: "crewlet-editing-status__dot", "aria-hidden": "true" }),
21
+ /* @__PURE__ */ jsx("span", { className: "crewlet-editing-status__label", children: text.editing }),
22
+ state && /* @__PURE__ */ jsx("span", { className: "crewlet-editing-status__state", children: state })
23
+ ]
24
+ }
25
+ );
26
+ }
27
+
28
+ export { EditingStatus };
@@ -1,4 +1,4 @@
1
- import { ArtifactKindGlyph } from './chunk-6J35F334.js';
1
+ import { ArtifactKindGlyph } from './chunk-GOSQXEZU.js';
2
2
  import { ShieldGlyph, ActivityGlyph, GaugeGlyph, PackageGlyph, FolderGlyph, ClockGlyph, DatabaseGlyph, Settings2Glyph, BookOpenGlyph, FlagGlyph, StarGlyph, WandSparklesGlyph, BugGlyph, TargetGlyph, ImageGlyph, CodeGlyph, CoinsGlyph, UserGlyph, UsersGlyph, ChartNoAxesGanttGlyph, SquareKanbanGlyph, ListChecksGlyph, ListGlyph, GlobeGlyph, CompassGlyph, FileTextGlyph, TableGlyph, CalendarGlyph, LayoutDashboardGlyph, ChartPieGlyph, ChartColumnGlyph } from '@crewlethq/icons/glyphs';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
@@ -1,5 +1,5 @@
1
- import { Document } from './chunk-WI6K5M5X.js';
2
- import { ArtifactKindGlyph } from './chunk-6J35F334.js';
1
+ import { Document } from './chunk-M3LUNN7F.js';
2
+ import { ArtifactKindGlyph } from './chunk-GOSQXEZU.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './ArtifactCover-D4MBEJ5H.css';
5
5
  import './DashboardCover-RMINBODB.css';