neo.mjs 6.15.10 → 6.16.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/apps/ServiceWorker.mjs +2 -2
- package/apps/colors/app.mjs +6 -0
- package/apps/colors/childapps/widget/app.mjs +7 -0
- package/apps/colors/childapps/widget/index.html +11 -0
- package/apps/colors/childapps/widget/neo-config.json +10 -0
- package/apps/colors/childapps/widget/view/Viewport.mjs +19 -0
- package/apps/colors/index.html +11 -0
- package/apps/colors/model/Color.mjs +59 -0
- package/apps/colors/neo-config.json +9 -0
- package/apps/colors/store/Colors.mjs +24 -0
- package/apps/colors/view/BarChartComponent.mjs +67 -0
- package/apps/colors/view/PieChartComponent.mjs +53 -0
- package/apps/colors/view/TableContainer.mjs +73 -0
- package/apps/colors/view/Viewport.mjs +83 -0
- package/apps/colors/view/ViewportController.mjs +268 -0
- package/apps/colors/view/ViewportModel.mjs +32 -0
- package/apps/covid/view/MainContainerController.mjs +1 -1
- package/apps/portal/view/home/MainContainer.mjs +2 -12
- package/apps/sharedcovid/view/MainContainerController.mjs +1 -1
- package/buildScripts/webpack/json/myApps.template.json +1 -0
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/layout/card/MainContainer.mjs +148 -0
- package/examples/layout/card/app.mjs +6 -0
- package/examples/layout/card/index.html +11 -0
- package/examples/layout/card/neo-config.json +6 -0
- package/package.json +3 -3
- package/resources/data/deck/learnneo/pages/2023-10-14T19-25-08-153Z.md +2 -2
- package/resources/data/deck/learnneo/pages/Earthquakes.md +3 -3
- package/resources/data/deck/learnneo/pages/Setup.md +1 -1
- package/resources/data/deck/learnneo/pages/WhyNeo-Speed.md +1 -1
- package/resources/data/deck/learnneo/tree.json +1 -1
- package/resources/scss/src/apps/colors/BarChartComponent.scss +3 -0
- package/resources/scss/src/apps/colors/PieChartComponent.scss +3 -0
- package/resources/scss/src/apps/colors/TableContainer.scss +44 -0
- package/resources/scss/src/apps/colors/Viewport.scss +17 -0
- package/resources/scss/src/layout/Card.scss +17 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/component/Base.mjs +6 -0
- package/src/component/wrapper/AmChart.mjs +16 -16
- package/src/core/Base.mjs +2 -2
- package/src/data/RecordFactory.mjs +3 -0
- package/src/date/SelectorContainer.mjs +3 -0
- package/src/layout/Card.mjs +115 -24
- package/src/main/addon/AmCharts.mjs +3 -0
- package/src/model/Component.mjs +5 -1
- package/src/worker/App.mjs +2 -1
- package/test/components/files/form/field/ComboBox.mjs +4 -3
@@ -0,0 +1,268 @@
|
|
1
|
+
import Component from '../../../src/controller/Component.mjs';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @class Colors.view.ViewportController
|
5
|
+
* @extends Neo.controller.Component
|
6
|
+
*/
|
7
|
+
class ViewportController extends Component {
|
8
|
+
static config = {
|
9
|
+
/**
|
10
|
+
* @member {String} className='Colors.view.ViewportController'
|
11
|
+
* @protected
|
12
|
+
*/
|
13
|
+
className: 'Colors.view.ViewportController'
|
14
|
+
}
|
15
|
+
|
16
|
+
/**
|
17
|
+
* @member {String[]} connectedApps=[]
|
18
|
+
*/
|
19
|
+
connectedApps = []
|
20
|
+
/**
|
21
|
+
* @member {Number|null} intervalId
|
22
|
+
*/
|
23
|
+
intervalId = null
|
24
|
+
/**
|
25
|
+
* @member {Object} widgetIndexMap
|
26
|
+
*/
|
27
|
+
widgetIndexMap = {
|
28
|
+
'bar-chart': 3,
|
29
|
+
'pie-chart': 2,
|
30
|
+
table : 1
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* @param {String} name The name of the reference
|
35
|
+
*/
|
36
|
+
async createPopupWindow(name) {
|
37
|
+
let me = this,
|
38
|
+
widget = me.getReference(name),
|
39
|
+
winData = await Neo.Main.getWindowData(),
|
40
|
+
rect = await me.component.getDomRect(widget.vdom.id), // using the vdom id to always get the top-level node
|
41
|
+
{height, left, top, width} = rect;
|
42
|
+
|
43
|
+
height -= 50; // popup header in Chrome
|
44
|
+
left += winData.screenLeft;
|
45
|
+
top += (winData.outerHeight - winData.innerHeight + winData.screenTop);
|
46
|
+
|
47
|
+
Neo.Main.windowOpen({
|
48
|
+
url : `./childapps/widget/index.html?name=${name}`,
|
49
|
+
windowFeatures: `height=${height},left=${left},top=${top},width=${width}`,
|
50
|
+
windowName : name
|
51
|
+
})
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* @returns {Object[]}
|
56
|
+
*/
|
57
|
+
generateData() {
|
58
|
+
let me = this,
|
59
|
+
data = [],
|
60
|
+
i = 0,
|
61
|
+
len = 20;
|
62
|
+
|
63
|
+
for (; i < len; i++) {
|
64
|
+
data.push({
|
65
|
+
id : `row${i + 1}`,
|
66
|
+
columnA: me.getRandomInteger(),
|
67
|
+
columnB: me.getRandomInteger(),
|
68
|
+
columnC: me.getRandomInteger(),
|
69
|
+
columnD: me.getRandomInteger(),
|
70
|
+
columnE: me.getRandomInteger(),
|
71
|
+
columnF: me.getRandomInteger(),
|
72
|
+
columnG: me.getRandomInteger(),
|
73
|
+
columnH: me.getRandomInteger(),
|
74
|
+
columnI: me.getRandomInteger(),
|
75
|
+
columnJ: me.getRandomInteger()
|
76
|
+
})
|
77
|
+
}
|
78
|
+
|
79
|
+
return data
|
80
|
+
}
|
81
|
+
|
82
|
+
/**
|
83
|
+
* @returns {Number}
|
84
|
+
*/
|
85
|
+
getRandomInteger() {
|
86
|
+
return Math.floor(Math.random() * 5) + 1
|
87
|
+
}
|
88
|
+
|
89
|
+
/**
|
90
|
+
* @param {Object} data
|
91
|
+
* @param {String} data.appName
|
92
|
+
* @param {Number} data.windowId
|
93
|
+
*/
|
94
|
+
async onAppConnect(data) {
|
95
|
+
if (data.appName !== 'Colors') {
|
96
|
+
let me = this,
|
97
|
+
app = Neo.apps[data.appName],
|
98
|
+
mainView = app.mainView,
|
99
|
+
{windowId} = data,
|
100
|
+
url = await Neo.Main.getByPath({path: 'document.URL', windowId}),
|
101
|
+
widgetName = new URL(url).searchParams.get('name'),
|
102
|
+
widget = me.getReference(widgetName),
|
103
|
+
widgetParent = widget.up();
|
104
|
+
|
105
|
+
me.connectedApps.push(widgetName);
|
106
|
+
|
107
|
+
widgetParent.remove(widget, false);
|
108
|
+
mainView.add(widget)
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
/**
|
113
|
+
* @param {Object} data
|
114
|
+
* @param {String} data.appName
|
115
|
+
* @param {Number} data.windowId
|
116
|
+
*/
|
117
|
+
async onAppDisconnect(data) {
|
118
|
+
let me = this,
|
119
|
+
{appName, windowId} = data,
|
120
|
+
url = await Neo.Main.getByPath({path: 'document.URL', windowId}),
|
121
|
+
widgetName = new URL(url).searchParams.get('name'),
|
122
|
+
widget = me.getReference(widgetName),
|
123
|
+
widgetParent = widget.up();
|
124
|
+
|
125
|
+
// Closing a code preview window needs to drop the preview back into the related main app
|
126
|
+
if (appName !== 'Colors') {
|
127
|
+
widgetParent.remove(widget, false);
|
128
|
+
me.component.insert(me.widgetIndexMap[widgetName], widget);
|
129
|
+
|
130
|
+
me.getReference(`detach-${widgetName}-button`).disabled = false
|
131
|
+
}
|
132
|
+
// Close popup windows when closing or reloading the main window
|
133
|
+
else {
|
134
|
+
Neo.Main.windowClose({names: me.connectedApps, windowId})
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
/**
|
139
|
+
*
|
140
|
+
*/
|
141
|
+
onConstructed() {
|
142
|
+
super.onConstructed();
|
143
|
+
|
144
|
+
let me = this;
|
145
|
+
|
146
|
+
Neo.currentWorker.on({
|
147
|
+
connect : me.onAppConnect,
|
148
|
+
disconnect: me.onAppDisconnect,
|
149
|
+
scope : me
|
150
|
+
})
|
151
|
+
}
|
152
|
+
|
153
|
+
/**
|
154
|
+
*
|
155
|
+
*/
|
156
|
+
onComponentConstructed() {
|
157
|
+
super.onComponentConstructed();
|
158
|
+
|
159
|
+
let me = this,
|
160
|
+
data = me.generateData();
|
161
|
+
|
162
|
+
me.getStore('colors').data = data;
|
163
|
+
me.updateCharts(data)
|
164
|
+
}
|
165
|
+
|
166
|
+
/**
|
167
|
+
* @param {Object} data
|
168
|
+
*/
|
169
|
+
async onDetachBarChartButtonClick(data) {
|
170
|
+
data.component.disabled = true;
|
171
|
+
await this.createPopupWindow('bar-chart')
|
172
|
+
}
|
173
|
+
|
174
|
+
/**
|
175
|
+
* @param {Object} data
|
176
|
+
*/
|
177
|
+
async onDetachPieChartButtonClick(data) {
|
178
|
+
data.component.disabled = true;
|
179
|
+
await this.createPopupWindow('pie-chart')
|
180
|
+
}
|
181
|
+
|
182
|
+
/**
|
183
|
+
* @param {Object} data
|
184
|
+
*/
|
185
|
+
async onDetachTableButtonClick(data) {
|
186
|
+
data.component.disabled = true;
|
187
|
+
await this.createPopupWindow('table')
|
188
|
+
}
|
189
|
+
|
190
|
+
/**
|
191
|
+
* @param {Object} data
|
192
|
+
*/
|
193
|
+
onStopButtonClick(data) {
|
194
|
+
let me = this;
|
195
|
+
|
196
|
+
if (me.intervalId) {
|
197
|
+
clearInterval(me.intervalId);
|
198
|
+
me.intervalId = null
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
/**
|
203
|
+
* @param {Object} data
|
204
|
+
*/
|
205
|
+
onStartButtonClick(data) {
|
206
|
+
let me = this,
|
207
|
+
intervalTime = 1000 / 60, // assuming 60 FPS
|
208
|
+
store = me.getStore('colors'),
|
209
|
+
table = me.getReference('table'),
|
210
|
+
tableView = table.view;
|
211
|
+
|
212
|
+
if (!me.intervalId) {
|
213
|
+
me.intervalId = setInterval(() => {
|
214
|
+
let data = me.generateData();
|
215
|
+
|
216
|
+
tableView.silentVdomUpdate = true;
|
217
|
+
|
218
|
+
store.items.forEach((record, index) => {
|
219
|
+
record.set(data[index])
|
220
|
+
});
|
221
|
+
|
222
|
+
tableView.silentVdomUpdate = false;
|
223
|
+
|
224
|
+
tableView.update();
|
225
|
+
|
226
|
+
me.updateCharts(data)
|
227
|
+
}, intervalTime);
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
/**
|
232
|
+
* @param {Object} data
|
233
|
+
*/
|
234
|
+
updateCharts(data) {
|
235
|
+
let startCharCode = 'A'.charCodeAt(0),
|
236
|
+
colorSummary = {
|
237
|
+
colorA: 0,
|
238
|
+
colorB: 0,
|
239
|
+
colorC: 0,
|
240
|
+
colorD: 0,
|
241
|
+
colorE: 0
|
242
|
+
},
|
243
|
+
chartData;
|
244
|
+
|
245
|
+
data.forEach(item => {
|
246
|
+
Object.entries(item).forEach(([key, value]) => {
|
247
|
+
if (key !== 'id') {
|
248
|
+
colorSummary['color' + String.fromCharCode(startCharCode + value - 1)]++
|
249
|
+
}
|
250
|
+
})
|
251
|
+
});
|
252
|
+
|
253
|
+
chartData = [
|
254
|
+
{color: '#247acb', count: colorSummary['colorA']},
|
255
|
+
{color: '#4493de', count: colorSummary['colorB']},
|
256
|
+
{color: '#6face6', count: colorSummary['colorC']},
|
257
|
+
{color: '#9bc5ed', count: colorSummary['colorD']},
|
258
|
+
{color: '#c6def5', count: colorSummary['colorE']}
|
259
|
+
];
|
260
|
+
|
261
|
+
this.getReference('bar-chart').chartData = chartData;
|
262
|
+
this.getReference('pie-chart').chartData = chartData
|
263
|
+
}
|
264
|
+
}
|
265
|
+
|
266
|
+
Neo.setupClass(ViewportController);
|
267
|
+
|
268
|
+
export default ViewportController;
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import Component from '../../../src/model/Component.mjs';
|
2
|
+
import ColorsStore from '../store/Colors.mjs';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @class Colors.view.ViewportModel
|
6
|
+
* @extends Neo.model.Component
|
7
|
+
*/
|
8
|
+
class ViewportModel extends Component {
|
9
|
+
static config = {
|
10
|
+
/**
|
11
|
+
* @member {String} className='Colors.view.ViewportModel'
|
12
|
+
* @protected
|
13
|
+
*/
|
14
|
+
className: 'Colors.view.ViewportModel',
|
15
|
+
/**
|
16
|
+
* @member {Object} data
|
17
|
+
*/
|
18
|
+
data: {},
|
19
|
+
/**
|
20
|
+
* @member {Object} stores
|
21
|
+
*/
|
22
|
+
stores: {
|
23
|
+
colors: {
|
24
|
+
module: ColorsStore
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
Neo.setupClass(ViewportModel);
|
31
|
+
|
32
|
+
export default ViewportModel;
|
@@ -56,11 +56,11 @@ class Viewport extends Container {
|
|
56
56
|
|
57
57
|
items: [{
|
58
58
|
module: ContentBox,
|
59
|
-
header: '
|
59
|
+
header: 'Next-Generation Runtime',
|
60
60
|
route : '#/learn/WhyNeo-Quick',
|
61
61
|
|
62
62
|
content: [
|
63
|
-
'
|
63
|
+
'Multi-threaded',
|
64
64
|
'Elegant state management',
|
65
65
|
'Simple and powerful debugging'
|
66
66
|
]
|
@@ -74,16 +74,6 @@ class Viewport extends Container {
|
|
74
74
|
'Over 40,000 delta updates per second',
|
75
75
|
'Item 3'
|
76
76
|
]
|
77
|
-
}, {
|
78
|
-
module: ContentBox,
|
79
|
-
header: 'Multi Window Apps',
|
80
|
-
route : '#/learn/WhyNeo-Multi-Window',
|
81
|
-
|
82
|
-
content: [
|
83
|
-
'Item 1',
|
84
|
-
'Item 2',
|
85
|
-
'Item 3'
|
86
|
-
]
|
87
77
|
}]
|
88
78
|
}]
|
89
79
|
}
|
@@ -0,0 +1,148 @@
|
|
1
|
+
import ConfigurationViewport from '../../ConfigurationViewport.mjs';
|
2
|
+
import Container from '../../../src/container/Base.mjs';
|
3
|
+
import NumberField from '../../../src/form/field/Number.mjs';
|
4
|
+
import Radio from '../../../src/form/field/Radio.mjs';
|
5
|
+
import Toolbar from '../../../src/toolbar/Base.mjs';
|
6
|
+
|
7
|
+
/**
|
8
|
+
* @class Neo.examples.layout.card.MainContainer
|
9
|
+
* @extends Neo.examples.ConfigurationViewport
|
10
|
+
*/
|
11
|
+
class MainContainer extends ConfigurationViewport {
|
12
|
+
static config = {
|
13
|
+
className : 'Neo.examples.layout.card.MainContainer',
|
14
|
+
configItemLabelWidth: 160,
|
15
|
+
configItemWidth : 280,
|
16
|
+
layout : {ntype: 'hbox', align: 'stretch'}
|
17
|
+
}
|
18
|
+
|
19
|
+
createConfigurationComponents() {
|
20
|
+
let me = this,
|
21
|
+
{layout} = me.exampleComponent.getItem('card-container');
|
22
|
+
|
23
|
+
return [{
|
24
|
+
module : Radio,
|
25
|
+
checked : layout.slideDirection === 'horizontal',
|
26
|
+
hideValueLabel: false,
|
27
|
+
labelText : 'slideDirection',
|
28
|
+
listeners : {change: me.onRadioLayoutChange.bind(me, 'slideDirection', 'horizontal')},
|
29
|
+
name : 'slideDirection',
|
30
|
+
valueLabelText: 'horizontal'
|
31
|
+
}, {
|
32
|
+
module : Radio,
|
33
|
+
checked : layout.slideDirection === 'vertical',
|
34
|
+
hideValueLabel: false,
|
35
|
+
labelText : '',
|
36
|
+
listeners : {change: me.onRadioLayoutChange.bind(me, 'slideDirection', 'vertical')},
|
37
|
+
name : 'slideDirection',
|
38
|
+
valueLabelText: 'vertical'
|
39
|
+
}, {
|
40
|
+
module : Radio,
|
41
|
+
checked : layout.slideDirection === null,
|
42
|
+
hideValueLabel: false,
|
43
|
+
labelText : '',
|
44
|
+
listeners : {change: me.onRadioLayoutChange.bind(me, 'slideDirection', null)},
|
45
|
+
name : 'slideDirection',
|
46
|
+
valueLabelText: 'null'
|
47
|
+
}, {
|
48
|
+
module : NumberField,
|
49
|
+
clearable : true,
|
50
|
+
labelText : 'height',
|
51
|
+
listeners : {change: me.onConfigChange.bind(me, 'height')},
|
52
|
+
maxValue : 300,
|
53
|
+
minValue : 30,
|
54
|
+
stepSize : 5,
|
55
|
+
style : {marginTop: '10px'},
|
56
|
+
value : me.exampleComponent.height
|
57
|
+
}, {
|
58
|
+
module : NumberField,
|
59
|
+
clearable : true,
|
60
|
+
labelText : 'width',
|
61
|
+
listeners : {change: me.onConfigChange.bind(me, 'width')},
|
62
|
+
maxValue : 300,
|
63
|
+
minValue : 100,
|
64
|
+
stepSize : 5,
|
65
|
+
style : {marginTop: '10px'},
|
66
|
+
value : me.exampleComponent.width
|
67
|
+
}];
|
68
|
+
}
|
69
|
+
|
70
|
+
/**
|
71
|
+
* @returns {Neo.component.Base}
|
72
|
+
*/
|
73
|
+
createExampleComponent() {
|
74
|
+
return Neo.create({
|
75
|
+
module : Container,
|
76
|
+
height : 300,
|
77
|
+
width : 400,
|
78
|
+
|
79
|
+
items: [{
|
80
|
+
module : Container,
|
81
|
+
layout : {ntype: 'card', slideDirection: 'horizontal'},
|
82
|
+
reference: 'card-container',
|
83
|
+
|
84
|
+
items: [{
|
85
|
+
style: {backgroundColor: 'red'}
|
86
|
+
}, {
|
87
|
+
style: {backgroundColor: 'blue'}
|
88
|
+
}, {
|
89
|
+
style: {backgroundColor: 'green'}
|
90
|
+
}]
|
91
|
+
}, {
|
92
|
+
module: Toolbar,
|
93
|
+
flex : 'none',
|
94
|
+
style : {marginTop: '1em'},
|
95
|
+
|
96
|
+
items: [{
|
97
|
+
disabled: true,
|
98
|
+
handler : 'up.onPrevButtonClick',
|
99
|
+
reference: 'prev-button',
|
100
|
+
text : 'Prev'
|
101
|
+
}, '->', {
|
102
|
+
handler : 'up.onNextButtonClick',
|
103
|
+
reference: 'next-button',
|
104
|
+
text : 'Next'
|
105
|
+
}]
|
106
|
+
}]
|
107
|
+
})
|
108
|
+
}
|
109
|
+
|
110
|
+
/**
|
111
|
+
* @param {Object} data
|
112
|
+
*/
|
113
|
+
onNextButtonClick(data) {
|
114
|
+
let cardContainer = this.getItem('card-container'),
|
115
|
+
{layout} = cardContainer;
|
116
|
+
|
117
|
+
layout.activeIndex++;
|
118
|
+
data.component.disabled = layout.activeIndex === cardContainer.items.length - 1;
|
119
|
+
this.getItem('prev-button').disabled = false
|
120
|
+
}
|
121
|
+
|
122
|
+
/**
|
123
|
+
* @param {String} config
|
124
|
+
* @param {String} value
|
125
|
+
* @param {Object} opts
|
126
|
+
*/
|
127
|
+
onRadioLayoutChange(config, value, opts) {
|
128
|
+
if (opts.value === true) { // we only want to listen to check events, not uncheck
|
129
|
+
this.getItem('card-container').layout[config] = value
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* @param {Object} data
|
135
|
+
*/
|
136
|
+
onPrevButtonClick(data) {
|
137
|
+
let cardContainer = this.getItem('card-container'),
|
138
|
+
{layout} = cardContainer;
|
139
|
+
|
140
|
+
layout.activeIndex--;
|
141
|
+
data.component.disabled = layout.activeIndex === 0;
|
142
|
+
this.getItem('next-button').disabled = false
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
Neo.setupClass(MainContainer);
|
147
|
+
|
148
|
+
export default MainContainer;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!DOCTYPE HTML>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
<title>Neo Card Layout</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<script src="../../../src/MicroLoader.mjs" type="module"></script>
|
10
|
+
</body>
|
11
|
+
</html>
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "neo.mjs",
|
3
|
-
"version": "6.
|
3
|
+
"version": "6.16.0",
|
4
4
|
"description": "The webworkers driven UI framework",
|
5
5
|
"type": "module",
|
6
6
|
"repository": {
|
@@ -52,8 +52,8 @@
|
|
52
52
|
"envinfo": "^7.12.0",
|
53
53
|
"fs-extra": "^11.2.0",
|
54
54
|
"highlightjs-line-numbers.js": "^2.8.0",
|
55
|
-
"inquirer": "^9.2.
|
56
|
-
"marked": "^12.0.
|
55
|
+
"inquirer": "^9.2.19",
|
56
|
+
"marked": "^12.0.2",
|
57
57
|
"monaco-editor": "^0.47.0",
|
58
58
|
"neo-jsdoc": "1.0.1",
|
59
59
|
"neo-jsdoc-x": "1.0.5",
|
@@ -22,10 +22,10 @@ The `docs` directory holds the Neo.mjs API docs.
|
|
22
22
|
## The structure of a simple app
|
23
23
|
|
24
24
|
In order to discuss the structure of an app, we'll create a simple starter
|
25
|
-
app
|
25
|
+
app via this script, run from the workspace. The script prompts for various
|
26
26
|
application settings.
|
27
27
|
|
28
|
-
`npm run create-app-
|
28
|
+
`npm run create-app-minimal`
|
29
29
|
|
30
30
|
At the first prompt, we'll name the app `Foo`, and accept the default for everything else.
|
31
31
|
The script creates an application structured as follows.
|
@@ -41,7 +41,7 @@ In this lab, you'll generate a Neo.mjs workspace and run the starter app.
|
|
41
41
|
|
42
42
|
<details>
|
43
43
|
<summary>Wait!</summary>
|
44
|
-
You may already have a workspace! If so, you can skip this lab. For example, if you followed the
|
44
|
+
You may already have a workspace! If so, you can skip this lab. For example, if you followed the <a href="#/learn/Setup">Getting Started > Setup</a> topic, above, you should already have a workspace.
|
45
45
|
|
46
46
|
If you don't have a workspace, then continue on to the next step.
|
47
47
|
</details>
|
@@ -125,7 +125,7 @@ Parallel processing — along wih the efficient way the vdom worker applies
|
|
125
125
|
If you look in the `package.json` script block you'll see several scripts used for generating applications
|
126
126
|
and classes, doing builds, and starting a server. We'll use several of them throughout the tutorials.
|
127
127
|
|
128
|
-
-
|
128
|
+
- — creates a simple demo app
|
129
129
|
- create-app-minimal — creates a application shell with no content
|
130
130
|
- server-start — starts a server with webroot set to the workspace
|
131
131
|
- build-all — builds minimized versions of your apps
|
@@ -146,7 +146,7 @@ In this lab you'll create a starter app and add a single component.
|
|
146
146
|
Use a terminal window to navigate to the workspace and run the following script. Use "Earthquakes"
|
147
147
|
as the app name, and defaults for everything else.
|
148
148
|
|
149
|
-
npm run
|
149
|
+
npm run create-app-minimal
|
150
150
|
|
151
151
|
After the script runs yous should see these files in the `app/earthquakes` directory.
|
152
152
|
|
@@ -22,4 +22,4 @@ Then run the following command, choosing the defaults for each prompt.
|
|
22
22
|
|
23
23
|
When you're finished you should have a Neo.mjs workspace, as described in the _Workspaces and Applications_ topic, which follows.
|
24
24
|
|
25
|
-
|
25
|
+
It's probably a good idea to do an `npm install` in the workspace as soon as you've created it.
|
@@ -20,7 +20,7 @@ Click on Preview, then use your mouse or trackpad to pan and zoom — the he
|
|
20
20
|
If you move quickly, you might reach 20,000 or 30,000 delta updates per second. We've seen some examples that go over 40,000 updates per
|
21
21
|
second — but we've never actually hit the limit.
|
22
22
|
|
23
|
-
<pre data-neo>
|
23
|
+
<pre data-neo data-read-only>
|
24
24
|
import Base from '../../../../src/container/Base.mjs';
|
25
25
|
import Helix from '../../../../src/component/Helix.mjs';
|
26
26
|
class Foo extends Base {
|
@@ -41,7 +41,7 @@
|
|
41
41
|
{"name": "Other JavaScript Class Features", "parentId": "JavaScriptClasses", "isLeaf": true, "id": "2023-10-08T20-20-37-336Z"},
|
42
42
|
{"name": "Super", "parentId": "JavaScriptClasses", "isLeaf": true, "id": "2023-10-08T21-58-25-809Z"},
|
43
43
|
{"name": "New Node", "parentId": "JavaScriptClasses", "isLeaf": true, "id": "2023-10-31T13-59-37-550Z"},
|
44
|
-
{"name": "Appendix", "parentId": null, "id": "appendix", "collapsed": true},
|
44
|
+
{"name": "Appendix", "parentId": null, "id": "appendix", "hidden": true, "collapsed": true},
|
45
45
|
{"name": "Stylesheet", "parentId": "appendix", "isLeaf": true, "id": "stylesheet"},
|
46
46
|
{"name": "Test", "parentId": "appendix", "isLeaf": true, "id": "TestLivePreview"}
|
47
47
|
]}
|