create-ui0 0.1.2 → 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.js CHANGED
@@ -8,12 +8,16 @@ import prompts from 'prompts';
8
8
  * Usage: npm create ui0 [dir]
9
9
  */
10
10
  const templateDir = fileURLToPath(new URL('../template', import.meta.url));
11
+ const templateNuxtDir = fileURLToPath(new URL('../template-nuxt', import.meta.url));
11
12
  const componentTemplateDir = fileURLToPath(new URL('../template-component', import.meta.url));
12
13
  const toKebab = (s) => s
13
14
  .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
14
15
  .replace(/[\s_]+/g, '-')
15
16
  .toLowerCase();
16
- const toPascal = (s) => s.split(/[-\s_]+/).map((w) => w[0].toUpperCase() + w.slice(1)).join('');
17
+ const toPascal = (s) => s
18
+ .split(/[-\s_]+/)
19
+ .map((w) => w[0].toUpperCase() + w.slice(1))
20
+ .join('');
17
21
  const toCamel = (s) => {
18
22
  const p = toPascal(s);
19
23
  return p[0].toLowerCase() + p.slice(1);
@@ -81,7 +85,12 @@ const runComponent = async () => {
81
85
  message: 'Target directory',
82
86
  initial: path.join('src', 'components', kebab)
83
87
  }, { onCancel });
84
- const { spec } = await prompts({ type: 'confirm', name: 'spec', message: 'Include a vitest spec (adds vitest + @vue/test-utils to devDependencies)?', initial: false }, { onCancel });
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 });
85
94
  const dir = path.resolve(process.cwd(), target);
86
95
  if (existsSync(dir)) {
87
96
  console.error(`${target} already exists`);
@@ -125,42 +134,67 @@ const run = async () => {
125
134
  const target = path.resolve(process.cwd(), argDir ?? dir);
126
135
  const name = path.basename(target);
127
136
  if (existsSync(target)) {
128
- const { overwrite } = await prompts({ type: 'confirm', name: 'overwrite', message: `${name} exists - continue and fill missing files?`, initial: false }, { onCancel });
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 });
129
143
  if (!overwrite)
130
144
  process.exit(0);
131
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 }));
132
156
  const { features } = (await prompts({
133
157
  type: 'multiselect',
134
158
  name: 'features',
135
- message: 'Packages to include',
159
+ message: host === 'nuxt' ? 'Demo sections to include' : 'Packages to include',
136
160
  choices: FEATURES.map((f) => ({ title: f.title, value: f.id, selected: f.id !== 'icon' })),
137
161
  instructions: false
138
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;
139
166
  mkdirSync(target, { recursive: true });
140
- cpSync(templateDir, target, { recursive: true });
167
+ cpSync(sourceDir, target, { recursive: true });
141
168
  rmSync(path.join(target, 'package.json.tpl'));
142
169
  const picked = FEATURES.filter((f) => features.includes(f.id));
143
- // package.json from the template manifest + chosen deps
144
- const manifest = JSON.parse(readFileSync(path.join(templateDir, 'package.json.tpl'), 'utf8'));
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'));
145
173
  manifest.name = name;
146
- Object.assign(manifest.dependencies, ...picked.map((f) => f.deps));
174
+ if (host !== 'nuxt')
175
+ Object.assign(manifest.dependencies, ...picked.map((f) => f.deps));
147
176
  writeFileSync(path.join(target, 'package.json'), JSON.stringify(manifest, null, 2) + '\n');
148
- // App.vue: inject the demo sections of the picked features
149
- const appVue = path.join(target, 'src/App.vue');
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'));
150
181
  let app = readFileSync(appVue, 'utf8');
151
182
  app = app
152
- .replace('/* FEATURE_IMPORTS */', picked.map((f) => f.importLine).join('\n'))
183
+ .replace('/* FEATURE_IMPORTS */', host === 'nuxt' ? '' : picked.map((f) => f.importLine).join('\n'))
153
184
  .replace('/* FEATURE_SECTIONS */', picked.map((f) => f.section).join('\n\n'));
154
185
  writeFileSync(appVue, app);
155
- // the icon pack registers itself as a vue plugin
156
- const mainTs = path.join(target, 'src/main.ts');
157
- let main = readFileSync(mainTs, 'utf8');
158
- if (features.includes('icon')) {
159
- main = main
160
- .replace("import { createUi0 } from '@ui0/core'", "import Icons from '@ui0/icons'\nimport { createUi0 } from '@ui0/core'")
161
- .replace('app.use(ui0)', 'app.use(ui0)\napp.use(Icons)');
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);
162
197
  }
163
- writeFileSync(mainTs, main);
164
198
  console.log(`\nScaffolded ${name}:\n`);
165
199
  console.log(` cd ${path.relative(process.cwd(), target)}`);
166
200
  console.log(' npm install');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ui0",
3
- "version": "0.1.2",
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,7 @@
1
+ export default defineNuxtConfig({
2
+ ssr: true,
3
+ compatibilityDate: '2026-11-12',
4
+ devtools: { enabled: false },
5
+ // theme css pipeline, core+theme runtime and component auto-imports
6
+ modules: ['@ui0/nuxt']
7
+ })
@@ -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,4 @@
1
+ {
2
+ // generated by nuxt (prepare) - the project config extends it
3
+ "extends": "./.nuxt/tsconfig.json"
4
+ }
@@ -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