create-nala 3.0.3 → 3.1.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 (182) hide show
  1. package/package.json +6 -6
  2. package/template/.agents/skills/nala-project/SKILL.md +217 -70
  3. package/template/AGENTS.md +1 -1
  4. package/template/CLAUDE.md +27 -0
  5. package/template/GEMINI.md +27 -0
  6. package/template/README.md +3 -1
  7. package/template/package.json +1 -1
  8. package/template/src/App.vue +1 -1
  9. package/template/src/assets/fonts/InterVariable.woff2 +0 -0
  10. package/template/src/assets/fonts/inter-v20-latin-300.woff2 +0 -0
  11. package/template/src/assets/fonts/inter-v20-latin-500.woff2 +0 -0
  12. package/template/src/assets/fonts/inter-v20-latin-600.woff2 +0 -0
  13. package/template/src/assets/fonts/inter-v20-latin-700.woff2 +0 -0
  14. package/template/src/assets/fonts/inter-v20-latin-regular.woff2 +0 -0
  15. package/template/src/assets/hero.png +0 -0
  16. package/template/src/assets/vite.svg +1 -0
  17. package/template/src/assets/vue.svg +1 -0
  18. package/template/src/components/ui/alert/Alert.vue +8 -8
  19. package/template/src/components/ui/alert/AlertDescription.vue +5 -5
  20. package/template/src/components/ui/alert/AlertTitle.vue +5 -5
  21. package/template/src/components/ui/alert-dialog/AlertDialog.vue +6 -6
  22. package/template/src/components/ui/alert-dialog/AlertDialogAction.vue +9 -9
  23. package/template/src/components/ui/alert-dialog/AlertDialogCancel.vue +9 -9
  24. package/template/src/components/ui/alert-dialog/AlertDialogContent.vue +20 -20
  25. package/template/src/components/ui/alert-dialog/AlertDialogDescription.vue +10 -10
  26. package/template/src/components/ui/alert-dialog/AlertDialogFooter.vue +5 -5
  27. package/template/src/components/ui/alert-dialog/AlertDialogHeader.vue +5 -5
  28. package/template/src/components/ui/alert-dialog/AlertDialogTitle.vue +8 -8
  29. package/template/src/components/ui/alert-dialog/AlertDialogTrigger.vue +3 -3
  30. package/template/src/components/ui/alert-dialog/index.ts +8 -8
  31. package/template/src/components/ui/avatar/AvatarFallback.vue +8 -8
  32. package/template/src/components/ui/avatar/AvatarImage.vue +3 -3
  33. package/template/src/components/ui/breadcrumb/Breadcrumb.vue +4 -4
  34. package/template/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +6 -6
  35. package/template/src/components/ui/breadcrumb/BreadcrumbItem.vue +5 -5
  36. package/template/src/components/ui/breadcrumb/BreadcrumbLink.vue +7 -7
  37. package/template/src/components/ui/breadcrumb/BreadcrumbList.vue +5 -5
  38. package/template/src/components/ui/breadcrumb/BreadcrumbPage.vue +5 -5
  39. package/template/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +6 -6
  40. package/template/src/components/ui/breadcrumb/index.ts +6 -6
  41. package/template/src/components/ui/button/Button.vue +15 -15
  42. package/template/src/components/ui/card/CardAction.vue +5 -5
  43. package/template/src/components/ui/card/CardContent.vue +5 -5
  44. package/template/src/components/ui/card/CardDescription.vue +5 -5
  45. package/template/src/components/ui/card/CardFooter.vue +5 -5
  46. package/template/src/components/ui/card/CardTitle.vue +5 -5
  47. package/template/src/components/ui/card/index.ts +6 -6
  48. package/template/src/components/ui/command/Command.vue +75 -75
  49. package/template/src/components/ui/command/CommandDialog.vue +14 -14
  50. package/template/src/components/ui/command/CommandEmpty.vue +14 -14
  51. package/template/src/components/ui/command/CommandGroup.vue +27 -27
  52. package/template/src/components/ui/command/CommandInput.vue +20 -20
  53. package/template/src/components/ui/command/CommandItem.vue +57 -57
  54. package/template/src/components/ui/command/CommandList.vue +10 -10
  55. package/template/src/components/ui/command/CommandSeparator.vue +8 -8
  56. package/template/src/components/ui/command/CommandShortcut.vue +5 -5
  57. package/template/src/components/ui/command/index.ts +24 -24
  58. package/template/src/components/ui/dialog/Dialog.vue +6 -6
  59. package/template/src/components/ui/dialog/DialogClose.vue +3 -3
  60. package/template/src/components/ui/dialog/DialogContent.vue +24 -24
  61. package/template/src/components/ui/dialog/DialogDescription.vue +10 -10
  62. package/template/src/components/ui/dialog/DialogFooter.vue +10 -10
  63. package/template/src/components/ui/dialog/DialogHeader.vue +5 -5
  64. package/template/src/components/ui/dialog/DialogOverlay.vue +8 -8
  65. package/template/src/components/ui/dialog/DialogScrollContent.vue +22 -22
  66. package/template/src/components/ui/dialog/DialogTitle.vue +10 -10
  67. package/template/src/components/ui/dialog/DialogTrigger.vue +3 -3
  68. package/template/src/components/ui/dialog/index.ts +9 -9
  69. package/template/src/components/ui/dropdown-menu/DropdownMenu.vue +6 -6
  70. package/template/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +16 -16
  71. package/template/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +3 -3
  72. package/template/src/components/ui/dropdown-menu/DropdownMenuItem.vue +16 -16
  73. package/template/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +9 -9
  74. package/template/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +9 -9
  75. package/template/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +17 -17
  76. package/template/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +12 -12
  77. package/template/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +5 -5
  78. package/template/src/components/ui/dropdown-menu/DropdownMenuSub.vue +9 -9
  79. package/template/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +14 -14
  80. package/template/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +13 -13
  81. package/template/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +5 -5
  82. package/template/src/components/ui/dropdown-menu/index.ts +15 -15
  83. package/template/src/components/ui/form/FormControl.vue +3 -3
  84. package/template/src/components/ui/form/FormDescription.vue +8 -8
  85. package/template/src/components/ui/form/FormItem.vue +11 -11
  86. package/template/src/components/ui/form/FormLabel.vue +8 -8
  87. package/template/src/components/ui/form/FormMessage.vue +10 -10
  88. package/template/src/components/ui/form/index.ts +6 -6
  89. package/template/src/components/ui/form/injectionKeys.ts +3 -3
  90. package/template/src/components/ui/form/useFormField.ts +29 -29
  91. package/template/src/components/ui/input/Input.vue +17 -17
  92. package/template/src/components/ui/label/Label.vue +8 -8
  93. package/template/src/components/ui/pagination/Pagination.vue +12 -12
  94. package/template/src/components/ui/pagination/PaginationContent.vue +8 -8
  95. package/template/src/components/ui/pagination/PaginationEllipsis.vue +9 -9
  96. package/template/src/components/ui/pagination/PaginationFirst.vue +17 -17
  97. package/template/src/components/ui/pagination/PaginationItem.vue +16 -16
  98. package/template/src/components/ui/pagination/PaginationLast.vue +17 -17
  99. package/template/src/components/ui/pagination/PaginationNext.vue +17 -17
  100. package/template/src/components/ui/pagination/PaginationPrevious.vue +17 -17
  101. package/template/src/components/ui/pagination/index.ts +7 -7
  102. package/template/src/components/ui/popover/Popover.vue +6 -6
  103. package/template/src/components/ui/popover/PopoverAnchor.vue +3 -3
  104. package/template/src/components/ui/popover/PopoverContent.vue +25 -25
  105. package/template/src/components/ui/popover/PopoverTrigger.vue +3 -3
  106. package/template/src/components/ui/popover/index.ts +3 -3
  107. package/template/src/components/ui/select/Select.vue +6 -6
  108. package/template/src/components/ui/select/SelectContent.vue +26 -26
  109. package/template/src/components/ui/select/SelectGroup.vue +3 -3
  110. package/template/src/components/ui/select/SelectItem.vue +16 -16
  111. package/template/src/components/ui/select/SelectItemText.vue +3 -3
  112. package/template/src/components/ui/select/SelectLabel.vue +5 -5
  113. package/template/src/components/ui/select/SelectScrollDownButton.vue +11 -11
  114. package/template/src/components/ui/select/SelectScrollUpButton.vue +11 -11
  115. package/template/src/components/ui/select/SelectSeparator.vue +8 -8
  116. package/template/src/components/ui/select/SelectTrigger.vue +13 -13
  117. package/template/src/components/ui/select/SelectValue.vue +3 -3
  118. package/template/src/components/ui/select/index.ts +10 -10
  119. package/template/src/components/ui/separator/Separator.vue +13 -13
  120. package/template/src/components/ui/sheet/Sheet.vue +6 -6
  121. package/template/src/components/ui/sheet/SheetClose.vue +3 -3
  122. package/template/src/components/ui/sheet/SheetContent.vue +29 -29
  123. package/template/src/components/ui/sheet/SheetDescription.vue +8 -8
  124. package/template/src/components/ui/sheet/SheetFooter.vue +3 -3
  125. package/template/src/components/ui/sheet/SheetHeader.vue +3 -3
  126. package/template/src/components/ui/sheet/SheetOverlay.vue +8 -8
  127. package/template/src/components/ui/sheet/SheetTitle.vue +8 -8
  128. package/template/src/components/ui/sheet/SheetTrigger.vue +3 -3
  129. package/template/src/components/ui/sheet/index.ts +7 -7
  130. package/template/src/components/ui/sidebar/Sidebar.vue +18 -18
  131. package/template/src/components/ui/sidebar/SidebarContent.vue +6 -6
  132. package/template/src/components/ui/sidebar/SidebarControl.vue +0 -3
  133. package/template/src/components/ui/sidebar/SidebarFooter.vue +5 -5
  134. package/template/src/components/ui/sidebar/SidebarGroup.vue +5 -5
  135. package/template/src/components/ui/sidebar/SidebarGroupAction.vue +7 -7
  136. package/template/src/components/ui/sidebar/SidebarGroupContent.vue +5 -5
  137. package/template/src/components/ui/sidebar/SidebarGroupLabel.vue +7 -7
  138. package/template/src/components/ui/sidebar/SidebarHeader.vue +5 -5
  139. package/template/src/components/ui/sidebar/SidebarInput.vue +6 -6
  140. package/template/src/components/ui/sidebar/SidebarInset.vue +5 -5
  141. package/template/src/components/ui/sidebar/SidebarMenu.vue +5 -5
  142. package/template/src/components/ui/sidebar/SidebarMenuAction.vue +10 -10
  143. package/template/src/components/ui/sidebar/SidebarMenuBadge.vue +5 -5
  144. package/template/src/components/ui/sidebar/SidebarMenuButton.vue +21 -21
  145. package/template/src/components/ui/sidebar/SidebarMenuButtonChild.vue +18 -18
  146. package/template/src/components/ui/sidebar/SidebarMenuItem.vue +5 -5
  147. package/template/src/components/ui/sidebar/SidebarMenuSkeleton.vue +12 -12
  148. package/template/src/components/ui/sidebar/SidebarMenuSub.vue +5 -5
  149. package/template/src/components/ui/sidebar/SidebarMenuSubButton.vue +12 -12
  150. package/template/src/components/ui/sidebar/SidebarMenuSubItem.vue +5 -5
  151. package/template/src/components/ui/sidebar/SidebarProvider.vue +4 -8
  152. package/template/src/components/ui/sidebar/SidebarRail.vue +8 -8
  153. package/template/src/components/ui/sidebar/SidebarSeparator.vue +6 -6
  154. package/template/src/components/ui/sidebar/SidebarTrigger.vue +10 -10
  155. package/template/src/components/ui/sidebar/utils.ts +1 -1
  156. package/template/src/components/ui/skeleton/Skeleton.vue +7 -7
  157. package/template/src/components/ui/sonner/Sonner.vue +47 -17
  158. package/template/src/components/ui/switch/Switch.vue +16 -16
  159. package/template/src/components/ui/table/Table.vue +5 -5
  160. package/template/src/components/ui/table/TableBody.vue +5 -5
  161. package/template/src/components/ui/table/TableCaption.vue +5 -5
  162. package/template/src/components/ui/table/TableCell.vue +5 -5
  163. package/template/src/components/ui/table/TableEmpty.vue +13 -13
  164. package/template/src/components/ui/table/TableFooter.vue +5 -5
  165. package/template/src/components/ui/table/TableHead.vue +5 -5
  166. package/template/src/components/ui/table/TableHeader.vue +5 -5
  167. package/template/src/components/ui/table/TableRow.vue +5 -5
  168. package/template/src/components/ui/table/index.ts +8 -8
  169. package/template/src/components/ui/table/utils.ts +9 -9
  170. package/template/src/components/ui/tabs/Tabs.vue +10 -10
  171. package/template/src/components/ui/tabs/TabsContent.vue +8 -8
  172. package/template/src/components/ui/tabs/TabsList.vue +8 -8
  173. package/template/src/components/ui/tabs/TabsTrigger.vue +10 -10
  174. package/template/src/components/ui/tabs/index.ts +3 -3
  175. package/template/src/components/ui/textarea/Textarea.vue +17 -17
  176. package/template/src/components/ui/tooltip/Tooltip.vue +6 -6
  177. package/template/src/components/ui/tooltip/TooltipContent.vue +17 -17
  178. package/template/src/components/ui/tooltip/TooltipProvider.vue +5 -5
  179. package/template/src/components/ui/tooltip/TooltipTrigger.vue +3 -3
  180. package/template/src/components/ui/tooltip/index.ts +3 -3
  181. package/template/src/lib/utils.ts +6 -6
  182. package/template/tsconfig.app.json +17 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nala",
