@matops/editor 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/README.md +277 -0
- package/dist/index.d.ts +1140 -0
- package/dist/index.esm.js +9067 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +9067 -0
- package/dist/index.js.map +1 -0
- package/dist/style.css +4710 -0
- package/package.json +99 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1140 @@
|
|
|
1
|
+
import { ClassValue } from 'clsx';
|
|
2
|
+
import { DecorationSet } from '@tiptap/pm/view';
|
|
3
|
+
import { default as default_2 } from 'react';
|
|
4
|
+
import { Dispatch } from 'react';
|
|
5
|
+
import { Doc } from 'yjs';
|
|
6
|
+
import { Editor as Editor_2 } from '@tiptap/core';
|
|
7
|
+
import { Extension } from '@tiptap/core';
|
|
8
|
+
import { Extensions } from '@tiptap/core';
|
|
9
|
+
import { JSONContent } from '@tiptap/core';
|
|
10
|
+
import { JSX as JSX_2 } from 'react/jsx-runtime';
|
|
11
|
+
import { Node as Node_2 } from '@tiptap/core';
|
|
12
|
+
import { PluginKey } from '@tiptap/pm/state';
|
|
13
|
+
import { ReactNode } from 'react';
|
|
14
|
+
import { RefObject } from 'react';
|
|
15
|
+
import { SetStateAction } from 'react';
|
|
16
|
+
|
|
17
|
+
export declare interface AttachmentItem {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
size: number;
|
|
21
|
+
mimeType: string;
|
|
22
|
+
url: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export declare interface AttachmentsAttrs {
|
|
26
|
+
items: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export declare interface AttachmentsDocAttr {
|
|
30
|
+
items: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* AttachmentsGuard — stub extension for the `"attachments"` feature.
|
|
35
|
+
* Previously guarded the attachments content node; now a no-op since
|
|
36
|
+
* attachments data lives in doc.attrs and is rendered as a React panel.
|
|
37
|
+
*/
|
|
38
|
+
export declare const AttachmentsGuard: Extension<any, any>;
|
|
39
|
+
|
|
40
|
+
export declare const AttachmentsNode: Node_2<any, any>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* AttachmentsPanel — React panel (Panel 3) for document attachments.
|
|
44
|
+
*
|
|
45
|
+
* Reads from `editor.state.doc.attrs.attachments` (an AttachmentsDocAttr or null).
|
|
46
|
+
* Writes via `editor.commands.setAttachmentsAttr(items)`.
|
|
47
|
+
*
|
|
48
|
+
* Structure (mirrors the old AttachmentsSectionView layout exactly):
|
|
49
|
+
* ────── [separator-icon mirror] ────── ← static, reads from doc.attrs.separatorIcon
|
|
50
|
+
* 📎 Attachments [+ Add attachment]
|
|
51
|
+
* [ file list ]
|
|
52
|
+
*
|
|
53
|
+
* No ProseMirror NodeView — this is pure React rendered below <EditorContent>.
|
|
54
|
+
*
|
|
55
|
+
* All drag events call e.stopPropagation() so files dropped here don't also
|
|
56
|
+
* get picked up by the editor's useImageUpload handler.
|
|
57
|
+
*/
|
|
58
|
+
export declare function AttachmentsPanel(): JSX_2.Element | null;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* BlockFloatingMenu
|
|
62
|
+
*
|
|
63
|
+
* A compact "+" trigger button on empty lines.
|
|
64
|
+
* Click to expand into an icon-only pill of available commands.
|
|
65
|
+
* Hover each icon to see the label as a tooltip.
|
|
66
|
+
*/
|
|
67
|
+
export declare function BlockFloatingMenu(): JSX_2.Element | null;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* CharacterCountBar
|
|
71
|
+
*
|
|
72
|
+
* A slim footer bar rendered below the editor content area.
|
|
73
|
+
* Shows: words, characters, paragraphs, and estimated reading time.
|
|
74
|
+
*
|
|
75
|
+
* IMPORTANT: useEditorUpdate() is called so this component re-renders on
|
|
76
|
+
* every editor transaction — without it, stats would only refresh on
|
|
77
|
+
* React prop changes (i.e. never, since the editor ref is stable).
|
|
78
|
+
*/
|
|
79
|
+
export declare function CharacterCountBar({ wordLimit, charLimit, }: CharacterCountBarProps): JSX_2.Element | null;
|
|
80
|
+
|
|
81
|
+
declare interface CharacterCountBarProps {
|
|
82
|
+
/** Optional word limit — shows a progress indicator when set */
|
|
83
|
+
wordLimit?: number;
|
|
84
|
+
/** Optional character limit */
|
|
85
|
+
charLimit?: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Merge Tailwind CSS classes safely.
|
|
90
|
+
* Combines clsx (conditional classes) with tailwind-merge (deduplication).
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* cn("p-4", isActive && "bg-blue-500", "p-2")
|
|
94
|
+
* // → "bg-blue-500 p-2" (p-4 deduplicated by tailwind-merge)
|
|
95
|
+
*/
|
|
96
|
+
export declare function cn(...inputs: ClassValue[]): string;
|
|
97
|
+
|
|
98
|
+
export declare interface CollaborationProvider {
|
|
99
|
+
document: Doc;
|
|
100
|
+
user?: CollaborationUser;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export declare interface CollaborationUser {
|
|
104
|
+
name: string;
|
|
105
|
+
color: string;
|
|
106
|
+
avatar?: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export declare function computeCropStyle(crop: CropRect, objectPosition?: string): React.CSSProperties;
|
|
110
|
+
|
|
111
|
+
export declare function computeCropStyleStr(crop: CropRect, objectPosition?: string): string;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Registers (or re-registers) the "tables" feature with the given options.
|
|
115
|
+
*
|
|
116
|
+
* Calling this function multiple times is intentional when you need custom
|
|
117
|
+
* configuration — the registry warns on overwrite, which is expected.
|
|
118
|
+
*
|
|
119
|
+
* @param options - Partial options to override TABLE_DEFAULTS.
|
|
120
|
+
*/
|
|
121
|
+
export declare function configureTablesFeature(options?: TableFeatureOptions): void;
|
|
122
|
+
|
|
123
|
+
export declare type ContentWidth = (typeof ContentWidths)[keyof typeof ContentWidths];
|
|
124
|
+
|
|
125
|
+
export declare const ContentWidths: {
|
|
126
|
+
readonly full: "full";
|
|
127
|
+
readonly normal: "normal";
|
|
128
|
+
readonly compact: "compact";
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export declare interface CoverImageAttrs {
|
|
132
|
+
src: string | null;
|
|
133
|
+
alt: string;
|
|
134
|
+
objectPosition: string;
|
|
135
|
+
cropX: number;
|
|
136
|
+
cropY: number;
|
|
137
|
+
cropWidth: number;
|
|
138
|
+
cropHeight: number;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export declare interface CoverImageDocAttr {
|
|
142
|
+
src: string | null;
|
|
143
|
+
alt: string;
|
|
144
|
+
objectPosition: string;
|
|
145
|
+
cropX: number;
|
|
146
|
+
cropY: number;
|
|
147
|
+
cropWidth: number;
|
|
148
|
+
cropHeight: number;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* CoverImageGuard — stub extension for the `"cover-image"` feature.
|
|
153
|
+
* Previously guarded the cover-image content node; now a no-op since
|
|
154
|
+
* cover-image data lives in doc.attrs.
|
|
155
|
+
*/
|
|
156
|
+
export declare const CoverImageGuard: Extension<any, any>;
|
|
157
|
+
|
|
158
|
+
export declare const CoverImageNode: Node_2<any, any>;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* CoverImagePanel — React panel (Panel 1) for the cover/banner image.
|
|
162
|
+
*
|
|
163
|
+
* Reads from `editor.state.doc.attrs.coverImage` (a CoverImageDocAttr or null).
|
|
164
|
+
* Writes via `editor.commands.setCoverImageAttr(...)`.
|
|
165
|
+
*
|
|
166
|
+
* No ProseMirror NodeView — this is pure React rendered above <EditorContent>.
|
|
167
|
+
*
|
|
168
|
+
* Crop coordinates are percentages (0–100) stored in doc.attrs.coverImage.
|
|
169
|
+
*/
|
|
170
|
+
export declare function CoverImagePanel(): JSX_2.Element | null;
|
|
171
|
+
|
|
172
|
+
/** @deprecated Use `createDocContent()` instead. */
|
|
173
|
+
export declare function createAttachmentsNode(items?: AttachmentItem[]): JSONContent;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @deprecated Use `createDocContent()` instead.
|
|
177
|
+
* Returns a `cover-image` content node for internal Tiptap use.
|
|
178
|
+
*/
|
|
179
|
+
export declare function createCoverImageNode(src: string, options?: Partial<Omit<CoverImageAttrs, "src">>): JSONContent;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Build a complete Tiptap document JSONContent in **external format**.
|
|
183
|
+
*
|
|
184
|
+
* Structural metadata (cover image, title, separator icon, attachments) is
|
|
185
|
+
* stored in `doc.attrs`. Only body content goes in `content[]`.
|
|
186
|
+
*
|
|
187
|
+
* Pass the result as `initialContent` to `<Editor>` — it reads doc.attrs and
|
|
188
|
+
* injects the appropriate content nodes internally.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* createDocContent({
|
|
192
|
+
* coverSrc: "https://cdn.example.com/cover.jpg",
|
|
193
|
+
* title: "Getting Started",
|
|
194
|
+
* body: [{ type: "paragraph", content: [{ type: "text", text: "Hello!" }] }],
|
|
195
|
+
* })
|
|
196
|
+
*/
|
|
197
|
+
export declare function createDocContent(options?: DocContentOptions): JSONContent;
|
|
198
|
+
|
|
199
|
+
/** @deprecated Use `createDocContent()` instead. */
|
|
200
|
+
export declare function createEmptyCoverImageNode(): JSONContent;
|
|
201
|
+
|
|
202
|
+
/** @deprecated Use `createDocContent()` instead. */
|
|
203
|
+
export declare function createEmptySeparatorIconNode(): JSONContent;
|
|
204
|
+
|
|
205
|
+
/** @deprecated Use `createDocContent()` instead. */
|
|
206
|
+
export declare function createSeparatorIconNode(src: string, options?: Partial<Omit<SeparatorIconAttrs, "src">>): JSONContent;
|
|
207
|
+
|
|
208
|
+
/** @deprecated Use `createDocContent()` instead. */
|
|
209
|
+
export declare function createTitleNode(text?: string, options?: Partial<TitleAttrs>): JSONContent;
|
|
210
|
+
|
|
211
|
+
export declare function CropModal({ src, initialCrop, aspectRatio, onConfirm, onCancel, }: CropModalProps): default_2.ReactPortal;
|
|
212
|
+
|
|
213
|
+
declare interface CropModalProps {
|
|
214
|
+
src: string;
|
|
215
|
+
initialCrop?: CropRect;
|
|
216
|
+
aspectRatio?: number;
|
|
217
|
+
onConfirm: (crop: CropRect) => void;
|
|
218
|
+
onCancel: () => void;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export declare interface CropRect {
|
|
222
|
+
x: number;
|
|
223
|
+
y: number;
|
|
224
|
+
width: number;
|
|
225
|
+
height: number;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export declare function cropToAttrs(crop: CropRect): {
|
|
229
|
+
cropX: number;
|
|
230
|
+
cropY: number;
|
|
231
|
+
cropWidth: number;
|
|
232
|
+
cropHeight: number;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export declare const DEFAULT_CONTENT_WIDTH: ContentWidth;
|
|
236
|
+
|
|
237
|
+
export declare const DEFAULT_CROP: CropRect;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* DefaultSeparatorIcon — the quill SVG used as the fallback badge icon
|
|
241
|
+
* in TitleSeparator, SeparatorIconView, and EditorViewer.
|
|
242
|
+
* Single source of truth — no more duplication across three files.
|
|
243
|
+
*/
|
|
244
|
+
export declare const DefaultSeparatorIcon: ({ size }: IconProps) => JSX_2.Element;
|
|
245
|
+
|
|
246
|
+
export declare interface DocAttrs {
|
|
247
|
+
contentWidth?: ContentWidth;
|
|
248
|
+
coverImage?: CoverImageDocAttr | null;
|
|
249
|
+
title?: TitleDocAttr | null;
|
|
250
|
+
separatorIcon?: SeparatorIconDocAttr | null;
|
|
251
|
+
attachments?: AttachmentsDocAttr | null;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export declare interface DocContentOptions {
|
|
255
|
+
/** Cover image URL. Omit to skip the `coverImage` attr entirely. */
|
|
256
|
+
coverSrc?: string;
|
|
257
|
+
coverOptions?: Partial<Omit<CoverImageDocAttr, "src">>;
|
|
258
|
+
/**
|
|
259
|
+
* Document title text. Pass `""` to include the title with no text
|
|
260
|
+
* (shows placeholder in the editor). Omit to skip entirely.
|
|
261
|
+
*/
|
|
262
|
+
title?: string;
|
|
263
|
+
titleOptions?: Partial<TitleDocAttr>;
|
|
264
|
+
/**
|
|
265
|
+
* Separator icon URL. Only applied when `title` is also present.
|
|
266
|
+
*/
|
|
267
|
+
separatorIconSrc?: string;
|
|
268
|
+
/** Body content nodes. Defaults to a single empty paragraph. */
|
|
269
|
+
body?: JSONContent[];
|
|
270
|
+
/**
|
|
271
|
+
* Attachments section.
|
|
272
|
+
* - `true` → empty section
|
|
273
|
+
* - `AttachmentItem[]` → pre-populated
|
|
274
|
+
* - omit / `false` → disabled
|
|
275
|
+
*/
|
|
276
|
+
attachments?: boolean | AttachmentItem[];
|
|
277
|
+
layout?: DocLayout;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export declare interface DocLayout {
|
|
281
|
+
contentWidth?: ContentWidth;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export declare interface DropdownPosition {
|
|
285
|
+
top: number;
|
|
286
|
+
left: number;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
declare interface EditorContextValue {
|
|
290
|
+
editor: Editor_2 | null;
|
|
291
|
+
features: EditorFeature[];
|
|
292
|
+
featureSet: Set<EditorFeature>;
|
|
293
|
+
theme: EditorTheme;
|
|
294
|
+
editable: boolean;
|
|
295
|
+
onFileUploaded?: (file: File) => Promise<string>;
|
|
296
|
+
separatorIcon?: ReactNode;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export declare type EditorFeature = (typeof EditorFeatures)[keyof typeof EditorFeatures];
|
|
300
|
+
|
|
301
|
+
export declare const EditorFeatures: {
|
|
302
|
+
readonly formatting: "formatting";
|
|
303
|
+
readonly code: "code";
|
|
304
|
+
readonly media: "media";
|
|
305
|
+
readonly tables: "tables";
|
|
306
|
+
readonly taskList: "task-list";
|
|
307
|
+
readonly layout: "layout";
|
|
308
|
+
readonly collaboration: "collaboration";
|
|
309
|
+
readonly history: "history";
|
|
310
|
+
readonly slashCommand: "slash-command";
|
|
311
|
+
readonly placeholder: "placeholder";
|
|
312
|
+
readonly characterCount: "character-count";
|
|
313
|
+
readonly findReplace: "find-replace";
|
|
314
|
+
readonly coverImage: "cover-image";
|
|
315
|
+
readonly pageHeader: "page-header";
|
|
316
|
+
readonly attachments: "attachments";
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
export declare interface EditorProps {
|
|
320
|
+
features?: EditorFeature[];
|
|
321
|
+
initialContent?: JSONContent;
|
|
322
|
+
theme?: EditorTheme;
|
|
323
|
+
editable?: boolean;
|
|
324
|
+
placeholder?: string;
|
|
325
|
+
collaborationProvider?: CollaborationProvider;
|
|
326
|
+
className?: string;
|
|
327
|
+
onChange?: (json: JSONContent) => void;
|
|
328
|
+
onContentChange?: (html: string, json: JSONContent) => void;
|
|
329
|
+
onPublish?: (content: JSONContent) => void;
|
|
330
|
+
onFileUploaded?: (file: File) => Promise<string>;
|
|
331
|
+
onEditorReady?: (editor: Editor_2) => void;
|
|
332
|
+
separatorIcon?: ReactNode;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export declare function EditorProvider({ children, editor, features, theme, editable, onFileUploaded, separatorIcon, }: EditorProviderProps): JSX_2.Element;
|
|
336
|
+
|
|
337
|
+
declare interface EditorProviderProps {
|
|
338
|
+
children: ReactNode;
|
|
339
|
+
editor: Editor_2 | null;
|
|
340
|
+
features: EditorFeature[];
|
|
341
|
+
theme: EditorTheme;
|
|
342
|
+
editable: boolean;
|
|
343
|
+
onFileUploaded?: (file: File) => Promise<string>;
|
|
344
|
+
separatorIcon?: ReactNode;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export declare type EditorTheme = (typeof EditorThemes)[keyof typeof EditorThemes];
|
|
348
|
+
|
|
349
|
+
export declare const EditorThemes: {
|
|
350
|
+
readonly light: "light";
|
|
351
|
+
readonly dark: "dark";
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
export declare function EditorToolbar(): JSX_2.Element | null;
|
|
355
|
+
|
|
356
|
+
export declare function EditorToolbarWithActions({ onOpenFind, onOpenExport, onOpenShortcuts, previewMode, onTogglePreview, }?: EditorToolbarWithActionsProps): JSX_2.Element | null;
|
|
357
|
+
|
|
358
|
+
declare interface EditorToolbarWithActionsProps {
|
|
359
|
+
onOpenFind?: () => void;
|
|
360
|
+
onOpenExport?: () => void;
|
|
361
|
+
onOpenShortcuts?: () => void;
|
|
362
|
+
/** Whether preview (read-only viewer) mode is currently active */
|
|
363
|
+
previewMode?: boolean;
|
|
364
|
+
/** Called when the user clicks the preview toggle pill */
|
|
365
|
+
onTogglePreview?: () => void;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
declare interface EditorViewerProps {
|
|
369
|
+
content: JSONContent;
|
|
370
|
+
theme?: EditorTheme;
|
|
371
|
+
className?: string;
|
|
372
|
+
features?: EditorFeature[];
|
|
373
|
+
separatorIcon?: ReactNode;
|
|
374
|
+
showStats?: boolean;
|
|
375
|
+
}
|
|
376
|
+
export { EditorViewerProps }
|
|
377
|
+
export { EditorViewerProps as MatopsViewerProps }
|
|
378
|
+
|
|
379
|
+
export declare function ExportPanel({ open, onClose }: ExportPanelProps): JSX_2.Element | null;
|
|
380
|
+
|
|
381
|
+
declare interface ExportPanelProps {
|
|
382
|
+
open: boolean;
|
|
383
|
+
onClose: () => void;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Extract the attachment list. Reads `doc.attrs.attachments.items` first,
|
|
388
|
+
* then falls back to the legacy `attachments` content node.
|
|
389
|
+
*/
|
|
390
|
+
export declare function extractAttachments(doc: JSONContent): AttachmentItem[];
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Extract `contentWidth`. Returns `DEFAULT_CONTENT_WIDTH` if absent or invalid.
|
|
394
|
+
*/
|
|
395
|
+
export declare function extractContentWidth(doc: JSONContent): ContentWidth;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Extract the full cover-image attr object.
|
|
399
|
+
* Returns `null` if no cover image attr is present.
|
|
400
|
+
*/
|
|
401
|
+
export declare function extractCoverImageAttr(doc: JSONContent): CoverImageDocAttr | null;
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Extract the cover image src. Reads `doc.attrs.coverImage.src` first,
|
|
405
|
+
* then falls back to the legacy `cover-image` content node.
|
|
406
|
+
*/
|
|
407
|
+
export declare function extractCoverSrc(doc: JSONContent): string | null;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Extract the separator icon src. Reads `doc.attrs.separatorIcon.src` first,
|
|
411
|
+
* then falls back to the legacy `separator-icon` content node.
|
|
412
|
+
*/
|
|
413
|
+
export declare function extractSeparatorIconSrc(doc: JSONContent): string | null;
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Extract the title text. Reads `doc.attrs.title.text` first,
|
|
417
|
+
* then falls back to the legacy `title` content node.
|
|
418
|
+
*/
|
|
419
|
+
export declare function extractTitle(doc: JSONContent): string;
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Extract the full title attr object.
|
|
423
|
+
* Returns `null` if no title attr is present.
|
|
424
|
+
*/
|
|
425
|
+
export declare function extractTitleAttr(doc: JSONContent): TitleDocAttr | null;
|
|
426
|
+
|
|
427
|
+
export declare interface FeatureDefinition {
|
|
428
|
+
name: EditorFeature;
|
|
429
|
+
extensions: Extensions;
|
|
430
|
+
dependencies?: EditorFeature[];
|
|
431
|
+
enabled?: (activeFeatures: EditorFeature[]) => boolean;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
declare class FeatureRegistry {
|
|
435
|
+
private readonly registry;
|
|
436
|
+
register(definition: FeatureDefinition): void;
|
|
437
|
+
resolve(requestedFeatures: EditorFeature[]): ResolvedEditorConfig;
|
|
438
|
+
has(name: EditorFeature): boolean;
|
|
439
|
+
get(name: EditorFeature): FeatureDefinition | undefined;
|
|
440
|
+
list(): EditorFeature[];
|
|
441
|
+
get size(): number;
|
|
442
|
+
unregister(name: EditorFeature): void;
|
|
443
|
+
clear(): void;
|
|
444
|
+
private resolveDependencies;
|
|
445
|
+
private filterEnabled;
|
|
446
|
+
private collectExtensions;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
export declare const featureRegistry: FeatureRegistry;
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* FindReplacePanel
|
|
453
|
+
*
|
|
454
|
+
* UI for the find-and-replace feature. Works with SearchExtension
|
|
455
|
+
* (extensions/plugins/searchPlugin.ts) which manages all ProseMirror
|
|
456
|
+
* decoration state.
|
|
457
|
+
*
|
|
458
|
+
* Optimisation notes vs original:
|
|
459
|
+
* - Search (query + caseSensitive) and navigation (currentIndex) are
|
|
460
|
+
* dispatched separately so changing the active match doesn't re-run the
|
|
461
|
+
* full text search.
|
|
462
|
+
* - Plugin state is read immediately after each dispatch (synchronous in
|
|
463
|
+
* ProseMirror) so results are always consistent.
|
|
464
|
+
*/
|
|
465
|
+
export declare function FindReplacePanel({ open, onClose }: FindReplacePanelProps): JSX_2.Element | null;
|
|
466
|
+
|
|
467
|
+
declare interface FindReplacePanelProps {
|
|
468
|
+
open: boolean;
|
|
469
|
+
onClose: () => void;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
export declare function FormattingBubbleMenu(): JSX_2.Element | null;
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Returns the `attachments` attr from a live editor's document.
|
|
476
|
+
* Returns `null` if the attr is absent or null.
|
|
477
|
+
*/
|
|
478
|
+
export declare function getAttachmentsAttr(editor: Editor_2 | null): AttachmentsDocAttr | null;
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Returns the `contentWidth` stored in a live Tiptap editor's document,
|
|
482
|
+
* falling back to `DEFAULT_CONTENT_WIDTH` if the attr is missing or invalid.
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* const width = getContentWidth(editor);
|
|
486
|
+
* // → "normal" | "compact" | "full"
|
|
487
|
+
*/
|
|
488
|
+
export declare function getContentWidth(editor: Editor_2 | null): ContentWidth;
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Returns the `coverImage` attr from a live editor's document.
|
|
492
|
+
* Returns `null` if the attr is absent or null.
|
|
493
|
+
*/
|
|
494
|
+
export declare function getCoverImageAttr(editor: Editor_2 | null): CoverImageDocAttr | null;
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Returns the `separatorIcon` attr from a live editor's document.
|
|
498
|
+
* Returns `null` if the attr is absent or null.
|
|
499
|
+
*/
|
|
500
|
+
export declare function getSeparatorIconAttr(editor: Editor_2 | null): SeparatorIconDocAttr | null;
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Returns the `title` attr from a live editor's document.
|
|
504
|
+
* Returns `null` if the attr is absent or null.
|
|
505
|
+
*/
|
|
506
|
+
export declare function getTitleAttr(editor: Editor_2 | null): TitleDocAttr | null;
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* @matops/editor — Icon Library
|
|
510
|
+
*
|
|
511
|
+
* Single source of truth for all inline SVG icons used across the editor UI.
|
|
512
|
+
* No external icon library dependency — keeps bundle lean and icons consistent.
|
|
513
|
+
*
|
|
514
|
+
* Naming convention: <PurposeName>Icon
|
|
515
|
+
* All icons default to 14×14 unless a specific size is needed by their context.
|
|
516
|
+
*/
|
|
517
|
+
declare interface IconProps {
|
|
518
|
+
size?: number;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* ImageBubbleMenu
|
|
523
|
+
*
|
|
524
|
+
* Appears when an image is selected. Provides:
|
|
525
|
+
* - Text alignment (left / center / right)
|
|
526
|
+
* - Alt text editing via prompt
|
|
527
|
+
* - Delete image
|
|
528
|
+
*
|
|
529
|
+
* Uses `pluginKey="imageMenu"` to coexist with text + link bubble menus.
|
|
530
|
+
*/
|
|
531
|
+
export declare function ImageBubbleMenu(): JSX_2.Element | null;
|
|
532
|
+
|
|
533
|
+
export declare function isDefaultCrop(crop: CropRect): boolean;
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* KeyboardShortcutsModal
|
|
537
|
+
*
|
|
538
|
+
* Feature-aware keyboard shortcut reference.
|
|
539
|
+
* Only shows shortcuts whose `feature` is currently active.
|
|
540
|
+
* Closes on Escape or overlay click.
|
|
541
|
+
*
|
|
542
|
+
* Triggered by: `?` key (via useShortcutsModal) or toolbar Help button.
|
|
543
|
+
*/
|
|
544
|
+
export declare function KeyboardShortcutsModal({ open, onClose, }: KeyboardShortcutsModalProps): JSX_2.Element | null;
|
|
545
|
+
|
|
546
|
+
declare interface KeyboardShortcutsModalProps {
|
|
547
|
+
open: boolean;
|
|
548
|
+
onClose: () => void;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* LinkPopover
|
|
553
|
+
*
|
|
554
|
+
* Appears when the cursor is inside a link node.
|
|
555
|
+
* Two modes:
|
|
556
|
+
* - Preview: shows URL with edit / open / unlink buttons
|
|
557
|
+
* - Edit: inline input field to change the URL
|
|
558
|
+
*
|
|
559
|
+
* Uses `pluginKey="linkMenu"` to coexist with the text formatting BubbleMenu.
|
|
560
|
+
*/
|
|
561
|
+
export declare function LinkPopover(): JSX_2.Element | null;
|
|
562
|
+
|
|
563
|
+
export declare const MatopsDocument: Node_2<any, any>;
|
|
564
|
+
|
|
565
|
+
declare function MatopsEditor(props: EditorProps): JSX_2.Element;
|
|
566
|
+
export { MatopsEditor as Editor }
|
|
567
|
+
export { MatopsEditor }
|
|
568
|
+
export default MatopsEditor;
|
|
569
|
+
|
|
570
|
+
declare function MatopsViewer({ content, theme, className, separatorIcon, showStats, }: EditorViewerProps): JSX_2.Element;
|
|
571
|
+
export { MatopsViewer as EditorViewer }
|
|
572
|
+
export { MatopsViewer }
|
|
573
|
+
|
|
574
|
+
export declare function MenuButton({ onClick, isActive, isDisabled, isDanger, title, className, children, }: MenuButtonProps): JSX_2.Element;
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* MenuButton — shared button primitive for all floating menus.
|
|
578
|
+
*
|
|
579
|
+
* Uses `onMouseDown` + `e.preventDefault()` to prevent the editor from
|
|
580
|
+
* losing focus when a menu button is pressed.
|
|
581
|
+
*/
|
|
582
|
+
declare interface MenuButtonProps {
|
|
583
|
+
onClick: () => void;
|
|
584
|
+
isActive?: boolean;
|
|
585
|
+
isDisabled?: boolean;
|
|
586
|
+
isDanger?: boolean;
|
|
587
|
+
title: string;
|
|
588
|
+
className?: string;
|
|
589
|
+
children: default_2.ReactNode;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
export declare function MenuDivider(): JSX_2.Element;
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Migrate a **legacy** document (structural nodes in `content[]`) to the
|
|
596
|
+
* **external** format (structural metadata in `doc.attrs`).
|
|
597
|
+
*
|
|
598
|
+
* Safe to call on already-migrated documents — returns them unchanged.
|
|
599
|
+
* Alias of `toExternalFormat`.
|
|
600
|
+
*/
|
|
601
|
+
export declare const migrateToDocAttrs: typeof toExternalFormat;
|
|
602
|
+
|
|
603
|
+
export declare function ModalDialog({ children, className, label, }: {
|
|
604
|
+
children: default_2.ReactNode;
|
|
605
|
+
className?: string;
|
|
606
|
+
label?: string;
|
|
607
|
+
}): JSX_2.Element;
|
|
608
|
+
|
|
609
|
+
export declare function ModalHeader({ title, onClose, }: {
|
|
610
|
+
title: string;
|
|
611
|
+
onClose: () => void;
|
|
612
|
+
}): JSX_2.Element;
|
|
613
|
+
|
|
614
|
+
export declare function ModalOverlay({ onClose, children, }: {
|
|
615
|
+
onClose: () => void;
|
|
616
|
+
children: default_2.ReactNode;
|
|
617
|
+
}): default_2.ReactPortal;
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* PageHeaderGuard — stub extension for the `"page-header"` feature.
|
|
621
|
+
* Previously guarded title + separator-icon content nodes; now a no-op since
|
|
622
|
+
* those sections live in doc.attrs and are rendered as React panels.
|
|
623
|
+
*/
|
|
624
|
+
export declare const PageHeaderGuard: Extension<any, any>;
|
|
625
|
+
|
|
626
|
+
export declare function parseAttachments(raw: string | null | undefined): AttachmentItem[];
|
|
627
|
+
|
|
628
|
+
export declare function readCropFromAttrs(attrs: unknown): CropRect;
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Rebuild a Tiptap document in **internal format** (structural nodes in `content[]`)
|
|
632
|
+
* from any input format: external (doc.attrs), legacy (structural content nodes),
|
|
633
|
+
* or internal (already has content nodes).
|
|
634
|
+
*
|
|
635
|
+
* Called by `Editor.tsx` when features change so that Tiptap always receives a
|
|
636
|
+
* document whose `content[]` contains the correct set of structural nodes for the
|
|
637
|
+
* active feature set.
|
|
638
|
+
*
|
|
639
|
+
* @param current - Latest live document JSON (any format).
|
|
640
|
+
* @param hasCoverImage - Whether `"cover-image"` feature is active.
|
|
641
|
+
* @param hasPageHeader - Whether `"page-header"` feature is active.
|
|
642
|
+
* @param hasAttachments - Whether `"attachments"` feature is active.
|
|
643
|
+
* @param fallbackContent - Used as a secondary source when structural data is
|
|
644
|
+
* absent from `current`. Defaults to `current`.
|
|
645
|
+
*/
|
|
646
|
+
export declare function rebuildContent(current: JSONContent, hasCoverImage: boolean, hasPageHeader: boolean, hasAttachments: boolean, fallbackContent?: JSONContent): JSONContent;
|
|
647
|
+
|
|
648
|
+
export declare function registerFeature(definition: FeatureDefinition): void;
|
|
649
|
+
|
|
650
|
+
declare interface ResolvedEditorConfig {
|
|
651
|
+
resolvedFeatures: EditorFeature[];
|
|
652
|
+
extensions: Extensions;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
export declare const SearchExtension: Extension<any, any>;
|
|
656
|
+
|
|
657
|
+
export declare interface SearchMatch {
|
|
658
|
+
from: number;
|
|
659
|
+
to: number;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
export declare const searchPluginKey: PluginKey<SearchPluginState>;
|
|
663
|
+
|
|
664
|
+
declare interface SearchPluginState {
|
|
665
|
+
query: string;
|
|
666
|
+
caseSensitive: boolean;
|
|
667
|
+
decorations: DecorationSet;
|
|
668
|
+
results: SearchMatch[];
|
|
669
|
+
currentIndex: number;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
export declare interface SeparatorIconAttrs {
|
|
673
|
+
src: string | null;
|
|
674
|
+
alt: string;
|
|
675
|
+
cropX: number;
|
|
676
|
+
cropY: number;
|
|
677
|
+
cropWidth: number;
|
|
678
|
+
cropHeight: number;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
export declare interface SeparatorIconDocAttr {
|
|
682
|
+
src: string | null;
|
|
683
|
+
alt: string;
|
|
684
|
+
cropX: number;
|
|
685
|
+
cropY: number;
|
|
686
|
+
cropWidth: number;
|
|
687
|
+
cropHeight: number;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
export declare const SeparatorIconNode: Node_2<any, any>;
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* SeparatorIconPanel — React panel (Panel 1) for the title/body separator.
|
|
694
|
+
*
|
|
695
|
+
* Reads from `editor.state.doc.attrs.separatorIcon` (a SeparatorIconDocAttr or null).
|
|
696
|
+
* Writes via `editor.commands.setSeparatorIconAttr(...)`.
|
|
697
|
+
*
|
|
698
|
+
* Renders: ────── [badge] ──────
|
|
699
|
+
*
|
|
700
|
+
* Icon resolution priority:
|
|
701
|
+
* 1. doc.attrs.separatorIcon.src + crop → uploaded image, cropped
|
|
702
|
+
* 2. separatorIcon prop (ReactNode from EditorProvider)
|
|
703
|
+
* 3. Default quill SVG
|
|
704
|
+
*
|
|
705
|
+
* No ProseMirror NodeView — this is pure React rendered above <EditorContent>.
|
|
706
|
+
*/
|
|
707
|
+
export declare function SeparatorIconPanel(): JSX_2.Element | null;
|
|
708
|
+
|
|
709
|
+
export declare function serializeAttachments(items: AttachmentItem[]): string;
|
|
710
|
+
|
|
711
|
+
export declare function SlashMenu(): JSX_2.Element | null;
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Live defaults consumed by the table insert command in commandRegistry.ts
|
|
715
|
+
* and by the toolbar / slash-menu integrations.
|
|
716
|
+
*
|
|
717
|
+
* Do NOT mutate this object directly — use configureTablesFeature() instead
|
|
718
|
+
* so that the feature registration is re-run with the updated options.
|
|
719
|
+
*/
|
|
720
|
+
export declare const TABLE_DEFAULTS: Required<TableFeatureOptions>;
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* TableContextMenu
|
|
724
|
+
*
|
|
725
|
+
* A BubbleMenu that appears whenever the cursor is inside a table.
|
|
726
|
+
* Uses `pluginKey="tableMenu"` to coexist with other BubbleMenus —
|
|
727
|
+
* FormattingBubbleMenu suppresses itself when `e.isActive("table")` so
|
|
728
|
+
* these two menus never overlap.
|
|
729
|
+
*
|
|
730
|
+
* Sections (always): Row | Column | Cell | Table
|
|
731
|
+
* Section (conditional): Format — shown only when text is selected inside
|
|
732
|
+
* a cell (from !== to), giving users bold/italic/etc. without needing to
|
|
733
|
+
* dismiss the table menu first.
|
|
734
|
+
*
|
|
735
|
+
* v3: imports from @tiptap/react/menus, uses `options` (not `tippyOptions`).
|
|
736
|
+
*/
|
|
737
|
+
export declare function TableContextMenu(): JSX_2.Element | null;
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* @feature tables
|
|
741
|
+
*
|
|
742
|
+
* Provides rich table support built on top of @tiptap/extension-table's
|
|
743
|
+
* TableKit bundle (Table + TableRow + TableHeader + TableCell).
|
|
744
|
+
*
|
|
745
|
+
* ── What this feature provides ────────────────────────────────────────
|
|
746
|
+
*
|
|
747
|
+
* Extensions (Tiptap)
|
|
748
|
+
* • Table — the table node with column-resize handles
|
|
749
|
+
* • TableRow — <tr> node
|
|
750
|
+
* • TableHeader — <th> node with default header styling
|
|
751
|
+
* • TableCell — <td> node
|
|
752
|
+
*
|
|
753
|
+
* UI (activated automatically when this feature is resolved)
|
|
754
|
+
* • Toolbar button — "Insert Table" icon in the toolbar block strip
|
|
755
|
+
* • Slash command — /table inserts a default-sized table
|
|
756
|
+
* • TableContextMenu — BubbleMenu that appears inside a table with
|
|
757
|
+
* Row / Column / Cell / Table action sections
|
|
758
|
+
*
|
|
759
|
+
* Keyboard shortcuts (built into Tiptap table extensions)
|
|
760
|
+
* • Tab — move to next cell (creates new row at end)
|
|
761
|
+
* • Shift+Tab — move to previous cell
|
|
762
|
+
*
|
|
763
|
+
* ── Enabled vs disabled ───────────────────────────────────────────────
|
|
764
|
+
*
|
|
765
|
+
* Enabled → TableKit is loaded. All of the above are active. The toolbar
|
|
766
|
+
* table button and /table slash command both insert a table with
|
|
767
|
+
* TABLE_DEFAULTS rows, cols, and withHeaderRow settings.
|
|
768
|
+
*
|
|
769
|
+
* Disabled → No table schema. Existing table nodes in a document will not
|
|
770
|
+
* parse correctly and content may be lost. If you need read-only
|
|
771
|
+
* table rendering without the editing UI, keep this feature on
|
|
772
|
+
* and set `editable={false}` on the editor instead.
|
|
773
|
+
*
|
|
774
|
+
* ── Custom configuration ──────────────────────────────────────────────
|
|
775
|
+
*
|
|
776
|
+
* Call configureTablesFeature(options) BEFORE featureBootstrap runs to
|
|
777
|
+
* override the defaults. Typically done in your app entry point:
|
|
778
|
+
*
|
|
779
|
+
* import { configureTablesFeature } from "@matops/editor/extensions/features/tablesFeature";
|
|
780
|
+
*
|
|
781
|
+
* configureTablesFeature({
|
|
782
|
+
* resizable: true,
|
|
783
|
+
* cellMinWidth: 80,
|
|
784
|
+
* defaultRows: 4,
|
|
785
|
+
* defaultCols: 4,
|
|
786
|
+
* withHeaderRow: true,
|
|
787
|
+
* });
|
|
788
|
+
*
|
|
789
|
+
* featureBootstrap.ts still re-imports this file — the registration is
|
|
790
|
+
* idempotent (it warns and overwrites on duplicate) so calling
|
|
791
|
+
* configureTablesFeature() first is safe and the correct approach.
|
|
792
|
+
*
|
|
793
|
+
* ── Dependencies ─────────────────────────────────────────────────────
|
|
794
|
+
* Requires "formatting" because TableCell content is paragraph-based and
|
|
795
|
+
* needs the paragraph + text extensions already registered.
|
|
796
|
+
*/
|
|
797
|
+
/**
|
|
798
|
+
* Options for the "tables" feature.
|
|
799
|
+
*
|
|
800
|
+
* All fields are optional — unset fields fall back to TABLE_DEFAULTS.
|
|
801
|
+
*/
|
|
802
|
+
export declare interface TableFeatureOptions {
|
|
803
|
+
/**
|
|
804
|
+
* Allow column widths to be dragged to resize.
|
|
805
|
+
* @default true
|
|
806
|
+
*/
|
|
807
|
+
resizable?: boolean;
|
|
808
|
+
/**
|
|
809
|
+
* Minimum width in pixels for every table cell.
|
|
810
|
+
* Prevents columns from collapsing to zero when resizing.
|
|
811
|
+
* @default 100
|
|
812
|
+
*/
|
|
813
|
+
cellMinWidth?: number;
|
|
814
|
+
/**
|
|
815
|
+
* Whether the last column can be resized.
|
|
816
|
+
* Set false when the table fills the full content width and the last
|
|
817
|
+
* column should stretch to absorb any remaining space.
|
|
818
|
+
* @default true
|
|
819
|
+
*/
|
|
820
|
+
lastColumnResizable?: boolean;
|
|
821
|
+
/**
|
|
822
|
+
* Number of rows inserted when a new table is created via the toolbar
|
|
823
|
+
* button or the /table slash command.
|
|
824
|
+
* @default 3
|
|
825
|
+
*/
|
|
826
|
+
defaultRows?: number;
|
|
827
|
+
/**
|
|
828
|
+
* Number of columns inserted when a new table is created.
|
|
829
|
+
* @default 3
|
|
830
|
+
*/
|
|
831
|
+
defaultCols?: number;
|
|
832
|
+
/**
|
|
833
|
+
* Whether newly inserted tables include a styled header row.
|
|
834
|
+
* @default true
|
|
835
|
+
*/
|
|
836
|
+
withHeaderRow?: boolean;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
export declare interface TitleAttrs {
|
|
840
|
+
placeholder: string;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
export declare interface TitleDocAttr {
|
|
844
|
+
text: string;
|
|
845
|
+
placeholder: string;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
export declare const TitleNode: Node_2<any, any>;
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* TitlePanel — React panel (Panel 1) for the document title.
|
|
852
|
+
*
|
|
853
|
+
* Reads from `editor.state.doc.attrs.title` (a TitleDocAttr or null).
|
|
854
|
+
* Writes via `editor.commands.setTitleAttr({ text })`.
|
|
855
|
+
*
|
|
856
|
+
* Uses a contentEditable div so the user gets native text-editing behaviour
|
|
857
|
+
* (cursor, selection, copy/paste). The doc.attrs.title.text is the source of
|
|
858
|
+
* truth; the div is kept in sync via a ref and only triggers a command when
|
|
859
|
+
* the user actually changes the text (avoids re-render loops).
|
|
860
|
+
*
|
|
861
|
+
* No ProseMirror NodeView — this is pure React rendered above <EditorContent>.
|
|
862
|
+
*/
|
|
863
|
+
export declare function TitlePanel(): JSX_2.Element | null;
|
|
864
|
+
|
|
865
|
+
export declare function TitleSeparator({ icon, hasImageIcon }: TitleSeparatorProps): JSX_2.Element;
|
|
866
|
+
|
|
867
|
+
declare interface TitleSeparatorProps {
|
|
868
|
+
/** Custom icon to render in the centre badge. Defaults to the quill SVG. */
|
|
869
|
+
icon?: ReactNode;
|
|
870
|
+
/**
|
|
871
|
+
* Set to true when the icon is an uploaded image that may use position:absolute
|
|
872
|
+
* crop styles. Adds `overflow:hidden` + `position:relative` to the badge span
|
|
873
|
+
* so the cropped image is clipped correctly.
|
|
874
|
+
*/
|
|
875
|
+
hasImageIcon?: boolean;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Convert a Tiptap **internal** document (structural nodes in `content[]`) to
|
|
880
|
+
* **external** format (structural metadata in `doc.attrs`, body-only `content[]`).
|
|
881
|
+
*
|
|
882
|
+
* This is called inside `useEditorInstance` before firing `onChange` so that
|
|
883
|
+
* consumers always receive the canonical external format regardless of how
|
|
884
|
+
* Tiptap stores the document internally.
|
|
885
|
+
*
|
|
886
|
+
* Safe to call on documents already in external format — returns them unchanged.
|
|
887
|
+
*/
|
|
888
|
+
export declare function toExternalFormat(doc: JSONContent): JSONContent;
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Convert a Tiptap JSONContent node tree to Markdown.
|
|
892
|
+
*
|
|
893
|
+
* Supports all standard nodes plus the page-header nodes:
|
|
894
|
+
* - `cover-image` → HTML img tag (no native Markdown equivalent)
|
|
895
|
+
* - `title` → # heading (H1)
|
|
896
|
+
*
|
|
897
|
+
* @param node - The JSONContent node to serialize
|
|
898
|
+
* @param depth - Indentation depth for nested lists (internal)
|
|
899
|
+
*/
|
|
900
|
+
export declare function toMarkdown(node: JSONContent, depth?: number): string;
|
|
901
|
+
|
|
902
|
+
export declare const UploadIcon: ({ size }: IconProps) => JSX_2.Element;
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* useDropdown
|
|
906
|
+
*
|
|
907
|
+
* Shared hook for portal-based dropdown menus used in EditorToolbar and
|
|
908
|
+
* FormattingBubbleMenu. Handles:
|
|
909
|
+
* - Open / close state
|
|
910
|
+
* - Post-render position measurement (via useLayoutEffect)
|
|
911
|
+
* - Viewport clamping so the menu never overflows the screen
|
|
912
|
+
* - Close on outside click and scroll
|
|
913
|
+
*
|
|
914
|
+
* The menu is initially rendered off-screen (left: -9999) and becomes
|
|
915
|
+
* visible only after its real dimensions are measured.
|
|
916
|
+
*
|
|
917
|
+
* @example
|
|
918
|
+
* const { open, visible, dropPos, triggerRef, menuRef, toggle, close } =
|
|
919
|
+
* useDropdown({ offset: 6 });
|
|
920
|
+
*/
|
|
921
|
+
export declare function useDropdown({ offset }?: UseDropdownOptions): UseDropdownResult;
|
|
922
|
+
|
|
923
|
+
declare interface UseDropdownOptions {
|
|
924
|
+
/** Extra vertical gap between trigger and menu (px). Default 4. */
|
|
925
|
+
offset?: number;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
declare interface UseDropdownResult {
|
|
929
|
+
open: boolean;
|
|
930
|
+
visible: boolean;
|
|
931
|
+
dropPos: DropdownPosition;
|
|
932
|
+
triggerRef: RefObject<HTMLButtonElement>;
|
|
933
|
+
menuRef: RefObject<HTMLDivElement>;
|
|
934
|
+
toggle: () => void;
|
|
935
|
+
close: () => void;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/**
|
|
939
|
+
* Returns the live Tiptap editor instance, or null while initializing.
|
|
940
|
+
*/
|
|
941
|
+
export declare const useEditor: () => Editor_2 | null;
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* Returns the raw EditorContext value.
|
|
945
|
+
* Use the focused hooks in editorHooks.ts for most cases — this is
|
|
946
|
+
* only needed when accessing onFileUploaded or separatorIcon directly.
|
|
947
|
+
*/
|
|
948
|
+
export declare function useEditorContext(): EditorContextValue;
|
|
949
|
+
|
|
950
|
+
/**
|
|
951
|
+
* useEditorInstance
|
|
952
|
+
*
|
|
953
|
+
* Manages the full Tiptap editor lifecycle for the <Editor> component.
|
|
954
|
+
*
|
|
955
|
+
* Design decisions:
|
|
956
|
+
* - `buildEditorConfig` is called once on mount and stored in a ref. The
|
|
957
|
+
* feature list and placeholder are intentionally not reactive — changing
|
|
958
|
+
* them after mount would require destroying and recreating the entire editor.
|
|
959
|
+
* - Callback props (onChange, onContentChange, onEditorReady) are stored in
|
|
960
|
+
* refs so they can be updated without recreating the editor instance.
|
|
961
|
+
* - `editable` is the only prop synced reactively via editor.setEditable().
|
|
962
|
+
*/
|
|
963
|
+
export declare function useEditorInstance({ features, initialContent, editable, placeholder, collaborationProvider, onChange, onContentChange, onEditorReady, }: UseEditorInstanceOptions): UseEditorInstanceResult;
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* Subset of EditorProps consumed by this hook.
|
|
967
|
+
* Uses Pick so adding a prop to EditorProps automatically makes it available here.
|
|
968
|
+
*
|
|
969
|
+
* NOTE: "placeholder" is intentionally included even though the Placeholder
|
|
970
|
+
* extension is configured at build time (not Tiptap's internal placeholder).
|
|
971
|
+
* It must flow through here → buildEditorConfig → Placeholder.configure().
|
|
972
|
+
*/
|
|
973
|
+
declare type UseEditorInstanceOptions = Pick<EditorProps, "features" | "initialContent" | "editable" | "placeholder" | "collaborationProvider" | "onChange" | "onContentChange" | "onEditorReady">;
|
|
974
|
+
|
|
975
|
+
declare interface UseEditorInstanceResult {
|
|
976
|
+
editor: Editor_2 | null;
|
|
977
|
+
resolvedFeatures: EditorFeature[];
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* useEditorKeyboard
|
|
982
|
+
*
|
|
983
|
+
* Central hub for all global keyboard shortcuts that live outside the
|
|
984
|
+
* Tiptap extension system. Tiptap handles its own shortcuts (bold, italic, etc.)
|
|
985
|
+
* internally — this hook only manages shortcuts that need React state or that
|
|
986
|
+
* trigger UI panels/modals.
|
|
987
|
+
*
|
|
988
|
+
* Shortcuts managed here:
|
|
989
|
+
* - Ctrl/Cmd + Shift + P → onPublish (save/publish document)
|
|
990
|
+
* - Ctrl/Cmd + F → open Find & Replace panel
|
|
991
|
+
*
|
|
992
|
+
* To add a new shortcut:
|
|
993
|
+
* 1. Add its handler inside the `handler` function below
|
|
994
|
+
* 2. Add it to KeyboardShortcutsModal.tsx SHORTCUTS data array
|
|
995
|
+
*
|
|
996
|
+
* Shortcuts NOT managed here:
|
|
997
|
+
* - `?` → KeyboardShortcutsModal (managed by useShortcutsModal)
|
|
998
|
+
* - Formatting shortcuts (Bold, Italic…) → handled by Tiptap extensions
|
|
999
|
+
* - Table navigation (Tab) → handled by Tiptap table extension
|
|
1000
|
+
* - Slash command (/) → handled by SlashMenu
|
|
1001
|
+
* - Escape → handled locally in each panel/modal component
|
|
1002
|
+
*/
|
|
1003
|
+
export declare function useEditorKeyboard({ editor, editable, resolvedFeatures, onPublish, onOpenFind, }: UseEditorKeyboardOptions): void;
|
|
1004
|
+
|
|
1005
|
+
declare interface UseEditorKeyboardOptions {
|
|
1006
|
+
editor: Editor_2 | null;
|
|
1007
|
+
editable: boolean;
|
|
1008
|
+
resolvedFeatures: EditorFeature[];
|
|
1009
|
+
onPublish?: (content: JSONContent) => void;
|
|
1010
|
+
onOpenFind?: () => void;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
/**
|
|
1014
|
+
* Subscribes to a derived slice of editor state.
|
|
1015
|
+
* Re-renders only when the selected value changes (by reference equality).
|
|
1016
|
+
*
|
|
1017
|
+
* @example
|
|
1018
|
+
* const isBold = useEditorState(ed => ed?.isActive("bold") ?? false);
|
|
1019
|
+
*/
|
|
1020
|
+
export declare function useEditorState<T>(selector: (editor: Editor_2 | null) => T): T;
|
|
1021
|
+
|
|
1022
|
+
/**
|
|
1023
|
+
* Returns the current editor theme.
|
|
1024
|
+
*/
|
|
1025
|
+
export declare function useEditorTheme(): EditorTheme;
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* Forces a re-render on every editor transaction.
|
|
1029
|
+
* Use when you need UI to stay in sync with every state change.
|
|
1030
|
+
*/
|
|
1031
|
+
export declare function useEditorUpdate(): void;
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* Returns true if a single feature is active in the current editor instance.
|
|
1035
|
+
*/
|
|
1036
|
+
export declare function useFeature(feature: EditorFeature): boolean;
|
|
1037
|
+
|
|
1038
|
+
/**
|
|
1039
|
+
* Returns a map of all feature flags as named booleans.
|
|
1040
|
+
* Prefer this over multiple `useFeature` calls in the same component.
|
|
1041
|
+
*/
|
|
1042
|
+
export declare function useFeatures(): {
|
|
1043
|
+
hasFormatting: boolean;
|
|
1044
|
+
hasCode: boolean;
|
|
1045
|
+
hasMedia: boolean;
|
|
1046
|
+
hasTables: boolean;
|
|
1047
|
+
hasTaskList: boolean;
|
|
1048
|
+
hasCollaboration: boolean;
|
|
1049
|
+
hasHistory: boolean;
|
|
1050
|
+
hasPlaceholder: boolean;
|
|
1051
|
+
hasCharCount: boolean;
|
|
1052
|
+
hasFindReplace: boolean;
|
|
1053
|
+
hasCoverImage: boolean;
|
|
1054
|
+
hasPageHeader: boolean;
|
|
1055
|
+
hasAttachments: boolean;
|
|
1056
|
+
};
|
|
1057
|
+
|
|
1058
|
+
export declare function useImageUpload({ editor, editable, onFileUploaded, containerRef, }: UseImageUploadOptions): void;
|
|
1059
|
+
|
|
1060
|
+
declare interface UseImageUploadOptions {
|
|
1061
|
+
editor: Editor_2 | null;
|
|
1062
|
+
editable: boolean;
|
|
1063
|
+
onFileUploaded?: (file: File) => Promise<string>;
|
|
1064
|
+
containerRef?: React.RefObject<HTMLElement>;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
/**
|
|
1068
|
+
* useShortcutsModal
|
|
1069
|
+
*
|
|
1070
|
+
* Manages open/close state for the KeyboardShortcutsModal.
|
|
1071
|
+
* Binds the `?` key globally to toggle the modal, but only when
|
|
1072
|
+
* the active element is not a text input or textarea (to avoid
|
|
1073
|
+
* interfering with typing "?" in form fields or in the editor itself).
|
|
1074
|
+
*
|
|
1075
|
+
* Usage in parent:
|
|
1076
|
+
* ```ts
|
|
1077
|
+
* const { open, onClose, setOpen } = useShortcutsModal();
|
|
1078
|
+
* <KeyboardShortcutsModal open={open} onClose={onClose} />
|
|
1079
|
+
* ```
|
|
1080
|
+
*/
|
|
1081
|
+
export declare function useShortcutsModal(): {
|
|
1082
|
+
open: boolean;
|
|
1083
|
+
setOpen: Dispatch<SetStateAction<boolean>>;
|
|
1084
|
+
onClose: () => void;
|
|
1085
|
+
};
|
|
1086
|
+
|
|
1087
|
+
export { }
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
/** Augment Tiptap's Commands interface so TypeScript knows about all doc-attr setters. */
|
|
1091
|
+
declare module "@tiptap/core" {
|
|
1092
|
+
interface Commands<ReturnType> {
|
|
1093
|
+
matopsDocument: {
|
|
1094
|
+
/**
|
|
1095
|
+
* Update the document-level `contentWidth` layout attribute.
|
|
1096
|
+
*
|
|
1097
|
+
* @example
|
|
1098
|
+
* editor.commands.setContentWidth("compact")
|
|
1099
|
+
*/
|
|
1100
|
+
setContentWidth: (width: MatopsContentWidth) => ReturnType;
|
|
1101
|
+
/**
|
|
1102
|
+
* Set or clear the cover-image doc attr.
|
|
1103
|
+
*
|
|
1104
|
+
* Pass a partial `CoverImageDocAttr` to merge into the existing value,
|
|
1105
|
+
* or `null` to remove the cover image (keeps the attr key with null value
|
|
1106
|
+
* so the feature knows the slot exists).
|
|
1107
|
+
*
|
|
1108
|
+
* @example
|
|
1109
|
+
* editor.commands.setCoverImageAttr({ src: "https://cdn.example.com/banner.jpg" })
|
|
1110
|
+
* editor.commands.setCoverImageAttr(null) // clear image
|
|
1111
|
+
*/
|
|
1112
|
+
setCoverImageAttr: (value: Partial<CoverImageDocAttr> | null) => ReturnType;
|
|
1113
|
+
/**
|
|
1114
|
+
* Update the title text and/or placeholder stored in the doc attr.
|
|
1115
|
+
*
|
|
1116
|
+
* @example
|
|
1117
|
+
* editor.commands.setTitleAttr({ text: "My Document" })
|
|
1118
|
+
* editor.commands.setTitleAttr({ text: "Draft", placeholder: "Untitled" })
|
|
1119
|
+
*/
|
|
1120
|
+
setTitleAttr: (value: Partial<TitleDocAttr> | null) => ReturnType;
|
|
1121
|
+
/**
|
|
1122
|
+
* Set or clear the separator-icon doc attr.
|
|
1123
|
+
*
|
|
1124
|
+
* @example
|
|
1125
|
+
* editor.commands.setSeparatorIconAttr({ src: "https://cdn.example.com/logo.png" })
|
|
1126
|
+
* editor.commands.setSeparatorIconAttr(null) // revert to default icon
|
|
1127
|
+
*/
|
|
1128
|
+
setSeparatorIconAttr: (value: Partial<SeparatorIconDocAttr> | null) => ReturnType;
|
|
1129
|
+
/**
|
|
1130
|
+
* Replace the attachments list stored in the doc attr.
|
|
1131
|
+
*
|
|
1132
|
+
* @example
|
|
1133
|
+
* editor.commands.setAttachmentsAttr([
|
|
1134
|
+
* { id: "a1", name: "brief.pdf", size: 51200, mimeType: "application/pdf", url: "https://…" }
|
|
1135
|
+
* ])
|
|
1136
|
+
*/
|
|
1137
|
+
setAttachmentsAttr: (items: AttachmentItem[]) => ReturnType;
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
}
|