zmp-cli 3.5.4 → 3.6.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.
- package/.vscode/launch.json +21 -0
- package/.vscode/settings.json +2 -1
- package/create/templates/common/tailwind/tailwind.config.js +1 -1
- package/create/templates/generate-index.js +1 -1
- package/create/templates/generate-routes.js +2 -2
- package/create/templates/generate-store.js +33 -0
- package/create/templates/generate-styles.js +19 -10
- package/create/templates/vue/components/header.vue +28 -0
- package/create/templates/vue/components/sun-and-moon.vue +34 -0
- package/create/templates/vue/copy-assets.js +28 -7
- package/create/templates/vue/dist/copy-assets.dev.js +1 -1
- package/create/templates/vue/generate-home-page.js +49 -103
- package/create/templates/vue/generate-root.js +30 -193
- package/create/templates/vue/generate-routes.js +2 -87
- package/create/templates/vue/generate-scripts.js +8 -3
- package/create/templates/vue/global-components.d.ts +121 -0
- package/create/templates/vue/icons/moon.svg +3 -0
- package/create/templates/vue/icons/sun.svg +3 -0
- package/create/templates/vue/pages/settings.vue +14 -158
- package/create/templates/vue/vite.config.js +11 -0
- package/create/utils/generate-package-json.js +14 -6
- package/create/utils/get-options.js +7 -8
- package/index.js +1 -0
- package/package.json +1 -1
- package/start/dist/index.dev.js +65 -28
- package/start/index.js +41 -4
- package/utils/find-files-by-ext.js +1 -1
- package/create/templates/common/icons/128x128.png +0 -0
- package/create/templates/common/icons/144x144.png +0 -0
- package/create/templates/common/icons/152x152.png +0 -0
- package/create/templates/common/icons/192x192.png +0 -0
- package/create/templates/common/icons/256x256.png +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"type": "pwa-node",
|
|
9
|
+
"request": "launch",
|
|
10
|
+
"name": "Launch Program",
|
|
11
|
+
"skipFiles": [
|
|
12
|
+
"<node_internals>/**"
|
|
13
|
+
],
|
|
14
|
+
"program": "${workspaceFolder}/index.js",
|
|
15
|
+
"args": [
|
|
16
|
+
"init"
|
|
17
|
+
],
|
|
18
|
+
"console": "integratedTerminal"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
package/.vscode/settings.json
CHANGED
|
@@ -10,7 +10,7 @@ module.exports = (options) => {
|
|
|
10
10
|
const scripts = `
|
|
11
11
|
<!-- built script files will be auto injected -->
|
|
12
12
|
${
|
|
13
|
-
framework === 'react'
|
|
13
|
+
framework === 'react' || framework === 'vue'
|
|
14
14
|
? `<script type="module" src="${srcFolder}app.js"></script>`
|
|
15
15
|
: ''
|
|
16
16
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// const generateCoreRoutes = require('./core/generate-routes');
|
|
2
|
-
|
|
2
|
+
const generateVueRoutes = require('./vue/generate-routes');
|
|
3
3
|
const generateReactRoutes = require('./react/generate-routes');
|
|
4
4
|
const generateReactTsRoutes = require('./react-typescript/generate-routes');
|
|
5
5
|
// const generateSvelteRoutes = require('./svelte/generate-routes');
|
|
@@ -7,7 +7,7 @@ const generateReactTsRoutes = require('./react-typescript/generate-routes');
|
|
|
7
7
|
module.exports = (options) => {
|
|
8
8
|
const { framework } = options;
|
|
9
9
|
// if (framework === 'core') return generateCoreRoutes(options);
|
|
10
|
-
|
|
10
|
+
if (framework === 'vue') return generateVueRoutes(options);
|
|
11
11
|
if (framework === 'react') return generateReactRoutes(options);
|
|
12
12
|
if (framework === 'react-typescript') return generateReactTsRoutes(options);
|
|
13
13
|
|
|
@@ -4,6 +4,39 @@ const templateIf = require('../utils/template-if');
|
|
|
4
4
|
|
|
5
5
|
module.exports = (options) => {
|
|
6
6
|
const { framework } = options;
|
|
7
|
+
if (framework === 'vue') {
|
|
8
|
+
return indent(0, `
|
|
9
|
+
import { createStore } from 'zmp-core/lite';
|
|
10
|
+
const store = createStore({
|
|
11
|
+
state: {
|
|
12
|
+
user: {
|
|
13
|
+
id: '',
|
|
14
|
+
name: '',
|
|
15
|
+
avatar: ''
|
|
16
|
+
},
|
|
17
|
+
darkMode: false,
|
|
18
|
+
},
|
|
19
|
+
getters: {
|
|
20
|
+
user({ state }) {
|
|
21
|
+
return state.user
|
|
22
|
+
},
|
|
23
|
+
darkMode({ state }) {
|
|
24
|
+
return state.darkMode
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
actions: {
|
|
28
|
+
setUser({ state }, data) {
|
|
29
|
+
state.user = { ...state.user, ...data }
|
|
30
|
+
},
|
|
31
|
+
setDarkMode({ state }, dark) {
|
|
32
|
+
state.darkMode = dark
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
export default store;
|
|
38
|
+
`);
|
|
39
|
+
}
|
|
7
40
|
return indent(0, `
|
|
8
41
|
import { createStore } from 'zmp-core${framework === 'core' ? '' : '/lite'}';
|
|
9
42
|
const store = createStore({
|
|
@@ -2,7 +2,7 @@ const indent = require('../utils/indent');
|
|
|
2
2
|
const { colorThemeCSSProperties } = require('../utils/colors');
|
|
3
3
|
|
|
4
4
|
module.exports = (options) => {
|
|
5
|
-
const { template, theming } = options;
|
|
5
|
+
const { template, theming, includeTailwind } = options;
|
|
6
6
|
const { customColor, color, fillBars } = theming;
|
|
7
7
|
|
|
8
8
|
let styles = '';
|
|
@@ -19,18 +19,18 @@ module.exports = (options) => {
|
|
|
19
19
|
/* Custom color theme properties */
|
|
20
20
|
:root {
|
|
21
21
|
${Object.keys(customProps)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
.filter(
|
|
23
|
+
(prop) =>
|
|
24
|
+
prop !== '--zmp-tabbar-fill-link-active-color' &&
|
|
25
|
+
prop !== '--zmp-tabbar-fill-link-active-border-color'
|
|
26
|
+
)
|
|
27
|
+
.map((prop) => `${prop}: ${customProps[prop]};`)
|
|
28
|
+
.join('\n ')}
|
|
29
29
|
}
|
|
30
30
|
:root.theme-dark,:root .theme-dark {
|
|
31
31
|
${Object.keys(customProps)
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
.map((prop) => `${prop}: ${customProps[prop]};`)
|
|
33
|
+
.join('\n ')}
|
|
34
34
|
}
|
|
35
35
|
`
|
|
36
36
|
);
|
|
@@ -44,6 +44,15 @@ module.exports = (options) => {
|
|
|
44
44
|
);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
if (includeTailwind) {
|
|
48
|
+
styles += indent(
|
|
49
|
+
0,
|
|
50
|
+
`
|
|
51
|
+
@import "./tailwind.css";
|
|
52
|
+
`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
47
56
|
if (template === 'split-view') {
|
|
48
57
|
styles += indent(
|
|
49
58
|
0,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<zmp-navbar>
|
|
3
|
+
<zmp-nav-left>
|
|
4
|
+
<zmp-skeleton-avatar v-if="!user.id" class="pt-2"></zmp-skeleton-avatar>
|
|
5
|
+
<zmp-avatar v-else :src="user.avatar" online />
|
|
6
|
+
</zmp-nav-left>
|
|
7
|
+
<zmp-nav-title v-if="!user.id">
|
|
8
|
+
<zmp-skeleton-text>
|
|
9
|
+
<zmp-title class="mb-0">Lorem ipsum</zmp-title>
|
|
10
|
+
</zmp-skeleton-text>
|
|
11
|
+
<zmp-skeleton-text>Lorem ipsum</zmp-skeleton-text>
|
|
12
|
+
</zmp-nav-title>
|
|
13
|
+
<zmp-nav-title v-else>
|
|
14
|
+
<zmp-title class="mb-0">{{ user.name }}</zmp-title>
|
|
15
|
+
<zmp-text class="mb-0">{{ user.id }}</zmp-text>
|
|
16
|
+
</zmp-nav-title>
|
|
17
|
+
<zmp-nav-right>
|
|
18
|
+
<sun-and-moon />
|
|
19
|
+
</zmp-nav-right>
|
|
20
|
+
</zmp-navbar>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script setup>
|
|
24
|
+
import { useStore } from "zmp-vue";
|
|
25
|
+
import SunAndMoon from "./sun-and-moon.vue";
|
|
26
|
+
|
|
27
|
+
const user = useStore('user')
|
|
28
|
+
</script>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<zmp-button
|
|
3
|
+
small
|
|
4
|
+
class="sun-moon"
|
|
5
|
+
@click="setLayoutTheme"
|
|
6
|
+
type-name="primary"
|
|
7
|
+
round
|
|
8
|
+
:color="darkMode ? 'gray' : 'default'"
|
|
9
|
+
>
|
|
10
|
+
<img :src="icon" alt="switch-mode" />
|
|
11
|
+
</zmp-button>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup>
|
|
15
|
+
import { useStore } from 'zmp-vue';
|
|
16
|
+
import { computed } from 'vue';
|
|
17
|
+
import store from '../store';
|
|
18
|
+
import sun from '../static/icons/sun.svg';
|
|
19
|
+
import moon from '../static/icons/moon.svg';
|
|
20
|
+
|
|
21
|
+
const darkMode = useStore('darkMode');
|
|
22
|
+
|
|
23
|
+
const icon = computed(() => (darkMode.value ? moon : sun));
|
|
24
|
+
|
|
25
|
+
const setLayoutTheme = () => {
|
|
26
|
+
store.dispatch('setDarkMode', !darkMode.value);
|
|
27
|
+
};
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<style scoped>
|
|
31
|
+
.sun-moon {
|
|
32
|
+
padding: 0;
|
|
33
|
+
}
|
|
34
|
+
</style>
|
|
@@ -5,15 +5,11 @@ const generateStore = require('../generate-store');
|
|
|
5
5
|
|
|
6
6
|
module.exports = (options) => {
|
|
7
7
|
const cwd = options.cwd || process.cwd();
|
|
8
|
-
const {
|
|
8
|
+
const { bundler } = options;
|
|
9
9
|
const toCopy = [];
|
|
10
10
|
|
|
11
11
|
// Copy Pages
|
|
12
|
-
const pages = [
|
|
13
|
-
...(template !== 'blank' ? ['404', 'about', 'dynamic-route', 'form'] : []),
|
|
14
|
-
...(template === 'tabs' ? ['catalog', 'product', 'settings'] : []),
|
|
15
|
-
...(template === 'split-view' ? ['left-page-1', 'left-page-2'] : []),
|
|
16
|
-
];
|
|
12
|
+
const pages = ['settings'];
|
|
17
13
|
|
|
18
14
|
pages.forEach((p) => {
|
|
19
15
|
const src = path.resolve(__dirname, 'pages', `${p}.vue`);
|
|
@@ -25,7 +21,7 @@ module.exports = (options) => {
|
|
|
25
21
|
});
|
|
26
22
|
toCopy.push({
|
|
27
23
|
content: generateHomePage(options),
|
|
28
|
-
to: path.resolve(cwd, 'src', 'pages', '
|
|
24
|
+
to: path.resolve(cwd, 'src', 'pages', 'index.vue'),
|
|
29
25
|
});
|
|
30
26
|
toCopy.push({
|
|
31
27
|
content: generateRoot(options),
|
|
@@ -35,6 +31,31 @@ module.exports = (options) => {
|
|
|
35
31
|
content: generateStore(options),
|
|
36
32
|
to: path.resolve(cwd, 'src', 'store.js'),
|
|
37
33
|
});
|
|
34
|
+
toCopy.push({
|
|
35
|
+
from: path.resolve(__dirname, 'vite.config.js'),
|
|
36
|
+
to: path.resolve(cwd, 'vite.config.js'),
|
|
37
|
+
});
|
|
38
|
+
toCopy.push({
|
|
39
|
+
from: path.resolve(__dirname, 'global-components.d.ts'),
|
|
40
|
+
to: path.resolve(cwd, 'src', 'global-components.d.ts'),
|
|
41
|
+
});
|
|
42
|
+
toCopy.push({
|
|
43
|
+
from: path.resolve(__dirname, 'components', 'header.vue'),
|
|
44
|
+
to: path.resolve(cwd, 'src', 'components', 'header.vue'),
|
|
45
|
+
});
|
|
46
|
+
toCopy.push({
|
|
47
|
+
from: path.resolve(__dirname, 'components', 'sun-and-moon.vue'),
|
|
48
|
+
to: path.resolve(cwd, 'src', 'components', 'sun-and-moon.vue'),
|
|
49
|
+
});
|
|
50
|
+
toCopy.push({
|
|
51
|
+
from: path.resolve(__dirname, 'icons', 'sun.svg'),
|
|
52
|
+
to: path.resolve(cwd, 'src', 'static', 'icons', 'sun.svg'),
|
|
53
|
+
});
|
|
54
|
+
toCopy.push({
|
|
55
|
+
from: path.resolve(__dirname, 'icons', 'moon.svg'),
|
|
56
|
+
to: path.resolve(cwd, 'src', 'static', 'icons', 'moon.svg'),
|
|
57
|
+
});
|
|
58
|
+
|
|
38
59
|
|
|
39
60
|
if (bundler) {
|
|
40
61
|
toCopy.push({
|
|
@@ -33,7 +33,7 @@ module.exports = function (options) {
|
|
|
33
33
|
});
|
|
34
34
|
toCopy.push({
|
|
35
35
|
content: generateHomePage(options),
|
|
36
|
-
to: path.resolve(cwd, 'src', 'pages', '
|
|
36
|
+
to: path.resolve(cwd, 'src', 'pages', 'index.vue')
|
|
37
37
|
});
|
|
38
38
|
toCopy.push({
|
|
39
39
|
content: generateRoot(options),
|
|
@@ -1,110 +1,56 @@
|
|
|
1
1
|
const indent = require('../../utils/indent');
|
|
2
2
|
|
|
3
3
|
module.exports = (options) => {
|
|
4
|
-
const {
|
|
5
|
-
name,
|
|
6
|
-
template,
|
|
7
|
-
} = options;
|
|
8
|
-
|
|
9
|
-
let description = '';
|
|
10
|
-
if (template === 'single-view' || template === 'blank') {
|
|
11
|
-
description = `
|
|
12
|
-
<p>Here is your blank ZMP app. Let's see what we have here.</p>
|
|
13
|
-
`;
|
|
14
|
-
}
|
|
15
|
-
if (template === 'split-view') {
|
|
16
|
-
description = `
|
|
17
|
-
<p>This is an example of split view application layout, commonly used on tablets. The main approach of such kind of layout is that you can see different views at the same time.</p>
|
|
18
|
-
|
|
19
|
-
<p>Each view may have different layout, different navbar type (dynamic, fixed or static) or without navbar.</p>
|
|
20
|
-
|
|
21
|
-
<p>The fun thing is that you can easily control one view from another without any line of JavaScript just using "data-view" attribute on links.</p>
|
|
22
|
-
`;
|
|
23
|
-
}
|
|
24
|
-
if (template === 'tabs') {
|
|
25
|
-
description = `
|
|
26
|
-
<p>This is an example of tabs-layout application. The main point of such tabbed layout is that each tab contains independent view with its own routing and navigation.</p>
|
|
27
|
-
|
|
28
|
-
<p>Each tab/view may have different layout, different navbar type (dynamic, fixed or static) or without navbar like this tab.</p>
|
|
29
|
-
`;
|
|
30
|
-
}
|
|
4
|
+
const { name, template } = options;
|
|
31
5
|
|
|
32
6
|
return indent(0, `
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
<zmp-
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<zmp-
|
|
56
|
-
<zmp-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
</zmp-row>
|
|
82
|
-
</zmp-block>
|
|
83
|
-
|
|
84
|
-
<zmp-block-title>Panels</zmp-block-title>
|
|
85
|
-
<zmp-block strong>
|
|
86
|
-
<zmp-row>
|
|
87
|
-
<zmp-col width="50">
|
|
88
|
-
<zmp-button fill raised panel-open="left">Left Panel</zmp-button>
|
|
89
|
-
</zmp-col>
|
|
90
|
-
<zmp-col width="50">
|
|
91
|
-
<zmp-button fill raised panel-open="right">Right Panel</zmp-button>
|
|
92
|
-
</zmp-col>
|
|
93
|
-
</zmp-row>
|
|
94
|
-
</zmp-block>
|
|
95
|
-
|
|
96
|
-
<zmp-list>
|
|
97
|
-
<zmp-list-item
|
|
98
|
-
title="Dynamic (Component) Route"
|
|
99
|
-
link="/dynamic-route/blog/45/post/125/?foo=bar#about"
|
|
100
|
-
></zmp-list-item>
|
|
101
|
-
<zmp-list-item
|
|
102
|
-
title="Default Route (404)"
|
|
103
|
-
link="/load-something-that-doesnt-exist/"
|
|
104
|
-
></zmp-list-item>
|
|
105
|
-
</zmp-list>
|
|
106
|
-
`.trim() : ''}
|
|
107
|
-
</zmp-page>
|
|
108
|
-
</template>
|
|
7
|
+
<template>
|
|
8
|
+
<zmp-page name="home" :theme-dark="darkMode">
|
|
9
|
+
<Header />
|
|
10
|
+
<zmp-box m="4">
|
|
11
|
+
<zmp-card inset title="Welcome to Zalo Mini App. Let's see what we have here.">
|
|
12
|
+
<p>
|
|
13
|
+
Recommended IDE Setup:
|
|
14
|
+
<a
|
|
15
|
+
href="https://code.visualstudio.com/"
|
|
16
|
+
target="_blank"
|
|
17
|
+
rel="nofollow"
|
|
18
|
+
>VSCode</a> +
|
|
19
|
+
<a
|
|
20
|
+
href="https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar"
|
|
21
|
+
target="_blank"
|
|
22
|
+
rel="nofollow"
|
|
23
|
+
>Volar</a>
|
|
24
|
+
</p>
|
|
25
|
+
<zmp-button @click="openDocs" fill responsive>Documentation</zmp-button>
|
|
26
|
+
</zmp-card>
|
|
27
|
+
</zmp-box>
|
|
28
|
+
<zmp-box m="4">
|
|
29
|
+
<zmp-card inset class="p-0">
|
|
30
|
+
<zmp-box flex justify-content="space-between" align-items="center">
|
|
31
|
+
<zmp-text bold class="mb-0">Example navigation</zmp-text>
|
|
32
|
+
<zmp-link href="/settings" transition="zmp-fade">
|
|
33
|
+
Settings
|
|
34
|
+
<zmp-icon zmp="zi-chevron-right" />
|
|
35
|
+
</zmp-link>
|
|
36
|
+
</zmp-box>
|
|
37
|
+
</zmp-card>
|
|
38
|
+
</zmp-box>
|
|
39
|
+
</zmp-page>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script setup>
|
|
43
|
+
import { useStore } from 'zmp-vue';
|
|
44
|
+
import api from 'zmp-sdk';
|
|
45
|
+
import Header from "../components/header.vue";
|
|
46
|
+
|
|
47
|
+
const openDocs = () => {
|
|
48
|
+
api.openWebview({
|
|
49
|
+
url: 'https://mini.zalo.me'
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const darkMode = useStore('darkMode');
|
|
54
|
+
</script>
|
|
109
55
|
`).trim();
|
|
110
56
|
};
|