@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,61 @@
1
+ "use client"
2
+
3
+ import {
4
+ DndContext,
5
+ closestCenter,
6
+ type DragEndEvent,
7
+ } from "@dnd-kit/core"
8
+ import {
9
+ SortableContext,
10
+ arrayMove,
11
+ useSortable,
12
+ verticalListSortingStrategy,
13
+ } from "@dnd-kit/sortable"
14
+ import { CSS } from "@dnd-kit/utilities"
15
+ import { GripVertical } from "lucide-react"
16
+
17
+ export type SortableItem = { id: string; label: string }
18
+
19
+ function Row({ item }: { item: SortableItem }) {
20
+ const { attributes, listeners, setNodeRef, transform, transition } =
21
+ useSortable({ id: item.id })
22
+ return (
23
+ <div
24
+ ref={setNodeRef}
25
+ style={{ transform: CSS.Transform.toString(transform), transition }}
26
+ className="flex items-center gap-2 rounded-lg border bg-card px-2 py-1.5 text-sm"
27
+ >
28
+ <button type="button" className="text-muted-foreground" {...attributes} {...listeners}>
29
+ <GripVertical className="size-3.5" />
30
+ </button>
31
+ {item.label}
32
+ </div>
33
+ )
34
+ }
35
+
36
+ export function SortableList({
37
+ items,
38
+ onChange,
39
+ }: {
40
+ items: SortableItem[]
41
+ onChange?: (items: SortableItem[]) => void
42
+ }) {
43
+ const onDragEnd = (event: DragEndEvent) => {
44
+ const { active, over } = event
45
+ if (!over || active.id === over.id) return
46
+ const oldIndex = items.findIndex((item) => item.id === active.id)
47
+ const newIndex = items.findIndex((item) => item.id === over.id)
48
+ onChange?.(arrayMove(items, oldIndex, newIndex))
49
+ }
50
+ return (
51
+ <DndContext collisionDetection={closestCenter} onDragEnd={onDragEnd}>
52
+ <SortableContext items={items.map((item) => item.id)} strategy={verticalListSortingStrategy}>
53
+ <div className="flex flex-col gap-1.5" data-testid="sortable-list">
54
+ {items.map((item) => (
55
+ <Row key={item.id} item={item} />
56
+ ))}
57
+ </div>
58
+ </SortableContext>
59
+ </DndContext>
60
+ )
61
+ }
@@ -0,0 +1,89 @@
1
+ "use client"
2
+
3
+ import { Check } from "lucide-react"
4
+
5
+ import { cn } from "@monkey-mini-app/ui/lib/utils"
6
+
7
+ export type Step = { id: string; title: string; description?: string }
8
+
9
+ export function Stepper({
10
+ steps,
11
+ current,
12
+ orientation = "vertical",
13
+ onStepClick,
14
+ }: {
15
+ steps: Step[]
16
+ current: number
17
+ orientation?: "vertical" | "horizontal"
18
+ onStepClick?: (index: number) => void
19
+ }) {
20
+ const horizontal = orientation === "horizontal"
21
+
22
+ return (
23
+ <ol
24
+ data-testid="stepper"
25
+ data-orientation={orientation}
26
+ className={cn(horizontal ? "flex items-start gap-0" : "flex flex-col gap-3")}
27
+ >
28
+ {steps.map((step, index) => {
29
+ const state =
30
+ index < current ? "done" : index === current ? "current" : "todo"
31
+ const clickable = Boolean(onStepClick)
32
+ return (
33
+ <li
34
+ key={step.id}
35
+ className={cn(
36
+ horizontal
37
+ ? "flex min-w-0 flex-1 flex-col items-center text-center"
38
+ : "flex gap-3"
39
+ )}
40
+ >
41
+ <div
42
+ className={cn(
43
+ "flex items-center",
44
+ horizontal ? "w-full justify-center" : "flex-col"
45
+ )}
46
+ >
47
+ {horizontal && index > 0 ? (
48
+ <span
49
+ className={cn(
50
+ "mr-2 h-px min-w-4 flex-1",
51
+ index <= current ? "bg-primary" : "bg-border"
52
+ )}
53
+ />
54
+ ) : null}
55
+ <button
56
+ type="button"
57
+ disabled={!clickable}
58
+ onClick={() => onStepClick?.(index)}
59
+ className={cn(
60
+ "flex size-7 shrink-0 items-center justify-center rounded-full text-xs font-medium",
61
+ state === "done" && "bg-primary text-primary-foreground",
62
+ state === "current" && "border-2 border-primary text-primary",
63
+ state === "todo" && "border text-muted-foreground",
64
+ clickable && "cursor-pointer"
65
+ )}
66
+ >
67
+ {state === "done" ? <Check className="size-3.5" /> : index + 1}
68
+ </button>
69
+ {horizontal && index < steps.length - 1 ? (
70
+ <span
71
+ className={cn(
72
+ "ml-2 h-px min-w-4 flex-1",
73
+ index < current ? "bg-primary" : "bg-border"
74
+ )}
75
+ />
76
+ ) : null}
77
+ </div>
78
+ <div className={cn(horizontal ? "mt-2 px-1" : "")}>
79
+ <div className="text-sm font-medium">{step.title}</div>
80
+ {step.description ? (
81
+ <p className="text-muted-foreground text-xs">{step.description}</p>
82
+ ) : null}
83
+ </div>
84
+ </li>
85
+ )
86
+ })}
87
+ </ol>
88
+ )
89
+ }
@@ -0,0 +1,32 @@
1
+ import { cn } from "@monkey-mini-app/ui/lib/utils"
2
+
3
+ export type TimelineItem = {
4
+ id: string
5
+ title: string
6
+ description?: string
7
+ time?: string
8
+ }
9
+
10
+ export function Timeline({ items }: { items: TimelineItem[] }) {
11
+ return (
12
+ <ol className="relative space-y-4 border-l pl-4" data-testid="timeline">
13
+ {items.map((item, index) => (
14
+ <li key={item.id} className="relative">
15
+ <span
16
+ className={cn(
17
+ "absolute top-1.5 -left-[21px] size-2.5 rounded-full border bg-background",
18
+ index === 0 ? "border-primary bg-primary" : "border-muted-foreground/40"
19
+ )}
20
+ />
21
+ <div className="text-sm font-medium">{item.title}</div>
22
+ {item.description ? (
23
+ <p className="text-muted-foreground text-xs">{item.description}</p>
24
+ ) : null}
25
+ {item.time ? (
26
+ <p className="text-muted-foreground mt-0.5 text-[11px]">{item.time}</p>
27
+ ) : null}
28
+ </li>
29
+ ))}
30
+ </ol>
31
+ )
32
+ }
@@ -0,0 +1,56 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { ChevronRight } from "lucide-react"
5
+
6
+ import { cn } from "@monkey-mini-app/ui/lib/utils"
7
+
8
+ export type TreeNode = {
9
+ id: string
10
+ label: string
11
+ children?: TreeNode[]
12
+ }
13
+
14
+ function Node({
15
+ node,
16
+ depth,
17
+ }: {
18
+ node: TreeNode
19
+ depth: number
20
+ }) {
21
+ const [open, setOpen] = React.useState(true)
22
+ const hasChildren = Boolean(node.children?.length)
23
+ return (
24
+ <div>
25
+ <button
26
+ type="button"
27
+ className="flex w-full items-center gap-1 rounded-md px-1 py-0.5 text-left text-sm hover:bg-muted"
28
+ style={{ paddingLeft: depth * 12 }}
29
+ onClick={() => hasChildren && setOpen((value) => !value)}
30
+ >
31
+ <ChevronRight
32
+ className={cn(
33
+ "size-3.5 text-muted-foreground transition",
34
+ hasChildren ? (open ? "rotate-90" : "") : "opacity-0"
35
+ )}
36
+ />
37
+ {node.label}
38
+ </button>
39
+ {open && hasChildren
40
+ ? node.children!.map((child) => (
41
+ <Node key={child.id} node={child} depth={depth + 1} />
42
+ ))
43
+ : null}
44
+ </div>
45
+ )
46
+ }
47
+
48
+ export function TreeView({ nodes }: { nodes: TreeNode[] }) {
49
+ return (
50
+ <div data-testid="tree-view">
51
+ {nodes.map((node) => (
52
+ <Node key={node.id} node={node} depth={0} />
53
+ ))}
54
+ </div>
55
+ )
56
+ }
@@ -0,0 +1,352 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @import "shadcn/tailwind.css";
4
+ @import "@fontsource-variable/geist";
5
+
6
+ @custom-variant dark (&:is(.dark *));
7
+
8
+ /* No @source directives: generate the FULL default Tailwind utility set (incl. all
9
+ responsive variants). Runtime mini-apps live outside this repo and would otherwise
10
+ miss any class that never appears here (e.g. lg:grid-cols-2) — the per-app Tailwind
11
+ re-scan was unreliable. A single comprehensive stylesheet served to every app is
12
+ ~480KB but shared/cached, covers all standard classes, and removes the fragile
13
+ per-app compile. Arbitrary values (w-[320px]) are NOT auto-generated by Tailwind;
14
+ apps should stick to standard utilities. */
15
+
16
+ @theme inline {
17
+ --font-heading: var(--font-sans);
18
+ --color-sidebar-ring: var(--sidebar-ring);
19
+ --color-sidebar-border: var(--sidebar-border);
20
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
21
+ --color-sidebar-accent: var(--sidebar-accent);
22
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
23
+ --color-sidebar-primary: var(--sidebar-primary);
24
+ --color-sidebar-foreground: var(--sidebar-foreground);
25
+ --color-sidebar: var(--sidebar);
26
+ --color-chart-5: var(--chart-5);
27
+ --color-chart-4: var(--chart-4);
28
+ --color-chart-3: var(--chart-3);
29
+ --color-chart-2: var(--chart-2);
30
+ --color-chart-1: var(--chart-1);
31
+ --color-ring: var(--ring);
32
+ --color-input: var(--input);
33
+ --color-border: var(--border);
34
+ --color-destructive: var(--destructive);
35
+ --color-accent-foreground: var(--accent-foreground);
36
+ --color-accent: var(--accent);
37
+ --color-muted-foreground: var(--muted-foreground);
38
+ --color-muted: var(--muted);
39
+ --color-secondary-foreground: var(--secondary-foreground);
40
+ --color-secondary: var(--secondary);
41
+ --color-primary-foreground: var(--primary-foreground);
42
+ --color-primary: var(--primary);
43
+ --color-popover-foreground: var(--popover-foreground);
44
+ --color-popover: var(--popover);
45
+ --color-card-foreground: var(--card-foreground);
46
+ --color-card: var(--card);
47
+ --color-foreground: var(--foreground);
48
+ --color-background: var(--background);
49
+ --radius-sm: calc(var(--radius) * 0.6);
50
+ --radius-md: calc(var(--radius) * 0.8);
51
+ --radius-lg: var(--radius);
52
+ --radius-xl: calc(var(--radius) * 1.4);
53
+ --radius-2xl: calc(var(--radius) * 1.8);
54
+ --radius-3xl: calc(var(--radius) * 2.2);
55
+ --radius-4xl: calc(var(--radius) * 2.6);
56
+ --font-sans: 'Geist Variable', sans-serif;
57
+ }
58
+
59
+ :root {
60
+ --background: oklch(1 0 0);
61
+ --foreground: oklch(0.145 0 0);
62
+ --card: oklch(1 0 0);
63
+ --card-foreground: oklch(0.145 0 0);
64
+ --popover: oklch(1 0 0);
65
+ --popover-foreground: oklch(0.145 0 0);
66
+ --primary: oklch(0.205 0 0);
67
+ --primary-foreground: oklch(0.985 0 0);
68
+ --secondary: oklch(0.97 0 0);
69
+ --secondary-foreground: oklch(0.205 0 0);
70
+ --muted: oklch(0.97 0 0);
71
+ --muted-foreground: oklch(0.556 0 0);
72
+ --accent: oklch(0.97 0 0);
73
+ --accent-foreground: oklch(0.205 0 0);
74
+ --destructive: oklch(0.577 0.245 27.325);
75
+ --border: oklch(0.922 0 0);
76
+ --input: oklch(0.922 0 0);
77
+ --ring: oklch(0.708 0 0);
78
+ --chart-1: oklch(0.87 0 0);
79
+ --chart-2: oklch(0.556 0 0);
80
+ --chart-3: oklch(0.439 0 0);
81
+ --chart-4: oklch(0.371 0 0);
82
+ --chart-5: oklch(0.269 0 0);
83
+ --radius: 0.625rem;
84
+ --sidebar: oklch(0.985 0 0);
85
+ --sidebar-foreground: oklch(0.145 0 0);
86
+ --sidebar-primary: oklch(0.205 0 0);
87
+ --sidebar-primary-foreground: oklch(0.985 0 0);
88
+ --sidebar-accent: oklch(0.97 0 0);
89
+ --sidebar-accent-foreground: oklch(0.205 0 0);
90
+ --sidebar-border: oklch(0.922 0 0);
91
+ --sidebar-ring: oklch(0.708 0 0);
92
+ }
93
+
94
+ .dark {
95
+ --background: oklch(0.145 0 0);
96
+ --foreground: oklch(0.985 0 0);
97
+ --card: oklch(0.205 0 0);
98
+ --card-foreground: oklch(0.985 0 0);
99
+ --popover: oklch(0.205 0 0);
100
+ --popover-foreground: oklch(0.985 0 0);
101
+ --primary: oklch(0.922 0 0);
102
+ --primary-foreground: oklch(0.205 0 0);
103
+ --secondary: oklch(0.269 0 0);
104
+ --secondary-foreground: oklch(0.985 0 0);
105
+ --muted: oklch(0.269 0 0);
106
+ --muted-foreground: oklch(0.708 0 0);
107
+ --accent: oklch(0.269 0 0);
108
+ --accent-foreground: oklch(0.985 0 0);
109
+ --destructive: oklch(0.704 0.191 22.216);
110
+ --border: oklch(1 0 0 / 10%);
111
+ --input: oklch(1 0 0 / 15%);
112
+ --ring: oklch(0.556 0 0);
113
+ --chart-1: oklch(0.87 0 0);
114
+ --chart-2: oklch(0.556 0 0);
115
+ --chart-3: oklch(0.439 0 0);
116
+ --chart-4: oklch(0.371 0 0);
117
+ --chart-5: oklch(0.269 0 0);
118
+ --sidebar: oklch(0.205 0 0);
119
+ --sidebar-foreground: oklch(0.985 0 0);
120
+ --sidebar-primary: oklch(0.488 0.243 264.376);
121
+ --sidebar-primary-foreground: oklch(0.985 0 0);
122
+ --sidebar-accent: oklch(0.269 0 0);
123
+ --sidebar-accent-foreground: oklch(0.985 0 0);
124
+ --sidebar-border: oklch(1 0 0 / 10%);
125
+ --sidebar-ring: oklch(0.556 0 0);
126
+ }
127
+
128
+ /* 草莓抹茶:奶油纸 + 抹茶底 + 草莓主色 */
129
+ [data-theme="strawberry-matcha"] {
130
+ --background: oklch(0.985 0.012 95);
131
+ --foreground: oklch(0.24 0.035 40);
132
+ --card: oklch(0.995 0.008 95);
133
+ --card-foreground: oklch(0.24 0.035 40);
134
+ --popover: oklch(0.995 0.008 95);
135
+ --popover-foreground: oklch(0.24 0.035 40);
136
+ --primary: oklch(0.58 0.175 18);
137
+ --primary-foreground: oklch(0.99 0.01 95);
138
+ --secondary: oklch(0.93 0.045 132);
139
+ --secondary-foreground: oklch(0.32 0.06 142);
140
+ --muted: oklch(0.95 0.028 128);
141
+ --muted-foreground: oklch(0.48 0.03 50);
142
+ --accent: oklch(0.90 0.065 138);
143
+ --accent-foreground: oklch(0.28 0.055 142);
144
+ --destructive: oklch(0.55 0.2 25);
145
+ --border: oklch(0.90 0.03 125);
146
+ --input: oklch(0.90 0.03 125);
147
+ --ring: oklch(0.58 0.14 18);
148
+ --chart-1: oklch(0.62 0.17 18);
149
+ --chart-2: oklch(0.62 0.11 140);
150
+ --chart-3: oklch(0.72 0.08 85);
151
+ --chart-4: oklch(0.45 0.06 40);
152
+ --chart-5: oklch(0.70 0.12 8);
153
+ --radius: 0.75rem;
154
+ --sidebar: oklch(0.96 0.035 132);
155
+ --sidebar-foreground: oklch(0.24 0.035 40);
156
+ --sidebar-primary: oklch(0.58 0.175 18);
157
+ --sidebar-primary-foreground: oklch(0.99 0.01 95);
158
+ --sidebar-accent: oklch(0.91 0.05 138);
159
+ --sidebar-accent-foreground: oklch(0.28 0.055 142);
160
+ --sidebar-border: oklch(0.88 0.035 128);
161
+ --sidebar-ring: oklch(0.58 0.14 18);
162
+ }
163
+
164
+ .dark[data-theme="strawberry-matcha"] {
165
+ --background: oklch(0.18 0.028 148);
166
+ --foreground: oklch(0.96 0.015 95);
167
+ --card: oklch(0.23 0.032 148);
168
+ --card-foreground: oklch(0.96 0.015 95);
169
+ --popover: oklch(0.23 0.032 148);
170
+ --popover-foreground: oklch(0.96 0.015 95);
171
+ --primary: oklch(0.74 0.14 16);
172
+ --primary-foreground: oklch(0.20 0.04 20);
173
+ --secondary: oklch(0.28 0.04 145);
174
+ --secondary-foreground: oklch(0.94 0.02 95);
175
+ --muted: oklch(0.27 0.03 148);
176
+ --muted-foreground: oklch(0.72 0.03 120);
177
+ --accent: oklch(0.32 0.055 142);
178
+ --accent-foreground: oklch(0.95 0.02 95);
179
+ --destructive: oklch(0.68 0.16 20);
180
+ --border: oklch(0.35 0.03 145);
181
+ --input: oklch(0.35 0.03 145);
182
+ --ring: oklch(0.70 0.12 16);
183
+ --chart-1: oklch(0.72 0.14 16);
184
+ --chart-2: oklch(0.70 0.1 140);
185
+ --chart-3: oklch(0.75 0.07 85);
186
+ --chart-4: oklch(0.62 0.05 40);
187
+ --chart-5: oklch(0.68 0.1 8);
188
+ --sidebar: oklch(0.20 0.03 148);
189
+ --sidebar-foreground: oklch(0.96 0.015 95);
190
+ --sidebar-primary: oklch(0.74 0.14 16);
191
+ --sidebar-primary-foreground: oklch(0.20 0.04 20);
192
+ --sidebar-accent: oklch(0.30 0.05 142);
193
+ --sidebar-accent-foreground: oklch(0.95 0.02 95);
194
+ --sidebar-border: oklch(0.35 0.03 145);
195
+ --sidebar-ring: oklch(0.70 0.12 16);
196
+ }
197
+
198
+ /* 苔原:霜白 + 地衣绿 + 泥炭 / 冷石 */
199
+ [data-theme="tundra"] {
200
+ --background: oklch(0.97 0.012 210);
201
+ --foreground: oklch(0.23 0.025 80);
202
+ --card: oklch(0.985 0.008 210);
203
+ --card-foreground: oklch(0.23 0.025 80);
204
+ --popover: oklch(0.985 0.008 210);
205
+ --popover-foreground: oklch(0.23 0.025 80);
206
+ --primary: oklch(0.42 0.065 155);
207
+ --primary-foreground: oklch(0.98 0.01 210);
208
+ --secondary: oklch(0.92 0.018 85);
209
+ --secondary-foreground: oklch(0.28 0.03 80);
210
+ --muted: oklch(0.94 0.012 210);
211
+ --muted-foreground: oklch(0.50 0.02 210);
212
+ --accent: oklch(0.89 0.04 160);
213
+ --accent-foreground: oklch(0.28 0.04 155);
214
+ --destructive: oklch(0.52 0.14 30);
215
+ --border: oklch(0.88 0.018 210);
216
+ --input: oklch(0.88 0.018 210);
217
+ --ring: oklch(0.45 0.06 155);
218
+ --chart-1: oklch(0.50 0.07 155);
219
+ --chart-2: oklch(0.68 0.06 220);
220
+ --chart-3: oklch(0.58 0.07 75);
221
+ --chart-4: oklch(0.62 0.03 80);
222
+ --chart-5: oklch(0.72 0.05 165);
223
+ --radius: 0.5rem;
224
+ --sidebar: oklch(0.95 0.014 210);
225
+ --sidebar-foreground: oklch(0.23 0.025 80);
226
+ --sidebar-primary: oklch(0.42 0.065 155);
227
+ --sidebar-primary-foreground: oklch(0.98 0.01 210);
228
+ --sidebar-accent: oklch(0.90 0.035 160);
229
+ --sidebar-accent-foreground: oklch(0.28 0.04 155);
230
+ --sidebar-border: oklch(0.86 0.018 210);
231
+ --sidebar-ring: oklch(0.45 0.06 155);
232
+ }
233
+
234
+ .dark[data-theme="tundra"] {
235
+ --background: oklch(0.17 0.022 225);
236
+ --foreground: oklch(0.93 0.012 210);
237
+ --card: oklch(0.22 0.025 225);
238
+ --card-foreground: oklch(0.93 0.012 210);
239
+ --popover: oklch(0.22 0.025 225);
240
+ --popover-foreground: oklch(0.93 0.012 210);
241
+ --primary: oklch(0.72 0.075 155);
242
+ --primary-foreground: oklch(0.18 0.03 155);
243
+ --secondary: oklch(0.26 0.02 80);
244
+ --secondary-foreground: oklch(0.93 0.012 210);
245
+ --muted: oklch(0.26 0.02 225);
246
+ --muted-foreground: oklch(0.70 0.02 210);
247
+ --accent: oklch(0.30 0.04 160);
248
+ --accent-foreground: oklch(0.93 0.012 210);
249
+ --destructive: oklch(0.65 0.14 28);
250
+ --border: oklch(0.32 0.02 220);
251
+ --input: oklch(0.32 0.02 220);
252
+ --ring: oklch(0.70 0.06 155);
253
+ --chart-1: oklch(0.68 0.08 155);
254
+ --chart-2: oklch(0.70 0.06 220);
255
+ --chart-3: oklch(0.62 0.07 75);
256
+ --chart-4: oklch(0.58 0.03 80);
257
+ --chart-5: oklch(0.74 0.05 165);
258
+ --sidebar: oklch(0.19 0.022 225);
259
+ --sidebar-foreground: oklch(0.93 0.012 210);
260
+ --sidebar-primary: oklch(0.72 0.075 155);
261
+ --sidebar-primary-foreground: oklch(0.18 0.03 155);
262
+ --sidebar-accent: oklch(0.28 0.035 160);
263
+ --sidebar-accent-foreground: oklch(0.93 0.012 210);
264
+ --sidebar-border: oklch(0.32 0.02 220);
265
+ --sidebar-ring: oklch(0.70 0.06 155);
266
+ }
267
+
268
+ /* 石墨青:石墨灰底 + 青/teal 点缀 */
269
+ [data-theme="graphite-qing"] {
270
+ --background: oklch(0.975 0.006 240);
271
+ --foreground: oklch(0.20 0.018 255);
272
+ --card: oklch(0.99 0.004 240);
273
+ --card-foreground: oklch(0.20 0.018 255);
274
+ --popover: oklch(0.99 0.004 240);
275
+ --popover-foreground: oklch(0.20 0.018 255);
276
+ --primary: oklch(0.40 0.075 205);
277
+ --primary-foreground: oklch(0.98 0.01 205);
278
+ --secondary: oklch(0.93 0.012 255);
279
+ --secondary-foreground: oklch(0.25 0.02 255);
280
+ --muted: oklch(0.94 0.01 250);
281
+ --muted-foreground: oklch(0.50 0.02 250);
282
+ --accent: oklch(0.90 0.04 205);
283
+ --accent-foreground: oklch(0.28 0.04 205);
284
+ --destructive: oklch(0.55 0.18 25);
285
+ --border: oklch(0.88 0.015 250);
286
+ --input: oklch(0.88 0.015 250);
287
+ --ring: oklch(0.45 0.07 205);
288
+ --chart-1: oklch(0.50 0.08 205);
289
+ --chart-2: oklch(0.45 0.02 255);
290
+ --chart-3: oklch(0.58 0.06 230);
291
+ --chart-4: oklch(0.62 0.04 190);
292
+ --chart-5: oklch(0.70 0.03 250);
293
+ --radius: 0.45rem;
294
+ --sidebar: oklch(0.95 0.01 250);
295
+ --sidebar-foreground: oklch(0.20 0.018 255);
296
+ --sidebar-primary: oklch(0.40 0.075 205);
297
+ --sidebar-primary-foreground: oklch(0.98 0.01 205);
298
+ --sidebar-accent: oklch(0.91 0.03 205);
299
+ --sidebar-accent-foreground: oklch(0.28 0.04 205);
300
+ --sidebar-border: oklch(0.86 0.015 250);
301
+ --sidebar-ring: oklch(0.45 0.07 205);
302
+ }
303
+
304
+ .dark[data-theme="graphite-qing"] {
305
+ --background: oklch(0.16 0.018 255);
306
+ --foreground: oklch(0.93 0.01 240);
307
+ --card: oklch(0.21 0.02 255);
308
+ --card-foreground: oklch(0.93 0.01 240);
309
+ --popover: oklch(0.21 0.02 255);
310
+ --popover-foreground: oklch(0.93 0.01 240);
311
+ --primary: oklch(0.76 0.085 198);
312
+ --primary-foreground: oklch(0.16 0.02 255);
313
+ --secondary: oklch(0.26 0.02 255);
314
+ --secondary-foreground: oklch(0.93 0.01 240);
315
+ --muted: oklch(0.26 0.018 255);
316
+ --muted-foreground: oklch(0.70 0.02 250);
317
+ --accent: oklch(0.30 0.04 205);
318
+ --accent-foreground: oklch(0.93 0.01 240);
319
+ --destructive: oklch(0.68 0.16 22);
320
+ --border: oklch(1 0.01 250 / 12%);
321
+ --input: oklch(1 0.01 250 / 16%);
322
+ --ring: oklch(0.70 0.07 198);
323
+ --chart-1: oklch(0.72 0.08 198);
324
+ --chart-2: oklch(0.62 0.02 255);
325
+ --chart-3: oklch(0.65 0.06 230);
326
+ --chart-4: oklch(0.68 0.05 190);
327
+ --chart-5: oklch(0.55 0.02 250);
328
+ --sidebar: oklch(0.18 0.02 255);
329
+ --sidebar-foreground: oklch(0.93 0.01 240);
330
+ --sidebar-primary: oklch(0.76 0.085 198);
331
+ --sidebar-primary-foreground: oklch(0.16 0.02 255);
332
+ --sidebar-accent: oklch(0.28 0.035 205);
333
+ --sidebar-accent-foreground: oklch(0.93 0.01 240);
334
+ --sidebar-border: oklch(1 0.01 250 / 12%);
335
+ --sidebar-ring: oklch(0.70 0.07 198);
336
+ }
337
+
338
+ /* unDraw illustrations (vendor, free/MIT) use --primary-svg-color for their accent.
339
+ Point it at --primary so empty states follow the active palette in light/dark.
340
+ Other unDraw colors are replaced with theme tokens at vendor time (vendor-undraw.mjs). */
341
+ :root {
342
+ --primary-svg-color: var(--primary);
343
+ }
344
+
345
+ @layer base {
346
+ * {
347
+ @apply border-border outline-ring/50;
348
+ }
349
+ body {
350
+ @apply bg-background text-foreground;
351
+ }
352
+ }
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "@monkey-mini-app/ui",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "private": false,
6
+ "scripts": {
7
+ "lint": "eslint",
8
+ "typecheck": "tsc --noEmit",
9
+ "test": "vitest run",
10
+ "test:watch": "vitest",
11
+ "skill:gen": "node ../../scripts/generate-skill.mjs",
12
+ "build:dist": "node ../../scripts/build-ui.mjs",
13
+ "build": "node ../../scripts/build-ui.mjs",
14
+ "prepack": "node ../../scripts/build-ui.mjs"
15
+ },
16
+ "dependencies": {
17
+ "@base-ui/react": "^1.7.0",
18
+ "@codemirror/autocomplete": "^6.20.3",
19
+ "@codemirror/lang-html": "^6.4.12",
20
+ "@codemirror/lang-javascript": "^6.2.5",
21
+ "@codemirror/lang-json": "^6.0.2",
22
+ "@codemirror/lang-markdown": "^6.5.2",
23
+ "@codemirror/language": "^6.12.4",
24
+ "@codemirror/theme-one-dark": "^6.1.3",
25
+ "@dnd-kit/core": "^6.3.1",
26
+ "@dnd-kit/sortable": "^10.0.0",
27
+ "@dnd-kit/utilities": "^3.2.2",
28
+ "@fontsource-variable/geist": "^5.3.0",
29
+ "@shadcn/react": "^0.3.0",
30
+ "@tanstack/react-table": "^8.21.3",
31
+ "@tanstack/react-virtual": "^3.13.12",
32
+ "@tiptap/extension-placeholder": "^3.30.3",
33
+ "@tiptap/pm": "^3.30.3",
34
+ "@tiptap/react": "^3.30.3",
35
+ "@tiptap/starter-kit": "^3.30.3",
36
+ "@uiw/react-codemirror": "^4.25.11",
37
+ "class-variance-authority": "^0.7.1",
38
+ "clsx": "^2.1.1",
39
+ "cmdk": "^1.1.1",
40
+ "date-fns": "^4.1.0",
41
+ "diff": "^9.0.0",
42
+ "lucide-react": "^0.544.0",
43
+ "react": "^19.2.6",
44
+ "react-day-picker": "^10.0.1",
45
+ "react-dom": "^19.2.6",
46
+ "react-dropzone": "^20.1.1",
47
+ "react-markdown": "^10.1.0",
48
+ "react-resizable-panels": "^4.12.3",
49
+ "recharts": "^3.8.0",
50
+ "remark-gfm": "^4.0.1",
51
+ "shadcn": "^4.19.0",
52
+ "shiki": "^4.4.3",
53
+ "tailwind-merge": "^3.6.0",
54
+ "tw-animate-css": "^1.4.0",
55
+ "zod": "^4.4.3"
56
+ },
57
+ "peerDependencies": {
58
+ "react": "^19",
59
+ "react-dom": "^19"
60
+ },
61
+ "devDependencies": {
62
+ "@eslint/js": "^9",
63
+ "@testing-library/jest-dom": "^6.8.0",
64
+ "@testing-library/react": "^16.3.0",
65
+ "@testing-library/user-event": "^14.6.1",
66
+ "@types/diff": "^8.0.0",
67
+ "@types/node": "^24",
68
+ "@types/react": "^19",
69
+ "@types/react-dom": "^19",
70
+ "@vitest/coverage-v8": "^3.2.4",
71
+ "eslint": "^9",
72
+ "jsdom": "^26.1.0",
73
+ "tailwindcss": "^4",
74
+ "typescript": "~5.9.2",
75
+ "vite": "^7",
76
+ "vitest": "^3.2.4"
77
+ },
78
+ "exports": {
79
+ ".": {
80
+ "types": "./dist/src/index.ts",
81
+ "default": "./dist/index.js"
82
+ },
83
+ "./globals.css": "./dist/globals.css",
84
+ "./*": {
85
+ "types": "./dist/src/*",
86
+ "default": "./dist/src/*"
87
+ },
88
+ "./package.json": "./package.json"
89
+ },
90
+ "sideEffects": [
91
+ "**/*.css",
92
+ "**/*.css.js",
93
+ "**/*.woff",
94
+ "**/*.woff2"
95
+ ],
96
+ "files": [
97
+ "dist",
98
+ "components.json"
99
+ ]
100
+ }