cortex-react-components 2.0.8 → 2.0.10
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/{chunk-5O4QU3FO.mjs → chunk-35MOYND3.mjs} +1 -1
- package/dist/chunk-45Z6Y2JZ.mjs +4 -0
- package/dist/{chunk-P53OTWDE.mjs → chunk-5TJPUM35.mjs} +1 -1
- package/dist/{chunk-CLGBBNRB.mjs → chunk-75WE6ZXB.mjs} +1 -1
- package/dist/{chunk-GLMVATBC.mjs → chunk-7NYJVQ22.mjs} +1 -1
- package/dist/{chunk-36PL6SXU.mjs → chunk-7Y6IS436.mjs} +1 -1
- package/dist/chunk-B753NNIJ.mjs +1 -0
- package/dist/{chunk-FONUFLBI.mjs → chunk-F3F54TXG.mjs} +1 -1
- package/dist/{chunk-PZCNIPIA.mjs → chunk-FMCBJ4WI.mjs} +1 -1
- package/dist/{chunk-WIIGZJLT.mjs → chunk-GKSMOZLR.mjs} +1 -1
- package/dist/{chunk-4FP5GLMD.mjs → chunk-GNFKYRNR.mjs} +1 -1
- package/dist/{chunk-MZ7ZHGT7.mjs → chunk-GUOVROAM.mjs} +1 -1
- package/dist/{chunk-MXISPX3W.mjs → chunk-HYX44K7F.mjs} +1 -1
- package/dist/{chunk-S36H4JAL.mjs → chunk-IGPG2Z5Y.mjs} +1 -1
- package/dist/{chunk-OO7RQCK6.mjs → chunk-MNMDMQ6E.mjs} +1 -1
- package/dist/{chunk-CSNHOTMZ.mjs → chunk-MZWGXTDT.mjs} +1 -1
- package/dist/{chunk-C3KGAABY.mjs → chunk-NABSSYAH.mjs} +1 -1
- package/dist/{chunk-MMOATE43.mjs → chunk-NEBCCCJK.mjs} +1 -1
- package/dist/{chunk-TIPBA4EM.mjs → chunk-ONJIFYPO.mjs} +1 -1
- package/dist/{chunk-IUDZWH6J.mjs → chunk-OWW3TCUF.mjs} +1 -1
- package/dist/{chunk-7RRPNMIO.mjs → chunk-OZWPWDGD.mjs} +1 -1
- package/dist/{chunk-FHJ4MHLT.mjs → chunk-TBM5A6KN.mjs} +1 -1
- package/dist/{chunk-SRUG246N.mjs → chunk-TXVA6XJT.mjs} +1 -1
- package/dist/{chunk-72SLLEHW.mjs → chunk-U2MZLHPX.mjs} +1 -1
- package/dist/{chunk-ZGQC6O62.mjs → chunk-UEBQJNVT.mjs} +1 -1
- package/dist/{chunk-B3IP63Q2.mjs → chunk-V5TQHIXH.mjs} +1 -1
- package/dist/{chunk-5B6FLVPH.mjs → chunk-V5W32NJ4.mjs} +1 -1
- package/dist/{chunk-RAMI7KEB.mjs → chunk-VX656CU4.mjs} +1 -1
- package/dist/{chunk-OE6DHWF3.mjs → chunk-WXPZ4HGC.mjs} +1 -1
- package/dist/{chunk-YYBKYJU2.mjs → chunk-XNJSFWXE.mjs} +1 -1
- package/dist/{chunk-3TFLP3CZ.mjs → chunk-YGEUYPGK.mjs} +1 -1
- package/dist/{chunk-RV2TWILK.mjs → chunk-ZJAZWWSJ.mjs} +1 -1
- package/dist/components/Blocks/Banner.mjs +1 -1
- package/dist/components/Blocks/CallToAction.mjs +1 -1
- package/dist/components/Blocks/CollapsibleArea.mjs +1 -1
- package/dist/components/Blocks/Content.mjs +1 -1
- package/dist/components/Blocks/FeaturesBlock.mjs +1 -1
- package/dist/components/Blocks/RelatedPosts.mjs +1 -1
- package/dist/components/Blocks/RenderBlocks.mjs +1 -1
- package/dist/components/Blocks/ReusableContentBlock.mjs +1 -1
- package/dist/components/Blocks/index.mjs +1 -1
- package/dist/components/Cards/ContentCard.mjs +1 -1
- package/dist/components/Cards/FeatureCard.mjs +1 -1
- package/dist/components/Cards/index.mjs +1 -1
- package/dist/components/Chat/ChatInterface.js +1 -1
- package/dist/components/Chat/ChatInterface.mjs +1 -1
- package/dist/components/Chat/CopilotInterface.js +1 -1
- package/dist/components/Chat/CopilotInterface.mjs +1 -1
- package/dist/components/Chat/FILE_UPLOAD_GUIDE.js +219 -0
- package/dist/components/Chat/FILE_UPLOAD_GUIDE.mjs +219 -0
- package/dist/components/Chat/demo-long-messages.css +1 -0
- package/dist/components/Chat/demo-long-messages.d.ts +5 -0
- package/dist/components/Chat/demo-long-messages.js +59 -0
- package/dist/components/Chat/demo-long-messages.mjs +55 -0
- package/dist/components/Chat/demo.js +1 -1
- package/dist/components/Chat/demo.mjs +1 -1
- package/dist/components/Chat/example-usage.js +1 -1
- package/dist/components/Chat/example-usage.mjs +1 -1
- package/dist/components/Chat/example-with-file-uploads.css +1 -0
- package/dist/components/Chat/example-with-file-uploads.d.ts +54 -0
- package/dist/components/Chat/example-with-file-uploads.js +2 -0
- package/dist/components/Chat/example-with-file-uploads.mjs +2 -0
- package/dist/components/Chat/example-with-vercel-ai.d.ts +4 -0
- package/dist/components/Chat/example-with-vercel-ai.js +1 -1
- package/dist/components/Chat/example-with-vercel-ai.mjs +1 -1
- package/dist/components/Chat/index.js +2 -2
- package/dist/components/Chat/index.mjs +1 -1
- package/dist/components/DeliveryLead/DeliveryLeadSubmissionWithList.mjs +1 -1
- package/dist/components/DeliveryLead/index.mjs +1 -1
- package/dist/components/DigitalColleagues/MainPage.mjs +1 -1
- package/dist/components/DigitalColleagues/Pages/dashboardpage.mjs +1 -1
- package/dist/components/DigitalColleagues/Views/ColleaguesView.mjs +1 -1
- package/dist/components/DigitalColleagues/Views/index.mjs +1 -1
- package/dist/components/HeaderFooter/Header.mjs +1 -1
- package/dist/components/HeaderFooter/SectionHeading.mjs +1 -1
- package/dist/components/HeaderFooter/VideoHeader.mjs +1 -1
- package/dist/components/HeaderFooter/index.mjs +1 -1
- package/dist/components/Heros/HighImpact/index.mjs +1 -1
- package/dist/components/Heros/LowImpact/index.mjs +1 -1
- package/dist/components/Heros/MediumImpact/index.mjs +1 -1
- package/dist/components/Heros/RenderHero.mjs +1 -1
- package/dist/components/Heros/SectionHero/index.mjs +1 -1
- package/dist/components/Heros/index.mjs +1 -1
- package/dist/components/Holidays/HolidayTracker.mjs +1 -1
- package/dist/components/Holidays/index.mjs +1 -1
- package/dist/components/Layouts/OutputHeaderFooter.mjs +1 -1
- package/dist/components/Layouts/Print.mjs +1 -1
- package/dist/components/Layouts/SlideShow.mjs +1 -1
- package/dist/components/Layouts/index.mjs +1 -1
- package/dist/components/Other/index.mjs +1 -1
- package/dist/components/Payload/RichText/index.mjs +1 -1
- package/dist/components/Payload/RichText/serialize.mjs +1 -1
- package/dist/components/Payload/index.mjs +1 -1
- package/dist/components/Projects/KanbanBoardView.mjs +1 -1
- package/dist/components/Projects/ProjectPage.mjs +1 -1
- package/dist/components/Projects/ProjectView.mjs +1 -1
- package/dist/components/dc-temp/index.mjs +1 -1
- package/dist/components/index.js +9 -9
- package/dist/components/index.mjs +1 -1
- package/dist/globals.css +1 -1
- package/dist/index.js +10 -10
- package/dist/index.mjs +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/pages/Blog.mjs +1 -1
- package/dist/pages/Documentation.mjs +1 -1
- package/dist/pages/IndexPage.mjs +1 -1
- package/dist/pages/Intranet.mjs +1 -1
- package/dist/pages/LandingPage.mjs +1 -1
- package/dist/pages/Page.mjs +1 -1
- package/dist/pages/Publish.mjs +1 -1
- package/dist/pages/Website.mjs +1 -1
- package/dist/sections/AboutSection.mjs +1 -1
- package/dist/sections/BlogDetail.mjs +1 -1
- package/dist/sections/BlogList.mjs +1 -1
- package/dist/sections/ContactSection.mjs +1 -1
- package/dist/sections/PageSections.mjs +1 -1
- package/dist/sections/PricingSection.mjs +1 -1
- package/dist/sections/ServiceDetail.mjs +1 -1
- package/dist/sections/ServiceDetailSection.mjs +1 -1
- package/dist/sections/ServiceSection.mjs +1 -1
- package/dist/sections/form/index.mjs +1 -1
- package/dist/sections/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-AAIHHUX2.mjs +0 -4
- package/dist/chunk-L7W3JS7W.mjs +0 -1
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
var s=`# File Uploads with AI SDK useChat Hook
|
|
2
|
+
|
|
3
|
+
This guide explains how to implement file attachments with the Vercel AI SDK v5 \`useChat\` hook.
|
|
4
|
+
|
|
5
|
+
## Key Concepts
|
|
6
|
+
|
|
7
|
+
1. **Use \`sendMessage\` with files parameter** - The AI SDK's \`sendMessage\` method accepts a \`files\` parameter
|
|
8
|
+
2. **Convert File[] to FileList** - The AI SDK expects a \`FileList\`, not an array of \`File\` objects
|
|
9
|
+
3. **Handle file validation** - Validate file size, type, and other constraints before sending
|
|
10
|
+
4. **Display files in chat** - Render uploaded files in the message parts
|
|
11
|
+
|
|
12
|
+
## Basic Implementation
|
|
13
|
+
|
|
14
|
+
\`\`\`tsx
|
|
15
|
+
import { useChat } from '@ai-sdk/react'
|
|
16
|
+
|
|
17
|
+
const MyChat = () => {
|
|
18
|
+
const chatHook = useChat({
|
|
19
|
+
// your configuration
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
const [selectedFiles, setSelectedFiles] = useState<File[]>([])
|
|
23
|
+
const [input, setInput] = useState('')
|
|
24
|
+
|
|
25
|
+
// Helper function to create FileList from File objects
|
|
26
|
+
const createFileList = (files: File[]): FileList => {
|
|
27
|
+
const dataTransfer = new DataTransfer()
|
|
28
|
+
files.forEach(file => dataTransfer.items.add(file))
|
|
29
|
+
return dataTransfer.files
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const handleSendWithFiles = () => {
|
|
33
|
+
const fileList = selectedFiles.length > 0
|
|
34
|
+
? createFileList(selectedFiles)
|
|
35
|
+
: undefined
|
|
36
|
+
|
|
37
|
+
chatHook.sendMessage({
|
|
38
|
+
text: input,
|
|
39
|
+
files: fileList
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
setInput('')
|
|
43
|
+
setSelectedFiles([])
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ... rest of your component
|
|
47
|
+
}
|
|
48
|
+
\`\`\`
|
|
49
|
+
|
|
50
|
+
## File Validation
|
|
51
|
+
|
|
52
|
+
\`\`\`tsx
|
|
53
|
+
const handleFileSelect = (files: FileList | null) => {
|
|
54
|
+
if (!files) return
|
|
55
|
+
|
|
56
|
+
const maxFileSize = 10 * 1024 * 1024 // 10MB
|
|
57
|
+
const allowedTypes = ['image/*', 'text/*', 'application/pdf']
|
|
58
|
+
const validFiles: File[] = []
|
|
59
|
+
|
|
60
|
+
Array.from(files).forEach(file => {
|
|
61
|
+
// Validate file size
|
|
62
|
+
if (file.size > maxFileSize) {
|
|
63
|
+
alert(\`File \${file.name} is too large. Maximum size is 10MB.\`)
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Validate file type
|
|
68
|
+
if (!allowedTypes.some(type => file.type.match(type))) {
|
|
69
|
+
alert(\`File type \${file.type} is not allowed.\`)
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
validFiles.push(file)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
setSelectedFiles(prev => [...prev, ...validFiles])
|
|
77
|
+
}
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
## Server-Side Handling
|
|
81
|
+
|
|
82
|
+
Your API route will receive the files in the \`messages\` array as file parts:
|
|
83
|
+
|
|
84
|
+
\`\`\`typescript
|
|
85
|
+
// app/api/chat/route.ts
|
|
86
|
+
import { openai } from '@ai-sdk/openai'
|
|
87
|
+
import { convertToModelMessages, streamText, UIMessage } from 'ai'
|
|
88
|
+
|
|
89
|
+
export async function POST(req: Request) {
|
|
90
|
+
const { messages }: { messages: UIMessage[] } = await req.json()
|
|
91
|
+
|
|
92
|
+
// Messages with files will have parts like:
|
|
93
|
+
// {
|
|
94
|
+
// role: 'user',
|
|
95
|
+
// parts: [
|
|
96
|
+
// { type: 'text', text: 'Here is my file' },
|
|
97
|
+
// {
|
|
98
|
+
// type: 'file',
|
|
99
|
+
// mimeType: 'image/jpeg',
|
|
100
|
+
// data: 'base64-encoded-data',
|
|
101
|
+
// url: 'data:image/jpeg;base64,...'
|
|
102
|
+
// }
|
|
103
|
+
// ]
|
|
104
|
+
// }
|
|
105
|
+
|
|
106
|
+
const result = streamText({
|
|
107
|
+
model: openai('gpt-4o'), // Use a model that supports vision for images
|
|
108
|
+
system: 'You are a helpful assistant that can analyze files and images.',
|
|
109
|
+
messages: convertToModelMessages(messages),
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
return result.toUIMessageStreamResponse()
|
|
113
|
+
}
|
|
114
|
+
\`\`\`
|
|
115
|
+
|
|
116
|
+
## Displaying Files in Chat
|
|
117
|
+
|
|
118
|
+
Files will appear in the \`message.parts\` array with \`type: 'file'\`:
|
|
119
|
+
|
|
120
|
+
\`\`\`tsx
|
|
121
|
+
{messages.map((message) => (
|
|
122
|
+
<div key={message.id}>
|
|
123
|
+
{message.parts.map((part, index) => {
|
|
124
|
+
if (part.type === 'text') {
|
|
125
|
+
return <p key={index}>{part.text}</p>
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (part.type === 'file') {
|
|
129
|
+
const filePart = part as any
|
|
130
|
+
return (
|
|
131
|
+
<div key={index} className="mb-2">
|
|
132
|
+
<p className="text-sm font-semibold">
|
|
133
|
+
\u{1F4CE} {filePart.filename || filePart.name}
|
|
134
|
+
</p>
|
|
135
|
+
{filePart.mediaType?.startsWith('image/') && (
|
|
136
|
+
<img
|
|
137
|
+
src={filePart.url}
|
|
138
|
+
alt={filePart.filename}
|
|
139
|
+
className="max-w-full h-auto rounded"
|
|
140
|
+
/>
|
|
141
|
+
)}
|
|
142
|
+
</div>
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return null
|
|
147
|
+
})}
|
|
148
|
+
</div>
|
|
149
|
+
))}
|
|
150
|
+
\`\`\`
|
|
151
|
+
|
|
152
|
+
## Integration with CopilotInterface
|
|
153
|
+
|
|
154
|
+
If using the \`CopilotInterface\` component, the file upload functionality is already integrated. You just need to pass the correct \`useChat\` hook:
|
|
155
|
+
|
|
156
|
+
\`\`\`tsx
|
|
157
|
+
import { CopilotInterface } from '@/components/Chat'
|
|
158
|
+
import { useChat } from '@ai-sdk/react'
|
|
159
|
+
|
|
160
|
+
const MyApp = () => {
|
|
161
|
+
const chatHook = useChat({
|
|
162
|
+
// your configuration
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<CopilotInterface
|
|
167
|
+
useCustomChat={chatHook}
|
|
168
|
+
enableAI={true}
|
|
169
|
+
enableFileUpload={true}
|
|
170
|
+
maxFileSize={10}
|
|
171
|
+
allowedFileTypes={['image/*', 'text/*', 'application/pdf']}
|
|
172
|
+
// ... other props
|
|
173
|
+
/>
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
\`\`\`
|
|
177
|
+
|
|
178
|
+
## Complete Example
|
|
179
|
+
|
|
180
|
+
See \`example-with-file-uploads.tsx\` for a complete working example that demonstrates:
|
|
181
|
+
|
|
182
|
+
- File selection and validation
|
|
183
|
+
- Converting File[] to FileList
|
|
184
|
+
- Sending messages with files using \`sendMessage\`
|
|
185
|
+
- Displaying files in the chat interface
|
|
186
|
+
- Error handling
|
|
187
|
+
|
|
188
|
+
## Supported File Types
|
|
189
|
+
|
|
190
|
+
The AI SDK automatically converts certain file types to multi-modal content:
|
|
191
|
+
|
|
192
|
+
- **Images** (\`image/*\`) - Converted to image parts for vision models
|
|
193
|
+
- **Text files** (\`text/*\`) - Content is extracted and included as text
|
|
194
|
+
- **Other files** - Included as file attachments with metadata
|
|
195
|
+
|
|
196
|
+
## Best Practices
|
|
197
|
+
|
|
198
|
+
1. **Validate file size and type** before sending
|
|
199
|
+
2. **Use appropriate models** - Use vision-capable models (like GPT-4o) for images
|
|
200
|
+
3. **Handle errors gracefully** - Show user-friendly error messages
|
|
201
|
+
4. **Provide file previews** - Show thumbnails or file info before sending
|
|
202
|
+
5. **Clear files after sending** - Reset the file selection after successful send
|
|
203
|
+
6. **Add loading states** - Show upload progress and sending status
|
|
204
|
+
|
|
205
|
+
## Troubleshooting
|
|
206
|
+
|
|
207
|
+
### Files not appearing in messages
|
|
208
|
+
- Make sure you're converting File[] to FileList using the helper function
|
|
209
|
+
- Verify your server is configured to handle multipart/form-data
|
|
210
|
+
|
|
211
|
+
### Large file errors
|
|
212
|
+
- Check your file size validation
|
|
213
|
+
- Verify your server's upload size limits
|
|
214
|
+
- Consider implementing chunked uploads for very large files
|
|
215
|
+
|
|
216
|
+
### File type issues
|
|
217
|
+
- Ensure your file type validation matches what the AI model supports
|
|
218
|
+
- Check that the MIME type is correctly detected
|
|
219
|
+
`;
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import"../../chunk-YEKQJ4YC.mjs";var s=`# File Uploads with AI SDK useChat Hook
|
|
2
|
+
|
|
3
|
+
This guide explains how to implement file attachments with the Vercel AI SDK v5 \`useChat\` hook.
|
|
4
|
+
|
|
5
|
+
## Key Concepts
|
|
6
|
+
|
|
7
|
+
1. **Use \`sendMessage\` with files parameter** - The AI SDK's \`sendMessage\` method accepts a \`files\` parameter
|
|
8
|
+
2. **Convert File[] to FileList** - The AI SDK expects a \`FileList\`, not an array of \`File\` objects
|
|
9
|
+
3. **Handle file validation** - Validate file size, type, and other constraints before sending
|
|
10
|
+
4. **Display files in chat** - Render uploaded files in the message parts
|
|
11
|
+
|
|
12
|
+
## Basic Implementation
|
|
13
|
+
|
|
14
|
+
\`\`\`tsx
|
|
15
|
+
import { useChat } from '@ai-sdk/react'
|
|
16
|
+
|
|
17
|
+
const MyChat = () => {
|
|
18
|
+
const chatHook = useChat({
|
|
19
|
+
// your configuration
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
const [selectedFiles, setSelectedFiles] = useState<File[]>([])
|
|
23
|
+
const [input, setInput] = useState('')
|
|
24
|
+
|
|
25
|
+
// Helper function to create FileList from File objects
|
|
26
|
+
const createFileList = (files: File[]): FileList => {
|
|
27
|
+
const dataTransfer = new DataTransfer()
|
|
28
|
+
files.forEach(file => dataTransfer.items.add(file))
|
|
29
|
+
return dataTransfer.files
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const handleSendWithFiles = () => {
|
|
33
|
+
const fileList = selectedFiles.length > 0
|
|
34
|
+
? createFileList(selectedFiles)
|
|
35
|
+
: undefined
|
|
36
|
+
|
|
37
|
+
chatHook.sendMessage({
|
|
38
|
+
text: input,
|
|
39
|
+
files: fileList
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
setInput('')
|
|
43
|
+
setSelectedFiles([])
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ... rest of your component
|
|
47
|
+
}
|
|
48
|
+
\`\`\`
|
|
49
|
+
|
|
50
|
+
## File Validation
|
|
51
|
+
|
|
52
|
+
\`\`\`tsx
|
|
53
|
+
const handleFileSelect = (files: FileList | null) => {
|
|
54
|
+
if (!files) return
|
|
55
|
+
|
|
56
|
+
const maxFileSize = 10 * 1024 * 1024 // 10MB
|
|
57
|
+
const allowedTypes = ['image/*', 'text/*', 'application/pdf']
|
|
58
|
+
const validFiles: File[] = []
|
|
59
|
+
|
|
60
|
+
Array.from(files).forEach(file => {
|
|
61
|
+
// Validate file size
|
|
62
|
+
if (file.size > maxFileSize) {
|
|
63
|
+
alert(\`File \${file.name} is too large. Maximum size is 10MB.\`)
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Validate file type
|
|
68
|
+
if (!allowedTypes.some(type => file.type.match(type))) {
|
|
69
|
+
alert(\`File type \${file.type} is not allowed.\`)
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
validFiles.push(file)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
setSelectedFiles(prev => [...prev, ...validFiles])
|
|
77
|
+
}
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
## Server-Side Handling
|
|
81
|
+
|
|
82
|
+
Your API route will receive the files in the \`messages\` array as file parts:
|
|
83
|
+
|
|
84
|
+
\`\`\`typescript
|
|
85
|
+
// app/api/chat/route.ts
|
|
86
|
+
import { openai } from '@ai-sdk/openai'
|
|
87
|
+
import { convertToModelMessages, streamText, UIMessage } from 'ai'
|
|
88
|
+
|
|
89
|
+
export async function POST(req: Request) {
|
|
90
|
+
const { messages }: { messages: UIMessage[] } = await req.json()
|
|
91
|
+
|
|
92
|
+
// Messages with files will have parts like:
|
|
93
|
+
// {
|
|
94
|
+
// role: 'user',
|
|
95
|
+
// parts: [
|
|
96
|
+
// { type: 'text', text: 'Here is my file' },
|
|
97
|
+
// {
|
|
98
|
+
// type: 'file',
|
|
99
|
+
// mimeType: 'image/jpeg',
|
|
100
|
+
// data: 'base64-encoded-data',
|
|
101
|
+
// url: 'data:image/jpeg;base64,...'
|
|
102
|
+
// }
|
|
103
|
+
// ]
|
|
104
|
+
// }
|
|
105
|
+
|
|
106
|
+
const result = streamText({
|
|
107
|
+
model: openai('gpt-4o'), // Use a model that supports vision for images
|
|
108
|
+
system: 'You are a helpful assistant that can analyze files and images.',
|
|
109
|
+
messages: convertToModelMessages(messages),
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
return result.toUIMessageStreamResponse()
|
|
113
|
+
}
|
|
114
|
+
\`\`\`
|
|
115
|
+
|
|
116
|
+
## Displaying Files in Chat
|
|
117
|
+
|
|
118
|
+
Files will appear in the \`message.parts\` array with \`type: 'file'\`:
|
|
119
|
+
|
|
120
|
+
\`\`\`tsx
|
|
121
|
+
{messages.map((message) => (
|
|
122
|
+
<div key={message.id}>
|
|
123
|
+
{message.parts.map((part, index) => {
|
|
124
|
+
if (part.type === 'text') {
|
|
125
|
+
return <p key={index}>{part.text}</p>
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (part.type === 'file') {
|
|
129
|
+
const filePart = part as any
|
|
130
|
+
return (
|
|
131
|
+
<div key={index} className="mb-2">
|
|
132
|
+
<p className="text-sm font-semibold">
|
|
133
|
+
\u{1F4CE} {filePart.filename || filePart.name}
|
|
134
|
+
</p>
|
|
135
|
+
{filePart.mediaType?.startsWith('image/') && (
|
|
136
|
+
<img
|
|
137
|
+
src={filePart.url}
|
|
138
|
+
alt={filePart.filename}
|
|
139
|
+
className="max-w-full h-auto rounded"
|
|
140
|
+
/>
|
|
141
|
+
)}
|
|
142
|
+
</div>
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return null
|
|
147
|
+
})}
|
|
148
|
+
</div>
|
|
149
|
+
))}
|
|
150
|
+
\`\`\`
|
|
151
|
+
|
|
152
|
+
## Integration with CopilotInterface
|
|
153
|
+
|
|
154
|
+
If using the \`CopilotInterface\` component, the file upload functionality is already integrated. You just need to pass the correct \`useChat\` hook:
|
|
155
|
+
|
|
156
|
+
\`\`\`tsx
|
|
157
|
+
import { CopilotInterface } from '@/components/Chat'
|
|
158
|
+
import { useChat } from '@ai-sdk/react'
|
|
159
|
+
|
|
160
|
+
const MyApp = () => {
|
|
161
|
+
const chatHook = useChat({
|
|
162
|
+
// your configuration
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<CopilotInterface
|
|
167
|
+
useCustomChat={chatHook}
|
|
168
|
+
enableAI={true}
|
|
169
|
+
enableFileUpload={true}
|
|
170
|
+
maxFileSize={10}
|
|
171
|
+
allowedFileTypes={['image/*', 'text/*', 'application/pdf']}
|
|
172
|
+
// ... other props
|
|
173
|
+
/>
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
\`\`\`
|
|
177
|
+
|
|
178
|
+
## Complete Example
|
|
179
|
+
|
|
180
|
+
See \`example-with-file-uploads.tsx\` for a complete working example that demonstrates:
|
|
181
|
+
|
|
182
|
+
- File selection and validation
|
|
183
|
+
- Converting File[] to FileList
|
|
184
|
+
- Sending messages with files using \`sendMessage\`
|
|
185
|
+
- Displaying files in the chat interface
|
|
186
|
+
- Error handling
|
|
187
|
+
|
|
188
|
+
## Supported File Types
|
|
189
|
+
|
|
190
|
+
The AI SDK automatically converts certain file types to multi-modal content:
|
|
191
|
+
|
|
192
|
+
- **Images** (\`image/*\`) - Converted to image parts for vision models
|
|
193
|
+
- **Text files** (\`text/*\`) - Content is extracted and included as text
|
|
194
|
+
- **Other files** - Included as file attachments with metadata
|
|
195
|
+
|
|
196
|
+
## Best Practices
|
|
197
|
+
|
|
198
|
+
1. **Validate file size and type** before sending
|
|
199
|
+
2. **Use appropriate models** - Use vision-capable models (like GPT-4o) for images
|
|
200
|
+
3. **Handle errors gracefully** - Show user-friendly error messages
|
|
201
|
+
4. **Provide file previews** - Show thumbnails or file info before sending
|
|
202
|
+
5. **Clear files after sending** - Reset the file selection after successful send
|
|
203
|
+
6. **Add loading states** - Show upload progress and sending status
|
|
204
|
+
|
|
205
|
+
## Troubleshooting
|
|
206
|
+
|
|
207
|
+
### Files not appearing in messages
|
|
208
|
+
- Make sure you're converting File[] to FileList using the helper function
|
|
209
|
+
- Verify your server is configured to handle multipart/form-data
|
|
210
|
+
|
|
211
|
+
### Large file errors
|
|
212
|
+
- Check your file size validation
|
|
213
|
+
- Verify your server's upload size limits
|
|
214
|
+
- Consider implementing chunked uploads for very large files
|
|
215
|
+
|
|
216
|
+
### File type issues
|
|
217
|
+
- Ensure your file type validation matches what the AI model supports
|
|
218
|
+
- Check that the MIME type is correctly detected
|
|
219
|
+
`;export{s as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[data-aos][data-aos][data-aos-duration="50"],body[data-aos-duration="50"] [data-aos]{transition-duration:50ms}[data-aos][data-aos][data-aos-delay="50"],body[data-aos-delay="50"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="50"].aos-animate,body[data-aos-delay="50"] [data-aos].aos-animate{transition-delay:50ms}[data-aos][data-aos][data-aos-duration="100"],body[data-aos-duration="100"] [data-aos]{transition-duration:.1s}[data-aos][data-aos][data-aos-delay="100"],body[data-aos-delay="100"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="100"].aos-animate,body[data-aos-delay="100"] [data-aos].aos-animate{transition-delay:.1s}[data-aos][data-aos][data-aos-duration="150"],body[data-aos-duration="150"] [data-aos]{transition-duration:.15s}[data-aos][data-aos][data-aos-delay="150"],body[data-aos-delay="150"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="150"].aos-animate,body[data-aos-delay="150"] [data-aos].aos-animate{transition-delay:.15s}[data-aos][data-aos][data-aos-duration="200"],body[data-aos-duration="200"] [data-aos]{transition-duration:.2s}[data-aos][data-aos][data-aos-delay="200"],body[data-aos-delay="200"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="200"].aos-animate,body[data-aos-delay="200"] [data-aos].aos-animate{transition-delay:.2s}[data-aos][data-aos][data-aos-duration="250"],body[data-aos-duration="250"] [data-aos]{transition-duration:.25s}[data-aos][data-aos][data-aos-delay="250"],body[data-aos-delay="250"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="250"].aos-animate,body[data-aos-delay="250"] [data-aos].aos-animate{transition-delay:.25s}[data-aos][data-aos][data-aos-duration="300"],body[data-aos-duration="300"] [data-aos]{transition-duration:.3s}[data-aos][data-aos][data-aos-delay="300"],body[data-aos-delay="300"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="300"].aos-animate,body[data-aos-delay="300"] [data-aos].aos-animate{transition-delay:.3s}[data-aos][data-aos][data-aos-duration="350"],body[data-aos-duration="350"] [data-aos]{transition-duration:.35s}[data-aos][data-aos][data-aos-delay="350"],body[data-aos-delay="350"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="350"].aos-animate,body[data-aos-delay="350"] [data-aos].aos-animate{transition-delay:.35s}[data-aos][data-aos][data-aos-duration="400"],body[data-aos-duration="400"] [data-aos]{transition-duration:.4s}[data-aos][data-aos][data-aos-delay="400"],body[data-aos-delay="400"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="400"].aos-animate,body[data-aos-delay="400"] [data-aos].aos-animate{transition-delay:.4s}[data-aos][data-aos][data-aos-duration="450"],body[data-aos-duration="450"] [data-aos]{transition-duration:.45s}[data-aos][data-aos][data-aos-delay="450"],body[data-aos-delay="450"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="450"].aos-animate,body[data-aos-delay="450"] [data-aos].aos-animate{transition-delay:.45s}[data-aos][data-aos][data-aos-duration="500"],body[data-aos-duration="500"] [data-aos]{transition-duration:.5s}[data-aos][data-aos][data-aos-delay="500"],body[data-aos-delay="500"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="500"].aos-animate,body[data-aos-delay="500"] [data-aos].aos-animate{transition-delay:.5s}[data-aos][data-aos][data-aos-duration="550"],body[data-aos-duration="550"] [data-aos]{transition-duration:.55s}[data-aos][data-aos][data-aos-delay="550"],body[data-aos-delay="550"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="550"].aos-animate,body[data-aos-delay="550"] [data-aos].aos-animate{transition-delay:.55s}[data-aos][data-aos][data-aos-duration="600"],body[data-aos-duration="600"] [data-aos]{transition-duration:.6s}[data-aos][data-aos][data-aos-delay="600"],body[data-aos-delay="600"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="600"].aos-animate,body[data-aos-delay="600"] [data-aos].aos-animate{transition-delay:.6s}[data-aos][data-aos][data-aos-duration="650"],body[data-aos-duration="650"] [data-aos]{transition-duration:.65s}[data-aos][data-aos][data-aos-delay="650"],body[data-aos-delay="650"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="650"].aos-animate,body[data-aos-delay="650"] [data-aos].aos-animate{transition-delay:.65s}[data-aos][data-aos][data-aos-duration="700"],body[data-aos-duration="700"] [data-aos]{transition-duration:.7s}[data-aos][data-aos][data-aos-delay="700"],body[data-aos-delay="700"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="700"].aos-animate,body[data-aos-delay="700"] [data-aos].aos-animate{transition-delay:.7s}[data-aos][data-aos][data-aos-duration="750"],body[data-aos-duration="750"] [data-aos]{transition-duration:.75s}[data-aos][data-aos][data-aos-delay="750"],body[data-aos-delay="750"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="750"].aos-animate,body[data-aos-delay="750"] [data-aos].aos-animate{transition-delay:.75s}[data-aos][data-aos][data-aos-duration="800"],body[data-aos-duration="800"] [data-aos]{transition-duration:.8s}[data-aos][data-aos][data-aos-delay="800"],body[data-aos-delay="800"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="800"].aos-animate,body[data-aos-delay="800"] [data-aos].aos-animate{transition-delay:.8s}[data-aos][data-aos][data-aos-duration="850"],body[data-aos-duration="850"] [data-aos]{transition-duration:.85s}[data-aos][data-aos][data-aos-delay="850"],body[data-aos-delay="850"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="850"].aos-animate,body[data-aos-delay="850"] [data-aos].aos-animate{transition-delay:.85s}[data-aos][data-aos][data-aos-duration="900"],body[data-aos-duration="900"] [data-aos]{transition-duration:.9s}[data-aos][data-aos][data-aos-delay="900"],body[data-aos-delay="900"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="900"].aos-animate,body[data-aos-delay="900"] [data-aos].aos-animate{transition-delay:.9s}[data-aos][data-aos][data-aos-duration="950"],body[data-aos-duration="950"] [data-aos]{transition-duration:.95s}[data-aos][data-aos][data-aos-delay="950"],body[data-aos-delay="950"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="950"].aos-animate,body[data-aos-delay="950"] [data-aos].aos-animate{transition-delay:.95s}[data-aos][data-aos][data-aos-duration="1000"],body[data-aos-duration="1000"] [data-aos]{transition-duration:1s}[data-aos][data-aos][data-aos-delay="1000"],body[data-aos-delay="1000"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1000"].aos-animate,body[data-aos-delay="1000"] [data-aos].aos-animate{transition-delay:1s}[data-aos][data-aos][data-aos-duration="1050"],body[data-aos-duration="1050"] [data-aos]{transition-duration:1.05s}[data-aos][data-aos][data-aos-delay="1050"],body[data-aos-delay="1050"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1050"].aos-animate,body[data-aos-delay="1050"] [data-aos].aos-animate{transition-delay:1.05s}[data-aos][data-aos][data-aos-duration="1100"],body[data-aos-duration="1100"] [data-aos]{transition-duration:1.1s}[data-aos][data-aos][data-aos-delay="1100"],body[data-aos-delay="1100"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1100"].aos-animate,body[data-aos-delay="1100"] [data-aos].aos-animate{transition-delay:1.1s}[data-aos][data-aos][data-aos-duration="1150"],body[data-aos-duration="1150"] [data-aos]{transition-duration:1.15s}[data-aos][data-aos][data-aos-delay="1150"],body[data-aos-delay="1150"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1150"].aos-animate,body[data-aos-delay="1150"] [data-aos].aos-animate{transition-delay:1.15s}[data-aos][data-aos][data-aos-duration="1200"],body[data-aos-duration="1200"] [data-aos]{transition-duration:1.2s}[data-aos][data-aos][data-aos-delay="1200"],body[data-aos-delay="1200"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1200"].aos-animate,body[data-aos-delay="1200"] [data-aos].aos-animate{transition-delay:1.2s}[data-aos][data-aos][data-aos-duration="1250"],body[data-aos-duration="1250"] [data-aos]{transition-duration:1.25s}[data-aos][data-aos][data-aos-delay="1250"],body[data-aos-delay="1250"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1250"].aos-animate,body[data-aos-delay="1250"] [data-aos].aos-animate{transition-delay:1.25s}[data-aos][data-aos][data-aos-duration="1300"],body[data-aos-duration="1300"] [data-aos]{transition-duration:1.3s}[data-aos][data-aos][data-aos-delay="1300"],body[data-aos-delay="1300"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1300"].aos-animate,body[data-aos-delay="1300"] [data-aos].aos-animate{transition-delay:1.3s}[data-aos][data-aos][data-aos-duration="1350"],body[data-aos-duration="1350"] [data-aos]{transition-duration:1.35s}[data-aos][data-aos][data-aos-delay="1350"],body[data-aos-delay="1350"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1350"].aos-animate,body[data-aos-delay="1350"] [data-aos].aos-animate{transition-delay:1.35s}[data-aos][data-aos][data-aos-duration="1400"],body[data-aos-duration="1400"] [data-aos]{transition-duration:1.4s}[data-aos][data-aos][data-aos-delay="1400"],body[data-aos-delay="1400"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1400"].aos-animate,body[data-aos-delay="1400"] [data-aos].aos-animate{transition-delay:1.4s}[data-aos][data-aos][data-aos-duration="1450"],body[data-aos-duration="1450"] [data-aos]{transition-duration:1.45s}[data-aos][data-aos][data-aos-delay="1450"],body[data-aos-delay="1450"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1450"].aos-animate,body[data-aos-delay="1450"] [data-aos].aos-animate{transition-delay:1.45s}[data-aos][data-aos][data-aos-duration="1500"],body[data-aos-duration="1500"] [data-aos]{transition-duration:1.5s}[data-aos][data-aos][data-aos-delay="1500"],body[data-aos-delay="1500"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1500"].aos-animate,body[data-aos-delay="1500"] [data-aos].aos-animate{transition-delay:1.5s}[data-aos][data-aos][data-aos-duration="1550"],body[data-aos-duration="1550"] [data-aos]{transition-duration:1.55s}[data-aos][data-aos][data-aos-delay="1550"],body[data-aos-delay="1550"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1550"].aos-animate,body[data-aos-delay="1550"] [data-aos].aos-animate{transition-delay:1.55s}[data-aos][data-aos][data-aos-duration="1600"],body[data-aos-duration="1600"] [data-aos]{transition-duration:1.6s}[data-aos][data-aos][data-aos-delay="1600"],body[data-aos-delay="1600"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1600"].aos-animate,body[data-aos-delay="1600"] [data-aos].aos-animate{transition-delay:1.6s}[data-aos][data-aos][data-aos-duration="1650"],body[data-aos-duration="1650"] [data-aos]{transition-duration:1.65s}[data-aos][data-aos][data-aos-delay="1650"],body[data-aos-delay="1650"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1650"].aos-animate,body[data-aos-delay="1650"] [data-aos].aos-animate{transition-delay:1.65s}[data-aos][data-aos][data-aos-duration="1700"],body[data-aos-duration="1700"] [data-aos]{transition-duration:1.7s}[data-aos][data-aos][data-aos-delay="1700"],body[data-aos-delay="1700"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1700"].aos-animate,body[data-aos-delay="1700"] [data-aos].aos-animate{transition-delay:1.7s}[data-aos][data-aos][data-aos-duration="1750"],body[data-aos-duration="1750"] [data-aos]{transition-duration:1.75s}[data-aos][data-aos][data-aos-delay="1750"],body[data-aos-delay="1750"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1750"].aos-animate,body[data-aos-delay="1750"] [data-aos].aos-animate{transition-delay:1.75s}[data-aos][data-aos][data-aos-duration="1800"],body[data-aos-duration="1800"] [data-aos]{transition-duration:1.8s}[data-aos][data-aos][data-aos-delay="1800"],body[data-aos-delay="1800"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1800"].aos-animate,body[data-aos-delay="1800"] [data-aos].aos-animate{transition-delay:1.8s}[data-aos][data-aos][data-aos-duration="1850"],body[data-aos-duration="1850"] [data-aos]{transition-duration:1.85s}[data-aos][data-aos][data-aos-delay="1850"],body[data-aos-delay="1850"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1850"].aos-animate,body[data-aos-delay="1850"] [data-aos].aos-animate{transition-delay:1.85s}[data-aos][data-aos][data-aos-duration="1900"],body[data-aos-duration="1900"] [data-aos]{transition-duration:1.9s}[data-aos][data-aos][data-aos-delay="1900"],body[data-aos-delay="1900"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1900"].aos-animate,body[data-aos-delay="1900"] [data-aos].aos-animate{transition-delay:1.9s}[data-aos][data-aos][data-aos-duration="1950"],body[data-aos-duration="1950"] [data-aos]{transition-duration:1.95s}[data-aos][data-aos][data-aos-delay="1950"],body[data-aos-delay="1950"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1950"].aos-animate,body[data-aos-delay="1950"] [data-aos].aos-animate{transition-delay:1.95s}[data-aos][data-aos][data-aos-duration="2000"],body[data-aos-duration="2000"] [data-aos]{transition-duration:2s}[data-aos][data-aos][data-aos-delay="2000"],body[data-aos-delay="2000"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2000"].aos-animate,body[data-aos-delay="2000"] [data-aos].aos-animate{transition-delay:2s}[data-aos][data-aos][data-aos-duration="2050"],body[data-aos-duration="2050"] [data-aos]{transition-duration:2.05s}[data-aos][data-aos][data-aos-delay="2050"],body[data-aos-delay="2050"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2050"].aos-animate,body[data-aos-delay="2050"] [data-aos].aos-animate{transition-delay:2.05s}[data-aos][data-aos][data-aos-duration="2100"],body[data-aos-duration="2100"] [data-aos]{transition-duration:2.1s}[data-aos][data-aos][data-aos-delay="2100"],body[data-aos-delay="2100"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2100"].aos-animate,body[data-aos-delay="2100"] [data-aos].aos-animate{transition-delay:2.1s}[data-aos][data-aos][data-aos-duration="2150"],body[data-aos-duration="2150"] [data-aos]{transition-duration:2.15s}[data-aos][data-aos][data-aos-delay="2150"],body[data-aos-delay="2150"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2150"].aos-animate,body[data-aos-delay="2150"] [data-aos].aos-animate{transition-delay:2.15s}[data-aos][data-aos][data-aos-duration="2200"],body[data-aos-duration="2200"] [data-aos]{transition-duration:2.2s}[data-aos][data-aos][data-aos-delay="2200"],body[data-aos-delay="2200"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2200"].aos-animate,body[data-aos-delay="2200"] [data-aos].aos-animate{transition-delay:2.2s}[data-aos][data-aos][data-aos-duration="2250"],body[data-aos-duration="2250"] [data-aos]{transition-duration:2.25s}[data-aos][data-aos][data-aos-delay="2250"],body[data-aos-delay="2250"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2250"].aos-animate,body[data-aos-delay="2250"] [data-aos].aos-animate{transition-delay:2.25s}[data-aos][data-aos][data-aos-duration="2300"],body[data-aos-duration="2300"] [data-aos]{transition-duration:2.3s}[data-aos][data-aos][data-aos-delay="2300"],body[data-aos-delay="2300"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2300"].aos-animate,body[data-aos-delay="2300"] [data-aos].aos-animate{transition-delay:2.3s}[data-aos][data-aos][data-aos-duration="2350"],body[data-aos-duration="2350"] [data-aos]{transition-duration:2.35s}[data-aos][data-aos][data-aos-delay="2350"],body[data-aos-delay="2350"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2350"].aos-animate,body[data-aos-delay="2350"] [data-aos].aos-animate{transition-delay:2.35s}[data-aos][data-aos][data-aos-duration="2400"],body[data-aos-duration="2400"] [data-aos]{transition-duration:2.4s}[data-aos][data-aos][data-aos-delay="2400"],body[data-aos-delay="2400"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2400"].aos-animate,body[data-aos-delay="2400"] [data-aos].aos-animate{transition-delay:2.4s}[data-aos][data-aos][data-aos-duration="2450"],body[data-aos-duration="2450"] [data-aos]{transition-duration:2.45s}[data-aos][data-aos][data-aos-delay="2450"],body[data-aos-delay="2450"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2450"].aos-animate,body[data-aos-delay="2450"] [data-aos].aos-animate{transition-delay:2.45s}[data-aos][data-aos][data-aos-duration="2500"],body[data-aos-duration="2500"] [data-aos]{transition-duration:2.5s}[data-aos][data-aos][data-aos-delay="2500"],body[data-aos-delay="2500"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2500"].aos-animate,body[data-aos-delay="2500"] [data-aos].aos-animate{transition-delay:2.5s}[data-aos][data-aos][data-aos-duration="2550"],body[data-aos-duration="2550"] [data-aos]{transition-duration:2.55s}[data-aos][data-aos][data-aos-delay="2550"],body[data-aos-delay="2550"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2550"].aos-animate,body[data-aos-delay="2550"] [data-aos].aos-animate{transition-delay:2.55s}[data-aos][data-aos][data-aos-duration="2600"],body[data-aos-duration="2600"] [data-aos]{transition-duration:2.6s}[data-aos][data-aos][data-aos-delay="2600"],body[data-aos-delay="2600"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2600"].aos-animate,body[data-aos-delay="2600"] [data-aos].aos-animate{transition-delay:2.6s}[data-aos][data-aos][data-aos-duration="2650"],body[data-aos-duration="2650"] [data-aos]{transition-duration:2.65s}[data-aos][data-aos][data-aos-delay="2650"],body[data-aos-delay="2650"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2650"].aos-animate,body[data-aos-delay="2650"] [data-aos].aos-animate{transition-delay:2.65s}[data-aos][data-aos][data-aos-duration="2700"],body[data-aos-duration="2700"] [data-aos]{transition-duration:2.7s}[data-aos][data-aos][data-aos-delay="2700"],body[data-aos-delay="2700"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2700"].aos-animate,body[data-aos-delay="2700"] [data-aos].aos-animate{transition-delay:2.7s}[data-aos][data-aos][data-aos-duration="2750"],body[data-aos-duration="2750"] [data-aos]{transition-duration:2.75s}[data-aos][data-aos][data-aos-delay="2750"],body[data-aos-delay="2750"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2750"].aos-animate,body[data-aos-delay="2750"] [data-aos].aos-animate{transition-delay:2.75s}[data-aos][data-aos][data-aos-duration="2800"],body[data-aos-duration="2800"] [data-aos]{transition-duration:2.8s}[data-aos][data-aos][data-aos-delay="2800"],body[data-aos-delay="2800"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2800"].aos-animate,body[data-aos-delay="2800"] [data-aos].aos-animate{transition-delay:2.8s}[data-aos][data-aos][data-aos-duration="2850"],body[data-aos-duration="2850"] [data-aos]{transition-duration:2.85s}[data-aos][data-aos][data-aos-delay="2850"],body[data-aos-delay="2850"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2850"].aos-animate,body[data-aos-delay="2850"] [data-aos].aos-animate{transition-delay:2.85s}[data-aos][data-aos][data-aos-duration="2900"],body[data-aos-duration="2900"] [data-aos]{transition-duration:2.9s}[data-aos][data-aos][data-aos-delay="2900"],body[data-aos-delay="2900"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2900"].aos-animate,body[data-aos-delay="2900"] [data-aos].aos-animate{transition-delay:2.9s}[data-aos][data-aos][data-aos-duration="2950"],body[data-aos-duration="2950"] [data-aos]{transition-duration:2.95s}[data-aos][data-aos][data-aos-delay="2950"],body[data-aos-delay="2950"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2950"].aos-animate,body[data-aos-delay="2950"] [data-aos].aos-animate{transition-delay:2.95s}[data-aos][data-aos][data-aos-duration="3000"],body[data-aos-duration="3000"] [data-aos]{transition-duration:3s}[data-aos][data-aos][data-aos-delay="3000"],body[data-aos-delay="3000"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="3000"].aos-animate,body[data-aos-delay="3000"] [data-aos].aos-animate{transition-delay:3s}[data-aos][data-aos][data-aos-easing=linear],body[data-aos-easing=linear] [data-aos]{transition-timing-function:cubic-bezier(.25,.25,.75,.75)}[data-aos][data-aos][data-aos-easing=ease],body[data-aos-easing=ease] [data-aos]{transition-timing-function:ease}[data-aos][data-aos][data-aos-easing=ease-in],body[data-aos-easing=ease-in] [data-aos]{transition-timing-function:ease-in}[data-aos][data-aos][data-aos-easing=ease-out],body[data-aos-easing=ease-out] [data-aos]{transition-timing-function:ease-out}[data-aos][data-aos][data-aos-easing=ease-in-out],body[data-aos-easing=ease-in-out] [data-aos]{transition-timing-function:ease-in-out}[data-aos][data-aos][data-aos-easing=ease-in-back],body[data-aos-easing=ease-in-back] [data-aos]{transition-timing-function:cubic-bezier(.6,-.28,.735,.045)}[data-aos][data-aos][data-aos-easing=ease-out-back],body[data-aos-easing=ease-out-back] [data-aos]{transition-timing-function:cubic-bezier(.175,.885,.32,1.275)}[data-aos][data-aos][data-aos-easing=ease-in-out-back],body[data-aos-easing=ease-in-out-back] [data-aos]{transition-timing-function:cubic-bezier(.68,-.55,.265,1.55)}[data-aos][data-aos][data-aos-easing=ease-in-sine],body[data-aos-easing=ease-in-sine] [data-aos]{transition-timing-function:cubic-bezier(.47,0,.745,.715)}[data-aos][data-aos][data-aos-easing=ease-out-sine],body[data-aos-easing=ease-out-sine] [data-aos]{transition-timing-function:cubic-bezier(.39,.575,.565,1)}[data-aos][data-aos][data-aos-easing=ease-in-out-sine],body[data-aos-easing=ease-in-out-sine] [data-aos]{transition-timing-function:cubic-bezier(.445,.05,.55,.95)}[data-aos][data-aos][data-aos-easing=ease-in-quad],body[data-aos-easing=ease-in-quad] [data-aos]{transition-timing-function:cubic-bezier(.55,.085,.68,.53)}[data-aos][data-aos][data-aos-easing=ease-out-quad],body[data-aos-easing=ease-out-quad] [data-aos]{transition-timing-function:cubic-bezier(.25,.46,.45,.94)}[data-aos][data-aos][data-aos-easing=ease-in-out-quad],body[data-aos-easing=ease-in-out-quad] [data-aos]{transition-timing-function:cubic-bezier(.455,.03,.515,.955)}[data-aos][data-aos][data-aos-easing=ease-in-cubic],body[data-aos-easing=ease-in-cubic] [data-aos]{transition-timing-function:cubic-bezier(.55,.085,.68,.53)}[data-aos][data-aos][data-aos-easing=ease-out-cubic],body[data-aos-easing=ease-out-cubic] [data-aos]{transition-timing-function:cubic-bezier(.25,.46,.45,.94)}[data-aos][data-aos][data-aos-easing=ease-in-out-cubic],body[data-aos-easing=ease-in-out-cubic] [data-aos]{transition-timing-function:cubic-bezier(.455,.03,.515,.955)}[data-aos][data-aos][data-aos-easing=ease-in-quart],body[data-aos-easing=ease-in-quart] [data-aos]{transition-timing-function:cubic-bezier(.55,.085,.68,.53)}[data-aos][data-aos][data-aos-easing=ease-out-quart],body[data-aos-easing=ease-out-quart] [data-aos]{transition-timing-function:cubic-bezier(.25,.46,.45,.94)}[data-aos][data-aos][data-aos-easing=ease-in-out-quart],body[data-aos-easing=ease-in-out-quart] [data-aos]{transition-timing-function:cubic-bezier(.455,.03,.515,.955)}[data-aos^=fade][data-aos^=fade]{opacity:0;transition-property:opacity,transform}[data-aos^=fade][data-aos^=fade].aos-animate{opacity:1;transform:translateZ(0)}[data-aos=fade-up]{transform:translate3d(0,100px,0)}[data-aos=fade-down]{transform:translate3d(0,-100px,0)}[data-aos=fade-right]{transform:translate3d(-100px,0,0)}[data-aos=fade-left]{transform:translate3d(100px,0,0)}[data-aos=fade-up-right]{transform:translate3d(-100px,100px,0)}[data-aos=fade-up-left]{transform:translate3d(100px,100px,0)}[data-aos=fade-down-right]{transform:translate3d(-100px,-100px,0)}[data-aos=fade-down-left]{transform:translate3d(100px,-100px,0)}[data-aos^=zoom][data-aos^=zoom]{opacity:0;transition-property:opacity,transform}[data-aos^=zoom][data-aos^=zoom].aos-animate{opacity:1;transform:translateZ(0) scale(1)}[data-aos=zoom-in]{transform:scale(.6)}[data-aos=zoom-in-up]{transform:translate3d(0,100px,0) scale(.6)}[data-aos=zoom-in-down]{transform:translate3d(0,-100px,0) scale(.6)}[data-aos=zoom-in-right]{transform:translate3d(-100px,0,0) scale(.6)}[data-aos=zoom-in-left]{transform:translate3d(100px,0,0) scale(.6)}[data-aos=zoom-out]{transform:scale(1.2)}[data-aos=zoom-out-up]{transform:translate3d(0,100px,0) scale(1.2)}[data-aos=zoom-out-down]{transform:translate3d(0,-100px,0) scale(1.2)}[data-aos=zoom-out-right]{transform:translate3d(-100px,0,0) scale(1.2)}[data-aos=zoom-out-left]{transform:translate3d(100px,0,0) scale(1.2)}[data-aos^=slide][data-aos^=slide]{transition-property:transform}[data-aos^=slide][data-aos^=slide].aos-animate{transform:translateZ(0)}[data-aos=slide-up]{transform:translate3d(0,100%,0)}[data-aos=slide-down]{transform:translate3d(0,-100%,0)}[data-aos=slide-right]{transform:translate3d(-100%,0,0)}[data-aos=slide-left]{transform:translate3d(100%,0,0)}[data-aos^=flip][data-aos^=flip]{backface-visibility:hidden;transition-property:transform}[data-aos=flip-left]{transform:perspective(2500px) rotateY(-100deg)}[data-aos=flip-left].aos-animate{transform:perspective(2500px) rotateY(0)}[data-aos=flip-right]{transform:perspective(2500px) rotateY(100deg)}[data-aos=flip-right].aos-animate{transform:perspective(2500px) rotateY(0)}[data-aos=flip-up]{transform:perspective(2500px) rotateX(-100deg)}[data-aos=flip-up].aos-animate{transform:perspective(2500px) rotateX(0)}[data-aos=flip-down]{transform:perspective(2500px) rotateX(100deg)}[data-aos=flip-down].aos-animate{transform:perspective(2500px) rotateX(0)}
|