@veltra/desktop 1.0.13 → 1.0.15
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/components/action/action-group.js +110 -3
- package/dist/components/action/action-group.js.map +1 -1
- package/dist/components/action/action-group.vue.d.ts +16 -3
- package/dist/components/action/action.js +26 -13
- package/dist/components/action/action.js.map +1 -1
- package/dist/components/action/style.js +2 -1
- package/dist/components/action/style2.css +35 -7
- package/dist/components/batch-edit/batch-edit-form.js +106 -42
- package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
- package/dist/components/batch-edit/batch-edit-list.js +84 -47
- package/dist/components/batch-edit/batch-edit-list.js.map +1 -1
- package/dist/components/batch-edit/batch-edit.js +42 -10
- package/dist/components/batch-edit/batch-edit.js.map +1 -1
- package/dist/components/batch-edit/style.js +2 -4
- package/dist/components/batch-edit/style2.css +202 -30
- package/dist/components/batch-edit/use-edit.js +45 -9
- package/dist/components/batch-edit/use-edit.js.map +1 -1
- package/dist/components/cascade/cascade.js +3 -1
- package/dist/components/cascade/cascade.js.map +1 -1
- package/dist/components/code-editor/code-editor.js +145 -49
- package/dist/components/code-editor/code-editor.js.map +1 -1
- package/dist/components/code-editor/code-editor.vue.d.ts +2 -0
- package/dist/components/code-editor/style2.css +87 -19
- package/dist/components/dialog/dialog.js +6 -2
- package/dist/components/dialog/dialog.js.map +1 -1
- package/dist/components/dialog/style2.css +2 -3
- package/dist/components/expression-editor/components/path-preview.js +27 -0
- package/dist/components/expression-editor/components/path-preview.js.map +1 -0
- package/dist/components/expression-editor/components/variable-picker.js +200 -153
- package/dist/components/expression-editor/components/variable-picker.js.map +1 -1
- package/dist/components/expression-editor/core/chip.js +54 -0
- package/dist/components/expression-editor/core/chip.js.map +1 -0
- package/dist/components/expression-editor/core/editor.js +425 -0
- package/dist/components/expression-editor/core/editor.js.map +1 -0
- package/dist/components/expression-editor/core/mention.js +91 -0
- package/dist/components/expression-editor/core/mention.js.map +1 -0
- package/dist/components/expression-editor/core/model.js +64 -0
- package/dist/components/expression-editor/core/model.js.map +1 -0
- package/dist/components/expression-editor/di.js +4 -10
- package/dist/components/expression-editor/di.js.map +1 -1
- package/dist/components/expression-editor/expression-editor.js +168 -114
- package/dist/components/expression-editor/expression-editor.js.map +1 -1
- package/dist/components/expression-editor/expression-editor.vue.d.ts +2 -1
- package/dist/components/expression-editor/style.js +0 -2
- package/dist/components/expression-editor/style2.css +145 -218
- package/dist/components/index.js +54 -54
- package/dist/components/layout/layout.js +12 -11
- package/dist/components/layout/layout.js.map +1 -1
- package/dist/components/multi-select/multi-select.vue.d.ts +1 -1
- package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +1 -1
- package/dist/components/number-input/number-input.js +4 -4
- package/dist/components/number-input/number-input.js.map +1 -1
- package/dist/components/pop-confirm/pop-confirm.vue.d.ts +1 -1
- package/dist/components/rich-text-editor/rich-text-editor.js +1 -1
- package/dist/components/rich-text-editor/toolbar.js +2 -2
- package/dist/components/steps/steps.vue.d.ts +1 -1
- package/dist/components/table/use-table.js +16 -0
- package/dist/components/table/use-table.js.map +1 -1
- package/dist/components/tabs/tabs-horizontal.vue.d.ts +3 -3
- package/dist/components/tabs/tabs-vertical.vue.d.ts +2 -2
- package/dist/components/tabs/tabs.vue.d.ts +3 -3
- package/dist/components/tip/tip.js +4 -5
- package/dist/components/tip/tip.js.map +1 -1
- package/dist/components/tip/tip.vue.d.ts +1 -1
- package/dist/components/tree/style2.css +18 -12
- package/dist/components/tree/tree-node.js +7 -4
- package/dist/components/tree/tree-node.js.map +1 -1
- package/dist/components/tree-select/tree-select.vue.d.ts +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +83 -83
- package/dist/style.js +3 -3
- package/dist/types/action.d.ts +38 -4
- package/dist/types/cascade.d.ts +2 -3
- package/dist/types/code-editor.d.ts +9 -2
- package/dist/types/expression-editor.d.ts +9 -1
- package/dist/types/index.d.ts +2 -2
- package/package.json +11 -12
- package/src/components/action/action-group.vue +126 -56
- package/src/components/action/action.vue +35 -12
- package/src/components/action/style.scss +46 -10
- package/src/components/action/style.ts +2 -1
- package/src/components/batch-edit/batch-edit-form.vue +121 -45
- package/src/components/batch-edit/batch-edit-list.vue +56 -39
- package/src/components/batch-edit/batch-edit.vue +57 -6
- package/src/components/batch-edit/style.scss +251 -37
- package/src/components/batch-edit/style.ts +5 -8
- package/src/components/batch-edit/use-edit.ts +58 -11
- package/src/components/cascade/cascade.vue +3 -1
- package/src/components/code-editor/code-editor.vue +198 -63
- package/src/components/code-editor/style.scss +110 -12
- package/src/components/dialog/dialog.vue +6 -2
- package/src/components/dialog/style.scss +4 -4
- package/src/components/expression-editor/__test__/chip.test.ts +86 -0
- package/src/components/expression-editor/__test__/editor.test.ts +47 -0
- package/src/components/expression-editor/__test__/mention.test.ts +122 -0
- package/src/components/expression-editor/__test__/model.test.ts +127 -0
- package/src/components/expression-editor/components/path-preview.vue +32 -0
- package/src/components/expression-editor/components/variable-picker.vue +225 -219
- package/src/components/expression-editor/core/chip.ts +101 -0
- package/src/components/expression-editor/core/editor.ts +514 -0
- package/src/components/expression-editor/core/mention.ts +121 -0
- package/src/components/expression-editor/core/model.ts +109 -0
- package/src/components/expression-editor/di.ts +4 -32
- package/src/components/expression-editor/expression-editor.vue +184 -151
- package/src/components/expression-editor/style.scss +148 -219
- package/src/components/expression-editor/style.ts +0 -2
- package/src/components/layout/layout.vue +17 -19
- package/src/components/number-input/number-input.vue +4 -4
- package/src/components/table/use-table.ts +16 -0
- package/src/components/tip/tip.vue +4 -3
- package/src/components/tree/style.scss +30 -33
- package/src/components/tree/tree-node.vue +4 -2
- package/src/types/action.ts +42 -4
- package/src/types/cascade.ts +4 -3
- package/src/types/code-editor.ts +9 -2
- package/src/types/expression-editor.ts +9 -0
- package/dist/components/action/action-group.vue_vue_type_script_setup_true_lang.js +0 -65
- package/dist/components/action/action-group.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/components/expression-editor/constants.js +0 -9
- package/dist/components/expression-editor/constants.js.map +0 -1
- package/dist/components/expression-editor/internal/editor-runtime/create-runtime.js +0 -47
- package/dist/components/expression-editor/internal/editor-runtime/create-runtime.js.map +0 -1
- package/dist/components/expression-editor/internal/editor-runtime/model-sync.js +0 -49
- package/dist/components/expression-editor/internal/editor-runtime/model-sync.js.map +0 -1
- package/dist/components/expression-editor/internal/features/commands/register-command-packs.js +0 -215
- package/dist/components/expression-editor/internal/features/commands/register-command-packs.js.map +0 -1
- package/dist/components/expression-editor/internal/features/drag-drop/drag-drop-service.js +0 -33
- package/dist/components/expression-editor/internal/features/drag-drop/drag-drop-service.js.map +0 -1
- package/dist/components/expression-editor/internal/features/insertion/insertion-service.js +0 -33
- package/dist/components/expression-editor/internal/features/insertion/insertion-service.js.map +0 -1
- package/dist/components/expression-editor/nodes/variable-node.js +0 -94
- package/dist/components/expression-editor/nodes/variable-node.js.map +0 -1
- package/dist/components/expression-editor/parser.js +0 -32
- package/dist/components/expression-editor/parser.js.map +0 -1
- package/dist/components/expression-editor/plain-text.js +0 -19
- package/dist/components/expression-editor/plain-text.js.map +0 -1
- package/dist/components/expression-editor/use-context.js +0 -69
- package/dist/components/expression-editor/use-context.js.map +0 -1
- package/dist/components/expression-editor/use-decorators.js +0 -27
- package/dist/components/expression-editor/use-decorators.js.map +0 -1
- package/dist/components/expression-editor/use-expression-drag-drop.js +0 -275
- package/dist/components/expression-editor/use-expression-drag-drop.js.map +0 -1
- package/src/components/batch-edit/batch-edit-new.vue +0 -168
- package/src/components/batch-edit/style-new.scss +0 -35
- package/src/components/batch-edit/use-edit-new.ts +0 -68
- package/src/components/batch-edit/use-tip.ts +0 -47
- package/src/components/expression-editor/__test__/architecture-boundaries.test.ts +0 -103
- package/src/components/expression-editor/__test__/architecture-compatibility.test.ts +0 -52
- package/src/components/expression-editor/__test__/drag-drop.test.ts +0 -171
- package/src/components/expression-editor/__test__/parser.test.ts +0 -62
- package/src/components/expression-editor/constants.ts +0 -6
- package/src/components/expression-editor/internal/contracts/editor-runtime.ts +0 -11
- package/src/components/expression-editor/internal/editor-runtime/create-runtime.ts +0 -64
- package/src/components/expression-editor/internal/editor-runtime/index.ts +0 -1
- package/src/components/expression-editor/internal/editor-runtime/model-sync.ts +0 -68
- package/src/components/expression-editor/internal/features/commands/register-command-packs.ts +0 -517
- package/src/components/expression-editor/internal/features/drag-drop/drag-drop-service.ts +0 -51
- package/src/components/expression-editor/internal/features/insertion/insertion-service.ts +0 -56
- package/src/components/expression-editor/nodes/variable-node.tsx +0 -118
- package/src/components/expression-editor/parser.ts +0 -46
- package/src/components/expression-editor/plain-text.ts +0 -25
- package/src/components/expression-editor/plan.md +0 -22
- package/src/components/expression-editor/use-context.ts +0 -134
- package/src/components/expression-editor/use-decorators.tsx +0 -29
- package/src/components/expression-editor/use-editor.ts +0 -12
- package/src/components/expression-editor/use-expression-drag-drop.ts +0 -396
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
//#region src/components/expression-editor/di.ts
|
|
2
|
-
/**
|
|
3
|
-
* 扁平化变量树,创建 value -> VariableItem 的映射
|
|
4
|
-
* @param variables 变量列表(支持树形结构)
|
|
5
|
-
* @returns value -> VariableItem 的映射表
|
|
6
|
-
*/
|
|
2
|
+
/** 扁平化变量树,创建 value -> VariableItem 的映射,用于 DOM → 模型反推时补齐 label/type。 */
|
|
7
3
|
function createVariableMap(variables) {
|
|
8
4
|
const map = /* @__PURE__ */ new Map();
|
|
9
|
-
function traverse(items
|
|
5
|
+
function traverse(items) {
|
|
10
6
|
if (!items) return;
|
|
11
7
|
for (const item of items) {
|
|
12
|
-
const currentPath = [...parentPath, item.label];
|
|
13
8
|
map.set(item.value, item);
|
|
14
|
-
if (item.children) traverse(item.children
|
|
9
|
+
if (item.children) traverse(item.children);
|
|
15
10
|
}
|
|
16
11
|
}
|
|
17
12
|
traverse(variables);
|
|
18
13
|
return map;
|
|
19
14
|
}
|
|
20
|
-
const ExpressionEditorDIKey = Symbol("ExpressionEditorDIKey");
|
|
21
15
|
//#endregion
|
|
22
|
-
export {
|
|
16
|
+
export { createVariableMap };
|
|
23
17
|
|
|
24
18
|
//# sourceMappingURL=di.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"di.js","names":[],"sources":["../../../src/components/expression-editor/di.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"di.js","names":[],"sources":["../../../src/components/expression-editor/di.ts"],"sourcesContent":["import type { VariableItem } from '../../types'\n\n/** 扁平化变量树,创建 value -> VariableItem 的映射,用于 DOM → 模型反推时补齐 label/type。 */\nexport function createVariableMap(variables?: VariableItem[]): Map<string, VariableItem> {\n const map = new Map<string, VariableItem>()\n function traverse(items: VariableItem[] | undefined) {\n if (!items) return\n for (const item of items) {\n map.set(item.value, item)\n if (item.children) traverse(item.children)\n }\n }\n traverse(variables)\n return map\n}\n"],"mappings":";;AAGA,SAAgB,kBAAkB,WAAuD;CACvF,MAAM,sBAAM,IAAI,KAA2B;CAC3C,SAAS,SAAS,OAAmC;AACnD,MAAI,CAAC,MAAO;AACZ,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,IAAI,KAAK,OAAO,KAAK;AACzB,OAAI,KAAK,SAAU,UAAS,KAAK,SAAS;;;AAG9C,UAAS,UAAU;AACnB,QAAO"}
|
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
import { ExpressionEditorDIKey, createVariableMap } from "./di.js";
|
|
2
1
|
import _sfc_main$1 from "./components/variable-picker.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { registerPlainText } from "./plain-text.js";
|
|
9
|
-
import { useContext } from "./use-context.js";
|
|
10
|
-
import { useDecorators } from "./use-decorators.js";
|
|
11
|
-
import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, isRef, normalizeClass, onBeforeUnmount, openBlock, provide, renderList, shallowRef, toDisplayString, unref, useTemplateRef } from "vue";
|
|
2
|
+
import { parse } from "./core/model.js";
|
|
3
|
+
import { createEditor } from "./core/editor.js";
|
|
4
|
+
import { createMention } from "./core/mention.js";
|
|
5
|
+
import { createVariableMap } from "./di.js";
|
|
6
|
+
import { computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, nextTick, normalizeClass, onBeforeUnmount, onMounted, openBlock, shallowRef, toDisplayString, unref, useTemplateRef, watch } from "vue";
|
|
12
7
|
import { bem } from "@veltra/utils";
|
|
13
8
|
import { useFormComponent, useFormFallbackProps } from "@veltra/compositions";
|
|
14
|
-
import { $getRoot } from "lexical";
|
|
15
9
|
//#region src/components/expression-editor/expression-editor.vue
|
|
16
|
-
const _hoisted_1 = [
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
const _hoisted_1 = [
|
|
11
|
+
"contenteditable",
|
|
12
|
+
"data-empty",
|
|
13
|
+
"data-placeholder"
|
|
14
|
+
];
|
|
19
15
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
20
16
|
name: "ExpressionEditor",
|
|
21
17
|
__name: "expression-editor",
|
|
@@ -23,6 +19,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
23
19
|
modelValue: {},
|
|
24
20
|
placeholder: { default: "请输入表达式,输入 @ 可插入变量" },
|
|
25
21
|
variables: {},
|
|
22
|
+
selectableLevels: { default: "leaf" },
|
|
26
23
|
tips: {},
|
|
27
24
|
span: {},
|
|
28
25
|
label: {},
|
|
@@ -35,127 +32,184 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
35
32
|
setup(__props, { emit: __emit }) {
|
|
36
33
|
const props = __props;
|
|
37
34
|
const emit = __emit;
|
|
38
|
-
const showPlaceholder = computed(() => !props.modelValue || props.modelValue.trim() === "");
|
|
39
35
|
const cls = bem("expression-editor");
|
|
40
36
|
const { formProps } = useFormComponent();
|
|
41
37
|
const { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props]);
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const { editor } = createExpressionEditorRuntime({
|
|
51
|
-
disabled,
|
|
52
|
-
readonly,
|
|
53
|
-
cls,
|
|
54
|
-
container: useTemplateRef("container"),
|
|
55
|
-
props,
|
|
56
|
-
emit
|
|
57
|
-
});
|
|
58
|
-
const { contextVisible, contextTriggerDom, textNode, charPosition, registerPickerKeyHandler, registerContextCommands } = useContext(editor);
|
|
59
|
-
registerPlainText(editor, { getContextCommands: registerContextCommands });
|
|
60
|
-
const decorators = useDecorators(editor);
|
|
61
|
-
const nativeDnDSupported = supportsNativeDnD();
|
|
62
|
-
const fallbackVariables = shallowRef(collectVariableNodeDescriptors(editor));
|
|
63
|
-
const showFallbackControls = computed(() => !nativeDnDSupported && fallbackVariables.value.length > 1);
|
|
64
|
-
const removeFallbackSync = editor.registerUpdateListener(() => {
|
|
65
|
-
fallbackVariables.value = collectVariableNodeDescriptors(editor);
|
|
66
|
-
});
|
|
67
|
-
onBeforeUnmount(() => {
|
|
68
|
-
removeFallbackSync();
|
|
69
|
-
});
|
|
38
|
+
const containerRef = useTemplateRef("container");
|
|
39
|
+
const pickerRef = useTemplateRef("pickerRef");
|
|
40
|
+
const className = computed(() => [
|
|
41
|
+
cls.b,
|
|
42
|
+
cls.m(size.value),
|
|
43
|
+
bem.is("disabled", disabled.value),
|
|
44
|
+
bem.is("readonly", readonly.value)
|
|
45
|
+
]);
|
|
70
46
|
const variableMap = computed(() => createVariableMap(props.variables));
|
|
71
|
-
|
|
72
|
-
|
|
47
|
+
const editorRef = shallowRef(null);
|
|
48
|
+
const mention = createMention();
|
|
49
|
+
const currentDoc = shallowRef([]);
|
|
50
|
+
const isEmpty = computed(() => currentDoc.value.length === 0);
|
|
51
|
+
const showPlaceholder = computed(() => isEmpty.value && !disabled.value);
|
|
52
|
+
const pickerMode = shallowRef(null);
|
|
53
|
+
const pickerTriggerDom = shallowRef(void 0);
|
|
54
|
+
const reselectingSegIdx = shallowRef(null);
|
|
55
|
+
const pickerFilter = shallowRef("");
|
|
56
|
+
const pickerVisible = computed(() => pickerMode.value !== null);
|
|
57
|
+
function syncMention() {
|
|
58
|
+
const editor = editorRef.value;
|
|
59
|
+
if (!editor) return;
|
|
60
|
+
if (pickerMode.value === "reselect") return;
|
|
61
|
+
const caret = editor.getCaretOffset();
|
|
62
|
+
const state = mention.update(currentDoc.value, caret);
|
|
63
|
+
if (state) {
|
|
64
|
+
pickerMode.value = "mention";
|
|
65
|
+
pickerFilter.value = state.filter;
|
|
66
|
+
pickerTriggerDom.value = containerRef.value ?? void 0;
|
|
67
|
+
} else if (pickerMode.value === "mention") closePicker();
|
|
73
68
|
}
|
|
74
|
-
function
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
function closePicker() {
|
|
70
|
+
pickerMode.value = null;
|
|
71
|
+
reselectingSegIdx.value = null;
|
|
72
|
+
pickerFilter.value = "";
|
|
77
73
|
}
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
74
|
+
onMounted(() => {
|
|
75
|
+
if (!containerRef.value) return;
|
|
76
|
+
const initialDoc = parse(props.modelValue ?? "", variableMap.value);
|
|
77
|
+
currentDoc.value = initialDoc;
|
|
78
|
+
const editor = createEditor({
|
|
79
|
+
container: containerRef.value,
|
|
80
|
+
cls,
|
|
81
|
+
initialDoc,
|
|
82
|
+
getVariableMap: () => variableMap.value,
|
|
83
|
+
onChange: (doc) => {
|
|
84
|
+
currentDoc.value = doc;
|
|
85
|
+
const value = serializeFromDoc(doc);
|
|
86
|
+
if (value !== (props.modelValue ?? "")) emit("update:modelValue", value);
|
|
87
|
+
syncMention();
|
|
88
|
+
},
|
|
89
|
+
onSelectionChange: () => {
|
|
90
|
+
syncMention();
|
|
91
|
+
},
|
|
92
|
+
onChipReselect: ({ chipEl, segIndex }) => {
|
|
93
|
+
if (disabled.value || readonly.value) return;
|
|
94
|
+
mention.commit();
|
|
95
|
+
pickerMode.value = "reselect";
|
|
96
|
+
pickerFilter.value = "";
|
|
97
|
+
pickerTriggerDom.value = chipEl;
|
|
98
|
+
reselectingSegIdx.value = segIndex;
|
|
99
|
+
},
|
|
100
|
+
onChipRemove: ({ segIndex }) => {
|
|
101
|
+
if (disabled.value || readonly.value) return;
|
|
102
|
+
editor.removeVarAt(segIndex);
|
|
89
103
|
}
|
|
90
104
|
});
|
|
105
|
+
editorRef.value = editor;
|
|
106
|
+
});
|
|
107
|
+
onBeforeUnmount(() => {
|
|
108
|
+
editorRef.value?.dispose();
|
|
109
|
+
});
|
|
110
|
+
function serializeFromDoc(doc) {
|
|
111
|
+
let s = "";
|
|
112
|
+
for (const seg of doc) s += seg.kind === "text" ? seg.value : `{${seg.value}}`;
|
|
113
|
+
return s;
|
|
91
114
|
}
|
|
92
|
-
|
|
93
|
-
editor
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
115
|
+
watch(() => props.modelValue, (v) => {
|
|
116
|
+
const editor = editorRef.value;
|
|
117
|
+
if (!editor) return;
|
|
118
|
+
if (v === editor.getValue()) return;
|
|
119
|
+
editor.setValue(v ?? "");
|
|
120
|
+
});
|
|
121
|
+
watch(variableMap, () => {
|
|
122
|
+
const editor = editorRef.value;
|
|
123
|
+
if (!editor) return;
|
|
124
|
+
editor.setValue(editor.getValue());
|
|
125
|
+
});
|
|
126
|
+
function onKeydown(e) {
|
|
127
|
+
if (disabled.value || readonly.value) return;
|
|
128
|
+
if (pickerMode.value !== null) {
|
|
129
|
+
if (pickerRef.value?.handleKeydown(e)) {
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
return;
|
|
103
132
|
}
|
|
104
|
-
|
|
105
|
-
|
|
133
|
+
}
|
|
134
|
+
if (pickerMode.value === "mention") {
|
|
135
|
+
if (e.key === " " || e.key === "ArrowLeft" || e.key === "ArrowRight") {
|
|
136
|
+
mention.dismiss();
|
|
137
|
+
closePicker();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function onBlur() {
|
|
142
|
+
if (pickerMode.value === "mention") {
|
|
143
|
+
mention.dismiss();
|
|
144
|
+
nextTick(() => closePicker());
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function onPickerSelect(item) {
|
|
148
|
+
const editor = editorRef.value;
|
|
149
|
+
if (!editor) return;
|
|
150
|
+
if (pickerMode.value === "mention") {
|
|
151
|
+
const state = mention.getState();
|
|
152
|
+
if (!state) return;
|
|
153
|
+
const anchor = state.anchorOffset;
|
|
154
|
+
const caret = editor.getCaretOffset() ?? anchor + state.filter.length + 1;
|
|
155
|
+
editor.replaceRangeWithVar(anchor, caret, {
|
|
156
|
+
value: item.value,
|
|
157
|
+
label: item.label,
|
|
158
|
+
...item.type ? { type: item.type } : {}
|
|
159
|
+
});
|
|
160
|
+
mention.commit();
|
|
161
|
+
} else if (pickerMode.value === "reselect") {
|
|
162
|
+
const idx = reselectingSegIdx.value;
|
|
163
|
+
if (idx !== null) editor.replaceVarAt(idx, {
|
|
164
|
+
value: item.value,
|
|
165
|
+
label: item.label,
|
|
166
|
+
...item.type ? { type: item.type } : {}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
closePicker();
|
|
170
|
+
}
|
|
171
|
+
function onPickerDismiss() {
|
|
172
|
+
if (pickerMode.value === "mention") mention.dismiss();
|
|
173
|
+
closePicker();
|
|
174
|
+
}
|
|
175
|
+
function onPickerVisibleChange(v) {
|
|
176
|
+
if (!v && pickerMode.value !== null) {
|
|
177
|
+
if (pickerMode.value === "mention") mention.dismiss();
|
|
178
|
+
closePicker();
|
|
179
|
+
}
|
|
106
180
|
}
|
|
107
|
-
provide(ExpressionEditorDIKey, {
|
|
108
|
-
cls,
|
|
109
|
-
editorProps: props,
|
|
110
|
-
editor,
|
|
111
|
-
updateVariableNode,
|
|
112
|
-
variableMap
|
|
113
|
-
});
|
|
114
181
|
return (_ctx, _cache) => {
|
|
115
182
|
return openBlock(), createElementBlock("div", { class: normalizeClass(className.value) }, [
|
|
116
|
-
createCommentVNode(" 编辑容器 "),
|
|
117
183
|
createElementVNode("div", {
|
|
118
|
-
class: normalizeClass(unref(cls).e("container")),
|
|
119
184
|
ref: "container",
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
key: item.key,
|
|
128
|
-
class: normalizeClass(unref(cls).e("fallback-item"))
|
|
129
|
-
}, [createElementVNode("span", { class: normalizeClass(unref(cls).e("fallback-label")) }, toDisplayString(item.label || item.variable), 3), createElementVNode("div", { class: normalizeClass(unref(cls).e("fallback-actions")) }, [createElementVNode("button", {
|
|
130
|
-
type: "button",
|
|
131
|
-
class: normalizeClass(unref(cls).e("fallback-button")),
|
|
132
|
-
disabled: unref(disabled) || unref(readonly) || index === 0,
|
|
133
|
-
onClick: ($event) => moveVariable(item.key, -1)
|
|
134
|
-
}, " 上移 ", 10, _hoisted_2), createElementVNode("button", {
|
|
135
|
-
type: "button",
|
|
136
|
-
class: normalizeClass(unref(cls).e("fallback-button")),
|
|
137
|
-
disabled: unref(disabled) || unref(readonly) || index === fallbackVariables.value.length - 1,
|
|
138
|
-
onClick: ($event) => moveVariable(item.key, 1)
|
|
139
|
-
}, " 下移 ", 10, _hoisted_3)], 2)], 2);
|
|
140
|
-
}), 128))], 2)) : createCommentVNode("v-if", true),
|
|
185
|
+
class: normalizeClass(unref(cls).e("container")),
|
|
186
|
+
contenteditable: !unref(readonly) && !unref(disabled),
|
|
187
|
+
"data-empty": isEmpty.value || void 0,
|
|
188
|
+
"data-placeholder": props.placeholder,
|
|
189
|
+
onKeydown,
|
|
190
|
+
onBlur
|
|
191
|
+
}, null, 42, _hoisted_1),
|
|
141
192
|
showPlaceholder.value ? (openBlock(), createElementBlock("div", {
|
|
142
|
-
key:
|
|
193
|
+
key: 0,
|
|
143
194
|
class: normalizeClass(unref(cls).e("placeholder"))
|
|
144
|
-
}, toDisplayString(
|
|
145
|
-
createCommentVNode(" 渲染装饰器节点,内部通过Vue的Teleport组件渲染至节点中 "),
|
|
146
|
-
createVNode(Decorators, { decorators: unref(decorators) }, null, 8, ["decorators"]),
|
|
147
|
-
createCommentVNode(" 变量选择器 "),
|
|
195
|
+
}, toDisplayString(props.placeholder), 3)) : createCommentVNode("v-if", true),
|
|
148
196
|
createVNode(_sfc_main$1, {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
197
|
+
ref_key: "pickerRef",
|
|
198
|
+
ref: pickerRef,
|
|
199
|
+
visible: pickerVisible.value,
|
|
200
|
+
"trigger-dom": pickerTriggerDom.value,
|
|
201
|
+
variables: props.variables,
|
|
202
|
+
filter: pickerFilter.value,
|
|
203
|
+
"selectable-levels": props.selectableLevels ?? "leaf",
|
|
204
|
+
onSelect: onPickerSelect,
|
|
205
|
+
onDismiss: onPickerDismiss,
|
|
206
|
+
"onUpdate:visible": onPickerVisibleChange
|
|
155
207
|
}, null, 8, [
|
|
156
208
|
"visible",
|
|
157
209
|
"trigger-dom",
|
|
158
|
-
"
|
|
210
|
+
"variables",
|
|
211
|
+
"filter",
|
|
212
|
+
"selectable-levels"
|
|
159
213
|
])
|
|
160
214
|
], 2);
|
|
161
215
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expression-editor.js","names":[],"sources":["../../../src/components/expression-editor/expression-editor.vue"],"sourcesContent":["<template>\n <div :class=\"className\">\n <!-- 编辑容器 -->\n <div\n :class=\"cls.e('container')\"\n ref=\"container\"\n :contenteditable=\"!readonly && !disabled\"\n ></div>\n\n <div v-if=\"showFallbackControls\" :class=\"cls.e('fallback')\">\n <div\n v-for=\"(item, index) in fallbackVariables\"\n :key=\"item.key\"\n :class=\"cls.e('fallback-item')\"\n >\n <span :class=\"cls.e('fallback-label')\">\n {{ item.label || item.variable }}\n </span>\n <div :class=\"cls.e('fallback-actions')\">\n <button\n type=\"button\"\n :class=\"cls.e('fallback-button')\"\n :disabled=\"disabled || readonly || index === 0\"\n @click=\"moveVariable(item.key, -1)\"\n >\n 上移\n </button>\n <button\n type=\"button\"\n :class=\"cls.e('fallback-button')\"\n :disabled=\"disabled || readonly || index === fallbackVariables.length - 1\"\n @click=\"moveVariable(item.key, 1)\"\n >\n 下移\n </button>\n </div>\n </div>\n </div>\n\n <div :class=\"cls.e('placeholder')\" v-if=\"showPlaceholder\">\n {{ placeholder }}\n </div>\n\n <!-- 渲染装饰器节点,内部通过Vue的Teleport组件渲染至节点中 -->\n <Decorators :decorators=\"decorators\" />\n\n <!-- 变量选择器 -->\n <VariablePicker\n v-model:visible=\"contextVisible\"\n :trigger-dom=\"contextTriggerDom\"\n :filterable=\"true\"\n :register-picker-key-handler=\"registerPickerKeyHandler\"\n @select=\"handleVariableSelect\"\n />\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFormComponent, useFormFallbackProps } from '@veltra/compositions'\nimport { bem } from '@veltra/utils'\nimport { $getRoot } from 'lexical'\nimport { useTemplateRef, provide, computed, onBeforeUnmount, shallowRef, type VNode } from 'vue'\n\nimport type { ExpressionEditorProps, VariableItem } from '../../types'\nimport VariablePicker from './components/variable-picker.vue'\nimport { ExpressionEditorDIKey, createVariableMap } from './di'\nimport { createExpressionEditorRuntime } from './internal/editor-runtime'\nimport { moveVariableByDirection } from './internal/features/drag-drop/drag-drop-service'\nimport { insertVariableAtTrigger } from './internal/features/insertion/insertion-service'\nimport { $isVariableNode } from './nodes/variable-node'\nimport { registerPlainText } from './plain-text'\nimport { useContext } from './use-context'\nimport { useDecorators } from './use-decorators'\nimport { collectVariableNodeDescriptors, supportsNativeDnD } from './use-expression-drag-drop'\n\ndefineOptions({\n name: 'ExpressionEditor'\n})\n\nconst props = withDefaults(defineProps<ExpressionEditorProps>(), {\n placeholder: '请输入表达式,输入 @ 可插入变量'\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nconst showPlaceholder = computed(() => !props.modelValue || props.modelValue.trim() === '')\n\nconst cls = bem('expression-editor')\n\nconst { formProps } = useFormComponent()\n\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst className = computed(() => {\n return [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n ]\n})\n\nconst containerRef = useTemplateRef('container')\n\nconst { editor } = createExpressionEditorRuntime({\n disabled,\n readonly,\n cls,\n container: containerRef,\n props,\n emit\n})\n\nconst {\n contextVisible,\n contextTriggerDom,\n textNode,\n charPosition,\n registerPickerKeyHandler,\n registerContextCommands\n} = useContext(editor)\n\nregisterPlainText(editor, {\n getContextCommands: registerContextCommands\n})\n\nconst decorators = useDecorators(editor)\nconst nativeDnDSupported = supportsNativeDnD()\nconst fallbackVariables = shallowRef(collectVariableNodeDescriptors(editor))\nconst showFallbackControls = computed(\n () => !nativeDnDSupported && fallbackVariables.value.length > 1\n)\n\nconst removeFallbackSync = editor.registerUpdateListener(() => {\n fallbackVariables.value = collectVariableNodeDescriptors(editor)\n})\n\nonBeforeUnmount(() => {\n removeFallbackSync()\n})\n\n// 创建变量映射表\nconst variableMap = computed(() => createVariableMap(props.variables))\n\nfunction Decorators(props: { decorators: VNode[] }) {\n return props.decorators\n}\n\nfunction moveVariable(variableKey: string, direction: -1 | 1) {\n if (disabled.value || readonly.value) return\n\n moveVariableByDirection(editor, variableKey, direction, true)\n}\n\n// 处理变量选择\nfunction handleVariableSelect(variable: VariableItem) {\n if (disabled.value || readonly.value) return\n\n const nodeKey = textNode.value?.getKey()\n if (!nodeKey) return\n\n insertVariableAtTrigger(editor, {\n nodeKey,\n charPosition: charPosition.value,\n variable: {\n value: variable.value,\n label: variable.label,\n type: variable.type\n }\n })\n}\n\n// 更新变量节点的函数\nfunction updateVariableNode(oldValue: string, newValue: string, newLabel?: string) {\n editor.update(() => {\n const root = $getRoot()\n\n // 如果没有提供 label 或 type,从映射表中查找\n const variable = variableMap.value.get(newValue)\n const label = newLabel ?? variable?.label ?? newValue\n const type = variable?.type\n\n // 递归遍历所有节点\n function traverse(node: any) {\n if ($isVariableNode(node)) {\n if (node.getVariable() === oldValue) {\n node.updateVariable(newValue, label, type)\n }\n }\n\n // 如果节点有 getChildren 方法,继续遍历\n if (typeof node.getChildren === 'function') {\n const children = node.getChildren()\n children.forEach((child: any) => traverse(child))\n }\n }\n\n traverse(root)\n })\n}\n\nprovide(ExpressionEditorDIKey, {\n cls,\n editorProps: props,\n editor,\n updateVariableNode,\n variableMap\n})\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"expression-editor.js","names":[],"sources":["../../../src/components/expression-editor/expression-editor.vue"],"sourcesContent":["<template>\n <div :class=\"className\">\n <div\n ref=\"container\"\n :class=\"cls.e('container')\"\n :contenteditable=\"!readonly && !disabled\"\n :data-empty=\"isEmpty || undefined\"\n :data-placeholder=\"props.placeholder\"\n @keydown=\"onKeydown\"\n @blur=\"onBlur\"\n ></div>\n\n <div v-if=\"showPlaceholder\" :class=\"cls.e('placeholder')\">\n {{ props.placeholder }}\n </div>\n\n <VariablePicker\n ref=\"pickerRef\"\n :visible=\"pickerVisible\"\n :trigger-dom=\"pickerTriggerDom\"\n :variables=\"props.variables\"\n :filter=\"pickerFilter\"\n :selectable-levels=\"props.selectableLevels ?? 'leaf'\"\n @select=\"onPickerSelect\"\n @dismiss=\"onPickerDismiss\"\n @update:visible=\"onPickerVisibleChange\"\n />\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFormComponent, useFormFallbackProps } from '@veltra/compositions'\nimport { bem } from '@veltra/utils'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch\n} from 'vue'\n\nimport type { ExpressionEditorProps, VariableItem } from '../../types'\nimport VariablePicker from './components/variable-picker.vue'\nimport { createEditor, type EditorAPI } from './core/editor'\nimport { createMention, type MentionAPI } from './core/mention'\nimport { parse, type Doc } from './core/model'\nimport { createVariableMap } from './di'\n\ndefineOptions({\n name: 'ExpressionEditor'\n})\n\nconst props = withDefaults(defineProps<ExpressionEditorProps>(), {\n placeholder: '请输入表达式,输入 @ 可插入变量',\n selectableLevels: 'leaf'\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nconst cls = bem('expression-editor')\nconst { formProps } = useFormComponent()\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst containerRef = useTemplateRef<HTMLDivElement>('container')\nconst pickerRef = useTemplateRef<{ handleKeydown: (e: KeyboardEvent) => boolean }>('pickerRef')\n\nconst className = computed(() => [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n])\n\nconst variableMap = computed(() => createVariableMap(props.variables))\n\nconst editorRef = shallowRef<EditorAPI | null>(null)\nconst mention: MentionAPI = createMention()\n\nconst currentDoc = shallowRef<Doc>([])\nconst isEmpty = computed(() => currentDoc.value.length === 0)\nconst showPlaceholder = computed(() => isEmpty.value && !disabled.value)\n\nconst pickerMode = shallowRef<'mention' | 'reselect' | null>(null)\nconst pickerTriggerDom = shallowRef<HTMLElement | undefined>(undefined)\nconst reselectingSegIdx = shallowRef<number | null>(null)\nconst pickerFilter = shallowRef('')\n\nconst pickerVisible = computed(() => pickerMode.value !== null)\n\nfunction syncMention() {\n const editor = editorRef.value\n if (!editor) return\n if (pickerMode.value === 'reselect') return\n const caret = editor.getCaretOffset()\n const state = mention.update(currentDoc.value, caret)\n if (state) {\n pickerMode.value = 'mention'\n pickerFilter.value = state.filter\n pickerTriggerDom.value = containerRef.value ?? undefined\n } else if (pickerMode.value === 'mention') {\n closePicker()\n }\n}\n\nfunction closePicker() {\n pickerMode.value = null\n reselectingSegIdx.value = null\n pickerFilter.value = ''\n}\n\nonMounted(() => {\n if (!containerRef.value) return\n const initialDoc = parse(props.modelValue ?? '', variableMap.value)\n currentDoc.value = initialDoc\n\n const editor = createEditor({\n container: containerRef.value,\n cls,\n initialDoc,\n getVariableMap: () => variableMap.value,\n onChange: (doc) => {\n currentDoc.value = doc\n const value = serializeFromDoc(doc)\n if (value !== (props.modelValue ?? '')) emit('update:modelValue', value)\n syncMention()\n },\n onSelectionChange: () => {\n syncMention()\n },\n onChipReselect: ({ chipEl, segIndex }) => {\n if (disabled.value || readonly.value) return\n mention.commit()\n pickerMode.value = 'reselect'\n pickerFilter.value = ''\n pickerTriggerDom.value = chipEl\n reselectingSegIdx.value = segIndex\n },\n onChipRemove: ({ segIndex }) => {\n if (disabled.value || readonly.value) return\n editor.removeVarAt(segIndex)\n }\n })\n editorRef.value = editor\n})\n\nonBeforeUnmount(() => {\n editorRef.value?.dispose()\n})\n\nfunction serializeFromDoc(doc: Doc): string {\n let s = ''\n for (const seg of doc) s += seg.kind === 'text' ? seg.value : `{${seg.value}}`\n return s\n}\n\nwatch(\n () => props.modelValue,\n (v) => {\n const editor = editorRef.value\n if (!editor) return\n if (v === editor.getValue()) return\n editor.setValue(v ?? '')\n }\n)\n\nwatch(variableMap, () => {\n // variables 变化:重渲染以刷新 chip label / type\n const editor = editorRef.value\n if (!editor) return\n editor.setValue(editor.getValue())\n})\n\nfunction onKeydown(e: KeyboardEvent) {\n if (disabled.value || readonly.value) return\n // mention / reselect 激活时,优先把箭头键 / Enter / Esc 转给 picker\n if (pickerMode.value !== null) {\n const handledByPicker = pickerRef.value?.handleKeydown(e)\n if (handledByPicker) {\n e.preventDefault()\n return\n }\n }\n\n if (pickerMode.value === 'mention') {\n // 这些键导致 mention 退出(保留 @filter 文本,光标继续移动)\n if (e.key === ' ' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n mention.dismiss()\n closePicker()\n }\n }\n}\n\nfunction onBlur() {\n if (pickerMode.value === 'mention') {\n mention.dismiss()\n // 下一帧再关闭,避免和 picker 内 click 冲突\n void nextTick(() => closePicker())\n }\n}\n\nfunction onPickerSelect(item: VariableItem) {\n const editor = editorRef.value\n if (!editor) return\n\n if (pickerMode.value === 'mention') {\n const state = mention.getState()\n if (!state) return\n const anchor = state.anchorOffset\n const caret = editor.getCaretOffset() ?? anchor + state.filter.length + 1\n editor.replaceRangeWithVar(anchor, caret, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n mention.commit()\n } else if (pickerMode.value === 'reselect') {\n const idx = reselectingSegIdx.value\n if (idx !== null) {\n editor.replaceVarAt(idx, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n }\n }\n closePicker()\n}\n\nfunction onPickerDismiss() {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n}\n\nfunction onPickerVisibleChange(v: boolean) {\n if (!v && pickerMode.value !== null) {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n }\n}\n</script>\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExpressionEditorProps } from "../../types/expression-editor.js";
|
|
1
|
+
import { ExpressionEditorProps, ExpressionSelectableLevels } from "../../types/expression-editor.js";
|
|
2
2
|
import * as _$vue from "vue";
|
|
3
3
|
|
|
4
4
|
//#region src/components/expression-editor/expression-editor.vue.d.ts
|
|
@@ -8,6 +8,7 @@ declare const __VLS_export: _$vue.DefineComponent<ExpressionEditorProps, {}, {},
|
|
|
8
8
|
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
9
9
|
}>, {
|
|
10
10
|
placeholder: string;
|
|
11
|
+
selectableLevels: ExpressionSelectableLevels;
|
|
11
12
|
}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
|
|
12
13
|
declare const _default: typeof __VLS_export;
|
|
13
14
|
//#endregion
|