@tanstack/create 0.68.0 → 0.68.1
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/CHANGELOG.md +10 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/components/demo-AIAssistant.tsx +15 -15
- package/dist/frameworks/react/add-ons/ai/assets/src/components/demo-GuitarRecommendation.tsx +8 -6
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-chat.css +21 -21
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-chat.tsx +14 -18
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-image.tsx +20 -26
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-structured.tsx +56 -67
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/guitars/$guitarId.tsx +17 -22
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/guitars/index.tsx +21 -27
- package/dist/frameworks/react/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx +35 -38
- package/dist/frameworks/react/add-ons/better-auth/assets/src/routes/demo/better-auth.tsx +64 -64
- package/dist/frameworks/react/add-ons/clerk/assets/src/routes/demo/clerk.tsx +17 -25
- package/dist/frameworks/react/add-ons/convex/assets/src/routes/demo/convex.tsx +30 -45
- package/dist/frameworks/react/add-ons/db/assets/src/components/demo.chat-area.tsx +5 -5
- package/dist/frameworks/react/add-ons/db/assets/src/components/demo.messages.tsx +7 -11
- package/dist/frameworks/react/add-ons/db/assets/src/routes/demo/db-chat.tsx +5 -3
- package/dist/frameworks/react/add-ons/drizzle/assets/src/routes/demo/drizzle.tsx.ejs +29 -79
- package/dist/frameworks/react/add-ons/form/assets/src/components/demo.FormComponents.tsx.ejs +12 -12
- package/dist/frameworks/react/add-ons/form/assets/src/routes/demo/form.address.tsx.ejs +11 -10
- package/dist/frameworks/react/add-ons/form/assets/src/routes/demo/form.simple.tsx.ejs +11 -10
- package/dist/frameworks/react/add-ons/mcp/assets/src/routes/demo/mcp-todos.tsx +10 -18
- package/dist/frameworks/react/add-ons/neon/assets/src/routes/demo/neon.tsx +38 -57
- package/dist/frameworks/react/add-ons/oRPC/assets/src/routes/demo/orpc-todo.tsx +10 -18
- package/dist/frameworks/react/add-ons/paraglide/assets/src/routes/demo.i18n.tsx.ejs +6 -7
- package/dist/frameworks/react/add-ons/posthog/assets/src/routes/demo/posthog.tsx +19 -22
- package/dist/frameworks/react/add-ons/powersync/assets/src/routes/demo/powersync.tsx +19 -18
- package/dist/frameworks/react/add-ons/prisma/assets/src/routes/demo/prisma.tsx.ejs +29 -79
- package/dist/frameworks/react/add-ons/sentry/assets/src/routes/demo/sentry.testing.tsx +71 -102
- package/dist/frameworks/react/add-ons/store/assets/src/lib/demo-store-devtools.tsx +3 -3
- package/dist/frameworks/react/add-ons/store/assets/src/routes/demo/store.tsx.ejs +9 -14
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.tsx +23 -26
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/dialog.tsx +12 -16
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.tsx +14 -17
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.tsx +15 -15
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.tsx +17 -17
- package/dist/frameworks/react/add-ons/storybook/assets/src/routes/demo/storybook.tsx +25 -25
- package/dist/frameworks/react/add-ons/strapi/assets/src/components/blocks/media.tsx +9 -9
- package/dist/frameworks/react/add-ons/strapi/assets/src/components/blocks/quote.tsx +8 -8
- package/dist/frameworks/react/add-ons/strapi/assets/src/components/markdown-content.tsx +52 -35
- package/dist/frameworks/react/add-ons/strapi/assets/src/components/pagination.tsx +8 -14
- package/dist/frameworks/react/add-ons/strapi/assets/src/components/search.tsx +12 -12
- package/dist/frameworks/react/add-ons/strapi/assets/src/components/strapi-image.tsx +15 -15
- package/dist/frameworks/react/add-ons/strapi/assets/src/routes/demo/strapi.$articleId.tsx +52 -63
- package/dist/frameworks/react/add-ons/strapi/assets/src/routes/demo/strapi.tsx +46 -61
- package/dist/frameworks/react/add-ons/tRPC/assets/src/routes/demo/trpc-todo.tsx +10 -18
- package/dist/frameworks/react/add-ons/table/assets/src/routes/demo/table.tsx.ejs +23 -22
- package/dist/frameworks/react/add-ons/tanstack-query/assets/src/routes/demo/tanstack-query.tsx.ejs +21 -35
- package/dist/frameworks/react/add-ons/workos/assets/src/components/workos-user.tsx +1 -1
- package/dist/frameworks/react/add-ons/workos/assets/src/routes/demo/workos.tsx +33 -43
- package/dist/frameworks/react/project/base/_dot_gitignore +1 -0
- package/dist/frameworks/react/project/base/src/styles.css.ejs +203 -0
- package/dist/frameworks/solid/add-ons/better-auth/assets/src/routes/demo.better-auth.tsx +62 -64
- package/dist/frameworks/solid/add-ons/convex/assets/src/routes/demo/convex.tsx +30 -43
- package/dist/frameworks/solid/add-ons/form/assets/src/routes/demo.form.tsx.ejs +22 -22
- package/dist/frameworks/solid/add-ons/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +15 -10
- package/dist/frameworks/solid/add-ons/store/assets/src/routes/demo.store.tsx.ejs +9 -14
- package/dist/frameworks/solid/add-ons/strapi/assets/src/routes/demo/strapi.tsx +11 -15
- package/dist/frameworks/solid/add-ons/strapi/assets/src/routes/demo/strapi_.$articleId.tsx +11 -18
- package/dist/frameworks/solid/project/base/_dot_gitignore +1 -0
- package/dist/frameworks/solid/project/base/src/styles.css.ejs +203 -0
- package/package.json +1 -1
- package/src/frameworks/react/add-ons/ai/assets/src/components/demo-AIAssistant.tsx +15 -15
- package/src/frameworks/react/add-ons/ai/assets/src/components/demo-GuitarRecommendation.tsx +8 -6
- package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-chat.css +21 -21
- package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-chat.tsx +14 -18
- package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-image.tsx +20 -26
- package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-structured.tsx +56 -67
- package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/guitars/$guitarId.tsx +17 -22
- package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/guitars/index.tsx +21 -27
- package/src/frameworks/react/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx +35 -38
- package/src/frameworks/react/add-ons/better-auth/assets/src/routes/demo/better-auth.tsx +64 -64
- package/src/frameworks/react/add-ons/clerk/assets/src/routes/demo/clerk.tsx +17 -25
- package/src/frameworks/react/add-ons/convex/assets/src/routes/demo/convex.tsx +30 -45
- package/src/frameworks/react/add-ons/db/assets/src/components/demo.chat-area.tsx +5 -5
- package/src/frameworks/react/add-ons/db/assets/src/components/demo.messages.tsx +7 -11
- package/src/frameworks/react/add-ons/db/assets/src/routes/demo/db-chat.tsx +5 -3
- package/src/frameworks/react/add-ons/drizzle/assets/src/routes/demo/drizzle.tsx.ejs +29 -79
- package/src/frameworks/react/add-ons/form/assets/src/components/demo.FormComponents.tsx.ejs +12 -12
- package/src/frameworks/react/add-ons/form/assets/src/routes/demo/form.address.tsx.ejs +11 -10
- package/src/frameworks/react/add-ons/form/assets/src/routes/demo/form.simple.tsx.ejs +11 -10
- package/src/frameworks/react/add-ons/mcp/assets/src/routes/demo/mcp-todos.tsx +10 -18
- package/src/frameworks/react/add-ons/neon/assets/src/routes/demo/neon.tsx +38 -57
- package/src/frameworks/react/add-ons/oRPC/assets/src/routes/demo/orpc-todo.tsx +10 -18
- package/src/frameworks/react/add-ons/paraglide/assets/src/routes/demo.i18n.tsx.ejs +6 -7
- package/src/frameworks/react/add-ons/posthog/assets/src/routes/demo/posthog.tsx +19 -22
- package/src/frameworks/react/add-ons/powersync/assets/src/routes/demo/powersync.tsx +19 -18
- package/src/frameworks/react/add-ons/prisma/assets/src/routes/demo/prisma.tsx.ejs +29 -79
- package/src/frameworks/react/add-ons/sentry/assets/src/routes/demo/sentry.testing.tsx +71 -102
- package/src/frameworks/react/add-ons/store/assets/src/lib/demo-store-devtools.tsx +3 -3
- package/src/frameworks/react/add-ons/store/assets/src/routes/demo/store.tsx.ejs +9 -14
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.tsx +23 -26
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/dialog.tsx +12 -16
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.tsx +14 -17
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.tsx +15 -15
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.tsx +17 -17
- package/src/frameworks/react/add-ons/storybook/assets/src/routes/demo/storybook.tsx +25 -25
- package/src/frameworks/react/add-ons/strapi/assets/src/components/blocks/media.tsx +9 -9
- package/src/frameworks/react/add-ons/strapi/assets/src/components/blocks/quote.tsx +8 -8
- package/src/frameworks/react/add-ons/strapi/assets/src/components/markdown-content.tsx +52 -35
- package/src/frameworks/react/add-ons/strapi/assets/src/components/pagination.tsx +8 -14
- package/src/frameworks/react/add-ons/strapi/assets/src/components/search.tsx +12 -12
- package/src/frameworks/react/add-ons/strapi/assets/src/components/strapi-image.tsx +15 -15
- package/src/frameworks/react/add-ons/strapi/assets/src/routes/demo/strapi.$articleId.tsx +52 -63
- package/src/frameworks/react/add-ons/strapi/assets/src/routes/demo/strapi.tsx +46 -61
- package/src/frameworks/react/add-ons/tRPC/assets/src/routes/demo/trpc-todo.tsx +10 -18
- package/src/frameworks/react/add-ons/table/assets/src/routes/demo/table.tsx.ejs +23 -22
- package/src/frameworks/react/add-ons/tanstack-query/assets/src/routes/demo/tanstack-query.tsx.ejs +21 -35
- package/src/frameworks/react/add-ons/workos/assets/src/components/workos-user.tsx +1 -1
- package/src/frameworks/react/add-ons/workos/assets/src/routes/demo/workos.tsx +33 -43
- package/src/frameworks/react/project/base/_dot_gitignore +1 -0
- package/src/frameworks/react/project/base/src/styles.css.ejs +203 -0
- package/src/frameworks/solid/add-ons/better-auth/assets/src/routes/demo.better-auth.tsx +62 -64
- package/src/frameworks/solid/add-ons/convex/assets/src/routes/demo/convex.tsx +30 -43
- package/src/frameworks/solid/add-ons/form/assets/src/routes/demo.form.tsx.ejs +22 -22
- package/src/frameworks/solid/add-ons/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +15 -10
- package/src/frameworks/solid/add-ons/store/assets/src/routes/demo.store.tsx.ejs +9 -14
- package/src/frameworks/solid/add-ons/strapi/assets/src/routes/demo/strapi.tsx +11 -15
- package/src/frameworks/solid/add-ons/strapi/assets/src/routes/demo/strapi_.$articleId.tsx +11 -18
- package/src/frameworks/solid/project/base/_dot_gitignore +1 -0
- package/src/frameworks/solid/project/base/src/styles.css.ejs +203 -0
- package/tests/framework-template.test.ts +15 -0
|
@@ -24,10 +24,8 @@ function InitialLayout({ children }: { children: React.ReactNode }) {
|
|
|
24
24
|
return (
|
|
25
25
|
<div className="flex-1 flex items-center justify-center px-4">
|
|
26
26
|
<div className="text-center max-w-3xl mx-auto w-full">
|
|
27
|
-
<h1 className="
|
|
28
|
-
|
|
29
|
-
</h1>
|
|
30
|
-
<p className="text-gray-400 mb-6 w-2/3 mx-auto text-lg">
|
|
27
|
+
<h1 className="demo-title mb-4">TanStack Chat</h1>
|
|
28
|
+
<p className="demo-muted mb-6 mx-auto max-w-2xl text-lg">
|
|
31
29
|
You can ask me about anything, I might or might not have a good
|
|
32
30
|
answer, but you can still ask.
|
|
33
31
|
</p>
|
|
@@ -39,7 +37,7 @@ function InitialLayout({ children }: { children: React.ReactNode }) {
|
|
|
39
37
|
|
|
40
38
|
function ChattingLayout({ children }: { children: React.ReactNode }) {
|
|
41
39
|
return (
|
|
42
|
-
<div className="sticky bottom-0 left-0 right-0
|
|
40
|
+
<div className="sticky bottom-0 left-0 right-0 z-10 border-t border-[var(--line)] bg-[var(--header-bg)] backdrop-blur-sm">
|
|
43
41
|
<div className="max-w-3xl mx-auto w-full px-4 py-3">{children}</div>
|
|
44
42
|
</div>
|
|
45
43
|
)
|
|
@@ -96,17 +94,17 @@ function Messages({
|
|
|
96
94
|
key={message.id}
|
|
97
95
|
className={`p-4 ${
|
|
98
96
|
message.role === 'assistant'
|
|
99
|
-
? 'bg-
|
|
97
|
+
? 'bg-[var(--chip-bg)]'
|
|
100
98
|
: 'bg-transparent'
|
|
101
99
|
}`}
|
|
102
100
|
>
|
|
103
101
|
<div className="flex items-start gap-4 max-w-3xl mx-auto w-full">
|
|
104
102
|
{message.role === 'assistant' ? (
|
|
105
|
-
<div className="
|
|
103
|
+
<div className="mt-2 flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-[var(--lagoon-deep)] text-sm font-medium text-white">
|
|
106
104
|
AI
|
|
107
105
|
</div>
|
|
108
106
|
) : (
|
|
109
|
-
<div className="
|
|
107
|
+
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-[var(--sea-ink-soft)] text-sm font-medium text-white">
|
|
110
108
|
Y
|
|
111
109
|
</div>
|
|
112
110
|
)}
|
|
@@ -115,7 +113,7 @@ function Messages({
|
|
|
115
113
|
if (part.type === 'text' && part.content) {
|
|
116
114
|
return (
|
|
117
115
|
<div
|
|
118
|
-
className="
|
|
116
|
+
className="prose prose-sm min-w-0 max-w-none flex-1"
|
|
119
117
|
key={index}
|
|
120
118
|
>
|
|
121
119
|
<Streamdown>{part.content}</Streamdown>
|
|
@@ -145,7 +143,7 @@ function Messages({
|
|
|
145
143
|
? onStopSpeak()
|
|
146
144
|
: onSpeak(textContent, message.id)
|
|
147
145
|
}
|
|
148
|
-
className="flex-shrink-0 p-2
|
|
146
|
+
className="demo-muted flex-shrink-0 p-2 transition-colors hover:text-[var(--lagoon-deep)]"
|
|
149
147
|
title={isPlaying ? 'Stop speaking' : 'Read aloud'}
|
|
150
148
|
>
|
|
151
149
|
{isPlaying ? (
|
|
@@ -190,7 +188,7 @@ function ChatPage() {
|
|
|
190
188
|
const Layout = messages.length ? ChattingLayout : InitialLayout
|
|
191
189
|
|
|
192
190
|
return (
|
|
193
|
-
<div className="relative flex h-[calc(100vh-
|
|
191
|
+
<div className="relative flex h-[calc(100vh-12rem)] min-h-[32rem]">
|
|
194
192
|
<div className="flex-1 flex flex-col min-h-0">
|
|
195
193
|
<Messages
|
|
196
194
|
messages={messages}
|
|
@@ -205,7 +203,7 @@ function ChatPage() {
|
|
|
205
203
|
<div className="flex items-center justify-center">
|
|
206
204
|
<button
|
|
207
205
|
onClick={stop}
|
|
208
|
-
className="
|
|
206
|
+
className="demo-button demo-button-danger"
|
|
209
207
|
>
|
|
210
208
|
<Square className="w-4 h-4 fill-current" />
|
|
211
209
|
Stop
|
|
@@ -226,10 +224,8 @@ function ChatPage() {
|
|
|
226
224
|
type="button"
|
|
227
225
|
onClick={handleMicClick}
|
|
228
226
|
disabled={isLoading || isTranscribing}
|
|
229
|
-
className={`p-3
|
|
230
|
-
isRecording
|
|
231
|
-
? 'bg-red-600 hover:bg-red-700 text-white'
|
|
232
|
-
: 'bg-gray-800/50 text-gray-400 hover:text-orange-400 border border-orange-500/20'
|
|
227
|
+
className={`demo-button p-3 ${
|
|
228
|
+
isRecording ? 'demo-button-danger' : 'demo-button-secondary'
|
|
233
229
|
} disabled:opacity-50`}
|
|
234
230
|
title={isRecording ? 'Stop recording' : 'Start recording'}
|
|
235
231
|
>
|
|
@@ -247,7 +243,7 @@ function ChatPage() {
|
|
|
247
243
|
value={input}
|
|
248
244
|
onChange={(e) => setInput(e.target.value)}
|
|
249
245
|
placeholder="Type something clever..."
|
|
250
|
-
className="
|
|
246
|
+
className="demo-textarea pr-12 text-sm"
|
|
251
247
|
rows={1}
|
|
252
248
|
style={{ minHeight: '44px', maxHeight: '200px' }}
|
|
253
249
|
disabled={isLoading}
|
|
@@ -268,7 +264,7 @@ function ChatPage() {
|
|
|
268
264
|
<button
|
|
269
265
|
type="submit"
|
|
270
266
|
disabled={!input.trim() || isLoading}
|
|
271
|
-
className="absolute right-2 top-1/2 -translate-y-1/2 p-2 text-
|
|
267
|
+
className="absolute right-2 top-1/2 -translate-y-1/2 p-2 text-[var(--lagoon-deep)] transition-colors hover:text-[var(--sea-ink)] disabled:text-[var(--sea-ink-soft)]"
|
|
272
268
|
>
|
|
273
269
|
<Send className="w-4 h-4" />
|
|
274
270
|
</button>
|
|
@@ -73,26 +73,25 @@ function ImagePage() {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
return (
|
|
76
|
-
<
|
|
77
|
-
<div
|
|
76
|
+
<main className="demo-page demo-page-wide">
|
|
77
|
+
<div>
|
|
78
78
|
<div className="flex items-center gap-3 mb-6">
|
|
79
|
-
<ImageIcon className="w-8 h-8 text-
|
|
80
|
-
<h1 className="
|
|
79
|
+
<ImageIcon className="w-8 h-8 text-[var(--lagoon-deep)]" />
|
|
80
|
+
<h1 className="demo-title">Image Generation</h1>
|
|
81
81
|
</div>
|
|
82
82
|
|
|
83
83
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
84
|
-
{/* Input Panel */}
|
|
85
84
|
<div className="space-y-4">
|
|
86
85
|
<div className="grid grid-cols-2 gap-4">
|
|
87
86
|
<div>
|
|
88
|
-
<label className="block text-sm font-medium text-
|
|
87
|
+
<label className="mb-2 block text-sm font-medium text-[var(--sea-ink)]">
|
|
89
88
|
Size
|
|
90
89
|
</label>
|
|
91
90
|
<select
|
|
92
91
|
value={size}
|
|
93
92
|
onChange={(e) => setSize(e.target.value)}
|
|
94
93
|
disabled={isLoading}
|
|
95
|
-
className="
|
|
94
|
+
className="demo-select text-sm"
|
|
96
95
|
>
|
|
97
96
|
{SIZES.map((s) => (
|
|
98
97
|
<option key={s} value={s}>
|
|
@@ -102,7 +101,7 @@ function ImagePage() {
|
|
|
102
101
|
</select>
|
|
103
102
|
</div>
|
|
104
103
|
<div>
|
|
105
|
-
<label className="block text-sm font-medium text-
|
|
104
|
+
<label className="mb-2 block text-sm font-medium text-[var(--sea-ink)]">
|
|
106
105
|
Count
|
|
107
106
|
</label>
|
|
108
107
|
<input
|
|
@@ -116,13 +115,13 @@ function ImagePage() {
|
|
|
116
115
|
min={1}
|
|
117
116
|
max={4}
|
|
118
117
|
disabled={isLoading}
|
|
119
|
-
className="
|
|
118
|
+
className="demo-input text-sm"
|
|
120
119
|
/>
|
|
121
120
|
</div>
|
|
122
121
|
</div>
|
|
123
122
|
|
|
124
123
|
<div>
|
|
125
|
-
<label className="block text-sm font-medium text-
|
|
124
|
+
<label className="mb-2 block text-sm font-medium text-[var(--sea-ink)]">
|
|
126
125
|
Prompt
|
|
127
126
|
</label>
|
|
128
127
|
<textarea
|
|
@@ -130,7 +129,7 @@ function ImagePage() {
|
|
|
130
129
|
onChange={(e) => setPrompt(e.target.value)}
|
|
131
130
|
disabled={isLoading}
|
|
132
131
|
rows={6}
|
|
133
|
-
className="
|
|
132
|
+
className="demo-textarea text-sm"
|
|
134
133
|
placeholder="Describe the image you want to generate..."
|
|
135
134
|
/>
|
|
136
135
|
</div>
|
|
@@ -138,7 +137,7 @@ function ImagePage() {
|
|
|
138
137
|
<button
|
|
139
138
|
onClick={handleGenerate}
|
|
140
139
|
disabled={isLoading || !prompt.trim()}
|
|
141
|
-
className="w-full
|
|
140
|
+
className="demo-button w-full"
|
|
142
141
|
>
|
|
143
142
|
{isLoading ? (
|
|
144
143
|
<>
|
|
@@ -151,16 +150,11 @@ function ImagePage() {
|
|
|
151
150
|
</button>
|
|
152
151
|
</div>
|
|
153
152
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
<h2 className="text-lg font-semibold text-white mb-4">
|
|
157
|
-
Generated Images
|
|
158
|
-
</h2>
|
|
153
|
+
<div className="demo-panel lg:col-span-2">
|
|
154
|
+
<h2 className="demo-section-title mb-4">Generated Images</h2>
|
|
159
155
|
|
|
160
156
|
{error && (
|
|
161
|
-
<div className="
|
|
162
|
-
{error}
|
|
163
|
-
</div>
|
|
157
|
+
<div className="demo-alert demo-alert-danger mb-4">{error}</div>
|
|
164
158
|
)}
|
|
165
159
|
|
|
166
160
|
{images.length > 0 ? (
|
|
@@ -171,17 +165,17 @@ function ImagePage() {
|
|
|
171
165
|
<img
|
|
172
166
|
src={getImageSrc(image)}
|
|
173
167
|
alt={`Generated image ${index + 1}`}
|
|
174
|
-
className="w-full rounded-lg border border-
|
|
168
|
+
className="w-full rounded-lg border border-[var(--line)]"
|
|
175
169
|
/>
|
|
176
170
|
<button
|
|
177
171
|
onClick={() => handleDownload(image, index)}
|
|
178
|
-
className="absolute
|
|
172
|
+
className="demo-button absolute right-2 top-2 p-2 opacity-0 transition-opacity group-hover:opacity-100"
|
|
179
173
|
title="Download image"
|
|
180
174
|
>
|
|
181
|
-
<Download className="w-4 h-4
|
|
175
|
+
<Download className="w-4 h-4" />
|
|
182
176
|
</button>
|
|
183
177
|
{image.revisedPrompt && (
|
|
184
|
-
<p className="mt-2 text-xs
|
|
178
|
+
<p className="demo-muted mt-2 text-xs italic">
|
|
185
179
|
Revised: {image.revisedPrompt}
|
|
186
180
|
</p>
|
|
187
181
|
)}
|
|
@@ -190,7 +184,7 @@ function ImagePage() {
|
|
|
190
184
|
</div>
|
|
191
185
|
</div>
|
|
192
186
|
) : !error && !isLoading ? (
|
|
193
|
-
<div className="flex flex-col items-center justify-center
|
|
187
|
+
<div className="demo-muted flex h-64 flex-col items-center justify-center">
|
|
194
188
|
<ImageIcon className="w-16 h-16 mb-4 opacity-50" />
|
|
195
189
|
<p>
|
|
196
190
|
Enter a prompt and click "Generate Image" to create an image.
|
|
@@ -200,7 +194,7 @@ function ImagePage() {
|
|
|
200
194
|
</div>
|
|
201
195
|
</div>
|
|
202
196
|
</div>
|
|
203
|
-
</
|
|
197
|
+
</main>
|
|
204
198
|
)
|
|
205
199
|
}
|
|
206
200
|
|
|
@@ -20,35 +20,37 @@ const SAMPLE_RECIPES = [
|
|
|
20
20
|
|
|
21
21
|
function RecipeCard({ recipe }: { recipe: Recipe }) {
|
|
22
22
|
const difficultyColors = {
|
|
23
|
-
easy: '
|
|
24
|
-
medium: '
|
|
25
|
-
hard: '
|
|
23
|
+
easy: 'demo-pill',
|
|
24
|
+
medium: 'demo-pill',
|
|
25
|
+
hard: 'demo-pill',
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
29
|
<div className="space-y-6">
|
|
30
30
|
{/* Header */}
|
|
31
31
|
<div>
|
|
32
|
-
<h3 className="text-2xl font-bold text-
|
|
33
|
-
|
|
32
|
+
<h3 className="text-2xl font-bold text-[var(--sea-ink)] mb-2">
|
|
33
|
+
{recipe.name}
|
|
34
|
+
</h3>
|
|
35
|
+
<p className="demo-muted">{recipe.description}</p>
|
|
34
36
|
</div>
|
|
35
37
|
|
|
36
38
|
{/* Meta info */}
|
|
37
39
|
<div className="flex flex-wrap gap-4">
|
|
38
|
-
<div className="flex items-center gap-2
|
|
39
|
-
<Clock className="w-4 h-4 text-
|
|
40
|
+
<div className="demo-muted flex items-center gap-2">
|
|
41
|
+
<Clock className="w-4 h-4 text-[var(--lagoon-deep)]" />
|
|
40
42
|
<span className="text-sm">Prep: {recipe.prepTime}</span>
|
|
41
43
|
</div>
|
|
42
|
-
<div className="flex items-center gap-2
|
|
43
|
-
<Clock className="w-4 h-4 text-
|
|
44
|
+
<div className="demo-muted flex items-center gap-2">
|
|
45
|
+
<Clock className="w-4 h-4 text-[var(--lagoon-deep)]" />
|
|
44
46
|
<span className="text-sm">Cook: {recipe.cookTime}</span>
|
|
45
47
|
</div>
|
|
46
|
-
<div className="flex items-center gap-2
|
|
47
|
-
<Users className="w-4 h-4 text-
|
|
48
|
+
<div className="demo-muted flex items-center gap-2">
|
|
49
|
+
<Users className="w-4 h-4 text-[var(--lagoon-deep)]" />
|
|
48
50
|
<span className="text-sm">{recipe.servings} servings</span>
|
|
49
51
|
</div>
|
|
50
52
|
<div
|
|
51
|
-
className={`flex items-center gap-2
|
|
53
|
+
className={`flex items-center gap-2 ${
|
|
52
54
|
difficultyColors[recipe.difficulty]
|
|
53
55
|
}`}
|
|
54
56
|
>
|
|
@@ -59,16 +61,16 @@ function RecipeCard({ recipe }: { recipe: Recipe }) {
|
|
|
59
61
|
|
|
60
62
|
{/* Ingredients */}
|
|
61
63
|
<div>
|
|
62
|
-
<h4 className="text-lg font-semibold text-
|
|
64
|
+
<h4 className="text-lg font-semibold text-[var(--sea-ink)] mb-3">
|
|
65
|
+
Ingredients
|
|
66
|
+
</h4>
|
|
63
67
|
<ul className="grid grid-cols-1 md:grid-cols-2 gap-2">
|
|
64
68
|
{recipe.ingredients.map((ing, idx) => (
|
|
65
|
-
<li key={idx} className="flex items-start gap-2
|
|
66
|
-
<span className="text-
|
|
69
|
+
<li key={idx} className="demo-muted flex items-start gap-2">
|
|
70
|
+
<span className="text-[var(--lagoon-deep)]">•</span>
|
|
67
71
|
<span>
|
|
68
72
|
<span className="font-medium">{ing.amount}</span> {ing.item}
|
|
69
|
-
{ing.notes && (
|
|
70
|
-
<span className="text-gray-500 text-sm"> ({ing.notes})</span>
|
|
71
|
-
)}
|
|
73
|
+
{ing.notes && <span className="text-sm"> ({ing.notes})</span>}
|
|
72
74
|
</span>
|
|
73
75
|
</li>
|
|
74
76
|
))}
|
|
@@ -77,11 +79,13 @@ function RecipeCard({ recipe }: { recipe: Recipe }) {
|
|
|
77
79
|
|
|
78
80
|
{/* Instructions */}
|
|
79
81
|
<div>
|
|
80
|
-
<h4 className="text-lg font-semibold text-
|
|
82
|
+
<h4 className="text-lg font-semibold text-[var(--sea-ink)] mb-3">
|
|
83
|
+
Instructions
|
|
84
|
+
</h4>
|
|
81
85
|
<ol className="space-y-3">
|
|
82
86
|
{recipe.instructions.map((step, idx) => (
|
|
83
|
-
<li key={idx} className="flex gap-3
|
|
84
|
-
<span className="flex-shrink-0 w-6 h-6 bg-
|
|
87
|
+
<li key={idx} className="demo-muted flex gap-3">
|
|
88
|
+
<span className="flex-shrink-0 w-6 h-6 rounded-full border border-[var(--line)] bg-[var(--chip-bg)] text-[var(--sea-ink)] flex items-center justify-center text-sm font-medium">
|
|
85
89
|
{idx + 1}
|
|
86
90
|
</span>
|
|
87
91
|
<span>{step}</span>
|
|
@@ -93,11 +97,13 @@ function RecipeCard({ recipe }: { recipe: Recipe }) {
|
|
|
93
97
|
{/* Tips */}
|
|
94
98
|
{recipe.tips && recipe.tips.length > 0 && (
|
|
95
99
|
<div>
|
|
96
|
-
<h4 className="text-lg font-semibold text-
|
|
100
|
+
<h4 className="text-lg font-semibold text-[var(--sea-ink)] mb-3">
|
|
101
|
+
Tips
|
|
102
|
+
</h4>
|
|
97
103
|
<ul className="space-y-2">
|
|
98
104
|
{recipe.tips.map((tip, idx) => (
|
|
99
|
-
<li key={idx} className="flex items-start gap-2
|
|
100
|
-
<span className="text-
|
|
105
|
+
<li key={idx} className="demo-muted flex items-start gap-2">
|
|
106
|
+
<span className="text-[var(--lagoon-deep)]">*</span>
|
|
101
107
|
<span>{tip}</span>
|
|
102
108
|
</li>
|
|
103
109
|
))}
|
|
@@ -108,27 +114,27 @@ function RecipeCard({ recipe }: { recipe: Recipe }) {
|
|
|
108
114
|
{/* Nutrition */}
|
|
109
115
|
{recipe.nutritionPerServing && (
|
|
110
116
|
<div>
|
|
111
|
-
<h4 className="text-lg font-semibold text-
|
|
117
|
+
<h4 className="text-lg font-semibold text-[var(--sea-ink)] mb-3">
|
|
112
118
|
Nutrition (per serving)
|
|
113
119
|
</h4>
|
|
114
120
|
<div className="flex flex-wrap gap-4 text-sm">
|
|
115
121
|
{recipe.nutritionPerServing.calories && (
|
|
116
|
-
<span className="
|
|
122
|
+
<span className="demo-pill">
|
|
117
123
|
{recipe.nutritionPerServing.calories} cal
|
|
118
124
|
</span>
|
|
119
125
|
)}
|
|
120
126
|
{recipe.nutritionPerServing.protein && (
|
|
121
|
-
<span className="
|
|
127
|
+
<span className="demo-pill">
|
|
122
128
|
Protein: {recipe.nutritionPerServing.protein}
|
|
123
129
|
</span>
|
|
124
130
|
)}
|
|
125
131
|
{recipe.nutritionPerServing.carbs && (
|
|
126
|
-
<span className="
|
|
132
|
+
<span className="demo-pill">
|
|
127
133
|
Carbs: {recipe.nutritionPerServing.carbs}
|
|
128
134
|
</span>
|
|
129
135
|
)}
|
|
130
136
|
{recipe.nutritionPerServing.fat && (
|
|
131
|
-
<span className="
|
|
137
|
+
<span className="demo-pill">
|
|
132
138
|
Fat: {recipe.nutritionPerServing.fat}
|
|
133
139
|
</span>
|
|
134
140
|
)}
|
|
@@ -182,26 +188,24 @@ function StructuredPage() {
|
|
|
182
188
|
const canExecute = !!(!isLoading && recipeName.trim() && !error)
|
|
183
189
|
|
|
184
190
|
return (
|
|
185
|
-
<
|
|
186
|
-
<div
|
|
191
|
+
<main className="demo-page demo-page-wide">
|
|
192
|
+
<div>
|
|
187
193
|
<div className="flex items-center gap-3 mb-6">
|
|
188
|
-
<ChefHat className="w-8 h-8 text-
|
|
189
|
-
<h1 className="
|
|
190
|
-
One-Shot & Structured Output
|
|
191
|
-
</h1>
|
|
194
|
+
<ChefHat className="w-8 h-8 text-[var(--lagoon-deep)]" />
|
|
195
|
+
<h1 className="demo-title">One-Shot & Structured Output</h1>
|
|
192
196
|
</div>
|
|
193
197
|
|
|
194
|
-
<p className="
|
|
198
|
+
<p className="demo-muted mb-6">
|
|
195
199
|
Compare two output modes:{' '}
|
|
196
|
-
<strong className="text-
|
|
197
|
-
markdown, while{' '}
|
|
198
|
-
<strong className="text-
|
|
200
|
+
<strong className="text-[var(--sea-ink)]">One-Shot</strong> returns
|
|
201
|
+
freeform markdown, while{' '}
|
|
202
|
+
<strong className="text-[var(--sea-ink)]">Structured</strong> returns
|
|
199
203
|
validated JSON conforming to a Zod schema.
|
|
200
204
|
</p>
|
|
201
205
|
|
|
202
206
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
203
207
|
<div>
|
|
204
|
-
<label className="block text-sm font-medium text-
|
|
208
|
+
<label className="mb-2 block text-sm font-medium text-[var(--sea-ink)]">
|
|
205
209
|
Recipe Name
|
|
206
210
|
</label>
|
|
207
211
|
<input
|
|
@@ -210,11 +214,11 @@ function StructuredPage() {
|
|
|
210
214
|
onChange={(e) => setRecipeName(e.target.value)}
|
|
211
215
|
disabled={isLoading}
|
|
212
216
|
placeholder="e.g., Chocolate Chip Cookies"
|
|
213
|
-
className="
|
|
217
|
+
className="demo-input text-sm"
|
|
214
218
|
/>
|
|
215
219
|
|
|
216
220
|
<div className="mt-2">
|
|
217
|
-
<label className="block text-sm font-medium text-
|
|
221
|
+
<label className="mb-2 block text-sm font-medium text-[var(--sea-ink)]">
|
|
218
222
|
Quick Picks
|
|
219
223
|
</label>
|
|
220
224
|
<div className="flex flex-wrap gap-2">
|
|
@@ -223,7 +227,7 @@ function StructuredPage() {
|
|
|
223
227
|
key={name}
|
|
224
228
|
onClick={() => setRecipeName(name)}
|
|
225
229
|
disabled={isLoading}
|
|
226
|
-
className="px-2 py-1 text-xs
|
|
230
|
+
className="demo-button demo-button-secondary px-2 py-1 text-xs"
|
|
227
231
|
>
|
|
228
232
|
{name}
|
|
229
233
|
</button>
|
|
@@ -237,18 +241,14 @@ function StructuredPage() {
|
|
|
237
241
|
<button
|
|
238
242
|
onClick={() => handleGenerate('oneshot')}
|
|
239
243
|
disabled={!canExecute}
|
|
240
|
-
className=
|
|
241
|
-
!canExecute ? 'bg-gray-600' : 'bg-orange-500'
|
|
242
|
-
}`}
|
|
244
|
+
className="demo-button"
|
|
243
245
|
>
|
|
244
246
|
One-Shot (Markdown)
|
|
245
247
|
</button>
|
|
246
248
|
<button
|
|
247
249
|
onClick={() => handleGenerate('structured')}
|
|
248
250
|
disabled={!canExecute}
|
|
249
|
-
className=
|
|
250
|
-
!canExecute ? 'bg-gray-600' : 'bg-blue-500'
|
|
251
|
-
}`}
|
|
251
|
+
className="demo-button"
|
|
252
252
|
>
|
|
253
253
|
Structured (JSON)
|
|
254
254
|
</button>
|
|
@@ -256,29 +256,18 @@ function StructuredPage() {
|
|
|
256
256
|
</div>
|
|
257
257
|
</div>
|
|
258
258
|
|
|
259
|
-
|
|
260
|
-
<div className="mt-5 lg:col-span-2 bg-gray-800 rounded-lg p-6 border border-orange-500/20">
|
|
259
|
+
<div className="demo-panel mt-5 lg:col-span-2">
|
|
261
260
|
<div className="flex items-center justify-between mb-4">
|
|
262
|
-
<h2 className="
|
|
263
|
-
Generated Recipe
|
|
264
|
-
</h2>
|
|
261
|
+
<h2 className="demo-section-title">Generated Recipe</h2>
|
|
265
262
|
{result && (
|
|
266
|
-
<span
|
|
267
|
-
className={`px-2 py-1 rounded text-xs font-medium ${
|
|
268
|
-
result.mode === 'structured'
|
|
269
|
-
? 'bg-purple-500/20 text-purple-400'
|
|
270
|
-
: 'bg-blue-500/20 text-blue-400'
|
|
271
|
-
}`}
|
|
272
|
-
>
|
|
263
|
+
<span className="demo-pill">
|
|
273
264
|
{result.mode === 'structured' ? 'Structured JSON' : 'Markdown'}
|
|
274
265
|
</span>
|
|
275
266
|
)}
|
|
276
267
|
</div>
|
|
277
268
|
|
|
278
269
|
{error && (
|
|
279
|
-
<div className="
|
|
280
|
-
{error}
|
|
281
|
-
</div>
|
|
270
|
+
<div className="demo-alert demo-alert-danger mb-4">{error}</div>
|
|
282
271
|
)}
|
|
283
272
|
|
|
284
273
|
{result ? (
|
|
@@ -286,13 +275,13 @@ function StructuredPage() {
|
|
|
286
275
|
{result.mode === 'structured' && result.recipe ? (
|
|
287
276
|
<RecipeCard recipe={result.recipe} />
|
|
288
277
|
) : result.markdown ? (
|
|
289
|
-
<div className="
|
|
278
|
+
<div className="max-w-none">
|
|
290
279
|
<Streamdown>{result.markdown}</Streamdown>
|
|
291
280
|
</div>
|
|
292
281
|
) : null}
|
|
293
282
|
</div>
|
|
294
283
|
) : !error && !isLoading ? (
|
|
295
|
-
<div className="flex flex-col items-center justify-center
|
|
284
|
+
<div className="demo-muted flex h-64 flex-col items-center justify-center">
|
|
296
285
|
<ChefHat className="w-16 h-16 mb-4 opacity-50" />
|
|
297
286
|
<p>
|
|
298
287
|
Enter a recipe name and click "Generate Recipe" to get started.
|
|
@@ -301,7 +290,7 @@ function StructuredPage() {
|
|
|
301
290
|
) : null}
|
|
302
291
|
</div>
|
|
303
292
|
</div>
|
|
304
|
-
</
|
|
293
|
+
</main>
|
|
305
294
|
)
|
|
306
295
|
}
|
|
307
296
|
|
|
@@ -17,35 +17,30 @@ function RouteComponent() {
|
|
|
17
17
|
const guitar = Route.useLoaderData()
|
|
18
18
|
|
|
19
19
|
return (
|
|
20
|
-
<
|
|
21
|
-
<div className="
|
|
22
|
-
<
|
|
23
|
-
to="/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
20
|
+
<main className="demo-page">
|
|
21
|
+
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(20rem,28rem)] lg:items-center">
|
|
22
|
+
<section className="demo-panel">
|
|
23
|
+
<Link to="/demo/guitars/" className="mb-4 inline-block">
|
|
24
|
+
← Back to all guitars
|
|
25
|
+
</Link>
|
|
26
|
+
<h1 className="demo-title mb-4">{guitar.name}</h1>
|
|
27
|
+
<p className="demo-muted mb-6">{guitar.description}</p>
|
|
28
|
+
<div className="flex items-center justify-between">
|
|
29
|
+
<div className="text-2xl font-bold text-[var(--lagoon-deep)]">
|
|
30
|
+
${guitar.price}
|
|
31
|
+
</div>
|
|
32
|
+
<button className="demo-button">Add to Cart</button>
|
|
33
33
|
</div>
|
|
34
|
-
|
|
35
|
-
Add to Cart
|
|
36
|
-
</button>
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
34
|
+
</section>
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
<div className="w-full h-full overflow-hidden rounded-2xl border-4 border-gray-800 shadow-2xl">
|
|
36
|
+
<div className="demo-card overflow-hidden p-0">
|
|
42
37
|
<img
|
|
43
38
|
src={guitar.image}
|
|
44
39
|
alt={guitar.name}
|
|
45
|
-
className="
|
|
40
|
+
className="guitar-image h-full w-full object-cover"
|
|
46
41
|
/>
|
|
47
42
|
</div>
|
|
48
43
|
</div>
|
|
49
|
-
</
|
|
44
|
+
</main>
|
|
50
45
|
)
|
|
51
46
|
}
|