neo.mjs 6.9.6 → 6.9.8

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 (103) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/learnneo/neo-config.json +6 -5
  3. package/apps/learnneo/store/Content.mjs +52 -2
  4. package/apps/learnneo/view/home/ContentTreeList.mjs +32 -4
  5. package/apps/learnneo/view/home/MainContainer.mjs +17 -29
  6. package/apps/learnneo/view/home/MainContainerController.mjs +28 -19
  7. package/apps/learnneo/view/home/MainContainerModel.mjs +35 -0
  8. package/docs/app/view/MainContainerController.mjs +12 -0
  9. package/examples/ServiceWorker.mjs +2 -2
  10. package/examples/button/base/neo-config.json +2 -1
  11. package/examples/form/field/textarea/MainContainer.mjs +7 -1
  12. package/package.json +1 -1
  13. package/resources/data/learnneo/p/2023-10-01T18-29-19-158Z.md +102 -0
  14. package/resources/data/learnneo/p/2023-10-07T19-18-28-517Z.md +110 -0
  15. package/resources/data/learnneo/p/2023-10-08T20-20-07-934Z.md +75 -0
  16. package/resources/data/learnneo/p/2023-10-08T20-20-37-336Z.md +29 -0
  17. package/resources/data/learnneo/p/2023-10-08T20-37-30-658Z.md +0 -0
  18. package/resources/data/learnneo/p/2023-10-08T21-58-25-809Z.md +68 -0
  19. package/resources/data/learnneo/p/2023-10-08T22-22-11-013Z.md +0 -0
  20. package/resources/data/learnneo/p/2023-10-14T19-25-08-153Z.md +124 -0
  21. package/resources/data/learnneo/pages/whyneo.md +4 -0
  22. package/resources/data/learnneo/t.json +130 -0
  23. package/resources/data/learnneo/tree.json +27 -0
  24. package/resources/deck/whyneo.md +80 -0
  25. package/resources/images/Neo_Vector.svg +3 -0
  26. package/resources/scss/src/apps/learnneo/Viewport.scss +63 -0
  27. package/resources/scss/src/apps/newwebsite/MainContainer.css +33 -0
  28. package/resources/scss/theme-neo-light/Global.scss +7 -0
  29. package/resources/scss/theme-neo-light/apps/covid/HeaderContainer.scss +10 -0
  30. package/resources/scss/theme-neo-light/apps/covid/country/Gallery.scss +7 -0
  31. package/resources/scss/theme-neo-light/apps/covid/country/Helix.scss +8 -0
  32. package/resources/scss/theme-neo-light/apps/covid/country/LineChartComponent.scss +3 -0
  33. package/resources/scss/theme-neo-light/apps/docs/ContentTabContainer.scss +4 -0
  34. package/resources/scss/theme-neo-light/apps/docs/HeaderContainer.scss +10 -0
  35. package/resources/scss/theme-neo-light/apps/docs/MainContainer.scss +3 -0
  36. package/resources/scss/theme-neo-light/apps/docs/classdetails/HeaderComponent.scss +4 -0
  37. package/resources/scss/theme-neo-light/apps/docs/classdetails/MembersList.scss +17 -0
  38. package/resources/scss/theme-neo-light/apps/docs/classdetails/TutorialComponent.scss +4 -0
  39. package/resources/scss/theme-neo-light/apps/website/HeaderContainer.scss +5 -0
  40. package/resources/scss/theme-neo-light/apps/website/MainContainer.scss +4 -0
  41. package/resources/scss/theme-neo-light/apps/website/blog/Container.scss +3 -0
  42. package/resources/scss/theme-neo-light/apps/website/home/TabContainer.scss +4 -0
  43. package/resources/scss/theme-neo-light/button/Base.scss +117 -0
  44. package/resources/scss/theme-neo-light/calendar/view/EditEventContainer.scss +5 -0
  45. package/resources/scss/theme-neo-light/calendar/view/MainContainer.scss +23 -0
  46. package/resources/scss/theme-neo-light/calendar/view/SettingsContainer.scss +3 -0
  47. package/resources/scss/theme-neo-light/calendar/view/YearComponent.scss +10 -0
  48. package/resources/scss/theme-neo-light/calendar/view/calendars/EditContainer.scss +5 -0
  49. package/resources/scss/theme-neo-light/calendar/view/calendars/List.scss +3 -0
  50. package/resources/scss/theme-neo-light/calendar/view/month/Component.scss +10 -0
  51. package/resources/scss/theme-neo-light/calendar/view/week/Component.scss +13 -0
  52. package/resources/scss/theme-neo-light/component/Base.scss +6 -0
  53. package/resources/scss/theme-neo-light/component/BoxLabel.scss +5 -0
  54. package/resources/scss/theme-neo-light/component/Chip.scss +14 -0
  55. package/resources/scss/theme-neo-light/component/DateSelector.scss +24 -0
  56. package/resources/scss/theme-neo-light/component/Process.scss +9 -0
  57. package/resources/scss/theme-neo-light/component/Progress.scss +3 -0
  58. package/resources/scss/theme-neo-light/component/Splitter.scss +5 -0
  59. package/resources/scss/theme-neo-light/component/StatusBadge.scss +19 -0
  60. package/resources/scss/theme-neo-light/component/Timer.scss +6 -0
  61. package/resources/scss/theme-neo-light/component/Toast.scss +9 -0
  62. package/resources/scss/theme-neo-light/component/Video.scss +4 -0
  63. package/resources/scss/theme-neo-light/container/Accordion.scss +5 -0
  64. package/resources/scss/theme-neo-light/container/AccordionItem.scss +10 -0
  65. package/resources/scss/theme-neo-light/container/Base.scss +4 -0
  66. package/resources/scss/theme-neo-light/container/Panel.scss +5 -0
  67. package/resources/scss/theme-neo-light/container/Viewport.scss +3 -0
  68. package/resources/scss/theme-neo-light/design-tokens/Components.scss +3 -0
  69. package/resources/scss/theme-neo-light/dialog/Base.scss +5 -0
  70. package/resources/scss/theme-neo-light/examples/ConfigurationPanel.scss +3 -0
  71. package/resources/scss/theme-neo-light/examples/calendar/basic/MainContainer.scss +4 -0
  72. package/resources/scss/theme-neo-light/form/Fieldset.scss +6 -0
  73. package/resources/scss/theme-neo-light/form/field/CheckBox.scss +8 -0
  74. package/resources/scss/theme-neo-light/form/field/FileUpload.scss +12 -0
  75. package/resources/scss/theme-neo-light/form/field/Picker.scss +5 -0
  76. package/resources/scss/theme-neo-light/form/field/Range.scss +4 -0
  77. package/resources/scss/theme-neo-light/form/field/Search.scss +3 -0
  78. package/resources/scss/theme-neo-light/form/field/Select.scss +9 -0
  79. package/resources/scss/theme-neo-light/form/field/Switch.scss +17 -0
  80. package/resources/scss/theme-neo-light/form/field/Text.scss +32 -0
  81. package/resources/scss/theme-neo-light/form/field/trigger/Base.scss +6 -0
  82. package/resources/scss/theme-neo-light/form/field/trigger/Time.scss +4 -0
  83. package/resources/scss/theme-neo-light/grid/Container.scss +7 -0
  84. package/resources/scss/theme-neo-light/grid/View.scss +13 -0
  85. package/resources/scss/theme-neo-light/grid/header/Button.scss +6 -0
  86. package/resources/scss/theme-neo-light/list/Base.scss +12 -0
  87. package/resources/scss/theme-neo-light/menu/List.scss +21 -0
  88. package/resources/scss/theme-neo-light/menu/Panel.scss +3 -0
  89. package/resources/scss/theme-neo-light/tab/Container.scss +3 -0
  90. package/resources/scss/theme-neo-light/tab/Strip.scss +5 -0
  91. package/resources/scss/theme-neo-light/tab/header/Button.scss +30 -0
  92. package/resources/scss/theme-neo-light/table/Container.scss +10 -0
  93. package/resources/scss/theme-neo-light/table/View.scss +13 -0
  94. package/resources/scss/theme-neo-light/table/header/Button.scss +7 -0
  95. package/resources/scss/theme-neo-light/toolbar/Base.scss +4 -0
  96. package/resources/scss/theme-neo-light/tree/List.scss +4 -0
  97. package/src/DefaultConfig.mjs +2 -2
  98. package/src/form/field/FileUpload.mjs +10 -8
  99. package/src/form/field/Text.mjs +2 -2
  100. package/src/form/field/TextArea.mjs +52 -0
  101. package/src/main/DomAccess.mjs +23 -0
  102. package/src/main/addon/HighlightJS.mjs +35 -10
  103. package/src/vdom/Helper.mjs +2 -1
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='6.9.6'
23
+ * @member {String} version='6.9.8'
24
24
  */
