@allbluecn/admin-app 0.3.1 → 0.3.3

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 (199) hide show
  1. package/package.json +19 -17
  2. package/src/components/admin/admin-user-menu.tsx +4 -4
  3. package/src/components/admin/developer-log.tsx +16 -32
  4. package/src/components/ai-memory/memory-facts-panel.tsx +30 -70
  5. package/src/components/ai-prompts/preview-panel.tsx +1 -1
  6. package/src/components/ai-prompts/prompt-editor.tsx +8 -9
  7. package/src/components/ai-prompts/prompt-table.tsx +6 -6
  8. package/src/components/ai-prompts/section-editor.tsx +3 -3
  9. package/src/components/ai-prompts/variable-panel.tsx +2 -2
  10. package/src/components/ai-prompts/version-history.tsx +21 -41
  11. package/src/components/ai-provider/model-list-editor.tsx +2 -3
  12. package/src/components/ai-provider/provider-form.tsx +7 -7
  13. package/src/components/ai-provider/provider-table.tsx +17 -40
  14. package/src/components/auth/admin-login-form.tsx +7 -7
  15. package/src/components/auth/icon-input.tsx +2 -2
  16. package/src/components/auth/password-input.tsx +2 -2
  17. package/src/components/component/component-form-dialog.tsx +10 -18
  18. package/src/components/component/component-import-dialog.tsx +6 -6
  19. package/src/components/component/component-preview.tsx +311 -0
  20. package/src/components/component/component-table.tsx +3 -3
  21. package/src/components/dependency/changelog-dialog.tsx +2 -2
  22. package/src/components/dependency/columns.tsx +3 -3
  23. package/src/components/dependency/dependency-table.tsx +7 -7
  24. package/src/components/dependency/edit-dialog.tsx +8 -8
  25. package/src/components/invitations/invitations-page.tsx +26 -49
  26. package/src/components/knowledge-public/bookmark-form-dialog.tsx +6 -6
  27. package/src/components/knowledge-public/compliance-form-dialog.tsx +6 -6
  28. package/src/components/knowledge-public/legal-form-dialog.tsx +7 -7
  29. package/src/components/layout/sidebar-02/app-sidebar.tsx +1 -2
  30. package/src/components/layout/sidebar-02/index.tsx +1 -1
  31. package/src/components/layout/sidebar-02/nav-main.tsx +2 -3
  32. package/src/components/layout/sidebar-02/nav-notifications.tsx +3 -3
  33. package/src/components/market/columns.tsx +4 -4
  34. package/src/components/market/market-app-form.tsx +6 -7
  35. package/src/components/market/market-app-list.tsx +14 -29
  36. package/src/components/monitoring/error-list.tsx +2 -2
  37. package/src/components/monitoring/metrics-stats.tsx +1 -1
  38. package/src/components/monitoring/request-log-table.tsx +2 -2
  39. package/src/components/oauth-providers/provider-page.tsx +20 -38
  40. package/src/components/permissions/assign-dialog.tsx +135 -0
  41. package/src/components/permissions/create-role-dialog.tsx +135 -0
  42. package/src/components/permissions/types.ts +49 -0
  43. package/src/components/user/columns.tsx +6 -6
  44. package/src/components/user/settings-activity-log.tsx +7 -7
  45. package/src/components/user/settings-profile/avatar-uploader.tsx +118 -0
  46. package/src/components/user/settings-profile/social-links.tsx +63 -0
  47. package/src/components/user/settings-profile.tsx +26 -125
  48. package/src/components/user/user-create-dialog.tsx +6 -6
  49. package/src/components/user/user-detail/error-boundary.tsx +19 -0
  50. package/src/components/user/user-detail/user-detail-dialogs.tsx +203 -0
  51. package/src/components/user/user-filters.tsx +4 -4
  52. package/src/lib/auth/page-gate.ts +28 -0
  53. package/src/lib/auth.config.ts +25 -9
  54. package/src/lib/i18n/detect.ts +1 -1
  55. package/src/lib/loader-serial.ts +14 -0
  56. package/src/paraglide/README.md +1 -1
  57. package/src/providers/index.tsx +1 -1
  58. package/src/routeTree.gen.ts +67 -78
  59. package/src/routes/__root.tsx +4 -4
  60. package/src/routes/_nav/audit/route.lazy.tsx +1 -2
  61. package/src/routes/_nav/compliance/route.lazy.tsx +5 -3
  62. package/src/routes/_nav/components/route.lazy.tsx +14 -34
  63. package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +18 -38
  64. package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +18 -38
  65. package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +6 -6
  66. package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +3 -3
  67. package/src/routes/_nav/licenses/new/route.lazy.tsx +5 -5
  68. package/src/routes/_nav/licenses/route.lazy.tsx +1 -1
  69. package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +2 -2
  70. package/src/routes/_nav/monitoring/errors/route.lazy.tsx +10 -10
  71. package/src/routes/_nav/monitoring/errors/route.tsx +7 -0
  72. package/src/routes/_nav/monitoring/health/route.lazy.tsx +13 -15
  73. package/src/routes/_nav/monitoring/health/route.tsx +14 -0
  74. package/src/routes/_nav/monitoring/logs/route.lazy.tsx +24 -9
  75. package/src/routes/_nav/monitoring/logs/route.tsx +13 -0
  76. package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +12 -14
  77. package/src/routes/_nav/monitoring/metrics/route.tsx +7 -0
  78. package/src/routes/_nav/monitoring/overview/route.lazy.tsx +14 -13
  79. package/src/routes/_nav/monitoring/overview/route.tsx +17 -0
  80. package/src/routes/_nav/monitoring/route.lazy.tsx +6 -6
  81. package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +2 -2
  82. package/src/routes/_nav/permissions/route.lazy.tsx +21 -311
  83. package/src/routes/_nav/permissions/route.tsx +1 -1
  84. package/src/routes/_nav/route.tsx +5 -13
  85. package/src/routes/_nav/sso/route.lazy.tsx +2 -3
  86. package/src/routes/_nav/users/$userId/route.lazy.tsx +91 -156
  87. package/src/routes/_nav/users/-components/users-table.tsx +1 -1
  88. package/src/routes/_nav/users/route.lazy.tsx +1 -1
  89. package/src/routes/login/route.lazy.tsx +1 -1
  90. package/src/routes/setup/route.lazy.tsx +2 -2
  91. package/src/server/__tests__/admin-billing.test.ts +191 -16
  92. package/src/server/__tests__/compliance.test.ts +44 -7
  93. package/src/server/__tests__/permissions.test.ts +10 -5
  94. package/src/server/__tests__/prompt-defaults.test.ts +3 -3
  95. package/src/server/admin-ai-alerts.ts +2 -1
  96. package/src/server/admin-ai-usage.ts +2 -1
  97. package/src/server/ai-memory/store.ts +6 -2
  98. package/src/server/{serverFns/ai-prompts → ai-prompts}/prompt-defaults.ts +5 -3
  99. package/src/server/{serverFns/dependency → dependency}/helpers.ts +4 -3
  100. package/src/server/knowledge-public/github-sync.ts +2 -1
  101. package/src/server/license-issue.ts +2 -1
  102. package/src/server/middlewares/auth-rate-limit.ts +117 -0
  103. package/src/server/observability/health-check.ts +4 -1
  104. package/src/server/observability/metrics.ts +17 -15
  105. package/src/server/observability/request-middleware.ts +2 -1
  106. package/src/server/observability/timing.ts +14 -16
  107. package/src/server/serverFns/admin-billing.ts +107 -12
  108. package/src/server/serverFns/ai-memory/list-users.ts +2 -1
  109. package/src/server/serverFns/ai-prompts/activate.ts +2 -1
  110. package/src/server/serverFns/ai-prompts/get.ts +3 -2
  111. package/src/server/serverFns/ai-prompts/list.ts +3 -2
  112. package/src/server/serverFns/ai-prompts/rollback.ts +3 -1
  113. package/src/server/serverFns/ai-prompts/save.ts +5 -3
  114. package/src/server/serverFns/ai-provider/create.ts +4 -1
  115. package/src/server/serverFns/ai-provider/delete.ts +4 -1
  116. package/src/server/serverFns/ai-provider/get.ts +4 -1
  117. package/src/server/serverFns/ai-provider/list.ts +28 -1
  118. package/src/server/serverFns/ai-provider/seed-from-seed.ts +2 -1
  119. package/src/server/serverFns/ai-provider/update.ts +4 -1
  120. package/src/server/serverFns/anyhub/market.ts +8 -1
  121. package/src/server/serverFns/audit.ts +14 -1
  122. package/src/server/serverFns/auth/setup.ts +3 -1
  123. package/src/server/serverFns/compliance.ts +32 -3
  124. package/src/server/serverFns/components/import.ts +69 -14
  125. package/src/server/serverFns/components/list.ts +4 -1
  126. package/src/server/serverFns/components/mutations.ts +9 -1
  127. package/src/server/serverFns/dependency/list.ts +28 -5
  128. package/src/server/serverFns/dependency/sync.ts +7 -2
  129. package/src/server/serverFns/dependency/update.ts +4 -1
  130. package/src/server/serverFns/developer-log-auto-generate.ts +63 -32
  131. package/src/server/serverFns/developer-logs.ts +5 -1
  132. package/src/server/serverFns/invitations.ts +7 -1
  133. package/src/server/serverFns/knowledge-public/bookmarks/create.ts +2 -1
  134. package/src/server/serverFns/knowledge-public/bookmarks/delete.ts +2 -1
  135. package/src/server/serverFns/knowledge-public/bookmarks/detail.ts +2 -1
  136. package/src/server/serverFns/knowledge-public/bookmarks/list.ts +2 -1
  137. package/src/server/serverFns/knowledge-public/bookmarks/sync-all-github.ts +2 -1
  138. package/src/server/serverFns/knowledge-public/bookmarks/update.ts +2 -1
  139. package/src/server/serverFns/knowledge-public/compliance/create.ts +2 -1
  140. package/src/server/serverFns/knowledge-public/compliance/delete.ts +2 -1
  141. package/src/server/serverFns/knowledge-public/compliance/detail.ts +2 -1
  142. package/src/server/serverFns/knowledge-public/compliance/list.ts +2 -1
  143. package/src/server/serverFns/knowledge-public/compliance/update.ts +2 -1
  144. package/src/server/serverFns/knowledge-public/legal/create.ts +2 -1
  145. package/src/server/serverFns/knowledge-public/legal/delete.ts +2 -1
  146. package/src/server/serverFns/knowledge-public/legal/detail.ts +2 -1
  147. package/src/server/serverFns/knowledge-public/legal/list.ts +2 -1
  148. package/src/server/serverFns/knowledge-public/legal/update.ts +2 -1
  149. package/src/server/serverFns/licenses.ts +8 -2
  150. package/src/server/serverFns/monitoring/get-errors.ts +2 -1
  151. package/src/server/serverFns/monitoring/get-health.ts +2 -1
  152. package/src/server/serverFns/monitoring/get-metrics.ts +2 -1
  153. package/src/server/serverFns/monitoring/get-request-logs.ts +2 -1
  154. package/src/server/serverFns/monitoring/report-error.ts +2 -1
  155. package/src/server/serverFns/monitoring/reset.ts +2 -1
  156. package/src/server/serverFns/oauth-providers.ts +4 -1
  157. package/src/server/serverFns/permissions.ts +18 -11
  158. package/src/server/serverFns/sentry/config.ts +11 -8
  159. package/src/server/serverFns/sso-config.ts +17 -2
  160. package/src/server/serverFns/user/create.ts +6 -1
  161. package/src/server/serverFns/user/delete.ts +6 -1
  162. package/src/server/serverFns/user/detail.ts +5 -2
  163. package/src/server/serverFns/user/list.ts +19 -4
  164. package/src/server/serverFns/user/reset-password.ts +10 -2
  165. package/src/server/serverFns/user/update-role.ts +10 -2
  166. package/src/server/serverFns/user/update-status.ts +10 -2
  167. package/src/styles/globals.css +4 -0
  168. package/src/components/data-table/data-table-pagination.tsx +0 -112
  169. package/src/components/data-table/data-table.tsx +0 -218
  170. package/src/components/data-table/table-detail-layout.tsx +0 -98
  171. package/src/components/ui/alert-dialog.tsx +0 -187
  172. package/src/components/ui/alert.tsx +0 -75
  173. package/src/components/ui/avatar.tsx +0 -106
  174. package/src/components/ui/badge.tsx +0 -51
  175. package/src/components/ui/button.tsx +0 -57
  176. package/src/components/ui/card.tsx +0 -102
  177. package/src/components/ui/checkbox.tsx +0 -28
  178. package/src/components/ui/collapsible.tsx +0 -19
  179. package/src/components/ui/dialog.tsx +0 -155
  180. package/src/components/ui/dropdown-menu.tsx +0 -267
  181. package/src/components/ui/field.tsx +0 -236
  182. package/src/components/ui/input-group.tsx +0 -158
  183. package/src/components/ui/input.tsx +0 -19
  184. package/src/components/ui/label.tsx +0 -17
  185. package/src/components/ui/pagination.tsx +0 -130
  186. package/src/components/ui/select.tsx +0 -234
  187. package/src/components/ui/separator.tsx +0 -22
  188. package/src/components/ui/sheet.tsx +0 -135
  189. package/src/components/ui/sidebar.tsx +0 -721
  190. package/src/components/ui/skeleton.tsx +0 -13
  191. package/src/components/ui/switch.tsx +0 -29
  192. package/src/components/ui/table.tsx +0 -115
  193. package/src/components/ui/textarea.tsx +0 -17
  194. package/src/components/ui/toast.tsx +0 -282
  195. package/src/components/ui/tooltip.tsx +0 -63
  196. package/src/hooks/use-mobile.ts +0 -19
  197. package/src/lib/avatar.ts +0 -41
  198. /package/src/routes/{api.auth.$.ts → api/auth/$.ts} +0 -0
  199. /package/src/routes/{api.sentry-test.ts → api/sentry-test.ts} +0 -0
