@crewlethq/ui 0.29.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 (45) hide show
  1. package/README.md +24 -3
  2. package/dist/ArtifactCover/index.js +2 -2
  3. package/dist/CommentThread/index.js +2 -2
  4. package/dist/Document/Document.d.ts +8 -1
  5. package/dist/Document/index.js +1 -1
  6. package/dist/{Document-PQGXJHB7.css → Document-G3YTZIUL.css} +71 -0
  7. package/dist/EditingStatus/EditingStatus.d.ts +25 -0
  8. package/dist/EditingStatus/index.d.ts +3 -0
  9. package/dist/EditingStatus/index.js +2 -0
  10. package/dist/EditingStatus-NFADEPSX.css +53 -0
  11. package/dist/Editor-YZ7KG2RD.js +2099 -0
  12. package/dist/Markdown/grammar.d.ts +170 -0
  13. package/dist/Markdown/index.d.ts +2 -0
  14. package/dist/Markdown/index.js +1 -0
  15. package/dist/RichEditor/Editor.d.ts +17 -0
  16. package/dist/RichEditor/RichEditor.d.ts +26 -0
  17. package/dist/RichEditor/codec.d.ts +78 -0
  18. package/dist/RichEditor/commands.d.ts +89 -0
  19. package/dist/RichEditor/index.d.ts +4 -0
  20. package/dist/RichEditor/index.js +8 -0
  21. package/dist/RichEditor/keys.d.ts +16 -0
  22. package/dist/RichEditor/nodeviews.d.ts +60 -0
  23. package/dist/RichEditor/paste.d.ts +47 -0
  24. package/dist/RichEditor/plugins.d.ts +49 -0
  25. package/dist/RichEditor/roundtrip.d.ts +14 -0
  26. package/dist/RichEditor/schema.d.ts +23 -0
  27. package/dist/RichEditor/types.d.ts +140 -0
  28. package/dist/RichEditor-NPD2KAPS.css +419 -0
  29. package/dist/RichEditorMarkdown/index.d.ts +1 -0
  30. package/dist/RichEditorMarkdown/index.js +3 -0
  31. package/dist/chunk-3DPIU2Q7.js +28 -0
  32. package/dist/{chunk-XALUCIG5.js → chunk-6AH2XJ3Q.js} +1 -1
  33. package/dist/chunk-A4E5YLXO.js +85 -0
  34. package/dist/{chunk-FKULOLKG.js → chunk-GR55WT4R.js} +1 -1
  35. package/dist/chunk-IDBHX5SR.js +12 -0
  36. package/dist/{chunk-WI6K5M5X.js → chunk-M3LUNN7F.js} +1 -1
  37. package/dist/chunk-SKOYC2CF.js +288 -0
  38. package/dist/chunk-VOX3YRFO.js +76 -0
  39. package/dist/chunk-YFW4MTK4.js +749 -0
  40. package/dist/generated/index.d.ts +4 -0
  41. package/dist/generated/index.js +44 -38
  42. package/dist/index.js +44 -38
  43. package/dist/styles.css +550 -1
  44. package/package.json +13 -3
  45. /package/dist/{chunk-IFNQKWUO.js → chunk-OC46246T.js} +0 -0
@@ -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';
@@ -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 { Document } from './chunk-WI6K5M5X.js';
1
+ import { Document } from './chunk-M3LUNN7F.js';
2
2
  import { ArtifactKindGlyph } from './chunk-GOSQXEZU.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './ArtifactCover-D4MBEJ5H.css';
