neo.mjs 6.18.0 → 6.18.2

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 (44) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/colors/view/HeaderToolbar.mjs +6 -6
  3. package/apps/portal/view/HeaderToolbar.mjs +1 -2
  4. package/apps/portal/view/home/MainContainer.mjs +39 -8
  5. package/apps/portal/view/home/parts/AfterMath.mjs +19 -16
  6. package/apps/portal/view/home/parts/BaseContainer.mjs +31 -0
  7. package/apps/portal/view/home/parts/Colors.mjs +43 -19
  8. package/apps/portal/view/home/parts/Features.mjs +6 -6
  9. package/apps/portal/view/home/parts/Helix.mjs +55 -19
  10. package/apps/portal/view/home/parts/HelloWorld.mjs +11 -10
  11. package/apps/portal/view/home/parts/How.mjs +66 -0
  12. package/apps/portal/view/home/parts/MainNeo.mjs +17 -14
  13. package/examples/ServiceWorker.mjs +2 -2
  14. package/examples/model/dialog/EditUserDialog.mjs +1 -8
  15. package/package.json +1 -1
  16. package/resources/data/deck/learnneo/pages/Events.md +15 -9
  17. package/resources/data/deck/learnneo/pages/GuideEvents.md +142 -19
  18. package/resources/data/deck/learnneo/pages/GuideViewModels.md +444 -0
  19. package/resources/data/deck/learnneo/tree.json +1 -0
  20. package/resources/scss/src/apps/portal/HeaderToolbar.scss +143 -125
  21. package/resources/scss/src/apps/portal/home/MainContainer.scss +0 -45
  22. package/resources/scss/src/apps/portal/home/parts/BaseContainer.scss +27 -0
  23. package/resources/scss/src/apps/portal/home/parts/MainNeo.scss +24 -0
  24. package/resources/scss/src/apps/portal/learn/ContentTreeList.scss +1 -1
  25. package/resources/scss/src/calendar/view/EditEventContainer.scss +1 -1
  26. package/resources/scss/src/calendar/view/calendars/List.scss +1 -1
  27. package/resources/scss/src/dialog/Base.scss +1 -6
  28. package/resources/scss/theme-dark/dialog/Base.scss +1 -0
  29. package/resources/scss/theme-light/dialog/Base.scss +1 -0
  30. package/resources/scss/theme-neo-light/Global.scss +13 -11
  31. package/resources/scss/theme-neo-light/dialog/Base.scss +1 -0
  32. package/src/DefaultConfig.mjs +2 -2
  33. package/src/button/Base.mjs +3 -2
  34. package/src/calendar/view/EditEventContainer.mjs +1 -1
  35. package/src/component/Base.mjs +49 -16
  36. package/src/controller/Base.mjs +5 -5
  37. package/src/core/Observable.mjs +23 -7
  38. package/src/dialog/Base.mjs +23 -45
  39. package/src/form/field/Color.mjs +5 -5
  40. package/src/main/addon/IntersectionObserver.mjs +20 -1
  41. package/src/model/Component.mjs +11 -9
  42. package/src/selection/DateSelectorModel.mjs +2 -2
  43. package/src/util/HashHistory.mjs +45 -12
  44. package/src/worker/Base.mjs +15 -8
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='6.18.0'
23
+ * @member {String} version='6.18.2'
24
24
  */
25
- version: '6.18.0'
25
+ version: '6.18.2'
26
26
  }
27
27
 
28
28
  /**
@@ -39,31 +39,31 @@ class HeaderToolbar extends Toolbar {
39
39
  clearable : false,
40
40
  editable : false,
41
41
  labelPosition: 'inline',
42
- labelText : 'Amount Colors',
42
+ labelText : '# Colors',
43
43
  listeners : {change: 'onChangeAmountColors'},
44
44
  maxValue : 10,
45
45
  minValue : 3,
46
- width : 120
46
+ width : 90
47
47
  }, {
48
48
  module : ComboBox,
49
49
  bind : {value: data => String(data.amountColumns)},
50
50
  clearable : false,
51
51
  editable : false,
52
52
  labelPosition: 'inline',
53
- labelText : 'Amount Columns',
53
+ labelText : '# Columns',
54
54
  listeners : {change: 'onChangeAmountColumns'},
55
55
  store : ['5', '10', '15', '20', '26'],
56
- width : 120
56
+ width : 90
57
57
  }, {
58
58
  module : ComboBox,
59
59
  bind : {value: data => String(data.amountRows)},
60
60
  clearable : false,
61
61
  editable : false,
62
62
  labelPosition: 'inline',
63
- labelText : 'Amount Rows',
63
+ labelText : '# Rows',
64
64
  listeners : {change: 'onChangeAmountRows'},
65
65
  store : ['5', '10', '15', '20'],
66
- width : 120
66
+ width : 90
67
67
  }, '->', {
68
68
  handler : 'onDetachTableButtonClick',
69
69
  iconCls : 'fas fa-table',
@@ -27,9 +27,8 @@ class HeaderToolbar extends Base {
27
27
  */
