@monkey-mini-app/ui 0.1.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 (149) hide show
  1. package/components.json +23 -0
  2. package/dist/globals.css +2 -0
  3. package/dist/index.js +138 -0
  4. package/dist/manifest.json +11 -0
  5. package/dist/src/blocks/activity-feed.tsx +9 -0
  6. package/dist/src/blocks/app-shell.tsx +37 -0
  7. package/dist/src/blocks/attachment-gallery.tsx +30 -0
  8. package/dist/src/blocks/bar-chart.tsx +33 -0
  9. package/dist/src/blocks/comment-thread.tsx +30 -0
  10. package/dist/src/blocks/description-list.tsx +16 -0
  11. package/dist/src/blocks/detail-panel.tsx +43 -0
  12. package/dist/src/blocks/donut-chart.tsx +38 -0
  13. package/dist/src/blocks/env-badge.tsx +23 -0
  14. package/dist/src/blocks/file-tree.tsx +5 -0
  15. package/dist/src/blocks/filter-bar.tsx +21 -0
  16. package/dist/src/blocks/gauge.tsx +13 -0
  17. package/dist/src/blocks/notification-center.tsx +22 -0
  18. package/dist/src/blocks/page-header.tsx +30 -0
  19. package/dist/src/blocks/progress-ring.tsx +25 -0
  20. package/dist/src/blocks/radar-chart.tsx +31 -0
  21. package/dist/src/blocks/request-inspector.tsx +34 -0
  22. package/dist/src/blocks/run-timeline.tsx +5 -0
  23. package/dist/src/blocks/scrollspy.tsx +42 -0
  24. package/dist/src/blocks/severity-chip.tsx +27 -0
  25. package/dist/src/blocks/sparkline.tsx +19 -0
  26. package/dist/src/blocks/stat-card.tsx +49 -0
  27. package/dist/src/blocks/status-badge.tsx +39 -0
  28. package/dist/src/blocks/terminal.tsx +10 -0
  29. package/dist/src/blocks/test-step-list.tsx +19 -0
  30. package/dist/src/blocks/trend-card.tsx +51 -0
  31. package/dist/src/components/accordion.tsx +72 -0
  32. package/dist/src/components/alert-dialog.tsx +185 -0
  33. package/dist/src/components/alert.tsx +76 -0
  34. package/dist/src/components/aspect-ratio.tsx +22 -0
  35. package/dist/src/components/attachment.tsx +207 -0
  36. package/dist/src/components/avatar.tsx +107 -0
  37. package/dist/src/components/badge.tsx +52 -0
  38. package/dist/src/components/breadcrumb.tsx +125 -0
  39. package/dist/src/components/bubble.tsx +128 -0
  40. package/dist/src/components/button-group.tsx +87 -0
  41. package/dist/src/components/button.tsx +58 -0
  42. package/dist/src/components/calendar.tsx +221 -0
  43. package/dist/src/components/card.tsx +103 -0
  44. package/dist/src/components/chart.tsx +371 -0
  45. package/dist/src/components/checkbox.tsx +29 -0
  46. package/dist/src/components/collapsible.tsx +19 -0
  47. package/dist/src/components/combobox.tsx +295 -0
  48. package/dist/src/components/command.tsx +196 -0
  49. package/dist/src/components/context-menu.tsx +271 -0
  50. package/dist/src/components/dialog.tsx +158 -0
  51. package/dist/src/components/drawer.tsx +226 -0
  52. package/dist/src/components/dropdown-menu.tsx +268 -0
  53. package/dist/src/components/empty.tsx +123 -0
  54. package/dist/src/components/field.tsx +236 -0
  55. package/dist/src/components/hover-card.tsx +49 -0
  56. package/dist/src/components/input-group.tsx +158 -0
  57. package/dist/src/components/input.tsx +20 -0
  58. package/dist/src/components/item.tsx +201 -0
  59. package/dist/src/components/kbd.tsx +26 -0
  60. package/dist/src/components/label.tsx +20 -0
  61. package/dist/src/components/marker.tsx +71 -0
  62. package/dist/src/components/menubar.tsx +280 -0
  63. package/dist/src/components/message-scroller.tsx +129 -0
  64. package/dist/src/components/message.tsx +92 -0
  65. package/dist/src/components/native-select.tsx +61 -0
  66. package/dist/src/components/navigation-menu.tsx +168 -0
  67. package/dist/src/components/pagination.tsx +135 -0
  68. package/dist/src/components/popover.tsx +88 -0
  69. package/dist/src/components/progress.tsx +83 -0
  70. package/dist/src/components/questionnaire.tsx +329 -0
  71. package/dist/src/components/radio-group.tsx +36 -0
  72. package/dist/src/components/resizable.tsx +50 -0
  73. package/dist/src/components/scroll-area.tsx +52 -0
  74. package/dist/src/components/select.tsx +201 -0
  75. package/dist/src/components/separator.tsx +23 -0
  76. package/dist/src/components/sheet.tsx +136 -0
  77. package/dist/src/components/sidebar.tsx +721 -0
  78. package/dist/src/components/skeleton.tsx +13 -0
  79. package/dist/src/components/slider.tsx +52 -0
  80. package/dist/src/components/spinner.tsx +10 -0
  81. package/dist/src/components/switch.tsx +32 -0
  82. package/dist/src/components/table.tsx +114 -0
  83. package/dist/src/components/tabs.tsx +82 -0
  84. package/dist/src/components/textarea.tsx +18 -0
  85. package/dist/src/components/toast.tsx +234 -0
  86. package/dist/src/components/toggle-group.tsx +89 -0
  87. package/dist/src/components/toggle.tsx +43 -0
  88. package/dist/src/components/tooltip.tsx +66 -0
  89. package/dist/src/composites/autocomplete.tsx +55 -0
  90. package/dist/src/composites/cascader.tsx +46 -0
  91. package/dist/src/composites/color-picker.tsx +19 -0
  92. package/dist/src/composites/confirm-dialog.tsx +56 -0
  93. package/dist/src/composites/copyable.tsx +37 -0
  94. package/dist/src/composites/currency-input.tsx +31 -0
  95. package/dist/src/composites/date-chrome.tsx +157 -0
  96. package/dist/src/composites/date-picker.tsx +91 -0
  97. package/dist/src/composites/date-range-picker.tsx +96 -0
  98. package/dist/src/composites/date-time-picker.tsx +115 -0
  99. package/dist/src/composites/date-time-range-picker.tsx +51 -0
  100. package/dist/src/composites/duration-input.tsx +122 -0
  101. package/dist/src/composites/mini-calendar.tsx +24 -0
  102. package/dist/src/composites/number-field.tsx +53 -0
  103. package/dist/src/composites/password-field.tsx +44 -0
  104. package/dist/src/composites/phone-input.tsx +22 -0
  105. package/dist/src/composites/rating.tsx +39 -0
  106. package/dist/src/composites/relative-date-picker.tsx +62 -0
  107. package/dist/src/composites/search-input.tsx +49 -0
  108. package/dist/src/composites/slider-range.tsx +30 -0
  109. package/dist/src/composites/tag-input.tsx +56 -0
  110. package/dist/src/composites/time-picker.tsx +199 -0
  111. package/dist/src/composites/time-range-picker.tsx +25 -0
  112. package/dist/src/composites/timezone-select.tsx +251 -0
  113. package/dist/src/composites/transfer.tsx +52 -0
  114. package/dist/src/composites/user-picker.tsx +40 -0
  115. package/dist/src/hooks/use-mobile.ts +19 -0
  116. package/dist/src/i18n/context.tsx +72 -0
  117. package/dist/src/i18n/en.ts +168 -0
  118. package/dist/src/i18n/zh.ts +160 -0
  119. package/dist/src/index.ts +134 -0
  120. package/dist/src/lib/icons.tsx +16 -0
  121. package/dist/src/lib/illustrations.tsx +573 -0
  122. package/dist/src/lib/utils.ts +6 -0
  123. package/dist/src/products/cells.tsx +18 -0
  124. package/dist/src/products/code-block.tsx +75 -0
  125. package/dist/src/products/code-editor.tsx +49 -0
  126. package/dist/src/products/column-meta.d.ts +9 -0
  127. package/dist/src/products/data-grid.tsx +689 -0
  128. package/dist/src/products/diff-viewer.tsx +129 -0
  129. package/dist/src/products/event-calendar.tsx +845 -0
  130. package/dist/src/products/export-csv.ts +25 -0
  131. package/dist/src/products/file-dropzone.tsx +41 -0
  132. package/dist/src/products/gantt.tsx +41 -0
  133. package/dist/src/products/jira-wiki-parse.ts +197 -0
  134. package/dist/src/products/jira-wiki.tsx +285 -0
  135. package/dist/src/products/jql-input.tsx +62 -0
  136. package/dist/src/products/jql-language.ts +70 -0
  137. package/dist/src/products/json-viewer.tsx +37 -0
  138. package/dist/src/products/kanban-issue-panel.tsx +98 -0
  139. package/dist/src/products/kanban.tsx +245 -0
  140. package/dist/src/products/log-viewer.tsx +33 -0
  141. package/dist/src/products/markdown-editor.tsx +63 -0
  142. package/dist/src/products/markdown.tsx +26 -0
  143. package/dist/src/products/rich-text-editor.tsx +84 -0
  144. package/dist/src/products/sortable-list.tsx +61 -0
  145. package/dist/src/products/stepper.tsx +89 -0
  146. package/dist/src/products/timeline.tsx +32 -0
  147. package/dist/src/products/tree-view.tsx +56 -0
  148. package/dist/src/styles/globals.css +352 -0
  149. package/package.json +100 -0
