basuicn 0.1.1 → 0.1.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/README.md CHANGED
@@ -1,146 +1,96 @@
1
- # basuicn
2
-
3
- Bộ component UI cho React, phân phối qua CLI — copy trực tiếp vào dự án của bạn, không cần cài như package dependency (tương tự shadcn/ui).
4
-
5
- ---
6
-
7
- ## Yêu cầu
8
-
9
- - Node.js 18+
10
- - Dự án React + Vite + TypeScript
11
-
12
- ---
13
-
14
- ## Bắt đầu nhanh
15
-
16
- ### 1. Khởi tạo dự án
17
-
18
- Đứng tại thư mục gốc dự án của bạn, chạy:
19
-
20
- ```bash
21
- npx basuicn init
22
- ```
23
-
24
- Lệnh này tự động thực hiện:
25
-
26
- | Bước | Nội dung |
27
- |------|----------|
28
- | Cài dev packages | `tailwindcss`, `@tailwindcss/vite`, `@vitejs/plugin-react`, `vite-plugin-babel`, `babel-plugin-react-compiler`, `@types/node` |
29
- | Cài runtime packages | `@base-ui/react`, `tailwind-variants`, `clsx`, `tailwind-merge`, `tailwindcss-animate` |
30
- | Tạo / cập nhật `vite.config.ts` | Thêm plugin Tailwind, React, React Compiler + alias `@`, `@lib`, `@components`, `@assets`, `@pages`, `@styles` |
31
- | Cập nhật `tsconfig.json` | Thêm `baseUrl` + `paths` tương ứng với alias trên |
32
- | Setup Tailwind CSS | Thêm `@import "tailwindcss";` vào `src/index.css` (tạo mới nếu chưa có) |
33
- | Cài core utilities | `clsx`, `tailwind-merge` + tạo `src/lib/utils/cn.ts` |
34
-
35
- > Nếu `vite.config.ts` hoặc `tsconfig.json` đã tồn tại và đã có cấu hình, CLI sẽ bỏ qua bước đó — không ghi đè.
36
-
37
- **Kết quả `vite.config.ts` sau init:**
38
-
39
- ```ts
40
- import { defineConfig } from 'vite';
41
- import tailwindcss from '@tailwindcss/vite';
42
- import react from '@vitejs/plugin-react';
43
- import babel from 'vite-plugin-babel';
44
- import { reactCompilerPreset } from 'babel-plugin-react-compiler';
45
- import path from 'path';
46
-
47
- export default defineConfig({
48
- plugins: [
49
- tailwindcss(),
50
- react(),
51
- babel({ presets: [reactCompilerPreset()] }),
52
- ],
53
- resolve: {
54
- alias: {
55
- '@': path.resolve(__dirname, './src'),
56
- '@lib': path.resolve(__dirname, './src/lib'),
57
- '@components': path.resolve(__dirname, './src/components'),
58
- '@assets': path.resolve(__dirname, './src/assets'),
59
- '@pages': path.resolve(__dirname, './src/pages'),
60
- '@styles': path.resolve(__dirname, './src/styles'),
61
- },
62
- },
63
- });
64
- ```
65
-
66
- ---
67
-
68
- ### 2. Thêm component
69
-
70
- ```bash
71
- npx basuicn add button
72
- npx basuicn add button input switch # nhiều component cùng lúc
73
- npx basuicn add button --force # ghi đè nếu đã tồn tại
74
- ```
75
-
76
- Component được copy thẳng vào `src/components/ui/<name>/`. Các component phụ thuộc lẫn nhau sẽ tự động được kéo theo.
77
-
78
- ---
79
-
80
- ### 3. Xóa component
81
-
82
- ```bash
83
- npx basuicn remove button
84
- ```
85
-
86
- ---
87
-
88
- ### 4. Liệt kê tất cả component
89
-
90
- ```bash
91
- npx basuicn list
92
- ```
93
-
94
- ---
95
-
96
- ### 5. Hướng dẫn cấu hình Tailwind theme
97
-
98
- ```bash
99
- npx basuicn tailwind
100
- ```
101
-
102
- ---
103
-
104
- ## Tùy chọn
105
-
106
- | Flag | Mô tả |
107
- |------|-------|
108
- | `--local` | Dùng `registry.json` cục bộ thay vì tải từ remote |
109
- | `--force` | Ghi đè file đã tồn tại khi `add` |
110
-
111
- ---
112
-
113
- ## Dành cho maintainer
114
-
115
- ### Cập nhật registry (sau khi thêm/sửa component)
116
-
117
- ```bash
118
- npm run registry:build
119
- ```
120
-
121
- Sau đó commit + push lên GitHub để người dùng nhận được bản mới nhất.
122
-
123
- ### Build CLI
124
-
125
- ```bash
126
- npm run build:cli
127
- ```
128
-
129
- Output: `dist/ui-cli.js`
130
-
131
- ### Phát hành lên NPM
132
-
133
- ```bash
134
- npm login
135
- npm publish
136
- ```
137
-
138
- > Nếu tên package bị trùng, đổi `name` trong `package.json` trước khi publish.
139
-
140
- ---
141
-
142
- ## Cơ chế hoạt động
143
-
144
- - **Remote mode (mặc định):** Tải `registry.json` từ `https://raw.githubusercontent.com/huy14032003/ui-component/main/registry.json`
145
- - **Local mode (`--local`):** Đọc `registry.json` ngay tại thư mục hiện tại
146
- - Registry chứa source code + danh sách npm dependencies của từng component — CLI đọc rồi copy/install vào dự án target
1
+ # basuicn — UI Component CLI
2
+
3
+ Bộ sưu tập component React hiện đại, được phân phối trực tiếp vào dự án của bạn thông qua CLI. Không cần cài đặt dependencies cồng kềnh, bạn hoàn toàn kiểm soát mã nguồn của mình (tương tự shadcn/ui).
4
+
5
+ ---
6
+
7
+ ## 🚀 Yêu cầu hệ thống
8
+
9
+ - **Node.js**: Phiên bản 18 trở lên.
10
+ - **Framework**: React + Vite + TypeScript.
11
+ - **Styling**: Tailwind CSS v4 (hoặc v3).
12
+
13
+ ---
14
+
15
+ ## 📦 Bắt đầu nhanh
16
+
17
+ ### 1. Khởi tạo dự án
18
+
19
+ Di chuyển đến thư mục gốc của dự án React và chạy lệnh:
20
+
21
+ ```bash
22
+ npx basuicn init
23
+ ```
24
+
25
+ Lệnh này sẽ thực hiện một chuỗi các thao tác tự động:
26
+ - **Cài đặt thư viện**: `@base-ui/react`, `tailwind-variants`, `clsx`, `tailwind-merge`, `lucide-react`, ...
27
+ - **Cấu hình Vite**: Tự động thêm alias `@/`, `@components/`, `@lib/`, ... vào `vite.config.ts`.
28
+ - **Cấu hình TypeScript**: Thêm `paths` tương ứng vào `tsconfig.json`.
29
+ - **Core Components**: Copy các file tiện ích như `cn.ts`, `ThemeProvider.tsx`, `themes.ts` và biến CSS theme vào dự án.
30
+ - **Patching Entry**: Tự động bọc ứng dụng của bạn trong `<ThemeProvider>` tại file `src/main.tsx`.
31
+
32
+ ---
33
+
34
+ ### 2. Thêm Component
35
+
36
+ Sử dụng lệnh `add` để tải component bạn cần:
37
+
38
+ ```bash
39
+ npx basuicn add button
40
+ npx basuicn add button input switch # Thêm nhiều component cùng lúc
41
+ npx basuicn add toast # Tự động thêm <Toaster /> vào main.tsx
42
+ ```
43
+
44
+ > **Lưu ý**: CLI sẽ tự động nhận diện và tải về các component phụ thuộc (ví dụ `add select` sẽ tự tải thêm `popover`).
45
+
46
+ ---
47
+
48
+ ### 3. Cập nhật & So sánh (Update & Diff)
49
+
50
+ Nếu có phiên bản mới của component từ thư viện gốc, bạn có thể kiểm tra và cập nhật:
51
+
52
+ ```bash
53
+ npx basuicn diff button # Xem sự khác biệt giữa code local và bản gốc trên registry
54
+ npx basuicn update button # Ghi đè phiên bản cục bộ bằng bản mới nhất
55
+ ```
56
+
57
+ ---
58
+
59
+ ### 4. Kiểm tra sức khỏe dự án (Doctor)
60
+
61
+ Nếu bạn gặp lỗi về import hoặc cấu hình, hãy chạy lệnh sau để CLI kiểm tra và gợi ý cách sửa lỗi:
62
+
63
+ ```bash\nnpx basuicn doctor
64
+ ```
65
+
66
+ ---
67
+
68
+ ## 🛠 Danh sách các lệnh (Commands)
69
+
70
+ | Lệnh | Mô tả |
71
+ |------|-------|
72
+ | `init` | Thiết lập môi trường dự án ban đầu. |
73
+ | `add <name>` | Thêm component vào thư mục `src/components/ui/`. |
74
+ | `update <name>` | Cập nhật component lên phiên bản mới nhất. |
75
+ | `diff <name>` | So sánh code hiện tại với bản gốc. |
76
+ | `remove <name>` | Xóa component khỏi dự án. |
77
+ | `list` | Xem danh sách tất cả các component có sẵn. |
78
+ | `doctor` | Kiểm tra cấu hình và các file core của dự án. |
79
+
80
+ ---
81
+
82
+ ## 📂 Tùy chọn (Options)
83
+
84
+ - `--force`: Ghi đè các file đã tồn tại nếu có xung đột khi `add` hoặc `init`.
85
+ - `--local`: Chỉ dành cho phát triển — Đọc `registry.json` từ thư mục cục bộ thay vì từ GitHub.
86
+
87
+ ---
88
+
89
+ ## 👨‍💻 Dành cho Maintainers
90
+
91
+ Nếu bạn muốn đóng góp hoặc tự xây dựng registry riêng:
92
+
93
+ 1. **Biên dịch CLI**: `npm run build:cli`
94
+ 2. **Đồng bộ Theme**: `npm run theme:sync` (Tạo file CSS theme từ `themes.ts`).
95
+ 3. **Xây dựng Registry**: `npm run registry:build` (Gom toàn bộ code component vào `registry.json`).
96
+ 4. **Publish**: `npm publish`
package/README_CLI.md CHANGED
@@ -1,51 +1,44 @@
1
- # CUS-UI CLI (Remote/NPM Ready)
1
+ # basuicn CLI Documentation
2
2
 
