@platejs/ai 52.3.10 → 52.3.12

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.
@@ -0,0 +1,235 @@
1
+ import { ElementApi, KEYS, TextApi, bindFirst, createTSlatePlugin, getPluginType } from "platejs";
2
+ import cloneDeep from "lodash/cloneDeep.js";
3
+ import { getTransientSuggestionKey } from "@platejs/suggestion";
4
+ import { isSelecting } from "@platejs/selection";
5
+
6
+ //#region src/lib/transforms/aiStreamSnapshot.ts
7
+ const AI_PREVIEW_KEY = "aiPreview";
8
+ const AI_STREAM_SNAPSHOT = /* @__PURE__ */ new WeakMap();
9
+ const clearAIPreview = (editor) => {
10
+ AI_STREAM_SNAPSHOT.delete(editor);
11
+ };
12
+ const getAIPreview = (editor) => AI_STREAM_SNAPSHOT.get(editor);
13
+ const getAIPreviewRange = (editor) => {
14
+ let closed = false;
15
+ let end = -1;
16
+ let invalid = false;
17
+ let start = -1;
18
+ editor.children.forEach((node, index) => {
19
+ if (!node?.[AI_PREVIEW_KEY]) {
20
+ if (start !== -1) closed = true;
21
+ return;
22
+ }
23
+ if (closed) {
24
+ invalid = true;
25
+ return;
26
+ }
27
+ if (start === -1) start = index;
28
+ end = index;
29
+ });
30
+ if (invalid) return { kind: "invalid" };
31
+ if (start === -1 && end === -1) return { kind: "none" };
32
+ return {
33
+ end,
34
+ kind: "range",
35
+ start
36
+ };
37
+ };
38
+ const removeAIPreviewAnchor = (editor) => {
39
+ const aiChatType = getPluginType(editor, KEYS.aiChat);
40
+ editor.tf.removeNodes({
41
+ at: [],
42
+ match: (node) => ElementApi.isElement(node) && node.type === aiChatType
43
+ });
44
+ };
45
+ const restoreAIPreviewSelection = (editor, selection) => {
46
+ if (selection) {
47
+ editor.tf.select(cloneDeep(selection));
48
+ return;
49
+ }
50
+ editor.tf.deselect();
51
+ };
52
+ const removePreviewRange = (editor, range) => {
53
+ for (let index = range.end; index >= range.start; index--) editor.tf.removeNodes({ at: [index] });
54
+ };
55
+ const replacePreviewRange = (editor, range, blocks) => {
56
+ removePreviewRange(editor, range);
57
+ if (blocks.length === 0) return;
58
+ editor.tf.insertNodes(cloneDeep(blocks), { at: [range.start] });
59
+ };
60
+ const cloneAcceptedPreviewBlocks = (editor, range) => {
61
+ const aiType = getPluginType(editor, KEYS.ai);
62
+ const blocks = cloneDeep(editor.children.slice(range.start, range.end + 1));
63
+ const stripNode = (node) => {
64
+ if (ElementApi.isElement(node)) {
65
+ const { [AI_PREVIEW_KEY]: _preview, children, ...rest$1 } = node;
66
+ return {
67
+ ...rest$1,
68
+ children: children.map(stripNode)
69
+ };
70
+ }
71
+ const { [aiType]: _ai, ...rest } = node;
72
+ return rest;
73
+ };
74
+ return blocks.map(stripNode);
75
+ };
76
+ const beginAIPreview = (editor, { originalBlocks = [] } = {}) => {
77
+ if (getAIPreview(editor)) return false;
78
+ AI_STREAM_SNAPSHOT.set(editor, {
79
+ originalBlocks: cloneDeep(originalBlocks),
80
+ selectionBefore: cloneDeep(editor.selection)
81
+ });
82
+ return true;
83
+ };
84
+ const hasAIPreview = (editor) => !!getAIPreview(editor);
85
+ const cancelAIPreview = (editor) => {
86
+ const preview = getAIPreview(editor);
87
+ if (!preview) return false;
88
+ const range = getAIPreviewRange(editor);
89
+ if (range.kind === "invalid") return false;
90
+ editor.tf.withoutSaving(() => {
91
+ if (range.kind === "range") replacePreviewRange(editor, range, preview.originalBlocks);
92
+ removeAIPreviewAnchor(editor);
93
+ restoreAIPreviewSelection(editor, preview.selectionBefore);
94
+ });
95
+ clearAIPreview(editor);
96
+ return true;
97
+ };
98
+ const discardAIPreview = (editor) => {
99
+ if (!getAIPreview(editor)) return false;
100
+ clearAIPreview(editor);
101
+ return true;
102
+ };
103
+ const acceptAIPreview = (editor, _value) => {
104
+ const preview = getAIPreview(editor);
105
+ if (!preview) return false;
106
+ const range = getAIPreviewRange(editor);
107
+ if (range.kind === "invalid") return false;
108
+ if (range.kind === "range") {
109
+ const acceptedBlocks = cloneAcceptedPreviewBlocks(editor, range);
110
+ editor.tf.withoutSaving(() => {
111
+ replacePreviewRange(editor, range, preview.originalBlocks);
112
+ removeAIPreviewAnchor(editor);
113
+ restoreAIPreviewSelection(editor, preview.selectionBefore);
114
+ });
115
+ editor.tf.withNewBatch(() => {
116
+ if (preview.originalBlocks.length > 0) for (let index = preview.originalBlocks.length - 1; index >= 0; index--) editor.tf.removeNodes({ at: [range.start + index] });
117
+ if (acceptedBlocks.length > 0) editor.tf.insertNodes(acceptedBlocks, { at: [range.start] });
118
+ });
119
+ const lastBatch = editor.history?.undos.at(-1);
120
+ if (lastBatch) lastBatch.selectionBefore = cloneDeep(preview.selectionBefore);
121
+ } else editor.tf.withoutSaving(() => {
122
+ removeAIPreviewAnchor(editor);
123
+ });
124
+ clearAIPreview(editor);
125
+ return true;
126
+ };
127
+
128
+ //#endregion
129
+ //#region src/lib/transforms/insertAINodes.ts
130
+ const insertAINodes = (editor, nodes, { target } = {}) => {
131
+ if (!target && !editor.selection?.focus.path) return;
132
+ const aiNodes = nodes.map((node) => ({
133
+ ...node,
134
+ ai: true
135
+ }));
136
+ editor.tf.withoutNormalizing(() => {
137
+ editor.tf.insertNodes(aiNodes, {
138
+ at: editor.api.end(target || editor.selection.focus.path),
139
+ select: true
140
+ });
141
+ editor.tf.collapse({ edge: "end" });
142
+ });
143
+ };
144
+
145
+ //#endregion
146
+ //#region src/lib/transforms/removeAIMarks.ts
147
+ const removeAIMarks = (editor, { at = [] } = {}) => {
148
+ const nodeType = getPluginType(editor, KEYS.ai);
149
+ editor.tf.unsetNodes(nodeType, {
150
+ at,
151
+ match: (n) => n[nodeType]
152
+ });
153
+ };
154
+
155
+ //#endregion
156
+ //#region src/lib/transforms/removeAINodes.ts
157
+ const removeAINodes = (editor, { at = [] } = {}) => {
158
+ editor.tf.removeNodes({
159
+ at,
160
+ match: (n) => TextApi.isText(n) && !!n.ai
161
+ });
162
+ };
163
+
164
+ //#endregion
165
+ //#region src/lib/transforms/undoAI.ts
166
+ const undoAI = (editor) => {
167
+ if (hasAIPreview(editor) && cancelAIPreview(editor)) return;
168
+ const hasAINodeOrAISuggestion = editor.api.some({
169
+ at: [],
170
+ match: (n) => !!n.ai
171
+ }) || editor.api.some({
172
+ at: [],
173
+ match: (n) => !!n[getTransientSuggestionKey()]
174
+ });
175
+ if (editor.history.undos.at(-1)?.ai && hasAINodeOrAISuggestion) {
176
+ editor.undo();
177
+ editor.history.redos.pop();
178
+ return;
179
+ }
180
+ if (hasAINodeOrAISuggestion) cancelAIPreview(editor);
181
+ };
182
+
183
+ //#endregion
184
+ //#region src/lib/transforms/withAIBatch.ts
185
+ const withAIBatch = (editor, fn, { split } = {}) => {
186
+ if (split) editor.tf.withNewBatch(fn);
187
+ else editor.tf.withMerging(fn);
188
+ const lastBatch = editor.history.undos?.at(-1);
189
+ if (lastBatch) lastBatch.ai = true;
190
+ };
191
+
192
+ //#endregion
193
+ //#region src/lib/BaseAIPlugin.ts
194
+ const getAITransforms = (editor) => ({
195
+ acceptPreview: bindFirst(acceptAIPreview, editor),
196
+ beginPreview: bindFirst(beginAIPreview, editor),
197
+ cancelPreview: bindFirst(cancelAIPreview, editor),
198
+ discardPreview: bindFirst(discardAIPreview, editor),
199
+ hasPreview: bindFirst(hasAIPreview, editor),
200
+ insertNodes: bindFirst(insertAINodes, editor),
201
+ removeMarks: bindFirst(removeAIMarks, editor),
202
+ removeNodes: bindFirst(removeAINodes, editor),
203
+ undo: bindFirst(undoAI, editor)
204
+ });
205
+ const BaseAIPlugin = createTSlatePlugin({
206
+ key: KEYS.ai,
207
+ node: {
208
+ isDecoration: false,
209
+ isLeaf: true
210
+ }
211
+ }).extendTransforms(({ editor }) => getAITransforms(editor)).extendEditorTransforms(({ editor }) => ({ ai: getAITransforms(editor) }));
212
+
213
+ //#endregion
214
+ //#region src/lib/utils/getEditorPrompt.ts
215
+ const createPromptFromConfig = (config, params) => {
216
+ const { isBlockSelecting, isSelecting: isSelecting$1 } = params;
217
+ if (isBlockSelecting && config.blockSelecting) return config.blockSelecting ?? config.default;
218
+ if (isSelecting$1 && config.selecting) return config.selecting ?? config.default;
219
+ return config.default;
220
+ };
221
+ const getEditorPrompt = (editor, { prompt = "" }) => {
222
+ const params = {
223
+ editor,
224
+ isBlockSelecting: editor.getOption({ key: KEYS.blockSelection }, "isSelectingSome"),
225
+ isSelecting: isSelecting(editor)
226
+ };
227
+ let promptText = "";
228
+ if (typeof prompt === "function") promptText = prompt(params);
229
+ else if (typeof prompt === "object") promptText = createPromptFromConfig(prompt, params);
230
+ else promptText = prompt;
231
+ return promptText;
232
+ };
233
+
234
+ //#endregion
235
+ export { removeAINodes as a, AI_PREVIEW_KEY as c, cancelAIPreview as d, discardAIPreview as f, undoAI as i, acceptAIPreview as l, BaseAIPlugin as n, removeAIMarks as o, hasAIPreview as p, withAIBatch as r, insertAINodes as s, getEditorPrompt as t, beginAIPreview as u };
@@ -0,0 +1,137 @@
1
+ import * as platejs0 from "platejs";
2
+ import { Descendant, History, OmitFirst, Path, PluginConfig, SlateEditor, TLocation, Value } from "platejs";
3
+
4
+ //#region src/lib/transforms/aiStreamSnapshot.d.ts
5
+ type BeginAIPreviewOptions = {
6
+ originalBlocks?: Value;
7
+ };
8
+ declare const AI_PREVIEW_KEY = "aiPreview";
9
+ declare const beginAIPreview: (editor: SlateEditor, {
10
+ originalBlocks
11
+ }?: BeginAIPreviewOptions) => boolean;
12
+ declare const hasAIPreview: (editor: SlateEditor) => boolean;
13
+ declare const cancelAIPreview: (editor: SlateEditor) => boolean;
14
+ declare const discardAIPreview: (editor: SlateEditor) => boolean;
15
+ declare const acceptAIPreview: (editor: SlateEditor, _value?: Value) => boolean;
16
+ //#endregion
17
+ //#region src/lib/transforms/insertAINodes.d.ts
18
+ declare const insertAINodes: (editor: SlateEditor, nodes: Descendant[], {
19
+ target
20
+ }?: {
21
+ target?: Path;
22
+ }) => void;
23
+ //#endregion
24
+ //#region src/lib/transforms/removeAIMarks.d.ts
25
+ declare const removeAIMarks: (editor: SlateEditor, {
26
+ at
27
+ }?: {
28
+ at?: TLocation;
29
+ }) => void;
30
+ //#endregion
31
+ //#region src/lib/transforms/removeAINodes.d.ts
32
+ declare const removeAINodes: (editor: SlateEditor, {
33
+ at
34
+ }?: {
35
+ at?: Path;
36
+ }) => void;
37
+ //#endregion
38
+ //#region src/lib/transforms/undoAI.d.ts
39
+ declare const undoAI: (editor: SlateEditor) => void;
40
+ //#endregion
41
+ //#region src/lib/transforms/withAIBatch.d.ts
42
+ type AIBatch = History['undos'][number] & {
43
+ ai?: boolean;
44
+ };
45
+ declare const withAIBatch: (editor: SlateEditor, fn: () => void, {
46
+ split
47
+ }?: {
48
+ split?: boolean;
49
+ }) => void;
50
+ //#endregion
51
+ //#region src/lib/BaseAIPlugin.d.ts
52
+ type BaseAIPluginConfig = PluginConfig<'ai', {}, {}, {
53
+ ai: {
54
+ /** Commit the active preview as one fresh undoable batch. */
55
+ acceptPreview: OmitFirst<typeof acceptAIPreview>;
56
+ /** Capture the rollback slice and selection for AI preview. */
57
+ beginPreview: OmitFirst<typeof beginAIPreview>;
58
+ /** Restore the rollback point and clear active preview state. */
59
+ cancelPreview: OmitFirst<typeof cancelAIPreview>;
60
+ /** Clear active preview bookkeeping without restoring content. */
61
+ discardPreview: OmitFirst<typeof discardAIPreview>;
62
+ /** Report whether an AI preview rollback point is active. */
63
+ hasPreview: OmitFirst<typeof hasAIPreview>;
64
+ insertNodes: OmitFirst<typeof insertAINodes>;
65
+ removeMarks: OmitFirst<typeof removeAIMarks>;
66
+ removeNodes: OmitFirst<typeof removeAINodes>;
67
+ undo: OmitFirst<typeof undoAI>;
68
+ };
69
+ }>;
70
+ declare const BaseAIPlugin: platejs0.SlatePlugin<PluginConfig<"ai", {}, {}, {
71
+ ai: {
72
+ acceptPreview: ((_value?: platejs0.Value | undefined) => boolean) & ((_value?: platejs0.Value | undefined) => boolean);
73
+ beginPreview: ((args_0?: {
74
+ originalBlocks?: platejs0.Value;
75
+ } | undefined) => boolean) & ((args_0?: {
76
+ originalBlocks?: platejs0.Value;
77
+ } | undefined) => boolean);
78
+ cancelPreview: (() => boolean) & (() => boolean);
79
+ discardPreview: (() => boolean) & (() => boolean);
80
+ hasPreview: (() => boolean) & (() => boolean);
81
+ insertNodes: ((nodes: platejs0.Descendant[], args_1?: {
82
+ target?: platejs0.Path;
83
+ } | undefined) => void) & ((nodes: platejs0.Descendant[], args_1?: {
84
+ target?: platejs0.Path;
85
+ } | undefined) => void);
86
+ removeMarks: ((args_0?: {
87
+ at?: platejs0.TLocation;
88
+ } | undefined) => void) & ((args_0?: {
89
+ at?: platejs0.TLocation;
90
+ } | undefined) => void);
91
+ removeNodes: ((args_0?: {
92
+ at?: platejs0.Path;
93
+ } | undefined) => void) & ((args_0?: {
94
+ at?: platejs0.Path;
95
+ } | undefined) => void);
96
+ undo: (() => void) & (() => void);
97
+ };
98
+ }, {}>>;
99
+ //#endregion
100
+ //#region src/lib/types.d.ts
101
+ type AIToolName = 'comment' | 'edit' | 'generate' | null;
102
+ type AIMode = 'chat' | 'insert';
103
+ //#endregion
104
+ //#region src/lib/utils/getEditorPrompt.d.ts
105
+ type EditorPrompt = ((params: EditorPromptParams) => string) | PromptConfig | string;
106
+ type EditorPromptParams = {
107
+ editor: SlateEditor;
108
+ isBlockSelecting: boolean;
109
+ isSelecting: boolean;
110
+ };
111
+ type PromptConfig = {
112
+ default: string;
113
+ blockSelecting?: string;
114
+ selecting?: string;
115
+ };
116
+ declare const getEditorPrompt: (editor: SlateEditor, {
117
+ prompt
118
+ }: {
119
+ prompt?: EditorPrompt;
120
+ }) => string;
121
+ //#endregion
122
+ //#region src/lib/utils/replacePlaceholders.d.ts
123
+ type MarkdownType = 'block' | 'blockSelection' | 'blockSelectionWithBlockId' | 'blockWithBlockId' | 'editor' | 'editorWithBlockId' | 'tableCellWithId';
124
+ declare const replacePlaceholders: (editor: SlateEditor, text: string, {
125
+ prompt
126
+ }?: {
127
+ prompt?: string;
128
+ }) => string;
129
+ //#endregion
130
+ //#region src/lib/utils/getMarkdown.d.ts
131
+ declare const getMarkdown: (editor: SlateEditor, {
132
+ type
133
+ }: {
134
+ type: MarkdownType;
135
+ }) => string;
136
+ //#endregion
137
+ export { hasAIPreview as C, discardAIPreview as S, insertAINodes as _, EditorPromptParams as a, beginAIPreview as b, AIMode as c, BaseAIPluginConfig as d, AIBatch as f, removeAIMarks as g, removeAINodes as h, EditorPrompt as i, AIToolName as l, undoAI as m, MarkdownType as n, PromptConfig as o, withAIBatch as p, replacePlaceholders as r, getEditorPrompt as s, getMarkdown as t, BaseAIPlugin as u, AI_PREVIEW_KEY as v, cancelAIPreview as x, acceptAIPreview as y };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as insertAINodes, a as EditorPromptParams, c as AIMode, d as BaseAIPluginConfig, f as AIBatch, g as removeAIMarks, h as removeAINodes, i as EditorPrompt, l as AIToolName, m as undoAI, n as MarkdownType, o as PromptConfig, p as withAIBatch, r as replacePlaceholders, s as getEditorPrompt, t as getMarkdown, u as BaseAIPlugin } from "./index-Dyi5V2wm";
2
- export { AIBatch, AIMode, AIToolName, BaseAIPlugin, BaseAIPluginConfig, EditorPrompt, EditorPromptParams, MarkdownType, PromptConfig, getEditorPrompt, getMarkdown, insertAINodes, removeAIMarks, removeAINodes, replacePlaceholders, undoAI, withAIBatch };
1
+ import { C as hasAIPreview, S as discardAIPreview, _ as insertAINodes, a as EditorPromptParams, b as beginAIPreview, c as AIMode, d as BaseAIPluginConfig, f as AIBatch, g as removeAIMarks, h as removeAINodes, i as EditorPrompt, l as AIToolName, m as undoAI, n as MarkdownType, o as PromptConfig, p as withAIBatch, r as replacePlaceholders, s as getEditorPrompt, t as getMarkdown, u as BaseAIPlugin, v as AI_PREVIEW_KEY, x as cancelAIPreview, y as acceptAIPreview } from "./index-D2hJDomP";
2
+ export { AIBatch, AIMode, AIToolName, AI_PREVIEW_KEY, BaseAIPlugin, BaseAIPluginConfig, EditorPrompt, EditorPromptParams, MarkdownType, PromptConfig, acceptAIPreview, beginAIPreview, cancelAIPreview, discardAIPreview, getEditorPrompt, getMarkdown, hasAIPreview, insertAINodes, removeAIMarks, removeAINodes, replacePlaceholders, undoAI, withAIBatch };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as removeAINodes, i as undoAI, n as BaseAIPlugin, o as removeAIMarks, r as withAIBatch, s as insertAINodes, t as getEditorPrompt } from "./getEditorPrompt-BnVrgUl3.js";
1
+ import { a as removeAINodes, c as AI_PREVIEW_KEY, d as cancelAIPreview, f as discardAIPreview, i as undoAI, l as acceptAIPreview, n as BaseAIPlugin, o as removeAIMarks, p as hasAIPreview, r as withAIBatch, s as insertAINodes, t as getEditorPrompt, u as beginAIPreview } from "./getEditorPrompt-axDm9Fg4.js";
2
2
  import { KEYS } from "platejs";
