@ai-group/chat-sdk 3.7.0 → 3.7.1-alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/XAdkSender/InlineTagInput.d.ts +24 -0
- package/dist/cjs/components/XAdkSender/InlineTagInput.js +461 -0
- package/dist/cjs/components/XAdkSender/InlineTagInput.js.map +7 -0
- package/dist/cjs/components/XAdkSender/InputTags.d.ts +8 -0
- package/dist/cjs/components/XAdkSender/InputTags.js +51 -0
- package/dist/cjs/components/XAdkSender/InputTags.js.map +7 -0
- package/dist/cjs/components/XAdkSender/QuickList.d.ts +16 -0
- package/dist/cjs/components/XAdkSender/QuickList.js +105 -0
- package/dist/cjs/components/XAdkSender/QuickList.js.map +7 -0
- package/dist/cjs/components/XAdkSender/index.d.ts +1 -6
- package/dist/cjs/components/XAdkSender/index.js +289 -78
- package/dist/cjs/components/XAdkSender/index.js.map +3 -3
- package/dist/cjs/components/XAdkSender/styles.d.ts +15 -0
- package/dist/cjs/components/XAdkSender/styles.js +184 -5
- package/dist/cjs/components/XAdkSender/styles.js.map +2 -2
- package/dist/cjs/index.d.ts +1 -2
- package/dist/cjs/index.js +0 -3
- package/dist/cjs/index.js.map +3 -3
- package/dist/cjs/types/XAdkSender.d.ts +55 -0
- package/dist/cjs/types/XAdkSender.js.map +1 -1
- package/dist/esm/components/XAdkSender/InlineTagInput.d.ts +24 -0
- package/dist/esm/components/XAdkSender/InlineTagInput.js +437 -0
- package/dist/esm/components/XAdkSender/InlineTagInput.js.map +1 -0
- package/dist/esm/components/XAdkSender/InputTags.d.ts +8 -0
- package/dist/esm/components/XAdkSender/InputTags.js +36 -0
- package/dist/esm/components/XAdkSender/InputTags.js.map +1 -0
- package/dist/esm/components/XAdkSender/QuickList.d.ts +16 -0
- package/dist/esm/components/XAdkSender/QuickList.js +96 -0
- package/dist/esm/components/XAdkSender/QuickList.js.map +1 -0
- package/dist/esm/components/XAdkSender/index.d.ts +1 -6
- package/dist/esm/components/XAdkSender/index.js +327 -78
- package/dist/esm/components/XAdkSender/index.js.map +1 -1
- package/dist/esm/components/XAdkSender/styles.d.ts +15 -0
- package/dist/esm/components/XAdkSender/styles.js +29 -11
- package/dist/esm/components/XAdkSender/styles.js.map +1 -1
- package/dist/esm/index.d.ts +1 -2
- package/dist/esm/index.js +1 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/XAdkSender.d.ts +55 -0
- package/dist/esm/types/XAdkSender.js.map +1 -1
- package/dist/umd/chat-sdk.min.js +1 -1
- package/package.json +1 -1
- package/dist/cjs/components/XAdkSender/Switch.d.ts +0 -16
- package/dist/cjs/components/XAdkSender/Switch.js +0 -95
- package/dist/cjs/components/XAdkSender/Switch.js.map +0 -7
- package/dist/esm/components/XAdkSender/Switch.d.ts +0 -16
- package/dist/esm/components/XAdkSender/Switch.js +0 -53
- package/dist/esm/components/XAdkSender/Switch.js.map +0 -1
|
@@ -1,4 +1,41 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
/** 快捷键触发的列表项 */
|
|
3
|
+
export interface QuickListOption {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
icon?: React.ReactNode;
|
|
8
|
+
/** 分组名(用于聚合列表,子分组通过下划线分割) */
|
|
9
|
+
group?: string;
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}
|
|
12
|
+
/** 快捷键配置 */
|
|
13
|
+
export interface QuickKeyConfig {
|
|
14
|
+
/** 触发字符,如 '@', '#', '$' */
|
|
15
|
+
key: string;
|
|
16
|
+
/** 列表标题 */
|
|
17
|
+
title?: string;
|
|
18
|
+
/** 列表数据 */
|
|
19
|
+
options: QuickListOption[];
|
|
20
|
+
/** 自定义列表项渲染 */
|
|
21
|
+
renderItem?: (option: QuickListOption) => React.ReactNode;
|
|
22
|
+
/** 选中回调 */
|
|
23
|
+
onSelect?: (option: QuickListOption) => void;
|
|
24
|
+
}
|
|
25
|
+
/** 输入框内标签 */
|
|
26
|
+
export interface InputTag {
|
|
27
|
+
id: string;
|
|
28
|
+
label: string;
|
|
29
|
+
/** 标签类型,如 'aggregation', 'skill', 'app' */
|
|
30
|
+
type: string;
|
|
31
|
+
color?: string;
|
|
32
|
+
icon?: React.ReactNode;
|
|
33
|
+
/** 原始数据 */
|
|
34
|
+
data?: any;
|
|
35
|
+
}
|
|
36
|
+
export interface InlineTagRenderInfo {
|
|
37
|
+
onRemove: () => void;
|
|
38
|
+
}
|
|
2
39
|
export interface UploadFileResult {
|
|
3
40
|
fileName?: string;
|
|
4
41
|
fileId?: string | number;
|
|
@@ -76,6 +113,7 @@ export interface SenderUIProps {
|
|
|
76
113
|
draggable?: boolean;
|
|
77
114
|
loading?: boolean;
|
|
78
115
|
disabled?: boolean;
|
|
116
|
+
placeholder?: string;
|
|
79
117
|
/** 受控:输入框的值 */
|
|
80
118
|
value?: string;
|
|
81
119
|
/** 非受控:输入框默认值 */
|
|
@@ -85,6 +123,7 @@ export interface SenderUIProps {
|
|
|
85
123
|
onSubmit?: (data: {
|
|
86
124
|
text: string;
|
|
87
125
|
files: ServerFile[];
|
|
126
|
+
tags?: InputTag[];
|
|
88
127
|
}) => void;
|
|
89
128
|
onStop?: () => void;
|
|
90
129
|
/** 自定义发送按钮渲染 */
|
|
@@ -104,6 +143,22 @@ export interface SenderUIProps {
|
|
|
104
143
|
prefix?: React.ReactNode | false | SlotRenderFunction;
|
|
105
144
|
/** 底部内容 */
|
|
106
145
|
footer?: React.ReactNode | false | SlotRenderFunction;
|
|
146
|
+
/** 底部左侧拓展区域,不传时 footer 保持原有居中布局 */
|
|
147
|
+
footerLeft?: React.ReactNode | false | SlotRenderFunction;
|
|
148
|
+
/** 快捷键配置列表 */
|
|
149
|
+
quickKeys?: QuickKeyConfig[];
|
|
150
|
+
/** 是否把标签以内联 token 形式展示在输入区内;默认 false 保持历史 textarea 行为 */
|
|
151
|
+
inlineTags?: boolean;
|
|
152
|
+
/** 自定义内联标签渲染 */
|
|
153
|
+
renderTag?: (tag: InputTag, info: InlineTagRenderInfo) => React.ReactNode;
|
|
154
|
+
/** 受控:标签列表 */
|
|
155
|
+
tags?: InputTag[];
|
|
156
|
+
/** 非受控:默认标签列表 */
|
|
157
|
+
defaultTags?: InputTag[];
|
|
158
|
+
/** 标签变化回调 */
|
|
159
|
+
onTagsChange?: (tags: InputTag[]) => void;
|
|
160
|
+
/** 快捷键触发回调(业务方可在此处理搜索等逻辑) */
|
|
161
|
+
onQuickKeyTrigger?: (key: string, keyword: string) => void;
|
|
107
162
|
}
|
|
108
163
|
export type XAdkSenderProps = SenderUIProps & UploaderCoreProps;
|
|
109
164
|
export interface XAdkSenderHandle {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/types/XAdkSender.ts"],
|
|
4
|
-
"sourcesContent": ["// types/XAdkSender.ts\nimport React from \"react\";\n\nexport interface UploadFileResult {\n fileName?: string;\n fileId?: string | number;\n tempUrl?: string;\n url?: string;\n fileUrl?: string;\n fileType?: string;\n fileSize?: number;\n mimeType?: string;\n [key: string]: any;\n}\n\nexport interface UploadSuccessResponse {\n data?: UploadFileResult | UploadFileResult[];\n [key: string]: any;\n}\n\ninterface uploadRequestProps {\n (options: {\n file: File;\n onProgress?: (e: { percent: number }) => void;\n onSuccess?: (\n response: UploadFileResult | UploadFileResult[] | UploadSuccessResponse,\n ) => void;\n onError?: (error: Error) => void;\n }): Promise<void> | void;\n}\n\nexport type UploadRequestFn = uploadRequestProps;\n\nexport interface ServerFile {\n fileName: string;\n fileId: string | number;\n tempUrl: string;\n type: string;\n size?: number;\n mimeType: string;\n raw?: UploadFileResult;\n}\n\nexport interface LocalFile {\n id: string;\n uid: string;\n name: string;\n file: File;\n size: number;\n type: string;\n progress: number;\n status: \"pending\" | \"uploading\" | \"success\" | \"error\";\n // 服务器返回字段\n fileId?: string | number;\n tempUrl?: string;\n response?: any;\n errorMessage?: string; // 上传错误信息\n}\n\nexport type FileValidator = (\n file: File,\n context: { files: LocalFile[] },\n) => string | null;\n\nexport interface ActionsComponents {\n SendButton: React.ComponentType<any>;\n UploadButton: React.ComponentType<any>;\n ClearButton: React.ComponentType<any>;\n}\n\nexport type SlotRenderFunction = (\n oriNode: React.ReactNode,\n info: { components: ActionsComponents },\n) => React.ReactNode | false;\n\n// 上传相关\nexport interface UploaderCoreProps {\n uploadRequest?: uploadRequestProps;\n\n maxFileSize?: number;\n allowedFileTypes?: string[];\n maxFiles?: number;\n\n validators?: FileValidator[];\n\n // 数据层回调\n onFilesChange?: (files: LocalFile[]) => void;\n onUploadSuccess?: (file: LocalFile) => void;\n onUploadError?: (file: LocalFile, error: Error) => void;\n}\n\n// UI 相关\nexport interface SenderUIProps {\n clearBtnShow?: boolean;\n allowUpload?: boolean;\n /** 是否启用 Sender 自身的拖拽上传,设为 false 时由外层(如 DefaultLayout)管理拖拽 */\n draggable?: boolean;\n loading?: boolean;\n disabled?: boolean; // 只读状态\n /** 受控:输入框的值 */\n value?: string;\n /** 非受控:输入框默认值 */\n defaultValue?: string;\n onClear?: () => void;\n onChange?: (value: string) => void;\n onSubmit?: (data: {
|
|
4
|
+
"sourcesContent": ["// types/XAdkSender.ts\nimport React from \"react\";\n\n// ===================== 快捷键/标签相关类型 =====================\n\n/** 快捷键触发的列表项 */\nexport interface QuickListOption {\n id: string;\n label: string;\n description?: string;\n icon?: React.ReactNode;\n /** 分组名(用于聚合列表,子分组通过下划线分割) */\n group?: string;\n [key: string]: any;\n}\n\n/** 快捷键配置 */\nexport interface QuickKeyConfig {\n /** 触发字符,如 '@', '#', '$' */\n key: string;\n /** 列表标题 */\n title?: string;\n /** 列表数据 */\n options: QuickListOption[];\n /** 自定义列表项渲染 */\n renderItem?: (option: QuickListOption) => React.ReactNode;\n /** 选中回调 */\n onSelect?: (option: QuickListOption) => void;\n}\n\n/** 输入框内标签 */\nexport interface InputTag {\n id: string;\n label: string;\n /** 标签类型,如 'aggregation', 'skill', 'app' */\n type: string;\n color?: string;\n icon?: React.ReactNode;\n /** 原始数据 */\n data?: any;\n}\n\nexport interface InlineTagRenderInfo {\n onRemove: () => void;\n}\n\n// ===================== 上传相关类型 =====================\n\nexport interface UploadFileResult {\n fileName?: string;\n fileId?: string | number;\n tempUrl?: string;\n url?: string;\n fileUrl?: string;\n fileType?: string;\n fileSize?: number;\n mimeType?: string;\n [key: string]: any;\n}\n\nexport interface UploadSuccessResponse {\n data?: UploadFileResult | UploadFileResult[];\n [key: string]: any;\n}\n\ninterface uploadRequestProps {\n (options: {\n file: File;\n onProgress?: (e: { percent: number }) => void;\n onSuccess?: (\n response: UploadFileResult | UploadFileResult[] | UploadSuccessResponse,\n ) => void;\n onError?: (error: Error) => void;\n }): Promise<void> | void;\n}\n\nexport type UploadRequestFn = uploadRequestProps;\n\nexport interface ServerFile {\n fileName: string;\n fileId: string | number;\n tempUrl: string;\n type: string;\n size?: number;\n mimeType: string;\n raw?: UploadFileResult;\n}\n\nexport interface LocalFile {\n id: string;\n uid: string;\n name: string;\n file: File;\n size: number;\n type: string;\n progress: number;\n status: \"pending\" | \"uploading\" | \"success\" | \"error\";\n // 服务器返回字段\n fileId?: string | number;\n tempUrl?: string;\n response?: any;\n errorMessage?: string; // 上传错误信息\n}\n\nexport type FileValidator = (\n file: File,\n context: { files: LocalFile[] },\n) => string | null;\n\nexport interface ActionsComponents {\n SendButton: React.ComponentType<any>;\n UploadButton: React.ComponentType<any>;\n ClearButton: React.ComponentType<any>;\n}\n\nexport type SlotRenderFunction = (\n oriNode: React.ReactNode,\n info: { components: ActionsComponents },\n) => React.ReactNode | false;\n\n// 上传相关\nexport interface UploaderCoreProps {\n uploadRequest?: uploadRequestProps;\n\n maxFileSize?: number;\n allowedFileTypes?: string[];\n maxFiles?: number;\n\n validators?: FileValidator[];\n\n // 数据层回调\n onFilesChange?: (files: LocalFile[]) => void;\n onUploadSuccess?: (file: LocalFile) => void;\n onUploadError?: (file: LocalFile, error: Error) => void;\n}\n\n// UI 相关\nexport interface SenderUIProps {\n clearBtnShow?: boolean;\n allowUpload?: boolean;\n /** 是否启用 Sender 自身的拖拽上传,设为 false 时由外层(如 DefaultLayout)管理拖拽 */\n draggable?: boolean;\n loading?: boolean;\n disabled?: boolean; // 只读状态\n placeholder?: string;\n /** 受控:输入框的值 */\n value?: string;\n /** 非受控:输入框默认值 */\n defaultValue?: string;\n onClear?: () => void;\n onChange?: (value: string) => void;\n onSubmit?: (data: {\n text: string;\n files: ServerFile[];\n tags?: InputTag[];\n }) => void;\n onStop?: () => void;\n\n /** 自定义发送按钮渲染 */\n sendButtonRender?: (info: {\n loading: boolean;\n disabled: boolean;\n /** 当前是否可以发送(文本非空或有已上传的文件) */\n canSend: boolean;\n onSend: () => void;\n onStop?: () => void;\n }) => React.ReactNode;\n\n // UI插槽功能\n /** 后缀内容,默认展示操作按钮,设为 false 时不显示 */\n suffix?: React.ReactNode | false | SlotRenderFunction;\n /** 头部面板 */\n header?: React.ReactNode | false | SlotRenderFunction;\n /** 前缀内容 */\n prefix?: React.ReactNode | false | SlotRenderFunction;\n /** 底部内容 */\n footer?: React.ReactNode | false | SlotRenderFunction;\n /** 底部左侧拓展区域,不传时 footer 保持原有居中布局 */\n footerLeft?: React.ReactNode | false | SlotRenderFunction;\n\n // 快捷键/标签功能\n /** 快捷键配置列表 */\n quickKeys?: QuickKeyConfig[];\n /** 是否把标签以内联 token 形式展示在输入区内;默认 false 保持历史 textarea 行为 */\n inlineTags?: boolean;\n /** 自定义内联标签渲染 */\n renderTag?: (\n tag: InputTag,\n info: InlineTagRenderInfo,\n ) => React.ReactNode;\n /** 受控:标签列表 */\n tags?: InputTag[];\n /** 非受控:默认标签列表 */\n defaultTags?: InputTag[];\n /** 标签变化回调 */\n onTagsChange?: (tags: InputTag[]) => void;\n /** 快捷键触发回调(业务方可在此处理搜索等逻辑) */\n onQuickKeyTrigger?: (key: string, keyword: string) => void;\n}\n\nexport type XAdkSenderProps = SenderUIProps & UploaderCoreProps;\n\nexport interface XAdkSenderHandle {\n addFiles: (files: File[]) => void;\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { InlineTagRenderInfo, InputTag } from "../../types";
|
|
3
|
+
export interface InlineTagInputRef {
|
|
4
|
+
focus: () => void;
|
|
5
|
+
getText: () => string;
|
|
6
|
+
getCursorOffset: () => number;
|
|
7
|
+
insertTag: (tag: InputTag, replace?: {
|
|
8
|
+
start: number;
|
|
9
|
+
end: number;
|
|
10
|
+
}) => void;
|
|
11
|
+
}
|
|
12
|
+
export interface InlineTagInputProps {
|
|
13
|
+
value: string;
|
|
14
|
+
tags: InputTag[];
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
onChange: (value: string) => void;
|
|
18
|
+
onTagsChange: (tags: InputTag[]) => void;
|
|
19
|
+
onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;
|
|
20
|
+
onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;
|
|
21
|
+
renderTag?: (tag: InputTag, info: InlineTagRenderInfo) => React.ReactNode;
|
|
22
|
+
}
|
|
23
|
+
declare const InlineTagInput: React.ForwardRefExoticComponent<InlineTagInputProps & React.RefAttributes<InlineTagInputRef>>;
|
|
24
|
+
export default InlineTagInput;
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
2
|
+
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from "react";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
import { useStyles } from "./styles";
|
|
5
|
+
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
6
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
+
var TAG_ATTR = "data-xadk-inline-tag-id";
|
|
8
|
+
// contenteditable 无法把光标放进 contenteditable=false 的标签里,需用零宽字符承接“标签后方”的光标。
|
|
9
|
+
var CARET_TEXT = "\u200B";
|
|
10
|
+
var createTextNode = function createTextNode(text) {
|
|
11
|
+
return document.createTextNode(text);
|
|
12
|
+
};
|
|
13
|
+
var normalizeText = function normalizeText(text) {
|
|
14
|
+
return text.replace(/\u200B/g, "").replace(/\u00a0/g, " ");
|
|
15
|
+
};
|
|
16
|
+
var getPlainLength = function getPlainLength(text) {
|
|
17
|
+
return normalizeText(text).length;
|
|
18
|
+
};
|
|
19
|
+
// DOM 文本里包含零宽光标锚点,快捷键替换和光标定位都要在“用户可见文本 offset”和 DOM raw offset 之间转换。
|
|
20
|
+
var toRawOffset = function toRawOffset(text, plainOffset) {
|
|
21
|
+
var current = 0;
|
|
22
|
+
for (var i = 0; i < text.length; i++) {
|
|
23
|
+
if (current >= plainOffset) return i;
|
|
24
|
+
if (text[i] !== CARET_TEXT) current += 1;
|
|
25
|
+
}
|
|
26
|
+
return text.length;
|
|
27
|
+
};
|
|
28
|
+
var InlineTagInput = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
29
|
+
var value = _ref.value,
|
|
30
|
+
tags = _ref.tags,
|
|
31
|
+
placeholder = _ref.placeholder,
|
|
32
|
+
disabled = _ref.disabled,
|
|
33
|
+
onChange = _ref.onChange,
|
|
34
|
+
onTagsChange = _ref.onTagsChange,
|
|
35
|
+
onKeyDown = _ref.onKeyDown,
|
|
36
|
+
onKeyUp = _ref.onKeyUp,
|
|
37
|
+
renderTag = _ref.renderTag;
|
|
38
|
+
var styles = useStyles();
|
|
39
|
+
var editorRef = useRef(null);
|
|
40
|
+
var latestTagsRef = useRef(tags);
|
|
41
|
+
var tagRootMapRef = useRef(new WeakMap());
|
|
42
|
+
var composingRef = useRef(false);
|
|
43
|
+
var lastInsertedCaretRef = useRef(null);
|
|
44
|
+
useEffect(function () {
|
|
45
|
+
latestTagsRef.current = tags;
|
|
46
|
+
}, [tags]);
|
|
47
|
+
var getOrderedTags = useCallback(function () {
|
|
48
|
+
var editor = editorRef.current;
|
|
49
|
+
if (!editor) return [];
|
|
50
|
+
var tagMap = new Map(latestTagsRef.current.map(function (tag) {
|
|
51
|
+
return [tag.id, tag];
|
|
52
|
+
}));
|
|
53
|
+
return Array.from(editor.querySelectorAll("[".concat(TAG_ATTR, "]"))).map(function (node) {
|
|
54
|
+
return tagMap.get(node.dataset.xadkInlineTagId || "");
|
|
55
|
+
}).filter(Boolean);
|
|
56
|
+
}, []);
|
|
57
|
+
|
|
58
|
+
// 对外只暴露用户输入的纯文本,内部零宽锚点不进入 value。
|
|
59
|
+
var getPlainText = useCallback(function () {
|
|
60
|
+
var editor = editorRef.current;
|
|
61
|
+
if (!editor) return "";
|
|
62
|
+
var text = "";
|
|
63
|
+
editor.childNodes.forEach(function (node) {
|
|
64
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
65
|
+
text += node.textContent || "";
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return normalizeText(text);
|
|
69
|
+
}, []);
|
|
70
|
+
var emitChange = useCallback(function () {
|
|
71
|
+
onChange(getPlainText());
|
|
72
|
+
onTagsChange(getOrderedTags());
|
|
73
|
+
}, [getOrderedTags, getPlainText, onChange, onTagsChange]);
|
|
74
|
+
var removeTextRange = useCallback(function (node, start, end) {
|
|
75
|
+
var text = node.textContent || "";
|
|
76
|
+
node.textContent = "".concat(text.slice(0, start)).concat(text.slice(end));
|
|
77
|
+
if (!node.textContent) node.remove();
|
|
78
|
+
}, []);
|
|
79
|
+
var removeTagNode = useCallback(function (node) {
|
|
80
|
+
var _tagRootMapRef$curren;
|
|
81
|
+
var previous = node.previousSibling;
|
|
82
|
+
var next = node.nextSibling;
|
|
83
|
+
(_tagRootMapRef$curren = tagRootMapRef.current.get(node)) === null || _tagRootMapRef$curren === void 0 || _tagRootMapRef$curren.unmount();
|
|
84
|
+
node.remove();
|
|
85
|
+
|
|
86
|
+
// 标签后会补一个不可见光标锚点;删除标签时同步清理,避免留下冗余节点。
|
|
87
|
+
if ((next === null || next === void 0 ? void 0 : next.nodeType) === Node.TEXT_NODE) {
|
|
88
|
+
var _text$match;
|
|
89
|
+
var text = next.textContent || "";
|
|
90
|
+
var caretLength = ((_text$match = text.match(/^\u200B+/)) === null || _text$match === void 0 ? void 0 : _text$match[0].length) || 0;
|
|
91
|
+
if (caretLength > 0) {
|
|
92
|
+
removeTextRange(next, 0, caretLength);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if ((previous === null || previous === void 0 ? void 0 : previous.nodeType) === Node.TEXT_NODE) {
|
|
97
|
+
var _text$match2;
|
|
98
|
+
var _text = previous.textContent || "";
|
|
99
|
+
var spaceLength = ((_text$match2 = _text.match(/\s+$/)) === null || _text$match2 === void 0 ? void 0 : _text$match2[0].length) || 0;
|
|
100
|
+
if (spaceLength > 0) {
|
|
101
|
+
removeTextRange(previous, _text.length - spaceLength, _text.length);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}, [removeTextRange]);
|
|
105
|
+
var removeTagById = useCallback(function (id) {
|
|
106
|
+
var editor = editorRef.current;
|
|
107
|
+
var node = Array.from((editor === null || editor === void 0 ? void 0 : editor.querySelectorAll("[".concat(TAG_ATTR, "]"))) || []).find(function (item) {
|
|
108
|
+
return item.dataset.xadkInlineTagId === id;
|
|
109
|
+
});
|
|
110
|
+
if (node) {
|
|
111
|
+
removeTagNode(node);
|
|
112
|
+
}
|
|
113
|
+
emitChange();
|
|
114
|
+
editor === null || editor === void 0 || editor.focus();
|
|
115
|
+
}, [emitChange, removeTagNode]);
|
|
116
|
+
|
|
117
|
+
// 标签节点本身不可编辑;删除入口通过 onRemove 回到组件内部统一维护 DOM 与 tags。
|
|
118
|
+
var buildTagNode = useCallback(function (tag) {
|
|
119
|
+
var span = document.createElement("span");
|
|
120
|
+
span.setAttribute("contenteditable", "false");
|
|
121
|
+
span.setAttribute(TAG_ATTR, tag.id);
|
|
122
|
+
span.dataset.xadkInlineTagId = tag.id;
|
|
123
|
+
span.className = styles.inlineTag;
|
|
124
|
+
if (renderTag) {
|
|
125
|
+
var root = createRoot(span);
|
|
126
|
+
tagRootMapRef.current.set(span, root);
|
|
127
|
+
root.render( /*#__PURE__*/_jsx(_Fragment, {
|
|
128
|
+
children: renderTag(tag, {
|
|
129
|
+
onRemove: function onRemove() {
|
|
130
|
+
return removeTagById(tag.id);
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
}));
|
|
134
|
+
} else {
|
|
135
|
+
var label = document.createElement("span");
|
|
136
|
+
label.className = "xadk-inline-tag-label";
|
|
137
|
+
label.textContent = tag.label;
|
|
138
|
+
var close = document.createElement("span");
|
|
139
|
+
close.className = "xadk-inline-tag-close";
|
|
140
|
+
close.innerHTML = "×";
|
|
141
|
+
close.onclick = function (event) {
|
|
142
|
+
event.preventDefault();
|
|
143
|
+
event.stopPropagation();
|
|
144
|
+
removeTagById(tag.id);
|
|
145
|
+
};
|
|
146
|
+
span.append(label, close);
|
|
147
|
+
}
|
|
148
|
+
return span;
|
|
149
|
+
}, [removeTagById, renderTag, styles.inlineTag]);
|
|
150
|
+
var setCursorAtTextEnd = useCallback(function (node) {
|
|
151
|
+
var _node$textContent;
|
|
152
|
+
var range = document.createRange();
|
|
153
|
+
var selection = window.getSelection();
|
|
154
|
+
range.setStart(node, ((_node$textContent = node.textContent) === null || _node$textContent === void 0 ? void 0 : _node$textContent.length) || 0);
|
|
155
|
+
range.collapse(true);
|
|
156
|
+
selection === null || selection === void 0 || selection.removeAllRanges();
|
|
157
|
+
selection === null || selection === void 0 || selection.addRange(range);
|
|
158
|
+
}, []);
|
|
159
|
+
var restoreCursorAfterInsert = useCallback(function (node) {
|
|
160
|
+
var editor = editorRef.current;
|
|
161
|
+
if (!editor || !editor.contains(node)) return;
|
|
162
|
+
editor.focus();
|
|
163
|
+
setCursorAtTextEnd(node);
|
|
164
|
+
}, [setCursorAtTextEnd]);
|
|
165
|
+
var isTagNode = function isTagNode(node) {
|
|
166
|
+
return node instanceof HTMLElement && node.hasAttribute(TAG_ATTR);
|
|
167
|
+
};
|
|
168
|
+
var isOnlyCaretText = function isOnlyCaretText(text) {
|
|
169
|
+
return normalizeText(text) === "";
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Backspace/Delete 需要跨过零宽锚点识别相邻标签,不能只看光标所在文本节点。
|
|
173
|
+
var getTagBeforeRange = function getTagBeforeRange(range) {
|
|
174
|
+
var container = range.startContainer;
|
|
175
|
+
if (container.nodeType === Node.TEXT_NODE) {
|
|
176
|
+
var text = container.textContent || "";
|
|
177
|
+
var beforeCursor = text.slice(0, range.startOffset);
|
|
178
|
+
if (isOnlyCaretText(beforeCursor) && isTagNode(container.previousSibling)) {
|
|
179
|
+
return container.previousSibling;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (container instanceof HTMLElement) {
|
|
183
|
+
var previous = container.childNodes[range.startOffset - 1];
|
|
184
|
+
if (isTagNode(previous)) return previous;
|
|
185
|
+
if ((previous === null || previous === void 0 ? void 0 : previous.nodeType) === Node.TEXT_NODE && isOnlyCaretText(previous.textContent || "") && isTagNode(previous.previousSibling)) {
|
|
186
|
+
return previous.previousSibling;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return null;
|
|
190
|
+
};
|
|
191
|
+
var getTagAfterRange = function getTagAfterRange(range) {
|
|
192
|
+
var container = range.startContainer;
|
|
193
|
+
if (container.nodeType === Node.TEXT_NODE) {
|
|
194
|
+
var text = container.textContent || "";
|
|
195
|
+
var afterCursor = text.slice(range.startOffset);
|
|
196
|
+
if (isOnlyCaretText(afterCursor) && isTagNode(container.nextSibling)) {
|
|
197
|
+
return container.nextSibling;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (container instanceof HTMLElement) {
|
|
201
|
+
var next = container.childNodes[range.startOffset];
|
|
202
|
+
if (isTagNode(next)) return next;
|
|
203
|
+
if ((next === null || next === void 0 ? void 0 : next.nodeType) === Node.TEXT_NODE && isOnlyCaretText(next.textContent || "") && isTagNode(next.nextSibling)) {
|
|
204
|
+
return next.nextSibling;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// 读取光标在纯文本中的位置,供快捷键搜索词和 tag 插入位置复用。
|
|
211
|
+
var getOffsetInEditor = useCallback(function () {
|
|
212
|
+
var editor = editorRef.current;
|
|
213
|
+
var selection = window.getSelection();
|
|
214
|
+
if (!editor || !selection || selection.rangeCount === 0) return 0;
|
|
215
|
+
var range = selection.getRangeAt(0);
|
|
216
|
+
var offset = 0;
|
|
217
|
+
var found = false;
|
|
218
|
+
var visit = function visit(node) {
|
|
219
|
+
if (found) return;
|
|
220
|
+
if (node === range.startContainer) {
|
|
221
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
222
|
+
offset += getPlainLength((node.textContent || "").slice(0, range.startOffset));
|
|
223
|
+
}
|
|
224
|
+
found = true;
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (node instanceof HTMLElement && node.hasAttribute(TAG_ATTR)) return;
|
|
228
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
229
|
+
offset += getPlainLength(node.textContent || "");
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
node.childNodes.forEach(visit);
|
|
233
|
+
};
|
|
234
|
+
editor.childNodes.forEach(visit);
|
|
235
|
+
return offset;
|
|
236
|
+
}, []);
|
|
237
|
+
var getNodeIndex = function getNodeIndex(node) {
|
|
238
|
+
var index = 0;
|
|
239
|
+
var current = node;
|
|
240
|
+
while (current.previousSibling) {
|
|
241
|
+
index += 1;
|
|
242
|
+
current = current.previousSibling;
|
|
243
|
+
}
|
|
244
|
+
return index;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// 删除快捷键触发片段,例如把 “@文档” 替换成一个结构化 tag,并返回删除位置对应的真实 DOM Range。
|
|
248
|
+
// 注意:纯文本 offset 不包含 tag,标签前后可能都是 offset 0;插入 tag 必须依赖真实 Range,不能再反推 offset。
|
|
249
|
+
var replaceTextRange = useCallback(function (start, end) {
|
|
250
|
+
var editor = editorRef.current;
|
|
251
|
+
if (!editor) return null;
|
|
252
|
+
var offset = 0;
|
|
253
|
+
var insertRange = null;
|
|
254
|
+
var nodes = Array.from(editor.childNodes);
|
|
255
|
+
nodes.forEach(function (node) {
|
|
256
|
+
if (node.nodeType !== Node.TEXT_NODE) return;
|
|
257
|
+
var text = node.textContent || "";
|
|
258
|
+
var nodeStart = offset;
|
|
259
|
+
var plainLength = getPlainLength(text);
|
|
260
|
+
var nodeEnd = offset + plainLength;
|
|
261
|
+
offset = nodeEnd;
|
|
262
|
+
if (nodeEnd <= start || nodeStart >= end) return;
|
|
263
|
+
var rawStart = toRawOffset(text, Math.max(0, start - nodeStart));
|
|
264
|
+
var rawEnd = toRawOffset(text, Math.max(0, end - nodeStart));
|
|
265
|
+
var keepLeft = text.slice(0, rawStart);
|
|
266
|
+
var keepRight = text.slice(rawEnd);
|
|
267
|
+
var parent = node.parentNode;
|
|
268
|
+
var nodeIndex = getNodeIndex(node);
|
|
269
|
+
node.textContent = "".concat(keepLeft).concat(keepRight);
|
|
270
|
+
if (!insertRange) {
|
|
271
|
+
insertRange = document.createRange();
|
|
272
|
+
if (node.textContent) {
|
|
273
|
+
insertRange.setStart(node, rawStart);
|
|
274
|
+
} else if (parent) {
|
|
275
|
+
insertRange.setStart(parent, nodeIndex);
|
|
276
|
+
}
|
|
277
|
+
insertRange.collapse(true);
|
|
278
|
+
}
|
|
279
|
+
if (!node.textContent) node.remove();
|
|
280
|
+
});
|
|
281
|
+
return insertRange;
|
|
282
|
+
}, []);
|
|
283
|
+
|
|
284
|
+
// 浏览器拆分 Range 后可能留下空文本节点;清理后才能保证后续 tag 继续 append 在队尾。
|
|
285
|
+
var cleanupCaretTextNodes = useCallback(function () {
|
|
286
|
+
var editor = editorRef.current;
|
|
287
|
+
if (!editor) return;
|
|
288
|
+
Array.from(editor.childNodes).forEach(function (node) {
|
|
289
|
+
if (node.nodeType !== Node.TEXT_NODE) return;
|
|
290
|
+
var text = node.textContent || "";
|
|
291
|
+
if (!text) {
|
|
292
|
+
node.remove();
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
if (text && normalizeText(text) === "") {
|
|
296
|
+
node.textContent = CARET_TEXT;
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}, []);
|
|
300
|
+
var insertTag = useCallback(function (tag, replace) {
|
|
301
|
+
var editor = editorRef.current;
|
|
302
|
+
if (!editor) return;
|
|
303
|
+
editor.focus();
|
|
304
|
+
latestTagsRef.current = [].concat(_toConsumableArray(latestTagsRef.current.filter(function (item) {
|
|
305
|
+
return item.id !== tag.id;
|
|
306
|
+
})), [tag]);
|
|
307
|
+
var insertRange = null;
|
|
308
|
+
if (replace) {
|
|
309
|
+
insertRange = replaceTextRange(replace.start, replace.end);
|
|
310
|
+
cleanupCaretTextNodes();
|
|
311
|
+
}
|
|
312
|
+
var tagNode = buildTagNode(tag);
|
|
313
|
+
var caretNode = createTextNode(CARET_TEXT);
|
|
314
|
+
var selection = window.getSelection();
|
|
315
|
+
var range = insertRange || (selection !== null && selection !== void 0 && selection.rangeCount ? selection.getRangeAt(0) : null);
|
|
316
|
+
if (range && editor.contains(range.startContainer)) {
|
|
317
|
+
// 用 DocumentFragment 一次性插入,避免连续 insertNode 导致 tag/caret 顺序被浏览器 Range 状态打乱。
|
|
318
|
+
var fragment = document.createDocumentFragment();
|
|
319
|
+
fragment.append(tagNode, caretNode);
|
|
320
|
+
range.insertNode(fragment);
|
|
321
|
+
} else {
|
|
322
|
+
editor.append(tagNode, caretNode);
|
|
323
|
+
}
|
|
324
|
+
cleanupCaretTextNodes();
|
|
325
|
+
lastInsertedCaretRef.current = caretNode;
|
|
326
|
+
setCursorAtTextEnd(caretNode);
|
|
327
|
+
emitChange();
|
|
328
|
+
|
|
329
|
+
// 关闭快捷列表和父组件同步 tags/value 会触发一次 React 更新;
|
|
330
|
+
// 下一帧再恢复到刚插入 tag 后的零宽锚点,避免光标被 focus 或重渲染带回旧位置。
|
|
331
|
+
window.requestAnimationFrame(function () {
|
|
332
|
+
if (lastInsertedCaretRef.current === caretNode) {
|
|
333
|
+
restoreCursorAfterInsert(caretNode);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
}, [buildTagNode, cleanupCaretTextNodes, emitChange, replaceTextRange, restoreCursorAfterInsert, setCursorAtTextEnd]);
|
|
337
|
+
useImperativeHandle(ref, function () {
|
|
338
|
+
return {
|
|
339
|
+
focus: function focus() {
|
|
340
|
+
var _editorRef$current;
|
|
341
|
+
return (_editorRef$current = editorRef.current) === null || _editorRef$current === void 0 ? void 0 : _editorRef$current.focus();
|
|
342
|
+
},
|
|
343
|
+
getText: getPlainText,
|
|
344
|
+
getCursorOffset: getOffsetInEditor,
|
|
345
|
+
insertTag: insertTag
|
|
346
|
+
};
|
|
347
|
+
}, [getOffsetInEditor, getPlainText, insertTag]);
|
|
348
|
+
useEffect(function () {
|
|
349
|
+
var editor = editorRef.current;
|
|
350
|
+
if (!editor || editor.childNodes.length > 0) return;
|
|
351
|
+
if (value) editor.appendChild(createTextNode(value));
|
|
352
|
+
tags.forEach(function (tag) {
|
|
353
|
+
return editor.append(buildTagNode(tag), createTextNode(CARET_TEXT));
|
|
354
|
+
});
|
|
355
|
+
}, []);
|
|
356
|
+
|
|
357
|
+
// 外部受控 tags 变化时,同步补齐或删除 DOM 中的 tag 节点。
|
|
358
|
+
useEffect(function () {
|
|
359
|
+
var editor = editorRef.current;
|
|
360
|
+
if (!editor) return;
|
|
361
|
+
var existingNodes = Array.from(editor.querySelectorAll("[".concat(TAG_ATTR, "]")));
|
|
362
|
+
var nextTagMap = new Map(tags.map(function (tag) {
|
|
363
|
+
return [tag.id, tag];
|
|
364
|
+
}));
|
|
365
|
+
var existingIds = new Set(existingNodes.map(function (node) {
|
|
366
|
+
return node.dataset.xadkInlineTagId || "";
|
|
367
|
+
}));
|
|
368
|
+
existingNodes.forEach(function (node) {
|
|
369
|
+
var tagId = node.dataset.xadkInlineTagId || "";
|
|
370
|
+
if (!nextTagMap.has(tagId)) {
|
|
371
|
+
removeTagNode(node);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
tags.forEach(function (tag) {
|
|
375
|
+
if (existingIds.has(tag.id)) return;
|
|
376
|
+
editor.append(buildTagNode(tag), createTextNode(CARET_TEXT));
|
|
377
|
+
});
|
|
378
|
+
}, [buildTagNode, removeTagNode, tags]);
|
|
379
|
+
useEffect(function () {
|
|
380
|
+
var editor = editorRef.current;
|
|
381
|
+
if (!editor) return;
|
|
382
|
+
if (!value && tags.length === 0 && editor.childNodes.length > 0) {
|
|
383
|
+
editor.querySelectorAll("[".concat(TAG_ATTR, "]")).forEach(function (node) {
|
|
384
|
+
var _tagRootMapRef$curren2;
|
|
385
|
+
(_tagRootMapRef$curren2 = tagRootMapRef.current.get(node)) === null || _tagRootMapRef$curren2 === void 0 || _tagRootMapRef$curren2.unmount();
|
|
386
|
+
});
|
|
387
|
+
editor.innerHTML = "";
|
|
388
|
+
}
|
|
389
|
+
}, [tags.length, value]);
|
|
390
|
+
var handleInput = function handleInput() {
|
|
391
|
+
if (!composingRef.current) emitChange();
|
|
392
|
+
};
|
|
393
|
+
var handleKeyDown = function handleKeyDown(event) {
|
|
394
|
+
if (event.key === "Backspace" || event.key === "Delete") {
|
|
395
|
+
var selection = window.getSelection();
|
|
396
|
+
if (selection !== null && selection !== void 0 && selection.rangeCount) {
|
|
397
|
+
var range = selection.getRangeAt(0);
|
|
398
|
+
if (range.collapsed) {
|
|
399
|
+
var targetTag = event.key === "Backspace" ? getTagBeforeRange(range) : getTagAfterRange(range);
|
|
400
|
+
if (targetTag) {
|
|
401
|
+
event.preventDefault();
|
|
402
|
+
removeTagById(targetTag.dataset.xadkInlineTagId || "");
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
onKeyDown === null || onKeyDown === void 0 || onKeyDown(event);
|
|
409
|
+
};
|
|
410
|
+
return /*#__PURE__*/_jsx("div", {
|
|
411
|
+
className: styles.inlineInputWrapper,
|
|
412
|
+
"data-placeholder": placeholder,
|
|
413
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
414
|
+
ref: editorRef,
|
|
415
|
+
className: styles.inlineInput,
|
|
416
|
+
contentEditable: !disabled,
|
|
417
|
+
suppressContentEditableWarning: true,
|
|
418
|
+
role: "textbox",
|
|
419
|
+
"aria-multiline": "true",
|
|
420
|
+
onInput: handleInput,
|
|
421
|
+
onKeyDown: handleKeyDown,
|
|
422
|
+
onKeyUp: onKeyUp,
|
|
423
|
+
onCompositionStart: function onCompositionStart() {
|
|
424
|
+
composingRef.current = true;
|
|
425
|
+
},
|
|
426
|
+
onCompositionEnd: function onCompositionEnd() {
|
|
427
|
+
composingRef.current = false;
|
|
428
|
+
emitChange();
|
|
429
|
+
},
|
|
430
|
+
"data-empty": !getPlainText() && getOrderedTags().length === 0,
|
|
431
|
+
"data-cursor-offset": getOffsetInEditor()
|
|
432
|
+
})
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
InlineTagInput.displayName = "InlineTagInput";
|
|
436
|
+
export default InlineTagInput;
|
|
437
|
+
//# sourceMappingURL=InlineTagInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","forwardRef","useCallback","useEffect","useImperativeHandle","useRef","createRoot","useStyles","Fragment","_Fragment","jsx","_jsx","TAG_ATTR","CARET_TEXT","createTextNode","text","document","normalizeText","replace","getPlainLength","length","toRawOffset","plainOffset","current","i","InlineTagInput","_ref","ref","value","tags","placeholder","disabled","onChange","onTagsChange","onKeyDown","onKeyUp","renderTag","styles","editorRef","latestTagsRef","tagRootMapRef","WeakMap","composingRef","lastInsertedCaretRef","getOrderedTags","editor","tagMap","Map","map","tag","id","Array","from","querySelectorAll","concat","node","get","dataset","xadkInlineTagId","filter","Boolean","getPlainText","childNodes","forEach","nodeType","Node","TEXT_NODE","textContent","emitChange","removeTextRange","start","end","slice","remove","removeTagNode","_tagRootMapRef$curren","previous","previousSibling","next","nextSibling","unmount","_text$match","caretLength","match","_text$match2","spaceLength","removeTagById","find","item","focus","buildTagNode","span","createElement","setAttribute","className","inlineTag","root","set","render","children","onRemove","label","close","innerHTML","onclick","event","preventDefault","stopPropagation","append","setCursorAtTextEnd","_node$textContent","range","createRange","selection","window","getSelection","setStart","collapse","removeAllRanges","addRange","restoreCursorAfterInsert","contains","isTagNode","HTMLElement","hasAttribute","isOnlyCaretText","getTagBeforeRange","container","startContainer","beforeCursor","startOffset","getTagAfterRange","afterCursor","getOffsetInEditor","rangeCount","getRangeAt","offset","found","visit","getNodeIndex","index","replaceTextRange","insertRange","nodes","nodeStart","plainLength","nodeEnd","rawStart","Math","max","rawEnd","keepLeft","keepRight","parent","parentNode","nodeIndex","cleanupCaretTextNodes","insertTag","_toConsumableArray","tagNode","caretNode","fragment","createDocumentFragment","insertNode","requestAnimationFrame","_editorRef$current","getText","getCursorOffset","appendChild","existingNodes","nextTagMap","existingIds","Set","tagId","has","_tagRootMapRef$curren2","handleInput","handleKeyDown","key","collapsed","targetTag","inlineInputWrapper","inlineInput","contentEditable","suppressContentEditableWarning","role","onInput","onCompositionStart","onCompositionEnd","displayName"],"sources":["../../../../src/components/XAdkSender/InlineTagInput.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n} from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport type { InlineTagRenderInfo, InputTag } from \"@/types\";\nimport { useStyles } from \"./styles\";\n\nexport interface InlineTagInputRef {\n focus: () => void;\n getText: () => string;\n getCursorOffset: () => number;\n insertTag: (tag: InputTag, replace?: { start: number; end: number }) => void;\n}\n\nexport interface InlineTagInputProps {\n value: string;\n tags: InputTag[];\n placeholder?: string;\n disabled?: boolean;\n onChange: (value: string) => void;\n onTagsChange: (tags: InputTag[]) => void;\n onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;\n onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;\n renderTag?: (tag: InputTag, info: InlineTagRenderInfo) => React.ReactNode;\n}\n\nconst TAG_ATTR = \"data-xadk-inline-tag-id\";\n// contenteditable 无法把光标放进 contenteditable=false 的标签里,需用零宽字符承接“标签后方”的光标。\nconst CARET_TEXT = \"\\u200B\";\n\nconst createTextNode = (text: string) => document.createTextNode(text);\nconst normalizeText = (text: string) =>\n text.replace(/\\u200B/g, \"\").replace(/\\u00a0/g, \" \");\nconst getPlainLength = (text: string) => normalizeText(text).length;\n// DOM 文本里包含零宽光标锚点,快捷键替换和光标定位都要在“用户可见文本 offset”和 DOM raw offset 之间转换。\nconst toRawOffset = (text: string, plainOffset: number) => {\n let current = 0;\n for (let i = 0; i < text.length; i++) {\n if (current >= plainOffset) return i;\n if (text[i] !== CARET_TEXT) current += 1;\n }\n return text.length;\n};\n\nconst InlineTagInput = forwardRef<InlineTagInputRef, InlineTagInputProps>(\n (\n {\n value,\n tags,\n placeholder,\n disabled,\n onChange,\n onTagsChange,\n onKeyDown,\n onKeyUp,\n renderTag,\n },\n ref,\n ) => {\n const styles = useStyles();\n const editorRef = useRef<HTMLDivElement>(null);\n const latestTagsRef = useRef<InputTag[]>(tags);\n const tagRootMapRef = useRef<WeakMap<Element, Root>>(new WeakMap());\n const composingRef = useRef(false);\n const lastInsertedCaretRef = useRef<Text | null>(null);\n\n useEffect(() => {\n latestTagsRef.current = tags;\n }, [tags]);\n\n const getOrderedTags = useCallback(() => {\n const editor = editorRef.current;\n if (!editor) return [];\n const tagMap = new Map(latestTagsRef.current.map((tag) => [tag.id, tag]));\n return Array.from(editor.querySelectorAll(`[${TAG_ATTR}]`))\n .map((node) => tagMap.get((node as HTMLElement).dataset.xadkInlineTagId || \"\"))\n .filter(Boolean) as InputTag[];\n }, []);\n\n // 对外只暴露用户输入的纯文本,内部零宽锚点不进入 value。\n const getPlainText = useCallback(() => {\n const editor = editorRef.current;\n if (!editor) return \"\";\n let text = \"\";\n editor.childNodes.forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n text += node.textContent || \"\";\n }\n });\n return normalizeText(text);\n }, []);\n\n const emitChange = useCallback(() => {\n onChange(getPlainText());\n onTagsChange(getOrderedTags());\n }, [getOrderedTags, getPlainText, onChange, onTagsChange]);\n\n const removeTextRange = useCallback((node: Text, start: number, end: number) => {\n const text = node.textContent || \"\";\n node.textContent = `${text.slice(0, start)}${text.slice(end)}`;\n if (!node.textContent) node.remove();\n }, []);\n\n const removeTagNode = useCallback(\n (node: Element) => {\n const previous = node.previousSibling;\n const next = node.nextSibling;\n\n tagRootMapRef.current.get(node)?.unmount();\n node.remove();\n\n // 标签后会补一个不可见光标锚点;删除标签时同步清理,避免留下冗余节点。\n if (next?.nodeType === Node.TEXT_NODE) {\n const text = next.textContent || \"\";\n const caretLength = text.match(/^\\u200B+/)?.[0].length || 0;\n if (caretLength > 0) {\n removeTextRange(next as Text, 0, caretLength);\n return;\n }\n }\n\n if (previous?.nodeType === Node.TEXT_NODE) {\n const text = previous.textContent || \"\";\n const spaceLength = text.match(/\\s+$/)?.[0].length || 0;\n if (spaceLength > 0) {\n removeTextRange(previous as Text, text.length - spaceLength, text.length);\n }\n }\n },\n [removeTextRange],\n );\n\n const removeTagById = useCallback(\n (id: string) => {\n const editor = editorRef.current;\n const node = Array.from(editor?.querySelectorAll(`[${TAG_ATTR}]`) || []).find(\n (item) => (item as HTMLElement).dataset.xadkInlineTagId === id,\n );\n if (node) {\n removeTagNode(node);\n }\n emitChange();\n editor?.focus();\n },\n [emitChange, removeTagNode],\n );\n\n // 标签节点本身不可编辑;删除入口通过 onRemove 回到组件内部统一维护 DOM 与 tags。\n const buildTagNode = useCallback(\n (tag: InputTag) => {\n const span = document.createElement(\"span\");\n span.setAttribute(\"contenteditable\", \"false\");\n span.setAttribute(TAG_ATTR, tag.id);\n span.dataset.xadkInlineTagId = tag.id;\n span.className = styles.inlineTag;\n\n if (renderTag) {\n const root = createRoot(span);\n tagRootMapRef.current.set(span, root);\n root.render(\n <>{renderTag(tag, { onRemove: () => removeTagById(tag.id) })}</>,\n );\n } else {\n const label = document.createElement(\"span\");\n label.className = \"xadk-inline-tag-label\";\n label.textContent = tag.label;\n const close = document.createElement(\"span\");\n close.className = \"xadk-inline-tag-close\";\n close.innerHTML = \"×\";\n close.onclick = (event) => {\n event.preventDefault();\n event.stopPropagation();\n removeTagById(tag.id);\n };\n span.append(label, close);\n }\n return span;\n },\n [removeTagById, renderTag, styles.inlineTag],\n );\n\n const setCursorAtTextEnd = useCallback((node: Text) => {\n const range = document.createRange();\n const selection = window.getSelection();\n range.setStart(node, node.textContent?.length || 0);\n range.collapse(true);\n selection?.removeAllRanges();\n selection?.addRange(range);\n }, []);\n\n const restoreCursorAfterInsert = useCallback(\n (node: Text) => {\n const editor = editorRef.current;\n if (!editor || !editor.contains(node)) return;\n editor.focus();\n setCursorAtTextEnd(node);\n },\n [setCursorAtTextEnd],\n );\n\n const isTagNode = (node: Node | null): node is HTMLElement =>\n node instanceof HTMLElement && node.hasAttribute(TAG_ATTR);\n\n const isOnlyCaretText = (text: string) => normalizeText(text) === \"\";\n\n // Backspace/Delete 需要跨过零宽锚点识别相邻标签,不能只看光标所在文本节点。\n const getTagBeforeRange = (range: Range) => {\n const container = range.startContainer;\n if (container.nodeType === Node.TEXT_NODE) {\n const text = container.textContent || \"\";\n const beforeCursor = text.slice(0, range.startOffset);\n if (isOnlyCaretText(beforeCursor) && isTagNode(container.previousSibling)) {\n return container.previousSibling;\n }\n }\n\n if (container instanceof HTMLElement) {\n const previous = container.childNodes[range.startOffset - 1];\n if (isTagNode(previous)) return previous;\n if (\n previous?.nodeType === Node.TEXT_NODE &&\n isOnlyCaretText(previous.textContent || \"\") &&\n isTagNode(previous.previousSibling)\n ) {\n return previous.previousSibling;\n }\n }\n\n return null;\n };\n\n const getTagAfterRange = (range: Range) => {\n const container = range.startContainer;\n if (container.nodeType === Node.TEXT_NODE) {\n const text = container.textContent || \"\";\n const afterCursor = text.slice(range.startOffset);\n if (isOnlyCaretText(afterCursor) && isTagNode(container.nextSibling)) {\n return container.nextSibling;\n }\n }\n\n if (container instanceof HTMLElement) {\n const next = container.childNodes[range.startOffset];\n if (isTagNode(next)) return next;\n if (\n next?.nodeType === Node.TEXT_NODE &&\n isOnlyCaretText(next.textContent || \"\") &&\n isTagNode(next.nextSibling)\n ) {\n return next.nextSibling;\n }\n }\n\n return null;\n };\n\n // 读取光标在纯文本中的位置,供快捷键搜索词和 tag 插入位置复用。\n const getOffsetInEditor = useCallback(() => {\n const editor = editorRef.current;\n const selection = window.getSelection();\n if (!editor || !selection || selection.rangeCount === 0) return 0;\n const range = selection.getRangeAt(0);\n let offset = 0;\n let found = false;\n\n const visit = (node: Node) => {\n if (found) return;\n if (node === range.startContainer) {\n if (node.nodeType === Node.TEXT_NODE) {\n offset += getPlainLength(\n (node.textContent || \"\").slice(0, range.startOffset),\n );\n }\n found = true;\n return;\n }\n if (node instanceof HTMLElement && node.hasAttribute(TAG_ATTR)) return;\n if (node.nodeType === Node.TEXT_NODE) {\n offset += getPlainLength(node.textContent || \"\");\n return;\n }\n node.childNodes.forEach(visit);\n };\n\n editor.childNodes.forEach(visit);\n return offset;\n }, []);\n\n const getNodeIndex = (node: Node) => {\n let index = 0;\n let current = node;\n while (current.previousSibling) {\n index += 1;\n current = current.previousSibling;\n }\n return index;\n };\n\n // 删除快捷键触发片段,例如把 “@文档” 替换成一个结构化 tag,并返回删除位置对应的真实 DOM Range。\n // 注意:纯文本 offset 不包含 tag,标签前后可能都是 offset 0;插入 tag 必须依赖真实 Range,不能再反推 offset。\n const replaceTextRange = useCallback((start: number, end: number) => {\n const editor = editorRef.current;\n if (!editor) return null;\n let offset = 0;\n let insertRange: Range | null = null;\n const nodes = Array.from(editor.childNodes);\n nodes.forEach((node) => {\n if (node.nodeType !== Node.TEXT_NODE) return;\n const text = node.textContent || \"\";\n const nodeStart = offset;\n const plainLength = getPlainLength(text);\n const nodeEnd = offset + plainLength;\n offset = nodeEnd;\n if (nodeEnd <= start || nodeStart >= end) return;\n const rawStart = toRawOffset(text, Math.max(0, start - nodeStart));\n const rawEnd = toRawOffset(text, Math.max(0, end - nodeStart));\n const keepLeft = text.slice(0, rawStart);\n const keepRight = text.slice(rawEnd);\n const parent = node.parentNode;\n const nodeIndex = getNodeIndex(node);\n\n node.textContent = `${keepLeft}${keepRight}`;\n if (!insertRange) {\n insertRange = document.createRange();\n if (node.textContent) {\n insertRange.setStart(node, rawStart);\n } else if (parent) {\n insertRange.setStart(parent, nodeIndex);\n }\n insertRange.collapse(true);\n }\n if (!node.textContent) node.remove();\n });\n\n return insertRange;\n }, []);\n\n // 浏览器拆分 Range 后可能留下空文本节点;清理后才能保证后续 tag 继续 append 在队尾。\n const cleanupCaretTextNodes = useCallback(() => {\n const editor = editorRef.current;\n if (!editor) return;\n Array.from(editor.childNodes).forEach((node) => {\n if (node.nodeType !== Node.TEXT_NODE) return;\n const text = node.textContent || \"\";\n if (!text) {\n node.remove();\n return;\n }\n if (text && normalizeText(text) === \"\") {\n node.textContent = CARET_TEXT;\n }\n });\n }, []);\n\n const insertTag = useCallback(\n (tag: InputTag, replace?: { start: number; end: number }) => {\n const editor = editorRef.current;\n if (!editor) return;\n editor.focus();\n latestTagsRef.current = [\n ...latestTagsRef.current.filter((item) => item.id !== tag.id),\n tag,\n ];\n let insertRange: Range | null = null;\n if (replace) {\n insertRange = replaceTextRange(replace.start, replace.end);\n cleanupCaretTextNodes();\n }\n const tagNode = buildTagNode(tag);\n const caretNode = createTextNode(CARET_TEXT);\n const selection = window.getSelection();\n const range =\n insertRange || (selection?.rangeCount ? selection.getRangeAt(0) : null);\n if (range && editor.contains(range.startContainer)) {\n // 用 DocumentFragment 一次性插入,避免连续 insertNode 导致 tag/caret 顺序被浏览器 Range 状态打乱。\n const fragment = document.createDocumentFragment();\n fragment.append(tagNode, caretNode);\n range.insertNode(fragment);\n } else {\n editor.append(tagNode, caretNode);\n }\n cleanupCaretTextNodes();\n lastInsertedCaretRef.current = caretNode;\n setCursorAtTextEnd(caretNode);\n emitChange();\n\n // 关闭快捷列表和父组件同步 tags/value 会触发一次 React 更新;\n // 下一帧再恢复到刚插入 tag 后的零宽锚点,避免光标被 focus 或重渲染带回旧位置。\n window.requestAnimationFrame(() => {\n if (lastInsertedCaretRef.current === caretNode) {\n restoreCursorAfterInsert(caretNode);\n }\n });\n },\n [\n buildTagNode,\n cleanupCaretTextNodes,\n emitChange,\n replaceTextRange,\n restoreCursorAfterInsert,\n setCursorAtTextEnd,\n ],\n );\n\n useImperativeHandle(ref, () => ({\n focus: () => editorRef.current?.focus(),\n getText: getPlainText,\n getCursorOffset: getOffsetInEditor,\n insertTag,\n }), [getOffsetInEditor, getPlainText, insertTag]);\n\n useEffect(() => {\n const editor = editorRef.current;\n if (!editor || editor.childNodes.length > 0) return;\n if (value) editor.appendChild(createTextNode(value));\n tags.forEach((tag) => editor.append(buildTagNode(tag), createTextNode(CARET_TEXT)));\n }, []);\n\n // 外部受控 tags 变化时,同步补齐或删除 DOM 中的 tag 节点。\n useEffect(() => {\n const editor = editorRef.current;\n if (!editor) return;\n const existingNodes = Array.from(editor.querySelectorAll(`[${TAG_ATTR}]`));\n const nextTagMap = new Map(tags.map((tag) => [tag.id, tag]));\n const existingIds = new Set(\n existingNodes.map((node) => (node as HTMLElement).dataset.xadkInlineTagId || \"\"),\n );\n\n existingNodes.forEach((node) => {\n const tagId = (node as HTMLElement).dataset.xadkInlineTagId || \"\";\n if (!nextTagMap.has(tagId)) {\n removeTagNode(node);\n }\n });\n\n tags.forEach((tag) => {\n if (existingIds.has(tag.id)) return;\n editor.append(buildTagNode(tag), createTextNode(CARET_TEXT));\n });\n }, [buildTagNode, removeTagNode, tags]);\n\n useEffect(() => {\n const editor = editorRef.current;\n if (!editor) return;\n if (!value && tags.length === 0 && editor.childNodes.length > 0) {\n editor.querySelectorAll(`[${TAG_ATTR}]`).forEach((node) => {\n tagRootMapRef.current.get(node)?.unmount();\n });\n editor.innerHTML = \"\";\n }\n }, [tags.length, value]);\n\n const handleInput = () => {\n if (!composingRef.current) emitChange();\n };\n\n const handleKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (event) => {\n if (event.key === \"Backspace\" || event.key === \"Delete\") {\n const selection = window.getSelection();\n if (selection?.rangeCount) {\n const range = selection.getRangeAt(0);\n if (range.collapsed) {\n const targetTag =\n event.key === \"Backspace\"\n ? getTagBeforeRange(range)\n : getTagAfterRange(range);\n\n if (targetTag) {\n event.preventDefault();\n removeTagById(targetTag.dataset.xadkInlineTagId || \"\");\n return;\n }\n }\n }\n }\n onKeyDown?.(event);\n };\n\n return (\n <div className={styles.inlineInputWrapper} data-placeholder={placeholder}>\n <div\n ref={editorRef}\n className={styles.inlineInput}\n contentEditable={!disabled}\n suppressContentEditableWarning\n role=\"textbox\"\n aria-multiline=\"true\"\n onInput={handleInput}\n onKeyDown={handleKeyDown}\n onKeyUp={onKeyUp}\n onCompositionStart={() => {\n composingRef.current = true;\n }}\n onCompositionEnd={() => {\n composingRef.current = false;\n emitChange();\n }}\n data-empty={!getPlainText() && getOrderedTags().length === 0}\n data-cursor-offset={getOffsetInEditor()}\n />\n </div>\n );\n },\n);\n\nInlineTagInput.displayName = \"InlineTagInput\";\n\nexport default InlineTagInput;\n"],"mappings":"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"}
|