quoin-editor 0.4.2 → 1.0.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 (231) hide show
  1. package/CHANGELOG.md +205 -0
  2. package/MIGRATION.md +233 -0
  3. package/README.md +78 -716
  4. package/dist/ai.cjs +1107 -0
  5. package/dist/ai.cjs.map +1 -0
  6. package/dist/ai.d.cts +68 -0
  7. package/dist/ai.d.ts +68 -0
  8. package/dist/ai.js +1107 -0
  9. package/dist/ai.js.map +1 -0
  10. package/dist/catalogue.cjs +59 -0
  11. package/dist/catalogue.cjs.map +1 -0
  12. package/dist/catalogue.d.cts +39 -0
  13. package/dist/catalogue.d.ts +39 -0
  14. package/dist/catalogue.js +59 -0
  15. package/dist/catalogue.js.map +1 -0
  16. package/dist/chunk-2QCRZ7OL.cjs +319 -0
  17. package/dist/chunk-2QCRZ7OL.cjs.map +1 -0
  18. package/dist/chunk-2VDK27IF.cjs +6666 -0
  19. package/dist/chunk-2VDK27IF.cjs.map +1 -0
  20. package/dist/chunk-47MLKSI2.js +326 -0
  21. package/dist/chunk-47MLKSI2.js.map +1 -0
  22. package/dist/chunk-5DNCCN6X.cjs +326 -0
  23. package/dist/chunk-5DNCCN6X.cjs.map +1 -0
  24. package/dist/chunk-AEJXZBVR.cjs +1378 -0
  25. package/dist/chunk-AEJXZBVR.cjs.map +1 -0
  26. package/dist/chunk-CDELOHDY.cjs +239 -0
  27. package/dist/chunk-CDELOHDY.cjs.map +1 -0
  28. package/dist/chunk-E75EHRPA.cjs +175 -0
  29. package/dist/chunk-E75EHRPA.cjs.map +1 -0
  30. package/dist/chunk-EL2OEJQC.cjs +562 -0
  31. package/dist/chunk-EL2OEJQC.cjs.map +1 -0
  32. package/dist/chunk-GLLXHMH2.cjs +25 -0
  33. package/dist/chunk-GLLXHMH2.cjs.map +1 -0
  34. package/dist/chunk-GTTPVJSD.cjs +3286 -0
  35. package/dist/chunk-GTTPVJSD.cjs.map +1 -0
  36. package/dist/chunk-HELJTLNC.cjs +100 -0
  37. package/dist/chunk-HELJTLNC.cjs.map +1 -0
  38. package/dist/chunk-HJIQT3S5.js +4047 -0
  39. package/dist/chunk-HJIQT3S5.js.map +1 -0
  40. package/dist/chunk-HZSSEYJS.cjs +504 -0
  41. package/dist/chunk-HZSSEYJS.cjs.map +1 -0
  42. package/dist/chunk-JDPTZUBW.js +184 -0
  43. package/dist/chunk-JDPTZUBW.js.map +1 -0
  44. package/dist/chunk-JEIFJHEI.js +14 -0
  45. package/dist/chunk-JEIFJHEI.js.map +1 -0
  46. package/dist/chunk-K574XHMM.js +25 -0
  47. package/dist/chunk-K574XHMM.js.map +1 -0
  48. package/dist/chunk-KAVU6T6J.js +249 -0
  49. package/dist/chunk-KAVU6T6J.js.map +1 -0
  50. package/dist/chunk-KXOBZGQO.js +1378 -0
  51. package/dist/chunk-KXOBZGQO.js.map +1 -0
  52. package/dist/chunk-LCQSG4M6.js +3335 -0
  53. package/dist/chunk-LCQSG4M6.js.map +1 -0
  54. package/dist/chunk-MQ2XQ4MX.js +100 -0
  55. package/dist/chunk-MQ2XQ4MX.js.map +1 -0
  56. package/dist/chunk-ND5XJVK2.cjs +3335 -0
  57. package/dist/chunk-ND5XJVK2.cjs.map +1 -0
  58. package/dist/chunk-NNDYYEW5.js +504 -0
  59. package/dist/chunk-NNDYYEW5.js.map +1 -0
  60. package/dist/chunk-NOKWNK2O.js +319 -0
  61. package/dist/chunk-NOKWNK2O.js.map +1 -0
  62. package/dist/chunk-OMOBMXD5.cjs +57 -0
  63. package/dist/chunk-OMOBMXD5.cjs.map +1 -0
  64. package/dist/chunk-PMWCQSQX.js +239 -0
  65. package/dist/chunk-PMWCQSQX.js.map +1 -0
  66. package/dist/chunk-POBM7MGR.js +30 -0
  67. package/dist/chunk-POBM7MGR.js.map +1 -0
  68. package/dist/chunk-PWUEPDA3.cjs +598 -0
  69. package/dist/chunk-PWUEPDA3.cjs.map +1 -0
  70. package/dist/chunk-PZ4GT5JO.cjs +4047 -0
  71. package/dist/chunk-PZ4GT5JO.cjs.map +1 -0
  72. package/dist/chunk-QAW5NH6S.cjs +14 -0
  73. package/dist/chunk-QAW5NH6S.cjs.map +1 -0
  74. package/dist/chunk-RDG4VI6E.cjs +706 -0
  75. package/dist/chunk-RDG4VI6E.cjs.map +1 -0
  76. package/dist/chunk-RUDWMKYX.js +562 -0
  77. package/dist/chunk-RUDWMKYX.js.map +1 -0
  78. package/dist/chunk-SG37UBDO.js +706 -0
  79. package/dist/chunk-SG37UBDO.js.map +1 -0
  80. package/dist/chunk-SLVDAHHK.cjs +30 -0
  81. package/dist/chunk-SLVDAHHK.cjs.map +1 -0
  82. package/dist/chunk-T7SW6OWV.js +598 -0
  83. package/dist/chunk-T7SW6OWV.js.map +1 -0
  84. package/dist/chunk-TC4DARU2.js +175 -0
  85. package/dist/chunk-TC4DARU2.js.map +1 -0
  86. package/dist/chunk-WQHV3MRE.cjs +184 -0
  87. package/dist/chunk-WQHV3MRE.cjs.map +1 -0
  88. package/dist/chunk-WXMYDXPN.cjs +33 -0
  89. package/dist/chunk-WXMYDXPN.cjs.map +1 -0
  90. package/dist/chunk-XEBWC7ZL.js +57 -0
  91. package/dist/chunk-XEBWC7ZL.js.map +1 -0
  92. package/dist/chunk-ZC24WB7Y.cjs +249 -0
  93. package/dist/chunk-ZC24WB7Y.cjs.map +1 -0
  94. package/dist/chunk-ZGZEJCRV.js +6666 -0
  95. package/dist/chunk-ZGZEJCRV.js.map +1 -0
  96. package/dist/chunk-ZHOSSWUM.js +33 -0
  97. package/dist/chunk-ZHOSSWUM.js.map +1 -0
  98. package/dist/chunk-ZS2WA357.js +3286 -0
  99. package/dist/chunk-ZS2WA357.js.map +1 -0
  100. package/dist/comments.cjs +993 -0
  101. package/dist/comments.cjs.map +1 -0
  102. package/dist/comments.d.cts +88 -0
  103. package/dist/comments.d.ts +88 -0
  104. package/dist/comments.js +993 -0
  105. package/dist/comments.js.map +1 -0
  106. package/dist/diff.cjs +343 -0
  107. package/dist/diff.cjs.map +1 -0
  108. package/dist/diff.d.cts +67 -0
  109. package/dist/diff.d.ts +67 -0
  110. package/dist/diff.js +343 -0
  111. package/dist/diff.js.map +1 -0
  112. package/dist/docx.cjs +854 -0
  113. package/dist/docx.cjs.map +1 -0
  114. package/dist/docx.d.cts +27 -0
  115. package/dist/docx.d.ts +27 -0
  116. package/dist/docx.js +854 -0
  117. package/dist/docx.js.map +1 -0
  118. package/dist/embed-provider-jXwlRmnp.d.cts +19 -0
  119. package/dist/embed-provider-jXwlRmnp.d.ts +19 -0
  120. package/dist/embed.cjs +17 -0
  121. package/dist/embed.cjs.map +1 -0
  122. package/dist/embed.d.cts +56 -0
  123. package/dist/embed.d.ts +56 -0
  124. package/dist/embed.js +17 -0
  125. package/dist/embed.js.map +1 -0
  126. package/dist/emoji-data.cjs +1968 -0
  127. package/dist/emoji-data.cjs.map +1 -0
  128. package/dist/emoji-data.js +1968 -0
  129. package/dist/emoji-data.js.map +1 -0
  130. package/dist/emoji-extension-C12gDPm6.d.cts +46 -0
  131. package/dist/emoji-extension-DpQ43HjE.d.ts +46 -0
  132. package/dist/emoji.cjs +18 -0
  133. package/dist/emoji.cjs.map +1 -0
  134. package/dist/emoji.d.cts +31 -0
  135. package/dist/emoji.d.ts +31 -0
  136. package/dist/emoji.js +18 -0
  137. package/dist/emoji.js.map +1 -0
  138. package/dist/engine.cjs +119 -0
  139. package/dist/engine.cjs.map +1 -0
  140. package/dist/engine.d.cts +144 -0
  141. package/dist/engine.d.ts +144 -0
  142. package/dist/engine.js +119 -0
  143. package/dist/engine.js.map +1 -0
  144. package/dist/find-extension-DKqLLSuP.d.ts +41 -0
  145. package/dist/find-extension-_sbZEt3R.d.cts +41 -0
  146. package/dist/find.cjs +20 -0
  147. package/dist/find.cjs.map +1 -0
  148. package/dist/find.d.cts +44 -0
  149. package/dist/find.d.ts +44 -0
  150. package/dist/find.js +20 -0
  151. package/dist/find.js.map +1 -0
  152. package/dist/headless.cjs +151 -518
  153. package/dist/headless.cjs.map +1 -1
  154. package/dist/headless.d.cts +102 -69
  155. package/dist/headless.d.ts +102 -69
  156. package/dist/headless.js +149 -467
  157. package/dist/headless.js.map +1 -1
  158. package/dist/index-CgD72kHB.d.cts +65 -0
  159. package/dist/index-DNYbTK3w.d.ts +65 -0
  160. package/dist/index.cjs +183 -2753
  161. package/dist/index.cjs.map +1 -1
  162. package/dist/index.d.cts +345 -253
  163. package/dist/index.d.ts +345 -253
  164. package/dist/index.js +168 -2696
  165. package/dist/index.js.map +1 -1
  166. package/dist/math.cjs +18 -0
  167. package/dist/math.cjs.map +1 -0
  168. package/dist/math.d.cts +49 -0
  169. package/dist/math.d.ts +49 -0
  170. package/dist/math.js +18 -0
  171. package/dist/math.js.map +1 -0
  172. package/dist/mention.cjs +18 -0
  173. package/dist/mention.cjs.map +1 -0
  174. package/dist/mention.d.cts +50 -0
  175. package/dist/mention.d.ts +50 -0
  176. package/dist/mention.js +18 -0
  177. package/dist/mention.js.map +1 -0
  178. package/dist/presence.cjs +565 -0
  179. package/dist/presence.cjs.map +1 -0
  180. package/dist/presence.d.cts +30 -0
  181. package/dist/presence.d.ts +30 -0
  182. package/dist/presence.js +565 -0
  183. package/dist/presence.js.map +1 -0
  184. package/dist/registry-CWBOSAHm.d.cts +121 -0
  185. package/dist/registry-CWBOSAHm.d.ts +121 -0
  186. package/dist/stats-extension-Bly88uio.d.ts +40 -0
  187. package/dist/stats-extension-CJPijvUb.d.cts +40 -0
  188. package/dist/stats.cjs +19 -0
  189. package/dist/stats.cjs.map +1 -0
  190. package/dist/stats.d.cts +19 -0
  191. package/dist/stats.d.ts +19 -0
  192. package/dist/stats.js +19 -0
  193. package/dist/stats.js.map +1 -0
  194. package/dist/styles.css +1 -1
  195. package/dist/table-extension-BTLxFy2S.d.cts +57 -0
  196. package/dist/table-extension-Dzf4k6hI.d.ts +57 -0
  197. package/dist/table.cjs +50 -0
  198. package/dist/table.cjs.map +1 -0
  199. package/dist/table.d.cts +57 -0
  200. package/dist/table.d.ts +57 -0
  201. package/dist/table.js +50 -0
  202. package/dist/table.js.map +1 -0
  203. package/dist/to-html-C5t7xyaM.d.ts +21 -0
  204. package/dist/to-html-CNCITCln.d.cts +21 -0
  205. package/dist/toc-extension-B3-s6h2x.d.cts +25 -0
  206. package/dist/toc-extension-DWm5alVj.d.ts +25 -0
  207. package/dist/toc.cjs +18 -0
  208. package/dist/toc.cjs.map +1 -0
  209. package/dist/toc.d.cts +24 -0
  210. package/dist/toc.d.ts +24 -0
  211. package/dist/toc.js +18 -0
  212. package/dist/toc.js.map +1 -0
  213. package/dist/types-Cz7XJLaK.d.cts +366 -0
  214. package/dist/types-DULc8wwg.d.cts +120 -0
  215. package/dist/types-DULc8wwg.d.ts +120 -0
  216. package/dist/types-a1CRBlEh.d.ts +366 -0
  217. package/dist/view-controller-DSHw0ltQ.d.cts +118 -0
  218. package/dist/view-controller-UbpzblGl.d.ts +118 -0
  219. package/dist/view.cjs +23 -0
  220. package/dist/view.cjs.map +1 -0
  221. package/dist/view.d.cts +40 -0
  222. package/dist/view.d.ts +40 -0
  223. package/dist/view.js +23 -0
  224. package/dist/view.js.map +1 -0
  225. package/dist/yjs.cjs +1026 -0
  226. package/dist/yjs.cjs.map +1 -0
  227. package/dist/yjs.d.cts +22 -0
  228. package/dist/yjs.d.ts +22 -0
  229. package/dist/yjs.js +1026 -0
  230. package/dist/yjs.js.map +1 -0
  231. package/package.json +217 -18