3
- "version": "3.0.3",
3
+ "version": "3.1.0",
4
4
  "description": "Scaffolding CLI tool for Nala Admin Dashboard Template",
5
5
  "author": "candrasp",
6
6
  "license": "MIT",
@@ -32,6 +32,10 @@
32
32
  "url": "https://github.com/candrasp/Nala.git",
33
33
  "directory": "packages/create-nala"
34
34
  },
35
+ "scripts": {
36
+ "build": "tsup",
37
+ "dev": "tsup --watch"
38
+ },
35
39
  "dependencies": {
36
40
  "@clack/prompts": "^0.9.1",
37
41
  "kolorist": "^1.8.0"
@@ -40,9 +44,5 @@
40
44
  "@types/node": "^24.13.3",
41
45
  "tsup": "^8.4.0",
42
46
  "typescript": "~6.0.2"
43
- },
44
- "scripts": {
45
- "build": "tsup",
46
- "dev": "tsup --watch"
47
47
  }
48
- }
48
+ }
@@ -1,14 +1,59 @@
1
1
  ---
2
2
  name: nala-project
3
3
  description: >
4
- Skill for the Nala Admin Dashboard Project - Single SPA application built with Vue 3,
5
- Vite, TypeScript, Tailwind CSS v4, Reka UI (shadcn-vue), Pinia, and Axios.
6
- Activates when building views, components, stores, API services, or scaffolding features.
4
+ Skill for the Nala Admin Dashboard Project - a starter SPA template scaffolded with `pnpm create nala`,
5
+ built with Vue 3, Vite, TypeScript, Tailwind CSS v4, Reka UI (shadcn-vue), Unovis charts, Pinia, and Axios.
6
+ Activates when building views, components, stores, API services, or scaffolding new features.
7
7
  ---
