@thangnqdev/ui 0.1.2 → 0.2.1

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 (233) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +54 -206
  3. package/bin/cli.js +125 -0
  4. package/dist/bento/index.cjs.map +1 -1
  5. package/dist/bento/index.js +2 -2
  6. package/dist/bento/styles.css +2 -46
  7. package/dist/buttons/index.cjs +111 -18
  8. package/dist/buttons/index.cjs.map +1 -1
  9. package/dist/buttons/index.d.cts +1 -1
  10. package/dist/buttons/index.d.ts +1 -1
  11. package/dist/buttons/index.js +3 -3
  12. package/dist/buttons/styles.css +2 -6
  13. package/dist/{chunk-4S6L5V7X.js → chunk-2YJBW4E2.js} +2 -2
  14. package/dist/chunk-2YJBW4E2.js.map +1 -0
  15. package/dist/{chunk-F5Q7BTMH.js → chunk-4CRFNALF.js} +1011 -556
  16. package/dist/chunk-4CRFNALF.js.map +1 -0
  17. package/dist/{chunk-LWFRUJRU.js → chunk-4MS6ZHFQ.js} +225 -41
  18. package/dist/chunk-4MS6ZHFQ.js.map +1 -0
  19. package/dist/{chunk-2OXZK6IP.js → chunk-77KTYOMQ.js} +3 -3
  20. package/dist/chunk-77KTYOMQ.js.map +1 -0
  21. package/dist/{chunk-IABPUCAQ.js → chunk-ADO3SVUA.js} +2 -2
  22. package/dist/chunk-ADO3SVUA.js.map +1 -0
  23. package/dist/{chunk-GXI2H5XA.js → chunk-D7FB3TCA.js} +3 -3
  24. package/dist/chunk-D7FB3TCA.js.map +1 -0
  25. package/dist/chunk-DSEL7ELZ.js +314 -0
  26. package/dist/chunk-DSEL7ELZ.js.map +1 -0
  27. package/dist/{chunk-KJRBRTQE.js → chunk-EXFR2BFJ.js} +37 -28
  28. package/dist/chunk-EXFR2BFJ.js.map +1 -0
  29. package/dist/{chunk-PF4ZHGVW.js → chunk-GXWB6BSY.js} +116 -23
  30. package/dist/chunk-GXWB6BSY.js.map +1 -0
  31. package/dist/{chunk-66VWUJEI.js → chunk-I2FQBMVW.js} +3 -3
  32. package/dist/chunk-I2FQBMVW.js.map +1 -0
  33. package/dist/{chunk-EU2LPUYP.js → chunk-I5O2WCGF.js} +3 -3
  34. package/dist/chunk-I5O2WCGF.js.map +1 -0
  35. package/dist/{chunk-ATYGDTMK.js → chunk-ME4XILG5.js} +5 -5
  36. package/dist/chunk-ME4XILG5.js.map +1 -0
  37. package/dist/{chunk-5FZ6ZFII.js → chunk-PC5SZFZC.js} +373 -150
  38. package/dist/chunk-PC5SZFZC.js.map +1 -0
  39. package/dist/{chunk-C4SUXMI3.js → chunk-S6XJMYME.js} +3 -3
  40. package/dist/chunk-S6XJMYME.js.map +1 -0
  41. package/dist/{chunk-A7P3O5Z5.js → chunk-V52JOSDF.js} +3 -3
  42. package/dist/chunk-V52JOSDF.js.map +1 -0
  43. package/dist/{chunk-NFVONJUK.js → chunk-W5WNWTQC.js} +455 -211
  44. package/dist/chunk-W5WNWTQC.js.map +1 -0
  45. package/dist/{chunk-WAFHC4DQ.js → chunk-YJ64RI7J.js} +3 -3
  46. package/dist/chunk-YJ64RI7J.js.map +1 -0
  47. package/dist/chunk-YOCGBORV.js +155 -0
  48. package/dist/chunk-YOCGBORV.js.map +1 -0
  49. package/dist/chunk-ZEDXARXW.js +96 -0
  50. package/dist/chunk-ZEDXARXW.js.map +1 -0
  51. package/dist/components.css +2 -0
  52. package/dist/core/index.cjs +33 -24
  53. package/dist/core/index.cjs.map +1 -1
  54. package/dist/core/index.js +2 -2
  55. package/dist/core/styles.css +2 -134
  56. package/dist/data-display/index.cjs +770 -247
  57. package/dist/data-display/index.cjs.map +1 -1
  58. package/dist/data-display/index.d.cts +1 -1
  59. package/dist/data-display/index.d.ts +1 -1
  60. package/dist/data-display/index.js +5 -4
  61. package/dist/data-display/styles.css +2 -4
  62. package/dist/feedback/index.cjs.map +1 -1
  63. package/dist/feedback/index.js +2 -2
  64. package/dist/feedback/styles.css +2 -4
  65. package/dist/forms/index.cjs +1211 -459
  66. package/dist/forms/index.cjs.map +1 -1
  67. package/dist/forms/index.d.cts +1 -1
  68. package/dist/forms/index.d.ts +1 -1
  69. package/dist/forms/index.js +8 -8
  70. package/dist/forms/styles.css +2 -6
  71. package/dist/glass/index.cjs.map +1 -1
  72. package/dist/glass/index.js +2 -2
  73. package/dist/glass/styles.css +2 -81
  74. package/dist/{index-D6fE7w-b.d.cts → index-BGt_hecO.d.cts} +1 -0
  75. package/dist/{index-D6fE7w-b.d.ts → index-BGt_hecO.d.ts} +1 -0
  76. package/dist/{index-DzcWh1Hs.d.cts → index-BtDvpZCf.d.cts} +7 -0
  77. package/dist/{index-DzcWh1Hs.d.ts → index-BtDvpZCf.d.ts} +7 -0
  78. package/dist/{index-Cle6QzQl.d.ts → index-COX1sBUN.d.ts} +27 -3
  79. package/dist/{index-BkRqGNG1.d.ts → index-Cg8MuP7u.d.cts} +40 -13
  80. package/dist/{index-BkRqGNG1.d.cts → index-Cg8MuP7u.d.ts} +40 -13
  81. package/dist/{index-CenuF_P2.d.ts → index-DHkPRTvE.d.cts} +39 -8
  82. package/dist/{index-CenuF_P2.d.cts → index-DHkPRTvE.d.ts} +39 -8
  83. package/dist/{index-TyK-Ldpy.d.cts → index-Du_oht9k.d.cts} +27 -3
  84. package/dist/index.cjs +2481 -917
  85. package/dist/index.cjs.map +1 -1
  86. package/dist/index.d.cts +5 -5
  87. package/dist/index.d.ts +5 -5
  88. package/dist/index.js +19 -19
  89. package/dist/layout/index.cjs.map +1 -1
  90. package/dist/layout/index.js +2 -2
  91. package/dist/layout/styles.css +2 -8
  92. package/dist/navigation/index.cjs +288 -48
  93. package/dist/navigation/index.cjs.map +1 -1
  94. package/dist/navigation/index.d.cts +1 -1
  95. package/dist/navigation/index.d.ts +1 -1
  96. package/dist/navigation/index.js +6 -6
  97. package/dist/navigation/styles.css +2 -4
  98. package/dist/overlays/index.cjs +566 -229
  99. package/dist/overlays/index.cjs.map +1 -1
  100. package/dist/overlays/index.d.cts +1 -1
  101. package/dist/overlays/index.d.ts +1 -1
  102. package/dist/overlays/index.js +7 -7
  103. package/dist/overlays/styles.css +2 -8
  104. package/dist/reset.css +45 -0
  105. package/dist/styles.css +1 -1
  106. package/dist/tokens.css +11 -0
  107. package/dist/typography/index.cjs.map +1 -1
  108. package/dist/typography/index.js +4 -4
  109. package/dist/typography/styles.css +2 -5
  110. package/llms.txt +211 -113
  111. package/package.json +167 -116
  112. package/scripts/postinstall.js +125 -0
  113. package/src/bento/BentoCard.tsx +140 -140
  114. package/src/bento/BentoGrid.tsx +50 -50
  115. package/src/bento/index.ts +2 -2
  116. package/src/bento/tokens.css +46 -46
  117. package/src/buttons/Button.tsx +104 -104
  118. package/src/buttons/ButtonGroup.tsx +43 -43
  119. package/src/buttons/IconButton.tsx +79 -79
  120. package/src/buttons/SplitButton.tsx +186 -86
  121. package/src/buttons/ToggleButton.tsx +157 -157
  122. package/src/buttons/index.ts +5 -5
  123. package/src/buttons/tokens.css +6 -6
  124. package/src/core/ThemeProvider.tsx +135 -123
  125. package/src/core/index.ts +2 -2
  126. package/src/core/tokens.css +134 -134
  127. package/src/data-display/Accordion.tsx +147 -147
  128. package/src/data-display/Avatar.tsx +134 -134
  129. package/src/data-display/Card.tsx +112 -112
  130. package/src/data-display/Chip.tsx +74 -74
  131. package/src/data-display/DataTablePro.tsx +299 -121
  132. package/src/data-display/StatCard.tsx +60 -60
  133. package/src/data-display/Table.tsx +74 -74
  134. package/src/data-display/Timeline.tsx +62 -62
  135. package/src/data-display/TreeView.tsx +243 -104
  136. package/src/data-display/tokens.css +4 -4
  137. package/src/feedback/Alert.tsx +80 -80
  138. package/src/feedback/EmptyState.tsx +45 -45
  139. package/src/feedback/Skeleton.tsx +66 -66
  140. package/src/feedback/Spinner.tsx +65 -65
  141. package/src/feedback/index.ts +5 -5
  142. package/src/feedback/tokens.css +4 -4
  143. package/src/forms/Checkbox.tsx +149 -69
  144. package/src/forms/CheckboxGroup.tsx +76 -29
  145. package/src/forms/Combobox.tsx +172 -28
  146. package/src/forms/DatePicker.tsx +385 -81
  147. package/src/forms/FileUpload.tsx +51 -7
  148. package/src/forms/FormField.tsx +115 -115
  149. package/src/forms/Input.tsx +151 -151
  150. package/src/forms/NumberInput.tsx +34 -20
  151. package/src/forms/PasswordInput.tsx +35 -35
  152. package/src/forms/PinInput.tsx +139 -125
  153. package/src/forms/Radio.tsx +142 -142
  154. package/src/forms/RangeSlider.tsx +237 -111
  155. package/src/forms/SearchInput.tsx +34 -34
  156. package/src/forms/Select.tsx +103 -103
  157. package/src/forms/Slider.tsx +85 -85
  158. package/src/forms/Textarea.tsx +114 -114
  159. package/src/forms/tokens.css +6 -6
  160. package/src/glass/GlassButton.tsx +59 -59
  161. package/src/glass/GlassCard.tsx +71 -71
  162. package/src/glass/index.ts +3 -3
  163. package/src/glass/tokens.css +81 -81
  164. package/src/index.ts +26 -26
  165. package/src/layout/AspectRatio.tsx +39 -39
  166. package/src/layout/Container.tsx +53 -53
  167. package/src/layout/Divider.tsx +61 -61
  168. package/src/layout/Flex.tsx +79 -79
  169. package/src/layout/Grid.tsx +124 -124
  170. package/src/layout/PageLayout.tsx +59 -59
  171. package/src/layout/Section.tsx +47 -47
  172. package/src/layout/Spacer.tsx +30 -30
  173. package/src/layout/Stack.tsx +88 -88
  174. package/src/layout/tokens.css +8 -8
  175. package/src/navigation/Breadcrumb.tsx +73 -73
  176. package/src/navigation/CommandPalette.tsx +142 -142
  177. package/src/navigation/DropdownMenu.tsx +244 -160
  178. package/src/navigation/Pagination.tsx +114 -114
  179. package/src/navigation/Stepper.tsx +93 -93
  180. package/src/navigation/Tabs.tsx +265 -133
  181. package/src/navigation/index.ts +6 -6
  182. package/src/navigation/tokens.css +4 -4
  183. package/src/overlays/AlertDialog.tsx +63 -54
  184. package/src/overlays/BottomSheet.tsx +30 -10
  185. package/src/overlays/ContextMenu.tsx +51 -9
  186. package/src/overlays/Drawer.tsx +160 -145
  187. package/src/overlays/FocusTrap.tsx +122 -49
  188. package/src/overlays/Modal.tsx +296 -219
  189. package/src/overlays/Popover.tsx +55 -25
  190. package/src/overlays/Portal.tsx +23 -23
  191. package/src/overlays/Toast.tsx +175 -137
  192. package/src/overlays/Tooltip.tsx +125 -100
  193. package/src/overlays/tokens.css +8 -8
  194. package/src/registry/components.ts +1368 -0
  195. package/src/styles/components.css +39 -0
  196. package/src/styles/index.css +2 -93
  197. package/src/styles/reset.css +45 -0
  198. package/src/styles/tokens.css +11 -2
  199. package/src/typography/Blockquote.tsx +32 -32
  200. package/src/typography/Code.tsx +89 -89
  201. package/src/typography/Heading.tsx +56 -56
  202. package/src/typography/Kbd.tsx +25 -25
  203. package/src/typography/Label.tsx +47 -47
  204. package/src/typography/Link.tsx +56 -56
  205. package/src/typography/Text.tsx +62 -62
  206. package/src/typography/index.ts +7 -7
  207. package/src/typography/tokens.css +5 -5
  208. package/src/utils/cn.ts +6 -6
  209. package/src/utils/scroll-lock.ts +19 -0
  210. package/src/utils/useControllableState.ts +54 -0
  211. package/ui-contract.json +192 -35
  212. package/dist/chunk-2OXZK6IP.js.map +0 -1
  213. package/dist/chunk-4S6L5V7X.js.map +0 -1
  214. package/dist/chunk-5FZ6ZFII.js.map +0 -1
  215. package/dist/chunk-66VWUJEI.js.map +0 -1
  216. package/dist/chunk-A7P3O5Z5.js.map +0 -1
  217. package/dist/chunk-ATYGDTMK.js.map +0 -1
  218. package/dist/chunk-C4SUXMI3.js.map +0 -1
  219. package/dist/chunk-EU2LPUYP.js.map +0 -1
  220. package/dist/chunk-F5Q7BTMH.js.map +0 -1
  221. package/dist/chunk-GXI2H5XA.js.map +0 -1
  222. package/dist/chunk-H3LCNPMC.js +0 -101
  223. package/dist/chunk-H3LCNPMC.js.map +0 -1
  224. package/dist/chunk-IABPUCAQ.js.map +0 -1
  225. package/dist/chunk-KJRBRTQE.js.map +0 -1
  226. package/dist/chunk-LBUBXUYQ.js +0 -40
  227. package/dist/chunk-LBUBXUYQ.js.map +0 -1
  228. package/dist/chunk-LWFRUJRU.js.map +0 -1
  229. package/dist/chunk-NFVONJUK.js.map +0 -1
  230. package/dist/chunk-PF4ZHGVW.js.map +0 -1
  231. package/dist/chunk-WAFHC4DQ.js.map +0 -1
  232. package/dist/chunk-X76KBH4Y.js +0 -71
  233. package/dist/chunk-X76KBH4Y.js.map +0 -1
