neo.mjs 6.10.10 → 6.10.11

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 (79) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/portal/view/learn/ContentTreeList.mjs +24 -12
  3. package/apps/portal/view/learn/LivePreview.mjs +28 -11
  4. package/buildScripts/createAppMinimal.mjs +391 -0
  5. package/examples/ServiceWorker.mjs +2 -2
  6. package/examples/button/base/neo-config.json +2 -1
  7. package/examples/list/chip/neo-config.json +1 -2
  8. package/package.json +72 -70
  9. package/resources/data/deck/learnneo/data/theBeatles.json +22 -0
  10. package/resources/data/deck/learnneo/p/2023-10-14T19-25-08-153Z.md +29 -20
  11. package/resources/data/deck/learnneo/p/ComponentModels.md +116 -1
  12. package/resources/data/deck/learnneo/p/Config.md +157 -0
  13. package/resources/data/deck/learnneo/p/DescribingTheUI.md +67 -1
  14. package/resources/data/deck/learnneo/p/Earthquakes.md +214 -0
  15. package/resources/data/deck/learnneo/p/Events.md +142 -1
  16. package/resources/data/deck/learnneo/p/Extending.md +116 -1
  17. package/resources/data/deck/learnneo/p/References.md +126 -0
  18. package/resources/data/deck/learnneo/p/TestLivePreview.md +28 -6
  19. package/resources/data/deck/learnneo/t.json +5 -6
  20. package/resources/data/deck/training/p/2022-12-27T21-55-30-948Z.md +1 -1
  21. package/resources/data/deck/training/p/2022-12-27T22-23-55-083Z.md +1 -1
  22. package/resources/data/deck/training/p/2022-12-29T16-00-13-223Z.md +1 -1
  23. package/resources/data/deck/training/p/2022-12-29T18-34-25-826Z.md +1 -1
  24. package/resources/data/deck/training/p/2022-12-29T18-36-56-893Z.md +1 -1
  25. package/resources/data/deck/training/p/2022-12-31T18-43-56-338Z.md +1 -1
  26. package/resources/data/deck/training/p/2022-12-31T18-51-50-682Z.md +1 -1
  27. package/resources/data/deck/training/p/2022-12-31T18-54-04-176Z.md +1 -1
  28. package/resources/data/deck/training/p/2023-01-01T17-49-18-429Z.md +1 -1
  29. package/resources/data/deck/training/p/2023-01-01T21-23-17-716Z.md +1 -1
  30. package/resources/data/deck/training/p/2023-01-06T23-21-31-685Z.md +1 -1
  31. package/resources/data/deck/training/p/2023-01-06T23-34-13-897Z.md +2 -2
  32. package/resources/data/deck/training/p/2023-01-06T23-46-36-687Z.md +1 -1
  33. package/resources/data/deck/training/p/2023-01-08T01-24-21-088Z.md +1 -1
  34. package/resources/data/deck/training/p/2023-01-08T02-11-26-333Z.md +2 -2
  35. package/resources/data/deck/training/p/2023-01-14T00-40-27-784Z.md +2 -2
  36. package/resources/data/deck/training/p/2023-07-31T00-37-21-927Z.md +2 -2
  37. package/resources/data/deck/training/p/2023-10-14T19-25-08-153Z.md +3 -3
  38. package/resources/scss/src/apps/newwebsite/Viewport.scss +32 -0
  39. package/resources/scss/src/apps/portal/learn/ContentView.scss +20 -4
  40. package/resources/scss/src/apps/portal/learn/LivePreview.scss +8 -0
  41. package/resources/scss/src/component/Base.scss +13 -4
  42. package/resources/scss/src/form/field/Select.scss +2 -5
  43. package/resources/scss/src/form/field/Text.scss +0 -1
  44. package/resources/scss/src/list/Base.scss +47 -2
  45. package/resources/scss/src/list/Chip.scss +10 -4
  46. package/resources/scss/theme-dark/list/Base.scss +11 -10
  47. package/resources/scss/theme-light/list/Base.scss +11 -10
  48. package/resources/scss/theme-neo-light/design-tokens/Components.scss +3 -0
  49. package/resources/scss/theme-neo-light/list/Base.scss +1 -0
  50. package/src/DefaultConfig.mjs +3 -3
  51. package/src/component/Base.mjs +7 -0
  52. package/src/container/Base.mjs +6 -12
  53. package/src/core/Base.mjs +5 -2
  54. package/src/data/Model.mjs +7 -0
  55. package/src/data/RecordFactory.mjs +5 -4
  56. package/src/form/field/Base.mjs +11 -0
  57. package/src/form/field/Picker.mjs +0 -1
  58. package/src/form/field/Select.mjs +208 -257
  59. package/src/form/field/Text.mjs +3 -3
  60. package/src/form/field/trigger/Base.mjs +5 -6
  61. package/src/layout/Flexbox.mjs +23 -31
  62. package/src/layout/HBox.mjs +1 -1
  63. package/src/layout/VBox.mjs +1 -1
  64. package/src/list/Base.mjs +64 -31
  65. package/src/main/DomAccess.mjs +55 -28
  66. package/src/main/DomEvents.mjs +2 -1
  67. package/src/main/DomUtils.mjs +66 -0
  68. package/src/main/addon/Navigator.mjs +332 -0
  69. package/src/manager/DomEvent.mjs +2 -1
  70. package/src/selection/ListModel.mjs +46 -82
  71. package/src/selection/Model.mjs +56 -33
  72. package/src/util/Array.mjs +5 -2
  73. package/src/util/Function.mjs +31 -0
  74. package/src/util/String.mjs +9 -0
  75. package/src/vdom/Helper.mjs +1 -2
  76. package/test/components/app.mjs +4 -3
  77. package/test/components/files/component/ChipList.mjs +125 -0
  78. package/test/components/files/form/field/Select.mjs +177 -2
  79. package/test/components/siesta.js +34 -1