8
8
 
9
- # Nala Project Skill (Starter Edition)
9
+ # Nala Project Skill (Starter Template Edition)
10
10
 
11
- You are an expert frontend engineer building features for this **Nala Admin Dashboard** application. Follow these instructions strictly to ensure clean architecture, design consistency, and zero UI regressions.
11
+ You are an expert frontend engineer building features for this **Nala Admin Dashboard** application — a clean, minimal starter template scaffolded via `pnpm create nala`. Follow these instructions strictly to ensure clean architecture, design consistency, and zero UI regressions.
12
+
13
+ > **⚠️ Important Context:** This is the **Starter Template**, NOT the full Nala showcase monorepo.
14
+ > There are no showcase views, no ThemeCustomizer, no `CodePreview` component, and no demo-only stores like `notification`, `activity`, `billing`, or `role`. Reference the Nala showcase (`packages/showcase/`) as inspiration only.
15
+
16
+ ---
17
+
18
+ ## 🏗️ Project Structure
19
+
20
+ ```
21
+ src/
22
+ ├── components/
23
+ │ ├── AppLogo.vue ← Auto-imported brand logo component
24
+ │ ├── EmptyState.vue ← Auto-imported zero-data empty state component
25
+ │ ├── PageHeader.vue ← Auto-imported standard page top header
26
+ │ ├── layout/ ← AdminLayout sub-components (Navbar, Sidebar, etc.)
27
+ │ └── ui/ ← 45 Reka UI primitives (all auto-imported)
28
+ ├── composables/
29
+ │ ├── useFormatter.ts ← Auto-imported: currency, date, number, relative time formatting
30
+ │ └── useThemeConfig.ts ← Auto-imported: layout mode, border radius, accent color
31
+ ├── layouts/
32
+ │ ├── AdminLayout.vue ← Main dashboard shell (sidebar + navbar + content slot)
33
+ │ └── AuthLayout.vue ← Centered auth card layout
34
+ ├── lib/
35
+ │ ├── axios.ts ← Pre-configured Axios instance with interceptors
36
+ │ ├── formatters.ts ← Core formatter functions (used by useFormatter)
37
+ │ ├── loading-bar.ts ← Global loading bar singleton
38
+ │ ├── utils.ts ← cn() class merging utility
39
+ │ └── validation.ts ← Shared zod validation helpers
40
+ ├── router/
41
+ │ └── index.ts ← Vue Router with auth guard scaffold (commented, ready to enable)
42
+ ├── services/
43
+ │ ├── auth.service.ts ← Auth API methods (login, logout, refresh token)
44
+ │ ├── user.service.ts ← User CRUD API methods
45
+ │ ├── types.ts ← Shared API response types (ApiResponse<T>)
46
+ │ └── index.ts ← Service re-exports
47
+ ├── stores/
48
+ │ └── auth.ts ← Auth Pinia store (isAuthenticated, currentUser, login/logout)
49
+ └── views/
50
+ ├── _starter/
51
+ │ └── BlankView.vue ← Scaffolding starting point for new pages
52
+ ├── auth/ ← Full auth suite (Login, Register, Forgot/Reset Password, OTP, etc.)
53
+ ├── dashboard/
54
+ │ └── IndexView.vue ← Minimal dashboard with KPI stat cards (your starting point)
55
+ └── errors/ ← 404, 500, 403, Maintenance, Coming Soon pages
56
+ ```
12
57
 
13
58
  ---
14
59
 
@@ -19,12 +64,13 @@ You are an expert frontend engineer building features for this **Nala Admin Dash
19
64
  | **Framework** | Vue 3 (Composition API) | Always use `<script setup lang="ts">` |
20
65
  | **Build Tool** | Vite 8 (`@vitejs/plugin-vue`) | Super-fast HMR & production bundler |
21
66
  | **Styling** | Tailwind CSS v4 (`@tailwindcss/vite`) + `tw-animate-css` | OKLCH color tokens in `src/style.css` |
22
- | **UI Primitives** | `reka-ui` + shadcn-vue (New York style) | 34+ primitive components in `src/components/ui/` |
67
+ | **UI Primitives** | `reka-ui` + shadcn-vue (New York style) | 45 primitive components in `src/components/ui/` |
68
+ | **Charts** | `@unovis/ts` + `@unovis/vue` | SVG chart primitives: `AreaChart`, `BarChart`, `LineChart`, `DonutChart` |
23
69
  | **Data Table** | `@tanstack/vue-table` | Headless table logic with sorting & pagination |
24
70
  | **Form & Validation** | `vee-validate` + `@vee-validate/zod` + `zod` | Strongly-typed validation schemas |
25
71
  | **Icons** | `@lucide/vue` | Must be imported explicitly (`import { Plus } from '@lucide/vue'`) |
26
72
  | **State Management** | Pinia | Setup Stores pattern (`defineStore('name', () => { ... })`) |
27
- | **Routing** | Vue Router v5 | HTML5 history mode with route guards |
73
+ | **Routing** | Vue Router v5 | HTML5 history mode auth guard scaffold in `src/router/index.ts` (commented) |
28
74
  | **API Client** | Axios + Enterprise Interceptors | Silent Token Refresh, Global Loading Bar, Auto Error Toast |
29
75
  | **Notifications** | `vue-sonner` | Toast notifications via `toast.success()`, `toast.error()` |