package/dist/index.d.ts CHANGED
@@ -1,154 +1,242 @@
1
- import * as React from 'react';
1
+ import * as react from 'react';
2
2
  import { ComponentType } from 'react';
3
- import { LucideIcon } from 'lucide-react';
3
+ import { A as AnyBlockDefinition, U as UploadFn, C as CodeHighlighter, a as UploadResult } from './registry-CWBOSAHm.js';
4
+ export { B as BlockDefinition, b as BlockEditorProps, c as BlockPreviewProps, e as CodeToken, f as blockByType, d as defineBlock, p as paletteBlocks } from './registry-CWBOSAHm.js';
5
+ import { Q as QuoinBlock, P as Pos } from './types-DULc8wwg.js';
6
+ export { b as AtomNode, c as AtomSpec, A as Attrs, B as BlockAttrs, d as BlockContent, e as BlockFlow, f as BlockRangeSelection, g as BlockSpec, C as CodecContext, h as EngineBlock, E as EngineDoc, I as Inline, i as InlineCodec, j as InlineNode, M as Mark, k as MarkSpec, l as MarkdownExportContext, N as NodeSelection, m as ParseInlineOptions, S as Schema, a as Selection, n as SerializeInlineOptions, T as TextNode, o as TextSelection } from './types-DULc8wwg.js';
7
+ import { E as Extension, a as Editor, c as EditorState, b as Command } from './types-a1CRBlEh.js';
8
+ export { A as Align, e as Assoc, B as BlockStructureOptions, f as BoundCommands, g as Chain, C as CommandFactories, h as CoreCommands, i as CoreExtensionOptions, j as CreatedBlock, k as DOMParserLike, D as Decoration, l as EditorOptions, F as FromHTMLOptions, I as InputRule, m as InputRuleContext, n as InputRuleRange, o as InsertTextOptions, K as KeyLike, M as MarkdownOptions, p as PasteRule, P as PluginKey, d as PluginSpec, q as PosMap, r as Slice, S as Step, s as StepJSON, t as StepResult, u as TextStats, T as Transaction, v as TransactionOrigin, w as applyTransaction, x as coreExtensions, y as createEditor, z as createPluginKey, G as createState, H as fromHTML, J as getPluginState, L as insertBlockAfter, N as insertText, O as insertTextWithRules, Q as keyName, R as normalizeKey, U as setBlockType, V as toggleMark } from './types-a1CRBlEh.js';
9
+ import { PALETTE } from './engine.js';
10
+ export { AttrsPatch, BlockChange, BlockCodec, BlockDiff, FromMarkdownOptions, InlineChange, SchemaInput, ToMarkdownOptions, addMarkStep, atom, blockInputRules, blockRangeSelection, coreBlockSpecs, countDoc, countText, createBlockCodec, createSchema, defineExtension, diffBlocks, diffInline, fromMarkdown, insertBlocksStep, joinBlocksStep, markInputRules, moveBlocksStep, nodeSelection, normalizeInline, parseInline, redo, removeBlocksStep, removeMarkStep, replaceBlockStep, replaceDocStep, replaceInlineStep, sanitizeHref, serializeInline, setAttrsStep, setIndentStep, splitBlockStep, stepFromJSON, text, textSelection, toMarkdown, toPlainText, typographyRules, undo } from './engine.js';
11
+ import { V as ViewController, R as RenderOptions } from './view-controller-UbpzblGl.js';
12
+ export { A as AtomRenderer, K as KeyInterceptor, a as ViewControllerOptions, W as WidgetRenderer, h as hostKey } from './view-controller-UbpzblGl.js';
13
+ import { BlockRenderer } from './headless.js';
14
+ export { BlockLabel, BlockPlaceholder, BlockRenderProps, BlockShell, DomMap, DomPoint, EditableRegion, EditableRegionProps, EditorView, EditorViewProps, SelectionSink, UseQuoinEditorOptions, VoidBlockFallback, caretFromPoint, defaultRenderers, domMapOf, isCrossSelection, renderInline, useEditorState, useQuoinEditor, useViewController } from './headless.js';
15
+ export { E as EmbedProvider, a as EmbedUrl } from './embed-provider-jXwlRmnp.js';
16
+ export { H as HTMLOptions, t as toHTML } from './to-html-C5t7xyaM.js';
4
17
 
