zmp-cli 3.11.4-rc.1 → 3.12.0-rc.1

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/create/index.js CHANGED
@@ -220,7 +220,7 @@ ${chalk.bold(logSymbols.success)} ${chalk.bold('Done!')} 💪
220
220
 
221
221
  ${chalk.bold(logSymbols.info)} ${chalk.bold('Next steps:')}
222
222
  ${npmScripts.join('\n ')}
223
- - 📖 Visit documentation at ${chalk.bold('https://zmp.io/docs/')}
223
+ - 📖 Visit documentation at ${chalk.bold('https://mini.zalo.me/')}
224
224
  - 📖 Check ${chalk.bold(
225
225
  'README.md'
226
226
  )} in project root folder with further instructions
@@ -206,7 +206,7 @@ ${chalk.bold(logSymbols.success)} ${chalk.bold('Done!')} 💪
206
206
 
207
207
  ${chalk.bold(logSymbols.info)} ${chalk.bold('Next steps:')}
208
208
  ${npmScripts.join('\n ')}
209
- - 📖 Visit documentation at ${chalk.bold('https://zmp.io/docs/')}
209
+ - 📖 Visit documentation at ${chalk.bold('https://mini.zalo.me/')}
210
210
  - 📖 Check ${chalk.bold(
211
211
  'README.md'
212
212
  )} in project root folder with further instructions
@@ -1,19 +1,16 @@
1
1
  const path = require('path');
2
2
  const fse = require('../../utils/fs-extra');
3
3
  const stylesExtension = require('../utils/styles-extension');
4
- const copyCoreAssets = require('./core/copy-assets');
5
4
  const copyVueAssets = require('./vue/copy-assets');
6
5
  const copyReactAssets = require('./react/copy-assets');
7
- const copySvelteAssets = require('./svelte/copy-assets');
8
6
  const copyReactTsAssets = require('./react-typescript/copy-assets');
9
7
  const generateIndex = require('./generate-index');
10
8
  const generateStyles = require('./generate-styles');
11
9
  const generateScripts = require('./generate-scripts');
12
- const generateRoutes = require('./generate-routes');
13
- const generateManifest = require('./generate-manifest');
14
- const generateServiceWorker = require('./generate-service-worker');
15
10
  const generateZMPCustom = require('./generate-zmp-custom');
16
11
  const copyZauiAssets = require('./zaui/copy-assets');