30
76
  | **Language & Types** | TypeScript 6 + `vue-tsc` | Strict static typing, zero `any` |
@@ -35,32 +81,47 @@ You are an expert frontend engineer building features for this **Nala Admin Dash
35
81
 
36
82
  1. **Composition API Only:** Never use Options API — always use `<script setup lang="ts">`.
37
83
  2. **Strict TypeScript:** No `any` type — define explicit TypeScript interfaces for all props, emits, and API payloads.
38
- 3. **English Standard:** All user-facing UI text, form labels, placeholders, error messages, toast notifications, and in-code comments must be in **English**.
39
- 4. **Tailwind CSS v4 Strict Compliance:**
40
- - **Gradients:** ALWAYS use `bg-linear-to-r`, `bg-linear-to-b`, `bg-linear-to-tr` (NEVER use legacy v3 `bg-gradient-to-*`).
41
- - **Sizing Scale:** NEVER write arbitrary bracket sizing like `max-w-[170px]`, `w-[300px]`, or `p-[1px]`. ALWAYS use Tailwind v4 scale (`max-w-44`, `max-w-28`, `w-75`, `max-h-75`, `p-px`).
42
- - **Shadows:** Use `shadow-2xs`, `shadow-xs`, `shadow-sm`, `shadow-md`, `shadow-lg`.
43
- 5. **No Scoped CSS:** Use Tailwind utility classes. Do not write `<style scoped>`.
44
- 6. **Dialog Accessibility:** Every `DialogContent` MUST include `DialogTitle` and `DialogDescription` (use `sr-only` if visually hidden) to comply with Reka UI ARIA standards.
84
+ 3. **English Standard:** All user-facing UI text, form labels, placeholders, error messages, toast notifications, and in-code comments **MUST be in English**.
85
+ 4. **No Build Commands:** NEVER run `pnpm build` or `npm run build` autonomously. Build only on explicit user request.
86
+ 5. **No Automatic Tests:** NEVER run `vitest`, `pnpm test`, or `pnpm test:run` autonomously.
87
+ 6. **No Git Operations:** NEVER run `git add`, `git commit`, or `git push` autonomously.
88
+ 7. **No New Packages Without Confirmation:** Always ask in chat before running `pnpm add`.
89
+ 8. **No Scoped CSS:** Use Tailwind utility classes. Do not write `<style scoped>`.
90
+ 9. **Dialog Accessibility:** Every `DialogContent` MUST include `DialogTitle` and `DialogDescription` (use `sr-only` if visually hidden) to comply with Reka UI ARIA standards.
91
+ 10. **Tailwind CSS v4 Strict Syntax Compliance:**
92
+ - **Gradients:** ALWAYS use `bg-linear-to-r`, `bg-linear-to-b`, `bg-linear-to-tr` (NEVER `bg-gradient-to-*`).
93
+ - **Sizing:** NEVER use arbitrary brackets like `max-w-[170px]`, `w-[300px]`, `p-[1px]`. Use Tailwind v4 scale (`max-w-44`, `w-75`, `p-px`).
94
+ - **Shadows:** Use `shadow-2xs`, `shadow-xs`, `shadow-sm`, `shadow-md`, `shadow-lg`.
95
+ - **Viewport:** Use `min-h-dvh` / `h-dvh` instead of `min-h-screen` / `h-screen`.
96
+ - **Opacity:** Use integer percentage (`bg-primary/50`) NOT decimal (`bg-primary/0.5`).
45
97
 
46
98
  ---
47
99
 
48
100
  ## ⚡ Auto-Import Guide Matrix
49
101
 
50
- | Auto-Imported (No Import Needed) | Manual Import Required |
51
- |---|---|
52
- | Vue Reactivity (`ref`, `computed`, `watch`, `onMounted`, etc.) | Lucide Icons (`import { Plus, Search, Trash2 } from '@lucide/vue'`) |
53
- | Vue Router (`useRoute`, `useRouter`) | Toast Notifications (`import { toast } from '@/components/ui/sonner'`) |
54
- | VueUse (`useColorMode`, `useLocalStorage`, etc.) | Axios Client (`import { apiClient } from '@/lib/axios'`) |
55
- | Pinia (`defineStore`, `storeToRefs`) | Form Validation (`import { z } from 'zod'`, `import { useForm } from 'vee-validate'`) |
56
- | All UI Components (`<Button>`, `<Card>`, `<Dialog>`, `<Input>`, `<Table>`, `<PageHeader>`, etc.) | Class Merger (`import { cn } from '@/lib/utils'`) |
102
+ > The project uses `unplugin-auto-import` and `unplugin-vue-components`. Do NOT add manual imports for items marked ✅ AUTOMATIC.
103
+
104
+ | Category | Auto-Import Status | Usage |
105
+ |---|---|---|
106
+ | **Vue Reactivity** (`ref`, `computed`, `watch`, `onMounted`, `reactive`, etc.) | **AUTOMATIC** | Use directly: `const count = ref(0)` |
107
+ | **Vue Router** (`useRoute`, `useRouter`) | **AUTOMATIC** | Use directly: `const router = useRouter()` |
108
+ | **VueUse** (`useColorMode`, `useLocalStorage`, `useDebounceFn`, etc.) | **AUTOMATIC** | Use directly: `const mode = useColorMode()` |
109
+ | **Pinia** (`defineStore`, `storeToRefs`) | ✅ **AUTOMATIC** | Use directly: `defineStore(...)` |
110
+ | **All UI Components** (`Button`, `Card`, `Dialog`, `Input`, `InputGroup`, `Table`, `Tabs`, etc.) | ✅ **AUTOMATIC** | Use directly in template: `<Card>`, `<Button>`, `<InputGroup>` |
111
+ | **Shared Components** (`PageHeader`, `EmptyState`, `AppLogo`) | ✅ **AUTOMATIC** | Use directly: `<PageHeader>`, `<EmptyState>` |
112
+ | **Custom Composables** (`useFormatter`, `useThemeConfig`) | ✅ **AUTOMATIC** | Use directly: `const fmt = useFormatter()` |
113
+ | **Lucide Icons** (`Plus`, `Search`, `Trash2`, etc.) | ⚠️ **MANUAL IMPORT** | `import { Plus, Search } from '@lucide/vue'` |
114
+ | **Toast Notifications** (`toast`) | ⚠️ **MANUAL IMPORT** | `import { toast } from '@/components/ui/sonner'` |
115
+ | **HTTP API Client** (`apiClient`) | ⚠️ **MANUAL IMPORT** | `import { apiClient } from '@/lib/axios'` |
116
+ | **Class Merging Utility** (`cn`) | ⚠️ **MANUAL IMPORT** | `import { cn } from '@/lib/utils'` |
117
+ | **Form Validation** (`zod`, `toTypedSchema`, `useForm`) | ⚠️ **MANUAL IMPORT** | `import { z } from 'zod'`, `import { useForm } from 'vee-validate'` |
57
118
 