5
- /** A document is an ordered array of these; `type` is looked up in the registered block definitions. */
6
- type QuoinBlock = {
7
- id: string;
8
- type: string;
9
- data: Record<string, unknown>;
10
- };
11
- /** What your upload function resolves with so Quoin can reference the stored file later. */
12
- type UploadResult = {
13
- /** Opaque key your storage uses to find the file again. */
14
- storageKey: string;
15
- filename: string;
16
- size: number;
17
- /** Your own record id for the file, if you track one. */
18
- assetId?: string;
19
- };
20
- /**
21
- * Stores a file and returns its key. Quoin never performs the request itself.
22
- * `category` names what the file is for (for example an image or a recording) so you can route it.
23
- * Reject with an Error whose message is safe to show the user: it is rendered
24
- * verbatim beside the upload button. A non-Error rejection or an empty message shows a generic "Upload failed." instead.
25
- * A raw `fetch` rejection such as "Failed to fetch" would surface verbatim, so catch and rethrow with your own wording.
26
- * The control is disabled while an upload is in flight.
27
- */
28
- type UploadFn = (file: File, category: string) => Promise<UploadResult>;
29
- /** Props for a block's read-only rendering, which is what you see for every block you are not editing. */
30
- type BlockPreviewProps<D = Record<string, unknown>> = {
31
- data: D;
32
- /** Id of the block being drawn, for anchors and keys. */
33
- blockId?: string;
34
- };
35
- /** Props for a block's editing surface; call `onChange` with the whole next data, not a patch. */
36
- type BlockEditorProps<D = Record<string, unknown>> = {
37
- data: D;
38
- onChange: (data: D) => void;
39
- /** Inserts a new block of the given type after this one. */
40
- onInsertBlock?: (type: string) => void;
41
- /** Leaves edit mode and returns to the preview. */
42
- onDone?: () => void;
43
- };
18
+ type PaletteName = (typeof PALETTE)[number];
44
19
 
