@yh-ui/components 0.1.12 → 0.1.16
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/ai-artifacts/src/ai-artifacts.d.ts +1 -1
- package/dist/ai-artifacts/src/ai-artifacts.d.vue.ts +18 -1
- package/dist/ai-artifacts/src/ai-artifacts.vue +30 -2
- package/dist/ai-artifacts/src/ai-artifacts.vue.d.ts +18 -1
- package/dist/ai-editor-sender/src/ai-editor-sender.d.vue.ts +2 -2
- package/dist/ai-editor-sender/src/ai-editor-sender.vue.d.ts +2 -2
- package/dist/ai-mention/__tests__/ai-mention.ssr.test.cjs +38 -0
- package/dist/ai-mention/__tests__/ai-mention.ssr.test.d.ts +1 -0
- package/dist/ai-mention/__tests__/ai-mention.ssr.test.mjs +37 -0
- package/dist/ai-mention/__tests__/ai-mention.test.cjs +113 -0
- package/dist/ai-mention/__tests__/ai-mention.test.d.ts +1 -0
- package/dist/ai-mention/__tests__/ai-mention.test.mjs +84 -0
- package/dist/ai-mention/index.cjs +26 -0
- package/dist/ai-mention/index.d.ts +29 -0
- package/dist/ai-mention/index.mjs +5 -0
- package/dist/ai-mention/src/ai-mention.cjs +95 -0
- package/dist/ai-mention/src/ai-mention.css +545 -0
- package/dist/ai-mention/src/ai-mention.d.ts +99 -0
- package/dist/ai-mention/src/ai-mention.d.vue.ts +68 -0
- package/dist/ai-mention/src/ai-mention.mjs +89 -0
- package/dist/ai-mention/src/ai-mention.vue +650 -0
- package/dist/ai-mention/src/ai-mention.vue.d.ts +68 -0
- package/dist/ai-sender/__tests__/ai-sender.test.cjs +17 -10
- package/dist/ai-sender/__tests__/ai-sender.test.mjs +17 -10
- package/dist/ai-sender/src/ai-sender.cjs +7 -0
- package/dist/ai-sender/src/ai-sender.d.ts +7 -0
- package/dist/ai-sender/src/ai-sender.d.vue.ts +8 -3
- package/dist/ai-sender/src/ai-sender.mjs +7 -0
- package/dist/ai-sender/src/ai-sender.vue +25 -18
- package/dist/ai-sender/src/ai-sender.vue.d.ts +8 -3
- package/dist/ai-sources/src/ai-sources.d.vue.ts +2 -2
- package/dist/ai-sources/src/ai-sources.vue +41 -57
- package/dist/ai-sources/src/ai-sources.vue.d.ts +2 -2
- package/dist/ai-voice-trigger/__tests__/ai-voice-trigger.test.cjs +19 -2
- package/dist/ai-voice-trigger/__tests__/ai-voice-trigger.test.mjs +12 -2
- package/dist/ai-voice-trigger/src/ai-voice-trigger.cjs +32 -0
- package/dist/ai-voice-trigger/src/ai-voice-trigger.css +111 -12
- package/dist/ai-voice-trigger/src/ai-voice-trigger.d.ts +32 -0
- package/dist/ai-voice-trigger/src/ai-voice-trigger.d.vue.ts +22 -2
- package/dist/ai-voice-trigger/src/ai-voice-trigger.mjs +32 -0
- package/dist/ai-voice-trigger/src/ai-voice-trigger.vue +201 -50
- package/dist/ai-voice-trigger/src/ai-voice-trigger.vue.d.ts +22 -2
- package/dist/alert/src/alert.d.vue.ts +1 -1
- package/dist/alert/src/alert.vue.d.ts +1 -1
- package/dist/autocomplete/src/autocomplete.d.vue.ts +2 -2
- package/dist/autocomplete/src/autocomplete.vue.d.ts +2 -2
- package/dist/calendar/src/calendar.d.vue.ts +1 -1
- package/dist/calendar/src/calendar.vue.d.ts +1 -1
- package/dist/date-picker/src/date-picker.d.vue.ts +2 -2
- package/dist/date-picker/src/date-picker.vue.d.ts +2 -2
- package/dist/dialog/src/dialog.d.vue.ts +8 -8
- package/dist/dialog/src/dialog.vue.d.ts +8 -8
- package/dist/drawer/index.d.ts +42 -1
- package/dist/drawer/src/drawer.d.vue.ts +4 -4
- package/dist/drawer/src/drawer.vue.d.ts +4 -4
- package/dist/icon/src/icons/index.cjs +7 -2
- package/dist/icon/src/icons/index.d.ts +1 -0
- package/dist/icon/src/icons/index.mjs +7 -1
- package/dist/index.cjs +13 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +4 -1
- package/dist/infinite-scroll/src/infinite-scroll.d.vue.ts +1 -1
- package/dist/infinite-scroll/src/infinite-scroll.vue.d.ts +1 -1
- package/dist/input/index.d.ts +3 -3
- package/dist/input/src/input.d.vue.ts +1 -1
- package/dist/input/src/input.vue.d.ts +1 -1
- package/dist/input-number/index.d.ts +3 -3
- package/dist/input-number/src/input-number.d.vue.ts +1 -1
- package/dist/input-number/src/input-number.vue.d.ts +1 -1
- package/dist/input-tag/src/input-tag.d.vue.ts +2 -2
- package/dist/input-tag/src/input-tag.vue.d.ts +2 -2
- package/dist/mention/index.d.ts +181 -1
- package/dist/mention/src/mention.d.vue.ts +5 -5
- package/dist/mention/src/mention.vue +6 -2
- package/dist/mention/src/mention.vue.d.ts +5 -5
- package/dist/message/src/message.d.vue.ts +1 -1
- package/dist/message/src/message.vue.d.ts +1 -1
- package/dist/notification/src/notification.d.vue.ts +1 -1
- package/dist/notification/src/notification.vue.d.ts +1 -1
- package/dist/select/src/select.d.vue.ts +3 -3
- package/dist/select/src/select.vue.d.ts +3 -3
- package/dist/skeleton/src/skeleton.d.vue.ts +1 -1
- package/dist/skeleton/src/skeleton.vue.d.ts +1 -1
- package/dist/table/src/table-column.d.vue.ts +1 -1
- package/dist/table/src/table-column.vue.d.ts +1 -1
- package/dist/table/src/table.d.vue.ts +2 -2
- package/dist/table/src/table.vue.d.ts +2 -2
- package/dist/time-picker/src/time-picker.d.vue.ts +1 -1
- package/dist/time-picker/src/time-picker.vue.d.ts +1 -1
- package/package.json +5 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtractPropTypes, PropType } from 'vue';
|
|
2
|
-
export type ArtifactType = 'code' | 'html' | 'markdown' | 'react' | 'vue' | 'diagram';
|
|
2
|
+
export type ArtifactType = 'code' | 'html' | 'markdown' | 'react' | 'vue' | 'diagram' | 'chart' | 'sandbox' | 'canvas';
|
|
3
3
|
export interface ArtifactVersion {
|
|
4
4
|
/**
|
|
5
5
|
* 版本号或标识
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import 'highlight.js/styles/atom-one-dark.css';
|
|
2
|
-
declare
|
|
2
|
+
declare var __VLS_25: {
|
|
3
|
+
data: any;
|
|
4
|
+
title: any;
|
|
5
|
+
}, __VLS_31: {
|
|
6
|
+
data: any;
|
|
7
|
+
};
|
|
8
|
+
type __VLS_Slots = {} & {
|
|
9
|
+
chart?: (props: typeof __VLS_25) => any;
|
|
10
|
+
} & {
|
|
11
|
+
canvas?: (props: typeof __VLS_31) => any;
|
|
12
|
+
};
|
|
13
|
+
declare const __VLS_component: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
3
14
|
readonly visible: {
|
|
4
15
|
readonly type: BooleanConstructor;
|
|
5
16
|
readonly default: false;
|
|
@@ -30,4 +41,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
30
41
|
readonly fullscreen: boolean;
|
|
31
42
|
readonly mode: "inline" | "code" | "preview";
|
|
32
43
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
44
|
+
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
33
45
|
export default _default;
|
|
46
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
47
|
+
new (): {
|
|
48
|
+
$slots: S;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
@@ -32,6 +32,14 @@ watch(
|
|
|
32
32
|
if (val) currentVersionState.value = val;
|
|
33
33
|
}
|
|
34
34
|
);
|
|
35
|
+
const getIcon = (type) => {
|
|
36
|
+
if (type === "code") return "code";
|
|
37
|
+
if (type === "chart") return "chart-bar";
|
|
38
|
+
if (type === "canvas") return "edit";
|
|
39
|
+
if (type === "sandbox") return "play";
|
|
40
|
+
if (type === "diagram") return "connection";
|
|
41
|
+
return "document";
|
|
42
|
+
};
|
|
35
43
|
const currentVersionData = computed(() => {
|
|
36
44
|
if (!props.data || props.data.versions.length === 0) return null;
|
|
37
45
|
return props.data.versions.find((v) => v.version === currentVersionState.value) || props.data.versions[0];
|
|
@@ -88,7 +96,7 @@ const highlightedCode = computed(() => {
|
|
|
88
96
|
<!-- Header -->
|
|
89
97
|
<div :class="ns.e('header')">
|
|
90
98
|
<div :class="ns.e('title-area')">
|
|
91
|
-
<YhIcon :name="data?.type
|
|
99
|
+
<YhIcon :name="getIcon(data?.type)" />
|
|
92
100
|
<span :class="ns.e('title')">{{ data?.title || "Artifact" }}</span>
|
|
93
101
|
</div>
|
|
94
102
|
|
|
@@ -144,7 +152,27 @@ const highlightedCode = computed(() => {
|
|
|
144
152
|
<!-- Content area -->
|
|
145
153
|
<div :class="ns.e('content')">
|
|
146
154
|
<template v-if="internalMode === 'preview' || internalMode === 'inline'">
|
|
147
|
-
<iframe
|
|
155
|
+
<iframe
|
|
156
|
+
v-if="data?.type === 'html' || data?.type === 'sandbox'"
|
|
157
|
+
:src="sandboxSrc"
|
|
158
|
+
:class="ns.e('sandbox')"
|
|
159
|
+
></iframe>
|
|
160
|
+
<div v-else-if="data?.type === 'chart'" :class="ns.e('chart-container')">
|
|
161
|
+
<slot name="chart" :data="currentVersionData" :title="data.title">
|
|
162
|
+
<div :class="ns.e('placeholder')">
|
|
163
|
+
<YhIcon name="chart-bar" />
|
|
164
|
+
<p>{{ t("ai.artifacts.renderingChart") || "\u6B63\u5728\u6E32\u67D3\u56FE\u8868..." }}</p>
|
|
165
|
+
</div>
|
|
166
|
+
</slot>
|
|
167
|
+
</div>
|
|
168
|
+
<div v-else-if="data?.type === 'canvas'" :class="ns.e('canvas-container')">
|
|
169
|
+
<slot name="canvas" :data="currentVersionData">
|
|
170
|
+
<div :class="ns.e('placeholder')">
|
|
171
|
+
<YhIcon name="edit" />
|
|
172
|
+
<p>{{ t("ai.artifacts.renderingCanvas") || "\u6B63\u5728\u51C6\u5907\u753B\u677F..." }}</p>
|
|
173
|
+
</div>
|
|
174
|
+
</slot>
|
|
175
|
+
</div>
|
|
148
176
|
<div v-else :class="ns.e('placeholder')">
|
|
149
177
|
<YhIcon name="sparkles" />
|
|
150
178
|
<p>{{ t("ai.artifacts.rendering") || "\u6B63\u5728\u6E32\u67D3\u7EC4\u4EF6..." }}</p>
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import 'highlight.js/styles/atom-one-dark.css';
|
|
2
|
-
declare
|
|
2
|
+
declare var __VLS_25: {
|
|
3
|
+
data: any;
|
|
4
|
+
title: any;
|
|
5
|
+
}, __VLS_31: {
|
|
6
|
+
data: any;
|
|
7
|
+
};
|
|
8
|
+
type __VLS_Slots = {} & {
|
|
9
|
+
chart?: (props: typeof __VLS_25) => any;
|
|
10
|
+
} & {
|
|
11
|
+
canvas?: (props: typeof __VLS_31) => any;
|
|
12
|
+
};
|
|
13
|
+
declare const __VLS_component: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
3
14
|
readonly visible: {
|
|
4
15
|
readonly type: BooleanConstructor;
|
|
5
16
|
readonly default: false;
|
|
@@ -30,4 +41,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
30
41
|
readonly fullscreen: boolean;
|
|
31
42
|
readonly mode: "inline" | "code" | "preview";
|
|
32
43
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
44
|
+
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
33
45
|
export default _default;
|
|
46
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
47
|
+
new (): {
|
|
48
|
+
$slots: S;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
@@ -56,10 +56,10 @@ declare const __VLS_component: import("vue").DefineComponent<import("vue").Extra
|
|
|
56
56
|
readonly loading: boolean;
|
|
57
57
|
readonly placeholder: string;
|
|
58
58
|
readonly modelValue: string;
|
|
59
|
-
readonly maxLength: number;
|
|
60
59
|
readonly showWordLimit: boolean;
|
|
61
|
-
readonly attachments: AttachmentItem[];
|
|
62
60
|
readonly rows: number;
|
|
61
|
+
readonly maxLength: number;
|
|
62
|
+
readonly attachments: AttachmentItem[];
|
|
63
63
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
64
64
|
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
65
65
|
export default _default;
|
|
@@ -56,10 +56,10 @@ declare const __VLS_component: import("vue").DefineComponent<import("vue").Extra
|
|
|
56
56
|
readonly loading: boolean;
|
|
57
57
|
readonly placeholder: string;
|
|
58
58
|
readonly modelValue: string;
|
|
59
|
-
readonly maxLength: number;
|
|
60
59
|
readonly showWordLimit: boolean;
|
|
61
|
-
readonly attachments: AttachmentItem[];
|
|
62
60
|
readonly rows: number;
|
|
61
|
+
readonly maxLength: number;
|
|
62
|
+
readonly attachments: AttachmentItem[];
|
|
63
63
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
64
64
|
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
65
65
|
export default _default;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _vitest = require("vitest");
|
|
4
|
+
var _serverRenderer = require("@vue/server-renderer");
|
|
5
|
+
var _vue = require("vue");
|
|
6
|
+
var _aiMention = _interopRequireDefault(require("../src/ai-mention.vue"));
|
|
7
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
const options = [{
|
|
9
|
+
label: "DeepSeek",
|
|
10
|
+
value: "deepseek",
|
|
11
|
+
type: "agent"
|
|
12
|
+
}];
|
|
13
|
+
(0, _vitest.describe)("YhAiMention SSR", () => {
|
|
14
|
+
(0, _vitest.it)("should render to string on server", async () => {
|
|
15
|
+
const html = await (0, _serverRenderer.renderToString)((0, _vue.h)(_aiMention.default, {
|
|
16
|
+
modelValue: "hello",
|
|
17
|
+
options
|
|
18
|
+
}));
|
|
19
|
+
(0, _vitest.expect)(html).toContain("yh-ai-mention");
|
|
20
|
+
(0, _vitest.expect)(html).toMatch(/textarea|input/);
|
|
21
|
+
});
|
|
22
|
+
(0, _vitest.it)("should render custom placeholder on server", async () => {
|
|
23
|
+
const html = await (0, _serverRenderer.renderToString)((0, _vue.h)(_aiMention.default, {
|
|
24
|
+
modelValue: "",
|
|
25
|
+
options,
|
|
26
|
+
placeholder: "Custom SSR Placeholder"
|
|
27
|
+
}));
|
|
28
|
+
(0, _vitest.expect)(html).toContain("Custom SSR Placeholder");
|
|
29
|
+
});
|
|
30
|
+
(0, _vitest.it)("should apply disabled state on server", async () => {
|
|
31
|
+
const html = await (0, _serverRenderer.renderToString)((0, _vue.h)(_aiMention.default, {
|
|
32
|
+
modelValue: "",
|
|
33
|
+
options,
|
|
34
|
+
disabled: true
|
|
35
|
+
}));
|
|
36
|
+
(0, _vitest.expect)(html).toContain("disabled");
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { renderToString } from "@vue/server-renderer";
|
|
3
|
+
import { h } from "vue";
|
|
4
|
+
import AiMention from "../src/ai-mention.vue";
|
|
5
|
+
const options = [{ label: "DeepSeek", value: "deepseek", type: "agent" }];
|
|
6
|
+
describe("YhAiMention SSR", () => {
|
|
7
|
+
it("should render to string on server", async () => {
|
|
8
|
+
const html = await renderToString(
|
|
9
|
+
h(AiMention, {
|
|
10
|
+
modelValue: "hello",
|
|
11
|
+
options
|
|
12
|
+
})
|
|
13
|
+
);
|
|
14
|
+
expect(html).toContain("yh-ai-mention");
|
|
15
|
+
expect(html).toMatch(/textarea|input/);
|
|
16
|
+
});
|
|
17
|
+
it("should render custom placeholder on server", async () => {
|
|
18
|
+
const html = await renderToString(
|
|
19
|
+
h(AiMention, {
|
|
20
|
+
modelValue: "",
|
|
21
|
+
options,
|
|
22
|
+
placeholder: "Custom SSR Placeholder"
|
|
23
|
+
})
|
|
24
|
+
);
|
|
25
|
+
expect(html).toContain("Custom SSR Placeholder");
|
|
26
|
+
});
|
|
27
|
+
it("should apply disabled state on server", async () => {
|
|
28
|
+
const html = await renderToString(
|
|
29
|
+
h(AiMention, {
|
|
30
|
+
modelValue: "",
|
|
31
|
+
options,
|
|
32
|
+
disabled: true
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
expect(html).toContain("disabled");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _vitest = require("vitest");
|
|
4
|
+
var _testUtils = require("@vue/test-utils");
|
|
5
|
+
var _aiMention = _interopRequireDefault(require("../src/ai-mention.vue"));
|
|
6
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
const options = [{
|
|
8
|
+
label: "DeepSeek",
|
|
9
|
+
value: "deepseek",
|
|
10
|
+
type: "agent"
|
|
11
|
+
}, {
|
|
12
|
+
label: "GPT-4",
|
|
13
|
+
value: "gpt4",
|
|
14
|
+
type: "agent"
|
|
15
|
+
}, {
|
|
16
|
+
label: "PRD.docx",
|
|
17
|
+
value: "prd",
|
|
18
|
+
type: "document"
|
|
19
|
+
}, {
|
|
20
|
+
label: "Sales.xlsx",
|
|
21
|
+
value: "sales",
|
|
22
|
+
type: "table"
|
|
23
|
+
}, {
|
|
24
|
+
label: "Design System",
|
|
25
|
+
value: "design",
|
|
26
|
+
type: "knowledge"
|
|
27
|
+
}];
|
|
28
|
+
(0, _vitest.describe)("YhAiMention", () => {
|
|
29
|
+
(0, _vitest.it)("should render correctly", () => {
|
|
30
|
+
const wrapper = (0, _testUtils.mount)(_aiMention.default, {
|
|
31
|
+
props: {
|
|
32
|
+
modelValue: "",
|
|
33
|
+
options
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
(0, _vitest.expect)(wrapper.classes()).toContain("yh-ai-mention");
|
|
37
|
+
(0, _vitest.expect)(wrapper.findComponent({
|
|
38
|
+
name: "YhMention"
|
|
39
|
+
}).exists()).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
(0, _vitest.it)("should apply placeholder correctly", () => {
|
|
42
|
+
const placeholder = "Test Placeholder";
|
|
43
|
+
const wrapper = (0, _testUtils.mount)(_aiMention.default, {
|
|
44
|
+
props: {
|
|
45
|
+
modelValue: "",
|
|
46
|
+
options,
|
|
47
|
+
placeholder
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
const mention = wrapper.findComponent({
|
|
51
|
+
name: "YhMention"
|
|
52
|
+
});
|
|
53
|
+
(0, _vitest.expect)(mention.props("placeholder")).toBe(placeholder);
|
|
54
|
+
});
|
|
55
|
+
(0, _vitest.it)("should filter options based on types prop", () => {
|
|
56
|
+
const wrapper = (0, _testUtils.mount)(_aiMention.default, {
|
|
57
|
+
props: {
|
|
58
|
+
modelValue: "",
|
|
59
|
+
options,
|
|
60
|
+
types: ["agent"]
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
const mention = wrapper.findComponent({
|
|
64
|
+
name: "YhMention"
|
|
65
|
+
});
|
|
66
|
+
const passedOptions = mention.props("options");
|
|
67
|
+
(0, _vitest.expect)(passedOptions).toHaveLength(2);
|
|
68
|
+
(0, _vitest.expect)(passedOptions.every(opt => opt.type === "agent")).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
(0, _vitest.it)("should filter multiple types", () => {
|
|
71
|
+
const wrapper = (0, _testUtils.mount)(_aiMention.default, {
|
|
72
|
+
props: {
|
|
73
|
+
modelValue: "",
|
|
74
|
+
options,
|
|
75
|
+
types: ["document", "table"]
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
const mention = wrapper.findComponent({
|
|
79
|
+
name: "YhMention"
|
|
80
|
+
});
|
|
81
|
+
const passedOptions = mention.props("options");
|
|
82
|
+
(0, _vitest.expect)(passedOptions).toHaveLength(2);
|
|
83
|
+
(0, _vitest.expect)(passedOptions.some(opt => opt.type === "document")).toBe(true);
|
|
84
|
+
(0, _vitest.expect)(passedOptions.some(opt => opt.type === "table")).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
(0, _vitest.it)("should show all styles when no types specified (default)", () => {
|
|
87
|
+
const wrapper = (0, _testUtils.mount)(_aiMention.default, {
|
|
88
|
+
props: {
|
|
89
|
+
modelValue: "",
|
|
90
|
+
options
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
const mention = wrapper.findComponent({
|
|
94
|
+
name: "YhMention"
|
|
95
|
+
});
|
|
96
|
+
const passedOptions = mention.props("options");
|
|
97
|
+
(0, _vitest.expect)(passedOptions).toHaveLength(5);
|
|
98
|
+
});
|
|
99
|
+
(0, _vitest.it)("should emit update:modelValue when changed", async () => {
|
|
100
|
+
const wrapper = (0, _testUtils.mount)(_aiMention.default, {
|
|
101
|
+
props: {
|
|
102
|
+
modelValue: "",
|
|
103
|
+
options
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
const mention = wrapper.findComponent({
|
|
107
|
+
name: "YhMention"
|
|
108
|
+
});
|
|
109
|
+
await mention.vm.$emit("update:modelValue", "new value");
|
|
110
|
+
(0, _vitest.expect)(wrapper.emitted("update:modelValue")).toBeTruthy();
|
|
111
|
+
(0, _vitest.expect)(wrapper.emitted("update:modelValue")[0]).toEqual(["new value"]);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { mount } from "@vue/test-utils";
|
|
3
|
+
import AiMention from "../src/ai-mention.vue";
|
|
4
|
+
const options = [
|
|
5
|
+
{ label: "DeepSeek", value: "deepseek", type: "agent" },
|
|
6
|
+
{ label: "GPT-4", value: "gpt4", type: "agent" },
|
|
7
|
+
{ label: "PRD.docx", value: "prd", type: "document" },
|
|
8
|
+
{ label: "Sales.xlsx", value: "sales", type: "table" },
|
|
9
|
+
{ label: "Design System", value: "design", type: "knowledge" }
|
|
10
|
+
];
|
|
11
|
+
describe("YhAiMention", () => {
|
|
12
|
+
it("should render correctly", () => {
|
|
13
|
+
const wrapper = mount(AiMention, {
|
|
14
|
+
props: {
|
|
15
|
+
modelValue: "",
|
|
16
|
+
options
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
expect(wrapper.classes()).toContain("yh-ai-mention");
|
|
20
|
+
expect(wrapper.findComponent({ name: "YhMention" }).exists()).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
it("should apply placeholder correctly", () => {
|
|
23
|
+
const placeholder = "Test Placeholder";
|
|
24
|
+
const wrapper = mount(AiMention, {
|
|
25
|
+
props: {
|
|
26
|
+
modelValue: "",
|
|
27
|
+
options,
|
|
28
|
+
placeholder
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const mention = wrapper.findComponent({ name: "YhMention" });
|
|
32
|
+
expect(mention.props("placeholder")).toBe(placeholder);
|
|
33
|
+
});
|
|
34
|
+
it("should filter options based on types prop", () => {
|
|
35
|
+
const wrapper = mount(AiMention, {
|
|
36
|
+
props: {
|
|
37
|
+
modelValue: "",
|
|
38
|
+
options,
|
|
39
|
+
types: ["agent"]
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
const mention = wrapper.findComponent({ name: "YhMention" });
|
|
43
|
+
const passedOptions = mention.props("options");
|
|
44
|
+
expect(passedOptions).toHaveLength(2);
|
|
45
|
+
expect(passedOptions.every((opt) => opt.type === "agent")).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
it("should filter multiple types", () => {
|
|
48
|
+
const wrapper = mount(AiMention, {
|
|
49
|
+
props: {
|
|
50
|
+
modelValue: "",
|
|
51
|
+
options,
|
|
52
|
+
types: ["document", "table"]
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
const mention = wrapper.findComponent({ name: "YhMention" });
|
|
56
|
+
const passedOptions = mention.props("options");
|
|
57
|
+
expect(passedOptions).toHaveLength(2);
|
|
58
|
+
expect(passedOptions.some((opt) => opt.type === "document")).toBe(true);
|
|
59
|
+
expect(passedOptions.some((opt) => opt.type === "table")).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
it("should show all styles when no types specified (default)", () => {
|
|
62
|
+
const wrapper = mount(AiMention, {
|
|
63
|
+
props: {
|
|
64
|
+
modelValue: "",
|
|
65
|
+
options
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
const mention = wrapper.findComponent({ name: "YhMention" });
|
|
69
|
+
const passedOptions = mention.props("options");
|
|
70
|
+
expect(passedOptions).toHaveLength(5);
|
|
71
|
+
});
|
|
72
|
+
it("should emit update:modelValue when changed", async () => {
|
|
73
|
+
const wrapper = mount(AiMention, {
|
|
74
|
+
props: {
|
|
75
|
+
modelValue: "",
|
|
76
|
+
options
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
const mention = wrapper.findComponent({ name: "YhMention" });
|
|
80
|
+
await mention.vm.$emit("update:modelValue", "new value");
|
|
81
|
+
expect(wrapper.emitted("update:modelValue")).toBeTruthy();
|
|
82
|
+
expect(wrapper.emitted("update:modelValue")[0]).toEqual(["new value"]);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _exportNames = {
|
|
7
|
+
YhAiMention: true
|
|
8
|
+
};
|
|
9
|
+
module.exports = exports.YhAiMention = void 0;
|
|
10
|
+
var _utils = require("@yh-ui/utils");
|
|
11
|
+
var _aiMention = _interopRequireDefault(require("./src/ai-mention.vue"));
|
|
12
|
+
var _aiMention2 = require("./src/ai-mention.cjs");
|
|
13
|
+
Object.keys(_aiMention2).forEach(function (key) {
|
|
14
|
+
if (key === "default" || key === "__esModule") return;
|
|
15
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
16
|
+
if (key in exports && exports[key] === _aiMention2[key]) return;
|
|
17
|
+
Object.defineProperty(exports, key, {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function () {
|
|
20
|
+
return _aiMention2[key];
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
25
|
+
const YhAiMention = exports.YhAiMention = (0, _utils.withInstall)(_aiMention.default);
|
|
26
|
+
module.exports = YhAiMention;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const YhAiMention: import("@yh-ui/utils").SFCWithInstall<{
|
|
2
|
+
new (...args: any[]): any;
|
|
3
|
+
__isFragment?: never;
|
|
4
|
+
__isTeleport?: never;
|
|
5
|
+
__isSuspense?: never;
|
|
6
|
+
} & import("vue").ComponentOptionsBase<any, {
|
|
7
|
+
focus: () => void | undefined;
|
|
8
|
+
blur: () => void | undefined;
|
|
9
|
+
clear: () => void | undefined;
|
|
10
|
+
getRef: () => HTMLTextAreaElement | HTMLInputElement | undefined;
|
|
11
|
+
insertMention: (option: import("./src/ai-mention").AiMentionOption, trigger?: string) => void | undefined;
|
|
12
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, any, string, {
|
|
13
|
+
readonly disabled: boolean;
|
|
14
|
+
readonly themeOverrides: import("@yh-ui/theme").ComponentThemeVars;
|
|
15
|
+
readonly type: "textarea" | "input";
|
|
16
|
+
readonly loading: boolean;
|
|
17
|
+
readonly triggers: string[];
|
|
18
|
+
readonly options: import("./src/ai-mention").AiMentionOption[];
|
|
19
|
+
readonly modelValue: string;
|
|
20
|
+
readonly filterOption: false | ((keyword: string, option: import("../mention").MentionOption) => boolean);
|
|
21
|
+
readonly rows: number;
|
|
22
|
+
readonly types: ("table" | "document" | "agent" | "knowledge")[];
|
|
23
|
+
}, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & (new () => {
|
|
24
|
+
$slots: {
|
|
25
|
+
[x: string]: ((props: any) => any) | undefined;
|
|
26
|
+
};
|
|
27
|
+
})> & Record<string, unknown>;
|
|
28
|
+
export default YhAiMention;
|
|
29
|
+
export * from './src/ai-mention';
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.aiMentionTypes = exports.aiMentionProps = exports.aiMentionEmits = void 0;
|
|
7
|
+
const aiMentionTypes = exports.aiMentionTypes = ["agent", "document", "table", "knowledge"];
|
|
8
|
+
const aiMentionProps = exports.aiMentionProps = {
|
|
9
|
+
/**
|
|
10
|
+
* 绑定值
|
|
11
|
+
*/
|
|
12
|
+
modelValue: {
|
|
13
|
+
type: String,
|
|
14
|
+
default: ""
|
|
15
|
+
},
|
|
16
|
+
/**
|
|
17
|
+
* AI 提及类型,支持多种类型过滤
|
|
18
|
+
*/
|
|
19
|
+
types: {
|
|
20
|
+
type: Array,
|
|
21
|
+
default: () => ["agent", "document", "table", "knowledge"]
|
|
22
|
+
},
|
|
23
|
+
/**
|
|
24
|
+
* 选项列表
|
|
25
|
+
*/
|
|
26
|
+
options: {
|
|
27
|
+
type: Array,
|
|
28
|
+
default: () => []
|
|
29
|
+
},
|
|
30
|
+
/**
|
|
31
|
+
* 触发字符
|
|
32
|
+
*/
|
|
33
|
+
triggers: {
|
|
34
|
+
type: Array,
|
|
35
|
+
default: () => ["@"]
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* 是否在输入框中
|
|
39
|
+
*/
|
|
40
|
+
type: {
|
|
41
|
+
type: String,
|
|
42
|
+
default: "textarea"
|
|
43
|
+
},
|
|
44
|
+
/**
|
|
45
|
+
* 占位符
|
|
46
|
+
*/
|
|
47
|
+
placeholder: String,
|
|
48
|
+
/**
|
|
49
|
+
* 是否禁用
|
|
50
|
+
*/
|
|
51
|
+
disabled: Boolean,
|
|
52
|
+
/**
|
|
53
|
+
* 尺寸
|
|
54
|
+
*/
|
|
55
|
+
size: String,
|
|
56
|
+
/**
|
|
57
|
+
* 最大长度
|
|
58
|
+
*/
|
|
59
|
+
maxLength: Number,
|
|
60
|
+
/**
|
|
61
|
+
* 文本域行数
|
|
62
|
+
*/
|
|
63
|
+
rows: {
|
|
64
|
+
type: Number,
|
|
65
|
+
default: 3
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* 是否正在加载
|
|
69
|
+
*/
|
|
70
|
+
loading: Boolean,
|
|
71
|
+
/**
|
|
72
|
+
* 主题覆盖
|
|
73
|
+
*/
|
|
74
|
+
themeOverrides: {
|
|
75
|
+
type: Object,
|
|
76
|
+
default: () => ({})
|
|
77
|
+
},
|
|
78
|
+
/**
|
|
79
|
+
* 选项过滤
|
|
80
|
+
*/
|
|
81
|
+
filterOption: {
|
|
82
|
+
type: [Function, Boolean],
|
|
83
|
+
default: void 0
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const aiMentionEmits = exports.aiMentionEmits = {
|
|
87
|
+
"update:modelValue": value => typeof value === "string",
|
|
88
|
+
input: value => typeof value === "string",
|
|
89
|
+
change: value => typeof value === "string",
|
|
90
|
+
select: (option, trigger) => !!option && !!trigger,
|
|
91
|
+
search: (keyword, trigger) => typeof keyword === "string" && !!trigger,
|
|
92
|
+
focus: event => event instanceof FocusEvent,
|
|
93
|
+
blur: event => event instanceof FocusEvent,
|
|
94
|
+
keydown: event => event instanceof KeyboardEvent
|
|
95
|
+
};
|