@ai-group/chat-sdk 3.7.1-alpha2 → 3.7.1-alpha4

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.
Files changed (84) hide show
  1. package/dist/cjs/components/FileGallery/index.js +59 -40
  2. package/dist/cjs/components/FileGallery/index.js.map +2 -2
  3. package/dist/cjs/components/FileGallery/styles.d.ts +7 -0
  4. package/dist/cjs/components/FileGallery/styles.js +78 -0
  5. package/dist/cjs/components/FileGallery/styles.js.map +2 -2
  6. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/index.d.ts +7 -1
  7. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/index.js +82 -22
  8. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/index.js.map +2 -2
  9. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/styles.d.ts +3 -0
  10. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/styles.js +39 -0
  11. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/styles.js.map +2 -2
  12. package/dist/cjs/components/XAdkChatbot/index.js +35 -5
  13. package/dist/cjs/components/XAdkChatbot/index.js.map +2 -2
  14. package/dist/cjs/components/XAdkChatbot/styles.js +1 -1
  15. package/dist/cjs/components/XAdkChatbot/styles.js.map +1 -1
  16. package/dist/cjs/components/XAdkSender/InlineTagInput.d.ts +11 -5
  17. package/dist/cjs/components/XAdkSender/InlineTagInput.js +188 -113
  18. package/dist/cjs/components/XAdkSender/InlineTagInput.js.map +2 -2
  19. package/dist/cjs/components/XAdkSender/InputTags.d.ts +2 -2
  20. package/dist/cjs/components/XAdkSender/InputTags.js +8 -8
  21. package/dist/cjs/components/XAdkSender/InputTags.js.map +2 -2
  22. package/dist/cjs/components/XAdkSender/index.js +104 -64
  23. package/dist/cjs/components/XAdkSender/index.js.map +2 -2
  24. package/dist/cjs/components/XAdkSender/styles.d.ts +4 -0
  25. package/dist/cjs/components/XAdkSender/styles.js +34 -6
  26. package/dist/cjs/components/XAdkSender/styles.js.map +2 -2
  27. package/dist/cjs/index.d.ts +2 -1
  28. package/dist/cjs/index.js +7 -0
  29. package/dist/cjs/index.js.map +2 -2
  30. package/dist/cjs/types/FileGallery.d.ts +3 -0
  31. package/dist/cjs/types/FileGallery.js.map +1 -1
  32. package/dist/cjs/types/XAdkChatbot.d.ts +15 -0
  33. package/dist/cjs/types/XAdkChatbot.js.map +1 -1
  34. package/dist/cjs/types/XAdkSender.d.ts +74 -23
  35. package/dist/cjs/types/XAdkSender.js.map +1 -1
  36. package/dist/cjs/utils/index.d.ts +1 -0
  37. package/dist/cjs/utils/index.js +3 -1
  38. package/dist/cjs/utils/index.js.map +2 -2
  39. package/dist/cjs/utils/markdownResource.d.ts +7 -0
  40. package/dist/cjs/utils/markdownResource.js +73 -0
  41. package/dist/cjs/utils/markdownResource.js.map +7 -0
  42. package/dist/esm/components/FileGallery/index.js +22 -16
  43. package/dist/esm/components/FileGallery/index.js.map +1 -1
  44. package/dist/esm/components/FileGallery/styles.d.ts +7 -0
  45. package/dist/esm/components/FileGallery/styles.js +24 -17
  46. package/dist/esm/components/FileGallery/styles.js.map +1 -1
  47. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/index.d.ts +7 -1
  48. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/index.js +57 -7
  49. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/index.js.map +1 -1
  50. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/styles.d.ts +3 -0
  51. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/styles.js +5 -2
  52. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/styles.js.map +1 -1
  53. package/dist/esm/components/XAdkChatbot/index.js +20 -6
  54. package/dist/esm/components/XAdkChatbot/index.js.map +1 -1
  55. package/dist/esm/components/XAdkChatbot/styles.js +1 -1
  56. package/dist/esm/components/XAdkChatbot/styles.js.map +1 -1
  57. package/dist/esm/components/XAdkSender/InlineTagInput.d.ts +11 -5
  58. package/dist/esm/components/XAdkSender/InlineTagInput.js +185 -117
  59. package/dist/esm/components/XAdkSender/InlineTagInput.js.map +1 -1
  60. package/dist/esm/components/XAdkSender/InputTags.d.ts +2 -2
  61. package/dist/esm/components/XAdkSender/InputTags.js +9 -9
  62. package/dist/esm/components/XAdkSender/InputTags.js.map +1 -1
  63. package/dist/esm/components/XAdkSender/index.js +124 -77
  64. package/dist/esm/components/XAdkSender/index.js.map +1 -1
  65. package/dist/esm/components/XAdkSender/styles.d.ts +4 -0
  66. package/dist/esm/components/XAdkSender/styles.js +29 -25
  67. package/dist/esm/components/XAdkSender/styles.js.map +1 -1
  68. package/dist/esm/index.d.ts +2 -1
  69. package/dist/esm/index.js +2 -1
  70. package/dist/esm/index.js.map +1 -1
  71. package/dist/esm/types/FileGallery.d.ts +3 -0
  72. package/dist/esm/types/FileGallery.js.map +1 -1
  73. package/dist/esm/types/XAdkChatbot.d.ts +15 -0
  74. package/dist/esm/types/XAdkChatbot.js.map +1 -1
  75. package/dist/esm/types/XAdkSender.d.ts +74 -23
  76. package/dist/esm/types/XAdkSender.js.map +1 -1
  77. package/dist/esm/utils/index.d.ts +1 -0
  78. package/dist/esm/utils/index.js +1 -0
  79. package/dist/esm/utils/index.js.map +1 -1
  80. package/dist/esm/utils/markdownResource.d.ts +7 -0
  81. package/dist/esm/utils/markdownResource.js +33 -0
  82. package/dist/esm/utils/markdownResource.js.map +1 -0
  83. package/dist/umd/chat-sdk.min.js +1 -1
  84. package/package.json +1 -1
