neo.mjs 6.35.0 → 6.36.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 (32) hide show
  1. package/README.md +15 -1
  2. package/apps/ServiceWorker.mjs +2 -2
  3. package/apps/colors/view/ViewportController.mjs +27 -17
  4. package/apps/portal/view/home/FeatureSection.mjs +209 -0
  5. package/apps/portal/view/home/parts/Colors.mjs +34 -84
  6. package/apps/portal/view/home/parts/Features.mjs +1 -1
  7. package/apps/portal/view/home/parts/Helix.mjs +36 -95
  8. package/apps/portal/view/home/parts/How.mjs +31 -48
  9. package/apps/portal/view/learn/ContentView.mjs +53 -20
  10. package/examples/ServiceWorker.mjs +2 -2
  11. package/package.json +2 -2
  12. package/resources/data/deck/learnneo/pages/benefits/Multi-Threading.md +221 -0
  13. package/resources/data/deck/learnneo/tree.json +12 -13
  14. package/resources/scss/src/apps/portal/Viewport.scss +19 -0
  15. package/resources/scss/src/apps/portal/home/ContentBox.scss +9 -2
  16. package/resources/scss/src/apps/portal/home/FeatureSection.scss +68 -0
  17. package/resources/scss/src/apps/portal/home/parts/Colors.scss +1 -5
  18. package/resources/scss/src/apps/portal/home/parts/Helix.scss +1 -7
  19. package/resources/scss/src/apps/portal/home/parts/How.scss +0 -22
  20. package/resources/scss/src/apps/portal/learn/ContentView.scss +8 -0
  21. package/resources/scss/src/code/LivePreview.scss +1 -0
  22. package/src/DefaultConfig.mjs +2 -2
  23. package/src/Neo.mjs +5 -1
  24. package/src/code/LivePreview.mjs +16 -19
  25. package/src/component/Toast.mjs +8 -8
  26. package/src/component/Video.mjs +22 -28
  27. package/src/component/wrapper/AmChart.mjs +15 -8
  28. package/src/main/addon/AmCharts.mjs +1 -1
  29. package/src/manager/DomEvent.mjs +1 -1
  30. package/src/worker/App.mjs +1 -1
  31. package/src/worker/mixin/RemoteMethodAccess.mjs +1 -3
  32. package/resources/data/deck/learnneo/pages/WhyNeo-Multi-Threaded.md +0 -15
package/README.md CHANGED
@@ -13,6 +13,13 @@
13
13
 
14
14
  # Harness the Power of Multi-Threading for Ultra-Fast Frontends
15
15
 
16
+ ## Content
17
+ 1. <a href="#introduction">Introduction</a>
18
+ 2. <a href="#slack-channel">Slack Channel for questions & feedback</a>
19
+ 3. <a href="#architectures">Scalable frontend architectures</a>
20
+
21
+ </br></br>
22
+ <h2 id="introduction">1. Introduction</h2>
16
23
  Neo.mjs is **not** intended for rather simple & static websites.
17
24
 
18
25
  The Framework does not focus primarily on a fast first rendering experience for new users,
@@ -22,7 +29,7 @@ Neo.mjs drives the OMT (off the main thread) paradigm into perfection,
22
29
  which is intended to move expensive tasks into Workers.
23
30
 
24
31
  > So, what are the most expensive tasks we are dealing with?
25
-
32
+
26
33
  The answer is simple: a Framework and the Apps which we build with it.
27
34
 
28
35
  Neo.mjs moves most parts of the framework and your App(s) including their Components
@@ -44,6 +51,13 @@ Potential Use-Cases:
44
51
  3. Web-based IDEs
45
52
  4. Multi-Window Data Visualisation
46
53
 
54
+ </br></br>
55
+ <h2 id="slack-channel">2. Slack Channel for questions, ideas & feedback</h2>
56
+ Join our community:</br>
57
+ <a href="https://join.slack.com/t/neomjs/shared_invite/zt-6c50ueeu-3E1~M4T9xkNnb~M_prEEOA"><img src="https://img.shields.io/badge/Slack-neo.mjs-brightgreen.svg?logo=slack&style=for-the-badge" alt="Join the Slack channel"></a>
58
+
59
+
60
+
47
61
  </br></br>