3
3
  import { serializeMd } from "@platejs/markdown";
4
4
  import { getTableGridAbove } from "@platejs/table";
@@ -121,4 +121,4 @@ const replacePlaceholders = (editor, text, { prompt } = {}) => {
121
121
  };
122
122
 
123
123
  //#endregion
124
- export { BaseAIPlugin, getEditorPrompt, getMarkdown, insertAINodes, removeAIMarks, removeAINodes, replacePlaceholders, undoAI, withAIBatch };
124
+ export { AI_PREVIEW_KEY, BaseAIPlugin, acceptAIPreview, beginAIPreview, cancelAIPreview, discardAIPreview, getEditorPrompt, getMarkdown, hasAIPreview, insertAINodes, removeAIMarks, removeAINodes, replacePlaceholders, undoAI, withAIBatch };
@@ -1,5 +1,5 @@
1
- import { c as AIMode, d as BaseAIPluginConfig, i as EditorPrompt, l as AIToolName } from "../index-Dyi5V2wm";
2
- import * as platejs0 from "platejs";
1
+ import { c as AIMode, d as BaseAIPluginConfig, i as EditorPrompt, l as AIToolName } from "../index-D2hJDomP";
2
+ import * as platejs12 from "platejs";
3
3
  import { Descendant, EditorNodesOptions, ExtendConfig, NodeEntry, OmitFirst, Path, PluginConfig, Range, RemoveNodesOptions, SlateEditor, TElement, TIdElement, TRange, TTableElement, TText } from "platejs";