3
- Bộ công cụ CLI giúp bạn cài đặt các components từ thư viện UI này vào bất kỳ dự án React nào khác thông qua `npx`.
3
+ Bộ công cụ dòng lệnh mạnh mẽ để quản các component UI. Tương thích hoàn toàn với dự án React + Vite + TypeScript + Tailwind CSS.
4
4
 
5
- ## 🚀 Cách sử dụng từ dự án khác
5
+ ## 🚀 Cài đặt & Khởi tạo
6
6
 
7
- Bạn không cần cài đặt cả, chỉ cần đứng tại thư mục dự án của bạn gõ:
7
+ Để bắt đầu sử dụng `basuicn` trong dự án của bạn, hãy chạy:
8
8
 
9
- ### 1. Khởi tạo dự án (Lần đầu)
10
9
  ```bash
11
10
  npx basuicn init
12
11
  ```
13
- Lệnh này sẽ tự động cài các gói cần thiết (`clsx`, `tailwind-merge`) và tạo file `src/lib/utils/cn.ts`.
14
12
 
15
- ### 2. Thêm Component
16
- ```bash
17
- npx basuicn add button input switch
18
- ```
19
- *Lưu ý: CLI sẽ tự động nhận diện và tải thêm các component phụ thuộc nếu cần.*
13
+ Lệnh này sẽ chuẩn bị mọi thứ cần thiết: dependencies, path aliases, Tailwind v4 configuration, và `ThemeProvider` để quản lý giao diện sáng/tối.
20
14
 
