rxn-ui 0.5.4 → 0.5.5

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/cli/add.js ADDED
@@ -0,0 +1,73 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ import { cwd, STYLES_FILES, getRegistryUrl } from './constants.js'
5
+ import { loadConfig } from './utils/config.js'
6
+ import { fetchFile, fetchJSON } from './utils/fetch.js'
7
+ import { getSourceUrl } from './utils/getSourceUrl.js'
8
+ import { log } from './utils/logger.js'
9
+
10
+ export async function add(name, cmdOptions = {}) {
11
+ const config = loadConfig()
12
+ if (!config) {
13
+ log.error('Not initialized. Run: npx rxn-ui init')
14
+ process.exit(1)
15
+ }
16
+
17
+ const tag = cmdOptions.tag || null
18
+ const registryUrl = getRegistryUrl(tag)
19
+
20
+ let registry
21
+ try {
22
+ registry = await fetchJSON(registryUrl)
23
+ } catch (err) {
24
+ log.error(`Failed to fetch registry: ${err.message}`)
25
+ process.exit(1)
26
+ }
27
+
28
+ const entry = registry[name]
29
+ if (!entry) {
30
+ log.error(`Component "${name}" not found`)
31
+ log.info(`Available components: ${Object.keys(registry).join(', ')}`)
32
+ process.exit(1)
33
+ }
34
+
35
+ const type = name.startsWith('use-') ? 'composables' : 'components'
36
+ const itemsToDownload = [
37
+ { type, name, files: entry.files, dir: config[type] },
38
+ { type: 'styles', name: null, files: STYLES_FILES, dir: config.styles },
39
+ ]
40
+
41
+ log.bold(`\nAdding ${name}...`)
42
+
43
+ for (const item of itemsToDownload) {
44
+ const destDir = path.join(cwd, item.dir)
45
+ fs.mkdirSync(destDir, { recursive: true })
46
+ await downloadItems({ type: item.type, name: item.name, files: item.files, tag, destDir })
47
+ }
48
+
49
+ if (entry.imports) {
50
+ log.bold(`\nUsage:`)
51
+ for (const imp of entry.imports) {
52
+ log(` ${imp}`)
53
+ }
54
+ }
55
+ }
56
+
57
+ async function downloadItems({ type, name, files, tag, destDir }) {
58
+ log.bold(`\nAdding ${type}...`)
59
+ for (const file of files) {
60
+ const url = getSourceUrl(type, name, file, tag)
61
+ const destDirNested = name ? path.join(destDir, name) : destDir
62
+ const destPath = path.join(destDirNested, file)
63
+
64
+ try {
65
+ const content = await fetchFile(url)
66
+ fs.mkdirSync(destDirNested, { recursive: true })
67
+ fs.writeFileSync(destPath, content)
68
+ log.success(`Added ${path.relative(cwd, destPath)}`)
69
+ } catch (err) {
70
+ log.error(`Failed to download ${file}: ${err.message}`)
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,11 @@
1
+ import process from 'node:process'
2
+
3
+ export const GITHUB_REPO = 'r2-h/artharexian-ui'
4
+ export const GITHUB_RAW = `https://raw.githubusercontent.com/${GITHUB_REPO}/main`
5
+
6
+ export const cwd = process.env.INIT_CWD || process.cwd()
7
+ export const STYLES_FILES = ['style.css', 'variables.css']
8
+
9
+ export function getRegistryUrl(tag) {
10
+ return tag ? `${GITHUB_RAW}/cli/registry.json?ref=${tag}` : `${GITHUB_RAW}/cli/registry.json`
11
+ }
package/cli/index.mjs CHANGED
@@ -1,254 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from 'node:fs'
4
- import path from 'node:path'
5
3
  import process from 'node:process'
6
4
 
7
- import { detectProject, loadConfig, saveConfig } from './utils/config.js'
8
- import { fetchFile, fetchJSON } from './utils/fetch.js'
9
- import { colors, error, info, log, success } from './utils/logger.js'
10
-
11
- const GITHUB_REPO = 'r2-h/artharexian-ui'
12
- const GITHUB_RAW = `https://raw.githubusercontent.com/${GITHUB_REPO}/main`
13
-
14
- const cwd = process.env.INIT_CWD || process.cwd()
15
-
16
- const STYLES_FILES = ['style.css', 'variables.css']
17
-
18
- function getRegistryUrl(tag) {
19
- return tag ? `${GITHUB_RAW}/cli/registry.json?ref=${tag}` : `${GITHUB_RAW}/cli/registry.json`
20
- }
21
-
22
- function getComponentFileUrl(component, file, tag) {
23
- if (tag) {
24
- return `${GITHUB_RAW}/src/components/${component}/${file}?ref=${tag}`
25
- }
26
- return `${GITHUB_RAW}/src/components/${component}/${file}`
27
- }
28
-
29
- function getStyleFileUrl(file, tag) {
30
- if (tag) {
31
- return `${GITHUB_RAW}/src/styles/${file}?ref=${tag}`
32
- }
33
- return `${GITHUB_RAW}/src/styles/${file}`
34
- }
35
-
36
- async function init(cmdOptions = {}) {
37
- const configPath = path.join(cwd, 'rxn-ui.json')
38
-
39
- if (fs.existsSync(configPath) && !cmdOptions.overwrite) {
40
- const existing = loadConfig()
41
- info(`Already initialized at ${configPath}`)
42
- info(`Components: ${existing.components}`)
43
- info(`Styles: ${existing.styles}`)
44
- log('\nTo reinitialize, run: npx rxn-ui init --overwrite')
45
- return
46
- }
47
-
48
- const config = detectProject()
49
-
50
- if (cmdOptions.components) {
51
- config.components = cmdOptions.components
52
- }
53
- if (cmdOptions.styles) {
54
- config.styles = cmdOptions.styles
55
- }
56
-
57
- saveConfig(config)
58
- success('rxn-ui initialized')
59
- log(`\nConfiguration saved to ${configPath}`)
60
- log(` Components: ${config.components}`)
61
- log(` Styles: ${config.styles}`)
62
- log(`\nNow you can add components:`)
63
- log(` npx rxn-ui add button-base`)
64
- }
65
-
66
- async function add(name, cmdOptions = {}) {
67
- const config = loadConfig()
68
- if (!config) {
69
- error('Not initialized. Run: npx rxn-ui init')
70
- process.exit(1)
71
- }
72
-
73
- const tag = cmdOptions.tag || null
74
- const registryUrl = getRegistryUrl(tag)
75
-
76
- let registry
77
- try {
78
- registry = await fetchJSON(registryUrl)
79
- } catch (err) {
80
- error(`Failed to fetch registry: ${err.message}`)
81
- process.exit(1)
82
- }
83
-
84
- const entry = registry[name]
85
- if (!entry) {
86
- error(`Component "${name}" not found`)
87
- info(`Available components: ${Object.keys(registry).join(', ')}`)
88
- process.exit(1)
89
- }
90
-
91
- const componentsDir = path.join(cwd, config.components)
92
- const stylesDir = path.join(cwd, config.styles)
93
-
94
- fs.mkdirSync(componentsDir, { recursive: true })
95
- fs.mkdirSync(stylesDir, { recursive: true })
96
-
97
- log(`\n${colors.bold}Adding ${name}...${colors.reset}`)
98
-
99
- for (const file of entry.files) {
100
- const url = getComponentFileUrl(name, file, tag)
101
- const destDir = path.join(componentsDir, name)
102
- const destPath = path.join(destDir, file)
103
-
104
- try {
105
- const content = await fetchFile(url)
106
- fs.mkdirSync(destDir, { recursive: true })
107
- fs.writeFileSync(destPath, content)
108
- success(`Added ${path.relative(cwd, destPath)}`)
109
- } catch (err) {
110
- error(`Failed to download ${file}: ${err.message}`)
111
- }
112
- }
113
-
114
- await downloadStyles(stylesDir, tag)
115
- showDependencies(entry)
116
-
117
- if (entry.imports) {
118
- log(`\n${colors.bold}Usage:${colors.reset}`)
119
- for (const imp of entry.imports) {
120
- log(` ${imp}`)
121
- }
122
- }
123
- }
124
-
125
- async function downloadStyles(stylesDir, tag) {
126
- const existingStyles = fs.existsSync(stylesDir)
127
- ? fs.readdirSync(stylesDir).filter((f) => f.endsWith('.css'))
128
- : []
129
-
130
- const stylesToDownload = STYLES_FILES.filter((s) => !existingStyles.includes(s))
131
-
132
- if (stylesToDownload.length === 0) {
133
- info('Styles already exist, skipping...')
134
- return
135
- }
136
-
137
- log(`\n${colors.bold}Adding styles...${colors.reset}`)
138
- for (const styleFile of stylesToDownload) {
139
- const url = getStyleFileUrl(styleFile, tag)
140
- const destPath = path.join(stylesDir, styleFile)
141
-
142
- try {
143
- const content = await fetchFile(url)
144
- fs.mkdirSync(stylesDir, { recursive: true })
145
- fs.writeFileSync(destPath, content)
146
- success(`Added ${path.relative(cwd, destPath)}`)
147
- } catch (err) {
148
- error(`Failed to download ${styleFile}: ${err.message}`)
149
- }
150
- }
151
- }
152
-
153
- function showDependencies(entry) {
154
- if (!entry.dependencies || entry.dependencies.length === 0) {
155
- return
156
- }
157
-
158
- log(`\n${colors.bold}Installing dependencies...${colors.reset}`)
159
- info(`Packages: ${entry.dependencies.join(', ')}`)
160
-
161
- const isPnpm = fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))
162
- const isYarn = fs.existsSync(path.join(cwd, 'yarn.lock'))
163
- const isBun =
164
- fs.existsSync(path.join(cwd, 'bun.lock')) || fs.existsSync(path.join(cwd, 'bun.lockb'))
165
-
166
- let installCmd = 'npm install'
167
- if (isPnpm) installCmd = 'pnpm add'
168
- else if (isYarn) installCmd = 'yarn add'
169
- else if (isBun) installCmd = 'bun add'
170
-
171
- log(`\nRun this command to install dependencies:`)
172
- log(` ${installCmd} ${entry.dependencies.join(' ')}`)
173
- }
174
-
175
- async function list(cmdOptions = {}) {
176
- const tag = cmdOptions.tag || null
177
- const registryUrl = getRegistryUrl(tag)
178
-
179
- let registry
180
- try {
181
- registry = await fetchJSON(registryUrl)
182
- } catch (err) {
183
- error(`Failed to fetch registry: ${err.message}`)
184
- process.exit(1)
185
- }
186
-
187
- log(`\n${colors.bold}Available components:${colors.reset}\n`)
188
-
189
- const names = Object.keys(registry).sort()
190
- const maxLen = Math.max(...names.map((n) => n.length))
191
-
192
- for (const name of names) {
193
- const entry = registry[name]
194
- const desc = entry.description || ''
195
- const padded = name.padEnd(maxLen)
196
- log(` ${colors.blue}${padded}${colors.reset} ${desc}`)
197
- }
198
-
199
- log(`\nTo add a component: npx rxn-ui add <name>`)
200
- }
201
-
202
- function showHelp() {
203
- log(`
204
- ${colors.bold}rxn-ui${colors.reset} - Vue 3 UI components
205
-
206
- ${colors.bold}Usage:${colors.reset}
207
- npx rxn-ui <command> [options]
208
-
209
- ${colors.bold}Commands:${colors.reset}
210
- init Initialize rxn-ui in your project
211
- add <component> Add a component to your project
212
- list List available components
213
- help Show this help message
214
-
215
- ${colors.bold}Options:${colors.reset}
216
- --tag <version> Use a specific version from GitHub
217
- --overwrite Overwrite existing config (for init)
218
- --components <path> Custom components directory
219
- --styles <path> Custom styles directory
220
-
221
- ${colors.bold}Examples:${colors.reset}
222
- npx rxn-ui init
223
- npx rxn-ui add button-base
224
- npx rxn-ui add card-base --tag v0.4.6
225
- npx rxn-ui list
226
- `)
227
- }
228
-
229
- function parseArgs(args) {
230
- const cmd = args[0]
231
- const options = {}
232
- const positional = []
233
-
234
- for (let i = 1; i < args.length; i++) {
235
- const arg = args[i]
236
- if (arg.startsWith('--')) {
237
- const key = arg.slice(2)
238
- const value = args[i + 1]
239
- if (value && !value.startsWith('--')) {
240
- options[key] = value
241
- i++
242
- } else {
243
- options[key] = true
244
- }
245
- } else {
246
- positional.push(arg)
247
- }
248
- }
249
-
250
- return { cmd, options, positional }
251
- }
5
+ import { add } from './add.js'
6
+ import { init } from './init.js'
7
+ import { list } from './list.js'
8
+ import { showHelp } from './showHelp.js'
9
+ import { log } from './utils/logger.js'
10
+ import { parseArgs } from './utils/parseArgs.js'
252
11
 
253
12
  async function main() {
254
13
  const args = process.argv.slice(2)
@@ -260,7 +19,7 @@ async function main() {
260
19
  break
261
20
  case 'add':
262
21
  if (!positional[0]) {
263
- error('Please specify a component name')
22
+ log.error('Please specify a component name')
264
23
  log('Usage: npx rxn-ui add <component>')
265
24
  process.exit(1)
266
25
  }
@@ -278,7 +37,7 @@ async function main() {
278
37
  if (!cmd) {
279
38
  showHelp()
280
39
  } else {
281
- error(`Unknown command: ${cmd}`)
40
+ log.error(`Unknown command: ${cmd}`)
282
41
  log('Run "npx rxn-ui help" for usage')
283
42
  process.exit(1)
284
43
  }
@@ -286,6 +45,6 @@ async function main() {
286
45
  }
287
46
 
288
47
  main().catch((err) => {
289
- error(err.message)
48
+ log.error(err.message)
290
49
  process.exit(1)
291
50
  })
package/cli/init.js ADDED
@@ -0,0 +1,42 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ import { cwd } from './constants.js'
5
+ import { detectProject, loadConfig, saveConfig } from './utils/config.js'
6
+ import { log } from './utils/logger.js'
7
+
8
+ export async function init(cmdOptions = {}) {
9
+ const configPath = path.join(cwd, 'rxn-ui.json')
10
+
11
+ if (fs.existsSync(configPath) && !cmdOptions.overwrite) {
12
+ const existing = loadConfig()
13
+ log.info(`
14
+ Already initialized at ${configPath}
15
+ Components: ${existing.components}
16
+ Styles: ${existing.styles}`)
17
+ log('\nTo reinitialize, run: npx rxn-ui init --overwrite')
18
+ return
19
+ }
20
+
21
+ const config = detectProject()
22
+
23
+ if (cmdOptions.components) {
24
+ config.components = cmdOptions.components
25
+ }
26
+ if (cmdOptions.styles) {
27
+ config.styles = cmdOptions.styles
28
+ }
29
+ if (cmdOptions.composables) {
30
+ config.composables = cmdOptions.composables
31
+ }
32
+
33
+ saveConfig(config)
34
+ log.success('rxn-ui initialized')
35
+ log(`\n
36
+ Configuration saved to ${configPath}
37
+ Components: ${config.components}
38
+ Styles: ${config.styles}
39
+ Composables: ${config.composables}\n
40
+ Now you can add components:
41
+ npx rxn-ui add button-base`)
42
+ }
package/cli/list.js ADDED
@@ -0,0 +1,30 @@
1
+ import { getRegistryUrl } from './constants.js'
2
+ import { fetchJSON } from './utils/fetch.js'
3
+ import { log } from './utils/logger.js'
4
+
5
+ export async function list(cmdOptions = {}) {
6
+ const tag = cmdOptions.tag || null
7
+ const registryUrl = getRegistryUrl(tag)
8
+
9
+ let registry
10
+ try {
11
+ registry = await fetchJSON(registryUrl)
12
+ } catch (err) {
13
+ log.error(`Failed to fetch registry: ${err.message}`)
14
+ process.exit(1)
15
+ }
16
+
17
+ log(`\nAvailable components:\n`)
18
+
19
+ const names = Object.keys(registry).sort()
20
+ const maxLen = Math.max(...names.map((n) => n.length))
21
+
22
+ for (const name of names) {
23
+ const entry = registry[name]
24
+ const desc = entry.description || ''
25
+ const padded = name.padEnd(maxLen)
26
+ log(` ${padded} ${desc}`)
27
+ }
28
+
29
+ log(`\nTo add a component: npx rxn-ui add <name>`)
30
+ }
package/cli/registry.json CHANGED
@@ -1,14 +1,9 @@
1
1
  {
2
2
  "button-base": {
3
3
  "description": "Accessible button primitive",
4
- "files": [
5
- "ButtonBase.vue",
6
- "types.ts"
7
- ],
4
+ "files": ["ButtonBase.vue", "types.ts"],
8
5
  "dependencies": [],
9
- "imports": [
10
- "import { ButtonBase } from '@/components/button-base'"
11
- ]
6
+ "imports": ["import { ButtonBase } from '@/components/button-base'"]
12
7
  },
13
8
  "card-base": {
14
9
  "description": "Card container components",
@@ -27,46 +22,27 @@
27
22
  },
28
23
  "checkbox-base": {
29
24
  "description": "Checkbox input primitive",
30
- "files": [
31
- "CheckboxBase.vue"
32
- ],
25
+ "files": ["CheckboxBase.vue"],
33
26
  "dependencies": [],
34
- "imports": [
35
- "import { CheckboxBase } from '@/components/checkbox-base'"
36
- ]
27
+ "imports": ["import { CheckboxBase } from '@/components/checkbox-base'"]
37
28
  },
38
29
  "input-base": {
39
30
  "description": "Text input primitive",
40
- "files": [
41
- "InputBase.vue",
42
- "types.ts"
43
- ],
31
+ "files": ["InputBase.vue", "types.ts"],
44
32
  "dependencies": [],
45
- "imports": [
46
- "import { InputBase } from '@/components/input-base'"
47
- ]
33
+ "imports": ["import { InputBase } from '@/components/input-base'"]
48
34
  },
49
35
  "range-base": {
50
36
  "description": "Range slider primitive",
51
- "files": [
52
- "RangeBase.vue",
53
- "RangeOutput.vue",
54
- "types.ts"
55
- ],
37
+ "files": ["RangeBase.vue", "RangeOutput.vue", "types.ts"],
56
38
  "dependencies": [],
57
- "imports": [
58
- "import { RangeBase, RangeOutput } from '@/components/range-base'"
59
- ]
39
+ "imports": ["import { RangeBase, RangeOutput } from '@/components/range-base'"]
60
40
  },
61
41
  "switch-base": {
62
42
  "description": "Toggle switch primitive",
63
- "files": [
64
- "SwitchBase.vue"
65
- ],
43
+ "files": ["SwitchBase.vue"],
66
44
  "dependencies": [],
67
- "imports": [
68
- "import { SwitchBase } from '@/components/switch-base'"
69
- ]
45
+ "imports": ["import { SwitchBase } from '@/components/switch-base'"]
70
46
  },
71
47
  "tabs": {
72
48
  "description": "Tab navigation components",
@@ -84,14 +60,10 @@
84
60
  "import { TabsBase, TabsList, TabsTab, TabsIndicator, TabsPanel } from '@/components/tabs'"
85
61
  ]
86
62
  },
87
- "theme-toggle": {
88
- "description": "Dark/light theme toggle button",
89
- "files": [
90
- "ThemeToggle.vue"
91
- ],
63
+ "use-theme": {
64
+ "description": "Composable theme switcher",
65
+ "files": ["useTheme.ts"],
92
66
  "dependencies": [],
93
- "imports": [
94
- "import { ThemeToggle } from '@/components/theme-toggle'"
95
- ]
67
+ "imports": ["import { useTheme } from '@/composables/useTheme'"]
96
68
  }
97
69
  }
@@ -0,0 +1,29 @@
1
+ import { colors, log } from './utils/logger.js'
2
+
3
+ export function showHelp() {
4
+ log(`
5
+ ${colors.bold}rxn-ui${colors.reset} - Vue 3 UI components
6
+
7
+ ${colors.bold}Usage:${colors.reset}
8
+ npx rxn-ui <command> [options]
9
+
10
+ ${colors.bold}Commands:${colors.reset}
11
+ init Initialize rxn-ui in your project
12
+ add <component> Add a component to your project
13
+ list List available components
14
+ help Show this help message
15
+
16
+ ${colors.bold}Options:${colors.reset}
17
+ --tag <version> Use a specific version from GitHub
18
+ --overwrite Overwrite existing config (for init)
19
+ --components <path> Custom components directory
20
+ --styles <path> Custom styles directory
21
+ --composables <path> Custom composables directory
22
+
23
+ ${colors.bold}Examples:${colors.reset}
24
+ npx rxn-ui init
25
+ npx rxn-ui add button-base
26
+ npx rxn-ui add card-base --tag v0.4.6
27
+ npx rxn-ui list
28
+ `)
29
+ }
@@ -21,5 +21,6 @@ export function detectProject() {
21
21
  return {
22
22
  components: hasSrc ? 'src/shared/components' : 'components',
23
23
  styles: hasSrc ? 'src/app/styles' : 'styles',
24
+ composables: hasSrc ? 'src/shared/composables' : 'composables',
24
25
  }
25
26
  }
@@ -0,0 +1,11 @@
1
+ import { GITHUB_RAW } from '../constants.js'
2
+
3
+ export function getSourceUrl(type, name, file, tag) {
4
+ const ref = tag ? `?ref=${tag}` : ''
5
+ const paths = {
6
+ components: `/src/components/${name}/${file}`,
7
+ composables: `/src/composables/${name}/${file}`,
8
+ styles: `/src/styles/${file}`,
9
+ }
10
+ return `${GITHUB_RAW}${paths[type]}${ref}`
11
+ }
@@ -1,25 +1,17 @@
1
1
  // ANSI color codes
2
2
  export const colors = {
3
3
  reset: '\x1b[0m',
4
- bold: '\x1b[1m',
5
4
  green: '\x1b[32m',
6
- yellow: '\x1b[33m',
7
5
  blue: '\x1b[34m',
8
6
  red: '\x1b[31m',
7
+ bold: '\x1b[1m',
9
8
  }
10
9
 
11
10
  export function log(message, color = colors.reset) {
12
11
  console.log(`${color}${message}${colors.reset}`)
13
12
  }
14
13
 
15
- export function error(message) {
16
- console.error(`${colors.red} ${message}${colors.reset}`)
17
- }
18
-
19
- export function success(message) {
20
- log(`✔ ${message}`, colors.green)
21
- }
22
-
23
- export function info(message) {
24
- log(`ℹ ${message}`, colors.blue)
25
- }
14
+ log.error = (message) => console.error(`${colors.red}✖ ${message}${colors.reset}`)
15
+ log.info = (message) => console.info(`${colors.blue} ${message}${colors.reset}`)
16
+ log.success = (message) => log(`✔ ${message}`, colors.green)
17
+ log.bold = (message) => console.log(`${colors.bold}${message}${colors.reset}`)
@@ -0,0 +1,23 @@
1
+ export function parseArgs(args) {
2
+ const cmd = args[0]
3
+ const options = {}
4
+ const positional = []
5
+
6
+ for (let i = 1; i < args.length; i++) {
7
+ const arg = args[i]
8
+ if (arg.startsWith('--')) {
9
+ const key = arg.slice(2)
10
+ const value = args[i + 1]
11
+ if (value && !value.startsWith('--')) {
12
+ options[key] = value
13
+ i++
14
+ } else {
15
+ options[key] = true
16
+ }
17
+ } else {
18
+ positional.push(arg)
19
+ }
20
+ }
21
+
22
+ return { cmd, options, positional }
23
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rxn-ui",
3
3
  "description": "Vue 3 UI component library",
4
- "version": "0.5.4",
4
+ "version": "0.5.5",
5
5
  "license": "MIT",
6
6
  "private": false,
7
7
  "type": "module",