12
+ const { projectFramework } = require('../../utils/constants');
13
+
17
14
  module.exports = (options, iconFile) => {
18
15
  const cwd = options.cwd || process.cwd();
19
16
  const {
@@ -28,14 +25,15 @@ module.exports = (options, iconFile) => {
28
25
  const srcFolder = 'src';
29
26
 
30
27
  const toCopy = [];
31
- if (framework === 'core') toCopy.push(...copyCoreAssets(options));
32
- if (framework === 'vue') toCopy.push(...copyVueAssets(options));
33
- if (framework === 'react') toCopy.push(...copyReactAssets(options));
34
- if (framework === 'svelte') toCopy.push(...copySvelteAssets(options));
35
- if (framework === 'react-typescript') {
36
- toCopy.push(...copyReactTsAssets(options));
37
- }
38
- if (package === 'zmp-ui') {
28
+ if (package !== 'zmp-ui') {
29
+ if (framework === projectFramework.VUE)
30
+ toCopy.push(...copyVueAssets(options));
31
+ if (framework === projectFramework.REACT)
32
+ toCopy.push(...copyReactAssets(options));
33
+ if (framework === projectFramework.REACT_TYPESCRIPT) {
34
+ toCopy.push(...copyReactTsAssets(options));
35
+ }
36
+ } else {
39
37
  toCopy.push(...copyZauiAssets(options));
40
38
  }
41
39
  if (theming.iconFonts) {
@@ -1,8 +1,9 @@
1
1
  /* eslint curly: off */
2
+ const { projectFramework } = require('../../utils/constants');
2
3
  const generateCoreRoot = require('./core/generate-root.js');
3
4
 
4
5
  module.exports = (options) => {
5
- const { name, framework, theming, package } = options;
6
+ const { name, framework, theming } = options;
6
7
  const srcFolder = '/src/';
7
8
  const iconsAssetsFolder = 'static';
8
9
 
@@ -10,12 +11,12 @@ module.exports = (options) => {
10
11
  const scripts = `
11
12
  <!-- built script files will be auto injected -->
12
13
  ${
13
- package === 'zmp-ui' || framework === 'react' || framework === 'vue'
14
+ framework === projectFramework.REACT || framework === projectFramework.VUE
14
15
  ? `<script type="module" src="${srcFolder}app.js"></script>`
15
16
  : ''
16
17
  }
17
18
  ${
18
- framework === 'react-typescript'
19
+ framework === projectFramework.REACT_TYPESCRIPT
19
20
  ? `<script type="module" src="${srcFolder}app.ts"></script>`
20
21
  : ''
21
22
  }
@@ -6,11 +6,11 @@ const generateReactTsScripts = require('./react-typescript/generate-scripts');
6
6
  const generateZauiScripts = require('./zaui/generate-scripts');
7
7
  module.exports = (options) => {
8
8
  const { framework, package } = options;
9
+ if (package === 'zmp-ui') return generateZauiScripts(options);
9
10
  if (framework === 'core') return generateCoreScripts(options);
10
11
  if (framework === 'vue') return generateVueScripts(options);
11
12
  if (framework === 'react') return generateReactScripts(options);
12
13
  if (framework === 'svelte') return generateSvelteScripts(options);
13
14
  if (framework === 'react-typescript') return generateReactTsScripts(options);
14
- if (package === 'zmp-ui') return generateZauiScripts(options);
15
15
  return '';
16
16
  };
@@ -0,0 +1,33 @@
1
+ {
2
+ "compilerOptions": {
3
+ "noEmit": true,
4
+ "target": "es6",
5
+ "module": "esnext",
6
+ "noImplicitAny": false,
7
+ "preserveConstEnums": true,
8
+ "jsx": "react",
9
+ "lib": ["dom", "es5", "es6", "es7", "es2017"],
10
+ "allowSyntheticDefaultImports": true,
11
+ "esModuleInterop": true,
12
+ "allowJs": true,
13
+ "skipLibCheck": true,
14
+ "declaration": false,
15
+ "emitDecoratorMetadata": true,
16
+ "experimentalDecorators": true,
17
+ "forceConsistentCasingInFileNames": true,
18
+ "moduleResolution": "node",
19
+ "noEmitOnError": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "noImplicitReturns": true,
22
+ "noImplicitThis": true,
23
+ "noUnusedLocals": false,
24
+ "strict": true,
25
+ "strictFunctionTypes": false,
26
+ "pretty": true,
27
+ "removeComments": true,
28
+ "sourceMap": true,
29
+ "resolveJsonModule": true
30
+ },
31
+ "exclude": ["node_modules"],
32
+ "include": ["src"]
33
+ }
@@ -2,15 +2,20 @@ const path = require('path');
2
2
  const generateHomePage = require('./generate-home-page');
3
3
  const generateRoot = require('./generate-root');
4
4
  const generateRecoil = require('../generate-recoil');
5
+ const generateUserCard = require('./generate-user-card');
5
6
  const copyPages = require('./pages');
7
+ const { projectFramework } = require('../../../utils/constants');
8
+ const fse = require('../../../utils/fs-extra');
6
9
 
7
10
  module.exports = (options) => {
8
11
  const cwd = options.cwd || process.cwd();
9
- const { template, stateManagement } = options;
12
+ const { template, stateManagement, framework } = options;
10
13
  const toCopy = [];
11
14
 
12
15
  // Copy Pages
13
16
 
17
+ const ext = framework === projectFramework.REACT_TYPESCRIPT ?'tsx': 'jsx'
18
+
14
19
  let pages = [];
15
20
  if (template !== 'blank')
16
21
  pages.push(
@@ -23,7 +28,7 @@ module.exports = (options) => {
23
28
 
24
29
 
25
30
  pages.forEach(({ fileName, content }) => {
26
- const dest = path.resolve(cwd, 'src', 'pages', `${fileName}.jsx`);
31
+ const dest = path.resolve(cwd, 'src', 'pages', `${fileName}.${ext}`);
27
32
  toCopy.push({
28
33
  content: copyPages[content](options),
29
34
  to: dest,
@@ -33,39 +38,53 @@ module.exports = (options) => {
33
38
 
34
39
  toCopy.push({
35
40
  content: generateHomePage(options),
36
- to: path.resolve(cwd, 'src', 'pages', 'index.jsx'),
41
+ to: path.resolve(cwd, 'src', 'pages', `index.${ext}`),
37
42
  });
38
43
 
39
- // Copy compoents
40
- const components = [
41
- ...(template !== 'blank' ? ['user-card'] : []),
42
- ];
43
- components.forEach((name) => {
44
- const src = path.resolve(__dirname, 'components', `${name}.jsx`);
45
- const dest = path.resolve(cwd, 'src', 'components', `${name}.jsx`);
44
+ if(template !== 'blank') {
46
45
  toCopy.push({
47
- from: src,
48
- to: dest,
49
- });
50
- });
46
+ content: generateUserCard(options),
47
+ to: path.resolve(cwd, 'src','components', `user-card.${ext}`)
48
+ })
49
+ }
50
+
51
51
 
52
52
  toCopy.push({
53
53
  content: generateRoot(options),
54
- to: path.resolve(cwd, 'src', 'components', 'app.jsx'),
54
+ to: path.resolve(cwd, 'src', 'components', `app.${ext}`),
55
55
  });
56
56
 
57
- if (stateManagement === 'recoil') {
58
- toCopy.push({
59
- content: generateRecoil(options),
60
- to: path.resolve(cwd, 'src', 'state.js'),
61
- });
62
- }
57
+ if(framework === projectFramework.REACT_TYPESCRIPT){
58
+ if (stateManagement === 'recoil') {
59
+ toCopy.push({
60
+ content: generateRecoil(options),
61
+ to: path.resolve(cwd, 'src', 'state.ts'),
62
+ });
63
+ }
64
+
65
+
66
+ }else {
67
+ if (stateManagement === 'recoil') {
68
+ toCopy.push({
69
+ content: generateRecoil(options),
70
+ to: path.resolve(cwd, 'src', 'state.js'),
71
+ });
72
+ }
73
+
74
+ }
75
+ const isTs = framework === projectFramework.REACT_TYPESCRIPT
63
76
 
64
77
  toCopy.push({
65
- from: path.resolve(__dirname, 'vite.config.js'),
66
- to: path.resolve(cwd, 'vite.config.js'),
78
+ content: fse.readFileSync(path.resolve(__dirname, 'vite.config.js'),'utf8'),
79
+ to: path.resolve(cwd, `vite.config.${isTs ? 'ts':'js'}`),
67
80
  });
68
81
 
82
+ if(framework === projectFramework.REACT_TYPESCRIPT){
83
+ toCopy.push({
84
+ from: path.resolve(__dirname, '_tsconfig.json'),
85
+ to: path.resolve(cwd, 'tsconfig.json')
86
+ })
87
+ }
69
88
 
70
89
  return toCopy;
71
90
  };
@@ -1,6 +1,66 @@
1
+ const { projectFramework } = require('../../../utils/constants');
1
2
  const indent = require('../../utils/indent');
2
3
  module.exports = (options) => {
3
- const { name, template, theming, stateManagement } = options;
4
+ const { name, template, framework, stateManagement } = options;
5
+ if(framework === projectFramework.REACT_TYPESCRIPT){
6
+ return indent(
7
+ 0,
8
+ `
9
+ import React from 'react';
10
+ ${
11
+ template === 'blank'
12
+ ? `
13
+ import {
14
+ Page
15
+ } from 'zmp-ui';
16
+ `.trim()
17
+ : `
18
+ import {
19
+ List,
20
+ Page,
21
+ Icon
22
+ } from 'zmp-ui';${stateManagement === 'recoil' ? `
23
+ import { useRecoilValue } from 'recoil';
24
+ import { userInfo } from "zmp-sdk";
25
+ import { userState } from '../state';` : ''}
26
+ ${template !=='blank' ?`
27
+ import UserCard from '../components/user-card';
28
+ import { useNavigate } from 'react-router-dom'
29
+ `:''}
30
+ `.trim()
31
+ }
32
+
33
+ const HomePage:React.FunctionComponent = () => {
34
+ ${template !== 'blank' ? (stateManagement === 'recoil' ? "const user = useRecoilValue<userInfo>(userState);" : "const user = useStore('user');") : ''}
35
+ ${template !=='blank' ? `const navigate = useNavigate()`:''}
36
+ return (
37
+ ${template==='blank' ?`<Page className="page">
38
+ Hello Zalo Mini App
39
+ </Page> `.trim():
40
+ `
41
+ <Page className="page">
42
+ <div className="section-container">
43
+ <UserCard user={user}/>
44
+ </div>
45
+ <div className="section-container">
46
+ <List >
47
+ <List.Item suffix={<Icon icon="zi-arrow-right"/>}>
48
+ <div onClick={()=>navigate('/about')}>About</div>
49
+ </List.Item>
50
+ <List.Item suffix={<Icon icon="zi-arrow-right"/>}>
51
+ <div onClick={()=>navigate('/user')}>User</div>
52
+ </List.Item>
53
+ </List>
54
+ </div>
55
+ </Page>`.trim()
56
+ }
57
+ );
58
+ }
59
+
60
+ export default HomePage;
61
+ `
62
+ ).trim();
63
+ }
4
64
  return indent(
5
65
  0,
6
66
  `
@@ -29,13 +89,13 @@ module.exports = (options) => {
29
89
 
30
90
  const HomePage = () => {
31
91
  ${template !== 'blank' ? (stateManagement === 'recoil' ? "const user = useRecoilValue(userState);" : "const user = useStore('user');") : ''}
32
- ${template !=='blank' && `const navigate = useNavigate();`}
92
+ ${template !=='blank' ? `const navigate = useNavigate()`:''}
33
93
  return (
34
- ${template==='blank' ?`<Page name="home" className="page">
94
+ ${template==='blank' ?`<Page className="page">
35
95
  Hello Zalo Mini App
36
96
  </Page> `.trim():
37
97
  `
38
- <Page name="home" className="page">
98
+ <Page className="page">
39
99
  <div className="section-container">
40
100
  <UserCard user={user}/>
41
101
  </div>
@@ -15,31 +15,33 @@ module.exports = (options) => {
15
15
  `
16
16
  import React from 'react';
17
17
  import { Route} from 'react-router-dom'
18
- import HomePage from '../pages';
19
- ${routes.length && routes.map((route) => ` import ${capitalize(route)} from '../pages/${route}';\n`).join('').trim()}
20
18
  ${['blank', 'single-view'].indexOf(template) >= 0
21
- && `
22
- import { App, ZMPRouter, AnimationRoutes } from 'zmp-ui';
23
- `.trim()
24
- }
19
+ ? `
20
+ import { App, ZMPRouter, AnimationRoutes, SnackbarProvider } from 'zmp-ui';
21
+ `.trim(): ''
22
+ }
25
23
  ${templateIf(stateManagement === 'recoil', () => `import { RecoilRoot } from 'recoil';`,'')}
24
+ import HomePage from '../pages';
25
+ ${routes.length>0 ? routes.map((route) => ` import ${capitalize(route)} from '../pages/${route}';\n`).join('').trim():''}
26
26
 
27
- const MyApp = () => {
28
27
 
28
+ const MyApp = () => {
29
29
  ${`
30
30
  return (${stateManagement === 'recoil' ? `
31
31
  <RecoilRoot>` : ''}
32
32
  ${indent(stateManagement === 'recoil' ? 2 : 0, `<App ${theming.darkTheme ? 'themeDark' : ''}>`)}
33
- <ZMPRouter>
34
- <AnimationRoutes>
35
- <Route path="/" element={<HomePage></HomePage>}></Route>
36
- ${routes.length && routes.map((route) =>{
37
- const pageName = capitalize(route)
38
- return ` <Route path="/${route}" element={<${pageName}></${pageName}>}></Route>\n`
39
- }).join('').trim()
40
- }
41
- </AnimationRoutes>
42
- </ZMPRouter>
33
+ <SnackbarProvider>
34
+ <ZMPRouter>
35
+ <AnimationRoutes>
36
+ <Route path="/" element={<HomePage></HomePage>}></Route>
37
+ ${routes.length>0 ? routes.map((route) =>{
38
+ const pageName = capitalize(route)
39
+ return ` <Route path="/${route}" element={<${pageName}></${pageName}>}></Route>\n`
40
+ }).join('').trim(): ''
41
+ }
42
+ </AnimationRoutes>
43
+ </ZMPRouter>
44
+ </SnackbarProvider>
43
45
  ${indent(stateManagement === 'recoil' ? 2 : 0, `</App>`)}${stateManagement === 'recoil' ? `
44
46
  </RecoilRoot>` : ''}
45
47
  );
@@ -22,7 +22,7 @@ module.exports = (options) => {
22
22
  import './css/app.${stylesExtension(cssPreProcessor)}';
23
23
 
24
24
  // Import App Component
25
- import App from './components/app.jsx';
25
+ import App from './components/app';
26
26
  import appConfig from '../app-config.json';
27
27
 
28
28
  if (!window.APP_CONFIG) {
@@ -0,0 +1,55 @@
1
+ const indent = require('../../utils/indent');
2
+ const {projectFramework} = require('../../../utils/constants')
3
+ // eslint-disable-next-line no-unused-vars
4
+ module.exports = (options) => {
5
+ const {framework} = options
6
+ if(framework === projectFramework.REACT_TYPESCRIPT){
7
+ return indent(
8
+ 0,
9
+ `
10
+ import React from 'react';
11
+ import { Avatar, Box, Text } from 'zmp-ui';
12
+ import { userInfo } from 'zmp-sdk';
13
+
14
+ interface UserProps{
15
+ user: userInfo
16
+ }
17
+
18
+ const UserCard: React.FunctionComponent<UserProps> = ({ user }) => {
19
+ return (
20
+ <Box flex>
21
+ <Avatar story='default' online src={user.avatar.startsWith('http') ? user.avatar : undefined}>{user.avatar}</Avatar>
22
+ <Box ml={4}>
23
+ <Text.Title>{user.name}</Text.Title>
24
+ <Text>{user.id}</Text>
25
+ </Box>
26
+ </Box>
27
+ )
28
+ };
29
+
30
+ export default UserCard;
31
+ `
32
+ ).trim();
33
+ }
34
+ return indent(
35
+ 0,
36
+ `
37
+ import React from 'react';
38
+ import { Avatar, Box, Text } from 'zmp-ui';
39
+
40
+ const UserCard = ({ user }) => {
41
+ return (
42
+ <Box flex>
43
+ <Avatar story='default' online src={user.avatar.startsWith('http') ? user.avatar : null}>{user.avatar}</Avatar>
44
+ <Box ml={4}>
45
+ <Text.Title>{user.name}</Text.Title>
46
+ <Text>{user.id}</Text>
47
+ </Box>
48
+ </Box>
49
+ )
50
+ };
51
+
52
+ export default UserCard;
53
+ `
54
+ ).trim();
55
+ };
@@ -1,7 +1,72 @@
1
1
  const indent = require('../../../utils/indent');
2
+ const {projectFramework} = require('../../../../utils/constants')
2
3
 
3
4
  // eslint-disable-next-line no-unused-vars
4
5
  module.exports = (options) => {
6
+ const {framework} = options
7
+
8
+ if(framework === projectFramework.REACT_TYPESCRIPT){
9
+ return indent(
10
+ 0,
11
+ `
12
+ import React from "react";
13
+ import { Sheet, Button, Page, Text } from "zmp-ui";
14
+ import { useNavigate } from 'react-router-dom'
15
+
16
+ const AboutPage: React.FunctionComponent = (props) => {
17
+ const [actionSheetOpened, setActionSheetOpened] = React.useState(false);
18
+ const navigate = useNavigate()
19
+ return (
20
+ <Page className="page">
21
+ <div className="section-container">
22
+ <Text>This mini app was generated by zmp-cli</Text>
23
+ </div>
24
+ <div>
25
+ <Button
26
+ variant='secondary'
27
+ fullWidth
28
+ onClick={() => setActionSheetOpened(true)}
29
+ >
30
+ Back
31
+ </Button>
32
+ </div>
33
+ <Sheet.Actions
34
+ visible={actionSheetOpened}
35
+ onClose={() => setActionSheetOpened(false)}
36
+ actions={[
37
+ [
38
+ {
39
+ text: "Go back",
40
+ onClick: () => {
41
+ navigate(-1);
42
+ },
43
+ },
44
+ {
45
+ text: "Action 1",
46
+ close: true,
47
+ },
48
+ {
49
+ text: "Action 2",
50
+ close: true,
51
+ },
52
+ ],
53
+ [
54
+ {
55
+ text: "Close",
56
+ close: true,
57
+ danger: true,
58
+ },
59
+ ],
60
+ ]}
61
+ ></Sheet.Actions>
62
+ </Page>
63
+ );
64
+ };
65
+
66
+ export default AboutPage;
67
+ `
68
+ ).trim();
69
+ }
5
70
  return indent(
6
71
  0,
7
72
  `
@@ -18,18 +83,17 @@ module.exports = (options) => {
18
83
  <Text>This mini app was generated by zmp-cli</Text>
19
84
  </div>
20
85
  <div>
21
- <Button
22
- type="secondary"
23
- size="full-width"
24
- onClick={() => setActionSheetOpened(true)}
25
- >
26
- Back
27
- </Button>
86
+ <Button
87
+ variant='secondary'
88
+ fullWidth
89
+ onClick={() => setActionSheetOpened(true)}
90
+ >
91
+ Back
92
+ </Button>
28
93
  </div>
29
94
  <Sheet.Actions
30
95
  visible={actionSheetOpened}
31
96
  onClose={() => setActionSheetOpened(false)}
32
- id="actions-two-groups"
33
97
  actions={[
34
98
  [
35
99
  {
@@ -1,25 +1,88 @@
1
1
  const indent = require('../../../utils/indent');
2
+ const {projectFramework} = require('../../../../utils/constants');
2
3
 
3
4
  module.exports = (options) => {
5
+ const { framework } = options
6
+
7
+ if(framework === projectFramework.REACT_TYPESCRIPT){
8
+ return indent(
9
+ 0,
10
+ `
11
+ import React from 'react';
12
+ import { Button, Input, Box, Page, useSnackbar } from 'zmp-ui';
13
+ import { useRecoilState } from 'recoil';
14
+ import { userInfo } from 'zmp-sdk';
15
+ import { userState } from '../state';
16
+
17
+ type UserForm = Omit<userInfo, "id">
18
+
19
+ const FormPage: React.FunctionComponent = () => {
20
+ const [user, setUser] = useRecoilState<userInfo>(userState)
21
+ const [form, setForm] = React.useState<UserForm>({ name: user.name, avatar: user.avatar, birthday: user.birthday, gender: user.gender });
22
+ const snackbar = useSnackbar()
23
+
24
+ const handleChangeInput = (field, value) => {
25
+ setForm({ ...form, [field]: value })
26
+ }
27
+
28
+ const handleSubmit = () => {
29
+ snackbar.openSnackbar({duration: 3000, text: 'saved', type: 'success'});
30
+ setUser((user) => ({ ...user, ...form }));
31
+ }
32
+
33
+ return (
34
+ <Page className="page">
35
+ <div className='section-container'>
36
+ <Box >
37
+ <Input
38
+ id="name"
39
+ label="Name"
40
+ type="text"
41
+ placeholder="Zalo"
42
+ value={form?.name}
43
+ onChange={(e) => handleChangeInput('name', e.target.value)}
44
+ />
45
+ <Input
46
+ label="Avatar"
47
+ type="text"
48
+ placeholder="zalo@zalo.me"
49
+ value={form?.avatar}
50
+ onChange={(e) => handleChangeInput('avatar', e.target.value)}
51
+ />
52
+ <Box mt={4}>
53
+ <Button fullWidth variant='primary' onClick={handleSubmit}>
54
+ Submit
55
+ </Button>
56
+ </Box>
57
+ </Box>
58
+ </div>
59
+ </Page>
60
+ )
61
+ }
62
+
63
+ export default FormPage;
64
+ `
65
+ ).trim();
66
+ }
4
67
  return indent(
5
68
  0,
6
69
  `
7
70
  import React from 'react';
8
- import { Button,Input, Box, Page } from 'zmp-ui';
71
+ import { Button,Input, Box, Page, useSnackbar } from 'zmp-ui';
9
72
  import { useRecoilState } from 'recoil';
10
73
  import { userState } from '../state';
11
74
 
12
75
  const FormPage = () => {
13
76
  const [user, setUser] = useRecoilState(userState)
14
-
15
77
  const [form, setForm] = React.useState({ ...user });
16
-
78
+ const snackbar = useSnackbar()
79
+
17
80
  const handleChangeInput = (field, value) => {
18
81
  setForm({ ...form, [field]: value })
19
82
  }
20
83
 
21
84
  const handleSubmit = () => {
22
- alert('saved');
85
+ snackbar.openSnackbar({duration: 3000, text: 'saved', type: 'success'})
23
86
  setUser(form);
24
87
  }
25
88
 
@@ -43,9 +106,9 @@ module.exports = (options) => {
43
106
  onChange={(e) => handleChangeInput('avatar', e.target.value)}
44
107
  />
45
108
  <Box mt={4}>
46
- <Button size="full-width" type="primary" onClick={handleSubmit}>
47
- Submit
48
- </Button>
109
+ <Button fullWidth variant='primary' onClick={handleSubmit}>
110
+ Submit
111
+ </Button>
49
112
  </Box>
50
113
  </Box>
51
114
  </div>
@@ -1,8 +1,62 @@
1
1
  const indent = require('../../../utils/indent');
2
+ const { projectFramework } = require('../../../../utils/constants')
2
3
 
3
4
  module.exports = (options) => {
4
- const { template, stateManagement } = options;
5
- const modules = ['Avatar', 'List', 'Page', 'Box', 'Text'];
5
+ const { framework } = options;
6
+
7
+ if(framework === projectFramework.REACT_TYPESCRIPT){
8
+ return indent(
9
+ 0,
10
+ `
11
+ import React from "react";
12
+ import { Avatar, List, Text, Box, Page, Button, Icon } from "zmp-ui";
13
+ import {useNavigate} from 'react-router-dom';
14
+ import { useRecoilValue } from "recoil";
15
+ import { userState } from "../state";
16
+ import { userInfo } from "zmp-sdk";
17
+
18
+ const UserPage = () => {
19
+ const user = useRecoilValue<userInfo>(userState);
20
+ const navigate = useNavigate()
21
+ return (
22
+ <Page className="page">
23
+ <Box flex flexDirection="column" justifyContent="center" alignItems="center">
24
+ <Box>
25
+ <Avatar
26
+ story='default'
27
+ size={96}
28
+ online
29
+ src={user.avatar.startsWith("http") ? user.avatar : undefined}
30
+ >
31
+ {user.avatar}
32
+ </Avatar>
33
+ </Box>
34
+ <Box flex flexDirection="row" alignItems="center" ml={8}>
35
+ <Box>
36
+ <Text.Title >{user.name}</Text.Title>
37
+ </Box>
38
+ <Box ml={4}>
39
+ <Button onClick={()=>{navigate('/form')}} size='small' icon={<Icon icon="zi-edit"/>}/>
40
+ </Box>
41
+ </Box>
42
+ </Box>
43
+ <Box m={0} p={0} mt={4}>
44
+ <div className="section-container">
45
+ <List>
46
+ <List.Item title="Display name" subTitle={user.name} />
47
+ <List.Item title="ID" subTitle={user.id} />
48
+ </List>
49
+ </div>
50
+ </Box>
51
+
52
+ </Page>
53
+ );
54
+ };
55
+
56
+ export default UserPage;
57
+ `
58
+ ).trim();
59
+ }
6
60
 
7
61
  return indent(
8
62
  0,
@@ -13,7 +13,9 @@ module.exports = function generatePackageJson(options) {
13
13
 
14
14
  // Dependencies
15
15
  const dependencies =
16
- package === 'zmp-ui' ? ['zmp-ui'] : ['zmp-framework', 'zmp-sdk', 'swiper'];
16
+ package === 'zmp-ui'
17
+ ? ['zmp-ui', 'zmp-sdk']
18
+ : ['zmp-framework', 'zmp-sdk', 'swiper'];
17
19
  const dependenciesVue = ['vue@3', 'zmp-framework'];
18
20
  const dependenciesReact = ['react', 'react-dom', 'prop-types'];
19
21
  const dependenciesReactTs = ['@types/react', '@types/react-dom'];
@@ -1,6 +1,7 @@
1
1
  /* eslint no-param-reassign: ["off"] */
2
2
  const inquirer = require('inquirer');
3
3
  var chalk = require('chalk');
4
+ const { projectFramework } = require('../../utils/constants');
4
5
 
5
6
  const moreOptionsText = chalk.italic(
6
7
  `\t- Including Tailwind CSS\n\t- Including Recoil (React only)`
@@ -31,7 +32,7 @@ const questions = [
31
32
  type: 'list',
32
33
  name: 'package',
33
34
  when: (opts) => opts.newProject,
34
- message: 'Choose an UI library / UI framework:',
35
+ message: 'Choose an UI library',
35
36
  choices: [
36
37
  {
37
38
  name: 'zmp-ui',
@@ -40,103 +41,24 @@ const questions = [
40
41
  ],
41
42
  },
42
43
  // Framework
44
+
43
45
  {
44
46
  type: 'list',
45
47
  name: 'framework',
46
- when: (opts) => opts.package == 'zmp-framework',
47
- message: 'What type of framework do you prefer?',
48
- choices: [
49
- {
50
- name: 'ZMP with React',
51
- value: 'react',
52
- },
53
- {
54
- name: 'ZMP with React (TypeScript)',
55
- value: 'react-typescript',
56
- },
57
- {
58
- name: 'ZMP with Vue.js',
59
- value: 'vue',
60
- },
61
- {
62
- name: 'ZMP Core',
63
- value: 'core',
64
- disabled: true,
65
- },
66
- ],
67
- },
68
- {
69
- type: 'list',
70
- name: 'language',
71
48
  when: (opts) => opts.package == 'zmp-ui',
72
- message: 'What language do you prefer?',
49
+ message: 'What type of framework/library do you prefer?',
73
50
  choices: [
74
51
  {
75
52
  name: 'ReactJS',
76
- value: 'react',
77
- },
78
- ],
79
- },
80
- {
81
- type: 'list',
82
- name: 'useUIKits',
83
- when: (opts) =>
84
- opts.package === 'zmp-framework' && opts.framework !== 'vue',
85
- message: 'Do you want to use Zalo UI kits style?',
86
- default: true,
87
- choices: [
88
- {
89
- name: 'Yes, i want to use UI kits style',
90
- value: true,
53
+ value: projectFramework.REACT,
91
54
  },
92
55
  {
93
- name: 'No, i want to use only styles with minimal required set of components',
94
- value: false,
56
+ name: 'React Typescript',
57
+ value: projectFramework.REACT_TYPESCRIPT,
95
58
  },
96
59
  ],
97
60
  },
98
61
  // Template
99
- {
100
- type: 'list',
101
- name: 'template',
102
- when: (opts) =>
103
- opts.newProject &&
104
- opts.package === 'zmp-framework' &&
105
- opts.useUIKits &&
106
- opts.framework !== 'vue',
107
- message: 'Choose starter template:',
108
- choices: [
109
- {
110
- name: 'Blank',
111
- value: 'blank',
112
- },
113
- {
114
- name: 'Single View',
115
- value: 'single-view',
116
- },
117
- {
118
- name: 'Tabs Layout',
119
- value: 'tabs',
120
- },
121
- ],
122
- },
123
- // Template
124
- {
125
- type: 'list',
126
- name: 'template',
127
- when: (opts) =>
128
- opts.newProject &&
129
- opts.package === 'zmp-framework' &&
130
- !opts.useUIKits &&
131
- opts.framework !== 'vue',
132
- message: 'Choose starter template:',
133
- choices: [
134
- {
135
- name: 'Blank',
136
- value: 'blank',
137
- },
138
- ],
139
- },
140
62
  {
141
63
  type: 'list',
142
64
  name: 'cssPreProcessor',
@@ -212,23 +134,6 @@ const questions = [
212
134
  return input.replace(/#/g, '');
213
135
  },
214
136
  },
215
- {
216
- type: 'list',
217
- name: 'themingIconFonts',
218
- when: (opts) => opts.newProject && opts.package !== 'zmp-ui',
219
- message: 'Do you want to include ZMP Icons and Material Icons icon fonts?',
220
- default: true,
221
- choices: [
222
- {
223
- name: 'Yes, include icon fonts',
224
- value: true,
225
- },
226
- {
227
- name: 'No, i want to use my own custom icons',
228
- value: false,
229
- },
230
- ],
231
- },
232
137
  {
233
138
  type: 'list',
234
139
  name: 'moreOptions',
@@ -264,25 +169,6 @@ const questions = [
264
169
  },
265
170
  ],
266
171
  },
267
- {
268
- type: 'list',
269
- name: 'stateManagement',
270
- when: (opts) =>
271
- opts.moreOptions &&
272
- (opts.framework === 'react' || opts.framework === 'react-typescript'),
273
- message: 'Which state management library would you like to use?',
274
- default: 'store',
275
- choices: [
276
- {
277
- name: 'ZMP Store (Redux pattern)',
278
- value: 'store',
279
- },
280
- {
281
- name: 'Recoil',
282
- value: 'recoil',
283
- },
284
- ],
285
- },
286
172
  ];
287
173
 
288
174
  module.exports = function getOptions() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zmp-cli",
3
- "version": "3.11.4-rc.1",
3
+ "version": "3.12.0-rc.1",
4
4
  "description": "ZMP command line utility (CLI)",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -3,6 +3,13 @@ const versionStatus = {
3
3
  TESTING: 2,
4
4
  };
5
5
 
6
+ const projectFramework = {
7
+ REACT: 'react',
8
+ REACT_TYPESCRIPT: 'react-typescript',
9
+ VUE: 'vue',
10
+ };
11
+
6
12
  module.exports = {
7
13
  versionStatus,
14
+ projectFramework,
8
15
  };