48
62
 
49
63
  [Spoiler] We are in the middle of wrapping up the new Framework Website,
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='6.35.0'
23
+ * @member {String} version='6.36.0'
24
24
  */
25
- version: '6.35.0'
25
+ version: '6.36.0'
26
26
  }
27
27
 
28
28
  /**
@@ -61,6 +61,14 @@ class ViewportController extends Controller {
61
61
  }
62
62
  }
63
63
 
64
+ /**
65
+ * @param args
66
+ */
67
+ destroy(...args) {
68
+ this.intervalId && clearInterval(this.intervalId);
69
+ super.destroy(...args)
70
+ }
71
+
64
72
  /**
65
73
  * @param {Object} data
66
74
  * @param {String} data.appName
@@ -184,20 +192,6 @@ class ViewportController extends Controller {
184
192
  await this.createBrowserWindow('table')
185
193
  }
186
194
 
187
- /**
188
- * @param {Object} data
189
- */
190
- onStopButtonClick(data) {
191
- let me = this;
192
-
193
- me.getModel().setData({isUpdating: false});
194
-
195
- if (me.intervalId) {
196
- clearInterval(me.intervalId);
197
- me.intervalId = null
198
- }
199
- }
200
-
201
195
  /**
202
196
  * @param {Object} data
203
197
  */
@@ -214,6 +208,20 @@ class ViewportController extends Controller {
214
208
  }
215
209
  }
216
210
 
211
+ /**
212
+ * @param {Object} data
213
+ */
214
+ onStopButtonClick(data) {
215
+ let me = this;
216
+
217
+ me.getModel().setData({isUpdating: false});
218
+
219
+ if (me.intervalId) {
220
+ clearInterval(me.intervalId);
221
+ me.intervalId = null
222
+ }
223
+ }
224
+
217
225
  /**
218
226
  * @param {Object} data
219
227
  */
@@ -268,10 +276,12 @@ class ViewportController extends Controller {
268
276
  amountColumns: model.getData('amountColumns'),
269
277
  amountRows : model.getData('amountRows')
270
278
  }).then(response => {
271
- let {data} = response;
279
+ if (!me.isDestroyed) {
280
+ let {data} = response;
272
281
 
273
- me.updateTable(data.tableData);
274
- me.updateCharts(data.summaryData)
282
+ me.updateTable(data.tableData);
283
+ me.updateCharts(data.summaryData)
284
+ }
275
285
  })
276
286
  }
277
287
  }
