tiptop-editor 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -2
- package/dist/components/editor/TableSelectionMenu.d.ts +1 -1
- package/dist/components/editor/TiptopEditor.stories.d.ts +1 -0
- package/dist/components/editor/TiptopEditorContext.d.ts +3 -0
- package/dist/components/editor/createDefaultExtensions.d.ts +8 -0
- package/dist/components/editor/renderTiptopSlot.d.ts +4 -0
- package/dist/components/editor/useDuplicateExtensionWarnings.d.ts +2 -0
- package/dist/helpers.d.ts +29 -1
- package/dist/index.d.ts +2 -0
- package/dist/tiptop-editor.es.js +3098 -2938
- package/dist/tiptop-editor.umd.js +18 -18
- package/dist/types.d.ts +96 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ export function Editor() {
|
|
|
43
43
|
}
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
`editorOptions` accepts the same options as `useEditor` from `@tiptap/react`, except `extensions`, which is managed internally by the package.
|
|
46
|
+
`editorOptions` accepts the same options as `useEditor` from `@tiptap/react`, except `extensions`, which is managed internally by the package. To add your own extensions, use `editorOptions.extraExtensions`.
|
|
47
47
|
|
|
48
48
|
## Editor Ref and Events
|
|
49
49
|
|
|
@@ -79,6 +79,99 @@ Available ref methods:
|
|
|
79
79
|
- `off(event, callback?)`
|
|
80
80
|
- `once(event, callback)`
|
|
81
81
|
|
|
82
|
+
## Extending the Editor
|
|
83
|
+
|
|
84
|
+
The package now supports two extension points:
|
|
85
|
+
|
|
86
|
+
- `editorOptions.extraExtensions`
|
|
87
|
+
Appends custom Tiptap extensions after the built-in set.
|
|
88
|
+
- `slots`
|
|
89
|
+
Lets you inject custom React UI around the editor and inside the selection menus.
|
|
90
|
+
|
|
91
|
+
### Add custom Tiptap extensions
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import { Extension } from '@tiptap/core'
|
|
95
|
+
import { TiptopEditor } from 'tiptop-editor'
|
|
96
|
+
|
|
97
|
+
const MyExtension = Extension.create({
|
|
98
|
+
name: 'myExtension',
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
export function EditorWithExtraExtensions() {
|
|
102
|
+
return (
|
|
103
|
+
<TiptopEditor
|
|
104
|
+
editorOptions={{
|
|
105
|
+
immediatelyRender: false,
|
|
106
|
+
extraExtensions: [MyExtension],
|
|
107
|
+
}}
|
|
108
|
+
/>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`extraExtensions` is additive only. If you pass an extension with the same name as one of the built-in extensions, the editor will warn in the console and show a toast because duplicate extension names can lead to unstable behavior.
|
|
114
|
+
|
|
115
|
+
### Add custom UI with slots
|
|
116
|
+
|
|
117
|
+
Supported slots:
|
|
118
|
+
|
|
119
|
+
- `editorTop`
|
|
120
|
+
- `editorBottom`
|
|
121
|
+
- `selectionMenuPrepend`
|
|
122
|
+
- `selectionMenuAppend`
|
|
123
|
+
- `tableMenuPrepend`
|
|
124
|
+
- `tableMenuAppend`
|
|
125
|
+
|
|
126
|
+
Each slot accepts either:
|
|
127
|
+
|
|
128
|
+
- a React node
|
|
129
|
+
- a render function receiving `{ editor }`
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
<TiptopEditor
|
|
133
|
+
slots={{
|
|
134
|
+
editorTop: ({ editor }) => (
|
|
135
|
+
<button onClick={() => editor.chain().focus().insertContent('<p>Draft</p>').run()}>
|
|
136
|
+
Insert draft
|
|
137
|
+
</button>
|
|
138
|
+
),
|
|
139
|
+
}}
|
|
140
|
+
/>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Use the editor context hook
|
|
144
|
+
|
|
145
|
+
For slotted components, you can consume the current editor instance through `useTiptopEditor()` instead of passing `editor` down manually.
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
import { TiptopEditor, useTiptopEditor } from 'tiptop-editor'
|
|
149
|
+
|
|
150
|
+
function AiToolbar() {
|
|
151
|
+
const editor = useTiptopEditor()
|
|
152
|
+
|
|
153
|
+
if (!editor) {
|
|
154
|
+
return null
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<button onClick={() => editor.chain().focus().insertContent('<p>AI draft</p>').run()}>
|
|
159
|
+
Insert draft
|
|
160
|
+
</button>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function EditorWithSlots() {
|
|
165
|
+
return (
|
|
166
|
+
<TiptopEditor
|
|
167
|
+
slots={{
|
|
168
|
+
editorTop: <AiToolbar />,
|
|
169
|
+
}}
|
|
170
|
+
/>
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
82
175
|
## Custom Editor UI Options
|
|
83
176
|
|
|
84
177
|
`TiptopEditor` also supports a few package-specific options inside `editorOptions`:
|
|
@@ -97,6 +190,8 @@ Available ref methods:
|
|
|
97
190
|
Disables the default HeroUI `Card` wrapper and removes the editor's built-in padding. Use this when you want the editor to live inside your own container/layout.
|
|
98
191
|
- `showDragHandle`
|
|
99
192
|
Controls whether the block drag handle is rendered. Default: `true`.
|
|
193
|
+
- `extraExtensions`
|
|
194
|
+
Appends custom Tiptap extensions after the built-in editor set.
|
|
100
195
|
|
|
101
196
|
## Built-in Extensions
|
|
102
197
|
|
|
@@ -242,7 +337,7 @@ Example:
|
|
|
242
337
|
## Notes
|
|
243
338
|
|
|
244
339
|
- If you use SSR, keep `immediatelyRender: false`.
|
|
245
|
-
- The package manages the editor extensions internally
|
|
340
|
+
- The package manages the built-in editor extensions internally. Use `editorOptions.extraExtensions` to append your own feature extensions.
|
|
246
341
|
|
|
247
342
|
## Feedback
|
|
248
343
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { TextSelectionMenuProps } from '../../types';
|
|
3
|
-
declare const _default: React.MemoExoticComponent<({ editor }: TextSelectionMenuProps) => import("react/jsx-runtime").JSX.Element>;
|
|
3
|
+
declare const _default: React.MemoExoticComponent<({ editor, prepend, append }: TextSelectionMenuProps) => import("react/jsx-runtime").JSX.Element>;
|
|
4
4
|
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Extensions } from '@tiptap/core';
|
|
2
|
+
import { ImageUploadResponseResolver } from '../../types';
|
|
3
|
+
interface CreateDefaultExtensionsOptions {
|
|
4
|
+
imgUploadUrl?: string;
|
|
5
|
+
imgUploadResponseKey?: ImageUploadResponseResolver;
|
|
6
|
+
}
|
|
7
|
+
export declare const createDefaultExtensions: ({ imgUploadUrl, imgUploadResponseKey, }: CreateDefaultExtensionsOptions) => Extensions;
|
|
8
|
+
export {};
|
package/dist/helpers.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Editor } from '@tiptap/core';
|
|
2
2
|
import { EditorState } from '@tiptap/pm/state';
|
|
3
|
-
import { SlashCommandGroupCommandsProps } from './types';
|
|
3
|
+
import { DocumentMap, SlashCommandGroupCommandsProps, TargetedUpdate } from './types';
|
|
4
4
|
import { Node } from '@tiptap/pm/model';
|
|
5
5
|
export declare const isTextSelected: (editor: Editor) => boolean;
|
|
6
6
|
export declare const hasTextNodeInSelection: (editor: Editor) => boolean;
|
|
@@ -38,3 +38,31 @@ export declare const getUploaderAtPos: (state: Editor["state"], pos: number) =>
|
|
|
38
38
|
depth: number;
|
|
39
39
|
node: Node;
|
|
40
40
|
} | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Returns a structured snapshot of every top-level block in the editor.
|
|
43
|
+
* Send this to your AI model so it can reference nodes and words by index.
|
|
44
|
+
*/
|
|
45
|
+
export declare const getDocumentMap: (editor: Editor) => DocumentMap;
|
|
46
|
+
/**
|
|
47
|
+
* Applies a single targeted content update.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // Translate the first word of the second paragraph
|
|
51
|
+
* applyTargetedUpdate(editor, { nodeIndex: 1, wordIndex: 0, replacement: 'Bonjour' })
|
|
52
|
+
*/
|
|
53
|
+
export declare const applyTargetedUpdate: (editor: Editor, update: TargetedUpdate) => boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Applies multiple targeted updates in a single atomic ProseMirror transaction.
|
|
56
|
+
*
|
|
57
|
+
* All positions are resolved against the document state *before* any mutations,
|
|
58
|
+
* then applied from the bottom of the document upward so that earlier replacements
|
|
59
|
+
* never shift the absolute positions of later ones.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Bold-ify two specific words in one go
|
|
63
|
+
* applyTargetedUpdates(editor, [
|
|
64
|
+
* { nodeIndex: 0, wordIndex: 2, replacement: [{ type: 'text', text: 'foo', marks: [{ type: 'bold' }] }] },
|
|
65
|
+
* { nodeIndex: 2, wordRange: [0, 1], replacement: 'Hello world' },
|
|
66
|
+
* ])
|
|
67
|
+
*/
|
|
68
|
+
export declare const applyTargetedUpdates: (editor: Editor, updates: TargetedUpdate[]) => boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { default as TiptopEditor } from './components/editor/TiptopEditor';
|
|
2
|
+
export { TiptopEditorContext, useTiptopEditor } from './components/editor/TiptopEditorContext';
|
|
3
|
+
export { getDocumentMap, applyTargetedUpdate, applyTargetedUpdates } from './helpers';
|
|
2
4
|
export * from './types';
|