@allbluecn/admin-app 0.3.3 → 0.3.4

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 (41) hide show
  1. package/allblue-ui/package.json +6 -0
  2. package/allblue-ui/src/components/confirm-dialog.tsx +94 -0
  3. package/allblue-ui/src/components/infinite-scroll-sentinel.tsx +37 -0
  4. package/allblue-ui/src/components/notion-avatar.tsx +126 -0
  5. package/allblue-ui/src/components/user-avatar.tsx +82 -0
  6. package/allblue-ui/src/data-table/data-table-pagination.tsx +121 -0
  7. package/allblue-ui/src/data-table/data-table.tsx +218 -0
  8. package/allblue-ui/src/data-table/table-detail-layout.tsx +97 -0
  9. package/allblue-ui/src/hooks/use-load-more.ts +57 -0
  10. package/allblue-ui/src/hooks/use-mobile.ts +19 -0
  11. package/allblue-ui/src/index.ts +31 -0
  12. package/allblue-ui/src/lib/avatar.ts +41 -0
  13. package/allblue-ui/src/lib/datetime.ts +226 -0
  14. package/allblue-ui/src/lib/sanitize.ts +18 -0
  15. package/allblue-ui/src/lib/utils.ts +1 -0
  16. package/allblue-ui/src/ui/alert-dialog.tsx +185 -0
  17. package/allblue-ui/src/ui/alert.tsx +75 -0
  18. package/allblue-ui/src/ui/avatar.tsx +106 -0
  19. package/allblue-ui/src/ui/badge.tsx +51 -0
  20. package/allblue-ui/src/ui/button.tsx +57 -0
  21. package/allblue-ui/src/ui/card.tsx +102 -0
  22. package/allblue-ui/src/ui/checkbox.tsx +27 -0
  23. package/allblue-ui/src/ui/collapsible.tsx +19 -0
  24. package/allblue-ui/src/ui/dialog.tsx +155 -0
  25. package/allblue-ui/src/ui/dropdown-menu.tsx +265 -0
  26. package/allblue-ui/src/ui/field.tsx +236 -0
  27. package/allblue-ui/src/ui/input-group.tsx +157 -0
  28. package/allblue-ui/src/ui/input.tsx +19 -0
  29. package/allblue-ui/src/ui/label.tsx +17 -0
  30. package/allblue-ui/src/ui/pagination.tsx +130 -0
  31. package/allblue-ui/src/ui/select.tsx +232 -0
  32. package/allblue-ui/src/ui/separator.tsx +23 -0
  33. package/allblue-ui/src/ui/sheet.tsx +134 -0
  34. package/allblue-ui/src/ui/sidebar.tsx +721 -0
  35. package/allblue-ui/src/ui/skeleton.tsx +13 -0
  36. package/allblue-ui/src/ui/switch.tsx +30 -0
  37. package/allblue-ui/src/ui/table.tsx +113 -0
  38. package/allblue-ui/src/ui/textarea.tsx +17 -0
  39. package/allblue-ui/src/ui/toast.tsx +308 -0
  40. package/allblue-ui/src/ui/tooltip.tsx +64 -0
  41. package/package.json +3 -2