25
- version: '6.9.6'
25
+ version: '6.9.8'
26
26
  }
27
27
 
28
28
  /**
@@ -1,6 +1,7 @@
1
1
  {
2
- "appPath": "apps/learnneo/app.mjs",
3
- "basePath": "../../",
4
- "environment": "development",
5
- "mainPath": "./Main.mjs"
6
- }
2
+ "appPath" : "apps/learnneo/app.mjs",
3
+ "basePath" : "../../",
4
+ "environment" : "development",
5
+ "mainPath" : "./Main.mjs",
6
+ "mainThreadAddons": ["DragDrop", "HighlightJS", "Stylesheet", "Markdown"]
7
+ }
@@ -1,5 +1,5 @@
1
1
  import ContentModel from '../model/Content.mjs';
2
- import Store from '../../../src/data/Store.mjs';
2
+ import Store from '../../../src/data/Store.mjs';
3
3
 
4
4
  /**
5
5
  * @class LearnNeo.store.Content
@@ -15,7 +15,57 @@ class Content extends Store {
15
15
  /**
16
16
  * @member {Neo.data.Model} model=ContentModel
17
17
  */
18
- model: ContentModel
18
+ model: ContentModel,
19
+ // autoLoad: true
20
+
21
+
22
+ }
23
+
24
+ xonConstructed() {
25
+ super.onConstructed();
26
+
27
+ let me = this;
28
+
29
+ // Neo.Main.getByPath({path: 'location.search'})
30
+ // .then(data => {
31
+ // const searchString = data?.substr(1) || '';
32
+ // const search = searchString ? JSON.parse(`{"${decodeURI(searchString.replace(/&/g, "\",\"").replace(/=/g, "\":\""))}"}`) : {};
33
+ // this.deck = search.deck || 'learnneo';
34
+ // this.url = `${this.contentPath}/tree.json`;
35
+ // this.load();
36
+ // // this.doLoadStore();
37
+ // console.log(search);
38
+ // });
39
+
40
+ }
41
+ xload() {
42
+ this.model = ContentModel;
43
+ Neo.Main.getByPath({path: 'location.search'})
44
+ .then(data => {
45
+ const searchString = data?.substr(1) || '';
46
+ const search = searchString ? JSON.parse(`{"${decodeURI(searchString.replace(/&/g, "\",\"").replace(/=/g, "\":\""))}"}`) : {};
47
+ this.deck = search.deck || 'learnneo';
48
+ this.url = `${this.contentPath}/tree.json`;
49
+ // this.load();
50
+ super.load();
51
+ console.log(search);
52
+ });
53
+ }
54
+
55
+ get contentPath() {
56
+ return `../../../resources/data/${this.deck}`;
57
+ }
58
+ doLoadStore() {
59
+ debugger;
60
+ const me = this;
61
+ Neo.Xhr.promiseJson({
62
+ url: `${this.contentPath}/tree.json`
63
+ }).then(data => {
64
+ // TODO: Tree lists should do this themselves when their store is loaded.
65
+ me.data = data.json.data;
66
+ // me.createItems(null, me.getListItemsRoot(), 0);
67
+ // me.update();
68
+ })
19
69
  }
