zmp-cli 3.7.2 → 3.8.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.
Files changed (31) hide show
  1. package/assets/index.js +0 -0
  2. package/build/index.js +0 -0
  3. package/config/index.js +0 -0
  4. package/create/index.js +0 -0
  5. package/create/templates/react/copy-assets.js +13 -4
  6. package/create/templates/react/generate-home-page.js +25 -8
  7. package/create/templates/react/generate-root.js +26 -176
  8. package/create/templates/react/generate-routes.js +1 -1
  9. package/create/templates/react/pages/catalog.jsx +18 -16
  10. package/create/templates/react/pages/form-tabs.jsx +64 -0
  11. package/create/templates/react/pages/settings.jsx +16 -163
  12. package/create/templates/react/pages/user-tabs.jsx +31 -0
  13. package/create/templates/react-typescript/copy-assets.js +8 -0
  14. package/create/templates/react-typescript/generate-home-page.js +26 -8
  15. package/create/templates/react-typescript/generate-root.js +43 -2
  16. package/create/templates/react-typescript/generate-routes.js +3 -1
  17. package/create/templates/react-typescript/pages/404.js +2 -1
  18. package/create/templates/react-typescript/pages/about.js +1 -0
  19. package/create/templates/react-typescript/pages/catalog.js +60 -0
  20. package/create/templates/react-typescript/pages/dynamic-route.js +1 -0
  21. package/create/templates/react-typescript/pages/form.js +13 -1
  22. package/create/templates/react-typescript/pages/index.js +4 -0
  23. package/create/templates/react-typescript/pages/settings.js +39 -0
  24. package/create/templates/react-typescript/pages/user.js +17 -2
  25. package/create/utils/generate-package-json.js +4 -4
  26. package/create/utils/get-options.js +5 -9
  27. package/deploy/index.js +0 -0
  28. package/login/index.js +0 -0
  29. package/migrate/index.js +0 -0
  30. package/package.json +2 -2
  31. package/start/index.js +0 -0
