@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,23 +1,6 @@
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"
2
+ import { cn } from "cn"
19
3
 
20
- import { cn } from "@/lib/utils"
21
4
  import { Button } from "@/components/ui/button"
22
5
  import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
23
6
 
@@ -40,7 +23,7 @@ function PaginationContent({
40
23
  return (
41
24
  <ul
42
25
  data-slot="pagination-content"
43
- className={cn("flex items-center gap-0.5", className)}
26
+ className={cn("flex items-center gap-1", className)}
44
27
  {...props}
45
28
  />
46
29
  )
@@ -63,18 +46,19 @@ function PaginationLink({
63
46
  }: PaginationLinkProps) {
64
47
  return (
65
48
  <Button
66
- asChild
67
49
  variant={isActive ? "outline" : "ghost"}
68
50
  size={size}
69
51
  className={cn(className)}
70
- >
71
- <a
72
- aria-current={isActive ? "page" : undefined}
73
- data-slot="pagination-link"
74
- data-active={isActive}
75
- {...props}
76
- />
77
- </Button>
52
+ nativeButton={false}
53
+ render={
54
+ <a
55
+ aria-current={isActive ? "page" : undefined}
56
+ data-slot="pagination-link"
57
+ data-active={isActive}
58
+ {...props}
59
+ />
60
+ }
61
+ />
78
62
  )
79
63
  }
80
64
 
@@ -86,7 +70,8 @@ function PaginationPrevious({
86
70
  return (
87
71
  <PaginationLink
88
72
  aria-label="Go to previous page"
89
- className={cn("pl-1.5!", className)}
73
+ size="default"
74
+ className={cn("pl-2!", className)}
90
75
  {...props}
91
76
  >
92
77
  <ChevronLeftIcon data-icon="inline-start" />
@@ -103,7 +88,8 @@ function PaginationNext({
103
88
  return (
104
89
  <PaginationLink
105
90
  aria-label="Go to next page"
106
- className={cn("pr-1.5!", className)}
91
+ size="default"
92
+ className={cn("pr-2!", className)}
107
93
  {...props}
108
94
  >
109
95
  <span className="hidden sm:block">{text}</span>
@@ -121,7 +107,7 @@ function PaginationEllipsis({
121
107
  aria-hidden
122
108
  data-slot="pagination-ellipsis"
123
109
  className={cn(
124
- "flex size-8 items-center justify-center [&_svg:not([class*='size-'])]:size-4",
110
+ "flex size-9 items-center justify-center [&_svg:not([class*='size-'])]:size-4",
125
111
  className
126
112
  )}
127
113
  {...props}
@@ -1,38 +1,47 @@
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 { Select as SelectPrimitive } from "radix-ui"
22
-
23
- import { cn } from "@/lib/utils"
4
+ import { Select as SelectPrimitive } from "@base-ui/react/select"
5
+ import { cn } from "cn"
24
6
  import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react"
25
7
 
26
- function Select({
27
- ...props
28
- }: React.ComponentProps<typeof SelectPrimitive.Root>) {
29
- return <SelectPrimitive.Root data-slot="select" {...props} />
8
+ type CollectedItem = {
9
+ label: React.ReactNode
10
+ value: any
30
11
  }
31
12
 
32
- function SelectGroup({
33
- className,
34
- ...props
35
- }: React.ComponentProps<typeof SelectPrimitive.Group>) {
13
+ function collectItems(children: React.ReactNode, acc: CollectedItem[] = []): CollectedItem[] {
14
+ React.Children.forEach(children, child => {
15
+ if (!React.isValidElement(child)) {
16
+ return
17
+ }
18
+ const el = child as React.ReactElement<any>
19
+ if (el.type === SelectItem) {
20
+ const { value, children: label } = el.props
21
+ if (value !== undefined) {
22
+ acc.push({ value, label })
23
+ }
24
+ return
25
+ }
26
+ if (el.props?.children) {
27
+ collectItems(el.props.children, acc)
28
+ }
29
+ })
30
+ return acc
31
+ }
32
+
33
+ function Select<Value, Multiple extends boolean | undefined = false>(
34
+ { children, items, ...props }: SelectPrimitive.Root.Props<Value, Multiple>
35
+ ) {
36
+ const resolvedItems = React.useMemo(() => items ?? collectItems(children), [items, children])
37
+ return (
38
+ <SelectPrimitive.Root items={resolvedItems} {...props}>
39
+ {children}
40
+ </SelectPrimitive.Root>
41
+ )
42
+ }
43
+
44
+ function SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {
36
45
  return (
37
46
  <SelectPrimitive.Group
38
47
  data-slot="select-group"
@@ -42,10 +51,14 @@ function SelectGroup({
42
51
  )
43
52
  }
44
53
 
45
- function SelectValue({
46
- ...props
47
- }: React.ComponentProps<typeof SelectPrimitive.Value>) {
48
- return <SelectPrimitive.Value data-slot="select-value" {...props} />
54
+ function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
55
+ return (
56
+ <SelectPrimitive.Value
57
+ data-slot="select-value"
58
+ className={cn("flex flex-1 text-left", className)}
59
+ {...props}
60
+ />
61
+ )
49
62
  }
50
63
 
51
64
  function SelectTrigger({
@@ -53,7 +66,7 @@ function SelectTrigger({
53
66
  size = "default",
54
67
  children,
55
68
  ...props
56
- }: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
69
+ }: SelectPrimitive.Trigger.Props & {
57
70
  size?: "sm" | "default"
58
71
  }) {
59
72
  return (
@@ -61,15 +74,17 @@ function SelectTrigger({
61
74
  data-slot="select-trigger"
62
75
  data-size={size}
63
76
  className={cn(
64
- "flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none 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 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
77
+ "flex w-fit items-center justify-between gap-1.5 rounded-md border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none 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 data-placeholder:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
65
78
  className
66
79
  )}
67
80
  {...props}
68
81
  >
69
82
  {children}
70
- <SelectPrimitive.Icon asChild>
71
- <ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
72
- </SelectPrimitive.Icon>
83
+ <SelectPrimitive.Icon
84
+ render={
85
+ <ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
86
+ }
87
+ />
73
88
  </SelectPrimitive.Trigger>
74
89
  )
75
90
  }
@@ -77,32 +92,38 @@ function SelectTrigger({
77
92
  function SelectContent({
78
93
  className,
79
94
  children,
80
- position = "item-aligned",
95
+ side = "bottom",
96
+ sideOffset = 4,
81
97
  align = "center",
98
+ alignOffset = 0,
99
+ alignItemWithTrigger = true,
82
100
  ...props
83
- }: React.ComponentProps<typeof SelectPrimitive.Content>) {
101
+ }: SelectPrimitive.Popup.Props &
102
+ Pick<
103
+ SelectPrimitive.Positioner.Props,
104
+ "align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger"
105
+ >) {
84
106
  return (
85
107
  <SelectPrimitive.Portal>
86
- <SelectPrimitive.Content
87
- data-slot="select-content"
88
- data-align-trigger={position === "item-aligned"}
89
- className={cn("relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 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", position ==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className )}
90
- position={position}
108
+ <SelectPrimitive.Positioner
109
+ side={side}
110
+ sideOffset={sideOffset}
91
111
  align={align}
92
- {...props}
112
+ alignOffset={alignOffset}
113
+ alignItemWithTrigger={alignItemWithTrigger}
114
+ className="isolate z-50"
93
115
  >
94
- <SelectScrollUpButton />
95
- <SelectPrimitive.Viewport
96
- data-position={position}
97
- className={cn(
98
- "data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)",
99
- position === "popper" && ""
100
- )}
116
+ <SelectPrimitive.Popup
117
+ data-slot="select-content"
118
+ data-align-trigger={alignItemWithTrigger}
119
+ className={cn("relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-md bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 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", className )}
120
+ {...props}
101
121
  >
102
- {children}
103
- </SelectPrimitive.Viewport>
104
- <SelectScrollDownButton />
105
- </SelectPrimitive.Content>
122
+ <SelectScrollUpButton />
123
+ <SelectPrimitive.List>{children}</SelectPrimitive.List>
124
+ <SelectScrollDownButton />
125
+ </SelectPrimitive.Popup>
126
+ </SelectPrimitive.Positioner>
106
127
  </SelectPrimitive.Portal>
107
128
  )
108
129
  }
@@ -110,11 +131,11 @@ function SelectContent({
110
131
  function SelectLabel({
111
132
  className,
112
133
  ...props
113
- }: React.ComponentProps<typeof SelectPrimitive.Label>) {
134
+ }: SelectPrimitive.GroupLabel.Props) {
114
135
  return (
115
- <SelectPrimitive.Label
136
+ <SelectPrimitive.GroupLabel
116
137
  data-slot="select-label"
117
- className={cn("px-1.5 py-1 text-xs text-muted-foreground", className)}
138
+ className={cn("px-2 py-1.5 text-xs text-muted-foreground", className)}
118
139
  {...props}
119
140
  />
120
141
  )
@@ -124,22 +145,26 @@ function SelectItem({
124
145
  className,
125
146
  children,
126
147
  ...props
127
- }: React.ComponentProps<typeof SelectPrimitive.Item>) {
148
+ }: SelectPrimitive.Item.Props) {
128
149
  return (
129
150
  <SelectPrimitive.Item
130
151
  data-slot="select-item"
131
152
  className={cn(
132
- "relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
153
+ "relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
133
154
  className
134
155
  )}
135
156
  {...props}
136
157
  >
137
- <span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center">
138
- <SelectPrimitive.ItemIndicator>
139
- <CheckIcon className="pointer-events-none" />
140
- </SelectPrimitive.ItemIndicator>
141
- </span>
142
- <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
158
+ <SelectPrimitive.ItemText className="flex flex-1 shrink-0 gap-2 whitespace-nowrap">
159
+ {children}
160
+ </SelectPrimitive.ItemText>
161
+ <SelectPrimitive.ItemIndicator
162
+ render={
163
+ <span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" />
164
+ }
165
+ >
166
+ <CheckIcon className="pointer-events-none" />
167
+ </SelectPrimitive.ItemIndicator>
143
168
  </SelectPrimitive.Item>
144
169
  )
145
170
  }
@@ -147,7 +172,7 @@ function SelectItem({
147
172
  function SelectSeparator({
148
173
  className,
149
174
  ...props
150
- }: React.ComponentProps<typeof SelectPrimitive.Separator>) {
175
+ }: SelectPrimitive.Separator.Props) {
151
176
  return (
152
177
  <SelectPrimitive.Separator
153
178
  data-slot="select-separator"
@@ -160,38 +185,38 @@ function SelectSeparator({
160
185
  function SelectScrollUpButton({
161
186
  className,
162
187
  ...props
163
- }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
188
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>) {
164
189
  return (
165
- <SelectPrimitive.ScrollUpButton
190
+ <SelectPrimitive.ScrollUpArrow
166
191
  data-slot="select-scroll-up-button"
167
192
  className={cn(
168
- "z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
193
+ "top-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
169
194
  className
170
195
  )}
171
196
  {...props}
172
197
  >
173
198
  <ChevronUpIcon
174
199
  />
175
- </SelectPrimitive.ScrollUpButton>
200
+ </SelectPrimitive.ScrollUpArrow>
176
201
  )
177
202
  }
178
203
 
179
204
  function SelectScrollDownButton({
180
205
  className,
181
206
  ...props
182
- }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
207
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>) {
183
208
  return (
184
- <SelectPrimitive.ScrollDownButton
209
+ <SelectPrimitive.ScrollDownArrow
185
210
  data-slot="select-scroll-down-button"
186
211
  className={cn(
187
- "z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
212
+ "bottom-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
188
213
  className
189
214
  )}
190
215
  {...props}
191
216
  >
192
217
  <ChevronDownIcon
193
218
  />
194
- </SelectPrimitive.ScrollDownButton>
219
+ </SelectPrimitive.ScrollDownArrow>
195
220
  )
196
221
  }
197
222
 
@@ -1,37 +1,14 @@
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
- import * as React from "react"
21
- import { Separator as SeparatorPrimitive } from "radix-ui"
22
-
23
- import { cn } from "@/lib/utils"
1
+ import { Separator as SeparatorPrimitive } from "@base-ui/react/separator"
2
+ import { cn } from "cn"
24
3
 
25
4
  function Separator({
26
5
  className,
27
6
  orientation = "horizontal",
28
- decorative = true,
29
7
  ...props
30
- }: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
8
+ }: SeparatorPrimitive.Props) {
31
9
  return (
32
- <SeparatorPrimitive.Root
10
+ <SeparatorPrimitive
33
11
  data-slot="separator"
34
- decorative={decorative}
35
12
  orientation={orientation}
36
13
  className={cn(
37
14
  "shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
@@ -1,60 +1,34 @@
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 { Dialog as SheetPrimitive } from "radix-ui"
4
+ import { Dialog as SheetPrimitive } from "@base-ui/react/dialog"
5
+ import { cn } from "cn"
22
6
 
23
- import { cn } from "@/lib/utils"
24
7
  import { Button } from "@/components/ui/button"
25
8
  import { XIcon } from "lucide-react"
26
9
 
27
- function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
10
+ function Sheet({ ...props }: SheetPrimitive.Root.Props) {
28
11
  return <SheetPrimitive.Root data-slot="sheet" {...props} />
29
12
  }
30
13
 
31
- function SheetTrigger({
32
- ...props
33
- }: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
14
+ function SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {
34
15
  return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
35
16
  }
36
17
 
37
- function SheetClose({
38
- ...props
39
- }: React.ComponentProps<typeof SheetPrimitive.Close>) {
18
+ function SheetClose({ ...props }: SheetPrimitive.Close.Props) {
40
19
  return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
41
20
  }
42
21
 
43
- function SheetPortal({
44
- ...props
45
- }: React.ComponentProps<typeof SheetPrimitive.Portal>) {
22
+ function SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {
46
23
  return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
47
24
  }
48
25
 
49
- function SheetOverlay({
50
- className,
51
- ...props
52
- }: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
26
+ function SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {
53
27
  return (
54
- <SheetPrimitive.Overlay
28
+ <SheetPrimitive.Backdrop
55
29
  data-slot="sheet-overlay"
56
30
  className={cn(
57
- "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",
31
+ "fixed inset-0 z-50 bg-black/10 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs",
58
32
  className
59
33
  )}
60
34
  {...props}
@@ -68,37 +42,40 @@ function SheetContent({
68
42
  side = "right",
69
43
  showCloseButton = true,
70
44
  ...props
71
- }: React.ComponentProps<typeof SheetPrimitive.Content> & {
45
+ }: SheetPrimitive.Popup.Props & {
72
46
  side?: "top" | "right" | "bottom" | "left"
73
47
  showCloseButton?: boolean
74
48
  }) {
75
49
  return (
76
50
  <SheetPortal>
77
51
  <SheetOverlay />
78
- <SheetPrimitive.Content
52
+ <SheetPrimitive.Popup
79
53
  data-slot="sheet-content"
80
54
  data-side={side}
81
55
  className={cn(
82
- "fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-[side=bottom]:data-open:slide-in-from-bottom-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:animate-out data-closed:fade-out-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=right]:data-closed:slide-out-to-right-10 data-[side=top]:data-closed:slide-out-to-top-10",
56
+ "fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm",
83
57
  className
84
58
  )}
85
59
  {...props}
86
60
  >
87
61
  {children}
88
62
  {showCloseButton && (
89
- <SheetPrimitive.Close data-slot="sheet-close" asChild>
90
- <Button
91
- variant="ghost"
92
- className="absolute top-3 right-3"
93
- size="icon-sm"
94
- >
95
- <XIcon
63
+ <SheetPrimitive.Close
64
+ data-slot="sheet-close"
65
+ render={
66
+ <Button
67
+ variant="ghost"
68
+ className="absolute top-4 right-4"
69
+ size="icon-sm"
96
70
  />
97
- <span className="sr-only">Close</span>
98
- </Button>
71
+ }
72
+ >
73
+ <XIcon
74
+ />
75
+ <span className="sr-only">Close</span>
99
76
  </SheetPrimitive.Close>
100
77
  )}
101
- </SheetPrimitive.Content>
78
+ </SheetPrimitive.Popup>
102
79
  </SheetPortal>
103
80
  )
104
81
  }
@@ -107,7 +84,7 @@ function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
107
84
  return (
108
85
  <div
109
86
  data-slot="sheet-header"
110
- className={cn("flex flex-col gap-0.5 p-4", className)}
87
+ className={cn("flex flex-col gap-1.5 p-4", className)}
111
88
  {...props}
112
89
  />
113
90
  )
@@ -123,17 +100,11 @@ function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
123
100
  )
124
101
  }
125
102
 
126
- function SheetTitle({
127
- className,
128
- ...props
129
- }: React.ComponentProps<typeof SheetPrimitive.Title>) {
103
+ function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
130
104
  return (
131
105
  <SheetPrimitive.Title
132
106
  data-slot="sheet-title"
133
- className={cn(
134
- "text-base font-medium text-foreground",
135
- className
136
- )}
107
+ className={cn("font-heading font-medium text-foreground", className)}
137
108
  {...props}
138
109
  />
139
110
  )
@@ -142,7 +113,7 @@ function SheetTitle({
142
113
  function SheetDescription({
143
114
  className,
144
115
  ...props
145
- }: React.ComponentProps<typeof SheetPrimitive.Description>) {
116
+ }: SheetPrimitive.Description.Props) {
146
117
  return (
147
118
  <SheetPrimitive.Description
148
119
  data-slot="sheet-description"