create-fate 1.0.3 → 1.3.0
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/README.md +3 -0
- package/bin/create-fate.mjs +594 -9
- package/package.json +2 -2
- package/templates/fate/README.md +3 -0
- package/templates/fate/_shared/vue-app/package.json +54 -0
- package/templates/fate/_shared/vue-app/pages/index.vue +57 -0
- package/templates/fate/_shared/vue-app/pages/layout.vue +32 -0
- package/templates/fate/_shared/vue-app/pages/post/[id].vue +24 -0
- package/templates/fate/_shared/vue-app/src/App.css +63 -0
- package/templates/fate/_shared/vue-app/src/fateViews.ts +14 -0
- package/templates/fate/_shared/vue-app/src/lib/cx.ts +6 -0
- package/templates/fate/_shared/vue-app/src/lib/env.ts +3 -0
- package/templates/fate/_shared/vue-app/src/ui/Button.vue +67 -0
- package/templates/fate/_shared/vue-app/src/ui/Card.vue +16 -0
- package/templates/fate/_shared/vue-app/src/ui/Error.vue +9 -0
- package/templates/fate/_shared/vue-app/src/ui/ErrorBoundary.vue +22 -0
- package/templates/fate/_shared/vue-app/src/ui/Header.vue +35 -0
- package/templates/fate/_shared/vue-app/src/ui/Link.vue +15 -0
- package/templates/fate/_shared/vue-app/src/ui/PostCard.vue +29 -0
- package/templates/fate/_shared/vue-app/src/ui/Section.vue +19 -0
- package/templates/fate/_shared/vue-app/src/ui/Thinking.vue +11 -0
- package/templates/fate/_shared/vue-app/src/ui/UserCard.vue +23 -0
- package/templates/fate/_shared/vue-app/src/vue-shims.d.ts +6 -0
- package/templates/fate/_shared/vue-app/tsconfig.json +22 -0
- package/templates/fate/_shared/vue-app/vite.config.ts +58 -0
- package/templates/fate/_shared/vue-app/void.json +5 -0
- package/templates/fate/cloudflare/.github/workflows/push.yml +27 -0
- package/templates/fate/cloudflare/.vite-hooks/pre-commit +1 -0
- package/templates/fate/cloudflare/.vscode/extensions.json +12 -0
- package/templates/fate/cloudflare/.vscode/settings.json +25 -0
- package/templates/fate/cloudflare/AGENTS.md +55 -0
- package/templates/fate/cloudflare/README.md +126 -0
- package/templates/fate/cloudflare/_gitignore +20 -0
- package/templates/fate/cloudflare/client/package.json +56 -0
- package/templates/fate/cloudflare/client/pages/index.tsx +96 -0
- package/templates/fate/cloudflare/client/pages/layout.tsx +82 -0
- package/templates/fate/cloudflare/client/pages/login.tsx +107 -0
- package/templates/fate/cloudflare/client/pages/post/[id].tsx +22 -0
- package/templates/fate/cloudflare/client/pages/search.tsx +99 -0
- package/templates/fate/cloudflare/client/public/icon.svg +1 -0
- package/templates/fate/cloudflare/client/src/App.css +153 -0
- package/templates/fate/cloudflare/client/src/lib/AvailableLanguages.tsx +5 -0
- package/templates/fate/cloudflare/client/src/lib/cx.tsx +6 -0
- package/templates/fate/cloudflare/client/src/lib/env.tsx +5 -0
- package/templates/fate/cloudflare/client/src/ui/Badge.tsx +31 -0
- package/templates/fate/cloudflare/client/src/ui/Button.tsx +108 -0
- package/templates/fate/cloudflare/client/src/ui/Card.tsx +32 -0
- package/templates/fate/cloudflare/client/src/ui/CommentCard.tsx +75 -0
- package/templates/fate/cloudflare/client/src/ui/Error.tsx +19 -0
- package/templates/fate/cloudflare/client/src/ui/H2.tsx +15 -0
- package/templates/fate/cloudflare/client/src/ui/H3.tsx +20 -0
- package/templates/fate/cloudflare/client/src/ui/Header.tsx +98 -0
- package/templates/fate/cloudflare/client/src/ui/Input.tsx +17 -0
- package/templates/fate/cloudflare/client/src/ui/Link.tsx +11 -0
- package/templates/fate/cloudflare/client/src/ui/LocaleSwitcher.tsx +52 -0
- package/templates/fate/cloudflare/client/src/ui/PostCard.tsx +303 -0
- package/templates/fate/cloudflare/client/src/ui/Section.tsx +23 -0
- package/templates/fate/cloudflare/client/src/ui/UserCard.tsx +131 -0
- package/templates/fate/cloudflare/client/src/user/AuthClient.tsx +6 -0
- package/templates/fate/cloudflare/client/translations/de_DE.json +689 -0
- package/templates/fate/cloudflare/client/translations/ja_JP.json +689 -0
- package/templates/fate/cloudflare/client/vite.config.ts +45 -0
- package/templates/fate/cloudflare/client/void.json +29 -0
- package/templates/fate/cloudflare/package.json +46 -0
- package/templates/fate/cloudflare/pnpm-workspace.yaml +39 -0
- package/templates/fate/cloudflare/server/.env.example +1 -0
- package/templates/fate/cloudflare/server/db/db.ts +30 -0
- package/templates/fate/cloudflare/server/db/migrations/20260508073357_initial_schema.sql +133 -0
- package/templates/fate/cloudflare/server/db/migrations/20260508120500_seed_cloudflare_demo.sql +170 -0
- package/templates/fate/cloudflare/server/db/migrations/meta/20260508073357_snapshot.json +868 -0
- package/templates/fate/cloudflare/server/db/migrations/meta/_journal.json +20 -0
- package/templates/fate/cloudflare/server/db/queries.ts +211 -0
- package/templates/fate/cloudflare/server/db/schema.ts +332 -0
- package/templates/fate/cloudflare/server/package.json +34 -0
- package/templates/fate/cloudflare/server/src/fate/commentPermissions.ts +17 -0
- package/templates/fate/cloudflare/server/src/fate/context.ts +15 -0
- package/templates/fate/cloudflare/server/src/fate/live.ts +7 -0
- package/templates/fate/cloudflare/server/src/fate/server.ts +411 -0
- package/templates/fate/cloudflare/server/src/fate/views.ts +164 -0
- package/templates/fate/cloudflare/server/src/index.ts +80 -0
- package/templates/fate/cloudflare/server/src/lib/auth.ts +66 -0
- package/templates/fate/cloudflare/server/src/lib/origins.ts +17 -0
- package/templates/fate/cloudflare/server/src/router.ts +2 -0
- package/templates/fate/cloudflare/server/src/user/SessionUser.tsx +17 -0
- package/templates/fate/cloudflare/server/tsconfig.json +10 -0
- package/templates/fate/cloudflare/server/wrangler.jsonc +29 -0
- package/templates/fate/cloudflare/tsconfig.json +33 -0
- package/templates/fate/cloudflare/vite.config.ts +72 -0
- package/templates/fate/drizzle/README.md +2 -8
- package/templates/fate/drizzle/client/pages/layout.tsx +2 -2
- package/templates/fate/drizzle/client/src/ui/PostCard.tsx +38 -15
- package/templates/fate/drizzle/pnpm-workspace.yaml +9 -3
- package/templates/fate/drizzle/server/vite.config.ts +1 -1
- package/templates/fate/graphql/.github/workflows/push.yml +27 -0
- package/templates/fate/graphql/.vite-hooks/pre-commit +1 -0
- package/templates/fate/graphql/.vscode/extensions.json +12 -0
- package/templates/fate/graphql/.vscode/settings.json +25 -0
- package/templates/fate/graphql/AGENTS.md +55 -0
- package/templates/fate/graphql/README.md +121 -0
- package/templates/fate/graphql/_gitignore +23 -0
- package/templates/fate/graphql/client/package.json +57 -0
- package/templates/fate/graphql/client/pages/index.tsx +96 -0
- package/templates/fate/graphql/client/pages/layout.tsx +83 -0
- package/templates/fate/graphql/client/pages/login.tsx +107 -0
- package/templates/fate/graphql/client/pages/post/[id].tsx +22 -0
- package/templates/fate/graphql/client/pages/search.tsx +99 -0
- package/templates/fate/graphql/client/public/icon.svg +1 -0
- package/templates/fate/graphql/client/src/App.css +153 -0
- package/templates/fate/graphql/client/src/lib/AvailableLanguages.tsx +5 -0
- package/templates/fate/graphql/client/src/lib/cx.tsx +6 -0
- package/templates/fate/graphql/client/src/lib/env.tsx +5 -0
- package/templates/fate/graphql/client/src/ui/Badge.tsx +31 -0
- package/templates/fate/graphql/client/src/ui/Button.tsx +108 -0
- package/templates/fate/graphql/client/src/ui/Card.tsx +32 -0
- package/templates/fate/graphql/client/src/ui/CommentCard.tsx +75 -0
- package/templates/fate/graphql/client/src/ui/Error.tsx +19 -0
- package/templates/fate/graphql/client/src/ui/H2.tsx +15 -0
- package/templates/fate/graphql/client/src/ui/H3.tsx +20 -0
- package/templates/fate/graphql/client/src/ui/Header.tsx +98 -0
- package/templates/fate/graphql/client/src/ui/Input.tsx +17 -0
- package/templates/fate/graphql/client/src/ui/Link.tsx +11 -0
- package/templates/fate/graphql/client/src/ui/LocaleSwitcher.tsx +52 -0
- package/templates/fate/graphql/client/src/ui/PostCard.tsx +303 -0
- package/templates/fate/graphql/client/src/ui/Section.tsx +23 -0
- package/templates/fate/graphql/client/src/ui/UserCard.tsx +131 -0
- package/templates/fate/graphql/client/src/user/AuthClient.tsx +6 -0
- package/templates/fate/graphql/client/translations/de_DE.json +689 -0
- package/templates/fate/graphql/client/translations/ja_JP.json +689 -0
- package/templates/fate/graphql/client/vite.config.ts +40 -0
- package/templates/fate/graphql/client/void.json +29 -0
- package/templates/fate/graphql/docker-compose.yml +11 -0
- package/templates/fate/graphql/package.json +47 -0
- package/templates/fate/graphql/pnpm-workspace.yaml +45 -0
- package/templates/fate/graphql/server/.env.example +5 -0
- package/templates/fate/graphql/server/README.md +27 -0
- package/templates/fate/graphql/server/package.json +64 -0
- package/templates/fate/graphql/server/prisma.config.ts +17 -0
- package/templates/fate/graphql/server/scripts/generate-graphql.tsx +40 -0
- package/templates/fate/graphql/server/src/__tests__/index.test.tsx +5 -0
- package/templates/fate/graphql/server/src/app.tsx +47 -0
- package/templates/fate/graphql/server/src/graphql/builder.tsx +121 -0
- package/templates/fate/graphql/server/src/graphql/context.tsx +22 -0
- package/templates/fate/graphql/server/src/graphql/fate.ts +85 -0
- package/templates/fate/graphql/server/src/graphql/lib/authDirectives.tsx +93 -0
- package/templates/fate/graphql/server/src/graphql/lib/decodeGlobalID.tsx +12 -0
- package/templates/fate/graphql/server/src/graphql/lib/decodeIDOrThrow.tsx +10 -0
- package/templates/fate/graphql/server/src/graphql/lib/encodeGlobalID.tsx +5 -0
- package/templates/fate/graphql/server/src/graphql/live.tsx +241 -0
- package/templates/fate/graphql/server/src/graphql/mutations.tsx +265 -0
- package/templates/fate/graphql/server/src/graphql/nodes/Category.tsx +35 -0
- package/templates/fate/graphql/server/src/graphql/nodes/Comment.tsx +46 -0
- package/templates/fate/graphql/server/src/graphql/nodes/Event.tsx +71 -0
- package/templates/fate/graphql/server/src/graphql/nodes/Post.tsx +45 -0
- package/templates/fate/graphql/server/src/graphql/nodes/Tag.tsx +11 -0
- package/templates/fate/graphql/server/src/graphql/nodes/User.tsx +28 -0
- package/templates/fate/graphql/server/src/graphql/schema.tsx +16 -0
- package/templates/fate/graphql/server/src/graphql/views.ts +193 -0
- package/templates/fate/graphql/server/src/index.tsx +45 -0
- package/templates/fate/graphql/server/src/lib/auth.tsx +31 -0
- package/templates/fate/graphql/server/src/lib/env.tsx +3 -0
- package/templates/fate/graphql/server/src/lib/origins.ts +18 -0
- package/templates/fate/graphql/server/src/prisma/prisma.tsx +9 -0
- package/templates/fate/graphql/server/src/prisma/schema.prisma +181 -0
- package/templates/fate/graphql/server/src/prisma/seed.tsx +161 -0
- package/templates/fate/graphql/server/src/user/SessionUser.tsx +17 -0
- package/templates/fate/graphql/server/src/user/isAdmin.tsx +3 -0
- package/templates/fate/graphql/server/tsconfig.json +33 -0
- package/templates/fate/graphql/server/vite.config.ts +55 -0
- package/templates/fate/graphql/tsconfig.json +33 -0
- package/templates/fate/graphql/vite.config.ts +80 -0
- package/templates/fate/graphql-client/.env.example +3 -0
- package/templates/fate/graphql-client/AGENTS.md +3 -0
- package/templates/fate/graphql-client/README.md +69 -0
- package/templates/fate/graphql-client/_gitignore +14 -0
- package/templates/fate/graphql-client/package.json +62 -0
- package/templates/fate/graphql-client/pages/index.tsx +69 -0
- package/templates/fate/graphql-client/pages/layout.tsx +41 -0
- package/templates/fate/graphql-client/pnpm-workspace.yaml +38 -0
- package/templates/fate/graphql-client/public/icon.svg +8 -0
- package/templates/fate/graphql-client/src/App.css +28 -0
- package/templates/fate/graphql-client/src/fate/graphql.ts +52 -0
- package/templates/fate/graphql-client/tsconfig.json +30 -0
- package/templates/fate/graphql-client/vite.config.ts +87 -0
- package/templates/fate/graphql-client/void.json +29 -0
- package/templates/fate/http/README.md +2 -8
- package/templates/fate/http/client/pages/layout.tsx +2 -2
- package/templates/fate/http/client/src/ui/PostCard.tsx +37 -15
- package/templates/fate/http/pnpm-workspace.yaml +9 -3
- package/templates/fate/http/server/vite.config.ts +1 -1
- package/templates/fate/prisma/README.md +2 -8
- package/templates/fate/prisma/client/pages/layout.tsx +2 -2
- package/templates/fate/prisma/client/src/ui/PostCard.tsx +37 -15
- package/templates/fate/prisma/pnpm-workspace.yaml +9 -3
- package/templates/fate/prisma/server/vite.config.ts +1 -1
- package/templates/fate/prisma/vite.config.ts +1 -1
- package/templates/fate/void/package.json +10 -2
- package/templates/fate/void/pages/login.tsx +3 -3
- package/templates/fate/void/pnpm-workspace.yaml +12 -4
- package/templates/fate/void/src/ui/Button.tsx +42 -26
- package/templates/fate/void/src/ui/CategoryCard.tsx +3 -7
- package/templates/fate/void/src/ui/PostCard.tsx +38 -15
- package/templates/fate/void/vite.config.ts +15 -14
- package/templates/fate/drizzle/public/fate-logo-dark.svg +0 -4
- package/templates/fate/drizzle/public/fate-logo.svg +0 -4
- package/templates/fate/http/public/fate-logo-dark.svg +0 -4
- package/templates/fate/http/public/fate-logo.svg +0 -4
- package/templates/fate/prisma/public/fate-logo-dark.svg +0 -4
- package/templates/fate/prisma/public/fate-logo.svg +0 -4
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
.fate/
|
|
2
|
+
**/.fate/
|
|
3
|
+
.void/
|
|
4
|
+
**/.void/
|
|
5
|
+
.eslintcache
|
|
6
|
+
.pnpm-debug.log
|
|
7
|
+
**/node_modules/
|
|
8
|
+
/node_modules/
|
|
9
|
+
client/.enum_manifest.json
|
|
10
|
+
client/dist/
|
|
11
|
+
client/source_strings.json
|
|
12
|
+
client/src/translations/
|
|
13
|
+
coverage/
|
|
14
|
+
dist/
|
|
15
|
+
server/.env
|
|
16
|
+
server/.prod.env
|
|
17
|
+
server/dist/
|
|
18
|
+
server/src/graphql/schema.graphql
|
|
19
|
+
server/src/graphql/schemaImportMap.tsx
|
|
20
|
+
server/src/prisma/pothos-types.ts
|
|
21
|
+
server/src/prisma/prisma-client/
|
|
22
|
+
tsconfig.tsbuildinfo
|
|
23
|
+
vite.config.ts.timestamp-*
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@app/client",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"author": "Christoph Nakazawa <christoph.pojer@gmail.com>",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git://github.com/nkzw-tech/fate.git"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "vp build",
|
|
13
|
+
"dev": "vp dev",
|
|
14
|
+
"dev:setup": "vp run fbtee:all",
|
|
15
|
+
"fate:generate": "vp exec fate generate",
|
|
16
|
+
"fbtee:all": "vpx fbtee collect && vpx fbtee translate"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@app/server": "workspace:*",
|
|
20
|
+
"@hono/node-server": "^2.0.1",
|
|
21
|
+
"@nkzw/core": "^1.3.1",
|
|
22
|
+
"@nkzw/define-env": "^1.1.0",
|
|
23
|
+
"@nkzw/stack": "^2.3.2",
|
|
24
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
25
|
+
"@void/react": "^0.7.13",
|
|
26
|
+
"better-auth": "^1.6.9",
|
|
27
|
+
"class-variance-authority": "^0.7.1",
|
|
28
|
+
"clsx": "^2.1.1",
|
|
29
|
+
"fbtee": "^1.7.4",
|
|
30
|
+
"graphql-sse": "^2.6.0",
|
|
31
|
+
"lucide-react": "^1.14.0",
|
|
32
|
+
"react": "^19.2.5",
|
|
33
|
+
"react-dom": "^19.2.5",
|
|
34
|
+
"react-error-boundary": "^6.1.1",
|
|
35
|
+
"react-fate": "latest",
|
|
36
|
+
"tailwind-merge": "^3.5.0",
|
|
37
|
+
"void": "^0.7.13"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@nkzw/babel-preset-fbtee": "^1.7.4",
|
|
41
|
+
"@rolldown/plugin-babel": "^0.2.3",
|
|
42
|
+
"@tailwindcss/vite": "^4.2.4",
|
|
43
|
+
"@types/babel__core": "^7.20.5",
|
|
44
|
+
"@types/node": "^25.6.0",
|
|
45
|
+
"@types/react": "^19.2.14",
|
|
46
|
+
"@types/react-dom": "^19.2.3",
|
|
47
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
48
|
+
"tailwindcss": "^4.2.4",
|
|
49
|
+
"vite": "catalog:",
|
|
50
|
+
"vite-plus": "catalog:"
|
|
51
|
+
},
|
|
52
|
+
"browserslist": [
|
|
53
|
+
">0.2%",
|
|
54
|
+
"not dead",
|
|
55
|
+
"not op_mini all"
|
|
56
|
+
]
|
|
57
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import Stack, { VStack } from '@nkzw/stack';
|
|
2
|
+
import { ConnectionRef, useListView, useRequest } from 'react-fate';
|
|
3
|
+
import cx from '../src/lib/cx.tsx';
|
|
4
|
+
import { Button } from '../src/ui/Button.tsx';
|
|
5
|
+
import Card from '../src/ui/Card.tsx';
|
|
6
|
+
import H2 from '../src/ui/H2.tsx';
|
|
7
|
+
import Link from '../src/ui/Link.tsx';
|
|
8
|
+
import { PostCard, PostView } from '../src/ui/PostCard.tsx';
|
|
9
|
+
import Section from '../src/ui/Section.tsx';
|
|
10
|
+
import UserCard, { UserView } from '../src/ui/UserCard.tsx';
|
|
11
|
+
|
|
12
|
+
const PostConnectionView = {
|
|
13
|
+
args: { first: 3 },
|
|
14
|
+
items: {
|
|
15
|
+
node: PostView,
|
|
16
|
+
},
|
|
17
|
+
pagination: {
|
|
18
|
+
hasNext: true,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const PostFeed = ({ posts: postsRef }: { posts: ConnectionRef<'Post'> }) => {
|
|
23
|
+
const [posts, loadNext] = useListView(PostConnectionView, postsRef);
|
|
24
|
+
|
|
25
|
+
return posts.length ? (
|
|
26
|
+
<VStack gap={16}>
|
|
27
|
+
<H2 className="pl-5">
|
|
28
|
+
<fbt desc="Latest posts header">Latest posts</fbt>
|
|
29
|
+
</H2>
|
|
30
|
+
<VStack gap={32}>
|
|
31
|
+
{posts.map(({ node }) => (
|
|
32
|
+
<PostCard key={node.id} post={node} />
|
|
33
|
+
))}
|
|
34
|
+
{loadNext ? (
|
|
35
|
+
<Stack center>
|
|
36
|
+
<Button onClick={loadNext} variant="ghost">
|
|
37
|
+
<fbt desc="Load more posts button">Load more posts</fbt>
|
|
38
|
+
</Button>
|
|
39
|
+
</Stack>
|
|
40
|
+
) : null}
|
|
41
|
+
</VStack>
|
|
42
|
+
</VStack>
|
|
43
|
+
) : null;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default function HomePage() {
|
|
47
|
+
const { posts, viewer } = useRequest({
|
|
48
|
+
posts: { list: PostConnectionView },
|
|
49
|
+
viewer: { view: UserView },
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Section gap={32}>
|
|
54
|
+
<div
|
|
55
|
+
className={cx('grid gap-8 lg:items-stretch', viewer?.id ? 'lg:grid-cols-[1.6fr_1fr]' : '')}
|
|
56
|
+
>
|
|
57
|
+
<Card className="border border-white/20 bg-linear-to-r from-blue-500 to-sky-500 text-white dark:from-blue-600 dark:to-sky-600">
|
|
58
|
+
<Stack alignCenter gap={12} wrap>
|
|
59
|
+
<span className="squircle bg-white/20 px-2 py-1 text-xs font-semibold tracking-widest uppercase">
|
|
60
|
+
<span className="lowercase italic">fate</span> demo
|
|
61
|
+
</span>
|
|
62
|
+
</Stack>
|
|
63
|
+
<div className="space-y-3">
|
|
64
|
+
<h1 className="text-3xl leading-tight font-semibold text-balance lg:text-4xl">
|
|
65
|
+
<fbt desc="Description of fate">
|
|
66
|
+
fate is a modern data client for React inspired by Relay and GraphQL.
|
|
67
|
+
</fbt>
|
|
68
|
+
</h1>
|
|
69
|
+
<p className="text-sm text-white/80 lg:text-base">
|
|
70
|
+
<fbt desc="Tagline for fate">
|
|
71
|
+
fate combines view composition, normalized caching, data masking, Async React
|
|
72
|
+
features, and type-safe data fetching.
|
|
73
|
+
</fbt>
|
|
74
|
+
</p>
|
|
75
|
+
</div>
|
|
76
|
+
<Stack alignCenter gap={12} wrap>
|
|
77
|
+
{!viewer?.id && (
|
|
78
|
+
<>
|
|
79
|
+
<Button asChild size="sm" variant="secondary">
|
|
80
|
+
<Link className="squircle px-4 py-2 text-sm font-semibold" to="/login">
|
|
81
|
+
<fbt desc="Login button">Login</fbt>
|
|
82
|
+
</Link>
|
|
83
|
+
</Button>
|
|
84
|
+
<span className="text-sm text-white/80">
|
|
85
|
+
<fbt desc="Login button label">Sign in to post comments.</fbt>
|
|
86
|
+
</span>
|
|
87
|
+
</>
|
|
88
|
+
)}
|
|
89
|
+
</Stack>
|
|
90
|
+
</Card>
|
|
91
|
+
{viewer?.id && <UserCard user={viewer} />}
|
|
92
|
+
</div>
|
|
93
|
+
<PostFeed posts={posts} />
|
|
94
|
+
</Section>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/// <reference types="fbtee/ReactTypes.d.ts" />
|
|
2
|
+
|
|
3
|
+
import '../src/App.css';
|
|
4
|
+
import Stack from '@nkzw/stack';
|
|
5
|
+
import { createLocaleContext } from 'fbtee';
|
|
6
|
+
import { ReactNode, Suspense, useMemo } from 'react';
|
|
7
|
+
import { ErrorBoundary } from 'react-error-boundary';
|
|
8
|
+
import { FateClient } from 'react-fate';
|
|
9
|
+
import { createFateClient } from 'react-fate/client';
|
|
10
|
+
import AvailableLanguages from '../src/lib/AvailableLanguages.tsx';
|
|
11
|
+
import env from '../src/lib/env.tsx';
|
|
12
|
+
import Card from '../src/ui/Card.tsx';
|
|
13
|
+
import Error from '../src/ui/Error.tsx';
|
|
14
|
+
import Header from '../src/ui/Header.tsx';
|
|
15
|
+
import Section from '../src/ui/Section.tsx';
|
|
16
|
+
import AuthClient from '../src/user/AuthClient.tsx';
|
|
17
|
+
|
|
18
|
+
const Thinking = () => (
|
|
19
|
+
<Section>
|
|
20
|
+
<Stack center className="animate-pulse text-gray-500 italic" verticalPadding={48}>
|
|
21
|
+
<fbt desc="Text for thinking/loading screen">Thinking...</fbt>
|
|
22
|
+
</Stack>
|
|
23
|
+
</Section>
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const LocaleContext = createLocaleContext({
|
|
27
|
+
availableLanguages: AvailableLanguages,
|
|
28
|
+
clientLocales: [navigator.language, ...navigator.languages],
|
|
29
|
+
loadLocale: async (locale: string) => {
|
|
30
|
+
if (locale !== 'en_US' && AvailableLanguages.has(locale)) {
|
|
31
|
+
return (await import(`../src/translations/${locale}.json`)).default[locale];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {};
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export default function Layout({ children }: { children: ReactNode }) {
|
|
39
|
+
const { data: session } = AuthClient.useSession();
|
|
40
|
+
const userId = session?.user.id;
|
|
41
|
+
|
|
42
|
+
const fate = useMemo(
|
|
43
|
+
() =>
|
|
44
|
+
createFateClient({
|
|
45
|
+
fetch: userId
|
|
46
|
+
? (input, init) =>
|
|
47
|
+
fetch(input, {
|
|
48
|
+
...init,
|
|
49
|
+
credentials: 'include',
|
|
50
|
+
})
|
|
51
|
+
: undefined,
|
|
52
|
+
url: `${env('SERVER_URL')}/graphql`,
|
|
53
|
+
}),
|
|
54
|
+
[userId],
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<LocaleContext>
|
|
59
|
+
<div className="min-h-screen bg-background text-foreground">
|
|
60
|
+
<div className="min-h-screen bg-[radial-gradient(circle_at_20%_20%,rgba(59,130,246,0.08),transparent_35%),radial-gradient(circle_at_80%_0,rgba(99,102,241,0.08),transparent_28%)]">
|
|
61
|
+
<Header />
|
|
62
|
+
{session ? (
|
|
63
|
+
<Thinking />
|
|
64
|
+
) : (
|
|
65
|
+
<FateClient client={fate} key={userId}>
|
|
66
|
+
<ErrorBoundary
|
|
67
|
+
fallbackRender={({ error }) => (
|
|
68
|
+
<Section>
|
|
69
|
+
<Card>
|
|
70
|
+
<Error error={error} />
|
|
71
|
+
</Card>
|
|
72
|
+
</Section>
|
|
73
|
+
)}
|
|
74
|
+
>
|
|
75
|
+
<Suspense fallback={<Thinking />}>{children}</Suspense>
|
|
76
|
+
</ErrorBoundary>
|
|
77
|
+
</FateClient>
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</LocaleContext>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import Stack, { VStack } from '@nkzw/stack';
|
|
2
|
+
import { useRouter } from '@void/react';
|
|
3
|
+
import { fbs } from 'fbtee';
|
|
4
|
+
import { ExternalLinkIcon } from 'lucide-react';
|
|
5
|
+
import { useActionState, useEffect, useState } from 'react';
|
|
6
|
+
import { AsyncButton } from '../src/ui/Button.tsx';
|
|
7
|
+
import Card from '../src/ui/Card.tsx';
|
|
8
|
+
import H2 from '../src/ui/H2.tsx';
|
|
9
|
+
import Input from '../src/ui/Input.tsx';
|
|
10
|
+
import Section from '../src/ui/Section.tsx';
|
|
11
|
+
import AuthClient from '../src/user/AuthClient.tsx';
|
|
12
|
+
|
|
13
|
+
export default function LoginPage() {
|
|
14
|
+
const [email, setEmail] = useState('');
|
|
15
|
+
const [password, setPassword] = useState('');
|
|
16
|
+
const router = useRouter();
|
|
17
|
+
const { data: session } = AuthClient.useSession();
|
|
18
|
+
|
|
19
|
+
const [, signInAction] = useActionState(async () => {
|
|
20
|
+
await AuthClient.signIn.email(
|
|
21
|
+
{
|
|
22
|
+
email,
|
|
23
|
+
password,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
onError: () => {},
|
|
27
|
+
onRequest: () => {},
|
|
28
|
+
onSuccess: () => {
|
|
29
|
+
router.flushAll();
|
|
30
|
+
void router.visit('/', { replace: true });
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
return null;
|
|
36
|
+
}, null);
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (session) {
|
|
40
|
+
router.flushAll();
|
|
41
|
+
void router.visit('/', { replace: true });
|
|
42
|
+
}
|
|
43
|
+
}, [router, session]);
|
|
44
|
+
|
|
45
|
+
if (session) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Section>
|
|
51
|
+
<VStack center gap={16}>
|
|
52
|
+
<H2 className="pl-5">
|
|
53
|
+
<fbt desc="Sign In headline">Sign In</fbt>
|
|
54
|
+
</H2>
|
|
55
|
+
<Stack gap={32} wrap>
|
|
56
|
+
<Card className="w-84">
|
|
57
|
+
<Stack gap vertical>
|
|
58
|
+
<VStack action={signInAction} as="form" gap={12}>
|
|
59
|
+
<Input
|
|
60
|
+
className="w-48"
|
|
61
|
+
name="email"
|
|
62
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
63
|
+
placeholder={fbs('email', 'Email placeholder')}
|
|
64
|
+
type="email"
|
|
65
|
+
value={email}
|
|
66
|
+
/>
|
|
67
|
+
<Input
|
|
68
|
+
className="w-48"
|
|
69
|
+
name="password"
|
|
70
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
71
|
+
placeholder={fbs('password', 'Password placeholder')}
|
|
72
|
+
type="password"
|
|
73
|
+
value={password}
|
|
74
|
+
/>
|
|
75
|
+
<div>
|
|
76
|
+
<AsyncButton type="submit" variant="outline">
|
|
77
|
+
<fbt desc="Sign in button">Sign In</fbt>
|
|
78
|
+
</AsyncButton>
|
|
79
|
+
</div>
|
|
80
|
+
</VStack>
|
|
81
|
+
</Stack>
|
|
82
|
+
</Card>
|
|
83
|
+
<Card className="w-84">
|
|
84
|
+
<p>
|
|
85
|
+
<fbt desc="Login details">
|
|
86
|
+
Try one of the
|
|
87
|
+
<Stack
|
|
88
|
+
alignCenter
|
|
89
|
+
as="a"
|
|
90
|
+
className="inline-flex! px-1 underline hover:no-underline"
|
|
91
|
+
gap={4}
|
|
92
|
+
href="https://github.com/nkzw-tech/fate/blob/main/packages/create-fate/templates/fate/prisma/server/src/prisma/seedData.ts#L1"
|
|
93
|
+
rel="noreferrer"
|
|
94
|
+
target="_blank"
|
|
95
|
+
>
|
|
96
|
+
Example Accounts
|
|
97
|
+
<ExternalLinkIcon className="h-4 w-4" />
|
|
98
|
+
</Stack>{' '}
|
|
99
|
+
in the seed data.
|
|
100
|
+
</fbt>
|
|
101
|
+
</p>
|
|
102
|
+
</Card>
|
|
103
|
+
</Stack>
|
|
104
|
+
</VStack>
|
|
105
|
+
</Section>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useParams } from '@void/react';
|
|
2
|
+
import { useRequest } from 'react-fate';
|
|
3
|
+
import { PostCard, PostView } from '../../src/ui/PostCard.tsx';
|
|
4
|
+
import Section from '../../src/ui/Section.tsx';
|
|
5
|
+
|
|
6
|
+
export default function PostPage() {
|
|
7
|
+
const { id } = useParams<{ id: string }>();
|
|
8
|
+
|
|
9
|
+
if (!id) {
|
|
10
|
+
throw new Error('fate: Post ID is required.');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { post } = useRequest({
|
|
14
|
+
post: { id, view: PostView },
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Section>
|
|
19
|
+
<PostCard detail post={post} />
|
|
20
|
+
</Section>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { Comment, Post } from '@app/server/src/graphql/fate.ts';
|
|
2
|
+
import Stack, { VStack } from '@nkzw/stack';
|
|
3
|
+
import { fbs } from 'fbtee';
|
|
4
|
+
import { Suspense, useDeferredValue, useState } from 'react';
|
|
5
|
+
import { ErrorBoundary } from 'react-error-boundary';
|
|
6
|
+
import { useRequest, useView, view, ViewRef } from 'react-fate';
|
|
7
|
+
import cx from '../src/lib/cx.tsx';
|
|
8
|
+
import Card from '../src/ui/Card.tsx';
|
|
9
|
+
import CommentCard, { CommentView } from '../src/ui/CommentCard.tsx';
|
|
10
|
+
import Error from '../src/ui/Error.tsx';
|
|
11
|
+
import Input from '../src/ui/Input.tsx';
|
|
12
|
+
import Section from '../src/ui/Section.tsx';
|
|
13
|
+
|
|
14
|
+
const CommentPostView = view<Post>()({
|
|
15
|
+
commentCount: true,
|
|
16
|
+
id: true,
|
|
17
|
+
title: true,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const CommentSearchView = view<Comment>()({
|
|
21
|
+
...CommentView,
|
|
22
|
+
id: true,
|
|
23
|
+
post: CommentPostView,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const isDevelopment = import.meta.env.DEV;
|
|
27
|
+
|
|
28
|
+
const CommentResult = ({ comment: commentRef }: { comment: ViewRef<'Comment'> }) => {
|
|
29
|
+
const comment = useView(CommentSearchView, commentRef);
|
|
30
|
+
const post = useView(CommentPostView, comment.post);
|
|
31
|
+
|
|
32
|
+
return <CommentCard comment={comment} link post={post} />;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const SearchResults = ({ isStale, query }: { isStale: boolean; query: string }) => {
|
|
36
|
+
const { commentSearch } = useRequest({
|
|
37
|
+
commentSearch: { args: { query }, list: CommentSearchView },
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (commentSearch.length === 0) {
|
|
41
|
+
return (
|
|
42
|
+
<p>
|
|
43
|
+
<fbt desc="No matches text">
|
|
44
|
+
No matches for{' '}
|
|
45
|
+
<i>
|
|
46
|
+
"<fbt:param name="query">{query}</fbt:param>"
|
|
47
|
+
</i>
|
|
48
|
+
</fbt>
|
|
49
|
+
</p>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<VStack className={cx(isStale && 'opacity-50')} gap={12}>
|
|
55
|
+
{commentSearch.map((comment) => (
|
|
56
|
+
<CommentResult comment={comment} key={comment.id} />
|
|
57
|
+
))}
|
|
58
|
+
</VStack>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export default function SearchPage() {
|
|
63
|
+
const [query, setQuery] = useState('');
|
|
64
|
+
const deferredQuery = useDeferredValue(query);
|
|
65
|
+
const isStale = query !== deferredQuery;
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<Section>
|
|
69
|
+
<Card>
|
|
70
|
+
<Stack alignCenter between gap={16}>
|
|
71
|
+
<Input
|
|
72
|
+
className="w-64"
|
|
73
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
74
|
+
placeholder={fbs('Search comments...', 'Search input placeholder')}
|
|
75
|
+
ref={(ref) => ref?.focus()}
|
|
76
|
+
value={query}
|
|
77
|
+
/>
|
|
78
|
+
{isDevelopment ? (
|
|
79
|
+
<div className="text-xs text-muted-foreground">
|
|
80
|
+
<fbt desc="Slowdown label explanation">500ms artificial slowdown</fbt>
|
|
81
|
+
</div>
|
|
82
|
+
) : null}
|
|
83
|
+
</Stack>
|
|
84
|
+
|
|
85
|
+
<ErrorBoundary FallbackComponent={Error}>
|
|
86
|
+
<Suspense
|
|
87
|
+
fallback={
|
|
88
|
+
<h2>
|
|
89
|
+
<fbt desc="Text for thinking/loading screen">Thinking…</fbt>
|
|
90
|
+
</h2>
|
|
91
|
+
}
|
|
92
|
+
>
|
|
93
|
+
{query.trim().length > 0 ? <SearchResults isStale={isStale} query={query} /> : null}
|
|
94
|
+
</Suspense>
|
|
95
|
+
</ErrorBoundary>
|
|
96
|
+
</Card>
|
|
97
|
+
</Section>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMax" viewBox="0 0 160 160"><path d="M108.301 17.465h.272c1.797-.005 3.563.177 5.331.496l.349.063c5.588 1.02 10.731 3.447 15.201 6.933l.347.267c1.579 1.26 3.083 2.684 4.386 4.227l.161.186c4.018 4.719 6.924 10.686 7.767 16.852l.033.239c.262 1.848.351 3.688.352 5.551l.001.307c-.001 1.623-.092 3.188-.386 4.788l-.05.292c-1.003 5.874-3.476 11.447-7.286 16.034l-.29.358c-1.422 1.721-3.011 3.382-4.797 4.729l-.444.354c-3.046 2.405-6.436 4.147-10.084 5.442l-.497.186c-1.766.627-3.615.974-5.465 1.266l-.364.058c-1.591.238-3.185.286-4.791.281h-.499l-1.339-.002h-1.408c-.886-.001-1.772-.001-2.656-.003-3.085-.001-6.163-.005-9.247-.008v-12.78l3.606-.006 2.282-.007c1.205-.006 2.407-.01 3.611-.011.878 0 1.754-.003 2.63-.007.462-.002.928-.005 1.389-.002 6.302.01 12.003-1.72 16.65-6.117l.291-.272c3.951-3.807 6.097-9.302 6.241-14.736.04-3.078-.476-6.048-1.68-8.892l-.104-.244c-2.382-5.559-6.98-9.439-12.504-11.675-2.204-.816-4.522-1.16-6.863-1.134-.301.004-.606.004-.909.001-1.677.003-3.304.127-4.924.591l-.331.098c-2.625.758-5.093 1.928-7.254 3.607l-.323.249c-1.046.817-2.031 1.682-2.873 2.71l-.154.179c-2.354 2.782-3.9 5.988-4.727 9.529l-.054.229c-.391 1.8-.423 3.633-.42 5.471l-.001.74c.002 1.4.001 2.801-.004 4.201l-.004 3.779c0 1.824-.001 3.649-.003 5.473l-.006 2.813-.005 6.076-.001.267-.008 8.614c-.001 2.023-.004 4.045-.006 6.066v.259l-.004 2.55-.006 5.46c0 1.331-.001 2.658-.003 3.985-.002.72-.002 1.438-.002 2.156 0 .658 0 1.317-.002 1.978v.708c.004 2.098-.07 4.214-.545 6.263l-.077.359-.161.716c-.071.302-.136.605-.199.909-.55 2.538-1.6 5.067-2.832 7.348l-.214.42c-.965 1.921-2.22 3.714-3.574 5.38l-.152.183c-.78.973-1.639 1.866-2.519 2.751l-.308.313a25.81 25.81 0 0 1-2.226 1.955l-.22.179c-3.698 2.953-7.975 5.044-12.538 6.262-.212.056-.422.115-.631.176-8.366 2.287-17.8.738-25.278-3.512-3.639-2.122-7.171-4.945-9.721-8.307-.121-.15-.241-.298-.356-.448a36.247 36.247 0 0 1-2.605-3.814l-.144-.234c-.889-1.466-1.562-3.034-2.222-4.617l-.11-.265c-3.253-7.791-2.911-17.367.184-25.133.865-2.069 1.869-4.089 3.123-5.951l.172-.261a31.91 31.91 0 0 1 2.547-3.29l.229-.263c.13-.152.266-.304.396-.452l.425-.493c1.216-1.389 2.593-2.615 4.068-3.723.208-.157.414-.315.62-.476 1.184-.901 2.437-1.665 3.729-2.4l.272-.159c1.586-.893 3.235-1.573 4.934-2.21l.253-.097c4.232-1.567 8.615-1.836 13.079-1.82 1.359 0 2.732.002 4.093.007 1.209.005 2.417.006 3.621.006 1.899.002 3.794.007 5.688.012v12.78l-3.612.013-2.282.011c-1.201.005-2.401.012-3.61.016-.876.003-1.751.005-2.629.013-.463.002-.924.005-1.387.006-4.322.005-8.193.592-12.033 2.662l-.217.114c-1.458.773-2.697 1.731-3.908 2.849-.206.185-.413.362-.63.535-.435.376-.794.788-1.16 1.232l-.153.18a21.18 21.18 0 0 0-4.474 8.651l-.094.342c-.42 1.682-.54 3.395-.536 5.127v.272c.019 5.672 2.392 10.671 6.206 14.769l.215.237c3.296 3.453 8.483 5.917 13.247 6.046.448.008.896.01 1.345.01.276 0 .553.003.835.005 4.917.019 9.864-1.73 13.577-4.995l.303-.267c.299-.263.592-.527.881-.799l.262-.247c.787-.756 1.451-1.599 2.104-2.474l.151-.201c1.929-2.606 3.117-5.723 3.635-8.909l.059-.362c.194-1.296.21-2.573.207-3.883l.003-.74v-2.02c0-.73 0-1.459.005-2.188v-3.782c0-1.827.004-3.654.007-5.481 0-.939 0-1.877.004-2.816l.003-6.082v-.268c.005-2.876.008-5.75.008-8.627l.013-8.883c.004-1.823.004-3.646.004-5.469 0-1.33.004-2.659.004-3.989.003-.721.003-1.442.003-2.159v-1.98c.005-.237.005-.473 0-.711-.011-8.523 3.072-17.023 8.941-23.268.244-.263.483-.531.717-.805.416-.48.861-.918 1.324-1.352l.252-.232a26.259 26.259 0 0 1 2.184-1.812l.46-.349c1.39-1.058 2.837-1.951 4.375-2.775l.318-.172c5.005-2.666 10.5-3.877 16.15-3.889Z" style="transform-box:fill-box;transform-origin:50% 50%" transform="rotate(-31 0 0)"/></svg>
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
body {
|
|
4
|
+
font-family:
|
|
5
|
+
system-ui,
|
|
6
|
+
-apple-system,
|
|
7
|
+
BlinkMacSystemFont,
|
|
8
|
+
'Segoe UI',
|
|
9
|
+
'Open Sans',
|
|
10
|
+
'Helvetica Neue',
|
|
11
|
+
sans-serif;
|
|
12
|
+
|
|
13
|
+
background-color: hsl(var(--background));
|
|
14
|
+
color: hsl(var(--foreground));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@theme {
|
|
18
|
+
--color-accent: hsl(var(--accent));
|
|
19
|
+
--color-accent-foreground: hsl(var(--accent-foreground));
|
|
20
|
+
|
|
21
|
+
--color-background: hsl(var(--background));
|
|
22
|
+
--color-foreground: hsl(var(--foreground));
|
|
23
|
+
--color-border: hsl(var(--border));
|
|
24
|
+
--color-ring: hsl(var(--ring));
|
|
25
|
+
|
|
26
|
+
--color-card: hsl(var(--card));
|
|
27
|
+
--color-card-foreground: hsl(var(--card-foreground));
|
|
28
|
+
|
|
29
|
+
--color-muted: hsl(var(--muted));
|
|
30
|
+
--color-muted-foreground: hsl(var(--muted-foreground));
|
|
31
|
+
|
|
32
|
+
--color-secondary: hsl(var(--secondary));
|
|
33
|
+
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
|
34
|
+
|
|
35
|
+
--color-destructive: hsl(var(--destructive));
|
|
36
|
+
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@layer utilities {
|
|
40
|
+
.text-balance {
|
|
41
|
+
text-wrap: balance;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@layer base {
|
|
46
|
+
:root {
|
|
47
|
+
--background: 0 0% 100%;
|
|
48
|
+
--foreground: 0 0% 3.9%;
|
|
49
|
+
--card: 0 0% 100%;
|
|
50
|
+
--card-foreground: 0 0% 3.9%;
|
|
51
|
+
--popover: 0 0% 100%;
|
|
52
|
+
--popover-foreground: 0 0% 3.9%;
|
|
53
|
+
--primary: 0 0% 9%;
|
|
54
|
+
--primary-foreground: 0 0% 98%;
|
|
55
|
+
--secondary: 0 0% 96.1%;
|
|
56
|
+
--secondary-foreground: 0 0% 9%;
|
|
57
|
+
--muted: 0 0% 96.1%;
|
|
58
|
+
--muted-foreground: 0 0 40%;
|
|
59
|
+
--accent: 0 0% 96.1%;
|
|
60
|
+
--accent-foreground: 0 0% 9%;
|
|
61
|
+
--destructive: 0 84.2% 60.2%;
|
|
62
|
+
--destructive-foreground: 0 0% 98%;
|
|
63
|
+
--border: 0 0% 89.8%;
|
|
64
|
+
--input: 0 0% 89.8%;
|
|
65
|
+
--ring: 0 0% 3.9%;
|
|
66
|
+
--chart-1: 12 76% 61%;
|
|
67
|
+
--chart-2: 173 58% 39%;
|
|
68
|
+
--chart-3: 197 37% 24%;
|
|
69
|
+
--chart-4: 43 74% 66%;
|
|
70
|
+
--chart-5: 27 87% 67%;
|
|
71
|
+
--radius: 0.5rem;
|
|
72
|
+
--sidebar-background: 0 0% 98%;
|
|
73
|
+
--sidebar-foreground: 240 5.3% 26.1%;
|
|
74
|
+
--sidebar-primary: 240 5.9% 10%;
|
|
75
|
+
--sidebar-primary-foreground: 0 0% 98%;
|
|
76
|
+
--sidebar-accent: 240 4.8% 95.9%;
|
|
77
|
+
--sidebar-accent-foreground: 240 5.9% 10%;
|
|
78
|
+
--sidebar-border: 220 13% 91%;
|
|
79
|
+
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
80
|
+
}
|
|
81
|
+
@media (prefers-color-scheme: dark) {
|
|
82
|
+
:root {
|
|
83
|
+
--background: 0 0% 3.9%;
|
|
84
|
+
--foreground: 0 0% 98%;
|
|
85
|
+
--card: 0 0% 3.9%;
|
|
86
|
+
--card-foreground: 0 0% 98%;
|
|
87
|
+
--popover: 0 0% 3.9%;
|
|
88
|
+
--popover-foreground: 0 0% 98%;
|
|
89
|
+
--primary: 0 0% 98%;
|
|
90
|
+
--primary-foreground: 0 0% 9%;
|
|
91
|
+
--secondary: 0 0% 14.9%;
|
|
92
|
+
--secondary-foreground: 0 0% 98%;
|
|
93
|
+
--muted: 0 0% 14.9%;
|
|
94
|
+
--muted-foreground: 0 0% 63.9%;
|
|
95
|
+
--accent: 0 0% 14.9%;
|
|
96
|
+
--accent-foreground: 0 0% 98%;
|
|
97
|
+
--destructive: 0 62.8% 30.6%;
|
|
98
|
+
--destructive-foreground: 0 0% 98%;
|
|
99
|
+
--border: 0 0% 14.9%;
|
|
100
|
+
--input: 0 0% 14.9%;
|
|
101
|
+
--ring: 0 0% 83.1%;
|
|
102
|
+
--chart-1: 220 70% 50%;
|
|
103
|
+
--chart-2: 160 60% 45%;
|
|
104
|
+
--chart-3: 30 80% 55%;
|
|
105
|
+
--chart-4: 280 65% 60%;
|
|
106
|
+
--chart-5: 340 75% 55%;
|
|
107
|
+
--sidebar-background: 240 5.9% 10%;
|
|
108
|
+
--sidebar-foreground: 240 4.8% 95.9%;
|
|
109
|
+
--sidebar-primary: 224.3 76.3% 48%;
|
|
110
|
+
--sidebar-primary-foreground: 0 0% 100%;
|
|
111
|
+
--sidebar-accent: 240 3.7% 15.9%;
|
|
112
|
+
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
|
113
|
+
--sidebar-border: 240 3.7% 15.9%;
|
|
114
|
+
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
* {
|
|
119
|
+
@apply border-border;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
textarea {
|
|
124
|
+
resize: none;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.squircle {
|
|
128
|
+
border-radius: 32px;
|
|
129
|
+
corner-shape: squircle;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
::backdrop {
|
|
133
|
+
backdrop-filter: blur(4px);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
[popover] {
|
|
137
|
+
transition:
|
|
138
|
+
opacity 150ms ease-in-out,
|
|
139
|
+
display 150ms ease-out allow-discrete,
|
|
140
|
+
overlay 150ms ease-out allow-discrete;
|
|
141
|
+
opacity: 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
[popover]:popover-open {
|
|
145
|
+
opacity: 1;
|
|
146
|
+
display: block;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@starting-style {
|
|
150
|
+
[popover]:popover-open {
|
|
151
|
+
opacity: 0;
|
|
152
|
+
}
|
|
153
|
+
}
|