@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.
@@ -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
- if (!e.clipboardData?.getData("text/plain") && files?.length && ctx.onPasteFile) {
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
- ctx.onPaste?.(e);
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
- }, { onPaste: onInternalPaste }, {
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 };
@@ -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
- [`&:empty::before`]: {
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
- if (Array.isArray(nextItems)) itemList.value = nextItems;
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
- if (typeof props.items === "function") itemList.value = props.items(nextInfo);
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 {};