28
28
  items: [{
29
29
  cls : ['logo'],
30
- id : 'neo-logo-button',
31
- minWidth: 60,
32
30
  iconCls : 'neo-logo-blue',
31
+ minWidth: 60,
33
32
  route : '/home',
34
33
  text : 'Neo.mjs'
35
34
  }, '->', {
@@ -3,6 +3,7 @@ import Colors from './parts/Colors.mjs';
3
3
  import Container from '../../../../src/container/Base.mjs';
4
4
  import Features from './parts/Features.mjs';
5
5
  import Helix from './parts/Helix.mjs';
6
+ import How from './parts/How.mjs';
6
7
  import HelloWorld from './parts/HelloWorld.mjs';
7
8
  import MainNeo from './parts/MainNeo.mjs';
8
9
 
@@ -21,28 +22,58 @@ class MainContainer extends Container {
21
22
  * @member {String[]} cls=['portal-home-maincontainer']
22
23
  */
23
24
  cls: ['portal-home-maincontainer'],
25
+ /**
26
+ * @member {Object[]} domListeners
27
+ */
28
+ domListeners: [{
29
+ intersect(data) {
30
+ Neo.getComponent(data.targetId)?.activate?.()
31
+ },
32
+ scroll(event) {
33
+ this.toggleCls('hide-sidebar', event.scrollTop > 80)
34
+ }
35
+ }],
24
36
  /**
25
37
  * @member {Object[]} items
26
38
  */
27
39
  items: [
28
- {ntype: 'component', id: 'progress'},
40
+ {ntype: 'component', cls: ['portal-home-progress']},
29
41
  MainNeo,
30
42
  Features,
31
43
  HelloWorld,
32
- Colors,
33
44
  Helix,
45
+ Colors,
46
+ How,
34
47
  AfterMath
35
48
  ],
36
49
  /**
37
50
  * @member {Boolean} scrollable=true
38
51
  */
39
- scrollable: true,
52
+ scrollable: true
53
+ }
40
54
 
41
- domListeners: [{
42
- scroll(event) {
43
- this.toggleCls('hide-sidebar', event.scrollTop > 80)
44
- }
45
- }]
55
+ /**
56
+ * Triggered after the mounted config got changed
57
+ * @param {Boolean} value
58
+ * @param {Boolean} oldValue
59
+ * @protected
60
+ */
61
+ afterSetMounted(value, oldValue) {
62
+ super.afterSetMounted(value, oldValue);
63
+
64
+ let me = this,
65
+ {id, windowId} = me;
66
+
67
+ value && setTimeout(() => {
68
+ Neo.main.addon.IntersectionObserver.register({
69
+ callback : 'isVisible',
70
+ id,
71
+ observe : ['.portal-home-content-view'],
72
+ root : `#${id}`,
73
+ threshold: 1.0,
74
+ windowId
75
+ })
76
+ }, 50)
46
77
  }
47
78
  }
48
79
 
@@ -1,54 +1,57 @@
1
- import Container from '../../../../../src/container/Base.mjs';
1
+ import BaseContainer from './BaseContainer.mjs';
2
2
 
3
3
  /**
4
4
  * @class Portal.view.home.parts.AfterMath
5
- * @extends Neo.container.Base
5
+ * @extends Portal.view.home.parts.BaseContainer
6
6
  */
7
- class AfterMath extends Container {
7
+ class AfterMath extends BaseContainer {
8
8
  static config = {
9
9
  /**
10
10
  * @member {String} className='Portal.view.home.parts.AfterMath'
11
11
  * @protected
12
12
  */
13
13
  className: 'Portal.view.home.parts.AfterMath',
14
-
15
- cls: ['page', 'after-math'],
16
-
14
+ /**
15
+ * @member {Object} layout={ntype:'vbox',align:'stretch',pack:'center'}
16
+ */
17
17
  layout: {ntype: 'vbox', align: 'stretch', pack: 'center'},
18
18
  /**
19
19
  * @member {Object[]} items
20
20
  */
21
21
  items: [{
22
- module: Container,
23
- flex : 1
22
+ ntype: 'container',
23
+ flex : 1
24
24
  }, {
25
25
  cls : 'neo-h1',
26
26
  flex: 'none',
27
- html: 'Additional Stuff'
27
+ html: 'Additional Stuff',
28
+ vdom: {tag: 'h1'}
28
29
  }, {
29
30
  cls : 'neo-h2',
30
31
  flex: 'none',
31
32
  html: 'More to come here',
32
- // height: 200
33
+ vdom: {tag: 'h2'}
33
34
  }, {
34
35
  cls : 'neo-content',
35
36
  flex: 'none',
36
37
  html: 'Neo uses several cores to run the application. See the spinner on the page?',
37
- // height: 200
38
+ vdom: {tag: 'p'}
38
39
  }, {
39
- module: Container,
40
- flex : 1
40
+ ntype: 'container',
41
+ flex : 1
41
42
  }, {
42
- module: Container,
43
+ ntype : 'container',
43
44
  cls : 'home-footer',
44
45
  height: '40%',
46
+ html : 'This is the footer',
47
+ vdom : {tag: 'footer'},
48
+
45
49
  style : { // todo: css
46
50
  background: 'black',
47
51
  color : 'white',
48
52
  height : '40%',
49
53
  padding : '15px'
50
- },
51
- html : 'This is the footer'
54
+ }
52
55
  }]
53
56
  }
54
57
  }
@@ -0,0 +1,31 @@
1
+ import Container from '../../../../../src/container/Base.mjs';
2
+
3
+ /**
4
+ * Abstract base class for all views inside the landing page
5
+ * @class Portal.view.home.parts.BaseContainer
6
+ * @extends Neo.container.Base
7
+ * @abstract
8
+ */
9
+ class BaseContainer extends Container {
10
+ static config = {
11
+ /**
12
+ * @member {String} className='Portal.view.home.parts.BaseContainer'
13
+ * @protected
14
+ */
15
+ className: 'Portal.view.home.parts.BaseContainer',
16
+ /**
17
+ * @member {String[]} cls=['portal-home-content-view','neo-container']
18
+ */
19
+ baseCls: ['portal-home-content-view', 'neo-container']
20
+ }
21
+
22
+ /**
23
+ * Hook which will trigger whenever the container fully gets scrolled into the visible area.
24
+ * Override it as needed.
25
+ */
26
+ activate() {}
27
+ }
28
+
29
+ Neo.setupClass(BaseContainer);
30
+
31
+ export default BaseContainer;
@@ -1,56 +1,72 @@
1
- import Container from '../../../../../src/container/Base.mjs';
2
- import LivePreview from '../../learn/LivePreview.mjs';
1
+ import BaseContainer from './BaseContainer.mjs';
2
+ import LivePreview from '../../learn/LivePreview.mjs';
3
3
 
4
4
  /**
5
5
  * @class Portal.view.home.parts.Colors
6
- * @extends Neo.container.Base
6
+ * @extends Portal.view.home.parts.BaseContainer
7
7
  */
8
- class Colors extends Container {
8
+ class Colors extends BaseContainer {
9
9
  static config = {
10
10
  /**
11
11
  * @member {String} className='Portal.view.home.parts.Colors'
12
12
  * @protected
13
13
  */
14
14
  className: 'Portal.view.home.parts.Colors',
15
-
16
- cls: ['page', 'cool-stuff'],
17
-
15
+ /**
16
+ * @member {Object} responsive
17
+ */
18
18
  responsive: {
19
19
  medium: {layout: {ntype: 'vbox', align: 'stretch', pack: 'center'}},
20
20
  large : {layout: {ntype: 'hbox', align: 'stretch', pack: 'center'}}
21
21
  },
22
-
23
22
  /**
24
23
  * @member {Object[]} items
25
24
  */
26
25
  items: [{
27
- module: Container,
26
+ ntype : 'container',
28
27
  flex : '1',
29
28
  style : {padding: '2rem'},
30
29
  layout: {ntype: 'vbox', align: 'center', pack: 'center'},
31
30
  items : [{
32
31
  cls : 'neo-h1',
33
32
  flex: 'none',
34
- html: 'Colors Dashboard'
33
+ html: 'Amazing Potential',
34
+ vdom: {tag: 'h1'}
35
35
  }, {
36
36
  cls : 'neo-h2',
37
37
  flex: 'none',
38
- html: 'Expand the widgets into multiple Windows'
38
+ html: 'Socket Data',
39
+ vdom: {tag: 'h2'}
39
40
  }, {
40
- cls : 'neo-content',
41
41
  flex: 'none',
42
- html: 'The State Management will continue to work.'
42
+ vdom: {tag: 'p'},
43
+ html: [
44
+ 'This is similar to the Helix demo — it\'s an extremely fast multi-window app. Click the start button ',
45
+ 'to see the view reflect changes in the data. And the app is multi-window: the table and charts can be ',
46
+ 'undocked into their own windows. In fact, the entire demo can be undocked.'
47
+ ].join('')
48
+ }, {
49
+ flex: 'none',
50
+ html: 'But the demo differs from the helix example because the data is provided via a <i>socket</i>.',
51
+ vdom: {tag: 'p'}
52
+ }, {
53
+ flex: 'none',
54
+ vdom: {tag: 'p'},
55
+ html: [
56
+ 'Neo.mjs uniquely fits the bill for applications that need real-time visualizations of real-time data, such as ',
57
+ 'stock market trading data and medical or scientific telemetry.'
58
+ ].join('')
43
59
  }]
44
60
  }, {
45
- module: Container,
61
+ ntype : 'container',
46
62
  flex : '2',
47
- style : {background: 'grey', padding: '20px'},
63
+ style : {background: 'lightgray', padding: '20px'},
48
64
  layout: {ntype: 'vbox', align: 'stretch', pack: 'center'},
49
65
  items : [{
50
- module : LivePreview,
51
- activeView: 'preview',
52
- cls : ['page-live-preview'],
53
- height : '100%',
66
+ module : LivePreview,
67
+ cls : ['page-live-preview'],
68
+ height : '100%',
69
+ reference: 'live-preview',
54
70
 
55
71
  value: [
56
72
  "import Viewport from '../../../../apps/colors/view/Viewport.mjs';",
@@ -67,6 +83,14 @@ class Colors extends Container {
67
83
  }]
68
84
  }]
69
85
  }
86
+
87
+ /**
88
+ *
89
+ */
90
+ async activate() {
91
+ await this.timeout(1000);
92
+ this.getReference('live-preview').activeView = 'preview'
93
+ }
70
94
  }
71
95
 
72
96
  Neo.setupClass(Colors);
@@ -1,11 +1,11 @@
1
- import Container from '../../../../../src/container/Base.mjs';
2
- import ContentBox from '../ContentBox.mjs';
1
+ import BaseContainer from './BaseContainer.mjs';
2
+ import ContentBox from '../ContentBox.mjs';
3
3
 
4
4
  /**
5
5
  * @class Portal.view.home.parts.Features
6
- * @extends Neo.container.Base
6
+ * @extends Portal.view.home.parts.BaseContainer
7
7
  */
8
- class Features extends Container {
8
+ class Features extends BaseContainer {
9
9
  static config = {
10
10
  /**
11
11
  * @member {String} className='Portal.view.home.parts.Features'
@@ -13,9 +13,9 @@ class Features extends Container {
13
13
  */
14
14
  className: 'Portal.view.home.parts.Features',
15
15
  /**
16
- * @member {String[]} cls=['portal-home-features','page']
16
+ * @member {String[]} cls=['portal-home-features']
17
17
  */
18
- cls: ['portal-home-features', 'page'],
18
+ cls: ['portal-home-features'],
19
19
  /**
20
20
  * @member {Object} layout={ntype:'hbox',align:'stretch',wrap:'wrap'}
21
21
  */
@@ -1,56 +1,84 @@
1
- import Container from '../../../../../src/container/Base.mjs';
2
- import LivePreview from '../../learn/LivePreview.mjs';
1
+ import BaseContainer from './BaseContainer.mjs';
2
+ import LivePreview from '../../learn/LivePreview.mjs';
3
3
 
4
4
  /**
5
5
  * @class Portal.view.home.parts.Helix
6
- * @extends Neo.container.Base
6
+ * @extends Portal.view.home.parts.BaseContainer
7
7
  */
8
- class Helix extends Container {
8
+ class Helix extends BaseContainer {
9
9
  static config = {
10
10
  /**
11
11
  * @member {String} className='Portal.view.home.parts.Helix'
12
12
  * @protected
13
13
  */
14
14
  className: 'Portal.view.home.parts.Helix',
15
-
16
- cls: ['page', 'cool-stuff'],
17
-
15
+ /**
16
+ * @member {Object} responsive
17
+ */
18
18
  responsive: {
19
19
  medium: {layout: {ntype: 'vbox', align: 'stretch', pack: 'center'}},
20
20
  large : {layout: {ntype: 'hbox', align: 'stretch', pack: 'center'}}
21
21
  },
22
-
23
22
  /**
24
23
  * @member {Object[]} items
25
24
  */
26
25
  items: [{
27
- module: Container,
26
+ ntype : 'container',
28
27
  flex : '1',
29
28
  style : {padding: '2rem'},
30
29
  layout: {ntype: 'vbox', align: 'center', pack: 'center'},
31
30
  items : [{
32
31
  cls : 'neo-h1',
33
32
  flex: 'none',
34
- html: 'Interactive Views'
33
+ html: 'Extreme Speed',
34
+ vdom: {tag: 'h1'}
35
35
  }, {
36
36
  cls : 'neo-h2',
37
37
  flex: 'none',
38
- html: 'Expand the widget into multiple Windows'
38
+ html: '40,000 Updates /s',
39
+ vdom: {tag: 'h2'}
39
40
  }, {
40
- cls : 'neo-content',
41
+ cls : 'neo-h3',
42
+ flex: 'none',
43
+ vdom: {tag: 'p'},
44
+
45
+ html: [
46
+ 'This demo shows the Neo.mjs helix component, along with a "Helix Controls" panel. ',
47
+ 'Move your cursor over the helix, then rapidly scroll left and right to rotate, and up and down to zoom. ',
48
+ 'As you do, look at the delta updates counter at the top. ',
49
+ 'Neo.mjs easily handles 40,000 updates per second, and beyond.'
50
+ ].join('')
51
+ }, {
52
+ cls : 'neo-h1',
41
53
  flex: 'none',
42
- html: 'The State Management will continue to work.'
54
+ html: 'Multi-Window',
55
+ vdom: {tag: 'h1'}
56
+ }, {
57
+ cls : 'neo-h2',
58
+ flex: 'none',
59
+ html: 'Seamless and Simple',
60
+ vdom: {tag: 'h2'}
61
+ }, {
62
+ cls : 'neo-h3',
63
+ flex: 'none',
64
+ vdom: {tag: 'p'},
65
+
66
+ html: [
67
+ 'Click on the small window icon in the Helix Controls title bar and the controls open in their own window ',
68
+ 'which can be moved to a separate monitor. But the application logic doesn\'t care &mdash; ',
69
+ 'the logic updates the controls just like before, and framework seamlessly handles updating the DOM across windows.'
70
+ ].join('')
43
71
  }]
44
72
  }, {
45
- module: Container,
73
+ ntype : 'container',
46
74
  flex : '2',
47
- style : {background: 'grey', padding: '20px'},
75
+ style : {background: 'lightgray', padding: '20px'},
48
76
  layout: {ntype: 'vbox', align: 'stretch', pack: 'center'},
49
77
  items : [{
50
- module : LivePreview,
51
- activeView: 'preview',
52
- cls : ['page-live-preview'],
53
- height : '100%',
78
+ module : LivePreview,
79
+ cls : ['page-live-preview'],
80
+ height : '100%',
81
+ reference: 'live-preview',
54
82
 
55
83
  value: [
56
84
  "import Viewport from '../../../../examples/component/multiWindowHelix/Viewport.mjs';",
@@ -68,6 +96,14 @@ class Helix extends Container {
68
96
  }]
69
97
  }]
70
98
  }
99
+
100
+ /**
101
+ *
102
+ */
103
+ async activate() {
104
+ await this.timeout(1000);
105
+ this.getReference('live-preview').activeView = 'preview'
106
+ }
71
107
  }
72
108
 
73
109
  Neo.setupClass(Helix);
@@ -1,11 +1,11 @@
1
- import Container from '../../../../../src/container/Base.mjs';
1
+ import BaseContainer from './BaseContainer.mjs';
2
2
  import LivePreviewContainer from '../preview/PageCodeContainer.mjs';
3
3
 
4
4
  /**
5
5
  * @class Portal.view.home.parts.HelloWorld
6
- * @extends Neo.container.Base
6
+ * @extends Portal.view.home.parts.BaseContainer
7
7
  */
8
- class HelloWorld extends Container {
8
+ class HelloWorld extends BaseContainer {
9
9
  static config = {
10
10
  /**
11
11
  * @member {String} className='Portal.view.home.parts.HelloWorld'
@@ -31,32 +31,33 @@ class HelloWorld extends Container {
31
31
  medium: {layout: {ntype: 'vbox', align: 'stretch', pack: 'center'}},
32
32
  large : {layout: {ntype: 'hbox', align: 'stretch', pack: 'center'}}
33
33
  },
34
-
35
34
  /**
36
35
  * @member {Object[]} items
37
36
  */
38
37
  items: [{
39
- module: Container,
38
+ ntype : 'container',
40
39
  flex : '1',
41
40
  style : {padding: '2rem'},
42
41
  layout: {ntype: 'vbox', align: 'center', pack: 'center'},
43
42
  items : [{
44
43
  cls : 'neo-h1',
45
- id : 'neo-hello-world-h1',
46
44
  flex: 'none',
47
- html: 'Hello World'
45
+ html: 'Hello World',
46
+ vdom: {tag: 'h1'}
48
47
  }, {
49
48
  cls : 'neo-h2',
50
49
  flex: 'none',
51
- html: 'Your first code snippet'
50
+ html: 'Your first code snippet',
51
+ vdom: {tag: 'h2'}
52
52
  }, {
53
53
  cls : 'neo-content',
54
54
  flex: 'none',
55
- html: 'If you understand these lines, you are ready to start with Neo.mjs'
55
+ html: 'If you understand these lines, you are ready to start with Neo.mjs',
56
+ vdom: {tag: 'p'}
56
57
  }]
57
58
  }, {
58
59
  module: LivePreviewContainer,
59
- flex: 0.8,
60
+ flex : 0.8,
60
61
  value : [
61
62
  "import Container from '../../../../src/container/Base.mjs';",
62
63
  "",
@@ -0,0 +1,66 @@
1
+ import BaseContainer from './BaseContainer.mjs';
2
+
3
+ /**
4
+ * @class Portal.view.home.parts.How
5
+ * @extends Portal.view.home.parts.BaseContainer
6
+ */
7
+ class How extends BaseContainer {
8
+ static config = {
9
+ /**
10
+ * @member {String} className='Portal.view.home.parts.How'
11
+ * @protected
12
+ */
13
+ className: 'Portal.view.home.parts.How',
14
+ /**
15
+ * @member {Object} responsive
16
+ */
17
+ responsive: {
18
+ medium: {layout: {ntype: 'vbox', align: 'stretch', pack: 'center'}},
19
+ large : {layout: {ntype: 'hbox', align: 'stretch', pack: 'center'}}
20
+ },
21
+ /**
22
+ * @member {Object[]} items
23
+ */
24
+ items: [{
25
+ ntype : 'container',
26
+ flex : '1',
27
+ style : {padding: '2rem'},
28
+ layout: {ntype: 'vbox', align: 'center', pack: 'center'},
29
+ items : [{
30
+ cls : 'neo-h1',
31
+ flex: 'none',
32
+ html: 'How?',
33
+ vdom: {tag: 'h1'}
34
+ }, {
35
+ cls : 'neo-h2',
36
+ flex: 'none',
37
+ html: 'How Does Neo.mjs Do It?',
38
+ vdom: {tag: 'h2'}
39
+ }, {
40
+ cls : 'neo-h3',
41
+ flex: 'none',
42
+ vdom: {tag: 'p'},
43
+ html: [
44
+ 'When a Neo.mjs app launches three webworkers are spawned: one that holds app logic, one for tracking delta DOM updates, ',
45
+ 'and one for backend calls. Each webworker runs in its own thread, and thus, in its own processor core. ',
46
+ 'This means these processes run in parallel: your app logic isn\'t affected by DOM changes or ',
47
+ 'by Ajax or socket calls. If you have processor-intensive tasks you can easily run them in their own threads.'
48
+ ].join('')
49
+ }]
50
+ }, {
51
+ ntype : 'container',
52
+ flex : '2',
53
+ style : {background: 'lightgray', padding: '20px'},
54
+ layout: {ntype: 'vbox', align: 'stretch', pack: 'center'},
55
+ items : [{
56
+ flex : 'none',
57
+ style: {width: '100%'},
58
+ vdom : {tag: 'img', src: 'https://s3.amazonaws.com/mjs.neo.learning.images/why/IndexHtmlFlow.png'}
59
+ }]
60
+ }]
61
+ }
62
+ }
63
+
64
+ Neo.setupClass(How);
65
+
66
+ export default How;