package/LICENSE ADDED
@@ -0,0 +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.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @thangnqdev/ui
2
2
 
3
- > **AETHER** — Spatial Optics & Apple Human Interface System for React & Tailwind CSS.
3
+ > **AETHER** — Spatial Optics & Enterprise-Grade Component Infrastructure for React & Tailwind CSS.
4
4
 
5
- An enterprise-grade, Apple HIG & visionOS-inspired architectural UI component system designed for complex SaaS, Fintech, AI Agents, ERP dashboards, and spatial web applications.
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
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/@thangnqdev/ui.svg?style=flat-square)](https://www.npmjs.com/package/@thangnqdev/ui)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE)
@@ -29,7 +29,7 @@ npm install react react-dom
29
29
 
30
30
  ## 🎨 Thiết Lập Nhanh (Quickstart)
31
31
 
32
- ### Cách 1: Sử dụng Standalone CSS (Đơn giản nhất, Đẹp ngay 100%)
32
+ ### Cách 1: Sử dụng Standalone All-In-One CSS
33
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
34
 
35
35
  ```tsx
@@ -41,259 +41,107 @@ import { ThemeProvider, Button, DataTablePro, DatePicker, Combobox } from '@than
41
41
  export default function App() {
42
42
  return (
43
43
  <ThemeProvider defaultTheme="dark">
44
- <Button variant="primary">Apple Keynote Button</Button>
44
+ <Button variant="primary">Primary Action</Button>
45
45
  </ThemeProvider>
46
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
+
50
61
  ---
51
62
 
52
- ### Cách 2: Tích hợp sâu với Tailwind CSS (Tùy chọn)
63
+ ## 🏛️ Kiến Trúc Hệ Thống (Architectural Pillars)
53
64
 
54
- #### A. Tailwind CSS v4
55
- Trong file CSS chính của bạn (`src/index.css`):
56
- ```css
57
- @import "tailwindcss";
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}$$
58
68
 
