neo.mjs 6.15.4 → 6.15.6

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 (67) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/form/view/FormContainerController.mjs +1 -1
  3. package/apps/form/view/ViewportController.mjs +2 -2
  4. package/apps/portal/view/home/MainContainer.mjs +2 -2
  5. package/apps/portal/view/learn/ContentView.mjs +1 -1
  6. package/apps/portal/view/learn/LivePreview.mjs +0 -27
  7. package/apps/realworld2/view/user/LoginFormContainer.mjs +1 -1
  8. package/docs/app/view/MainContainer.mjs +1 -11
  9. package/examples/ServiceWorker.mjs +2 -2
  10. package/examples/component/timer/MainContainerController.mjs +2 -2
  11. package/examples/component/toast/MainContainerController.mjs +2 -2
  12. package/examples/date/selectorContainer/MainContainer.mjs +215 -0
  13. package/examples/date/selectorContainer/app.mjs +6 -0
  14. package/examples/date/selectorContainer/index.html +11 -0
  15. package/examples/date/selectorContainer/neo-config.json +6 -0
  16. package/package.json +5 -5
  17. package/resources/data/deck/learnneo/pages/TestLivePreview.md +1 -2
  18. package/resources/data/deck/learnneo/pages/Welcome.md +68 -0
  19. package/resources/data/deck/learnneo/pages/WhyNeo-Multi-Threaded.md +2 -0
  20. package/resources/data/deck/learnneo/pages/WhyNeo-Multi-Window.md +3 -3
  21. package/resources/data/deck/learnneo/pages/WhyNeo-Speed.md +36 -12
  22. package/resources/data/deck/learnneo/tree.json +5 -4
  23. package/resources/scss/src/apps/portal/learn/PageContainer.scss +4 -3
  24. package/resources/scss/src/date/SelectorContainer.scss +120 -0
  25. package/resources/scss/theme-dark/date/SelectorContainer.scss +24 -0
  26. package/resources/scss/theme-light/date/SelectorContainer.scss +24 -0
  27. package/resources/scss/theme-neo-light/date/SelectorContainer.scss +24 -0
  28. package/src/DefaultConfig.mjs +2 -2
  29. package/src/Neo.mjs +5 -5
  30. package/src/component/Base.mjs +1 -1
  31. package/src/container/Base.mjs +42 -17
  32. package/src/controller/Component.mjs +5 -4
  33. package/src/core/Observable.mjs +30 -5
  34. package/src/core/Util.mjs +1 -1
  35. package/src/date/DayViewComponent.mjs +251 -0
  36. package/src/date/SelectorContainer.mjs +352 -0
  37. package/src/date/SelectorContainerModel.mjs +33 -0
  38. package/src/form/Container.mjs +10 -2
  39. package/src/form/field/Base.mjs +10 -2
  40. package/src/form/field/CheckBox.mjs +13 -5
  41. package/src/form/field/ComboBox.mjs +21 -15
  42. package/src/form/field/Date.mjs +2 -2
  43. package/src/form/field/Text.mjs +18 -17
  44. package/src/main/addon/IntersectionObserver.mjs +27 -20
  45. package/src/tab/Container.mjs +56 -55
  46. package/test/components/app.mjs +1 -0
  47. package/test/components/files/component/Base.mjs +88 -0
  48. package/test/components/siesta.js +1 -0
  49. package/docs/app/model/Tutorial.mjs +0 -41
  50. package/docs/app/store/Tutorials.mjs +0 -28
  51. package/docs/app/view/TutorialsTreeList.mjs +0 -51
  52. package/docs/tutorials/01_Concept.html +0 -45
  53. package/docs/tutorials/01_Concept.json +0 -123
  54. package/docs/tutorials/01_Concept.md +0 -55
  55. package/docs/tutorials/02_ClassSystem.html +0 -171
  56. package/docs/tutorials/02_ClassSystem.md +0 -187
  57. package/docs/tutorials/03_ComponentLifecycle.html +0 -28
  58. package/docs/tutorials/03_ComponentLifecycle.md +0 -23
  59. package/docs/tutorials/04_VdomVnode.html +0 -161
  60. package/docs/tutorials/05_RemoteMethodAccess.html +0 -82
  61. package/docs/tutorials/06_EcmaScript6Plus.html +0 -10
  62. package/docs/tutorials/07_WebWorkers.html +0 -9
  63. package/docs/tutorials/08_DomEvents.html +0 -7
  64. package/docs/tutorials/09_TodoList_version1.html +0 -503
  65. package/docs/tutorials/11_CreateApp.html +0 -94
  66. package/docs/tutorials/tutorials.json +0 -100
  67. package/resources/scss/src/apps/docs/TutorialsTreeList.scss +0 -7
