@charcuterie/ui 3.2.0 → 3.4.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 (58) hide show
  1. package/dist/Field/Field.d.ts +1 -1
  2. package/dist/Field/Field.d.ts.map +1 -1
  3. package/dist/Field/Field.js +19 -1
  4. package/dist/Field/Field.js.map +1 -1
  5. package/dist/MarkdownEditor/MarkdownEditor.d.ts.map +1 -1
  6. package/dist/MarkdownEditor/MarkdownEditor.js +21 -8
  7. package/dist/MarkdownEditor/MarkdownEditor.js.map +1 -1
  8. package/dist/MarkdownEditor/markdownCommands.d.ts +32 -0
  9. package/dist/MarkdownEditor/markdownCommands.d.ts.map +1 -1
  10. package/dist/MarkdownEditor/markdownCommands.js +47 -0
  11. package/dist/MarkdownEditor/markdownCommands.js.map +1 -1
  12. package/dist/MarkdownEditor/markdownSpans.d.ts.map +1 -1
  13. package/dist/MarkdownEditor/markdownSpans.js +30 -0
  14. package/dist/MarkdownEditor/markdownSpans.js.map +1 -1
  15. package/dist/Select/Select.d.ts +43 -2
  16. package/dist/Select/Select.d.ts.map +1 -1
  17. package/dist/Select/Select.js +27 -2
  18. package/dist/Select/Select.js.map +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/markdownEditorCodeMirror/MarkdownEditorCodeMirror.d.ts +93 -0
  22. package/dist/markdownEditorCodeMirror/MarkdownEditorCodeMirror.d.ts.map +1 -0
  23. package/dist/markdownEditorCodeMirror/MarkdownEditorCodeMirror.js +545 -0
  24. package/dist/markdownEditorCodeMirror/MarkdownEditorCodeMirror.js.map +1 -0
  25. package/dist/markdownEditorCodeMirror/index.d.ts +16 -0
  26. package/dist/markdownEditorCodeMirror/index.d.ts.map +1 -0
  27. package/dist/markdownEditorCodeMirror/index.js +14 -0
  28. package/dist/markdownEditorCodeMirror/index.js.map +1 -0
  29. package/dist/markdownEditorCodeMirror/livePreview.d.ts +40 -0
  30. package/dist/markdownEditorCodeMirror/livePreview.d.ts.map +1 -0
  31. package/dist/markdownEditorCodeMirror/livePreview.js +428 -0
  32. package/dist/markdownEditorCodeMirror/livePreview.js.map +1 -0
  33. package/dist/markdownEditorCodeMirror/livePreviewRanges.d.ts +128 -0
  34. package/dist/markdownEditorCodeMirror/livePreviewRanges.d.ts.map +1 -0
  35. package/dist/markdownEditorCodeMirror/livePreviewRanges.js +345 -0
  36. package/dist/markdownEditorCodeMirror/livePreviewRanges.js.map +1 -0
  37. package/package.json +36 -1
  38. package/src/Field/Field.mdx +2 -2
  39. package/src/Field/Field.stories.tsx +9 -5
  40. package/src/Field/Field.test.tsx +43 -6
  41. package/src/Field/Field.tsx +19 -1
  42. package/src/MarkdownEditor/MarkdownEditor.tsx +33 -7
  43. package/src/MarkdownEditor/markdownCommands.test.ts +55 -0
  44. package/src/MarkdownEditor/markdownCommands.ts +60 -0
  45. package/src/MarkdownEditor/markdownSpans.test.ts +65 -0
  46. package/src/MarkdownEditor/markdownSpans.ts +35 -0
  47. package/src/Select/Select.mdx +27 -1
  48. package/src/Select/Select.stories.tsx +6 -1
  49. package/src/Select/Select.tsx +43 -2
  50. package/src/index.ts +5 -0
  51. package/src/markdownEditorCodeMirror/MarkdownEditorCodeMirror.mdx +144 -0
  52. package/src/markdownEditorCodeMirror/MarkdownEditorCodeMirror.stories.tsx +147 -0
  53. package/src/markdownEditorCodeMirror/MarkdownEditorCodeMirror.tsx +866 -0
  54. package/src/markdownEditorCodeMirror/index.ts +26 -0
  55. package/src/markdownEditorCodeMirror/livePreview.ts +535 -0
  56. package/src/markdownEditorCodeMirror/livePreviewRanges.test.ts +431 -0
  57. package/src/markdownEditorCodeMirror/livePreviewRanges.ts +581 -0
  58. package/src/sourceRules.test.ts +20 -0
