@antdv-next/x 1.2.1 → 1.2.3-beta.1
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/index.d.ts +1 -1
- package/dist/index.umd.js +13195 -761
- package/dist/package.js +1 -1
- package/dist/sender/Sender.d.ts +23 -5
- package/dist/sender/Sender.js +13 -3
- package/dist/sender/components/Skill.d.ts +11 -1
- package/dist/sender/components/Skill.js +31 -3
- package/dist/sender/components/SlotTextAreaProseMirror.js +1144 -0
- package/dist/sender/components/TextArea.js +44 -3
- package/dist/sender/components/prosemirror/model.d.ts +15 -0
- package/dist/sender/components/prosemirror/model.js +276 -0
- package/dist/sender/components/prosemirror/value.d.ts +11 -0
- package/dist/sender/components/prosemirror/value.js +171 -0
- package/dist/sender/index.d.ts +2 -2
- package/dist/sender/interface.d.ts +14 -1
- package/dist/sender/style/slot-textarea.js +9 -2
- package/dist/suggestion/Suggestion.js +37 -6
- package/dist/suggestion/useActive.d.ts +1 -1
- package/dist/suggestion/useActive.js +42 -2
- package/dist/thought-chain/style/index.d.ts +71 -3
- package/dist/thought-chain/style/index.js +25 -14
- package/dist/thought-chain/style/item.d.ts +5 -5
- package/dist/thought-chain/style/item.js +5 -5
- package/dist/thought-chain/style/thought-chain.d.ts +2 -1
- package/dist/thought-chain/style/thought-chain.js +8 -20
- package/es/antdv-next-x.esm.js +14988 -6949
- package/package.json +7 -1
- package/dist/sender/components/SlotTextArea.js +0 -808
- /package/dist/sender/components/{SlotTextArea.d.ts → SlotTextAreaProseMirror.d.ts} +0 -0
|
@@ -64,11 +64,48 @@ var TextArea_default = /* @__PURE__ */ defineComponent({
|
|
|
64
64
|
const onInternalPaste = (e) => {
|
|
65
65
|
const ctx = senderCtx.value;
|
|
66
66
|
const files = e.clipboardData?.files;
|
|
67
|
-
|
|
67
|
+
const text = e.clipboardData?.getData("text/plain");
|
|
68
|
+
const info = {
|
|
69
|
+
text: text ?? "",
|
|
70
|
+
slotConfig: [],
|
|
71
|
+
skill: void 0
|
|
72
|
+
};
|
|
73
|
+
ctx.onPaste?.(e, info);
|
|
74
|
+
if (!e.defaultPrevented && !ctx.disabled && !ctx.readOnly && !text && files?.length && ctx.onPasteFile) {
|
|
68
75
|
ctx.onPasteFile(files);
|
|
69
76
|
e.preventDefault();
|
|
70
77
|
}
|
|
71
|
-
|
|
78
|
+
};
|
|
79
|
+
const getSelectedText = () => {
|
|
80
|
+
const el = getNativeEl();
|
|
81
|
+
if (!el) return "";
|
|
82
|
+
const start = el.selectionStart ?? 0;
|
|
83
|
+
const end = el.selectionEnd ?? start;
|
|
84
|
+
return el.value.slice(start, end);
|
|
85
|
+
};
|
|
86
|
+
const onInternalCopy = (e) => {
|
|
87
|
+
const ctx = senderCtx.value;
|
|
88
|
+
if (!ctx.onCopy) return;
|
|
89
|
+
const text = getSelectedText();
|
|
90
|
+
const info = {
|
|
91
|
+
value: text,
|
|
92
|
+
slotConfig: [],
|
|
93
|
+
skill: void 0,
|
|
94
|
+
text
|
|
95
|
+
};
|
|
96
|
+
ctx.onCopy(e, info);
|
|
97
|
+
};
|
|
98
|
+
const onInternalCut = (e) => {
|
|
99
|
+
const ctx = senderCtx.value;
|
|
100
|
+
if (!ctx.onCut) return;
|
|
101
|
+
const text = getSelectedText();
|
|
102
|
+
const info = {
|
|
103
|
+
value: text,
|
|
104
|
+
slotConfig: [],
|
|
105
|
+
skill: void 0,
|
|
106
|
+
text
|
|
107
|
+
};
|
|
108
|
+
ctx.onCut(e, info);
|
|
72
109
|
};
|
|
73
110
|
return () => {
|
|
74
111
|
const ctx = senderCtx.value;
|
|
@@ -91,7 +128,11 @@ var TextArea_default = /* @__PURE__ */ defineComponent({
|
|
|
91
128
|
isComposing.value = false;
|
|
92
129
|
},
|
|
93
130
|
"onKeydown": onInternalKeyDown
|
|
94
|
-
}, {
|
|
131
|
+
}, {
|
|
132
|
+
onPaste: onInternalPaste,
|
|
133
|
+
onCopy: onInternalCopy,
|
|
134
|
+
onCut: onInternalCut
|
|
135
|
+
}, {
|
|
95
136
|
"variant": "borderless",
|
|
96
137
|
"readonly": ctx.readOnly,
|
|
97
138
|
"placeholder": ctx.placeholder,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Node as ProseMirrorNode, Schema } from 'prosemirror-model';
|
|
2
|
+
import { SkillType, SlotConfigType } from '../../interface';
|
|
3
|
+
import { HistoryValueStore } from './value';
|
|
4
|
+
export declare const senderSchema: Schema<"text" | "doc" | "slot" | "skill" | "hardBreak" | "contentSlot", any>;
|
|
5
|
+
export declare function stringifyValue(value: unknown): string;
|
|
6
|
+
export declare function getSlotValue(config: SlotConfigType): unknown;
|
|
7
|
+
export declare function createDocument(configs: readonly SlotConfigType[] | undefined, skill: SkillType | undefined, values: HistoryValueStore): ProseMirrorNode;
|
|
8
|
+
export type EditorResult = {
|
|
9
|
+
value: string;
|
|
10
|
+
slotConfig: SlotConfigType[];
|
|
11
|
+
skill?: SkillType;
|
|
12
|
+
};
|
|
13
|
+
export declare function documentToResult(doc: ProseMirrorNode, values: HistoryValueStore, definitions: ReadonlyMap<string, SlotConfigType>, skills: ReadonlyMap<string, SkillType>): EditorResult;
|
|
14
|
+
export declare function isEquivalentDocument(doc: ProseMirrorNode, configs: readonly SlotConfigType[] | undefined, skill: SkillType | undefined, values: HistoryValueStore, definitions: ReadonlyMap<string, SlotConfigType>): boolean;
|
|
15
|
+
export declare function collectDefinitions(definitions: Map<string, SlotConfigType>, configs: readonly SlotConfigType[] | undefined): void;
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { isSameValue, snapshotValue } from "./value.js";
|
|
2
|
+
import { Schema } from "prosemirror-model";
|
|
3
|
+
//#region components/sender/components/prosemirror/model.ts
|
|
4
|
+
function stringifyLabel(value) {
|
|
5
|
+
if (value === void 0 || value === null || typeof value === "boolean") return "";
|
|
6
|
+
if (typeof value === "string" || typeof value === "number") return `${value}`;
|
|
7
|
+
if (Array.isArray(value)) return value.map(stringifyLabel).join("");
|
|
8
|
+
if (value.__v_isVNode) {
|
|
9
|
+
const children = value.children;
|
|
10
|
+
if (typeof children === "function") return stringifyLabel(children());
|
|
11
|
+
if (children && typeof children === "object" && !Array.isArray(children)) {
|
|
12
|
+
const defaultSlot = children.default;
|
|
13
|
+
if (typeof defaultSlot === "function") return stringifyLabel(defaultSlot());
|
|
14
|
+
}
|
|
15
|
+
return stringifyLabel(children);
|
|
16
|
+
}
|
|
17
|
+
return stringifyValue(value);
|
|
18
|
+
}
|
|
19
|
+
var senderSchema = new Schema({ nodes: {
|
|
20
|
+
doc: { content: "inline*" },
|
|
21
|
+
text: { group: "inline" },
|
|
22
|
+
hardBreak: {
|
|
23
|
+
group: "inline",
|
|
24
|
+
inline: true,
|
|
25
|
+
selectable: false,
|
|
26
|
+
parseDOM: [{ tag: "br" }],
|
|
27
|
+
toDOM: () => ["br"]
|
|
28
|
+
},
|
|
29
|
+
slot: {
|
|
30
|
+
group: "inline",
|
|
31
|
+
inline: true,
|
|
32
|
+
atom: true,
|
|
33
|
+
selectable: true,
|
|
34
|
+
attrs: {
|
|
35
|
+
key: {},
|
|
36
|
+
type: {},
|
|
37
|
+
valueId: {},
|
|
38
|
+
selectionStart: { default: null },
|
|
39
|
+
selectionEnd: { default: null },
|
|
40
|
+
selectionDirection: { default: "none" }
|
|
41
|
+
},
|
|
42
|
+
toDOM: (node) => ["span", {
|
|
43
|
+
"data-slot-key": node.attrs.key,
|
|
44
|
+
"data-slot-type": node.attrs.type
|
|
45
|
+
}]
|
|
46
|
+
},
|
|
47
|
+
contentSlot: {
|
|
48
|
+
group: "inline",
|
|
49
|
+
inline: true,
|
|
50
|
+
content: "(text | hardBreak)*",
|
|
51
|
+
isolating: true,
|
|
52
|
+
selectable: true,
|
|
53
|
+
attrs: { key: {} },
|
|
54
|
+
toDOM: (node) => [
|
|
55
|
+
"span",
|
|
56
|
+
{ "data-content-key": node.attrs.key },
|
|
57
|
+
[
|
|
58
|
+
"span",
|
|
59
|
+
{ "data-slot-key": node.attrs.key },
|
|
60
|
+
0
|
|
61
|
+
]
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
skill: {
|
|
65
|
+
group: "inline",
|
|
66
|
+
inline: true,
|
|
67
|
+
atom: true,
|
|
68
|
+
selectable: true,
|
|
69
|
+
attrs: { value: {} },
|
|
70
|
+
toDOM: (node) => ["span", { "data-skill-key": node.attrs.value }]
|
|
71
|
+
}
|
|
72
|
+
} });
|
|
73
|
+
function stringifyValue(value) {
|
|
74
|
+
if (value === void 0 || value === null) return "";
|
|
75
|
+
if (typeof value === "string") return value;
|
|
76
|
+
if (typeof value === "number" || typeof value === "boolean") return `${value}`;
|
|
77
|
+
try {
|
|
78
|
+
return JSON.stringify(value);
|
|
79
|
+
} catch {
|
|
80
|
+
return "";
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function getSlotValue(config) {
|
|
84
|
+
if (config.type === "text") return config.value ?? "";
|
|
85
|
+
const rawConfig = config;
|
|
86
|
+
if (Object.prototype.hasOwnProperty.call(rawConfig, "value")) return rawConfig.value;
|
|
87
|
+
if (config.type === "tag") return config.props?.value ?? stringifyLabel(config.props?.label);
|
|
88
|
+
if (config.type === "select") {
|
|
89
|
+
const defaultValue = config.props?.defaultValue;
|
|
90
|
+
const options = config.props?.options ?? [];
|
|
91
|
+
if (defaultValue !== void 0 && !options.includes(defaultValue)) return options[0] ?? "";
|
|
92
|
+
return defaultValue ?? "";
|
|
93
|
+
}
|
|
94
|
+
return config.props?.defaultValue ?? "";
|
|
95
|
+
}
|
|
96
|
+
function createDocument(configs, skill, values) {
|
|
97
|
+
const nodes = [];
|
|
98
|
+
if (skill?.value) nodes.push(senderSchema.nodes.skill.create({ value: skill.value }));
|
|
99
|
+
(configs ?? []).forEach((config) => {
|
|
100
|
+
if (config.type === "text") {
|
|
101
|
+
if (config.value) nodes.push(senderSchema.text(config.value));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (config.type === "content") {
|
|
105
|
+
const text = stringifyValue(getSlotValue(config));
|
|
106
|
+
const contentNodes = [];
|
|
107
|
+
if (text) {
|
|
108
|
+
const lines = text.split("\n");
|
|
109
|
+
lines.forEach((line, index) => {
|
|
110
|
+
if (line) contentNodes.push(senderSchema.text(line));
|
|
111
|
+
if (index < lines.length - 1) contentNodes.push(senderSchema.nodes.hardBreak.create());
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
nodes.push(senderSchema.nodes.contentSlot.create({ key: config.key }, contentNodes.length > 0 ? contentNodes : void 0));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
nodes.push(senderSchema.nodes.slot.create({
|
|
118
|
+
key: config.key,
|
|
119
|
+
type: config.type,
|
|
120
|
+
valueId: values.add(getSlotValue(config))
|
|
121
|
+
}));
|
|
122
|
+
});
|
|
123
|
+
return senderSchema.nodes.doc.create(void 0, nodes);
|
|
124
|
+
}
|
|
125
|
+
function documentToResult(doc, values, definitions, skills) {
|
|
126
|
+
const text = [];
|
|
127
|
+
const slotConfig = [];
|
|
128
|
+
let skill;
|
|
129
|
+
doc.forEach((node) => {
|
|
130
|
+
if (node.isText) {
|
|
131
|
+
const value = node.text ?? "";
|
|
132
|
+
text.push(value);
|
|
133
|
+
if (value) slotConfig.push({
|
|
134
|
+
type: "text",
|
|
135
|
+
value
|
|
136
|
+
});
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (node.type === senderSchema.nodes.hardBreak) {
|
|
140
|
+
text.push("\n");
|
|
141
|
+
slotConfig.push({
|
|
142
|
+
type: "text",
|
|
143
|
+
value: "\n"
|
|
144
|
+
});
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (node.type === senderSchema.nodes.skill) {
|
|
148
|
+
skill = skills.get(node.attrs.value);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const key = node.attrs.key;
|
|
152
|
+
const definition = definitions.get(key);
|
|
153
|
+
if (!definition) return;
|
|
154
|
+
let rawValue;
|
|
155
|
+
let displayValue;
|
|
156
|
+
if (node.type === senderSchema.nodes.contentSlot) {
|
|
157
|
+
const parts = [];
|
|
158
|
+
node.forEach((child) => {
|
|
159
|
+
if (child.isText) parts.push(child.text ?? "");
|
|
160
|
+
else if (child.type === senderSchema.nodes.hardBreak) parts.push("\n");
|
|
161
|
+
});
|
|
162
|
+
rawValue = parts.join("");
|
|
163
|
+
displayValue = definition.formatResult?.(rawValue) ?? stringifyValue(rawValue);
|
|
164
|
+
} else {
|
|
165
|
+
rawValue = values.read(node.attrs.valueId);
|
|
166
|
+
displayValue = definition.formatResult?.(rawValue) ?? stringifyValue(rawValue);
|
|
167
|
+
}
|
|
168
|
+
if (definition.type === "content") text.push(displayValue);
|
|
169
|
+
else text.push(displayValue);
|
|
170
|
+
const structuredValue = definition.type === "custom" ? snapshotValue(rawValue) : displayValue;
|
|
171
|
+
slotConfig.push({
|
|
172
|
+
...definition,
|
|
173
|
+
value: structuredValue
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
return {
|
|
177
|
+
value: text.join(""),
|
|
178
|
+
slotConfig,
|
|
179
|
+
skill
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function configsToComparable(configs, skill) {
|
|
183
|
+
const result = [];
|
|
184
|
+
if (skill?.value) result.push({
|
|
185
|
+
kind: "skill",
|
|
186
|
+
value: skill.value
|
|
187
|
+
});
|
|
188
|
+
(configs ?? []).forEach((config) => {
|
|
189
|
+
if (config.type === "text") {
|
|
190
|
+
if (config.value) result.push({
|
|
191
|
+
kind: "text",
|
|
192
|
+
value: config.value
|
|
193
|
+
});
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
result.push({
|
|
197
|
+
kind: "slot",
|
|
198
|
+
key: config.key,
|
|
199
|
+
type: config.type,
|
|
200
|
+
value: getSlotValue(config),
|
|
201
|
+
definition: config
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
function docToComparable(doc, values, definitions) {
|
|
207
|
+
const result = [];
|
|
208
|
+
doc.forEach((node) => {
|
|
209
|
+
if (node.isText) {
|
|
210
|
+
if (node.text) result.push({
|
|
211
|
+
kind: "text",
|
|
212
|
+
value: node.text
|
|
213
|
+
});
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (node.type === senderSchema.nodes.hardBreak) {
|
|
217
|
+
result.push({
|
|
218
|
+
kind: "text",
|
|
219
|
+
value: "\n"
|
|
220
|
+
});
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (node.type === senderSchema.nodes.skill) {
|
|
224
|
+
result.push({
|
|
225
|
+
kind: "skill",
|
|
226
|
+
value: node.attrs.value
|
|
227
|
+
});
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const key = node.attrs.key;
|
|
231
|
+
const definition = definitions.get(key);
|
|
232
|
+
if (!definition) return;
|
|
233
|
+
let value;
|
|
234
|
+
if (node.type === senderSchema.nodes.contentSlot) {
|
|
235
|
+
const parts = [];
|
|
236
|
+
node.forEach((child) => {
|
|
237
|
+
if (child.isText) parts.push(child.text ?? "");
|
|
238
|
+
else if (child.type === senderSchema.nodes.hardBreak) parts.push("\n");
|
|
239
|
+
});
|
|
240
|
+
value = parts.join("");
|
|
241
|
+
} else value = values.peek(node.attrs.valueId);
|
|
242
|
+
result.push({
|
|
243
|
+
kind: "slot",
|
|
244
|
+
key,
|
|
245
|
+
type: definition.type,
|
|
246
|
+
value,
|
|
247
|
+
definition
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
function isEquivalentDocument(doc, configs, skill, values, definitions) {
|
|
253
|
+
const expected = configsToComparable(configs, skill);
|
|
254
|
+
const current = docToComparable(doc, values, definitions);
|
|
255
|
+
return expected.length === current.length && expected.every((node, index) => {
|
|
256
|
+
const currentNode = current[index];
|
|
257
|
+
if (!currentNode || node.kind !== currentNode.kind) return false;
|
|
258
|
+
if (node.kind === "text" && currentNode.kind === "text") return node.value === currentNode.value;
|
|
259
|
+
if (node.kind === "skill" && currentNode.kind === "skill") return node.value === currentNode.value;
|
|
260
|
+
if (node.kind !== "slot" || currentNode.kind !== "slot") return false;
|
|
261
|
+
if (node.key !== currentNode.key || node.type !== currentNode.type) return false;
|
|
262
|
+
if (isSameValue(node.value, currentNode.value)) return true;
|
|
263
|
+
if (node.type !== "custom") {
|
|
264
|
+
const currentDisplayValue = currentNode.definition.formatResult?.(currentNode.value) ?? stringifyValue(currentNode.value);
|
|
265
|
+
return isSameValue(node.value, currentDisplayValue);
|
|
266
|
+
}
|
|
267
|
+
return false;
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
function collectDefinitions(definitions, configs) {
|
|
271
|
+
(configs ?? []).forEach((config) => {
|
|
272
|
+
if (config.type !== "text") definitions.set(config.key, config);
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
//#endregion
|
|
276
|
+
export { collectDefinitions, createDocument, documentToResult, getSlotValue, isEquivalentDocument, senderSchema, stringifyValue };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function isSafelyCloneableValue(value: unknown, seen?: WeakSet<object>): boolean;
|
|
2
|
+
export declare function snapshotValue<T>(value: T): T;
|
|
3
|
+
export declare function isSameValue(left: unknown, right: unknown): boolean;
|
|
4
|
+
export declare class HistoryValueStore {
|
|
5
|
+
private nextId;
|
|
6
|
+
private readonly values;
|
|
7
|
+
add(value: unknown): string;
|
|
8
|
+
read<T = unknown>(id: string): T;
|
|
9
|
+
peek<T = unknown>(id: string): T;
|
|
10
|
+
isSame(id: string, value: unknown): boolean;
|
|
11
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { toRaw } from "vue";
|
|
2
|
+
//#region components/sender/components/prosemirror/value.ts
|
|
3
|
+
var VALUE_COMPARE_LIMIT = 2048;
|
|
4
|
+
var asRaw = (value) => value && typeof value === "object" ? toRaw(value) : value;
|
|
5
|
+
function isSafelyCloneableValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
6
|
+
if (value === null || typeof value !== "object") return typeof value !== "function" && typeof value !== "symbol";
|
|
7
|
+
const rawValue = asRaw(value);
|
|
8
|
+
if (seen.has(rawValue)) return true;
|
|
9
|
+
seen.add(rawValue);
|
|
10
|
+
if (rawValue.__v_isVNode || typeof Node !== "undefined" && rawValue instanceof Node || rawValue instanceof Promise || rawValue instanceof WeakMap || rawValue instanceof WeakSet || typeof SharedArrayBuffer !== "undefined" && rawValue instanceof SharedArrayBuffer) return false;
|
|
11
|
+
if (rawValue instanceof Date || rawValue instanceof RegExp || rawValue instanceof ArrayBuffer) return true;
|
|
12
|
+
if (ArrayBuffer.isView(rawValue)) return isSafelyCloneableValue(rawValue.buffer, seen);
|
|
13
|
+
if (rawValue instanceof Map) return Array.from(rawValue).every(([key, entryValue]) => isSafelyCloneableValue(key, seen) && isSafelyCloneableValue(entryValue, seen));
|
|
14
|
+
if (rawValue instanceof Set) return Array.from(rawValue).every((entryValue) => isSafelyCloneableValue(entryValue, seen));
|
|
15
|
+
const prototype = Object.getPrototypeOf(rawValue);
|
|
16
|
+
if (!Array.isArray(rawValue) && prototype !== Object.prototype && prototype !== null) return false;
|
|
17
|
+
return Reflect.ownKeys(rawValue).every((key) => {
|
|
18
|
+
if (typeof key === "symbol") return false;
|
|
19
|
+
const descriptor = Object.getOwnPropertyDescriptor(rawValue, key);
|
|
20
|
+
return !!descriptor && "value" in descriptor && isSafelyCloneableValue(descriptor.value, seen);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function snapshotValue(value) {
|
|
24
|
+
const rawValue = asRaw(value);
|
|
25
|
+
if (!isSafelyCloneableValue(rawValue)) return rawValue;
|
|
26
|
+
const clones = /* @__PURE__ */ new WeakMap();
|
|
27
|
+
const clone = (input) => {
|
|
28
|
+
if (input === null || typeof input !== "object") return input;
|
|
29
|
+
const rawInput = asRaw(input);
|
|
30
|
+
const existing = clones.get(rawInput);
|
|
31
|
+
if (existing) return existing;
|
|
32
|
+
if (rawInput instanceof Date) return new Date(rawInput.getTime());
|
|
33
|
+
if (rawInput instanceof RegExp) {
|
|
34
|
+
const result = new RegExp(rawInput.source, rawInput.flags);
|
|
35
|
+
result.lastIndex = rawInput.lastIndex;
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
if (rawInput instanceof ArrayBuffer) return rawInput.slice(0);
|
|
39
|
+
if (ArrayBuffer.isView(rawInput)) return structuredClone(rawInput);
|
|
40
|
+
if (rawInput instanceof Error) {
|
|
41
|
+
const result = Object.create(Object.getPrototypeOf(rawInput));
|
|
42
|
+
clones.set(rawInput, result);
|
|
43
|
+
result.message = rawInput.message;
|
|
44
|
+
result.name = rawInput.name;
|
|
45
|
+
result.stack = rawInput.stack;
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
if (rawInput instanceof Map) {
|
|
49
|
+
const result = /* @__PURE__ */ new Map();
|
|
50
|
+
clones.set(rawInput, result);
|
|
51
|
+
rawInput.forEach((entryValue, key) => {
|
|
52
|
+
result.set(clone(key), clone(entryValue));
|
|
53
|
+
});
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
if (rawInput instanceof Set) {
|
|
57
|
+
const result = /* @__PURE__ */ new Set();
|
|
58
|
+
clones.set(rawInput, result);
|
|
59
|
+
rawInput.forEach((entryValue) => {
|
|
60
|
+
result.add(clone(entryValue));
|
|
61
|
+
});
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
const result = Array.isArray(rawInput) ? [] : Object.create(Object.getPrototypeOf(rawInput));
|
|
65
|
+
clones.set(rawInput, result);
|
|
66
|
+
Reflect.ownKeys(rawInput).forEach((key) => {
|
|
67
|
+
const descriptor = Object.getOwnPropertyDescriptor(rawInput, key);
|
|
68
|
+
Object.defineProperty(result, key, {
|
|
69
|
+
...descriptor,
|
|
70
|
+
value: clone(descriptor.value)
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
return result;
|
|
74
|
+
};
|
|
75
|
+
return clone(rawValue);
|
|
76
|
+
}
|
|
77
|
+
function isSameValue(left, right) {
|
|
78
|
+
const pending = [[left, right]];
|
|
79
|
+
const leftMatches = /* @__PURE__ */ new WeakMap();
|
|
80
|
+
const rightMatches = /* @__PURE__ */ new WeakMap();
|
|
81
|
+
let comparedObjects = 0;
|
|
82
|
+
let pendingPairs = 0;
|
|
83
|
+
const sameBytes = (leftBytes, rightBytes) => leftBytes.byteLength === rightBytes.byteLength && leftBytes.every((value, index) => value === rightBytes[index]);
|
|
84
|
+
while (pending.length) {
|
|
85
|
+
const [pendingLeft, pendingRight] = pending.pop();
|
|
86
|
+
if (Object.is(pendingLeft, pendingRight)) continue;
|
|
87
|
+
if (pendingLeft === null || pendingRight === null || typeof pendingLeft !== "object" || typeof pendingRight !== "object") return false;
|
|
88
|
+
const leftValue = asRaw(pendingLeft);
|
|
89
|
+
const rightValue = asRaw(pendingRight);
|
|
90
|
+
if (Object.is(leftValue, rightValue)) continue;
|
|
91
|
+
if (++comparedObjects > VALUE_COMPARE_LIMIT) return false;
|
|
92
|
+
pendingPairs += pending.length;
|
|
93
|
+
if (pendingPairs > VALUE_COMPARE_LIMIT * 2) return false;
|
|
94
|
+
const matchedRight = leftMatches.get(leftValue);
|
|
95
|
+
if (matchedRight) {
|
|
96
|
+
if (matchedRight !== rightValue) return false;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const matchedLeft = rightMatches.get(rightValue);
|
|
100
|
+
if (matchedLeft) {
|
|
101
|
+
if (matchedLeft !== leftValue) return false;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
leftMatches.set(leftValue, rightValue);
|
|
105
|
+
rightMatches.set(rightValue, leftValue);
|
|
106
|
+
if (leftValue instanceof Date || rightValue instanceof Date) {
|
|
107
|
+
if (!(leftValue instanceof Date) || !(rightValue instanceof Date) || !Object.is(leftValue.getTime(), rightValue.getTime())) return false;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (leftValue instanceof RegExp || rightValue instanceof RegExp) {
|
|
111
|
+
if (!(leftValue instanceof RegExp) || !(rightValue instanceof RegExp) || leftValue.source !== rightValue.source || leftValue.flags !== rightValue.flags || leftValue.lastIndex !== rightValue.lastIndex) return false;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (leftValue instanceof ArrayBuffer || rightValue instanceof ArrayBuffer) {
|
|
115
|
+
if (!(leftValue instanceof ArrayBuffer) || !(rightValue instanceof ArrayBuffer) || !sameBytes(new Uint8Array(leftValue), new Uint8Array(rightValue))) return false;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (ArrayBuffer.isView(leftValue) || ArrayBuffer.isView(rightValue)) {
|
|
119
|
+
if (!ArrayBuffer.isView(leftValue) || !ArrayBuffer.isView(rightValue) || leftValue.constructor !== rightValue.constructor || !sameBytes(new Uint8Array(leftValue.buffer, leftValue.byteOffset, leftValue.byteLength), new Uint8Array(rightValue.buffer, rightValue.byteOffset, rightValue.byteLength))) return false;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (leftValue instanceof Map || rightValue instanceof Map) {
|
|
123
|
+
if (!(leftValue instanceof Map) || !(rightValue instanceof Map) || leftValue.size !== rightValue.size) return false;
|
|
124
|
+
const leftEntries = Array.from(leftValue);
|
|
125
|
+
const rightEntries = Array.from(rightValue);
|
|
126
|
+
for (let index = 0; index < leftEntries.length; index += 1) pending.push([leftEntries[index][0], rightEntries[index][0]], [leftEntries[index][1], rightEntries[index][1]]);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (leftValue instanceof Set || rightValue instanceof Set) {
|
|
130
|
+
if (!(leftValue instanceof Set) || !(rightValue instanceof Set) || leftValue.size !== rightValue.size) return false;
|
|
131
|
+
const leftEntries = Array.from(leftValue);
|
|
132
|
+
const rightEntries = Array.from(rightValue);
|
|
133
|
+
for (let index = 0; index < leftEntries.length; index += 1) pending.push([leftEntries[index], rightEntries[index]]);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const leftIsArray = Array.isArray(leftValue);
|
|
137
|
+
if (leftIsArray !== Array.isArray(rightValue)) return false;
|
|
138
|
+
const leftPrototype = Object.getPrototypeOf(leftValue);
|
|
139
|
+
if (leftPrototype !== Object.getPrototypeOf(rightValue) || !leftIsArray && leftPrototype !== Object.prototype && leftPrototype !== null) return false;
|
|
140
|
+
const leftKeys = Reflect.ownKeys(leftValue);
|
|
141
|
+
const rightKeys = Reflect.ownKeys(rightValue);
|
|
142
|
+
if (leftKeys.length !== rightKeys.length || leftKeys.some((key) => !Object.prototype.hasOwnProperty.call(rightValue, key))) return false;
|
|
143
|
+
for (const key of leftKeys) {
|
|
144
|
+
const leftDescriptor = Object.getOwnPropertyDescriptor(leftValue, key);
|
|
145
|
+
const rightDescriptor = Object.getOwnPropertyDescriptor(rightValue, key);
|
|
146
|
+
if (!leftDescriptor || !rightDescriptor || !("value" in leftDescriptor) || !("value" in rightDescriptor)) return false;
|
|
147
|
+
pending.push([leftDescriptor.value, rightDescriptor.value]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
var HistoryValueStore = class {
|
|
153
|
+
nextId = 0;
|
|
154
|
+
values = /* @__PURE__ */ new Map();
|
|
155
|
+
add(value) {
|
|
156
|
+
const id = `value-${++this.nextId}`;
|
|
157
|
+
this.values.set(id, snapshotValue(value));
|
|
158
|
+
return id;
|
|
159
|
+
}
|
|
160
|
+
read(id) {
|
|
161
|
+
return snapshotValue(this.values.get(id));
|
|
162
|
+
}
|
|
163
|
+
peek(id) {
|
|
164
|
+
return this.values.get(id);
|
|
165
|
+
}
|
|
166
|
+
isSame(id, value) {
|
|
167
|
+
return isSameValue(this.values.get(id), value);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
//#endregion
|
|
171
|
+
export { HistoryValueStore, isSafelyCloneableValue, isSameValue, snapshotValue };
|
package/dist/sender/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { SenderProps, SenderRef, SlotConfigType } from './interface';
|
|
1
|
+
import { SenderCopyInfo, SenderPasteInfo, SenderProps, SenderRef, SlotConfigType } from './interface';
|
|
2
2
|
import { default as ForwardSender } from './Sender';
|
|
3
3
|
import { default as SenderHeader } from './SenderHeader';
|
|
4
4
|
import { default as SenderSwitch } from './SenderSwitch';
|
|
5
|
-
export type { SenderProps, SenderRef, SlotConfigType };
|
|
5
|
+
export type { SenderCopyInfo, SenderPasteInfo, SenderProps, SenderRef, SlotConfigType, };
|
|
6
6
|
type CompoundedSender = typeof ForwardSender & {
|
|
7
7
|
Header: typeof SenderHeader;
|
|
8
8
|
Switch: typeof SenderSwitch;
|
|
@@ -84,6 +84,17 @@ export interface SkillType {
|
|
|
84
84
|
disabled?: boolean;
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
|
+
export interface SenderCopyInfo {
|
|
88
|
+
value: string;
|
|
89
|
+
slotConfig: SlotConfigType[];
|
|
90
|
+
skill?: SkillType;
|
|
91
|
+
text: string;
|
|
92
|
+
}
|
|
93
|
+
export interface SenderPasteInfo {
|
|
94
|
+
text: string;
|
|
95
|
+
slotConfig: SlotConfigType[];
|
|
96
|
+
skill?: SkillType;
|
|
97
|
+
}
|
|
87
98
|
export interface SenderProps {
|
|
88
99
|
prefixCls?: string;
|
|
89
100
|
defaultValue?: string;
|
|
@@ -99,8 +110,10 @@ export interface SenderProps {
|
|
|
99
110
|
onCancel?: () => void;
|
|
100
111
|
onKeyDown?: (event: KeyboardEvent) => void | false;
|
|
101
112
|
onKeyUp?: (event: KeyboardEvent) => void;
|
|
102
|
-
onPaste?: (event: ClipboardEvent) => void;
|
|
113
|
+
onPaste?: (event: ClipboardEvent, info: SenderPasteInfo) => void;
|
|
103
114
|
onPasteFile?: (files: FileList) => void;
|
|
115
|
+
onCopy?: (event: ClipboardEvent, info: SenderCopyInfo) => void;
|
|
116
|
+
onCut?: (event: ClipboardEvent, info: SenderCopyInfo) => void;
|
|
104
117
|
onFocus?: (event: FocusEvent) => void;
|
|
105
118
|
onBlur?: (event: FocusEvent) => void;
|
|
106
119
|
classNames?: Partial<Record<SemanticType, string>>;
|
|
@@ -17,12 +17,19 @@ var genSlotTextAreaStyle = (token) => {
|
|
|
17
17
|
cursor: "text",
|
|
18
18
|
whiteSpace: "pre-wrap",
|
|
19
19
|
width: "100%",
|
|
20
|
+
position: "relative",
|
|
20
21
|
caretColor: token.colorPrimary,
|
|
21
22
|
fontSize: token.fontSize,
|
|
22
23
|
lineHeight: token.lineHeight,
|
|
23
|
-
[
|
|
24
|
+
[`&[data-empty]::before`]: {
|
|
24
25
|
content: "attr(data-placeholder)",
|
|
25
|
-
color: token.colorTextPlaceholder
|
|
26
|
+
color: token.colorTextPlaceholder,
|
|
27
|
+
position: "absolute",
|
|
28
|
+
insetInlineStart: 0,
|
|
29
|
+
top: 0,
|
|
30
|
+
pointerEvents: "none",
|
|
31
|
+
userSelect: "none",
|
|
32
|
+
whiteSpace: "pre-wrap"
|
|
26
33
|
}
|
|
27
34
|
},
|
|
28
35
|
[`${slotCls}:not(${slotContentCls})`]: {
|
|
@@ -85,10 +85,18 @@ var XSuggestion = /* @__PURE__ */ defineComponent({
|
|
|
85
85
|
const innerOpen = ref(false);
|
|
86
86
|
const mergedOpen = computed(() => props.open ?? innerOpen.value);
|
|
87
87
|
const itemList = ref([]);
|
|
88
|
+
/**
|
|
89
|
+
* What the last `onTrigger` asked for. A function `items` is usually an inline arrow,
|
|
90
|
+
* so it gets a new identity on every parent render — without this the watcher below
|
|
91
|
+
* would re-evaluate it with no info and drop the triggered list.
|
|
92
|
+
*/
|
|
93
|
+
const triggerInfo = ref();
|
|
94
|
+
const resolveItems = (source, info) => {
|
|
95
|
+
if (typeof source === "function") return source(info);
|
|
96
|
+
return Array.isArray(source) ? source : [];
|
|
97
|
+
};
|
|
88
98
|
watch(() => props.items, (nextItems) => {
|
|
89
|
-
|
|
90
|
-
else if (typeof nextItems === "function") itemList.value = nextItems();
|
|
91
|
-
else itemList.value = [];
|
|
99
|
+
itemList.value = resolveItems(nextItems, triggerInfo.value);
|
|
92
100
|
}, { immediate: true });
|
|
93
101
|
const triggerOpen = (nextOpen) => {
|
|
94
102
|
if (props.open === void 0) innerOpen.value = nextOpen;
|
|
@@ -103,7 +111,8 @@ var XSuggestion = /* @__PURE__ */ defineComponent({
|
|
|
103
111
|
triggerOpen(false);
|
|
104
112
|
return;
|
|
105
113
|
}
|
|
106
|
-
|
|
114
|
+
triggerInfo.value = nextInfo;
|
|
115
|
+
if (typeof props.items === "function") itemList.value = resolveItems(props.items, nextInfo);
|
|
107
116
|
triggerOpen(true);
|
|
108
117
|
};
|
|
109
118
|
const onInternalChange = (valuePath, selectedOptions) => {
|
|
@@ -113,10 +122,31 @@ var XSuggestion = /* @__PURE__ */ defineComponent({
|
|
|
113
122
|
if (lastValue !== void 0) emit("select", String(lastValue), selected);
|
|
114
123
|
triggerOpen(false);
|
|
115
124
|
};
|
|
116
|
-
const [activePath, onKeyDown] = useActive(itemList, mergedOpen, isRtl, onClose);
|
|
125
|
+
const [activePath, onKeyDown, shouldSelectOnEnter] = useActive(itemList, mergedOpen, isRtl, onClose);
|
|
117
126
|
const onInternalOpenChange = (nextOpen) => {
|
|
118
127
|
if (!nextOpen) onClose();
|
|
119
128
|
};
|
|
129
|
+
/**
|
|
130
|
+
* Cascader renders our children as its raw input element, so every keydown from the
|
|
131
|
+
* children bubbles into BaseSelect's keyboard model. That model is built for a
|
|
132
|
+
* non-editable trigger and breaks typing inside an editable one such as Sender:
|
|
133
|
+
*
|
|
134
|
+
* - Space is always `preventDefault()`ed, so no space can be typed;
|
|
135
|
+
* - Enter is always `preventDefault()`ed, even when there is nothing to select;
|
|
136
|
+
* - Backspace makes the option list step back a level or close the popup.
|
|
137
|
+
*
|
|
138
|
+
* Keep exactly those inside the content wrapper. Every other key — Escape, arrows,
|
|
139
|
+
* application shortcuts — must keep bubbling, otherwise the app around us stops
|
|
140
|
+
* receiving keyboard events while the trigger has focus.
|
|
141
|
+
*/
|
|
142
|
+
const onContentKeyDown = (event) => {
|
|
143
|
+
const { key } = event;
|
|
144
|
+
if (key === "Enter") {
|
|
145
|
+
if (!shouldSelectOnEnter(event)) event.stopPropagation();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (key === " " || key === "Backspace" && mergedOpen.value) event.stopPropagation();
|
|
149
|
+
};
|
|
120
150
|
const domAttrs = computed(() => {
|
|
121
151
|
const { class: _class, style: _style, ...rest } = attrs;
|
|
122
152
|
return rest;
|
|
@@ -190,7 +220,8 @@ var XSuggestion = /* @__PURE__ */ defineComponent({
|
|
|
190
220
|
contextConfig.value.classes?.content,
|
|
191
221
|
mergedClasses.value.content
|
|
192
222
|
],
|
|
193
|
-
"style": [contextConfig.value.styles?.content, mergedStyles.value.content]
|
|
223
|
+
"style": [contextConfig.value.styles?.content, mergedStyles.value.content],
|
|
224
|
+
"onKeydown": onContentKeyDown
|
|
194
225
|
}, [childNode])])] });
|
|
195
226
|
};
|
|
196
227
|
}
|
|
@@ -6,5 +6,5 @@ interface ActiveItem {
|
|
|
6
6
|
/**
|
|
7
7
|
* Cascader does not expose active item control, so we use `value` to mirror focus path.
|
|
8
8
|
*/
|
|
9
|
-
export default function useActive(items: Ref<ActiveItem[]>, open: Ref<boolean>, rtl: Ref<boolean>, onCancel: () => void): readonly [Ref<string[], string[]>, (event: KeyboardEvent) => false | undefined];
|
|
9
|
+
export default function useActive(items: Ref<ActiveItem[]>, open: Ref<boolean>, rtl: Ref<boolean>, onCancel: () => void): readonly [Ref<string[], string[]>, (event: KeyboardEvent) => false | undefined, (event: KeyboardEvent) => boolean];
|
|
10
10
|
export {};
|