@@ -1,503 +0,0 @@
1
- <div class="neo-header-text-container" xmlns="http://www.w3.org/1999/html">
2
- <span class="neo-header-text">Tutorial: Building a TodoList, Version 1</span>
3
- </div>
4
- <article>
5
- <h3>About the tutorial</h3>
6
- <p>
7
- This tutorial is split into 2 versions.
8
- </p>
9
- <ol>
10
- <li>The first version will start from scratch extending component.Base as well as dealing with the basic setup.</br>
11
- The goal is to give you a basic understanding on how to craft a custom component and work with the virtual dom.</li>
12
- <li>Version 2 will use a viewport, list & store and shows you how to solve the task using all Neo has to offer for it.</li>
13
- </ol>
14
- You can find the code-related results of each of these 2 tutorials inside neoteric/examples/todoList.</br>
15
- They are also available inside the examples tab of the docs app.
16
- <h3>1) Basic Setup</h3>
17
- <p>
18
- Since this might be your first App using Neo, let us start with the basic file structure.</br>
19
- I created 3 new files inside the neoteric/examples folder:
20
- </p>
21
- <img src="./resources/images/tutorials/todolist-v1-files.png">
22
- <ol>
23
- <li><h4>index.html:</h4>
24
- The index file needs to include Main.mjs, which is the starting point of the Neo main thread.</br>
25
- You can use this file to add config options for the Neo framework.</br>
26
- Take a look at API/Neo => config for further details.
27
- <pre><code>&lt;!DOCTYPE HTML&gt;
28
- &lt;html manifest=""&gt;
29
- &lt;head&gt;
30
- &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
31
- &lt;meta charset="UTF-8"&gt;
32
- &lt;title&gt;Neo TodoList version1&lt;/title&gt;
33
- &lt;/head&gt;
34
- &lt;body&gt;
35
- &lt;script&gt;
36
- Neo = self.Neo || {}; Neo.config = Neo.config || {};
37
-
38
- Object.assign(Neo.config, {
39
- appPath : 'examples/todoList/version1/app.mjs',
40
- basePath : '../../../',
41
- environment: 'development'
42
- });
43
- &lt;/script&gt;
44
-
45
- &lt;script src="../../../src/Main.mjs" type="module"&gt;&lt;/script&gt;
46
- &lt;/body&gt;
47
- &lt;/html&gt;</code></pre></li>
48
- <li><h4>app.mjs:</h4>
49
- <p>
50
- This file is the main entry point for the apps that you create using Neo.</br>
51
- Once the workers are started, the App worker will dynamically import this file.</br>
52
- You need to import your main view here, give your App a name and point to the directory of the app code base.</br>
53
- Be aware: Inside this scope, there is no window or window.document.</br>
54
- If you like to, you can use Neo.app() multiple times to create more than one App.
55
- </p>
56
- <pre><code>import MainComponent from './MainComponent.mjs';
57
-
58
- const onStart = () => Neo.app({
59
- appPath : 'examples/todoList/version1/',
60
- mainView: MainComponent,
61
- name : 'TodoListApp1'
62
- });
63
-
64
- export {onStart as onStart};</code></pre>
65
- </li>
66
- <li><h4>MainComponent.mjs:</h4>
67
- <p>The class definition of your main App view. In "full screen" mode, you would most likely extend container.Viewport,
68
- in case you want to render a Neo App inside an already existing Container, you can do this as well.</br>
69
- In this case you would use renderTo: 'nodeId' inside your app.mjs file.</br>
70
- For version1 we will just extend component.Base to get you familiar with some basic concepts.</p>
71
- <pre><code>import {default as Component} from '../../../src/component/Base.mjs';
72
-
73
- /**
74
- * @class TodoListApp1.MainComponent
75
- * @extends Neo.component.Base
76
- */
77
- class MainComponent extends Component {
78
- static getConfig() {return {
79
- className: 'TodoListApp1.MainComponent',
80
- ntype : 'todolistapp1-maincomponent',
81
-
82
- autoMount: true,
83
- height : 150,
84
- margin : 10,
85
- width : 300,
86
-
87
- vdom: {
88
- tag : 'div',
89
- style: {
90
- border: '1px solid #000',
91
- margin: '20px'
92
- }
93
- }
94
- }}
95
- }
96
-
97
- Neo.applyClassConfig(MainComponent);
98
-
99
- export {MainComponent as default};</code></pre>
100
- </li>
101
- </ol>
102
- <p>This is literally all you need to do to get started crafting your first custom component!</p>
103
- <p>Moving forward from here we will only need to apply changes to MainComponent.mjs.</p>
104
- <p>As a first step, let us add some content into our component:</p>
105
- <pre><code>import {default as Component} from '../../../src/component/Base.mjs';
106
-
107
- /**
108
- * @class TodoListApp1.MainComponent
109
- * @extends Neo.component.Base
110
- */
111
- class MainComponent extends Component {
112
- static getConfig() {return {
113
- className: 'TodoListApp1.MainComponent',
114
- ntype : 'todolistapp1-maincomponent',
115
-
116
- autoMount: true,
117
- height : 150,
118
- margin : 10,
119
- maxWidth : 300,
120
- style : {border: '1px solid #000', margin: '20px', overflow: 'scroll'},
121
- width : 300,
122
-
123
- /**
124
- * @member {Object[]} data
125
- */
126
- data: [
127
- {id: 1, done: true, text: 'Todo Item 1'},
128
- {id: 2, done: false, text: 'Todo Item 2'},
129
- {id: 3, done: false, text: 'Todo Item 3'}
130
- ],
131
-
132
- vdom: {
133
- tag: 'div',
134
- cn : [{
135
- tag: 'ol',
136
- cn : []
137
- }, {
138
- tag: 'div',
139
- cn : [{
140
- tag : 'input',
141
- required: true,
142
- style : {marginLeft: '20px'}
143
- }, {
144
- tag : 'button',
145
- html : 'Add Item',
146
- style: {marginLeft: '10px'}
147
- }]
148
- }]
149
- }
150
- }}
151
-
152
- construct(config) {
153
- super.construct(config);
154
- this.createItems(this.data || []);
155
- }
156
-
157
- createItems(data) {
158
- let me = this,
159
- vdom = me.vdom,
160
- cls;
161
-
162
- data.forEach(item => {
163
- cls = ['todo-item'];
164
-
165
- if (item.done) {
166
- cls.push('fa', 'fa-check');
167
- } else {
168
- cls.push('far', 'fa-square');
169
- }
170
-
171
- vdom.cn[0].cn.push({
172
- tag: 'li',
173
- cn : [{
174
- tag : 'span',
175
- cls : cls,
176
- style: {cursor: 'pointer', width: '20px'}
177
- }, {
178
- vtype: 'text',
179
- html : item.text
180
- }]
181
- });
182
- });
183
-
184
- me.vdom = vdom;
185
- }
186
- }
187
-
188
- Neo.applyClassConfig(MainComponent);
189
-
190
- export {MainComponent as default};</code></pre>
191
- <p>
192
- We moved "style" from the top level vdom node to the component level, which is equivalent.</br>
193
- height, margin, maxWidth & width are convenience shortcuts: they default to px and get assigned to the top level
194
- vdom node style property. Take a look at API/component/Base for a full list of the available configs!
195
- </p>
196
- <p>
197
- We added the custom config "data", which contains the information we need to initially render some todo-items.</br>
198
- Our constructor will call createItems() passing this data array.
199
- </p>
200
- <p>
201
- createItems() will iterate through the data array and push the new items into vdom.cn[0].cn</br>
202
- This is the ol tag which we defined inside our vdom skeleton.
203
- </p>
204
- <p>
205
- Afterwards we call me.vdom = vdom; which is not an assignment, but a setter.</br>
206
- Since our component is neither rendered nor mounted at this point, it will just change the vdom object though.
207
- </p>
208
- <p>
209
- vtype: 'text' is useful to add innerHTML behind (or before) the span tag without creating a new tag.
210
- </p>
211
- <p>
212
- Side node: You should not use so many inline styles and go for (S)CSS files instead.
213
- </p>
214
- <p>
215
- Our App will look like this now:
216
- </p>
217
-
218
- <div style="border:1px solid #000;margin:20px;overflow:scroll;height:200px;width:300px;max-width:300px;" id="neo-todolistapp1-maincomponent-1">
219
- <ol id="neo-vnode-7">
220
- <li id="neo-vnode-2"><span style="cursor:pointer;width:20px;" class="todo-item fa fa-check" id="neo-vnode-1"></span>Todo Item 1</li>
221
- <li id="neo-vnode-4"><span style="cursor:pointer;width:20px;" class="todo-item far fa-square" id="neo-vnode-3"></span>Todo Item 2</li>
222
- <li id="neo-vnode-6"><span style="cursor:pointer;width:20px;" class="todo-item far fa-square" id="neo-vnode-5"></span>Todo Item 3</li>
223
- </ol>
224
- <div id="neo-vnode-10">
225
- <input style="margin-left:20px;" class="todo-input" id="neo-vnode-8" required="">
226
- <button style="margin-left:10px;" class="todo-add-button" id="neo-vnode-9">Add Item</button>
227
- </div>
228
- </div>
229
-
230
- <p>The generated DOM will be:</p>
231
- <pre><code>&lt;div style="border:1px solid #000;margin:20px;overflow:scroll;height:200px;width:300px;max-width:300px;" id="neo-todolistapp1-maincomponent-1"&gt;
232
- &lt;ol id="neo-vnode-7"&gt;
233
- &lt;li id="neo-vnode-2"&gt;&lt;span style="cursor:pointer;width:20px;" class="todo-item fa fa-check" id="neo-vnode-1"&gt;&lt;/span&gt;Todo Item 1&lt;/li&gt;
234
- &lt;li id="neo-vnode-4"&gt;&lt;span style="cursor:pointer;width:20px;" class="todo-item far fa-square" id="neo-vnode-3"&gt;&lt;/span&gt;Todo Item 2&lt;/li&gt;
235
- &lt;li id="neo-vnode-6"&gt;&lt;span style="cursor:pointer;width:20px;" class="todo-item far fa-square" id="neo-vnode-5"&gt;&lt;/span&gt;Todo Item 3&lt;/li&gt;
236
- &lt;/ol&gt;
237
- &lt;div id="neo-vnode-10"&gt;
238
- &lt;input style="margin-left:20px;" class="todo-input" id="neo-vnode-8" required=""&gt;
239
- &lt;button style="margin-left:10px;" class="todo-add-button" id="neo-vnode-9"&gt;Add Item&lt;/button&gt;
240
- &lt;/div&gt;
241
- &lt;/div&gt;</code></pre>
242
- <p>
243
- You will notice that all dom nodes got an id. This is important for the vdom
244
- Engine to detect moved nodes.</br>
245
- Since a todoList without any logic is no fun, let's change this!
246
- </p>
247
- <pre><code>construct(config) {
248
- super.construct(config);
249
-
250
- let me = this,
251
- domListeners = me.domListeners || [];
252
-
253
- domListeners.push(
254
- {click: me.onAddButtonClick, delegate: 'todo-add-button'},
255
- {click: me.onCheckIconClick, delegate: 'todo-item'},
256
- {input: me.onInputFieldChange, delegate: 'todo-input'}
257
- );
258
-
259
- me.domListeners = domListeners;
260
-
261
- me.createItems(me.data || []);
262
- }</code></pre>
263
- <p>
264
- To interact with the real dom, it is important to use dom listeners. You can assign them locally to any dom node
265
- (in which case you need to add local: true and a dom id), but there is no need to do so. Neo will assign listeners to
266
- the document.body for all important events and they will get delegated to your components main node. In case you want
267
- to delegate further down to specific child nodes inside your component, using css classnames is a smart way to assign them to element groups.</br>
268
- (you can delegate to specific node ids as well using # => delegate: '#myNodeId')
269
- </p>
270
- <p>
271
- At this point our "Add Item" button will trigger onAddButtonClick() when it receives a click event, all check or square
272
- icons will receive onCheckIconClick() and the input field will call onInputFieldChange() in case an input event fires.
273
- </p>
274
-
275
- <pre><code>onInputFieldChange(data) {
276
- this.inputValue = data.value;
277
- }</code></pre>
278
- <p>I added a new custom config into the component (inputValue:null), which will now get the real value of the textfield.</p>
279
- <pre><code>onAddButtonClick() {
280
- let me = this;
281
-
282
- if (me.inputValue) {
283
- me.createItems([{
284
- id : null,
285
- done: false,
286
- text: me.inputValue
287
- }]);
288
- }
289
- }</code></pre>
290
- <p>
291
- Once we receive a button click, we do a check if there is a value (assigning a todo item without a name makes little sense).
292
- In case there is content, we use createItems() like before (we set the id to null, assuming it would get generated on your backend.
293
- </p>
294
- <p>
295
- Afterwards we call me.vdom = vdom; again.</br>
296
- <b>Now this part is really important:</b> At this point, our component will already be rendered & mounted.</br>
297
- Instead of just changing the vdom object locally, the setter will now send the new vdom to the vdom worker thread, it will get checked
298
- for delta updates and create a new vnode and then the main thread applies the delta updates to the real DOM.
299
- </p>
300
- <p>
301
- In case you do add a new todo item and log the resulting deltas (main.DomAccess => logDeltaUpdates:true, you will see something like:
302
- </p>
303
- <pre><code>{
304
- action : "insertNode",
305
- id : "neo-vnode-12",
306
- index : 3,
307
- outerHTML: "&lt;li id="neo-vnode-12"&gt;&lt;span style="cursor:pointer;width:20px;" class="todo-item far fa-square" id="neo-vnode-11"&gt;&lt;/span&gt;Learn Neo&lt;/li&gt;",
308
- parentId : "neo-vnode-7"
309
- }</code></pre>
310
- <p>
311
- The last missing dom listener is onCheckIconClick:
312
- </p>
313
- <pre><code>onCheckIconClick(data) {
314
- let me = this,
315
- cls = ['far', 'fa-square'],
316
- oldCls = ['fa', 'fa-check'],
317
- vdom = me.vdom,
318
- node = VdomUtil.findVdomChild(me.vdom, data.path[0].id).vdom;
319
-
320
- if (data.path[0].cls.includes('fa-square')) {
321
- cls = ['fa', 'fa-check'];
322
- oldCls = ['far', 'fa-square'];
323
- }
324
-
325
- NeoArray.remove(node.cls, oldCls);
326
- NeoArray.add(node.cls, cls);
327
-
328
- me.vdom = vdom;
329
- }</code></pre>
330
- <p>
331
- We imported NeoArray & VdomUtil to keep the logic short.<br>
332
- NeoArray add() & remove() can pass an array of items which will add / remove each item, in case it is not already there / exists.<br>
333
- VdomUtil.findVdomChild() can either pass a node id or an opts object, containing multiple vdom properties to search for.
334
- E.g. VdomUtil.findVdomChild(me.vdom, {tag:'div', cls:'color-red'}). It does return the vdom (node), the parent node and the index inside
335
- the parent node cn array.<br>
336
- Take a look at API/util/Array and API/util/Vdom for further infos!
337
- </p>
338
- <p>
339
- Of course you could as well manually iterate through the list items and spot the one with the matching id.
340
- </p>
341
- <p>
342
- The data param contains the info of the dom event (converted into json), it is available for all dom event listeners.<br>
343
- We are checking the first item inside the event path and just replace the square with a check icon or vice versa.<br>
344
- Again we are calling me.vdom = vdom; which will result in an delta update like this:
345
- </p>
346
- <pre><code>{
347
- cls: {
348
- add: ["fa", "fa-check"]
349
- remove: ["far", "fa-square"]
350
- }
351
- }</code></pre>
352
- <p>
353
- Here is the full code of our todoList component:
354
- </p>
355
-
356
- <pre><code style="height: 500px;">import {default as Component} from '../../../src/component/Base.mjs';
357
- import NeoArray from '../../../src/util/Array.mjs';
358
- import {default as VdomUtil} from '../../../src/util/VDom.mjs';
359
-
360
- /**
361
- * @class TodoListApp1.MainComponent
362
- * @extends Neo.component.Base
363
- */
364
- class MainComponent extends Component {
365
- static getConfig() {return {
366
- className: 'TodoListApp1.MainComponent',
367
- ntype : 'todolistapp1-maincomponent',
368
-
369
- autoMount: true,
370
- height : 200,
371
- margin : 10,
372
- maxWidth : 300,
373
- style : {border: '1px solid #000', margin: '20px', overflow: 'scroll'},
374
- width : 300,
375
-
376
- /**
377
- * @member {Object[]} data
378
- */
379
- data: [
380
- {id: 1, done: true, text: 'Todo Item 1'},
381
- {id: 2, done: false, text: 'Todo Item 2'},
382
- {id: 3, done: false, text: 'Todo Item 3'}
383
- ],
384
-
385
- /**
386
- * @member {String|null} inputValue=null
387
- */
388
- inputValue: null,
389
-
390
- vdom: {
391
- tag: 'div',
392
- cn : [{
393
- tag: 'ol',
394
- cn : []
395
- }, {
396
- tag: 'div',
397
- cn : [{
398
- tag : 'input',
399
- cls : ['todo-input'],
400
- required: true,
401
- style : {marginLeft: '20px'}
402
- }, {
403
- tag : 'button',
404
- cls : ['todo-add-button'],
405
- html : 'Add Item',
406
- style: {marginLeft: '10px'}
407
- }]
408
- }]
409
- }
410
- }}
411
-
412
- construct(config) {
413
- super.construct(config);
414
-
415
- let me = this,
416
- domListeners = me.domListeners || [];
417
-
418
- domListeners.push(
419
- {click: me.onAddButtonClick, delegate: 'todo-add-button'},
420
- {click: me.onCheckIconClick, delegate: 'todo-item'},
421
- {input: me.onInputFieldChange, delegate: 'todo-input'}
422
- );
423
-
424
- me.domListeners = domListeners;
425
-
426
- me.createItems(me.data || []);
427
- }
428
-
429
- createItems(data) {
430
- let me = this,
431
- vdom = me.vdom,
432
- cls;
433
-
434
- data.forEach(item => {
435
- cls = ['todo-item'];
436
-
437
- if (item.done) {
438
- cls.push('fa', 'fa-check');
439
- } else {
440
- cls.push('far', 'fa-square');
441
- }
442
-
443
- vdom.cn[0].cn.push({
444
- tag: 'li',
445
- cn : [{
446
- tag : 'span',
447
- cls : cls,
448
- style: {cursor: 'pointer', width: '20px'}
449
- }, {
450
- vtype: 'text',
451
- html : item.text
452
- }]
453
- });
454
- });
455
-
456
- me.vdom = vdom;
457
- }
458
-
459
- onAddButtonClick() {
460
- let me = this;
461
-
462
- if (me.inputValue) {
463
- me.createItems([{
464
- id : null,
465
- done: false,
466
- text: me.inputValue
467
- }]);
468
- }
469
- }
470
-
471
- onCheckIconClick(data) {
472
- let me = this,
473
- cls = ['far', 'fa-square'],
474
- oldCls = ['fa', 'fa-check'],
475
- vdom = me.vdom,
476
- node = VdomUtil.findVdomChild(me.vdom, data.path[0].id).vdom;
477
-
478
- if (data.path[0].cls.includes('fa-square')) {
479
- cls = ['fa', 'fa-check'];
480
- oldCls = ['far', 'fa-square'];
481
- }
482
-
483
- NeoArray.remove(node.cls, oldCls);
484
- NeoArray.add(node.cls, cls);
485
-
486
- me.vdom = vdom;
487
- }
488
-
489
- onInputFieldChange(data) {
490
- this.inputValue = data.value;
491
- }
492
- }
493
-
494
- Neo.applyClassConfig(MainComponent);
495
-
496
- export {MainComponent as default};</code></pre>
497
- <p>
498
- This is already the end of the version1 tutorial. Version2 will show you how to solve the task easier.
499
- </p>
500
- <p>
501
- We hope this tutorial helped you to get a basic understanding on how to create a first custom component and on how to work with dom listeners!
502
- </p>
503
- </article>
@@ -1,94 +0,0 @@
1
- <div class="neo-header-text-container">
2
- <span class="neo-header-text">Guide: the create-app script in detail</span>
3
- </div>
4
- <article>
5
- <p>Inside the package.json you will find the script "create-app", which is a very good starting point for creating
6
- your first neo.mjs app. You can run it inside the root folder of the neo.mjs repository like this:</p>
7
- <pre><code>npm run create-app</code></pre>
8
- <p>We would like to shed some light on the internals of this process to show you how to:</p>
9
- <ol>
10
- <li>Create an app using the script</li>
11
- <li>Change the name of your app</li>
12
- <li>Change the theme(s) of your app</li>
13
- <li>Create an app manually</li>
14
- <li>Remove an app you no longer need</li>
15
- <li>Enhancing the script (feature request)</li>
16
- </ol>
17
- <h3><b style="color:red;">1)</b> After running the script, you will get asked to enter the name of your app (defaults to MyApp)</h3>
18
- <img src="./resources/images/tutorials/create-app-choose-name.png">
19
- <p>Afterwards you will get asked if you want to use the neo-theme-dark, neo-theme-light or both:</p>
20
- <img src="./resources/images/tutorials/create-app-choose-theme.png">
21
- <p>This is pretty much it. You will see a new folder under neo/apps with the lowercase version of your app name.<br/>
22
- Hint: We recommend to stick to alphabetic characters for your app name.</p>
23
- <img src="./resources/images/tutorials/create-app-files.png">
24
- <p>You can see the code of the script in <a href="https://github.com/neomjs/neo/blob/dev/buildScripts/createApp.js">neo/buildScripts/createApp.js</a></p>
25
- <p>The script will check, if neo/buildScripts/webpack/development/json/myApps.json exists.<br/>
26
- The same will happen for neo/buildScripts/webpack/production/ (sticking to dev from here on, it is 1:1 for prod)</p>
27
- <p>In case the file does not exist, neo/buildScripts/webpack/development/json/myApps.template.json will get consumed to generate it.</p>
28
- <pre><code>{
29
- "bodyTag": "<body>",
30
- "buildFolder": "../../../dist/development",
31
- "environment": "development",
32
- "mainInput": "./src/Main.mjs",
33
- "mainOutput": "main.js",
34
-
35
- "workers": {
36
- "data": {
37
- "input": "./src/worker/Data.mjs",
38
- "output": "dataworker.js"
39
- },
40
- "vdom": {
41
- "input": "./src/worker/VDom.mjs",
42
- "output": "vdomworker.js"
43
- }
44
- },
45
-
46
- "apps": {
47
- "RealWorld": {
48
- "input": "myApps/RealWorld.mjs",
49
- "output": "/apps/realworld/",
50
- "title": "RealWorld"
51
- }
52
- }
53
- }</code></pre>
54
- <p>At this point, the RealWorld demo app is already included here to give you an example of how to create an neo.mjs app.
55
- The docs app is a neo.mjs app as well (and probably the better starting point.</p>
56
- <p>The .../json/myApps.json files as well as the content inside the neo/apps folder is added to the .gitignore.</p>
57
- <p>To generate the index.html file for your app, neo/buildScripts/webpack/index.ejs will get consumed.<br/>
58
- We have an open ticket to enhance this file: <a href="https://github.com/neomjs/neo/issues/134">#134</a>,
59
- please let us know in case this is important for you!</p>
60
- <h3><b style="color:red;">2)</b> Change the name of your app</h3>
61
- <ol>
62
- <li>Change the keys inside the .../json/myApps.json files (inside the apps object)</li>
63
- <li>Rename the app folder to the lowercase version of your new app name</li>
64
- <li>Open the app.mjs file inside your app folder and adjust the appPath & name</li>
65
- <li>Open the index.html file inside your app folder and adjust the appPath</li>
66
- <li>Open the MainContainer.mjs file inside your app folder and adjust the className</li>
67
- <li>Although this process feels like an edge-case, it could get automated with a new script.<br/>
68
- Feel free to open a feature request ticket in case this feels important for you!</li>
69
- </ol>
70
- <h3><b style="color:red;">3)</b> Change the theme(s) of your app</h3>
71
- <p>Open the index.html file inside your app folder and adjust the Neo.config => themes</p>
72
- <ol>
73
- <li>The default value is themes: ['neo-theme-light', 'neo-theme-dark'], so not using the config includes both themes</li>
74
- <li>themes: ['neo-theme-dark'] => include only the dark theme</li>
75
- <li>themes: ['neo-theme-light'] => include only the light theme</li>
76
- <li>themes: ['neo-theme-dark', 'neo-theme-light'] => include both themes and use the dark theme as the default one.</li>
77
- </ol>
78
- <h3><b style="color:red;">4)</b> Create an app manually</h3>
79
- <p>This process is similar to changing the app name.</p>
80
- <ol>
81
- <li>Copy an existing app folder into neo/apps and use the new lowercase app name as the folder name</li>
82
- <li>Follow the steps in <span style="color:red;">3)</span></li>
83
- <li>Add your new app into the .../json/myApps.json files</li>
84
- </ol>
85
- <h3><b style="color:red;">5)</b> Remove an app you no longer need</h3>
86
- <ol>
87
- <li>Delete your app folder inside neo/apps</li>
88
- <li>Remove the entries inside the .../json/myApps.json files.<br/>
89
- In case this was your only app, you can delete the the .../json/myApps.json files instead.</li>
90
- </ol>
91
- <h3><b style="color:red;">6)</b> Enhancing the script (feature request)</h3>
92
- <p>We do have an open feature request ticket for creating an npx script, which would allow to create neo apps
93
- outside the neo repository root folder. Please take a look at: <a href="https://github.com/neomjs/neo/issues/90">#90</a></p>
94
- </article>