59
- /* Scan source bundle */
60
- @source "node_modules/@thangnqdev/ui/dist";
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`...).
61
74
 
62
- /* Import design tokens & Apple glass rules */
63
- @import "@thangnqdev/ui/styles.css";
64
- ```
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`.
65
79
 
66
- #### B. Tailwind CSS v3
67
- Trong `tailwind.config.js`:
68
- ```javascript
69
- /** @type {import('tailwindcss').Config} */
70
- module.exports = {
71
- content: [
72
- './src/**/*.{js,ts,jsx,tsx}',
73
- './node_modules/@thangnqdev/ui/dist/**/*.{js,cjs}',
74
- ],
75
- darkMode: 'class',
76
- theme: {
77
- extend: {},
78
- },
79
- plugins: [],
80
- };
81
- ```
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.
82
82
 
83
83
  ---
84
84
 
85
- ## 🛠️ Hướng Dẫn Tùy Biến Toàn Diện (Customization Guide)
86
-
87
- Thư viện được thiết kế để người dùng có thể **tùy biến 100%** theo phong cách thương hiệu riêng qua 4 tầng:
85
+ ## 🛠️ Hướng Dẫn Tùy Biến (Customization Guide)
88
86
 
89
87
  ### 1. Tùy Biến Toàn Cục bằng CSS Variables (Global Theming)
90
- Mặc định, thư viện sử dụng bảng màu **Apple Human Interface (`#0071e3` / `#000000`)**.
91
-
92
- Khi người khác kéo package về dùng, nếu họ muốn **đổi sang màu thương hiệu riêng** (ví dụ Fintech Indigo, Neon Cyberpunk...), họ chỉ cần ghi đè các biến CSS trong file `src/index.css` của họ:
93
88
 