@@ -0,0 +1,93 @@
1
+ import type { ReactNode } from "react";
2
+ import type { MarkdownEditorIcons, MarkdownImageUpload } from "../MarkdownEditor/MarkdownEditor.tsx";
3
+ import type { SlotProps } from "../slotProps.ts";
4
+ export type MarkdownEditorCodeMirrorProps = SlotProps & {
5
+ className?: string;
6
+ /**
7
+ * **Initial** only, and the same uncontrolled contract as the
8
+ * sibling `MarkdownEditor` — for the same reason, one layer over:
9
+ * reassigning the whole document from outside throws away the
10
+ * undo history that belonged to it. Swap documents with a `key`.
11
+ */
12
+ defaultValue?: string;
13
+ /** Start in raw-markdown mode. **Initial** only. */
14
+ isRawModeDefault?: boolean;
15
+ icons?: MarkdownEditorIcons;
16
+ isDisabled?: boolean;
17
+ isReadOnly?: boolean;
18
+ /**
19
+ * The accessible name. Omit it inside a `Field`, which supplies a
20
+ * real `<label htmlFor>`.
21
+ */
22
+ label?: string;
23
+ onChange?: (value: string) => void;
24
+ onUploadError?: (file: File, error: unknown) => void;
25
+ /**
26
+ * Paste or drop an image and this runs; the URL you return is
27
+ * inserted at the caret as `![alt](url)` — and, unlike the
28
+ * textarea sibling, is then **rendered in place**.
29
+ */
30
+ onUploadImage?: (file: File) => Promise<MarkdownImageUpload>;
31
+ placeholder?: string;
32
+ /** Label for the raw-markdown toggle. */
33
+ rawModeLabel?: string;
34
+ toolbarLabel?: string;
35
+ };
36
+ /**
37
+ * The live-preview markdown editor: Obsidian's model, on CodeMirror.
38
+ *
39
+ * This is the **opt-in** sibling of `MarkdownEditor`, and picking
40
+ * between them is a real decision rather than a preference:
41
+ *
42
+ * | | `MarkdownEditor` | this |
43
+ * | --- | --- | --- |
44
+ * | Surface | `<textarea>` + painted layer | CodeMirror 6 |
45
+ * | New dependency | **none** | ~176 KB gz of optional peer |
46
+ * | Markers | dimmed, never hidden | **concealed** until the caret arrives |
47
+ * | Headings | weight and colour only | **actually larger** |
48
+ * | Images | shown as `![alt](url)` | **rendered in place** |
49
+ * | Undo, IME | the platform's own | CodeMirror's |
50
+ *
51
+ * The default is still the textarea. A component library that makes
52
+ * every consumer install an editor core to render a description
53
+ * field has made the wrong trade, which is why this lives behind
54
+ * `@charcuterie/ui/markdown-editor-codemirror` with every CodeMirror
55
+ * package as an **optional** peer: a consumer that never imports
56
+ * this subpath resolves, installs and audits none of it.
57
+ *
58
+ * ## What is the same, and it is the important part
59
+ *
60
+ * **Markdown is the stored value, byte for byte.** There is no
61
+ * document model here and no serialiser. CodeMirror's state holds
62
+ * the markdown *text*; live preview is a set of decorations
63
+ * *over* that text; concealing `**` hides two characters that are
64
+ * still in the document and still in `onChange`. Every command is
65
+ * the same pure `markdownCommands.ts` the sibling uses, returning
66
+ * markdown in and markdown out.
67
+ *
68
+ * That distinction is the whole reason this is not TipTap or
69
+ * Lexical. Those invert it — their document model is authoritative
70
+ * and markdown becomes a lossy *export* — and the tracker Docket
71
+ * replaces died of exactly that: HTML in a field it later read back
72
+ * as text. An editor core would have been easier to build and is
73
+ * the one thing that could not be allowed.
74
+ *
75
+ * ## What genuinely costs something
76
+ *
77
+ * The `<textarea>` sibling gets caret movement, IME composition,
78
+ * spellcheck, the platform undo stack and `role="textbox"` from the
79
+ * browser, tested by the vendors. A `contenteditable` re-earns each
80
+ * of those, and CodeMirror is the reason that is acceptable rather
81
+ * than reckless: it is the most heavily exercised implementation of
82
+ * that re-earning in the ecosystem. It is still a re-implementation,
83
+ * and that is the honest cost of this subpath.
84
+ *
85
+ * ## Clicking a link opens it
86
+ *
87
+ * Obsidian's behaviour, not VS Code's: where the markup is hidden, a
88
+ * link that looks like a link acts like one. The trade is that you
89
+ * cannot click *into* link text to edit it — arrow in from the edge,
90
+ * or flip the raw-markdown toggle, which is exactly what it is for.
91
+ */
92
+ export declare const MarkdownEditorCodeMirror: ({ className, defaultValue, icons, isDisabled, isRawModeDefault, isReadOnly, label, onChange, onUploadError, onUploadImage, placeholder, rawModeLabel, toolbarLabel, ...receivedSlotProps }: MarkdownEditorCodeMirrorProps) => ReactNode;
93
+ //# sourceMappingURL=MarkdownEditorCodeMirror.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownEditorCodeMirror.d.ts","sourceRoot":"","sources":["../../src/markdownEditorCodeMirror/MarkdownEditorCodeMirror.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,sCAAsC,CAAA;AAkB7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAQhD,MAAM,MAAM,6BAA6B,GAAG,SAAS,GAAG;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,KAAK,CAAC,EAAE,mBAAmB,CAAA;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IACpD;;;;OAIG;IACH,aAAa,CAAC,EAAE,CACd,IAAI,EAAE,IAAI,KACP,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AA2ID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,eAAO,MAAM,wBAAwB,GAAI,4LAetC,6BAA6B,KAAG,SA8jBlC,CAAA"}
@@ -0,0 +1,545 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useUniqueId } from "@charcuterie/logic";
3
+ import { defaultKeymap, history, historyKeymap, } from "@codemirror/commands";
4
+ import { markdown, markdownLanguage, } from "@codemirror/lang-markdown";
5
+ import { Compartment, EditorState } from "@codemirror/state";
6
+ import { EditorView, keymap, placeholder as placeholderExtension, } from "@codemirror/view";
7
+ import { useEffect, useRef, useState } from "react";
8
+ import { continueList, getMinimalEdit, indentLines, insertLink, insertText, isLinkPaste, MARKDOWN_LINE_PREFIXES, outdentLines, toggleHeading, toggleInlineMarker, toggleLinePrefix, toMarkdownImage, wrapSelectionInLink, } from "../MarkdownEditor/markdownCommands.js";
9
+ import { Switch } from "../Switch/Switch.js";
10
+ import { Toolbar } from "../Toolbar/Toolbar.js";
11
+ import { toClassName } from "../toClassName.js";
12
+ import { livePreview, setLivePreviewRawMode, } from "./livePreview.js";
13
+ const isImageFile = (file) => file.type.startsWith("image/");
14
+ const readSelection = (view) => {
15
+ const { main } = view.state.selection;
16
+ return {
17
+ selectionEnd: main.to,
18
+ selectionStart: main.from,
19
+ text: view.state.doc.toString(),
20
+ };
21
+ };
22
+ /**
23
+ * Apply a pure command's result as a **minimal** change.
24
+ *
25
+ * `getMinimalEdit` earns its keep differently here than in the
26
+ * textarea sibling. There it was about not wiping the browser's own
27
+ * undo stack; here CodeMirror's history would happily record a
28
+ * document-sized replacement — and then Ctrl+Z undoes the whole
29
+ * description instead of the bold toggle that caused it.
30
+ *
31
+ * Module scope, not a closure, because it is a pure function of its
32
+ * two arguments. That is not a lint dodge: a helper defined inside
33
+ * the component is a new identity every render, and this one gets
34
+ * captured by extensions that are built exactly once.
35
+ */
36
+ const applyEdit = (view, next) => {
37
+ const current = view.state.doc.toString();
38
+ const edit = getMinimalEdit(current, next.text);
39
+ view.dispatch({
40
+ changes: {
41
+ from: edit.start,
42
+ insert: edit.text,
43
+ to: edit.end,
44
+ },
45
+ selection: {
46
+ anchor: next.selectionStart,
47
+ head: next.selectionEnd,
48
+ },
49
+ });
50
+ view.focus();
51
+ };
52
+ /**
53
+ * Upload one file, with a **markdown** placeholder holding the
54
+ * caret's place while the request is in flight.
55
+ *
56
+ * The placeholder is real text in the document rather than an
57
+ * overlay, because the user keeps typing during an upload and the
58
+ * insertion point has to travel with what they type. It carries a
59
+ * counter so two files of the same name do not resolve into each
60
+ * other's slot, and it is markdown like everything else — a failed
61
+ * upload leaves a document the user can read and fix, not a
62
+ * dangling widget.
63
+ */
64
+ const uploadImage = async ({ count, file, handlers, setMessage, view, }) => {
65
+ const { onUploadError, onUploadImage } = handlers;
66
+ if (!onUploadImage) {
67
+ return;
68
+ }
69
+ const marker = `![Uploading ${file.name}](#uploading-${count})`;
70
+ applyEdit(view, insertText(readSelection(view), marker));
71
+ setMessage(`Uploading ${file.name}`);
72
+ const replaceMarker = (insertion) => {
73
+ const text = view.state.doc.toString();
74
+ const start = text.indexOf(marker);
75
+ if (start === -1) {
76
+ return;
77
+ }
78
+ const caret = start + insertion.length;
79
+ applyEdit(view, {
80
+ selectionEnd: caret,
81
+ selectionStart: caret,
82
+ text: text.slice(0, start) +
83
+ insertion +
84
+ text.slice(start + marker.length),
85
+ });
86
+ };
87
+ try {
88
+ const uploaded = await onUploadImage(file);
89
+ replaceMarker(toMarkdownImage({
90
+ alt: uploaded.alt ?? file.name,
91
+ url: uploaded.url,
92
+ }));
93
+ setMessage(`Inserted ${file.name}`);
94
+ }
95
+ catch (error) {
96
+ replaceMarker("");
97
+ setMessage(`Could not upload ${file.name}`);
98
+ onUploadError?.(file, error);
99
+ }
100
+ };
101
+ /**
102
+ * The live-preview markdown editor: Obsidian's model, on CodeMirror.
103
+ *
104
+ * This is the **opt-in** sibling of `MarkdownEditor`, and picking
105
+ * between them is a real decision rather than a preference:
106
+ *
107
+ * | | `MarkdownEditor` | this |
108
+ * | --- | --- | --- |
109
+ * | Surface | `<textarea>` + painted layer | CodeMirror 6 |
110
+ * | New dependency | **none** | ~176 KB gz of optional peer |
111
+ * | Markers | dimmed, never hidden | **concealed** until the caret arrives |
112
+ * | Headings | weight and colour only | **actually larger** |
113
+ * | Images | shown as `![alt](url)` | **rendered in place** |
114
+ * | Undo, IME | the platform's own | CodeMirror's |
115
+ *
116
+ * The default is still the textarea. A component library that makes
117
+ * every consumer install an editor core to render a description
118
+ * field has made the wrong trade, which is why this lives behind
119
+ * `@charcuterie/ui/markdown-editor-codemirror` with every CodeMirror
120
+ * package as an **optional** peer: a consumer that never imports
121
+ * this subpath resolves, installs and audits none of it.
122
+ *
123
+ * ## What is the same, and it is the important part
124
+ *
125
+ * **Markdown is the stored value, byte for byte.** There is no
126
+ * document model here and no serialiser. CodeMirror's state holds
127
+ * the markdown *text*; live preview is a set of decorations
128
+ * *over* that text; concealing `**` hides two characters that are
129
+ * still in the document and still in `onChange`. Every command is
130
+ * the same pure `markdownCommands.ts` the sibling uses, returning
131
+ * markdown in and markdown out.
132
+ *
133
+ * That distinction is the whole reason this is not TipTap or
134
+ * Lexical. Those invert it — their document model is authoritative
135
+ * and markdown becomes a lossy *export* — and the tracker Docket
136
+ * replaces died of exactly that: HTML in a field it later read back
137
+ * as text. An editor core would have been easier to build and is
138
+ * the one thing that could not be allowed.
139
+ *
140
+ * ## What genuinely costs something
141
+ *
142
+ * The `<textarea>` sibling gets caret movement, IME composition,
143
+ * spellcheck, the platform undo stack and `role="textbox"` from the
144
+ * browser, tested by the vendors. A `contenteditable` re-earns each
145
+ * of those, and CodeMirror is the reason that is acceptable rather
146
+ * than reckless: it is the most heavily exercised implementation of
147
+ * that re-earning in the ecosystem. It is still a re-implementation,
148
+ * and that is the honest cost of this subpath.
149
+ *
150
+ * ## Clicking a link opens it
151
+ *
152
+ * Obsidian's behaviour, not VS Code's: where the markup is hidden, a
153
+ * link that looks like a link acts like one. The trade is that you
154
+ * cannot click *into* link text to edit it — arrow in from the edge,
155
+ * or flip the raw-markdown toggle, which is exactly what it is for.
156
+ */
157
+ export const MarkdownEditorCodeMirror = ({ className, defaultValue = "", icons, isDisabled = false, isRawModeDefault = false, isReadOnly = false, label, onChange, onUploadError, onUploadImage, placeholder, rawModeLabel = "Markdown source", toolbarLabel = "Markdown formatting", ...receivedSlotProps }) => {
158
+ const baseId = useUniqueId();
159
+ const hintId = `${baseId}-hint`;
160
+ const hostRef = useRef(null);
161
+ const viewRef = useRef(null);
162
+ const uploadCount = useRef(0);
163
+ const editabilityRef = useRef(new Compartment());
164
+ const [isRawMode, setIsRawMode] = useState(isRawModeDefault);
165
+ const [uploadMessage, setUploadMessage] = useState("");
166
+ /**
167
+ * Callbacks reach the editor through a ref, never a closure.
168
+ *
169
+ * The `EditorView` is built once and lives for the component's
170
+ * whole life — rebuilding it on every render would discard the
171
+ * undo history and the caret. So its extensions capture *this*
172
+ * object, and the render loop keeps the object current.
173
+ */
174
+ const handlersRef = useRef({
175
+ onChange,
176
+ onUploadError,
177
+ onUploadImage,
178
+ });
179
+ handlersRef.current = {
180
+ onChange,
181
+ onUploadError,
182
+ onUploadImage,
183
+ };
184
+ /**
185
+ * The uncontrolled contract, made explicit.
186
+ *
187
+ * These are the props that are **initial only**, frozen at mount
188
+ * in a ref rather than read from the render closure. Writing it
189
+ * this way says the quiet part out loud — changing `placeholder`
190
+ * later genuinely does nothing — and it keeps the build-once
191
+ * effect honestly dependency-free instead of suppressing a lint
192
+ * rule that is, in every other component here, correct.
193
+ */
194
+ const mountRef = useRef({
195
+ ariaDescribedBy: receivedSlotProps["aria-describedby"],
196
+ defaultValue,
197
+ hintId,
198
+ id: receivedSlotProps.id,
199
+ isRawModeDefault,
200
+ label,
201
+ placeholder,
202
+ });
203
+ const runCommand = (command) => {
204
+ const view = viewRef.current;
205
+ if (!view || isDisabled || isReadOnly) {
206
+ return;
207
+ }
208
+ applyEdit(view, command(readSelection(view)));
209
+ };
210
+ /**
211
+ * Built exactly once, and the empty dependency array is the whole
212
+ * point rather than an oversight.
213
+ *
214
+ * An `EditorView` owns the caret, the selection, the scroll
215
+ * position and the undo history. Rebuilding it throws all four
216
+ * away — so a dependency list here would mean that typing a
217
+ * description, then having a parent re-render with a new
218
+ * `placeholder` string, silently drops the user's undo stack
219
+ * mid-sentence. The values read inside are the *initial* half of
220
+ * the uncontrolled contract; everything that can legitimately
221
+ * change afterwards reaches the view through a compartment
222
+ * (editability) or through `handlersRef` (the callbacks).
223
+ *
224
+ * Swapping the document itself — Docket opening a different task —
225
+ * is a `key`, which is honest about the old history belonging to
226
+ * the old document.
227
+ */
228
+ useEffect(() => {
229
+ const host = hostRef.current;
230
+ if (!host) {
231
+ return;
232
+ }
233
+ const view = new EditorView({
234
+ parent: host,
235
+ state: EditorState.create({
236
+ doc: mountRef.current.defaultValue,
237
+ extensions: [
238
+ history(),
239
+ // `Tab` is deliberately absent, at every level: indenting
240
+ // with it is the convention in editors that own the whole
241
+ // page, and inside a form it is a keyboard trap (WCAG
242
+ // 2.1.2). `indentWithTab` is the extension that would add
243
+ // it, and it is not here. Indent is Ctrl+] / Ctrl+[.
244
+ keymap.of([
245
+ {
246
+ key: "Enter",
247
+ run: (target) => {
248
+ const continued = continueList(readSelection(target));
249
+ if (!continued) {
250
+ return false;
251
+ }
252
+ applyEdit(target, continued);
253
+ return true;
254
+ },
255
+ },
256
+ {
257
+ key: "Mod-b",
258
+ run: (target) => {
259
+ applyEdit(target, toggleInlineMarker(readSelection(target), "**"));
260
+ return true;
261
+ },
262
+ },
263
+ {
264
+ key: "Mod-i",
265
+ run: (target) => {
266
+ applyEdit(target, toggleInlineMarker(readSelection(target), "_"));
267
+ return true;
268
+ },
269
+ },
270
+ {
271
+ key: "Mod-e",
272
+ run: (target) => {
273
+ applyEdit(target, toggleInlineMarker(readSelection(target), "`"));
274
+ return true;
275
+ },
276
+ },
277
+ {
278
+ key: "Mod-k",
279
+ run: (target) => {
280
+ applyEdit(target, insertLink(readSelection(target)));
281
+ return true;
282
+ },
283
+ },
284
+ {
285
+ key: "Mod-]",
286
+ run: (target) => {
287
+ applyEdit(target, indentLines(readSelection(target)));
288
+ return true;
289
+ },
290
+ },
291
+ {
292
+ key: "Mod-[",
293
+ run: (target) => {
294
+ applyEdit(target, outdentLines(readSelection(target)));
295
+ return true;
296
+ },
297
+ },
298
+ ...historyKeymap,
299
+ ...defaultKeymap,
300
+ ]),
301
+ // GFM, not strict CommonMark — which is what autolinks a
302
+ // bare URL, renders task lists, and parses tables. A
303
+ // pasted link becoming a link with nothing typed around
304
+ // it falls straight out of this one argument.
305
+ markdown({ base: markdownLanguage }),
306
+ EditorView.lineWrapping,
307
+ livePreview(),
308
+ mountRef.current.placeholder
309
+ ? placeholderExtension(mountRef.current.placeholder)
310
+ : [],
311
+ EditorView.contentAttributes.of({
312
+ ...(mountRef.current.label
313
+ ? { "aria-label": mountRef.current.label }
314
+ : {}),
315
+ /**
316
+ * Named by the `Field` above, when there is one and no
317
+ * `label` was passed.
318
+ *
319
+ * The sibling editor needs none of this: a `<textarea>`
320
+ * is a **labelable** element, so `Field`'s
321
+ * `<label htmlFor>` names it and that is the end of it.
322
+ * This surface is a `div[role="textbox"]`, which is not
323
+ * labelable — `htmlFor` pointing at it names nothing,
324
+ * silently, and axe was the only thing that caught it.
325
+ *
326
+ * `Field` gives its `<label>` the id below for exactly
327
+ * this, and `Field.test.tsx` pins the format.
328
+ */
329
+ ...(mountRef.current.id &&
330
+ !mountRef.current.label
331
+ ? {
332
+ "aria-labelledby": `${mountRef.current.id}-label`,
333
+ }
334
+ : {}),
335
+ // Joined, not replaced. `aria-describedby` is the one
336
+ // slot-props key that is a list, and a `Field` above
337
+ // this component has already written its description and
338
+ // its error into it.
339
+ "aria-describedby": [
340
+ mountRef.current.ariaDescribedBy,
341
+ mountRef.current.hintId,
342
+ ]
343
+ .filter(Boolean)
344
+ .join(" "),
345
+ ...(mountRef.current.id
346
+ ? { id: mountRef.current.id }
347
+ : {}),
348
+ }),
349
+ EditorView.updateListener.of((update) => {
350
+ if (update.docChanged) {
351
+ handlersRef.current.onChange?.(update.state.doc.toString());
352
+ }
353
+ }),
354
+ EditorView.domEventHandlers({
355
+ drop: (event, target) => {
356
+ const files = Array.from(event.dataTransfer?.files ?? []).filter(isImageFile);
357
+ if (files.length === 0 ||
358
+ !handlersRef.current.onUploadImage) {
359
+ return false;
360
+ }
361
+ event.preventDefault();
362
+ for (const file of files) {
363
+ uploadCount.current += 1;
364
+ void uploadImage({
365
+ count: uploadCount.current,
366
+ file,
367
+ handlers: handlersRef.current,
368
+ setMessage: setUploadMessage,
369
+ view: target,
370
+ });
371
+ }
372
+ return true;
373
+ },
374
+ paste: (event, target) => {
375
+ const files = Array.from(event.clipboardData?.files ?? []).filter(isImageFile);
376
+ if (files.length > 0 &&
377
+ handlersRef.current.onUploadImage) {
378
+ event.preventDefault();
379
+ for (const file of files) {
380
+ uploadCount.current += 1;
381
+ void uploadImage({
382
+ count: uploadCount.current,
383
+ file,
384
+ handlers: handlersRef.current,
385
+ setMessage: setUploadMessage,
386
+ view: target,
387
+ });
388
+ }
389
+ return true;
390
+ }
391
+ const pasted = event.clipboardData?.getData("text/plain") ?? "";
392
+ const selection = readSelection(target);
393
+ if (isLinkPaste(pasted) &&
394
+ selection.selectionStart !==
395
+ selection.selectionEnd) {
396
+ event.preventDefault();
397
+ applyEdit(target, wrapSelectionInLink(selection, pasted.trim()));
398
+ return true;
399
+ }
400
+ return false;
401
+ },
402
+ }),
403
+ editabilityRef.current.of([
404
+ EditorView.editable.of(true),
405
+ EditorState.readOnly.of(false),
406
+ ]),
407
+ ],
408
+ }),
409
+ });
410
+ viewRef.current = view;
411
+ if (mountRef.current.isRawModeDefault) {
412
+ view.dispatch({
413
+ effects: setLivePreviewRawMode.of(true),
414
+ });
415
+ }
416
+ return () => {
417
+ view.destroy();
418
+ viewRef.current = null;
419
+ };
420
+ }, []);
421
+ // Editability flips through a compartment rather than a rebuild,
422
+ // so toggling `isReadOnly` keeps the undo history and the caret.
423
+ useEffect(() => {
424
+ const view = viewRef.current;
425
+ if (!view) {
426
+ return;
427
+ }
428
+ const isEditable = !isDisabled && !isReadOnly;
429
+ view.dispatch({
430
+ effects: editabilityRef.current.reconfigure([
431
+ EditorView.editable.of(isEditable),
432
+ EditorState.readOnly.of(!isEditable),
433
+ ]),
434
+ });
435
+ }, [isDisabled, isReadOnly]);
436
+ useEffect(() => {
437
+ viewRef.current?.dispatch({
438
+ effects: setLivePreviewRawMode.of(isRawMode),
439
+ });
440
+ }, [isRawMode]);
441
+ return (_jsxs("div", { className: toClassName(
442
+ // `@container` here rather than on a wrapper: a container
443
+ // query matches a container's *descendants*, never the
444
+ // container itself.
445
+ "@container flex flex-col gap-2 rounded-md border border-border-default bg-surface-base text-content-primary focus-within:outline-solid focus-within:outline-(length:--focus-ring-width) focus-within:outline-offset-(--focus-ring-offset) focus-within:outline-focus-ring",
446
+ // A token pair, never `opacity-*` — fading the whole box
447
+ // fades the hint under it too, and axe measures the
448
+ // *composited* colour.
449
+ isDisabled &&
450
+ "border-border-subtle bg-surface-sunken", className), children: [_jsx("div", { className: "border-border-subtle border-b px-2 pt-2 pb-1", children: _jsx(Toolbar, { items: [
451
+ {
452
+ icon: icons?.bold,
453
+ isDisabled: isDisabled || isReadOnly,
454
+ key: "bold",
455
+ label: "Bold",
456
+ onSelect: () => {
457
+ runCommand((state) => toggleInlineMarker(state, "**"));
458
+ },
459
+ },
460
+ {
461
+ icon: icons?.italic,
462
+ isDisabled: isDisabled || isReadOnly,
463
+ key: "italic",
464
+ label: "Italic",
465
+ onSelect: () => {
466
+ runCommand((state) => toggleInlineMarker(state, "_"));
467
+ },
468
+ },
469
+ {
470
+ icon: icons?.heading,
471
+ isDisabled: isDisabled || isReadOnly,
472
+ key: "heading",
473
+ label: "Heading",
474
+ onSelect: () => {
475
+ runCommand((state) => toggleHeading(state, 2));
476
+ },
477
+ },
478
+ {
479
+ icon: icons?.bulletedList,
480
+ isDisabled: isDisabled || isReadOnly,
481
+ key: "bulleted-list",
482
+ label: "Bulleted list",
483
+ onSelect: () => {
484
+ runCommand((state) => toggleLinePrefix(state, MARKDOWN_LINE_PREFIXES.bulletList));
485
+ },
486
+ },
487
+ {
488
+ icon: icons?.taskList,
489
+ isDisabled: isDisabled || isReadOnly,
490
+ key: "task-list",
491
+ label: "Task list",
492
+ onSelect: () => {
493
+ runCommand((state) => toggleLinePrefix(state, MARKDOWN_LINE_PREFIXES.taskList));
494
+ },
495
+ },
496
+ {
497
+ icon: icons?.numberedList,
498
+ isDisabled: isDisabled || isReadOnly,
499
+ key: "numbered-list",
500
+ label: "Numbered list",
501
+ onSelect: () => {
502
+ runCommand((state) => toggleLinePrefix(state, MARKDOWN_LINE_PREFIXES.orderedList));
503
+ },
504
+ },
505
+ {
506
+ icon: icons?.quote,
507
+ isDisabled: isDisabled || isReadOnly,
508
+ key: "quote",
509
+ label: "Quote",
510
+ onSelect: () => {
511
+ runCommand((state) => toggleLinePrefix(state, MARKDOWN_LINE_PREFIXES.blockquote));
512
+ },
513
+ },
514
+ {
515
+ icon: icons?.code,
516
+ isDisabled: isDisabled || isReadOnly,
517
+ key: "code",
518
+ label: "Code",
519
+ onSelect: () => {
520
+ runCommand((state) => toggleInlineMarker(state, "`"));
521
+ },
522
+ },
523
+ {
524
+ icon: icons?.link,
525
+ isDisabled: isDisabled || isReadOnly,
526
+ key: "link",
527
+ label: "Link",
528
+ onSelect: () => {
529
+ runCommand((state) => insertLink(state));
530
+ },
531
+ },
532
+ {
533
+ /**
534
+ * The "edit Markdown" toggle, as a `Switch` and not a
535
+ * toolbar action — because it is state, not a verb.
536
+ * A `ToolbarAction` renders a `Button`, which
537
+ * announces nothing about being on.
538
+ */
539
+ element: (_jsx(Switch, { isChecked: isRawMode, isDisabled: isDisabled, label: rawModeLabel, onChange: setIsRawMode, size: "sm" })),
540
+ key: "raw-mode",
541
+ type: "control",
542
+ },
543
+ ], label: toolbarLabel, overflow: "panel" }) }), _jsx("div", { className: "min-h-32 px-1 text-md cq-md:min-h-48", ref: hostRef }), _jsxs("div", { className: "flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1 px-3 pb-2", children: [_jsx("p", { className: "sr-only text-content-secondary text-sm cq-sm:not-sr-only", id: hintId, children: "Markdown. Ctrl+B bold, Ctrl+I italic, Ctrl+K link, Ctrl+E code." }), _jsx("span", { "aria-label": "Image upload", className: "text-content-secondary text-sm", role: "status", children: uploadMessage })] })] }));
544
+ };
545
+ //# sourceMappingURL=MarkdownEditorCodeMirror.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownEditorCodeMirror.js","sourceRoot":"","sources":["../../src/markdownEditorCodeMirror/MarkdownEditorCodeMirror.tsx"],"names":[],"mappings":"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"}