create-yoya-ui 0.1.0

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.
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
4
+ import { join, resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const templateDir = resolve(fileURLToPath(new URL('../templates/basic', import.meta.url)));
8
+ const args = process.argv.slice(2);
9
+ const targetName = args[0] || 'yoya-ui-app';
10
+ const targetDir = resolve(process.cwd(), targetName);
11
+
12
+ if (existsSync(targetDir) && readdirSafe(targetDir).length > 0) {
13
+ console.error(`目标目录已存在且非空:${targetDir}`);
14
+ process.exit(1);
15
+ }
16
+
17
+ mkdirSync(targetDir, { recursive: true });
18
+ cpSync(templateDir, targetDir, { recursive: true });
19
+
20
+ // 把模板 package.json 的 name 改为目标目录名
21
+ const packagePath = join(targetDir, 'package.json');
22
+ const pkg = JSON.parse(readFileSync(packagePath, 'utf8'));
23
+ pkg.name = sanitizeName(targetName);
24
+ writeFileSync(packagePath, `${JSON.stringify(pkg, null, 2)}\n`);
25
+
26
+ console.log(`\n已创建 yoya-ui 项目:${targetName}\n`);
27
+ console.log(` cd ${targetName}`);
28
+ console.log(' npm install');
29
+ console.log(' npm run dev');
30
+ console.log('\n更多:npm run build 构建,npm run preview 预览产物。\n');
31
+
32
+ function sanitizeName(name) {
33
+ return name
34
+ .trim()
35
+ .toLowerCase()
36
+ .replace(/[^a-z0-9-_./@]/g, '-')
37
+ .replace(/^[._]+/, '');
38
+ }
39
+
40
+ function readdirSafe(dir) {
41
+ try {
42
+ return readdirSync(dir);
43
+ } catch {
44
+ return [];
45
+ }
46
+ }
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "create-yoya-ui",
3
+ "version": "0.1.0",
4
+ "description": "Scaffold a new yoya-ui project with Vite: quick start template with example page, form and theme switching.",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-yoya-ui": "bin/create-yoya-ui.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "templates"
12
+ ],
13
+ "keywords": [
14
+ "yoya-ui",
15
+ "scaffold",
16
+ "vite",
17
+ "template"
18
+ ],
19
+ "license": "MIT",
20
+ "engines": {
21
+ "node": "^20.19.0 || ^22.13.0 || >=24.0.0"
22
+ }
23
+ }
@@ -0,0 +1,27 @@
1
+ # yoya-ui 示例项目
2
+
3
+ 基于 [yoya-ui](https://github.com/yoyaflow/yoya-ui) 的快速开始模板,包含:
4
+
5
+ - 页面壳(vBody,主题 token 自动跟随)
6
+ - 按钮与事件(快捷方法返回父节点,事件用回调参数)
7
+ - 表单收集与校验(vForm + vFormItem)
8
+ - 明暗模式切换(data-yoya-mode)
9
+
10
+ ## 启动
11
+
12
+ ```bash
13
+ npm install
14
+ npm run dev
15
+ ```
16
+
17
+ ## 构建
18
+
19
+ ```bash
20
+ npm run build
21
+ npm run preview
22
+ ```
23
+
24
+ ## 学习资源
25
+
26
+ - 组件使用说明、表单、主题、SSR 与业务模块组织见 yoya-ui skill(`skills/yoya-ui`)
27
+ - 完整 API 见包内类型声明(`types/*.d.ts`)
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>yoya-ui 示例项目</title>
7
+ </head>
8
+ <body>
9
+ <div id="app"></div>
10
+ <script type="module" src="/src/main.js"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "yoya-ui-app",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "@yoyaflow/yoya-ui": "^0.1.0"
13
+ },
14
+ "devDependencies": {
15
+ "vite": "^8.2.0"
16
+ }
17
+ }
@@ -0,0 +1,77 @@
1
+ import { div, toast, vBody, vButton, vCard, vForm, vFormItem, vInput, vSelect, vText } from '@yoyaflow/yoya-ui';
2
+ import '@yoyaflow/yoya-ui/ui.css';
3
+
4
+ // 页面壳:消费主题 token,明暗切换自动跟随
5
+ const page = vBody({
6
+ maxWidth: 860,
7
+ children: [
8
+ div((root) => {
9
+ root.h1('yoya-ui 快速开始');
10
+ root.p('声明式组件、表单收集、主题切换一条命令跑通。');
11
+
12
+ // 示例卡片:按钮 + 事件(快捷方法返回父节点,事件用回调参数)
13
+ const output = vText('未点击');
14
+ root.vCard((card) => {
15
+ card.vCardHeader('按钮示例');
16
+ card.vCardBody((body) => {
17
+ body.vstack({ gap: '12px' }, (stack) => {
18
+ stack.p('点击按钮,事件绑定在回调参数里。');
19
+ stack.hstack((row) => {
20
+ row.vButton('点击我', (btn) => {
21
+ btn.variant('primary');
22
+ btn.on('click', () => {
23
+ output.textContent('已点击:' + new Date().toLocaleTimeString());
24
+ });
25
+ });
26
+ row.vButton('提示', (btn) => btn.on('click', () => toast.info('yoya-ui 已就绪')));
27
+ row.spacer();
28
+ row.child(output);
29
+ });
30
+ });
31
+ });
32
+ });
33
+
34
+ // 表单示例:vForm + vFormItem 收集与校验
35
+ const form = vForm((form) => {
36
+ form.vFormItem((item) => {
37
+ item.label('服务名').name('service').required({ message: '请填写服务名' });
38
+ item.control((editor) => editor.vInput({ name: 'service', value: 'api-gateway' }));
39
+ });
40
+ form.vFormItem((item) => {
41
+ item.label('环境').name('env').required({ message: '请选择环境' });
42
+ item.control((editor) => editor.vSelect({ name: 'env', options: ['dev', 'prod'] }));
43
+ });
44
+ form.vButton('提交', (btn) => {
45
+ btn.variant('primary');
46
+ btn.on('click', () => {
47
+ if (form.validate()) {
48
+ toast.success('提交成功:' + JSON.stringify(form.values()));
49
+ }
50
+ });
51
+ });
52
+ });
53
+ root.vCard((card) => {
54
+ card.vCardHeader('表单示例');
55
+ card.vCardBody((body) => body.child(form));
56
+ });
57
+
58
+ // 主题切换:明暗模式
59
+ root.vCard((card) => {
60
+ card.vCardHeader('主题');
61
+ card.vCardBody((body) => {
62
+ body.hstack((row) => {
63
+ row.vButton('深色模式', (btn) => btn.on('click', () => setMode('dark')));
64
+ row.vButton('浅色模式', (btn) => btn.on('click', () => setMode('light')));
65
+ row.vButton('跟随系统', (btn) => btn.on('click', () => setMode('system')));
66
+ });
67
+ });
68
+ });
69
+ })
70
+ ]
71
+ });
72
+
73
+ page.bindTo('#app');
74
+
75
+ function setMode(mode) {
76
+ document.documentElement.setAttribute('data-yoya-mode', mode);
77
+ }
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'vite';
2
+
3
+ export default defineConfig({
4
+ server: {
5
+ port: 5173
6
+ }
7
+ });