@podosoft/podokit 0.1.1 → 0.2.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.
Files changed (153) hide show
  1. package/README.md +17 -3
  2. package/dist/add.d.ts +40 -0
  3. package/dist/add.js +114 -0
  4. package/dist/create.d.ts +2 -1
  5. package/dist/create.js +3 -2
  6. package/dist/index.js +39 -1
  7. package/dist/prompt.d.ts +0 -1
  8. package/dist/prompt.js +6 -7
  9. package/dist/templates/fullstack-nest-svelte/README.md +20 -8
  10. package/dist/templates/fullstack-nest-svelte/apps/api/package.json +14 -2
  11. package/dist/templates/fullstack-nest-svelte/apps/api/src/app.module.ts +11 -1
  12. package/dist/templates/fullstack-nest-svelte/apps/api/src/config/env.validation.ts +20 -15
  13. package/dist/templates/fullstack-nest-svelte/apps/api/src/database/data-source.ts +19 -0
  14. package/dist/templates/fullstack-nest-svelte/apps/api/src/health/health.controller.ts +15 -5
  15. package/dist/templates/fullstack-nest-svelte/apps/api/src/main.ts +8 -0
  16. package/dist/templates/fullstack-nest-svelte/apps/web/components.json +1 -1
  17. package/dist/templates/fullstack-nest-svelte/apps/web/package.json +9 -2
  18. package/dist/templates/fullstack-nest-svelte/apps/web/src/app.css +72 -8
  19. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/button/button.svelte +82 -0
  20. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/button/index.ts +17 -0
  21. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/card/card-action.svelte +23 -0
  22. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/card/card-content.svelte +20 -0
  23. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/card/card-description.svelte +20 -0
  24. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/card/card-footer.svelte +20 -0
  25. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/card/card-header.svelte +23 -0
  26. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/card/card-title.svelte +20 -0
  27. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/card/card.svelte +22 -0
  28. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/card/index.ts +25 -0
  29. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/checkbox/checkbox.svelte +39 -0
  30. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/checkbox/index.ts +6 -0
  31. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/input/index.ts +7 -0
  32. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/input/input.svelte +48 -0
  33. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/label/index.ts +7 -0
  34. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/label/label.svelte +20 -0
  35. package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/utils.ts +11 -0
  36. package/dist/templates/fullstack-nest-svelte/apps/web/src/routes/+page.svelte +19 -12
  37. package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/auth.controller.ts +31 -0
  38. package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/auth.module.ts +22 -0
  39. package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/auth.service.ts +44 -0
  40. package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/dto/login.dto.ts +12 -0
  41. package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/dto/register.dto.ts +13 -0
  42. package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/jwt-auth.guard.ts +5 -0
  43. package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/jwt.strategy.ts +23 -0
  44. package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/user.entity.ts +16 -0
  45. package/dist/templates/modules/auth-jwt/files/apps/api/src/migrations/1720200000000-InitUsers.ts +23 -0
  46. package/dist/templates/modules/auth-jwt/module.manifest.json +31 -0
  47. package/dist/templates/modules/bullmq/files/apps/api/src/jobs/demo.processor.ts +12 -0
  48. package/dist/templates/modules/bullmq/files/apps/api/src/jobs/dto/create-job.dto.ts +9 -0
  49. package/dist/templates/modules/bullmq/files/apps/api/src/jobs/jobs.controller.ts +29 -0
  50. package/dist/templates/modules/bullmq/files/apps/api/src/jobs/jobs.module.ts +15 -0
  51. package/dist/templates/modules/bullmq/files/apps/api/src/jobs/queue.ts +8 -0
  52. package/dist/templates/modules/bullmq/files/apps/api/src/jobs/worker.module.ts +20 -0
  53. package/dist/templates/modules/bullmq/files/apps/api/src/main-worker.ts +14 -0
  54. package/dist/templates/modules/bullmq/files/infra/docker/worker.compose.example.yml +18 -0
  55. package/dist/templates/modules/bullmq/files/infra/k3s/worker-deployment.yaml +22 -0
  56. package/dist/templates/modules/bullmq/module.manifest.json +28 -0
  57. package/dist/templates/modules/file-upload/files/apps/api/src/files/files.controller.ts +29 -0
  58. package/dist/templates/modules/file-upload/files/apps/api/src/files/files.module.ts +9 -0
  59. package/dist/templates/modules/file-upload/module.manifest.json +19 -0
  60. package/dist/templates/modules/job-progress/files/apps/api/src/progress/dto/start-job.dto.ts +11 -0
  61. package/dist/templates/modules/job-progress/files/apps/api/src/progress/job-progress.module.ts +13 -0
  62. package/dist/templates/modules/job-progress/files/apps/api/src/progress/progress.bridge.ts +19 -0
  63. package/dist/templates/modules/job-progress/files/apps/api/src/progress/progress.controller.ts +17 -0
  64. package/dist/templates/modules/job-progress/files/apps/api/src/progress/progress.processor.ts +25 -0
  65. package/dist/templates/modules/job-progress/module.manifest.json +23 -0
  66. package/dist/templates/modules/object-storage-s3/files/apps/api/src/storage/dto/put-object.dto.ts +8 -0
  67. package/dist/templates/modules/object-storage-s3/files/apps/api/src/storage/storage.config.ts +31 -0
  68. package/dist/templates/modules/object-storage-s3/files/apps/api/src/storage/storage.controller.ts +29 -0
  69. package/dist/templates/modules/object-storage-s3/files/apps/api/src/storage/storage.module.ts +11 -0
  70. package/dist/templates/modules/object-storage-s3/files/apps/api/src/storage/storage.service.ts +37 -0
  71. package/dist/templates/modules/object-storage-s3/files/infra/docker/minio.compose.yml +33 -0
  72. package/dist/templates/modules/object-storage-s3/module.manifest.json +31 -0
  73. package/dist/templates/modules/redis/files/apps/api/src/redis/cache.controller.ts +21 -0
  74. package/dist/templates/modules/redis/files/apps/api/src/redis/dto/set-cache.dto.ts +14 -0
  75. package/dist/templates/modules/redis/files/apps/api/src/redis/redis.module.ts +12 -0
  76. package/dist/templates/modules/redis/files/apps/api/src/redis/redis.service.ts +43 -0
  77. package/dist/templates/modules/redis/module.manifest.json +21 -0
  78. package/dist/templates/modules/sse/files/apps/api/src/events/dto/publish-event.dto.ts +8 -0
  79. package/dist/templates/modules/sse/files/apps/api/src/events/events.controller.ts +25 -0
  80. package/dist/templates/modules/sse/files/apps/api/src/events/events.module.ts +12 -0
  81. package/dist/templates/modules/sse/files/apps/api/src/events/events.service.ts +17 -0
  82. package/dist/templates/modules/sse/module.manifest.json +16 -0
  83. package/dist/templates/todo/README.md +40 -0
  84. package/dist/templates/todo/apps/api/Dockerfile +22 -0
  85. package/dist/templates/todo/apps/api/nest-cli.json +5 -0
  86. package/dist/templates/todo/apps/api/package.json +44 -0
  87. package/dist/templates/todo/apps/api/src/app.module.ts +19 -0
  88. package/dist/templates/todo/apps/api/src/common/all-exceptions.filter.ts +43 -0
  89. package/dist/templates/todo/apps/api/src/common/app-exception.ts +12 -0
  90. package/dist/templates/todo/apps/api/src/config/env.validation.ts +23 -0
  91. package/dist/templates/todo/apps/api/src/database/data-source.ts +19 -0
  92. package/dist/templates/todo/apps/api/src/health/health.controller.ts +23 -0
  93. package/dist/templates/todo/apps/api/src/health/health.module.ts +7 -0
  94. package/dist/templates/todo/apps/api/src/main.ts +29 -0
  95. package/dist/templates/todo/apps/api/src/migrations/1720100000000-InitTodos.ts +22 -0
  96. package/dist/templates/todo/apps/api/src/todos/dto/create-todo.dto.ts +10 -0
  97. package/dist/templates/todo/apps/api/src/todos/dto/update-todo.dto.ts +10 -0
  98. package/dist/templates/todo/apps/api/src/todos/todo.entity.ts +16 -0
  99. package/dist/templates/todo/apps/api/src/todos/todos.controller.ts +38 -0
  100. package/dist/templates/todo/apps/api/src/todos/todos.module.ts +12 -0
  101. package/dist/templates/todo/apps/api/src/todos/todos.service.ts +41 -0
  102. package/dist/templates/todo/apps/api/test/health.e2e-spec.ts +23 -0
  103. package/dist/templates/todo/apps/api/tsconfig.json +21 -0
  104. package/dist/templates/todo/apps/web/Dockerfile +22 -0
  105. package/dist/templates/todo/apps/web/components.json +15 -0
  106. package/dist/templates/todo/apps/web/package.json +35 -0
  107. package/dist/templates/todo/apps/web/src/app.css +81 -0
  108. package/dist/templates/todo/apps/web/src/app.d.ts +11 -0
  109. package/dist/templates/todo/apps/web/src/app.html +11 -0
  110. package/dist/templates/todo/apps/web/src/lib/components/ui/button/button.svelte +82 -0
  111. package/dist/templates/todo/apps/web/src/lib/components/ui/button/index.ts +17 -0
  112. package/dist/templates/todo/apps/web/src/lib/components/ui/card/card-action.svelte +23 -0
  113. package/dist/templates/todo/apps/web/src/lib/components/ui/card/card-content.svelte +20 -0
  114. package/dist/templates/todo/apps/web/src/lib/components/ui/card/card-description.svelte +20 -0
  115. package/dist/templates/todo/apps/web/src/lib/components/ui/card/card-footer.svelte +20 -0
  116. package/dist/templates/todo/apps/web/src/lib/components/ui/card/card-header.svelte +23 -0
  117. package/dist/templates/todo/apps/web/src/lib/components/ui/card/card-title.svelte +20 -0
  118. package/dist/templates/todo/apps/web/src/lib/components/ui/card/card.svelte +22 -0
  119. package/dist/templates/todo/apps/web/src/lib/components/ui/card/index.ts +25 -0
  120. package/dist/templates/todo/apps/web/src/lib/components/ui/checkbox/checkbox.svelte +39 -0
  121. package/dist/templates/todo/apps/web/src/lib/components/ui/checkbox/index.ts +6 -0
  122. package/dist/templates/todo/apps/web/src/lib/components/ui/input/index.ts +7 -0
  123. package/dist/templates/todo/apps/web/src/lib/components/ui/input/input.svelte +48 -0
  124. package/dist/templates/todo/apps/web/src/lib/components/ui/label/index.ts +7 -0
  125. package/dist/templates/todo/apps/web/src/lib/components/ui/label/label.svelte +20 -0
  126. package/dist/templates/todo/apps/web/src/lib/i18n/README.md +7 -0
  127. package/dist/templates/todo/apps/web/src/lib/i18n/en.ts +10 -0
  128. package/dist/templates/todo/apps/web/src/lib/i18n/ko.ts +8 -0
  129. package/dist/templates/todo/apps/web/src/lib/server/backend-proxy.ts +16 -0
  130. package/dist/templates/todo/apps/web/src/lib/utils.ts +11 -0
  131. package/dist/templates/todo/apps/web/src/routes/+layout.svelte +9 -0
  132. package/dist/templates/todo/apps/web/src/routes/+page.svelte +95 -0
  133. package/dist/templates/todo/apps/web/src/routes/api/health/+server.ts +12 -0
  134. package/dist/templates/todo/apps/web/src/routes/api/todos/+server.ts +24 -0
  135. package/dist/templates/todo/apps/web/src/routes/api/todos/[id]/+server.ts +24 -0
  136. package/dist/templates/todo/apps/web/static/.gitkeep +0 -0
  137. package/dist/templates/todo/apps/web/svelte.config.js +15 -0
  138. package/dist/templates/todo/apps/web/tsconfig.json +9 -0
  139. package/dist/templates/todo/apps/web/vite.config.ts +7 -0
  140. package/dist/templates/todo/dot-env.example +16 -0
  141. package/dist/templates/todo/dot-gitignore +9 -0
  142. package/dist/templates/todo/infra/docker/docker-compose.yml +29 -0
  143. package/dist/templates/todo/infra/k3s/api-deployment.yaml +24 -0
  144. package/dist/templates/todo/infra/k3s/configmap.yaml +10 -0
  145. package/dist/templates/todo/infra/k3s/ingress.yaml +18 -0
  146. package/dist/templates/todo/infra/k3s/namespace.yaml +4 -0
  147. package/dist/templates/todo/infra/k3s/secret.example.yaml +10 -0
  148. package/dist/templates/todo/infra/k3s/services.yaml +21 -0
  149. package/dist/templates/todo/infra/k3s/web-deployment.yaml +20 -0
  150. package/dist/templates/todo/package.json +13 -0
  151. package/dist/templates.d.ts +10 -0
  152. package/dist/templates.js +33 -0
  153. package/package.json +2 -2
