@charcuterie/ui 3.0.0 → 3.2.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 (130) hide show
  1. package/README.md +10 -0
  2. package/dist/Badge/Badge.d.ts +33 -3
  3. package/dist/Badge/Badge.d.ts.map +1 -1
  4. package/dist/Badge/Badge.js +20 -2
  5. package/dist/Badge/Badge.js.map +1 -1
  6. package/dist/Board/Board.d.ts +119 -0
  7. package/dist/Board/Board.d.ts.map +1 -0
  8. package/dist/Board/Board.js +165 -0
  9. package/dist/Board/Board.js.map +1 -0
  10. package/dist/Board/BoardCard.d.ts +120 -0
  11. package/dist/Board/BoardCard.d.ts.map +1 -0
  12. package/dist/Board/BoardCard.js +77 -0
  13. package/dist/Board/BoardCard.js.map +1 -0
  14. package/dist/Board/BoardLaneList.d.ts +103 -0
  15. package/dist/Board/BoardLaneList.d.ts.map +1 -0
  16. package/dist/Board/BoardLaneList.js +69 -0
  17. package/dist/Board/BoardLaneList.js.map +1 -0
  18. package/dist/Board/boardMove.d.ts +116 -0
  19. package/dist/Board/boardMove.d.ts.map +1 -0
  20. package/dist/Board/boardMove.js +116 -0
  21. package/dist/Board/boardMove.js.map +1 -0
  22. package/dist/Board/useBoardDrag.d.ts +44 -0
  23. package/dist/Board/useBoardDrag.d.ts.map +1 -0
  24. package/dist/Board/useBoardDrag.js +237 -0
  25. package/dist/Board/useBoardDrag.js.map +1 -0
  26. package/dist/Checkbox/Checkbox.d.ts.map +1 -1
  27. package/dist/Checkbox/Checkbox.js +15 -4
  28. package/dist/Checkbox/Checkbox.js.map +1 -1
  29. package/dist/DataTable/DataTable.d.ts +159 -0
  30. package/dist/DataTable/DataTable.d.ts.map +1 -0
  31. package/dist/DataTable/DataTable.js +197 -0
  32. package/dist/DataTable/DataTable.js.map +1 -0
  33. package/dist/DatePicker/DateGrid.d.ts +79 -0
  34. package/dist/DatePicker/DateGrid.d.ts.map +1 -0
  35. package/dist/DatePicker/DateGrid.js +220 -0
  36. package/dist/DatePicker/DateGrid.js.map +1 -0
  37. package/dist/DatePicker/DatePicker.d.ts +138 -0
  38. package/dist/DatePicker/DatePicker.d.ts.map +1 -0
  39. package/dist/DatePicker/DatePicker.js +384 -0
  40. package/dist/DatePicker/DatePicker.js.map +1 -0
  41. package/dist/DatePicker/datePresets.d.ts +29 -0
  42. package/dist/DatePicker/datePresets.d.ts.map +1 -0
  43. package/dist/DatePicker/datePresets.js +28 -0
  44. package/dist/DatePicker/datePresets.js.map +1 -0
  45. package/dist/DatePicker/parseDateInput.d.ts +106 -0
  46. package/dist/DatePicker/parseDateInput.d.ts.map +1 -0
  47. package/dist/DatePicker/parseDateInput.js +419 -0
  48. package/dist/DatePicker/parseDateInput.js.map +1 -0
  49. package/dist/DatePicker/plainDate.d.ts +167 -0
  50. package/dist/DatePicker/plainDate.d.ts.map +1 -0
  51. package/dist/DatePicker/plainDate.js +272 -0
  52. package/dist/DatePicker/plainDate.js.map +1 -0
  53. package/dist/Dialog/Dialog.d.ts +12 -2
  54. package/dist/Dialog/Dialog.d.ts.map +1 -1
  55. package/dist/Dialog/Dialog.js +2 -2
  56. package/dist/Dialog/Dialog.js.map +1 -1
  57. package/dist/MarkdownEditor/MarkdownEditor.d.ts +147 -0
  58. package/dist/MarkdownEditor/MarkdownEditor.d.ts.map +1 -0
  59. package/dist/MarkdownEditor/MarkdownEditor.js +492 -0
  60. package/dist/MarkdownEditor/MarkdownEditor.js.map +1 -0
  61. package/dist/MarkdownEditor/markdownCommands.d.ts +202 -0
  62. package/dist/MarkdownEditor/markdownCommands.d.ts.map +1 -0
  63. package/dist/MarkdownEditor/markdownCommands.js +379 -0
  64. package/dist/MarkdownEditor/markdownCommands.js.map +1 -0
  65. package/dist/MarkdownEditor/markdownSpans.d.ts +92 -0
  66. package/dist/MarkdownEditor/markdownSpans.d.ts.map +1 -0
  67. package/dist/MarkdownEditor/markdownSpans.js +303 -0
  68. package/dist/MarkdownEditor/markdownSpans.js.map +1 -0
  69. package/dist/Modal/Modal.d.ts +6 -2
  70. package/dist/Modal/Modal.d.ts.map +1 -1
  71. package/dist/Modal/Modal.js +1 -1
  72. package/dist/Modal/Modal.js.map +1 -1
  73. package/dist/Overlay/OverlayPanel.d.ts +13 -2
  74. package/dist/Overlay/OverlayPanel.d.ts.map +1 -1
  75. package/dist/Overlay/OverlayPanel.js +5 -1
  76. package/dist/Overlay/OverlayPanel.js.map +1 -1
  77. package/dist/categoricalStyles.d.ts +53 -0
  78. package/dist/categoricalStyles.d.ts.map +1 -0
  79. package/dist/categoricalStyles.js +195 -0
  80. package/dist/categoricalStyles.js.map +1 -0
  81. package/dist/index.d.ts +22 -0
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +11 -0
  84. package/dist/index.js.map +1 -1
  85. package/package.json +2 -2
  86. package/src/Badge/Badge.mdx +46 -0
  87. package/src/Badge/Badge.stories.tsx +98 -4
  88. package/src/Badge/Badge.test.tsx +157 -2
  89. package/src/Badge/Badge.tsx +49 -3
  90. package/src/Board/Board.mdx +199 -0
  91. package/src/Board/Board.stories.tsx +707 -0
  92. package/src/Board/Board.test.tsx +310 -0
  93. package/src/Board/Board.tsx +333 -0
  94. package/src/Board/BoardCard.tsx +290 -0
  95. package/src/Board/BoardLaneList.tsx +275 -0
  96. package/src/Board/boardMove.test.ts +213 -0
  97. package/src/Board/boardMove.ts +225 -0
  98. package/src/Board/useBoardDrag.ts +413 -0
  99. package/src/Checkbox/Checkbox.tsx +34 -3
  100. package/src/DataTable/DataTable.mdx +123 -0
  101. package/src/DataTable/DataTable.stories.tsx +411 -0
  102. package/src/DataTable/DataTable.test.tsx +386 -0
  103. package/src/DataTable/DataTable.tsx +497 -0
  104. package/src/DatePicker/DateGrid.tsx +467 -0
  105. package/src/DatePicker/DatePicker.mdx +170 -0
  106. package/src/DatePicker/DatePicker.stories.tsx +268 -0
  107. package/src/DatePicker/DatePicker.test.tsx +455 -0
  108. package/src/DatePicker/DatePicker.tsx +852 -0
  109. package/src/DatePicker/datePresets.ts +34 -0
  110. package/src/DatePicker/parseDateInput.test.ts +187 -0
  111. package/src/DatePicker/parseDateInput.ts +629 -0
  112. package/src/DatePicker/plainDate.test.ts +375 -0
  113. package/src/DatePicker/plainDate.ts +465 -0
  114. package/src/Dialog/Dialog.stories.tsx +48 -0
  115. package/src/Dialog/Dialog.test.tsx +30 -0
  116. package/src/Dialog/Dialog.tsx +13 -1
  117. package/src/MarkdownEditor/MarkdownEditor.mdx +189 -0
  118. package/src/MarkdownEditor/MarkdownEditor.stories.tsx +267 -0
  119. package/src/MarkdownEditor/MarkdownEditor.test.tsx +627 -0
  120. package/src/MarkdownEditor/MarkdownEditor.tsx +862 -0
  121. package/src/MarkdownEditor/markdownCommands.test.ts +384 -0
  122. package/src/MarkdownEditor/markdownCommands.ts +566 -0
  123. package/src/MarkdownEditor/markdownSpans.test.ts +217 -0
  124. package/src/MarkdownEditor/markdownSpans.ts +458 -0
  125. package/src/Modal/Modal.tsx +7 -1
  126. package/src/Overlay/OverlayPanel.tsx +17 -1
  127. package/src/argTypes.storyHelpers.ts +39 -0
  128. package/src/categoricalStyles.ts +244 -0
  129. package/src/index.ts +89 -0
  130. package/src/sourceRules.test.ts +52 -1
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Every edit the editor can make, as pure text-in / text-out.
3
+ *
4
+ * Nothing here touches the DOM, so the whole formatting grammar —
5
+ * what Ctrl+B does to a selection that already has asterisks
6
+ * outside it, what Enter does at the end of an empty list item,
7
+ * how an ordered list renumbers when you promote three paragraphs
8
+ * — is a Node test rather than a browser one. That split is not
9
+ * tidiness: the browser suite is where the expensive tests live,
10
+ * and this is the half with all the edge cases.
11
+ *
12
+ * ### Everything is `{ selectionEnd, selectionStart, text }`
13
+ *
14
+ * The same three fields a `<textarea>` exposes, in and out. A
15
+ * command takes the state the control is in and returns the state
16
+ * it should be in, and the component's only job is to get from one
17
+ * to the other without breaking undo.
18
+ *
19
+ * ### And that is what `getMinimalEdit` is for
20
+ *
21
+ * Writing `textarea.value = next` — or handing a controlled React
22
+ * `value` a new string — **erases the browser's undo stack**. Ctrl+Z
23
+ * after a toolbar click then jumps past everything the user typed,
24
+ * or does nothing at all. The fix is to express the change as a
25
+ * *replacement of a range*, select that range, and let the browser
26
+ * apply it through its own editing pipeline
27
+ * (`document.execCommand("insertText", …)`, which is deprecated and
28
+ * is still the only API that appends to the native undo stack).
29
+ *
30
+ * So commands return whole strings, because that is the easy thing
31
+ * to reason about and to test, and `getMinimalEdit` turns the pair
32
+ * back into the range replacement the DOM wants. A bold toggle
33
+ * becomes one undo step covering four characters instead of a
34
+ * document-sized one.
35
+ *
36
+ * ### No HTML, anywhere
37
+ *
38
+ * Every function here returns markdown. There is no serialiser, no
39
+ * intermediate document model, and no HTML string — which is the
40
+ * mechanical reason `<b>` cannot reach the stored value: nothing in
41
+ * this file can produce one, and the surface these run against is a
42
+ * `<textarea>`, which takes `text/plain` off the clipboard and
43
+ * nothing else.
44
+ */
45
+ export type MarkdownSelection = {
46
+ selectionEnd: number;
47
+ selectionStart: number;
48
+ text: string;
49
+ };
50
+ export type MarkdownLinePrefix = {
51
+ /**
52
+ * Matches a line that **already is** this kind, which is what
53
+ * decides whether the toggle adds or removes.
54
+ */
55
+ pattern: RegExp;
56
+ /**
57
+ * What to take off before adding — wider than `pattern`, and the
58
+ * two genuinely differ. A task list *detects* `- [ ] `, because a
59
+ * plain bullet is not a task; but it *strips* the bare `- ` too,
60
+ * so toggling a task on an existing bullet replaces the marker
61
+ * instead of producing `- - [ ] `. Collapsing these into one
62
+ * regex is how that bug gets written.
63
+ */
64
+ stripPattern: RegExp;
65
+ /**
66
+ * The prefix to add, given the line's zero-based position inside
67
+ * the selection. Ordered lists are the only kind that uses the
68
+ * argument, and it is why this is a function.
69
+ */
70
+ toPrefix: (indexInSelection: number) => string;
71
+ };
72
+ /**
73
+ * The prefixes the toolbar and the shortcuts drive, written out
74
+ * rather than derived.
75
+ *
76
+ * `task` deliberately matches a plain bullet's prefix *plus* the
77
+ * checkbox, so toggling a task on an existing `- item` replaces the
78
+ * bullet rather than nesting one inside the other.
79
+ */
80
+ export declare const MARKDOWN_LINE_PREFIXES: {
81
+ readonly blockquote: {
82
+ readonly pattern: RegExp;
83
+ readonly stripPattern: RegExp;
84
+ readonly toPrefix: () => string;
85
+ };
86
+ readonly bulletList: {
87
+ readonly pattern: RegExp;
88
+ readonly stripPattern: RegExp;
89
+ readonly toPrefix: () => string;
90
+ };
91
+ readonly orderedList: {
92
+ readonly pattern: RegExp;
93
+ readonly stripPattern: RegExp;
94
+ readonly toPrefix: (indexInSelection: number) => string;
95
+ };
96
+ readonly taskList: {
97
+ readonly pattern: RegExp;
98
+ readonly stripPattern: RegExp;
99
+ readonly toPrefix: () => string;
100
+ };
101
+ };
102
+ /** The character range of the whole lines a selection touches. */
103
+ export declare const getLineRange: ({ selectionEnd, selectionStart, text, }: MarkdownSelection) => {
104
+ end: number;
105
+ start: number;
106
+ };
107
+ /** Type text over the selection, as if it had been typed. */
108
+ export declare const insertText: ({ selectionEnd, selectionStart, text }: MarkdownSelection, insertion: string) => MarkdownSelection;
109
+ /**
110
+ * Wrap or unwrap a selection in `**`, `_`, `` ` `` or `~~`.
111
+ *
112
+ * Three cases, and the middle one is the one hand-rolled editors
113
+ * miss: the markers may be **outside** the selection. Double-click
114
+ * a word inside `**bold**` and the browser selects `bold`, not
115
+ * `**bold**`, so a naive implementation adds a second pair and
116
+ * produces `****bold****`. Looking just past both ends first is
117
+ * what makes Ctrl+B genuinely a toggle.
118
+ */
119
+ export declare const toggleInlineMarker: ({ selectionEnd, selectionStart, text }: MarkdownSelection, marker: string) => MarkdownSelection;
120
+ /**
121
+ * Add or remove a line prefix across every line the selection
122
+ * touches.
123
+ *
124
+ * Removal wins when **every** line already has the prefix, which is
125
+ * the behaviour that makes the toolbar button a toggle rather than
126
+ * a one-way trip. A mixed block — two bullets and a paragraph —
127
+ * gets the prefix added to all three, because the alternative is a
128
+ * button whose effect depends on invisible state.
129
+ */
130
+ export declare const toggleLinePrefix: (state: MarkdownSelection, { pattern, stripPattern, toPrefix }: MarkdownLinePrefix) => MarkdownSelection;
131
+ /**
132
+ * `#` … `######`, and pressing the same level twice removes it.
133
+ *
134
+ * A heading replaces any heading already on the line rather than
135
+ * stacking, so H2-then-H3 is H3 and not `## ### `.
136
+ */
137
+ export declare const toggleHeading: (state: MarkdownSelection, level: number) => MarkdownSelection;
138
+ /**
139
+ * Markdown-safe `![alt](url)`.
140
+ *
141
+ * The alt text is escaped rather than stripped — a filename with a
142
+ * bracket in it is legal, and silently deleting characters out of
143
+ * somebody's caption is worse than the escape being visible. The
144
+ * destination goes inside angle brackets when it contains anything
145
+ * that would end the destination early, which is the CommonMark
146
+ * spelling for "this whole thing is the URL".
147
+ */
148
+ export declare const toMarkdownImage: ({ alt, url, }: {
149
+ alt?: string;
150
+ url: string;
151
+ }) => string;
152
+ /** Insert an image at the caret, replacing any selection. */
153
+ export declare const insertImage: (state: MarkdownSelection, image: {
154
+ alt?: string;
155
+ url: string;
156
+ }) => MarkdownSelection;
157
+ /**
158
+ * `[selected](url)`, with the caret parked in the destination when
159
+ * there is nothing to put there yet — which is the only reason this
160
+ * is not `toggleInlineMarker` with a funny marker.
161
+ */
162
+ export declare const insertLink: (state: MarkdownSelection, url?: string) => MarkdownSelection;
163
+ /**
164
+ * What Enter should do inside a list, a task list or a blockquote —
165
+ * or `null` when it should do the ordinary thing and the component
166
+ * must not call `preventDefault`.
167
+ *
168
+ * Two behaviours, and the second is the one people notice when it
169
+ * is missing: continuing the marker onto the next line, and
170
+ * **clearing** it when the item is empty. Without the second, an
171
+ * empty bullet is a trap — every Enter makes another empty bullet
172
+ * and the only way out is Backspace.
173
+ *
174
+ * Returning `null` rather than the unchanged state is deliberate.
175
+ * A plain Enter has to fall through to the browser so it lands on
176
+ * the native undo stack as a normal typing step.
177
+ */
178
+ export declare const continueList: ({ selectionEnd, selectionStart, text, }: MarkdownSelection) => MarkdownSelection | null;
179
+ /** Two spaces onto every line the selection touches. */
180
+ export declare const indentLines: (state: MarkdownSelection) => MarkdownSelection;
181
+ /** Up to two spaces, or one tab, off every line. */
182
+ export declare const outdentLines: (state: MarkdownSelection) => MarkdownSelection;
183
+ /**
184
+ * The smallest range replacement that turns `before` into `after`.
185
+ *
186
+ * Whole-string commands are easy to write and easy to test; whole
187
+ * string *assignments* destroy undo. This closes the gap between
188
+ * the two by finding the common prefix and the common suffix and
189
+ * reporting only what is left, so a bold toggle on one word is one
190
+ * four-character edit and one undo step — not a document-sized one
191
+ * that swallows the paragraph the user typed before it.
192
+ *
193
+ * The prefix scan runs first and the suffix scan is bounded by what
194
+ * it left, so the two can never overlap on a repetitive string
195
+ * (`aaaa` → `aaaaa` reports an insert, not a negative range).
196
+ */
197
+ export declare const getMinimalEdit: (before: string, after: string) => {
198
+ end: number;
199
+ start: number;
200
+ text: string;
201
+ };
202
+ //# sourceMappingURL=markdownCommands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdownCommands.d.ts","sourceRoot":"","sources":["../../src/MarkdownEditor/markdownCommands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,QAAQ,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,MAAM,CAAA;CAC/C,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;8CAcF,MAAM;;;;;;;CAQgB,CAAA;AAevD,kEAAkE;AAClE,eAAO,MAAM,YAAY,GAAI,yCAI1B,iBAAiB,KAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAUlD,CAAA;AAsBD,6DAA6D;AAC7D,eAAO,MAAM,UAAU,GACrB,wCAAwC,iBAAiB,EACzD,WAAW,MAAM,KAChB,iBAQC,CAAA;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,GAC7B,wCAAwC,iBAAiB,EACzD,QAAQ,MAAM,KACb,iBAyDF,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,GAC3B,OAAO,iBAAiB,EACxB,qCAAqC,kBAAkB,KACtD,iBA+BF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,iBAAiB,EACxB,OAAO,MAAM,KACZ,iBA+BF,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAAI,eAG7B;IACD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,KAAG,MAYH,CAAA;AAED,6DAA6D;AAC7D,eAAO,MAAM,WAAW,GACtB,OAAO,iBAAiB,EACxB,OAAO;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,KACnC,iBACwC,CAAA;AAE3C;;;;GAIG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,iBAAiB,EACxB,YAAQ,KACP,iBAmBF,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,GAAI,yCAI1B,iBAAiB,KAAG,iBAAiB,GAAG,IA0D1C,CAAA;AAID,wDAAwD;AACxD,eAAO,MAAM,WAAW,GACtB,OAAO,iBAAiB,KACvB,iBAiBF,CAAA;AAED,oDAAoD;AACpD,eAAO,MAAM,YAAY,GACvB,OAAO,iBAAiB,KACvB,iBAiBF,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,GACzB,QAAQ,MAAM,EACd,OAAO,MAAM,KACZ;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CA2B5C,CAAA"}
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Every edit the editor can make, as pure text-in / text-out.
3
+ *
4
+ * Nothing here touches the DOM, so the whole formatting grammar —
5
+ * what Ctrl+B does to a selection that already has asterisks
6
+ * outside it, what Enter does at the end of an empty list item,
7
+ * how an ordered list renumbers when you promote three paragraphs
8
+ * — is a Node test rather than a browser one. That split is not
9
+ * tidiness: the browser suite is where the expensive tests live,
10
+ * and this is the half with all the edge cases.
11
+ *
12
+ * ### Everything is `{ selectionEnd, selectionStart, text }`
13
+ *
14
+ * The same three fields a `<textarea>` exposes, in and out. A
15
+ * command takes the state the control is in and returns the state
16
+ * it should be in, and the component's only job is to get from one
17
+ * to the other without breaking undo.
18
+ *
19
+ * ### And that is what `getMinimalEdit` is for
20
+ *
21
+ * Writing `textarea.value = next` — or handing a controlled React
22
+ * `value` a new string — **erases the browser's undo stack**. Ctrl+Z
23
+ * after a toolbar click then jumps past everything the user typed,
24
+ * or does nothing at all. The fix is to express the change as a
25
+ * *replacement of a range*, select that range, and let the browser
26
+ * apply it through its own editing pipeline
27
+ * (`document.execCommand("insertText", …)`, which is deprecated and
28
+ * is still the only API that appends to the native undo stack).
29
+ *
30
+ * So commands return whole strings, because that is the easy thing
31
+ * to reason about and to test, and `getMinimalEdit` turns the pair
32
+ * back into the range replacement the DOM wants. A bold toggle
33
+ * becomes one undo step covering four characters instead of a
34
+ * document-sized one.
35
+ *
36
+ * ### No HTML, anywhere
37
+ *
38
+ * Every function here returns markdown. There is no serialiser, no
39
+ * intermediate document model, and no HTML string — which is the
40
+ * mechanical reason `<b>` cannot reach the stored value: nothing in
41
+ * this file can produce one, and the surface these run against is a
42
+ * `<textarea>`, which takes `text/plain` off the clipboard and
43
+ * nothing else.
44
+ */
45
+ /**
46
+ * The prefixes the toolbar and the shortcuts drive, written out
47
+ * rather than derived.
48
+ *
49
+ * `task` deliberately matches a plain bullet's prefix *plus* the
50
+ * checkbox, so toggling a task on an existing `- item` replaces the
51
+ * bullet rather than nesting one inside the other.
52
+ */
53
+ export const MARKDOWN_LINE_PREFIXES = {
54
+ blockquote: {
55
+ pattern: /^>[ \t]?/,
56
+ stripPattern: /^>[ \t]?/,
57
+ toPrefix: () => "> ",
58
+ },
59
+ bulletList: {
60
+ pattern: /^[-*+][ \t]+(?:\[[ xX]\][ \t]*)?/,
61
+ stripPattern: /^[-*+][ \t]+(?:\[[ xX]\][ \t]*)?/,
62
+ toPrefix: () => "- ",
63
+ },
64
+ orderedList: {
65
+ pattern: /^\d{1,9}[.)][ \t]+/,
66
+ stripPattern: /^\d{1,9}[.)][ \t]+/,
67
+ toPrefix: (indexInSelection) => `${indexInSelection + 1}. `,
68
+ },
69
+ taskList: {
70
+ pattern: /^[-*+][ \t]+\[[ xX]\][ \t]*/,
71
+ stripPattern: /^[-*+][ \t]+(?:\[[ xX]\][ \t]*)?/,
72
+ toPrefix: () => "- [ ] ",
73
+ },
74
+ };
75
+ const INDENT_PATTERN = /^[ \t]*/;
76
+ const HEADING_PATTERN = /^#{1,6}[ \t]+/;
77
+ /**
78
+ * A continuable line: an ordered item, a bullet, a task, or a
79
+ * blockquote — with its indent, its marker, its optional checkbox
80
+ * and whatever came after them, captured separately so Enter can
81
+ * rebuild the marker without the content.
82
+ */
83
+ const CONTINUABLE_PATTERN = /^([ \t]*)(?:(\d{1,9})([.)])[ \t]+|([-*+])[ \t]+|(>[ \t]?))(\[[ xX]\][ \t]*)?(.*)$/;
84
+ /** The character range of the whole lines a selection touches. */
85
+ export const getLineRange = ({ selectionEnd, selectionStart, text, }) => {
86
+ const start = text.lastIndexOf("\n", selectionStart - 1) + 1;
87
+ const nextNewline = text.indexOf("\n", selectionEnd);
88
+ return {
89
+ end: nextNewline === -1 ? text.length : nextNewline,
90
+ start,
91
+ };
92
+ };
93
+ const replaceRange = ({ end, insertion, selectionEnd, selectionStart, start, text, }) => ({
94
+ selectionEnd,
95
+ selectionStart,
96
+ text: text.slice(0, start) + insertion + text.slice(end),
97
+ });
98
+ /** Type text over the selection, as if it had been typed. */
99
+ export const insertText = ({ selectionEnd, selectionStart, text }, insertion) => replaceRange({
100
+ end: selectionEnd,
101
+ insertion,
102
+ selectionEnd: selectionStart + insertion.length,
103
+ selectionStart: selectionStart + insertion.length,
104
+ start: selectionStart,
105
+ text,
106
+ });
107
+ /**
108
+ * Wrap or unwrap a selection in `**`, `_`, `` ` `` or `~~`.
109
+ *
110
+ * Three cases, and the middle one is the one hand-rolled editors
111
+ * miss: the markers may be **outside** the selection. Double-click
112
+ * a word inside `**bold**` and the browser selects `bold`, not
113
+ * `**bold**`, so a naive implementation adds a second pair and
114
+ * produces `****bold****`. Looking just past both ends first is
115
+ * what makes Ctrl+B genuinely a toggle.
116
+ */
117
+ export const toggleInlineMarker = ({ selectionEnd, selectionStart, text }, marker) => {
118
+ const selected = text.slice(selectionStart, selectionEnd);
119
+ if (selected.length >= marker.length * 2 &&
120
+ selected.startsWith(marker) &&
121
+ selected.endsWith(marker)) {
122
+ const stripped = selected.slice(marker.length, selected.length - marker.length);
123
+ return replaceRange({
124
+ end: selectionEnd,
125
+ insertion: stripped,
126
+ selectionEnd: selectionStart + stripped.length,
127
+ selectionStart,
128
+ start: selectionStart,
129
+ text,
130
+ });
131
+ }
132
+ const isWrappedOutside = text.slice(selectionStart - marker.length, selectionStart) === marker &&
133
+ text.slice(selectionEnd, selectionEnd + marker.length) === marker;
134
+ if (isWrappedOutside) {
135
+ return replaceRange({
136
+ end: selectionEnd + marker.length,
137
+ insertion: selected,
138
+ selectionEnd: selectionStart - marker.length + selected.length,
139
+ selectionStart: selectionStart - marker.length,
140
+ start: selectionStart - marker.length,
141
+ text,
142
+ });
143
+ }
144
+ return replaceRange({
145
+ end: selectionEnd,
146
+ insertion: `${marker}${selected}${marker}`,
147
+ // The caret lands *inside* the new pair when nothing was
148
+ // selected, so Ctrl+B then typing works the way it does in
149
+ // every other editor.
150
+ selectionEnd: selectionStart + marker.length + selected.length,
151
+ selectionStart: selectionStart + marker.length,
152
+ start: selectionStart,
153
+ text,
154
+ });
155
+ };
156
+ /**
157
+ * Add or remove a line prefix across every line the selection
158
+ * touches.
159
+ *
160
+ * Removal wins when **every** line already has the prefix, which is
161
+ * the behaviour that makes the toolbar button a toggle rather than
162
+ * a one-way trip. A mixed block — two bullets and a paragraph —
163
+ * gets the prefix added to all three, because the alternative is a
164
+ * button whose effect depends on invisible state.
165
+ */
166
+ export const toggleLinePrefix = (state, { pattern, stripPattern, toPrefix }) => {
167
+ const { end, start } = getLineRange(state);
168
+ const lines = state.text.slice(start, end).split("\n");
169
+ const hasPrefixEverywhere = lines.every((line) => pattern.test(line.replace(INDENT_PATTERN, "")));
170
+ const nextLines = lines.map((line, indexInSelection) => {
171
+ const indent = INDENT_PATTERN.exec(line)?.[0] ?? "";
172
+ const body = line.slice(indent.length);
173
+ const stripped = body.replace(stripPattern, "");
174
+ return hasPrefixEverywhere
175
+ ? `${indent}${stripped}`
176
+ : `${indent}${toPrefix(indexInSelection)}${stripped}`;
177
+ });
178
+ const insertion = nextLines.join("\n");
179
+ return replaceRange({
180
+ end,
181
+ insertion,
182
+ selectionEnd: start + insertion.length,
183
+ selectionStart: start,
184
+ start,
185
+ text: state.text,
186
+ });
187
+ };
188
+ /**
189
+ * `#` … `######`, and pressing the same level twice removes it.
190
+ *
191
+ * A heading replaces any heading already on the line rather than
192
+ * stacking, so H2-then-H3 is H3 and not `## ### `.
193
+ */
194
+ export const toggleHeading = (state, level) => {
195
+ const { end, start } = getLineRange(state);
196
+ const wanted = `${"#".repeat(level)} `;
197
+ const insertion = state.text
198
+ .slice(start, end)
199
+ .split("\n")
200
+ .map((line) => {
201
+ const indent = INDENT_PATTERN.exec(line)?.[0] ?? "";
202
+ const body = line.slice(indent.length);
203
+ const existing = HEADING_PATTERN.exec(body)?.[0];
204
+ const stripped = body.replace(HEADING_PATTERN, "");
205
+ return existing?.trimEnd() === wanted.trimEnd()
206
+ ? `${indent}${stripped}`
207
+ : `${indent}${wanted}${stripped}`;
208
+ })
209
+ .join("\n");
210
+ return replaceRange({
211
+ end,
212
+ insertion,
213
+ selectionEnd: start + insertion.length,
214
+ selectionStart: start,
215
+ start,
216
+ text: state.text,
217
+ });
218
+ };
219
+ /**
220
+ * Markdown-safe `![alt](url)`.
221
+ *
222
+ * The alt text is escaped rather than stripped — a filename with a
223
+ * bracket in it is legal, and silently deleting characters out of
224
+ * somebody's caption is worse than the escape being visible. The
225
+ * destination goes inside angle brackets when it contains anything
226
+ * that would end the destination early, which is the CommonMark
227
+ * spelling for "this whole thing is the URL".
228
+ */
229
+ export const toMarkdownImage = ({ alt = "", url, }) => {
230
+ const safeAlt = alt
231
+ .replace(/[\r\n]+/g, " ")
232
+ .replace(/([\\[\]])/g, "\\$1");
233
+ const flatUrl = url.replace(/[\r\n]+/g, "");
234
+ const safeUrl = /[\s()<>]/.test(flatUrl)
235
+ ? `<${flatUrl.replace(/([<>])/g, "\\$1")}>`
236
+ : flatUrl;
237
+ return `![${safeAlt}](${safeUrl})`;
238
+ };
239
+ /** Insert an image at the caret, replacing any selection. */
240
+ export const insertImage = (state, image) => insertText(state, toMarkdownImage(image));
241
+ /**
242
+ * `[selected](url)`, with the caret parked in the destination when
243
+ * there is nothing to put there yet — which is the only reason this
244
+ * is not `toggleInlineMarker` with a funny marker.
245
+ */
246
+ export const insertLink = (state, url = "") => {
247
+ const selected = state.text.slice(state.selectionStart, state.selectionEnd);
248
+ const insertion = `[${selected}](${url})`;
249
+ const destinationStart = state.selectionStart + selected.length + 3;
250
+ return replaceRange({
251
+ end: state.selectionEnd,
252
+ insertion,
253
+ selectionEnd: destinationStart + url.length,
254
+ selectionStart: destinationStart,
255
+ start: state.selectionStart,
256
+ text: state.text,
257
+ });
258
+ };
259
+ /**
260
+ * What Enter should do inside a list, a task list or a blockquote —
261
+ * or `null` when it should do the ordinary thing and the component
262
+ * must not call `preventDefault`.
263
+ *
264
+ * Two behaviours, and the second is the one people notice when it
265
+ * is missing: continuing the marker onto the next line, and
266
+ * **clearing** it when the item is empty. Without the second, an
267
+ * empty bullet is a trap — every Enter makes another empty bullet
268
+ * and the only way out is Backspace.
269
+ *
270
+ * Returning `null` rather than the unchanged state is deliberate.
271
+ * A plain Enter has to fall through to the browser so it lands on
272
+ * the native undo stack as a normal typing step.
273
+ */
274
+ export const continueList = ({ selectionEnd, selectionStart, text, }) => {
275
+ if (selectionStart !== selectionEnd) {
276
+ return null;
277
+ }
278
+ const lineStart = text.lastIndexOf("\n", selectionStart - 1) + 1;
279
+ const line = text.slice(lineStart, selectionStart);
280
+ const match = CONTINUABLE_PATTERN.exec(line);
281
+ if (!match) {
282
+ return null;
283
+ }
284
+ const [, indent = "", orderedNumber, orderedDelimiter, bullet, quote, checkbox, content = "",] = match;
285
+ if (content === "") {
286
+ // An empty item: clear the marker instead of making another
287
+ // one. The line becomes its own indent, and the caret sits at
288
+ // the end of it.
289
+ return replaceRange({
290
+ end: selectionStart,
291
+ insertion: indent,
292
+ selectionEnd: lineStart + indent.length,
293
+ selectionStart: lineStart + indent.length,
294
+ start: lineStart,
295
+ text,
296
+ });
297
+ }
298
+ const nextMarker = orderedNumber === undefined
299
+ ? `${bullet ?? quote ?? ""}${quote === undefined ? " " : ""}`
300
+ : `${Number(orderedNumber) + 1}${orderedDelimiter ?? "."} `;
301
+ const insertion = `\n${indent}${nextMarker}${checkbox === undefined ? "" : "[ ] "}`;
302
+ return replaceRange({
303
+ end: selectionEnd,
304
+ insertion,
305
+ selectionEnd: selectionStart + insertion.length,
306
+ selectionStart: selectionStart + insertion.length,
307
+ start: selectionStart,
308
+ text,
309
+ });
310
+ };
311
+ const INDENT_UNIT = " ";
312
+ /** Two spaces onto every line the selection touches. */
313
+ export const indentLines = (state) => {
314
+ const { end, start } = getLineRange(state);
315
+ const insertion = state.text
316
+ .slice(start, end)
317
+ .split("\n")
318
+ .map((line) => `${INDENT_UNIT}${line}`)
319
+ .join("\n");
320
+ return replaceRange({
321
+ end,
322
+ insertion,
323
+ selectionEnd: start + insertion.length,
324
+ selectionStart: start,
325
+ start,
326
+ text: state.text,
327
+ });
328
+ };
329
+ /** Up to two spaces, or one tab, off every line. */
330
+ export const outdentLines = (state) => {
331
+ const { end, start } = getLineRange(state);
332
+ const insertion = state.text
333
+ .slice(start, end)
334
+ .split("\n")
335
+ .map((line) => line.replace(/^(?: {1,2}|\t)/, ""))
336
+ .join("\n");
337
+ return replaceRange({
338
+ end,
339
+ insertion,
340
+ selectionEnd: start + insertion.length,
341
+ selectionStart: start,
342
+ start,
343
+ text: state.text,
344
+ });
345
+ };
346
+ /**
347
+ * The smallest range replacement that turns `before` into `after`.
348
+ *
349
+ * Whole-string commands are easy to write and easy to test; whole
350
+ * string *assignments* destroy undo. This closes the gap between
351
+ * the two by finding the common prefix and the common suffix and
352
+ * reporting only what is left, so a bold toggle on one word is one
353
+ * four-character edit and one undo step — not a document-sized one
354
+ * that swallows the paragraph the user typed before it.
355
+ *
356
+ * The prefix scan runs first and the suffix scan is bounded by what
357
+ * it left, so the two can never overlap on a repetitive string
358
+ * (`aaaa` → `aaaaa` reports an insert, not a negative range).
359
+ */
360
+ export const getMinimalEdit = (before, after) => {
361
+ const shortest = Math.min(before.length, after.length);
362
+ let start = 0;
363
+ while (start < shortest &&
364
+ before[start] === after[start]) {
365
+ start += 1;
366
+ }
367
+ let suffix = 0;
368
+ while (suffix < shortest - start &&
369
+ before[before.length - 1 - suffix] ===
370
+ after[after.length - 1 - suffix]) {
371
+ suffix += 1;
372
+ }
373
+ return {
374
+ end: before.length - suffix,
375
+ start,
376
+ text: after.slice(start, after.length - suffix),
377
+ };
378
+ };
379
+ //# sourceMappingURL=markdownCommands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdownCommands.js","sourceRoot":"","sources":["../../src/MarkdownEditor/markdownCommands.ts"],"names":[],"mappings":"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"}