@4399ywkf/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/dist/doc.d.ts ADDED
@@ -0,0 +1,1108 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, RefObject, useEffect, HTMLAttributes } from 'react';
3
+ import { JSONContent, Editor, NodeWithPos, Extension as Extension$1, Node as Node$1 } from '@tiptap/react';
4
+ import { Extensions, Extension } from '@tiptap/core';
5
+ import { Doc } from 'yjs';
6
+ import { UseFloatingOptions, UseDismissProps, AutoUpdateOptions } from '@floating-ui/react';
7
+ import { Selection, Transaction } from '@tiptap/pm/state';
8
+ import { Node } from '@tiptap/pm/model';
9
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
10
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
11
+
12
+ /**
13
+ * 包消费者通过 `<EditorConfigProvider>` 注入业务侧能力。
14
+ *
15
+ * 设计原则:包内不感知业务 store / API / 路由,所有外部依赖都从这里取。
16
+ * 也不直接依赖私有付费包(如 @tiptap-pro/provider),所以 provider 用最小接口约束。
17
+ */
18
+ /**
19
+ * 协同 provider 的最小接口约束。
20
+ * 任何 yjs awareness provider(TiptapCollabProvider / HocuspocusProvider / 自定义)
21
+ * 只要实现 `destroy()` 就可以传入。`CollaborationCaret` 会通过 `provider.awareness`
22
+ * 自取协同状态,不需要在这里 typed。
23
+ */
24
+ interface CollabProviderLike {
25
+ destroy: () => void;
26
+ [key: string]: unknown;
27
+ }
28
+ interface CollabCreateParams {
29
+ /** 拼好的文档名:`${docPrefix}${room}` */
30
+ name: string;
31
+ /** yjs 共享文档 */
32
+ ydoc: Doc;
33
+ /** 业务方通过 `fetchToken` 获取的 JWT */
34
+ token: string;
35
+ }
36
+ interface EditorCollabConfig {
37
+ /** 协同服务的 App ID(透传给 createProvider,包不直接用) */
38
+ appId?: string;
39
+ /** room 名前缀,最终 docName = `${docPrefix}${room}` */
40
+ docPrefix?: string;
41
+ /**
42
+ * 选项 A:业务方自己 new 好 provider,自管理生命周期。
43
+ * 包不在内部创建/销毁,hasCollab 直接为 true。
44
+ */
45
+ provider?: CollabProviderLike;
46
+ /**
47
+ * 选项 B:业务方提供 token 获取函数 + provider 工厂,包内调用工厂创建实例,
48
+ * 并在组件卸载时调用 `provider.destroy()`。
49
+ */
50
+ fetchToken?: () => Promise<string | null>;
51
+ createProvider?: (params: CollabCreateParams) => CollabProviderLike;
52
+ }
53
+ interface EditorUserConfig {
54
+ id: string;
55
+ name: string;
56
+ color: string;
57
+ avatar?: string;
58
+ }
59
+ /** 包内识别的媒体大类,决定走哪个 tiptap 节点 + 哪个 size 上限。 */
60
+ type MediaKind = "image" | "video" | "audio" | "file";
61
+ interface EditorUploadConfig {
62
+ /**
63
+ * 上传文件,返回最终可访问的 URL。业务侧按 file.type 自己决定走哪个端点
64
+ * (图片走 /assets/image,其它走 /assets/attachment 等)。
65
+ * 包内 ImageUploadNode / PasteDropMedia / 工具栏 / slash 菜单都走它。
66
+ */
67
+ onUpload: (file: File, onProgress?: (event: {
68
+ progress: number;
69
+ }) => void, abortSignal?: AbortSignal) => Promise<string>;
70
+ /**
71
+ * @deprecated 用 `maxFileSizes.image` 替代。保留用于向后兼容。
72
+ */
73
+ maxFileSize?: number;
74
+ /**
75
+ * 按媒体大类分别设置单文件大小上限(字节,0 = 不限制)。
76
+ * 未设置的类型走包内默认值:image 5MB、video 100MB、audio/file 20MB。
77
+ */
78
+ maxFileSizes?: Partial<Record<MediaKind, number>>;
79
+ /**
80
+ * 上传相关错误的统一回调。业务侧通常接到 toast / message.error。
81
+ * 包内 ImageUploadNode 和 PasteDropMedia 都走这个 hook,没接的话退化为 console.error。
82
+ */
83
+ onError?: (error: Error) => void;
84
+ /**
85
+ * 外链图片转存到 CDN 的全程进度(下载 → 上传 → 完成),业务侧通常接到
86
+ * antd `message.loading`。同一 URL 的事件按相同 `url` 字段聚合,业务侧用
87
+ * `message.loading({ key: 'rehost:' + url, ... })` / `message.destroy(key)`
88
+ * 即可获得"进度更新 → 完成销毁"的体验。
89
+ */
90
+ onRehostProgress?: (event: RehostProgressEvent) => void;
91
+ }
92
+ type RehostProgressEvent = {
93
+ url: string;
94
+ phase: "downloading";
95
+ progress: number;
96
+ } | {
97
+ url: string;
98
+ phase: "uploading";
99
+ progress: number;
100
+ } | {
101
+ url: string;
102
+ phase: "done";
103
+ progress: 100;
104
+ };
105
+ /** 默认分类型大小上限(字节)。可被 EditorUploadConfig.maxFileSizes 覆盖。 */
106
+ declare const DEFAULT_MAX_FILE_SIZES: Record<MediaKind, number>;
107
+ /** 通过 file.type 判断走哪个媒体节点。 */
108
+ declare const detectMediaKind: (file: {
109
+ type: string;
110
+ }) => MediaKind;
111
+ /** 合并业务配置 + 默认值,拿到指定类型的 size 上限。 */
112
+ declare const resolveMaxSize: (kind: MediaKind, config: EditorUploadConfig | null | undefined) => number;
113
+ interface EditorConfig {
114
+ collab?: EditorCollabConfig;
115
+ user?: EditorUserConfig;
116
+ upload?: EditorUploadConfig;
117
+ }
118
+ interface EditorConfigProviderProps {
119
+ config: EditorConfig;
120
+ children: ReactNode;
121
+ }
122
+ declare function EditorConfigProvider({ config, children, }: EditorConfigProviderProps): react.JSX.Element;
123
+ /** 拿到当前注入的编辑器业务配置;未注入时返回 null。 */
124
+ declare const useEditorConfig: () => EditorConfig | null;
125
+
126
+ interface NotionEditorProps {
127
+ room: string;
128
+ placeholder?: string;
129
+ /**
130
+ * 初始内容(HTML 字符串或 tiptap JSONContent)。
131
+ * 仅在**非协同模式**(无 provider)下生效——业务方通过 HTTP 拿到文档内容后传入。
132
+ * 协同模式下 yjs Doc 接管内容,传入会被忽略以免跟 sync 冲突。
133
+ */
134
+ content?: string | JSONContent;
135
+ /**
136
+ * 只读模式:用于展示文章内容。设为 true 时编辑器不可编辑(editable:false),
137
+ * 且隐藏所有编辑态 UI(头部工具栏、浮动工具栏、拖拽手柄、slash/mention/emoji
138
+ * 菜单、移动端工具栏、表格手柄),仅保留内容与目录侧栏。
139
+ * 扩展集与编辑态完全一致,保证自定义节点(图片/视频/附件/分栏/表格等)渲染像素一致。
140
+ */
141
+ readOnly?: boolean;
142
+ /**
143
+ * 隐藏包内置顶部工具条(undo/redo、主题切换、协同用户,含底部分隔线)。
144
+ * 业务方页面自带头部(如 wiki 编辑页的面包屑 + 操作区)时开启,
145
+ * 避免出现第二条贴在标题下方的工具条。undo/redo 快捷键不受影响。
146
+ */
147
+ hideHeader?: boolean;
148
+ /**
149
+ * 编辑器实例就绪回调。包不感知业务 store —— 业务方拿到 editor 实例后自行接管
150
+ * (如写进 zustand store,发布时用 editor.getHTML()/getJSON() 取正文)。
151
+ * 每次 editor 重建(如 room 切换触发 remount)都会带新实例再次回调。
152
+ */
153
+ onEditorReady?: (editor: Editor) => void;
154
+ /**
155
+ * 追加的 tiptap 扩展,挂在包内置扩展集之后。
156
+ *
157
+ * 用于接入包不感知的能力(如 docx 导入、自定义节点),业务方按需注入。
158
+ * 注意:注入的扩展会改变 schema —— 协同场景下所有客户端必须注入同一组,
159
+ * 否则各端 schema 不一致,yjs 同步会出现内容被判为非法而丢弃。
160
+ */
161
+ extensions?: Extensions;
162
+ }
163
+ interface EditorProviderProps {
164
+ /**
165
+ * 协同 provider,可以为 null。null 时退化到本地编辑(不挂 CollaborationCaret,
166
+ * 但仍挂 Collaboration extension 以操作本地 yjs 文档)。
167
+ */
168
+ provider: CollabProviderLike | null;
169
+ ydoc: Doc;
170
+ placeholder?: string;
171
+ /** 本地编辑模式下的初始/同步内容,详见 NotionEditorProps.content */
172
+ content?: string | JSONContent;
173
+ /** 只读模式,详见 NotionEditorProps.readOnly */
174
+ readOnly?: boolean;
175
+ /** 隐藏包内置顶部工具条,详见 NotionEditorProps.hideHeader */
176
+ hideHeader?: boolean;
177
+ /**
178
+ * 内嵌模式:用于把正文嵌进业务页面(ArticleViewer 场景)。
179
+ * 开启后去掉编辑器整页 chrome —— 不渲染 TocSidebar,布局退化为单列铺满
180
+ * (去掉左右大边距列与 708px 内容上限),内边距交给外层容器控制。
181
+ * 与 readOnly 正交:`<NotionEditor readOnly>`(编辑器内预览)仍保留整页布局 + TOC。
182
+ */
183
+ embedded?: boolean;
184
+ /** editor 实例就绪回调,详见 NotionEditorProps.onEditorReady */
185
+ onEditorReady?: (editor: Editor) => void;
186
+ /**
187
+ * 追加的 tiptap 扩展,挂在包内置扩展集之后。
188
+ *
189
+ * 用于接入包不感知的能力(如 docx 导入、自定义节点),业务方按需注入。
190
+ * 注意:注入的扩展会改变 schema —— 协同场景下所有客户端必须注入同一组,
191
+ * 否则各端 schema 不一致,yjs 同步会出现内容被判为非法而丢弃。
192
+ */
193
+ extensions?: Extensions;
194
+ }
195
+ /**
196
+ * Loading spinner component shown while connecting to the notion server
197
+ */
198
+ declare function LoadingSpinner({ text }: {
199
+ text?: string;
200
+ }): react.JSX.Element;
201
+ /**
202
+ * EditorContent component that renders the actual editor
203
+ */
204
+ declare function EditorContentArea(): react.JSX.Element | null;
205
+ /**
206
+ * Component that creates and provides the editor instance
207
+ */
208
+ declare function EditorProvider(props: EditorProviderProps): react.JSX.Element;
209
+ /**
210
+ * Full editor with all necessary providers, ready to use with just a room ID
211
+ */
212
+ declare function NotionEditor({ room, placeholder, content, readOnly, hideHeader, onEditorReady, extensions, }: NotionEditorProps): react.JSX.Element;
213
+ /**
214
+ * Internal component that handles the editor loading state
215
+ */
216
+ declare function NotionEditorContent({ placeholder, content, readOnly, hideHeader, onEditorReady, extensions, }: {
217
+ placeholder?: string;
218
+ content?: string | JSONContent;
219
+ readOnly?: boolean;
220
+ hideHeader?: boolean;
221
+ onEditorReady?: (editor: Editor) => void;
222
+ /**
223
+ * 追加的 tiptap 扩展,挂在包内置扩展集之后。
224
+ *
225
+ * 用于接入包不感知的能力(如 docx 导入、自定义节点),业务方按需注入。
226
+ * 注意:注入的扩展会改变 schema —— 协同场景下所有客户端必须注入同一组,
227
+ * 否则各端 schema 不一致,yjs 同步会出现内容被判为非法而丢弃。
228
+ */
229
+ extensions?: Extensions;
230
+ }): react.JSX.Element;
231
+ interface ArticleViewerProps {
232
+ /** 文章内容(HTML 字符串或 tiptap JSONContent),通常由 HTTP 接口拉取后传入 */
233
+ content?: string | JSONContent;
234
+ /** 空内容时的占位文案,默认空(viewer 一般不显示占位) */
235
+ placeholder?: string;
236
+ }
237
+ /**
238
+ * 文章只读展示组件。
239
+ *
240
+ * 与 <NotionEditor readOnly> 的区别:
241
+ * - 不需要 room,也不接入任何协同——刻意绕过 CollabProvider、自建本地 yjs Doc,
242
+ * 保证 viewer 不会建立 websocket 连接(即使业务侧注入了 collab 配置)。
243
+ * - 复用 EditorProvider 的完整扩展集 + readOnly,渲染结果与编辑器像素一致。
244
+ *
245
+ * 用法:<ArticleViewer content={articleContent} />
246
+ */
247
+ declare function ArticleViewer({ content, placeholder }: ArticleViewerProps): react.JSX.Element;
248
+
249
+ type CollabContextValue = {
250
+ provider: CollabProviderLike | null;
251
+ ydoc: Doc;
252
+ hasCollab: boolean;
253
+ setupError: boolean;
254
+ };
255
+ declare const CollabContext: react.Context<CollabContextValue>;
256
+ declare const useCollab: () => CollabContextValue;
257
+ /**
258
+ * 协同钩子:从 EditorConfigProvider 注入的 config.collab 决定接入方式。
259
+ *
260
+ * 行为:
261
+ * 1. `config.collab.provider` 存在 → 直接使用业务方传入的 provider(包不创建、不销毁)
262
+ * 2. `config.collab.fetchToken` + `createProvider` → 包内调用工厂创建 provider,
263
+ * 组件卸载时自动 `destroy()`
264
+ * 3. URL `?noCollab=1` → 强制跳过协同(hasCollab=false,仅本地编辑)
265
+ * 4. 业务方完全未配置 collab → hasCollab=false(本地编辑模式,不报错)
266
+ * 5. 业务方部分配置但缺 fetchToken/createProvider → setupError
267
+ */
268
+ declare const useCollaboration: (room: string) => {
269
+ provider: CollabProviderLike | null;
270
+ ydoc: Doc;
271
+ hasCollab: boolean;
272
+ setupError: boolean;
273
+ };
274
+ declare function CollabProvider({ children, room, }: Readonly<{
275
+ children: React.ReactNode;
276
+ room: string;
277
+ }>): react.JSX.Element;
278
+
279
+ type User = {
280
+ id: string;
281
+ name: string;
282
+ color: string;
283
+ avatar: string;
284
+ };
285
+ type UserContextValue = {
286
+ user: User;
287
+ };
288
+ declare const UserContext: react.Context<UserContextValue>;
289
+ /**
290
+ * UserProvider:优先用 EditorConfigProvider 注入的 user,
291
+ * 未注入时退化到 localStorage(生成随机用户名/颜色,仅用于本地开发或预览场景)。
292
+ */
293
+ declare function UserProvider({ children }: {
294
+ children: React.ReactNode;
295
+ }): react.JSX.Element;
296
+ declare const useUser: () => UserContextValue;
297
+
298
+ declare function useTiptapEditor(providedEditor?: Editor | null): {
299
+ editor: Editor | null;
300
+ editorState?: Editor["state"];
301
+ canCommand?: Editor["can"];
302
+ };
303
+
304
+ declare module "@tiptap/core" {
305
+ interface Commands<ReturnType> {
306
+ uiState: {
307
+ commentInputShow: () => ReturnType;
308
+ commentInputHide: () => ReturnType;
309
+ setLockDragHandle: (value: boolean) => ReturnType;
310
+ resetUiState: () => ReturnType;
311
+ setIsDragging: (value: boolean) => ReturnType;
312
+ };
313
+ }
314
+ interface Storage {
315
+ uiState: UiState;
316
+ }
317
+ }
318
+ declare const defaultUiState: UiState;
319
+ interface UiState {
320
+ commentInputVisible: boolean;
321
+ lockDragHandle: boolean;
322
+ isDragging: boolean;
323
+ }
324
+ declare const UiState: Extension<UiState, any>;
325
+
326
+ declare function useUiEditorState(editor: Editor | null): UiState;
327
+
328
+ declare const HIDE_FLOATING_META = "hideFloatingToolbar";
329
+ /**
330
+ * Centralizes all logic about when the floating toolbar should be hidden/shown.
331
+ *
332
+ * - Listens for transactions that carry HIDE_FLOATING_META
333
+ * - Clears the hide flag on common “user intent” events
334
+ * - Handles the “re-click on the same selected node” case
335
+ * - Exposes `shouldShow` so UI can just render based on it
336
+ * - Exposes helpers to set selections with the meta flag
337
+ */
338
+ declare function useFloatingToolbarVisibility(params: {
339
+ editor: Editor | null;
340
+ isSelectionValid: (editor: Editor, selection: Editor["state"]["selection"]) => boolean;
341
+ extraHideWhen?: boolean;
342
+ }): {
343
+ shouldShow: boolean;
344
+ };
345
+ /**
346
+ * Programmatically select a node and hide floating for that selection
347
+ * @param editor
348
+ * @param pos
349
+ */
350
+ declare const selectNodeAndHideFloating: (editor: Editor, pos: number) => void;
351
+ /**
352
+ * Mark “hide floating” on the next relevant transaction (no selection change needed)
353
+ * @param editor
354
+ */
355
+ declare const markHideFloatingOnNext: (editor: Editor) => void;
356
+
357
+ type RectState = Omit<DOMRect, "toJSON">;
358
+ interface ElementRectOptions {
359
+ /**
360
+ * The element to track. Can be an Element, ref, or selector string.
361
+ * Defaults to document.body if not provided.
362
+ */
363
+ element?: Element | React.RefObject<Element> | string | null;
364
+ /**
365
+ * Whether to enable rect tracking
366
+ */
367
+ enabled?: boolean;
368
+ /**
369
+ * Throttle delay in milliseconds for rect updates
370
+ */
371
+ throttleMs?: number;
372
+ /**
373
+ * Whether to use ResizeObserver for more accurate tracking
374
+ */
375
+ useResizeObserver?: boolean;
376
+ }
377
+ /**
378
+ * Custom hook that tracks an element's bounding rectangle and updates on resize, scroll, etc.
379
+ *
380
+ * @param options Configuration options for element rect tracking
381
+ * @returns The current bounding rectangle of the element
382
+ */
383
+ declare function useElementRect({ element, enabled, throttleMs, useResizeObserver, }?: ElementRectOptions): RectState;
384
+
385
+ interface CursorVisibilityOptions {
386
+ /**
387
+ * The Tiptap editor instance
388
+ */
389
+ editor?: Editor | null;
390
+ /**
391
+ * Reference to the toolbar element that may obscure the cursor
392
+ */
393
+ overlayHeight?: number;
394
+ }
395
+ /**
396
+ * Custom hook that ensures the cursor remains visible when typing in a Tiptap editor.
397
+ * Automatically scrolls the window when the cursor would be hidden by the toolbar.
398
+ *
399
+ * @param options.editor The Tiptap editor instance
400
+ * @param options.overlayHeight Toolbar height to account for
401
+ * @returns The bounding rect of the body
402
+ */
403
+ declare function useCursorVisibility({ editor, overlayHeight, }: CursorVisibilityOptions): RectState;
404
+
405
+ interface FloatingElementReturn {
406
+ /**
407
+ * Whether the floating element is currently mounted in the DOM.
408
+ */
409
+ isMounted: boolean;
410
+ /**
411
+ * Ref function to attach to the floating element DOM node.
412
+ */
413
+ ref: (node: HTMLElement | null) => void;
414
+ /**
415
+ * Combined styles for positioning, transitions, and z-index.
416
+ */
417
+ style: React.CSSProperties;
418
+ /**
419
+ * Returns props that should be spread onto the floating element.
420
+ */
421
+ getFloatingProps: (userProps?: React.HTMLProps<HTMLElement>) => Record<string, unknown>;
422
+ /**
423
+ * Returns props that should be spread onto the reference element.
424
+ */
425
+ getReferenceProps: (userProps?: React.HTMLProps<Element>) => Record<string, unknown>;
426
+ }
427
+ /**
428
+ * Custom hook for creating and managing floating elements relative to a reference position
429
+ *
430
+ * @param show - Boolean controlling visibility of the floating element
431
+ * @param referencePos - DOMRect, function returning DOMRect, or null representing the position to anchor the floating element to
432
+ * @param zIndex - Z-index value for the floating element
433
+ * @param options - Additional options to pass to the underlying useFloating hook
434
+ * @returns Object containing properties and methods to control the floating element
435
+ */
436
+ declare function useFloatingElement(show: boolean, reference: HTMLElement | DOMRect | (() => DOMRect | null) | null, zIndex: number, options?: Partial<UseFloatingOptions & {
437
+ dismissOptions?: UseDismissProps;
438
+ }>, autoUpdateOptions?: AutoUpdateOptions): FloatingElementReturn;
439
+
440
+ type BreakpointMode = "min" | "max";
441
+ /**
442
+ * Hook to detect whether the current viewport matches a given breakpoint rule.
443
+ * Example:
444
+ * useIsBreakpoint("max", 768) // true when width < 768
445
+ * useIsBreakpoint("min", 1024) // true when width >= 1024
446
+ */
447
+ declare function useIsBreakpoint(mode?: BreakpointMode, breakpoint?: number): boolean;
448
+
449
+ type Orientation$1 = "horizontal" | "vertical" | "both";
450
+ interface MenuNavigationOptions<T> {
451
+ /**
452
+ * The Tiptap editor instance, if using with a Tiptap editor.
453
+ */
454
+ editor?: Editor | null;
455
+ /**
456
+ * Reference to the container element for handling keyboard events.
457
+ */
458
+ containerRef?: React.RefObject<HTMLElement | null>;
459
+ /**
460
+ * Search query that affects the selected item.
461
+ */
462
+ query?: string;
463
+ /**
464
+ * Array of items to navigate through.
465
+ */
466
+ items: T[];
467
+ /**
468
+ * Callback fired when an item is selected.
469
+ */
470
+ onSelect?: (item: T) => void;
471
+ /**
472
+ * Callback fired when the menu should close.
473
+ */
474
+ onClose?: () => void;
475
+ /**
476
+ * The navigation orientation of the menu.
477
+ * @default "vertical"
478
+ */
479
+ orientation?: Orientation$1;
480
+ /**
481
+ * Whether to automatically select the first item when the menu opens.
482
+ * @default true
483
+ */
484
+ autoSelectFirstItem?: boolean;
485
+ }
486
+ /**
487
+ * Hook that implements keyboard navigation for dropdown menus and command palettes.
488
+ *
489
+ * Handles arrow keys, tab, home/end, enter for selection, and escape to close.
490
+ * Works with both Tiptap editors and regular DOM elements.
491
+ *
492
+ * @param options - Configuration options for the menu navigation
493
+ * @returns Object containing the selected index and a setter function
494
+ */
495
+ declare function useMenuNavigation<T>({ editor, containerRef, query, items, onSelect, onClose, orientation, autoSelectFirstItem, }: MenuNavigationOptions<T>): {
496
+ selectedIndex: number | undefined;
497
+ setSelectedIndex: react.Dispatch<react.SetStateAction<number>>;
498
+ };
499
+
500
+ /** Supported event types. */
501
+ type EventType = "mousedown" | "mouseup" | "touchstart" | "touchend" | "focusin" | "focusout";
502
+ /**
503
+ * Custom hook that handles clicks outside a specified element.
504
+ * @template T - The type of the element's reference.
505
+ * @param {RefObject<T> | RefObject<T>[]} ref - The React ref object(s) representing the element(s) to watch for outside clicks.
506
+ * @param {(event: MouseEvent | TouchEvent | FocusEvent) => void} handler - The callback function to be executed when a click outside the element occurs.
507
+ * @param {EventType} [eventType] - The mouse event type to listen for (optional, default is 'mousedown').
508
+ * @param {?AddEventListenerOptions} [eventListenerOptions] - The options object to be passed to the `addEventListener` method (optional).
509
+ * @returns {void}
510
+ */
511
+ declare function useOnClickOutside<T extends HTMLElement | null = HTMLElement>(ref: RefObject<T> | RefObject<T>[], handler: (event: MouseEvent | TouchEvent | FocusEvent) => void, eventType?: EventType, eventListenerOptions?: AddEventListenerOptions): void;
512
+
513
+ type ScrollTarget = RefObject<HTMLElement> | Window | null | undefined;
514
+ interface UseScrollingOptions {
515
+ debounce?: number;
516
+ fallbackToDocument?: boolean;
517
+ }
518
+ declare function useScrolling(target?: ScrollTarget, options?: UseScrollingOptions): boolean;
519
+
520
+ interface ThrottleSettings {
521
+ leading?: boolean | undefined;
522
+ trailing?: boolean | undefined;
523
+ }
524
+ /**
525
+ * A hook that returns a throttled callback function.
526
+ *
527
+ * @param fn The function to throttle
528
+ * @param wait The time in ms to wait before calling the function
529
+ * @param dependencies The dependencies to watch for changes
530
+ * @param options The throttle options
531
+ */
532
+ declare function useThrottledCallback<T extends (...args: any[]) => any>(fn: T, wait?: number, dependencies?: React.DependencyList, options?: ThrottleSettings): {
533
+ (this: ThisParameterType<T>, ...args: Parameters<T>): ReturnType<T>;
534
+ cancel: () => void;
535
+ flush: () => void;
536
+ };
537
+
538
+ /**
539
+ * Hook that executes a callback when the component unmounts.
540
+ *
541
+ * @param callback Function to be called on component unmount
542
+ */
543
+ declare const useUnmount: (callback: (...args: Array<any>) => any) => void;
544
+
545
+ interface WindowSizeState {
546
+ /**
547
+ * The width of the window's visual viewport in pixels.
548
+ */
549
+ width: number;
550
+ /**
551
+ * The height of the window's visual viewport in pixels.
552
+ */
553
+ height: number;
554
+ /**
555
+ * The distance from the top of the visual viewport to the top of the layout viewport.
556
+ * Particularly useful for handling mobile keyboard appearance.
557
+ */
558
+ offsetTop: number;
559
+ /**
560
+ * The distance from the left of the visual viewport to the left of the layout viewport.
561
+ */
562
+ offsetLeft: number;
563
+ /**
564
+ * The scale factor of the visual viewport.
565
+ * This is useful for scaling elements based on the current zoom level.
566
+ */
567
+ scale: number;
568
+ }
569
+ /**
570
+ * Hook that tracks the window's visual viewport dimensions, position, and provides
571
+ * a CSS transform for positioning elements.
572
+ *
573
+ * Uses the Visual Viewport API to get accurate measurements, especially important
574
+ * for mobile devices where virtual keyboards can change the visible area.
575
+ * Only updates state when values actually change to optimize performance.
576
+ *
577
+ * @returns An object containing viewport properties and a CSS transform string
578
+ */
579
+ declare function useWindowSize(): WindowSizeState;
580
+
581
+ /**
582
+ * Custom hook that uses either `useLayoutEffect` or `useEffect` based on the environment (client-side or server-side).
583
+ * @param {Function} effect - The effect function to be executed.
584
+ * @param {Array<any>} [dependencies] - An array of dependencies for the effect (optional).
585
+ */
586
+ declare const useIsomorphicLayoutEffect: typeof useEffect;
587
+
588
+ type UserRef<T> = ((instance: T | null) => void) | React.RefObject<T | null> | null | undefined;
589
+ declare const useComposedRef: <T extends HTMLElement>(libRef: React.RefObject<T | null>, userRef: UserRef<T>) => (instance: T | null) => void;
590
+
591
+ type OverflowPosition = "none" | "top" | "bottom" | "both";
592
+ /**
593
+ * Utility function to get URL parameters
594
+ */
595
+ declare const getUrlParam: (param: string) => string | null;
596
+ /**
597
+ * Returns a display name for the current node in the editor
598
+ * @param editor The Tiptap editor instance
599
+ * @returns The display name of the current node
600
+ */
601
+ declare const getNodeDisplayName: (editor: Editor | null) => string;
602
+ /**
603
+ * Removes empty paragraph nodes from content
604
+ */
605
+ declare const removeEmptyParagraphs: (content: JSONContent) => {
606
+ content: JSONContent[] | undefined;
607
+ type?: string;
608
+ attrs?: Record<string, any> | undefined;
609
+ marks?: {
610
+ type: string;
611
+ attrs?: Record<string, any>;
612
+ [key: string]: any;
613
+ }[];
614
+ text?: string;
615
+ };
616
+ /**
617
+ * Determines how a target element overflows relative to a container element
618
+ */
619
+ declare function getElementOverflowPosition(targetElement: Element, containerElement: HTMLElement): OverflowPosition;
620
+ /**
621
+ * Checks if the current selection is valid for a given editor
622
+ */
623
+ declare const isSelectionValid: (editor: Editor | null, selection?: Selection, excludedNodeTypes?: string[]) => boolean;
624
+ /**
625
+ * Checks if the current text selection is valid for editing
626
+ * - Not empty
627
+ * - Not a code block
628
+ * - Not a node selection
629
+ */
630
+ declare const isTextSelectionValid: (editor: Editor | null) => boolean;
631
+ /**
632
+ * Gets the bounding rect of the current selection in the editor.
633
+ */
634
+ declare const getSelectionBoundingRect: (editor: Editor) => DOMRect | null;
635
+ /**
636
+ * Generates a deterministic avatar URL from a user name
637
+ */
638
+ declare const getAvatar: (name: string) => string;
639
+
640
+ declare const MAX_FILE_SIZE: number;
641
+ declare const MAC_SYMBOLS: Record<string, string>;
642
+ declare const SR_ONLY: {
643
+ readonly position: "absolute";
644
+ readonly width: "1px";
645
+ readonly height: "1px";
646
+ readonly padding: 0;
647
+ readonly margin: "-1px";
648
+ readonly overflow: "hidden";
649
+ readonly clip: "rect(0, 0, 0, 0)";
650
+ readonly whiteSpace: "nowrap";
651
+ readonly borderWidth: 0;
652
+ };
653
+ declare function cn(...classes: (string | boolean | undefined | null)[]): string;
654
+ /**
655
+ * Determines if the current platform is macOS
656
+ * @returns boolean indicating if the current platform is Mac
657
+ */
658
+ declare function isMac(): boolean;
659
+ /**
660
+ * Formats a shortcut key based on the platform (Mac or non-Mac)
661
+ * @param key - The key to format (e.g., "ctrl", "alt", "shift")
662
+ * @param isMac - Boolean indicating if the platform is Mac
663
+ * @param capitalize - Whether to capitalize the key (default: true)
664
+ * @returns Formatted shortcut key symbol
665
+ */
666
+ declare const formatShortcutKey: (key: string, isMac: boolean, capitalize?: boolean) => string;
667
+ /**
668
+ * Parses a shortcut key string into an array of formatted key symbols
669
+ * @param shortcutKeys - The string of shortcut keys (e.g., "ctrl-alt-shift")
670
+ * @param delimiter - The delimiter used to split the keys (default: "-")
671
+ * @param capitalize - Whether to capitalize the keys (default: true)
672
+ * @returns Array of formatted shortcut key symbols
673
+ */
674
+ declare const parseShortcutKeys: (props: {
675
+ shortcutKeys: string | undefined;
676
+ delimiter?: string;
677
+ capitalize?: boolean;
678
+ }) => string[];
679
+ /**
680
+ * Checks if a mark exists in the editor schema
681
+ * @param markName - The name of the mark to check
682
+ * @param editor - The editor instance
683
+ * @returns boolean indicating if the mark exists in the schema
684
+ */
685
+ declare const isMarkInSchema: (markName: string, editor: Editor | null) => boolean;
686
+ /**
687
+ * Checks if a node exists in the editor schema
688
+ * @param nodeName - The name of the node to check
689
+ * @param editor - The editor instance
690
+ * @returns boolean indicating if the node exists in the schema
691
+ */
692
+ declare const isNodeInSchema: (nodeName: string, editor: Editor | null) => boolean;
693
+ /**
694
+ * Moves the focus to the next node in the editor
695
+ * @param editor - The editor instance
696
+ * @returns boolean indicating if the focus was moved
697
+ */
698
+ declare function focusNextNode(editor: Editor): boolean;
699
+ /**
700
+ * Checks if a value is a valid number (not null, undefined, or NaN)
701
+ * @param value - The value to check
702
+ * @returns boolean indicating if the value is a valid number
703
+ */
704
+ declare function isValidPosition(pos: number | null | undefined): pos is number;
705
+ /**
706
+ * Checks if one or more extensions are registered in the Tiptap editor.
707
+ * @param editor - The Tiptap editor instance
708
+ * @param extensionNames - A single extension name or an array of names to check
709
+ * @returns True if at least one of the extensions is available, false otherwise
710
+ */
711
+ declare function isExtensionAvailable(editor: Editor | null, extensionNames: string | string[]): boolean;
712
+ /**
713
+ * Finds a node at the specified position with error handling
714
+ * @param editor The Tiptap editor instance
715
+ * @param position The position in the document to find the node
716
+ * @returns The node at the specified position, or null if not found
717
+ */
718
+ declare function findNodeAtPosition(editor: Editor, position: number): Node | null;
719
+ /**
720
+ * Finds the position and instance of a node in the document
721
+ * @param props Object containing editor, node (optional), and nodePos (optional)
722
+ * @param props.editor The Tiptap editor instance
723
+ * @param props.node The node to find (optional if nodePos is provided)
724
+ * @param props.nodePos The position of the node to find (optional if node is provided)
725
+ * @returns An object with the position and node, or null if not found
726
+ */
727
+ declare function findNodePosition(props: {
728
+ editor: Editor | null;
729
+ node?: Node | null;
730
+ nodePos?: number | null;
731
+ }): {
732
+ pos: number;
733
+ node: Node;
734
+ } | null;
735
+ /**
736
+ * Determines whether the current selection contains a node whose type matches
737
+ * any of the provided node type names.
738
+ * @param editor Tiptap editor instance
739
+ * @param nodeTypeNames List of node type names to match against
740
+ * @param checkAncestorNodes Whether to check ancestor node types up the depth chain
741
+ */
742
+ declare function isNodeTypeSelected(editor: Editor | null, nodeTypeNames?: string[], checkAncestorNodes?: boolean): boolean;
743
+ /**
744
+ * Check whether the current selection is fully within nodes
745
+ * whose type names are in the provided `types` list.
746
+ *
747
+ * - NodeSelection → checks the selected node.
748
+ * - Text/AllSelection → ensures all textblocks within [from, to) are allowed.
749
+ */
750
+ declare function selectionWithinConvertibleTypes(editor: Editor, types?: string[]): boolean;
751
+ /**
752
+ * Handles image upload with progress tracking and abort capability
753
+ * @param file The file to upload
754
+ * @param onProgress Optional callback for tracking upload progress
755
+ * @param abortSignal Optional AbortSignal for cancelling the upload
756
+ * @returns Promise resolving to the URL of the uploaded image
757
+ */
758
+ declare const handleImageUpload: (file: File, onProgress?: (event: {
759
+ progress: number;
760
+ }) => void, abortSignal?: AbortSignal) => Promise<string>;
761
+ type ProtocolOptions = {
762
+ /**
763
+ * The protocol scheme to be registered.
764
+ * @default '''
765
+ * @example 'ftp'
766
+ * @example 'git'
767
+ */
768
+ scheme: string;
769
+ /**
770
+ * If enabled, it allows optional slashes after the protocol.
771
+ * @default false
772
+ * @example true
773
+ */
774
+ optionalSlashes?: boolean;
775
+ };
776
+ type ProtocolConfig = Array<ProtocolOptions | string>;
777
+ declare function isAllowedUri(uri: string | undefined, protocols?: ProtocolConfig): true | RegExpMatchArray | null;
778
+ declare function sanitizeUrl(inputUrl: string, baseUrl: string, protocols?: ProtocolConfig): string;
779
+ /**
780
+ * Update a single attribute on multiple nodes.
781
+ *
782
+ * @param tr - The transaction to mutate
783
+ * @param targets - Array of { node, pos }
784
+ * @param attrName - Attribute key to update
785
+ * @param next - New value OR updater function receiving previous value
786
+ * Pass `undefined` to remove the attribute.
787
+ * @returns true if at least one node was updated, false otherwise
788
+ */
789
+ declare function updateNodesAttr<A extends string = string, V = unknown>(tr: Transaction, targets: readonly NodeWithPos[], attrName: A, next: V | ((prev: V | undefined) => V | undefined)): boolean;
790
+ /**
791
+ * Selects the entire content of the current block node if the selection is empty.
792
+ * If the selection is not empty, it does nothing.
793
+ * @param editor The Tiptap editor instance
794
+ */
795
+ declare function selectCurrentBlockContent(editor: Editor): void;
796
+ /**
797
+ * Retrieves all nodes of specified types from the current selection.
798
+ * @param selection The current editor selection
799
+ * @param allowedNodeTypes An array of node type names to look for (e.g., ["image", "table"])
800
+ * @returns An array of objects containing the node and its position
801
+ */
802
+ declare function getSelectedNodesOfType(selection: Selection, allowedNodeTypes: string[]): NodeWithPos[];
803
+ /**
804
+ * Clamps a value between min and max bounds
805
+ */
806
+ declare function clamp(value: number, min: number, max: number): number;
807
+ declare function getSelectedBlockNodes(editor: Editor): Node[];
808
+
809
+ /**
810
+ * Helper function to check if there's content above the current position
811
+ */
812
+ declare function hasContentAbove(editor: Editor | null): {
813
+ hasContent: boolean;
814
+ content: string;
815
+ };
816
+ /**
817
+ * Finds the position of a node in the editor selection
818
+ * @param params Object containing editor, node (optional), and nodePos (optional)
819
+ * @returns The position of the node in the selection or null if not found
820
+ */
821
+ declare function findSelectionPosition(params: {
822
+ editor: Editor;
823
+ node?: Node | null;
824
+ nodePos?: number | null;
825
+ }): number | null;
826
+
827
+ type ButtonVariant = "ghost" | "primary";
828
+ type ButtonSize = "small" | "default" | "large";
829
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
830
+ showTooltip?: boolean;
831
+ tooltip?: React.ReactNode;
832
+ shortcutKeys?: string;
833
+ variant?: ButtonVariant;
834
+ size?: ButtonSize;
835
+ }
836
+ declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
837
+
838
+ type BaseProps = React.HTMLAttributes<HTMLDivElement>;
839
+ interface ToolbarProps extends BaseProps {
840
+ variant?: "floating" | "fixed";
841
+ }
842
+ declare const Toolbar: react.ForwardRefExoticComponent<ToolbarProps & react.RefAttributes<HTMLDivElement>>;
843
+ declare const ToolbarGroup: react.ForwardRefExoticComponent<BaseProps & react.RefAttributes<HTMLDivElement>>;
844
+ declare const ToolbarSeparator: react.ForwardRefExoticComponent<BaseProps & react.RefAttributes<HTMLDivElement>>;
845
+
846
+ declare function Popover({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Root>): react.JSX.Element;
847
+ declare function PopoverTrigger({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Trigger>): react.JSX.Element;
848
+ declare function PopoverContent({ className, align, sideOffset, ...props }: React.ComponentProps<typeof PopoverPrimitive.Content>): react.JSX.Element;
849
+
850
+ declare function DropdownMenu({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>): react.JSX.Element;
851
+ declare function DropdownMenuPortal({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>): react.JSX.Element;
852
+ declare function DropdownMenuTrigger({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>): react.JSX.Element;
853
+ declare function DropdownMenuContent({ className, align, sideOffset, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>): react.JSX.Element;
854
+ declare function DropdownMenuGroup({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>): react.JSX.Element;
855
+ declare function DropdownMenuItem({ className, inset, variant, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
856
+ inset?: boolean;
857
+ variant?: "default" | "destructive";
858
+ }): react.JSX.Element;
859
+ declare function DropdownMenuLabel({ className, inset, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
860
+ inset?: boolean;
861
+ }): react.JSX.Element;
862
+ declare function DropdownMenuSub({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>): react.JSX.Element;
863
+ declare function DropdownMenuSubTrigger({ className, inset, children, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
864
+ inset?: boolean;
865
+ }): react.JSX.Element;
866
+ declare function DropdownMenuSubContent({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>): react.JSX.Element;
867
+
868
+ type Orientation = "horizontal" | "vertical";
869
+ declare function Separator({ decorative, orientation, className, ...props }: React.ComponentProps<"div"> & {
870
+ orientation?: Orientation;
871
+ decorative?: boolean;
872
+ }): react.JSX.Element;
873
+
874
+ type SpacerOrientation = "horizontal" | "vertical";
875
+ declare function Spacer({ orientation, size, style, ...props }: React.ComponentProps<"div"> & {
876
+ orientation?: SpacerOrientation;
877
+ size?: string | number;
878
+ }): react.JSX.Element;
879
+
880
+ interface FloatingElementProps extends HTMLAttributes<HTMLDivElement> {
881
+ /**
882
+ * The Tiptap editor instance to attach to.
883
+ */
884
+ editor?: Editor | null;
885
+ /**
886
+ * Controls whether the floating element should be visible.
887
+ * @default undefined
888
+ */
889
+ shouldShow?: boolean;
890
+ /**
891
+ * Additional options to pass to the floating UI.
892
+ */
893
+ floatingOptions?: Partial<UseFloatingOptions>;
894
+ /**
895
+ * Z-index for the floating element.
896
+ * @default 50
897
+ */
898
+ zIndex?: number;
899
+ /**
900
+ * Callback fired when the visibility state changes.
901
+ */
902
+ onOpenChange?: (open: boolean) => void;
903
+ /**
904
+ * Reference element to position the floating element relative to.
905
+ * If provided, this takes precedence over getBoundingClientRect.
906
+ */
907
+ referenceElement?: HTMLElement | null;
908
+ /**
909
+ * Custom function to determine the position of the floating element.
910
+ * Only used if referenceElement is not provided.
911
+ * @default getSelectionBoundingRect
912
+ */
913
+ getBoundingClientRect?: (editor: Editor) => DOMRect | null;
914
+ /**
915
+ * Whether to close the floating element when Escape key is pressed.
916
+ * @default true
917
+ */
918
+ closeOnEscape?: boolean;
919
+ /**
920
+ * Whether to reset the text selection when the floating element is closed or clicked outside the editor.
921
+ * @default true
922
+ */
923
+ resetTextSelectionOnClose?: boolean;
924
+ }
925
+ /**
926
+ * A floating UI element that positions itself relative to the current selection in a Tiptap editor.
927
+ * Used for floating toolbars, menus, and other UI elements that need to appear near the text cursor.
928
+ */
929
+ declare const FloatingElement: react.ForwardRefExoticComponent<FloatingElementProps & react.RefAttributes<HTMLDivElement>>;
930
+
931
+ /**
932
+ * 编辑器整面的粘贴/拖拽多媒体接入。覆盖:
933
+ * 1. 粘贴文件(截图、复制本地图片/视频/任意文件)— `clipboardData.files`
934
+ * 2. 拖拽本地文件到正文 — `dataTransfer.files`
935
+ * 3. 拖拽外链图片到正文 — `dataTransfer.text/uri-list` + 后缀名命中
936
+ *
937
+ * 按 `file.type` 分发到对应 tiptap 节点:
938
+ * image/* → image,video/* → video,audio/* → audio,其它 → fileAttachment
939
+ *
940
+ * UX(统一占位流程,见 media-upload-placeholder-node):
941
+ * - 所有类型先插入 `mediaUploadPlaceholder` 占位节点显示进度(image/video 带 blob 预览,
942
+ * audio/file 显示卡片),上传完成后按 uploadId 替换为真实节点;失败移除占位 + onError;
943
+ * 点 ✕ 取消则 abort 上传并移除占位。
944
+ *
945
+ * 外链 rehost 仅对图片做(视频通常太大、防盗链多,转存价值低),仍走"乐观插入外链 +
946
+ * 按 src 回填 CDN"的旧路径(不经占位节点)。
947
+ */
948
+ type PasteDropMediaUploadFn = (file: File, onProgress?: (event: {
949
+ progress: number;
950
+ }) => void, abortSignal?: AbortSignal) => Promise<string>;
951
+ type PasteDropRehostProgressEvent = {
952
+ url: string;
953
+ phase: "downloading";
954
+ progress: number;
955
+ } | {
956
+ url: string;
957
+ phase: "uploading";
958
+ progress: number;
959
+ } | {
960
+ url: string;
961
+ phase: "done";
962
+ progress: 100;
963
+ };
964
+ interface PasteDropMediaOptions {
965
+ upload?: PasteDropMediaUploadFn;
966
+ /** 按媒体大类分别设置单文件大小上限(字节,0 = 不限制)。未配置走包内默认。 */
967
+ maxFileSizes?: Partial<Record<MediaKind, number>>;
968
+ /**
969
+ * 拖入外链图片时是否走 XHR → blob → onUpload 转存到自家 CDN。
970
+ * 默认 true。CORS 失败 / 超大 / 上传失败时回退为外链直接显示并触发 onError。
971
+ * 仅对图片 URL 生效。
972
+ */
973
+ rehostExternalUrls?: boolean;
974
+ onError?: (error: Error) => void;
975
+ /** 外链转存的全程进度(下载 / 上传 / 完成),按 url 聚合。 */
976
+ onRehostProgress?: (event: PasteDropRehostProgressEvent) => void;
977
+ }
978
+ /**
979
+ * 统一入口:插入进度占位 → 上传(带进度/取消)→ 成功替换为真实节点 / 失败移除 / 取消 abort。
980
+ * 同时被 plugin(paste/drop)和 addCommands(slash 菜单 / 工具栏)调用。
981
+ */
982
+ declare const runMediaUpload: (editor: Editor, file: File, insertPos: number, options: PasteDropMediaOptions) => void;
983
+ declare module "@tiptap/react" {
984
+ interface Commands<ReturnType> {
985
+ pasteDropMedia: {
986
+ /** slash 菜单 / 工具栏可调用:把 file 走跟 paste/drop 完全一样的流程插入到当前选区。 */
987
+ uploadMediaFile: (file: File) => ReturnType;
988
+ };
989
+ }
990
+ }
991
+ declare const PasteDropMedia: Extension$1<PasteDropMediaOptions, any>;
992
+
993
+ interface VideoOptions {
994
+ HTMLAttributes: Record<string, unknown>;
995
+ }
996
+ declare module "@tiptap/react" {
997
+ interface Commands<ReturnType> {
998
+ video: {
999
+ setVideo: (options: {
1000
+ src: string;
1001
+ title?: string;
1002
+ }) => ReturnType;
1003
+ };
1004
+ }
1005
+ }
1006
+ /**
1007
+ * 块级 atom:原生 <video controls> 播放器。
1008
+ * 不带自定义 NodeView,浏览器原生播放足够;将来要"自动播放/封面/字幕"再扩展。
1009
+ */
1010
+ declare const Video: Node$1<VideoOptions, any>;
1011
+
1012
+ interface AudioOptions {
1013
+ HTMLAttributes: Record<string, unknown>;
1014
+ }
1015
+ declare module "@tiptap/react" {
1016
+ interface Commands<ReturnType> {
1017
+ audio: {
1018
+ setAudio: (options: {
1019
+ src: string;
1020
+ title?: string;
1021
+ }) => ReturnType;
1022
+ };
1023
+ }
1024
+ }
1025
+ /**
1026
+ * 块级 atom:原生 <audio controls> 播放器。
1027
+ */
1028
+ declare const Audio: Node$1<AudioOptions, any>;
1029
+
1030
+ interface FileAttachmentOptions {
1031
+ HTMLAttributes: Record<string, unknown>;
1032
+ }
1033
+ interface FileAttachmentAttrs {
1034
+ src: string;
1035
+ name: string;
1036
+ size?: number;
1037
+ mimeType?: string;
1038
+ }
1039
+ declare module "@tiptap/react" {
1040
+ interface Commands<ReturnType> {
1041
+ fileAttachment: {
1042
+ setFileAttachment: (options: FileAttachmentAttrs) => ReturnType;
1043
+ };
1044
+ }
1045
+ }
1046
+ /**
1047
+ * 块级 atom:通用文件卡片(pdf / doc / zip 等)。
1048
+ * 序列化为 <a data-type="file-attachment" data-size data-mime href download>name</a>,
1049
+ * 没 NodeView 的环境(如纯阅读视图)也能显示成可点击链接。
1050
+ */
1051
+ declare const FileAttachment: Node$1<FileAttachmentOptions, any>;
1052
+
1053
+ /**
1054
+ * 临时占位节点:拖拽/粘贴上传过程中显示进度,上传完成由 runMediaUpload 替换为
1055
+ * 真实 image/video/audio/fileAttachment 节点。正常不会进入保存内容(保存前已替换)。
1056
+ */
1057
+ declare const MediaUploadPlaceholder: Node$1<any, any>;
1058
+
1059
+ type ColumnLayout = "column" | "sidebar-left" | "sidebar-right" | "three-column";
1060
+ declare module "@tiptap/react" {
1061
+ interface Commands<ReturnType> {
1062
+ columns: {
1063
+ /** 插入分栏:layout 决定列数(three-column→3,其余→2)与比例 */
1064
+ setColumns: (layout?: ColumnLayout) => ReturnType;
1065
+ /** 切换当前所在分栏的 layout(仅同列数档位间,带列数守卫) */
1066
+ setColumnsLayout: (layout: ColumnLayout) => ReturnType;
1067
+ /**
1068
+ * 解包分栏,列内容提升为普通块。
1069
+ * pos 给定时按该位置的 columns 节点解包(NodeView 用 getPos() 传入,
1070
+ * 不依赖选区);不给则回退到选区所在 columns。
1071
+ */
1072
+ unsetColumns: (pos?: number) => ReturnType;
1073
+ };
1074
+ }
1075
+ }
1076
+ declare const Column: Node$1<any, any>;
1077
+ declare const Columns: Node$1<any, any>;
1078
+
1079
+ type MediaKindForButton = "video" | "audio" | "file";
1080
+ interface MediaUploadButtonProps extends Omit<ButtonProps, "type"> {
1081
+ /** 决定 accept / icon / 目标节点 / aria-label */
1082
+ kind: MediaKindForButton;
1083
+ /** 编辑器实例;不传则走 useTiptapEditor 默认(EditorContext) */
1084
+ editor?: Editor | null;
1085
+ /** 按钮文本,不传只显示图标 */
1086
+ text?: string;
1087
+ /** 节点不在 schema 时是否隐藏(默认 false:始终显示但 disabled) */
1088
+ hideWhenUnavailable?: boolean;
1089
+ }
1090
+ /**
1091
+ * 工具栏 / 自定义 UI 用的"上传媒体"按钮。点击后打开原生文件选择器,
1092
+ * 选中的 File 通过 `editor.commands.uploadMediaFile(file)` 走 PasteDropMedia 的
1093
+ * 完整流程(size 校验 / 乐观插入 / message.error)。
1094
+ *
1095
+ * 注意:依赖 PasteDropMedia 扩展和对应目标节点(video / audio / fileAttachment)。
1096
+ */
1097
+ declare const MediaUploadButton: react.ForwardRefExoticComponent<MediaUploadButtonProps & react.RefAttributes<HTMLButtonElement>>;
1098
+
1099
+ /**
1100
+ * 程序触发原生文件选择器,返回选中的 File 数组。
1101
+ * 工具栏 / slash 菜单的"插入媒体"按钮共用,避免每个组件自己拼 input。
1102
+ *
1103
+ * 用户取消(按 ESC / 点关闭):现代浏览器派发 cancel 事件,老浏览器不发——
1104
+ * 没有 cancel 事件的浏览器会留一个隐藏 input 在 body,由 GC 兜底回收。
1105
+ */
1106
+ declare function pickFile(accept: string, multiple?: boolean): Promise<File[]>;
1107
+
1108
+ export { ArticleViewer, type ArticleViewerProps, Audio, Button, type ButtonProps, CollabContext, type CollabContextValue, CollabProvider, Column, type ColumnLayout, Columns, DEFAULT_MAX_FILE_SIZES, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type EditorCollabConfig, type EditorConfig, EditorConfigProvider, type EditorConfigProviderProps, EditorContentArea, type EditorProviderProps, type EditorUploadConfig, type EditorUserConfig, FileAttachment, type FileAttachmentAttrs, FloatingElement, HIDE_FLOATING_META, LoadingSpinner, MAC_SYMBOLS, MAX_FILE_SIZE, type MediaKind, type MediaKindForButton, MediaUploadButton, type MediaUploadButtonProps, MediaUploadPlaceholder, NotionEditor, NotionEditorContent, EditorProvider as NotionEditorInner, type NotionEditorProps, type OverflowPosition, PasteDropMedia, type PasteDropMediaOptions, type PasteDropMediaUploadFn, type PasteDropRehostProgressEvent, Popover, PopoverContent, PopoverTrigger, type RehostProgressEvent, SR_ONLY, Separator, Spacer, Toolbar, ToolbarGroup, ToolbarSeparator, UiState, UiState as UiStateType, type User, UserContext, type UserContextValue, UserProvider, Video, clamp, cn, defaultUiState, detectMediaKind, findNodeAtPosition, findNodePosition, findSelectionPosition, focusNextNode, formatShortcutKey, getAvatar, getElementOverflowPosition, getNodeDisplayName, getSelectedBlockNodes, getSelectedNodesOfType, getSelectionBoundingRect, getUrlParam, handleImageUpload, hasContentAbove, isAllowedUri, isExtensionAvailable, isMac, isMarkInSchema, isNodeInSchema, isNodeTypeSelected, isSelectionValid, isTextSelectionValid, isValidPosition, markHideFloatingOnNext, parseShortcutKeys, pickFile, removeEmptyParagraphs, resolveMaxSize, runMediaUpload, sanitizeUrl, selectCurrentBlockContent, selectNodeAndHideFloating, selectionWithinConvertibleTypes, updateNodesAttr, useCollab, useCollaboration, useComposedRef, useCursorVisibility, useEditorConfig, useElementRect, useFloatingElement, useFloatingToolbarVisibility, useIsBreakpoint, useIsomorphicLayoutEffect, useMenuNavigation, useOnClickOutside, useScrolling, useThrottledCallback, useTiptapEditor, useUiEditorState, useUiEditorState as useUiEditorStateDefault, useUnmount, useUser, useWindowSize };