21
- ### 3. Cấu hình Tailwind
22
- Chạy lệnh sau để nhận hướng dẫn copy-paste cấu hình theme:
23
- ```bash
24
- npx basuicn tailwind
25
- ```
15
+ ## 🛠 Lệnh thông dụng
26
16
 
27
- ---
28
-
29
- ## 🛠 Cách để tự bạn quản lý và phát hành
30
-
31
- ### 1. Cập nhật Registry (Khi thêm component mới)
17
+ ### Thêm Component
32
18
  ```bash
33
- npm run registry:build
19
+ npx basuicn add <component-name>
34
20
  ```
35
- Sau đó hãy `git commit` `git push` lên GitHub để CLI trên máy người dùng có thể thấy update mới.
21
+ dụ: `npx basuicn add button input`.
22
+
23
+ ### Quản lý phiên bản
24
+ - **So sánh**: `npx basuicn diff <component-name>` để xem các thay đổi bạn đã sửa so với bản gốc.
25
+ - **Cập nhật**: `npx basuicn update <component-name>` để lấy bản mới nhất từ remote registry.
36
26
 
37
- ### 2. Biên dịch CLI
27
+ ### Kiểm tra lỗi cấu hình
28
+ Nếu component không hiển thị đúng style hoặc lỗi import, hãy dùng:
38
29
  ```bash
39
- npm run build:cli
30
+ npx basuicn doctor
40
31
  ```