package/package.json CHANGED
@@ -1,72 +1,74 @@
1
1
  {
2
- "name": "neo.mjs",
3
- "version": "6.10.10",
4
- "description": "The webworkers driven UI framework",
5
- "type": "module",
6
- "repository": {
7
- "type": "git",
8
- "url": "https://github.com/neomjs/neo.git"
9
- },
10
- "bin": {
11
- "neo-cc": "./buildScripts/createClass.mjs"
12
- },
13
- "scripts": {
14
- "add-config": "node ./buildScripts/addConfig.mjs",
15
- "build-all": "node ./buildScripts/buildAll.mjs -f -n",
16
- "build-all-questions": "node ./buildScripts/buildAll.mjs -f",
17
- "build-themes": "node ./buildScripts/buildThemes.mjs -f",
18
- "build-threads": "node ./buildScripts/webpack/buildThreads.mjs -f",
19
- "convert-design-tokens": "node ./buildScripts/convertDesignTokens.mjs",
20
- "create-app": "node ./buildScripts/createApp.mjs",
21
- "create-class": "node ./buildScripts/createClass.mjs",
22
- "create-component": "node ./buildScripts/createComponent.mjs",
23
- "generate-docs-json": "node ./buildScripts/docs/jsdocx.mjs",
24
- "inject-package-version": "node ./buildScripts/injectPackageVersion.mjs",
25
- "server-start": "webpack serve -c ./buildScripts/webpack/webpack.server.config.mjs --open",
26
- "test": "echo \"Error: no test specified\" && exit 1",
27
- "watch-themes": "node ./buildScripts/watchThemes.mjs"
28
- },
29
- "keywords": [
30
- "javascript",
31
- "frontend",
32
- "framework",
33
- "webworker",
34
- "ecmascript",
35
- "css",
36
- "json"
37
- ],
38
- "author": "Tobias Uhlig, Rich Waters",
39
- "license": "MIT",
40
- "bugs": {
41
- "url": "https://github.com/neomjs/neo/issues"
42
- },
43
- "homepage": "https://neomjs.github.io/pages/",
44
- "devDependencies": {
45
- "@fortawesome/fontawesome-free": "^6.5.1",
46
- "autoprefixer": "^10.4.16",
47
- "chalk": "^5.3.0",
48
- "clean-webpack-plugin": "^4.0.0",
49
- "commander": "^11.1.0",
50
- "cssnano": "^6.0.2",
51
- "envinfo": "^7.11.0",
52
- "fs-extra": "^11.2.0",
53
- "highlightjs-line-numbers.js": "^2.8.0",
54
- "inquirer": "^9.2.12",
55
- "neo-jsdoc": "1.0.1",
56
- "neo-jsdoc-x": "1.0.5",
57
- "postcss": "^8.4.32",
58
- "sass": "^1.69.5",
59
- "siesta-lite": "5.5.2",
60
- "showdown": "^2.1.0",
61
- "url": "^0.11.3",
62
- "webpack": "^5.89.0",
63
- "webpack-cli": "^5.1.4",
64
- "webpack-dev-server": "4.15.1",
65
- "webpack-hook-plugin": "^1.0.7",
66
- "webpack-node-externals": "^3.0.0"
67
- },
68
- "funding": {
69
- "type": "GitHub Sponsors",
70
- "url": "https://github.com/sponsors/tobiu"
71
- }
2
+ "name" : "neo.mjs",
3
+ "version" : "6.10.11",
4
+ "description" : "The webworkers driven UI framework",
5
+ "type" : "module",
6
+ "repository" : {
7
+ "type" : "git",
8
+ "url" : "https://github.com/neomjs/neo.git"
9
+ },
10
+ "bin" : {
11
+ "neo-cc" : "./buildScripts/createClass.mjs"
12
+ },
13
+ "scripts" : {
14
+ "add-config" : "node ./buildScripts/addConfig.mjs",
15
+ "build-all" : "node ./buildScripts/buildAll.mjs -f -n",
16
+ "build-all-questions" : "node ./buildScripts/buildAll.mjs -f",
17
+ "build-themes" : "node ./buildScripts/buildThemes.mjs -f",
18
+ "build-threads" : "node ./buildScripts/webpack/buildThreads.mjs -f",
19
+ "convert-design-tokens" : "node ./buildScripts/convertDesignTokens.mjs",
20
+ "create-app" : "node ./buildScripts/createApp.mjs",
21
+ "create-app-minimal" : "node ./buildScripts/createAppMinimal.mjs",
22
+ "create-class" : "node ./buildScripts/createClass.mjs",
23
+ "create-component" : "node ./buildScripts/createComponent.mjs",
24
+ "generate-docs-json" : "node ./buildScripts/docs/jsdocx.mjs",
25
+ "inject-package-version" : "node ./buildScripts/injectPackageVersion.mjs",
26
+ "server-start" : "webpack serve -c ./buildScripts/webpack/webpack.server.config.mjs --open",
27
+ "test" : "echo \"Error: no test specified\" && exit 1",
28
+ "watch-themes" : "node ./buildScripts/watchThemes.mjs"
29
+ },
30
+ "keywords" : [
31
+ "javascript",
32
+ "frontend",
33
+ "framework",
34
+ "webworker",
35
+ "ecmascript",
36
+ "css",
37
+ "json"
38
+ ],
39
+ "author" : "Tobias Uhlig, Rich Waters",
40
+ "license" : "MIT",
41
+ "bugs" : {
42
+ "url" : "https://github.com/neomjs/neo/issues"
43
+ },
44
+ "homepage" : "https://neomjs.github.io/pages/",
45
+ "devDependencies" : {
46
+ "@fortawesome/fontawesome-free" : "^6.5.1",
47
+ "autoprefixer" : "^10.4.16",
48
+ "chalk" : "^5.3.0",
49
+ "clean-webpack-plugin" : "^4.0.0",
50
+ "commander" : "^11.1.0",
51
+ "cssnano" : "^6.0.2",
52
+ "envinfo" : "^7.11.0",
53
+ "fs-extra" : "^11.2.0",
54
+ "highlightjs-line-numbers.js" : "^2.8.0",
55
+ "inquirer" : "^9.2.12",
56
+ "neo-jsdoc" : "1.0.1",
57
+ "neo-jsdoc-x" : "1.0.5",
58
+ "postcss" : "^8.4.32",
59
+ "sass" : "^1.69.5",
60
+ "siesta-lite" : "5.5.2",
61
+ "showdown" : "^2.1.0",
62
+ "url" : "^0.11.3",
63
+ "webpack" : "^5.89.0",
64
+ "webpack-cli" : "^5.1.4",
65
+ "webpack-dev-server" : "4.15.1",
66
+ "webpack-hook-plugin" : "^1.0.7",
67
+ "webpack-node-externals" : "^3.0.0"
68
+ },
69
+ "funding" : {
70
+ "type" : "GitHub Sponsors",
71
+ "url" : "https://github.com/sponsors/tobiu"
72
+ }
73
+
72
74
  }
