@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.
- package/LICENSE +21 -21
- package/README.md +144 -142
- package/bin/cli.js +125 -125
- package/dist/bento/index.cjs.map +1 -1
- package/dist/bento/index.js +2 -2
- package/dist/buttons/index.cjs.map +1 -1
- package/dist/buttons/index.js +3 -3
- package/dist/{chunk-EXFR2BFJ.js → chunk-2ANJFOIU.js} +38 -36
- package/dist/chunk-2ANJFOIU.js.map +1 -0
- package/dist/{chunk-77KTYOMQ.js → chunk-2OXZK6IP.js} +3 -3
- package/dist/chunk-2OXZK6IP.js.map +1 -0
- package/dist/{chunk-4CRFNALF.js → chunk-4GNFT2ZJ.js} +7 -7
- package/dist/chunk-4GNFT2ZJ.js.map +1 -0
- package/dist/{chunk-2YJBW4E2.js → chunk-4S6L5V7X.js} +2 -2
- package/dist/chunk-4S6L5V7X.js.map +1 -0
- package/dist/{chunk-I2FQBMVW.js → chunk-66VWUJEI.js} +3 -3
- package/dist/chunk-66VWUJEI.js.map +1 -0
- package/dist/{chunk-YOCGBORV.js → chunk-7NMB2Y64.js} +4 -4
- package/dist/chunk-7NMB2Y64.js.map +1 -0
- package/dist/{chunk-V52JOSDF.js → chunk-A7P3O5Z5.js} +3 -3
- package/dist/chunk-A7P3O5Z5.js.map +1 -0
- package/dist/{chunk-ME4XILG5.js → chunk-ATYGDTMK.js} +5 -5
- package/dist/chunk-ATYGDTMK.js.map +1 -0
- package/dist/{chunk-S6XJMYME.js → chunk-C4SUXMI3.js} +3 -3
- package/dist/chunk-C4SUXMI3.js.map +1 -0
- package/dist/{chunk-I5O2WCGF.js → chunk-EU2LPUYP.js} +3 -3
- package/dist/chunk-EU2LPUYP.js.map +1 -0
- package/dist/{chunk-D7FB3TCA.js → chunk-GXI2H5XA.js} +3 -3
- package/dist/chunk-GXI2H5XA.js.map +1 -0
- package/dist/{chunk-ADO3SVUA.js → chunk-IABPUCAQ.js} +2 -2
- package/dist/chunk-IABPUCAQ.js.map +1 -0
- package/dist/{chunk-PC5SZFZC.js → chunk-JOKEKOP3.js} +8 -8
- package/dist/chunk-JOKEKOP3.js.map +1 -0
- package/dist/{chunk-GXWB6BSY.js → chunk-KUQWUTZA.js} +4 -4
- package/dist/chunk-KUQWUTZA.js.map +1 -0
- package/dist/{chunk-ZEDXARXW.js → chunk-U3J4UPV3.js} +2 -2
- package/dist/chunk-U3J4UPV3.js.map +1 -0
- package/dist/{chunk-DSEL7ELZ.js → chunk-VE2PNSDQ.js} +4 -4
- package/dist/chunk-VE2PNSDQ.js.map +1 -0
- package/dist/{chunk-YJ64RI7J.js → chunk-WAFHC4DQ.js} +3 -3
- package/dist/chunk-WAFHC4DQ.js.map +1 -0
- package/dist/{chunk-W5WNWTQC.js → chunk-YJ67WYVW.js} +5 -5
- package/dist/chunk-YJ67WYVW.js.map +1 -0
- package/dist/{chunk-4MS6ZHFQ.js → chunk-Z427NPMU.js} +7 -7
- package/dist/chunk-Z427NPMU.js.map +1 -0
- package/dist/core/index.cjs +34 -32
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/data-display/index.cjs.map +1 -1
- package/dist/data-display/index.js +5 -5
- package/dist/feedback/index.cjs.map +1 -1
- package/dist/feedback/index.js +2 -2
- package/dist/forms/index.cjs.map +1 -1
- package/dist/forms/index.js +8 -8
- package/dist/glass/index.cjs.map +1 -1
- package/dist/glass/index.js +2 -2
- package/dist/index.cjs +34 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +19 -19
- package/dist/layout/index.cjs.map +1 -1
- package/dist/layout/index.js +2 -2
- package/dist/navigation/index.cjs.map +1 -1
- package/dist/navigation/index.js +6 -6
- package/dist/overlays/index.cjs.map +1 -1
- package/dist/overlays/index.js +7 -7
- package/dist/reset.css +45 -45
- package/dist/tokens.css +11 -11
- package/dist/typography/index.cjs.map +1 -1
- package/dist/typography/index.js +4 -4
- package/llms.txt +3 -3
- package/package.json +165 -165
- package/scripts/postinstall.js +125 -125
- package/src/bento/BentoCard.tsx +140 -140
- package/src/bento/BentoGrid.tsx +50 -50
- package/src/bento/index.ts +2 -2
- package/src/bento/tokens.css +46 -46
- package/src/buttons/Button.tsx +104 -104
- package/src/buttons/ButtonGroup.tsx +43 -43
- package/src/buttons/IconButton.tsx +79 -79
- package/src/buttons/SplitButton.tsx +186 -186
- package/src/buttons/ToggleButton.tsx +157 -157
- package/src/buttons/index.ts +5 -5
- package/src/buttons/tokens.css +6 -6
- package/src/core/ThemeProvider.tsx +124 -106
- package/src/core/index.ts +2 -2
- package/src/core/tokens.css +134 -134
- package/src/data-display/Accordion.tsx +147 -147
- package/src/data-display/Avatar.tsx +134 -134
- package/src/data-display/Card.tsx +112 -112
- package/src/data-display/Chip.tsx +74 -74
- package/src/data-display/DataTablePro.tsx +534 -534
- package/src/data-display/StatCard.tsx +60 -60
- package/src/data-display/Table.tsx +74 -74
- package/src/data-display/Timeline.tsx +62 -62
- package/src/data-display/TreeView.tsx +279 -279
- package/src/data-display/tokens.css +4 -4
- package/src/feedback/Alert.tsx +80 -80
- package/src/feedback/EmptyState.tsx +45 -45
- package/src/feedback/Skeleton.tsx +66 -66
- package/src/feedback/Spinner.tsx +65 -65
- package/src/feedback/index.ts +5 -5
- package/src/feedback/tokens.css +4 -4
- package/src/forms/Checkbox.tsx +149 -149
- package/src/forms/CheckboxGroup.tsx +76 -76
- package/src/forms/Combobox.tsx +512 -512
- package/src/forms/DatePicker.tsx +784 -784
- package/src/forms/FileUpload.tsx +266 -266
- package/src/forms/FormField.tsx +115 -115
- package/src/forms/Input.tsx +151 -151
- package/src/forms/NumberInput.tsx +262 -262
- package/src/forms/PasswordInput.tsx +35 -35
- package/src/forms/PinInput.tsx +139 -139
- package/src/forms/Radio.tsx +142 -142
- package/src/forms/RangeSlider.tsx +237 -237
- package/src/forms/SearchInput.tsx +34 -34
- package/src/forms/Select.tsx +103 -103
- package/src/forms/Slider.tsx +85 -85
- package/src/forms/Textarea.tsx +114 -114
- package/src/forms/tokens.css +6 -6
- package/src/glass/GlassButton.tsx +59 -59
- package/src/glass/GlassCard.tsx +71 -71
- package/src/glass/index.ts +3 -3
- package/src/glass/tokens.css +81 -81
- package/src/index.ts +26 -26
- package/src/layout/AspectRatio.tsx +39 -39
- package/src/layout/Container.tsx +53 -53
- package/src/layout/Divider.tsx +61 -61
- package/src/layout/Flex.tsx +79 -79
- package/src/layout/Grid.tsx +124 -124
- package/src/layout/PageLayout.tsx +59 -59
- package/src/layout/Section.tsx +47 -47
- package/src/layout/Spacer.tsx +30 -30
- package/src/layout/Stack.tsx +88 -88
- package/src/layout/tokens.css +8 -8
- package/src/navigation/Breadcrumb.tsx +73 -73
- package/src/navigation/CommandPalette.tsx +142 -142
- package/src/navigation/DropdownMenu.tsx +244 -244
- package/src/navigation/Pagination.tsx +114 -114
- package/src/navigation/Stepper.tsx +93 -93
- package/src/navigation/Tabs.tsx +265 -265
- package/src/navigation/index.ts +6 -6
- package/src/navigation/tokens.css +4 -4
- package/src/overlays/AlertDialog.tsx +63 -63
- package/src/overlays/BottomSheet.tsx +143 -143
- package/src/overlays/ContextMenu.tsx +161 -161
- package/src/overlays/Drawer.tsx +160 -160
- package/src/overlays/FocusTrap.tsx +122 -122
- package/src/overlays/Modal.tsx +296 -296
- package/src/overlays/Popover.tsx +156 -156
- package/src/overlays/Portal.tsx +23 -23
- package/src/overlays/Toast.tsx +175 -175
- package/src/overlays/Tooltip.tsx +125 -125
- package/src/overlays/tokens.css +8 -8
- package/src/registry/components.ts +1368 -1368
- package/src/styles/components.css +39 -39
- package/src/styles/index.css +5 -5
- package/src/styles/reset.css +45 -45
- package/src/styles/tokens.css +11 -11
- package/src/typography/Blockquote.tsx +32 -32
- package/src/typography/Code.tsx +89 -89
- package/src/typography/Heading.tsx +56 -56
- package/src/typography/Kbd.tsx +25 -25
- package/src/typography/Label.tsx +47 -47
- package/src/typography/Link.tsx +56 -56
- package/src/typography/Text.tsx +62 -62
- package/src/typography/index.ts +7 -7
- package/src/typography/tokens.css +5 -5
- package/src/utils/cn.ts +6 -6
- package/src/utils/scroll-lock.ts +19 -19
- package/src/utils/useControllableState.ts +54 -54
- package/ui-contract.json +1 -1
- package/dist/chunk-2YJBW4E2.js.map +0 -1
- package/dist/chunk-4CRFNALF.js.map +0 -1
- package/dist/chunk-4MS6ZHFQ.js.map +0 -1
- package/dist/chunk-77KTYOMQ.js.map +0 -1
- package/dist/chunk-ADO3SVUA.js.map +0 -1
- package/dist/chunk-D7FB3TCA.js.map +0 -1
- package/dist/chunk-DSEL7ELZ.js.map +0 -1
- package/dist/chunk-EXFR2BFJ.js.map +0 -1
- package/dist/chunk-GXWB6BSY.js.map +0 -1
- package/dist/chunk-I2FQBMVW.js.map +0 -1
- package/dist/chunk-I5O2WCGF.js.map +0 -1
- package/dist/chunk-ME4XILG5.js.map +0 -1
- package/dist/chunk-PC5SZFZC.js.map +0 -1
- package/dist/chunk-S6XJMYME.js.map +0 -1
- package/dist/chunk-V52JOSDF.js.map +0 -1
- package/dist/chunk-W5WNWTQC.js.map +0 -1
- package/dist/chunk-YJ64RI7J.js.map +0 -1
- package/dist/chunk-YOCGBORV.js.map +0 -1
- 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
|
-
[](https://www.npmjs.com/package/@thangnqdev/ui)
|
|
8
|
-
[](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
|
+
[](https://www.npmjs.com/package/@thangnqdev/ui)
|
|
8
|
+
[](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="
|
|
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
|
-
|
|
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ì vậy có 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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
#
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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` 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.
|
|
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
|
+
}
|
package/dist/bento/index.cjs.map
CHANGED
|
@@ -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"]}
|
package/dist/bento/index.js
CHANGED