@allbluecn/admin-app 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) 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/messages/_index.js +95 -0
  65. package/src/paraglide/messages/admin_ai_memory_action_clearuser1.js +30 -0
  66. package/src/paraglide/messages/admin_ai_memory_action_query.js +30 -0
  67. package/src/paraglide/messages/admin_ai_memory_clear_cancel.js +30 -0
  68. package/src/paraglide/messages/admin_ai_memory_clear_confirm_action.js +30 -0
  69. package/src/paraglide/messages/admin_ai_memory_clear_confirm_description.js +30 -0
  70. package/src/paraglide/messages/admin_ai_memory_clear_confirm_title.js +30 -0
  71. package/src/paraglide/messages/admin_ai_memory_columns_actions.js +30 -0
  72. package/src/paraglide/messages/admin_ai_memory_columns_content.js +30 -0
  73. package/src/paraglide/messages/admin_ai_memory_columns_createdat1.js +30 -0
  74. package/src/paraglide/messages/admin_ai_memory_columns_threadid1.js +30 -0
  75. package/src/paraglide/messages/admin_ai_memory_delete_cancel.js +30 -0
  76. package/src/paraglide/messages/admin_ai_memory_delete_confirm_action.js +30 -0
  77. package/src/paraglide/messages/admin_ai_memory_delete_confirm_description.js +30 -0
  78. package/src/paraglide/messages/admin_ai_memory_delete_confirm_title.js +30 -0
  79. package/src/paraglide/messages/admin_ai_memory_empty.js +30 -0
  80. package/src/paraglide/messages/admin_ai_memory_emptyhint1.js +30 -0
  81. package/src/paraglide/messages/admin_ai_memory_error_nouserid2.js +30 -0
  82. package/src/paraglide/messages/admin_ai_memory_error_query.js +30 -0
  83. package/src/paraglide/messages/admin_ai_memory_error_title.js +30 -0
  84. package/src/paraglide/messages/admin_ai_memory_form_user.js +30 -0
  85. package/src/paraglide/messages/admin_ai_memory_page_description.js +30 -0
  86. package/src/paraglide/messages/admin_ai_memory_page_title.js +30 -0
  87. package/src/paraglide/messages/admin_ai_memory_placeholder_user.js +30 -0
  88. package/src/paraglide/messages/admin_ai_memory_stat_count.js +30 -0
  89. package/src/paraglide/messages/admin_ai_memory_stat_lastwrite1.js +30 -0
  90. package/src/paraglide/messages/admin_ai_memory_toast_cleared.js +30 -0
  91. package/src/paraglide/messages/admin_ai_memory_toast_deleted.js +30 -0
  92. package/src/paraglide/messages/admin_ai_prompts_active.js +30 -0
  93. package/src/paraglide/messages/admin_ai_prompts_back.js +30 -0
  94. package/src/paraglide/messages/admin_ai_prompts_badge_protected.js +30 -0
  95. package/src/paraglide/messages/admin_ai_prompts_cache_hint.js +30 -0
  96. package/src/paraglide/messages/admin_ai_prompts_columns_active.js +30 -0
  97. package/src/paraglide/messages/admin_ai_prompts_columns_key.js +30 -0
  98. package/src/paraglide/messages/admin_ai_prompts_columns_name.js +30 -0
  99. package/src/paraglide/messages/admin_ai_prompts_columns_protected.js +30 -0
  100. package/src/paraglide/messages/admin_ai_prompts_columns_updatedat1.js +30 -0
  101. package/src/paraglide/messages/admin_ai_prompts_columns_version.js +30 -0
  102. package/src/paraglide/messages/admin_ai_prompts_description.js +30 -0
  103. package/src/paraglide/messages/admin_ai_prompts_description_placeholder.js +30 -0
  104. package/src/paraglide/messages/admin_ai_prompts_edit.js +30 -0
  105. package/src/paraglide/messages/admin_ai_prompts_name.js +30 -0
  106. package/src/paraglide/messages/admin_ai_prompts_name_placeholder.js +30 -0
  107. package/src/paraglide/messages/admin_ai_prompts_note_placeholder.js +30 -0
  108. package/src/paraglide/messages/admin_ai_prompts_page_description.js +30 -0
  109. package/src/paraglide/messages/admin_ai_prompts_page_title.js +30 -0
  110. package/src/paraglide/messages/admin_ai_prompts_preview_empty.js +30 -0
  111. package/src/paraglide/messages/admin_ai_prompts_preview_generating.js +30 -0
  112. package/src/paraglide/messages/admin_ai_prompts_preview_hint.js +30 -0
  113. package/src/paraglide/messages/admin_ai_prompts_preview_nocontent1.js +30 -0
  114. package/src/paraglide/messages/admin_ai_prompts_preview_placeholder.js +30 -0
  115. package/src/paraglide/messages/admin_ai_prompts_preview_section.js +30 -0
  116. package/src/paraglide/messages/admin_ai_prompts_preview_title.js +30 -0
  117. package/src/paraglide/messages/admin_ai_prompts_protected_hint.js +30 -0
  118. package/src/paraglide/messages/admin_ai_prompts_rollback.js +30 -0
  119. package/src/paraglide/messages/admin_ai_prompts_rollback_confirm_action.js +30 -0
  120. package/src/paraglide/messages/admin_ai_prompts_rollback_confirm_description.js +30 -0
  121. package/src/paraglide/messages/admin_ai_prompts_rollback_confirm_title.js +30 -0
  122. package/src/paraglide/messages/admin_ai_prompts_save.js +30 -0
  123. package/src/paraglide/messages/admin_ai_prompts_section_add.js +30 -0
  124. package/src/paraglide/messages/admin_ai_prompts_section_id.js +30 -0
  125. package/src/paraglide/messages/admin_ai_prompts_section_movedown1.js +30 -0
  126. package/src/paraglide/messages/admin_ai_prompts_section_moveup1.js +30 -0
  127. package/src/paraglide/messages/admin_ai_prompts_section_order.js +30 -0
  128. package/src/paraglide/messages/admin_ai_prompts_section_remove.js +30 -0
  129. package/src/paraglide/messages/admin_ai_prompts_section_template_placeholder.js +30 -0
  130. package/src/paraglide/messages/admin_ai_prompts_sections_empty.js +30 -0
  131. package/src/paraglide/messages/admin_ai_prompts_sections_hint.js +30 -0
  132. package/src/paraglide/messages/admin_ai_prompts_sections_title.js +30 -0
  133. package/src/paraglide/messages/admin_ai_prompts_toast_activated.js +30 -0
  134. package/src/paraglide/messages/admin_ai_prompts_toast_failed.js +30 -0
  135. package/src/paraglide/messages/admin_ai_prompts_toast_protected_locked.js +30 -0
  136. package/src/paraglide/messages/admin_ai_prompts_toast_rolled_back.js +30 -0
  137. package/src/paraglide/messages/admin_ai_prompts_toast_save_failed.js +30 -0
  138. package/src/paraglide/messages/admin_ai_prompts_toast_saved.js +30 -0
  139. package/src/paraglide/messages/admin_ai_prompts_variable_add.js +30 -0
  140. package/src/paraglide/messages/admin_ai_prompts_variable_declarehint1.js +30 -0
  141. package/src/paraglide/messages/admin_ai_prompts_variable_description_placeholder.js +30 -0
  142. package/src/paraglide/messages/admin_ai_prompts_variable_name_placeholder.js +30 -0
  143. package/src/paraglide/messages/admin_ai_prompts_variable_remove.js +30 -0
  144. package/src/paraglide/messages/admin_ai_prompts_variable_undeclared.js +30 -0
  145. package/src/paraglide/messages/admin_ai_prompts_variables_empty.js +30 -0
  146. package/src/paraglide/messages/admin_ai_prompts_variables_title.js +30 -0
  147. package/src/paraglide/messages/admin_ai_prompts_versions_current.js +30 -0
  148. package/src/paraglide/messages/admin_ai_prompts_versions_empty.js +30 -0
  149. package/src/paraglide/messages/admin_ai_prompts_versions_hint.js +30 -0
  150. package/src/paraglide/messages/admin_ai_prompts_versions_nonote1.js +30 -0
  151. package/src/paraglide/messages/admin_ai_prompts_versions_title.js +30 -0
  152. package/src/paraglide/messages/admin_ai_prompts_versions_unknowncreator1.js +30 -0
  153. package/src/paraglide/messages/admin_ai_table_seedfromseed2.js +30 -0
  154. package/src/paraglide/messages/admin_ai_table_toast_seedcreated1.js +30 -0
  155. package/src/paraglide/messages/admin_ai_table_toast_seedfailed1.js +30 -0
  156. package/src/paraglide/messages/admin_ai_table_toast_seednonew2.js +30 -0
  157. package/src/paraglide/messages/common_monitoring_aiusage_sandbox1.js +30 -0
  158. package/src/paraglide/messages/common_monitoring_aiusage_sandboxvalue2.js +30 -0
  159. package/src/paraglide/messages/common_nav_aiprompts1.js +30 -0
  160. package/src/routeTree.gen.ts +101 -0
  161. package/src/routes/__root.tsx +2 -2
  162. package/src/{components/ui/sonner.tsx → routes/_nav/ai-memory/route.lazy.tsx} +24 -16
  163. package/src/routes/_nav/ai-memory/route.tsx +31 -0
  164. package/src/routes/_nav/ai-prompts/$key/route.lazy.tsx +32 -0
  165. package/src/routes/_nav/ai-prompts/$key/route.tsx +37 -0
  166. package/src/routes/_nav/ai-prompts/index/route.lazy.tsx +47 -0
  167. package/src/routes/_nav/ai-prompts/route.lazy.tsx +26 -0
  168. package/src/routes/_nav/ai-prompts/route.tsx +31 -0
  169. package/src/routes/_nav/compliance/route.lazy.tsx +2 -4
  170. package/src/routes/_nav/components/route.lazy.tsx +1 -1
  171. package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +1 -1
  172. package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +1 -1
  173. package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +1 -1
  174. package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +1 -1
  175. package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +10 -1
  176. package/src/routes/_nav/monitoring/errors/route.lazy.tsx +1 -1
  177. package/src/routes/_nav/monitoring/health/route.lazy.tsx +1 -1
  178. package/src/routes/_nav/monitoring/logs/route.lazy.tsx +1 -1
  179. package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +1 -1
  180. package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +1 -1
  181. package/src/routes/_nav/permissions/route.lazy.tsx +2 -2
  182. package/src/routes/_nav/sso/route.lazy.tsx +1 -1
  183. package/src/routes/_nav/users/$userId/route.lazy.tsx +3 -3
  184. package/src/routes/setup/route.lazy.tsx +1 -1
  185. package/src/server/__tests__/prompt-defaults.test.ts +139 -0
  186. package/src/server/admin-ai-usage.ts +22 -4
  187. package/src/server/ai-memory/store.ts +103 -0
  188. package/src/server/serverFns/ai-memory/clear.ts +31 -0
  189. package/src/server/serverFns/ai-memory/delete.ts +31 -0
  190. package/src/server/serverFns/ai-memory/list-users.ts +40 -0
  191. package/src/server/serverFns/ai-memory/list.ts +54 -0
  192. package/src/server/serverFns/ai-prompts/activate.ts +53 -0
  193. package/src/server/serverFns/ai-prompts/get.ts +74 -0
  194. package/src/server/serverFns/ai-prompts/list.ts +55 -0
  195. package/src/server/serverFns/ai-prompts/preview.ts +66 -0
  196. package/src/server/serverFns/ai-prompts/prompt-defaults.ts +63 -0
  197. package/src/server/serverFns/ai-prompts/prompt-schemas.ts +47 -0
  198. package/src/server/serverFns/ai-prompts/rollback.ts +86 -0
  199. package/src/server/serverFns/ai-prompts/save.ts +129 -0
  200. package/src/server/serverFns/ai-provider/seed-from-seed.ts +64 -0
  201. package/src/styles/globals.css +92 -77
  202. package/src/components/layout/sidebar-02/logo.tsx +0 -40
  203. package/src/components/layout/sidebar-02/team-switcher.tsx +0 -106
  204. package/src/components/providers/theme-toggle.tsx +0 -59
