@pubwave/editor 0.1.1-alpha.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/LICENSE +22 -0
- package/README.md +661 -0
- package/dist/index.cjs +7499 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +1339 -0
- package/dist/index.js +7499 -0
- package/dist/index.js.map +1 -0
- package/package.json +132 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1339 @@
|
|
|
1
|
+
import { default as default_2 } from 'react';
|
|
2
|
+
import { Editor } from '@tiptap/react';
|
|
3
|
+
import { Editor as Editor_2 } from '@tiptap/core';
|
|
4
|
+
import { Extension } from '@tiptap/core';
|
|
5
|
+
import { ForwardRefExoticComponent } from 'react';
|
|
6
|
+
import { JSONContent } from '@tiptap/core';
|
|
7
|
+
import { Node as Node_2 } from '@tiptap/pm/model';
|
|
8
|
+
import { Plugin as Plugin_2 } from '@tiptap/pm/state';
|
|
9
|
+
import { PluginKey } from '@tiptap/pm/state';
|
|
10
|
+
import { RefAttributes } from 'react';
|
|
11
|
+
import { SuggestionKeyDownProps } from '@tiptap/suggestion';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Action result for feedback
|
|
15
|
+
*/
|
|
16
|
+
export declare interface ActionResult {
|
|
17
|
+
success: boolean;
|
|
18
|
+
message?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
declare interface BlockExtensionsConfig {
|
|
22
|
+
/**
|
|
23
|
+
* Heading levels to support
|
|
24
|
+
* @default [1, 2, 3]
|
|
25
|
+
*/
|
|
26
|
+
headingLevels?: (1 | 2 | 3 | 4 | 5 | 6)[];
|
|
27
|
+
/**
|
|
28
|
+
* Image upload configuration
|
|
29
|
+
*/
|
|
30
|
+
imageUpload?: ImageUploadConfig;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* BlockHandle Component - Notion-style block controls
|
|
35
|
+
*/
|
|
36
|
+
export declare function BlockHandle({ editor }: BlockHandleProps): default_2.ReactElement | null;
|
|
37
|
+
|
|
38
|
+
export declare interface BlockHandleProps {
|
|
39
|
+
/** The Tiptap editor instance */
|
|
40
|
+
editor: Editor_2;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Supported block types in the editor
|
|
45
|
+
*/
|
|
46
|
+
export declare type BlockType = 'paragraph' | 'heading' | 'bulletList' | 'orderedList' | 'taskList' | 'blockquote' | 'codeBlock' | 'horizontalRule' | 'image';
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* BubbleToolbar - Selection-driven floating toolbar
|
|
50
|
+
*/
|
|
51
|
+
export declare function BubbleToolbar({ editor, className, children, onVisibilityChange, }: BubbleToolbarProps): default_2.ReactElement | null;
|
|
52
|
+
|
|
53
|
+
export declare interface BubbleToolbarProps {
|
|
54
|
+
/** The Tiptap editor instance */
|
|
55
|
+
editor: Editor_2;
|
|
56
|
+
/** Additional CSS class names */
|
|
57
|
+
className?: string;
|
|
58
|
+
/** Custom toolbar content (renders default if not provided) */
|
|
59
|
+
children?: default_2.ReactNode;
|
|
60
|
+
/** Callback when toolbar visibility changes */
|
|
61
|
+
onVisibilityChange?: (visible: boolean) => void;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Cancel a drag operation
|
|
66
|
+
*/
|
|
67
|
+
export declare function cancelDrag(editor: Editor_2): void;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check if DOM APIs are available
|
|
71
|
+
* Use this before accessing window, document, or other browser APIs
|
|
72
|
+
*/
|
|
73
|
+
export declare const canUseDOM: boolean;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Clear all formatting from the selection
|
|
77
|
+
*/
|
|
78
|
+
export declare function clearFormatting(editor: Editor_2): boolean;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Utility function to combine class names
|
|
82
|
+
* Filters out falsy values and joins with space
|
|
83
|
+
*/
|
|
84
|
+
export declare function cn(...classes: (string | boolean | undefined | null)[]): string;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Action factory for creating toolbar action handlers
|
|
88
|
+
* Returns a function that can be used as onClick handler
|
|
89
|
+
*/
|
|
90
|
+
export declare function createActionHandler(editor: Editor_2, action: (editor: Editor_2) => ActionResult, onResult?: (result: ActionResult) => void): () => void;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Auto-scroll Utility
|
|
94
|
+
*
|
|
95
|
+
* Enables automatic scrolling when dragging near viewport edges.
|
|
96
|
+
* Essential for long documents where blocks need to be moved across visible area.
|
|
97
|
+
*
|
|
98
|
+
* Key behaviors:
|
|
99
|
+
* - Smooth scrolling that accelerates near edges
|
|
100
|
+
* - Works with both window and container scrolling
|
|
101
|
+
* - Cleans up properly when drag ends
|
|
102
|
+
*/
|
|
103
|
+
/**
|
|
104
|
+
* Create an auto-scroll controller for drag operations
|
|
105
|
+
*/
|
|
106
|
+
export declare function createAutoScroller(scrollContainer?: HTMLElement | null): {
|
|
107
|
+
start: () => void;
|
|
108
|
+
update: (clientY: number) => void;
|
|
109
|
+
stop: () => void;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Create the DnD ProseMirror plugin
|
|
114
|
+
*/
|
|
115
|
+
export declare function createDndPlugin(editor?: Editor_2): Plugin_2<DndState>;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Create a new editor instance
|
|
119
|
+
*
|
|
120
|
+
* This factory function creates a configured Tiptap editor with all necessary
|
|
121
|
+
* extensions and settings based on the provided configuration.
|
|
122
|
+
*
|
|
123
|
+
* @param config - Editor configuration options
|
|
124
|
+
* @returns A configured Tiptap Editor instance
|
|
125
|
+
* @throws Error if called in a non-browser environment without proper guards
|
|
126
|
+
*/
|
|
127
|
+
export declare function createEditor(config?: EditorConfig): Editor_2;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Create the core extension set for the editor
|
|
131
|
+
*
|
|
132
|
+
* This composes all block, mark, and feature extensions into a single array.
|
|
133
|
+
*/
|
|
134
|
+
export declare function createExtensions(config?: ExtensionConfig): Extension[];
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Create a focus trap within the editor UI
|
|
138
|
+
*
|
|
139
|
+
* Useful for modals/dialogs that should trap focus
|
|
140
|
+
*/
|
|
141
|
+
export declare function createFocusTrap(container: HTMLElement): {
|
|
142
|
+
activate: () => void;
|
|
143
|
+
deactivate: () => void;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Create the Slash Commands Extension
|
|
148
|
+
*/
|
|
149
|
+
export declare function createSlashCommandsExtension(commands?: SlashCommand[], imageUploadConfig?: ImageUploadConfig, locale?: EditorLocale_2): Extension<any, any>;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Create a toast ID
|
|
153
|
+
*/
|
|
154
|
+
export declare function createToastId(): string;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Default slash commands (without image upload config, uses base64)
|
|
158
|
+
* Note: This is deprecated, use createDefaultSlashCommands with locale instead
|
|
159
|
+
*/
|
|
160
|
+
export declare const defaultSlashCommands: SlashCommand[];
|
|
161
|
+
|
|
162
|
+
export declare const defaultTokens = "\n:root {\n /* Colors - Light theme */\n --pubwave-color-background: #ffffff;\n --pubwave-color-surface: #ffffff;\n --pubwave-color-text: #1a1a1a;\n --pubwave-color-text-muted: #6b7280;\n --pubwave-color-border: #e5e7eb;\n --pubwave-color-border-light: #f3f4f6;\n --pubwave-color-hover: rgba(0, 0, 0, 0.03);\n --pubwave-color-focus: rgba(0, 0, 0, 0.05);\n --pubwave-color-selection: #3b82f6;\n --pubwave-color-selection-bg: rgba(59, 130, 246, 0.1);\n --pubwave-color-primary: #3b82f6;\n --pubwave-color-primary-faded: rgba(59, 130, 246, 0.1);\n --pubwave-color-drop-indicator: #3b82f6;\n --pubwave-color-drop-target: rgba(59, 130, 246, 0.05);\n --pubwave-color-error: #ef4444;\n\n /* Spacing */\n --pubwave-spacing-xs: 0.25rem;\n --pubwave-spacing-sm: 0.5rem;\n --pubwave-spacing-md: 1rem;\n --pubwave-spacing-lg: 1.5rem;\n --pubwave-spacing-xl: 2rem;\n --pubwave-block-padding-x: 0;\n --pubwave-block-padding-y: 0.25rem;\n --pubwave-block-margin-y: 0.25rem;\n --pubwave-toolbar-gap: 0.25rem;\n\n /* Typography */\n --pubwave-font-family: inherit;\n --pubwave-font-size-base: 1rem;\n --pubwave-font-size-small: 0.875rem;\n --pubwave-line-height-base: 1.625;\n --pubwave-line-height-heading: 1.25;\n --pubwave-font-weight-normal: 400;\n --pubwave-font-weight-medium: 500;\n --pubwave-font-weight-bold: 700;\n --pubwave-font-weight-heading: 600;\n\n /* Borders */\n --pubwave-border-radius-sm: 0.25rem;\n --pubwave-border-radius: 0.375rem;\n --pubwave-border-radius-large: 0.5rem;\n\n /* Shadows */\n --pubwave-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --pubwave-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n --pubwave-shadow-toolbar: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n --pubwave-shadow-popup: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n\n /* Transitions */\n --pubwave-transition-fast: 0.1s ease;\n --pubwave-transition-normal: 0.15s ease;\n\n /* Z-index layers */\n --pubwave-z-drag-preview: 100;\n --pubwave-z-toolbar: 50;\n --pubwave-z-dropdown: 60;\n}\n\n/* Dark theme (if prefers-color-scheme is dark) */\n@media (prefers-color-scheme: dark) {\n :root {\n --pubwave-color-background: #1a1a1a;\n --pubwave-color-surface: #262626;\n --pubwave-color-text: #e5e7eb;\n --pubwave-color-text-muted: #9ca3af;\n --pubwave-color-border: #374151;\n --pubwave-color-border-light: #4b5563;\n --pubwave-color-hover: rgba(255, 255, 255, 0.05);\n --pubwave-color-focus: rgba(255, 255, 255, 0.08);\n --pubwave-color-selection: #60a5fa;\n --pubwave-color-selection-bg: rgba(96, 165, 250, 0.15);\n --pubwave-color-primary: #60a5fa;\n --pubwave-color-primary-faded: rgba(96, 165, 250, 0.15);\n --pubwave-color-drop-indicator: #60a5fa;\n --pubwave-color-drop-target: rgba(96, 165, 250, 0.08);\n --pubwave-color-error: #f87171;\n }\n}\n";
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Default toolbar actions
|
|
166
|
+
*/
|
|
167
|
+
export declare const defaultToolbarActions: ToolbarActionDescriptor[];
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Destroy an editor instance and clean up resources
|
|
171
|
+
*
|
|
172
|
+
* @param editor - The editor instance to destroy
|
|
173
|
+
*/
|
|
174
|
+
export declare function destroyEditor(editor: Editor_2 | null): void;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Plugin key for accessing DnD state
|
|
178
|
+
*/
|
|
179
|
+
export declare const dndPluginKey: PluginKey<any>;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* DnD state stored in plugin
|
|
183
|
+
*/
|
|
184
|
+
export declare interface DndState {
|
|
185
|
+
/** Block currently being dragged */
|
|
186
|
+
draggingBlockId: string | null;
|
|
187
|
+
/** Position of the block being dragged */
|
|
188
|
+
draggingBlockPos: number | null;
|
|
189
|
+
/** Target position for drop (null if no valid target) */
|
|
190
|
+
dropTargetPos: number | null;
|
|
191
|
+
/** Whether drop is before or after the target */
|
|
192
|
+
dropPosition: 'before' | 'after' | null;
|
|
193
|
+
/** Whether drag was cancelled */
|
|
194
|
+
cancelled: boolean;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* DragHandle - Block drag affordance
|
|
199
|
+
*/
|
|
200
|
+
export declare function DragHandle({ blockId, isHovered, isDragging, onDragStart, onDragEnd, className, }: DragHandleProps): default_2.ReactElement;
|
|
201
|
+
|
|
202
|
+
export declare interface DragHandleProps {
|
|
203
|
+
/** Block ID for drag identification */
|
|
204
|
+
blockId: string;
|
|
205
|
+
/** Whether the block is currently hovered */
|
|
206
|
+
isHovered: boolean;
|
|
207
|
+
/** Whether a drag is currently in progress */
|
|
208
|
+
isDragging?: boolean;
|
|
209
|
+
/** Callback when drag starts */
|
|
210
|
+
onDragStart?: (blockId: string, event: default_2.DragEvent) => void;
|
|
211
|
+
/** Callback when drag ends */
|
|
212
|
+
onDragEnd?: (blockId: string, event: default_2.DragEvent) => void;
|
|
213
|
+
/** Additional CSS class names */
|
|
214
|
+
className?: string;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* DropIndicator - Visual drop target indicator
|
|
219
|
+
*/
|
|
220
|
+
export declare function DropIndicator({ visible, position, className, }: DropIndicatorProps): default_2.ReactElement;
|
|
221
|
+
|
|
222
|
+
export declare interface DropIndicatorProps {
|
|
223
|
+
/** Whether the indicator is visible */
|
|
224
|
+
visible: boolean;
|
|
225
|
+
/** Position relative to target block */
|
|
226
|
+
position: 'before' | 'after';
|
|
227
|
+
/** Additional CSS class names */
|
|
228
|
+
className?: string;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Public API exposed by the editor
|
|
233
|
+
*/
|
|
234
|
+
export declare interface EditorAPI {
|
|
235
|
+
/**
|
|
236
|
+
* Get the current editor state
|
|
237
|
+
*/
|
|
238
|
+
getState: () => EditorState;
|
|
239
|
+
/**
|
|
240
|
+
* Get the content as JSON
|
|
241
|
+
*/
|
|
242
|
+
getJSON: () => JSONContent;
|
|
243
|
+
/**
|
|
244
|
+
* Get the content as HTML
|
|
245
|
+
*/
|
|
246
|
+
getHTML: () => string;
|
|
247
|
+
/**
|
|
248
|
+
* Get the content as plain text
|
|
249
|
+
*/
|
|
250
|
+
getText: () => string;
|
|
251
|
+
/**
|
|
252
|
+
* Set new content
|
|
253
|
+
*/
|
|
254
|
+
setContent: (content: JSONContent) => void;
|
|
255
|
+
/**
|
|
256
|
+
* Clear all content
|
|
257
|
+
*/
|
|
258
|
+
clearContent: () => void;
|
|
259
|
+
/**
|
|
260
|
+
* Set editable state
|
|
261
|
+
*/
|
|
262
|
+
setEditable: (editable: boolean) => void;
|
|
263
|
+
/**
|
|
264
|
+
* Focus the editor
|
|
265
|
+
*/
|
|
266
|
+
focus: (position?: 'start' | 'end') => void;
|
|
267
|
+
/**
|
|
268
|
+
* Blur the editor
|
|
269
|
+
*/
|
|
270
|
+
blur: () => void;
|
|
271
|
+
/**
|
|
272
|
+
* Toggle bold mark
|
|
273
|
+
*/
|
|
274
|
+
toggleBold: () => void;
|
|
275
|
+
/**
|
|
276
|
+
* Toggle italic mark
|
|
277
|
+
*/
|
|
278
|
+
toggleItalic: () => void;
|
|
279
|
+
/**
|
|
280
|
+
* Set or remove a link
|
|
281
|
+
*/
|
|
282
|
+
setLink: (href: string | null) => void;
|
|
283
|
+
/**
|
|
284
|
+
* Destroy the editor instance
|
|
285
|
+
*/
|
|
286
|
+
destroy: () => void;
|
|
287
|
+
/**
|
|
288
|
+
* Access the underlying Tiptap editor instance
|
|
289
|
+
* Use with caution - this is an escape hatch
|
|
290
|
+
*/
|
|
291
|
+
readonly tiptapEditor: Editor | null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Configuration options for creating an editor instance
|
|
296
|
+
*/
|
|
297
|
+
export declare interface EditorConfig {
|
|
298
|
+
/**
|
|
299
|
+
* Initial content in Tiptap JSON format
|
|
300
|
+
*/
|
|
301
|
+
content?: JSONContent;
|
|
302
|
+
/**
|
|
303
|
+
* Whether the editor is in read-only mode
|
|
304
|
+
* When true, all editing affordances are hidden
|
|
305
|
+
* @default false
|
|
306
|
+
*/
|
|
307
|
+
editable?: boolean;
|
|
308
|
+
/**
|
|
309
|
+
* Placeholder text shown when the editor is empty
|
|
310
|
+
*/
|
|
311
|
+
placeholder?: string;
|
|
312
|
+
/**
|
|
313
|
+
* Theme configuration for styling
|
|
314
|
+
*/
|
|
315
|
+
theme?: EditorTheme;
|
|
316
|
+
/**
|
|
317
|
+
* Enable autofocus on mount
|
|
318
|
+
* - true: Focus at the end
|
|
319
|
+
* - 'start': Focus at the beginning
|
|
320
|
+
* - 'end': Focus at the end
|
|
321
|
+
* - false: No autofocus
|
|
322
|
+
* @default false
|
|
323
|
+
*/
|
|
324
|
+
autofocus?: boolean | 'start' | 'end';
|
|
325
|
+
/**
|
|
326
|
+
* Image upload configuration
|
|
327
|
+
* If not provided, images will be converted to base64 by default
|
|
328
|
+
*/
|
|
329
|
+
imageUpload?: ImageUploadConfig;
|
|
330
|
+
/**
|
|
331
|
+
* Callback fired when the editor content changes
|
|
332
|
+
*/
|
|
333
|
+
onUpdate?: (props: {
|
|
334
|
+
editor: Editor;
|
|
335
|
+
}) => void;
|
|
336
|
+
/**
|
|
337
|
+
* Callback fired when the selection changes
|
|
338
|
+
*/
|
|
339
|
+
onSelectionUpdate?: (props: {
|
|
340
|
+
editor: Editor;
|
|
341
|
+
}) => void;
|
|
342
|
+
/**
|
|
343
|
+
* Callback fired when the editor gains focus
|
|
344
|
+
*/
|
|
345
|
+
onFocus?: (props: {
|
|
346
|
+
editor: Editor;
|
|
347
|
+
}) => void;
|
|
348
|
+
/**
|
|
349
|
+
* Callback fired when the editor loses focus
|
|
350
|
+
*/
|
|
351
|
+
onBlur?: (props: {
|
|
352
|
+
editor: Editor;
|
|
353
|
+
}) => void;
|
|
354
|
+
/**
|
|
355
|
+
* Callback fired when the editor is ready
|
|
356
|
+
*/
|
|
357
|
+
onCreate?: (props: {
|
|
358
|
+
editor: Editor;
|
|
359
|
+
}) => void;
|
|
360
|
+
/**
|
|
361
|
+
* Callback fired before the editor is destroyed
|
|
362
|
+
*/
|
|
363
|
+
onDestroy?: () => void;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Theme configuration using CSS custom property tokens
|
|
368
|
+
* All colors must be CSS custom properties, never hard-coded values
|
|
369
|
+
*/
|
|
370
|
+
/**
|
|
371
|
+
* Locale for internationalization
|
|
372
|
+
* @default 'en'
|
|
373
|
+
*/
|
|
374
|
+
export declare type EditorLocale = 'en' | 'zh' | 'zh-CN' | 'ja' | 'ko' | 'fr' | 'de' | 'es' | 'pt';
|
|
375
|
+
|
|
376
|
+
declare interface EditorLocale_2 {
|
|
377
|
+
slashMenu: {
|
|
378
|
+
groups: {
|
|
379
|
+
basic: string;
|
|
380
|
+
list: string;
|
|
381
|
+
media: string;
|
|
382
|
+
advanced: string;
|
|
383
|
+
};
|
|
384
|
+
commands: {
|
|
385
|
+
paragraph: {
|
|
386
|
+
title: string;
|
|
387
|
+
description: string;
|
|
388
|
+
};
|
|
389
|
+
heading1: {
|
|
390
|
+
title: string;
|
|
391
|
+
description: string;
|
|
392
|
+
};
|
|
393
|
+
heading2: {
|
|
394
|
+
title: string;
|
|
395
|
+
description: string;
|
|
396
|
+
};
|
|
397
|
+
heading3: {
|
|
398
|
+
title: string;
|
|
399
|
+
description: string;
|
|
400
|
+
};
|
|
401
|
+
bulletList: {
|
|
402
|
+
title: string;
|
|
403
|
+
description: string;
|
|
404
|
+
};
|
|
405
|
+
orderedList: {
|
|
406
|
+
title: string;
|
|
407
|
+
description: string;
|
|
408
|
+
};
|
|
409
|
+
taskList: {
|
|
410
|
+
title: string;
|
|
411
|
+
description: string;
|
|
412
|
+
};
|
|
413
|
+
image: {
|
|
414
|
+
title: string;
|
|
415
|
+
description: string;
|
|
416
|
+
};
|
|
417
|
+
blockquote: {
|
|
418
|
+
title: string;
|
|
419
|
+
description: string;
|
|
420
|
+
};
|
|
421
|
+
codeBlock: {
|
|
422
|
+
title: string;
|
|
423
|
+
description: string;
|
|
424
|
+
};
|
|
425
|
+
horizontalRule: {
|
|
426
|
+
title: string;
|
|
427
|
+
description: string;
|
|
428
|
+
};
|
|
429
|
+
};
|
|
430
|
+
};
|
|
431
|
+
toolbar: {
|
|
432
|
+
bold: string;
|
|
433
|
+
italic: string;
|
|
434
|
+
underline: string;
|
|
435
|
+
strike: string;
|
|
436
|
+
code: string;
|
|
437
|
+
link: string;
|
|
438
|
+
turnInto: string;
|
|
439
|
+
colorPicker: string;
|
|
440
|
+
textColor: string;
|
|
441
|
+
backgroundColor: string;
|
|
442
|
+
recentlyUsed: string;
|
|
443
|
+
openLink: string;
|
|
444
|
+
removeLink: string;
|
|
445
|
+
blockTypes: {
|
|
446
|
+
text: string;
|
|
447
|
+
heading1: string;
|
|
448
|
+
heading2: string;
|
|
449
|
+
heading3: string;
|
|
450
|
+
bulletedList: string;
|
|
451
|
+
numberedList: string;
|
|
452
|
+
};
|
|
453
|
+
};
|
|
454
|
+
aria: {
|
|
455
|
+
editor: string;
|
|
456
|
+
editorContent: string;
|
|
457
|
+
toolbar: string;
|
|
458
|
+
boldButton: string;
|
|
459
|
+
italicButton: string;
|
|
460
|
+
underlineButton: string;
|
|
461
|
+
strikeButton: string;
|
|
462
|
+
codeButton: string;
|
|
463
|
+
linkButton: string;
|
|
464
|
+
turnIntoButton: string;
|
|
465
|
+
colorPickerButton: string;
|
|
466
|
+
headingButton: string;
|
|
467
|
+
paragraphButton: string;
|
|
468
|
+
dragHandle: string;
|
|
469
|
+
dropIndicator: string;
|
|
470
|
+
blockMenu: string;
|
|
471
|
+
addBlock: string;
|
|
472
|
+
deleteBlock: string;
|
|
473
|
+
linkDialog: string;
|
|
474
|
+
linkUrlInput: string;
|
|
475
|
+
linkSaveButton: string;
|
|
476
|
+
linkRemoveButton: string;
|
|
477
|
+
linkCancelButton: string;
|
|
478
|
+
addBlockBelow: string;
|
|
479
|
+
dragToMove: string;
|
|
480
|
+
openLinkInNewTab: string;
|
|
481
|
+
};
|
|
482
|
+
placeholder: string;
|
|
483
|
+
linkPlaceholder: string;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Complete editor state exposed to consumers
|
|
488
|
+
*/
|
|
489
|
+
export declare interface EditorState {
|
|
490
|
+
/**
|
|
491
|
+
* Current selection state
|
|
492
|
+
*/
|
|
493
|
+
selection: SelectionState;
|
|
494
|
+
/**
|
|
495
|
+
* Current mark state for the selection
|
|
496
|
+
*/
|
|
497
|
+
marks: MarkState;
|
|
498
|
+
/**
|
|
499
|
+
* Whether the editor is currently focused
|
|
500
|
+
*/
|
|
501
|
+
isFocused: boolean;
|
|
502
|
+
/**
|
|
503
|
+
* Whether the editor is in read-only mode
|
|
504
|
+
*/
|
|
505
|
+
isEditable: boolean;
|
|
506
|
+
/**
|
|
507
|
+
* Whether the editor content is empty
|
|
508
|
+
*/
|
|
509
|
+
isEmpty: boolean;
|
|
510
|
+
/**
|
|
511
|
+
* Current character count
|
|
512
|
+
*/
|
|
513
|
+
characterCount: number;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export declare interface EditorTheme {
|
|
517
|
+
/**
|
|
518
|
+
* CSS class name prefix for styling hooks
|
|
519
|
+
* @default 'pubwave-editor'
|
|
520
|
+
*/
|
|
521
|
+
classNamePrefix?: string;
|
|
522
|
+
/**
|
|
523
|
+
* Locale for internationalization
|
|
524
|
+
* @default 'en'
|
|
525
|
+
*/
|
|
526
|
+
locale?: EditorLocale;
|
|
527
|
+
/**
|
|
528
|
+
* Additional CSS classes to apply to the editor container
|
|
529
|
+
*/
|
|
530
|
+
containerClassName?: string;
|
|
531
|
+
/**
|
|
532
|
+
* Additional CSS classes to apply to the content area
|
|
533
|
+
*/
|
|
534
|
+
contentClassName?: string;
|
|
535
|
+
/**
|
|
536
|
+
* Color theme configuration
|
|
537
|
+
* Colors will be applied as CSS custom properties to the editor container
|
|
538
|
+
* If not provided, default theme colors will be used
|
|
539
|
+
*/
|
|
540
|
+
colors?: {
|
|
541
|
+
/**
|
|
542
|
+
* Editor background color
|
|
543
|
+
*/
|
|
544
|
+
background?: string;
|
|
545
|
+
/**
|
|
546
|
+
* Primary text color
|
|
547
|
+
*/
|
|
548
|
+
text?: string;
|
|
549
|
+
/**
|
|
550
|
+
* Muted/secondary text color (e.g., for placeholders)
|
|
551
|
+
*/
|
|
552
|
+
textMuted?: string;
|
|
553
|
+
/**
|
|
554
|
+
* Border color
|
|
555
|
+
*/
|
|
556
|
+
border?: string;
|
|
557
|
+
/**
|
|
558
|
+
* Primary color (for links, buttons, etc.)
|
|
559
|
+
*/
|
|
560
|
+
primary?: string;
|
|
561
|
+
/**
|
|
562
|
+
* Link color (if not provided, will use primary color)
|
|
563
|
+
* Useful for dark themes where a brighter link color is needed for visibility
|
|
564
|
+
*/
|
|
565
|
+
linkColor?: string;
|
|
566
|
+
};
|
|
567
|
+
/**
|
|
568
|
+
* Background image configuration
|
|
569
|
+
* Can be a URL string or CSS background-image value
|
|
570
|
+
* If provided, will be applied as the editor container background image
|
|
571
|
+
* Background image will be layered on top of background color
|
|
572
|
+
*/
|
|
573
|
+
backgroundImage?: string;
|
|
574
|
+
/**
|
|
575
|
+
* Background image options
|
|
576
|
+
* Controls how the background image is displayed
|
|
577
|
+
*/
|
|
578
|
+
backgroundImageOptions?: {
|
|
579
|
+
/**
|
|
580
|
+
* Background image repeat behavior
|
|
581
|
+
* @default 'no-repeat'
|
|
582
|
+
*/
|
|
583
|
+
repeat?: 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat';
|
|
584
|
+
/**
|
|
585
|
+
* Background image position
|
|
586
|
+
* @default 'center'
|
|
587
|
+
*/
|
|
588
|
+
position?: string;
|
|
589
|
+
/**
|
|
590
|
+
* Background image size
|
|
591
|
+
* @default 'cover'
|
|
592
|
+
*/
|
|
593
|
+
size?: 'cover' | 'contain' | string;
|
|
594
|
+
/**
|
|
595
|
+
* Background image attachment
|
|
596
|
+
* @default 'scroll'
|
|
597
|
+
*/
|
|
598
|
+
attachment?: 'scroll' | 'fixed' | 'local';
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Configuration for creating the extension set
|
|
604
|
+
*/
|
|
605
|
+
declare interface ExtensionConfig extends BlockExtensionsConfig, MarkExtensionsConfig {
|
|
606
|
+
/**
|
|
607
|
+
* Placeholder text for empty editor
|
|
608
|
+
*/
|
|
609
|
+
placeholder?: string;
|
|
610
|
+
/**
|
|
611
|
+
* Undo/redo history depth
|
|
612
|
+
* @default 100
|
|
613
|
+
*/
|
|
614
|
+
historyDepth?: number;
|
|
615
|
+
/**
|
|
616
|
+
* Enable slash commands menu
|
|
617
|
+
* @default true
|
|
618
|
+
*/
|
|
619
|
+
enableSlashCommands?: boolean;
|
|
620
|
+
/**
|
|
621
|
+
* Custom slash commands (merged with defaults)
|
|
622
|
+
*/
|
|
623
|
+
slashCommands?: SlashCommand[];
|
|
624
|
+
/**
|
|
625
|
+
* Image upload configuration
|
|
626
|
+
*/
|
|
627
|
+
imageUpload?: ImageUploadConfig;
|
|
628
|
+
/**
|
|
629
|
+
* Locale for internationalization
|
|
630
|
+
*/
|
|
631
|
+
locale?: EditorLocale;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Find top-level block node at a given document position
|
|
636
|
+
* Returns the direct child of doc that contains the position
|
|
637
|
+
*/
|
|
638
|
+
export declare function findBlockAtPos(doc: Node_2, pos: number): {
|
|
639
|
+
node: Node_2;
|
|
640
|
+
pos: number;
|
|
641
|
+
} | null;
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Focus the editor after a click event
|
|
645
|
+
*
|
|
646
|
+
* Handles edge cases where clicking on toolbar/UI elements
|
|
647
|
+
* should restore focus to the editor
|
|
648
|
+
*/
|
|
649
|
+
export declare function focusAfterClick(editor: Editor_2, event: React.MouseEvent): void;
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Focus the editor at a specific position
|
|
653
|
+
*/
|
|
654
|
+
export declare function focusAt(editor: Editor_2, position: FocusPosition): void;
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Focus the editor
|
|
658
|
+
*/
|
|
659
|
+
export declare function focusEditor(editor: Editor_2, position?: 'start' | 'end' | 'all' | number): boolean;
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Focus position options
|
|
663
|
+
*/
|
|
664
|
+
export declare type FocusPosition = 'start' | 'end' | 'preserve' | number;
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* Get the current link href if selection is inside a link
|
|
668
|
+
*/
|
|
669
|
+
export declare function getActiveLinkHref(editor: Editor_2): string | null;
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Get current marks at the selection
|
|
673
|
+
*/
|
|
674
|
+
export declare function getActiveMarks(editor: Editor_2): string[];
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* Get the current DnD state from an editor
|
|
678
|
+
*/
|
|
679
|
+
export declare function getDndState(editor: Editor_2): DndState;
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* Get selection coordinates for positioning UI elements (like toolbar)
|
|
683
|
+
* Returns the bounding box of the current selection
|
|
684
|
+
*/
|
|
685
|
+
export declare function getSelectionBounds(editor: Editor_2): {
|
|
686
|
+
top: number;
|
|
687
|
+
left: number;
|
|
688
|
+
right: number;
|
|
689
|
+
bottom: number;
|
|
690
|
+
width: number;
|
|
691
|
+
height: number;
|
|
692
|
+
} | null;
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Get the current selection state from the editor
|
|
696
|
+
*
|
|
697
|
+
* This is the primary function for determining toolbar visibility.
|
|
698
|
+
* Per constitution: toolbar MUST NOT be visible when selection is empty.
|
|
699
|
+
*/
|
|
700
|
+
export declare function getSelectionState(editor: Editor_2): SelectionState_2;
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* Handle focus for selection clear
|
|
704
|
+
*
|
|
705
|
+
* When selection is cleared (e.g., clicking in empty space),
|
|
706
|
+
* ensure cursor is placed at a sensible position
|
|
707
|
+
*/
|
|
708
|
+
export declare function handleSelectionClear(editor: Editor_2): void;
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Image upload configuration
|
|
712
|
+
*/
|
|
713
|
+
declare interface ImageUploadConfig {
|
|
714
|
+
/**
|
|
715
|
+
* Custom image upload handler
|
|
716
|
+
* If provided, images will be uploaded using this function
|
|
717
|
+
* If not provided, images will be converted to base64 (default)
|
|
718
|
+
*/
|
|
719
|
+
handler?: ImageUploadHandler;
|
|
720
|
+
/**
|
|
721
|
+
* Maximum file size in bytes
|
|
722
|
+
* @default 10MB (10 * 1024 * 1024)
|
|
723
|
+
*/
|
|
724
|
+
maxSize?: number;
|
|
725
|
+
/**
|
|
726
|
+
* Accepted file types
|
|
727
|
+
* @default ['image/*']
|
|
728
|
+
*/
|
|
729
|
+
accept?: string[];
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Image upload handler function
|
|
734
|
+
* Should return a Promise that resolves to the image URL
|
|
735
|
+
* If the function throws or rejects, the editor will fall back to base64
|
|
736
|
+
*/
|
|
737
|
+
declare type ImageUploadHandler = (file: File) => Promise<string>;
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Check if the editor is editable (inverse of read-only)
|
|
741
|
+
*/
|
|
742
|
+
export declare function isEditable(editor: Editor_2 | null): boolean;
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Check if an editor instance is in a valid state
|
|
746
|
+
*
|
|
747
|
+
* @param editor - The editor instance to check
|
|
748
|
+
* @returns true if the editor exists and is not destroyed
|
|
749
|
+
*/
|
|
750
|
+
export declare function isEditorValid(editor: Editor_2 | null): editor is Editor_2;
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Check if a mark is currently active
|
|
754
|
+
*/
|
|
755
|
+
export declare function isMarkActive(editor: Editor_2, markType: string): boolean;
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* Check if a node type is currently active
|
|
759
|
+
*/
|
|
760
|
+
export declare function isNodeActive(editor: Editor_2, nodeType: string, attrs?: Record<string, unknown>): boolean;
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* Check if the editor is in read-only mode
|
|
764
|
+
*/
|
|
765
|
+
export declare function isReadOnly(editor: Editor_2 | null): boolean;
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Check if the selection is empty (cursor only)
|
|
769
|
+
*
|
|
770
|
+
* This is the key check for toolbar visibility.
|
|
771
|
+
* Returns true when toolbar should be HIDDEN.
|
|
772
|
+
*/
|
|
773
|
+
export declare function isSelectionEmpty(editor: Editor_2): boolean;
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Check if code is running in a server-side environment
|
|
777
|
+
*/
|
|
778
|
+
export declare const isSSR: boolean;
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Keep focus within the editor
|
|
782
|
+
*
|
|
783
|
+
* Prevents focus from escaping during common operations
|
|
784
|
+
*/
|
|
785
|
+
export declare function maintainFocus(editor: Editor_2): () => void;
|
|
786
|
+
|
|
787
|
+
declare interface MarkExtensionsConfig {
|
|
788
|
+
/**
|
|
789
|
+
* Whether links should open in a new tab
|
|
790
|
+
* @default true
|
|
791
|
+
*/
|
|
792
|
+
linkOpenInNewTab?: boolean;
|
|
793
|
+
/**
|
|
794
|
+
* Whether to open links on click (within editor)
|
|
795
|
+
* @default true - links open on click
|
|
796
|
+
*/
|
|
797
|
+
linkOpenOnClick?: boolean;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* Mark state for the current selection
|
|
802
|
+
*/
|
|
803
|
+
export declare interface MarkState {
|
|
804
|
+
/**
|
|
805
|
+
* Whether bold is active at the current selection
|
|
806
|
+
*/
|
|
807
|
+
isBold: boolean;
|
|
808
|
+
/**
|
|
809
|
+
* Whether italic is active at the current selection
|
|
810
|
+
*/
|
|
811
|
+
isItalic: boolean;
|
|
812
|
+
/**
|
|
813
|
+
* Whether a link is active at the current selection
|
|
814
|
+
*/
|
|
815
|
+
isLink: boolean;
|
|
816
|
+
/**
|
|
817
|
+
* The href of the active link, if any
|
|
818
|
+
*/
|
|
819
|
+
linkHref?: string;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Supported mark types for inline formatting
|
|
824
|
+
*/
|
|
825
|
+
export declare type MarkType = 'bold' | 'italic' | 'underline' | 'strike' | 'code' | 'link';
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* Move a block from one position to another
|
|
829
|
+
*/
|
|
830
|
+
export declare function moveBlock(editor: Editor_2, fromPos: number, toPos: number, position: 'before' | 'after'): boolean;
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* PubwaveEditor Component
|
|
834
|
+
*
|
|
835
|
+
* A Notion-level block editor with:
|
|
836
|
+
* - Premium writing experience
|
|
837
|
+
* - Selection-only formatting toolbar
|
|
838
|
+
* - Block drag & drop
|
|
839
|
+
* - Full theme customization via CSS tokens
|
|
840
|
+
*/
|
|
841
|
+
export declare const PubwaveEditor: ForwardRefExoticComponent<PubwaveEditorProps & RefAttributes<EditorAPI | null>>;
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Props for the PubwaveEditor component
|
|
845
|
+
*/
|
|
846
|
+
declare interface PubwaveEditorProps {
|
|
847
|
+
/**
|
|
848
|
+
* Initial content in Tiptap JSON format
|
|
849
|
+
*/
|
|
850
|
+
content?: JSONContent;
|
|
851
|
+
/**
|
|
852
|
+
* Whether the editor is in read-only mode
|
|
853
|
+
* @default false
|
|
854
|
+
*/
|
|
855
|
+
editable?: boolean;
|
|
856
|
+
/**
|
|
857
|
+
* Placeholder text shown when the editor is empty
|
|
858
|
+
*/
|
|
859
|
+
placeholder?: string;
|
|
860
|
+
/**
|
|
861
|
+
* Theme configuration
|
|
862
|
+
*/
|
|
863
|
+
theme?: EditorTheme;
|
|
864
|
+
/**
|
|
865
|
+
* Enable autofocus on mount
|
|
866
|
+
* @default false
|
|
867
|
+
*/
|
|
868
|
+
autofocus?: boolean | 'start' | 'end';
|
|
869
|
+
/**
|
|
870
|
+
* Callback when content changes
|
|
871
|
+
*/
|
|
872
|
+
onChange?: (content: JSONContent) => void;
|
|
873
|
+
/**
|
|
874
|
+
* Callback when selection changes
|
|
875
|
+
*/
|
|
876
|
+
onSelectionChange?: () => void;
|
|
877
|
+
/**
|
|
878
|
+
* Callback when editor gains focus
|
|
879
|
+
*/
|
|
880
|
+
onFocus?: () => void;
|
|
881
|
+
/**
|
|
882
|
+
* Callback when editor loses focus
|
|
883
|
+
*/
|
|
884
|
+
onBlur?: () => void;
|
|
885
|
+
/**
|
|
886
|
+
* Callback when editor is ready
|
|
887
|
+
*/
|
|
888
|
+
onReady?: (api: EditorAPI) => void;
|
|
889
|
+
/**
|
|
890
|
+
* Image upload configuration
|
|
891
|
+
* If not provided, images will be converted to base64 by default
|
|
892
|
+
*/
|
|
893
|
+
imageUpload?: ImageUploadConfig;
|
|
894
|
+
/**
|
|
895
|
+
* Additional CSS class for the container
|
|
896
|
+
*/
|
|
897
|
+
className?: string;
|
|
898
|
+
/**
|
|
899
|
+
* Editor container width
|
|
900
|
+
* Can be a CSS value like '100%', '1200px', '90vw', etc.
|
|
901
|
+
* @default '100%'
|
|
902
|
+
*/
|
|
903
|
+
width?: string;
|
|
904
|
+
/**
|
|
905
|
+
* Test ID for testing
|
|
906
|
+
*/
|
|
907
|
+
'data-testid'?: string;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/**
|
|
911
|
+
* Redo the last undone action
|
|
912
|
+
*/
|
|
913
|
+
export declare function redo(editor: Editor_2): boolean;
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Restore focus after a DOM operation
|
|
917
|
+
*
|
|
918
|
+
* Use this after operations that might cause focus loss:
|
|
919
|
+
* - Modal/dialog interactions
|
|
920
|
+
* - Toolbar button clicks
|
|
921
|
+
* - Context menu actions
|
|
922
|
+
*/
|
|
923
|
+
export declare function restoreFocus(editor: Editor_2): void;
|
|
924
|
+
|
|
925
|
+
export declare function restoreSelection(editor: Editor_2, savedSelection: SavedSelection | null): void;
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* Save and restore selection state
|
|
929
|
+
*
|
|
930
|
+
* Useful for operations that need to temporarily change selection
|
|
931
|
+
* then restore it (e.g., inserting content at cursor)
|
|
932
|
+
*/
|
|
933
|
+
export declare interface SavedSelection {
|
|
934
|
+
from: number;
|
|
935
|
+
to: number;
|
|
936
|
+
empty: boolean;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
export declare function saveSelection(editor: Editor_2): SavedSelection | null;
|
|
940
|
+
|
|
941
|
+
/**
|
|
942
|
+
* Select all content
|
|
943
|
+
*/
|
|
944
|
+
export declare function selectAll(editor: Editor_2): boolean;
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Current selection state derived from the editor
|
|
948
|
+
*/
|
|
949
|
+
export declare interface SelectionState {
|
|
950
|
+
/**
|
|
951
|
+
* Whether there is a non-empty text selection
|
|
952
|
+
*/
|
|
953
|
+
hasSelection: boolean;
|
|
954
|
+
/**
|
|
955
|
+
* Whether the selection spans multiple blocks
|
|
956
|
+
*/
|
|
957
|
+
isMultiBlock: boolean;
|
|
958
|
+
/**
|
|
959
|
+
* Start position of the selection
|
|
960
|
+
*/
|
|
961
|
+
from: number;
|
|
962
|
+
/**
|
|
963
|
+
* End position of the selection
|
|
964
|
+
*/
|
|
965
|
+
to: number;
|
|
966
|
+
/**
|
|
967
|
+
* Whether the selection is empty (cursor only)
|
|
968
|
+
*/
|
|
969
|
+
isEmpty: boolean;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* Selection state information
|
|
974
|
+
*/
|
|
975
|
+
declare interface SelectionState_2 {
|
|
976
|
+
/**
|
|
977
|
+
* Whether there is any selection at all
|
|
978
|
+
*/
|
|
979
|
+
hasSelection: boolean;
|
|
980
|
+
/**
|
|
981
|
+
* Whether the selection is empty (cursor only, no text selected)
|
|
982
|
+
*/
|
|
983
|
+
isEmpty: boolean;
|
|
984
|
+
/**
|
|
985
|
+
* Whether the selection spans actual text content
|
|
986
|
+
*/
|
|
987
|
+
hasTextContent: boolean;
|
|
988
|
+
/**
|
|
989
|
+
* Whether this is a node selection (e.g., selected image or block)
|
|
990
|
+
*/
|
|
991
|
+
isNodeSelection: boolean;
|
|
992
|
+
/**
|
|
993
|
+
* The selected text, if any
|
|
994
|
+
*/
|
|
995
|
+
selectedText: string;
|
|
996
|
+
/**
|
|
997
|
+
* Start position of the selection
|
|
998
|
+
*/
|
|
999
|
+
from: number;
|
|
1000
|
+
/**
|
|
1001
|
+
* End position of the selection
|
|
1002
|
+
*/
|
|
1003
|
+
to: number;
|
|
1004
|
+
/**
|
|
1005
|
+
* Whether bold mark is active in selection
|
|
1006
|
+
*/
|
|
1007
|
+
isBold: boolean;
|
|
1008
|
+
/**
|
|
1009
|
+
* Whether italic mark is active in selection
|
|
1010
|
+
*/
|
|
1011
|
+
isItalic: boolean;
|
|
1012
|
+
/**
|
|
1013
|
+
* Whether underline mark is active in selection
|
|
1014
|
+
*/
|
|
1015
|
+
isUnderline: boolean;
|
|
1016
|
+
/**
|
|
1017
|
+
* Whether strike mark is active in selection
|
|
1018
|
+
*/
|
|
1019
|
+
isStrike: boolean;
|
|
1020
|
+
/**
|
|
1021
|
+
* Whether code mark is active in selection
|
|
1022
|
+
*/
|
|
1023
|
+
isCode: boolean;
|
|
1024
|
+
/**
|
|
1025
|
+
* Whether the selection has a link
|
|
1026
|
+
*/
|
|
1027
|
+
hasLink: boolean;
|
|
1028
|
+
/**
|
|
1029
|
+
* Active link href if any
|
|
1030
|
+
*/
|
|
1031
|
+
linkHref: string | null;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* Set the current block to a heading
|
|
1036
|
+
*/
|
|
1037
|
+
export declare function setHeading(editor: Editor_2, level: 1 | 2 | 3 | 4 | 5 | 6): boolean;
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* Set a link on the current selection
|
|
1041
|
+
*/
|
|
1042
|
+
export declare function setLink(editor: Editor_2, href: string): boolean;
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* Set the current block to a paragraph
|
|
1046
|
+
*/
|
|
1047
|
+
export declare function setParagraph(editor: Editor_2): boolean;
|
|
1048
|
+
|
|
1049
|
+
/**
|
|
1050
|
+
* Guard function for any interactive element
|
|
1051
|
+
* Returns true if interactive elements should be enabled
|
|
1052
|
+
*/
|
|
1053
|
+
export declare function shouldAllowInteraction(editor: Editor_2 | null): boolean;
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Guard function for toolbar visibility
|
|
1057
|
+
* Returns true if toolbar should potentially be visible
|
|
1058
|
+
* (Still depends on selection state)
|
|
1059
|
+
*/
|
|
1060
|
+
export declare function shouldAllowToolbar(editor: Editor_2 | null): boolean;
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* Guard function for UI components
|
|
1064
|
+
* Returns true if the component should be rendered (editable mode)
|
|
1065
|
+
*/
|
|
1066
|
+
export declare function shouldRenderEditUI(editor: Editor_2 | null): boolean;
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* Guard function for drag handles
|
|
1070
|
+
* Returns true if drag handles should be visible
|
|
1071
|
+
*/
|
|
1072
|
+
export declare function shouldShowDragHandle(editor: Editor_2 | null): boolean;
|
|
1073
|
+
|
|
1074
|
+
/**
|
|
1075
|
+
* Check if selection should trigger toolbar visibility
|
|
1076
|
+
*
|
|
1077
|
+
* Per constitution: toolbar appears ONLY on non-empty text selection.
|
|
1078
|
+
* - Cursor only: NO toolbar
|
|
1079
|
+
* - Text selected: YES toolbar
|
|
1080
|
+
* - Node selected (image, etc.): Context-dependent
|
|
1081
|
+
*/
|
|
1082
|
+
export declare function shouldShowToolbar(editor: Editor_2): boolean;
|
|
1083
|
+
|
|
1084
|
+
/**
|
|
1085
|
+
* Command item definition
|
|
1086
|
+
*/
|
|
1087
|
+
export declare interface SlashCommand {
|
|
1088
|
+
id: string;
|
|
1089
|
+
title: string;
|
|
1090
|
+
description: string;
|
|
1091
|
+
icon: default_2.ReactNode;
|
|
1092
|
+
aliases?: string[];
|
|
1093
|
+
group: 'basic' | 'list' | 'media' | 'advanced';
|
|
1094
|
+
action: (editor: Editor_2) => void;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/**
|
|
1098
|
+
* Slash Menu List Component
|
|
1099
|
+
*/
|
|
1100
|
+
export declare const SlashMenuList: default_2.ForwardRefExoticComponent<SlashMenuListProps & default_2.RefAttributes<{
|
|
1101
|
+
onKeyDown: (props: SuggestionKeyDownProps) => boolean;
|
|
1102
|
+
}>>;
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Slash Menu Component Props
|
|
1106
|
+
*/
|
|
1107
|
+
declare interface SlashMenuListProps {
|
|
1108
|
+
items: SlashCommand[];
|
|
1109
|
+
command: (item: SlashCommand) => void;
|
|
1110
|
+
editor: Editor_2;
|
|
1111
|
+
query?: string;
|
|
1112
|
+
groupLabels?: Record<string, string>;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/**
|
|
1116
|
+
* Start a drag operation
|
|
1117
|
+
*/
|
|
1118
|
+
export declare function startDrag(editor: Editor_2, blockId: string, pos: number): void;
|
|
1119
|
+
|
|
1120
|
+
/**
|
|
1121
|
+
* Supported block types
|
|
1122
|
+
*/
|
|
1123
|
+
export declare const SUPPORTED_BLOCKS: readonly BlockType[];
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* Supported mark types
|
|
1127
|
+
*/
|
|
1128
|
+
export declare const SUPPORTED_MARKS: readonly MarkType[];
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* Toast - Transient notification component
|
|
1132
|
+
*/
|
|
1133
|
+
export declare function Toast({ message, type, duration, onDismiss, className, }: ToastProps): default_2.ReactElement;
|
|
1134
|
+
|
|
1135
|
+
export declare function ToastContainer({ toasts, onDismiss, }: ToastContainerProps): default_2.ReactElement;
|
|
1136
|
+
|
|
1137
|
+
export declare interface ToastContainerProps {
|
|
1138
|
+
toasts: ToastItem[];
|
|
1139
|
+
onDismiss: (id: string) => void;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* Toast container for managing multiple toasts
|
|
1144
|
+
*/
|
|
1145
|
+
export declare interface ToastItem {
|
|
1146
|
+
id: string;
|
|
1147
|
+
message: string;
|
|
1148
|
+
type?: 'info' | 'success' | 'error' | 'warning';
|
|
1149
|
+
duration?: number;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
export declare interface ToastProps {
|
|
1153
|
+
/** Toast message content */
|
|
1154
|
+
message: string;
|
|
1155
|
+
/** Toast type for styling */
|
|
1156
|
+
type?: 'info' | 'success' | 'error' | 'warning';
|
|
1157
|
+
/** Auto-dismiss duration in ms (0 = no auto-dismiss) */
|
|
1158
|
+
duration?: number;
|
|
1159
|
+
/** Callback when toast is dismissed */
|
|
1160
|
+
onDismiss?: () => void;
|
|
1161
|
+
/** Additional CSS class names */
|
|
1162
|
+
className?: string;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/**
|
|
1166
|
+
* Toggle bold formatting on the current selection
|
|
1167
|
+
*/
|
|
1168
|
+
export declare function toggleBold(editor: Editor_2): boolean;
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Toggle heading for the current block
|
|
1172
|
+
*/
|
|
1173
|
+
export declare function toggleHeading(editor: Editor_2, level: 1 | 2 | 3 | 4 | 5 | 6): boolean;
|
|
1174
|
+
|
|
1175
|
+
/**
|
|
1176
|
+
* Toggle italic formatting on the current selection
|
|
1177
|
+
*/
|
|
1178
|
+
export declare function toggleItalic(editor: Editor_2): boolean;
|
|
1179
|
+
|
|
1180
|
+
/**
|
|
1181
|
+
* CSS Token definitions
|
|
1182
|
+
* These map to CSS custom properties that host applications can override.
|
|
1183
|
+
*/
|
|
1184
|
+
export declare const tokens: {
|
|
1185
|
+
readonly colors: {
|
|
1186
|
+
readonly background: "var(--pubwave-color-background)";
|
|
1187
|
+
readonly surface: "var(--pubwave-color-surface)";
|
|
1188
|
+
readonly text: "var(--pubwave-color-text)";
|
|
1189
|
+
readonly textMuted: "var(--pubwave-color-text-muted)";
|
|
1190
|
+
readonly border: "var(--pubwave-color-border)";
|
|
1191
|
+
readonly borderLight: "var(--pubwave-color-border-light)";
|
|
1192
|
+
readonly hover: "var(--pubwave-color-hover)";
|
|
1193
|
+
readonly focus: "var(--pubwave-color-focus)";
|
|
1194
|
+
readonly selection: "var(--pubwave-color-selection)";
|
|
1195
|
+
readonly selectionBg: "var(--pubwave-color-selection-bg)";
|
|
1196
|
+
readonly primary: "var(--pubwave-color-primary)";
|
|
1197
|
+
readonly primaryFaded: "var(--pubwave-color-primary-faded)";
|
|
1198
|
+
readonly dropIndicator: "var(--pubwave-color-drop-indicator)";
|
|
1199
|
+
readonly dropTarget: "var(--pubwave-color-drop-target)";
|
|
1200
|
+
readonly error: "var(--pubwave-color-error)";
|
|
1201
|
+
};
|
|
1202
|
+
readonly spacing: {
|
|
1203
|
+
readonly xs: "var(--pubwave-spacing-xs)";
|
|
1204
|
+
readonly sm: "var(--pubwave-spacing-sm)";
|
|
1205
|
+
readonly md: "var(--pubwave-spacing-md)";
|
|
1206
|
+
readonly lg: "var(--pubwave-spacing-lg)";
|
|
1207
|
+
readonly xl: "var(--pubwave-spacing-xl)";
|
|
1208
|
+
readonly blockPaddingX: "var(--pubwave-block-padding-x)";
|
|
1209
|
+
readonly blockPaddingY: "var(--pubwave-block-padding-y)";
|
|
1210
|
+
readonly blockMarginY: "var(--pubwave-block-margin-y)";
|
|
1211
|
+
readonly toolbarGap: "var(--pubwave-toolbar-gap)";
|
|
1212
|
+
};
|
|
1213
|
+
readonly typography: {
|
|
1214
|
+
readonly fontFamily: "var(--pubwave-font-family)";
|
|
1215
|
+
readonly fontSizeBase: "var(--pubwave-font-size-base)";
|
|
1216
|
+
readonly fontSizeSmall: "var(--pubwave-font-size-small)";
|
|
1217
|
+
readonly lineHeightBase: "var(--pubwave-line-height-base)";
|
|
1218
|
+
readonly lineHeightHeading: "var(--pubwave-line-height-heading)";
|
|
1219
|
+
readonly fontWeightNormal: "var(--pubwave-font-weight-normal)";
|
|
1220
|
+
readonly fontWeightMedium: "var(--pubwave-font-weight-medium)";
|
|
1221
|
+
readonly fontWeightBold: "var(--pubwave-font-weight-bold)";
|
|
1222
|
+
readonly fontWeightHeading: "var(--pubwave-font-weight-heading)";
|
|
1223
|
+
};
|
|
1224
|
+
readonly borderRadius: {
|
|
1225
|
+
readonly sm: "var(--pubwave-border-radius-sm)";
|
|
1226
|
+
readonly md: "var(--pubwave-border-radius)";
|
|
1227
|
+
readonly lg: "var(--pubwave-border-radius-large)";
|
|
1228
|
+
};
|
|
1229
|
+
readonly shadow: {
|
|
1230
|
+
readonly sm: "var(--pubwave-shadow-sm)";
|
|
1231
|
+
readonly md: "var(--pubwave-shadow-md)";
|
|
1232
|
+
readonly toolbar: "var(--pubwave-shadow-toolbar)";
|
|
1233
|
+
readonly popup: "var(--pubwave-shadow-popup)";
|
|
1234
|
+
};
|
|
1235
|
+
readonly transition: {
|
|
1236
|
+
readonly fast: "var(--pubwave-transition-fast)";
|
|
1237
|
+
readonly normal: "var(--pubwave-transition-normal)";
|
|
1238
|
+
};
|
|
1239
|
+
readonly zIndex: {
|
|
1240
|
+
readonly dragPreview: 100;
|
|
1241
|
+
readonly dragHandle: 40;
|
|
1242
|
+
readonly toolbar: 50;
|
|
1243
|
+
readonly dropdown: 60;
|
|
1244
|
+
};
|
|
1245
|
+
};
|
|
1246
|
+
|
|
1247
|
+
/**
|
|
1248
|
+
* Toolbar action descriptors for dynamic toolbar generation
|
|
1249
|
+
*/
|
|
1250
|
+
export declare interface ToolbarActionDescriptor {
|
|
1251
|
+
id: string;
|
|
1252
|
+
label: string;
|
|
1253
|
+
shortcut?: string;
|
|
1254
|
+
icon: string;
|
|
1255
|
+
action: (editor: Editor_2) => ActionResult;
|
|
1256
|
+
isActive: (editor: Editor_2) => boolean;
|
|
1257
|
+
isDisabled?: (editor: Editor_2) => boolean;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* Toolbar position calculated relative to viewport
|
|
1262
|
+
*/
|
|
1263
|
+
export declare interface ToolbarPosition {
|
|
1264
|
+
top: number;
|
|
1265
|
+
left: number;
|
|
1266
|
+
visible: boolean;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
/**
|
|
1270
|
+
* Remove link from selection
|
|
1271
|
+
*/
|
|
1272
|
+
export declare function toolbarRemoveLink(editor: Editor_2): ActionResult;
|
|
1273
|
+
|
|
1274
|
+
/**
|
|
1275
|
+
* Set heading level
|
|
1276
|
+
*/
|
|
1277
|
+
export declare function toolbarSetHeading(editor: Editor_2, level: 1 | 2 | 3): ActionResult;
|
|
1278
|
+
|
|
1279
|
+
/**
|
|
1280
|
+
* Set a link on the selection
|
|
1281
|
+
*/
|
|
1282
|
+
export declare function toolbarSetLink(editor: Editor_2, href: string): ActionResult;
|
|
1283
|
+
|
|
1284
|
+
/**
|
|
1285
|
+
* Set paragraph (remove heading)
|
|
1286
|
+
*/
|
|
1287
|
+
export declare function toolbarSetParagraph(editor: Editor_2): ActionResult;
|
|
1288
|
+
|
|
1289
|
+
/**
|
|
1290
|
+
* Toggle bold mark on selection
|
|
1291
|
+
*/
|
|
1292
|
+
export declare function toolbarToggleBold(editor: Editor_2): ActionResult;
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* Toggle italic mark on selection
|
|
1296
|
+
*/
|
|
1297
|
+
export declare function toolbarToggleItalic(editor: Editor_2): ActionResult;
|
|
1298
|
+
|
|
1299
|
+
/**
|
|
1300
|
+
* Toggle link - prompts for URL if adding, removes if already linked
|
|
1301
|
+
*/
|
|
1302
|
+
export declare function toolbarToggleLink(editor: Editor_2, promptFn?: (message: string) => string | null): ActionResult;
|
|
1303
|
+
|
|
1304
|
+
/**
|
|
1305
|
+
* Undo the last action
|
|
1306
|
+
*/
|
|
1307
|
+
export declare function undo(editor: Editor_2): boolean;
|
|
1308
|
+
|
|
1309
|
+
/**
|
|
1310
|
+
* Remove link from the current selection
|
|
1311
|
+
*/
|
|
1312
|
+
export declare function unsetLink(editor: Editor_2): boolean;
|
|
1313
|
+
|
|
1314
|
+
/**
|
|
1315
|
+
* React hook for auto-scroll during drag operations
|
|
1316
|
+
*/
|
|
1317
|
+
export declare function useAutoScroll(scrollContainer?: HTMLElement | null): {
|
|
1318
|
+
startAutoScroll: () => void;
|
|
1319
|
+
updateAutoScroll: (event: {
|
|
1320
|
+
clientY: number;
|
|
1321
|
+
}) => void;
|
|
1322
|
+
stopAutoScroll: () => void;
|
|
1323
|
+
};
|
|
1324
|
+
|
|
1325
|
+
export { }
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
declare module '@tiptap/core' {
|
|
1329
|
+
interface Commands<ReturnType> {
|
|
1330
|
+
textColor: {
|
|
1331
|
+
setColor: (color: string) => ReturnType;
|
|
1332
|
+
unsetColor: () => ReturnType;
|
|
1333
|
+
};
|
|
1334
|
+
backgroundColor: {
|
|
1335
|
+
setBackgroundColor: (backgroundColor: string) => ReturnType;
|
|
1336
|
+
unsetBackgroundColor: () => ReturnType;
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
}
|