create-ui0 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/dist/index.d.ts +1 -0
- package/dist/index.js +54 -19
- package/package.json +2 -1
- package/template-nuxt/app/app.vue +37 -0
- package/template-nuxt/nuxt.config.ts +7 -0
- package/template-nuxt/package.json.tpl +20 -0
- package/template-nuxt/tsconfig.json +4 -0
- package/template-nuxt/ui0.config.ts +23 -0
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { fileURLToPath } from 'node:url';
|
|
@@ -7,12 +8,16 @@ import prompts from 'prompts';
|
|
|
7
8
|
* Usage: npm create ui0 [dir]
|
|
8
9
|
*/
|
|
9
10
|
const templateDir = fileURLToPath(new URL('../template', import.meta.url));
|
|
11
|
+
const templateNuxtDir = fileURLToPath(new URL('../template-nuxt', import.meta.url));
|
|
10
12
|
const componentTemplateDir = fileURLToPath(new URL('../template-component', import.meta.url));
|
|
11
13
|
const toKebab = (s) => s
|
|
12
14
|
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
13
15
|
.replace(/[\s_]+/g, '-')
|
|
14
16
|
.toLowerCase();
|
|
15
|
-
const toPascal = (s) => s
|
|
17
|
+
const toPascal = (s) => s
|
|
18
|
+
.split(/[-\s_]+/)
|
|
19
|
+
.map((w) => w[0].toUpperCase() + w.slice(1))
|
|
20
|
+
.join('');
|
|
16
21
|
const toCamel = (s) => {
|
|
17
22
|
const p = toPascal(s);
|
|
18
23
|
return p[0].toLowerCase() + p.slice(1);
|
|
@@ -80,7 +85,12 @@ const runComponent = async () => {
|
|
|
80
85
|
message: 'Target directory',
|
|
81
86
|
initial: path.join('src', 'components', kebab)
|
|
82
87
|
}, { onCancel });
|
|
83
|
-
const { spec } = await prompts({
|
|
88
|
+
const { spec } = await prompts({
|
|
89
|
+
type: 'confirm',
|
|
90
|
+
name: 'spec',
|
|
91
|
+
message: 'Include a vitest spec (adds vitest + @vue/test-utils to devDependencies)?',
|
|
92
|
+
initial: false
|
|
93
|
+
}, { onCancel });
|
|
84
94
|
const dir = path.resolve(process.cwd(), target);
|
|
85
95
|
if (existsSync(dir)) {
|
|
86
96
|
console.error(`${target} already exists`);
|
|
@@ -124,42 +134,67 @@ const run = async () => {
|
|
|
124
134
|
const target = path.resolve(process.cwd(), argDir ?? dir);
|
|
125
135
|
const name = path.basename(target);
|
|
126
136
|
if (existsSync(target)) {
|
|
127
|
-
const { overwrite } = await prompts({
|
|
137
|
+
const { overwrite } = await prompts({
|
|
138
|
+
type: 'confirm',
|
|
139
|
+
name: 'overwrite',
|
|
140
|
+
message: `${name} exists - continue and fill missing files?`,
|
|
141
|
+
initial: false
|
|
142
|
+
}, { onCancel });
|
|
128
143
|
if (!overwrite)
|
|
129
144
|
process.exit(0);
|
|
130
145
|
}
|
|
146
|
+
const { host } = (await prompts({
|
|
147
|
+
type: 'select',
|
|
148
|
+
name: 'host',
|
|
149
|
+
message: 'App host',
|
|
150
|
+
choices: [
|
|
151
|
+
{ title: 'Vite (SPA)', value: 'vite' },
|
|
152
|
+
{ title: 'Nuxt (SSR, @ui0/nuxt)', value: 'nuxt' }
|
|
153
|
+
],
|
|
154
|
+
initial: 0
|
|
155
|
+
}, { onCancel }));
|
|
131
156
|
const { features } = (await prompts({
|
|
132
157
|
type: 'multiselect',
|
|
133
158
|
name: 'features',
|
|
134
|
-
message: 'Packages to include',
|
|
159
|
+
message: host === 'nuxt' ? 'Demo sections to include' : 'Packages to include',
|
|
135
160
|
choices: FEATURES.map((f) => ({ title: f.title, value: f.id, selected: f.id !== 'icon' })),
|
|
136
161
|
instructions: false
|
|
137
162
|
}, { onCancel }));
|
|
163
|
+
// the nuxt flavour lives in its own template; @ui0/nuxt already carries
|
|
164
|
+
// every runtime package, so for nuxt the features only drive demo sections
|
|
165
|
+
const sourceDir = host === 'nuxt' ? templateNuxtDir : templateDir;
|
|
138
166
|
mkdirSync(target, { recursive: true });
|
|
139
|
-
cpSync(
|
|
167
|
+
cpSync(sourceDir, target, { recursive: true });
|
|
140
168
|
rmSync(path.join(target, 'package.json.tpl'));
|
|
141
169
|
const picked = FEATURES.filter((f) => features.includes(f.id));
|
|
142
|
-
// package.json from the template manifest + chosen deps
|
|
143
|
-
|
|
170
|
+
// package.json from the template manifest + chosen deps (vite hosts only;
|
|
171
|
+
// the nuxt manifest already depends on @ui0/nuxt, which bundles the rest)
|
|
172
|
+
const manifest = JSON.parse(readFileSync(path.join(sourceDir, 'package.json.tpl'), 'utf8'));
|
|
144
173
|
manifest.name = name;
|
|
145
|
-
|
|
174
|
+
if (host !== 'nuxt')
|
|
175
|
+
Object.assign(manifest.dependencies, ...picked.map((f) => f.deps));
|
|
146
176
|
writeFileSync(path.join(target, 'package.json'), JSON.stringify(manifest, null, 2) + '\n');
|
|
147
|
-
// App.vue
|
|
148
|
-
|
|
177
|
+
// app entry: src/App.vue (vite) or app/app.vue (nuxt) - inject the demo
|
|
178
|
+
// sections of the picked features; the nuxt module auto-registers the
|
|
179
|
+
// components, so no imports are added there
|
|
180
|
+
const appVue = path.join(target, host === 'nuxt' ? path.join('app', 'app.vue') : path.join('src', 'App.vue'));
|
|
149
181
|
let app = readFileSync(appVue, 'utf8');
|
|
150
182
|
app = app
|
|
151
|
-
.replace('/* FEATURE_IMPORTS */', picked.map((f) => f.importLine).join('\n'))
|
|
183
|
+
.replace('/* FEATURE_IMPORTS */', host === 'nuxt' ? '' : picked.map((f) => f.importLine).join('\n'))
|
|
152
184
|
.replace('/* FEATURE_SECTIONS */', picked.map((f) => f.section).join('\n\n'));
|
|
153
185
|
writeFileSync(appVue, app);
|
|
154
|
-
// the icon pack registers itself as a vue plugin
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
main =
|
|
159
|
-
|
|
160
|
-
|
|
186
|
+
// the icon pack registers itself as a vue plugin (vite hosts only - the
|
|
187
|
+
// nuxt module wires the icon framework and the pack itself)
|
|
188
|
+
if (host !== 'nuxt') {
|
|
189
|
+
const mainTs = path.join(target, 'src', 'main.ts');
|
|
190
|
+
let main = readFileSync(mainTs, 'utf8');
|
|
191
|
+
if (features.includes('icon')) {
|
|
192
|
+
main = main
|
|
193
|
+
.replace("import { createUi0 } from '@ui0/core'", "import Icons from '@ui0/icons'\nimport { createUi0 } from '@ui0/core'")
|
|
194
|
+
.replace('app.use(ui0)', 'app.use(ui0)\napp.use(Icons)');
|
|
195
|
+
}
|
|
196
|
+
writeFileSync(mainTs, main);
|
|
161
197
|
}
|
|
162
|
-
writeFileSync(mainTs, main);
|
|
163
198
|
console.log(`\nScaffolded ${name}:\n`);
|
|
164
199
|
console.log(` cd ${path.relative(process.cwd(), target)}`);
|
|
165
200
|
console.log(' npm install');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-ui0",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Scaffold a ui0 (Vue + @ui0) app - npm create ui0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
11
|
"template",
|
|
12
|
+
"template-nuxt",
|
|
12
13
|
"template-component"
|
|
13
14
|
],
|
|
14
15
|
"scripts": {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ThemeProvider preset="app">
|
|
3
|
+
<main :class="$style.page">
|
|
4
|
+
<h1>ui0 app</h1>
|
|
5
|
+
|
|
6
|
+
/* FEATURE_SECTIONS */
|
|
7
|
+
</main>
|
|
8
|
+
</ThemeProvider>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup lang="ts">
|
|
12
|
+
// ThemeProvider / Flex / Button / Icon are auto-registered by @ui0/nuxt
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<style module lang="scss">
|
|
16
|
+
.page {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
gap: 24px;
|
|
20
|
+
padding: 32px;
|
|
21
|
+
font-family: system-ui, sans-serif;
|
|
22
|
+
|
|
23
|
+
h1 {
|
|
24
|
+
font-size: 20px;
|
|
25
|
+
}
|
|
26
|
+
h2 {
|
|
27
|
+
font-size: 14px;
|
|
28
|
+
opacity: 0.7;
|
|
29
|
+
margin-bottom: 8px;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
.box {
|
|
33
|
+
padding: 12px 16px;
|
|
34
|
+
border: 1px solid rgba(127, 127, 127, 0.4);
|
|
35
|
+
border-radius: 6px;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ui0-app",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "nuxt dev",
|
|
8
|
+
"build": "nuxt build",
|
|
9
|
+
"preview": "nuxt preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@ui0/nuxt": "^0.1.0",
|
|
13
|
+
"nuxt": "^4.6.4",
|
|
14
|
+
"vue": "^3.5.45"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@ui0/types": "^0.1.2",
|
|
18
|
+
"sass-embedded": "^1.80.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Ui0CoreConfig } from '@ui0/types'
|
|
2
|
+
|
|
3
|
+
const config: Ui0CoreConfig = {
|
|
4
|
+
theme: {
|
|
5
|
+
default: 'app',
|
|
6
|
+
contracts: {
|
|
7
|
+
display: {}
|
|
8
|
+
},
|
|
9
|
+
presets: {
|
|
10
|
+
app: {
|
|
11
|
+
default: {
|
|
12
|
+
color: {
|
|
13
|
+
brand: ['rgb(86 59 177)', 4],
|
|
14
|
+
foreground: '#111',
|
|
15
|
+
background: '#fff'
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default config
|