@thangnqdev/ui 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +144 -142
  3. package/bin/cli.js +125 -125
  4. package/dist/bento/index.cjs.map +1 -1
  5. package/dist/bento/index.js +2 -2
  6. package/dist/buttons/index.cjs.map +1 -1
  7. package/dist/buttons/index.js +3 -3
  8. package/dist/{chunk-EXFR2BFJ.js → chunk-2ANJFOIU.js} +38 -36
  9. package/dist/chunk-2ANJFOIU.js.map +1 -0
  10. package/dist/{chunk-77KTYOMQ.js → chunk-2OXZK6IP.js} +3 -3
  11. package/dist/chunk-2OXZK6IP.js.map +1 -0
  12. package/dist/{chunk-4CRFNALF.js → chunk-4GNFT2ZJ.js} +7 -7
  13. package/dist/chunk-4GNFT2ZJ.js.map +1 -0
  14. package/dist/{chunk-2YJBW4E2.js → chunk-4S6L5V7X.js} +2 -2
  15. package/dist/chunk-4S6L5V7X.js.map +1 -0
  16. package/dist/{chunk-I2FQBMVW.js → chunk-66VWUJEI.js} +3 -3
  17. package/dist/chunk-66VWUJEI.js.map +1 -0
  18. package/dist/{chunk-YOCGBORV.js → chunk-7NMB2Y64.js} +4 -4
  19. package/dist/chunk-7NMB2Y64.js.map +1 -0
  20. package/dist/{chunk-V52JOSDF.js → chunk-A7P3O5Z5.js} +3 -3
  21. package/dist/chunk-A7P3O5Z5.js.map +1 -0
  22. package/dist/{chunk-ME4XILG5.js → chunk-ATYGDTMK.js} +5 -5
  23. package/dist/chunk-ATYGDTMK.js.map +1 -0
  24. package/dist/{chunk-S6XJMYME.js → chunk-C4SUXMI3.js} +3 -3
  25. package/dist/chunk-C4SUXMI3.js.map +1 -0
  26. package/dist/{chunk-I5O2WCGF.js → chunk-EU2LPUYP.js} +3 -3
  27. package/dist/chunk-EU2LPUYP.js.map +1 -0
  28. package/dist/{chunk-D7FB3TCA.js → chunk-GXI2H5XA.js} +3 -3
  29. package/dist/chunk-GXI2H5XA.js.map +1 -0
  30. package/dist/{chunk-ADO3SVUA.js → chunk-IABPUCAQ.js} +2 -2
  31. package/dist/chunk-IABPUCAQ.js.map +1 -0
  32. package/dist/{chunk-PC5SZFZC.js → chunk-JOKEKOP3.js} +8 -8
  33. package/dist/chunk-JOKEKOP3.js.map +1 -0
  34. package/dist/{chunk-GXWB6BSY.js → chunk-KUQWUTZA.js} +4 -4
  35. package/dist/chunk-KUQWUTZA.js.map +1 -0
  36. package/dist/{chunk-ZEDXARXW.js → chunk-U3J4UPV3.js} +2 -2
  37. package/dist/chunk-U3J4UPV3.js.map +1 -0
  38. package/dist/{chunk-DSEL7ELZ.js → chunk-VE2PNSDQ.js} +4 -4
  39. package/dist/chunk-VE2PNSDQ.js.map +1 -0
  40. package/dist/{chunk-YJ64RI7J.js → chunk-WAFHC4DQ.js} +3 -3
  41. package/dist/chunk-WAFHC4DQ.js.map +1 -0
  42. package/dist/{chunk-W5WNWTQC.js → chunk-YJ67WYVW.js} +5 -5
  43. package/dist/chunk-YJ67WYVW.js.map +1 -0
  44. package/dist/{chunk-4MS6ZHFQ.js → chunk-Z427NPMU.js} +7 -7
  45. package/dist/chunk-Z427NPMU.js.map +1 -0
  46. package/dist/core/index.cjs +34 -32
  47. package/dist/core/index.cjs.map +1 -1
  48. package/dist/core/index.js +2 -2
  49. package/dist/data-display/index.cjs.map +1 -1
  50. package/dist/data-display/index.js +5 -5
  51. package/dist/feedback/index.cjs.map +1 -1
  52. package/dist/feedback/index.js +2 -2
  53. package/dist/forms/index.cjs.map +1 -1
  54. package/dist/forms/index.js +8 -8
  55. package/dist/glass/index.cjs.map +1 -1
  56. package/dist/glass/index.js +2 -2
  57. package/dist/index.cjs +34 -32
  58. package/dist/index.cjs.map +1 -1
  59. package/dist/index.js +19 -19
  60. package/dist/layout/index.cjs.map +1 -1
  61. package/dist/layout/index.js +2 -2
  62. package/dist/navigation/index.cjs.map +1 -1
  63. package/dist/navigation/index.js +6 -6
  64. package/dist/overlays/index.cjs.map +1 -1
  65. package/dist/overlays/index.js +7 -7
  66. package/dist/reset.css +45 -45
  67. package/dist/tokens.css +11 -11
  68. package/dist/typography/index.cjs.map +1 -1
  69. package/dist/typography/index.js +4 -4
  70. package/llms.txt +3 -3
  71. package/package.json +165 -165
  72. package/scripts/postinstall.js +125 -125
  73. package/src/bento/BentoCard.tsx +140 -140
  74. package/src/bento/BentoGrid.tsx +50 -50
  75. package/src/bento/index.ts +2 -2
  76. package/src/bento/tokens.css +46 -46
  77. package/src/buttons/Button.tsx +104 -104
  78. package/src/buttons/ButtonGroup.tsx +43 -43
  79. package/src/buttons/IconButton.tsx +79 -79
  80. package/src/buttons/SplitButton.tsx +186 -186
  81. package/src/buttons/ToggleButton.tsx +157 -157
  82. package/src/buttons/index.ts +5 -5
  83. package/src/buttons/tokens.css +6 -6
  84. package/src/core/ThemeProvider.tsx +124 -106
  85. package/src/core/index.ts +2 -2
  86. package/src/core/tokens.css +134 -134
  87. package/src/data-display/Accordion.tsx +147 -147
  88. package/src/data-display/Avatar.tsx +134 -134
  89. package/src/data-display/Card.tsx +112 -112
  90. package/src/data-display/Chip.tsx +74 -74
  91. package/src/data-display/DataTablePro.tsx +534 -534
  92. package/src/data-display/StatCard.tsx +60 -60
  93. package/src/data-display/Table.tsx +74 -74
  94. package/src/data-display/Timeline.tsx +62 -62
  95. package/src/data-display/TreeView.tsx +279 -279
  96. package/src/data-display/tokens.css +4 -4
  97. package/src/feedback/Alert.tsx +80 -80
  98. package/src/feedback/EmptyState.tsx +45 -45
  99. package/src/feedback/Skeleton.tsx +66 -66
  100. package/src/feedback/Spinner.tsx +65 -65
  101. package/src/feedback/index.ts +5 -5
  102. package/src/feedback/tokens.css +4 -4
  103. package/src/forms/Checkbox.tsx +149 -149
  104. package/src/forms/CheckboxGroup.tsx +76 -76
  105. package/src/forms/Combobox.tsx +512 -512
  106. package/src/forms/DatePicker.tsx +784 -784
  107. package/src/forms/FileUpload.tsx +266 -266
  108. package/src/forms/FormField.tsx +115 -115
  109. package/src/forms/Input.tsx +151 -151
  110. package/src/forms/NumberInput.tsx +262 -262
  111. package/src/forms/PasswordInput.tsx +35 -35
  112. package/src/forms/PinInput.tsx +139 -139
  113. package/src/forms/Radio.tsx +142 -142
  114. package/src/forms/RangeSlider.tsx +237 -237
  115. package/src/forms/SearchInput.tsx +34 -34
  116. package/src/forms/Select.tsx +103 -103
  117. package/src/forms/Slider.tsx +85 -85
  118. package/src/forms/Textarea.tsx +114 -114
  119. package/src/forms/tokens.css +6 -6
  120. package/src/glass/GlassButton.tsx +59 -59
  121. package/src/glass/GlassCard.tsx +71 -71
  122. package/src/glass/index.ts +3 -3
  123. package/src/glass/tokens.css +81 -81
  124. package/src/index.ts +26 -26
  125. package/src/layout/AspectRatio.tsx +39 -39
  126. package/src/layout/Container.tsx +53 -53
  127. package/src/layout/Divider.tsx +61 -61
  128. package/src/layout/Flex.tsx +79 -79
  129. package/src/layout/Grid.tsx +124 -124
  130. package/src/layout/PageLayout.tsx +59 -59
  131. package/src/layout/Section.tsx +47 -47
  132. package/src/layout/Spacer.tsx +30 -30
  133. package/src/layout/Stack.tsx +88 -88
  134. package/src/layout/tokens.css +8 -8
  135. package/src/navigation/Breadcrumb.tsx +73 -73
  136. package/src/navigation/CommandPalette.tsx +142 -142
  137. package/src/navigation/DropdownMenu.tsx +244 -244
  138. package/src/navigation/Pagination.tsx +114 -114
  139. package/src/navigation/Stepper.tsx +93 -93
  140. package/src/navigation/Tabs.tsx +265 -265
  141. package/src/navigation/index.ts +6 -6
  142. package/src/navigation/tokens.css +4 -4
  143. package/src/overlays/AlertDialog.tsx +63 -63
  144. package/src/overlays/BottomSheet.tsx +143 -143
  145. package/src/overlays/ContextMenu.tsx +161 -161
  146. package/src/overlays/Drawer.tsx +160 -160
  147. package/src/overlays/FocusTrap.tsx +122 -122
  148. package/src/overlays/Modal.tsx +296 -296
  149. package/src/overlays/Popover.tsx +156 -156
  150. package/src/overlays/Portal.tsx +23 -23
  151. package/src/overlays/Toast.tsx +175 -175
  152. package/src/overlays/Tooltip.tsx +125 -125
  153. package/src/overlays/tokens.css +8 -8
  154. package/src/registry/components.ts +1368 -1368
  155. package/src/styles/components.css +39 -39
  156. package/src/styles/index.css +5 -5
  157. package/src/styles/reset.css +45 -45
  158. package/src/styles/tokens.css +11 -11
  159. package/src/typography/Blockquote.tsx +32 -32
  160. package/src/typography/Code.tsx +89 -89
  161. package/src/typography/Heading.tsx +56 -56
  162. package/src/typography/Kbd.tsx +25 -25
  163. package/src/typography/Label.tsx +47 -47
  164. package/src/typography/Link.tsx +56 -56
  165. package/src/typography/Text.tsx +62 -62
  166. package/src/typography/index.ts +7 -7
  167. package/src/typography/tokens.css +5 -5
  168. package/src/utils/cn.ts +6 -6
  169. package/src/utils/scroll-lock.ts +19 -19
  170. package/src/utils/useControllableState.ts +54 -54
  171. package/ui-contract.json +1 -1
  172. package/dist/chunk-2YJBW4E2.js.map +0 -1
  173. package/dist/chunk-4CRFNALF.js.map +0 -1
  174. package/dist/chunk-4MS6ZHFQ.js.map +0 -1
  175. package/dist/chunk-77KTYOMQ.js.map +0 -1
  176. package/dist/chunk-ADO3SVUA.js.map +0 -1
  177. package/dist/chunk-D7FB3TCA.js.map +0 -1
  178. package/dist/chunk-DSEL7ELZ.js.map +0 -1
  179. package/dist/chunk-EXFR2BFJ.js.map +0 -1
  180. package/dist/chunk-GXWB6BSY.js.map +0 -1
  181. package/dist/chunk-I2FQBMVW.js.map +0 -1
  182. package/dist/chunk-I5O2WCGF.js.map +0 -1
  183. package/dist/chunk-ME4XILG5.js.map +0 -1
  184. package/dist/chunk-PC5SZFZC.js.map +0 -1
  185. package/dist/chunk-S6XJMYME.js.map +0 -1
  186. package/dist/chunk-V52JOSDF.js.map +0 -1
  187. package/dist/chunk-W5WNWTQC.js.map +0 -1
  188. package/dist/chunk-YJ64RI7J.js.map +0 -1
  189. package/dist/chunk-YOCGBORV.js.map +0 -1
  190. package/dist/chunk-ZEDXARXW.js.map +0 -1
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 thangnqdev
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 thangnqdev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,147 +1,149 @@
1
- # @thangnqdev/ui
2
-
3
- > **AETHER** — Spatial Optics & Enterprise-Grade Component Infrastructure for React & Tailwind CSS.
4
-
5
- An enterprise-ready architectural UI system engineered for complex SaaS, Fintech, AI Agents, ERP dashboards, and spatial web applications. Features machine-readable contracts (`llms.txt`, `ui-contract.json`), 100% SSOT parity, WCAG 2.1 AA accessibility tiers, hydration-safe SSR, and modular standalone CSS packaging.
6
-
7
- [![npm version](https://img.shields.io/npm/v/@thangnqdev/ui.svg?style=flat-square)](https://www.npmjs.com/package/@thangnqdev/ui)
8
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE)
9
-
10
- ---
11
-
12
- ## 📦 Cài Đặt (Installation)
13
-
14
- ```bash
15
- npm install @thangnqdev/ui
16
- # or
17
- pnpm add @thangnqdev/ui
18
- # or
19
- yarn add @thangnqdev/ui
20
- ```
21
-
22
- ### Peer Dependencies
23
- Yêu cầu `react` và `react-dom` (>= 18.0.0 hoặc 19.0.0):
24
- ```bash
25
- npm install react react-dom
26
- ```
27
-
28
- ---
29
-
30
- ## 🎨 Thiết Lập Nhanh (Quickstart)
31
-
32
- ### Cách 1: Sử dụng Standalone All-In-One CSS
33
- File `styles.css` đã được biên dịch trọn gói toàn bộ hệ thống Apple Liquid Glass, màu sắc HSL, font SF Pro và các class tiện ích:
34
-
35
- ```tsx
36
- // Trong file src/main.tsx hoặc app/layout.tsx
37
- import '@thangnqdev/ui/styles.css';
38
-
39
- import { ThemeProvider, Button, DataTablePro, DatePicker, Combobox } from '@thangnqdev/ui';
40
-
1
+ # @thangnqdev/ui
2
+
3
+ > **AETHER** — Spatial Optics & Enterprise-Grade Component Infrastructure for React & Tailwind CSS.
4
+
5
+ An enterprise-ready architectural UI system engineered for complex SaaS, Fintech, AI Agents, ERP dashboards, and spatial web applications. Features machine-readable contracts (`llms.txt`, `ui-contract.json`), 100% SSOT parity, WCAG 2.1 AA accessibility tiers, hydration-safe SSR, and modular standalone CSS packaging.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@thangnqdev/ui.svg?style=flat-square)](https://www.npmjs.com/package/@thangnqdev/ui)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE)
9
+
10
+ ---
11
+
12
+ ## 📦 Cài Đặt (Installation)
13
+
14
+ ```bash
15
+ npm install @thangnqdev/ui
16
+ # or
17
+ pnpm add @thangnqdev/ui
18
+ # or
19
+ yarn add @thangnqdev/ui
20
+ ```
21
+
22
+ ### Peer Dependencies
23
+ Yêu cầu `react` và `react-dom` (>= 18.0.0 hoặc 19.0.0):
24
+ ```bash
25
+ npm install react react-dom
26
+ ```
27
+
28
+ ---
29
+
30
+ ## 🎨 Thiết Lập Nhanh (Quickstart)
31
+
32
+ ### Cách 1: Sử dụng Standalone All-In-One CSS
33
+ File `styles.css` đã được biên dịch trọn gói toàn bộ hệ thống Apple Liquid Glass, màu sắc HSL, font SF Pro và các class tiện ích:
34
+
35
+ ```tsx
36
+ // Trong file src/main.tsx hoặc app/layout.tsx
37
+ import '@thangnqdev/ui/styles.css';
38
+
39
+ import { ThemeProvider, Button, DataTablePro, DatePicker, Combobox } from '@thangnqdev/ui';
40
+
41
41
  export default function App() {
42
- return (
43
- <ThemeProvider defaultTheme="dark">
44
- <Button variant="primary">Primary Action</Button>
45
- </ThemeProvider>
46
- );
42
+ return (
43
+ <ThemeProvider defaultTheme="light">
44
+ <Button variant="primary">Primary Action</Button>
45
+ </ThemeProvider>
46
+ );
47
47
  }
48
48
  ```
49
49
 
50
- ### Cách 2: Sử dụng Domain Modular Subpath CSS (Tối ưu hóa Bundle Size)
51
- Mỗi domain module có stylesheet độc lập đã được biên dịch toàn bộ utility class và design tokens:
52
-
53
- ```tsx
54
- import { Button, IconButton } from '@thangnqdev/ui/buttons';
55
- import '@thangnqdev/ui/buttons/styles.css';
56
-
57
- import { Modal, ModalTitle, ModalBody } from '@thangnqdev/ui/overlays';
58
- import '@thangnqdev/ui/overlays/styles.css';
59
- ```
60
-
61
- ---
62
-
63
- ## 🏛️ Kiến Trúc Hệ Thống (Architectural Pillars)
64
-
65
- ### 1. Single Source of Truth (SSOT) Invariant Guarantee
66
- Toàn bộ metadata component, public exports, `ui-contract.json` và `llms.txt` được liên kết trực tiếp với `COMPONENT_REGISTRY` (145 components). CI tự động kiểm tra tính bất biến 1-to-1:
67
- $$\text{Registry Exports} \equiv \text{Public TS Exports} \equiv \text{ui-contract.json} \equiv \text{llms.txt}$$
68
-
69
- ### 2. Ba Cấp Độ Accessibility Rõ Ràng (A11y Tiers)
70
- Không overclaim accessibility; mọi primitive được phân loại minh bạch:
71
- - **`native`**: Các thẻ nền tảng browser (`Container`, `Grid`, `Heading`, `Text`, `Link`, `Portal`, `Divider`...).
72
- - **`supported`**: Các component composite hỗ trợ ARIA attributes và keyboard shortcuts.
73
- - **`verified`**: Các interactive primitives đã vượt qua kiểm thử WAI-ARIA pattern đầy đủ và automated audit bằng `axe-core` (`Button`, `Modal`, `FocusTrap`, `DatePicker`, `DateRangePicker`, `TimePicker`, `Tooltip`, `SplitButton`, `Checkbox`, `RangeSlider`, `Tabs`, `Accordion`, `DataTablePro`...).
74
-
75
- ### 3. Chuẩn Hóa State với `useControllableState`
76
- Mọi stateful component (`CurrencyInput`, `NumberInput`, `Popover`, `DatePicker`, `Combobox`, `Checkbox`...) hỗ trợ cả **Controlled** và **Uncontrolled** mode với cam kết:
77
- - Khi controlled, UI luôn trung thực với `value` prop (không bao giờ lệch khi parent reject update).
78
- - Chuyển đổi trạng thái mượt mà, hỗ trợ `open` / `defaultOpen` / `onOpenChange` và `value` / `defaultValue` / `onChange`.
79
-
80
- ### 4. Hydration-Safe SSR cho Next.js / Remix
81
- `ThemeProvider` và toàn bộ overlay components khởi tạo an toàn, đồng bộ theme client-side sau mount để loại bỏ hoàn toàn lỗi React hydration mismatch.
50
+ `ThemeProvider` mặc định sử dụng theme `light`, vậy thể bỏ prop `defaultTheme` nếu ứng dụng không cần chọn theme khác. Các giá trị `dark` và `system` vẫn được hỗ trợ.
82
51
 
83
- ---
84
-
85
- ## 🛠️ Hướng Dẫn Tùy Biến (Customization Guide)
86
-
87
- ### 1. Tùy Biến Toàn Cục bằng CSS Variables (Global Theming)
88
-
89
- ```css
90
- :root {
91
- /* 🔤 Font chữ & Monospace */
92
- --ui-font-sans: 'Plus Jakarta Sans', 'Inter', sans-serif;
93
- --ui-font-mono: 'JetBrains Mono', 'Fira Code', monospace;
94
-
95
- /* 🎨 Màu chủ đạo thương hiệu (Brand Colors) */
96
- --ui-primary: #6366f1;
97
- --ui-primary-hover: #4f46e5;
98
- --ui-primary-glow: rgba(99, 102, 241, 0.35);
99
- --ui-accent: #ec4899;
100
-
101
- /* 📐 Bo góc */
102
- --ui-radius-lg: 16px;
103
- }
104
-
105
- .dark, [data-theme="dark"] {
106
- --ui-primary: #818cf8;
107
- --ui-bg-page: #09090b;
108
- --ui-bg-secondary: #18181b;
109
- }
110
- ```
111
-
112
- ---
113
-
114
- ## 🤖 Machine-Readable Contracts for AI Agents
115
-
116
- Thư viện cung cấp hợp đồng chuẩn máy cho các trợ lý AI (Antigravity, Claude Code, Cursor, Codex):
117
- - **`llms.txt`**: Đặc tả toàn diện cấu trúc import, signature, và quy tắc lập trình.
118
- - **`ui-contract.json`**: Schema JSON chặt chẽ phục vụ validate và sinh code tự động.
119
-
120
- ---
121
-
122
- ## 🧪 Quality Gates & Kiểm Thử
123
-
124
- ```bash
125
- # Kiểm tra strict TypeScript
126
- npm run typecheck
127
-
128
- # Chạy toàn bộ 115+ test cases (A11y, Axe, Invariant, SSR, Controllable State)
129
- npm test
130
-
131
- # Kiểm tra tính bất biến SSOT
132
- npm run test:ssot
133
-
134
- # Kiểm tra WAI-ARIA & Axe automated scans
135
- npm run test:a11y
136
-
137
- # Kiểm tra Server-Side Rendering
138
- npm run test:ssr
139
-
140
- # Quy trình Prepack Gate trước khi phát hành
141
- npm run prepack
142
- ```
143
-
144
- ---
145
-
146
- ## 📄 License
147
- MIT © 2026 AETHER Spatial UI
52
+ ### Cách 2: Sử dụng Domain Modular Subpath CSS (Tối ưu hóa Bundle Size)
53
+ Mỗi domain module có stylesheet độc lập đã được biên dịch toàn bộ utility class và design tokens:
54
+
55
+ ```tsx
56
+ import { Button, IconButton } from '@thangnqdev/ui/buttons';
57
+ import '@thangnqdev/ui/buttons/styles.css';
58
+
59
+ import { Modal, ModalTitle, ModalBody } from '@thangnqdev/ui/overlays';
60
+ import '@thangnqdev/ui/overlays/styles.css';
61
+ ```
62
+
63
+ ---
64
+
65
+ ## 🏛️ Kiến Trúc Hệ Thống (Architectural Pillars)
66
+
67
+ ### 1. Single Source of Truth (SSOT) Invariant Guarantee
68
+ Toàn bộ metadata component, public exports, `ui-contract.json` và `llms.txt` được liên kết trực tiếp với `COMPONENT_REGISTRY` (145 components). CI tự động kiểm tra tính bất biến 1-to-1:
69
+ $$\text{Registry Exports} \equiv \text{Public TS Exports} \equiv \text{ui-contract.json} \equiv \text{llms.txt}$$
70
+
71
+ ### 2. Ba Cấp Độ Accessibility Rõ Ràng (A11y Tiers)
72
+ Không overclaim accessibility; mọi primitive được phân loại minh bạch:
73
+ - **`native`**: Các thẻ nền tảng browser (`Container`, `Grid`, `Heading`, `Text`, `Link`, `Portal`, `Divider`...).
74
+ - **`supported`**: Các component composite hỗ trợ ARIA attributes và keyboard shortcuts.
75
+ - **`verified`**: Các interactive primitives đã vượt qua kiểm thử WAI-ARIA pattern đầy đủ và automated audit bằng `axe-core` (`Button`, `Modal`, `FocusTrap`, `DatePicker`, `DateRangePicker`, `TimePicker`, `Tooltip`, `SplitButton`, `Checkbox`, `RangeSlider`, `Tabs`, `Accordion`, `DataTablePro`...).
76
+
77
+ ### 3. Chuẩn Hóa State với `useControllableState`
78
+ Mọi stateful component (`CurrencyInput`, `NumberInput`, `Popover`, `DatePicker`, `Combobox`, `Checkbox`...) hỗ trợ cả **Controlled** và **Uncontrolled** mode với cam kết:
79
+ - Khi controlled, UI luôn trung thực với `value` prop (không bao giờ lệch khi parent reject update).
80
+ - Chuyển đổi trạng thái mượt mà, hỗ trợ `open` / `defaultOpen` / `onOpenChange` và `value` / `defaultValue` / `onChange`.
81
+
82
+ ### 4. Hydration-Safe SSR cho Next.js / Remix
83
+ `ThemeProvider` toàn bộ overlay components khởi tạo an toàn, đồng bộ theme client-side sau mount để loại bỏ hoàn toàn lỗi React hydration mismatch.
84
+
85
+ ---
86
+
87
+ ## 🛠️ Hướng Dẫn Tùy Biến (Customization Guide)
88
+
89
+ ### 1. Tùy Biến Toàn Cục bằng CSS Variables (Global Theming)
90
+
91
+ ```css
92
+ :root {
93
+ /* 🔤 Font chữ & Monospace */
94
+ --ui-font-sans: 'Plus Jakarta Sans', 'Inter', sans-serif;
95
+ --ui-font-mono: 'JetBrains Mono', 'Fira Code', monospace;
96
+
97
+ /* 🎨 Màu chủ đạo thương hiệu (Brand Colors) */
98
+ --ui-primary: #6366f1;
99
+ --ui-primary-hover: #4f46e5;
100
+ --ui-primary-glow: rgba(99, 102, 241, 0.35);
101
+ --ui-accent: #ec4899;
102
+
103
+ /* 📐 Bo góc */
104
+ --ui-radius-lg: 16px;
105
+ }
106
+
107
+ .dark, [data-theme="dark"] {
108
+ --ui-primary: #818cf8;
109
+ --ui-bg-page: #09090b;
110
+ --ui-bg-secondary: #18181b;
111
+ }
112
+ ```
113
+
114
+ ---
115
+
116
+ ## 🤖 Machine-Readable Contracts for AI Agents
117
+
118
+ Thư viện cung cấp hợp đồng chuẩn máy cho các trợ lý AI (Antigravity, Claude Code, Cursor, Codex):
119
+ - **`llms.txt`**: Đặc tả toàn diện cấu trúc import, signature, và quy tắc lập trình.
120
+ - **`ui-contract.json`**: Schema JSON chặt chẽ phục vụ validate và sinh code tự động.
121
+
122
+ ---
123
+
124
+ ## 🧪 Quality Gates & Kiểm Thử
125
+
126
+ ```bash
127
+ # Kiểm tra strict TypeScript
128
+ npm run typecheck
129
+
130
+ # Chạy toàn bộ 115+ test cases (A11y, Axe, Invariant, SSR, Controllable State)
131
+ npm test
132
+
133
+ # Kiểm tra tính bất biến SSOT
134
+ npm run test:ssot
135
+
136
+ # Kiểm tra WAI-ARIA & Axe automated scans
137
+ npm run test:a11y
138
+
139
+ # Kiểm tra Server-Side Rendering
140
+ npm run test:ssr
141
+
142
+ # Quy trình Prepack Gate trước khi phát hành
143
+ npm run prepack
144
+ ```
145
+
146
+ ---
147
+
148
+ ## 📄 License
149
+ MIT © 2026 AETHER Spatial UI
package/bin/cli.js CHANGED
@@ -1,125 +1,125 @@
1
- #!/usr/bin/env node
2
-
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- import os from 'node:os';
6
- import readline from 'node:readline';
7
- import { execSync } from 'node:child_process';
8
-
9
- const CONFIG_DIR = path.join(os.homedir(), '.thangnqdev-ui');
10
- const CONFIG_FILE = path.join(CONFIG_DIR, 'telemetry.json');
11
-
12
- const args = process.argv.slice(2);
13
- const command = args[0] || 'help';
14
-
15
- function getGitRemote() {
16
- try {
17
- return execSync('git remote get-url origin', {
18
- stdio: ['pipe', 'pipe', 'ignore'],
19
- timeout: 1000,
20
- })
21
- .toString()
22
- .trim();
23
- } catch {
24
- return null;
25
- }
26
- }
27
-
28
- function loadConfig() {
29
- if (fs.existsSync(CONFIG_FILE)) {
30
- try {
31
- return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'));
32
- } catch {
33
- return {};
34
- }
35
- }
36
- return {};
37
- }
38
-
39
- function saveConfig(data) {
40
- if (!fs.existsSync(CONFIG_DIR)) {
41
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
42
- }
43
- fs.writeFileSync(
44
- CONFIG_FILE,
45
- JSON.stringify(
46
- {
47
- ...loadConfig(),
48
- ...data,
49
- updatedAt: new Date().toISOString(),
50
- },
51
- null,
52
- 2
53
- )
54
- );
55
- }
56
-
57
- switch (command) {
58
- case 'showcase':
59
- case 'register': {
60
- const detected = getGitRemote();
61
- const rl = readline.createInterface({
62
- input: process.stdin,
63
- output: process.stdout,
64
- });
65
-
66
- console.log('\n\x1b[36m✦ AETHER Community Showcase Registration\x1b[0m');
67
- console.log('Share your project or repository using @thangnqdev/ui:\n');
68
-
69
- rl.question(` Repository URL [${detected || 'none'}]: `, (repoUrl) => {
70
- const finalRepo = repoUrl.trim() || detected || 'custom';
71
- rl.question(' Project / Company Name (optional): ', (name) => {
72
- saveConfig({
73
- enabled: true,
74
- repo: finalRepo,
75
- projectName: name.trim() || undefined,
76
- prompted: true,
77
- });
78
-
79
- console.log('\n\x1b[32m✔ Successfully registered for AETHER Community Showcase!\x1b[0m');
80
- console.log(` Repo: \x1b[33m${finalRepo}\x1b[0m\n`);
81
- rl.close();
82
- });
83
- });
84
- break;
85
- }
86
-
87
- case 'telemetry': {
88
- const sub = args[1] || 'status';
89
- if (sub === 'enable') {
90
- const remote = getGitRemote();
91
- saveConfig({ enabled: true, repo: remote, prompted: true });
92
- console.log('\x1b[32m✔ Repository sharing & showcase telemetry enabled.\x1b[0m');
93
- } else if (sub === 'disable') {
94
- saveConfig({ enabled: false, repo: null, prompted: true });
95
- console.log('\x1b[90m✔ Repository sharing & showcase telemetry disabled.\x1b[0m');
96
- } else {
97
- const cfg = loadConfig();
98
- console.log('\n\x1b[36m✦ AETHER Telemetry & Showcase Status\x1b[0m');
99
- console.log(` Status: ${cfg.enabled ? '\x1b[32mEnabled (Sharing active)\x1b[0m' : '\x1b[90mDisabled (Anonymous)\x1b[0m'}`);
100
- if (cfg.repo) console.log(` Repository: \x1b[33m${cfg.repo}\x1b[0m`);
101
- console.log('\n Commands:');
102
- console.log(' npx @thangnqdev/ui showcase # Register project for showcase');
103
- console.log(' npx @thangnqdev/ui telemetry enable # Enable repo telemetry');
104
- console.log(' npx @thangnqdev/ui telemetry disable # Disable repo telemetry\n');
105
- }
106
- break;
107
- }
108
-
109
- case 'help':
110
- default: {
111
- console.log(`
112
- \x1b[1m@thangnqdev/ui CLI\x1b[0m (AETHER System)
113
-
114
- Usage:
115
- npx @thangnqdev/ui <command>
116
-
117
- Commands:
118
- showcase Register repository for AETHER Community Showcase
119
- telemetry status View repository sharing & telemetry status
120
- telemetry enable Opt-in to share repository telemetry
121
- telemetry disable Opt-out from repository telemetry
122
- `);
123
- break;
124
- }
125
- }
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import os from 'node:os';
6
+ import readline from 'node:readline';
7
+ import { execSync } from 'node:child_process';
8
+
9
+ const CONFIG_DIR = path.join(os.homedir(), '.thangnqdev-ui');
10
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'telemetry.json');
11
+
12
+ const args = process.argv.slice(2);
13
+ const command = args[0] || 'help';
14
+
15
+ function getGitRemote() {
16
+ try {
17
+ return execSync('git remote get-url origin', {
18
+ stdio: ['pipe', 'pipe', 'ignore'],
19
+ timeout: 1000,
20
+ })
21
+ .toString()
22
+ .trim();
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+
28
+ function loadConfig() {
29
+ if (fs.existsSync(CONFIG_FILE)) {
30
+ try {
31
+ return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'));
32
+ } catch {
33
+ return {};
34
+ }
35
+ }
36
+ return {};
37
+ }
38
+
39
+ function saveConfig(data) {
40
+ if (!fs.existsSync(CONFIG_DIR)) {
41
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
42
+ }
43
+ fs.writeFileSync(
44
+ CONFIG_FILE,
45
+ JSON.stringify(
46
+ {
47
+ ...loadConfig(),
48
+ ...data,
49
+ updatedAt: new Date().toISOString(),
50
+ },
51
+ null,
52
+ 2
53
+ )
54
+ );
55
+ }
56
+
57
+ switch (command) {
58
+ case 'showcase':
59
+ case 'register': {
60
+ const detected = getGitRemote();
61
+ const rl = readline.createInterface({
62
+ input: process.stdin,
63
+ output: process.stdout,
64
+ });
65
+
66
+ console.log('\n\x1b[36m✦ AETHER Community Showcase Registration\x1b[0m');
67
+ console.log('Share your project or repository using @thangnqdev/ui:\n');
68
+
69
+ rl.question(` Repository URL [${detected || 'none'}]: `, (repoUrl) => {
70
+ const finalRepo = repoUrl.trim() || detected || 'custom';
71
+ rl.question(' Project / Company Name (optional): ', (name) => {
72
+ saveConfig({
73
+ enabled: true,
74
+ repo: finalRepo,
75
+ projectName: name.trim() || undefined,
76
+ prompted: true,
77
+ });
78
+
79
+ console.log('\n\x1b[32m✔ Successfully registered for AETHER Community Showcase!\x1b[0m');
80
+ console.log(` Repo: \x1b[33m${finalRepo}\x1b[0m\n`);
81
+ rl.close();
82
+ });
83
+ });
84
+ break;
85
+ }
86
+
87
+ case 'telemetry': {
88
+ const sub = args[1] || 'status';
89
+ if (sub === 'enable') {
90
+ const remote = getGitRemote();
91
+ saveConfig({ enabled: true, repo: remote, prompted: true });
92
+ console.log('\x1b[32m✔ Repository sharing & showcase telemetry enabled.\x1b[0m');
93
+ } else if (sub === 'disable') {
94
+ saveConfig({ enabled: false, repo: null, prompted: true });
95
+ console.log('\x1b[90m✔ Repository sharing & showcase telemetry disabled.\x1b[0m');
96
+ } else {
97
+ const cfg = loadConfig();
98
+ console.log('\n\x1b[36m✦ AETHER Telemetry & Showcase Status\x1b[0m');
99
+ console.log(` Status: ${cfg.enabled ? '\x1b[32mEnabled (Sharing active)\x1b[0m' : '\x1b[90mDisabled (Anonymous)\x1b[0m'}`);
100
+ if (cfg.repo) console.log(` Repository: \x1b[33m${cfg.repo}\x1b[0m`);
101
+ console.log('\n Commands:');
102
+ console.log(' npx @thangnqdev/ui showcase # Register project for showcase');
103
+ console.log(' npx @thangnqdev/ui telemetry enable # Enable repo telemetry');
104
+ console.log(' npx @thangnqdev/ui telemetry disable # Disable repo telemetry\n');
105
+ }
106
+ break;
107
+ }
108
+
109
+ case 'help':
110
+ default: {
111
+ console.log(`
112
+ \x1b[1m@thangnqdev/ui CLI\x1b[0m (AETHER System)
113
+
114
+ Usage:
115
+ npx @thangnqdev/ui <command>
116
+
117
+ Commands:
118
+ showcase Register repository for AETHER Community Showcase
119
+ telemetry status View repository sharing & telemetry status
120
+ telemetry enable Opt-in to share repository telemetry
121
+ telemetry disable Opt-out from repository telemetry
122
+ `);
123
+ break;
124
+ }
125
+ }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/cn.ts","../../src/bento/BentoGrid.tsx","../../src/bento/BentoCard.tsx"],"names":["twMerge","clsx","cva","jsx","forwardRef","jsxs"],"mappings":"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","file":"index.cjs","sourcesContent":["import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../utils/cn';\n\nconst bentoGridVariants = cva('grid w-full auto-rows-[minmax(240px,auto)]', {\n variants: {\n cols: {\n 1: 'grid-cols-1',\n 2: 'grid-cols-1 md:grid-cols-2',\n 3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',\n 4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4',\n },\n gap: {\n sm: 'gap-4',\n md: 'gap-6',\n lg: 'gap-8',\n },\n flow: {\n row: 'grid-flow-row',\n col: 'grid-flow-col',\n dense: 'grid-flow-dense',\n 'row-dense': 'grid-flow-row-dense',\n 'col-dense': 'grid-flow-col-dense',\n },\n },\n defaultVariants: {\n cols: 3,\n gap: 'md',\n flow: 'row',\n },\n});\n\nexport interface BentoGridProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof bentoGridVariants> {}\n\nexport const BentoGrid: React.FC<BentoGridProps> = ({\n className,\n cols,\n gap,\n flow,\n children,\n ...props\n}) => {\n return (\n <div className={cn(bentoGridVariants({ cols, gap, flow, className }))} {...props}>\n {children}\n </div>\n );\n};\n","import React, { forwardRef } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../utils/cn';\n\nconst bentoCardVariants = cva(\n 'group relative flex flex-col justify-between overflow-hidden transition-all duration-500 ease-out border text-[var(--ui-bento-text-title)]',\n {\n variants: {\n colSpan: {\n 1: 'col-span-1',\n 2: 'col-span-1 md:col-span-2',\n 3: 'col-span-1 md:col-span-2 lg:col-span-3',\n },\n rowSpan: {\n 1: 'row-span-1',\n 2: 'row-span-1 md:row-span-2 md:min-h-[460px]',\n 3: 'row-span-1 md:row-span-3 md:min-h-[680px]',\n },\n variant: {\n default:\n 'bg-[var(--ui-bento-bg-card)] border-[var(--ui-bento-border)] hover:border-[var(--ui-bento-border-hover)] hover:bg-[var(--ui-bento-bg-card-hover)] shadow-[var(--ui-bento-shadow)]',\n spotlight:\n 'bg-[var(--ui-bento-bg-card)] border-[var(--ui-bento-border)] hover:border-white/30 dark:hover:border-white/30 hover:shadow-[0_0_35px_-8px_rgba(255,255,255,0.12)]',\n elevated:\n 'bg-[image:var(--ui-bento-bg-elevated)] border-[var(--ui-bento-border)] hover:border-[var(--ui-bento-border-hover)] shadow-[var(--ui-bento-shadow-elevated)]',\n },\n radius: {\n md: 'rounded-[var(--ui-bento-radius-md)]',\n lg: 'rounded-[var(--ui-bento-radius-lg)]',\n },\n padding: {\n sm: 'p-4 sm:p-5',\n md: 'p-5 sm:p-7',\n lg: 'p-6 sm:p-9',\n },\n },\n defaultVariants: {\n colSpan: 1,\n rowSpan: 1,\n variant: 'default',\n radius: 'lg',\n padding: 'md',\n },\n }\n);\n\nexport interface BentoCardProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'>,\n VariantProps<typeof bentoCardVariants> {\n title?: React.ReactNode;\n description?: React.ReactNode;\n icon?: React.ReactNode;\n tag?: React.ReactNode;\n /**\n * Decorative background graphic. Non-interactive backdrop element.\n */\n backgroundGraphic?: React.ReactNode;\n /**\n * @deprecated Use `backgroundGraphic` instead.\n */\n graphic?: React.ReactNode;\n}\n\nexport const BentoCard = forwardRef<HTMLDivElement, BentoCardProps>(\n (\n {\n className,\n colSpan,\n rowSpan,\n variant,\n radius,\n padding,\n title,\n description,\n icon,\n tag,\n backgroundGraphic,\n graphic,\n children,\n ...props\n },\n ref\n ) => {\n const bgGraphic = backgroundGraphic ?? graphic;\n\n return (\n <div\n ref={ref}\n className={cn(bentoCardVariants({ colSpan, rowSpan, variant, radius, padding, className }))}\n {...props}\n >\n {/* Subtle Specular Top Line */}\n <div\n className=\"pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/20 to-transparent opacity-50\"\n aria-hidden=\"true\"\n />\n\n {/* Background Visual Graphic Slot (Decorative) */}\n {bgGraphic && (\n <div className=\"absolute inset-0 z-0 overflow-hidden pointer-events-none opacity-70 transition-transform duration-700 ease-out motion-safe:group-hover:scale-105\">\n {bgGraphic}\n </div>\n )}\n\n {/* Top Header Section */}\n {(icon || tag) && (\n <div className=\"relative z-10 flex items-start justify-between gap-4\">\n {icon && (\n <div className=\"flex h-11 w-11 items-center justify-center rounded-2xl bg-[var(--ui-bento-icon-bg)] border border-[var(--ui-bento-icon-border)] backdrop-blur-md shadow-inner transition-transform duration-300 group-hover:scale-105\">\n {icon}\n </div>\n )}\n {tag && (\n <div className=\"font-mono text-[10px] font-semibold uppercase tracking-widest text-[var(--ui-bento-text-tag)] border border-[var(--ui-bento-icon-border)] bg-[var(--ui-bento-icon-bg)] px-2.5 py-1 rounded-md backdrop-blur-sm\">\n {tag}\n </div>\n )}\n </div>\n )}\n\n {/* Main Content Area */}\n <div className=\"relative z-10 mt-auto pt-6\">\n {title && (\n <h3 className=\"text-xl font-bold tracking-tight text-[var(--ui-bento-text-title)] transition-colors group-hover:text-[var(--ui-primary)] dark:group-hover:text-white\">\n {title}\n </h3>\n )}\n {description && (\n <p className=\"mt-2 text-sm leading-relaxed text-[var(--ui-bento-text-desc)] font-normal\">\n {description}\n </p>\n )}\n {children}\n </div>\n </div>\n );\n }\n);\n\nBentoCard.displayName = 'BentoCard';\n"]}
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/bento/BentoGrid.tsx","../../src/bento/BentoCard.tsx"],"names":["twMerge","clsx","cva","jsx","forwardRef","jsxs"],"mappings":";;;;;;;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAOA,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACDA,IAAM,iBAAA,GAAoBC,2BAAI,4CAAA,EAA8C;AAAA,EAC1E,QAAA,EAAU;AAAA,IACR,IAAA,EAAM;AAAA,MACJ,CAAA,EAAG,aAAA;AAAA,MACH,CAAA,EAAG,4BAAA;AAAA,MACH,CAAA,EAAG,2CAAA;AAAA,MACH,CAAA,EAAG;AAAA,KACL;AAAA,IACA,GAAA,EAAK;AAAA,MACH,EAAA,EAAI,OAAA;AAAA,MACJ,EAAA,EAAI,OAAA;AAAA,MACJ,EAAA,EAAI;AAAA,KACN;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,GAAA,EAAK,eAAA;AAAA,MACL,GAAA,EAAK,eAAA;AAAA,MACL,KAAA,EAAO,iBAAA;AAAA,MACP,WAAA,EAAa,qBAAA;AAAA,MACb,WAAA,EAAa;AAAA;AACf,GACF;AAAA,EACA,eAAA,EAAiB;AAAA,IACf,IAAA,EAAM,CAAA;AAAA,IACN,GAAA,EAAK,IAAA;AAAA,IACL,IAAA,EAAM;AAAA;AAEV,CAAC,CAAA;AAMM,IAAM,YAAsC,CAAC;AAAA,EAClD,SAAA;AAAA,EACA,IAAA;AAAA,EACA,GAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,uBACEC,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,kBAAkB,EAAE,IAAA,EAAM,GAAA,EAAK,IAAA,EAAM,WAAW,CAAC,CAAA,EAAI,GAAG,OACxE,QAAA,EACH,CAAA;AAEJ;AC7CA,IAAM,iBAAA,GAAoBD,0BAAAA;AAAA,EACxB,4IAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,CAAA,EAAG,YAAA;AAAA,QACH,CAAA,EAAG,0BAAA;AAAA,QACH,CAAA,EAAG;AAAA,OACL;AAAA,MACA,OAAA,EAAS;AAAA,QACP,CAAA,EAAG,YAAA;AAAA,QACH,CAAA,EAAG,2CAAA;AAAA,QACH,CAAA,EAAG;AAAA,OACL;AAAA,MACA,OAAA,EAAS;AAAA,QACP,OAAA,EACE,mLAAA;AAAA,QACF,SAAA,EACE,mKAAA;AAAA,QACF,QAAA,EACE;AAAA,OACJ;AAAA,MACA,MAAA,EAAQ;AAAA,QACN,EAAA,EAAI,qCAAA;AAAA,QACJ,EAAA,EAAI;AAAA,OACN;AAAA,MACA,OAAA,EAAS;AAAA,QACP,EAAA,EAAI,YAAA;AAAA,QACJ,EAAA,EAAI,YAAA;AAAA,QACJ,EAAA,EAAI;AAAA;AACN,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS,CAAA;AAAA,MACT,OAAA,EAAS,CAAA;AAAA,MACT,OAAA,EAAS,SAAA;AAAA,MACT,MAAA,EAAQ,IAAA;AAAA,MACR,OAAA,EAAS;AAAA;AACX;AAEJ,CAAA;AAmBO,IAAM,SAAA,GAAYE,gBAAA;AAAA,EACvB,CACE;AAAA,IACE,SAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,WAAA;AAAA,IACA,IAAA;AAAA,IACA,GAAA;AAAA,IACA,iBAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,YAAY,iBAAA,IAAqB,OAAA;AAEvC,IAAA,uBACEC,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW,EAAA,CAAG,iBAAA,CAAkB,EAAE,OAAA,EAAS,OAAA,EAAS,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,SAAA,EAAW,CAAC,CAAA;AAAA,QACzF,GAAG,KAAA;AAAA,QAGJ,QAAA,EAAA;AAAA,0BAAAF,cAAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAU,4HAAA;AAAA,cACV,aAAA,EAAY;AAAA;AAAA,WACd;AAAA,UAGC,6BACCA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oJACZ,QAAA,EAAA,SAAA,EACH,CAAA;AAAA,UAAA,CAIA,IAAA,IAAQ,GAAA,qBACRE,eAAA,CAAC,KAAA,EAAA,EAAI,WAAU,sDAAA,EACZ,QAAA,EAAA;AAAA,YAAA,IAAA,oBACCF,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yNACZ,QAAA,EAAA,IAAA,EACH,CAAA;AAAA,YAED,uBACCA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kNACZ,QAAA,EAAA,GAAA,EACH;AAAA,WAAA,EAEJ,CAAA;AAAA,0BAIFE,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EACZ,QAAA,EAAA;AAAA,YAAA,KAAA,oBACCF,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,yJACX,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,YAED,+BACCA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,6EACV,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,YAED;AAAA,WAAA,EACH;AAAA;AAAA;AAAA,KACF;AAAA,EAEJ;AACF;AAEA,SAAA,CAAU,WAAA,GAAc,WAAA","file":"index.cjs","sourcesContent":["import { clsx, type ClassValue } from 'clsx';\r\nimport { twMerge } from 'tailwind-merge';\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","import React from 'react';\r\nimport { cva, type VariantProps } from 'class-variance-authority';\r\nimport { cn } from '../utils/cn';\r\n\r\nconst bentoGridVariants = cva('grid w-full auto-rows-[minmax(240px,auto)]', {\r\n variants: {\r\n cols: {\r\n 1: 'grid-cols-1',\r\n 2: 'grid-cols-1 md:grid-cols-2',\r\n 3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',\r\n 4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4',\r\n },\r\n gap: {\r\n sm: 'gap-4',\r\n md: 'gap-6',\r\n lg: 'gap-8',\r\n },\r\n flow: {\r\n row: 'grid-flow-row',\r\n col: 'grid-flow-col',\r\n dense: 'grid-flow-dense',\r\n 'row-dense': 'grid-flow-row-dense',\r\n 'col-dense': 'grid-flow-col-dense',\r\n },\r\n },\r\n defaultVariants: {\r\n cols: 3,\r\n gap: 'md',\r\n flow: 'row',\r\n },\r\n});\r\n\r\nexport interface BentoGridProps\r\n extends React.HTMLAttributes<HTMLDivElement>,\r\n VariantProps<typeof bentoGridVariants> {}\r\n\r\nexport const BentoGrid: React.FC<BentoGridProps> = ({\r\n className,\r\n cols,\r\n gap,\r\n flow,\r\n children,\r\n ...props\r\n}) => {\r\n return (\r\n <div className={cn(bentoGridVariants({ cols, gap, flow, className }))} {...props}>\r\n {children}\r\n </div>\r\n );\r\n};\r\n","import React, { forwardRef } from 'react';\r\nimport { cva, type VariantProps } from 'class-variance-authority';\r\nimport { cn } from '../utils/cn';\r\n\r\nconst bentoCardVariants = cva(\r\n 'group relative flex flex-col justify-between overflow-hidden transition-all duration-500 ease-out border text-[var(--ui-bento-text-title)]',\r\n {\r\n variants: {\r\n colSpan: {\r\n 1: 'col-span-1',\r\n 2: 'col-span-1 md:col-span-2',\r\n 3: 'col-span-1 md:col-span-2 lg:col-span-3',\r\n },\r\n rowSpan: {\r\n 1: 'row-span-1',\r\n 2: 'row-span-1 md:row-span-2 md:min-h-[460px]',\r\n 3: 'row-span-1 md:row-span-3 md:min-h-[680px]',\r\n },\r\n variant: {\r\n default:\r\n 'bg-[var(--ui-bento-bg-card)] border-[var(--ui-bento-border)] hover:border-[var(--ui-bento-border-hover)] hover:bg-[var(--ui-bento-bg-card-hover)] shadow-[var(--ui-bento-shadow)]',\r\n spotlight:\r\n 'bg-[var(--ui-bento-bg-card)] border-[var(--ui-bento-border)] hover:border-white/30 dark:hover:border-white/30 hover:shadow-[0_0_35px_-8px_rgba(255,255,255,0.12)]',\r\n elevated:\r\n 'bg-[image:var(--ui-bento-bg-elevated)] border-[var(--ui-bento-border)] hover:border-[var(--ui-bento-border-hover)] shadow-[var(--ui-bento-shadow-elevated)]',\r\n },\r\n radius: {\r\n md: 'rounded-[var(--ui-bento-radius-md)]',\r\n lg: 'rounded-[var(--ui-bento-radius-lg)]',\r\n },\r\n padding: {\r\n sm: 'p-4 sm:p-5',\r\n md: 'p-5 sm:p-7',\r\n lg: 'p-6 sm:p-9',\r\n },\r\n },\r\n defaultVariants: {\r\n colSpan: 1,\r\n rowSpan: 1,\r\n variant: 'default',\r\n radius: 'lg',\r\n padding: 'md',\r\n },\r\n }\r\n);\r\n\r\nexport interface BentoCardProps\r\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'>,\r\n VariantProps<typeof bentoCardVariants> {\r\n title?: React.ReactNode;\r\n description?: React.ReactNode;\r\n icon?: React.ReactNode;\r\n tag?: React.ReactNode;\r\n /**\r\n * Decorative background graphic. Non-interactive backdrop element.\r\n */\r\n backgroundGraphic?: React.ReactNode;\r\n /**\r\n * @deprecated Use `backgroundGraphic` instead.\r\n */\r\n graphic?: React.ReactNode;\r\n}\r\n\r\nexport const BentoCard = forwardRef<HTMLDivElement, BentoCardProps>(\r\n (\r\n {\r\n className,\r\n colSpan,\r\n rowSpan,\r\n variant,\r\n radius,\r\n padding,\r\n title,\r\n description,\r\n icon,\r\n tag,\r\n backgroundGraphic,\r\n graphic,\r\n children,\r\n ...props\r\n },\r\n ref\r\n ) => {\r\n const bgGraphic = backgroundGraphic ?? graphic;\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={cn(bentoCardVariants({ colSpan, rowSpan, variant, radius, padding, className }))}\r\n {...props}\r\n >\r\n {/* Subtle Specular Top Line */}\r\n <div\r\n className=\"pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/20 to-transparent opacity-50\"\r\n aria-hidden=\"true\"\r\n />\r\n\r\n {/* Background Visual Graphic Slot (Decorative) */}\r\n {bgGraphic && (\r\n <div className=\"absolute inset-0 z-0 overflow-hidden pointer-events-none opacity-70 transition-transform duration-700 ease-out motion-safe:group-hover:scale-105\">\r\n {bgGraphic}\r\n </div>\r\n )}\r\n\r\n {/* Top Header Section */}\r\n {(icon || tag) && (\r\n <div className=\"relative z-10 flex items-start justify-between gap-4\">\r\n {icon && (\r\n <div className=\"flex h-11 w-11 items-center justify-center rounded-2xl bg-[var(--ui-bento-icon-bg)] border border-[var(--ui-bento-icon-border)] backdrop-blur-md shadow-inner transition-transform duration-300 group-hover:scale-105\">\r\n {icon}\r\n </div>\r\n )}\r\n {tag && (\r\n <div className=\"font-mono text-[10px] font-semibold uppercase tracking-widest text-[var(--ui-bento-text-tag)] border border-[var(--ui-bento-icon-border)] bg-[var(--ui-bento-icon-bg)] px-2.5 py-1 rounded-md backdrop-blur-sm\">\r\n {tag}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Main Content Area */}\r\n <div className=\"relative z-10 mt-auto pt-6\">\r\n {title && (\r\n <h3 className=\"text-xl font-bold tracking-tight text-[var(--ui-bento-text-title)] transition-colors group-hover:text-[var(--ui-primary)] dark:group-hover:text-white\">\r\n {title}\r\n </h3>\r\n )}\r\n {description && (\r\n <p className=\"mt-2 text-sm leading-relaxed text-[var(--ui-bento-text-desc)] font-normal\">\r\n {description}\r\n </p>\r\n )}\r\n {children}\r\n </div>\r\n </div>\r\n );\r\n }\r\n);\r\n\r\nBentoCard.displayName = 'BentoCard';\r\n"]}
@@ -1,4 +1,4 @@
1
- export { BentoCard, BentoGrid } from '../chunk-S6XJMYME.js';
2
- import '../chunk-2YJBW4E2.js';
1
+ export { BentoCard, BentoGrid } from '../chunk-C4SUXMI3.js';
2
+ import '../chunk-4S6L5V7X.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map