41
32
 
42
- ### 3. Phát hành lên NPM
43
- Để mọi người có thể gõ `npx basuicn`, bạn cần đưa nó lên NPM:
44
- 1. Đăng nhập: `npm login`
45
- 2. Phát hành: `npm publish` (Nếu tên `basuicn` đã bị trùng trên NPM, hãy đổi tên trong `package.json`).
33
+ ## ⚙️ chế hoạt động
46
34
 
47
- ---
35
+ CLI hoạt động dựa trên một file `registry.json` phân phối từ GitHub. Khi bạn thêm một component:
36
+ 1. CLI tải Metadata của component đó.
37
+ 2. Tự động cài đặt các thư viện `npm` tương ứng.
38
+ 3. Kiểm tra và tải các component phụ thuộc nội bộ.
39
+ 4. Copy source code trực tiếp vào thư mục dự án của bạn.
40
+ 5. (Tùy chọn) Thêm code khởi tạo vào `src/main.tsx` nếu component cần (ví dụ: `Toaster`).
48
41
 
49
- ## 📂 chế hoạt động
50
- - **Local Mode**: Nếu bạn chạy `npx cus-ui add --local`, nó sẽ tìm file `registry.json` ngay tại thư mục hiện tại.
51
- - **Remote Mode (Mặc định)**: CLI sẽ tải dữ liệu trực tiếp từ: `https://raw.githubusercontent.com/huy14032003/ui-component/main/registry.json`.
42
+ ## 🛡 Bảo mật & Tin cậy
43
+ - Không phụ thuộc vào runtime sau khi cài đặt.
44
+ - nguồn mở 100%, bạn thể thoải mái tùy chỉnh sau khi copy vào dự án.
package/dist/ui-cli.cjs CHANGED
@@ -400,6 +400,114 @@ var main = async () => {
400
400
  console.log("// See README_CLI.md for full theme config");
401
401
  break;
402
402
  }
