@lucasvu/scope-ui 0.0.2 → 0.0.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/AI_SETUP.md ADDED
@@ -0,0 +1,101 @@
1
+ # AI Setup
2
+
3
+ Mục tiêu của file này là để AI của project dùng `@lucasvu/scope-ui` đúng cách, không import lung tung, không hardcode màu sai chỗ và không chọn nhầm component.
4
+
5
+ Nếu project consumer đã cài package, cách nhanh nhất là chạy:
6
+
7
+ ```bash
8
+ npx scope-ui-init
9
+ ```
10
+
11
+ CLI này sẽ tạo `AGENTS.md` và `src/styles/ui-theme.css` theo đúng convention bên dưới.
12
+
13
+ ## 1. Import style đúng thứ tự
14
+
15
+ Import package CSS trước, rồi mới import file override theme của project.
16
+
17
+ ```ts
18
+ import '@lucasvu/scope-ui/styles.css'
19
+ import './styles/ui-theme.css'
20
+ ```
21
+
22
+ `ui-theme.css` nên là nơi duy nhất override màu, surface, border, shadow và gradient của thư viện.
23
+
24
+ ## 2. Tạo file theme của project
25
+
26
+ Đặt file tại `src/styles/ui-theme.css`.
27
+
28
+ ```css
29
+ :root {
30
+ --tw-primary: 12 88% 56%;
31
+ --tw-accent: 24 95% 52%;
32
+ --primary-grad-from: 24 95% 52%;
33
+ --primary-grad-to: 12 88% 56%;
34
+ --surface: rgba(255, 248, 240, 0.92);
35
+ }
36
+
37
+ .dark {
38
+ --tw-primary: 18 100% 62%;
39
+ --tw-accent: 35 100% 58%;
40
+ --surface: rgba(24, 24, 27, 0.82);
41
+ }
42
+ ```
43
+
44
+ Không nên override màu trực tiếp trong từng component nếu chỉ đang đổi theme.
45
+
46
+ ## 3. Rule cho AI của project
47
+
48
+ Copy phần này vào system prompt, repo instructions, `AGENTS.md`, Cursor rules, hoặc bất kỳ chỗ nào project đang dùng để ép AI theo convention:
49
+
50
+ ```md
51
+ Use `@lucasvu/scope-ui` as the default UI library.
52
+
53
+ Always:
54
+ - import `@lucasvu/scope-ui/styles.css` once at the app entry
55
+ - import the project theme override file after the package stylesheet
56
+ - use root exports from `@lucasvu/scope-ui`
57
+ - read `uiAiManifest` to choose the right component by intent
58
+ - read `uiThemeContract` before changing colors, surfaces, borders, or shadows
59
+
60
+ Do not:
61
+ - import from `MainFe` unless the task explicitly targets a legacy screen
62
+ - hardcode brand colors inside page components when a theme token already exists
63
+ - create duplicate Button/Input/Select wrappers unless a project-specific behavior is required
64
+
65
+ Component choice:
66
+ - `Input` for short text
67
+ - `Textarea` for multiline text
68
+ - `Select` for small fixed options
69
+ - `SearchableSelect` for larger local option sets
70
+ - `Combobox` for type-and-pick
71
+ - `AsyncCombobox` for remote search
72
+ - `MultiSelect` for multi-pick
73
+ - `Field` only for custom controls or grouped content
74
+ - `DataTable` for tabular records
75
+ ```
76
+
77
+ ## 4. Runtime contract cho AI/codegen
78
+
79
+ Trong code, AI có thể đọc trực tiếp:
80
+
81
+ ```ts
82
+ import { uiAiManifest, uiThemeContract, uiProjectAiRules } from '@lucasvu/scope-ui'
83
+ ```
84
+
85
+ - `uiAiManifest`: chọn component theo intent
86
+ - `uiThemeContract`: biết override token nào và override ở đâu
87
+ - `uiProjectAiRules`: rule ngắn gọn để inject vào agent của project
88
+
89
+ ## 5. Chỗ override theme
90
+
91
+ Nếu project có app shell:
92
+
93
+ - import `@lucasvu/scope-ui/styles.css` ở app entry
94
+ - import `src/styles/ui-theme.css` ngay sau đó
95
+ - toggle dark mode bằng class `.dark` trên `html` hoặc `body`, hoặc dùng `[data-ui-theme='dark']`
96
+
97
+ Nếu project có nhiều brand/theme:
98
+
99
+ - giữ `:root` là theme mặc định
100
+ - tạo selector như `[data-ui-theme='brand-a']`, `[data-ui-theme='brand-b']`
101
+ - chỉ override token trong file theme, không fork component
package/README.md CHANGED
@@ -43,7 +43,15 @@ npm install @lucasvu/scope-ui
43
43
  import '@lucasvu/scope-ui/styles.css'