@@ -0,0 +1,38 @@
1
+ import { Body, Controller, Delete, Get, HttpCode, Param, Patch, Post } from "@nestjs/common";
2
+ import { ApiTags } from "@nestjs/swagger";
3
+ import { TodosService } from "./todos.service";
4
+ import { CreateTodoDto } from "./dto/create-todo.dto";
5
+ import { UpdateTodoDto } from "./dto/update-todo.dto";
6
+ import { Todo } from "./todo.entity";
7
+
8
+ @ApiTags("todos")
9
+ @Controller("todos")
10
+ export class TodosController {
11
+ constructor(private readonly todos: TodosService) {}
12
+
13
+ @Get()
14
+ findAll(): Promise<Todo[]> {
15
+ return this.todos.findAll();
16
+ }
17
+
18
+ @Get(":id")
19
+ findOne(@Param("id") id: string): Promise<Todo> {
20
+ return this.todos.findOne(id);
21
+ }
22
+
23
+ @Post()
24
+ create(@Body() dto: CreateTodoDto): Promise<Todo> {
25
+ return this.todos.create(dto);
26
+ }
27
+
28
+ @Patch(":id")
29
+ update(@Param("id") id: string, @Body() dto: UpdateTodoDto): Promise<Todo> {
30
+ return this.todos.update(id, dto);
31
+ }
32
+
33
+ @Delete(":id")
34
+ @HttpCode(204)
35
+ remove(@Param("id") id: string): Promise<void> {
36
+ return this.todos.remove(id);
37
+ }
38
+ }
@@ -0,0 +1,12 @@
1
+ import { Module } from "@nestjs/common";
2
+ import { TypeOrmModule } from "@nestjs/typeorm";
3
+ import { Todo } from "./todo.entity";
4
+ import { TodosController } from "./todos.controller";
5
+ import { TodosService } from "./todos.service";
6
+
7
+ @Module({
8
+ imports: [TypeOrmModule.forFeature([Todo])],
9
+ controllers: [TodosController],
10
+ providers: [TodosService],
11
+ })
12
+ export class TodosModule {}
@@ -0,0 +1,41 @@
1
+ import { Injectable, NotFoundException } from "@nestjs/common";
2
+ import { InjectRepository } from "@nestjs/typeorm";
3
+ import { Repository } from "typeorm";
4
+ import { Todo } from "./todo.entity";
5
+ import { CreateTodoDto } from "./dto/create-todo.dto";
6
+ import { UpdateTodoDto } from "./dto/update-todo.dto";
7
+
8
+ @Injectable()
9
+ export class TodosService {
10
+ constructor(
11
+ @InjectRepository(Todo)
12
+ private readonly todos: Repository<Todo>,
13
+ ) {}
14
+
15
+ findAll(): Promise<Todo[]> {
16
+ return this.todos.find({ order: { createdAt: "DESC" } });
17
+ }
18
+
19
+ async findOne(id: string): Promise<Todo> {
20
+ const todo = await this.todos.findOne({ where: { id } });
21
+ if (!todo) {
22
+ throw new NotFoundException(`Todo ${id} not found`);
23
+ }
24
+ return todo;
25
+ }
26
+
27
+ create(dto: CreateTodoDto): Promise<Todo> {
28
+ return this.todos.save(this.todos.create(dto));
29
+ }
30
+
31
+ async update(id: string, dto: UpdateTodoDto): Promise<Todo> {
32
+ const todo = await this.findOne(id);
33
+ Object.assign(todo, dto);
34
+ return this.todos.save(todo);
35
+ }
36
+
37
+ async remove(id: string): Promise<void> {
38
+ const todo = await this.findOne(id);
39
+ await this.todos.remove(todo);
40
+ }
41
+ }
@@ -0,0 +1,23 @@
1
+ import { Test } from "@nestjs/testing";
2
+ import type { INestApplication } from "@nestjs/common";
3
+ import request from "supertest";
4
+ import { HealthModule } from "../src/health/health.module";
5
+
6
+ describe("Health (e2e)", () => {
7
+ let app: INestApplication;
8
+
9
+ beforeAll(async () => {
10
+ const moduleRef = await Test.createTestingModule({ imports: [HealthModule] }).compile();
11
+ app = moduleRef.createNestApplication();
12
+ await app.init();
13
+ });
14
+
15
+ afterAll(async () => {
16
+ await app.close();
17
+ });
18
+
19
+ it("GET /health returns ok", async () => {
20
+ const res = await request(app.getHttpServer()).get("/health").expect(200);
21
+ expect(res.body.status).toBe("ok");
22
+ });
23
+ });
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "CommonJS",
4
+ "target": "ES2022",
5
+ "moduleResolution": "Node",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "declaration": false,
9
+ "emitDecoratorMetadata": true,
10
+ "experimentalDecorators": true,
11
+ "strict": true,
12
+ "noUnusedLocals": true,
13
+ "noUnusedParameters": true,
14
+ "noImplicitReturns": true,
15
+ "esModuleInterop": true,
16
+ "skipLibCheck": true,
17
+ "forceConsistentCasingInFileNames": true
18
+ },
19
+ "include": ["src/**/*.ts"],
20
+ "exclude": ["node_modules", "dist", "test"]
21
+ }
@@ -0,0 +1,22 @@
1
+ # syntax=docker/dockerfile:1
2
+ FROM node:20-alpine AS deps
3
+ WORKDIR /app
4
+ COPY package.json ./
5
+ RUN npm install --no-audit --no-fund
6
+
7
+ FROM node:20-alpine AS build
8
+ WORKDIR /app
9
+ COPY --from=deps /app/node_modules ./node_modules
10
+ COPY . .
11
+ RUN npm run build
12
+
13
+ FROM node:20-alpine AS runtime
14
+ WORKDIR /app
15
+ ENV NODE_ENV=production
16
+ RUN addgroup -S app && adduser -S app -G app
17
+ COPY --from=build /app/build ./build
18
+ COPY --from=build /app/node_modules ./node_modules
19
+ COPY package.json ./
20
+ USER app
21
+ EXPOSE 3000
22
+ CMD ["node", "build"]
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "https://shadcn-svelte.com/schema.json",
3
+ "style": "nova",
4
+ "tailwind": {
5
+ "css": "src/app.css",
6
+ "baseColor": "zinc"
7
+ },
8
+ "aliases": {
9
+ "components": "$lib/components",
10
+ "ui": "$lib/components/ui",
11
+ "utils": "$lib/utils"
12
+ },
13
+ "typescript": true,
14
+ "registry": "https://shadcn-svelte.com/registry"
15
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "{{projectName}}-web",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite dev --port 5173",
8
+ "build": "vite build",
9
+ "preview": "vite preview",
10
+ "lint": "svelte-check --tsconfig ./tsconfig.json",
11
+ "test": "echo \"add Playwright tests here\" && exit 0"
12
+ },
13
+ "dependencies": {
14
+ "mode-watcher": "^0.5.0",
15
+ "bits-ui": "^2.18.1",
16
+ "clsx": "^2.1.1",
17
+ "tailwind-merge": "^3.6.0",
18
+ "tailwind-variants": "^3.2.2",
19
+ "@lucide/svelte": "^1.23.0",
20
+ "@internationalized/date": "^3.12.2"
21
+ },
22
+ "devDependencies": {
23
+ "@sveltejs/adapter-node": "^5.2.0",
24
+ "@sveltejs/kit": "^2.8.0",
25
+ "@sveltejs/vite-plugin-svelte": "^4.0.0",
26
+ "@tailwindcss/vite": "^4.0.0",
27
+ "svelte": "^5.1.0",
28
+ "svelte-check": "^4.0.0",
29
+ "tailwindcss": "^4.0.0",
30
+ "typesafe-i18n": "^5.26.2",
31
+ "typescript": "^5.6.3",
32
+ "vite": "^5.4.0",
33
+ "tw-animate-css": "^1.4.0"
34
+ }
35
+ }
@@ -0,0 +1,81 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+
4
+ @custom-variant dark (&:is(.dark *));
5
+
6
+ :root {
7
+ --radius: 0.625rem;
8
+ --background: oklch(1 0 0);
9
+ --foreground: oklch(0.141 0.005 285.823);
10
+ --card: oklch(1 0 0);
11
+ --card-foreground: oklch(0.141 0.005 285.823);
12
+ --popover: oklch(1 0 0);
13
+ --popover-foreground: oklch(0.141 0.005 285.823);
14
+ --primary: oklch(0.21 0.006 285.885);
15
+ --primary-foreground: oklch(0.985 0 0);
16
+ --secondary: oklch(0.967 0.001 286.375);
17
+ --secondary-foreground: oklch(0.21 0.006 285.885);
18
+ --muted: oklch(0.967 0.001 286.375);
19
+ --muted-foreground: oklch(0.552 0.016 285.938);
20
+ --accent: oklch(0.967 0.001 286.375);
21
+ --accent-foreground: oklch(0.21 0.006 285.885);
22
+ --destructive: oklch(0.577 0.245 27.325);
23
+ --border: oklch(0.92 0.004 286.32);
24
+ --input: oklch(0.92 0.004 286.32);
25
+ --ring: oklch(0.705 0.015 286.067);
26
+ }
27
+
28
+ .dark {
29
+ --background: oklch(0.141 0.005 285.823);
30
+ --foreground: oklch(0.985 0 0);
31
+ --card: oklch(0.21 0.006 285.885);
32
+ --card-foreground: oklch(0.985 0 0);
33
+ --popover: oklch(0.21 0.006 285.885);
34
+ --popover-foreground: oklch(0.985 0 0);
35
+ --primary: oklch(0.92 0.004 286.32);
36
+ --primary-foreground: oklch(0.21 0.006 285.885);
37
+ --secondary: oklch(0.274 0.006 286.033);
38
+ --secondary-foreground: oklch(0.985 0 0);
39
+ --muted: oklch(0.274 0.006 286.033);
40
+ --muted-foreground: oklch(0.705 0.015 286.067);
41
+ --accent: oklch(0.274 0.006 286.033);
42
+ --accent-foreground: oklch(0.985 0 0);
43
+ --destructive: oklch(0.704 0.191 22.216);
44
+ --border: oklch(1 0 0 / 10%);
45
+ --input: oklch(1 0 0 / 15%);
46
+ --ring: oklch(0.552 0.016 285.938);
47
+ }
48
+
49
+ @theme inline {
50
+ --radius-sm: calc(var(--radius) - 4px);
51
+ --radius-md: calc(var(--radius) - 2px);
52
+ --radius-lg: var(--radius);
53
+ --radius-xl: calc(var(--radius) + 4px);
54
+ --color-background: var(--background);
55
+ --color-foreground: var(--foreground);
56
+ --color-card: var(--card);
57
+ --color-card-foreground: var(--card-foreground);
58
+ --color-popover: var(--popover);
59
+ --color-popover-foreground: var(--popover-foreground);
60
+ --color-primary: var(--primary);
61
+ --color-primary-foreground: var(--primary-foreground);
62
+ --color-secondary: var(--secondary);
63
+ --color-secondary-foreground: var(--secondary-foreground);
64
+ --color-muted: var(--muted);
65
+ --color-muted-foreground: var(--muted-foreground);
66
+ --color-accent: var(--accent);
67
+ --color-accent-foreground: var(--accent-foreground);
68
+ --color-destructive: var(--destructive);
69
+ --color-border: var(--border);
70
+ --color-input: var(--input);
71
+ --color-ring: var(--ring);
72
+ }
73
+
74
+ @layer base {
75
+ * {
76
+ @apply border-border outline-ring/50;
77
+ }
78
+ body {
79
+ @apply bg-background text-foreground;
80
+ }
81
+ }
@@ -0,0 +1,11 @@
1
+ // See https://svelte.dev/docs/kit/types#app
2
+ declare global {
3
+ namespace App {
4
+ // interface Error {}
5
+ // interface Locals {}
6
+ // interface PageData {}
7
+ // interface Platform {}
8
+ }
9
+ }
10
+
11
+ export {};
@@ -0,0 +1,11 @@
1
+ <!doctype html>
2
+ <html lang="en" class="h-full">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ %sveltekit.head%
7
+ </head>
8
+ <body data-sveltekit-preload-data="hover" class="h-full">
9
+ <div style="display: contents">%sveltekit.body%</div>
10
+ </body>
11
+ </html>
@@ -0,0 +1,82 @@
1
+ <script lang="ts" module>
2
+ import { cn, type WithElementRef } from "$lib/utils.js";
3
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
4
+ import { type VariantProps, tv } from "tailwind-variants";
5
+
6
+ export const buttonVariants = tv({
7
+ base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 active:not-aria-[haspopup]:translate-y-px aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap transition-all outline-none select-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
8
+ variants: {
9
+ variant: {
10
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
11
+ outline: "border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground",
12
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
13
+ ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
14
+ destructive: "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
15
+ link: "text-primary underline-offset-4 hover:underline",
16
+ },
17
+ size: {
18
+ default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
19
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
20
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
21
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
22
+ icon: "size-8",
23
+ "icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
24
+ "icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
25
+ "icon-lg": "size-9",
26
+ },
27
+ },
28
+ defaultVariants: {
29
+ variant: "default",
30
+ size: "default",
31
+ },
32
+ });
33
+
34
+ export type ButtonVariant = VariantProps<typeof buttonVariants>["variant"];
35
+ export type ButtonSize = VariantProps<typeof buttonVariants>["size"];
36
+
37
+ export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
38
+ WithElementRef<HTMLAnchorAttributes> & {
39
+ variant?: ButtonVariant;
40
+ size?: ButtonSize;
41
+ };
42
+ </script>
43
+
44
+ <script lang="ts">
45
+ let {
46
+ class: className,
47
+ variant = "default",
48
+ size = "default",
49
+ ref = $bindable(null),
50
+ href = undefined,
51
+ type = "button",
52
+ disabled,
53
+ children,
54
+ ...restProps
55
+ }: ButtonProps = $props();
56
+ </script>
57
+
58
+ {#if href}
59
+ <a
60
+ bind:this={ref}
61
+ data-slot="button"
62
+ class={cn(buttonVariants({ variant, size }), className)}
63
+ href={disabled ? undefined : href}
64
+ aria-disabled={disabled}
65
+ role={disabled ? "link" : undefined}
66
+ tabindex={disabled ? -1 : undefined}
67
+ {...restProps}
68
+ >
69
+ {@render children?.()}
70
+ </a>
71
+ {:else}
72
+ <button
73
+ bind:this={ref}
74
+ data-slot="button"
75
+ class={cn(buttonVariants({ variant, size }), className)}
76
+ {type}
77
+ {disabled}
78
+ {...restProps}
79
+ >
80
+ {@render children?.()}
81
+ </button>
82
+ {/if}
@@ -0,0 +1,17 @@
1
+ import Root, {
2
+ type ButtonProps,
3
+ type ButtonSize,
4
+ type ButtonVariant,
5
+ buttonVariants,
6
+ } from "./button.svelte";
7
+
8
+ export {
9
+ Root,
10
+ type ButtonProps as Props,
11
+ //
12
+ Root as Button,
13
+ buttonVariants,
14
+ type ButtonProps,
15
+ type ButtonSize,
16
+ type ButtonVariant,
17
+ };
@@ -0,0 +1,23 @@
1
+ <script lang="ts">
2
+ import { cn, type WithElementRef } from "$lib/utils.js";
3
+ import type { HTMLAttributes } from "svelte/elements";
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ children,
9
+ ...restProps
10
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+ </script>
12
+
13
+ <div
14
+ bind:this={ref}
15
+ data-slot="card-action"
16
+ class={cn(
17
+ "cn-card-action col-start-2 row-span-2 row-start-1 self-start justify-self-end",
18
+ className
19
+ )}
20
+ {...restProps}
21
+ >
22
+ {@render children?.()}
23
+ </div>
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ import { cn, type WithElementRef } from "$lib/utils.js";
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ children,
9
+ ...restProps
10
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+ </script>
12
+
13
+ <div
14
+ bind:this={ref}
15
+ data-slot="card-content"
16
+ class={cn("px-4 group-data-[size=sm]/card:px-3", className)}
17
+ {...restProps}
18
+ >
19
+ {@render children?.()}
20
+ </div>
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ import { cn, type WithElementRef } from "$lib/utils.js";
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ children,
9
+ ...restProps
10
+ }: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
11
+ </script>
12
+
13
+ <p
14
+ bind:this={ref}
15
+ data-slot="card-description"
16
+ class={cn("text-muted-foreground text-sm", className)}
17
+ {...restProps}
18
+ >
19
+ {@render children?.()}
20
+ </p>
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import { cn, type WithElementRef } from "$lib/utils.js";
3
+ import type { HTMLAttributes } from "svelte/elements";
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ children,
9
+ ...restProps
10
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+ </script>
12
+
13
+ <div
14
+ bind:this={ref}
15
+ data-slot="card-footer"
16
+ class={cn("bg-muted/50 rounded-b-xl border-t p-4 group-data-[size=sm]/card:p-3 flex items-center", className)}
17
+ {...restProps}
18
+ >
19
+ {@render children?.()}
20
+ </div>
@@ -0,0 +1,23 @@
1
+ <script lang="ts">
2
+ import { cn, type WithElementRef } from "$lib/utils.js";
3
+ import type { HTMLAttributes } from "svelte/elements";
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ children,
9
+ ...restProps
10
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+ </script>
12
+
13
+ <div
14
+ bind:this={ref}
15
+ data-slot="card-header"
16
+ class={cn(
17
+ "gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]",
18
+ className
19
+ )}
20
+ {...restProps}
21
+ >
22
+ {@render children?.()}
23
+ </div>
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ import { cn, type WithElementRef } from "$lib/utils.js";
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ children,
9
+ ...restProps
10
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+ </script>
12
+
13
+ <div
14
+ bind:this={ref}
15
+ data-slot="card-title"
16
+ class={cn("text-base leading-snug font-medium group-data-[size=sm]/card:text-sm", className)}
17
+ {...restProps}
18
+ >
19
+ {@render children?.()}
20
+ </div>
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ import { cn, type WithElementRef } from "$lib/utils.js";
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ children,
9
+ size = "default",
10
+ ...restProps
11
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> & { size?: "default" | "sm" } = $props();
12
+ </script>
13
+
14
+ <div
15
+ bind:this={ref}
16
+ data-slot="card"
17
+ data-size={size}
18
+ class={cn("ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-xl py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col", className)}
19
+ {...restProps}
20
+ >
21
+ {@render children?.()}
22
+ </div>
@@ -0,0 +1,25 @@
1
+ import Root from "./card.svelte";
2
+ import Content from "./card-content.svelte";
3
+ import Description from "./card-description.svelte";
4
+ import Footer from "./card-footer.svelte";
5
+ import Header from "./card-header.svelte";
6
+ import Title from "./card-title.svelte";
7
+ import Action from "./card-action.svelte";
8
+
9
+ export {
10
+ Root,
11
+ Content,
12
+ Description,
13
+ Footer,
14
+ Header,
15
+ Title,
16
+ Action,
17
+ //
18
+ Root as Card,
19
+ Content as CardContent,
20
+ Description as CardDescription,
21
+ Footer as CardFooter,
22
+ Header as CardHeader,
23
+ Title as CardTitle,
24
+ Action as CardAction,
25
+ };
@@ -0,0 +1,39 @@
1
+ <script lang="ts">
2
+ import { Checkbox as CheckboxPrimitive } from "bits-ui";
3
+ import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
4
+ import CheckIcon from '@lucide/svelte/icons/check';
5
+ import MinusIcon from '@lucide/svelte/icons/minus';
6
+
7
+ let {
8
+ ref = $bindable(null),
9
+ checked = $bindable(false),
10
+ indeterminate = $bindable(false),
11
+ class: className,
12
+ ...restProps
13
+ }: WithoutChildrenOrChild<CheckboxPrimitive.RootProps> = $props();
14
+ </script>
15
+
16
+ <CheckboxPrimitive.Root
17
+ bind:ref
18
+ data-slot="checkbox"
19
+ class={cn(
20
+ "border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-[4px] border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-3 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50",
21
+ className
22
+ )}
23
+ bind:checked
24
+ bind:indeterminate
25
+ {...restProps}
26
+ >
27
+ {#snippet children({ checked, indeterminate })}
28
+ <div
29
+ data-slot="checkbox-indicator"
30
+ class="[&>svg]:size-3.5 grid place-content-center text-current transition-none"
31
+ >
32
+ {#if checked}
33
+ <CheckIcon />
34
+ {:else if indeterminate}
35
+ <MinusIcon />
36
+ {/if}
37
+ </div>
38
+ {/snippet}
39
+ </CheckboxPrimitive.Root>
@@ -0,0 +1,6 @@
1
+ import Root from "./checkbox.svelte";
2
+ export {
3
+ Root,
4
+ //
5
+ Root as Checkbox,
6
+ };
@@ -0,0 +1,7 @@
1
+ import Root from "./input.svelte";
2
+
3
+ export {
4
+ Root,
5
+ //
6
+ Root as Input,
7
+ };