94
89
  ```css
95
- /* Ví dụ: Người dùng tùy biến đổi sang màu thương hiệu của riêng họ */
96
90
  :root {
97
- /* 🔤 Đổi Font chữ chính & Font Monospace */
91
+ /* 🔤 Font chữ & Monospace */
98
92
  --ui-font-sans: 'Plus Jakarta Sans', 'Inter', sans-serif;
99
93
  --ui-font-mono: 'JetBrains Mono', 'Fira Code', monospace;
100
94
 
101
- /* 🎨 Đổi màu chủ đạo sang thương hiệu riêng ( dụ: Tím Indigo) */
95
+ /* 🎨 Màu chủ đạo thương hiệu (Brand Colors) */
102
96
  --ui-primary: #6366f1;
103
97
  --ui-primary-hover: #4f46e5;
104
98
  --ui-primary-glow: rgba(99, 102, 241, 0.35);
105
99
  --ui-accent: #ec4899;
106
100
 
107
- /* 📐 Đổi độ bo góc */
101
+ /* 📐 Bo góc */
108
102
  --ui-radius-lg: 16px;
109
-
110
- /* 📏 Phóng to/thu nhỏ toàn bộ tỷ lệ UI */
111
- font-size: 16px;
112
103
  }
113
104
 
114
- /* Tùy chỉnh riêng cho Dark Mode của người dùng */
115
105
  .dark, [data-theme="dark"] {
116
106
  --ui-primary: #818cf8;
117
- --ui-bg-page: #09090b; /* Nền trang Dark Mode tùy chọn */
118
- --ui-bg-secondary: #18181b; /* Nền Card tùy chọn */
107
+ --ui-bg-page: #09090b;
108
+ --ui-bg-secondary: #18181b;
119
109
  }
120
110
  ```
