@suphark/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 (147) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +21 -0
  3. package/README.md +120 -0
  4. package/components.json +21 -0
  5. package/package.json +108 -0
  6. package/scripts/audit-base-ui-props.mjs +179 -0
  7. package/scripts/audit-tailwind-typography.mjs +100 -0
  8. package/src/components/design-system/design-system-showcase.tsx +138 -0
  9. package/src/components/design-system/sections/showcase-data-display.tsx +454 -0
  10. package/src/components/design-system/sections/showcase-feedback.tsx +273 -0
  11. package/src/components/design-system/sections/showcase-forms.tsx +373 -0
  12. package/src/components/design-system/sections/showcase-foundations.tsx +384 -0
  13. package/src/components/design-system/sections/showcase-guidelines-recipes.tsx +397 -0
  14. package/src/components/design-system/sections/showcase-overlays-navigation.tsx +479 -0
  15. package/src/components/design-system/sections/showcase-overview.tsx +368 -0
  16. package/src/components/design-system/sections/showcase-primitives.tsx +463 -0
  17. package/src/components/shared/__tests__/multi-select-combobox.test.tsx +180 -0
  18. package/src/components/shared/__tests__/name-id-fields.test.ts +24 -0
  19. package/src/components/shared/button/add-new-button.tsx +19 -0
  20. package/src/components/shared/button/base/action-button.tsx +134 -0
  21. package/src/components/shared/button/base/link-button.tsx +130 -0
  22. package/src/components/shared/button/cancel-button.tsx +27 -0
  23. package/src/components/shared/button/confirm-button.tsx +26 -0
  24. package/src/components/shared/button/delete-button.tsx +36 -0
  25. package/src/components/shared/button/floating-save-button.tsx +89 -0
  26. package/src/components/shared/button/index.ts +13 -0
  27. package/src/components/shared/button/print-button.tsx +67 -0
  28. package/src/components/shared/button/refresh-button.tsx +63 -0
  29. package/src/components/shared/button/save-button.tsx +29 -0
  30. package/src/components/shared/button/submit-button.tsx +58 -0
  31. package/src/components/shared/client-redirect.tsx +11 -0
  32. package/src/components/shared/combobox.tsx +116 -0
  33. package/src/components/shared/data-list.tsx +65 -0
  34. package/src/components/shared/date/date-range-picker.tsx +106 -0
  35. package/src/components/shared/description-list.tsx +27 -0
  36. package/src/components/shared/empty-row.tsx +13 -0
  37. package/src/components/shared/empty-state.tsx +31 -0
  38. package/src/components/shared/env-snippet.tsx +62 -0
  39. package/src/components/shared/form/__tests__/simple-select.test.tsx +72 -0
  40. package/src/components/shared/form/form-field-boolean.tsx +93 -0
  41. package/src/components/shared/form/form-field-color-select.tsx +86 -0
  42. package/src/components/shared/form/form-field-combobox.tsx +167 -0
  43. package/src/components/shared/form/form-field-date.tsx +55 -0
  44. package/src/components/shared/form/form-field-formatted-number.tsx +103 -0
  45. package/src/components/shared/form/form-field-input.tsx +372 -0
  46. package/src/components/shared/form/form-field-radio-cards.tsx +127 -0
  47. package/src/components/shared/form/form-field-radio-group.tsx +56 -0
  48. package/src/components/shared/form/form-field-select.tsx +312 -0
  49. package/src/components/shared/form/simple-select.tsx +152 -0
  50. package/src/components/shared/form-dialog.tsx +109 -0
  51. package/src/components/shared/form-message.tsx +30 -0
  52. package/src/components/shared/initials.tsx +33 -0
  53. package/src/components/shared/layout/error-state.tsx +160 -0
  54. package/src/components/shared/layout/page-shell.tsx +57 -0
  55. package/src/components/shared/link/transition-link.tsx +72 -0
  56. package/src/components/shared/multi-select-combobox.tsx +392 -0
  57. package/src/components/shared/name-id-fields.tsx +133 -0
  58. package/src/components/shared/navigation/page-breadcrumb.tsx +100 -0
  59. package/src/components/shared/notice.tsx +35 -0
  60. package/src/components/shared/number/formatted-number.tsx +133 -0
  61. package/src/components/shared/page-header.tsx +25 -0
  62. package/src/components/shared/page-skeleton.tsx +18 -0
  63. package/src/components/shared/row-actions.tsx +93 -0
  64. package/src/components/shared/row-menu.tsx +55 -0
  65. package/src/components/shared/secret-reveal.tsx +53 -0
  66. package/src/components/shared/section-card.tsx +44 -0
  67. package/src/components/shared/stat.tsx +26 -0
  68. package/src/components/shared/status-badge.tsx +47 -0
  69. package/src/components/shared/text/primary-secondary-text.tsx +186 -0
  70. package/src/components/shared/theme/index.ts +4 -0
  71. package/src/components/shared/theme/theme-menu-items.tsx +43 -0
  72. package/src/components/shared/theme/theme-provider.tsx +39 -0
  73. package/src/components/shared/theme/theme-switch.tsx +36 -0
  74. package/src/components/shared/theme/theme-toggle.tsx +76 -0
  75. package/src/components/shared/time/client-date-formatter.tsx +188 -0
  76. package/src/components/shared/ui-text.tsx +47 -0
  77. package/src/components/ui/__tests__/combobox.test.tsx +40 -0
  78. package/src/components/ui/__tests__/date-picker.test.tsx +53 -0
  79. package/src/components/ui/__tests__/slider.test.tsx +18 -0
  80. package/src/components/ui/__tests__/tabs.test.tsx +33 -0
  81. package/src/components/ui/accordion.tsx +69 -0
  82. package/src/components/ui/alert-dialog.tsx +161 -0
  83. package/src/components/ui/alert.tsx +68 -0
  84. package/src/components/ui/aspect-ratio.tsx +22 -0
  85. package/src/components/ui/attachment.tsx +194 -0
  86. package/src/components/ui/avatar.tsx +92 -0
  87. package/src/components/ui/badge.tsx +48 -0
  88. package/src/components/ui/breadcrumb.tsx +102 -0
  89. package/src/components/ui/button-group.tsx +77 -0
  90. package/src/components/ui/button.tsx +57 -0
  91. package/src/components/ui/calendar.tsx +184 -0
  92. package/src/components/ui/card.tsx +87 -0
  93. package/src/components/ui/carousel.tsx +230 -0
  94. package/src/components/ui/chart.tsx +338 -0
  95. package/src/components/ui/checkbox.tsx +27 -0
  96. package/src/components/ui/collapsible.tsx +17 -0
  97. package/src/components/ui/combobox.tsx +272 -0
  98. package/src/components/ui/command.tsx +180 -0
  99. package/src/components/ui/context-menu.tsx +244 -0
  100. package/src/components/ui/date-picker.tsx +308 -0
  101. package/src/components/ui/dialog.tsx +137 -0
  102. package/src/components/ui/drawer.tsx +208 -0
  103. package/src/components/ui/dropdown-menu.tsx +257 -0
  104. package/src/components/ui/empty.tsx +93 -0
  105. package/src/components/ui/field.tsx +223 -0
  106. package/src/components/ui/form.tsx +161 -0
  107. package/src/components/ui/hover-card.tsx +46 -0
  108. package/src/components/ui/input-group.tsx +145 -0
  109. package/src/components/ui/input-otp.tsx +85 -0
  110. package/src/components/ui/input.tsx +19 -0
  111. package/src/components/ui/item.tsx +187 -0
  112. package/src/components/ui/kbd.tsx +26 -0
  113. package/src/components/ui/label.tsx +19 -0
  114. package/src/components/ui/menubar.tsx +266 -0
  115. package/src/components/ui/navigation-menu.tsx +160 -0
  116. package/src/components/ui/pagination.tsx +117 -0
  117. package/src/components/ui/popover.tsx +76 -0
  118. package/src/components/ui/progress.tsx +66 -0
  119. package/src/components/ui/radio-group.tsx +38 -0
  120. package/src/components/ui/relative-date.tsx +40 -0
  121. package/src/components/ui/resizable.tsx +41 -0
  122. package/src/components/ui/scroll-area.tsx +67 -0
  123. package/src/components/ui/searchable-select.tsx +124 -0
  124. package/src/components/ui/select.tsx +189 -0
  125. package/src/components/ui/separator.tsx +21 -0
  126. package/src/components/ui/sheet.tsx +124 -0
  127. package/src/components/ui/sidebar.tsx +691 -0
  128. package/src/components/ui/skeleton.tsx +13 -0
  129. package/src/components/ui/slider.tsx +55 -0
  130. package/src/components/ui/sonner.tsx +45 -0
  131. package/src/components/ui/spinner.tsx +16 -0
  132. package/src/components/ui/switch.tsx +32 -0
  133. package/src/components/ui/table.tsx +95 -0
  134. package/src/components/ui/tabs.tsx +79 -0
  135. package/src/components/ui/textarea.tsx +17 -0
  136. package/src/components/ui/toggle-group.tsx +86 -0
  137. package/src/components/ui/toggle.tsx +44 -0
  138. package/src/components/ui/tooltip.tsx +54 -0
  139. package/src/hooks/use-copy-to-clipboard.ts +27 -0
  140. package/src/hooks/use-mobile.ts +21 -0
  141. package/src/index.ts +156 -0
  142. package/src/lib/formatters.ts +44 -0
  143. package/src/lib/permission.ts +75 -0
  144. package/src/lib/status-colors.ts +52 -0
  145. package/src/lib/utils.ts +6 -0
  146. package/src/next.ts +15 -0
  147. package/src/styles.css +214 -0
