Skip to content

Commit 7e27894

Browse files
authored
feat: charts and graphs support (#5)
* feat: port rn syntax highlighter * chore: cleanup * chore: remove lib * chore: export new component * chore: cleanup * chore: add recognition * feat: add support for charts and graphs * chore: figs visual bugs and qol improvements * chore: cleanup * refactor: extract generic chart component * chore: refactor charts and do some perf improvements on syntax highlights * feat: implement PerfText for Android for syntax highlighting * fix: ts issues * chore: clean up text style conversion parsing * refactor: charts ergonomics improvement * refactor: directory structure * refactor: syntax highlighter ergonomics * perf: implement self measuring view for android syntax highlighting and further ergonomic improvements * chore: remove redundant imports * refactor: final ergonomics refactoring * fix: remove extensions * fix: revert unwanted change
1 parent 50dfc4f commit 7e27894

File tree

85 files changed

+2705
-119
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+2705
-119
lines changed

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,16 @@ dist
137137
# Vite logs files
138138
vite.config.js.timestamp-*
139139
vite.config.ts.timestamp-*
140+
141+
# Android/IJ
142+
#
143+
**/android/build/
144+
**/android/.idea/
145+
.classpath
146+
.cxx
147+
.gradle
148+
.project
149+
.settings
150+
local.properties
151+
android.iml
152+
*.hprof

.idea/codeStyles/Project.xml

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.prettierignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Add files here to ignore them from prettier formatting
2-
/dist
2+
**/dist
3+
**/android
34
/coverage
45
/.changeset
56
/.github

examples/nextjs-ai-chatbot/app/api/chats/[id]/route.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { createConfigFromEnv } from '@stream-io/ai-sdk-storage/dist/utils';
44

55
const storage = createStreamStorageClient(createConfigFromEnv());
66

7-
87
export async function GET(_req: Request, { params }: any) {
98
const { id } = await params;
109
try {

examples/nextjs-ai-chatbot/app/layout.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ export const metadata: Metadata = {
2424

2525
export default function RootLayout({ children }: LayoutProps) {
2626
return (
27-
<html lang='en' data-theme='dim'>
27+
<html lang="en" data-theme="dim">
2828
<body
2929
className={`${geistSans.variable} ${geistMono.variable} antialiased prose`}
3030
>
3131
<AppProvider>
32-
<div className='grid grid-cols-1 md:grid-cols-[300px_auto] h-screen w-screen'>
33-
<div className='bg-base-200 px-5 py-2 md:relative absolute top-0 bottom-0 translate-x-[-100%] md:translate-x-0 transition-all duration-300'>
32+
<div className="grid grid-cols-1 md:grid-cols-[300px_auto] h-screen w-screen">
33+
<div className="bg-base-200 px-5 py-2 md:relative absolute top-0 bottom-0 translate-x-[-100%] md:translate-x-0 transition-all duration-300">
3434
<Sidebar />
3535
</div>
36-
<div className='flex flex-col h-full relative px-5'>
37-
<div className='w-full mx-auto flex flex-col h-[100vh] gap-2'>
38-
<div className='flex-1 overflow-y-auto'>{children}</div>
39-
<div className='flex-shrink-0 pb-5'>
40-
<div className='max-w-3xl mx-auto'>
36+
<div className="flex flex-col h-full relative px-5">
37+
<div className="w-full mx-auto flex flex-col h-[100vh] gap-2">
38+
<div className="flex-1 overflow-y-auto">{children}</div>
39+
<div className="flex-shrink-0 pb-5">
40+
<div className="max-w-3xl mx-auto">
4141
<Composer />
4242
</div>
4343
</div>

examples/nextjs-ai-chatbot/components/markdown.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Weather from './tools/weather';
1010
export const NonMemoizedMarkdown = ({ children }: { children: string }) => {
1111
const components = {
1212
p: ({ children }: { children: string }) => {
13-
return <div className='no-prose'>{children}</div>;
13+
return <div className="no-prose">{children}</div>;
1414
},
1515
pre: ({ children, ...props }: any) => {
1616
const codeElement = React.Children.only(children);
@@ -33,21 +33,21 @@ export const NonMemoizedMarkdown = ({ children }: { children: string }) => {
3333
},
3434
ol: ({ node, children, ...props }: any) => {
3535
return (
36-
<ol className='list-decimal list-inside ml-4' {...props}>
36+
<ol className="list-decimal list-inside ml-4" {...props}>
3737
{children}
3838
</ol>
3939
);
4040
},
4141
li: ({ node, children, ...props }: any) => {
4242
return (
43-
<li className='py-1' {...props}>
43+
<li className="py-1" {...props}>
4444
{children}
4545
</li>
4646
);
4747
},
4848
ul: ({ node, children, ...props }: any) => {
4949
return (
50-
<ul className='list-decimal list-inside ml-4' {...props}>
50+
<ul className="list-decimal list-inside ml-4" {...props}>
5151
{children}
5252
</ul>
5353
);

examples/nextjs-ai-chatbot/components/messages.tsx

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@ export default function Messages() {
2323

2424
if (isLoadingMessages) {
2525
return (
26-
<div className='flex justify-center items-center h-full animate__animated animate__fadeIn'>
27-
<span className='loading loading-spinner loading-md'></span>
26+
<div className="flex justify-center items-center h-full animate__animated animate__fadeIn">
27+
<span className="loading loading-spinner loading-md"></span>
2828
</div>
2929
);
3030
}
3131

3232
if (!id) {
3333
return (
34-
<div className='flex justify-center items-center flex-col h-full '>
35-
<h1 className='animate__animated animate__fadeInUp mb-0 '>
36-
<span className='ai-thinking'>Welcome to AI Assistant</span>
34+
<div className="flex justify-center items-center flex-col h-full ">
35+
<h1 className="animate__animated animate__fadeInUp mb-0 ">
36+
<span className="ai-thinking">Welcome to AI Assistant</span>
3737
</h1>
38-
<p className='animate__animated animate__fadeInUp animate__delay-1s text-gray-500'>
38+
<p className="animate__animated animate__fadeInUp animate__delay-1s text-gray-500">
3939
Ready to help you with any questions or tasks. How can I assist you
4040
today?
4141
</p>
@@ -44,29 +44,29 @@ export default function Messages() {
4444
}
4545

4646
return (
47-
<div className='py-15 pl-3 max-w-3xl mx-auto space-y-5'>
47+
<div className="py-15 pl-3 max-w-3xl mx-auto space-y-5">
4848
{messages.map((m: UIMessage) => (
4949
<div
5050
key={m.id}
5151
className={`chat animate__animated animate__fadeIn ${
5252
m.role === 'user' ? 'chat-end' : 'chat-start'
5353
}`}
5454
>
55-
<div className='flex gap-2 flex-wrap'>
55+
<div className="flex gap-2 flex-wrap">
5656
{m.parts.map(
5757
(part, index) =>
5858
part.type === 'file' &&
5959
part.url && (
6060
<a
6161
key={'file-' + index + m.id}
6262
href={part.url}
63-
target='_blank'
64-
className='not-prose mb-2'
63+
target="_blank"
64+
className="not-prose mb-2"
6565
>
6666
<Image
6767
src={part.url}
6868
alt={part.filename || 'unknown'}
69-
className='w-30 h-30 rounded-lg object-cover'
69+
className="w-30 h-30 rounded-lg object-cover"
7070
width={300}
7171
height={300}
7272
/>
@@ -91,9 +91,9 @@ export default function Messages() {
9191
</div>
9292
))}
9393
{status === 'submitted' && (
94-
<div className='flex gap-1 items-center text-sm my-4 animate-pulse'>
95-
<Sparkles className='w-3 h-3 animate-pulse text-[#00ffe0]' />
96-
<span className='ai-thinking'>Thinking</span>
94+
<div className="flex gap-1 items-center text-sm my-4 animate-pulse">
95+
<Sparkles className="w-3 h-3 animate-pulse text-[#00ffe0]" />
96+
<span className="ai-thinking">Thinking</span>
9797
</div>
9898
)}
9999
<div ref={messagesEndRef} />

examples/nextjs-ai-chatbot/components/sidebar.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ export default function Sidebar({ title = 'Chats' }) {
1111
const { id } = useParams();
1212
return (
1313
<>
14-
<h3 className='flex items-center gap-2'>
15-
<MessageSquareText className='w-5 h-5' /> {title}
14+
<h3 className="flex items-center gap-2">
15+
<MessageSquareText className="w-5 h-5" /> {title}
1616
</h3>
17-
<div className='animate__animated animate__fadeIn relative'>
17+
<div className="animate__animated animate__fadeIn relative">
1818
{chats?.length > 0 ? (
1919
chats.map((chat: ChatType) => (
2020
<Link
@@ -25,23 +25,23 @@ export default function Sidebar({ title = 'Chats' }) {
2525
id === chat.id ? 'text-primary' : ''
2626
}`}
2727
>
28-
<div className='flex items-center gap-1 min-w-0'>
29-
<Dot className='flex-shrink-0' />
30-
<span className='truncate'>{chat.name}</span>
28+
<div className="flex items-center gap-1 min-w-0">
29+
<Dot className="flex-shrink-0" />
30+
<span className="truncate">{chat.name}</span>
3131
</div>
3232
</Link>
3333
))
3434
) : (
35-
<div className='flex items-center gap-2 text-gray-600'>
35+
<div className="flex items-center gap-2 text-gray-600">
3636
No chats found
3737
</div>
3838
)}
3939
</div>
4040
<Link
41-
href='/'
42-
className='mb-2 btn btn-default btn-soft left-4 right-4 absolute bottom-2'
41+
href="/"
42+
className="mb-2 btn btn-default btn-soft left-4 right-4 absolute bottom-2"
4343
>
44-
<MessageSquarePlus className='w-4 h-4' />
44+
<MessageSquarePlus className="w-4 h-4" />
4545
New Chat
4646
</Link>
4747
</>

examples/nextjs-ai-chatbot/components/tools/weather.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ import { CloudSunIcon, MapPinIcon } from 'lucide-react';
44
export default function Weather({ data }: { data: string }) {
55
const weather: WeatherToolResponse = JSON.parse(data);
66
return (
7-
<div className='bg-base-200 p-4 pb-8 rounded-lg relative overflow-hidden min-w-sm'>
8-
<div className='text-lg font-bold flex items-center gap-2'>
9-
<MapPinIcon className='w-4 h-4' />
7+
<div className="bg-base-200 p-4 pb-8 rounded-lg relative overflow-hidden min-w-sm">
8+
<div className="text-lg font-bold flex items-center gap-2">
9+
<MapPinIcon className="w-4 h-4" />
1010
{weather.location?.name || 'Unknown'}
1111
</div>
12-
<div className='grid grid-cols-[1fr_2fr] gap-4 items-center justify-center my-4 font-bold'>
12+
<div className="grid grid-cols-[1fr_2fr] gap-4 items-center justify-center my-4 font-bold">
1313
<div>
1414
<img
1515
src={weather.current?.condition?.icon}
1616
alt={weather.current?.condition?.text}
17-
className='object-cover not-prose bg-base-100 rounded-lg p-2'
17+
className="object-cover not-prose bg-base-100 rounded-lg p-2"
1818
width={64}
1919
height={64}
2020
/>
@@ -24,15 +24,15 @@ export default function Weather({ data }: { data: string }) {
2424
<br /> Feels like: {weather.current?.feelslike_c}°C
2525
</div>
2626
</div>
27-
<div className='text-sm text-gray-500'>
27+
<div className="text-sm text-gray-500">
2828
<div>Condition: {weather.current?.condition?.text}</div>
2929
<div>Wind: {weather.current?.wind_kph} km/h</div>
3030
<div>Humidity: {weather.current?.humidity}%</div>
3131
<div>Pressure: {weather.current?.pressure_mb} mb</div>
3232
</div>
33-
<div className='flex items-center gap-1 opacity-50 text-xs absolute bottom-2 right-2 text-[#00ffe0]'>
34-
<CloudSunIcon className='w-3 h-3' />
35-
<span className='ai-thinking'>weather tool</span>
33+
<div className="flex items-center gap-1 opacity-50 text-xs absolute bottom-2 right-2 text-[#00ffe0]">
34+
<CloudSunIcon className="w-3 h-3" />
35+
<span className="ai-thinking">weather tool</span>
3636
</div>
3737
</div>
3838
);

0 commit comments

Comments
 (0)