45
- /** The fields every block definition carries, whatever it can do with its data. */
46
- type BlockDefinitionCommon<D extends object> = {
47
- type: string;
48
- label: string;
49
- icon: LucideIcon;
50
- /**
51
- * Called when a new block of this type is inserted, to seed its data.
52
- * `NoInfer` keeps `D` inferred from `editor` and `preview` alone, so the seed is checked
53
- * against the editor's data type instead of widening it.
54
- */
55
- initialData?: () => NoInfer<D>;
56
- /** Whether the block is offered in the slash palette and inserter; defaults to true. */
57
- inSlashPalette?: boolean;
58
- /**
59
- * Renders this block's editor permanently instead of a preview you click to edit.
60
- * Also supply a `preview`: a read-only canvas draws the preview rather than the editor,
61
- * so without one the block's content is invisible there.
62
- */
63
- alwaysEditing?: boolean;
20
+ type SlashGroup = 'basic' | 'lists' | 'media' | 'advanced' | 'embeds' | 'ai' | 'custom';
21
+ type CalloutTone = 'info' | 'tip' | 'success' | 'warning' | 'danger';
22
+ /** The block types the menus name. Headings are named by `heading`. */
23
+ type BlockName = 'text' | 'bulletedList' | 'numberedList' | 'todoList' | 'quote' | 'callout' | 'toggle' | 'code' | 'divider' | 'image' | 'file';
24
+ /** The slash commands that insert a block, which the menu explains under their names. */
25
+ type SlashBlockCommand = BlockName | 'heading1' | 'heading2' | 'heading3';
26
+ type ModifierKey = 'ctrl' | 'alt' | 'shift';
27
+ /** The keys a shortcut writes out by name rather than by the character they type. */
28
+ type NamedKey = 'escape' | 'tab' | 'enter' | 'space' | 'backspace' | 'delete' | 'f10';
29
+ type ShortcutGroupName = 'text' | 'blocks' | 'selection' | 'navigation' | 'menus';
30
+ /** The rows of the keyboard shortcuts dialog that no other label names. */
31
+ type ShortcutName = 'lineBreak' | 'flipBlock' | 'selectBlock' | 'openBlockEditor' | 'leaveBlockEditor' | 'selectAll' | 'extendUp' | 'extendDown' | 'lineUp' | 'lineDown' | 'leaveEditor' | 'blockMenu' | 'closeMenu' | 'splitBlock' | 'joinAbove' | 'joinBelow' | 'previousBlockEnd' | 'nextBlockStart';
32
+ /** Every string the editor shows or speaks. A label that depends on a value is a function of it. */
33
+ type QuoinLabels = {
34
+ document: string;
35
+ editorHint: string;
36
+ paragraph: string;
37
+ heading: (level: number) => string;
38
+ bulletItem: string;
39
+ numberedItem: (n: number) => string;
40
+ task: string;
41
+ quote: string;
42
+ /** The name of a callout's text, given the name of its tone from `calloutTones`, which it takes as written. */
43
+ callout: (tone: string) => string;
44
+ /** The name of each tone, on its chip and in its menus as inside the name of a callout's text. */
45
+ calloutTones: Record<CalloutTone, string>;
46
+ calloutIcon: string;
47
+ /** The name of the button that shows a callout's tone and opens the menu of tones, given the tone's name. */
48
+ calloutToneMenu: (tone: string) => string;
49
+ toggle: string;
50
+ /** The name of a toggle's chevron, given how many blocks the closed toggle hides, 0 while it is open. */
51
+ toggleButton: (hidden: number) => string;
52
+ placeholderEmpty: string;
53
+ placeholderHeading: (level: number) => string;
54
+ placeholderList: string;
55
+ placeholderQuote: string;
56
+ blockMenu: (type: string) => string;
57
+ blockNames: Record<BlockName, string>;
58
+ turnInto: string;
59
+ color: string;
60
+ textColor: string;
61
+ backgroundColor: string;
62
+ /** The submenus of a callout's block menu that set its tone and its icon. */
63
+ tone: string;
64
+ icon: string;
65
+ duplicate: string;
66
+ copy: string;
67
+ copyLink: string;
68
+ copied: string;
69
+ moveUp: string;
70
+ moveDown: string;
71
+ delete: string;
72
+ askAi: string;
73
+ addBelow: string;
74
+ dragHandle: string;
75
+ slashMenu: string;
76
+ noResults: string;
77
+ /** What the open slash menu says once its list settles, given how many commands match. */
78
+ resultCount: (n: number) => string;
79
+ slashDescriptions: Record<SlashBlockCommand, string>;
80
+ groups: Record<SlashGroup, string>;
81
+ bold: string;
82
+ italic: string;
83
+ underline: string;
84
+ strike: string;
85
+ code: string;
86
+ link: string;
87
+ highlight: string;
88
+ align: string;
89
+ alignLeft: string;
90
+ alignCenter: string;
91
+ alignRight: string;
92
+ alignJustify: string;
93
+ subscript: string;
94
+ superscript: string;
95
+ comment: string;
96
+ linkUrl: string;
97
+ linkApply: string;
98
+ linkRemove: string;
99
+ linkOpen: string;
100
+ linkEdit: string;
101
+ invalidLink: string;
102
+ colors: Record<PaletteName, string>;
103
+ blockMoved: (position: number, total: number) => string;
104
+ blockInserted: (position: number, total: number) => string;
105
+ blockDeleted: (n: number) => string;
106
+ blocksSelected: (n: number) => string;
107
+ /** How to bring deleted blocks back, given the platform's undo shortcut. */
108
+ undoHint: (shortcut: string) => string;
109
+ shortcuts: string;
110
+ shortcutGroupNames: Record<ShortcutGroupName, string>;
111
+ shortcutNames: Record<ShortcutName, string>;
112
+ /** Two keys pressed one after the other. */
113
+ keySequence: (first: string, then: string) => string;
114
+ /** Two shortcuts that do the same thing. */
115
+ keyAlternative: (first: string, other: string) => string;
116
+ /** The modifier keys a shortcut hint names away from a Mac, where it draws their symbols instead. */
117
+ keyNames: Record<ModifierKey, string>;
118
+ namedKeys: Record<NamedKey, string>;
119
+ formattingToolbar: string;
120
+ mobileToolbar: string;
121
+ indent: string;
122
+ outdent: string;
123
+ undo: string;
124
+ redo: string;
125
+ close: string;
126
+ selectedContent: string;
127
+ editBlock: (label: string) => string;
128
+ unsupportedBlock: string;
129
+ uploading: string;
130
+ uploaded: (name: string) => string;
131
+ /** What an upload field shows when the host's upload fails without a message of its own. */
132
+ uploadFailed: string;
133
+ /** What an upload field shows in place of working when the canvas was given no upload function. */
134
+ uploadsUnavailable: string;
135
+ /** An empty image block: its upload button, the link it can embed instead and what can be dropped or pasted on it. */
136
+ uploadImage: string;
137
+ embedLink: string;
138
+ imageLink: string;
139
+ dropImage: string;
140
+ /** An image block: its caption, its toolbar, the handles of its width with their value, and the toolbar's buttons. */
141
+ imageCaption: string;
142
+ addCaption: string;
143
+ imageTools: string;
144
+ resizeFromLeft: string;
145
+ resizeFromRight: string;
146
+ widthValue: (percent: number) => string;
147
+ replaceImage: string;
148
+ download: string;
149
+ /** The alt text of an image: its field, what the field asks for, its button, and the name of an image without one. */
150
+ altText: string;
151
+ altTextHint: string;
152
+ save: string;
153
+ imageNoAlt: string;
154
+ /** An empty file block: its upload button and what can be dropped or pasted on it. */
155
+ uploadFile: string;
156
+ dropFile: string;
157
+ /** A file block: its toolbar and the toolbar's replace button. */
158
+ fileTools: string;
159
+ replaceFile: string;
160
+ /** The name of a file's download link, given the file's name. It contains `download`, the link's visible text. */
161
+ downloadFile: (name: string) => string;
162
+ /** The size of a file, given in bytes. */
163
+ fileSize: (bytes: number) => string;
164
+ /** The name of a file block selected as a whole, given the file's name. */
165
+ fileBlockName: (name: string) => string;
166
+ /** A code block: its code, its language, the name of a code in no language, and its copy button. */
167
+ codeText: string;
168
+ /** The name of a code block selected as a whole, given the name of its language. */
169
+ codeBlockName: (language: string) => string;
170
+ codeLanguage: string;
171
+ plainText: string;
172
+ copyCode: string;
173
+ /** What the preview of a block without content says. */
174
+ emptyImage: string;
175
+ emptyFile: string;
176
+ emptyMarkdown: string;
177
+ emptyCallout: string;
64
178
  };
65
- /**
66
- * Describes one block type: how to label it, how to draw it at rest, how to edit it.
67
- *
68
- * Supply `editor`, `preview`, or both, and the canvas does the rest. A definition with no
69
- * `preview` is edit-only: a read-only canvas has nothing to draw for it but its label.
70
- * A definition with no `editor` can never be edited in the canvas, which is what a block
71
- * whose content belongs to a server-side record wants; the card offers no edit affordance
72
- * for it and a click goes through to whatever the preview itself renders.
73
- *
74
- * Omitting both is a type error, because such a block would only ever draw its own label.
75
- */
76
- type BlockDefinition<D extends object = Record<string, unknown>> = (BlockDefinitionCommon<D> & {
77
- editor: ComponentType<BlockEditorProps<D>>;
78
- /**
79
- * What the block shows when it is not being edited. Optional so a host can register an
80
- * edit-only block type, and overridable so a host can supply rich rendering (a full
81
- * markdown pipeline, a chart) without Quoin depending on one.
82
- */
83
- preview?: ComponentType<BlockPreviewProps<D>>;
84
- }) | (BlockDefinitionCommon<D> & {
85
- /** Omitted: this block is never editable in the canvas. */
86
- editor?: undefined;
87
- /** Required here, because it is the only thing that can draw the block. */
88
- preview: ComponentType<BlockPreviewProps<D>>;
89
- });
90
- /** A definition with its data type erased, so definitions of different shapes compose in one array. */
91
- type AnyBlockDefinition = BlockDefinition<Record<string, unknown>>;
92
- /**
93
- * Types `data` inside your editor component, then erases the generic on the way out.
94
- * The erasure is deliberate: `D` appears in both covariant and contravariant positions
95
- * on `editor`, so without it an array of differently-shaped definitions will not typecheck.
96
- * `initialData` is checked against the editor's data type. That relies on `NoInfer`, so
97
- * TypeScript 5.4 or later is required.
98
- *
99
- * `D` defaults to `Record<string, unknown>`, so a definition whose components take no
100
- * annotation still gets a usable `data` rather than a bare `object`.
101
- */
102
- declare function defineBlock<D extends object = Record<string, unknown>>(definition: BlockDefinition<D>): AnyBlockDefinition;
103
- /** The definition for a type, or undefined; the last registration of a type wins, so a host can override a core block. */
104
- declare function blockByType(definitions: AnyBlockDefinition[], type: string): AnyBlockDefinition | undefined;
105
- /** The definitions offered in the slash palette, in registration order, one per type, with the last registration of a type winning. */
106
- declare function paletteBlocks(definitions: AnyBlockDefinition[]): AnyBlockDefinition[];
107
179
 
108
- /** Props for `BlockCanvas`; `blocks` and `onChange` are the whole document contract. */
109
180
  type BlockCanvasProps = {
110
181
  /**
111
- * The document. Update it synchronously from `onChange`, as with a controlled `<input value onChange>`.
112
- * Applying the edit late is tolerated: the canvas recognises an array it emitted however late it comes back, and
113
- * a structural copy of one within 64 edits, so a transition, a debounced setter or a store that clones the
114
- * document on the way through is safe.
115
- * A new array that differs from the last one you supplied replaces what the canvas shows, which is how a host
116
- * loads, undoes or merges. An array structurally equal to the last one you supplied is ignored, so a "discard
117
- * changes" button that hands back the original document does nothing. A host that does not echo `onChange` back
118
- * meets the same when it restores a copy of a state from the last 64 edits, which reads as a late echo. Remount
119
- * the canvas with a React `key` to force a reset in either case. The comparison is shallow over each block's
120
- * `data`: a host whose block `data` holds nested objects rebuilt on every render, and which does not echo
121
- * `onChange` back, can still lose an edit. The core block types all have flat data, so this only affects custom
122
- * blocks.
182
+ * The document, controlled like `<input value onChange>`. An array the canvas emitted, or a copy of one, coming back
183
+ * late is recognised as its echo, and an array structurally equal to the last one supplied is ignored. Any other
184
+ * array replaces the document. Remount with a React `key` to force a reset.
123
185
  */
124
186
  blocks: QuoinBlock[];
125
187
  onChange: (blocks: QuoinBlock[]) => void;
126
188
  /**
127
- * Called when a block is removed through its actions menu, with the block and the index it held.
128
- * It runs just after the `onChange` that reports the document without it, so a host acting on the
129
- * deletion is already looking at the new array. Restore the block by supplying a `blocks` array
130
- * with it spliced back at that index, the same way any other document arrives.
131
- *
132
- * Restore it on a later tick or a later interaction, such as the click of an Undo toast. A
133
- * restore applied synchronously inside this callback batches with the echo of the deletion, so
134
- * what arrives is structurally equal to the document last supplied and is ignored.
189
+ * Called for each whole block the writer removed, with the index it held, once `onChange` has reported the document
190
+ * without it: through a command such as the block menu's Delete, by typing over a selected block, or by pasting over
191
+ * selected blocks. A line that Backspace or Delete merges into its neighbour or drops when empty is not reported, nor
192
+ * a line that pasted blocks take the place of. Restore a block by splicing it back at that index into `blocks` once
193
+ * they no longer hold it, as on a later interaction. A host that applies `onChange` in a transition or after a debounce
194
+ * has not applied the removal when this runs: splicing into its state here duplicates the block, and supplying again
195
+ * an array equal to the one it last supplied is ignored.
135
196
  */
136
197
  onDelete?: (block: QuoinBlock, index: number) => void;
137
- /** Defaults to the five core block types. Pass `[...coreBlocks, yours]` to extend them. */
138
198
  blockTypes?: AnyBlockDefinition[];
199
+ /**
200
+ * Added after the core extensions when the canvas mounts. Remount it with a new `key` to change them. An extension's
201
+ * `ui` field, an `ExtensionUI`, adds slash commands, block menu items, block renderers and overlays to the canvas.
202
+ */
203
+ extensions?: readonly Extension[];
139
204
  upload?: UploadFn;
140
205
  resolveAssetUrl?: (storageKey: string) => string;
141
206
  onError?: (error: Error) => void;
142
- /** Renders the document with no inserters, menus, drag handles or editors. */
207
+ /**
208
+ * Colours the code of code blocks: one array of tokens per line, whose texts spell the line exactly. Keep the function
209
+ * stable, as for `labels`. Without it, or when its tokens do not spell the code, the code is drawn as plain text.
210
+ */
211
+ highlight?: CodeHighlighter;
143
212
  readOnly?: boolean;
144
- /** Added to the root element's own classes rather than replacing them. */
213
+ autoFocus?: boolean;
214
+ /** The text of an empty paragraph holding the caret, or alone in the document, in place of `labels.placeholderEmpty`. */
215
+ placeholder?: string;
216
+ /**
217
+ * Every string the canvas shows or speaks, English by default. A key left out stays English. Keep the object stable,
218
+ * hoisted or memoised: a new one each render re-renders everything that reads the canvas configuration.
219
+ */
220
+ labels?: Partial<QuoinLabels>;
221
+ /**
222
+ * The address the block menu's "Copy link to block" copies. By default the current page with `#block-<id>`, a fragment
223
+ * the canvas follows on load and on hash changes to select the block and scroll it into view.
224
+ */
225
+ blockLink?: (blockId: string) => string;
145
226
  className?: string;
146
227
  id?: string;
147
- /** Names the document for assistive technology; the root then becomes a labelled group. */
148
228
  'aria-label'?: string;
149
229
  };
150
- /** The editor: renders `blocks`, reports every edit through `onChange`, and accepts a new `blocks` array from outside at any time. */
151
- declare function BlockCanvas({ blocks, onChange, onDelete, blockTypes, upload, resolveAssetUrl, onError, readOnly, className, id, 'aria-label': ariaLabel, }: BlockCanvasProps): React.JSX.Element;
230
+ type QuoinEditorHandle = {
231
+ readonly editor: Editor;
232
+ readonly controller: ViewController;
233
+ focus(target?: Pos | 'start' | 'end'): void;
234
+ toMarkdown(options?: {
235
+ comments?: boolean;
236
+ }): string;
237
+ };
238
+
239
+ declare const BlockCanvas: react.ForwardRefExoticComponent<BlockCanvasProps & react.RefAttributes<QuoinEditorHandle>>;
152
240
 
153
241
  /** The block types Quoin ships with. Spread them alongside your own definitions. */
154
242
  declare const coreBlocks: AnyBlockDefinition[];
@@ -160,9 +248,10 @@ declare const coreBlocks: AnyBlockDefinition[];
160
248
  * that writes it and the seed it starts from.
161
249
  *
162
250
  * Every field is declared because something writes it. The optional ones are written
163
- * later than the block's first save: an image's `caption` when the author types one, its
164
- * `width` and `height` once the uploaded bytes have been measured, a file's `size` when
165
- * the upload reports it.
251
+ * later than the block's first save, and only once set: an image's `caption` when the
252
+ * author types one, its `width` and `height` once the uploaded bytes have been measured,
253
+ * its `url`, `align` and `widthPercent` when the author links, aligns or resizes it, a
254
+ * file's `size` when the upload reports it and its `mime` when the file declares a type.
166
255
  */
167
256
  /** `MARKDOWN`. The source text, not rendered HTML: Quoin stores and edits markdown. */
168
257
  type MarkdownBlockData = {
@@ -178,19 +267,30 @@ type CodeBlockData = {
178
267
  language: string;
179
268
  code: string;
180
269
  };
181
- /** `IMAGE`. `storageKey` names the uploaded file; the host's `resolveAssetUrl` turns it into a URL. */
270
+ /**
271
+ * `IMAGE`. `storageKey` names the uploaded file, which the host's `resolveAssetUrl` turns into a URL, unless `url`
272
+ * links a picture instead. `caption` is inline markdown, `width` and `height` the measured size of the upload, and
273
+ * `widthPercent` the share of the line the picture is drawn at.
274
+ */
182
275
  type ImageBlockData = {
183
276
  storageKey: string;
184
277
  alt: string;
185
278
  caption?: string;
186
279
  width?: number;
187
280
  height?: number;
281
+ url?: string;
282
+ align?: 'left' | 'center' | 'right';
283
+ widthPercent?: number;
188
284
  };
189
- /** `FILE`. `storageKey` names the uploaded file; `filename` is what the author picked. */
285
+ /**
286
+ * `FILE`. `storageKey` names the uploaded file, which the host's `resolveAssetUrl` turns into a URL; `filename` is the
287
+ * name the upload kept, `size` its size in bytes and `mime` the type the file declared.
288
+ */
190
289
  type FileBlockData = {
191
290
  storageKey: string;
192
291
  filename: string;
193
292
  size?: number;
293
+ mime?: string;
194
294
  };
195
295
  /** Maps each core block's `type` string to its data shape. */
196
296
  type CoreBlockData = {
@@ -212,8 +312,8 @@ type UploadFieldProps = {
212
312
  /** Called once the upload resolves. The field stays busy until a returned promise settles, and throwing or rejecting is reported through the canvas `onError`. */
213
313
  onUploaded: (result: UploadResult) => void | Promise<void>;
214
314
  };
215
- /** A file picker wired to the canvas `upload` function, with its own busy state and inline error. */
216
- declare function UploadField({ category, label, accept, onUploaded }: UploadFieldProps): React.JSX.Element;
315
+ /** A file picker wired to the canvas `upload` function, with its own busy state, success message and inline error. */
316
+ declare function UploadField({ category, label, accept, onUploaded }: UploadFieldProps): react.JSX.Element;
217
317
 
218
318
  /** Props for `FilePickerButton`. */
219
319
  type FilePickerButtonProps = {
@@ -221,13 +321,15 @@ type FilePickerButtonProps = {
221
321
  label: string;
222
322
  /** An `accept` attribute for the file input, such as `'image/*'` or `'.pdf'`. */
223
323
  accept?: string;
224
- /** Greys the button out and disables the input behind it. */
324
+ /** Greys the button out and disables the input behind it. After a pick, focus the browser dropped while it was disabled comes back once it is enabled again. */
225
325
  disabled?: boolean;
326
+ /** Greys the button out and refuses picks, as `disabled` does, but leaves the input focusable, so focus stays on it while an upload runs. */
327
+ busy?: boolean;
226
328
  /** Called with the chosen file, and again if the same file is picked after a failure. */
227
329
  onPick: (file: File) => void;
228
330
  };
229
331
  /** A button that opens the file picker and hands back the chosen file, performing no upload of its own. */
230
- declare function FilePickerButton({ label, accept, disabled, onPick }: FilePickerButtonProps): React.JSX.Element;
332
+ declare function FilePickerButton({ label, accept, disabled, busy, onPick }: FilePickerButtonProps): react.JSX.Element;
231
333
 
232
334
  /** The resolved canvas configuration every block editor reads through `useQuoin`. */
233
335
  type QuoinConfig = {
@@ -236,42 +338,127 @@ type QuoinConfig = {
236
338
  upload?: UploadFn;
237
339
  resolveAssetUrl: (storageKey: string) => string;
238
340
  onError: (error: Error) => void;
341
+ /** Highlights the code of code blocks; without it their code is drawn as plain text. */
342
+ highlight?: CodeHighlighter;
343
+ /** The controller of the canvas the block is drawn in; null under a provider no canvas set up. */
344
+ controller: ViewController | null;
345
+ labels: QuoinLabels;
239
346
  };
240
347
  /** What a host passes to `QuoinProvider`: only the block types are required. */
241
348
  type QuoinConfigInput = Partial<QuoinConfig> & {
242
349
  blockTypes: AnyBlockDefinition[];
243
350
  };
244
- /** Supplies the block registry and the host couplings (upload, asset URLs, error reporting) to every block below it. */
351
+ /** Supplies the block registry, the host couplings (upload, asset URLs, error reporting, code highlighting), the canvas controller and the labels to every block below it. */
245
352
  declare function QuoinProvider({ value, children, }: {
246
353
  value: QuoinConfigInput;
247
- children: React.ReactNode;
248
- }): React.JSX.Element;
354
+ children: react.ReactNode;
355
+ }): react.JSX.Element;
249
356
  /** Reads the canvas configuration. Throws outside a QuoinProvider rather than returning a silent default. */
250
357
  declare function useQuoin(): QuoinConfig;
251
358
 
252
- /** Handed back by `remove` and accepted by `undo` to restore that one block. */
253
- type UndoToken = number;
254
- /** The document plus every way to change it; `reset` replaces the whole document and voids outstanding undo tokens. */
255
- type BlockList = {
256
- blocks: QuoinBlock[];
257
- insertAt: (index: number, type: string, data?: Record<string, unknown>) => string;
258
- update: (id: string, data: Record<string, unknown>) => void;
259
- /** Returns a token `undo` restores that block with; only the last 20 removals stay restorable. */
260
- remove: (id: string) => UndoToken;
261
- undo: (token: UndoToken) => void;
262
- move: (index: number, dir: -1 | 1) => void;
263
- reorder: (from: number, to: number) => void;
264
- reset: (blocks: QuoinBlock[]) => void;
359
+ declare const englishLabels: QuoinLabels;
360
+
361
+ /** The English labels with the host's overrides on top. A key the host leaves out, or passes as undefined, stays
362
+ * English. */
363
+ declare function resolveLabels(overrides?: Partial<QuoinLabels>): QuoinLabels;
364
+
365
+ type BlockMenuAction = {
366
+ id: string;
367
+ label: string;
368
+ icon: ComponentType<{
369
+ className?: string;
370
+ }>;
371
+ /** A key in the keymap's own form, such as `Mod-d`. */
372
+ shortcut?: string;
373
+ destructive?: boolean;
374
+ run(controller: ViewController, blockIds: string[]): void;
375
+ available?(state: EditorState, blockIds: string[]): boolean;
265
376
  };
266
- /** Holds a document in a reducer and returns its blocks with insert, update, remove, undo, move, reorder and reset. Reads `initial` once. */
267
- declare function useBlockList(initial: QuoinBlock[]): BlockList;
377
+
378
+ type SuggestionRange = {
379
+ block: string;
380
+ region: string;
381
+ from: number;
382
+ to: number;
383
+ };
384
+ type SlashItem = {
385
+ id: string;
386
+ title: string;
387
+ description?: string;
388
+ group: SlashGroup;
389
+ icon?: ComponentType<{
390
+ className?: string;
391
+ }>;
392
+ keywords?: readonly string[];
393
+ /** A key in the keymap's own form, such as `Mod-Alt-1`. */
394
+ shortcut?: string;
395
+ available?(state: EditorState): boolean;
396
+ /**
397
+ * The change the item makes, run once the menu has removed the slash and the query, in the same transaction, so one
398
+ * undo brings the query back. `state` and `range` are those of the moment the item is chosen.
399
+ */
400
+ command?(ctx: {
401
+ state: EditorState;
402
+ range: SuggestionRange;
403
+ }): Command;
404
+ /**
405
+ * Work no command can do, such as opening a dialog, called once the slash and the query are gone. `range` is the
406
+ * empty range where they were.
407
+ */
408
+ run?(ctx: {
409
+ controller: ViewController;
410
+ range: SuggestionRange;
411
+ }): void;
412
+ };
413
+ type ToolbarItem = {
414
+ id: string;
415
+ title: string;
416
+ icon: ComponentType<{
417
+ className?: string;
418
+ }>;
419
+ shortcut?: string;
420
+ isActive?(state: EditorState): boolean;
421
+ available?(state: EditorState): boolean;
422
+ run(controller: ViewController): void;
423
+ };
424
+ /** What an extension adds to the canvas UI, through its `ui` field. */
425
+ type ExtensionUI = {
426
+ slashItems?: readonly SlashItem[];
427
+ bubbleItems?: readonly ToolbarItem[];
428
+ blockMenuItems?: readonly BlockMenuAction[];
429
+ renderers?: Readonly<Record<string, BlockRenderer>>;
430
+ /** What the block types the extension draws are called, in their block menu and while one is selected as a whole. */
431
+ blockNames?: Readonly<Record<string, string>>;
432
+ render?: RenderOptions;
433
+ overlays?: readonly ComponentType<{
434
+ controller: ViewController;
435
+ }>[];
436
+ };
437
+
438
+ /** The labels of the canvas around the caller, English unless its host overrode some. */
439
+ declare function useLabels(): QuoinLabels;
440
+
441
+ /** The words a shortcut is written in: the modifiers away from a Mac, and the keys written out by name. */
442
+ type KeyLabels = Pick<QuoinLabels, 'keyNames' | 'namedKeys'>;
443
+ type ShortcutPlatform = {
444
+ /** Whether to write the keys the way a Mac does. Defaults to the platform the page runs on. */
445
+ isMac?: boolean;
446
+ /** English by default. */
447
+ labels?: KeyLabels;
448
+ };
449
+ /**
450
+ * Writes a shortcut, in the keymap's form such as `Mod-Shift-b` or as `mod+shift+b`, the way the platform does: the
451
+ * Command and Shift symbols then B on a Mac, and `Ctrl+Shift+B` elsewhere.
452
+ */
453
+ declare function formatShortcut(shortcut: string, platform?: ShortcutPlatform): string;
268
454
 
269
455
  /** Where a debounced save stands, for a "Saving..." or "Saved" indicator. */
270
456
  type AutosaveStatus = 'idle' | 'saving' | 'saved' | 'retrying' | 'failed';
457
+
271
458
  /** What `useAutosave` tracks, how to build the payload, and how to persist it. */
272
459
  type UseAutosaveInput<T> = {
273
460
  /** The tracked fields. An edit to any of them marks dirty and restarts the debounce. */
274
- deps: React.DependencyList;
461
+ deps: react.DependencyList;
275
462
  build: () => T;
276
463
  /**
277
464
  * Persists the payload. Return anything: a mutation or a `fetch` that resolves to a body
@@ -310,99 +497,4 @@ type UseAutosaveResult = {
310
497
  */
311
498
  declare function useAutosave<T>({ deps, build, save, debounceMs, maxBackoffMs, maxRetries, isRetryable, flushOnHide, }: UseAutosaveInput<T>): UseAutosaveResult;
312
499
 
313
- /** Height follows the content, and is recomputed when the box gets narrower or
314
- * wider, because a re-wrap changes the line count without changing the value.
315
- * Only a width change refits: reacting to the height this hook just set would
316
- * feed the observer its own output. */
317
- declare function useAutoGrow<T extends HTMLTextAreaElement>(value: string): React.RefObject<T>;
318
-
319
- /** A slash-palette entry: how it is shown and searched, and the markdown it inserts. */
320
- type TextCommand = {
321
- id: string;
322
- label: string;
323
- keywords: string[];
324
- icon: LucideIcon;
325
- hint?: string;
326
- insert: string;
327
- caretOffset: number;
328
- selectLength?: number;
329
- /** Needs a blank line above it: a divider after a paragraph line parses as a
330
- * setext heading, and a GFM table cannot interrupt a paragraph at all. */
331
- separate: boolean;
332
- };
333
- /** The built-in slash-palette commands, in display order. */
334
- declare const TEXT_COMMANDS: TextCommand[];
335
-
336
- /** A text transform result: the next value and where the selection should land. */
337
- type Edit = {
338
- value: string;
339
- selectionStart: number;
340
- selectionEnd: number;
341
- };
342
- /** Applies an edit to a textarea through the native undo stack when the browser allows it, so Ctrl+Z still works. */
343
- declare function applyEdit(el: HTMLTextAreaElement, edit: Edit, commit: (value: string) => void): void;
344
-
345
- type Line = {
346
- start: number;
347
- end: number;
348
- text: string;
349
- };
350
- /** The line containing the offset, with its start and end offsets and its text (no trailing newline). */
351
- declare function lineAt(value: string, offset: number): Line;
352
-
353
- /** A line-level markdown prefix: a heading level, a bullet or a numbered item. */
354
- type LinePrefix = 'h1' | 'h2' | 'h3' | 'bullet' | 'ordered';
355
- /** Adds the prefix to every line in the selection, or removes it when every line already carries it; fenced code is left alone. */
356
- declare function toggleLinePrefix(kind: LinePrefix, value: string, selectionStart: number, selectionEnd: number): Edit;
357
-
358
- /** Continues a list item on Enter, or climbs out of the list on an empty item or Backspace at the marker; returns null when the caret is not in a list item or is inside a code fence, so the default key behaviour runs. */
359
- declare function continueList(value: string, caret: number, key: 'Enter' | 'Backspace'): Edit | null;
360
-
361
- /** Indents or outdents the selected list items; returns null when the selection is not entirely list items, is inside a code fence, or cannot move further, so Tab keeps its default behaviour. */
362
- declare function indentList(value: string, selectionStart: number, selectionEnd: number, direction: 1 | -1): Edit | null;
363
-
364
- /** An inline markdown wrapper: bold, italic, code or a link. */
365
- type WrapKind = 'bold' | 'italic' | 'code' | 'link';
366
- /** Wraps the selection in the markers for the kind, or removes them when it is already wrapped. */
367
- declare function wrapSelection(kind: WrapKind, value: string, selectionStart: number, selectionEnd: number): Edit;
368
- /** Turns a pasted URL over a selection into a markdown link; returns null when nothing is selected or the paste is not a bare URL, so the paste goes through unchanged. */
369
- declare function linkPaste(value: string, selectionStart: number, selectionEnd: number, pasted: string): Edit | null;
370
-
371
- /** The fields `insertCommand` needs. `TextCommand` satisfies this structurally. */
372
- type InsertableCommand = {
373
- insert: string;
374
- caretOffset: number;
375
- selectLength?: number;
376
- separate: boolean;
377
- };
378
- /** Inserts a command's markdown at the caret, starting a new line (or a blank line if it asks) when the caret is mid-line. */
379
- declare function insertCommand(command: InsertableCommand, value: string, caret: number): Edit;
380
-
381
- /** Whether typing "/" here should open the command palette: only at a word start, with no selection and outside a code fence. */
382
- declare function shouldOpenPalette(value: string, selectionStart: number, selectionEnd: number): boolean;
383
-
384
- /** Renders a "mod+shift+b" style hint as the platform's own label, such as ⌘⇧B on a Mac and Ctrl+Shift+B elsewhere. */
385
- declare function formatShortcut(hint: string): string;
386
-
387
- /** The caret's position and line height, in pixels relative to the textarea's top left corner. */
388
- type CaretRect = {
389
- top: number;
390
- left: number;
391
- height: number;
392
- };
393
- /** A textarea exposes no caret geometry, so the text before the caret is laid
394
- * out again in a hidden div that copies the box's own metrics, and a marker at
395
- * the end of it is measured. Returns null when the textarea is not laid out
396
- * (hidden or detached), because there is nothing to measure. */
397
- declare function caretRect(el: HTMLTextAreaElement): CaretRect | null;
398
-
399
- /** Keyboard and paste handlers that give a plain textarea markdown shortcuts, list continuation, Tab indent and the slash palette trigger. */
400
- declare function useMarkdownKeymap({ commit, onOpenPalette, }: {
401
- commit: (markdown: string) => void;
402
- onOpenPalette: () => void;
403
- }): {
404
- onKeyDown: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;
405
- onPaste: (event: React.ClipboardEvent<HTMLTextAreaElement>) => void;
406
- };
407
-
408
- export { type AnyBlockDefinition, type AutosaveStatus, BlockCanvas, type BlockCanvasProps, type BlockDefinition, type BlockEditorProps, type BlockList, type BlockPreviewProps, type CalloutBlockData, type CaretRect, type CodeBlockData, type CoreBlockData, type Edit, type FileBlockData, FilePickerButton, type FilePickerButtonProps, type ImageBlockData, type InsertableCommand, type LinePrefix, type MarkdownBlockData, type QuoinBlock, type QuoinConfig, type QuoinConfigInput, QuoinProvider, TEXT_COMMANDS, type TextCommand, type UndoToken, UploadField, type UploadFieldProps, type UploadFn, type UploadResult, type UseAutosaveInput, type UseAutosaveResult, type WrapKind, applyEdit, blockByType, caretRect, continueList, coreBlocks, defineBlock, formatShortcut, indentList, insertCommand, lineAt, linkPaste, paletteBlocks, shouldOpenPalette, toggleLinePrefix, useAutoGrow, useAutosave, useBlockList, useMarkdownKeymap, useQuoin, wrapSelection };
500
+ export { AnyBlockDefinition, type AutosaveStatus, BlockCanvas, type BlockCanvasProps, type BlockMenuAction, BlockRenderer, type CalloutBlockData, type CodeBlockData, CodeHighlighter, Command, type CoreBlockData, Editor, EditorState, Extension, type ExtensionUI, type FileBlockData, FilePickerButton, type FilePickerButtonProps, type ImageBlockData, type MarkdownBlockData, PALETTE, Pos, QuoinBlock, type QuoinConfig, type QuoinConfigInput, type QuoinEditorHandle, type QuoinLabels, QuoinProvider, RenderOptions, type ShortcutPlatform, type SlashGroup, type SlashItem, type SuggestionRange, type ToolbarItem, UploadField, type UploadFieldProps, UploadFn, UploadResult, type UseAutosaveInput, type UseAutosaveResult, ViewController, coreBlocks, englishLabels, formatShortcut, resolveLabels, useAutosave, useLabels, useQuoin };