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 CHANGED
@@ -1,2 +1,3 @@
1
+ #!/usr/bin/env node
1
2
  export {};
2
3
  //# sourceMappingURL=index.d.ts.map
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.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('');
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({ 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 });
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({ 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 });
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(templateDir, target, { recursive: true });
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
- 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'));
144
173
  manifest.name = name;
145
- Object.assign(manifest.dependencies, ...picked.map((f) => f.deps));
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: inject the demo sections of the picked features
148
- 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'));
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
- const mainTs = path.join(target, 'src/main.ts');
156
- let main = readFileSync(mainTs, 'utf8');
157
- if (features.includes('icon')) {
158
- main = main
159
- .replace("import { createUi0 } from '@ui0/core'", "import Icons from '@ui0/icons'\nimport { createUi0 } from '@ui0/core'")
160
- .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);
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.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,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