20
70
  }
21
71
 
@@ -1,5 +1,5 @@
1
1
  import ContentStore from '../../store/Content.mjs'
2
- import TreeList from '../../../../src/tree/List.mjs';
2
+ import TreeList from '../../../../src/tree/List.mjs';
3
3
 
4
4
  /**
5
5
  * @class LearnNeo.view.home.ContentTreeList
@@ -23,17 +23,45 @@ class ContentTreeList extends TreeList {
23
23
  */
24
24
  onConstructed() {
25
25
  super.onConstructed();
26
-
27
26
  let me = this;
28
-
27
+ Neo.Main.getByPath({path: 'location.search'})
28
+ .then(data => {
29
+ const searchString = data?.substr(1) || '';
30
+ const search = searchString ? JSON.parse(`{"${decodeURI(searchString.replace(/&/g, "\",\"").replace(/=/g, "\":\""))}"}`) : {};
31
+ me.deck = search.deck || 'learnneo';
32
+ me.doLoadStore();
33
+ console.log(search);
34
+ });
35
+ }
36
+ get contentPath() {
37
+ return `../../../resources/data/${this.deck}`;
38
+ }
39
+ doLoadStore() {
40
+ const me = this;
29
41
  Neo.Xhr.promiseJson({
30
- url: '../../../resources/data/learnneo/content.json'
42
+ url: `${this.contentPath}/t.json`
31
43
  }).then(data => {
44
+ // TODO: Tree lists should do this themselves when their store is loaded.
32
45
  me.store.data = data.json.data;
33
46
  me.createItems(null, me.getListItemsRoot(), 0);
34
47
  me.update();
35
48
  })
36
49
  }
