@platejs/ai 52.0.16 → 52.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.
@@ -1,6 +1,6 @@
1
- import { c as AIMode, d as BaseAIPluginConfig, i as EditorPrompt, l as AIToolName } from "../index-CyVv31EV.js";
2
- import * as platejs4 from "platejs";
3
- import { Descendant, EditorNodesOptions, ExtendConfig, NodeEntry, OmitFirst, Path, PluginConfig, Range, RemoveNodesOptions, SlateEditor, TElement, TIdElement, TRange, TText } from "platejs";
1
+ import { c as AIMode, d as BaseAIPluginConfig, i as EditorPrompt, l as AIToolName } from "../index-Dyi5V2wm.js";
2
+ import * as platejs0 from "platejs";
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";
6
6
  import { OverrideEditor, PlateEditor, RenderNodeWrapperProps } from "platejs/react";
@@ -11,15 +11,15 @@ 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<platejs4.PluginConfig<any, {}, {}, Record<any, {
15
- insertNodes: (nodes: platejs4.Descendant[], args_1?: {
16
- target?: platejs4.Path;
14
+ declare const AIPlugin: platejs_react0.PlatePlugin<platejs0.PluginConfig<any, {}, {}, Record<any, {
15
+ insertNodes: (nodes: platejs0.Descendant[], args_1?: {
16
+ target?: platejs0.Path;
17
17
  } | undefined) => void;
18
18
  removeMarks: (args_0?: {
19
- at?: platejs4.TLocation;
19
+ at?: platejs0.TLocation;
20
20
  } | undefined) => void;
21
21
  removeNodes: (args_0?: {
22
- at?: platejs4.Path;
22
+ at?: platejs0.Path;
23
23
  } | undefined) => void;
24
24
  undo: () => void;
25
25
  }>, {}>>;
@@ -227,7 +227,7 @@ declare const AIChatPlugin: platejs_react0.PlatePlugin<PluginConfig<"aiChat", {
227
227
  insertBelow: (sourceEditor: SlateEditor, args_1?: {
228
228
  format?: "all" | "none" | "single";
229
229
  } | undefined) => void;
230
- removeAnchor: (options?: platejs4.RemoveNodesOptions | undefined) => void;
230
+ removeAnchor: (options?: platejs0.RemoveNodesOptions | undefined) => void;
231
231
  replaceSelection: (sourceEditor: SlateEditor, args_1?: {
232
232
  format?: "all" | "none" | "single";
233
233
  } | undefined) => void;
@@ -240,10 +240,12 @@ declare const withAIChat: OverrideEditor<AIChatPluginConfig>;
240
240
  /**
241
241
  * Register an editor in the AI chat plugin, and deserializes the content into
242
242
  * `editor.children` with block-level memoization.
243
+ *
244
+ * @returns Deserialized children to pass as `value` prop to PlateStatic
243
245
  */
244
246
  declare const useAIChatEditor: (editor: SlateEditor, content: string, {
245
247
  parser
246
- }?: DeserializeMdOptions) => void;
248
+ }?: DeserializeMdOptions) => platejs0.Value;
247
249
  //#endregion
248
250
  //#region src/react/ai-chat/hooks/useChatChunk.d.ts
249
251
  declare const useChatChunk: ({
@@ -279,7 +281,7 @@ declare const useEditorChat: ({
279
281
  }: UseEditorChatOptions) => void;
280
282
  //#endregion
281
283
  //#region src/react/ai-chat/streaming/streamDeserializeInlineMd.d.ts
282
- declare const streamDeserializeInlineMd: (editor: PlateEditor, text: string, options?: DeserializeMdOptions) => platejs4.Descendant[];
284
+ declare const streamDeserializeInlineMd: (editor: PlateEditor, text: string, options?: DeserializeMdOptions) => platejs0.Descendant[];
283
285
  //#endregion
284
286
  //#region src/react/ai-chat/streaming/streamDeserializeMd.d.ts
285
287
  declare const streamDeserializeMd: (editor: PlateEditor, data: string, options?: DeserializeMdOptions) => TElement[] | {
@@ -330,11 +332,31 @@ declare const acceptAISuggestions: (editor: PlateEditor) => void;
330
332
  //#endregion
331
333
  //#region src/react/ai-chat/utils/applyAISuggestions.d.ts
332
334
  declare const applyAISuggestions: (editor: SlateEditor, content: string) => void;
335
+ declare const withTransient: (diffNodes: Descendant[]) => Descendant[];
336
+ declare const withoutSuggestionAndComments: (nodes: Descendant[]) => Descendant[];
337
+ //#endregion
338
+ //#region src/react/ai-chat/utils/applyTableCellSuggestion.d.ts
339
+ type TableCellUpdate = {
340
+ content: string;
341
+ id: string;
342
+ };
343
+ /**
344
+ * Apply AI-generated content to a table cell as diff suggestions. Finds the
345
+ * cell by ID, deserializes the markdown content, computes diff, and replaces
346
+ * the cell's children with suggestion-marked nodes.
347
+ */
348
+ declare const applyTableCellSuggestion: (editor: SlateEditor, cellUpdate: TableCellUpdate) => void;
333
349
  //#endregion
334
350
  //#region src/react/ai-chat/utils/getLastAssistantMessage.d.ts
335
351
  declare function getLastAssistantMessage(editor: PlateEditor): ChatMessage | undefined;
336
352
  declare function useLastAssistantMessage(): ChatMessage | undefined;
337
353
  //#endregion
354
+ //#region src/react/ai-chat/utils/nestedContainerUtils.d.ts
355
+ /** Check if nodes is a single table with single cell */
356
+ declare const isSingleCellTable: (nodes: Descendant[]) => nodes is [TTableElement];
357
+ /** Extract td children from single-cell table */
358
+ declare const getTableCellChildren: (table: TTableElement) => Descendant[];
359
+ //#endregion
338
360
  //#region src/react/ai-chat/utils/rejectAISuggestions.d.ts
339
361
  declare const rejectAISuggestions: (editor: PlateEditor) => void;
340
362
  //#endregion
@@ -560,4 +582,4 @@ declare const withCopilot: OverrideEditor<CopilotPluginConfig>;
560
582
  //#region src/react/copilot/utils/withoutAbort.d.ts
561
583
  declare const withoutAbort: (editor: PlateEditor, fn: () => void) => void;
562
584
  //#endregion
563
- export { AIChatPlugin, AIChatPluginConfig, AIPlugin, AIPluginConfig, CallCompletionApiOptions, CompleteOptions, CopilotPlugin, CopilotPluginConfig, GetNextWord, SteamInsertChunkOptions, UseEditorChatOptions, acceptAIChat, acceptAISuggestions, acceptCopilot, acceptCopilotNextWord, aiCommentToRange, applyAISuggestions, callCompletionApi, createFormattedBlocks, escapeInput, findTextRangeInBlock, getChunkTrimmed, getCurrentBlockPath, getLastAssistantMessage, getListNode, getNextWord, insertBelowAIChat, insertBelowGenerate, isCompleteCodeBlock, isCompleteMath, isSameNode, nodesWithProps, rejectAISuggestions, removeAnchorAIChat, renderCopilotBelowNodes, replaceSelectionAIChat, resetAIChat, streamDeserializeInlineMd, streamDeserializeMd, streamInsertChunk, streamSerializeMd, submitAIChat, triggerCopilotSuggestion, useAIChatEditor, useChatChunk, useEditorChat, useLastAssistantMessage, withAIChat, withCopilot, withoutAbort };
585
+ 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 };
@@ -3,11 +3,11 @@ import { ElementApi, KEYS, NodeApi, PathApi, RangeApi, TextApi, bindFirst, getPl
3
3
  import { SkipSuggestionDeletes, acceptSuggestion, diffToSuggestions, getSuggestionKey, getTransientSuggestionKey, rejectSuggestion } from "@platejs/suggestion";
4
4
  import { isSelecting } from "@platejs/selection";
5
5
  import { MarkdownPlugin, deserializeInlineMd, deserializeMd, serializeInlineMd, serializeMd } from "@platejs/markdown";
6
- import { createTPlatePlugin, getEditorPlugin, toPlatePlugin, useEditorPlugin, usePluginOption } from "platejs/react";
6
+ import cloneDeep from "lodash/cloneDeep.js";
7
+ import { createTPlatePlugin, getEditorPlugin as getEditorPlugin$1, toPlatePlugin, useEditorPlugin, usePluginOption } from "platejs/react";
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";
@@ -171,7 +171,7 @@ const acceptAISuggestions = (editor) => {
171
171
  const acceptAIChat = (editor) => {
172
172
  const mode = editor.getOption(AIChatPlugin, "mode");
173
173
  if (mode === "insert") {
174
- const { tf } = getEditorPlugin(editor, AIPlugin);
174
+ const { tf } = getEditorPlugin$1(editor, AIPlugin);
175
175
  const api = editor.getApi({ key: KEYS.ai });
176
176
  const lastAINodePath = api.aiChat.node({
177
177
  at: [],
@@ -197,6 +197,26 @@ const acceptAIChat = (editor) => {
197
197
  }
198
198
  };
199
199
 
200
+ //#endregion
201
+ //#region src/react/ai-chat/utils/nestedContainerUtils.ts
202
+ /** Check if nodes is a single table with single cell */
203
+ const isSingleCellTable = (nodes) => {
204
+ if (nodes.length !== 1) return false;
205
+ const table = nodes[0];
206
+ if (table.type !== KEYS.table) return false;
207
+ const rows = table.children;
208
+ if (rows.length !== 1) return false;
209
+ const row = rows[0];
210
+ if (row.type !== KEYS.tr) return false;
211
+ const cells = row.children;
212
+ if (cells.length !== 1) return false;
213
+ return cells[0].type === KEYS.td;
214
+ };
215
+ /** Extract td children from single-cell table */
216
+ const getTableCellChildren = (table) => {
217
+ return table.children[0].children[0].children;
218
+ };
219
+
200
220
  //#endregion
201
221
  //#region src/react/ai-chat/utils/applyAISuggestions.ts
202
222
  const applyAISuggestions = (editor, content) => {
@@ -281,9 +301,36 @@ const withoutSuggestionAndComments = (nodes) => nodes.map((node) => {
281
301
  return node;
282
302
  });
283
303
  const getDiffNodes = (editor, aiContent) => {
284
- /** Original document nodes */
285
- const chatNodes = withoutSuggestionAndComments(editor.getOption(AIChatPlugin, "chatNodes"));
286
- return withTransient(diffToSuggestions(editor, chatNodes, withProps(deserializeMd(editor, aiContent), chatNodes), { ignoreProps: ["id", "listStart"] }));
304
+ let chatNodes = withoutSuggestionAndComments(editor.getOption(AIChatPlugin, "chatNodes"));
305
+ /**If selecting one single cell table, we just need to compare it's children to get diff nodes */
306
+ if (isSingleCellTable(chatNodes)) chatNodes = getTableCellChildren(chatNodes[0]);
307
+ const aiNodes = withProps(deserializeMd(editor, aiContent), chatNodes);
308
+ return withTransient(diffToSuggestions(editor, chatNodes, aiNodes, { ignoreProps: ["id", "listStart"] }));
309
+ };
310
+
311
+ //#endregion
312
+ //#region src/react/ai-chat/utils/applyTableCellSuggestion.ts
313
+ /**
314
+ * Apply AI-generated content to a table cell as diff suggestions. Finds the
315
+ * cell by ID, deserializes the markdown content, computes diff, and replaces
316
+ * the cell's children with suggestion-marked nodes.
317
+ */
318
+ const applyTableCellSuggestion = (editor, cellUpdate) => {
319
+ const { content, id } = cellUpdate;
320
+ const cellEntry = editor.api.node({
321
+ at: [],
322
+ match: (n) => ElementApi.isElement(n) && n.id === id
323
+ });
324
+ if (!cellEntry) {
325
+ console.warn(`Table cell with id "${id}" not found`);
326
+ return;
327
+ }
328
+ const [cell, cellPath] = cellEntry;
329
+ const transientDiffNodes = withTransient(diffToSuggestions(editor, withoutSuggestionAndComments(cell.children), deserializeMd(editor, content), { ignoreProps: ["id"] }));
330
+ editor.tf.replaceNodes(transientDiffNodes, {
331
+ at: cellPath,
332
+ children: true
333
+ });
287
334
  };
288
335
 
289
336
  //#endregion
@@ -332,7 +379,7 @@ const rejectAISuggestions = (editor) => {
332
379
  //#endregion
333
380
  //#region src/react/ai-chat/utils/resetAIChat.ts
334
381
  const resetAIChat = (editor, { undo = true } = {}) => {
335
- const { api, getOptions, setOptions } = getEditorPlugin(editor, { key: KEYS.aiChat });
382
+ const { api, getOptions, setOptions } = getEditorPlugin$1(editor, { key: KEYS.aiChat });
336
383
  api.aiChat.stop();
337
384
  const chat = getOptions().chat;
338
385
  if (chat.messages && chat.messages.length > 0) chat.setMessages?.([]);
@@ -348,7 +395,7 @@ const resetAIChat = (editor, { undo = true } = {}) => {
348
395
  //#endregion
349
396
  //#region src/react/ai-chat/utils/submitAIChat.ts
350
397
  const submitAIChat = (editor, input, { mode, options, prompt, toolName: toolNameProps } = {}) => {
351
- const { getOptions, setOption } = getEditorPlugin(editor, { key: KEYS.aiChat });
398
+ const { getOptions, setOption } = getEditorPlugin$1(editor, { key: KEYS.aiChat });
352
399
  const { chat, toolName: toolNameOption } = getOptions();
353
400
  const toolName = toolNameProps ?? toolNameOption ?? null;
354
401
  if (!prompt && input?.length === 0) return;
@@ -680,16 +727,22 @@ const AIChatPlugin = createTPlatePlugin({
680
727
  /**
681
728
  * Register an editor in the AI chat plugin, and deserializes the content into
682
729
  * `editor.children` with block-level memoization.
730
+ *
731
+ * @returns Deserialized children to pass as `value` prop to PlateStatic
683
732
  */
684
733
  const useAIChatEditor = (editor, content, { parser } = {}) => {
685
734
  const { setOption } = useEditorPlugin(AIChatPlugin);
686
- editor.children = useMemo(() => editor.getApi(MarkdownPlugin).markdown.deserialize(content, {
687
- memoize: true,
688
- parser
689
- }), [content]);
735
+ const children = useMemo(() => {
736
+ return editor.getApi(MarkdownPlugin).markdown.deserialize(content, {
737
+ memoize: true,
738
+ parser
739
+ });
740
+ }, [content]);
741
+ editor.children = children;
690
742
  useEffect(() => {
691
743
  setOption("aiEditor", editor);
692
744
  }, [editor, setOption]);
745
+ return children;
693
746
  };
694
747
 
695
748
  //#endregion
@@ -1038,7 +1091,7 @@ const getCurrentBlockPath = (editor) => {
1038
1091
  //#endregion
1039
1092
  //#region src/react/copilot/renderCopilotBelowNodes.tsx
1040
1093
  const renderCopilotBelowNodes = ({ editor }) => {
1041
- const { renderGhostText: GhostText } = getEditorPlugin(editor, { key: KEYS.copilot }).getOptions();
1094
+ const { renderGhostText: GhostText } = getEditorPlugin$1(editor, { key: KEYS.copilot }).getOptions();
1042
1095
  if (!GhostText) return;
1043
1096
  return ({ children }) => /* @__PURE__ */ React.createElement(React.Fragment, null, children, /* @__PURE__ */ React.createElement(GhostText, null));
1044
1097
  };
@@ -1146,7 +1199,7 @@ const getNextWord = ({ text }) => {
1146
1199
  //#endregion
1147
1200
  //#region src/react/copilot/utils/triggerCopilotSuggestion.ts
1148
1201
  const triggerCopilotSuggestion = async (editor) => {
1149
- const { api, getOptions, setOption } = getEditorPlugin(editor, { key: KEYS.copilot });
1202
+ const { api, getOptions, setOption } = getEditorPlugin$1(editor, { key: KEYS.copilot });
1150
1203
  const { completeOptions, getPrompt, isLoading, triggerQuery } = getOptions();
1151
1204
  if (isLoading || editor.getOptions({ key: KEYS.aiChat }).chat?.isLoading) return false;
1152
1205
  if (!triggerQuery({ editor })) return false;
@@ -1181,7 +1234,7 @@ const withoutAbort = (editor, fn) => {
1181
1234
  //#endregion
1182
1235
  //#region src/react/copilot/transforms/acceptCopilotNextWord.ts
1183
1236
  const acceptCopilotNextWord = (editor) => {
1184
- const { api, getOptions } = getEditorPlugin(editor, { key: KEYS.copilot });
1237
+ const { api, getOptions } = getEditorPlugin$1(editor, { key: KEYS.copilot });
1185
1238
  const { getNextWord: getNextWord$1, suggestionText } = getOptions();
1186
1239
  if (!suggestionText?.length) return false;
1187
1240
  const { firstWord, remainingText } = getNextWord$1({ text: suggestionText });
@@ -1347,4 +1400,4 @@ const CopilotPlugin = createTPlatePlugin({
1347
1400
  });
1348
1401
 
1349
1402
  //#endregion
1350
- export { AIChatPlugin, AIPlugin, CopilotPlugin, acceptAIChat, acceptAISuggestions, acceptCopilot, acceptCopilotNextWord, aiCommentToRange, applyAISuggestions, callCompletionApi, createFormattedBlocks, escapeInput, findTextRangeInBlock, getChunkTrimmed, getCurrentBlockPath, getLastAssistantMessage, getListNode, getNextWord, insertBelowAIChat, insertBelowGenerate, isCompleteCodeBlock, isCompleteMath, isSameNode, nodesWithProps, rejectAISuggestions, removeAnchorAIChat, renderCopilotBelowNodes, replaceSelectionAIChat, resetAIChat, streamDeserializeInlineMd, streamDeserializeMd, streamInsertChunk, streamSerializeMd, submitAIChat, triggerCopilotSuggestion, useAIChatEditor, useChatChunk, useEditorChat, useLastAssistantMessage, withAIChat, withCopilot, withoutAbort };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platejs/ai",
3
- "version": "52.0.16",
3
+ "version": "52.1.0",
4
4
  "description": "Text AI plugin for Plate",
5
5
  "keywords": [
6
6
  "plate",
@@ -40,7 +40,7 @@
40
40
  "typecheck": "yarn p:typecheck"
41
41
  },
42
42
  "dependencies": {
43
- "@platejs/markdown": "52.0.11",
43
+ "@platejs/markdown": "52.1.0",
44
44
  "@platejs/selection": "52.0.16",
45
45
  "@platejs/suggestion": "52.0.11",
46
46
  "fastest-levenshtein": "1.0.16",
@@ -48,9 +48,9 @@
48
48
  "react-compiler-runtime": "^1.0.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@ai-sdk/react": "2.0.28",
51
+ "@ai-sdk/react": "^3.0.0",
52
52
  "@platejs/combobox": "52.0.15",
53
- "ai": "5.0.28"
53
+ "ai": "^6.0.0"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "platejs": ">=52.0.15",