@@ -1,28 +1,10 @@
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"
2
+ import { mergeProps } from "@base-ui/react/merge-props"
3
+ import { useRender } from "@base-ui/react/use-render"
21
4
  import { cva, type VariantProps } from "class-variance-authority"
22
- import { Slot } from "radix-ui"
5
+ import { cn } from "cn"
23
6
 
24
7
  import { useIsMobile } from "@/hooks/use-mobile"
25
- import { cn } from "@/lib/utils"
26
8
  import { Button } from "@/components/ui/button"
27
9
  import { Input } from "@/components/ui/input"
28
10
  import { Separator } from "@/components/ui/separator"
@@ -258,7 +240,7 @@ function Sidebar({
258
240
  <div
259
241
  data-sidebar="sidebar"
260
242
  data-slot="sidebar-inner"
261
- className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm"
243
+ className="flex size-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border"
262
244
  >
263
245
  {children}
264
246
  </div>
@@ -281,7 +263,7 @@ function SidebarTrigger({
281
263
  variant="ghost"
282
264
  size="icon-sm"
283
265
  className={cn(className)}
284
- onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
266
+ onClick={(event) => {
285
267
  onClick?.(event)
286
268
  toggleSidebar()
287
269
  }}
@@ -387,7 +369,7 @@ function SidebarContent({ className, ...props }: React.ComponentProps<"div">) {
387
369
  data-slot="sidebar-content"
388
370
  data-sidebar="content"
389
371
  className={cn(
390
- "no-scrollbar flex min-h-0 flex-1 flex-col gap-0 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
372
+ "no-scrollbar flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
391
373
  className
392
374
  )}
393
375
  {...props}
@@ -408,42 +390,50 @@ function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) {
408
390
 
409
391
  function SidebarGroupLabel({
410
392
  className,
411
- asChild = false,
393
+ render,
412
394
  ...props
413
- }: React.ComponentProps<"div"> & { asChild?: boolean }) {
414
- const Comp = asChild ? Slot.Root : "div"
415
-
416
- return (
417
- <Comp
418
- data-slot="sidebar-group-label"
419
- data-sidebar="group-label"
420
- className={cn(
421
- "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
422
- className
423
- )}
424
- {...props}
425
- />
426
- )
395
+ }: useRender.ComponentProps<"div"> & React.ComponentProps<"div">) {
396
+ return useRender({
397
+ defaultTagName: "div",
398
+ props: mergeProps<"div">(
399
+ {
400
+ className: cn(
401
+ "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
402
+ className
403
+ ),
404
+ },
405
+ props
406
+ ),
407
+ render,
408
+ state: {
409
+ slot: "sidebar-group-label",
410
+ sidebar: "group-label",
411
+ },
412
+ })
427
413
  }
428
414
 
429
415
  function SidebarGroupAction({
430
416
  className,
431
- asChild = false,
417
+ render,
432
418
  ...props
433
- }: React.ComponentProps<"button"> & { asChild?: boolean }) {
434
- const Comp = asChild ? Slot.Root : "button"
435
-
436
- return (
437
- <Comp
438
- data-slot="sidebar-group-action"
439
- data-sidebar="group-action"
440
- className={cn(
441
- "absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
442
- className
443
- )}
444
- {...props}
445
- />
446
- )
419
+ }: useRender.ComponentProps<"button"> & React.ComponentProps<"button">) {
420
+ return useRender({
421
+ defaultTagName: "button",
422
+ props: mergeProps<"button">(
423
+ {
424
+ className: cn(
425
+ "absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
426
+ className
427
+ ),
428
+ },
429
+ props
430
+ ),
431
+ render,
432
+ state: {
433
+ slot: "sidebar-group-action",
434
+ sidebar: "group-action",
435
+ },
436
+ })
447
437
  }
448
438
 
449
439
  function SidebarGroupContent({
@@ -465,7 +455,7 @@ function SidebarMenu({ className, ...props }: React.ComponentProps<"ul">) {
465
455
  <ul
466
456
  data-slot="sidebar-menu"
467
457
  data-sidebar="menu"
468
- className={cn("flex w-full min-w-0 flex-col gap-0", className)}
458
+ className={cn("flex w-full min-w-0 flex-col gap-1", className)}
469
459
  {...props}
470
460
  />
471
461
  )
@@ -483,7 +473,7 @@ function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) {
483
473
  }
484
474
 
485
475
  const sidebarMenuButtonVariants = cva(
486
- "peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate cursor-pointer",
476
+ "peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate",
487
477
  {
488
478
  variants: {
489
479
  variant: {
@@ -505,34 +495,38 @@ const sidebarMenuButtonVariants = cva(
505
495
  )
506
496
 
507
497
  function SidebarMenuButton({
508
- asChild = false,
498
+ render,
509
499
  isActive = false,
510
500
  variant = "default",
511
501
  size = "default",
512
502
  tooltip,
513
503
  className,
514
504
  ...props
515
- }: React.ComponentProps<"button"> & {
516
- asChild?: boolean
517
- isActive?: boolean
518
- tooltip?: string | React.ComponentProps<typeof TooltipContent>
519
- } & VariantProps<typeof sidebarMenuButtonVariants>) {
520
- const Comp = asChild ? Slot.Root : "button"
505
+ }: useRender.ComponentProps<"button"> &
506
+ React.ComponentProps<"button"> & {
507
+ isActive?: boolean
508
+ tooltip?: string | React.ComponentProps<typeof TooltipContent>
509
+ } & VariantProps<typeof sidebarMenuButtonVariants>) {
521
510
  const { isMobile, state } = useSidebar()
522
-
523
- const button = (
524
- <Comp
525
- data-slot="sidebar-menu-button"
526
- data-sidebar="menu-button"
527
- data-size={size}
528
- data-active={isActive || undefined}
529
- className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
530
- {...props}
531
- />
532
- )
511
+ const comp = useRender({
512
+ defaultTagName: "button",
513
+ props: mergeProps<"button">(
514
+ {
515
+ className: cn(sidebarMenuButtonVariants({ variant, size }), className),
516
+ },
517
+ props
518
+ ),
519
+ render: !tooltip ? render : <TooltipTrigger render={render} />,
520
+ state: {
521
+ slot: "sidebar-menu-button",
522
+ sidebar: "menu-button",
523
+ size,
524
+ active: isActive,
525
+ },
526
+ })
533
527
 
534
528
  if (!tooltip) {
535
- return button
529
+ return comp
536
530
  }
537
531
 
538
532
  if (typeof tooltip === "string") {
@@ -543,7 +537,7 @@ function SidebarMenuButton({
543
537
 
544
538
  return (
545
539
  <Tooltip>
546
- <TooltipTrigger asChild>{button}</TooltipTrigger>
540
+ {comp}
547
541
  <TooltipContent
548
542
  side="right"
549
543
  align="center"
@@ -556,28 +550,32 @@ function SidebarMenuButton({
556
550
 
557
551
  function SidebarMenuAction({
558
552
  className,
559
- asChild = false,
553
+ render,
560
554
  showOnHover = false,
561
555
  ...props
562
- }: React.ComponentProps<"button"> & {
563
- asChild?: boolean
564
- showOnHover?: boolean
565
- }) {
566
- const Comp = asChild ? Slot.Root : "button"
567
-
568
- return (
569
- <Comp
570
- data-slot="sidebar-menu-action"
571
- data-sidebar="menu-action"
572
- className={cn(
573
- "absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
574
- showOnHover &&
575
- "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-active/menu-button:text-sidebar-accent-foreground aria-expanded:opacity-100 md:opacity-0",
576
- className
577
- )}
578
- {...props}
579
- />
580
- )
556
+ }: useRender.ComponentProps<"button"> &
557
+ React.ComponentProps<"button"> & {
558
+ showOnHover?: boolean
559
+ }) {
560
+ return useRender({
561
+ defaultTagName: "button",
562
+ props: mergeProps<"button">(
563
+ {
564
+ className: cn(
565
+ "absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
566
+ showOnHover &&
567
+ "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-active/menu-button:text-sidebar-accent-foreground aria-expanded:opacity-100 md:opacity-0",
568
+ className
569
+ ),
570
+ },
571
+ props
572
+ ),
573
+ render,
574
+ state: {
575
+ slot: "sidebar-menu-action",
576
+ sidebar: "menu-action",
577
+ },
578
+ })
581
579
  }
582
580
 
583
581
  function SidebarMenuBadge({
@@ -664,31 +662,35 @@ function SidebarMenuSubItem({
664
662
  }
665
663
 
666
664
  function SidebarMenuSubButton({
667
- asChild = false,
665
+ render,
668
666
  size = "md",
669
667
  isActive = false,
670
668
  className,
671
669
  ...props
672
- }: React.ComponentProps<"a"> & {
673
- asChild?: boolean
674
- size?: "sm" | "md"
675
- isActive?: boolean
676
- }) {
677
- const Comp = asChild ? Slot.Root : "a"
678
-
679
- return (
680
- <Comp
681
- data-slot="sidebar-menu-sub-button"
682
- data-sidebar="menu-sub-button"
683
- data-size={size}
684
- data-active={isActive || undefined}
685
- className={cn(
686
- "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-sm data-[size=sm]:text-xs data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground cursor-pointer",
687
- className
688
- )}
689
- {...props}
690
- />
691
- )
670
+ }: useRender.ComponentProps<"a"> &
671
+ React.ComponentProps<"a"> & {
672
+ size?: "sm" | "md"
673
+ isActive?: boolean
674
+ }) {
675
+ return useRender({
676
+ defaultTagName: "a",
677
+ props: mergeProps<"a">(
678
+ {
679
+ className: cn(
680
+ "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-sm data-[size=sm]:text-xs data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
681
+ className
682
+ ),
683
+ },
684
+ props
685
+ ),
686
+ render,
687
+ state: {
688
+ slot: "sidebar-menu-sub-button",
689
+ sidebar: "menu-sub-button",
690
+ size,
691
+ active: isActive,
692
+ },
693
+ })
692
694
  }
693
695
 
694
696
  export {
@@ -1,21 +1,4 @@
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
- import { cn } from "@/lib/utils"
1
+ import { cn } from "cn"
19
2
 
20
3
  function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
21
4
  return (
@@ -1,30 +1,11 @@
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
- import * as React from "react"
19
- import { Switch as SwitchPrimitive } from "radix-ui"
20
-
21
- import { cn } from "@/lib/utils"
1
+ import { Switch as SwitchPrimitive } from "@base-ui/react/switch"
2
+ import { cn } from "cn"
22
3
 
23
4
  function Switch({
24
5
  className,
25
6
  size = "default",
26
7
  ...props
27
- }: React.ComponentProps<typeof SwitchPrimitive.Root> & {
8
+ }: SwitchPrimitive.Root.Props & {
28
9
  size?: "sm" | "default"
29
10
  }) {
30
11
  return (
@@ -32,14 +13,14 @@ function Switch({
32
13
  data-slot="switch"
33
14
  data-size={size}
34
15
  className={cn(
35
- "peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50",
16
+ "peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none group-has-[:focus-visible]/field-label:border-transparent group-has-[:focus-visible]/field-label:ring-0 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50",
36
17
  className
37
18
  )}
38
19
  {...props}
39
20
  >
40
21
  <SwitchPrimitive.Thumb
41
22
  data-slot="switch-thumb"
42
- className="pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-[state=checked]:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-[state=checked]:translate-x-[calc(100%-2px)] dark:data-[state=checked]:bg-primary-foreground group-data-[size=default]/switch:data-[state=unchecked]:translate-x-0 group-data-[size=sm]/switch:data-[state=unchecked]:translate-x-0 dark:data-[state=unchecked]:bg-foreground"
23
+ className="pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] dark:data-checked:bg-primary-foreground group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 dark:data-unchecked:bg-foreground"
43
24
  />
44
25
  </SwitchPrimitive.Root>
45
26
  )
@@ -1,25 +1,7 @@
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
-
22
- import { cn } from "@/lib/utils"
4
+ import { cn } from "cn"
23
5
 
24
6
  function Table({ className, ...props }: React.ComponentProps<"table">) {
25
7
  return (
@@ -1,30 +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
1
  import * as React from "react"
19
-
20
- import { cn } from "@/lib/utils"
2
+ import { cn } from "cn"
21
3
 
22
4
  function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
23
5
  return (
24
6
  <textarea
25
7
  data-slot="textarea"
26
8
  className={cn(
27
- "flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
9
+ "flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-2.5 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
28
10
  className
29
11
  )}
30
12
  {...props}