@@ -0,0 +1,13 @@
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 }
@@ -0,0 +1,30 @@
1
+
2
+ import { Switch as SwitchPrimitive } from "@base-ui/react/switch"
3
+ import { cn } from "cn"
4
+
5
+ function Switch({
6
+ className,
7
+ size = "default",
8
+ ...props
9
+ }: SwitchPrimitive.Root.Props & {
10
+ size?: "sm" | "default"
11
+ }) {
12
+ return (
13
+ <SwitchPrimitive.Root
14
+ data-slot="switch"
15
+ data-size={size}
16
+ className={cn(
17
+ "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",
18
+ className
19
+ )}
20
+ {...props}
21
+ >
22
+ <SwitchPrimitive.Thumb
23
+ data-slot="switch-thumb"
24
+ 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"
25
+ />
26
+ </SwitchPrimitive.Root>
27
+ )
28
+ }
29
+
30
+ export { Switch }
@@ -0,0 +1,113 @@
1
+ import * as React from "react"
2
+ import { cn } from "cn"
3
+
4
+ function Table({ className, ...props }: React.ComponentProps<"table">) {
5
+ return (
6
+ <div
7
+ data-slot="table-container"
8
+ className="relative w-full overflow-x-auto"
9
+ >
10
+ <table
11
+ data-slot="table"
12
+ className={cn("w-full caption-bottom text-sm", className)}
13
+ {...props}
14
+ />
15
+ </div>
16
+ )
17
+ }
18
+
19
+ function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
20
+ return (
21
+ <thead
22
+ data-slot="table-header"
23
+ className={cn("[&_tr]:border-b", className)}
24
+ {...props}
25
+ />
26
+ )
27
+ }
28
+
29
+ function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
30
+ return (
31
+ <tbody
32
+ data-slot="table-body"
33
+ className={cn("[&_tr:last-child]:border-0", className)}
34
+ {...props}
35
+ />
36
+ )
37
+ }
38
+
39
+ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
40
+ return (
41
+ <tfoot
42
+ data-slot="table-footer"
43
+ className={cn(
44
+ "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
45
+ className
46
+ )}
47
+ {...props}
48
+ />
49
+ )
50
+ }
51
+
52
+ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
53
+ return (
54
+ <tr
55
+ data-slot="table-row"
56
+ className={cn(
57
+ "border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",
58
+ className
59
+ )}
60
+ {...props}
61
+ />
62
+ )
63
+ }
64
+
65
+ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
66
+ return (
67
+ <th
68
+ data-slot="table-head"
69
+ className={cn(
70
+ "h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
71
+ className
72
+ )}
73
+ {...props}
74
+ />
75
+ )
76
+ }
77
+
78
+ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
79
+ return (
80
+ <td
81
+ data-slot="table-cell"
82
+ className={cn(
83
+ "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
84
+ className
85
+ )}
86
+ {...props}
87
+ />
88
+ )
89
+ }
90
+
91
+ function TableCaption({
92
+ className,
93
+ ...props
94
+ }: React.ComponentProps<"caption">) {
95
+ return (
96
+ <caption
97
+ data-slot="table-caption"
98
+ className={cn("mt-4 text-sm text-muted-foreground", className)}
99
+ {...props}
100
+ />
101
+ )
102
+ }
103
+
104
+ export {
105
+ Table,
106
+ TableHeader,
107
+ TableBody,
108
+ TableFooter,
109
+ TableHead,
110
+ TableRow,
111
+ TableCell,
112
+ TableCaption,
113
+ }
@@ -0,0 +1,17 @@
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 }
@@ -0,0 +1,308 @@
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 "./button"
6
+ import { XIcon, CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react"
7
+
8
+ const toastManager = ToastPrimitive.createToastManager()
9
+
10
+ // 双端历史分叉:web 顶部居中堆叠(top-center),admin 右下角堆叠(bottom-right)。
11
+ // 差异为纯 class 组 + swipeDirection,通过 position 参数承载,行为逐字节等价于原实现。
12
+ type ToasterPosition = "top-center" | "bottom-right"
13
+
14
+ const ToastPositionContext = React.createContext<ToasterPosition>("top-center")
15
+
16
+ interface SonnerToastOptions {
17
+ description?: React.ReactNode
18
+ duration?: number
19
+ action?: { label: React.ReactNode; onClick?: () => void }
20
+ }
21
+
22
+ function buildOptions(message: React.ReactNode, type: string | undefined, opts?: SonnerToastOptions) {
23
+ return {
24
+ type,
25
+ title: message,
26
+ description: opts?.description,
27
+ timeout: opts?.duration,
28
+ actionProps: opts?.action
29
+ ? { children: opts.action.label, onClick: opts.action.onClick }
30
+ : undefined,
31
+ }
32
+ }
33
+
34
+ const toast = Object.assign(
35
+ (message: React.ReactNode, opts?: SonnerToastOptions) =>
36
+ toastManager.add(buildOptions(message, undefined, opts)),
37
+ {
38
+ success: (message: React.ReactNode, opts?: SonnerToastOptions) =>
39
+ toastManager.add(buildOptions(message, "success", opts)),
40
+ error: (message: React.ReactNode, opts?: SonnerToastOptions) =>
41
+ toastManager.add(buildOptions(message, "error", opts)),
42
+ warning: (message: React.ReactNode, opts?: SonnerToastOptions) =>
43
+ toastManager.add(buildOptions(message, "warning", opts)),
44
+ info: (message: React.ReactNode, opts?: SonnerToastOptions) =>
45
+ toastManager.add(buildOptions(message, "info", opts)),
46
+ loading: (message: React.ReactNode, opts?: SonnerToastOptions) =>
47
+ toastManager.add(buildOptions(message, "loading", { ...opts, duration: 0 })),
48
+ message: (message: React.ReactNode, opts?: SonnerToastOptions) =>
49
+ toastManager.add(buildOptions(message, undefined, opts)),
50
+ dismiss: (id?: string) => toastManager.close(id),
51
+ promise: <Value,>(
52
+ promiseValue: Promise<Value>,
53
+ options: {
54
+ loading: string
55
+ success: string | ((result: Value) => string)
56
+ error: string | ((error: unknown) => string)
57
+ },
58
+ ) =>
59
+ toastManager.promise(promiseValue, {
60
+ loading: options.loading,
61
+ success: options.success,
62
+ error: options.error,
63
+ }),
64
+ },
65
+ )
66
+
67
+ function ToastProvider({ ...props }: ToastPrimitive.Provider.Props) {
68
+ return <ToastPrimitive.Provider {...props} />
69
+ }
70
+
71
+ function ToastPortal({ ...props }: ToastPrimitive.Portal.Props) {
72
+ return <ToastPrimitive.Portal data-slot="toast-portal" {...props} />
73
+ }
74
+
75
+ function ToastViewport({ className, ...props }: ToastPrimitive.Viewport.Props) {
76
+ const top = React.useContext(ToastPositionContext) === "top-center"
77
+ return (
78
+ <ToastPrimitive.Viewport
79
+ data-slot="toast-viewport"
80
+ className={cn(
81
+ top
82
+ ? "pointer-events-none fixed top-4 left-0 right-0 z-50 mx-auto w-full max-w-sm outline-none sm:top-6"
83
+ : "pointer-events-none fixed bottom-4 right-4 z-50 w-full max-w-sm outline-none sm:bottom-6 sm:right-6",
84
+ className
85
+ )}
86
+ {...props}
87
+ />
88
+ )
89
+ }
90
+
91
+ function Toast({ className, ...props }: ToastPrimitive.Root.Props) {
92
+ const top = React.useContext(ToastPositionContext) === "top-center"
93
+ return (
94
+ <ToastPrimitive.Root
95
+ data-slot="toast"
96
+ className={cn(
97
+ top
98
+ ? "group/toast pointer-events-auto absolute top-0 right-0 left-0 z-[calc(1000-var(--toast-index))] mx-auto w-full origin-top 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"
99
+ : "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",
100
+ top
101
+ ? "[--gap:0.75rem] [--height:var(--toast-frontmost-height,var(--toast-height))] [--offset-y:calc(var(--toast-offset-y)+calc(var(--toast-index)*var(--gap))+var(--toast-swipe-movement-y))] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))]"
102
+ : "[--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))]",
103
+ top
104
+ ? "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]"
105
+ : "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]",
106
+ top
107
+ ? "after:absolute after:bottom-full after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-['']"
108
+ : "after:absolute after:top-full after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-['']",
109
+ "data-expanded:h-(--toast-height) data-expanded:[transform:translateX(var(--toast-swipe-movement-x))_translateY(var(--offset-y))]",
110
+ top
111
+ ? "data-limited:opacity-0 data-starting-style:[transform:translateY(-150%)]"
112
+ : "data-limited:opacity-0 data-starting-style:[transform:translateY(150%)]",
113
+ top
114
+ ? "[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(-150%)]"
115
+ : "[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(150%)]",
116
+ "data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))]",
117
+ "data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))]",
118
+ "data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))]",
119
+ "data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))]",
120
+ "data-expanded:data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))]",
121
+ "data-expanded:data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))]",
122
+ "data-expanded:data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))]",
123
+ "data-expanded:data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))]",
124
+ className
125
+ )}
126
+ {...props}
127
+ />
128
+ )
129
+ }
130
+
131
+ function ToastContent({ className, ...props }: ToastPrimitive.Content.Props) {
132
+ return (
133
+ <ToastPrimitive.Content
134
+ data-slot="toast-content"
135
+ className={cn(
136
+ "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",
137
+ className
138
+ )}
139
+ {...props}
140
+ />
141
+ )
142
+ }
143
+
144
+ function ToastTitle({ className, ...props }: ToastPrimitive.Title.Props) {
145
+ return (
146
+ <ToastPrimitive.Title
147
+ data-slot="toast-title"
148
+ className={cn("text-sm font-medium", className)}
149
+ {...props}
150
+ />
151
+ )
152
+ }
153
+
154
+ function ToastDescription({
155
+ className,
156
+ ...props
157
+ }: ToastPrimitive.Description.Props) {
158
+ return (
159
+ <ToastPrimitive.Description
160
+ data-slot="toast-description"
161
+ className={cn("text-sm text-muted-foreground", className)}
162
+ {...props}
163
+ />
164
+ )
165
+ }
166
+
167
+ function ToastAction({
168
+ className,
169
+ render = <Button variant="outline" size="sm" />,
170
+ ...props
171
+ }: ToastPrimitive.Action.Props) {
172
+ return (
173
+ <ToastPrimitive.Action
174
+ data-slot="toast-action"
175
+ render={render}
176
+ className={cn("shrink-0", className)}
177
+ {...props}
178
+ />
179
+ )
180
+ }
181
+
182
+ function ToastClose({
183
+ className,
184
+ children,
185
+ render = <Button variant="ghost" size="icon-sm" />,
186
+ ...props
187
+ }: ToastPrimitive.Close.Props) {
188
+ return (
189
+ <ToastPrimitive.Close
190
+ data-slot="toast-close"
191
+ aria-label="Close toast"
192
+ render={render}
193
+ className={cn(
194
+ "relative shrink-0 text-muted-foreground after:absolute after:-inset-2 after:content-[''] hover:text-foreground",
195
+ className
196
+ )}
197
+ {...props}
198
+ >
199
+ {children ?? (
200
+ <XIcon aria-hidden="true" />
201
+ )}
202
+ </ToastPrimitive.Close>
203
+ )
204
+ }
205
+
206
+ function ToastIcon({ type }: { type: string | undefined }) {
207
+ let icon: React.ReactNode = null
208
+
209
+ if (type === "success") {
210
+ icon = (
211
+ <CircleCheckIcon aria-hidden="true" />
212
+ )
213
+ }
214
+
215
+ if (type === "info") {
216
+ icon = (
217
+ <InfoIcon aria-hidden="true" />
218
+ )
219
+ }
220
+
221
+ if (type === "warning") {
222
+ icon = (
223
+ <TriangleAlertIcon aria-hidden="true" />
224
+ )
225
+ }
226
+
227
+ if (type === "error") {
228
+ icon = (
229
+ <OctagonXIcon className="text-destructive" aria-hidden="true" />
230
+ )
231
+ }
232
+
233
+ if (type === "loading") {
234
+ icon = (
235
+ <Loader2Icon className="animate-spin" aria-hidden="true" />
236
+ )
237
+ }
238
+
239
+ if (!icon) {
240
+ return null
241
+ }
242
+
243
+ return (
244
+ <span
245
+ data-slot="toast-icon"
246
+ className="shrink-0 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4"
247
+ >
248
+ {icon}
249
+ </span>
250
+ )
251
+ }
252
+
253
+ function ToastList() {
254
+ const { toasts } = ToastPrimitive.useToastManager()
255
+ const top = React.useContext(ToastPositionContext) === "top-center"
256
+
257
+ return toasts.map((toastItem) => (
258
+ <Toast key={toastItem.id} toast={toastItem} swipeDirection={top ? "up" : undefined}>
259
+ <ToastContent>
260
+ <ToastIcon type={toastItem.type} />
261
+ <div className="flex min-w-0 flex-1 flex-col gap-1">
262
+ <ToastTitle />
263
+ <ToastDescription />
264
+ </div>
265
+ <ToastAction />
266
+ <ToastClose />
267
+ </ToastContent>
268
+ </Toast>
269
+ ))
270
+ }
271
+
272
+ function Toaster({
273
+ children,
274
+ position = "top-center",
275
+ ...props
276
+ }: ToastPrimitive.Provider.Props & { position?: ToasterPosition }) {
277
+ return (
278
+ <ToastPositionContext.Provider value={position}>
279
+ <ToastProvider toastManager={toastManager} {...props}>
280
+ {children}
281
+ <ToastPortal>
282
+ <ToastViewport>
283
+ <ToastList />
284
+ </ToastViewport>
285
+ </ToastPortal>
286
+ </ToastProvider>
287
+ </ToastPositionContext.Provider>
288
+ )
289
+ }
290
+
291
+ const createToastManager = ToastPrimitive.createToastManager
292
+ const useToastManager = ToastPrimitive.useToastManager
293
+
294
+ export {
295
+ Toaster,
296
+ Toast,
297
+ ToastAction,
298
+ ToastClose,
299
+ ToastContent,
300
+ ToastDescription,
301
+ ToastPortal,
302
+ ToastProvider,
303
+ ToastTitle,
304
+ ToastViewport,
305
+ createToastManager,
306
+ toast,
307
+ useToastManager,
308
+ }
@@ -0,0 +1,64 @@
1
+
2
+ import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip"
3
+ import { cn } from "cn"
4
+
5
+ function TooltipProvider({
6
+ delay = 0,
7
+ ...props
8
+ }: TooltipPrimitive.Provider.Props) {
9
+ return (
10
+ <TooltipPrimitive.Provider
11
+ data-slot="tooltip-provider"
12
+ delay={delay}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ function Tooltip({ ...props }: TooltipPrimitive.Root.Props) {
19
+ return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
20
+ }
21
+
22
+ function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
23
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
24
+ }
25
+
26
+ function TooltipContent({
27
+ className,
28
+ side = "top",
29
+ sideOffset = 4,
30
+ align = "center",
31
+ alignOffset = 0,
32
+ children,
33
+ ...props
34
+ }: TooltipPrimitive.Popup.Props &
35
+ Pick<
36
+ TooltipPrimitive.Positioner.Props,
37
+ "align" | "alignOffset" | "side" | "sideOffset"
38
+ >) {
39
+ return (
40
+ <TooltipPrimitive.Portal>
41
+ <TooltipPrimitive.Positioner
42
+ align={align}
43
+ alignOffset={alignOffset}
44
+ side={side}
45
+ sideOffset={sideOffset}
46
+ className="isolate z-50"
47
+ >
48
+ <TooltipPrimitive.Popup
49
+ data-slot="tooltip-content"
50
+ className={cn(
51
+ "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",
52
+ className
53
+ )}
54
+ {...props}
55
+ >
56
+ {children}
57
+ <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" />
58
+ </TooltipPrimitive.Popup>
59
+ </TooltipPrimitive.Positioner>
60
+ </TooltipPrimitive.Portal>
61
+ )
62
+ }
63
+
64
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allbluecn/admin-app",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "private": false,
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",
@@ -80,7 +80,8 @@
80
80
  },
81
81
  "files": [
82
82
  "src",
83
- "public"
83
+ "public",
84
+ "allblue-ui"
84
85
  ],
85
86
  "publishConfig": {
86
87
  "access": "public"