4
4
  import { DeserializeMdOptions, SerializeMdOptions } from "@platejs/markdown";
5
5
  import * as platejs_react0 from "platejs/react";
@@ -11,18 +11,35 @@ import { TriggerComboboxPluginOptions } from "@platejs/combobox";
11
11
 
12
12
  //#region src/react/ai/AIPlugin.d.ts
13
13
  type AIPluginConfig = ExtendConfig<BaseAIPluginConfig>;
14
- declare const AIPlugin: platejs_react0.PlatePlugin<platejs0.PluginConfig<any, {}, {}, Record<any, {
15
- insertNodes: (nodes: platejs0.Descendant[], args_1?: {
16
- target?: platejs0.Path;
17
- } | undefined) => void;
18
- removeMarks: (args_0?: {
19
- at?: platejs0.TLocation;
20
- } | undefined) => void;
21
- removeNodes: (args_0?: {
22
- at?: platejs0.Path;
23
- } | undefined) => void;
24
- undo: () => void;
25
- }>, {}>>;
14
+ declare const AIPlugin: platejs_react0.PlatePlugin<platejs12.PluginConfig<"ai", {}, {}, {
15
+ ai: {
16
+ acceptPreview: ((_value?: platejs12.Value | undefined) => boolean) & ((_value?: platejs12.Value | undefined) => boolean);
17
+ beginPreview: ((args_0?: {
18
+ originalBlocks?: platejs12.Value;
19
+ } | undefined) => boolean) & ((args_0?: {
20
+ originalBlocks?: platejs12.Value;
21
+ } | undefined) => boolean);
22
+ cancelPreview: (() => boolean) & (() => boolean);
23
+ discardPreview: (() => boolean) & (() => boolean);
24
+ hasPreview: (() => boolean) & (() => boolean);
25
+ insertNodes: ((nodes: platejs12.Descendant[], args_1?: {
26
+ target?: platejs12.Path;
27
+ } | undefined) => void) & ((nodes: platejs12.Descendant[], args_1?: {
28
+ target?: platejs12.Path;
29
+ } | undefined) => void);
30
+ removeMarks: ((args_0?: {
31
+ at?: platejs12.TLocation;
32
+ } | undefined) => void) & ((args_0?: {
33
+ at?: platejs12.TLocation;
34
+ } | undefined) => void);
35
+ removeNodes: ((args_0?: {
36
+ at?: platejs12.Path;
37
+ } | undefined) => void) & ((args_0?: {
38
+ at?: platejs12.Path;
39
+ } | undefined) => void);
40
+ undo: (() => void) & (() => void);
41
+ };
42
+ }, {}>>;
26
43
  //#endregion
