@tanstack/create 0.68.0 → 0.68.2
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 +16 -0
- package/dist/create-app.js +22 -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/package.json +1 -0
- package/dist/frameworks/react/project/base/src/styles.css.ejs +203 -0
- package/dist/frameworks/react/project/base/tsr.config.json +3 -0
- package/dist/frameworks/react/project/packages.json +3 -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/package.json +1 -0
- package/dist/frameworks/solid/project/base/src/styles.css.ejs +203 -0
- package/dist/frameworks/solid/project/base/tsr.config.json +3 -0
- package/dist/frameworks/solid/project/packages.json +3 -0
- package/package.json +1 -1
- package/src/create-app.ts +32 -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/package.json +1 -0
- package/src/frameworks/react/project/base/src/styles.css.ejs +203 -0
- package/src/frameworks/react/project/base/tsr.config.json +3 -0
- package/src/frameworks/react/project/packages.json +3 -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/package.json +1 -0
- package/src/frameworks/solid/project/base/src/styles.css.ejs +203 -0
- package/src/frameworks/solid/project/base/tsr.config.json +3 -0
- package/src/frameworks/solid/project/packages.json +3 -0
- package/tests/create-app.test.ts +39 -3
- package/tests/framework-template.test.ts +34 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @tanstack/create
|
|
2
2
|
|
|
3
|
+
## 0.68.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Keep the generated route tree tracked in new React and Solid apps and run route generation once during scaffold. ([#464](https://github.com/TanStack/cli/pull/464))
|
|
8
|
+
|
|
9
|
+
## 0.68.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Keep the generated AI assistant demo panel inside the viewport. ([#459](https://github.com/TanStack/cli/pull/459))
|
|
14
|
+
|
|
15
|
+
- Normalize generated demo pages to use the base template styling instead of bespoke full-page gradients and mismatched color treatments. ([#461](https://github.com/TanStack/cli/pull/461))
|
|
16
|
+
|
|
17
|
+
- Ignore the generated route tree in new React and Solid app gitignores. ([#460](https://github.com/TanStack/cli/pull/460))
|
|
18
|
+
|
|
3
19
|
## 0.68.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
package/dist/create-app.js
CHANGED
|
@@ -202,6 +202,28 @@ async function runCommandsAndInstallDependencies(environment, options) {
|
|
|
202
202
|
}
|
|
203
203
|
await installShadcnComponents(environment, options.targetDir, options);
|
|
204
204
|
await setupIntent(environment, options.targetDir, options);
|
|
205
|
+
if (shouldGenerateRoutes(options)) {
|
|
206
|
+
s.start(`Generating route tree...`);
|
|
207
|
+
const command = getPackageManagerScriptCommand(options.packageManager, [
|
|
208
|
+
'generate-routes',
|
|
209
|
+
]);
|
|
210
|
+
const cmd = formatCommand(command);
|
|
211
|
+
environment.startStep({
|
|
212
|
+
id: 'generate-routes',
|
|
213
|
+
type: 'command',
|
|
214
|
+
message: cmd,
|
|
215
|
+
});
|
|
216
|
+
await environment.execute(command.command, command.args, options.targetDir, {
|
|
217
|
+
inherit: true,
|
|
218
|
+
});
|
|
219
|
+
environment.finishStep('generate-routes', 'Route tree generated');
|
|
220
|
+
s.stop(`Route tree generated`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function shouldGenerateRoutes(options) {
|
|
224
|
+
return (options.install !== false &&
|
|
225
|
+
options.mode === 'file-router' &&
|
|
226
|
+
(options.framework.id === 'react' || options.framework.id === 'solid'));
|
|
205
227
|
}
|
|
206
228
|
async function seedEnvValues(environment, options) {
|
|
207
229
|
const envVarValues = options.envVarValues || {};
|
|
@@ -24,7 +24,7 @@ function Messages({ messages }: { messages: ChatMessages }) {
|
|
|
24
24
|
|
|
25
25
|
if (!messages.length) {
|
|
26
26
|
return (
|
|
27
|
-
<div className="flex-1
|
|
27
|
+
<div className="demo-muted flex flex-1 items-center justify-center text-sm">
|
|
28
28
|
Ask me anything! I'm here to help.
|
|
29
29
|
</div>
|
|
30
30
|
)
|
|
@@ -36,9 +36,7 @@ function Messages({ messages }: { messages: ChatMessages }) {
|
|
|
36
36
|
<div
|
|
37
37
|
key={id}
|
|
38
38
|
className={`py-3 ${
|
|
39
|
-
role === 'assistant'
|
|
40
|
-
? 'bg-linear-to-r from-orange-500/5 to-red-600/5'
|
|
41
|
-
: 'bg-transparent'
|
|
39
|
+
role === 'assistant' ? 'bg-[var(--chip-bg)]' : 'bg-transparent'
|
|
42
40
|
}`}
|
|
43
41
|
>
|
|
44
42
|
{parts.map((part, index) => {
|
|
@@ -46,15 +44,15 @@ function Messages({ messages }: { messages: ChatMessages }) {
|
|
|
46
44
|
return (
|
|
47
45
|
<div key={index} className="flex items-start gap-2 px-4">
|
|
48
46
|
{role === 'assistant' ? (
|
|
49
|
-
<div className="
|
|
47
|
+
<div className="flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-lg bg-[var(--lagoon-deep)] text-xs font-medium text-white">
|
|
50
48
|
AI
|
|
51
49
|
</div>
|
|
52
50
|
) : (
|
|
53
|
-
<div className="
|
|
51
|
+
<div className="flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-lg bg-[var(--sea-ink-soft)] text-xs font-medium text-white">
|
|
54
52
|
Y
|
|
55
53
|
</div>
|
|
56
54
|
)}
|
|
57
|
-
<div className="
|
|
55
|
+
<div className="min-w-0 flex-1 max-w-none text-sm text-[var(--sea-ink)]">
|
|
58
56
|
<Streamdown>{part.content}</Streamdown>
|
|
59
57
|
</div>
|
|
60
58
|
</div>
|
|
@@ -87,7 +85,7 @@ export default function AIAssistant() {
|
|
|
87
85
|
<div className="relative z-50">
|
|
88
86
|
<button
|
|
89
87
|
onClick={() => showAIAssistant.setState((state) => !state)}
|
|
90
|
-
className="w-full
|
|
88
|
+
className="demo-button w-full justify-between px-4 py-2.5"
|
|
91
89
|
>
|
|
92
90
|
<div className="flex items-center gap-2">
|
|
93
91
|
<BotIcon size={24} />
|
|
@@ -97,12 +95,14 @@ export default function AIAssistant() {
|
|
|
97
95
|
</button>
|
|
98
96
|
|
|
99
97
|
{isOpen && (
|
|
100
|
-
<div className="
|
|
101
|
-
<div className="flex items-center justify-between
|
|
102
|
-
<h3 className="font-semibold text-
|
|
98
|
+
<div className="demo-panel fixed inset-x-4 top-20 z-[100] flex h-[calc(100vh-6rem)] max-h-[600px] flex-col overflow-hidden p-0 sm:left-auto sm:w-[min(calc(100vw-2rem),700px)]">
|
|
99
|
+
<div className="flex items-center justify-between border-b border-[var(--line)] p-3">
|
|
100
|
+
<h3 className="font-semibold text-[var(--sea-ink)]">
|
|
101
|
+
AI Assistant
|
|
102
|
+
</h3>
|
|
103
103
|
<button
|
|
104
104
|
onClick={() => showAIAssistant.setState((state) => !state)}
|
|
105
|
-
className="
|
|
105
|
+
className="demo-muted transition-colors hover:text-[var(--sea-ink)]"
|
|
106
106
|
>
|
|
107
107
|
<X className="w-4 h-4" />
|
|
108
108
|
</button>
|
|
@@ -110,7 +110,7 @@ export default function AIAssistant() {
|
|
|
110
110
|
|
|
111
111
|
<Messages messages={messages} />
|
|
112
112
|
|
|
113
|
-
<div className="
|
|
113
|
+
<div className="border-t border-[var(--line)] p-3">
|
|
114
114
|
<form
|
|
115
115
|
onSubmit={(e) => {
|
|
116
116
|
e.preventDefault()
|
|
@@ -125,7 +125,7 @@ export default function AIAssistant() {
|
|
|
125
125
|
value={input}
|
|
126
126
|
onChange={(e) => setInput(e.target.value)}
|
|
127
127
|
placeholder="Type your message..."
|
|
128
|
-
className="
|
|
128
|
+
className="demo-textarea pr-10 text-sm"
|
|
129
129
|
rows={1}
|
|
130
130
|
style={{ minHeight: '36px', maxHeight: '120px' }}
|
|
131
131
|
onInput={(e) => {
|
|
@@ -145,7 +145,7 @@ export default function AIAssistant() {
|
|
|
145
145
|
<button
|
|
146
146
|
type="submit"
|
|
147
147
|
disabled={!input.trim()}
|
|
148
|
-
className="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 text-
|
|
148
|
+
className="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 text-[var(--lagoon-deep)] transition-colors hover:text-[var(--sea-ink)] disabled:text-[var(--sea-ink-soft)]"
|
|
149
149
|
>
|
|
150
150
|
<Send className="w-4 h-4" />
|
|
151
151
|
</button>
|
package/dist/frameworks/react/add-ons/ai/assets/src/components/demo-GuitarRecommendation.tsx
CHANGED
|
@@ -11,7 +11,7 @@ export default function GuitarRecommendation({ id }: { id: string }) {
|
|
|
11
11
|
return null
|
|
12
12
|
}
|
|
13
13
|
return (
|
|
14
|
-
<div className="my-4
|
|
14
|
+
<div className="demo-card my-4 overflow-hidden p-0">
|
|
15
15
|
<div className="aspect-[4/3] relative overflow-hidden">
|
|
16
16
|
<img
|
|
17
17
|
src={guitar.image}
|
|
@@ -20,23 +20,25 @@ export default function GuitarRecommendation({ id }: { id: string }) {
|
|
|
20
20
|
/>
|
|
21
21
|
</div>
|
|
22
22
|
<div className="p-4">
|
|
23
|
-
<h3 className="text-lg font-semibold text-
|
|
24
|
-
|
|
23
|
+
<h3 className="mb-2 text-lg font-semibold text-[var(--sea-ink)]">
|
|
24
|
+
{guitar.name}
|
|
25
|
+
</h3>
|
|
26
|
+
<p className="demo-muted mb-3 line-clamp-2 text-sm">
|
|
25
27
|
{guitar.shortDescription}
|
|
26
28
|
</p>
|
|
27
29
|
<div className="flex items-center justify-between">
|
|
28
|
-
<div className="text-lg font-bold text-
|
|
30
|
+
<div className="text-lg font-bold text-[var(--lagoon-deep)]">
|
|
29
31
|
${guitar.price}
|
|
30
32
|
</div>
|
|
31
33
|
<button
|
|
32
34
|
onClick={() => {
|
|
33
35
|
navigate({
|
|
34
|
-
to: '/
|
|
36
|
+
to: '/demo/guitars/$guitarId',
|
|
35
37
|
params: { guitarId: guitar.id.toString() },
|
|
36
38
|
})
|
|
37
39
|
showAIAssistant.setState(() => false)
|
|
38
40
|
}}
|
|
39
|
-
className="
|
|
41
|
+
className="demo-button px-4 py-1.5 text-sm"
|
|
40
42
|
>
|
|
41
43
|
View Details
|
|
42
44
|
</button>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
@import 'tailwindcss';
|
|
2
|
-
@import 'highlight.js/styles/github
|
|
2
|
+
@import 'highlight.js/styles/github.css';
|
|
3
3
|
@source "../../../../node_modules/streamdown/dist/*.js";
|
|
4
4
|
|
|
5
5
|
/* Custom scrollbar styles */
|
|
@@ -28,7 +28,7 @@ html {
|
|
|
28
28
|
/* Markdown content styles */
|
|
29
29
|
.prose {
|
|
30
30
|
max-width: none;
|
|
31
|
-
color:
|
|
31
|
+
color: var(--sea-ink-soft);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/* .prose p {
|
|
@@ -37,15 +37,15 @@ html {
|
|
|
37
37
|
} */
|
|
38
38
|
|
|
39
39
|
.prose code {
|
|
40
|
-
color:
|
|
41
|
-
background-color:
|
|
40
|
+
color: var(--sea-ink);
|
|
41
|
+
background-color: var(--chip-bg);
|
|
42
42
|
padding: 0.2em 0.4em;
|
|
43
43
|
border-radius: 0.375rem;
|
|
44
44
|
font-size: 0.875em;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
.prose pre {
|
|
48
|
-
background-color:
|
|
48
|
+
background-color: var(--chip-bg);
|
|
49
49
|
border-radius: 0.5rem;
|
|
50
50
|
padding: 1rem;
|
|
51
51
|
margin: 1.25em 0;
|
|
@@ -63,7 +63,7 @@ html {
|
|
|
63
63
|
.prose h2,
|
|
64
64
|
.prose h3,
|
|
65
65
|
.prose h4 {
|
|
66
|
-
color:
|
|
66
|
+
color: var(--sea-ink);
|
|
67
67
|
/* margin-top: 2em; */
|
|
68
68
|
/* margin-bottom: 1em; */
|
|
69
69
|
}
|
|
@@ -81,27 +81,27 @@ html {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
.prose blockquote {
|
|
84
|
-
border-left-color:
|
|
85
|
-
background-color:
|
|
84
|
+
border-left-color: var(--lagoon-deep);
|
|
85
|
+
background-color: var(--chip-bg);
|
|
86
86
|
padding: 1em;
|
|
87
87
|
margin: 1.25em 0;
|
|
88
88
|
border-radius: 0.5rem;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
.prose hr {
|
|
92
|
-
border-color:
|
|
92
|
+
border-color: var(--line);
|
|
93
93
|
margin: 2em 0;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
.prose a {
|
|
97
|
-
color:
|
|
97
|
+
color: var(--lagoon-deep);
|
|
98
98
|
text-decoration: underline;
|
|
99
99
|
text-decoration-thickness: 0.1em;
|
|
100
100
|
text-underline-offset: 0.2em;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
.prose a:hover {
|
|
104
|
-
color:
|
|
104
|
+
color: var(--sea-ink);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
.prose table {
|
|
@@ -113,11 +113,11 @@ html {
|
|
|
113
113
|
.prose th,
|
|
114
114
|
.prose td {
|
|
115
115
|
padding: 0.75em;
|
|
116
|
-
border: 1px solid
|
|
116
|
+
border: 1px solid var(--line);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
.prose th {
|
|
120
|
-
background-color:
|
|
120
|
+
background-color: var(--chip-bg);
|
|
121
121
|
font-weight: 600;
|
|
122
122
|
}
|
|
123
123
|
|
|
@@ -181,16 +181,16 @@ html {
|
|
|
181
181
|
|
|
182
182
|
.prose th,
|
|
183
183
|
.prose td {
|
|
184
|
-
border: 1px solid
|
|
184
|
+
border: 1px solid var(--line);
|
|
185
185
|
padding: 0.5em;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
.prose th {
|
|
189
|
-
background-color:
|
|
189
|
+
background-color: var(--chip-bg);
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
.prose strong {
|
|
193
|
-
color:
|
|
193
|
+
color: var(--sea-ink);
|
|
194
194
|
font-weight: 600;
|
|
195
195
|
}
|
|
196
196
|
|
|
@@ -199,23 +199,23 @@ html {
|
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
.prose blockquote {
|
|
202
|
-
border-left: 4px solid
|
|
202
|
+
border-left: 4px solid var(--lagoon-deep);
|
|
203
203
|
padding-left: 1em;
|
|
204
204
|
margin: 1em 0;
|
|
205
|
-
color:
|
|
205
|
+
color: var(--sea-ink-soft);
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
/* Ensure code blocks match the AI's formatting */
|
|
209
209
|
.prose code {
|
|
210
|
-
color:
|
|
211
|
-
background-color:
|
|
210
|
+
color: var(--sea-ink);
|
|
211
|
+
background-color: var(--chip-bg);
|
|
212
212
|
padding: 0.2em 0.4em;
|
|
213
213
|
border-radius: 0.375rem;
|
|
214
214
|
font-size: 0.875em;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
.prose pre {
|
|
218
|
-
background-color:
|
|
218
|
+
background-color: var(--chip-bg);
|
|
219
219
|
border-radius: 0.5rem;
|
|
220
220
|
padding: 1rem;
|
|
221
221
|
margin: 1em 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
|
|