@railway/inkwell 0.1.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.
- package/dist/index.cjs +1628 -0
- package/dist/index.d.cts +375 -0
- package/dist/index.d.ts +375 -0
- package/dist/index.js +1605 -0
- package/package.json +72 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
import { ReactNode, JSX, RefObject, KeyboardEvent } from 'react';
|
|
2
|
+
import { Plugin } from 'unified';
|
|
3
|
+
import { Awareness } from 'y-protocols/awareness';
|
|
4
|
+
import { XmlText } from 'yjs';
|
|
5
|
+
import { BaseEditor, BaseElement, BaseText } from 'slate';
|
|
6
|
+
import { HistoryEditor } from 'slate-history';
|
|
7
|
+
import { ReactEditor } from 'slate-react';
|
|
8
|
+
|
|
9
|
+
type RehypePlugin$1 = Plugin<any[], any>;
|
|
10
|
+
type RehypePluginConfig$1 = RehypePlugin$1 | [RehypePlugin$1, Record<string, unknown>];
|
|
11
|
+
/**
|
|
12
|
+
* Props for the InkwellEditor component.
|
|
13
|
+
*/
|
|
14
|
+
interface InkwellEditorProps {
|
|
15
|
+
/**
|
|
16
|
+
* Markdown content string
|
|
17
|
+
*/
|
|
18
|
+
content: string;
|
|
19
|
+
/**
|
|
20
|
+
* Called with serialized markdown on every document change
|
|
21
|
+
*/
|
|
22
|
+
onChange?: (content: string) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Additional CSS class for the wrapper element
|
|
25
|
+
*/
|
|
26
|
+
className?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Placeholder text shown when editor is empty
|
|
29
|
+
*/
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Editor plugins (bubble toolbar, snippets, custom)
|
|
33
|
+
*/
|
|
34
|
+
plugins?: InkwellPlugin[];
|
|
35
|
+
/**
|
|
36
|
+
* Custom rehype plugins for the syntax highlighting pipeline
|
|
37
|
+
*/
|
|
38
|
+
rehypePlugins?: RehypePluginConfig$1[];
|
|
39
|
+
/**
|
|
40
|
+
* Configure which block-level decorations the editor recognizes. All enabled by default.
|
|
41
|
+
*/
|
|
42
|
+
decorations?: InkwellDecorations;
|
|
43
|
+
/**
|
|
44
|
+
* Enable real-time collaborative editing via Yjs
|
|
45
|
+
*/
|
|
46
|
+
collaboration?: CollaborationConfig;
|
|
47
|
+
/**
|
|
48
|
+
* Include the built-in bubble menu plugin (default: true). Pass `false` to
|
|
49
|
+
* disable the built-in toolbar; consumers can still add their own via `plugins`.
|
|
50
|
+
*/
|
|
51
|
+
bubbleMenu?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Props for the InkwellRenderer component.
|
|
55
|
+
*/
|
|
56
|
+
interface InkwellRendererProps {
|
|
57
|
+
/**
|
|
58
|
+
* Markdown content string
|
|
59
|
+
*/
|
|
60
|
+
content: string;
|
|
61
|
+
/**
|
|
62
|
+
* Additional CSS class for the wrapper element
|
|
63
|
+
*/
|
|
64
|
+
className?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Custom component overrides for rendered markdown elements
|
|
67
|
+
*/
|
|
68
|
+
components?: InkwellComponents;
|
|
69
|
+
/**
|
|
70
|
+
* Custom rehype plugins for the markdown pipeline
|
|
71
|
+
*/
|
|
72
|
+
rehypePlugins?: RehypePluginConfig$1[];
|
|
73
|
+
/**
|
|
74
|
+
* Show a copy button on fenced code blocks (default: true)
|
|
75
|
+
*/
|
|
76
|
+
copyButton?: boolean;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Map of HTML element names to custom React components
|
|
80
|
+
*/
|
|
81
|
+
type InkwellComponents = Partial<{
|
|
82
|
+
[K in keyof JSX.IntrinsicElements]: (props: JSX.IntrinsicElements[K] & {
|
|
83
|
+
children?: ReactNode;
|
|
84
|
+
}) => ReactNode;
|
|
85
|
+
}>;
|
|
86
|
+
/**
|
|
87
|
+
* Keyboard trigger for a plugin.
|
|
88
|
+
*
|
|
89
|
+
* Uses tinykeys-style key strings:
|
|
90
|
+
* - `"Control+/"` — modifier combo, prevents default
|
|
91
|
+
* - `"@"` — single character, typed into editor (e.g. for mentions)
|
|
92
|
+
*/
|
|
93
|
+
interface PluginTrigger {
|
|
94
|
+
/**
|
|
95
|
+
* Key combo (tinykeys format)
|
|
96
|
+
*/
|
|
97
|
+
key: string;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Props passed to every plugin's render function on every render
|
|
101
|
+
*/
|
|
102
|
+
interface PluginRenderProps {
|
|
103
|
+
/**
|
|
104
|
+
* Whether this plugin's trigger has fired (always true for plugins without triggers)
|
|
105
|
+
*/
|
|
106
|
+
active: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Text typed after the trigger fired
|
|
109
|
+
*/
|
|
110
|
+
query: string;
|
|
111
|
+
/**
|
|
112
|
+
* Insert text into the editor at the current cursor position
|
|
113
|
+
*/
|
|
114
|
+
onSelect: (text: string) => void;
|
|
115
|
+
/**
|
|
116
|
+
* Deactivate this plugin (resets `active` to false)
|
|
117
|
+
*/
|
|
118
|
+
onDismiss: () => void;
|
|
119
|
+
/**
|
|
120
|
+
* Cursor position when the trigger fired
|
|
121
|
+
*/
|
|
122
|
+
position: {
|
|
123
|
+
top: number;
|
|
124
|
+
left: number;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Ref to the editor's contenteditable element
|
|
128
|
+
*/
|
|
129
|
+
editorRef: RefObject<HTMLDivElement | null>;
|
|
130
|
+
/**
|
|
131
|
+
* Wrap the current selection with markdown markers
|
|
132
|
+
*/
|
|
133
|
+
wrapSelection: (before: string, after: string) => void;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Context passed to a plugin's `onKeyDown` handler.
|
|
137
|
+
*/
|
|
138
|
+
interface PluginKeyDownContext {
|
|
139
|
+
/**
|
|
140
|
+
* Wrap the current selection with markdown markers
|
|
141
|
+
*/
|
|
142
|
+
wrapSelection: (before: string, after: string) => void;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* A Inkwell editor plugin.
|
|
146
|
+
*
|
|
147
|
+
* Every plugin is always rendered. Plugins with a `trigger` receive
|
|
148
|
+
* `active: true` when the trigger fires and `active: false` otherwise.
|
|
149
|
+
* Plugins without a trigger always receive `active: true`.
|
|
150
|
+
*/
|
|
151
|
+
interface InkwellPlugin {
|
|
152
|
+
/**
|
|
153
|
+
* Unique plugin name
|
|
154
|
+
*/
|
|
155
|
+
name: string;
|
|
156
|
+
/**
|
|
157
|
+
* Optional keyboard trigger
|
|
158
|
+
*/
|
|
159
|
+
trigger?: PluginTrigger;
|
|
160
|
+
/**
|
|
161
|
+
* Render the plugin UI. Return `null` when inactive.
|
|
162
|
+
*/
|
|
163
|
+
render: (props: PluginRenderProps) => ReactNode;
|
|
164
|
+
/**
|
|
165
|
+
* Optional keydown handler. Runs for events on the editor before trigger
|
|
166
|
+
* matching, and is skipped while another plugin is active. Call
|
|
167
|
+
* `event.preventDefault()` to stop further dispatch for this event.
|
|
168
|
+
*/
|
|
169
|
+
onKeyDown?: (event: KeyboardEvent, ctx: PluginKeyDownContext) => void;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Props passed to each bubble menu item component.
|
|
173
|
+
*/
|
|
174
|
+
interface BubbleMenuItemProps {
|
|
175
|
+
/**
|
|
176
|
+
* Wrap or unwrap the current selection with markdown markers. Toggles if already wrapped.
|
|
177
|
+
*/
|
|
178
|
+
wrapSelection: (before: string, after: string) => void;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* An item in the bubble menu.
|
|
182
|
+
*/
|
|
183
|
+
interface BubbleMenuItem {
|
|
184
|
+
/**
|
|
185
|
+
* Unique key for React reconciliation
|
|
186
|
+
*/
|
|
187
|
+
key: string;
|
|
188
|
+
/**
|
|
189
|
+
* Optional keyboard shortcut (single key, used with Cmd/Ctrl).
|
|
190
|
+
*/
|
|
191
|
+
shortcut?: string;
|
|
192
|
+
/**
|
|
193
|
+
* Action to run when the shortcut fires. Receives wrapSelection.
|
|
194
|
+
*/
|
|
195
|
+
onShortcut?: (wrapSelection: (before: string, after: string) => void) => void;
|
|
196
|
+
/**
|
|
197
|
+
* React component to render in the menu. Receives `wrapSelection`.
|
|
198
|
+
*/
|
|
199
|
+
render: (props: BubbleMenuItemProps) => ReactNode;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Snippet item for the snippets plugin
|
|
203
|
+
*/
|
|
204
|
+
interface Snippet {
|
|
205
|
+
/**
|
|
206
|
+
* Display title (searchable)
|
|
207
|
+
*/
|
|
208
|
+
title: string;
|
|
209
|
+
/**
|
|
210
|
+
* Markdown content to insert
|
|
211
|
+
*/
|
|
212
|
+
content: string;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Controls which markdown block elements the editor recognizes.
|
|
216
|
+
* All decorations are enabled by default. Pass `false` to disable.
|
|
217
|
+
*/
|
|
218
|
+
interface InkwellDecorations {
|
|
219
|
+
/**
|
|
220
|
+
* Recognize `# ` as h1 (default: true)
|
|
221
|
+
*/
|
|
222
|
+
heading1?: boolean;
|
|
223
|
+
/**
|
|
224
|
+
* Recognize `## ` as h2 (default: true)
|
|
225
|
+
*/
|
|
226
|
+
heading2?: boolean;
|
|
227
|
+
/**
|
|
228
|
+
* Recognize `### ` as h3 (default: true)
|
|
229
|
+
*/
|
|
230
|
+
heading3?: boolean;
|
|
231
|
+
/**
|
|
232
|
+
* Recognize `#### ` as h4 (default: true)
|
|
233
|
+
*/
|
|
234
|
+
heading4?: boolean;
|
|
235
|
+
/**
|
|
236
|
+
* Recognize `##### ` as h5 (default: true)
|
|
237
|
+
*/
|
|
238
|
+
heading5?: boolean;
|
|
239
|
+
/**
|
|
240
|
+
* Recognize `###### ` as h6 (default: true)
|
|
241
|
+
*/
|
|
242
|
+
heading6?: boolean;
|
|
243
|
+
/**
|
|
244
|
+
* Recognize `- `, `* `, `+ ` as list items (default: true)
|
|
245
|
+
*/
|
|
246
|
+
lists?: boolean;
|
|
247
|
+
/**
|
|
248
|
+
* Recognize `> ` as blockquotes (default: true)
|
|
249
|
+
*/
|
|
250
|
+
blockquotes?: boolean;
|
|
251
|
+
/**
|
|
252
|
+
* Recognize ``` fences as code blocks (default: true)
|
|
253
|
+
*/
|
|
254
|
+
codeBlocks?: boolean;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Configuration for real-time collaborative editing via Yjs.
|
|
258
|
+
*
|
|
259
|
+
* The consumer owns the Yjs document and provider (WebSocket,
|
|
260
|
+
* WebRTC, Hocuspocus, etc.). Inkwell only needs the shared type
|
|
261
|
+
* and awareness instance.
|
|
262
|
+
*/
|
|
263
|
+
interface CollaborationConfig {
|
|
264
|
+
/**
|
|
265
|
+
* Yjs shared type for the document. Create via `doc.get("content", Y.XmlText)`.
|
|
266
|
+
*/
|
|
267
|
+
sharedType: XmlText;
|
|
268
|
+
/**
|
|
269
|
+
* Awareness instance for remote cursor/presence sharing.
|
|
270
|
+
*/
|
|
271
|
+
awareness: Awareness;
|
|
272
|
+
/**
|
|
273
|
+
* Local user metadata, displayed on remote cursors.
|
|
274
|
+
*/
|
|
275
|
+
user: {
|
|
276
|
+
name: string;
|
|
277
|
+
color: string;
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
declare function InkwellEditor$1({ content, onChange, className, placeholder, plugins: userPlugins, rehypePlugins, decorations, collaboration, bubbleMenu, }: InkwellEditorProps): ReactNode;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Element types in the Inkwell editor
|
|
285
|
+
*/
|
|
286
|
+
type ElementType = "paragraph" | "code-fence" | "code-line" | "blockquote" | "list-item" | "heading";
|
|
287
|
+
/**
|
|
288
|
+
* A block-level element in the editor
|
|
289
|
+
*/
|
|
290
|
+
interface InkwellElement extends BaseElement {
|
|
291
|
+
type: ElementType;
|
|
292
|
+
/**
|
|
293
|
+
* Unique element identifier. Session-scoped, not persisted in markdown.
|
|
294
|
+
*/
|
|
295
|
+
id: string;
|
|
296
|
+
/**
|
|
297
|
+
* Heading level (1-6). Only present on `heading` elements.
|
|
298
|
+
*/
|
|
299
|
+
level?: number;
|
|
300
|
+
children: InkwellText[];
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* A text leaf node
|
|
304
|
+
*/
|
|
305
|
+
interface InkwellText extends BaseText {
|
|
306
|
+
text: string;
|
|
307
|
+
bold?: true;
|
|
308
|
+
italic?: true;
|
|
309
|
+
strikethrough?: true;
|
|
310
|
+
inlineCode?: true;
|
|
311
|
+
boldMarker?: true;
|
|
312
|
+
italicMarker?: true;
|
|
313
|
+
strikeMarker?: true;
|
|
314
|
+
codeMarker?: true;
|
|
315
|
+
hljs?: string;
|
|
316
|
+
remoteCursor?: string;
|
|
317
|
+
remoteCursorCaret?: boolean;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* The composed Inkwell editor type
|
|
321
|
+
*/
|
|
322
|
+
type InkwellEditor = BaseEditor & ReactEditor & HistoryEditor;
|
|
323
|
+
declare module "slate" {
|
|
324
|
+
interface CustomTypes {
|
|
325
|
+
Editor: InkwellEditor;
|
|
326
|
+
Element: InkwellElement;
|
|
327
|
+
Text: InkwellText;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Deserialize a markdown string into Slate decorations.
|
|
333
|
+
*
|
|
334
|
+
* Each line becomes its own element. Block-level patterns (code fences,
|
|
335
|
+
* blockquotes, list items, headings) get their own element types based
|
|
336
|
+
* on the `decorations` config. Everything else is a paragraph. Text content
|
|
337
|
+
* is stored verbatim — visual formatting is handled by decorations at
|
|
338
|
+
* render time, not in the data model.
|
|
339
|
+
*/
|
|
340
|
+
declare function deserialize(markdown: string, decorations?: InkwellDecorations): InkwellElement[];
|
|
341
|
+
|
|
342
|
+
declare function pluginClass(pluginName: string): (component: string) => string;
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Default bubble menu items: bold, italic, strikethrough.
|
|
346
|
+
*/
|
|
347
|
+
declare const defaultBubbleMenuItems: BubbleMenuItem[];
|
|
348
|
+
interface BubbleMenuOptions {
|
|
349
|
+
/**
|
|
350
|
+
* Menu items. Defaults to bold, italic, strikethrough.
|
|
351
|
+
*/
|
|
352
|
+
items?: BubbleMenuItem[];
|
|
353
|
+
}
|
|
354
|
+
declare function createBubbleMenuPlugin(options?: BubbleMenuOptions): InkwellPlugin;
|
|
355
|
+
|
|
356
|
+
declare function createSnippetsPlugin(options: {
|
|
357
|
+
snippets: Snippet[];
|
|
358
|
+
key?: string;
|
|
359
|
+
}): InkwellPlugin;
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Convert an HTML string to a markdown string
|
|
363
|
+
*/
|
|
364
|
+
declare function serializeToMarkdown(html: string): string;
|
|
365
|
+
|
|
366
|
+
declare function InkwellRenderer({ content, className, components, rehypePlugins, copyButton, }: InkwellRendererProps): ReactNode;
|
|
367
|
+
|
|
368
|
+
type RehypePlugin = Plugin<any[], any>;
|
|
369
|
+
type RehypePluginConfig = RehypePlugin | [RehypePlugin, Record<string, unknown>];
|
|
370
|
+
/**
|
|
371
|
+
* Parse a markdown string into React elements synchronously
|
|
372
|
+
*/
|
|
373
|
+
declare function parseMarkdown(markdown: string, components?: InkwellComponents, rehypePlugins?: RehypePluginConfig[]): ReactNode;
|
|
374
|
+
|
|
375
|
+
export { type BubbleMenuItem, type BubbleMenuItemProps, type CollaborationConfig, type InkwellComponents, type InkwellDecorations, InkwellEditor$1 as InkwellEditor, type InkwellEditorProps, type InkwellPlugin, InkwellRenderer, type InkwellRendererProps, type PluginKeyDownContext, type PluginRenderProps, type PluginTrigger, type RehypePluginConfig$1 as RehypePluginConfig, type Snippet, createBubbleMenuPlugin, createSnippetsPlugin, defaultBubbleMenuItems, deserialize, parseMarkdown, pluginClass, serializeToMarkdown };
|