58
119
  ---
59
120
 
60
- ## 🎨 UI Design System & Component Blueprints
121
+ ## 🎨 UI Design System Key Patterns
61
122
 
62
- ### 1. Standard Page Header (`<PageHeader>`)
63
- Always use the standardized `<PageHeader>` component at the top of every view:
123
+ ### 1. Standard Page Header
124
+ Always use `<PageHeader>` at the top of every view — never build a custom header layout:
64
125
  ```vue
65
126
  <PageHeader
66
127
  title="Products"
@@ -75,32 +136,62 @@ Always use the standardized `<PageHeader>` component at the top of every view:
75
136
  </PageHeader>
76
137
  ```
77
138
 
78
- ### 2. Standard KPI Stats Cards Blueprint
79
- When building summary metrics / stats cards, follow this exact blueprint:
139
+ ### 2. Edge-to-Edge Card Layout (`<Card flush>` + `<CardHeader section>`)
140
+ - Use `<Card flush>` auto-applies `overflow-hidden py-0 gap-0`
141
+ - Use `<CardHeader section>` → auto-applies `p-6 border-b border-border bg-muted/10`
142
+ - Use `<CardContent class="p-0">` for table content (zero inner padding)
143
+
144
+ ```vue
145
+ <Card flush class="shadow-xs border">
146
+ <CardHeader section class="flex items-center justify-between gap-4">
147
+ <div>
148
+ <CardTitle class="text-base font-semibold">Title</CardTitle>
149
+ <CardDescription class="text-xs mt-0.5">Subtitle</CardDescription>
150
+ </div>
151
+ </CardHeader>
152
+ <CardContent class="p-0">
153
+ <!-- Table content here -->
154
+ </CardContent>
155
+ </Card>
156
+ ```
157
+
158
+ ### 3. Input Groups with Icons & Addons
159
+ Never write manual `absolute` positioning for input icons:
160
+ ```vue
161
+ <!-- Search icon input -->
162
+ <InputGroup>
163
+ <InputIcon side="left">
164
+ <Search class="h-3.5 w-3.5" />
165
+ </InputIcon>
166
+ <Input v-model="searchQuery" placeholder="Search..." class="pl-8 h-8 text-xs" />
167
+ </InputGroup>
168
+
169
+ <!-- URL prefix/suffix addon -->
170
+ <InputGroup>
171
+ <InputAddon side="left">https://</InputAddon>
172
+ <Input placeholder="my-subdomain" class="rounded-none border-x-0" />
173
+ <InputAddon side="right">.example.com</InputAddon>
174
+ </InputGroup>
175
+ ```
176
+
177
+ ### 4. Standard KPI Stats Cards
80
178
  ```vue
81
179
  <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
82
180
  <Card
83
181
  v-for="stat in stats"
84
182
  :key="stat.title"
85
183
  flush
86
- class="highlight-card shadow-xs border-border/80 bg-card hover:border-border transition-all duration-200"
184
+ class="highlight-card shadow-xs border-border/80 hover:border-border transition-all duration-200"
87
185
  >
88
186
  <CardContent class="p-5 space-y-2">
89
- <!-- 1. Top Row: Title + Icon -->
90
187
  <div class="flex items-center justify-between">
91
188
  <span class="text-xs font-medium text-muted-foreground">{{ stat.title }}</span>
92
189
  <component :is="stat.icon" class="h-4 w-4 text-primary" />
93
190
  </div>
94
-
95
- <!-- 2. Value -->
96
- <div class="text-2xl font-bold tracking-tight text-foreground">{{ stat.value }}</div>
97
-
98
- <!-- 3. Trend Indicator -->
191
+ <div class="text-2xl font-bold tracking-tight">{{ stat.value }}</div>
99
192
  <p class="text-xs text-muted-foreground flex items-center gap-1">
100
- <span
101
- class="font-semibold inline-flex items-center gap-0.5"
102
- :class="stat.positive ? 'text-emerald-500' : 'text-rose-500'"
103
- >
193
+ <span class="font-semibold inline-flex items-center gap-0.5"
194
+ :class="stat.positive ? 'text-emerald-500' : 'text-rose-500'">
104
195
  <component :is="stat.positive ? ArrowUpRight : ArrowDownRight" class="h-3.5 w-3.5" />
105
196
  {{ stat.change }}
106
197
  </span>
@@ -111,23 +202,28 @@ When building summary metrics / stats cards, follow this exact blueprint:
111
202
  </div>
112
203
  ```
113
204
 
114
- ### 3. Input Groups with Icons & Addons
115
- Never write manual absolute positioning for input icons:
205
+ ### 5. Empty State (use `<EmptyState>` don't build inline)
116
206
  ```vue
117
- <!-- Search Icon Input -->
118
- <InputGroup>
119
- <InputIcon side="left">
120
- <Search class="h-3.5 w-3.5" />
121
- </InputIcon>
122
- <Input v-model="searchQuery" placeholder="Search..." class="pl-8 h-8 text-xs" />
123
- </InputGroup>
207
+ <!-- Inside a table cell or card content when data is empty -->
208
+ <EmptyState
209
+ title="No products found"
210
+ description="Try adjusting your search or add a new product."
211
+ />
212
+ ```
124
213
 
125
- <!-- URL Prefix / Suffix Addon -->
126
- <InputGroup>
127
- <InputAddon side="left">https://</InputAddon>
128
- <Input placeholder="my-subdomain" class="rounded-none border-x-0" />
129
- <InputAddon side="right">.nala.dev</InputAddon>
130
- </InputGroup>
214
+ ### 6. `useFormatter()` Data Formatting
215
+ ```ts
216
+ const fmt = useFormatter()
217
+
218
+ fmt.currency(150000, 'IDR') // "Rp 150.000"
219
+ fmt.currency(1999, 'USD') // "$1,999.00"
220
+ fmt.number(1500000) // "1,500,000"
221
+ fmt.compact(1500000) // "1.5M"
222
+ fmt.date(new Date()) // "Sep 3, 2026"
223
+ fmt.dateTime(new Date()) // "Sep 3, 2026, 14:30"
224
+ fmt.relative(pastDate) // "5 minutes ago"
225
+ fmt.bytes(1024 * 1024) // "1 MB"
226
+ fmt.initials('John Doe') // "JD"
131
227
  ```
132
228
 
133
229
  ---
