Skip to content

Commit aac48ac

Browse files
committed
feat(elements): enhance Response and PromptInput
1 parent 770037e commit aac48ac

File tree

15 files changed

+369
-246
lines changed

15 files changed

+369
-246
lines changed

apps/test/app/assets/css/tailwind.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
@source "../../../**/*.{vue,ts,tsx}";
55
@source "../../../node_modules/@repo/**/*.{vue,ts,tsx}";
6-
@source "../../../node_modules/@repo/elements/node_modules/streamdown/dist/index.js";
6+
@source "../../../node_modules/@repo/elements/node_modules/streamdown-vue/dist/*.js";
77

88
@custom-variant dark (&:is(.dark *));
99

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
<script setup lang="ts">
2-
import type { ChatStatus } from 'ai'
3-
42
import {
53
PromptInput,
64
PromptInputButton,
@@ -14,47 +12,78 @@ import {
1412
PromptInputToolbar,
1513
PromptInputTools,
1614
} from '@repo/elements/prompt-input'
15+
import { Globe, Mic, Plus } from 'lucide-vue-next'
1716
import { ref } from 'vue'
1817
19-
const status = ref<ChatStatus | undefined>(undefined)
18+
type Status = 'submitted' | 'streaming' | 'ready' | 'error'
19+
20+
const models = [
21+
{ id: 'gpt-4', name: 'GPT-4' },
22+
{ id: 'gpt-3.5-turbo', name: 'GPT-3.5 Turbo' },
23+
{ id: 'claude-2', name: 'Claude 2' },
24+
{ id: 'claude-instant', name: 'Claude Instant' },
25+
{ id: 'palm-2', name: 'PaLM 2' },
26+
{ id: 'llama-2-70b', name: 'Llama 2 70B' },
27+
{ id: 'llama-2-13b', name: 'Llama 2 13B' },
28+
{ id: 'cohere-command', name: 'Command' },
29+
{ id: 'mistral-7b', name: 'Mistral 7B' },
30+
]
31+
32+
const text = ref('')
33+
const model = ref(models[0]!.id)
34+
const status = ref<Status>('ready')
35+
36+
function onSubmit(event: Event) {
37+
event.preventDefault()
38+
if (!text.value)
39+
return
2040
21-
function onSubmit(e: Event) {
22-
e.preventDefault()
2341
status.value = 'submitted'
42+
43+
setTimeout(() => {
44+
status.value = 'streaming'
45+
}, 200)
46+
2447
setTimeout(() => {
25-
status.value = undefined
26-
}, 800)
48+
status.value = 'ready'
49+
}, 2000)
2750
}
2851
</script>
2952

3053
<template>
3154
<PromptInput @submit="onSubmit">
32-
<div class="p-1">
33-
<PromptInputTextarea placeholder="Ask something..." />
34-
</div>
55+
<PromptInputTextarea v-model="text" />
56+
3557
<PromptInputToolbar>
3658
<PromptInputTools>
37-
<PromptInputModelSelect>
59+
<PromptInputButton>
60+
<Plus class="size-4" />
61+
</PromptInputButton>
62+
<PromptInputButton>
63+
<Mic class="size-4" />
64+
</PromptInputButton>
65+
<PromptInputButton>
66+
<Globe class="size-4" />
67+
<span>Search</span>
68+
</PromptInputButton>
69+
70+
<PromptInputModelSelect v-model="model">
3871
<PromptInputModelSelectTrigger>
39-
<PromptInputModelSelectValue placeholder="Select model" />
72+
<PromptInputModelSelectValue />
4073
</PromptInputModelSelectTrigger>
4174
<PromptInputModelSelectContent>
42-
<PromptInputModelSelectItem value="gpt-4o">
43-
gpt-4o
44-
</PromptInputModelSelectItem>
45-
<PromptInputModelSelectItem value="claude-3.7">
46-
claude-3.7
75+
<PromptInputModelSelectItem
76+
v-for="m in models"
77+
:key="m.id"
78+
:value="m.id"
79+
>
80+
{{ m.name }}
4781
</PromptInputModelSelectItem>
4882
</PromptInputModelSelectContent>
4983
</PromptInputModelSelect>
5084
</PromptInputTools>
5185