121
111
 
122
- #### Bảng Biến CSS Tokens Chính:
123
- | CSS Variable | Mô tả | Mặc định Light | Mặc định Dark |
124
- |---|---|---|---|
125
- | `--ui-font-sans` | Font chữ chính | SF Pro Display, Inter | SF Pro Display, Inter |
126
- | `--ui-font-mono` | Font số & code | SF Mono, Consolas | SF Mono, Consolas |
127
- | `--ui-primary` | Màu chính (Primary) | `#0071e3` (Apple Blue) | `#2997ff` (Vision Blue) |
128
- | `--ui-accent` | Màu điểm nhấn (Accent) | `#af52de` (Apple Purple) | `#bf5af2` |
129
- | `--ui-success` | Màu thành công / Pin | `#34c759` (Apple Green) | `#30d158` |
130
- | `--ui-warning` | Màu cảnh báo | `#ff9500` (Apple Orange) | `#ffd60a` |
131
- | `--ui-error` | Màu lỗi | `#ff3b30` (Apple Red) | `#ff453a` |
132
- | `--ui-bg-page` | Màu nền trang | `#f5f5f7` | `#000000` |
133
- | `--ui-bg-surface` | Màu bề mặt kính mờ | `rgba(255,255,255,0.75)` | `rgba(30,30,34,0.72)` |
134
- | `--ui-radius-lg` | Bo góc tiêu chuẩn | `1.125rem` (18px) | `1.125rem` (18px) |
135
-
136
- ---
137
-
138
- ### 2. Tùy Biến Từng Component qua Props
139
- Mọi component đều hỗ trợ đầy đủ các props để thay đổi kích cỡ, màu sắc, hiệu ứng:
140
-
141
- ```tsx
142
- import { Button, GlassBadge, CircularProgress, GlassCard } from '@thangnqdev/ui';
143
-
144
- // Nút bấm kích thước lớn, kiểu trong suốt
145
- <Button variant="outline" size="lg" className="rounded-full">
146
- Khám Phá Thêm
147
- </Button>
148
-
149
- // Thẻ kính mờ với viền phát sáng màu ngọc lam (Cyan Glow)
150
- <GlassCard intensity="acrylic" glow="cyan" radius="xl" padding="lg">
151
- <h3>Card Content</h3>
152
- </GlassCard>
153
-
154
- // Vòng tiến trình màu vàng cảnh báo với hiệu ứng phát sáng
155
- <CircularProgress value={78} size={64} strokeWidth={6} variant="warning" glow />
156
- ```
157
-
158
112
  ---