@@ -0,0 +1,479 @@
1
+ "use client";
2
+
3
+ import {
4
+ AlertDialog,
5
+ AlertDialogAction,
6
+ AlertDialogCancel,
7
+ AlertDialogContent,
8
+ AlertDialogDescription,
9
+ AlertDialogFooter,
10
+ AlertDialogHeader,
11
+ AlertDialogTitle,
12
+ AlertDialogTrigger,
13
+ } from "@suphark/ui/components/ui/alert-dialog";
14
+ import { Badge } from "@suphark/ui/components/ui/badge";
15
+ import {
16
+ Breadcrumb,
17
+ BreadcrumbItem,
18
+ BreadcrumbLink,
19
+ BreadcrumbList,
20
+ BreadcrumbPage,
21
+ BreadcrumbSeparator,
22
+ } from "@suphark/ui/components/ui/breadcrumb";
23
+ import { Button } from "@suphark/ui/components/ui/button";
24
+ import {
25
+ Card,
26
+ CardContent,
27
+ CardDescription,
28
+ CardHeader,
29
+ CardTitle,
30
+ } from "@suphark/ui/components/ui/card";
31
+ import {
32
+ ContextMenu,
33
+ ContextMenuContent,
34
+ ContextMenuItem,
35
+ ContextMenuSeparator,
36
+ ContextMenuTrigger,
37
+ } from "@suphark/ui/components/ui/context-menu";
38
+ import {
39
+ Dialog,
40
+ DialogContent,
41
+ DialogDescription,
42
+ DialogFooter,
43
+ DialogHeader,
44
+ DialogTitle,
45
+ DialogTrigger,
46
+ } from "@suphark/ui/components/ui/dialog";
47
+ import {
48
+ Drawer,
49
+ DrawerClose,
50
+ DrawerContent,
51
+ DrawerDescription,
52
+ DrawerFooter,
53
+ DrawerHeader,
54
+ DrawerTitle,
55
+ DrawerTrigger,
56
+ } from "@suphark/ui/components/ui/drawer";
57
+ import { Field, FieldGroup, FieldLabel } from "@suphark/ui/components/ui/field";
58
+ import {
59
+ HoverCard,
60
+ HoverCardContent,
61
+ HoverCardTrigger,
62
+ } from "@suphark/ui/components/ui/hover-card";
63
+ import { Input } from "@suphark/ui/components/ui/input";
64
+ import {
65
+ Menubar,
66
+ MenubarContent,
67
+ MenubarItem,
68
+ MenubarMenu,
69
+ MenubarSeparator,
70
+ MenubarShortcut,
71
+ MenubarTrigger,
72
+ } from "@suphark/ui/components/ui/menubar";
73
+ import {
74
+ Pagination,
75
+ PaginationContent,
76
+ PaginationEllipsis,
77
+ PaginationItem,
78
+ PaginationLink,
79
+ PaginationNext,
80
+ PaginationPrevious,
81
+ } from "@suphark/ui/components/ui/pagination";
82
+ import { Popover, PopoverContent, PopoverTrigger } from "@suphark/ui/components/ui/popover";
83
+ import {
84
+ ResizableHandle,
85
+ ResizablePanel,
86
+ ResizablePanelGroup,
87
+ } from "@suphark/ui/components/ui/resizable";
88
+ import { Separator } from "@suphark/ui/components/ui/separator";
89
+ import {
90
+ Sheet,
91
+ SheetContent,
92
+ SheetDescription,
93
+ SheetFooter,
94
+ SheetHeader,
95
+ SheetTitle,
96
+ SheetTrigger,
97
+ } from "@suphark/ui/components/ui/sheet";
98
+ import { Textarea } from "@suphark/ui/components/ui/textarea";
99
+ import {
100
+ Tooltip,
101
+ TooltipContent,
102
+ TooltipProvider,
103
+ TooltipTrigger,
104
+ } from "@suphark/ui/components/ui/tooltip";
105
+ import {
106
+ Building,
107
+ Compass,
108
+ FileCheck,
109
+ Filter,
110
+ HelpCircle,
111
+ Layers,
112
+ Share2,
113
+ ShieldAlert,
114
+ Trash2,
115
+ } from "lucide-react";
116
+
117
+ export function ShowcaseOverlaysNavigation() {
118
+ return (
119
+ <TooltipProvider>
120
+ <div className="flex flex-col gap-8">
121
+ {/* Section Header */}
122
+ <div className="flex flex-col gap-1">
123
+ <div className="flex items-center gap-2">
124
+ <Badge variant="outline">Overlays & Navigation</Badge>
125
+ <span className="text-xs text-muted-foreground">
126
+ Dialogs, Sheets, Drawers, Menus, Breadcrumbs, Tabs & Resizable Panels
127
+ </span>
128
+ </div>
129
+ <h2 className="text-xl font-bold tracking-tight text-foreground">
130
+ หน้าต่างซ้อนและการนำทาง (Overlays & Navigation)
131
+ </h2>
132
+ <p className="text-sm text-muted-foreground">
133
+ Modal Dialogs ที่รองรับ Screen Reader อย่างสมบูรณ์, การจัดการ Destructive Confirmation,
134
+ และระบบนำทางหลายระดับ
135
+ </p>
136
+ </div>
137
+
138
+ {/* Modal Overlays & Drawers */}
139
+ <div className="grid gap-6 lg:grid-cols-2">
140
+ {/* Dialog & AlertDialog */}
141
+ <Card>
142
+ <CardHeader>
143
+ <CardTitle className="text-base flex items-center gap-2">
144
+ <ShieldAlert className="size-4 text-primary" /> Dialogs & Consequence Confirmations
145
+ </CardTitle>
146
+ <CardDescription className="text-xs">
147
+ ใช้ <code>Dialog</code> สำหรับแบบฟอร์มแก้ไข และใช้ <code>AlertDialog</code>{" "}
148
+ สำหรับการยืนยันการลบ
149
+ </CardDescription>
150
+ </CardHeader>
151
+ <CardContent className="flex flex-wrap items-center gap-3">
152
+ {/* Standard Form Dialog */}
153
+ <Dialog>
154
+ <DialogTrigger render={<Button variant="default" />}>เปิด Form Dialog</DialogTrigger>
155
+ <DialogContent className="sm:max-w-md">
156
+ <DialogHeader>
157
+ <DialogTitle>แก้ไขข้อมูลแพ็กเกจจัดซื้อ</DialogTitle>
158
+ <DialogDescription>ระบุข้อมูลเพื่อส่งต่อให้คณะกรรมการจัดซื้อพิจารณาอนุมัติ</DialogDescription>
159
+ </DialogHeader>
160
+ <FieldGroup className="py-2">
161
+ <Field>
162
+ <FieldLabel htmlFor="dlg-pkg-name">ชื่อแพ็กเกจ</FieldLabel>
163
+ <Input id="dlg-pkg-name" defaultValue="งานจัดซื้อโครงสร้างเหล็กอาคาร 1" />
164
+ </Field>
165
+ <Field>
166
+ <FieldLabel htmlFor="dlg-memo">บันทึกเหตุผลความจำเป็น</FieldLabel>
167
+ <Textarea
168
+ id="dlg-memo"
169
+ rows={2}
170
+ defaultValue="จำเป็นต้องเร่งเปิดซองราคาเนื่องจากราคาเหล็กเส้นมีแนวโน้มปรับตัวขึ้น"
171
+ />
172
+ </Field>
173
+ </FieldGroup>
174
+ <DialogFooter showCloseButton>
175
+ <Button type="submit">บันทึกการเปลี่ยนแปลง</Button>
176
+ </DialogFooter>
177
+ </DialogContent>
178
+ </Dialog>
179
+
180
+ {/* Destructive AlertDialog */}
181
+ <AlertDialog>
182
+ <AlertDialogTrigger render={<Button variant="destructive" />}>
183
+ เปิด Destructive AlertDialog
184
+ </AlertDialogTrigger>
185
+ <AlertDialogContent>
186
+ <AlertDialogHeader>
187
+ <AlertDialogTitle>ยืนยันการยกเลิกแพ็กเกจจัดซื้อนี้?</AlertDialogTitle>
188
+ <AlertDialogDescription>
189
+ การกระทำนี้ไม่สามารถย้อนกลับได้ เอกสารเสนอราคา ใบเปรียบเทียบราคา
190
+ และประวัติการตรวจสอบทั้งหมดจะถูกเก็บถาวรและไม่สามารถเสนอราคาซ้ำได้
191
+ </AlertDialogDescription>
192
+ </AlertDialogHeader>
193
+ <AlertDialogFooter>
194
+ <AlertDialogCancel>ยกเลิก</AlertDialogCancel>
195
+ <AlertDialogAction variant="destructive">ยืนยันการยกเลิกแพ็กเกจ</AlertDialogAction>
196
+ </AlertDialogFooter>
197
+ </AlertDialogContent>
198
+ </AlertDialog>
199
+ </CardContent>
200
+ </Card>
201
+
202
+ {/* Sheet & Drawer */}
203
+ <Card>
204
+ <CardHeader>
205
+ <CardTitle className="text-base flex items-center gap-2">
206
+ <Layers className="size-4 text-primary" /> Side Sheets & Bottom Drawers
207
+ </CardTitle>
208
+ <CardDescription className="text-xs">
209
+ ใช้ <code>Sheet</code> สำหรับแผงฟิลเตอร์ด้านข้าง และ <code>Drawer</code> สำหรับมุมมองมือถือ
210
+ </CardDescription>
211
+ </CardHeader>
212
+ <CardContent className="flex flex-wrap items-center gap-3">
213
+ {/* Side Sheet */}
214
+ <Sheet>
215
+ <SheetTrigger render={<Button variant="outline" className="gap-2" />}>
216
+ <Filter className="size-4" />
217
+ เปิด Filter Sheet
218
+ </SheetTrigger>
219
+ <SheetContent side="right" className="w-full sm:max-w-sm">
220
+ <SheetHeader>
221
+ <SheetTitle>ตัวกรองข้อมูลจัดซื้อ (Filters)</SheetTitle>
222
+ <SheetDescription>กรองตามสถานะ, วงเงินงบประมาณ และรายชื่อผู้รับเหมา</SheetDescription>
223
+ </SheetHeader>
224
+ <div className="flex flex-col gap-4 py-4">
225
+ <Field>
226
+ <FieldLabel>สถานะแพ็กเกจ</FieldLabel>
227
+ <Input placeholder="เช่น Approved, Review..." />
228
+ </Field>
229
+ <Field>
230
+ <FieldLabel>วงเงินต่ำสุด - สูงสุด</FieldLabel>
231
+ <Input placeholder="1,000,000 - 10,000,000" />
232
+ </Field>
233
+ </div>
234
+ <SheetFooter>
235
+ <Button className="w-full">นำตัวกรองไปใช้</Button>
236
+ </SheetFooter>
237
+ </SheetContent>
238
+ </Sheet>
239
+
240
+ {/* Bottom Drawer */}
241
+ <Drawer>
242
+ <DrawerTrigger render={<Button variant="outline" className="gap-2" />}>
243
+ <Compass className="size-4" />
244
+ เปิด Bottom Drawer
245
+ </DrawerTrigger>
246
+ <DrawerContent>
247
+ <div className="mx-auto w-full max-w-sm">
248
+ <DrawerHeader>
249
+ <DrawerTitle>สรุปรายละเอียดผู้รับเหมา</DrawerTitle>
250
+ <DrawerDescription>คะแนนประเมินผลงานย้อนหลัง 12 เดือนล่าสุด</DrawerDescription>
251
+ </DrawerHeader>
252
+ <div className="p-4 flex flex-col gap-2 text-xs">
253
+ <div className="flex justify-between border-b pb-2">
254
+ <span>ส่งมอบตรงเวลา (On-Time Delivery)</span>
255
+ <span className="font-semibold text-emerald-600">96.5%</span>
256
+ </div>
257
+ <div className="flex justify-between border-b pb-2">
258
+ <span>มาตรฐานคุณภาพวัสดุ (Quality Pass Rate)</span>
259
+ <span className="font-semibold text-emerald-600">98.2%</span>
260
+ </div>
261
+ </div>
262
+ <DrawerFooter>
263
+ <DrawerClose render={<Button variant="outline" />}>ปิดหน้าต่าง</DrawerClose>
264
+ </DrawerFooter>
265
+ </div>
266
+ </DrawerContent>
267
+ </Drawer>
268
+ </CardContent>
269
+ </Card>
270
+ </div>
271
+
272
+ {/* Popovers, Tooltips & Context Menus */}
273
+ <div className="grid gap-6 lg:grid-cols-2">
274
+ {/* Popover & Tooltip */}
275
+ <Card>
276
+ <CardHeader className="pb-3">
277
+ <CardTitle className="text-base">Tooltips, HoverCard & Popovers</CardTitle>
278
+ <CardDescription className="text-xs">คำอธิบายเพิ่มเติมและเนื้อหาแบบบริบท</CardDescription>
279
+ </CardHeader>
280
+ <CardContent className="flex flex-wrap items-center gap-4">
281
+ {/* Tooltip */}
282
+ <Tooltip>
283
+ <TooltipTrigger render={<Button variant="outline" size="sm" className="gap-1.5" />}>
284
+ <HelpCircle className="size-3.5" />
285
+ ชี้เพื่อดู Tooltip
286
+ </TooltipTrigger>
287
+ <TooltipContent>
288
+ <p className="text-xs">สูตรคำนวณราคากลาง = Median(Q1..Q3) หลังตัดค่า Outlier</p>
289
+ </TooltipContent>
290
+ </Tooltip>
291
+
292
+ {/* HoverCard */}
293
+ <HoverCard>
294
+ <HoverCardTrigger
295
+ render={<Button variant="ghost" size="sm" className="gap-1.5 underline" />}
296
+ >
297
+ <Building className="size-3.5" />
298
+ Hover เพื่อดูข้อมูลคู่ค้า
299
+ </HoverCardTrigger>
300
+ <HoverCardContent className="w-80">
301
+ <div className="flex justify-between space-x-4">
302
+ <div className="space-y-1">
303
+ <h4 className="text-xs font-semibold">Alpha Cement Co., Ltd.</h4>
304
+ <p className="text-xs text-muted-foreground">
305
+ ผู้ผลิตและจัดจำหน่ายปูนซีเมนต์และวัสดุก่อสร้างชั้นนำในประเทศไทย
306
+ </p>
307
+ <div className="flex items-center pt-2">
308
+ <Badge variant="outline" className="text-xs">
309
+ Tier-1 Vendor
310
+ </Badge>
311
+ </div>
312
+ </div>
313
+ </div>
314
+ </HoverCardContent>
315
+ </HoverCard>
316
+
317
+ {/* Popover */}
318
+ <Popover>
319
+ <PopoverTrigger render={<Button variant="outline" size="sm" />}>
320
+ เปิด Popover
321
+ </PopoverTrigger>
322
+ <PopoverContent className="w-64">
323
+ <div className="flex flex-col gap-2">
324
+ <h4 className="font-medium text-xs">ตัวช่วยการประเมินราคา</h4>
325
+ <p className="text-xs text-muted-foreground">
326
+ สามารถส่งออกตารางเปรียบเทียบในรูปแบบ Excel หรือ PDF เพื่อเข้าที่ประชุม
327
+ </p>
328
+ </div>
329
+ </PopoverContent>
330
+ </Popover>
331
+ </CardContent>
332
+ </Card>
333
+
334
+ {/* Menubar & ContextMenu */}
335
+ <Card>
336
+ <CardHeader className="pb-3">
337
+ <CardTitle className="text-base">Menubar & Context Menu</CardTitle>
338
+ <CardDescription className="text-xs">
339
+ เมนูบาร์สำหรับระบบบริหารจัดการ และคลิกขวาในพื้นที่ตาราง
340
+ </CardDescription>
341
+ </CardHeader>
342
+ <CardContent className="flex flex-col gap-4">
343
+ {/* Menubar */}
344
+ <Menubar className="w-fit">
345
+ <MenubarMenu>
346
+ <MenubarTrigger className="text-xs">แฟ้มข้อมูล (File)</MenubarTrigger>
347
+ <MenubarContent>
348
+ <MenubarItem className="text-xs">
349
+ สร้างแพ็กเกจใหม่ <MenubarShortcut>⌘N</MenubarShortcut>
350
+ </MenubarItem>
351
+ <MenubarItem className="text-xs">
352
+ ส่งออกรายงาน BOQ <MenubarShortcut>⌘E</MenubarShortcut>
353
+ </MenubarItem>
354
+ <MenubarSeparator />
355
+ <MenubarItem className="text-xs">
356
+ พิมพ์ตารางเปรียบเทียบ <MenubarShortcut>⌘P</MenubarShortcut>
357
+ </MenubarItem>
358
+ </MenubarContent>
359
+ </MenubarMenu>
360
+ <MenubarMenu>
361
+ <MenubarTrigger className="text-xs">ตัวกรอง (View)</MenubarTrigger>
362
+ <MenubarContent>
363
+ <MenubarItem className="text-xs">แสดงเฉพาะรายการที่ยังไม่อนุมัติ</MenubarItem>
364
+ <MenubarItem className="text-xs">ซ่อนรายการที่ถูกปฏิเสธ</MenubarItem>
365
+ </MenubarContent>
366
+ </MenubarMenu>
367
+ </Menubar>
368
+
369
+ {/* ContextMenu Area */}
370
+ <ContextMenu>
371
+ <ContextMenuTrigger className="flex h-20 w-full items-center justify-center rounded-md border border-dashed text-xs text-muted-foreground bg-muted/20">
372
+ คลิกขวาในกรอบนี้เพื่อทดสอบ Context Menu
373
+ </ContextMenuTrigger>
374
+ <ContextMenuContent className="w-48">
375
+ <ContextMenuItem className="text-xs gap-2">
376
+ <FileCheck className="size-3.5" /> ตรวจสอบเอกสาร
377
+ </ContextMenuItem>
378
+ <ContextMenuItem className="text-xs gap-2">
379
+ <Share2 className="size-3.5" /> ส่งต่อผู้ตรวจสอบ
380
+ </ContextMenuItem>
381
+ <ContextMenuSeparator />
382
+ <ContextMenuItem className="text-xs gap-2 text-destructive">
383
+ <Trash2 className="size-3.5" /> ลบรายการ
384
+ </ContextMenuItem>
385
+ </ContextMenuContent>
386
+ </ContextMenu>
387
+ </CardContent>
388
+ </Card>
389
+ </div>
390
+
391
+ {/* Navigation & Resizable Layout */}
392
+ <div className="grid gap-6 lg:grid-cols-2">
393
+ {/* Breadcrumb & Pagination */}
394
+ <Card>
395
+ <CardHeader className="pb-3">
396
+ <CardTitle className="text-base">Breadcrumbs & Pagination</CardTitle>
397
+ <CardDescription className="text-xs">
398
+ ลำดับชั้นของหน้าและตัวแบ่งหน้าสำหรับตารางข้อมูล
399
+ </CardDescription>
400
+ </CardHeader>
401
+ <CardContent className="flex flex-col gap-6">
402
+ {/* Breadcrumb */}
403
+ <Breadcrumb>
404
+ <BreadcrumbList>
405
+ <BreadcrumbItem>
406
+ <BreadcrumbLink href="#">ระบบจัดซื้อ (Procurement)</BreadcrumbLink>
407
+ </BreadcrumbItem>
408
+ <BreadcrumbSeparator />
409
+ <BreadcrumbItem>
410
+ <BreadcrumbLink href="#">โครงการอาคารศูนย์การแพทย์</BreadcrumbLink>
411
+ </BreadcrumbItem>
412
+ <BreadcrumbSeparator />
413
+ <BreadcrumbItem>
414
+ <BreadcrumbPage>แพ็กเกจงานโครงสร้างและสถาปัตย์</BreadcrumbPage>
415
+ </BreadcrumbItem>
416
+ </BreadcrumbList>
417
+ </Breadcrumb>
418
+
419
+ <Separator />
420
+
421
+ {/* Pagination */}
422
+ <Pagination className="mx-0 justify-start">
423
+ <PaginationContent>
424
+ <PaginationItem>
425
+ <PaginationPrevious href="#" />
426
+ </PaginationItem>
427
+ <PaginationItem>
428
+ <PaginationLink href="#" isActive>
429
+ 1
430
+ </PaginationLink>
431
+ </PaginationItem>
432
+ <PaginationItem>
433
+ <PaginationLink href="#">2</PaginationLink>
434
+ </PaginationItem>
435
+ <PaginationItem>
436
+ <PaginationLink href="#">3</PaginationLink>
437
+ </PaginationItem>
438
+ <PaginationItem>
439
+ <PaginationEllipsis />
440
+ </PaginationItem>
441
+ <PaginationItem>
442
+ <PaginationNext href="#" />
443
+ </PaginationItem>
444
+ </PaginationContent>
445
+ </Pagination>
446
+ </CardContent>
447
+ </Card>
448
+
449
+ {/* Resizable Panels */}
450
+ <Card>
451
+ <CardHeader className="pb-3">
452
+ <CardTitle className="text-base">Resizable Layout Panels</CardTitle>
453
+ <CardDescription className="text-xs">
454
+ แบ่งพื้นที่หน้าจอระหว่างตารางรายการและรายละเอียดแบบลากปรับขนาดได้
455
+ </CardDescription>
456
+ </CardHeader>
457
+ <CardContent>
458
+ <div className="h-36 rounded-md border overflow-hidden">
459
+ <ResizablePanelGroup>
460
+ <ResizablePanel defaultSize={40} minSize={25}>
461
+ <div className="flex h-full items-center justify-center p-3 text-xs font-medium bg-muted/30">
462
+ รายชื่อแพ็กเกจ (40%)
463
+ </div>
464
+ </ResizablePanel>
465
+ <ResizableHandle withHandle />
466
+ <ResizablePanel defaultSize={60} minSize={30}>
467
+ <div className="flex h-full items-center justify-center p-3 text-xs font-medium bg-card">
468
+ รายละเอียด BOQ & เอกสารแนบ (60%)
469
+ </div>
470
+ </ResizablePanel>
471
+ </ResizablePanelGroup>
472
+ </div>
473
+ </CardContent>
474
+ </Card>
475
+ </div>
476
+ </div>
477
+ </TooltipProvider>
478
+ );
479
+ }