27
44
  //#region src/react/ai-chat/internal/types.d.ts
28
45
  type ToolName = 'comment' | 'edit' | 'generate';
@@ -206,7 +223,7 @@ declare const AIChatPlugin: platejs_react0.PlatePlugin<PluginConfig<"aiChat", {
206
223
  reload: () => void;
207
224
  show: () => void;
208
225
  stop: () => void;
209
- }, "node" | "stop" | "reset" | "submit">> & Record<"aiChat", {
226
+ }, "node" | "reset" | "stop" | "submit">> & Record<"aiChat", {
210
227
  hide: ({
211
228
  focus,
212
229
  undo
@@ -227,7 +244,7 @@ declare const AIChatPlugin: platejs_react0.PlatePlugin<PluginConfig<"aiChat", {
227
244
  insertBelow: (sourceEditor: SlateEditor, args_1?: {
228
245
  format?: "all" | "none" | "single";
229
246
  } | undefined) => void;
230
- removeAnchor: (options?: platejs0.RemoveNodesOptions | undefined) => void;
247
+ removeAnchor: (options?: platejs12.RemoveNodesOptions | undefined) => void;
231
248
  replaceSelection: (sourceEditor: SlateEditor, args_1?: {
232
249
  format?: "all" | "none" | "single";
233
250
  } | undefined) => void;
@@ -245,7 +262,7 @@ declare const withAIChat: OverrideEditor<AIChatPluginConfig>;
245
262
  */
246
263
  declare const useAIChatEditor: (editor: SlateEditor, content: string, {
247
264
  parser
248
- }?: DeserializeMdOptions) => platejs0.Value;
265
+ }?: DeserializeMdOptions) => platejs12.Value;
249
266
  //#endregion
250
267
  //#region src/react/ai-chat/hooks/useChatChunk.d.ts
251
268
  declare const useChatChunk: ({
@@ -281,7 +298,7 @@ declare const useEditorChat: ({
281
298
  }: UseEditorChatOptions) => void;
282
299
  //#endregion
283
300
  //#region src/react/ai-chat/streaming/streamDeserializeInlineMd.d.ts
284
- declare const streamDeserializeInlineMd: (editor: PlateEditor, text: string, options?: DeserializeMdOptions) => platejs0.Descendant[] | {
301
+ declare const streamDeserializeInlineMd: (editor: PlateEditor, text: string, options?: DeserializeMdOptions) => platejs12.Descendant[] | {
285
302
  text: string;
286
303
  }[];
287
304
  //#endregion
@@ -298,6 +315,11 @@ type SteamInsertChunkOptions = {
298
315
  elementProps?: any;
299
316
  textProps?: any;
300
317
  };
318
+ declare const getInsertPreviewStart: (editor: SlateEditor) => {
319
+ path: Path;
320
+ startBlock: platejs12.TElement | platejs12.TText | undefined;
321
+ startInEmptyParagraph: boolean;
322
+ };
301
323
  /** @experimental */
302
324
  declare function streamInsertChunk(editor: PlateEditor, chunk: string, options?: SteamInsertChunkOptions): void;
303
325
  declare const getCurrentBlockPath: (editor: SlateEditor) => Path;
@@ -584,4 +606,4 @@ declare const withCopilot: OverrideEditor<CopilotPluginConfig>;
584
606
  //#region src/react/copilot/utils/withoutAbort.d.ts
585
607
  declare const withoutAbort: (editor: PlateEditor, fn: () => void) => void;
586
608
  //#endregion
587
- export { AIChatPlugin, AIChatPluginConfig, AIPlugin, AIPluginConfig, CallCompletionApiOptions, CompleteOptions, CopilotPlugin, CopilotPluginConfig, GetNextWord, SteamInsertChunkOptions, TableCellUpdate, UseEditorChatOptions, acceptAIChat, acceptAISuggestions, acceptCopilot, acceptCopilotNextWord, aiCommentToRange, applyAISuggestions, applyTableCellSuggestion, callCompletionApi, createFormattedBlocks, escapeInput, findTextRangeInBlock, getChunkTrimmed, getCurrentBlockPath, getLastAssistantMessage, getListNode, getNextWord, getTableCellChildren, insertBelowAIChat, insertBelowGenerate, isCompleteCodeBlock, isCompleteMath, isSameNode, isSingleCellTable, nodesWithProps, rejectAISuggestions, removeAnchorAIChat, renderCopilotBelowNodes, replaceSelectionAIChat, resetAIChat, streamDeserializeInlineMd, streamDeserializeMd, streamInsertChunk, streamSerializeMd, submitAIChat, triggerCopilotSuggestion, useAIChatEditor, useChatChunk, useEditorChat, useLastAssistantMessage, withAIChat, withCopilot, withTransient, withoutAbort, withoutSuggestionAndComments };
609
+ export { AIChatPlugin, AIChatPluginConfig, AIPlugin, AIPluginConfig, CallCompletionApiOptions, CompleteOptions, CopilotPlugin, CopilotPluginConfig, GetNextWord, SteamInsertChunkOptions, TableCellUpdate, UseEditorChatOptions, acceptAIChat, acceptAISuggestions, acceptCopilot, acceptCopilotNextWord, aiCommentToRange, applyAISuggestions, applyTableCellSuggestion, callCompletionApi, createFormattedBlocks, escapeInput, findTextRangeInBlock, getChunkTrimmed, getCurrentBlockPath, getInsertPreviewStart, getLastAssistantMessage, getListNode, getNextWord, getTableCellChildren, insertBelowAIChat, insertBelowGenerate, isCompleteCodeBlock, isCompleteMath, isSameNode, isSingleCellTable, nodesWithProps, rejectAISuggestions, removeAnchorAIChat, renderCopilotBelowNodes, replaceSelectionAIChat, resetAIChat, streamDeserializeInlineMd, streamDeserializeMd, streamInsertChunk, streamSerializeMd, submitAIChat, triggerCopilotSuggestion, useAIChatEditor, useChatChunk, useEditorChat, useLastAssistantMessage, withAIChat, withCopilot, withTransient, withoutAbort, withoutSuggestionAndComments };
@@ -1,5 +1,6 @@
1
- import { n as BaseAIPlugin, r as withAIBatch, t as getEditorPrompt } from "../getEditorPrompt-BnVrgUl3.js";
1
+ import { c as AI_PREVIEW_KEY, n as BaseAIPlugin, p as hasAIPreview, r as withAIBatch, t as getEditorPrompt } from "../getEditorPrompt-axDm9Fg4.js";
2
2
  import { ElementApi, KEYS, NodeApi, PathApi, RangeApi, TextApi, bindFirst, getPluginKey, getPluginType, isDefined, nanoid } from "platejs";
3
+ import cloneDeep from "lodash/cloneDeep.js";
3
4
  import { SkipSuggestionDeletes, acceptSuggestion, diffToSuggestions, getSuggestionKey, getTransientSuggestionKey, rejectSuggestion } from "@platejs/suggestion";
4
5
  import { isSelecting } from "@platejs/selection";
5
6
  import { MarkdownPlugin, deserializeInlineMd, deserializeMd, serializeInlineMd, serializeMd } from "@platejs/markdown";
@@ -7,7 +8,6 @@ import { createTPlatePlugin, getEditorPlugin, toPlatePlugin, useEditorPlugin, us
7
8
  import { distance } from "fastest-levenshtein";
8
9
  import { BlockSelectionPlugin, removeBlockSelectionNodes } from "@platejs/selection/react";
9
10
  import { SuggestionPlugin } from "@platejs/suggestion/react";
10
- import cloneDeep from "lodash/cloneDeep.js";
11
11
  import { c } from "react-compiler-runtime";
12
12
  import React, { useEffect, useMemo, useRef } from "react";
13
13
  import debounce from "lodash/debounce.js";
@@ -168,23 +168,31 @@ const acceptAISuggestions = (editor) => {
168
168
 
169
169
  //#endregion
170
170
  //#region src/react/ai-chat/transforms/acceptAIChat.ts
171
+ const getAcceptedInsertFocusPoint = (editor) => {
172
+ let endIndex = null;
173
+ editor.children.forEach((node, index) => {
174
+ if (ElementApi.isElement(node) && node[AI_PREVIEW_KEY]) endIndex = index;
175
+ });
176
+ if (endIndex === null) return null;
177
+ return editor.api.end([endIndex]) ?? null;
178
+ };
171
179
  const acceptAIChat = (editor) => {
172
180
  const mode = editor.getOption(AIChatPlugin, "mode");
173
181
  if (mode === "insert") {
174
- const { tf } = getEditorPlugin(editor, AIPlugin);
182
+ const ai = editor.getTransforms(BaseAIPlugin).ai;
175
183
  const api = editor.getApi({ key: KEYS.ai });
176
- const lastAINodePath = api.aiChat.node({
177
- at: [],
178
- reverse: true
179
- })[1];
180
- withAIBatch(editor, () => {
181
- tf.ai.removeMarks();
184
+ const focusPoint = getAcceptedInsertFocusPoint(editor);
185
+ if (!ai.acceptPreview()) withAIBatch(editor, () => {
186
+ editor.tf.unsetNodes(AI_PREVIEW_KEY, {
187
+ at: [],
188
+ match: (node) => ElementApi.isElement(node) && !!node[AI_PREVIEW_KEY]
189
+ });
190
+ ai.removeMarks();
182
191
  editor.getTransforms(AIChatPlugin).aiChat.removeAnchor();
183
192
  });
184
193
  api.aiChat.hide();
185
194
  editor.tf.focus();
186
- const focusPoint = editor.api.end(lastAINodePath);
187
- editor.tf.setSelection({
195
+ if (focusPoint) editor.tf.select({
188
196
  anchor: focusPoint,
189
197
  focus: focusPoint
190
198
  });
@@ -389,7 +397,8 @@ const resetAIChat = (editor, { undo = true } = {}) => {
389
397
  mode: "insert",
390
398
  toolName: null
391
399
  });
392
- if (undo) editor.getTransforms(AIPlugin).ai.undo();
400
+ if (undo) editor.getTransforms(BaseAIPlugin).ai.undo();
401
+ else editor.getTransforms(BaseAIPlugin).ai.discardPreview();
393
402
  };
394
403
 
395
404
  //#endregion
@@ -401,7 +410,7 @@ const submitAIChat = (editor, input, { mode, options, prompt, toolName: toolName
401
410
  if (!prompt && input?.length === 0) return;
402
411
  if (!prompt) prompt = input;
403
412
  if (!mode) mode = isSelecting(editor) ? "chat" : "insert";
404
- if (mode === "insert") editor.getTransforms(AIPlugin).ai.undo();
413
+ if (mode === "insert") editor.getTransforms(BaseAIPlugin).ai.undo();
405
414
  setOption("mode", mode);
406
415
  setOption("toolName", toolName);
407
416
  const blocks = editor.getApi(BlockSelectionPlugin).blockSelection.getNodes();
@@ -517,7 +526,7 @@ const insertBelowAIChat = (editor, sourceEditor, { format = "single" } = {}) =>
517
526
  if (toolName === "generate") return insertBelowGenerate(editor, sourceEditor, { format });
518
527
  const selectedBlocks = editor.getApi(BlockSelectionPlugin).blockSelection.getNodes();
519
528
  const selectedIds = editor.getOptions(BlockSelectionPlugin).selectedIds;
520
- editor.getTransforms(AIPlugin).ai.undo();
529
+ editor.getTransforms(BaseAIPlugin).ai.undo();
521
530
  const insertBlocksAndSelect = editor.getTransforms(BlockSelectionPlugin).blockSelection.insertBlocksAndSelect;
522
531
  if (!selectedIds || selectedIds.size === 0) return;
523
532
  const lastBlock = selectedBlocks.at(-1);
@@ -594,7 +603,7 @@ const removeAnchorAIChat = (editor, options) => {
594
603
  //#endregion
595
604
  //#region src/react/ai-chat/withAIChat.ts
596
605
  const withAIChat = ({ api, editor, getOptions, tf: { insertText, normalizeNode }, type }) => {
597
- const tf = editor.getTransforms(AIPlugin);
606
+ const ai = editor.getTransforms(BaseAIPlugin).ai;
598
607
  const matchesTrigger = (text) => {
599
608
  const { trigger } = getOptions();
600
609
  if (trigger instanceof RegExp) return trigger.test(text);
@@ -619,7 +628,7 @@ const withAIChat = ({ api, editor, getOptions, tf: { insertText, normalizeNode }
619
628
  normalizeNode(entry) {
620
629
  const [node, path] = entry;
621
630
  if (node[KEYS.ai] && !getOptions().open) {
622
- tf.ai.removeMarks({ at: path });
631
+ ai.removeMarks({ at: path });
623
632
  return;
624
633
  }
625
634
  if (ElementApi.isElement(node) && node.type === type && !getOptions().open) {
@@ -683,7 +692,7 @@ const AIChatPlugin = createTPlatePlugin({
683
692
  },
684
693
  reload: () => {
685
694
  const { chat, chatNodes, chatSelection } = getOptions();
686
- editor.getTransforms(AIPlugin).ai.undo();
695
+ editor.getTransforms(BaseAIPlugin).ai.undo();
687
696
  if (chatSelection) editor.tf.setSelection(chatSelection);
688
697
  else editor.getApi(BlockSelectionPlugin).blockSelection.set(chatNodes.map((node) => node.id));
689
698
  const blocks = editor.getApi(BlockSelectionPlugin).blockSelection.getNodes();
@@ -995,17 +1004,35 @@ const getNextPath = (path, length) => {
995
1004
  for (let i = 0; i < length; i++) result = PathApi.next(result);
996
1005
  return result;
997
1006
  };
1007
+ const withPreviewElementProps = (editor, options) => {
1008
+ if (!hasAIPreview(editor)) return options;
1009
+ return {
1010
+ ...options,
1011
+ elementProps: {
1012
+ ...options.elementProps,
1013
+ [AI_PREVIEW_KEY]: true
1014
+ }
1015
+ };
1016
+ };
1017
+ const getInsertPreviewStart = (editor) => {
1018
+ const path = getCurrentBlockPath(editor);
1019
+ const startBlock = editor.api.node(path)?.[0];
1020
+ return {
1021
+ path,
1022
+ startBlock,
1023
+ startInEmptyParagraph: !!startBlock && NodeApi.string(startBlock).length === 0 && startBlock.type === getPluginType(editor, KEYS.p)
1024
+ };
1025
+ };
998
1026
  /** @experimental */
999
1027
  function streamInsertChunk(editor, chunk, options = {}) {
1028
+ const insertOptions = withPreviewElementProps(editor, options);
1000
1029
  const { _blockChunks, _blockPath } = editor.getOptions(AIChatPlugin);
1001
1030
  if (_blockPath === null) {
1002
1031
  const blocks = streamDeserializeMd(editor, chunk);
1003
- const path = getCurrentBlockPath(editor);
1004
- const startBlock = editor.api.node(path)[0];
1005
- const startInEmptyParagraph = NodeApi.string(startBlock).length === 0 && startBlock.type === getPluginType(editor, KEYS.p);
1032
+ const { path, startInEmptyParagraph } = getInsertPreviewStart(editor);
1006
1033
  if (startInEmptyParagraph) editor.tf.removeNodes({ at: path });
1007
1034
  if (blocks.length > 0) {
1008
- editor.tf.insertNodes(nodesWithProps(editor, [blocks[0]], options), {
1035
+ editor.tf.insertNodes(nodesWithProps(editor, [blocks[0]], insertOptions), {
1009
1036
  at: path,
1010
1037
  nextBlock: !startInEmptyParagraph,
1011
1038
  select: true
@@ -1015,7 +1042,7 @@ function streamInsertChunk(editor, chunk, options = {}) {
1015
1042
  if (blocks.length > 1) {
1016
1043
  const nextBlocks = blocks.slice(1);
1017
1044
  const nextPath = getCurrentBlockPath(editor);
1018
- editor.tf.insertNodes(nodesWithProps(editor, nextBlocks, options), {
1045
+ editor.tf.insertNodes(nodesWithProps(editor, nextBlocks, insertOptions), {
1019
1046
  at: nextPath,
1020
1047
  nextBlock: true,
1021
1048
  select: true
@@ -1034,7 +1061,7 @@ function streamInsertChunk(editor, chunk, options = {}) {
1034
1061
  const currentBlock = editor.api.node(_blockPath)[0];
1035
1062
  if (isSameNode(editor, currentBlock, tempBlocks[0])) {
1036
1063
  const chunkNodes = streamDeserializeInlineMd(editor, chunk);
1037
- editor.tf.insertNodes(nodesWithProps(editor, chunkNodes, options), {
1064
+ editor.tf.insertNodes(nodesWithProps(editor, chunkNodes, insertOptions), {
1038
1065
  at: editor.api.end(_blockPath),
1039
1066
  select: true
1040
1067
  });
@@ -1042,7 +1069,7 @@ function streamInsertChunk(editor, chunk, options = {}) {
1042
1069
  const blockText = NodeApi.string(tempBlocks[0]);
1043
1070
  if (serializedBlock === tempBlockChunks && blockText === serializedBlock) editor.setOption(AIChatPlugin, "_blockChunks", tempBlockChunks);
1044
1071
  else {
1045
- editor.tf.replaceNodes(nodesWithProps(editor, [tempBlocks[0]], options), {
1072
+ editor.tf.replaceNodes(nodesWithProps(editor, [tempBlocks[0]], insertOptions), {
1046
1073
  at: _blockPath,
1047
1074
  select: true
1048
1075
  });
@@ -1051,20 +1078,20 @@ function streamInsertChunk(editor, chunk, options = {}) {
1051
1078
  }
1052
1079
  } else {
1053
1080
  const serializedBlock = streamSerializeMd(editor, { value: [tempBlocks[0]] }, tempBlockChunks);
1054
- editor.tf.replaceNodes(nodesWithProps(editor, [tempBlocks[0]], options), {
1081
+ editor.tf.replaceNodes(nodesWithProps(editor, [tempBlocks[0]], insertOptions), {
1055
1082
  at: _blockPath,
1056
1083
  select: true
1057
1084
  });
1058
1085
  editor.setOption(AIChatPlugin, "_blockChunks", serializedBlock);
1059
1086
  }
1060
1087
  } else {
1061
- editor.tf.replaceNodes(nodesWithProps(editor, [tempBlocks[0]], options), {
1088
+ editor.tf.replaceNodes(nodesWithProps(editor, [tempBlocks[0]], insertOptions), {
1062
1089
  at: _blockPath,
1063
1090
  select: true
1064
1091
  });
1065
1092
  if (tempBlocks.length > 1) {
1066
1093
  const newEndBlockPath = getNextPath(_blockPath, tempBlocks.length - 1);
1067
- editor.tf.insertNodes(nodesWithProps(editor, tempBlocks.slice(1), options), {
1094
+ editor.tf.insertNodes(nodesWithProps(editor, tempBlocks.slice(1), insertOptions), {
1068
1095
  at: PathApi.next(_blockPath),
1069
1096
  select: true
1070
1097
  });
@@ -1400,4 +1427,4 @@ const CopilotPlugin = createTPlatePlugin({
1400
1427
  });
1401
1428
 
1402
1429
  //#endregion
1403
- export { AIChatPlugin, AIPlugin, CopilotPlugin, acceptAIChat, acceptAISuggestions, acceptCopilot, acceptCopilotNextWord, aiCommentToRange, applyAISuggestions, applyTableCellSuggestion, callCompletionApi, createFormattedBlocks, escapeInput, findTextRangeInBlock, getChunkTrimmed, getCurrentBlockPath, getLastAssistantMessage, getListNode, getNextWord, getTableCellChildren, insertBelowAIChat, insertBelowGenerate, isCompleteCodeBlock, isCompleteMath, isSameNode, isSingleCellTable, nodesWithProps, rejectAISuggestions, removeAnchorAIChat, renderCopilotBelowNodes, replaceSelectionAIChat, resetAIChat, streamDeserializeInlineMd, streamDeserializeMd, streamInsertChunk, streamSerializeMd, submitAIChat, triggerCopilotSuggestion, useAIChatEditor, useChatChunk, useEditorChat, useLastAssistantMessage, withAIChat, withCopilot, withTransient, withoutAbort, withoutSuggestionAndComments };
1430
+ export { AIChatPlugin, AIPlugin, CopilotPlugin, acceptAIChat, acceptAISuggestions, acceptCopilot, acceptCopilotNextWord, aiCommentToRange, applyAISuggestions, applyTableCellSuggestion, callCompletionApi, createFormattedBlocks, escapeInput, findTextRangeInBlock, getChunkTrimmed, getCurrentBlockPath, getInsertPreviewStart, getLastAssistantMessage, getListNode, getNextWord, getTableCellChildren, insertBelowAIChat, insertBelowGenerate, isCompleteCodeBlock, isCompleteMath, isSameNode, isSingleCellTable, nodesWithProps, rejectAISuggestions, removeAnchorAIChat, renderCopilotBelowNodes, replaceSelectionAIChat, resetAIChat, streamDeserializeInlineMd, streamDeserializeMd, streamInsertChunk, streamSerializeMd, submitAIChat, triggerCopilotSuggestion, useAIChatEditor, useChatChunk, useEditorChat, useLastAssistantMessage, withAIChat, withCopilot, withTransient, withoutAbort, withoutSuggestionAndComments };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platejs/ai",
3
- "version": "52.3.10",
3
+ "version": "52.3.12",
4
4
  "description": "Text AI plugin for Plate",
5
5
  "keywords": [
6
6
  "plate",
@@ -41,7 +41,7 @@
41
41
  "@ai-sdk/react": "^3.0.0",
42
42
  "ai": "^6.0.0",
43
43
  "@plate/scripts": "1.0.0",
44
- "platejs": "^52.3.9"
44
+ "platejs": "^52.3.11"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "platejs": ">=52.0.15",
@@ -1,102 +0,0 @@
1
- import { KEYS, TextApi, bindFirst, createTSlatePlugin, getPluginType } from "platejs";
2
- import { getTransientSuggestionKey } from "@platejs/suggestion";
3
- import { isSelecting } from "@platejs/selection";
4
-
5
- //#region src/lib/transforms/insertAINodes.ts
6
- const insertAINodes = (editor, nodes, { target } = {}) => {
7
- if (!target && !editor.selection?.focus.path) return;
8
- const aiNodes = nodes.map((node) => ({
9
- ...node,
10
- ai: true
11
- }));
12
- editor.tf.withoutNormalizing(() => {
13
- editor.tf.insertNodes(aiNodes, {
14
- at: editor.api.end(target || editor.selection.focus.path),
15
- select: true
16
- });
17
- editor.tf.collapse({ edge: "end" });
18
- });
19
- };
20
-
21
- //#endregion
22
- //#region src/lib/transforms/removeAIMarks.ts
23
- const removeAIMarks = (editor, { at = [] } = {}) => {
24
- const nodeType = getPluginType(editor, KEYS.ai);
25
- editor.tf.unsetNodes(nodeType, {
26
- at,
27
- match: (n) => n[nodeType]
28
- });
29
- };
30
-
31
- //#endregion
32
- //#region src/lib/transforms/removeAINodes.ts
33
- const removeAINodes = (editor, { at = [] } = {}) => {
34
- editor.tf.removeNodes({
35
- at,
36
- match: (n) => TextApi.isText(n) && !!n.ai
37
- });
38
- };
39
-
40
- //#endregion
41
- //#region src/lib/transforms/undoAI.ts
42
- const undoAI = (editor) => {
43
- const hasAINodeOrAISuggestion = editor.api.some({
44
- at: [],
45
- match: (n) => !!n.ai
46
- }) || editor.api.some({
47
- at: [],
48
- match: (n) => !!n[getTransientSuggestionKey()]
49
- });
50
- if (editor.history.undos.at(-1)?.ai && hasAINodeOrAISuggestion) {
51
- editor.undo();
52
- editor.history.redos.pop();
53
- }
54
- };
55
-
56
- //#endregion
57
- //#region src/lib/transforms/withAIBatch.ts
58
- const withAIBatch = (editor, fn, { split } = {}) => {
59
- if (split) editor.tf.withNewBatch(fn);
60
- else editor.tf.withMerging(fn);
61
- const lastBatch = editor.history.undos?.at(-1);
62
- if (lastBatch) lastBatch.ai = true;
63
- };
64
-
65
- //#endregion
66
- //#region src/lib/BaseAIPlugin.ts
67
- const BaseAIPlugin = createTSlatePlugin({
68
- key: KEYS.ai,
69
- node: {
70
- isDecoration: false,
71
- isLeaf: true
72
- }
73
- }).extendTransforms(({ editor }) => ({
74
- insertNodes: bindFirst(insertAINodes, editor),
75
- removeMarks: bindFirst(removeAIMarks, editor),
76
- removeNodes: bindFirst(removeAINodes, editor),
77
- undo: bindFirst(undoAI, editor)
78
- }));
79
-
80
- //#endregion
81
- //#region src/lib/utils/getEditorPrompt.ts
82
- const createPromptFromConfig = (config, params) => {
83
- const { isBlockSelecting, isSelecting: isSelecting$1 } = params;
84
- if (isBlockSelecting && config.blockSelecting) return config.blockSelecting ?? config.default;
85
- if (isSelecting$1 && config.selecting) return config.selecting ?? config.default;
86
- return config.default;
87
- };
88
- const getEditorPrompt = (editor, { prompt = "" }) => {
89
- const params = {
90
- editor,
91
- isBlockSelecting: editor.getOption({ key: KEYS.blockSelection }, "isSelectingSome"),
92
- isSelecting: isSelecting(editor)
93
- };
94
- let promptText = "";
95
- if (typeof prompt === "function") promptText = prompt(params);
96
- else if (typeof prompt === "object") promptText = createPromptFromConfig(prompt, params);
97
- else promptText = prompt;
98
- return promptText;
99
- };
100
-
101
- //#endregion
102
- export { removeAINodes as a, undoAI as i, BaseAIPlugin as n, removeAIMarks as o, withAIBatch as r, insertAINodes as s, getEditorPrompt as t };
@@ -1,96 +0,0 @@
1
- import * as platejs5 from "platejs";
2
- import { Descendant, History, OmitFirst, Path, PluginConfig, SlateEditor, TLocation } from "platejs";
3
-
4
- //#region src/lib/transforms/insertAINodes.d.ts
5
- declare const insertAINodes: (editor: SlateEditor, nodes: Descendant[], {
6
- target
7
- }?: {
8
- target?: Path;
9
- }) => void;
10
- //#endregion
11
- //#region src/lib/transforms/removeAIMarks.d.ts
12
- declare const removeAIMarks: (editor: SlateEditor, {
13
- at
14
- }?: {
15
- at?: TLocation;
16
- }) => void;
17
- //#endregion
18
- //#region src/lib/transforms/removeAINodes.d.ts
19
- declare const removeAINodes: (editor: SlateEditor, {
20
- at
21
- }?: {
22
- at?: Path;
23
- }) => void;
24
- //#endregion
25
- //#region src/lib/transforms/undoAI.d.ts
26
- declare const undoAI: (editor: SlateEditor) => void;
27
- //#endregion
28
- //#region src/lib/transforms/withAIBatch.d.ts
29
- type AIBatch = History['undos'][number] & {
30
- ai?: boolean;
31
- };
32
- declare const withAIBatch: (editor: SlateEditor, fn: () => void, {
33
- split
34
- }?: {
35
- split?: boolean;
36
- }) => void;
37
- //#endregion
38
- //#region src/lib/BaseAIPlugin.d.ts
39
- type BaseAIPluginConfig = PluginConfig<'ai', {}, {}, {
40
- ai: {
41
- insertNodes: OmitFirst<typeof insertAINodes>;
42
- removeMarks: OmitFirst<typeof removeAIMarks>;
43
- removeNodes: OmitFirst<typeof removeAINodes>;
44
- };
45
- }>;
46
- declare const BaseAIPlugin: platejs5.SlatePlugin<PluginConfig<any, {}, {}, Record<any, {
47
- insertNodes: (nodes: platejs5.Descendant[], args_1?: {
48
- target?: platejs5.Path;
49
- } | undefined) => void;
50
- removeMarks: (args_0?: {
51
- at?: platejs5.TLocation;
52
- } | undefined) => void;
53
- removeNodes: (args_0?: {
54
- at?: platejs5.Path;
55
- } | undefined) => void;
56
- undo: () => void;
57
- }>, {}>>;
58
- //#endregion
59
- //#region src/lib/types.d.ts
60
- type AIToolName = 'comment' | 'edit' | 'generate' | null;
61
- type AIMode = 'chat' | 'insert';
62
- //#endregion
63
- //#region src/lib/utils/getEditorPrompt.d.ts
64
- type EditorPrompt = ((params: EditorPromptParams) => string) | PromptConfig | string;
65
- type EditorPromptParams = {
66
- editor: SlateEditor;
67
- isBlockSelecting: boolean;
68
- isSelecting: boolean;
69
- };
70
- type PromptConfig = {
71
- default: string;
72
- blockSelecting?: string;
73
- selecting?: string;
74
- };
75
- declare const getEditorPrompt: (editor: SlateEditor, {
76
- prompt
77
- }: {
78
- prompt?: EditorPrompt;
79
- }) => string;
80
- //#endregion
81
- //#region src/lib/utils/replacePlaceholders.d.ts
82
- type MarkdownType = 'block' | 'blockSelection' | 'blockSelectionWithBlockId' | 'blockWithBlockId' | 'editor' | 'editorWithBlockId' | 'tableCellWithId';
83
- declare const replacePlaceholders: (editor: SlateEditor, text: string, {
84
- prompt
85
- }?: {
86
- prompt?: string;
87
- }) => string;
88
- //#endregion
89
- //#region src/lib/utils/getMarkdown.d.ts
90
- declare const getMarkdown: (editor: SlateEditor, {
91
- type
92
- }: {
93
- type: MarkdownType;
94
- }) => string;
95
- //#endregion
96
- export { insertAINodes as _, EditorPromptParams as a, AIMode as c, BaseAIPluginConfig as d, AIBatch as f, removeAIMarks as g, removeAINodes as h, EditorPrompt as i, AIToolName as l, undoAI as m, MarkdownType as n, PromptConfig as o, withAIBatch as p, replacePlaceholders as r, getEditorPrompt as s, getMarkdown as t, BaseAIPlugin as u };