@@ -0,0 +1,85 @@
1
+ import { MARKDOWN_CALLOUT_NAMES } from './chunk-SKOYC2CF.js';
2
+
3
+ // src/RichEditor/types.ts
4
+ var RICH_EDITOR_LABELS = {
5
+ description: "Type a slash for blocks. Press Alt and F10 to reach the formatting toolbar.",
6
+ placeholder: "Write, or type a slash for blocks",
7
+ emptyLine: "Type / for blocks",
8
+ slashMenu: "Blocks",
9
+ slashEmpty: "No block matches",
10
+ slashGroupBlocks: "Blocks",
11
+ slashGroupInsert: "Insert",
12
+ blocks: {
13
+ paragraph: { label: "Text", description: "A plain paragraph" },
14
+ heading1: { label: "Heading 1", description: "A section heading" },
15
+ heading2: { label: "Heading 2", description: "A subsection heading" },
16
+ heading3: { label: "Heading 3", description: "A smaller heading" },
17
+ bullet: { label: "Bulleted list", description: "A simple list" },
18
+ ordered: { label: "Numbered list", description: "A list in order" },
19
+ task: { label: "Task list", description: "Items with a checkbox" },
20
+ quote: { label: "Quote", description: "Words set off from the text" },
21
+ callout: { label: "Callout", description: "A note that stands out" },
22
+ code: { label: "Code block", description: "Code, with its language" },
23
+ table: { label: "Table", description: "Rows and columns" },
24
+ divider: { label: "Divider", description: "A line between sections" },
25
+ image: { label: "Image", description: "A picture, by its address" }
26
+ },
27
+ toolbar: "Formatting",
28
+ bold: "Bold",
29
+ italic: "Italic",
30
+ strike: "Strikethrough",
31
+ code: "Inline code",
32
+ link: "Link",
33
+ heading: (level) => `Heading ${level}`,
34
+ linkPanel: "Link",
35
+ linkAddress: "Address",
36
+ linkText: "Text",
37
+ linkApply: "Apply",
38
+ linkRemove: "Remove link",
39
+ linkOpen: "Open link",
40
+ linkEdit: "Edit link",
41
+ linkInvalid: "Use an address that starts with https://, http://, mailto: or #/.",
42
+ linkRefused: "This address does not open from a page.",
43
+ imagePanel: "Image",
44
+ imageAddress: "Image address",
45
+ imageAlt: "Alt text",
46
+ imageAltHelp: "Describes the picture for anyone who cannot see it.",
47
+ imageInsert: "Insert image",
48
+ imageEdit: "Edit image",
49
+ imageRemove: "Remove image",
50
+ tableBar: "Table",
51
+ tableRow: "Row",
52
+ tableColumn: "Column",
53
+ rowAbove: "Insert row above",
54
+ rowBelow: "Insert row below",
55
+ rowDelete: "Delete row",
56
+ columnLeft: "Insert column left",
57
+ columnRight: "Insert column right",
58
+ columnDelete: "Delete column",
59
+ alignStart: "Align left",
60
+ alignCenter: "Align center",
61
+ alignEnd: "Align right",
62
+ tableDelete: "Delete table",
63
+ codeLanguage: "Code language",
64
+ codeLanguagePlaceholder: "Language",
65
+ calloutTone: "Callout type",
66
+ calloutRemove: "Remove callout",
67
+ tones: MARKDOWN_CALLOUT_NAMES,
68
+ taskDone: "Mark as done",
69
+ taskNotDone: "Mark as not done",
70
+ loading: "Loading the editor",
71
+ failed: "The editor did not load",
72
+ failedDetail: "The page may have been updated while it was open. Try again, or reload the page.",
73
+ retry: "Try again"
74
+ };
75
+ function richEditorLabels(overrides) {
76
+ if (!overrides) return RICH_EDITOR_LABELS;
77
+ return {
78
+ ...RICH_EDITOR_LABELS,
79
+ ...overrides,
80
+ blocks: { ...RICH_EDITOR_LABELS.blocks, ...overrides.blocks },
81
+ tones: { ...RICH_EDITOR_LABELS.tones, ...overrides.tones }
82
+ };
83
+ }
84
+
85
+ export { RICH_EDITOR_LABELS, richEditorLabels };
@@ -1,5 +1,5 @@
1
1
  import { Composer } from './chunk-7DZDSSJS.js';
2
- import { Document } from './chunk-WI6K5M5X.js';
2
+ import { Document } from './chunk-M3LUNN7F.js';
3
3
  import { PrincipalAvatar } from './chunk-4KP4RC3O.js';
4
4
  import { toInstant, RelativeTime, formatExact, toISO } from './chunk-3CZ7XAVY.js';
5
5
  import { Count } from './chunk-BHHIIK3M.js';