159
113
 
160
- ### 3. Ghi Đè Trực Tiếp Bằng `className` (Không lo xung đột CSS)
161
- Tất cả component đều được xử lý qua hàm `cn()` (`clsx` + `tailwind-merge`). Class bạn truyền vào sẽ tự động ghi đè class mặc định:
162
-
163
- ```tsx
164
- // Ghi đè cỡ chữ 2xl, font Serif, background gradient
165
- <Button className="text-2xl font-serif bg-gradient-to-r from-purple-500 to-pink-500 hover:opacity-90 shadow-2xl">
166
- Custom Button
167
- </Button>
114
+ ## 🤖 Machine-Readable Contracts for AI Agents
168
115
 
169
- // Ghi đè bảng DataTablePro
170
- <DataTablePro className="border-2 border-purple-500/30 rounded-none font-mono" ... />
171
- ```
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.
172
119
 
173
120
  ---
174
121
 
175
- ### 4. Quản Theme & Chuyển Đổi Dark / Light Mode
176
- Sử dụng hook `useTheme()` để tạo nút chuyển đổi giao diện trong 1 dòng:
177
-
178
- ```tsx
179
- import { ThemeProvider, useTheme, Button } from '@thangnqdev/ui';
122
+ ## 🧪 Quality Gates & Kiểm Thử
180
123
 
181
- function Header() {
182
- const { theme, toggleTheme } = useTheme();
183
-
184
- return (
185
- <Button variant="outline" onClick={toggleTheme}>
186
- {theme === 'dark' ? '☀️ Chuyển sang Light Mode' : '🌙 Chuyển sang Dark Mode'}
187
- </Button>
188
- );
189
- }
190
-
191
- export default function App() {
192
- return (
193
- <ThemeProvider defaultTheme="dark" storageKey="my-app-theme">
194
- <Header />
195
- </ThemeProvider>
196
- );
197
- }
198
- ```
199
-
200
- ---
124
+ ```bash
125
+ # Kiểm tra strict TypeScript
126
+ npm run typecheck
201
127
 
202
- ### 5. Tích Hợp với React Hook Form & Zod
203
- Các component Form hỗ trợ cả **Controlled** và **Uncontrolled** mode:
128
+ # Chạy toàn bộ 115+ test cases (A11y, Axe, Invariant, SSR, Controllable State)
129
+ npm test
204
130
 
205
- ```tsx
206
- import { useForm, Controller } from 'react-hook-form';
207
- import { DatePicker, Combobox, NumberInput, Switch, Button } from '@thangnqdev/ui';
131
+ # Kiểm tra tính bất biến SSOT
132
+ npm run test:ssot
208
133
 