package/assets/index.js CHANGED
File without changes
package/build/index.js CHANGED
File without changes
package/config/index.js CHANGED
File without changes
package/create/index.js CHANGED
File without changes
@@ -10,14 +10,23 @@ module.exports = (options) => {
10
10
 
11
11
  // Copy Pages
12
12
  let pages = [];
13
- if (template !== 'blank')
14
- pages.push(...['404', 'about', 'dynamic-route', 'user', 'form']);
15
- if (template === 'tabs') pages.push(...['catalog', 'product', 'settings']);
13
+ if (template !== 'blank') pages.push(...['404', 'about', 'dynamic-route']);
14
+ if (template !== 'blank' && template !== 'tabs')
15
+ pages.push(...['user', 'form']);
16
+ if (template === 'tabs')
17
+ pages.push(...['catalog', 'settings', 'form-tabs', 'user-tabs']);
16
18
  if (template === 'split-view') pages.push(...['left-page-1', 'left-page-2']);
17
19
 
18
20
  pages.forEach((p) => {
19
21
  const src = path.resolve(__dirname, 'pages', `${p}.jsx`);
20
- const dest = path.resolve(cwd, 'src', 'pages', `${p}.jsx`);
22
+ let destPage = p;
23
+ if (p === 'user-tabs') {
24
+ destPage = 'user';
25
+ }
26
+ if (p === 'form-tabs') {
27
+ destPage = 'form';
28
+ }
29
+ const dest = path.resolve(cwd, 'src', 'pages', `${destPage}.jsx`);
21
30
  toCopy.push({
22
31
  from: src,
23
32
  to: dest,
@@ -1,5 +1,4 @@
1
1
  const indent = require('../../utils/indent');
2
-
3
2
  module.exports = (options) => {
4
3
  const { name, template, theming } = options;
5
4
  const { fillBars } = theming;
@@ -21,9 +20,7 @@ module.exports = (options) => {
21
20
  }
22
21
  if (template === 'tabs') {
23
22
  description = `
24
- <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>
25
-
26
- <p>Each tab/view may have different layout, different navbar type (dynamic, fixed or static) or without navbar like this tab.</p>
23
+ <p>Here is your blank ZMP app with tabs-layout. Let's see what we have here.</p>
27
24
  `;
28
25
  }
29
26
 
@@ -59,17 +56,21 @@ module.exports = (options) => {
59
56
  const HomePage = () => {
60
57
  ${template !== 'blank' ? "const user = useStore('user');" : ''}
61
58
  return (
62
- <Page name="home" navbarLarge>
63
- {/* Top Navbar */}
59
+ <Page name="home" ${template === 'tabs' ? '' : 'navbarLarge'}>
60
+ ${
61
+ template !== 'tabs'
62
+ ? `{/* Top Navbar */}
64
63
  <Navbar ${fillBars ? 'fill' : ''}>
65
64
  <NavTitleLarge>${name}</NavTitleLarge>
66
- </Navbar>
65
+ </Navbar>`
66
+ : ''
67
+ }
67
68
  {/* Page content */}
68
69
  <Card inset>
69
70
  ${description.trim()}
70
71
  </Card>
71
72
  ${
72
- template !== 'blank'
73
+ template !== 'blank' && template !== 'tabs'
73
74
  ? `
74
75
  {/* User info */}
75
76
  <List>
@@ -81,6 +82,21 @@ module.exports = (options) => {
81
82
  {/* Grid apps */}
82
83
  <AppItems />
83
84
 
85
+ {/* Route */}
86
+ <List>
87
+ <ListItem title="Dynamic (Component) Route" link="/dynamic-route/?blog=45&post=125&foo=bar" />
88
+ <ListItem title="Default Route (404)" link="/something-that-doesnt-exist" />
89
+ <ListItem title="About" link="/about/" />
90
+ </List>
91
+ `.trim()
92
+ : ''
93
+ }
94
+ ${
95
+ template === 'tabs'
96
+ ? `
97
+ {/* Grid apps */}
98
+ <AppItems />
99
+
84
100
  {/* Route */}
85
101
  <List>
86
102
  <ListItem title="Dynamic (Component) Route" link="/dynamic-route/?blog=45&post=125&foo=bar" />
@@ -93,6 +109,7 @@ module.exports = (options) => {
93
109
  </Page>
94
110
  );
95
111
  }
112
+
96
113
  export default HomePage;
97
114
  `
98
115
  ).trim();
@@ -1,74 +1,12 @@
1
1
  const indent = require('../../utils/indent');
2
- const templateIf = require('../../utils/template-if');
3
2
  const appParameters = require('../app-parameters');
4
3
 
5
4
  module.exports = (options) => {
6
5
  const { template, theming } = options;
7
6
 
8
- // Panels
9
- const leftPanelPlain = indent(
10
- 12,
11
- `
12
- {/* Left panel with cover effect*/}
13
- <Panel left cover themeDark>
14
- <View>
15
- <Page>
16
- <Navbar title="Left Panel"/>
17
- <Block>Left panel content goes here</Block>
18
- </Page>
19
- </View>
20
- </Panel>
21
- `
22
- );
23
-
24
- const leftPanelWithView = indent(
25
- 12,
26
- `
27
- {/* Left panel with cover effect when hidden */}
28
- <Panel left cover themeDark visibleBreakpoint={960}>
29
- <View>
30
- <Page>
31
- <Navbar title="Left Panel"/>
32
- <BlockTitle>Left View Navigation</BlockTitle>
33
- <List>
34
- <ListItem link="/left-page-1/" title="Left Page 1"/>
35
- <ListItem link="/left-page-2/" title="Left Page 2"/>
36
- </List>
37
- <BlockTitle>Control Main View</BlockTitle>
38
- <List>
39
- <ListItem link="/about/" view=".view-main" panelClose title="About"/>
40
- <ListItem link="/form/" view=".view-main" panelClose title="Form"/>
41
- <ListItem link="#" view=".view-main" back panelClose title="Back in history"/>
42
- </List>
43
- </Page>
44
- </View>
45
- </Panel>
46
- `
47
- );
48
- const leftPanel =
49
- template === 'split-view' ? leftPanelWithView : leftPanelPlain;
50
- const rightPanel = indent(
51
- 12,
52
- `
53
- {/* Right panel with reveal effect*/}
54
- <Panel right reveal themeDark>
55
- <View>
56
- <Page>
57
- <Navbar title="Right Panel"/>
58
- <Block>Right panel content goes here</Block>
59
- </Page>
60
- </View>
61
- </Panel>
62
- `
63
- );
64
-
65
7
  // Views
66
8
  let views = '';
67
- if (
68
- template === 'single-view' ||
69
- template === 'split-view' ||
70
- template === 'blank'
71
- ) {
9
+ if (template === 'single-view' || template === 'blank') {
72
10
  views = indent(
73
11
  12,
74
12
  `
@@ -81,25 +19,25 @@ module.exports = (options) => {
81
19
  views = indent(
82
20
  12,
83
21
  `
84
- {/* Views/Tabs container */}
85
- <Views tabs className="safe-areas">
86
- {/* Tabbar for switching views-tabs */}
87
- <Toolbar tabbar labels bottom>
88
- <Link tabLink="#view-home" tabLinkActive iconIos="zmp:house_fill" iconAurora="zmp:house_fill" iconMd="material:home" text="Home" />
89
- <Link tabLink="#view-catalog" iconIos="zmp:square_list_fill" iconAurora="zmp:square_list_fill" iconMd="material:view_list" text="Catalog" />
90
- <Link tabLink="#view-settings" iconIos="zmp:gear" iconAurora="zmp:gear" iconMd="material:settings" text="Settings" />
91
- </Toolbar>
92
-
93
- {/* Your main view/tab, should have "view-main" class. It also has "tabActive" prop */}
94
- <View id="view-home" main tab tabActive url="/" />
95
-
96
- {/* Catalog View */}
97
- <View id="view-catalog" name="catalog" tab url="/catalog/" />
22
+ {/* TabView container */}
23
+ <TabView className="safe-areas">
24
+ {/* Tabbar for switching Tab*/}
25
+ <Tabbar bottom id="app-tab-bar">
26
+ <Link tabLink="#view-home" iconZMP="zi-home" tabLinkActive>
27
+ Home
28
+ </Link>
29
+ <Link tabLink="#view-catalog" iconZMP="zi-list-1">
30
+ Catalog
31
+ </Link>
32
+ <Link tabLink="#view-settings" iconZMP="zi-setting">
33
+ Settings
34
+ </Link>
35
+ </Tabbar>
98
36
 
99
- {/* Settings View */}
100
- <View id="view-settings" name="settings" tab url="/settings/" />
101
-
102
- </Views>
37
+ <View id="view-home" main tab tabActive url="/" />
38
+ <View id="view-catalog" name="catalog" tab url="/catalog/" />
39
+ <View id="view-settings" name="settings" tab url="/settings/" />
40
+ </TabView>
103
41
  `
104
42
  );
105
43
  }
@@ -123,120 +61,32 @@ module.exports = (options) => {
123
61
  zmp,
124
62
  zmpready,
125
63
  App,
126
- Panel,
127
- Views,
64
+ TabView,
128
65
  View,
129
- Popup,
130
- Page,
131
- Navbar,
132
- Toolbar,
133
- NavRight,
66
+ Tabbar,
134
67
  Link,
135
- Block,
136
- BlockTitle,
137
- LoginScreen,
138
- LoginScreenTitle,
139
- List,
140
- ListItem,
141
- ListInput,
142
- ListButton,
143
- BlockFooter
144
68
  } from 'zmp-framework/react';
145
69
  `.trim()
146
70
  }
147
71
  import store from '../store';
148
72
 
149
73
  const MyApp = () => {
150
- ${templateIf(
151
- ['blank', 'single-view'].indexOf(template) === -1,
152
- () => `
153
- // Login screen demo data
154
- const [username, setUsername] = useState('');
155
- const [password, setPassword] = useState('');
156
- `
157
- )}
158
74
  // ZMP Parameters
159
75
  const zmpparams = {
160
76
  ${indent(10, appParameters(options)).trim()}
161
77
  };
162
- ${templateIf(
163
- ['blank', 'single-view'].indexOf(template) === -1,
164
- () => `
165
- const alertLoginData = () => {
166
- zmp.dialog.alert('Username: ' + username + '<br>Password: ' + password, () => {
167
- zmp.loginScreen.close();
78
+ useEffect(()=>{
79
+ zmpready(() => {
80
+ // Call ZMP APIs here
168
81
  });
169
- }
170
- `
171
- )}
172
- zmpready(() => {
173
- // Call ZMP APIs here
174
- });
175
82
 
176
- ${
177
- ['blank', 'single-view'].indexOf(template) !== -1
178
- ? `
83
+ },[])
84
+
179
85
  return (
180
86
  <App { ...zmpparams } ${theming.darkTheme ? 'themeDark' : ''}>
181
87
  ${views}
182
88
  </App>
183
89
  );
184
- `.trim()
185
- : `
186
- return (
187
- <App { ...zmpparams } ${theming.darkTheme ? 'themeDark' : ''}>
188
- ${leftPanel}
189
- ${rightPanel}
190
- ${views}
191
- {/* Popup */}
192
- <Popup id="my-popup">
193
- <View>
194
- <Page>
195
- <Navbar title="Popup">
196
- <NavRight>
197
- <Link popupClose>Close</Link>
198
- </NavRight>
199
- </Navbar>
200
- <Block>
201
- <p>Popup content goes here.</p>
202
- </Block>
203
- </Page>
204
- </View>
205
- </Popup>
206
-
207
- <LoginScreen id="my-login-screen">
208
- <View>
209
- <Page loginScreen>
210
- <LoginScreenTitle>Login</LoginScreenTitle>
211
- <List form>
212
- <ListInput
213
- type="text"
214
- name="username"
215
- placeholder="Your username"
216
- value={username}
217
- onInput={(e) => setUsername(e.target.value)}
218
- ></ListInput>
219
- <ListInput
220
- type="password"
221
- name="password"
222
- placeholder="Your password"
223
- value={password}
224
- onInput={(e) => setPassword(e.target.value)}
225
- ></ListInput>
226
- </List>
227
- <List>
228
- <ListButton title="Sign In" onClick={() => alertLoginData()} />
229
- <BlockFooter>
230
- Some text about login information.<br />Click "Sign In" to close Login Screen
231
- </BlockFooter>
232
- </List>
233
- </Page>
234
- </View>
235
- </LoginScreen>
236
- </App>
237
- )
238
- `.trim()
239
- }
240
90
  }
241
91
  export default MyApp;
242
92
  `
@@ -7,7 +7,7 @@ module.exports = (options) => {
7
7
  // Webpack Routes
8
8
  const routes = ['/user', '/form', '/dynamic-route', '/about', '/404'];
9
9
  if (template === 'tabs') {
10
- routes.push(...['/catalog', '/product', '/settings']);
10
+ routes.push(...['/catalog', '/settings']);
11
11
  } else if (template === 'split-view') {
12
12
  routes.push(...['/left-page-1', '/left-page-2']);
13
13
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { Page, Navbar, List, ListItem, Block, Button, useStore } from 'zmp-framework/react';
2
+ import { Page, Title, List, ListItem, Box, Button, useStore } from 'zmp-framework/react';
3
3
  import store from '../store'
4
4
 
5
5
  const CatalogPage = () => {
@@ -15,21 +15,23 @@ const CatalogPage = () => {
15
15
 
16
16
  return (
17
17
  <Page name="catalog">
18
- <Navbar title="Catalog" />
19
- <List>
20
- {products.map((product) => (
21
- <ListItem
22
- key={product.id}
23
- title={product.title}
24
- link={`/product/${product.id}/`}
25
- />
26
- ))}
27
- </List>
28
- {products.length === 3 && (
29
- <Block>
30
- <Button fill onClick={addProduct}>Add Product</Button>
31
- </Block>
32
- )}
18
+ <Box m={0} p={4}>
19
+ <Title>Catalog</Title>
20
+ <List>
21
+ {products.map((product) => (
22
+ <ListItem
23
+ key={product.id}
24
+ title={product.title}
25
+ link={`/product/${product.id}/`}
26
+ />
27
+ ))}
28
+ </List>
29
+ {products.length === 3 && (
30
+ <Box>
31
+ <Button responsive typeName='secondary' onClick={addProduct}>Add Product</Button>
32
+ </Box>
33
+ )}
34
+ </Box>
33
35
  </Page>
34
36
  );
35
37
  }
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import { Button, Card, Input, Page, useStore, zmp, Box } from 'zmp-framework/react';
3
+ import NavbarBack from '../components/navbar-back';
4
+
5
+ import store from '../store'
6
+
7
+ const FormPage = () => {
8
+ const user = useStore('user')
9
+ const toast = React.useRef(null)
10
+ const [form, setForm] = React.useState({
11
+ displayName: user.displayName,
12
+ email: user.email,
13
+ })
14
+ const handleChangeInput = (field, value) => {
15
+ setForm({ ...form, [field]: value })
16
+ }
17
+
18
+ const handleSubmit = () => {
19
+ if (!toast.current) {
20
+ toast.current = zmp.toast.create({
21
+ text: 'Saved',
22
+ position: 'bottom',
23
+ closeTimeout: 2000,
24
+ })
25
+ }
26
+ store.dispatch('setUser', form)
27
+ toast.current.open()
28
+ }
29
+
30
+ return (
31
+ <Page name="user-form" onPageBeforeIn={()=>{
32
+ //hide navbar
33
+ zmp.toolbar.hide('#app-tab-bar')
34
+ }}>
35
+ <NavbarBack title="Update user info" />
36
+ <Box>
37
+ <Card inset>
38
+ <Input
39
+ id="displayName"
40
+ label="Display name"
41
+ type="text"
42
+ placeholder="Zalo"
43
+ value={form?.displayName}
44
+ onChange={(e) => handleChangeInput('displayName', e.target.value)}
45
+ />
46
+ <Input
47
+ label="Email"
48
+ type="text"
49
+ placeholder="zalo@zalo.me"
50
+ value={form?.email}
51
+ onChange={(e) => handleChangeInput('email', e.target.value)}
52
+ />
53
+ <Box mx={0} mt={4}>
54
+ <Button responsive typeName="primary" onClick={handleSubmit}>
55
+ Submit
56
+ </Button>
57
+ </Box>
58
+ </Card>
59
+ </Box>
60
+ </Page>
61
+ )
62
+ }
63
+
64
+ export default FormPage;
@@ -1,175 +1,28 @@
1
1
  import React from 'react';
2
2
  import {
3
3
  Page,
4
- Navbar,
5
4
  List,
6
- ListInput,
7
5
  ListItem,
8
- Toggle,
9
- BlockTitle,
10
- Row,
11
- Button,
12
- Range,
13
- Block
6
+ useStore,
7
+ Title,
8
+ Box
14
9
  } from 'zmp-framework/react';
10
+ import UserCard from '../components/user-card';
15
11
 
16
- const SettingsPage = () => (
17
- <Page name="settings">
18
- <Navbar title="Settings" />
19
-
20
- <BlockTitle>Form Example</BlockTitle>
21
- <List noHairlinesMd>
22
- <ListInput
23
- label="Name"
24
- type="text"
25
- placeholder="Your name"
26
- ></ListInput>
27
-
28
- <ListInput
29
- label="E-mail"
30
- type="email"
31
- placeholder="E-mail"
32
- ></ListInput>
33
-
34
- <ListInput
35
- label="URL"
36
- type="url"
37
- placeholder="URL"
38
- ></ListInput>
39
-
40
- <ListInput
41
- label="Password"
42
- type="password"
43
- placeholder="Password"
44
- ></ListInput>
45
-
46
- <ListInput
47
- label="Phone"
48
- type="tel"
49
- placeholder="Phone"
50
- ></ListInput>
51
-
52
- <ListInput
53
- label="Gender"
54
- type="select"
55
- >
56
- <option>Male</option>
57
- <option>Female</option>
58
- </ListInput>
12
+ const SettingsPage = () => {
13
+ const user = useStore('user');
59
14
 
60
- <ListInput
61
- label="Birth date"
62
- type="date"
63
- placeholder="Birth day"
64
- defaultValue="2014-04-30"
65
- ></ListInput>
66
-
67
- <ListItem
68
- title="Toggle"
69
- >
70
- <Toggle slot="after" />
15
+ return(
16
+ <Page name="settings">
17
+ <Box m={0} p={4}>
18
+ <Title>Settings</Title>
19
+ <List className='m-0'>
20
+ <ListItem link="/user/">
21
+ <UserCard user={user} />
71
22
  </ListItem>
72
-
73
- <ListInput
74
- label="Range"
75
- input={false}
76
- >
77
- <Range slot="input" value={50} min={0} max={100} step={1} />
78
- </ListInput>
79
-
80
- <ListInput
81
- type="textarea"
82
- label="Textarea"
83
- placeholder="Bio"
84
- ></ListInput>
85
- <ListInput
86
- type="textarea"
87
- label="Resizable"
88
- placeholder="Bio"
89
- resizable
90
- ></ListInput>
91
- </List>
92
-
93
- <BlockTitle>Buttons</BlockTitle>
94
- <Block strong>
95
- <Row tag="p">
96
- <Button className="col">Button</Button>
97
- <Button className="col" fill>Fill</Button>
98
- </Row>
99
- <Row tag="p">
100
- <Button className="col" raised>Raised</Button>
101
- <Button className="col" raised fill>Raised Fill</Button>
102
- </Row>
103
- <Row tag="p">
104
- <Button className="col" round>Round</Button>
105
- <Button className="col" round fill>Round Fill</Button>
106
- </Row>
107
- <Row tag="p">
108
- <Button className="col" outline>Outline</Button>
109
- <Button className="col" round outline>Outline Round</Button>
110
- </Row>
111
- <Row tag="p">
112
- <Button className="col" small outline>Small</Button>
113
- <Button className="col" small round outline>Small Round</Button>
114
- </Row>
115
- <Row tag="p">
116
- <Button className="col" small fill>Small</Button>
117
- <Button className="col" small round fill>Small Round</Button>
118
- </Row>
119
- <Row tag="p">
120
- <Button className="col" large raised>Large</Button>
121
- <Button className="col" large fill raised>Large Fill</Button>
122
- </Row>
123
- <Row tag="p">
124
- <Button className="col" large fill raised color="red">Large Red</Button>
125
- <Button className="col" large fill raised color="green">Large Green</Button>
126
- </Row>
127
- </Block>
128
-
129
- <BlockTitle>Checkbox group</BlockTitle>
130
- <List>
131
- <ListItem
132
- checkbox
133
- name="my-checkbox"
134
- value="Books"
135
- title="Books"
136
- ></ListItem>
137
- <ListItem
138
- checkbox
139
- name="my-checkbox"
140
- value="Movies"
141
- title="Movies"
142
- ></ListItem>
143
- <ListItem
144
- checkbox
145
- name="my-checkbox"
146
- value="Food"
147
- title="Food"
148
- ></ListItem>
149
- </List>
150
-
151
- <BlockTitle>Radio buttons group</BlockTitle>
152
- <List>
153
- <ListItem
154
- radio
155
- name="radio"
156
- value="Books"
157
- title="Books"
158
- ></ListItem>
159
- <ListItem
160
- radio
161
- name="radio"
162
- value="Movies"
163
- title="Movies"
164
- ></ListItem>
165
- <ListItem
166
- radio
167
- name="radio"
168
- value="Food"
169
- title="Food"
170
- ></ListItem>
171
- </List>
23
+ </List>
24
+ </Box>
172
25
  </Page>
173
- );
26
+ )};
174
27
 
175
28
  export default SettingsPage;
@@ -0,0 +1,31 @@
1
+ import React from 'react'
2
+
3
+ import { Avatar, zmp, List, ListItem, Page, Title, useStore } from 'zmp-framework/react'
4
+ import NavbarBack from '../components/navbar-back'
5
+
6
+ const UserPage = () => {
7
+ const user = useStore('user')
8
+
9
+ return (
10
+ <Page name="user" onPageBeforeIn={()=>{
11
+ // hide navbar
12
+ zmp.toolbar.hide('#app-tab-bar')
13
+ }}>
14
+ <NavbarBack
15
+ title="User info"
16
+ linkRight="/form"
17
+ labelRight="Edit"
18
+ />
19
+ <div style={{ textAlign: 'center', marginTop: 32 }}>
20
+ <Avatar story online size={96}>{user.avatar}</Avatar>
21
+ <Title style={{ marginTop: 8 }}>{user.displayName}</Title>
22
+ </div>
23
+ <List>
24
+ <ListItem title="Display name" after={user.displayName} />
25
+ <ListItem title="Email" after={user.email} />
26
+ </List>
27
+ </Page>
28
+ )
29
+ }
30
+
31
+ export default UserPage;
@@ -23,6 +23,14 @@ module.exports = (options) => {
23
23
  { fileName: 'form', content: 'copyForm' },
24
24
  ]
25
25
  );
26
+ if (template === 'tabs') {
27
+ pages.push(
28
+ ...[
29
+ { fileName: 'catalog', content: 'copyCatalog' },
30
+ { fileName: 'settings', content: 'copySettings' },
31
+ ]
32
+ );
33
+ }
26
34
 
27
35
  pages.forEach(({ fileName, content }) => {
28
36
  const dest = path.resolve(cwd, 'src', 'pages', `${fileName}.tsx`);
@@ -1,5 +1,4 @@
1
1
  const indent = require('../../utils/indent');
2
-
3
2
  module.exports = (options) => {
4
3
  const { name, template, theming } = options;
5
4
  const { fillBars } = theming;
@@ -21,9 +20,7 @@ module.exports = (options) => {
21
20
  }
22
21
  if (template === 'tabs') {
23
22
  description = `
24
- <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>
25
-
26
- <p>Each tab/view may have different layout, different navbar type (dynamic, fixed or static) or without navbar like this tab.</p>
23
+ <p>Here is your blank ZMP app with tabs-layout. Let's see what we have here.</p>
27
24
  `;
28
25
  }
29
26
 
@@ -59,17 +56,21 @@ module.exports = (options) => {
59
56
  const HomePage = () => {
60
57
  ${template !== 'blank' ? "const user = useStore('user');" : ''}
61
58
  return (
62
- <Page name="home" navbarLarge>
63
- {/* Top Navbar */}
59
+ <Page name="home" ${template === 'tabs' ? '' : 'navbarLarge'}>
60
+ ${
61
+ template !== 'tabs'
62
+ ? `{/* Top Navbar */}
64
63
  <Navbar ${fillBars ? 'fill' : ''}>
65
64
  <NavTitleLarge>${name}</NavTitleLarge>
66
- </Navbar>
65
+ </Navbar>`
66
+ : ''
67
+ }
67
68
  {/* Page content */}
68
69
  <Card inset>
69
70
  ${description.trim()}
70
71
  </Card>
71
72
  ${
72
- template !== 'blank'
73
+ template !== 'blank' && template !== 'tabs'
73
74
  ? `
74
75
  {/* User info */}
75
76
  <List>
@@ -84,6 +85,22 @@ module.exports = (options) => {
84
85
  {/* Route */}
85
86
  <List>
86
87
  <ListItem title="Dynamic (Component) Route" link="/dynamic-route/?blog=45&post=125&foo=bar" />
88
+ <ListItem title="Default Route (404)" link="/something-that-doesnt-exist" />
89
+ <ListItem title="About" link="/about/" />
90
+ </List>
91
+ `.trim()
92
+ : ''
93
+ }
94
+ ${
95
+ template === 'tabs'
96
+ ? `
97
+ {/* Grid apps */}
98
+ <AppItems />
99
+
100
+ {/* Route */}
101
+ <List>
102
+ <ListItem title="Dynamic (Component) Route" link="/dynamic-route/?blog=45&post=125&foo=bar" />
103
+ <ListItem title="Default Route (404)" link="/something-that-doesnt-exist" />
87
104
  <ListItem title="About" link="/about/" />
88
105
  </List>
89
106
  `.trim()
@@ -92,6 +109,7 @@ module.exports = (options) => {
92
109
  </Page>
93
110
  );
94
111
  }
112
+
95
113
  export default HomePage;
96
114
  `
97
115
  ).trim();
@@ -18,18 +18,59 @@ module.exports = (options) => {
18
18
  `
19
19
  ).trim();
20
20
  }
21
+ if (template === 'tabs') {
22
+ views = indent(
23
+ 12,
24
+ `
25
+ {/* TabView container */}
26
+ <TabView className="safe-areas">
27
+ {/* Tabbar for switching Tab*/}
28
+ <Tabbar bottom id="app-tab-bar">
29
+ <Link tabLink="#view-home" iconZMP="zi-home" tabLinkActive>
30
+ Home
31
+ </Link>
32
+ <Link tabLink="#view-catalog" iconZMP="zi-list-1">
33
+ Catalog
34
+ </Link>
35
+ <Link tabLink="#view-settings" iconZMP="zi-setting">
36
+ Settings
37
+ </Link>
38
+ </Tabbar>
39
+
40
+ <View id="view-home" main tab tabActive url="/" />
41
+ <View id="view-catalog" name="catalog" tab url="/catalog/" />
42
+ <View id="view-settings" name="settings" tab url="/settings/" />
43
+ </TabView>
44
+ `
45
+ );
46
+ }
47
+
21
48
  return indent(
22
49
  0,
23
50
  `
24
51
  import React from 'react';
25
- ${`
52
+ ${
53
+ ['blank', 'single-view'].indexOf(template) >= 0
54
+ ? `
55
+ import {
56
+ zmp,
57
+ zmpready,
58
+ App,
59
+ View,
60
+ } from 'zmp-framework/react';
61
+ `.trim()
62
+ : `
26
63
  import {
27
64
  zmp,
28
65
  zmpready,
29
66
  App,
67
+ TabView,
30
68
  View,
69
+ Tabbar,
70
+ Link,
31
71
  } from 'zmp-framework/react';
32
- `.trim()}
72
+ `.trim()
73
+ }
33
74
  import store from '../store';
34
75
 
35
76
  const MyApp = () => {
@@ -5,6 +5,8 @@ module.exports = (options) => {
5
5
  return [];
6
6
  }
7
7
  const routes = ['/user', '/form', '/dynamic-route', '/about', '/404'];
8
-
8
+ if (template === 'tabs') {
9
+ routes.push(...['/catalog', '/settings']);
10
+ }
9
11
  return routes;
10
12
  };
@@ -1,5 +1,6 @@
1
1
  const indent = require('../../../utils/indent');
2
2
 
3
+ // eslint-disable-next-line no-unused-vars
3
4
  module.exports = (options) => {
4
5
  return indent(
5
6
  0,
@@ -11,7 +12,7 @@ module.exports = (options) => {
11
12
  const NotFoundPage = () => (
12
13
  <Page>
13
14
  <NavbarBack title="Not found" />
14
- <Box mt={2}>
15
+ <Box mt="2">
15
16
  <Card inset>
16
17
  <Title>Sorry</Title>
17
18
  <p>Requested content not found.</p>
@@ -1,5 +1,6 @@
1
1
  const indent = require('../../../utils/indent');
2
2
 
3
+ // eslint-disable-next-line no-unused-vars
3
4
  module.exports = (options) => {
4
5
  return indent(
5
6
  0,
@@ -0,0 +1,60 @@
1
+ const indent = require('../../../utils/indent');
2
+
3
+ // eslint-disable-next-line no-unused-vars
4
+ module.exports = (options) => {
5
+ return indent(
6
+ 0,
7
+ `
8
+ import React from "react";
9
+ import {
10
+ Page,
11
+ Title,
12
+ List,
13
+ ListItem,
14
+ Box,
15
+ Button,
16
+ useStore
17
+ } from "zmp-framework/react";
18
+ import store from "../store";
19
+
20
+ const CatalogPage = () => {
21
+ const products = useStore("products");
22
+
23
+ const addProduct = () => {
24
+ store.dispatch("addProduct", {
25
+ id: "4",
26
+ title: "Apple iPhone 12",
27
+ description:
28
+ "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi tempora similique reiciendis, error nesciunt vero, blanditiis pariatur dolor, minima sed sapiente rerum, dolorem corrupti hic modi praesentium unde saepe perspiciatis."
29
+ });
30
+ };
31
+
32
+ return (
33
+ <Page name="catalog">
34
+ <Box m="0" p="4">
35
+ <Title>Catalog</Title>
36
+ <List>
37
+ {products.map((product) => (
38
+ <ListItem
39
+ key={product.id}
40
+ title={product.title}
41
+ link={\`/product/\${product.id}/\`}
42
+ />
43
+ ))}
44
+ </List>
45
+ {products.length === 3 && (
46
+ <Box>
47
+ <Button responsive typeName="secondary" onClick={addProduct}>
48
+ Add Product
49
+ </Button>
50
+ </Box>
51
+ )}
52
+ </Box>
53
+ </Page>
54
+ );
55
+ };
56
+
57
+ export default CatalogPage;
58
+ `
59
+ ).trim();
60
+ };
@@ -1,5 +1,6 @@
1
1
  const indent = require('../../../utils/indent');
2
2
 
3
+ // eslint-disable-next-line no-unused-vars
3
4
  module.exports = (options) => {
4
5
  return indent(
5
6
  0,
@@ -1,6 +1,15 @@
1
1
  const indent = require('../../../utils/indent');
2
2
 
3
3
  module.exports = (options) => {
4
+ const { template } = options;
5
+ const hideNavBar =
6
+ template === 'tabs'
7
+ ? ` onPageBeforeIn={()=>{
8
+ //hide navbar
9
+ zmp.toolbar.hide('#app-tab-bar')
10
+ }}`
11
+ : '';
12
+
4
13
  return indent(
5
14
  0,
6
15
  `
@@ -36,7 +45,10 @@ module.exports = (options) => {
36
45
  }
37
46
 
38
47
  return (
39
- <Page name="user-form">
48
+ <Page
49
+ name="user-form"
50
+ ${hideNavBar}
51
+ >
40
52
  <NavbarBack title="Update user info" />
41
53
  <Box>
42
54
  <Card inset>
@@ -3,6 +3,8 @@ const copyForm = require('./form');
3
3
  const copyDynamicRoute = require('./dynamic-route');
4
4
  const copyAbout = require('./about');
5
5
  const copy404 = require('./404');
6
+ const copySettings = require('./settings');
7
+ const copyCatalog = require('./catalog');
6
8
 
7
9
  module.exports = {
8
10
  copyUser,
@@ -10,4 +12,6 @@ module.exports = {
10
12
  copyDynamicRoute,
11
13
  copyAbout,
12
14
  copy404,
15
+ copySettings,
16
+ copyCatalog,
13
17
  };
@@ -0,0 +1,39 @@
1
+ const indent = require('../../../utils/indent');
2
+
3
+ // eslint-disable-next-line no-unused-vars
4
+ module.exports = (options) => {
5
+ return indent(
6
+ 0,
7
+ `
8
+ import React from "react";
9
+ import {
10
+ Page,
11
+ List,
12
+ ListItem,
13
+ useStore,
14
+ Title,
15
+ Box
16
+ } from "zmp-framework/react";
17
+ import UserCard from "../components/user-card";
18
+
19
+ const SettingsPage = () => {
20
+ const user = useStore("user");
21
+
22
+ return (
23
+ <Page name="settings">
24
+ <Box m="0" p="4">
25
+ <Title>Settings</Title>
26
+ <List className="m-0">
27
+ <ListItem link="/user/">
28
+ <UserCard user={user} />
29
+ </ListItem>
30
+ </List>
31
+ </Box>
32
+ </Page>
33
+ );
34
+ };
35
+
36
+ export default SettingsPage;
37
+ `
38
+ ).trim();
39
+ };
@@ -1,18 +1,33 @@
1
1
  const indent = require('../../../utils/indent');
2
2
 
3
3
  module.exports = (options) => {
4
+ const { template } = options;
5
+ const hideNavBar =
6
+ template === 'tabs'
7
+ ? ` onPageBeforeIn={()=>{
8
+ //hide navbar
9
+ zmp.toolbar.hide('#app-tab-bar')
10
+ }}`
11
+ : '';
12
+ const modules = ['Avatar', 'List', 'ListItem', 'Page', 'Title', 'useStore'];
13
+ if (template === 'tabs') {
14
+ modules.push('zmp');
15
+ }
4
16
  return indent(
5
17
  0,
6
18
  `
7
19
  import React from 'react'
8
- import { Avatar , List, ListItem, Page, Title, useStore } from 'zmp-framework/react'
20
+ import { ${modules.join(', ')} } from 'zmp-framework/react'
9
21
  import NavbarBack from '../components/navbar-back'
10
22
 
11
23
  const UserPage = () => {
12
24
  const user = useStore('user')
13
25
 
14
26
  return (
15
- <Page name="user">
27
+ <Page
28
+ name="user"
29
+ ${hideNavBar}
30
+ >
16
31
  <NavbarBack
17
32
  title="User info"
18
33
  linkRight="/form"
@@ -6,7 +6,7 @@ module.exports = function generatePackageJson(options) {
6
6
 
7
7
  // Dependencies
8
8
  const dependencies = ['zmp-framework', 'zmp-sdk', 'swiper'];
9
- const dependenciesVue = ['vue@3', 'zmp-framework@next'];
9
+ const dependenciesVue = ['vue@3', 'zmp-framework'];
10
10
  const dependenciesReact = ['react', 'react-dom', 'prop-types'];
11
11
  const dependenciesReactTs = ['@types/react', '@types/react-dom'];
12
12
  const tailwindDependencies = [
@@ -72,9 +72,9 @@ module.exports = function generatePackageJson(options) {
72
72
  const content = `
73
73
  {
74
74
  "name": "${name
75
- .toLowerCase()
76
- .replace(/[ ]{2,}/, ' ')
77
- .replace(/ /g, '-')}",
75
+ .toLowerCase()
76
+ .replace(/[ ]{2,}/, ' ')
77
+ .replace(/ /g, '-')}",
78
78
  "private": true,
79
79
  "version": "1.0.0",
80
80
  "description": "${name}",
@@ -73,7 +73,8 @@ const questions = [
73
73
  {
74
74
  type: 'list',
75
75
  name: 'template',
76
- when: (opts) => opts.newProject && opts.useUIKits && opts.framework !== 'vue',
76
+ when: (opts) =>
77
+ opts.newProject && opts.useUIKits && opts.framework !== 'vue',
77
78
  message: 'Choose starter template:',
78
79
  choices: [
79
80
  {
@@ -85,14 +86,8 @@ const questions = [
85
86
  value: 'single-view',
86
87
  },
87
88
  {
88
- name: 'Tabbed Views (Tabs)',
89
+ name: 'Tabs Layout',
89
90
  value: 'tabs',
90
- disabled: true,
91
- },
92
- {
93
- name: 'Split View (Split Panel)',
94
- value: 'split-view',
95
- disabled: true,
96
91
  },
97
92
  ],
98
93
  },
@@ -100,7 +95,8 @@ const questions = [
100
95
  {
101
96
  type: 'list',
102
97
  name: 'template',
103
- when: (opts) => opts.newProject && !opts.useUIKits && opts.framework !== 'vue',
98
+ when: (opts) =>
99
+ opts.newProject && !opts.useUIKits && opts.framework !== 'vue',
104
100
  message: 'Choose starter template:',
105
101
  choices: [
106
102
  {
package/deploy/index.js CHANGED
File without changes
package/login/index.js CHANGED
File without changes
package/migrate/index.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zmp-cli",
3
- "version": "3.7.2",
3
+ "version": "3.8.0",
4
4
  "description": "ZMP command line utility (CLI)",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -103,4 +103,4 @@
103
103
  "eslint-plugin-promise": "^4.2.1",
104
104
  "eslint-plugin-standard": "^5.0.0"
105
105
  }
106
- }
106
+ }
package/start/index.js CHANGED
File without changes