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