52-
<div class="flex items-center gap-2">
53-
<PromptInputButton type="button">
54-
Attach
55-
</PromptInputButton>
56-
<PromptInputSubmit :status="status" />
57-
</div>
86+
<PromptInputSubmit :disabled="!text" :status="status" />
5887
</PromptInputToolbar>
5988
</PromptInput>
6089
</template>
Lines changed: 246 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,253 @@
11
<script setup lang="ts">
22
import { Response } from '@repo/elements/response'
3+
import { onBeforeUnmount, onMounted, ref } from 'vue'
4+
5+
const tokens = [
6+
'### Hello',
7+
' World',
8+
'\n\n',
9+
'This',
10+
' is',
11+
' a',
12+
' **mark',
13+
'down',
14+
'**',
15+
' response',
16+
' from',
17+
' an',
18+
' AI',
19+
' model',
20+
'.',
21+
'\n\n',
22+
'---',
23+
'\n\n',
24+
'## Tables',
25+
'\n\n',
26+
'| Column 1',
27+
' | Column 2',
28+
' | Column 3',
29+
' |',
30+
'\n',
31+
'|----------|----------|----------|',
32+
'\n',
33+
'| Row 1, Col 1',
34+
' | Row 1, Col 2',
35+
' | Row 1, Col 3',
36+
' |',
37+
'\n',
38+
'| Row 2, Col 1',
39+
' | Row 2, Col 2',
40+
' | Row 2, Col 3',
41+
' |',
42+
'\n',
43+
'| Row 3, Col 1',
44+
' | Row 3, Col 2',
45+
' | Row 3, Col 3',
46+
' |',
47+
'\n\n',
48+
'## Blockquotes',
49+
'\n\n',
50+
'> This',
51+
' is',
52+
' a',
53+
' blockquote.',
54+
' It',
55+
' can',
56+
' contain',
57+
' multiple',
58+
' lines',
59+
' and',
60+
' **formatted**',
61+
' text.',
62+
'\n',
63+
'>',
64+
'\n',
65+
'> It',
66+
' can',
67+
' even',
68+
' have',
69+
' multiple',
70+
' paragraphs.',
71+
'\n\n',
72+
'## Inline',
73+
' Code',
74+
'\n\n',
75+
'Here',
76+
' is',
77+
' some',
78+
' text',
79+
' with',
80+
' `inline',
81+
' code`',
82+
' in',
83+
' the',
84+
' middle',
85+
' of',
86+
' a',
87+
' sentence.',
88+
' You',
89+
' can',
90+
' also',
91+
' use',
92+
' `const',
93+
' x',
94+
' =',
95+
' 42`',
96+
' for',
97+
' variable',
98+
' declarations.',
99+
'\n\n',
100+
'## Code',
101+
' Blocks',
102+
'\n\n',
103+
'```',
104+
'javascript',
105+
'\n',
106+
'const',
107+
' greeting',
108+
' = ',
109+
'\'Hello, world!\'',
110+
';',
111+
'\n',
112+
'console',
113+
'.',
114+
'log',
115+
'(',
116+
'greeting',
117+
')',
118+
';',
119+
'\n',
120+
'```',
121+
'\n\n',
122+
'## Math',
123+
'\n\n',
124+
'It',
125+
' also',
126+
' supports',
127+
' math',
128+
' equations',
129+
', ',
130+
'like',
131+
' this',
132+
' inline',
133+
' one',
134+
': ',
135+
'$',
136+
'E',
137+
' = ',
138+
'mc',
139+
'^2',
140+
'$',
141+
'.',
142+
'\n\n',
143+
'And',
144+
' here',
145+
' is',
146+
' a',
147+
' display',
148+
' equation',
149+
' for',
150+
' the',
151+
' quadratic',
152+
' formula',
153+
':',
154+
'\n\n',
155+
'$$',
156+
'\n',
157+
'x',
158+
' = ',
159+
'\\frac',
160+
'{',
161+
'-b',
162+
' \\pm',
163+
' \\sqrt',
164+
'{',
165+
'b^2',
166+
' -',
167+
' 4ac',
168+
'}',
169+
'}',
170+
'{',
171+
'2a',
172+
'}',
173+
'\n',
174+
'$$',
175+
'\n\n',
176+
'## Links',
177+
' and',
178+
' Lists',
179+
'\n\n',
180+
'Here\'s',
181+
' a',
182+
' [',
183+
'link',
184+
'](',
185+
'https://example.com',
186+
')',
187+
' and',
188+
' some',
189+
' more',
190+
' text',
191+
' with',
192+
' an',
193+
' unordered',
194+
' list',
195+
':',
196+
'\n\n',
197+
'-',
198+
' Item',
199+
' one',
200+
'\n',
201+
'-',
202+
' Item',
203+
' two',
204+
'\n',
205+
'-',
206+
' Item',
207+
' three',
208+
'\n\n',
209+
'## Ordered',
210+
' Lists',
211+
'\n\n',
212+
'1.',
213+
' First',
214+
' item',
215+
'\n',
216+
'2.',
217+
' Second',
218+
' item',
219+
'\n',
220+
'3.',
221+
' Third',
222+
' item',
223+
]
224+
225+
const content = ref('')
226+
227+
let interval: number | undefined
228+
onMounted(() => {
229+
let currentContent = ''
230+
let index = 0
231+
interval = window.setInterval(() => {
232+
if (index < tokens.length) {
233+
currentContent += tokens[index]
234+
content.value = currentContent
235+
index++
236+
}
237+
else if (interval) {
238+
clearInterval(interval)
239+
}
240+
}, 100)
241+
})
242+
243+
onBeforeUnmount(() => {
244+
if (interval)
245+
clearInterval(interval)
246+
})
3247
</script>
4248

5249
<template>
6-
<Response>
7-
<div class="prose dark:prose-invert">
8-
<h3>Response Container</h3>
9-
<p>
10-
This area renders content from the assistant, with consistent spacing and
11-
styles. You can place markdown-rendered content, lists, images, etc.
12-
</p>
13-
<ul>
14-
<li>Automatic top/bottom margin trimming</li>
15-
<li>Works with any content</li>
16-
</ul>
17-
</div>
250+
<Response :style="{ height: '500px', overflow: 'auto' }">
251+
{{ content }}
18252
</Response>
19253
</template>

apps/test/app/pages/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const components = [
1414
</script>
1515

1616
<template>
17-
<div class="container mx-auto space-y-8 py-16">
17+
<div class="container mx-auto grid grid-cols-1 lg:grid-cols-2 gap-8 py-16">
1818
<Card v-for="item in components" :key="item.name">
1919
<CardHeader>
2020
<CardTitle class="text-lg">

0 commit comments

Comments
 (0)