@@ -473,21 +569,72 @@ const filteredProducts = computed(() => {
473
569
  </template>
474
570
  ```
475
571
 
476
- ### 5. Register in Router & Sidebar
477
- - **`src/router/index.ts`:**
478
- ```ts
479
- {
480
- path: 'products',
481
- name: 'products',
482
- component: () => import('@/views/products/IndexView.vue'),
483
- }
484
- ```
485
- - **`src/components/layout/AppSidebar.vue`:**
486
- ```ts
487
- import { Package } from '@lucide/vue'
488
-
489
- const mainNav = [
490
- { name: 'Dashboard', routeName: 'dashboard', href: '/', icon: LayoutDashboard },
491
- { name: 'Products', routeName: 'products', href: '/products', icon: Package },
492
- ]
493
- ```
572
+ ### 5. Register Route & Sidebar Entry
573
+
574
+ **`src/router/index.ts`** — Add inside the AdminLayout children array:
575
+ ```ts
576
+ {
577
+ path: 'products',
578
+ name: 'products',
579
+ component: () => import('@/views/products/IndexView.vue'),
580
+ },
581
+ ```
582
+
583
+ **`src/components/layout/AppSidebar.vue`** Add to the `mainNav` array:
584
+ ```ts
585
+ import { Package } from '@lucide/vue'
586
+
587
+ const mainNav = [
588
+ { name: 'Dashboard', routeName: 'dashboard', href: '/', icon: LayoutDashboard },
589
+ { name: 'Products', routeName: 'products', href: '/products', icon: Package },
590
+ ]
591
+ ```
592
+
593
+ ---
594
+
595
+ ## 🗺️ Available Routes (Starter Template)
596
+
597
+ | Route | Name | View |
598
+ |---|---|---|
599
+ | `/` | `dashboard` | `views/dashboard/IndexView.vue` |
600
+ | `/_blank` | `starter-blank` | `views/_starter/BlankView.vue` — starting point for new pages |
601
+ | `/auth/login` | `login` | Full login form with demo credentials |
602
+ | `/auth/register` | `register` | Registration with password strength meter |
603
+ | `/auth/forgot-password` | `forgot-password` | Recovery email request |
604
+ | `/auth/reset-password` | `reset-password` | Token-based password reset |
605
+ | `/auth/verify-otp` | `verify-otp` | 6-box OTP input |
606
+ | `/auth/confirm-email` | `confirm-email` | Email confirmation with polling |
607
+ | `/auth/lock-screen` | `lock-screen` | Session lock screen |
608
+ | `/errors/404` | `not-found` | 404 Not Found page |
609
+ | `/errors/500` | `server-error` | 500 Server Error page |
610
+ | `/errors/403` | `unauthorized` | 403 Access Denied page |
611
+ | `/errors/maintenance` | `maintenance` | Maintenance mode with countdown |
612
+ | `/errors/coming-soon` | `coming-soon` | Coming soon with newsletter capture |
613
+
614
+ > **Auth Guard:** The router file (`src/router/index.ts`) has a pre-built auth guard scaffold in comments. Uncomment and configure it to protect your routes.
615
+
616
+ ---
617
+
618
+ ## 🔧 Tailwind v4 Syntax Reference (Anti-Pattern Table)
619
+
620
+ | Category | ❌ NEVER (v3 / Anti-Pattern) | ✅ ALWAYS (Tailwind v4) |
621
+ |---|---|---|
622
+ | **Gradients** | `bg-gradient-to-r` | `bg-linear-to-r` |
623
+ | **Max Width** | `max-w-[170px]` | `max-w-44` |
624
+ | **Width/Height** | `w-[300px]` / `h-[400px]` | `w-75` / `h-100` |
625
+ | **1px Spacing** | `p-[1px]` / `m-[1px]` | `p-px` / `m-px` |
626
+ | **Shadows** | `shadow-[0_1px_...]` | `shadow-2xs` / `shadow-xs` / `shadow-sm` |
627
+ | **Viewport** | `min-h-screen` / `h-screen` | `min-h-dvh` / `h-dvh` |
628
+ | **Opacity** | `bg-primary/0.5` | `bg-primary/50` |
629
+
630
+ ---
631
+
632
+ ## 🛠️ Dev Commands
633
+
634
+ | Command | Action |
635
+ |---|---|
636
+ | `pnpm dev` | Start dev server |
637
+ | `pnpm build` | Build for production (run manually only) |
638
+ | `pnpm preview` | Preview production build |
639
+ | `pnpm test` | Run unit tests in watch mode |
640
+ | `pnpm test:run` | Run unit tests once (CI mode) |
@@ -40,7 +40,7 @@ The following modules are auto-imported via `unplugin-auto-import` and `unplugin
40
40
 
41
41
  ## 📦 UI Primitives Catalog (`src/components/ui/`)
42
42
 
43
- All 34+ primitive components in `src/components/ui/` are globally registered and ready to use:
43
+ All 45 primitive components in `src/components/ui/` are globally registered and ready to use:
44
44
  - `Button`, `Badge`, `Avatar`, `Breadcrumb`, `Card`, `Checkbox`, `Dialog`, `DropdownMenu`
45
45
  - `Form` (`FormField`, `FormItem`, `FormLabel`, `FormControl`, `FormMessage`)
46
46
  - `Input`, `InputGroup`, `InputIcon`, `InputAddon`, `PinInput`, `Textarea`, `Select`, `Switch`
@@ -0,0 +1,27 @@
1
+ # CLAUDE.md — Nala Application AI Guardrails
2
+
3
+ This file defines the strict, high-priority guardrails and behavioral constraints for AI agents working on this **Nala** application.
4
+
5
+ ---
6
+
7
+ ## 🛑 Strict Rules (Enforced on Every Invocation)
8
+
9
+ 1. **No Automatic Build:** NEVER run `pnpm build` or `npm run build` after writing or modifying code. Transpilation/build checks are only performed when explicitly requested by the user.
10
+ 2. **No Automatic Unit Tests:** NEVER run `vitest`, `pnpm test`, `pnpm test:run`, or `npm test` autonomously after writing or modifying code. Unit tests are strictly executed only upon explicit user instruction.
11
+ 3. **No Unauthorized Git Operations:** NEVER run `git add`, `git commit`, or `git push` autonomously. Git commands are strictly executed only upon explicit user instruction.
12
+ 4. **English Standard (UI & Code Comments):** All user-facing UI text, form labels, validation/error messages, toast notifications, and in-code comments (JSDoc/inline notes in `.vue` and `.ts` files) MUST be written in **English**.
13
+ 5. **Strict Vue 3 & TypeScript Hygiene:** Always use Composition API `<script setup lang="ts">`. Never use Options API. Never use `any` type — define explicit TypeScript interfaces for all props, emits, and API payloads.
14
+ 6. **Tailwind CSS v4 Standard & Syntax Compliance:**
15
+ - **Gradients:** ALWAYS use `bg-linear-to-r`, `bg-linear-to-b`, `bg-linear-to-tr` (NEVER use legacy v3 `bg-gradient-to-*`).
16
+ - **Sizing Scale:** NEVER write arbitrary bracket sizing like `max-w-[170px]`, `w-[300px]`, or `p-[1px]`. ALWAYS use Tailwind v4 scale (`max-w-44`, `max-w-28`, `w-75`, `max-h-75`, `p-px`).
17
+ - **Shadows:** Use `shadow-2xs`, `shadow-xs`, `shadow-sm`, `shadow-md`, `shadow-lg`.
18
+ 7. **Package Installation Confirmation:** NEVER install new npm packages autonomously. Always ask the user directly in chat for approval before running `pnpm add` or `npm install`.
19
+ 8. **No Scoped Styles:** Use Tailwind CSS utility classes instead of `<style scoped>`.
20
+ 9. **Dialog / Modal Accessibility Standard:** Every `DialogContent` MUST include `DialogTitle` and `DialogDescription` (use `sr-only` if visually hidden) to comply with Reka UI ARIA standards.
21
+
22
+ ---
23
+
24
+ ## 📚 Deep Technical Blueprints & Component Catalog
25
+
26
+ For the complete 45 Reka UI Primitives, Shared Components (`PageHeader`, `EmptyState`, `AppLogo`), Auto-Import Matrix, Axios Service Layer, Pinia Store patterns, and end-to-end CRUD scaffolding blueprints, refer to the **`nala-project` skill** located at:
27
+ 👉 [`.agents/skills/nala-project/SKILL.md`](.agents/skills/nala-project/SKILL.md)
@@ -0,0 +1,27 @@
1
+ # GEMINI.md — Nala Application AI Guardrails
2
+
3
+ This file defines the strict, high-priority guardrails and behavioral constraints for AI agents working on this **Nala** application.
4
+
5
+ ---
6
+
7
+ ## 🛑 Strict Rules (Enforced on Every Invocation)
8
+
9
+ 1. **No Automatic Build:** NEVER run `pnpm build` or `npm run build` after writing or modifying code. Transpilation/build checks are only performed when explicitly requested by the user.
10
+ 2. **No Automatic Unit Tests:** NEVER run `vitest`, `pnpm test`, `pnpm test:run`, or `npm test` autonomously after writing or modifying code. Unit tests are strictly executed only upon explicit user instruction.
11
+ 3. **No Unauthorized Git Operations:** NEVER run `git add`, `git commit`, or `git push` autonomously. Git commands are strictly executed only upon explicit user instruction.
12
+ 4. **English Standard (UI & Code Comments):** All user-facing UI text, form labels, validation/error messages, toast notifications, and in-code comments (JSDoc/inline notes in `.vue` and `.ts` files) MUST be written in **English**.
13
+ 5. **Strict Vue 3 & TypeScript Hygiene:** Always use Composition API `<script setup lang="ts">`. Never use Options API. Never use `any` type — define explicit TypeScript interfaces for all props, emits, and API payloads.
14
+ 6. **Tailwind CSS v4 Standard & Syntax Compliance:**
15
+ - **Gradients:** ALWAYS use `bg-linear-to-r`, `bg-linear-to-b`, `bg-linear-to-tr` (NEVER use legacy v3 `bg-gradient-to-*`).
16
+ - **Sizing Scale:** NEVER write arbitrary bracket sizing like `max-w-[170px]`, `w-[300px]`, or `p-[1px]`. ALWAYS use Tailwind v4 scale (`max-w-44`, `max-w-28`, `w-75`, `max-h-75`, `p-px`).
17
+ - **Shadows:** Use `shadow-2xs`, `shadow-xs`, `shadow-sm`, `shadow-md`, `shadow-lg`.
18
+ 7. **Package Installation Confirmation:** NEVER install new npm packages autonomously. Always ask the user directly in chat for approval before running `pnpm add` or `npm install`.
19
+ 8. **No Scoped Styles:** Use Tailwind CSS utility classes instead of `<style scoped>`.
20
+ 9. **Dialog / Modal Accessibility Standard:** Every `DialogContent` MUST include `DialogTitle` and `DialogDescription` (use `sr-only` if visually hidden) to comply with Reka UI ARIA standards.
21
+
22
+ ---
23
+
24
+ ## 📚 Deep Technical Blueprints & Component Catalog
25
+
26
+ For the complete 45 Reka UI Primitives, Shared Components (`PageHeader`, `EmptyState`, `AppLogo`), Auto-Import Matrix, Axios Service Layer, Pinia Store patterns, and end-to-end CRUD scaffolding blueprints, refer to the **`nala-project` skill** located at:
27
+ 👉 [`.agents/skills/nala-project/SKILL.md`](.agents/skills/nala-project/SKILL.md)
@@ -57,7 +57,9 @@ src/
57
57
  ├── assets/fonts/ # High-performance local Inter fonts (woff2)
58
58
  ├── components/
59
59
  │ ├── layout/ # Admin shell (AppNavbar, AppSidebar, CommandPalette)
60
- │ ├── ui/ # 34+ accessible UI primitives (Reka UI / shadcn-vue)
60
+ │ ├── ui/ # 45 accessible UI primitives (Reka UI / shadcn-vue)
61
+ │ ├── AppLogo.vue # Auto-imported brand logo component
62
+ │ ├── EmptyState.vue # Auto-imported empty state component
61
63
  │ └── PageHeader.vue # Standardized page header component
62
64
  ├── composables/
63
65
  │ ├── useFormatter.ts # Native Intl data formatting helpers (auto-imported)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "NALA_APP_SLUG",
3
- "version": "3.0.3",
3
+ "version": "3.1.0",
4
4
  "description": "Production-ready admin dashboard built with Vue 3, Vite, TypeScript, and Tailwind CSS v4.",
5
5
  "private": true,
6
6
  "type": "module",
@@ -11,5 +11,5 @@ useThemeConfig()
11
11
  <template>
12
12
  <LoadingBar />
13
13
  <RouterView />
14
- <Toaster position="top-right" rich-colors close-button />
14
+ <Toaster position="top-right" />
15
15
  </template>
Binary file
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="77" height="47" fill="none" aria-labelledby="vite-logo-title" viewBox="0 0 77 47"><title id="vite-logo-title">Vite</title><style>.parenthesis{fill:#000}@media (prefers-color-scheme:dark){.parenthesis{fill:#fff}}</style><path fill="#9135ff" d="M40.151 45.71c-.663.844-2.02.374-2.02-.699V34.708a2.26 2.26 0 0 0-2.262-2.262H24.493c-.92 0-1.457-1.04-.92-1.788l7.479-10.471c1.07-1.498 0-3.578-1.842-3.578H15.443c-.92 0-1.456-1.04-.92-1.788l9.696-13.576c.213-.297.556-.474.92-.474h28.894c.92 0 1.456 1.04.92 1.788l-7.48 10.472c-1.07 1.497 0 3.578 1.842 3.578h11.376c.944 0 1.474 1.087.89 1.83L40.153 45.712z"/><mask id="a" width="48" height="47" x="14" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha"><path fill="#000" d="M40.047 45.71c-.663.843-2.02.374-2.02-.699V34.708a2.26 2.26 0 0 0-2.262-2.262H24.389c-.92 0-1.457-1.04-.92-1.788l7.479-10.472c1.07-1.497 0-3.578-1.842-3.578H15.34c-.92 0-1.456-1.04-.92-1.788l9.696-13.575c.213-.297.556-.474.92-.474H53.93c.92 0 1.456 1.04.92 1.788L47.37 13.03c-1.07 1.498 0 3.578 1.842 3.578h11.376c.944 0 1.474 1.088.89 1.831L40.049 45.712z"/></mask><g mask="url(#a)"><g filter="url(#b)"><ellipse cx="5.508" cy="14.704" fill="#eee6ff" rx="5.508" ry="14.704" transform="rotate(269.814 20.96 11.29)scale(-1 1)"/></g><g filter="url(#c)"><ellipse cx="10.399" cy="29.851" fill="#eee6ff" rx="10.399" ry="29.851" transform="rotate(89.814 -16.902 -8.275)scale(1 -1)"/></g><g filter="url(#d)"><ellipse cx="5.508" cy="30.487" fill="#8900ff" rx="5.508" ry="30.487" transform="rotate(89.814 -19.197 -7.127)scale(1 -1)"/></g><g filter="url(#e)"><ellipse cx="5.508" cy="30.599" fill="#8900ff" rx="5.508" ry="30.599" transform="rotate(89.814 -25.928 4.177)scale(1 -1)"/></g><g filter="url(#f)"><ellipse cx="5.508" cy="30.599" fill="#8900ff" rx="5.508" ry="30.599" transform="rotate(89.814 -25.738 5.52)scale(1 -1)"/></g><g filter="url(#g)"><ellipse cx="14.072" cy="22.078" fill="#eee6ff" rx="14.072" ry="22.078" transform="rotate(93.35 31.245 55.578)scale(-1 1)"/></g><g filter="url(#h)"><ellipse cx="3.47" cy="21.501" fill="#8900ff" rx="3.47" ry="21.501" transform="rotate(89.009 35.419 55.202)scale(-1 1)"/></g><g filter="url(#i)"><ellipse cx="3.47" cy="21.501" fill="#8900ff" rx="3.47" ry="21.501" transform="rotate(89.009 35.419 55.202)scale(-1 1)"/></g><g filter="url(#j)"><ellipse cx="14.592" cy="9.743" fill="#8900ff" rx="4.407" ry="29.108" transform="rotate(39.51 14.592 9.743)"/></g><g filter="url(#k)"><ellipse cx="61.728" cy="-5.321" fill="#8900ff" rx="4.407" ry="29.108" transform="rotate(37.892 61.728 -5.32)"/></g><g filter="url(#l)"><ellipse cx="55.618" cy="7.104" fill="#00c2ff" rx="5.971" ry="9.665" transform="rotate(37.892 55.618 7.104)"/></g><g filter="url(#m)"><ellipse cx="12.326" cy="39.103" fill="#8900ff" rx="4.407" ry="29.108" transform="rotate(37.892 12.326 39.103)"/></g><g filter="url(#n)"><ellipse cx="12.326" cy="39.103" fill="#8900ff" rx="4.407" ry="29.108" transform="rotate(37.892 12.326 39.103)"/></g><g filter="url(#o)"><ellipse cx="49.857" cy="30.678" fill="#8900ff" rx="4.407" ry="29.108" transform="rotate(37.892 49.857 30.678)"/></g><g filter="url(#p)"><ellipse cx="52.623" cy="33.171" fill="#00c2ff" rx="5.971" ry="15.297" transform="rotate(37.892 52.623 33.17)"/></g></g><path d="M6.919 0c-9.198 13.166-9.252 33.575 0 46.789h6.215c-9.25-13.214-9.196-33.623 0-46.789zm62.424 0h-6.215c9.198 13.166 9.252 33.575 0 46.789h6.215c9.25-13.214 9.196-33.623 0-46.789" class="parenthesis"/><defs><filter id="b" width="60.045" height="41.654" x="-5.564" y="16.92" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="7.659"/></filter><filter id="c" width="90.34" height="51.437" x="-40.407" y="-6.762" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="7.659"/></filter><filter id="d" width="79.355" height="29.4" x="-35.435" y="2.801" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="e" width="79.579" height="29.4" x="-30.84" y="20.8" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="f" width="79.579" height="29.4" x="-29.307" y="21.949" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="g" width="74.749" height="58.852" x="29.961" y="-17.13" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="7.659"/></filter><filter id="h" width="61.377" height="25.362" x="37.754" y="3.055" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="i" width="61.377" height="25.362" x="37.754" y="3.055" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="j" width="56.045" height="63.649" x="-13.43" y="-22.082" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="k" width="54.814" height="64.646" x="34.321" y="-37.644" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="l" width="33.541" height="35.313" x="38.847" y="-10.552" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="m" width="54.814" height="64.646" x="-15.081" y="6.78" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="n" width="54.814" height="64.646" x="-15.081" y="6.78" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="o" width="54.814" height="64.646" x="22.45" y="-1.645" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter><filter id="p" width="39.409" height="43.623" x="32.919" y="11.36" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17286" stdDeviation="4.596"/></filter></defs></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
@@ -1,12 +1,12 @@
1
1
  <script setup lang="ts">
2
- import type { HTMLAttributes } from "vue"
3
- import type { AlertVariants } from "."
4
- import { cn } from "@/lib/utils"
5
- import { alertVariants } from "."
6
-
7
- const props = defineProps<{
8
- class?: HTMLAttributes["class"]
9
- variant?: AlertVariants["variant"]
2
+ import type { HTMLAttributes } from "vue"
3
+ import type { AlertVariants } from "."
4
+ import { cn } from "@/lib/utils"
5
+ import { alertVariants } from "."
6
+
7
+ const props = defineProps<{
8
+ class?: HTMLAttributes["class"]
9
+ variant?: AlertVariants["variant"]
10
10
  }>()
11
11
  </script>
12
12
 
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
- import type { HTMLAttributes } from "vue"
3
- import { cn } from "@/lib/utils"
4
-
5
- const props = defineProps<{
6
- class?: HTMLAttributes["class"]
2
+ import type { HTMLAttributes } from "vue"
3
+ import { cn } from "@/lib/utils"
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes["class"]
7
7
  }>()
8
8
  </script>
9
9
 
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
- import type { HTMLAttributes } from "vue"
3
- import { cn } from "@/lib/utils"
4
-
5
- const props = defineProps<{
6
- class?: HTMLAttributes["class"]
2
+ import type { HTMLAttributes } from "vue"
3
+ import { cn } from "@/lib/utils"
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes["class"]
7
7
  }>()
8
8
  </script>
9
9
 
@@ -1,10 +1,10 @@
1
1
  <script setup lang="ts">
2
- import type { AlertDialogEmits, AlertDialogProps } from "reka-ui"
3
- import { AlertDialogRoot, useForwardPropsEmits } from "reka-ui"
4
-
5
- const props = defineProps<AlertDialogProps>()
6
- const emits = defineEmits<AlertDialogEmits>()
7
-
2
+ import type { AlertDialogEmits, AlertDialogProps } from "reka-ui"
3
+ import { AlertDialogRoot, useForwardPropsEmits } from "reka-ui"
4
+
5
+ const props = defineProps<AlertDialogProps>()
6
+ const emits = defineEmits<AlertDialogEmits>()
7
+
8
8
  const forwarded = useForwardPropsEmits(props, emits)
9
9
  </script>
10
10