@@ -1,13 +0,0 @@
1
- import { cn } from "cn"
2
-
3
- function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4
- return (
5
- <div
6
- data-slot="skeleton"
7
- className={cn("animate-pulse rounded-md bg-muted", className)}
8
- {...props}
9
- />
10
- )
11
- }
12
-
13
- export { Skeleton }
@@ -1,29 +0,0 @@
1
- import { Switch as SwitchPrimitive } from "@base-ui/react/switch"
2
- import { cn } from "cn"
3
-
4
- function Switch({
5
- className,
6
- size = "default",
7
- ...props
8
- }: SwitchPrimitive.Root.Props & {
9
- size?: "sm" | "default"
10
- }) {
11
- return (
12
- <SwitchPrimitive.Root
13
- data-slot="switch"
14
- data-size={size}
15
- className={cn(
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",
17
- className
18
- )}
19
- {...props}
20
- >
21
- <SwitchPrimitive.Thumb
22
- data-slot="switch-thumb"
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"
24
- />
25
- </SwitchPrimitive.Root>
26
- )
27
- }
28
-
29
- export { Switch }
@@ -1,115 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { cn } from "cn"
5
-
6
- function Table({ className, ...props }: React.ComponentProps<"table">) {
7
- return (
8
- <div
9
- data-slot="table-container"
10
- className="relative w-full overflow-x-auto"
11
- >
12
- <table
13
- data-slot="table"
14
- className={cn("w-full caption-bottom text-sm", className)}
15
- {...props}
16
- />
17
- </div>
18
- )
19
- }
20
-
21
- function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
22
- return (
23
- <thead
24
- data-slot="table-header"
25
- className={cn("[&_tr]:border-b", className)}
26
- {...props}
27
- />
28
- )
29
- }
30
-
31
- function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
32
- return (
33
- <tbody
34
- data-slot="table-body"
35
- className={cn("[&_tr:last-child]:border-0", className)}
36
- {...props}
37
- />
38
- )
39
- }
40
-
41
- function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
42
- return (
43
- <tfoot
44
- data-slot="table-footer"
45
- className={cn(
46
- "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
47
- className
48
- )}
49
- {...props}
50
- />
51
- )
52
- }
53
-
54
- function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
55
- return (
56
- <tr
57
- data-slot="table-row"
58
- className={cn(
59
- "border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",
60
- className
61
- )}
62
- {...props}
63
- />
64
- )
65
- }
66
-
67
- function TableHead({ className, ...props }: React.ComponentProps<"th">) {
68
- return (
69
- <th
70
- data-slot="table-head"
71
- className={cn(
72
- "h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
73
- className
74
- )}
75
- {...props}
76
- />
77
- )
78
- }
79
-
80
- function TableCell({ className, ...props }: React.ComponentProps<"td">) {
81
- return (
82
- <td
83
- data-slot="table-cell"
84
- className={cn(
85
- "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
86
- className
87
- )}
88
- {...props}
89
- />
90
- )
91
- }
92
-
93
- function TableCaption({
94
- className,
95
- ...props
96
- }: React.ComponentProps<"caption">) {
97
- return (
98
- <caption
99
- data-slot="table-caption"
100
- className={cn("mt-4 text-sm text-muted-foreground", className)}
101
- {...props}
102
- />
103
- )
104
- }
105
-
106
- export {
107
- Table,
108
- TableHeader,
109
- TableBody,
110
- TableFooter,
111
- TableHead,
112
- TableRow,
113
- TableCell,
114
- TableCaption,
115
- }
@@ -1,17 +0,0 @@
1
- import * as React from "react"
2
- import { cn } from "cn"
3
-
4
- function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
5
- return (
6
- <textarea
7
- data-slot="textarea"
8
- className={cn(
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",
10
- className
11
- )}
12
- {...props}
13
- />
14
- )
15
- }
16
-
17
- export { Textarea }
@@ -1,282 +0,0 @@
1
- import * as React from "react"
2
- import { Toast as ToastPrimitive } from "@base-ui/react/toast"
3
- import { cn } from "cn"
4
-
5
- import { Button } from "@/components/ui/button"
6
- import { XIcon, CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react"
7
-
8
- const toastManager = ToastPrimitive.createToastManager()
9
-
10
- interface SonnerToastOptions {
11
- description?: React.ReactNode
12
- duration?: number
13
- action?: { label: React.ReactNode; onClick?: () => void }
14
- }
15
-
16
- function buildOptions(message: React.ReactNode, type: string | undefined, opts?: SonnerToastOptions) {
17
- return {
18
- type,
19
- title: message,
20
- description: opts?.description,
21
- timeout: opts?.duration,
22
- actionProps: opts?.action
23
- ? { children: opts.action.label, onClick: opts.action.onClick }
24
- : undefined,
25
- }
26
- }
27
-
28
- const toast = Object.assign(
29
- (message: React.ReactNode, opts?: SonnerToastOptions) =>
30
- toastManager.add(buildOptions(message, undefined, opts)),
31
- {
32
- success: (message: React.ReactNode, opts?: SonnerToastOptions) =>
33
- toastManager.add(buildOptions(message, "success", opts)),
34
- error: (message: React.ReactNode, opts?: SonnerToastOptions) =>
35
- toastManager.add(buildOptions(message, "error", opts)),
36
- warning: (message: React.ReactNode, opts?: SonnerToastOptions) =>
37
- toastManager.add(buildOptions(message, "warning", opts)),
38
- info: (message: React.ReactNode, opts?: SonnerToastOptions) =>
39
- toastManager.add(buildOptions(message, "info", opts)),
40
- loading: (message: React.ReactNode, opts?: SonnerToastOptions) =>
41
- toastManager.add(buildOptions(message, "loading", { ...opts, duration: 0 })),
42
- message: (message: React.ReactNode, opts?: SonnerToastOptions) =>
43
- toastManager.add(buildOptions(message, undefined, opts)),
44
- dismiss: (id?: string) => toastManager.close(id),
45
- promise: <Value,>(
46
- promiseValue: Promise<Value>,
47
- options: {
48
- loading: string
49
- success: string | ((result: Value) => string)
50
- error: string | ((error: unknown) => string)
51
- },
52
- ) =>
53
- toastManager.promise(promiseValue, {
54
- loading: options.loading,
55
- success: options.success,
56
- error: options.error,
57
- }),
58
- },
59
- )
60
-
61
- function ToastProvider({ ...props }: ToastPrimitive.Provider.Props) {
62
- return <ToastPrimitive.Provider {...props} />
63
- }
64
-
65
- function ToastPortal({ ...props }: ToastPrimitive.Portal.Props) {
66
- return <ToastPrimitive.Portal data-slot="toast-portal" {...props} />
67
- }
68
-
69
- function ToastViewport({ className, ...props }: ToastPrimitive.Viewport.Props) {
70
- return (
71
- <ToastPrimitive.Viewport
72
- data-slot="toast-viewport"
73
- className={cn(
74
- "pointer-events-none fixed bottom-4 right-4 z-50 w-full max-w-sm outline-none sm:bottom-6 sm:right-6",
75
- className
76
- )}
77
- {...props}
78
- />
79
- )
80
- }
81
-
82
- function Toast({ className, ...props }: ToastPrimitive.Root.Props) {
83
- return (
84
- <ToastPrimitive.Root
85
- data-slot="toast"
86
- className={cn(
87
- "group/toast pointer-events-auto absolute right-0 bottom-0 z-[calc(1000-var(--toast-index))] w-full origin-bottom rounded-2xl border bg-popover text-popover-foreground shadow-lg will-change-transform outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
88
- "[--gap:0.75rem] [--height:var(--toast-frontmost-height,var(--toast-height))] [--offset-y:calc(var(--toast-offset-y)*-1+calc(var(--toast-index)*var(--gap)*-1)+var(--toast-swipe-movement-y))] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))]",
89
- "h-(--height) [transform:translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)-(var(--toast-index)*var(--peek))-(var(--shrink)*var(--height))))_scale(var(--scale))] [transition:transform_500ms_cubic-bezier(0.22,1,0.36,1),opacity_500ms,height_150ms]",
90
- "after:absolute after:top-full after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-['']",
91
- "data-expanded:h-(--toast-height) data-expanded:[transform:translateX(var(--toast-swipe-movement-x))_translateY(var(--offset-y))]",
92
- "data-limited:opacity-0 data-starting-style:[transform:translateY(150%)]",
93
- "[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(150%)]",
94
- "data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))]",
95
- "data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))]",
96
- "data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))]",
97
- "data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))]",
98
- "data-expanded:data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))]",
99
- "data-expanded:data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))]",
100
- "data-expanded:data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))]",
101
- "data-expanded:data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))]",
102
- className
103
- )}
104
- {...props}
105
- />
106
- )
107
- }
108
-
109
- function ToastContent({ className, ...props }: ToastPrimitive.Content.Props) {
110
- return (
111
- <ToastPrimitive.Content
112
- data-slot="toast-content"
113
- className={cn(
114
- "flex h-full items-center gap-3 overflow-hidden p-4 transition-opacity duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] data-behind:opacity-0 data-expanded:opacity-100",
115
- className
116
- )}
117
- {...props}
118
- />
119
- )
120
- }
121
-
122
- function ToastTitle({ className, ...props }: ToastPrimitive.Title.Props) {
123
- return (
124
- <ToastPrimitive.Title
125
- data-slot="toast-title"
126
- className={cn("text-sm font-medium", className)}
127
- {...props}
128
- />
129
- )
130
- }
131
-
132
- function ToastDescription({
133
- className,
134
- ...props
135
- }: ToastPrimitive.Description.Props) {
136
- return (
137
- <ToastPrimitive.Description
138
- data-slot="toast-description"
139
- className={cn("text-sm text-muted-foreground", className)}
140
- {...props}
141
- />
142
- )
143
- }
144
-
145
- function ToastAction({
146
- className,
147
- render = <Button variant="outline" size="sm" />,
148
- ...props
149
- }: ToastPrimitive.Action.Props) {
150
- return (
151
- <ToastPrimitive.Action
152
- data-slot="toast-action"
153
- render={render}
154
- className={cn("shrink-0", className)}
155
- {...props}
156
- />
157
- )
158
- }
159
-
160
- function ToastClose({
161
- className,
162
- children,
163
- render = <Button variant="ghost" size="icon-sm" />,
164
- ...props
165
- }: ToastPrimitive.Close.Props) {
166
- return (
167
- <ToastPrimitive.Close
168
- data-slot="toast-close"
169
- aria-label="Close toast"
170
- render={render}
171
- className={cn(
172
- "relative shrink-0 text-muted-foreground after:absolute after:-inset-2 after:content-[''] hover:text-foreground",
173
- className
174
- )}
175
- {...props}
176
- >
177
- {children ?? (
178
- <XIcon aria-hidden="true" />
179
- )}
180
- </ToastPrimitive.Close>
181
- )
182
- }
183
-
184
- function ToastIcon({ type }: { type: string | undefined }) {
185
- let icon: React.ReactNode = null
186
-
187
- if (type === "success") {
188
- icon = (
189
- <CircleCheckIcon aria-hidden="true" />
190
- )
191
- }
192
-
193
- if (type === "info") {
194
- icon = (
195
- <InfoIcon aria-hidden="true" />
196
- )
197
- }
198
-
199
- if (type === "warning") {
200
- icon = (
201
- <TriangleAlertIcon aria-hidden="true" />
202
- )
203
- }
204
-
205
- if (type === "error") {
206
- icon = (
207
- <OctagonXIcon className="text-destructive" aria-hidden="true" />
208
- )
209
- }
210
-
211
- if (type === "loading") {
212
- icon = (
213
- <Loader2Icon className="animate-spin" aria-hidden="true" />
214
- )
215
- }
216
-
217
- if (!icon) {
218
- return null
219
- }
220
-
221
- return (
222
- <span
223
- data-slot="toast-icon"
224
- className="shrink-0 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4"
225
- >
226
- {icon}
227
- </span>
228
- )
229
- }
230
-
231
- function ToastList() {
232
- const { toasts } = ToastPrimitive.useToastManager()
233
-
234
- return toasts.map((toastItem) => (
235
- <Toast key={toastItem.id} toast={toastItem}>
236
- <ToastContent>
237
- <ToastIcon type={toastItem.type} />
238
- <div className="flex min-w-0 flex-1 flex-col gap-1">
239
- <ToastTitle />
240
- <ToastDescription />
241
- </div>
242
- <ToastAction />
243
- <ToastClose />
244
- </ToastContent>
245
- </Toast>
246
- ))
247
- }
248
-
249
- function Toaster({
250
- children,
251
- ...props
252
- }: ToastPrimitive.Provider.Props) {
253
- return (
254
- <ToastProvider toastManager={toastManager} {...props}>
255
- {children}
256
- <ToastPortal>
257
- <ToastViewport>
258
- <ToastList />
259
- </ToastViewport>
260
- </ToastPortal>
261
- </ToastProvider>
262
- )
263
- }
264
-
265
- const createToastManager = ToastPrimitive.createToastManager
266
- const useToastManager = ToastPrimitive.useToastManager
267
-
268
- export {
269
- Toaster,
270
- Toast,
271
- ToastAction,
272
- ToastClose,
273
- ToastContent,
274
- ToastDescription,
275
- ToastPortal,
276
- ToastProvider,
277
- ToastTitle,
278
- ToastViewport,
279
- createToastManager,
280
- toast,
281
- useToastManager,
282
- }
@@ -1,63 +0,0 @@
1
- import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip"
2
- import { cn } from "cn"
3
-
4
- function TooltipProvider({
5
- delay = 0,
6
- ...props
7
- }: TooltipPrimitive.Provider.Props) {
8
- return (
9
- <TooltipPrimitive.Provider
10
- data-slot="tooltip-provider"
11
- delay={delay}
12
- {...props}
13
- />
14
- )
15
- }
16
-
17
- function Tooltip({ ...props }: TooltipPrimitive.Root.Props) {
18
- return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
19
- }
20
-
21
- function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
22
- return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
23
- }
24
-
25
- function TooltipContent({
26
- className,
27
- side = "top",
28
- sideOffset = 4,
29
- align = "center",
30
- alignOffset = 0,
31
- children,
32
- ...props
33
- }: TooltipPrimitive.Popup.Props &
34
- Pick<
35
- TooltipPrimitive.Positioner.Props,
36
- "align" | "alignOffset" | "side" | "sideOffset"
37
- >) {
38
- return (
39
- <TooltipPrimitive.Portal>
40
- <TooltipPrimitive.Positioner
41
- align={align}
42
- alignOffset={alignOffset}
43
- side={side}
44
- sideOffset={sideOffset}
45
- className="isolate z-50"
46
- >
47
- <TooltipPrimitive.Popup
48
- data-slot="tooltip-content"
49
- className={cn(
50
- "z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 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-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 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",
51
- className
52
- )}
53
- {...props}
54
- >
55
- {children}
56
- <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" />
57
- </TooltipPrimitive.Popup>
58
- </TooltipPrimitive.Positioner>
59
- </TooltipPrimitive.Portal>
60
- )
61
- }
62
-
63
- export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
@@ -1,19 +0,0 @@
1
- import * as React from "react"
2
-
3
- const MOBILE_BREAKPOINT = 768
4
-
5
- export function useIsMobile() {
6
- const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
-
8
- React.useEffect(() => {
9
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
- const onChange = () => {
11
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
- }
13
- mql.addEventListener("change", onChange)
14
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
- return () => mql.removeEventListener("change", onChange)
16
- }, [])
17
-
18
- return !!isMobile
19
- }
package/src/lib/avatar.ts DELETED
@@ -1,41 +0,0 @@
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
- const DICE_BEAR_BASE = "https://api.dicebear.com/7.x";
19
-
20
- const DICE_BEAR_STYLES = ["avataaars", "micah", "notionists", "lorelei", "adventurer"] as const;
21
-
22
- type DiceBearStyle = (typeof DICE_BEAR_STYLES)[number];
23
-
24
- export interface AvatarOptions {
25
- style?: DiceBearStyle;
26
- size?: number;
27
- square?: boolean;
28
- }
29
-
30
- export function getBoringAvatarUrl(
31
- seed: string,
32
- options: AvatarOptions = {}
33
- ): string {
34
- const { style = "avataaars", size = 80 } = options;
35
-
36
- return `${DICE_BEAR_BASE}/${style}/svg?seed=${encodeURIComponent(seed)}&size=${size}`;
37
- }
38
-
39
- export function getAvatarFallback(name: string): string {
40
- return name.charAt(0).toUpperCase();
41
- }
File without changes