209
- export function RegistrationForm() {
210
- const { control, handleSubmit } = useForm({
211
- defaultValues: {
212
- birthDate: new Date(),
213
- role: 'developer',
214
- experienceYears: 5,
215
- notifications: true,
216
- },
217
- });
134
+ # Kiểm tra WAI-ARIA & Axe automated scans
135
+ npm run test:a11y
218
136
 
219
- const onSubmit = (data) => console.log('Form Submit:', data);
137
+ # Kiểm tra Server-Side Rendering
138
+ npm run test:ssr
220
139
 
221
- return (
222
- <form onSubmit={handleSubmit(onSubmit)} className="space-y-4 max-w-md">
223
- <Controller
224
- name="birthDate"
225
- control={control}
226
- render={({ field }) => <DatePicker value={field.value} onChange={field.onChange} />}
227
- />
228
-
229
- <Controller
230
- name="role"
231
- control={control}
232
- render={({ field }) => (
233
- <Combobox
234
- value={field.value}
235
- onChange={field.onChange}
236
- options={[
237
- { value: 'developer', label: 'Software Engineer' },
238
- { value: 'designer', label: 'UI/UX Designer' },
239
- ]}
240
- />
241
- )}
242
- />
243
-
244
- <Controller
245
- name="experienceYears"
246
- control={control}
247
- render={({ field }) => <NumberInput value={field.value} onChange={field.onChange} min={1} max={30} />}
248
- />
249
-
250
- <Button type="submit" variant="primary">Lưu Thay Đổi</Button>
251
- </form>
252
- );
253
- }
140
+ # Quy trình Prepack Gate trước khi phát hành
141
+ npm run prepack
254
142
  ```
255
143
 
256
144
  ---
257
145
 
258
- ## 🚀 Danh Mục 48+ Components Chi Tiết
259
-
260
- ### 1. Nhóm Form & Nhập Liệu Phức Tạp (`@thangnqdev/ui/forms`)
261
- * **`DatePicker` & `DateRangePicker`**: Lịch popover kính mờ, chọn ngày đơn lẻ hoặc khoảng ngày (Date Range).
262
- * **`TimePicker`**: Bộ chọn giờ/phút định dạng 24h & 12h.
263
- * **`Combobox` & `MultiSelect`**: Dropdown tìm kiếm gõ để lọc (search-as-you-type) & chọn nhiều tag.
264
- * **`FileUpload` & Dropzone**: Vùng kéo thả file với hiệu ứng bắt sáng và xem trước ảnh.
265
- * **`NumberInput` & `CurrencyInput`**: Input số tăng giảm `+ / -` và format tiền tệ tự động.
266
- * **`MaskedInput`**: Input định dạng số điện thoại `(###) ###-####`, thẻ tín dụng, CCCD.
267
- * **Cơ bản**: `FormField`, `Input`, `SearchInput`, `PasswordInput`, `Textarea`, `Select`, `Checkbox`, `Radio`, `Switch`, `Slider`, `RangeSlider`, `PinInput`.
268
-
269
- ### 2. Nhóm Xử Lý Dữ Liệu Lớn (`@thangnqdev/ui/data-display`)
270
- * **`DataTablePro`**: Bảng dữ liệu cấp doanh nghiệp với Live Search toàn bộ cột, Multi-Column Sort, Row Selection, Phân trang và Export CSV.
271
- * **`TreeView`**: Cây thư mục phân cấp chuẩn macOS Finder.
272
- * **`Carousel`**: Trình chiếu trượt ngang tự động chạy với hiệu ứng Apple Keynote.
273
- * **Cơ bản**: `Card`, `Table`, `Avatar`, `Accordion`, `Chip`, `StatCard`, `Timeline`.
274
-
275
- ### 3. Nhóm Điều Hướng & Overlays (`@thangnqdev/ui/overlays` & `@thangnqdev/ui/navigation`)
276
- * **`BottomSheet`**: Tấm trượt đáy màn hình tối ưu cho Mobile.
277
- * **`ContextMenu`**: Menu chuột phải Desktop với phím tắt (`⌘C`, `⌘S`).
278
- * **`HoverCard`**: Card xem trước thông tin khi rê chuột.
279
- * **Cơ bản**: `Modal`, `AlertDialog`, `Drawer`, `Tooltip`, `Popover`, `Toast`, `Tabs`, `Breadcrumb`, `Pagination`, `Stepper`, `CommandPalette`.
280
-
281
- ### 4. Nhóm Phản Hồi & Vật Liệu Apple (`@thangnqdev/ui/glass` & `@thangnqdev/ui/feedback`)
282
- * **`GlassCard` & `GlassButton`**: Kính mờ Acrylic 28px blur với 1px viền phản quang (Specular Hairline).
283
- * **`GlassBadge`**: Huy hiệu SF Pro capsule pill với đèn LED phát sáng xung nhịp.
284
- * **`CircularProgress`**: Vòng tiến trình Apple Watch Activity gradient rings.
285
- * **`ScrollArea`**: Thanh cuộn capsule tự ẩn chuẩn Apple.
286
- * **`BentoGrid` & `BentoCard`**: Lưới bento Apple Keynote editorial.
287
-
288
- ---
289
-
290
- ## 🤖 AI Machine Context Manifests
291
-
292
- Thư viện tích hợp sẵn các manifest định dạng chuẩn AI coding assistants (Cursor, Antigravity, Claude Code):
293
- - `llms.txt`: Đặc tả đầy đủ token, API component và triết lý thiết kế.
294
- - `ui-contract.json`: Schema JSON nghiêm ngặt để sinh mã tự động không bị lệch kiểu.
295
-
296
- ---
297
-
298
146
  ## 📄 License
299
147
  MIT © 2026 AETHER Spatial UI
package/bin/cli.js ADDED
@@ -0,0 +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 +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';\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
+ {"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,4 +1,4 @@
1
- export { BentoCard, BentoGrid } from '../chunk-C4SUXMI3.js';
2
- import '../chunk-4S6L5V7X.js';
1
+ export { BentoCard, BentoGrid } from '../chunk-S6XJMYME.js';
2
+ import '../chunk-2YJBW4E2.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map