create-ui0 0.1.3 → 0.1.4

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
@@ -6,6 +6,8 @@ import prompts from 'prompts';
6
6
  /**
7
7
  * create-ui0 - scaffolds a ui0 (Vue + @ui0 packages) app.
8
8
  * Usage: npm create ui0 [dir]
9
+ * npm create ui0 [dir] [vite|nuxt] [features] (non-interactive;
10
+ * features: comma list of flex,button,icon)
9
11
  */
10
12
  const templateDir = fileURLToPath(new URL('../template', import.meta.url));
11
13
  const templateNuxtDir = fileURLToPath(new URL('../template-nuxt', import.meta.url));
@@ -32,8 +34,9 @@ const FEATURES = [
32
34
  {
33
35
  id: 'flex',
34
36
  title: 'Flex layout',
35
- deps: { '@ui0/flex': '^0.1.1' },
37
+ deps: { '@ui0/flex': '^0.1.3' },
36
38
  importLine: "import Flex from '@ui0/flex'",
39
+ cssLines: ["'@ui0/flex/style.css'"],
37
40
  section: ` <section>
38
41
  <h2>Flex</h2>
39
42
  <Flex items="center">
@@ -46,8 +49,9 @@ const FEATURES = [
46
49
  {
47
50
  id: 'button',
48
51
  title: 'Button component',
49
- deps: { '@ui0/button': '^0.1.1' },
52
+ deps: { '@ui0/button': '^0.1.3' },
50
53
  importLine: "import Button from '@ui0/button'",
54
+ cssLines: ["'@ui0/button/style.css'"],
51
55
  section: ` <section>
52
56
  <h2>Button</h2>
53
57
  <Button>default</Button>
@@ -56,11 +60,19 @@ const FEATURES = [
56
60
  {
57
61
  id: 'icon',
58
62
  title: 'Icon component + ui0 icon pack',
59
- deps: { '@ui0/icon': '^0.1.1', '@ui0/icons': '^0.1.1' },
63
+ deps: { '@ui0/icon': '^0.1.3', '@ui0/icons': '^0.1.3' },
60
64
  importLine: "import { Icon } from '@ui0/icon'",
65
+ cssLines: ["'@ui0/icon/style.css'", "'@ui0/icons/style.css'"],
61
66
  section: ` <section>
62
67
  <h2>Icon</h2>
63
68
  <Icon value="ui0/heart-alt" />
69
+ </section>`,
70
+ // the nuxt template also wires the svg loader, so the demo shows an
71
+ // app-local icon next to the built-in pack one
72
+ sectionNuxt: ` <section>
73
+ <h2>Icon</h2>
74
+ <Icon value="ui0/heart-alt" />
75
+ <Icon value="assets/icons/bookmark" />
64
76
  </section>`
65
77
  }
66
78
  ];
@@ -125,6 +137,8 @@ const run = async () => {
125
137
  return;
126
138
  }
127
139
  const argDir = process.argv[2];
140
+ const argHost = process.argv[3];
141
+ const argFeatures = process.argv[4]?.split(',').filter(Boolean);
128
142
  const { dir } = await prompts({
129
143
  type: argDir ? null : 'text',
130
144
  name: 'dir',
@@ -143,8 +157,8 @@ const run = async () => {
143
157
  if (!overwrite)
144
158
  process.exit(0);
145
159
  }
146
- const { host } = (await prompts({
147
- type: 'select',
160
+ const { host: pickedHost } = (await prompts({
161
+ type: argHost ? null : 'select',
148
162
  name: 'host',
149
163
  message: 'App host',
150
164
  choices: [
@@ -153,36 +167,57 @@ const run = async () => {
153
167
  ],
154
168
  initial: 0
155
169
  }, { onCancel }));
156
- const { features } = (await prompts({
157
- type: 'multiselect',
170
+ const host = argHost ?? pickedHost;
171
+ const { features: pickedFeatures } = (await prompts({
172
+ type: argFeatures ? null : 'multiselect',
158
173
  name: 'features',
159
- message: host === 'nuxt' ? 'Demo sections to include' : 'Packages to include',
174
+ message: 'Packages to include',
160
175
  choices: FEATURES.map((f) => ({ title: f.title, value: f.id, selected: f.id !== 'icon' })),
161
176
  instructions: false
162
177
  }, { 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
178
+ const features = argFeatures ?? pickedFeatures ?? [];
179
+ // the nuxt flavour lives in its own template, in manual-import mode
180
+ // (components: false): the picked features drive the imports in app.vue,
181
+ // the demo sections and the built styles in the nuxt css pipeline
165
182
  const sourceDir = host === 'nuxt' ? templateNuxtDir : templateDir;
166
183
  mkdirSync(target, { recursive: true });
167
184
  cpSync(sourceDir, target, { recursive: true });
168
185
  rmSync(path.join(target, 'package.json.tpl'));
169
186
  const picked = FEATURES.filter((f) => features.includes(f.id));
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)
187
+ // package.json from the template manifest + the chosen feature deps (the
188
+ // nuxt template pins @ui0/core + @ui0/theme itself for the manual imports)
172
189
  const manifest = JSON.parse(readFileSync(path.join(sourceDir, 'package.json.tpl'), 'utf8'));
173
190
  manifest.name = name;
174
- if (host !== 'nuxt')
175
- Object.assign(manifest.dependencies, ...picked.map((f) => f.deps));
191
+ Object.assign(manifest.dependencies, ...picked.map((f) => f.deps));
176
192
  writeFileSync(path.join(target, 'package.json'), JSON.stringify(manifest, null, 2) + '\n');
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
193
+ // app entry: src/App.vue (vite) or app/app.vue (nuxt) - inject the imports
194
+ // and the demo sections of the picked features
180
195
  const appVue = path.join(target, host === 'nuxt' ? path.join('app', 'app.vue') : path.join('src', 'App.vue'));
181
196
  let app = readFileSync(appVue, 'utf8');
182
197
  app = app
183
- .replace('/* FEATURE_IMPORTS */', host === 'nuxt' ? '' : picked.map((f) => f.importLine).join('\n'))
184
- .replace('/* FEATURE_SECTIONS */', picked.map((f) => f.section).join('\n\n'));
198
+ .replace('/* FEATURE_IMPORTS */', picked.map((f) => f.importLine).join('\n'))
199
+ .replace('/* FEATURE_SECTIONS */', picked.map((f) => (host === 'nuxt' ? (f.sectionNuxt ?? f.section) : f.section)).join('\n\n'));
185
200
  writeFileSync(appVue, app);
201
+ // nuxt manual mode: the picked features' built styles join the css
202
+ // pipeline, the icon feature wires the svg loader (the template ships
203
+ // sample icons under assets/ - they need the configured dir to exist)
204
+ if (host === 'nuxt') {
205
+ const nuxtConfigPath = path.join(target, 'nuxt.config.ts');
206
+ const withIcons = features.includes('icon');
207
+ const configSrc = readFileSync(nuxtConfigPath, 'utf8')
208
+ .replace('/* FEATURE_VITE_IMPORT */', withIcons ? "import { fileURLToPath } from 'node:url'\n\nimport ViteUi0Icon from '@ui0/icon/vite'\n" : '')
209
+ .replace('/* FEATURE_VITE_PLUGINS */',
210
+ // absolute on purpose: nuxt's vite root is the app/ dir, relative
211
+ // dirs would resolve against it. dir is the scan root - an svg at
212
+ // <dir>/icons/bookmark.svg is addressed 'assets/icons/bookmark'
213
+ withIcons ? "ViteUi0Icon({ dir: fileURLToPath(new URL('./assets', import.meta.url)) })" : '')
214
+ .replace('/* FEATURE_CSS */',
215
+ // the placeholder trails the array's first entry - lead with a comma
216
+ picked.length ? `,\n ${picked.flatMap((f) => f.cssLines ?? []).join(',\n ')}` : '');
217
+ writeFileSync(nuxtConfigPath, configSrc);
218
+ if (!withIcons)
219
+ rmSync(path.join(target, 'assets'), { recursive: true, force: true });
220
+ }
186
221
  // the icon pack registers itself as a vue plugin (vite hosts only - the
187
222
  // nuxt module wires the icon framework and the pack itself)
188
223
  if (host !== 'nuxt') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ui0",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Scaffold a ui0 (Vue + @ui0) app - npm create ui0",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,7 +14,7 @@
14
14
  ],
15
15
  "scripts": {
16
16
  "create:build": "tsc -p tsconfig.json",
17
- "create:publish": "npm publish --access public"
17
+ "create:publish": "node ../../scripts/publish-packages.ts"
18
18
  },
19
19
  "dependencies": {
20
20
  "prompts": "^2.4.2"
@@ -9,7 +9,8 @@
9
9
  </template>
10
10
 
11
11
  <script setup lang="ts">
12
- // ThemeProvider / Flex / Button / Icon are auto-registered by @ui0/nuxt
12
+ import { ThemeProvider } from '@ui0/theme/theme-provider'
13
+ /* FEATURE_IMPORTS */
13
14
  </script>
14
15
 
15
16
  <style module lang="scss">
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 960">
2
+ <path d="M629.531,180H330.469c-27.528,0-49.844,24.345-49.844,54.375V760L480,609.63,679.375,760V234.375C679.375,204.345,657.061,180,629.531,180Z"/>
3
+ </svg>
@@ -1,7 +1,25 @@
1
+ /* FEATURE_VITE_IMPORT */
1
2
  export default defineNuxtConfig({
2
3
  ssr: true,
3
4
  compatibilityDate: '2026-11-12',
4
5
  devtools: { enabled: false },
5
- // theme css pipeline, core+theme runtime and component auto-imports
6
- modules: ['@ui0/nuxt']
6
+ // built ui0 component styles ship in the head of every ssr response; the
7
+ // module pushes @ui0/core/style.css itself - one entry per ui0 component
8
+ // the app renders (app/app.vue imports them in code, manual mode below)
9
+ css: ['@ui0/theme/theme-provider/style.css'/* FEATURE_CSS */],
10
+ modules: ['@ui0/nuxt'],
11
+ ui0: {
12
+ // manual component imports: no auto-registration, the template imports
13
+ // Flex / Button / Icon / ThemeProvider in app/app.vue and lists their
14
+ // style.css above
15
+ components: false
16
+ },
17
+ vite: {
18
+ plugins: [
19
+ // the svg icon loader - only for the app's OWN icons (dir) and
20
+ // compositions (virtual); the built-in ui0 pack ships prebuilt from
21
+ // @ui0/icons and needs no loader
22
+ /* FEATURE_VITE_PLUGINS */
23
+ ]
24
+ }
7
25
  })
@@ -9,12 +9,14 @@
9
9
  "preview": "nuxt preview"
10
10
  },
11
11
  "dependencies": {
12
- "@ui0/nuxt": "^0.1.0",
12
+ "@ui0/core": "^0.1.4",
13
+ "@ui0/nuxt": "^0.1.1",
14
+ "@ui0/theme": "^0.1.4",
13
15
  "nuxt": "^4.6.4",
14
16
  "vue": "^3.5.45"
15
17
  },
16
18
  "devDependencies": {
17
- "@ui0/types": "^0.1.2",
19
+ "@ui0/types": "^0.1.4",
18
20
  "sass-embedded": "^1.80.0"
19
21
  }
20
22
  }