@allbluecn/admin-app 0.3.2 → 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 (198) 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/providers/index.tsx +1 -1
  57. package/src/routeTree.gen.ts +67 -78
  58. package/src/routes/__root.tsx +4 -4
  59. package/src/routes/_nav/audit/route.lazy.tsx +1 -2
  60. package/src/routes/_nav/compliance/route.lazy.tsx +5 -3
  61. package/src/routes/_nav/components/route.lazy.tsx +14 -34
  62. package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +18 -38
  63. package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +18 -38
  64. package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +6 -6
  65. package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +3 -3
  66. package/src/routes/_nav/licenses/new/route.lazy.tsx +5 -5
  67. package/src/routes/_nav/licenses/route.lazy.tsx +1 -1
  68. package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +2 -2
  69. package/src/routes/_nav/monitoring/errors/route.lazy.tsx +10 -10
  70. package/src/routes/_nav/monitoring/errors/route.tsx +7 -0
  71. package/src/routes/_nav/monitoring/health/route.lazy.tsx +13 -15
  72. package/src/routes/_nav/monitoring/health/route.tsx +14 -0
  73. package/src/routes/_nav/monitoring/logs/route.lazy.tsx +24 -9
  74. package/src/routes/_nav/monitoring/logs/route.tsx +13 -0
  75. package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +12 -14
  76. package/src/routes/_nav/monitoring/metrics/route.tsx +7 -0
  77. package/src/routes/_nav/monitoring/overview/route.lazy.tsx +14 -13
  78. package/src/routes/_nav/monitoring/overview/route.tsx +17 -0
  79. package/src/routes/_nav/monitoring/route.lazy.tsx +6 -6
  80. package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +2 -2
  81. package/src/routes/_nav/permissions/route.lazy.tsx +21 -311
  82. package/src/routes/_nav/permissions/route.tsx +1 -1
  83. package/src/routes/_nav/route.tsx +5 -13
  84. package/src/routes/_nav/sso/route.lazy.tsx +2 -3
  85. package/src/routes/_nav/users/$userId/route.lazy.tsx +91 -156
  86. package/src/routes/_nav/users/-components/users-table.tsx +1 -1
  87. package/src/routes/_nav/users/route.lazy.tsx +1 -1
  88. package/src/routes/login/route.lazy.tsx +1 -1
  89. package/src/routes/setup/route.lazy.tsx +2 -2
  90. package/src/server/__tests__/admin-billing.test.ts +191 -16
  91. package/src/server/__tests__/compliance.test.ts +44 -7
  92. package/src/server/__tests__/permissions.test.ts +10 -5
  93. package/src/server/__tests__/prompt-defaults.test.ts +3 -3
  94. package/src/server/admin-ai-alerts.ts +2 -1
  95. package/src/server/admin-ai-usage.ts +2 -1
  96. package/src/server/ai-memory/store.ts +6 -2
  97. package/src/server/{serverFns/ai-prompts → ai-prompts}/prompt-defaults.ts +5 -3
  98. package/src/server/{serverFns/dependency → dependency}/helpers.ts +4 -3
  99. package/src/server/knowledge-public/github-sync.ts +2 -1
  100. package/src/server/license-issue.ts +2 -1
  101. package/src/server/middlewares/auth-rate-limit.ts +117 -0
  102. package/src/server/observability/health-check.ts +4 -1
  103. package/src/server/observability/metrics.ts +17 -15
  104. package/src/server/observability/request-middleware.ts +2 -1
  105. package/src/server/observability/timing.ts +14 -16
  106. package/src/server/serverFns/admin-billing.ts +107 -12
  107. package/src/server/serverFns/ai-memory/list-users.ts +2 -1
  108. package/src/server/serverFns/ai-prompts/activate.ts +2 -1
  109. package/src/server/serverFns/ai-prompts/get.ts +3 -2
  110. package/src/server/serverFns/ai-prompts/list.ts +3 -2
  111. package/src/server/serverFns/ai-prompts/rollback.ts +3 -1
  112. package/src/server/serverFns/ai-prompts/save.ts +5 -3
  113. package/src/server/serverFns/ai-provider/create.ts +4 -1
  114. package/src/server/serverFns/ai-provider/delete.ts +4 -1
  115. package/src/server/serverFns/ai-provider/get.ts +4 -1
  116. package/src/server/serverFns/ai-provider/list.ts +28 -1
  117. package/src/server/serverFns/ai-provider/seed-from-seed.ts +2 -1
  118. package/src/server/serverFns/ai-provider/update.ts +4 -1
  119. package/src/server/serverFns/anyhub/market.ts +8 -1
  120. package/src/server/serverFns/audit.ts +14 -1
  121. package/src/server/serverFns/auth/setup.ts +3 -1
  122. package/src/server/serverFns/compliance.ts +32 -3
  123. package/src/server/serverFns/components/import.ts +69 -14
  124. package/src/server/serverFns/components/list.ts +4 -1
  125. package/src/server/serverFns/components/mutations.ts +9 -1
  126. package/src/server/serverFns/dependency/list.ts +28 -5
  127. package/src/server/serverFns/dependency/sync.ts +7 -2
  128. package/src/server/serverFns/dependency/update.ts +4 -1
  129. package/src/server/serverFns/developer-log-auto-generate.ts +63 -32
  130. package/src/server/serverFns/developer-logs.ts +5 -1
  131. package/src/server/serverFns/invitations.ts +7 -1
  132. package/src/server/serverFns/knowledge-public/bookmarks/create.ts +2 -1
  133. package/src/server/serverFns/knowledge-public/bookmarks/delete.ts +2 -1
  134. package/src/server/serverFns/knowledge-public/bookmarks/detail.ts +2 -1
  135. package/src/server/serverFns/knowledge-public/bookmarks/list.ts +2 -1
  136. package/src/server/serverFns/knowledge-public/bookmarks/sync-all-github.ts +2 -1
  137. package/src/server/serverFns/knowledge-public/bookmarks/update.ts +2 -1
  138. package/src/server/serverFns/knowledge-public/compliance/create.ts +2 -1
  139. package/src/server/serverFns/knowledge-public/compliance/delete.ts +2 -1
  140. package/src/server/serverFns/knowledge-public/compliance/detail.ts +2 -1
  141. package/src/server/serverFns/knowledge-public/compliance/list.ts +2 -1
  142. package/src/server/serverFns/knowledge-public/compliance/update.ts +2 -1
  143. package/src/server/serverFns/knowledge-public/legal/create.ts +2 -1
  144. package/src/server/serverFns/knowledge-public/legal/delete.ts +2 -1
  145. package/src/server/serverFns/knowledge-public/legal/detail.ts +2 -1
  146. package/src/server/serverFns/knowledge-public/legal/list.ts +2 -1
  147. package/src/server/serverFns/knowledge-public/legal/update.ts +2 -1
  148. package/src/server/serverFns/licenses.ts +8 -2
  149. package/src/server/serverFns/monitoring/get-errors.ts +2 -1
  150. package/src/server/serverFns/monitoring/get-health.ts +2 -1
  151. package/src/server/serverFns/monitoring/get-metrics.ts +2 -1
  152. package/src/server/serverFns/monitoring/get-request-logs.ts +2 -1
  153. package/src/server/serverFns/monitoring/report-error.ts +2 -1
  154. package/src/server/serverFns/monitoring/reset.ts +2 -1
  155. package/src/server/serverFns/oauth-providers.ts +4 -1
  156. package/src/server/serverFns/permissions.ts +18 -11
  157. package/src/server/serverFns/sentry/config.ts +11 -8
  158. package/src/server/serverFns/sso-config.ts +17 -2
  159. package/src/server/serverFns/user/create.ts +6 -1
  160. package/src/server/serverFns/user/delete.ts +6 -1
  161. package/src/server/serverFns/user/detail.ts +5 -2
  162. package/src/server/serverFns/user/list.ts +19 -4
  163. package/src/server/serverFns/user/reset-password.ts +10 -2
  164. package/src/server/serverFns/user/update-role.ts +10 -2
  165. package/src/server/serverFns/user/update-status.ts +10 -2
  166. package/src/styles/globals.css +4 -0
  167. package/src/components/data-table/data-table-pagination.tsx +0 -112
  168. package/src/components/data-table/data-table.tsx +0 -218
  169. package/src/components/data-table/table-detail-layout.tsx +0 -98
  170. package/src/components/ui/alert-dialog.tsx +0 -187
  171. package/src/components/ui/alert.tsx +0 -75
  172. package/src/components/ui/avatar.tsx +0 -106
  173. package/src/components/ui/badge.tsx +0 -51
  174. package/src/components/ui/button.tsx +0 -57
  175. package/src/components/ui/card.tsx +0 -102
  176. package/src/components/ui/checkbox.tsx +0 -28
  177. package/src/components/ui/collapsible.tsx +0 -19
  178. package/src/components/ui/dialog.tsx +0 -155
  179. package/src/components/ui/dropdown-menu.tsx +0 -267
  180. package/src/components/ui/field.tsx +0 -236
  181. package/src/components/ui/input-group.tsx +0 -158
  182. package/src/components/ui/input.tsx +0 -19
  183. package/src/components/ui/label.tsx +0 -17
  184. package/src/components/ui/pagination.tsx +0 -130
  185. package/src/components/ui/select.tsx +0 -234
  186. package/src/components/ui/separator.tsx +0 -22
  187. package/src/components/ui/sheet.tsx +0 -135
  188. package/src/components/ui/sidebar.tsx +0 -721
  189. package/src/components/ui/skeleton.tsx +0 -13
  190. package/src/components/ui/switch.tsx +0 -29
  191. package/src/components/ui/table.tsx +0 -115
  192. package/src/components/ui/textarea.tsx +0 -17
  193. package/src/components/ui/toast.tsx +0 -282
  194. package/src/components/ui/tooltip.tsx +0 -63
  195. package/src/hooks/use-mobile.ts +0 -19
  196. package/src/lib/avatar.ts +0 -41
  197. /package/src/routes/{api.auth.$.ts → api/auth/$.ts} +0 -0
  198. /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