@@ -0,0 +1,22 @@
1
+ [
2
+ {
3
+ "first": "John",
4
+ "last": "Lennon",
5
+ "dob": "1940/10/09"
6
+ },
7
+ {
8
+ "first": "Paul",
9
+ "last": "McCartney",
10
+ "dob": "1942/06/18"
11
+ },
12
+ {
13
+ "first": "George",
14
+ "last": "Harrison",
15
+ "dob": "1943/02/25"
16
+ },
17
+ {
18
+ "first": "Ringo",
19
+ "last": "Starr",
20
+ "dob": "1940/07/07"
21
+ }
22
+ ]
@@ -78,8 +78,7 @@ class MainView extends Container {
78
78
  className : 'Foo.view.MainView',
79
79
  controller: Controller,
80
80
  model : ViewModel,
81
-
82
- layout: {ntype: 'fit'},
81
+ layout: {ntype:'vbox', align:'start'},
83
82
  items : [{
84
83
  module: Button,
85
84
  text : 'Button'
@@ -92,26 +91,36 @@ Neo.applyClassConfig(MainView);
92
91
  export default MainView;
93
92
  </pre>
94
93
 
95
- Note the entry in `items:[]`. That's a description of the button that'll be created as the single
96
- item in our container. In Neo.mjs terms we're _configuring_ the button. Neo.mjs is a declarative framework,
97
- in which components and objects are described. It's an abstraction. In other words, the code describes
98
- what we want, but not how it's done. In the code above, we want our container to have one item &mdash; a button
99
- with some text. _How_ that's done isn't important here in the container. A non-declarative approach would be
100
- more focused on _how_, where you might way "I want a &lt;button> HTML element with its innerHTML set to some
101
- value."
94
+ Note the entry in `items:[]`. That's a description of the button that will be the single item in our
95
+ container. In Neo.mjs terms we're _configuring_ the button. Neo.mjs is a declarative framework, in
96
+ which components and objects are described. It's an abstraction. In other words, the code describes
97
+ what we want, but not how it's done. In the code above, we want our container to have one item &mdash;
98
+ a button with some text. _How_ that's done isn't important. A non-declarative approach would be more
99
+ focused on _how_, where you might way "I want a &lt;button> HTML element with its innerHTML set to
100
+ some value."
102
101
 
103
- In another topic you'll learn about the Neo.mjs config system and declaratively describing
104
- views, controllers, and other things.
102
+ In another topic you'll learn about the Neo.mjs config system and declaratively describing views,
103
+ controllers, and other things.
105
104
 
106
- If you run the app you'll see one huge button. That's because the container is configured to
107
- use the "fit" layout, which means the container is designed to hold one and only one component,
108
- and that component will take up all available space. We could get a more normal looking button
109
- by changing the layout.
105
+ Here's a simplified running example. The `model` and `controller` are omitted, because they aren't
106
+ actually used in the example, and the import root path is different to reflect the location of the
107
+ Neo.mjs libarary relative to the examples.
110
108
 
111
- `layout: {ntype:'vbox', align:'start},`
112
109
 
113
- Neo.mjs has scores of component classes.
114
- You can extend them to create your own reusable components and sets of components.
110
+ <pre data-neo>
111
+ import Base from '../../../../src/container/Base.mjs';
112
+ import Button from '../../../../src/button/Base.mjs';
113
+ import Split from '../../../../src/button/Split.mjs';
114
+ class MainView extends Base {
115
+ static config = {
116
+ className : 'Example.view.MainView',
117
+ layout: {ntype:'vbox', align:'start'},
118
+ items : [{
119
+ module: Button,
120
+ text : 'Button'
121
+ }]
122
+ }
123
+ }
124
+ Neo.applyClassConfig(MainView);
125
+ </pre>
115
126
 
116
- Other topics discuss coding applications, how the config system works, controllers,
117
- and bindable data. However, as long as we're here
@@ -1 +1,116 @@
1
- ### todo: Component Models and Binding
1
+
2
+ Neo has a feature that allows shared, bindable, data.
3
+
4
+ A _view model_ &mdash; `Neo.model.Component` &mdash; instance holds properties that
5
+ can be bound to component properties.
6
+
7
+ <pre data-neo>
8
+ import Base from '../../../../src/container/Base.mjs';
9
+ import Label from '../../../../src/component/Label.mjs';
10
+ import TextField from '../../../../src/form/field/Text.mjs';
11
+
12
+ class MainView extends Base {
13
+ static config = {
14
+ className : 'Example.view.MainView',
15
+
16
+ model: {
17
+ data: {
18
+ foo: 'Hi there!'
19
+ }
20
+ },
21
+ layout: 'vbox',
22
+ items: [{
23
+ module: Label,
24
+ bind: {
25
+ text: data => `The value of foo is "${data.foo}"` // The "text" property is set as data.foo changes
26
+ }
27
+ }, {
28
+ module: TextField,
29
+ bind: {
30
+ value: {twoWay: true, value: data => data.foo} // "twoWay" means data.foo is set as the text field changes
31
+ },
32
+ labelText: 'Bound to foo:',
33
+ width: 300,
34
+ }],
35
+ style: {padding: '1em'},
36
+ }
37
+ }
38
+ Neo.applyClassConfig(MainView);
39
+ </pre>
40
+
41
+ View model properties are visible up the containment hierarchy:
42
+ Properties introduced in a parent container will be available to any child component, and properties
43
+ introduces in a specific component are only visible to that component. This approach makes it easy to control scope.
44
+
45
+ In this example the main view has three child items of type `MyPanel`. The main view has a view model with a
46
+ `foo` property, and the third child has its own view model with a `foo` property.
47
+
48
+ `MyPanel` contains a `Neo.componnet.Label` whose `text` value is bound to `foo`. To resolve the binding, Neo.mjs looks up the
49
+ containment hierarchy until it finds the value. For the first two panels the label binding looks in the label, then in its `MyPanel`
50
+ container, then in the main view where it finds `foo`. For the third child panel the label binding looks in the label,
51
+ then in its `MyPanel` and finds it because the third copy of `MyPanel` has its own view model with the `foo` property.
52
+
53
+ The bottom line is the Neo.mjs view model and binding approach is simple and powerful, and gives you easy control over the scope
54
+ of a value. Thus, you can share properties as globally or narrowly as needed.
55
+
56
+ <pre data-neo>
57
+ import Base from '../../../../src/container/Base.mjs';
58
+ import Panel from '../../../../src/container/Panel.mjs';
59
+ import Label from '../../../../src/component/Label.mjs';
60
+
61
+ class MyPanel extends Panel {
62
+ static config = {
63
+ className : 'Example.view.MyPanel',
64
+ headers: [{
65
+ dock: 'top',
66
+ items: [{ module: Label, text: 'MyPanel' }]
67
+ }],
68
+ items: [{
69
+ module: Label,
70
+ bind: {
71
+ text: data => `The value of foo is "${data.foo}"`
72
+ },
73
+ style: {margin: '1em'}
74
+ }],
75
+ style: {margin: '1em'},
76
+ }
77
+ }
78
+ Neo.applyClassConfig(MyPanel);
79
+
80
+ class MainView extends Base {
81
+ static config = {
82
+ className : 'Example.view.MainView',
83
+
84
+ model: {
85
+ data: {
86
+ foo: 'parent'
87
+ }
88
+ },
89
+ layout: 'hbox',
90
+ items: [{
91
+ module: MyPanel,
92
+ }, {
93
+ module: MyPanel,
94
+ }, {
95
+ module: MyPanel,
96
+ model: {
97
+ data: {
98
+ foo: 'child'
99
+ }
100
+ }
101
+ }],
102
+ style: {margin: '1em'},
103
+ }
104
+ }
105
+ Neo.applyClassConfig(MainView);
106
+ </pre>
107
+
108
+
109
+
110
+
111
+
112
+ Note that in the example above, the view model is in-line. Normally your view model would be
113
+ coded in its own class that extends 'Neo.model.Component', and you'd use that in your component.
114
+ Just like with items component configs, trivial configs are often done in-line, and non-trivial
115
+ configs are coded as separate classes.
116
+
@@ -0,0 +1,157 @@
1
+ As you've probably noticed, Neo.mjs classes have a `static config` property.
2
+
3
+ The `config` specifies properties that are applied to instances as they are
4
+ created. In addition, Neo.mjs uses that information to set up propoerty lifecycle
5
+ methods.
6
+
7
+ Here's an example of a new component class `Simple` with three config properties:
8
+
9
+ 1. `className` &mdash; used by Neo.mjs to keep track of every class
10
+ 2. `foo` &mdash; an instance property
11
+ 2. `bar_` &mdash; another instance property
12
+
13
+ <pre data-neo>
14
+ import Component from '../../../../src/component/Base.mjs';
15
+ import Container from '../../../../src/container/Base.mjs';
16
+
17
+ class Simple extends Component {
18
+ static config = {
19
+ className: 'Example.view.Simple',
20
+
21
+ foo: 1, // An instance field and its initial (default) value
22
+ bar_: '' // Another instance field -- note the underscore at the end
23
+
24
+ }
25
+
26
+ }
27
+ Neo.applyClassConfig(Simple);
28
+
29
+
30
+ class MainView extends Container {
31
+ static config = {
32
+ className: 'Example.view.MainView',
33
+
34
+ items: [{
35
+ module: Simple,
36
+
37
+ foo: 17, // This is applied to the instance
38
+ bar: 'hi there' // This is applied to the instance
39
+
40
+ }]
41
+
42
+ }
43
+ }
44
+ Neo.applyClassConfig(MainView);
45
+ </pre>
46
+
47
+ The `Simple` class doesn't have any content, so if you run the code you won't see anything. We'll
48
+ change that in the next example.
49
+
50
+ Note that the `bar` property is defined with an underscore at the end. That tags the property as
51
+ a _lifecyle property_. A lifecycle property provides methods that are run as the property is
52
+ updated or accessed. You're free to implment the methods to implement business rules, normalize
53
+ values, or have side-effects, such as updating a view or firing an event.
54
+
55
+ <pre data-neo>
56
+ import Component from '../../../../src/component/Base.mjs';
57
+ import Container from '../../../../src/container/Base.mjs';
58
+
59
+ class Simple extends Component {
60
+ static config = {
61
+ className: 'Example.view.Simple',
62
+
63
+ foo: 1, // An instance field and its initial (default) value
64
+ bar_: null // Another instance field -- note the underscore at the end
65
+
66
+ }
67
+
68
+ beforeGetBar(){
69
+
70
+ }
71
+ beforeSetBar(value, oldValue){
72
+ // Use value if it's not empty
73
+ if (value) return value;
74
+ }
75
+ afterSetBar(value, oldValue){
76
+ this.html = value;
77
+ this.fire('barChange', {component: this, value, oldValue});
78
+ }
79
+
80
+ }
81
+ Neo.applyClassConfig(Simple);
82
+
83
+
84
+ class MainView extends Container {
85
+ static config = {
86
+ className: 'Example.view.MainView',
87
+
88
+ items: [{
89
+ module: Simple,
90
+
91
+ foo: 17 , // This is applied to the instance
92
+ bar: 'hi there' // This is applied to the instance
93
+
94
+ }]
95
+
96
+ }
97
+ }
98
+ Neo.applyClassConfig(MainView);
99
+ </pre>
100
+
101
+ This time if you run the code you'll "hi there" in the view. That's because the Simple instance is
102
+ configured with `bar: 'hi there'`, and since that's a lifecycle property the `afterSetBar()` method
103
+ is run. That method updates the view with the passed value.
104
+
105
+ Updating a view is a common use case for the _afterSet_ method. It's also often used to fire an event.
106
+ Look at this code: `afterSetBar()` fires an event, and the config in the `items[]` is listening to it.
107
+
108
+ <pre data-neo>
109
+ import Component from '../../../../src/component/Base.mjs';
110
+ import Container from '../../../../src/container/Base.mjs';
111
+
112
+ class Simple extends Component {
113
+ static config = {
114
+ className: 'Example.view.Simple',
115
+
116
+ foo: 1, // An instance field and its initial (default) value
117
+ bar_: null // Another instance field -- note the underscore at the end
118
+
119
+ }
120
+
121
+ beforeGetBar(){
122
+
123
+ }
124
+ beforeSetBar(value, oldValue){
125
+ // Use value if it's not empty
126
+ if (value) return value;
127
+ }
128
+ afterSetBar(value, oldValue){
129
+ this.html = value;
130
+ this.fire('barChange', {component: this, value, oldValue});
131
+ }
132
+
133
+ }
134
+ Neo.applyClassConfig(Simple);
135
+
136
+
137
+ class MainView extends Container {
138
+ static config = {
139
+ className: 'Example.view.MainView',
140
+
141
+ items: [{
142
+ module: Simple,
143
+
144
+ foo: 17 , // This is applied to the instance
145
+ bar: 'hi there', // This is applied to the instance
146
+
147
+ listeners: {
148
+ barChange: data => Neo.Main.alert({message: data.value})
149
+ }
150
+
151
+ }]
152
+
153
+ }
154
+ }
155
+ Neo.applyClassConfig(MainView);
156
+ </pre>
157
+
@@ -1 +1,67 @@
1
- ### todo: Describing a View
1
+ A Neo.mjs view is comprised of components and containers. A component is a visual widget, like a button,
2
+ and a container is a visual collection of components.
3
+
4
+ Neo.mjs is declarative, where your code _describes_ or _configures_ the things its creating.
5
+
6
+ For example, if you wanted to create a button, you'd look in the API docs and see that buttons
7
+ have a few key configs, including `text` and `iconCls`. The configs are properties you can
8
+ use to describe the component you're creating> You can also access or set the properties dynamically.
9
+
10
+ <pre data-neo>
11
+ import Base from '../../../../src/container/Base.mjs';
12
+ import Button from '../../../../src/button/Base.mjs';
13
+ class MainView extends Base {
14
+ static config = {
15
+ className : 'Example.view.MainView',
16
+ layout: {ntype:'vbox', align:'start'},
17
+ items : [{
18
+ module: Button,
19
+ text : 'Home',
20
+ iconCls: 'fa fa-home'
21
+ }]
22
+ }
23
+ }
24
+ Neo.applyClassConfig(MainView);
25
+ </pre>
26
+
27
+ The button config is just an object describing the button being created. In the example, it has three
28
+ properties:
29
+
30
+ - `module` is the type of thing being created; it's the imported module name.
31
+ - `text` is the button's text
32
+ - `iconCls` is the css class used for the button's icon. Neo.mjs automatically includes Font Awesome,
33
+ and `fa fa-home` matches a Font Awesome css class.
34
+
35
+ Components are almost always placed within a container. A container is a component that visually holds other
36
+ components. Containers have an `items:[]` config, which is an array of the components within the container.
37
+ Containers also have a `layout` property, which describes how the items are arranged.
38
+
39
+ Let's put a second button in the container.
40
+
41
+ <pre data-neo>
42
+ import Base from '../../../../src/container/Base.mjs';
43
+ import Button from '../../../../src/button/Base.mjs';
44
+ class MainView extends Base {
45
+ static config = {
46
+ className : 'Example.view.MainView',
47
+ layout: {ntype:'vbox', align:'start'}, // Change the ntype to 'hbox'
48
+ items : [{
49
+ module: Button,
50
+ text : 'Home',
51
+ iconCls: 'fa fa-home'
52
+ },{
53
+ module: Button,
54
+ text : 'Star',
55
+ iconCls: 'fa fa-star'
56
+ }]
57
+ }
58
+ }
59
+ Neo.applyClassConfig(MainView);
60
+ </pre>
61
+
62
+ If you run the example you'll see two buttons, arranged according to the `layout`. If you'd like,
63
+ modify the code to specify `ntype:'hbox'` and run it again.
64
+
65
+ Note that the layout specifies `ntype` rather than `module`. An `ntype` is an alias for a class
66
+ that has already been imported. Containers import all the layout types, so since we've already
67
+ imported container we can simply use `ntype` to specify which layout we want.