50
+
51
+ async doFetchContent(record) {
52
+ let me = this,
53
+ path = `${me.contentPath}`;
54
+ path += record.path ? `/pages/${record.path}` : `/p/${record.id}.md`;
55
+
56
+ if (record.isLeaf && path) {
57
+ const data = await fetch(path);
58
+ const content = await data.text();
59
+ await Neo.main.addon.Markdown.markdownToHtml(content)
60
+ .then(
61
+ html => me.fire('contentChange', {component: me, html}),
62
+ () => me.fire('contentChange', {component: me}));
63
+ }
64
+ }
37
65
  }
38
66
 
39
67
  Neo.applyClassConfig(ContentTreeList);
@@ -1,47 +1,35 @@
1
- import Container from '../../../../src/container/Base.mjs';
2
- import ContentTreeList from './ContentTreeList.mjs';
1
+ import Container from '../../../../src/container/Base.mjs';
2
+ import Component from '../../../../src/component/Base.mjs';
3
+ import ContentTreeList from './ContentTreeList.mjs';
3
4
  import MainContainerController from './MainContainerController.mjs';
4
- import Splitter from '../../../../src/component/Splitter.mjs';
5
+ import MainContainerModel from './MainContainerModel.mjs';
6
+ import Splitter from '../../../../src/component/Splitter.mjs';
5
7
 
6
- /**
7
- * @class LearnNeo.view.home.MainContainer
8
- * @extends Neo.container.Base
9
- */
10
8
  class MainContainer extends Container {
11
9
  static config = {
12
- /**
13
- * @member {String} className='LearnNeo.view.home.MainContainer'
14
- * @protected
15
- */
16
10
  className: 'LearnNeo.view.home.MainContainer',
17
- /**
18
- * @member {Neo.controller.Component} controller=MainContainerController
19
- */
11
+ model: MainContainerModel,
20
12
  controller: MainContainerController,
21
- /**
22
- * @member {Object[]} items
23
- */
24
13
  items: [{
25
- module : Container,
26
- layout : 'fit',
14
+ module: Container,
15
+ layout: 'fit',
27
16
  minWidth: 350,
28
- width : 350,
17
+ width: 350,
29
18
 
30
19
  items: [{
31
- module : ContentTreeList,
32
- listeners: {leafItemClick: 'onContentListLeafClick'}
20
+ module: ContentTreeList,
21
+ reference: 'tree',
22
+ listeners: {contentChange: 'onContentListLeafClick'},
33
23
  }]
34
24
  }, {
35
- module : Splitter,
25
+ module: Splitter,
36
26
  resizeTarget: 'previous'
37
27
  }, {
38
- module : Container,
39
- layout : {ntype: 'card', activeIndex: null},
40
- reference: 'content-container'
28
+ module: Component,
29
+ layout: {ntype: 'card', activeIndex: null},
30
+ cls: 'learn-content',
31
+ reference: 'content'
41
32
  }],
42
- /**
43
- * @member {Object} layout={ntype:'hbox',align:'stretch'}
44
- */
45
33
  layout: {ntype: 'hbox', align: 'stretch'}
46
34
  }
47
35
  }
