@allbluecn/admin-app 0.2.6 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/package.json +16 -12
  2. package/src/components/admin/admin-user-menu.tsx +2 -4
  3. package/src/components/admin/developer-log.tsx +3 -5
  4. package/src/components/ai-memory/memory-facts-panel.tsx +383 -0
  5. package/src/components/ai-prompts/preview-panel.tsx +165 -0
  6. package/src/components/ai-prompts/prompt-editor.tsx +328 -0
  7. package/src/components/ai-prompts/prompt-table.tsx +141 -0
  8. package/src/components/ai-prompts/prompt-utils.ts +124 -0
  9. package/src/components/ai-prompts/section-editor.tsx +135 -0
  10. package/src/components/ai-prompts/variable-panel.tsx +128 -0
  11. package/src/components/ai-prompts/version-history.tsx +157 -0
  12. package/src/components/ai-provider/provider-form.tsx +6 -10
  13. package/src/components/ai-provider/provider-table.tsx +33 -13
  14. package/src/components/auth/admin-login-form.tsx +1 -1
  15. package/src/components/component/component-form-dialog.tsx +4 -4
  16. package/src/components/component/component-import-dialog.tsx +2 -2
  17. package/src/components/dependency/changelog-dialog.tsx +2 -4
  18. package/src/components/dependency/columns.tsx +4 -8
  19. package/src/components/dependency/dependency-table.tsx +2 -2
  20. package/src/components/dependency/edit-dialog.tsx +7 -11
  21. package/src/components/invitations/invitations-page.tsx +4 -8
  22. package/src/components/knowledge-public/bookmark-form-dialog.tsx +1 -1
  23. package/src/components/knowledge-public/compliance-form-dialog.tsx +1 -1
  24. package/src/components/knowledge-public/legal-form-dialog.tsx +2 -2
  25. package/src/components/layout/sidebar-02/app-sidebar.tsx +17 -9
  26. package/src/components/layout/sidebar-02/nav-main.tsx +6 -14
  27. package/src/components/layout/sidebar-02/nav-notifications.tsx +3 -7
  28. package/src/components/magicui/rainbow-button.tsx +2 -2
  29. package/src/components/market/columns.tsx +2 -4
  30. package/src/components/market/market-app-form.tsx +2 -2
  31. package/src/components/market/market-app-list.tsx +1 -1
  32. package/src/components/oauth-providers/provider-page.tsx +1 -1
  33. package/src/components/ui/alert-dialog.tsx +28 -57
  34. package/src/components/ui/alert.tsx +3 -4
  35. package/src/components/ui/avatar.tsx +5 -28
  36. package/src/components/ui/badge.tsx +19 -34
  37. package/src/components/ui/button.tsx +14 -41
  38. package/src/components/ui/card.tsx +6 -24
  39. package/src/components/ui/checkbox.tsx +4 -26
  40. package/src/components/ui/collapsible.tsx +6 -37
  41. package/src/components/ui/dialog.tsx +30 -60
  42. package/src/components/ui/dropdown-menu.tsx +118 -137
  43. package/src/components/ui/field.tsx +8 -27
  44. package/src/components/ui/input-group.tsx +13 -26
  45. package/src/components/ui/input.tsx +4 -21
  46. package/src/components/ui/label.tsx +3 -27
  47. package/src/components/ui/pagination.tsx +17 -31
  48. package/src/components/ui/select.tsx +101 -76
  49. package/src/components/ui/separator.tsx +4 -27
  50. package/src/components/ui/sheet.tsx +29 -58
  51. package/src/components/ui/sidebar.tsx +119 -117
  52. package/src/components/ui/skeleton.tsx +1 -18
  53. package/src/components/ui/switch.tsx +5 -24
  54. package/src/components/ui/table.tsx +1 -19
  55. package/src/components/ui/textarea.tsx +2 -20
  56. package/src/components/ui/toast.tsx +282 -0
  57. package/src/components/ui/tooltip.tsx +34 -45
  58. package/src/components/user/settings-activity-log.tsx +1 -1
  59. package/src/components/user/user-create-dialog.tsx +2 -2
  60. package/src/components/user/user-filters.tsx +2 -2
  61. package/src/hooks/use-mobile.ts +0 -17
  62. package/src/lib/pacer.ts +21 -0
  63. package/src/lib/utils.ts +1 -23
  64. package/src/paraglide/README.md +1 -1
  65. package/src/paraglide/messages/_index.js +95 -0
  66. package/src/paraglide/messages/admin_ai_memory_action_clearuser1.js +30 -0
  67. package/src/paraglide/messages/admin_ai_memory_action_query.js +30 -0
  68. package/src/paraglide/messages/admin_ai_memory_clear_cancel.js +30 -0
  69. package/src/paraglide/messages/admin_ai_memory_clear_confirm_action.js +30 -0
  70. package/src/paraglide/messages/admin_ai_memory_clear_confirm_description.js +30 -0
  71. package/src/paraglide/messages/admin_ai_memory_clear_confirm_title.js +30 -0
  72. package/src/paraglide/messages/admin_ai_memory_columns_actions.js +30 -0
  73. package/src/paraglide/messages/admin_ai_memory_columns_content.js +30 -0
  74. package/src/paraglide/messages/admin_ai_memory_columns_createdat1.js +30 -0
  75. package/src/paraglide/messages/admin_ai_memory_columns_threadid1.js +30 -0
  76. package/src/paraglide/messages/admin_ai_memory_delete_cancel.js +30 -0
  77. package/src/paraglide/messages/admin_ai_memory_delete_confirm_action.js +30 -0
  78. package/src/paraglide/messages/admin_ai_memory_delete_confirm_description.js +30 -0
  79. package/src/paraglide/messages/admin_ai_memory_delete_confirm_title.js +30 -0
  80. package/src/paraglide/messages/admin_ai_memory_empty.js +30 -0
  81. package/src/paraglide/messages/admin_ai_memory_emptyhint1.js +30 -0
  82. package/src/paraglide/messages/admin_ai_memory_error_nouserid2.js +30 -0
  83. package/src/paraglide/messages/admin_ai_memory_error_query.js +30 -0
  84. package/src/paraglide/messages/admin_ai_memory_error_title.js +30 -0
  85. package/src/paraglide/messages/admin_ai_memory_form_user.js +30 -0
  86. package/src/paraglide/messages/admin_ai_memory_page_description.js +30 -0
  87. package/src/paraglide/messages/admin_ai_memory_page_title.js +30 -0
  88. package/src/paraglide/messages/admin_ai_memory_placeholder_user.js +30 -0
  89. package/src/paraglide/messages/admin_ai_memory_stat_count.js +30 -0
  90. package/src/paraglide/messages/admin_ai_memory_stat_lastwrite1.js +30 -0
  91. package/src/paraglide/messages/admin_ai_memory_toast_cleared.js +30 -0
  92. package/src/paraglide/messages/admin_ai_memory_toast_deleted.js +30 -0
  93. package/src/paraglide/messages/admin_ai_prompts_active.js +30 -0
  94. package/src/paraglide/messages/admin_ai_prompts_back.js +30 -0
  95. package/src/paraglide/messages/admin_ai_prompts_badge_protected.js +30 -0
  96. package/src/paraglide/messages/admin_ai_prompts_cache_hint.js +30 -0
  97. package/src/paraglide/messages/admin_ai_prompts_columns_active.js +30 -0
  98. package/src/paraglide/messages/admin_ai_prompts_columns_key.js +30 -0
  99. package/src/paraglide/messages/admin_ai_prompts_columns_name.js +30 -0
  100. package/src/paraglide/messages/admin_ai_prompts_columns_protected.js +30 -0
  101. package/src/paraglide/messages/admin_ai_prompts_columns_updatedat1.js +30 -0
  102. package/src/paraglide/messages/admin_ai_prompts_columns_version.js +30 -0
  103. package/src/paraglide/messages/admin_ai_prompts_description.js +30 -0
  104. package/src/paraglide/messages/admin_ai_prompts_description_placeholder.js +30 -0
  105. package/src/paraglide/messages/admin_ai_prompts_edit.js +30 -0
  106. package/src/paraglide/messages/admin_ai_prompts_name.js +30 -0
  107. package/src/paraglide/messages/admin_ai_prompts_name_placeholder.js +30 -0
  108. package/src/paraglide/messages/admin_ai_prompts_note_placeholder.js +30 -0
  109. package/src/paraglide/messages/admin_ai_prompts_page_description.js +30 -0
  110. package/src/paraglide/messages/admin_ai_prompts_page_title.js +30 -0
  111. package/src/paraglide/messages/admin_ai_prompts_preview_empty.js +30 -0
  112. package/src/paraglide/messages/admin_ai_prompts_preview_generating.js +30 -0
  113. package/src/paraglide/messages/admin_ai_prompts_preview_hint.js +30 -0
  114. package/src/paraglide/messages/admin_ai_prompts_preview_nocontent1.js +30 -0
  115. package/src/paraglide/messages/admin_ai_prompts_preview_placeholder.js +30 -0
  116. package/src/paraglide/messages/admin_ai_prompts_preview_section.js +30 -0
  117. package/src/paraglide/messages/admin_ai_prompts_preview_title.js +30 -0
  118. package/src/paraglide/messages/admin_ai_prompts_protected_hint.js +30 -0
  119. package/src/paraglide/messages/admin_ai_prompts_rollback.js +30 -0
  120. package/src/paraglide/messages/admin_ai_prompts_rollback_confirm_action.js +30 -0
  121. package/src/paraglide/messages/admin_ai_prompts_rollback_confirm_description.js +30 -0
  122. package/src/paraglide/messages/admin_ai_prompts_rollback_confirm_title.js +30 -0
  123. package/src/paraglide/messages/admin_ai_prompts_save.js +30 -0
  124. package/src/paraglide/messages/admin_ai_prompts_section_add.js +30 -0
  125. package/src/paraglide/messages/admin_ai_prompts_section_id.js +30 -0
  126. package/src/paraglide/messages/admin_ai_prompts_section_movedown1.js +30 -0
  127. package/src/paraglide/messages/admin_ai_prompts_section_moveup1.js +30 -0
  128. package/src/paraglide/messages/admin_ai_prompts_section_order.js +30 -0
  129. package/src/paraglide/messages/admin_ai_prompts_section_remove.js +30 -0
  130. package/src/paraglide/messages/admin_ai_prompts_section_template_placeholder.js +30 -0
  131. package/src/paraglide/messages/admin_ai_prompts_sections_empty.js +30 -0
  132. package/src/paraglide/messages/admin_ai_prompts_sections_hint.js +30 -0
  133. package/src/paraglide/messages/admin_ai_prompts_sections_title.js +30 -0
  134. package/src/paraglide/messages/admin_ai_prompts_toast_activated.js +30 -0
  135. package/src/paraglide/messages/admin_ai_prompts_toast_failed.js +30 -0
  136. package/src/paraglide/messages/admin_ai_prompts_toast_protected_locked.js +30 -0
  137. package/src/paraglide/messages/admin_ai_prompts_toast_rolled_back.js +30 -0
  138. package/src/paraglide/messages/admin_ai_prompts_toast_save_failed.js +30 -0
  139. package/src/paraglide/messages/admin_ai_prompts_toast_saved.js +30 -0
  140. package/src/paraglide/messages/admin_ai_prompts_variable_add.js +30 -0
  141. package/src/paraglide/messages/admin_ai_prompts_variable_declarehint1.js +30 -0
  142. package/src/paraglide/messages/admin_ai_prompts_variable_description_placeholder.js +30 -0
  143. package/src/paraglide/messages/admin_ai_prompts_variable_name_placeholder.js +30 -0
  144. package/src/paraglide/messages/admin_ai_prompts_variable_remove.js +30 -0
  145. package/src/paraglide/messages/admin_ai_prompts_variable_undeclared.js +30 -0
  146. package/src/paraglide/messages/admin_ai_prompts_variables_empty.js +30 -0
  147. package/src/paraglide/messages/admin_ai_prompts_variables_title.js +30 -0
  148. package/src/paraglide/messages/admin_ai_prompts_versions_current.js +30 -0
  149. package/src/paraglide/messages/admin_ai_prompts_versions_empty.js +30 -0
  150. package/src/paraglide/messages/admin_ai_prompts_versions_hint.js +30 -0
  151. package/src/paraglide/messages/admin_ai_prompts_versions_nonote1.js +30 -0
  152. package/src/paraglide/messages/admin_ai_prompts_versions_title.js +30 -0
  153. package/src/paraglide/messages/admin_ai_prompts_versions_unknowncreator1.js +30 -0
  154. package/src/paraglide/messages/admin_ai_table_seedfromseed2.js +30 -0
  155. package/src/paraglide/messages/admin_ai_table_toast_seedcreated1.js +30 -0
  156. package/src/paraglide/messages/admin_ai_table_toast_seedfailed1.js +30 -0
  157. package/src/paraglide/messages/admin_ai_table_toast_seednonew2.js +30 -0
  158. package/src/paraglide/messages/common_monitoring_aiusage_sandbox1.js +30 -0
  159. package/src/paraglide/messages/common_monitoring_aiusage_sandboxvalue2.js +30 -0
  160. package/src/paraglide/messages/common_nav_aiprompts1.js +30 -0
  161. package/src/routeTree.gen.ts +101 -0
  162. package/src/routes/__root.tsx +2 -2
  163. package/src/{components/ui/sonner.tsx → routes/_nav/ai-memory/route.lazy.tsx} +24 -16
  164. package/src/routes/_nav/ai-memory/route.tsx +31 -0
  165. package/src/routes/_nav/ai-prompts/$key/route.lazy.tsx +32 -0
  166. package/src/routes/_nav/ai-prompts/$key/route.tsx +37 -0
  167. package/src/routes/_nav/ai-prompts/index/route.lazy.tsx +47 -0
  168. package/src/routes/_nav/ai-prompts/route.lazy.tsx +26 -0
  169. package/src/routes/_nav/ai-prompts/route.tsx +31 -0
  170. package/src/routes/_nav/compliance/route.lazy.tsx +2 -4
  171. package/src/routes/_nav/components/route.lazy.tsx +1 -1
  172. package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +1 -1
  173. package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +1 -1
  174. package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +1 -1
  175. package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +1 -1
  176. package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +10 -1
  177. package/src/routes/_nav/monitoring/errors/route.lazy.tsx +1 -1
  178. package/src/routes/_nav/monitoring/health/route.lazy.tsx +1 -1
  179. package/src/routes/_nav/monitoring/logs/route.lazy.tsx +1 -1
  180. package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +1 -1
  181. package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +1 -1
  182. package/src/routes/_nav/permissions/route.lazy.tsx +2 -2
  183. package/src/routes/_nav/sso/route.lazy.tsx +1 -1
  184. package/src/routes/_nav/users/$userId/route.lazy.tsx +3 -3
  185. package/src/routes/setup/route.lazy.tsx +1 -1
  186. package/src/server/__tests__/prompt-defaults.test.ts +139 -0
  187. package/src/server/admin-ai-usage.ts +22 -4
  188. package/src/server/ai-memory/store.ts +103 -0
  189. package/src/server/serverFns/ai-memory/clear.ts +31 -0
  190. package/src/server/serverFns/ai-memory/delete.ts +31 -0
  191. package/src/server/serverFns/ai-memory/list-users.ts +40 -0
  192. package/src/server/serverFns/ai-memory/list.ts +54 -0
  193. package/src/server/serverFns/ai-prompts/activate.ts +53 -0
  194. package/src/server/serverFns/ai-prompts/get.ts +74 -0
  195. package/src/server/serverFns/ai-prompts/list.ts +55 -0
  196. package/src/server/serverFns/ai-prompts/preview.ts +66 -0
  197. package/src/server/serverFns/ai-prompts/prompt-defaults.ts +63 -0
  198. package/src/server/serverFns/ai-prompts/prompt-schemas.ts +47 -0
  199. package/src/server/serverFns/ai-prompts/rollback.ts +86 -0
  200. package/src/server/serverFns/ai-prompts/save.ts +129 -0
  201. package/src/server/serverFns/ai-provider/seed-from-seed.ts +64 -0
  202. package/src/styles/globals.css +92 -77
  203. package/src/components/layout/sidebar-02/logo.tsx +0 -40
  204. package/src/components/layout/sidebar-02/team-switcher.tsx +0 -106
  205. package/src/components/providers/theme-toggle.tsx +0 -59