@@ -0,0 +1,42 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+
5
+ export function Scrollspy({
6
+ sections,
7
+ }: {
8
+ sections: { id: string; label: string }[]
9
+ }) {
10
+ const [active, setActive] = React.useState(sections[0]?.id)
11
+ React.useEffect(() => {
12
+ const observer = new IntersectionObserver(
13
+ (entries) => {
14
+ const visible = entries.find((entry) => entry.isIntersecting)
15
+ if (visible?.target.id) setActive(visible.target.id)
16
+ },
17
+ { rootMargin: "-40% 0px -50% 0px" }
18
+ )
19
+ sections.forEach((section) => {
20
+ const el = document.getElementById(section.id)
21
+ if (el) observer.observe(el)
22
+ })
23
+ return () => observer.disconnect()
24
+ }, [sections])
25
+ return (
26
+ <nav className="flex flex-col gap-1 text-sm" data-testid="scrollspy">
27
+ {sections.map((section) => (
28
+ <a
29
+ key={section.id}
30
+ href={`#${section.id}`}
31
+ className={
32
+ active === section.id
33
+ ? "text-foreground font-medium"
34
+ : "text-muted-foreground"
35
+ }
36
+ >
37
+ {section.label}
38
+ </a>
39
+ ))}
40
+ </nav>
41
+ )
42
+ }
@@ -0,0 +1,27 @@
1
+ import { Badge } from "@monkey-mini-app/ui/components/badge"
2
+ import { cn } from "@monkey-mini-app/ui/lib/utils"
3
+
4
+ const tone = {
5
+ P0: "bg-destructive/15 text-destructive",
6
+ P1: "bg-orange-500/15 text-orange-700 dark:text-orange-400",
7
+ P2: "bg-amber-500/15 text-amber-700 dark:text-amber-400",
8
+ P3: "bg-muted text-muted-foreground",
9
+ critical: "bg-destructive/15 text-destructive",
10
+ high: "bg-orange-500/15 text-orange-700 dark:text-orange-400",
11
+ medium: "bg-amber-500/15 text-amber-700 dark:text-amber-400",
12
+ low: "bg-muted text-muted-foreground",
13
+ } as const
14
+
15
+ export type Severity = keyof typeof tone
16
+
17
+ export function SeverityChip({ severity }: { severity: Severity | string }) {
18
+ return (
19
+ <Badge
20
+ variant="outline"
21
+ data-testid="severity-chip"
22
+ className={cn("border-transparent uppercase", tone[severity as Severity] ?? tone.low)}
23
+ >
24
+ {severity}
25
+ </Badge>
26
+ )
27
+ }
@@ -0,0 +1,19 @@
1
+ "use client"
2
+
3
+ import { Line, LineChart } from "recharts"
4
+
5
+ import { ChartContainer, type ChartConfig } from "@monkey-mini-app/ui/components/chart"
6
+
7
+ const config = {
8
+ value: { label: "Value", color: "var(--chart-1)" },
9
+ } satisfies ChartConfig
10
+
11
+ export function Sparkline({ data }: { data: { value: number }[] }) {
12
+ return (
13
+ <ChartContainer config={config} className="h-10 w-24" data-testid="sparkline">
14
+ <LineChart data={data}>
15
+ <Line dataKey="value" type="monotone" stroke="var(--color-value)" strokeWidth={1.5} dot={false} />
16
+ </LineChart>
17
+ </ChartContainer>
18
+ )
19
+ }
@@ -0,0 +1,49 @@
1
+ import type { ReactNode } from "react"
2
+
3
+ import { Card, CardContent, CardHeader, CardTitle } from "@monkey-mini-app/ui/components/card"
4
+ import { cn } from "@monkey-mini-app/ui/lib/utils"
5
+
6
+ export type StatCardProps = {
7
+ title: string
8
+ value: ReactNode
9
+ delta?: string
10
+ trend?: "up" | "down" | "flat"
11
+ children?: ReactNode
12
+ }
13
+
14
+ /**
15
+ * KPI card: title, value, optional delta/trend.
16
+ * @when Dashboard metric strip
17
+ * @example
18
+ * <StatCard title="Pass rate" value="98%" delta="+1.2%" trend="up" />
19
+ */
20
+ export function StatCard({ title, value, delta, trend = "flat", children }: StatCardProps) {
21
+ return (
22
+ <Card data-testid="stat-card">
23
+ <CardHeader>
24
+ <CardTitle className="text-muted-foreground text-sm font-normal">
25
+ {title}
26
+ </CardTitle>
27
+ </CardHeader>
28
+ <CardContent className="flex flex-col gap-2">
29
+ <div className="text-2xl font-medium" data-testid="stat-card-value">
30
+ {value}
31
+ </div>
32
+ {delta ? (
33
+ <div
34
+ data-testid="stat-card-delta"
35
+ className={cn(
36
+ "text-xs",
37
+ trend === "up" && "text-emerald-600",
38
+ trend === "down" && "text-destructive",
39
+ trend === "flat" && "text-muted-foreground"
40
+ )}
41
+ >
42
+ {delta}
43
+ </div>
44
+ ) : null}
45
+ {children}
46
+ </CardContent>
47
+ </Card>
48
+ )
49
+ }
@@ -0,0 +1,39 @@
1
+ import { Badge } from "@monkey-mini-app/ui/components/badge"
2
+ import { cn } from "@monkey-mini-app/ui/lib/utils"
3
+
4
+ export const statusTone = {
5
+ pass: "border-transparent bg-emerald-600/15 text-emerald-700 dark:text-emerald-400",
6
+ fail: "border-transparent bg-destructive/15 text-destructive",
7
+ blocked: "border-transparent bg-amber-500/15 text-amber-700 dark:text-amber-400",
8
+ flaky: "border-transparent bg-orange-500/15 text-orange-700 dark:text-orange-400",
9
+ running: "border-transparent bg-sky-500/15 text-sky-700 dark:text-sky-400",
10
+ pending: "border-transparent bg-muted text-muted-foreground",
11
+ } as const
12
+
13
+ export type StatusKey = keyof typeof statusTone
14
+
15
+ /**
16
+ * Toned badge for run/test status.
17
+ * @when pass | fail | blocked | flaky | running | pending cells and chips
18
+ * @example
19
+ * <StatusBadge status="pass" />
20
+ */
21
+ export function StatusBadge({
22
+ status,
23
+ className,
24
+ }: {
25
+ status: StatusKey | string
26
+ className?: string
27
+ }) {
28
+ const tone = statusTone[status as StatusKey] ?? statusTone.pending
29
+ return (
30
+ <Badge
31
+ variant="outline"
32
+ data-testid="status-badge"
33
+ data-status={status}
34
+ className={cn("capitalize", tone, className)}
35
+ >
36
+ {status}
37
+ </Badge>
38
+ )
39
+ }
@@ -0,0 +1,10 @@
1
+ export function Terminal({ lines }: { lines: string[] }) {
2
+ return (
3
+ <pre
4
+ data-testid="terminal"
5
+ className="overflow-auto rounded-xl bg-zinc-950 p-3 font-mono text-xs leading-6 text-zinc-100"
6
+ >
7
+ {lines.join("\n")}
8
+ </pre>
9
+ )
10
+ }
@@ -0,0 +1,19 @@
1
+ import { StatusBadge, type StatusKey } from "@monkey-mini-app/ui/blocks/status-badge"
2
+
3
+ export type TestStep = { id: string; title: string; status: StatusKey | string }
4
+
5
+ export function TestStepList({ steps }: { steps: TestStep[] }) {
6
+ return (
7
+ <ol className="flex flex-col gap-2" data-testid="test-step-list">
8
+ {steps.map((step, index) => (
9
+ <li key={step.id} className="flex items-center justify-between gap-3 text-sm">
10
+ <span>
11
+ <span className="text-muted-foreground mr-2">{index + 1}.</span>
12
+ {step.title}
13
+ </span>
14
+ <StatusBadge status={step.status} />
15
+ </li>
16
+ ))}
17
+ </ol>
18
+ )
19
+ }
@@ -0,0 +1,51 @@
1
+ "use client"
2
+
3
+ import type { ReactNode } from "react"
4
+ import { CartesianGrid, Line, LineChart, XAxis } from "recharts"
5
+
6
+ import {
7
+ ChartContainer,
8
+ ChartTooltip,
9
+ ChartTooltipContent,
10
+ type ChartConfig,
11
+ } from "@monkey-mini-app/ui/components/chart"
12
+ import { StatCard } from "@monkey-mini-app/ui/blocks/stat-card"
13
+
14
+ export type TrendPoint = { label: string; value: number }
15
+
16
+ const chartConfig = {
17
+ value: { label: "Value", color: "var(--chart-1)" },
18
+ } satisfies ChartConfig
19
+
20
+ export function TrendCard({
21
+ title,
22
+ value,
23
+ delta,
24
+ trend,
25
+ data,
26
+ }: {
27
+ title: string
28
+ value: ReactNode
29
+ delta?: string
30
+ trend?: "up" | "down" | "flat"
31
+ data: TrendPoint[]
32
+ }) {
33
+ return (
34
+ <StatCard title={title} value={value} delta={delta} trend={trend}>
35
+ <ChartContainer config={chartConfig} className="h-[120px] w-full">
36
+ <LineChart data={data} accessibilityLayer>
37
+ <CartesianGrid vertical={false} />
38
+ <XAxis dataKey="label" tickLine={false} axisLine={false} />
39
+ <ChartTooltip content={<ChartTooltipContent />} />
40
+ <Line
41
+ dataKey="value"
42
+ type="monotone"
43
+ stroke="var(--color-value)"
44
+ strokeWidth={2}
45
+ dot={false}
46
+ />
47
+ </LineChart>
48
+ </ChartContainer>
49
+ </StatCard>
50
+ )
51
+ }
@@ -0,0 +1,72 @@
1
+ import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion"
2
+
3
+ import { cn } from "@monkey-mini-app/ui/lib/utils"
4
+ import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"
5
+
6
+ function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {
7
+ return (
8
+ <AccordionPrimitive.Root
9
+ data-slot="accordion"
10
+ className={cn("flex w-full flex-col", className)}
11
+ {...props}
12
+ />
13
+ )
14
+ }
15
+
16
+ function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {
17
+ return (
18
+ <AccordionPrimitive.Item
19
+ data-slot="accordion-item"
20
+ className={cn("not-last:border-b", className)}
21
+ {...props}
22
+ />
23
+ )
24
+ }
25
+
26
+ function AccordionTrigger({
27
+ className,
28
+ children,
29
+ ...props
30
+ }: AccordionPrimitive.Trigger.Props) {
31
+ return (
32
+ <AccordionPrimitive.Header className="flex">
33
+ <AccordionPrimitive.Trigger
34
+ data-slot="accordion-trigger"
35
+ className={cn(
36
+ "group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:after:border-ring aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
37
+ className
38
+ )}
39
+ {...props}
40
+ >
41
+ {children}
42
+ <ChevronDownIcon data-slot="accordion-trigger-icon" className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden" />
43
+ <ChevronUpIcon data-slot="accordion-trigger-icon" className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline" />
44
+ </AccordionPrimitive.Trigger>
45
+ </AccordionPrimitive.Header>
46
+ )
47
+ }
48
+
49
+ function AccordionContent({
50
+ className,
51
+ children,
52
+ ...props
53
+ }: AccordionPrimitive.Panel.Props) {
54
+ return (
55
+ <AccordionPrimitive.Panel
56
+ data-slot="accordion-content"
57
+ className="overflow-hidden text-sm data-open:animate-accordion-down data-closed:animate-accordion-up"
58
+ {...props}
59
+ >
60
+ <div
61
+ className={cn(
62
+ "h-(--accordion-panel-height) pt-0 pb-2.5 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
63
+ className
64
+ )}
65
+ >
66
+ {children}
67
+ </div>
68
+ </AccordionPrimitive.Panel>
69
+ )
70
+ }
71
+
72
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
@@ -0,0 +1,185 @@
1
+ import * as React from "react"
2
+ import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"
3
+
4
+ import { cn } from "@monkey-mini-app/ui/lib/utils"
5
+ import { Button } from "@monkey-mini-app/ui/components/button"
6
+
7
+ function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
8
+ return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
9
+ }
10
+
11
+ function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
12
+ return (
13
+ <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
14
+ )
15
+ }
16
+
17
+ function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
18
+ return (
19
+ <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
20
+ )
21
+ }
22
+
23
+ function AlertDialogOverlay({
24
+ className,
25
+ ...props
26
+ }: AlertDialogPrimitive.Backdrop.Props) {
27
+ return (
28
+ <AlertDialogPrimitive.Backdrop
29
+ data-slot="alert-dialog-overlay"
30
+ className={cn(
31
+ "fixed inset-0 isolate 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",
32
+ className
33
+ )}
34
+ {...props}
35
+ />
36
+ )
37
+ }
38
+
39
+ function AlertDialogContent({
40
+ className,
41
+ size = "default",
42
+ ...props
43
+ }: AlertDialogPrimitive.Popup.Props & {
44
+ size?: "default" | "sm"
45
+ }) {
46
+ return (
47
+ <AlertDialogPortal>
48
+ <AlertDialogOverlay />
49
+ <AlertDialogPrimitive.Popup
50
+ data-slot="alert-dialog-content"
51
+ data-size={size}
52
+ className={cn(
53
+ "group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm 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",
54
+ className
55
+ )}
56
+ {...props}
57
+ />
58
+ </AlertDialogPortal>
59
+ )
60
+ }
61
+
62
+ function AlertDialogHeader({
63
+ className,
64
+ ...props
65
+ }: React.ComponentProps<"div">) {
66
+ return (
67
+ <div
68
+ data-slot="alert-dialog-header"
69
+ className={cn(
70
+ "grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
71
+ className
72
+ )}
73
+ {...props}
74
+ />
75
+ )
76
+ }
77
+
78
+ function AlertDialogFooter({
79
+ className,
80
+ ...props
81
+ }: React.ComponentProps<"div">) {
82
+ return (
83
+ <div
84
+ data-slot="alert-dialog-footer"
85
+ className={cn(
86
+ "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
87
+ className
88
+ )}
89
+ {...props}
90
+ />
91
+ )
92
+ }
93
+
94
+ function AlertDialogMedia({
95
+ className,
96
+ ...props
97
+ }: React.ComponentProps<"div">) {
98
+ return (
99
+ <div
100
+ data-slot="alert-dialog-media"
101
+ className={cn(
102
+ "mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
103
+ className
104
+ )}
105
+ {...props}
106
+ />
107
+ )
108
+ }
109
+
110
+ function AlertDialogTitle({
111
+ className,
112
+ ...props
113
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
114
+ return (
115
+ <AlertDialogPrimitive.Title
116
+ data-slot="alert-dialog-title"
117
+ className={cn(
118
+ "font-heading text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
119
+ className
120
+ )}
121
+ {...props}
122
+ />
123
+ )
124
+ }
125
+
126
+ function AlertDialogDescription({
127
+ className,
128
+ ...props
129
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
130
+ return (
131
+ <AlertDialogPrimitive.Description
132
+ data-slot="alert-dialog-description"
133
+ className={cn(
134
+ "text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
135
+ className
136
+ )}
137
+ {...props}
138
+ />
139
+ )
140
+ }
141
+
142
+ function AlertDialogAction({
143
+ className,
144
+ ...props
145
+ }: React.ComponentProps<typeof Button>) {
146
+ return (
147
+ <Button
148
+ data-slot="alert-dialog-action"
149
+ className={cn(className)}
150
+ {...props}
151
+ />
152
+ )
153
+ }
154
+
155
+ function AlertDialogCancel({
156
+ className,
157
+ variant = "outline",
158
+ size = "default",
159
+ ...props
160
+ }: AlertDialogPrimitive.Close.Props &
161
+ Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
162
+ return (
163
+ <AlertDialogPrimitive.Close
164
+ data-slot="alert-dialog-cancel"
165
+ className={cn(className)}
166
+ render={<Button variant={variant} size={size} />}
167
+ {...props}
168
+ />
169
+ )
170
+ }
171
+
172
+ export {
173
+ AlertDialog,
174
+ AlertDialogAction,
175
+ AlertDialogCancel,
176
+ AlertDialogContent,
177
+ AlertDialogDescription,
178
+ AlertDialogFooter,
179
+ AlertDialogHeader,
180
+ AlertDialogMedia,
181
+ AlertDialogOverlay,
182
+ AlertDialogPortal,
183
+ AlertDialogTitle,
184
+ AlertDialogTrigger,
185
+ }
@@ -0,0 +1,76 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+
4
+ import { cn } from "@monkey-mini-app/ui/lib/utils"
5
+
6
+ const alertVariants = cva(
7
+ "group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-card text-card-foreground",
12
+ destructive:
13
+ "bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
14
+ },
15
+ },
16
+ defaultVariants: {
17
+ variant: "default",
18
+ },
19
+ }
20
+ )
21
+
22
+ function Alert({
23
+ className,
24
+ variant,
25
+ ...props
26
+ }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
27
+ return (
28
+ <div
29
+ data-slot="alert"
30
+ role="alert"
31
+ className={cn(alertVariants({ variant }), className)}
32
+ {...props}
33
+ />
34
+ )
35
+ }
36
+
37
+ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
38
+ return (
39
+ <div
40
+ data-slot="alert-title"
41
+ className={cn(
42
+ "font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
43
+ className
44
+ )}
45
+ {...props}
46
+ />
47
+ )
48
+ }
49
+
50
+ function AlertDescription({
51
+ className,
52
+ ...props
53
+ }: React.ComponentProps<"div">) {
54
+ return (
55
+ <div
56
+ data-slot="alert-description"
57
+ className={cn(
58
+ "text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
59
+ className
60
+ )}
61
+ {...props}
62
+ />
63
+ )
64
+ }
65
+
66
+ function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
67
+ return (
68
+ <div
69
+ data-slot="alert-action"
70
+ className={cn("absolute top-2 right-2", className)}
71
+ {...props}
72
+ />
73
+ )
74
+ }
75
+
76
+ export { Alert, AlertTitle, AlertDescription, AlertAction }
@@ -0,0 +1,22 @@
1
+ import { cn } from "@monkey-mini-app/ui/lib/utils"
2
+
3
+ function AspectRatio({
4
+ ratio,
5
+ className,
6
+ ...props
7
+ }: React.ComponentProps<"div"> & { ratio: number }) {
8
+ return (
9
+ <div
10
+ data-slot="aspect-ratio"
11
+ style={
12
+ {
13
+ "--ratio": ratio,
14
+ } as React.CSSProperties
15
+ }
16
+ className={cn("relative aspect-(--ratio)", className)}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ export { AspectRatio }