@@ -1,5 +1,6 @@
1
1
  import Component from '../../../../src/controller/Component.mjs';
2
2
 
3
+
3
4
  /**
4
5
  * @class LearnNeo.view.home.MainContainerController
5
6
  * @extends Neo.controller.Component
@@ -14,35 +15,43 @@ class MainContainerController extends Component {
14
15
  }
15
16
 
16
17
  /**
17
- * @param {Object} record
18
+ * @param {Object} data
18
19
  */
19
- async onContentListLeafClick(record) {
20
+ async onContentListLeafClick(data) {
20
21
  const
21
- contentContainer = this.getReference('content-container'),
22
- path = '../../../resources/data/learnneo/pages';
23
-
24
- console.log('onContentListLeafClick', {contentContainer, record});
25
- console.log('onContentListLeafClick', {contentContainer, record});
22
+ me = this,
23
+ content = me.getReference('content');
26
24
 
27
- if (record.isLeaf && record.path) {
28
- const data = await fetch(`${path}/${record.path}`);
29
- const content = await data.text();
25
+ content.html = data.html;
30
26
 
31
- contentContainer.removeAll();
27
+ await this.timeout(200);
32
28
 
33
- await this.timeout(50);
29
+ // todo: we need to add the links as neo configs
30
+ await Neo.main.addon.HighlightJS.loadLibrary({
31
+ appName : me.appName,
32
+ highlightJsPath: '../../docs/resources/highlight/highlight.pack.js',
33
+ themePath : '../../docs/resources/highlightjs-custom-github-theme.css'
34
+ });
34
35
 
35
- contentContainer.add({
36
- ntype: 'component',
37
- html : content
38
- });
36
+ await this.timeout(200);
39
37
 
40
- await this.timeout(50);
38
+ Neo.main.addon.HighlightJS.syntaxHighlightInit({
39
+ appName: me.appName,
40
+ vnodeId: content.id
41
+ })
41
42
 
43
+ // contentContainer.removeAll();
44
+ // contentContainer.add({
45
+ // ntype: 'component',
46
+ // html: data.html
47
+ // });
48
+ // contentContainer.layout.activeIndex = 0;
49
+ }
42
50
 
43
- contentContainer.layout.activeIndex = 0;
44
- }
51
+ get contentPath() {
52
+ return `../../../resources/data/${this.deck}`;
45
53
  }
54
+
46
55
  }
47
56
 
48
57
  Neo.applyClassConfig(MainContainerController);