@@ -22,7 +22,7 @@ import {
22
22
  useTable,
23
23
  type PaginationState,
24
24
  } from "@tanstack/react-table"
25
- import { toast } from '@/components/ui/sonner'
25
+ import { toast } from '@/components/ui/toast'
26
26
  import { RefreshCw, Search, TriangleAlert, Loader2 } from "lucide-react"
27
27
  import {
28
28
  DEPENDENCY_CATEGORIES,
@@ -231,7 +231,7 @@ export function DependencyTable({
231
231
  className="h-9 w-56 pl-8"
232
232
  />
233
233
  </div>
234
- <Select value={viewFilter} onValueChange={(v: string) => setViewFilter(v as "watched" | "all")}>
234
+ <Select value={viewFilter} onValueChange={(v) => setViewFilter((v ?? "watched") as "watched" | "all")}>
235
235
  <SelectTrigger className="h-9 w-32" size="sm">
236
236
  <SelectValue />
237
237
  </SelectTrigger>
@@ -17,7 +17,7 @@
17
17
 
18
18
  import { useState } from "react"
19
19
  import { m } from '@/paraglide/messages.js'
20
- import { toast } from '@/components/ui/sonner'
20
+ import { toast } from '@/components/ui/toast'
21
21
  import { Loader2, Pencil } from "lucide-react"
22
22
  import {
23
23
  DEPENDENCY_CATEGORIES,
@@ -83,11 +83,9 @@ export function EditDependencyDialog({
83
83
  if (row.id.startsWith("untracked:")) {
84
84
  return (
85
85
  <Tooltip>
86
- <TooltipTrigger asChild>
87
- <span>
86
+ <TooltipTrigger render={<span />}>
88
87
  <Pencil className="size-3.5 text-muted-foreground/50" />
89
- </span>
90
- </TooltipTrigger>
88
+ </TooltipTrigger>
91
89
  <TooltipContent>{m.common_dependency_edit_untracked()}</TooltipContent>
92
90
  </Tooltip>
93
91
  )
@@ -95,11 +93,9 @@ export function EditDependencyDialog({
95
93
 
96
94
  return (
97
95
  <Dialog open={open} onOpenChange={setOpen}>
98
- <DialogTrigger asChild>
99
- <Button size="sm" variant="ghost" className="size-7 p-0" title={m.common_common_edit()}>
96
+ <DialogTrigger render={<Button size="sm" variant="ghost" className="size-7 p-0" title={m.common_common_edit()} />}>
100
97
  <Pencil className="size-3.5" />
101
- </Button>
102
- </DialogTrigger>
98
+ </DialogTrigger>
103
99
  <DialogContent className="max-w-md">
104
100
  <DialogHeader>
105
101
  <DialogTitle>{m.common_dependency_edit_dialogTitle({ name: row.name })}</DialogTitle>
@@ -131,7 +127,7 @@ export function EditDependencyDialog({
131
127
  <Label>{m.common_dependency_edit_category()}</Label>
132
128
  <Select
133
129
  value={form.category}
134
- onValueChange={(v: string) => setForm({ ...form, category: v as DependencyCategory })}
130
+ onValueChange={(v) => setForm({ ...form, category: (v ?? "") as DependencyCategory })}
135
131
  >
136
132
  <SelectTrigger size="sm">
137
133
  <SelectValue />
@@ -149,7 +145,7 @@ export function EditDependencyDialog({
149
145
  <Label>{m.common_dependency_edit_priority()}</Label>
150
146
  <Select
151
147
  value={form.priority}
152
- onValueChange={(v: string) => setForm({ ...form, priority: v as ThirdPartyDependencyRow["priority"] })}
148
+ onValueChange={(v) => setForm({ ...form, priority: (v ?? "") as ThirdPartyDependencyRow["priority"] })}
153
149
  >
154
150
  <SelectTrigger size="sm">
155
151
  <SelectValue />
@@ -19,7 +19,7 @@ import { useState } from "react"
19
19
  import type React from "react"
20
20
  import { m } from "@/paraglide/messages.js"
21
21
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
22
- import { toast } from "sonner"
22
+ import { toast } from "@/components/ui/toast"
23
23
  import { Ticket, Plus, Copy, Ban, CheckCircle2, Trash2, Users } from "lucide-react"
24
24
  import { PageHeader } from "@/components/common/page-header"
25
25
  import { Button } from "@/components/ui/button"
@@ -342,16 +342,12 @@ export function InvitationsPage(): React.ReactElement {
342
342
  </Button>
343
343
  ) : (
344
344
  <Tooltip>
345
- <TooltipTrigger asChild>
346
- <Button
347
- variant="ghost"
345
+ <TooltipTrigger render={<Button variant="ghost"
348
346
  size="sm"
349
347
  className="h-8 text-destructive"
350
- disabled
351
- >
348
+ disabled />}>
352
349
  <Trash2 className="size-4" />
353
- </Button>
354
- </TooltipTrigger>
350
+ </TooltipTrigger>
355
351
  <TooltipContent>
356
352
  {m["admin-invitations_delete_disabled_hint"]()}
357
353
  </TooltipContent>
@@ -17,7 +17,7 @@
17
17
 
18
18
  import { useState, useEffect } from 'react'
19
19
  import { Loader2 } from 'lucide-react'
20
- import { toast } from '@/components/ui/sonner'
20
+ import { toast } from '@/components/ui/toast'
21
21
  import { Button } from '@/components/ui/button'
22
22
  import { Input } from '@/components/ui/input'
23
23
  import { Label } from '@/components/ui/label'
@@ -17,7 +17,7 @@
17
17
 
18
18
  import { useState, useEffect } from 'react'
19
19
  import { Loader2, PlusIcon, Trash2Icon } from 'lucide-react'
20
- import { toast } from '@/components/ui/sonner'
20
+ import { toast } from '@/components/ui/toast'
21
21
  import { Button } from '@/components/ui/button'
22
22
  import { Input } from '@/components/ui/input'
23
23
  import { Label } from '@/components/ui/label'
@@ -18,7 +18,7 @@
18
18
  import { useState, useEffect } from 'react'
19
19
  import { m } from '@/paraglide/messages.js'
20
20
  import { Loader2 } from 'lucide-react'
21
- import { toast } from '@/components/ui/sonner'
21
+ import { toast } from '@/components/ui/toast'
22
22
  import { Button } from '@/components/ui/button'
23
23
  import { Input } from '@/components/ui/input'
24
24
  import { Label } from '@/components/ui/label'
@@ -207,7 +207,7 @@ export function LegalFormDialog({ open, onOpenChange, item, onSuccess }: LegalFo
207
207
  <Label>{m.common_legalForm_jurisdiction()}</Label>
208
208
  <Select
209
209
  value={form.jurisdiction}
210
- onValueChange={(v: string) => setForm((f) => ({ ...f, jurisdiction: v }))}
210
+ onValueChange={(v) => setForm((f) => ({ ...f, jurisdiction: v ?? "" }))}
211
211
  >
212
212
  <SelectTrigger className="w-full">
213
213
  <SelectValue />
@@ -47,11 +47,13 @@ import {
47
47
  ScrollText,
48
48
  Ticket,
49
49
  KeyRound,
50
+ AlignLeft,
51
+ Brain,
50
52
  } from "lucide-react";
51
- import { Logo } from "@/components/layout/sidebar-02/logo";
52
53
  import type { Route } from "./nav-main";
53
54
  import DashboardNavigation from "@/components/layout/sidebar-02/nav-main";
54
55
  import { NotificationsPopover } from "@/components/layout/sidebar-02/nav-notifications";
56
+ import { AnimatedThemeToggler } from "@/components/magicui/animated-theme-toggler";
55
57
  import { AdminUserMenu } from "@/components/admin/admin-user-menu";
56
58
 
57
59
  function buildDashboardRoutes(): Route[] {
@@ -71,6 +73,8 @@ function buildDashboardRoutes(): Route[] {
71
73
  ],
72
74
  },
73
75
  { id: "ai-providers", title: m.common_nav_aiProviders(), icon: <Bot className="size-4" />, link: "/ai-providers" },
76
+ { id: "ai-prompts", title: m.common_nav_aiPrompts(), icon: <AlignLeft className="size-4" />, link: "/ai-prompts" },
77
+ { id: "ai-memory", title: m["admin-ai-memory_page_title"](), icon: <Brain className="size-4" />, link: "/ai-memory" },
74
78
  { id: "components", title: m.common_nav_components(), icon: <Layers className="size-4" />, link: "/components" },
75
79
  { id: "dependencies", title: m.common_nav_dependencies(), icon: <Boxes className="size-4" />, link: "/dependencies" },
76
80
  { id: "developer-logs", title: m.common_nav_developerLogs(), icon: <ScrollText className="size-4" />, link: "/developer-logs" },
@@ -107,12 +111,6 @@ function buildDashboardRoutes(): Route[] {
107
111
  ]
108
112
  }
109
113
 
110
- const teams = [
111
- { id: "1", name: "Alpha Inc.", logo: Logo, plan: "Free" },
112
- { id: "2", name: "Beta Corp.", logo: Logo, plan: "Free" },
113
- { id: "3", name: "Gamma Tech", logo: Logo, plan: "Free" },
114
- ];
115
-
116
114
  export function DashboardSidebar({ routes: propRoutes }: { routes?: Route[] }) {
117
115
  const { state } = useSidebar();
118
116
  const isCollapsed = state === "collapsed";
@@ -129,9 +127,18 @@ export function DashboardSidebar({ routes: propRoutes }: { routes?: Route[] }) {
129
127
  )}
130
128
  >
131
129
  <a href="#" className="flex items-center gap-2">
132
- <Logo className="h-8 w-8" />
130
+ <img
131
+ src="/logo/allblue-logo-dark.svg"
132
+ alt="AllBlue"
133
+ className="h-6 w-6 dark:hidden"
134
+ />
135
+ <img
136
+ src="/logo/allblue-logo-light.svg"
137
+ alt="AllBlue"
138
+ className="hidden h-6 w-6 dark:block"
139
+ />
133
140
  {!isCollapsed && (
134
- <span className="font-semibold text-black dark:text-white">
141
+ <span className="font-semibold text-foreground">
135
142
  Admin
136
143
  </span>
137
144
  )}
@@ -148,6 +155,7 @@ export function DashboardSidebar({ routes: propRoutes }: { routes?: Route[] }) {
148
155
  transition={{ duration: 0.8 }}
149
156
  >
150
157
  <NotificationsPopover notifications={[]} />
158
+ <AnimatedThemeToggler className="flex h-8 w-8 items-center justify-center rounded-full hover:bg-accent" />
151
159
  {!isCollapsed && <SidebarTrigger />}
152
160
  {isCollapsed && <SidebarTrigger />}
153
161
  </motion.div>
@@ -112,15 +112,11 @@ export default function DashboardNavigation({ routes }: { routes: Route[] }) {
112
112
  key={`${route.id}-${subRoute.title}`}
113
113
  className="h-auto"
114
114
  >
115
- <SidebarMenuSubButton asChild isActive={isActive(subRoute.link)}>
116
- <Link
117
- to={subRoute.link}
118
- className="flex items-center rounded-md px-4 py-1.5 text-sm font-medium"
119
- >
115
+ <SidebarMenuSubButton render={<Link to={subRoute.link}
116
+ className="flex items-center rounded-md px-4 py-1.5 text-sm font-medium" />} isActive={isActive(subRoute.link)}>
120
117
  {subRoute.icon}
121
118
  {subRoute.title}
122
- </Link>
123
- </SidebarMenuSubButton>
119
+ </SidebarMenuSubButton>
124
120
  </SidebarMenuSubItem>
125
121
  ))}
126
122
  </SidebarMenuSub>
@@ -128,22 +124,18 @@ export default function DashboardNavigation({ routes }: { routes: Route[] }) {
128
124
  )}
129
125
  </Collapsible>
130
126
  ) : (
131
- <SidebarMenuButton asChild tooltip={route.title} isActive={active} >
132
- <Link
133
- to={route.link}
127
+ <SidebarMenuButton render={<Link to={route.link}
134
128
  className={cn(
135
129
  "flex items-center rounded-lg px-2 ",
136
130
  isCollapsed && "justify-center"
137
- )}
138
- >
131
+ )} />} tooltip={route.title} isActive={active}>
139
132
  {route.icon}
140
133
  {!isCollapsed && (
141
134
  <span className="ml-2 text-sm font-medium">
142
135
  {route.title}
143
136
  </span>
144
137
  )}
145
- </Link>
146
- </SidebarMenuButton>
138
+ </SidebarMenuButton>
147
139
  )}
148
140
  </SidebarMenuItem>
149
141
  );
@@ -43,16 +43,12 @@ export function NotificationsPopover({
43
43
  }) {
44
44
  return (
45
45
  <DropdownMenu>
46
- <DropdownMenuTrigger asChild>
47
- <Button
48
- variant="ghost"
46
+ <DropdownMenuTrigger render={<Button variant="ghost"
49
47
  size="icon"
50
48
  className="rounded-full"
51
- aria-label="Open notifications"
52
- >
49
+ aria-label="Open notifications" />}>
53
50
  <BellIcon className="size-5" />
54
- </Button>
55
- </DropdownMenuTrigger>
51
+ </DropdownMenuTrigger>
56
52
  <DropdownMenuContent side="right" className="w-80 my-6">
57
53
  <DropdownMenuLabel>Notifications</DropdownMenuLabel>
58
54
  <DropdownMenuSeparator />
@@ -34,9 +34,9 @@ const rainbowButtonVariants = cva(
34
34
  variants: {
35
35
  variant: {
36
36
  default:
37
- "border-0 bg-[linear-gradient(#121213,#121213),linear-gradient(#121213_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))] bg-[length:200%] text-primary-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.125rem)_solid_transparent] before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))] before:bg-[length:200%] before:[filter:blur(0.75rem)] dark:bg-[linear-gradient(#fff,#fff),linear-gradient(#fff_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))]",
37
+ "border-0 bg-[linear-gradient(#121213,#121213),linear-gradient(#121213_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-accent-1),var(--color-accent-5),var(--color-accent-3),var(--color-accent-4),var(--color-accent-2))] bg-[length:200%] text-primary-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.125rem)_solid_transparent] before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-accent-1),var(--color-accent-5),var(--color-accent-3),var(--color-accent-4),var(--color-accent-2))] before:bg-[length:200%] before:[filter:blur(0.75rem)] dark:bg-[linear-gradient(#fff,#fff),linear-gradient(#fff_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-accent-1),var(--color-accent-5),var(--color-accent-3),var(--color-accent-4),var(--color-accent-2))]",
38
38
  outline:
39
- "border border-input border-b-transparent bg-[linear-gradient(#ffffff,#ffffff),linear-gradient(#ffffff_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))] bg-[length:200%] text-accent-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))] before:bg-[length:200%] before:[filter:blur(0.75rem)] dark:bg-[linear-gradient(#0a0a0a,#0a0a0a),linear-gradient(#0a0a0a_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))]",
39
+ "border border-input border-b-transparent bg-[linear-gradient(#ffffff,#ffffff),linear-gradient(#ffffff_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-accent-1),var(--color-accent-5),var(--color-accent-3),var(--color-accent-4),var(--color-accent-2))] bg-[length:200%] text-accent-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-accent-1),var(--color-accent-5),var(--color-accent-3),var(--color-accent-4),var(--color-accent-2))] before:bg-[length:200%] before:[filter:blur(0.75rem)] dark:bg-[linear-gradient(#0a0a0a,#0a0a0a),linear-gradient(#0a0a0a_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-accent-1),var(--color-accent-5),var(--color-accent-3),var(--color-accent-4),var(--color-accent-2))]",
40
40
  },
41
41
  size: {
42
42
  default: "h-9 px-4 py-2",
@@ -113,11 +113,9 @@ export function getMarketColumns(
113
113
  const app = row.original
114
114
  return (
115
115
  <DropdownMenu>
116
- <DropdownMenuTrigger asChild>
117
- <Button variant="ghost" size="icon" className="size-8">
116
+ <DropdownMenuTrigger render={<Button variant="ghost" size="icon" className="size-8" />}>
118
117
  <MoreHorizontalIcon className="size-4" />
119
- </Button>
120
- </DropdownMenuTrigger>
118
+ </DropdownMenuTrigger>
121
119
  <DropdownMenuContent align="end">
122
120
  <DropdownMenuItem onClick={() => onEdit(app)}>
123
121
  <PencilIcon className="mr-2 size-4" />
@@ -37,7 +37,7 @@ import {
37
37
  SelectTrigger,
38
38
  SelectValue,
39
39
  } from "@/components/ui/select"
40
- import { toast } from '@/components/ui/sonner'
40
+ import { toast } from '@/components/ui/toast'
41
41
 
42
42
  interface MarketAppFormProps {
43
43
  open: boolean
@@ -178,7 +178,7 @@ export function MarketAppForm({ open, onOpenChange, editData, onSuccess }: Marke
178
178
 
179
179
  <div className="grid gap-2">
180
180
  <Label>{m.common_market_form_category()}</Label>
181
- <Select value={form.category || ""} onValueChange={(v: string) => updateField("category", v === "__none__" ? "" : v)}>
181
+ <Select value={form.category || ""} onValueChange={(v) => updateField("category", v === "__none__" ? "" : (v ?? ""))}>
182
182
  <SelectTrigger>
183
183
  <SelectValue placeholder={m.common_market_form_categoryPlaceholder()} />
184
184
  </SelectTrigger>
@@ -23,7 +23,7 @@ import { MarketAppForm } from "./market-app-form"
23
23
  import { MarketAppFormData } from "@/lib/anyhub/types"
24
24
  import { Button } from "@/components/ui/button"
25
25
  import { PlusIcon } from "lucide-react"
26
- import { toast } from '@/components/ui/sonner'
26
+ import { toast } from '@/components/ui/toast'
27
27
  import { listMarketAppsFn, updateMarketAppFn, deleteMarketAppFn } from "@/server/serverFns/anyhub/market"
28
28
  import {
29
29
  AlertDialog,
@@ -19,7 +19,7 @@ import { useEffect, useState } from 'react'
19
19
  import type React from 'react'
20
20
  import { m } from '@/paraglide/messages.js'
21
21
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
22
- import { toast } from 'sonner'
22
+ import { toast } from '@/components/ui/toast'
23
23
  import { Eye, EyeOff, KeyRound, PlugZap, Save, Trash2 } from 'lucide-react'
24
24
  import { PageHeader } from '@/components/common/page-header'
25
25
  import { Button } from '@/components/ui/button'
@@ -1,45 +1,22 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // AllBlue - 理想之海
3
- // Copyright (C) 2026 AllBlue Contributors
4
- //
5
- // This program is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Affero General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // This program is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Affero General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Affero General Public License
16
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
-
18
1
  "use client"
19
2
 
20
3
  import * as React from "react"
21
- import { AlertDialog as AlertDialogPrimitive } from "radix-ui"
4
+ import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"
5
+ import { cn } from "cn"
22
6
 
23
- import { cn } from "@/lib/utils"
24
7
  import { Button } from "@/components/ui/button"
25
8
 
26
- function AlertDialog({
27
- ...props
28
- }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
9
+ function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
29
10
  return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
30
11
  }
31
12
 
32
- function AlertDialogTrigger({
33
- ...props
34
- }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
13
+ function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
35
14
  return (
36
15
  <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
37
16
  )
38
17
  }
39
18
 
40
- function AlertDialogPortal({
41
- ...props
42
- }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
19
+ function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
43
20
  return (
44
21
  <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
45
22
  )
@@ -48,12 +25,12 @@ function AlertDialogPortal({
48
25
  function AlertDialogOverlay({
49
26
  className,
50
27
  ...props
51
- }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
28
+ }: AlertDialogPrimitive.Backdrop.Props) {
52
29
  return (
53
- <AlertDialogPrimitive.Overlay
30
+ <AlertDialogPrimitive.Backdrop
54
31
  data-slot="alert-dialog-overlay"
55
32
  className={cn(
56
- "fixed inset-0 z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
33
+ "fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
57
34
  className
58
35
  )}
59
36
  {...props}
@@ -65,17 +42,17 @@ function AlertDialogContent({
65
42
  className,
66
43
  size = "default",
67
44
  ...props
68
- }: React.ComponentProps<typeof AlertDialogPrimitive.Content> & {
45
+ }: AlertDialogPrimitive.Popup.Props & {
69
46
  size?: "default" | "sm"
70
47
  }) {
71
48
  return (
72
49
  <AlertDialogPortal>
73
50
  <AlertDialogOverlay />
74
- <AlertDialogPrimitive.Content
51
+ <AlertDialogPrimitive.Popup
75
52
  data-slot="alert-dialog-content"
76
53
  data-size={size}
77
54
  className={cn(
78
- "group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
55
+ "group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-6 rounded-xl bg-popover p-6 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
79
56
  className
80
57
  )}
81
58
  {...props}
@@ -92,7 +69,7 @@ function AlertDialogHeader({
92
69
  <div
93
70
  data-slot="alert-dialog-header"
94
71
  className={cn(
95
- "grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
72
+ "grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
96
73
  className
97
74
  )}
98
75
  {...props}
@@ -108,7 +85,7 @@ function AlertDialogFooter({
108
85
  <div
109
86
  data-slot="alert-dialog-footer"
110
87
  className={cn(
111
- "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
88
+ "flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
112
89
  className
113
90
  )}
114
91
  {...props}
@@ -124,7 +101,7 @@ function AlertDialogMedia({
124
101
  <div
125
102
  data-slot="alert-dialog-media"
126
103
  className={cn(
127
- "mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
104
+ "mb-2 inline-flex size-16 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-8",
128
105
  className
129
106
  )}
130
107
  {...props}
@@ -140,7 +117,7 @@ function AlertDialogTitle({
140
117
  <AlertDialogPrimitive.Title
141
118
  data-slot="alert-dialog-title"
142
119
  className={cn(
143
- "text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
120
+ "font-heading text-lg font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
144
121
  className
145
122
  )}
146
123
  {...props}
@@ -166,19 +143,14 @@ function AlertDialogDescription({
166
143
 
167
144
  function AlertDialogAction({
168
145
  className,
169
- variant = "default",
170
- size = "default",
171
146
  ...props
172
- }: React.ComponentProps<typeof AlertDialogPrimitive.Action> &
173
- Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
147
+ }: React.ComponentProps<typeof Button>) {
174
148
  return (
175
- <Button variant={variant} size={size} asChild>
176
- <AlertDialogPrimitive.Action
177
- data-slot="alert-dialog-action"
178
- className={cn(className)}
179
- {...props}
180
- />
181
- </Button>
149
+ <Button
150
+ data-slot="alert-dialog-action"
151
+ className={cn(className)}
152
+ {...props}
153
+ />
182
154
  )
183
155
  }
184
156
 
@@ -187,16 +159,15 @@ function AlertDialogCancel({
187
159
  variant = "outline",
188
160
  size = "default",
189
161
  ...props
190
- }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel> &
162
+ }: AlertDialogPrimitive.Close.Props &
191
163
  Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
192
164
  return (
193
- <Button variant={variant} size={size} asChild>
194
- <AlertDialogPrimitive.Cancel
195
- data-slot="alert-dialog-cancel"
196
- className={cn(className)}
197
- {...props}
198
- />
199
- </Button>
165
+ <AlertDialogPrimitive.Close
166
+ data-slot="alert-dialog-cancel"
167
+ className={cn(className)}
168
+ render={<Button variant={variant} size={size} />}
169
+ {...props}
170
+ />
200
171
  )
201
172
  }
202
173
 
@@ -1,10 +1,9 @@
1
1
  import * as React from "react"
2
2
  import { cva, type VariantProps } from "class-variance-authority"
3
-
4
- import { cn } from "@/lib/utils"
3
+ import { cn } from "cn"
5
4
 
6
5
  const alertVariants = cva(
7
- "group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
6
+ "group/alert relative grid w-full gap-0.5 rounded-lg border px-4 py-3 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
8
7
  {
9
8
  variants: {
10
9
  variant: {
@@ -67,7 +66,7 @@ function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
67
66
  return (
68
67
  <div
69
68
  data-slot="alert-action"
70
- className={cn("absolute top-2 right-2", className)}
69
+ className={cn("absolute top-2.5 right-3", className)}
71
70
  {...props}
72
71
  />
73
72
  )
@@ -1,32 +1,12 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // AllBlue - 理想之海
3
- // Copyright (C) 2026 AllBlue Contributors
4
- //
5
- // This program is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Affero General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // This program is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Affero General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Affero General Public License
16
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
-
18
- "use client"
19
-
20
1
  import * as React from "react"
21
- import { Avatar as AvatarPrimitive } from "radix-ui"
22
-
23
- import { cn } from "@/lib/utils"
2
+ import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar"
3
+ import { cn } from "cn"
24
4
 
25
5
  function Avatar({
26
6
  className,
27
7
  size = "default",
28
8
  ...props
29
- }: React.ComponentProps<typeof AvatarPrimitive.Root> & {
9
+ }: AvatarPrimitive.Root.Props & {
30
10
  size?: "default" | "sm" | "lg"
31
11
  }) {
32
12
  return (
@@ -42,10 +22,7 @@ function Avatar({
42
22
  )
43
23
  }
44
24
 
45
- function AvatarImage({
46
- className,
47
- ...props
48
- }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
25
+ function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {
49
26
  return (
50
27
  <AvatarPrimitive.Image
51
28
  data-slot="avatar-image"
@@ -61,7 +38,7 @@ function AvatarImage({
61
38
  function AvatarFallback({
62
39
  className,
63
40
  ...props
64
- }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
41
+ }: AvatarPrimitive.Fallback.Props) {
65
42
  return (
66
43
  <AvatarPrimitive.Fallback
67
44
  data-slot="avatar-fallback"