44
44
  ```
45
45
 
46
- 3) Dùng component:
46
+ 3) Nếu muốn bootstrap rule/theme cho AI trong project consumer:
47
+
48
+ ```bash
49
+ npx scope-ui-init
50
+ ```
51
+
52
+ Lệnh này sẽ tạo `AGENTS.md` và `src/styles/ui-theme.css` trong repo hiện tại. Dùng `--force` nếu muốn overwrite file đã tồn tại.
53
+
54
+ 4) Dùng component:
47
55
 
48
56
  ```tsx
49
57
  import {
@@ -120,6 +128,7 @@ Nếu muốn AI render UI đúng và ổn định theo thư viện này, đừng
120
128
 
121
129
  - Import CSS global một lần: `@lucasvu/scope-ui/styles.css`
122
130
  - Import file theme override của project ngay sau package CSS, ví dụ `./styles/ui-theme.css`
131
+ - Chạy `npx scope-ui-init` ở project consumer để tạo `AGENTS.md` và `src/styles/ui-theme.css`
123
132
  - Chỉ dùng các component canonical ở root package; tránh `MainFe` nếu không phải legacy screen
124
133
  - Cho agent đọc `uiAiManifest` để biết component nào dùng cho intent nào, props quan trọng là gì, và khi nào không nên dùng
125
134
  - Cho agent đọc `uiThemeContract` để biết màu/token phải override ở đâu
@@ -132,7 +141,7 @@ import { uiAiManifest, uiProjectAiRules, uiThemeContract } from '@lucasvu/scope-
132
141
 
133
142
  `uiThemeContract` mô tả token màu, surface, border, shadow, gradient và selector theme (`:root`, `.dark`, `[data-ui-theme='*']`) để AI không hardcode màu sai chỗ.
134
143
 
135
- `AI_SETUP.md` chứa sẵn đoạn rule/prompt để copy vào settings của agent trong project.
144
+ `AI_SETUP.md` CLI `scope-ui-init` giúp bootstrap rule/theme cho repo consumer không cần copy tay.
136
145
 
137
146
  ## Theme Override
138
147
 
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
4
+ import { dirname, resolve } from 'node:path'
5
+ import process from 'node:process'
6
+
7
+ const PACKAGE_NAME = '@lucasvu/scope-ui'
8
+
9
+ function parseArgs(argv) {
10
+ const args = {
11
+ force: false,
12
+ agentsFile: 'AGENTS.md',
13
+ themeFile: 'src/styles/ui-theme.css',
14
+ }
15
+
16
+ for (let index = 0; index < argv.length; index += 1) {
17
+ const arg = argv[index]
18
+ if (arg === '--force') {
19
+ args.force = true
20
+ continue
21
+ }
22
+ if (arg === '--agents-file') {
23
+ args.agentsFile = argv[index + 1] ?? args.agentsFile
24
+ index += 1
25
+ continue
26
+ }
27
+ if (arg === '--theme-file') {
28
+ args.themeFile = argv[index + 1] ?? args.themeFile
29
+ index += 1
30
+ continue
31
+ }
32
+ if (arg === '--help' || arg === '-h') {
33
+ printHelp()
34
+ process.exit(0)
35
+ }
36
+ }
37
+
38
+ return args
39
+ }
40
+
41
+ function printHelp() {
42
+ console.log(`scope-ui-init
43
+
44
+ Create bootstrap files for using ${PACKAGE_NAME} with AI/codegen.
45
+
46
+ Usage:
47
+ npx scope-ui-init
48
+ npx scope-ui-init --force
49
+ npx scope-ui-init --agents-file AGENTS.md --theme-file src/styles/ui-theme.css
50
+
51
+ Options:
52
+ --force overwrite existing files
53
+ --agents-file target path for the generated AGENTS.md file
54
+ --theme-file target path for the generated theme override file
55
+ --help, -h show this help
56
+ `)
57
+ }
58
+
59
+ function createAgentsTemplate({ themeFile }) {
60
+ return `# Agent Rules
61
+
62
+ This repo uses \`${PACKAGE_NAME}\` as the default UI library.
63
+
64
+ Primary references:
65
+ - \`node_modules/${PACKAGE_NAME}/README.md\`
66
+ - \`node_modules/${PACKAGE_NAME}/AI_SETUP.md\`
67
+ - \`${themeFile}\`
68
+
69
+ Always:
70
+ - import \`${PACKAGE_NAME}/styles.css\` once at the app entry
71
+ - import the project theme override file after the package stylesheet
72
+ - use root exports from \`${PACKAGE_NAME}\`
73
+ - read \`uiAiManifest\` before choosing components
74
+ - read \`uiThemeContract\` before changing colors, surfaces, borders, or shadows
75
+ - keep UI token-driven and theme-driven
76
+
77
+ Do not:
78
+ - import from \`MainFe\` unless the task explicitly targets a legacy screen
79
+ - hardcode brand colors inside page components when a theme token already exists
80
+ - create duplicate Button/Input/Select wrappers unless a project-specific behavior is required
81
+
82
+ Component choice:
83
+ - \`Input\` for short text
84
+ - \`Textarea\` for multiline text
85
+ - \`Select\` for small fixed options
86
+ - \`SearchableSelect\` for larger local option sets
87
+ - \`Combobox\` for type-and-pick
88
+ - \`AsyncCombobox\` for remote search
89
+ - \`MultiSelect\` for multi-pick
90
+ - \`Field\` only for custom controls or grouped content
91
+ - \`DataTable\` for tabular records
92
+ `
93
+ }
94
+
95
+ function createThemeTemplate() {
96
+ return `:root {
97
+ /* Override only the tokens you need for the project brand. */
98
+ /* --tw-primary: 221.2 83.2% 53.3%; */
99
+ /* --tw-accent: 199 89% 48%; */
100
+ /* --primary-grad-from: 199 89% 48%; */
101
+ /* --primary-grad-to: 221.2 83.2% 53.3%; */
102
+ /* --surface: rgba(255, 255, 255, 0.92); */
103
+ }
104
+
105
+ .dark {
106
+ /* --tw-primary: 217.2 91.2% 59.8%; */
107
+ /* --tw-accent: 199 89% 48%; */
108
+ /* --surface: rgba(15, 23, 42, 0.78); */
109
+ }
110
+ `
111
+ }
112
+
113
+ function writeFile(targetPath, content, force) {
114
+ const absolutePath = resolve(process.cwd(), targetPath)
115
+ const alreadyExists = existsSync(absolutePath)
116
+
117
+ if (alreadyExists && !force) {
118
+ return { path: targetPath, status: 'skipped' }
119
+ }
120
+
121
+ mkdirSync(dirname(absolutePath), { recursive: true })
122
+ writeFileSync(absolutePath, content, 'utf8')
123
+ return { path: targetPath, status: alreadyExists ? 'overwritten' : 'created' }
124
+ }
125
+
126
+ const options = parseArgs(process.argv.slice(2))
127
+
128
+ const agentsResult = writeFile(
129
+ options.agentsFile,
130
+ createAgentsTemplate({ themeFile: options.themeFile }),
131
+ options.force,
132
+ )
133
+
134
+ const themeResult = writeFile(
135
+ options.themeFile,
136
+ createThemeTemplate(),
137
+ options.force,
138
+ )
139
+
140
+ console.log(`Initialized ${PACKAGE_NAME}`)
141
+ console.log(`- ${agentsResult.path}: ${agentsResult.status}`)
142
+ console.log(`- ${themeResult.path}: ${themeResult.status}`)
143
+ console.log('')
144
+ console.log('Next steps:')
145
+ console.log(`1. Import \`${PACKAGE_NAME}/styles.css\` once at your app entry.`)
146
+ console.log(`2. Import \`${options.themeFile}\` right after the package stylesheet.`)
147
+ console.log(`3. Let your agent read \`${options.agentsFile}\` before generating UI.`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lucasvu/scope-ui",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -14,13 +14,19 @@
14
14
  "./styles.css": "./dist/styles.css",
15
15
  "./package.json": "./package.json"
16
16
  },
17
+ "bin": {
18
+ "scope-ui-init": "./bin/scope-ui-init.mjs"
19
+ },
17
20
  "files": [
18
- "dist"
21
+ "dist",
22
+ "bin",
23
+ "AI_SETUP.md"
19
24
  ],
20
25
  "scripts": {
21
26
  "build": "npm run build:js && npm run build:css",
22
27
  "build:js": "tsup",
23
28
  "build:css": "tailwindcss -c ./tailwind.config.js -i ./src/styles.css -o ./dist/styles.css --minify",
29
+ "init-ai": "node ./bin/scope-ui-init.mjs",
24
30
  "prepublishOnly": "npm run build"
25
31
  },
26
32
  "publishConfig": {