403
+ case "update": {
404
+ if (componentNames.length === 0) {
405
+ error("Usage: npx basuicn update <component-name> [...]");
406
+ return;
407
+ }
408
+ for (const name of componentNames) {
409
+ log(`Updating: ${name}...`);
410
+ addComponent(name, registry, cwd, { force: true });
411
+ }
412
+ log("Update complete.");
413
+ break;
414
+ }
415
+ case "diff": {
416
+ if (componentNames.length === 0) {
417
+ error("Usage: npx basuicn diff <component-name>");
418
+ return;
419
+ }
420
+ for (const name of componentNames) {
421
+ const component = registry.components[name];
422
+ if (!component) {
423
+ error(`Component "${name}" not found. Run 'list' to see available components.`);
424
+ continue;
425
+ }
426
+ let hasDiff = false;
427
+ console.log(`
428
+ [diff] ${name}`);
429
+ for (const file of component.files) {
430
+ const targetPath = import_path.default.join(cwd, file.path);
431
+ if (!import_fs.default.existsSync(targetPath)) {
432
+ console.log(` + [new file] ${file.path}`);
433
+ hasDiff = true;
434
+ continue;
435
+ }
436
+ const localContent = import_fs.default.readFileSync(targetPath, "utf-8");
437
+ if (localContent === file.content) continue;
438
+ hasDiff = true;
439
+ console.log(`
440
+ ~ ${file.path}`);
441
+ const localLines = localContent.split("\n");
442
+ const remoteLines = file.content.split("\n");
443
+ const maxLen = Math.max(localLines.length, remoteLines.length);
444
+ let shownLines = 0;
445
+ for (let i = 0; i < maxLen; i++) {
446
+ if (localLines[i] !== remoteLines[i]) {
447
+ if (localLines[i] !== void 0) console.log(` - ${localLines[i]}`);
448
+ if (remoteLines[i] !== void 0) console.log(` + ${remoteLines[i]}`);
449
+ shownLines++;
450
+ if (shownLines >= 20) {
451
+ const remaining = maxLen - i - 1;
452
+ if (remaining > 0) console.log(` ... and ${remaining} more lines`);
453
+ break;
454
+ }
455
+ }
456
+ }
457
+ }
458
+ if (!hasDiff) log(`${name}: already up to date.`);
459
+ }
460
+ break;
461
+ }
462
+ case "doctor": {
463
+ log("Running project health check...\n");
464
+ let issues = 0;
465
+ const check = (ok, msg, fix) => {
466
+ const icon = ok ? " \u2713" : " \u2717";
467
+ console.log(`${icon} ${msg}`);
468
+ if (!ok) {
469
+ if (fix) console.log(` \u2192 ${fix}`);
470
+ issues++;
471
+ }
472
+ };
473
+ const cnPath = import_path.default.join(cwd, "src/lib/utils/cn.ts");
474
+ check(import_fs.default.existsSync(cnPath), "src/lib/utils/cn.ts", "run: npx basuicn init");
475
+ const pkgPath = import_path.default.join(cwd, "package.json");
476
+ if (import_fs.default.existsSync(pkgPath)) {
477
+ const pkg = JSON.parse(import_fs.default.readFileSync(pkgPath, "utf-8"));
478
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
479
+ for (const dep of RUNTIME_PACKAGES) {
480
+ check(!!allDeps[dep], `dependency: ${dep}`, `run: npm install ${dep}`);
481
+ }
482
+ } else {
483
+ check(false, "package.json found", "run: npm init -y");
484
+ }
485
+ const cssCandidates = ["src/index.css", "src/App.css", "src/main.css", "src/styles/index.css"];
486
+ const hasTailwind = cssCandidates.some((f) => {
487
+ const p = import_path.default.join(cwd, f);
488
+ if (!import_fs.default.existsSync(p)) return false;
489
+ const c = import_fs.default.readFileSync(p, "utf-8");
490
+ return c.includes('@import "tailwindcss"') || c.includes("@import 'tailwindcss'");
491
+ });
492
+ check(hasTailwind, "Tailwind CSS @import in CSS file", "run: npx basuicn init");
493
+ const tsCandidates = ["tsconfig.app.json", "tsconfig.json"];
494
+ const hasAlias = tsCandidates.some((f) => {
495
+ const p = import_path.default.join(cwd, f);
496
+ if (!import_fs.default.existsSync(p)) return false;
497
+ const c = import_fs.default.readFileSync(p, "utf-8");
498
+ return c.includes('"@/*"') || c.includes("'@/*'");
499
+ });
500
+ check(hasAlias, "TypeScript path aliases (@/*)", "run: npx basuicn init");
501
+ const hasViteConfig = import_fs.default.existsSync(import_path.default.join(cwd, "vite.config.ts")) || import_fs.default.existsSync(import_path.default.join(cwd, "vite.config.js"));
502
+ check(hasViteConfig, "vite.config.ts / vite.config.js", "run: npx basuicn init");
503
+ console.log("");
504
+ if (issues === 0) {
505
+ log("All checks passed! Project is healthy.");
506
+ } else {
507
+ warn(`${issues} issue(s) found. Run 'npx basuicn init' to fix most issues.`);
508
+ }
509
+ break;
510
+ }
403
511
  default: {
404
512
  console.log(`
405
513
  basuicn \u2014 UI Component CLI
@@ -407,8 +515,11 @@ var main = async () => {
407
515
  Commands:
408
516
  init Initialize project (install core deps + files)
409
517
  add <name> [--force] Add component(s) to your project
518
+ update <name> Update component(s) to the latest registry version
519
+ diff <name> Show diff between local and registry version
410
520
  remove <name> Remove component(s) from your project
411
521
  list List all available components
522
+ doctor Check project health and configuration
412
523
  tailwind Show Tailwind config instructions
413
524
 
414
525
  Options:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "basuicn",
3
3
  "private": false,
4
- "version": "0.1.1",
4
+ "version": "0.1.3",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "basuicn": "./dist/ui-cli.cjs"
@@ -22,9 +22,9 @@
22
22
  "test:ui": "vitest --ui",
23
23
  "test:coverage": "vitest run --coverage",
24
24
  "registry:build": "npx -y tsx scripts/build-registry.ts",
25
+ "theme:sync": "npx -y tsx scripts/generate-theme-css.ts",
25
26
  "ui:add": "npx -y tsx scripts/ui-cli.ts add"
26
27
  },
27
- "dependencies": {},
28
28
  "devDependencies": {
29
29
  "@babel/core": "^7.29.0",
30
30
  "@base-ui/react": "^1.3.0",
@@ -36,6 +36,7 @@
36
36
  "@rolldown/plugin-babel": "^0.2.1",
37
37
  "@tailwindcss/vite": "^4.2.2",
38
38
  "@tanstack/react-table": "^8.21.3",
39
+ "@tanstack/react-virtual": "^3.13.23",
39
40
  "@testing-library/jest-dom": "^6.9.1",
40
41
  "@testing-library/react": "^16.3.2",
41
42
  "@testing-library/user-event": "^14.6.1",