@@ -1,25 +1,31 @@
1
1
  import React from "react";
2
- import type { InlineTagRenderInfo, InputTag, XAdkSenderSubmitPart } from "../../types";
2
+ import type { InlineTagRenderInfo, MentionTag, XAdkSenderInputPart, XAdkSenderSubmitPart } from "../../types";
3
3
  export interface InlineTagInputRef {
4
4
  focus: () => void;
5
5
  getText: () => string;
6
6
  getParts: () => XAdkSenderSubmitPart[];
7
7
  getCursorOffset: () => number;
8
- insertTag: (tag: InputTag, replace?: {
8
+ insertMention: (mention: MentionTag, replace?: {
9
+ start: number;
10
+ end: number;
11
+ }) => void;
12
+ /** @deprecated 请使用 insertMention。 */
13
+ insertTag: (mention: MentionTag, replace?: {
9
14
  start: number;
10
15
  end: number;
11
16
  }) => void;
12
17
  }
13
18
  export interface InlineTagInputProps {
14
19
  value: string;
15
- tags: InputTag[];
20
+ mentions: MentionTag[];
21
+ defaultInputParts?: XAdkSenderInputPart[];
16
22
  placeholder?: string;
17
23
  disabled?: boolean;
18
24
  onChange: (value: string) => void;
19
- onTagsChange: (tags: InputTag[]) => void;
25
+ onMentionsChange: (mentions: MentionTag[]) => void;
20
26
  onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;
21
27
  onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;
22
- renderTag?: (tag: InputTag, info: InlineTagRenderInfo) => React.ReactNode;
28
+ renderMention?: (mention: MentionTag, info: InlineTagRenderInfo) => React.ReactNode;
23
29
  }
24
30
  declare const InlineTagInput: React.ForwardRefExoticComponent<InlineTagInputProps & React.RefAttributes<InlineTagInputRef>>;
25
31
  export default InlineTagInput;
@@ -26,9 +26,10 @@ var import_react = require("react");
26
26
  var import_client = require("react-dom/client");
27
27
  var import_styles = require("./styles");
28
28
  var import_jsx_runtime = require("react/jsx-runtime");
29
- var TAG_ATTR = "data-xadk-inline-tag-id";
29
+ var MENTION_ATTR = "data-xadk-inline-mention-id";
30
30
  var CARET_TEXT = "​";
31
31
  var createTextNode = (text) => document.createTextNode(text);
32
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? import_react.useEffect : import_react.useLayoutEffect;
32
33
  var normalizeText = (text) => text.replace(/\u200B/g, "").replace(/\u00a0/g, " ");
33
34
  var getPlainLength = (text) => normalizeText(text).length;
34
35
  var toRawOffset = (text, plainOffset) => {
@@ -44,30 +45,41 @@ var toRawOffset = (text, plainOffset) => {
44
45
  var InlineTagInput = (0, import_react.forwardRef)(
45
46
  ({
46
47
  value,
47
- tags,
48
+ mentions,
49
+ defaultInputParts,
48
50
  placeholder,
49
51
  disabled,
50
52
  onChange,
51
- onTagsChange,
53
+ onMentionsChange,
52
54
  onKeyDown,
53
55
  onKeyUp,
54
- renderTag
56
+ renderMention
55
57
  }, ref) => {
56
58
  const styles = (0, import_styles.useStyles)();
57
59
  const editorRef = (0, import_react.useRef)(null);
58
- const latestTagsRef = (0, import_react.useRef)(tags);
60
+ const latestMentionsRef = (0, import_react.useRef)(mentions);
59
61
  const tagRootMapRef = (0, import_react.useRef)(/* @__PURE__ */ new WeakMap());
60
62
  const composingRef = (0, import_react.useRef)(false);
61
63
  const lastInsertedCaretRef = (0, import_react.useRef)(null);
64
+ const savedRangeRef = (0, import_react.useRef)(null);
65
+ const defaultInputPartsAppliedRef = (0, import_react.useRef)(false);
66
+ const lastEmittedStateRef = (0, import_react.useRef)({
67
+ value,
68
+ mentionIds: mentions.map((mention) => mention.id).join("|")
69
+ });
62
70
  (0, import_react.useEffect)(() => {
63
- latestTagsRef.current = tags;
64
- }, [tags]);
65
- const getOrderedTags = (0, import_react.useCallback)(() => {
71
+ latestMentionsRef.current = mentions;
72
+ }, [mentions]);
73
+ const getOrderedMentions = (0, import_react.useCallback)(() => {
66
74
  const editor = editorRef.current;
67
75
  if (!editor)
68
76
  return [];
69
- const tagMap = new Map(latestTagsRef.current.map((tag) => [tag.id, tag]));
70
- return Array.from(editor.querySelectorAll(`[${TAG_ATTR}]`)).map((node) => tagMap.get(node.dataset.xadkInlineTagId || "")).filter(Boolean);
77
+ const mentionMap = new Map(
78
+ latestMentionsRef.current.map((mention) => [mention.id, mention])
79
+ );
80
+ return Array.from(editor.querySelectorAll(`[${MENTION_ATTR}]`)).map(
81
+ (node) => mentionMap.get(node.dataset.xadkInlineMentionId || "")
82
+ ).filter(Boolean);
71
83
  }, []);
72
84
  const getPlainText = (0, import_react.useCallback)(() => {
73
85
  const editor = editorRef.current;
@@ -85,7 +97,9 @@ var InlineTagInput = (0, import_react.forwardRef)(
85
97
  const editor = editorRef.current;
86
98
  if (!editor)
87
99
  return [];
88
- const tagMap = new Map(latestTagsRef.current.map((tag) => [tag.id, tag]));
100
+ const mentionMap = new Map(
101
+ latestMentionsRef.current.map((mention) => [mention.id, mention])
102
+ );
89
103
  const parts = [];
90
104
  editor.childNodes.forEach((node) => {
91
105
  if (node.nodeType === Node.TEXT_NODE) {
@@ -94,26 +108,32 @@ var InlineTagInput = (0, import_react.forwardRef)(
94
108
  parts.push({ type: "text", text });
95
109
  return;
96
110
  }
97
- if (node instanceof HTMLElement && node.hasAttribute(TAG_ATTR)) {
98
- const tagId = node.dataset.xadkInlineTagId || "";
99
- const tag = tagMap.get(tagId);
100
- if (tag)
101
- parts.push({ type: "tag", tag });
111
+ if (node instanceof HTMLElement && node.hasAttribute(MENTION_ATTR)) {
112
+ const mentionId = node.dataset.xadkInlineMentionId || "";
113
+ const mention = mentionMap.get(mentionId);
114
+ if (mention)
115
+ parts.push({ type: "mention", mention });
102
116
  }
103
117
  });
104
118
  return parts;
105
119
  }, []);
106
120
  const emitChange = (0, import_react.useCallback)(() => {
107
- onChange(getPlainText());
108
- onTagsChange(getOrderedTags());
109
- }, [getOrderedTags, getPlainText, onChange, onTagsChange]);
121
+ const nextValue = getPlainText();
122
+ const nextMentions = getOrderedMentions();
123
+ lastEmittedStateRef.current = {
124
+ value: nextValue,
125
+ mentionIds: nextMentions.map((mention) => mention.id).join("|")
126
+ };
127
+ onChange(nextValue);
128
+ onMentionsChange(nextMentions);
129
+ }, [getOrderedMentions, getPlainText, onChange, onMentionsChange]);
110
130
  const removeTextRange = (0, import_react.useCallback)((node, start, end) => {
111
131
  const text = node.textContent || "";
112
132
  node.textContent = `${text.slice(0, start)}${text.slice(end)}`;
113
133
  if (!node.textContent)
114
134
  node.remove();
115
135
  }, []);
116
- const removeTagNode = (0, import_react.useCallback)(
136
+ const removeMentionNode = (0, import_react.useCallback)(
117
137
  (node) => {
118
138
  var _a, _b, _c;
119
139
  const previous = node.previousSibling;
@@ -138,50 +158,76 @@ var InlineTagInput = (0, import_react.forwardRef)(
138
158
  },
139
159
  [removeTextRange]
140
160
  );
141
- const removeTagById = (0, import_react.useCallback)(
161
+ const removeMentionById = (0, import_react.useCallback)(
142
162
  (id) => {
143
163
  const editor = editorRef.current;
144
- const node = Array.from((editor == null ? void 0 : editor.querySelectorAll(`[${TAG_ATTR}]`)) || []).find(
145
- (item) => item.dataset.xadkInlineTagId === id
164
+ const node = Array.from(
165
+ (editor == null ? void 0 : editor.querySelectorAll(`[${MENTION_ATTR}]`)) || []
166
+ ).find(
167
+ (item) => item.dataset.xadkInlineMentionId === id
146
168
  );
147
169
  if (node) {
148
- removeTagNode(node);
170
+ removeMentionNode(node);
149
171
  }
150
172
  emitChange();
151
173
  editor == null ? void 0 : editor.focus();
152
174
  },
153
- [emitChange, removeTagNode]
175
+ [emitChange, removeMentionNode]
154
176
  );
155
- const buildTagNode = (0, import_react.useCallback)(
156
- (tag) => {
177
+ const buildMentionNode = (0, import_react.useCallback)(
178
+ (mention) => {
157
179
  const span = document.createElement("span");
158
180
  span.setAttribute("contenteditable", "false");
159
- span.setAttribute(TAG_ATTR, tag.id);
160
- span.dataset.xadkInlineTagId = tag.id;
181
+ span.setAttribute(MENTION_ATTR, mention.id);
182
+ span.dataset.xadkInlineMentionId = mention.id;
161
183
  span.className = styles.inlineTag;
162
- if (renderTag) {
184
+ if (renderMention) {
163
185
  const root = (0, import_client.createRoot)(span);
164
186
  tagRootMapRef.current.set(span, root);
165
187
  root.render(
166
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: renderTag(tag, { onRemove: () => removeTagById(tag.id) }) })
188
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: renderMention(mention, {
189
+ onRemove: () => removeMentionById(mention.id)
190
+ }) })
167
191
  );
168
192
  } else {
169
193
  const label = document.createElement("span");
170
194
  label.className = "xadk-inline-tag-label";
171
- label.textContent = tag.label;
195
+ label.textContent = mention.displayName || mention.label;
172
196
  const close = document.createElement("span");
173
197
  close.className = "xadk-inline-tag-close";
174
198
  close.innerHTML = "×";
175
199
  close.onclick = (event) => {
176
200
  event.preventDefault();
177
201
  event.stopPropagation();
178
- removeTagById(tag.id);
202
+ removeMentionById(mention.id);
179
203
  };
180
204
  span.append(label, close);
181
205
  }
182
206
  return span;
183
207
  },
184
- [removeTagById, renderTag, styles.inlineTag]
208
+ [removeMentionById, renderMention, styles.inlineTag]
209
+ );
210
+ const renderPartsToEditor = (0, import_react.useCallback)(
211
+ (parts) => {
212
+ const editor = editorRef.current;
213
+ if (!editor)
214
+ return;
215
+ editor.querySelectorAll(`[${MENTION_ATTR}]`).forEach((node) => {
216
+ var _a;
217
+ (_a = tagRootMapRef.current.get(node)) == null ? void 0 : _a.unmount();
218
+ });
219
+ editor.innerHTML = "";
220
+ parts.forEach((part) => {
221
+ if (part.type === "text") {
222
+ if (part.text)
223
+ editor.appendChild(createTextNode(part.text));
224
+ return;
225
+ }
226
+ const mention = part.type === "mention" ? part.mention : part.tag;
227
+ editor.append(buildMentionNode(mention), createTextNode(CARET_TEXT));
228
+ });
229
+ },
230
+ [buildMentionNode]
185
231
  );
186
232
  const setCursorAtTextEnd = (0, import_react.useCallback)((node) => {
187
233
  var _a;
@@ -191,6 +237,18 @@ var InlineTagInput = (0, import_react.forwardRef)(
191
237
  range.collapse(true);
192
238
  selection == null ? void 0 : selection.removeAllRanges();
193
239
  selection == null ? void 0 : selection.addRange(range);
240
+ savedRangeRef.current = range.cloneRange();
241
+ }, []);
242
+ const saveSelectionRange = (0, import_react.useCallback)(() => {
243
+ const editor = editorRef.current;
244
+ const selection = window.getSelection();
245
+ if (!editor || !selection || selection.rangeCount === 0)
246
+ return;
247
+ const range = selection.getRangeAt(0);
248
+ if (!editor.contains(range.startContainer) || !editor.contains(range.endContainer)) {
249
+ return;
250
+ }
251
+ savedRangeRef.current = range.cloneRange();
194
252
  }, []);
195
253
  const restoreCursorAfterInsert = (0, import_react.useCallback)(
196
254
  (node) => {
@@ -202,41 +260,41 @@ var InlineTagInput = (0, import_react.forwardRef)(
202
260
  },
203
261
  [setCursorAtTextEnd]
204
262
  );
205
- const isTagNode = (node) => node instanceof HTMLElement && node.hasAttribute(TAG_ATTR);
263
+ const isMentionNode = (node) => node instanceof HTMLElement && node.hasAttribute(MENTION_ATTR);
206
264
  const isOnlyCaretText = (text) => normalizeText(text) === "";
207
- const getTagBeforeRange = (range) => {
265
+ const getMentionBeforeRange = (range) => {
208
266
  const container = range.startContainer;
209
267
  if (container.nodeType === Node.TEXT_NODE) {
210
268
  const text = container.textContent || "";
211
269
  const beforeCursor = text.slice(0, range.startOffset);
212
- if (isOnlyCaretText(beforeCursor) && isTagNode(container.previousSibling)) {
270
+ if (isOnlyCaretText(beforeCursor) && isMentionNode(container.previousSibling)) {
213
271
  return container.previousSibling;
214
272
  }
215
273
  }
216
274
  if (container instanceof HTMLElement) {
217
275
  const previous = container.childNodes[range.startOffset - 1];
218
- if (isTagNode(previous))
276
+ if (isMentionNode(previous))
219
277
  return previous;
220
- if ((previous == null ? void 0 : previous.nodeType) === Node.TEXT_NODE && isOnlyCaretText(previous.textContent || "") && isTagNode(previous.previousSibling)) {
278
+ if ((previous == null ? void 0 : previous.nodeType) === Node.TEXT_NODE && isOnlyCaretText(previous.textContent || "") && isMentionNode(previous.previousSibling)) {
221
279
  return previous.previousSibling;
222
280
  }
223
281
  }
224
282
  return null;
225
283
  };
226
- const getTagAfterRange = (range) => {
284
+ const getMentionAfterRange = (range) => {
227
285
  const container = range.startContainer;
228
286
  if (container.nodeType === Node.TEXT_NODE) {
229
287
  const text = container.textContent || "";
230
288
  const afterCursor = text.slice(range.startOffset);
231
- if (isOnlyCaretText(afterCursor) && isTagNode(container.nextSibling)) {
289
+ if (isOnlyCaretText(afterCursor) && isMentionNode(container.nextSibling)) {
232
290
  return container.nextSibling;
233
291
  }
234
292
  }
235
293
  if (container instanceof HTMLElement) {
236
294
  const next = container.childNodes[range.startOffset];
237
- if (isTagNode(next))
295
+ if (isMentionNode(next))
238
296
  return next;
239
- if ((next == null ? void 0 : next.nodeType) === Node.TEXT_NODE && isOnlyCaretText(next.textContent || "") && isTagNode(next.nextSibling)) {
297
+ if ((next == null ? void 0 : next.nodeType) === Node.TEXT_NODE && isOnlyCaretText(next.textContent || "") && isMentionNode(next.nextSibling)) {
240
298
  return next.nextSibling;
241
299
  }
242
300
  }
@@ -262,7 +320,7 @@ var InlineTagInput = (0, import_react.forwardRef)(
262
320
  found = true;
263
321
  return;
264
322
  }
265
- if (node instanceof HTMLElement && node.hasAttribute(TAG_ATTR))
323
+ if (node instanceof HTMLElement && node.hasAttribute(MENTION_ATTR))
266
324
  return;
267
325
  if (node.nodeType === Node.TEXT_NODE) {
268
326
  offset += getPlainLength(node.textContent || "");
@@ -337,31 +395,32 @@ var InlineTagInput = (0, import_react.forwardRef)(
337
395
  }
338
396
  });
339
397
  }, []);
340
- const insertTag = (0, import_react.useCallback)(
341
- (tag, replace) => {
398
+ const insertMention = (0, import_react.useCallback)(
399
+ (mention, replace) => {
342
400
  const editor = editorRef.current;
343
401
  if (!editor)
344
402
  return;
345
403
  editor.focus();
346
- latestTagsRef.current = [
347
- ...latestTagsRef.current.filter((item) => item.id !== tag.id),
348
- tag
404
+ latestMentionsRef.current = [
405
+ ...latestMentionsRef.current.filter((item) => item.id !== mention.id),
406
+ mention
349
407
  ];
350
408
  let insertRange = null;
351
409
  if (replace) {
352
410
  insertRange = replaceTextRange(replace.start, replace.end);
353
411
  cleanupCaretTextNodes();
354
412
  }
355
- const tagNode = buildTagNode(tag);
413
+ const mentionNode = buildMentionNode(mention);
356
414
  const caretNode = createTextNode(CARET_TEXT);
357
415
  const selection = window.getSelection();
358
- const range = insertRange || ((selection == null ? void 0 : selection.rangeCount) ? selection.getRangeAt(0) : null);
416
+ const savedRange = savedRangeRef.current;
417
+ const range = insertRange || ((selection == null ? void 0 : selection.rangeCount) && editor.contains(selection.getRangeAt(0).startContainer) ? selection.getRangeAt(0) : savedRange && editor.contains(savedRange.startContainer) ? savedRange : null);
359
418
  if (range && editor.contains(range.startContainer)) {
360
419
  const fragment = document.createDocumentFragment();
361
- fragment.append(tagNode, caretNode);
420
+ fragment.append(mentionNode, caretNode);
362
421
  range.insertNode(fragment);
363
422
  } else {
364
- editor.append(tagNode, caretNode);
423
+ editor.append(mentionNode, caretNode);
365
424
  }
366
425
  cleanupCaretTextNodes();
367
426
  lastInsertedCaretRef.current = caretNode;
@@ -374,7 +433,7 @@ var InlineTagInput = (0, import_react.forwardRef)(
374
433
  });
375
434
  },
376
435
  [
377
- buildTagNode,
436
+ buildMentionNode,
378
437
  cleanupCaretTextNodes,
379
438
  emitChange,
380
439
  replaceTextRange,
@@ -382,6 +441,12 @@ var InlineTagInput = (0, import_react.forwardRef)(
382
441
  setCursorAtTextEnd
383
442
  ]
384
443
  );
444
+ (0, import_react.useEffect)(() => {
445
+ document.addEventListener("selectionchange", saveSelectionRange);
446
+ return () => {
447
+ document.removeEventListener("selectionchange", saveSelectionRange);
448
+ };
449
+ }, [saveSelectionRange]);
385
450
  (0, import_react.useImperativeHandle)(ref, () => ({
386
451
  focus: () => {
387
452
  var _a;
@@ -390,49 +455,52 @@ var InlineTagInput = (0, import_react.forwardRef)(
390
455
  getText: getPlainText,
391
456
  getParts,
392
457
  getCursorOffset: getOffsetInEditor,
393
- insertTag
394
- }), [getOffsetInEditor, getParts, getPlainText, insertTag]);
395
- (0, import_react.useEffect)(() => {
396
- const editor = editorRef.current;
397
- if (!editor || editor.childNodes.length > 0)
398
- return;
399
- if (value)
400
- editor.appendChild(createTextNode(value));
401
- tags.forEach((tag) => editor.append(buildTagNode(tag), createTextNode(CARET_TEXT)));
402
- }, []);
403
- (0, import_react.useEffect)(() => {
458
+ insertMention,
459
+ insertTag: insertMention
460
+ }), [getOffsetInEditor, getParts, getPlainText, insertMention]);
461
+ useIsomorphicLayoutEffect(() => {
404
462
  const editor = editorRef.current;
405
463
  if (!editor)
406
464
  return;
407
- const existingNodes = Array.from(editor.querySelectorAll(`[${TAG_ATTR}]`));
408
- const nextTagMap = new Map(tags.map((tag) => [tag.id, tag]));
409
- const existingIds = new Set(
410
- existingNodes.map((node) => node.dataset.xadkInlineTagId || "")
411
- );
412
- existingNodes.forEach((node) => {
413
- const tagId = node.dataset.xadkInlineTagId || "";
414
- if (!nextTagMap.has(tagId)) {
415
- removeTagNode(node);
416
- }
417
- });
418
- tags.forEach((tag) => {
419
- if (existingIds.has(tag.id))
420
- return;
421
- editor.append(buildTagNode(tag), createTextNode(CARET_TEXT));
422
- });
423
- }, [buildTagNode, removeTagNode, tags]);
424
- (0, import_react.useEffect)(() => {
465
+ if (!defaultInputPartsAppliedRef.current && (defaultInputParts == null ? void 0 : defaultInputParts.length) && !value && mentions.length === 0) {
466
+ defaultInputPartsAppliedRef.current = true;
467
+ renderPartsToEditor(defaultInputParts);
468
+ emitChange();
469
+ return;
470
+ }
471
+ const incomingMentionIds = mentions.map((mention) => mention.id).join("|");
472
+ const lastEmittedState = lastEmittedStateRef.current;
473
+ const isInternalControlledEcho = value === lastEmittedState.value && incomingMentionIds === lastEmittedState.mentionIds;
474
+ if (isInternalControlledEcho && editor.childNodes.length > 0)
475
+ return;
476
+ renderPartsToEditor([
477
+ ...value ? [{ type: "text", text: value }] : [],
478
+ ...mentions.map((mention) => ({ type: "mention", mention }))
479
+ ]);
480
+ const lastTextNode = Array.from(editor.childNodes).reverse().find((node) => node.nodeType === Node.TEXT_NODE);
481
+ if (document.activeElement === editor && lastTextNode) {
482
+ setCursorAtTextEnd(lastTextNode);
483
+ }
484
+ }, [
485
+ defaultInputParts,
486
+ emitChange,
487
+ renderPartsToEditor,
488
+ setCursorAtTextEnd,
489
+ mentions,
490
+ value
491
+ ]);
492
+ useIsomorphicLayoutEffect(() => {
425
493
  const editor = editorRef.current;
426
494
  if (!editor)
427
495
  return;
428
- if (!value && tags.length === 0 && editor.childNodes.length > 0) {
429
- editor.querySelectorAll(`[${TAG_ATTR}]`).forEach((node) => {
496
+ if (!value && mentions.length === 0 && editor.childNodes.length > 0) {
497
+ editor.querySelectorAll(`[${MENTION_ATTR}]`).forEach((node) => {
430
498
  var _a;
431
499
  (_a = tagRootMapRef.current.get(node)) == null ? void 0 : _a.unmount();
432
500
  });
433
501
  editor.innerHTML = "";
434
502
  }
435
- }, [tags.length, value]);
503
+ }, [mentions.length, value]);
436
504
  const handleInput = () => {
437
505
  if (!composingRef.current)
438
506
  emitChange();
@@ -443,10 +511,10 @@ var InlineTagInput = (0, import_react.forwardRef)(
443
511
  if (selection == null ? void 0 : selection.rangeCount) {
444
512
  const range = selection.getRangeAt(0);
445
513
  if (range.collapsed) {
446
- const targetTag = event.key === "Backspace" ? getTagBeforeRange(range) : getTagAfterRange(range);
447
- if (targetTag) {
514
+ const targetMention = event.key === "Backspace" ? getMentionBeforeRange(range) : getMentionAfterRange(range);
515
+ if (targetMention) {
448
516
  event.preventDefault();
449
- removeTagById(targetTag.dataset.xadkInlineTagId || "");
517
+ removeMentionById(targetMention.dataset.xadkInlineMentionId || "");
450
518
  return;
451
519
  }
452
520
  }
@@ -454,30 +522,37 @@ var InlineTagInput = (0, import_react.forwardRef)(
454
522
  }
455
523
  onKeyDown == null ? void 0 : onKeyDown(event);
456
524
  };
457
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.inlineInputWrapper, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
458
- "div",
459
- {
460
- ref: editorRef,
461
- className: styles.inlineInput,
462
- "data-placeholder": placeholder,
463
- contentEditable: !disabled,
464
- suppressContentEditableWarning: true,
465
- role: "textbox",
466
- "aria-multiline": "true",
467
- onInput: handleInput,
468
- onKeyDown: handleKeyDown,
469
- onKeyUp,
470
- onCompositionStart: () => {
471
- composingRef.current = true;
472
- },
473
- onCompositionEnd: () => {
474
- composingRef.current = false;
475
- emitChange();
476
- },
477
- "data-empty": !getPlainText() && getOrderedTags().length === 0,
478
- "data-cursor-offset": getOffsetInEditor()
479
- }
480
- ) });
525
+ const showPlaceholder = !value && mentions.length === 0;
526
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.inlineInputWrapper, children: [
527
+ showPlaceholder && placeholder && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.inlinePlaceholder, children: placeholder }),
528
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
529
+ "div",
530
+ {
531
+ ref: editorRef,
532
+ className: styles.inlineInput,
533
+ contentEditable: !disabled,
534
+ suppressContentEditableWarning: true,
535
+ role: "textbox",
536
+ "aria-multiline": "true",
537
+ onInput: handleInput,
538
+ onKeyDown: handleKeyDown,
539
+ onKeyUp: (event) => {
540
+ saveSelectionRange();
541
+ onKeyUp == null ? void 0 : onKeyUp(event);
542
+ },
543
+ onMouseUp: saveSelectionRange,
544
+ onFocus: saveSelectionRange,
545
+ onCompositionStart: () => {
546
+ composingRef.current = true;
547
+ },
548
+ onCompositionEnd: () => {
549
+ composingRef.current = false;
550
+ emitChange();
551
+ },
552
+ "data-cursor-offset": getOffsetInEditor()
553
+ }
554
+ )
555
+ ] });
481
556
  }
482
557
  );
483
558
  InlineTagInput.displayName = "InlineTagInput";