@@ -0,0 +1,35 @@
1
+ import Component from '../../../../src/model/Component.mjs';
2
+ import Tree from '../../store/Content.mjs';
3
+ import Store from '../../../../src/data/Store.mjs';
4
+
5
+ /**
6
+ * @class LearnNeo.view.home.MainContainerModel
7
+ * @extends Neo.model.Component
8
+ */
9
+ class MainContainerModel extends Component {
10
+ static config = {
11
+ /**
12
+ * @member {String} className='LearnNeo.view.home.MainContainerModel'
13
+ * @protected
14
+ */
15
+ className: 'LearnNeo.view.home.MainContainerModel',
16
+ /**
17
+ * @member {Object} data
18
+ */
19
+ data: {},
20
+ /**
21
+ * @member {Object} stores
22
+ */
23
+ stores: {
24
+ tree: {
25
+ // module: Tree,
26
+ module: Store,
27
+ responseRoot: "data",
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ Neo.applyClassConfig(MainContainerModel);
34
+
35
+ export default MainContainerModel;
@@ -19,6 +19,18 @@ class MainContainerController extends Component {
19
19
  ntype: 'docs-maincontainer-controller'
20
20
  }
21
21
 
22
+ /**
23
+ * @param {Object} config
24
+ */
25
+ construct(config) {
26
+ super.construct(config);
27
+
28
+ // todo: remove once paths are neo configs
29
+ Neo.main.addon.HighlightJS.loadLibrary({
30
+ appName: this.appName
31
+ })
32
+ }
33
+
22
34
  /**
23
35
  * @param {Object} record
24
36
  */
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='6.9.6'
23
+ * @member {String} version='6.9.8'
24
24
  */
25
- version: '6.9.6'
25
+ version: '6.9.8'
26
26
  }
27
27
 
28
28
  /**
@@ -2,5 +2,6 @@
2
2
  "appPath" : "examples/button/base/app.mjs",
3
3
  "basePath" : "../../../",
4
4
  "environment": "development",
5
- "mainPath" : "./Main.mjs"
5
+ "mainPath" : "./Main.mjs",
6
+ "themes" : ["neo-theme-neo-light"]
6
7
  }
@@ -113,6 +113,12 @@ class MainContainer extends ConfigurationViewport {
113
113
  labelText: 'resizable',
114
114
  listeners: {change: me.onConfigChange.bind(me, 'resizable')},
115
115
  style : {marginTop: '10px'}
116
+ }, {
117
+ module : CheckBox,
118
+ checked : me.exampleComponent.autoGrow,
119
+ labelText: 'autoGrow',
120
+ listeners: {change: me.onConfigChange.bind(me, 'autoGrow')},
121
+ style : {marginTop: '10px'}
116
122
  }, {
117
123
  module : CheckBox,
118
124
  checked : me.exampleComponent.required,
@@ -175,7 +181,7 @@ class MainContainer extends ConfigurationViewport {
175
181
  createExampleComponent() {
176
182
  return Neo.create(TextAreaField, {
177
183
  clearable : true,
178
- height : 600,
184
+ height : 60,
179
185
  labelText : 'Label',
180
186
  labelWidth: 70,
181
187
  value : 'Hello World',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "6.9.6",
3
+ "version": "6.9.8",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -0,0 +1,102 @@
1
+ # This is a h1
2
+ ## This is a h2
3
+ ### This is a h3
4
+ #### This is a h4
5
+
6
+
7
+ Neo.mjs is a framework used to create <mark>browser-based</mark> applications.
8
+
9
+ Some key features and benefits of Neo.mjs are:
10
+
11
+ <details>
12
+ <summary>Multi-Threaded</summary>
13
+ <p>
14
+ When a Neo.mjs application starts, the framework spawns three web-workers, in addition
15
+ to the main browser thread, resulting in:
16
+ <ol>
17
+ <li>The <b>main</b> browser thread, where DOM updates are applied
18
+ <li>An <b>application</b> web-worker where normal application locic is run
19
+ <li>A <b>data</b> web-worker were HTTP and socket calls are run
20
+ <li>A <b>view</b> web-worker that manages delta updates
21
+ </ol>
22
+ </details>
23
+ <details>
24
+ <summary>Extreme Speed</summary>
25
+ <p>
26
+ Web-worker proccesses are automatically run in parallel, on separate CPU cores.
27
+ </p>
28
+ <p>
29
+ By contrast, other JavaScript frameworks run in a single thread. That means
30
+ in a typical framework all business logic, data handling, and DOM rendering compete for
31
+ CPU reasources.
32
+ </p>
33
+ <p>
34
+ This means Neo.mjs applications run and render faster. This is
35
+ particularly beneficial for processor- and data-intensive applications,
36
+ and applications that need to rapidly update what's viewed. In testing, Neo.mjs applications
37
+ easily apply over 20,000 DOM updates per second.
38
+ </p>
39
+ <p>
40
+ If the default four threads aren't enough, you're free to launch additional web-worker threads
41
+ to run other specialized logic.
42
+ </p>
43
+ </details>
44
+ <details>
45
+ <summary>Quick Application Development</summary>
46
+ <p>
47
+ Neo.js classes let you specify properties in a way that allows code to detect "before" and "after"
48
+ changes. This makes it easy to handle value validation and transformation, and react to changes.
49
+ </p>
50
+ <p>
51
+ Neo.mjs also has elegant yet powerful state management features that make it easy to create shared,
52
+ bindable data. For example, if two components are bound to the same propery, a change to the
53
+ property will automatically be applied to both components.
54
+ </p>
55
+ <p>
56
+ Debugging is also easy because Neo.mjs uses standard JavaScript, the Neo.mjs class
57
+ config system, and built-in debugging tools. For example, while developing an application
58
+ you can click on a component, and in the debugger easily inspect the component and
59
+ update its properties &dash; these updates are immediately reflected in the running application.
60
+ </p>
61
+ </details>
62
+ <details>
63
+ <summary>Multi-Window Applications</summary>
64
+ <p>
65
+ Neo.mjs applications can also launch as <i>shared web workers</i>, which allows you to have a single
66
+ application run in multiple browser windows; those windows could be moved to multiple monitors.
67
+ </p>
68
+ <p>
69
+ For example, you can have a data analysis application with a control panel on one monitor,
70
+ tabular data in another, and charts on another &mdash; all sharing the same data, handling events
71
+ across windows, running seamlessly as a single application.
72
+ </p>
73
+ </details>
74
+ <details>
75
+ <summary>Open-Source and Standards-Based</summary>
76
+ <p>
77
+ Neo.mjs is an open-source library. Features needed for the community can be added to the
78
+ library via pull-requests. And since Neo.mjs uses the standard JavaScript class system,
79
+ all Neo.mjs classes can be extended.
80
+ </p>
81
+ <p>
82
+ Neo.mjs uses standard modular JavaScript, so developers don't need to learn non-standard language
83
+ syntax, and there's no need for special pre-compilers or WebPack modules.
84
+ That means fewer dependencies and easier configuration. Furthermore, the use of
85
+ standard JavaScript makes debugging easier: any statement you write while developing your
86
+ applcation can also be run in the debugging console.
87
+ </p>
88
+ </details>
89
+ <details>
90
+ <summary>Scalable</summary>
91
+ <p>
92
+ Applications can become exponentially difficult to implement as application
93
+ complexity increases. In contrast, the effort to code applications in Neo.mjs
94
+ is fairly linear. This is because of the Neo.mjs approach to binding, separation
95
+ of concerns, extensibility, and being standards based
96
+ </p>
97
+ <p>
98
+ Neo.mjs isn't just architecturally scalable &mdash; because of its multi-threaded
99
+ nature, it's designed to handles rapid DOM updates, data traffic, and processor-
100
+ intensive business logic.
101
+ </p>
102
+ </details>
@@ -0,0 +1,110 @@
1
+ Neo.mjs classes are standard JavaScript classes. Every source file
2
+ you write will be a class definition, extending some Neo.mjs
3
+ class.
4
+
5
+ <pre>
6
+ <code class="javascript">
7
+ import Base from '../../../node_modules/neo.mjs/src/core/Base.mjs';
8
+
9
+ class Mammal extends Base {
10
+ static config = {
11
+ className: 'Simple.example.Mammal'
12
+ }
13
+ }
14
+
15
+ const myMammal = Neo.create(Mammal);
16
+
17
+ Neo.applyClassConfig(Mammal); // Where Neo.mjs initialializes the class config.
18
+ export default Mammal; // Makes the class available elsewhere.
19
+ </code>
20
+ </pre>
21
+
22
+ In the example above, we're extending the Neo.mjs base class. The static
23
+ config block describes the class we're defining.
24
+
25
+ All classes specify `className`; you'll add other config properties to describe the class.
26
+
27
+ The `const myMammal = Neo.create(Mammal);` statement creates an instance of
28
+ our class. For the sake of our discussion we're putting that statement in the same source
29
+ file where the class is defined, but normally your code would import the class elsewhere,
30
+ and create instances as needed.
31
+
32
+ Let's add a `name` propery to the class.
33
+
34
+ <pre>
35
+ <code class="javascript">
36
+ import Base from '../../../node_modules/neo.mjs/src/core/Base.mjs';
37
+
38
+ class Mammal extends Base {
39
+ static config = {
40
+ className: 'Simple.example.Mammal',
41
+ name : 'Anonymous'
42
+ }
43
+ }
44
+
45
+ const myMammal = Neo.create(Mammal);
46
+ console.log(myMammal.name); // Logs "Anonymous"
47
+ myMammal.name = 'Herbert';
48
+ console.log(myMammal.name); // Logs "Herbert"
49
+
50
+ Neo.applyClassConfig(Mammal);
51
+
52
+ export default Mammal;
53
+ </code>
54
+ </pre>
55
+
56
+ In Neo.mjs, instance properties are usually added in the `static config` block.
57
+ The `static config` block does two things:
58
+ - It formally describes the properties API for your class.
59
+ - It lets Neo.mjs manage the initialization and lifecycle of those properties.
60
+
61
+ Think of the `static config` block as "these are the properties
62
+ that can be set as instances are created." Config properties can be introduced
63
+ anywhere in the class hierarchy.
64
+
65
+ Since our class defines a `name` property, we can specify that when creating
66
+ the instance, using the second argument to the `create` method.
67
+
68
+ <pre>
69
+ <code class="javascript">
70
+ const myMammal = Neo.create(Mammal, {
71
+ name: 'Creature'
72
+ });
73
+ console.log(myMammal.name); // Logs "Creature"
74
+ </code>
75
+ </pre>
76
+
77
+
78
+ Since _you_ define those properties, you can
79
+ look for them in class methods and use them as needed.
80
+ Let's add a `speak()` method that uses the `name` property.
81
+
82
+ <pre>
83
+ <code class="javascript">
84
+ import Base from '../../../node_modules/neo.mjs/src/core/Base.mjs';
85
+
86
+ class Mammal extends Base {
87
+ static config = {
88
+ className: 'Simple.example.Mammal',
89
+
90
+ name: 'Anonymous'
91
+ }
92
+ speak(){
93
+ console.log(`${this.name} is grunting`);
94
+ }
95
+ }
96
+
97
+ const myMammal = Neo.create(Mammal, {
98
+ name: 'Creature'
99
+ });
100
+
101
+ myMammal.speak(); // Logs "Creature is grunting."
102
+
103
+ Neo.applyClassConfig(Mammal);
104
+
105
+ export default Mammal;
106
+ </code>
107
+ </pre>
108
+
109
+
110
+
@@ -0,0 +1,75 @@
1
+ In Neo.mjs you sub-class and override methods in the usual way.
2
+
3
+ Here, we'll extend `Mammal` and override the `speak()` method.
4
+ (For brevity, we'll exclude `export` and `import` statements.)
5
+
6
+ <pre class="neo">
7
+ class Mammal extends Base {
8
+ static config = {
9
+ className: 'Simple.example.Mammal',
10
+
11
+ name: 'Anonymous'
12
+ }
13
+ speak(){
14
+ console.log(`(${this.name} is grunting)`);
15
+ }
16
+ }
17
+ Neo.applyClassConfig(Mammal);
18
+ </pre>
19
+ <pre class="neo">
20
+ class Human extends Mammal {
21
+ static config = {
22
+ className: 'Simple.example.Human',
23
+ }
24
+ speak(){
25
+ console.log(`Hello! My name is ${this.name}. I am ${this.married?'':'not'} married.`);
26
+ }
27
+ }
28
+
29
+ const myMammal = Neo.create(Human, {
30
+ name: 'Herbert'
31
+ });
32
+ myMammal.speak(); // Logs "Hello! My name is Herbert. I am not married."
33
+
34
+ Neo.applyClassConfig(Mammal);
35
+ </pre>
36
+
37
+ Any class in the hierarchy is free to add new properties and methods. Let's add
38
+ a property and behavior (method) to the Human class.
39
+
40
+ <pre class="neo">
41
+ import Base from '../../../node_modules/neo.mjs/src/core/Base.mjs';
42
+
43
+ class Mammal extends Base {
44
+ static config = {
45
+ className: 'Simple.example.Mammal',
46
+
47
+ name: 'Anonymous'
48
+ }
49
+ speak(){
50
+ console.log(`(${this.name} is grunting)`);
51
+ }
52
+ }
53
+ </pre>
54
+ <pre class="neo">
55
+ class Human extends Mammal {
56
+ static config = {
57
+ className: 'Simple.example.Human',
58
+ name: 'J. Doe',
59
+ married: false
60
+ }
61
+ speak(){
62
+ console.log(`Hello! My name is ${this.name}. I am ${this.married?'':'not'} married.`);
63
+ },
64
+ yodel(){
65
+ console.log('Yodelay hee hoo!');
66
+ }}
67
+
68
+ const myPerson = Neo.create(Human, {
69
+ name: 'Herbert'
70
+ });
71
+ myPerson.speak(); // Logs "Hello! My name is Herbert. I am not married."
72
+ myPerson.yodel(); // Logs "Yedelay hee hoo!"
73
+
74
+ Neo.applyClassConfig(Human);
75
+ </pre>