@@ -0,0 +1,209 @@
1
+ import Button from '../../../../src/button/Base.mjs';
2
+ import Container from '../../../../src/container/Base.mjs';
3
+ import LivePreview from '../../../../src/code/LivePreview.mjs';
4
+
5
+ /**
6
+ * @class Portal.view.home.FeatureSection
7
+ * @extends Neo.container.Base
8
+ */
9
+ class FeatureSection extends Container {
10
+ /**
11
+ * Valid values for textContainerPosition
12
+ * @member {String[]} textContainerPositions=['start','end']
13
+ * @protected
14
+ * @static
15
+ */
16
+ static textContainerPositions = ['start', 'end']
17
+
18
+ static config = {
19
+ /**
20
+ * @member {String} className='Portal.view.home.FeatureSection'
21
+ * @protected
22
+ */
23
+ className: 'Portal.view.home.FeatureSection',
24
+ /**
25
+ * @member {String[]} baseCls=['portal-home-feature-section','neo-container']
26
+ * @protected
27
+ */
28
+ baseCls: ['portal-home-feature-section', 'neo-container'],
29
+ /**
30
+ * If you want to use the LivePreview, use the config livePreviewCode.
31
+ * For custom content, use this config instead.
32
+ * @member {Object[]|null} contentItems_=null
33
+ */
34
+ contentItems_: null,
35
+ /**
36
+ * @member {String|null} headline_=null
37
+ */
38
+ headline_: null,
39
+ /**
40
+ * @member {String|null} learnMoreRoute_=null
41
+ */
42
+ learnMoreRoute_: null,
43
+ /**
44
+ * @member {String|null} livePreviewCode_=null
45
+ */
46
+ livePreviewCode_: null,
47
+ /**
48
+ * @member {String|null} paragraph_=null
49
+ */
50
+ paragraph_: null,
51
+ /**
52
+ * @member {String|null} subHeadline_=null
53
+ */
54
+ subHeadline_: null,
55
+ /**
56
+ * Valid values: 'start' or 'end'
57
+ * @member {String} textContainerPosition_='start'
58
+ */
59
+ textContainerPosition_: 'start',
60
+ /**
61
+ * @member {String} layout='base'
62
+ */
63
+ layout: 'base',
64
+ /**
65
+ * @member {Object[]} items
66
+ */
67
+ items: [{
68
+ module: Container,
69
+ cls : ['portal-content-text'],
70
+ layout: 'base',
71
+ items : [{
72
+ cls : 'neo-h1',
73
+ flex : 'none',
74
+ reference: 'headline',
75
+ tag : 'h1'
76
+ }, {
77
+ cls : 'neo-h2',
78
+ flex : 'none',
79
+ reference: 'sub-headline',
80
+ tag : 'h2'
81
+ }, {
82
+ flex : 'none',
83
+ reference: 'paragraph',
84
+ tag : 'p'
85
+ }, {
86
+ module : Button,
87
+ reference: 'learn-more-button',
88
+ text : 'Learn more',
89
+ ui : 'secondary'
90
+ }]
91
+ }, {
92
+ module : Container,
93
+ cls : 'portal-content-wrapper',
94
+ layout : 'fit',
95
+ reference: 'portal-content-wrapper'
96
+ }]
97
+ }
98
+
99
+ /**
100
+ *
101
+ */
102
+ async activate() {
103
+ let me = this,
104
+ {parent} = me;
105
+
106
+ if (me.livePreviewCode) {
107
+ await me.timeout(1000);
108
+
109
+ if (parent.activePartsId === me.id && parent.mounted) {
110
+ me.getReference('live-preview').activeView = 'preview'
111
+ }
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Triggered after the contentItems config got changed
117
+ * @param {Object[]|null} value
118
+ * @param {Object[]|null} oldValue
119
+ * @protected
120
+ */
121
+ afterSetContentItems(value, oldValue) {
122
+ value ??= [{
123
+ module : LivePreview,
124
+ cls : ['page-live-preview'],
125
+ reference: 'live-preview',
126
+ value : this.livePreviewCode
127
+ }]
128
+
129
+ this.getItem('portal-content-wrapper').items = value
130
+ }
131
+
132
+ /**
133
+ * Triggered after the learnMoreRoute config got changed
134
+ * @param {String} value
135
+ * @param {String} oldValue
136
+ * @protected
137
+ */
138
+ afterSetLearnMoreRoute(value, oldValue) {
139
+ this.getItem('learn-more-button').route = value
140
+ }
141
+
142
+ /**
143
+ * Triggered after the headline config got changed
144
+ * @param {String} value
145
+ * @param {String} oldValue
146
+ * @protected
147
+ */
148
+ afterSetHeadline(value, oldValue) {
149
+ this.getItem('headline').html = value
150
+ }
151
+
152
+ /**
153
+ * Triggered after the livePreviewCode config got changed
154
+ * @param {String} value
155
+ * @param {String} oldValue
156
+ * @protected
157
+ */
158
+ afterSetLivePreviewCode(value, oldValue) {
159
+ // the initial value will get handled via afterSetContentItems()
160
+ if (oldValue) {
161
+ this.getItem('live-preview').value = value
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Triggered after the paragraph config got changed
167
+ * @param {String} value
168
+ * @param {String} oldValue
169
+ * @protected
170
+ */
171
+ afterSetParagraph(value, oldValue) {
172
+ this.getItem('paragraph').html = value
173
+ }
174
+
175
+ /**
176
+ * Triggered after the subHeadline config got changed
177
+ * @param {String} value
178
+ * @param {String} oldValue
179
+ * @protected
180
+ */
181
+ afterSetSubHeadline(value, oldValue) {
182
+ this.getItem('sub-headline').html = value
183
+ }
184
+
185
+ /**
186
+ * Triggered after the textContainerPosition config got changed
187
+ * @param {String} value
188
+ * @param {String} oldValue
189
+ * @protected
190
+ */
191
+ afterSetTextContainerPosition(value, oldValue) {
192
+ this.toggleCls('portal-position-end', value === 'end')
193
+ }
194
+
195
+ /**
196
+ * Triggered before the textContainerPosition config gets changed
197
+ * @param {String} value
198
+ * @param {String} oldValue
199
+ * @returns {String}
200
+ * @protected
201
+ */
202
+ beforeSetTextContainerPosition(value, oldValue) {
203
+ return this.beforeSetEnumValue(value, oldValue, 'textContainerPosition')
204
+ }
205
+ }
206
+
207
+ Neo.setupClass(FeatureSection);
208
+
209
+ export default FeatureSection;
@@ -1,11 +1,10 @@
1
- import BaseContainer from './BaseContainer.mjs';
2
- import LivePreview from '../../../../../src/code/LivePreview.mjs';
1
+ import FeatureSection from '../FeatureSection.mjs';
3
2
 
4
3
  /**
5
4
  * @class Portal.view.home.parts.Colors
6
- * @extends Portal.view.home.parts.BaseContainer
5
+ * @extends Portal.view.home.FeatureSection
7
6
  */
8
- class Colors extends BaseContainer {
7
+ class Colors extends FeatureSection {
9
8
  static config = {
10
9
  /**
11
10
  * @member {String} className='Portal.view.home.parts.Colors'
@@ -17,89 +16,40 @@ class Colors extends BaseContainer {
17
16
  */
18
17
  cls: ['portal-home-parts-colors'],
19
18
  /**
20
- * @member {Object} layout={ntype:'hbox',align:'stretch',pack:'center'}
19
+ * @member {String} headline='Amazing Potential'
21
20
  */
22
- layout: {ntype: 'hbox', align: 'stretch', pack: 'center'},
21
+ headline: 'Amazing Potential',
23
22
  /**
24
- * @member {Object[]} items
23
+ * @member {String} learnMoreRoute='#/learn/WhyNeo-Speed'
25
24
  */
26
- items: [{
27
- ntype : 'container',
28
- cls : ['portal-content-text'],
29
- flex : '1',
30
- style : {padding: '2rem'},
31
- layout: {ntype: 'vbox', align: 'center', pack: 'center'},
32
- items : [{
33
- cls : ['neo-h1'],
34
- flex: 'none',
35
- html: 'Amazing Potential',
36
- tag : 'h1'
37
- }, {
38
- cls : ['neo-h2'],
39
- flex: 'none',
40
- html: 'Socket Data',
41
- tag : 'h2'
42
- }, {
43
- flex: 'none',
44
- tag : 'p',
45
-
46
- html: [
47
- 'This is similar to the Helix demo &mdash; it\'s an extremely fast multi-window app. Click the start button ',
48
- 'to see the view reflect changes in the data. And the app is multi-window: the table and charts can be ',
49
- 'undocked into their own windows. In fact, the entire demo can be undocked.'
50
- ].join('')
51
- }, {
52
- flex: 'none',
53
- html: 'But the demo differs from the helix example because the data is provided via a <i>socket</i>.',
54
- tag : 'p'
55
- }, {
56
- flex: 'none',
57
- tag : 'p',
58
-
59
- html: [
60
- 'Neo.mjs uniquely fits the bill for applications that need real-time visualizations of real-time data, such as ',
61
- 'stock market trading data and medical or scientific telemetry.'
62
- ].join('')
63
- }]
64
- }, {
65
- ntype : 'container',
66
- cls : 'portal-content-wrapper',
67
- flex : '2',
68
- layout: 'fit',
69
- items : [{
70
- module : LivePreview,
71
- cls : ['page-live-preview'],
72
- height : '100%',
73
- reference: 'live-preview',
74
-
75
- value: [
76
- "import Viewport from '../../apps/colors/view/Viewport.mjs';",
77
- "",
78
- "class MainView extends Viewport {",
79
- " static config = {",
80
- " className: 'Portal.view.Colors',",
81
- " theme : 'neo-theme-dark'",
82
- " }",
83
- "}",
84
- "",
85
- "Neo.setupClass(MainView);"
86
- ].join('\n')
87
- }]
88
- }]
89
- }
90
-
91
- /**
92
- *
93
- */
94
- async activate() {
95
- let me = this,
96
- {parent} = me;
97
-
98
- await me.timeout(1000);
99
-
100
- if (parent.activePartsId === me.id && parent.mounted) {
101
- me.getReference('live-preview').activeView = 'preview'
102
- }
25
+ learnMoreRoute: '#/learn/WhyNeo-Speed',
26
+ /**
27
+ * @member {String} livePreviewCode
28
+ */
29
+ livePreviewCode: [
30
+ "import Viewport from '../../apps/colors/view/Viewport.mjs';",
31
+ "",
32
+ "class MainView extends Viewport {",
33
+ " static config = {",
34
+ " className: 'Portal.view.Colors',",
35
+ " theme : 'neo-theme-dark'",
36
+ " }",
37
+ "}",
38
+ "",
39
+ "Neo.setupClass(MainView);"
40
+ ].join('\n'),
41
+ /**
42
+ * @member {String} paragraph
43
+ */
44
+ paragraph: [
45
+ 'This is similar to the Helix demo &mdash; it\'s an extremely fast multi-window app. Click the start button ',
46
+ 'to see the view reflect changes in the data. And the app is multi-window: the table and charts can be ',
47
+ 'undocked into their own windows. In fact, the entire demo can be undocked.'
48
+ ].join(''),
49
+ /**
50
+ * @member {String} subHeadline='Socket Data'
51
+ */
52
+ subHeadline: 'Socket Data'
103
53
  }
104
54
  }
105
55
 
@@ -51,7 +51,7 @@ class Features extends BaseContainer {
51
51
  'Moving Components across Windows while keeping the same JS instances'
52
52
  ]
53
53
  }, {
54
- header: 'Modern JavaScript directly in your Browser',
54
+ header: 'Modern JS in your Browser',
55
55
  route : '#/learn/WhyNeo-Quick',
56
56
 
57
57
  content: [
@@ -1,11 +1,10 @@
1
- import BaseContainer from './BaseContainer.mjs';
2
- import LivePreview from '../../../../../src/code/LivePreview.mjs';
1
+ import FeatureSection from '../FeatureSection.mjs';
3
2
 
4
3
  /**
5
4
  * @class Portal.view.home.parts.Helix
6
- * @extends Portal.view.home.parts.BaseContainer
5
+ * @extends Portal.view.home.FeatureSection
7
6
  */
8
- class Helix extends BaseContainer {
7
+ class Helix extends FeatureSection {
9
8
  static config = {
10
9
  /**
11
10
  * @member {String} className='Portal.view.home.parts.Helix'
@@ -17,100 +16,42 @@ class Helix extends BaseContainer {
17
16
  */
18
17
  cls: ['portal-home-parts-helix'],
19
18
  /**
20
- * @member {Object} layout={ntype:'hbox',align:'stretch',pack:'center'}
19
+ * @member {String} headline='Extreme Speed'
21
20
  */
22
- layout: {ntype: 'hbox', align: 'stretch', pack: 'center'},
21
+ headline: 'Extreme Speed',
23
22
  /**
24
- * @member {Object[]} items
23
+ * @member {String} learnMoreRoute='#/learn/WhyNeo-Speed'
25
24
  */
26
- items: [{
27
- ntype : 'container',
28
- cls : ['portal-content-text'],
29
- flex : '1',
30
- style : {padding: '2rem'},
31
- layout: {ntype: 'vbox', align: 'center', pack: 'center'},
32
- items : [{
33
- cls : 'neo-h1',
34
- flex: 'none',
35
- html: 'Extreme Speed',
36
- tag : 'h1'
37
- }, {
38
- cls : 'neo-h2',
39
- flex: 'none',
40
- html: '40,000 Updates /s',
41
- tag : 'h2'
42
- }, {
43
- cls : 'neo-h3',
44
- flex: 'none',
45
- tag : 'p',
46
-
47
- html: [
48
- 'This demo shows the Neo.mjs helix component, along with a "Helix Controls" panel. ',
49
- 'Move your cursor over the helix, then rapidly scroll left and right to rotate, and up and down to zoom. ',
50
- 'As you do, look at the delta updates counter at the top. ',
51
- 'Neo.mjs easily handles 40,000 updates per second, and beyond.'
52
- ].join('')
53
- }, {
54
- cls : 'neo-h1',
55
- flex: 'none',
56
- html: 'Multi-Window',
57
- tag : 'h1'
58
- }, {
59
- cls : 'neo-h2',
60
- flex: 'none',
61
- html: 'Seamless and Simple',
62
- tag : 'h2'
63
- }, {
64
- cls : 'neo-h3',
65
- flex: 'none',
66
- tag : 'p',
67
-
68
- html: [
69
- 'Click on the small window icon in the Helix Controls title bar and the controls open in their own window ',
70
- 'which can be moved to a separate monitor. But the application logic doesn\'t care &mdash; ',
71
- 'the logic updates the controls just like before, and framework seamlessly handles updating the DOM across windows.'
72
- ].join('')
73
- }]
74
- }, {
75
- ntype : 'container',
76
- cls : 'portal-content-wrapper',
77
- flex : '2',
78
- layout: 'fit',
79
- items : [{
80
- module : LivePreview,
81
- cls : ['page-live-preview'],
82
- height : '100%',
83
- reference: 'live-preview',
84
-
85
- value: [
86
- "import Viewport from '../../examples/component/multiWindowHelix/Viewport.mjs';",
87
- "",
88
- "class MainView extends Viewport {",
89
- " static config = {",
90
- " className : 'Portal.view.MultiWindowHelix',",
91
- " showGitHubStarButton: false,",
92
- " theme : 'neo-theme-dark'",
93
- " }",
94
- "}",
95
- "",
96
- "Neo.setupClass(MainView);"
97
- ].join('\n')
98
- }]
99
- }]
100
- }
101
-
102
- /**
103
- *
104
- */
105
- async activate() {
106
- let me = this,
107
- {parent} = me;
108
-
109
- await me.timeout(1000);
110
-
111
- if (parent.activePartsId === me.id && parent.mounted) {
112
- me.getReference('live-preview').activeView = 'preview'
113
- }
25
+ learnMoreRoute: '#/learn/WhyNeo-Speed',
26
+ /**
27
+ * @member {String} livePreviewCode
28
+ */
29
+ livePreviewCode: [
30
+ "import Viewport from '../../examples/component/multiWindowHelix/Viewport.mjs';",
31
+ "",
32
+ "class MainView extends Viewport {",
33
+ " static config = {",
34
+ " className : 'Portal.view.MultiWindowHelix',",
35
+ " showGitHubStarButton: false,",
36
+ " theme : 'neo-theme-dark'",
37
+ " }",
38
+ "}",
39
+ "",
40
+ "Neo.setupClass(MainView);"
41
+ ].join('\n'),
42
+ /**
43
+ * @member {String} paragraph
44
+ */
45
+ paragraph: [
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
+ * @member {String} subHeadline='40,000 Updates /s'
53
+ */
54
+ subHeadline: '40,000 Updates /s'
114
55
  }
115
56
  }
116
57