rxn-ui 0.6.0 → 0.6.2
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 +132 -79
- package/cli/constants.js +11 -11
- package/cli/init.js +49 -6
- package/cli/list.js +1 -4
- package/cli/registry.json +10 -3
- package/cli/showHelp.js +0 -3
- package/cli/utils/config.js +3 -2
- package/cli/utils/getSourceUrl.js +4 -4
- package/package.json +5 -6
package/cli/add.js
CHANGED
|
@@ -1,79 +1,132 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
|
|
4
|
-
import {
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
log.error(`
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// Скачиваем
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
import { cwd, 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
|
+
// Patterns to detect and rewrite import paths
|
|
11
|
+
const IMPORT_PATTERNS = [
|
|
12
|
+
{ type: 'assets', regex: /\.\.\/\.\.\/assets\//g },
|
|
13
|
+
{ type: 'composables', regex: /\.\.\/\.\.\/composables\//g },
|
|
14
|
+
{ type: 'utils', regex: /\.\.\/\.\.\/utils\//g },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
export async function add(componentName, cmdOptions = {}) {
|
|
18
|
+
const config = loadConfig()
|
|
19
|
+
if (!config) {
|
|
20
|
+
log.error('Not initialized. Run: npx rxn-ui init')
|
|
21
|
+
process.exit(1)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const registryUrl = getRegistryUrl()
|
|
25
|
+
|
|
26
|
+
let registry
|
|
27
|
+
try {
|
|
28
|
+
registry = await fetchJSON(registryUrl)
|
|
29
|
+
} catch (err) {
|
|
30
|
+
log.error(`Failed to fetch registry: ${err.message}`)
|
|
31
|
+
process.exit(1)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const entry = registry[componentName]
|
|
35
|
+
if (!entry) {
|
|
36
|
+
log.error(`Component "${componentName}" not found`)
|
|
37
|
+
log.info(`Available components: ${Object.keys(registry).join(', ')}`)
|
|
38
|
+
process.exit(1)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Если файлов больше одного — скачиваем в папку с именем компонента
|
|
42
|
+
const isMultipleFiles = entry.files.length > 1
|
|
43
|
+
const destDir = isMultipleFiles
|
|
44
|
+
? path.join(cwd, config[entry.type], componentName)
|
|
45
|
+
: path.join(cwd, config[entry.type])
|
|
46
|
+
|
|
47
|
+
log.bold(`\nAdding ${componentName}...`)
|
|
48
|
+
|
|
49
|
+
// Скачиваем зависимости (assets, composables, utils)
|
|
50
|
+
const depDirs = await downloadDependencies(entry, config)
|
|
51
|
+
|
|
52
|
+
// Скачиваем файлы компонента
|
|
53
|
+
await downloadItems({
|
|
54
|
+
type: entry.type,
|
|
55
|
+
componentName,
|
|
56
|
+
files: entry.files,
|
|
57
|
+
destDir,
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// Переписываем импорты в файлах компонента
|
|
61
|
+
rewriteImports(entry.files, destDir, depDirs, isMultipleFiles)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function downloadDependencies(entry, config) {
|
|
65
|
+
const deps = entry.dependencies
|
|
66
|
+
if (!deps) return {}
|
|
67
|
+
|
|
68
|
+
const depDirs = {}
|
|
69
|
+
|
|
70
|
+
for (const [type, files] of Object.entries(deps)) {
|
|
71
|
+
const destDir = path.join(cwd, config[type])
|
|
72
|
+
depDirs[type] = destDir
|
|
73
|
+
|
|
74
|
+
await downloadItems({
|
|
75
|
+
type,
|
|
76
|
+
componentName: null,
|
|
77
|
+
files,
|
|
78
|
+
destDir,
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return depDirs
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function rewriteImports(files, destDir, depDirs, isMultipleFiles) {
|
|
86
|
+
for (const file of files) {
|
|
87
|
+
const filePath = path.join(destDir, file)
|
|
88
|
+
if (!fs.existsSync(filePath)) continue
|
|
89
|
+
|
|
90
|
+
let content = fs.readFileSync(filePath, 'utf8')
|
|
91
|
+
|
|
92
|
+
for (const { type, regex } of IMPORT_PATTERNS) {
|
|
93
|
+
if (!depDirs[type]) continue
|
|
94
|
+
if (!regex.test(content)) continue
|
|
95
|
+
|
|
96
|
+
// Reset regex lastIndex
|
|
97
|
+
regex.lastIndex = 0
|
|
98
|
+
|
|
99
|
+
// Calculate relative path from component file to dependency dir
|
|
100
|
+
const fileDir = isMultipleFiles ? destDir : path.dirname(filePath)
|
|
101
|
+
const relPath = path.relative(fileDir, depDirs[type]).replace(/\\/g, '/')
|
|
102
|
+
const importPath = relPath.startsWith('.') ? relPath : `./${relPath}`
|
|
103
|
+
|
|
104
|
+
content = content.replace(regex, `${importPath}/`)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
fs.writeFileSync(filePath, content)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export async function downloadItems({ type, componentName, files, destDir }) {
|
|
112
|
+
log.bold(`\nAdding ${type}...`)
|
|
113
|
+
fs.mkdirSync(destDir, { recursive: true })
|
|
114
|
+
|
|
115
|
+
for (const file of files) {
|
|
116
|
+
const url = getSourceUrl(type, componentName, file)
|
|
117
|
+
const destPath = path.join(destDir, file)
|
|
118
|
+
|
|
119
|
+
if (fs.existsSync(destPath)) {
|
|
120
|
+
log.info(`Skipping ${path.relative(cwd, destPath)} (already exists)`)
|
|
121
|
+
continue
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
const content = await fetchFile(url)
|
|
126
|
+
fs.writeFileSync(destPath, content)
|
|
127
|
+
log.success(`Added ${path.relative(cwd, destPath)}`)
|
|
128
|
+
} catch (err) {
|
|
129
|
+
log.error(`Failed to download ${file}: ${err.message}`)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
package/cli/constants.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import process from 'node:process'
|
|
2
|
-
|
|
3
|
-
export const GITHUB_REPO = 'r2-h/
|
|
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(
|
|
10
|
-
return
|
|
11
|
-
}
|
|
1
|
+
import process from 'node:process'
|
|
2
|
+
|
|
3
|
+
export const GITHUB_REPO = 'r2-h/rxn-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() {
|
|
10
|
+
return `${GITHUB_RAW}/cli/registry.json`
|
|
11
|
+
}
|
package/cli/init.js
CHANGED
|
@@ -1,20 +1,45 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
|
|
4
|
-
import { cwd } from './constants.js'
|
|
4
|
+
import { STYLES_FILES, GITHUB_RAW, cwd } from './constants.js'
|
|
5
5
|
import { detectProject, loadConfig, saveConfig } from './utils/config.js'
|
|
6
|
+
import { downloadItems } from './add.js'
|
|
7
|
+
import { fetchFile } from './utils/fetch.js'
|
|
6
8
|
import { log } from './utils/logger.js'
|
|
7
9
|
|
|
10
|
+
async function downloadStyles(stylesDir) {
|
|
11
|
+
log.bold('\nAdding styles...')
|
|
12
|
+
fs.mkdirSync(stylesDir, { recursive: true })
|
|
13
|
+
|
|
14
|
+
for (const file of STYLES_FILES) {
|
|
15
|
+
const url = `${GITHUB_RAW}/src/styles/${file}`
|
|
16
|
+
const destPath = path.join(stylesDir, file)
|
|
17
|
+
|
|
18
|
+
if (fs.existsSync(destPath)) {
|
|
19
|
+
log.info(`Skipping ${path.relative(cwd, destPath)} (already exists)`)
|
|
20
|
+
continue
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const content = await fetchFile(url)
|
|
25
|
+
fs.writeFileSync(destPath, content)
|
|
26
|
+
log.success(`Added ${path.relative(cwd, destPath)}`)
|
|
27
|
+
} catch (err) {
|
|
28
|
+
log.error(`Failed to download ${file}: ${err.message}`)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
8
33
|
export async function init(cmdOptions = {}) {
|
|
9
34
|
const configPath = path.join(cwd, 'rxn-ui.json')
|
|
10
35
|
|
|
11
|
-
if (fs.existsSync(configPath)
|
|
36
|
+
if (fs.existsSync(configPath)) {
|
|
12
37
|
const existing = loadConfig()
|
|
13
38
|
log.info(`
|
|
14
39
|
Already initialized at ${configPath}
|
|
15
40
|
Components: ${existing.components}
|
|
16
|
-
Styles: ${existing.styles}
|
|
17
|
-
|
|
41
|
+
Styles: ${existing.styles}
|
|
42
|
+
Assets: ${existing.assets}`)
|
|
18
43
|
return
|
|
19
44
|
}
|
|
20
45
|
|
|
@@ -25,18 +50,36 @@ Styles: ${existing.styles}`)
|
|
|
25
50
|
}
|
|
26
51
|
if (cmdOptions.styles) {
|
|
27
52
|
config.styles = cmdOptions.styles
|
|
53
|
+
} else {
|
|
54
|
+
config.styles = 'styles'
|
|
28
55
|
}
|
|
29
56
|
if (cmdOptions.composables) {
|
|
30
57
|
config.composables = cmdOptions.composables
|
|
31
58
|
}
|
|
32
59
|
|
|
60
|
+
// Check if styles dir exists, use 'rxn-styles' prefix to avoid conflicts
|
|
61
|
+
const stylesPath = path.join(cwd, config.styles)
|
|
62
|
+
if (fs.existsSync(stylesPath)) {
|
|
63
|
+
const base = path.basename(config.styles)
|
|
64
|
+
const dir = path.dirname(config.styles)
|
|
65
|
+
config.styles = path.join(dir, `rxn-${base}`)
|
|
66
|
+
log.info(`Styles directory "${config.styles}" (prefixed to avoid conflict)`)
|
|
67
|
+
}
|
|
68
|
+
|
|
33
69
|
saveConfig(config)
|
|
34
70
|
log.success('rxn-ui initialized')
|
|
35
71
|
log(`\n
|
|
36
72
|
Configuration saved to ${configPath}
|
|
37
73
|
Components: ${config.components}
|
|
38
74
|
Styles: ${config.styles}
|
|
39
|
-
Composables: ${config.composables}
|
|
40
|
-
|
|
75
|
+
Composables: ${config.composables}
|
|
76
|
+
Assets: ${config.assets}
|
|
77
|
+
Utils: ${config.utils}`)
|
|
78
|
+
|
|
79
|
+
// Download styles
|
|
80
|
+
const stylesDir = path.join(cwd, config.styles)
|
|
81
|
+
await downloadStyles(stylesDir)
|
|
82
|
+
|
|
83
|
+
log(`\nNow you can add components:
|
|
41
84
|
npx rxn-ui add button-base`)
|
|
42
85
|
}
|
package/cli/list.js
CHANGED
|
@@ -3,12 +3,9 @@ import { fetchJSON } from './utils/fetch.js'
|
|
|
3
3
|
import { log } from './utils/logger.js'
|
|
4
4
|
|
|
5
5
|
export async function list(cmdOptions = {}) {
|
|
6
|
-
const tag = cmdOptions.tag || null
|
|
7
|
-
const registryUrl = getRegistryUrl(tag)
|
|
8
|
-
|
|
9
6
|
let registry
|
|
10
7
|
try {
|
|
11
|
-
registry = await fetchJSON(
|
|
8
|
+
registry = await fetchJSON(getRegistryUrl())
|
|
12
9
|
} catch (err) {
|
|
13
10
|
log.error(`Failed to fetch registry: ${err.message}`)
|
|
14
11
|
process.exit(1)
|
package/cli/registry.json
CHANGED
|
@@ -16,7 +16,10 @@
|
|
|
16
16
|
},
|
|
17
17
|
"checkbox-base": {
|
|
18
18
|
"type": "components",
|
|
19
|
-
"files": ["CheckboxBase.vue"]
|
|
19
|
+
"files": ["CheckboxBase.vue"],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"assets": ["CheckIcon.vue"]
|
|
22
|
+
}
|
|
20
23
|
},
|
|
21
24
|
"input-base": {
|
|
22
25
|
"type": "components",
|
|
@@ -24,7 +27,11 @@
|
|
|
24
27
|
},
|
|
25
28
|
"range-base": {
|
|
26
29
|
"type": "components",
|
|
27
|
-
"files": ["RangeBase.vue", "RangeOutput.vue", "types.ts"]
|
|
30
|
+
"files": ["RangeBase.vue", "RangeOutput.vue", "types.ts"],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"composables": ["useVars.ts"],
|
|
33
|
+
"utils": ["cssParser.ts", "mergeDefaultProps.ts"]
|
|
34
|
+
}
|
|
28
35
|
},
|
|
29
36
|
"switch-base": {
|
|
30
37
|
"type": "components",
|
|
@@ -44,7 +51,7 @@
|
|
|
44
51
|
},
|
|
45
52
|
"popover-base": {
|
|
46
53
|
"type": "components",
|
|
47
|
-
"files": ["context.ts", "
|
|
54
|
+
"files": ["context.ts", "PopoverMenu.vue", "PopoverTrigger.vue", "types.ts"]
|
|
48
55
|
},
|
|
49
56
|
"use-theme": {
|
|
50
57
|
"type": "composables",
|
package/cli/showHelp.js
CHANGED
|
@@ -14,8 +14,6 @@ ${colors.bold}Commands:${colors.reset}
|
|
|
14
14
|
help Show this help message
|
|
15
15
|
|
|
16
16
|
${colors.bold}Options:${colors.reset}
|
|
17
|
-
--tag <version> Use a specific version from GitHub
|
|
18
|
-
--overwrite Overwrite existing config (for init)
|
|
19
17
|
--components <path> Custom components directory
|
|
20
18
|
--styles <path> Custom styles directory
|
|
21
19
|
--composables <path> Custom composables directory
|
|
@@ -23,7 +21,6 @@ ${colors.bold}Options:${colors.reset}
|
|
|
23
21
|
${colors.bold}Examples:${colors.reset}
|
|
24
22
|
npx rxn-ui init
|
|
25
23
|
npx rxn-ui add button-base
|
|
26
|
-
npx rxn-ui add card-base --tag v0.4.6
|
|
27
24
|
npx rxn-ui list
|
|
28
25
|
`)
|
|
29
26
|
}
|
package/cli/utils/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import { cwd } from '../constants.js'
|
|
5
5
|
|
|
6
6
|
export function loadConfig() {
|
|
7
7
|
const configPath = path.join(cwd, 'rxn-ui.json')
|
|
@@ -20,7 +20,8 @@ export function detectProject() {
|
|
|
20
20
|
const hasSrc = fs.existsSync(path.join(cwd, 'src'))
|
|
21
21
|
return {
|
|
22
22
|
components: hasSrc ? 'src/shared/components' : 'components',
|
|
23
|
-
styles: hasSrc ? 'src/app/styles' : 'styles',
|
|
24
23
|
composables: hasSrc ? 'src/shared/composables' : 'composables',
|
|
24
|
+
assets: hasSrc ? 'src/assets' : 'assets',
|
|
25
|
+
utils: hasSrc ? 'src/shared/utils' : 'utils',
|
|
25
26
|
}
|
|
26
27
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { GITHUB_RAW } from '../constants.js'
|
|
2
2
|
|
|
3
|
-
export function getSourceUrl(type, componentName, file
|
|
4
|
-
const ref = tag ? `?ref=${tag}` : ''
|
|
3
|
+
export function getSourceUrl(type, componentName, file) {
|
|
5
4
|
const paths = {
|
|
6
5
|
components: componentName
|
|
7
6
|
? `/src/components/${componentName}/${file}`
|
|
@@ -9,7 +8,8 @@ export function getSourceUrl(type, componentName, file, tag) {
|
|
|
9
8
|
composables: componentName
|
|
10
9
|
? `/src/composables/${componentName}/${file}`
|
|
11
10
|
: `/src/composables/${file}`,
|
|
12
|
-
|
|
11
|
+
assets: `/src/assets/${file}`,
|
|
12
|
+
utils: `/src/utils/${file}`,
|
|
13
13
|
}
|
|
14
|
-
return `${GITHUB_RAW}${paths[type]}
|
|
14
|
+
return `${GITHUB_RAW}${paths[type]}`
|
|
15
15
|
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rxn-ui",
|
|
3
3
|
"description": "Vue 3 UI component library",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
7
7
|
"type": "module",
|
|
8
8
|
"author": "Artur Hareksian <artharexian@gmail.com> (https://github.com/r2-h)",
|
|
9
|
-
"repository":
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/r2-h/artharexian-ui.git"
|
|
12
|
-
},
|
|
9
|
+
"repository": "r2-h/rxn-ui",
|
|
13
10
|
"bin": {
|
|
14
11
|
"rxn-ui": "cli/index.mjs"
|
|
15
12
|
},
|
|
@@ -29,7 +26,8 @@
|
|
|
29
26
|
"build-storybook": "storybook build"
|
|
30
27
|
},
|
|
31
28
|
"peerDependencies": {
|
|
32
|
-
"vue": "^3.5.0"
|
|
29
|
+
"vue": "^3.5.0",
|
|
30
|
+
"vue-router": "^4.0.0"
|
|
33
31
|
},
|
|
34
32
|
"devDependencies": {
|
|
35
33
|
"@chromatic-com/storybook": "^5.0.1",
|
|
@@ -52,6 +50,7 @@
|
|
|
52
50
|
"vite": "^7.3.1",
|
|
53
51
|
"vitest": "^4.0.18",
|
|
54
52
|
"vue": "^3.5.25",
|
|
53
|
+
"vue-router": "^4.6.4",
|
|
55
54
|
"vue-tsc": "^3.1.5"
|
|
56
55
|
},
|
|
57
56
|
"eslintConfig": {
|