neo.mjs 6.18.0 → 6.18.1
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.
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/portal/view/home/MainContainer.mjs +30 -1
- package/apps/portal/view/home/parts/Colors.mjs +33 -9
- package/apps/portal/view/home/parts/Helix.mjs +51 -12
- package/apps/portal/view/home/parts/HelloWorld.mjs +6 -3
- package/apps/portal/view/home/parts/How.mjs +66 -0
- package/apps/portal/view/home/parts/MainNeo.mjs +4 -3
- package/examples/ServiceWorker.mjs +2 -2
- package/package.json +1 -1
- package/resources/data/deck/learnneo/pages/Events.md +15 -9
- package/resources/data/deck/learnneo/pages/GuideEvents.md +142 -19
- package/resources/scss/src/apps/portal/HeaderToolbar.scss +142 -124
- package/resources/scss/src/apps/portal/home/MainContainer.scss +9 -22
- package/resources/scss/src/apps/portal/home/parts/MainNeo.scss +22 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/component/Base.mjs +48 -10
- package/src/core/Observable.mjs +23 -7
- package/src/main/addon/IntersectionObserver.mjs +20 -1
- package/src/model/Component.mjs +11 -9
package/apps/ServiceWorker.mjs
CHANGED
@@ -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
|
|
@@ -29,8 +30,9 @@ class MainContainer extends Container {
|
|
29
30
|
MainNeo,
|
30
31
|
Features,
|
31
32
|
HelloWorld,
|
32
|
-
Colors,
|
33
33
|
Helix,
|
34
|
+
Colors,
|
35
|
+
How,
|
34
36
|
AfterMath
|
35
37
|
],
|
36
38
|
/**
|
@@ -39,11 +41,38 @@ class MainContainer extends Container {
|
|
39
41
|
scrollable: true,
|
40
42
|
|
41
43
|
domListeners: [{
|
44
|
+
intersect(data) {
|
45
|
+
Neo.getComponent(data.targetId)?.activate?.()
|
46
|
+
},
|
42
47
|
scroll(event) {
|
43
48
|
this.toggleCls('hide-sidebar', event.scrollTop > 80)
|
44
49
|
}
|
45
50
|
}]
|
46
51
|
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Triggered after the mounted config got changed
|
55
|
+
* @param {Boolean} value
|
56
|
+
* @param {Boolean} oldValue
|
57
|
+
* @protected
|
58
|
+
*/
|
59
|
+
afterSetMounted(value, oldValue) {
|
60
|
+
super.afterSetMounted(value, oldValue);
|
61
|
+
|
62
|
+
let me = this,
|
63
|
+
{id, windowId} = me;
|
64
|
+
|
65
|
+
value && setTimeout(() => {
|
66
|
+
Neo.main.addon.IntersectionObserver.register({
|
67
|
+
callback : 'isVisible',
|
68
|
+
id,
|
69
|
+
observe : ['.page'],
|
70
|
+
root : `#${id}`,
|
71
|
+
threshold: 1.0,
|
72
|
+
windowId
|
73
|
+
})
|
74
|
+
}, 50)
|
75
|
+
}
|
47
76
|
}
|
48
77
|
|
49
78
|
Neo.setupClass(MainContainer);
|
@@ -31,26 +31,43 @@ class Colors extends Container {
|
|
31
31
|
items : [{
|
32
32
|
cls : 'neo-h1',
|
33
33
|
flex: 'none',
|
34
|
-
html: '
|
34
|
+
html: 'Amazing Potential',
|
35
|
+
vdom: {tag: 'h1'}
|
35
36
|
}, {
|
36
37
|
cls : 'neo-h2',
|
37
38
|
flex: 'none',
|
38
|
-
html: '
|
39
|
+
html: 'Socket Data',
|
40
|
+
vdom: {tag: 'h2'}
|
39
41
|
}, {
|
40
|
-
cls : 'neo-content',
|
41
42
|
flex: 'none',
|
42
|
-
|
43
|
+
vdom: {tag: 'p'},
|
44
|
+
html: [
|
45
|
+
'This is similar to the Helix demo — 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
|
+
flex: 'none',
|
51
|
+
html: 'But the demo differs from the helix example because the data is provided via a <i>socket</i>.',
|
52
|
+
vdom: {tag: 'p'}
|
53
|
+
}, {
|
54
|
+
flex: 'none',
|
55
|
+
vdom: {tag: 'p'},
|
56
|
+
html: [
|
57
|
+
'Neo.mjs uniquely fits the bill for applications that need real-time visualizations of real-time data, such as',
|
58
|
+
'stock market trading data and medical or scientific telemetry.'
|
59
|
+
].join('')
|
43
60
|
}]
|
44
61
|
}, {
|
45
62
|
module: Container,
|
46
63
|
flex : '2',
|
47
|
-
style : {background: '
|
64
|
+
style : {background: 'lightgray', padding: '20px'},
|
48
65
|
layout: {ntype: 'vbox', align: 'stretch', pack: 'center'},
|
49
66
|
items : [{
|
50
|
-
module
|
51
|
-
|
52
|
-
|
53
|
-
|
67
|
+
module : LivePreview,
|
68
|
+
cls : ['page-live-preview'],
|
69
|
+
height : '100%',
|
70
|
+
reference: 'live-preview',
|
54
71
|
|
55
72
|
value: [
|
56
73
|
"import Viewport from '../../../../apps/colors/view/Viewport.mjs';",
|
@@ -67,6 +84,13 @@ class Colors extends Container {
|
|
67
84
|
}]
|
68
85
|
}]
|
69
86
|
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
*
|
90
|
+
*/
|
91
|
+
activate() {
|
92
|
+
this.getReference('live-preview').activeView = 'preview'
|
93
|
+
}
|
70
94
|
}
|
71
95
|
|
72
96
|
Neo.setupClass(Colors);
|
@@ -12,14 +12,17 @@ class Helix extends Container {
|
|
12
12
|
* @protected
|
13
13
|
*/
|
14
14
|
className: 'Portal.view.home.parts.Helix',
|
15
|
-
|
15
|
+
/**
|
16
|
+
* @member {String[]} cls=['page','cool-stuff']
|
17
|
+
*/
|
16
18
|
cls: ['page', 'cool-stuff'],
|
17
|
-
|
19
|
+
/**
|
20
|
+
* @member {Object} responsive
|
21
|
+
*/
|
18
22
|
responsive: {
|
19
23
|
medium: {layout: {ntype: 'vbox', align: 'stretch', pack: 'center'}},
|
20
24
|
large : {layout: {ntype: 'hbox', align: 'stretch', pack: 'center'}}
|
21
25
|
},
|
22
|
-
|
23
26
|
/**
|
24
27
|
* @member {Object[]} items
|
25
28
|
*/
|
@@ -31,26 +34,55 @@ class Helix extends Container {
|
|
31
34
|
items : [{
|
32
35
|
cls : 'neo-h1',
|
33
36
|
flex: 'none',
|
34
|
-
html: '
|
37
|
+
html: 'Extreme Speed',
|
38
|
+
vdom: {tag: 'h1'}
|
35
39
|
}, {
|
36
40
|
cls : 'neo-h2',
|
37
41
|
flex: 'none',
|
38
|
-
html: '
|
42
|
+
html: '40,000 Updates /s',
|
43
|
+
vdom: {tag: 'h2'}
|
39
44
|
}, {
|
40
|
-
cls : 'neo-
|
45
|
+
cls : 'neo-h3',
|
41
46
|
flex: 'none',
|
42
|
-
|
47
|
+
vdom: {tag: 'p'},
|
48
|
+
|
49
|
+
html: [
|
50
|
+
'This demo shows the Neo.mjs helix component, along with a "Helix Controls" panel. ',
|
51
|
+
'Move your cursor over the helix, then rapidly scroll left and right to rotate, and up and down to zoom. ',
|
52
|
+
'As you do, look at the delta updates counter at the top. ',
|
53
|
+
'Neo.mjs easily handles 40,000 updates per second, and beyond.'
|
54
|
+
].join('')
|
55
|
+
}, {
|
56
|
+
cls : 'neo-h1',
|
57
|
+
flex: 'none',
|
58
|
+
html: 'Multi-Window',
|
59
|
+
vdom: {tag: 'h1'}
|
60
|
+
}, {
|
61
|
+
cls : 'neo-h2',
|
62
|
+
flex: 'none',
|
63
|
+
html: 'Seamless and Simple',
|
64
|
+
vdom: {tag: 'h2'}
|
65
|
+
}, {
|
66
|
+
cls : 'neo-h3',
|
67
|
+
flex: 'none',
|
68
|
+
vdom: {tag: 'p'},
|
69
|
+
|
70
|
+
html: [
|
71
|
+
'Click on the small window icon in the Helix Controls title bar and the controls open in their own window ',
|
72
|
+
'which can be moved to a separate monitor. But the application logic doesn\'t care — ',
|
73
|
+
'the logic updates the controls just like before, and framework seamlessly handles updating the DOM across windows.'
|
74
|
+
].join('')
|
43
75
|
}]
|
44
76
|
}, {
|
45
77
|
module: Container,
|
46
78
|
flex : '2',
|
47
|
-
style : {background: '
|
79
|
+
style : {background: 'lightgray', padding: '20px'},
|
48
80
|
layout: {ntype: 'vbox', align: 'stretch', pack: 'center'},
|
49
81
|
items : [{
|
50
|
-
module
|
51
|
-
|
52
|
-
|
53
|
-
|
82
|
+
module : LivePreview,
|
83
|
+
cls : ['page-live-preview'],
|
84
|
+
height : '100%',
|
85
|
+
reference: 'live-preview',
|
54
86
|
|
55
87
|
value: [
|
56
88
|
"import Viewport from '../../../../examples/component/multiWindowHelix/Viewport.mjs';",
|
@@ -68,6 +100,13 @@ class Helix extends Container {
|
|
68
100
|
}]
|
69
101
|
}]
|
70
102
|
}
|
103
|
+
|
104
|
+
/**
|
105
|
+
*
|
106
|
+
*/
|
107
|
+
activate() {
|
108
|
+
this.getReference('live-preview').activeView = 'preview'
|
109
|
+
}
|
71
110
|
}
|
72
111
|
|
73
112
|
Neo.setupClass(Helix);
|
@@ -44,15 +44,18 @@ class HelloWorld extends Container {
|
|
44
44
|
cls : 'neo-h1',
|
45
45
|
id : 'neo-hello-world-h1',
|
46
46
|
flex: 'none',
|
47
|
-
html: 'Hello World'
|
47
|
+
html: 'Hello World',
|
48
|
+
vdom: {tag: 'h1'}
|
48
49
|
}, {
|
49
50
|
cls : 'neo-h2',
|
50
51
|
flex: 'none',
|
51
|
-
html: 'Your first code snippet'
|
52
|
+
html: 'Your first code snippet',
|
53
|
+
vdom: {tag: 'h2'}
|
52
54
|
}, {
|
53
55
|
cls : 'neo-content',
|
54
56
|
flex: 'none',
|
55
|
-
html: 'If you understand these lines, you are ready to start with Neo.mjs'
|
57
|
+
html: 'If you understand these lines, you are ready to start with Neo.mjs',
|
58
|
+
vdom: {tag: 'p'}
|
56
59
|
}]
|
57
60
|
}, {
|
58
61
|
module: LivePreviewContainer,
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import Container from '../../../../../src/container/Base.mjs';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @class Portal.view.home.parts.How
|
5
|
+
* @extends Neo.container.Base
|
6
|
+
*/
|
7
|
+
class How extends Container {
|
8
|
+
static config = {
|
9
|
+
className: 'Portal.view.home.parts.How',
|
10
|
+
/**
|
11
|
+
* @member {String[]} cls=['page','cool-stuff']
|
12
|
+
*/
|
13
|
+
cls: ['page', 'cool-stuff'],
|
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
|
+
module: 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
|
+
module: 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;
|
@@ -13,7 +13,7 @@ class MainNeo extends Container {
|
|
13
13
|
*/
|
14
14
|
className: 'Portal.view.home.parts.MainNeo',
|
15
15
|
|
16
|
-
cls: ['page', '
|
16
|
+
cls: ['page', 'portal-home-main-neo'],
|
17
17
|
|
18
18
|
layout: {ntype: 'vbox', align: 'center', pack: 'center'},
|
19
19
|
/**
|
@@ -24,9 +24,10 @@ class MainNeo extends Container {
|
|
24
24
|
cls : ['vector'],
|
25
25
|
flex : 'none',
|
26
26
|
}, {
|
27
|
-
cls : 'neo-h1',
|
27
|
+
cls : ['neo-h1'],
|
28
28
|
flex: 'none',
|
29
|
-
html: 'The High-Performance Web Framework for Next Generation Interfaces'
|
29
|
+
html: 'The High-Performance Web Framework for Next Generation Interfaces',
|
30
|
+
vdom: {tag: 'h1'}
|
30
31
|
}, {
|
31
32
|
module: Container,
|
32
33
|
cls : ['button-group'],
|
package/package.json
CHANGED
@@ -53,27 +53,31 @@ A `Neo.controller.Component` is a simple class associated with a component class
|
|
53
53
|
instance of its associated controller is automatically created.
|
54
54
|
|
55
55
|
<pre data-neo>
|
56
|
-
import
|
57
|
-
import Controller from '../../../../src/controller/Component.mjs';
|
58
|
-
import TextField from '../../../../src/form/field/Text.mjs';
|
56
|
+
import Base from '../../../../src/controller/Component.mjs';
|
59
57
|
|
60
|
-
class MainViewController extends
|
58
|
+
class MainViewController extends Base {
|
61
59
|
static config = {
|
62
|
-
className: 'Example.view.MainViewController'
|
60
|
+
className: 'Example.view.MainViewController',
|
63
61
|
}
|
64
62
|
onChange(data) {
|
65
|
-
Neo.Main.log({value: data.value})
|
63
|
+
Neo.Main.log({value: data.value});
|
66
64
|
}
|
65
|
+
|
67
66
|
}
|
68
67
|
Neo.setupClass(MainViewController);
|
69
68
|
|
70
69
|
|
70
|
+
import Container from '../../../../src/container/Base.mjs';
|
71
|
+
import TextField from '../../../../src/form/field/Text.mjs';
|
72
|
+
|
71
73
|
class MainView extends Container {
|
72
74
|
static config = {
|
73
|
-
|
75
|
+
|
74
76
|
controller: MainViewController,
|
75
|
-
|
76
|
-
|
77
|
+
className: 'Example.view.MainView',
|
78
|
+
|
79
|
+
layout : {ntype:'vbox', align:'start'},
|
80
|
+
items: [{
|
77
81
|
module : TextField,
|
78
82
|
labelText: 'Name',
|
79
83
|
listeners: {
|
@@ -85,6 +89,8 @@ class MainView extends Container {
|
|
85
89
|
Neo.setupClass(MainView);
|
86
90
|
</pre>
|
87
91
|
|
92
|
+
|
93
|
+
|
88
94
|
(It's important to keep in mind that in Neo.mjs, all class definitions are coded in their own
|
89
95
|
source file: one class per file. In the examples we're putting all the relevant classes together
|
90
96
|
to make it easier to see the source code for every class being used. But in an
|
@@ -1,4 +1,4 @@
|
|
1
|
-
As you read in the Getting Started > Events topic, components, stores, and many other objects fire events.
|
1
|
+
As you read in the <a href="#/learn/Events">Getting Started > Events</a> topic, components, stores, and many other objects fire events.
|
2
2
|
|
3
3
|
|
4
4
|
<pre data-neo>
|
@@ -32,12 +32,12 @@ Neo.setupClass(MainView);
|
|
32
32
|
|
33
33
|
### In-line
|
34
34
|
|
35
|
-
The event listener function can be coded in-line. Normally
|
36
|
-
but for very simple situation it can be convenient to use this syntax.
|
35
|
+
The event listener function can be coded in-line. Normally you want event handlers to be in a view's
|
36
|
+
controller, but for very simple situation it can be convenient to use this syntax.
|
37
37
|
|
38
38
|
<pre data-neo>
|
39
39
|
import Container from '../../../../src/container/Base.mjs';
|
40
|
-
import
|
40
|
+
import TextField from '../../../../src/form/field/Text.mjs';
|
41
41
|
|
42
42
|
class MainView extends Container {
|
43
43
|
static config = {
|
@@ -45,10 +45,10 @@ class MainView extends Container {
|
|
45
45
|
layout : {ntype:'vbox', align:'start'},
|
46
46
|
|
47
47
|
items: [{
|
48
|
-
module :
|
49
|
-
|
50
|
-
listeners: {
|
51
|
-
|
48
|
+
module : TextField,
|
49
|
+
labelText: 'Name',
|
50
|
+
listeners: {
|
51
|
+
change: data => Neo.Main.log({value:data.value})
|
52
52
|
}
|
53
53
|
}]
|
54
54
|
}
|
@@ -59,12 +59,12 @@ Neo.setupClass(MainView);
|
|
59
59
|
### As a view method
|
60
60
|
|
61
61
|
You can also use the `up.` qualifier to specify a method in the component's parent view. Like the
|
62
|
-
in-line syntax above, using `up.` might be convenient for simple
|
63
|
-
simply haven't gotten around to
|
62
|
+
in-line syntax you saw above, using the `up.` syntax might be convenient for simple classees,
|
63
|
+
or when you simply haven't gotten around to defining a view's controller.
|
64
64
|
|
65
65
|
<pre data-neo>
|
66
66
|
import Container from '../../../../src/container/Base.mjs';
|
67
|
-
import
|
67
|
+
import TextField from '../../../../src/form/field/Text.mjs';
|
68
68
|
|
69
69
|
class MainView extends Container {
|
70
70
|
static config = {
|
@@ -72,16 +72,15 @@ class MainView extends Container {
|
|
72
72
|
layout : {ntype:'vbox', align:'start'},
|
73
73
|
|
74
74
|
items: [{
|
75
|
-
module :
|
76
|
-
|
77
|
-
listeners: {
|
78
|
-
|
75
|
+
module : TextField,
|
76
|
+
labelText: 'Name',
|
77
|
+
listeners: {
|
78
|
+
change: 'up.foo'
|
79
79
|
}
|
80
80
|
}]
|
81
81
|
}
|
82
|
-
|
83
|
-
|
84
|
-
Neo.Main.log(arguments);
|
82
|
+
foo(data){
|
83
|
+
Neo.Main.log({value:data.value})
|
85
84
|
}
|
86
85
|
}
|
87
86
|
Neo.setupClass(MainView);
|
@@ -89,12 +88,136 @@ Neo.setupClass(MainView);
|
|
89
88
|
|
90
89
|
### As a controller method
|
91
90
|
|
91
|
+
Despite the examples above, the most correct way of setting up event handlers is to use a controller.
|
92
|
+
Any view class can specify a controller — wWhen the view is created a controller instance is
|
93
|
+
also created.
|
94
|
+
|
95
|
+
<pre data-neo>
|
96
|
+
import Controller from '../../../../src/controller/Component.mjs';
|
97
|
+
|
98
|
+
class MainViewController extends Controller {
|
99
|
+
static config = {
|
100
|
+
className: 'Example.view.MainViewController'
|
101
|
+
}
|
102
|
+
foo(data){
|
103
|
+
Neo.Main.log({value:data.value})
|
104
|
+
}
|
105
|
+
}
|
106
|
+
Neo.setupClass(MainViewController);
|
107
|
+
|
108
|
+
|
109
|
+
import Container from '../../../../src/container/Base.mjs';
|
110
|
+
import TextField from '../../../../src/form/field/Text.mjs';
|
111
|
+
|
112
|
+
class MainView extends Container {
|
113
|
+
static config = {
|
114
|
+
controller: {
|
115
|
+
module: MainViewController
|
116
|
+
},
|
117
|
+
className: 'Example.view.MainView',
|
118
|
+
layout : {ntype:'vbox', align:'start'},
|
119
|
+
|
120
|
+
items: [{
|
121
|
+
module : TextField,
|
122
|
+
labelText: 'Name',
|
123
|
+
listeners: {
|
124
|
+
change: 'foo'
|
125
|
+
}
|
126
|
+
}]
|
127
|
+
}
|
128
|
+
}
|
129
|
+
Neo.setupClass(MainView);
|
130
|
+
</pre>
|
131
|
+
|
92
132
|
## Adding listeners procedurally
|
93
133
|
|
94
134
|
Event listeners are normally specified declaratively, via the `listeners: {}` config. But occasionally you need to add
|
95
135
|
a listener proccedurally.
|
96
136
|
|
97
|
-
Any obversable class has an `addListener` method
|
137
|
+
Any obversable class has an `addListener` method, along with an easier-to-type version called `on`.
|
138
|
+
|
139
|
+
<pre data-neo>
|
140
|
+
import Controller from '../../../../src/controller/Component.mjs';
|
141
|
+
|
142
|
+
class MainViewController extends Controller {
|
143
|
+
static config = {
|
144
|
+
className: 'Example.view.MainViewController'
|
145
|
+
}
|
146
|
+
foo(data){
|
147
|
+
Neo.Main.log({value:data.value})
|
148
|
+
}
|
149
|
+
onComponentConstructed(){
|
150
|
+
debugger
|
151
|
+
}
|
152
|
+
}
|
153
|
+
Neo.setupClass(MainViewController);
|
154
|
+
|
155
|
+
|
156
|
+
import Container from '../../../../src/container/Base.mjs';
|
157
|
+
import TextField from '../../../../src/form/field/Text.mjs';
|
158
|
+
|
159
|
+
class MainView extends Container {
|
160
|
+
static config = {
|
161
|
+
controller: {
|
162
|
+
module: MainViewController
|
163
|
+
},
|
164
|
+
className: 'Example.view.MainView',
|
165
|
+
layout : {ntype:'vbox', align:'start'},
|
166
|
+
|
167
|
+
items: [{
|
168
|
+
module : TextField,
|
169
|
+
labelText: 'Name',
|
170
|
+
listeners: {
|
171
|
+
change: 'foo'
|
172
|
+
}
|
173
|
+
}]
|
174
|
+
}
|
175
|
+
}
|
176
|
+
Neo.setupClass(MainView);
|
177
|
+
</pre>
|
178
|
+
|
179
|
+
The method specified in `on()` doesn't have to be an arrow function; you can use a controller function.
|
180
|
+
|
181
|
+
<pre data-neo>
|
182
|
+
import Controller from '../../../../src/controller/Component.mjs';
|
183
|
+
|
184
|
+
class MainViewController extends Controller {
|
185
|
+
static config = {
|
186
|
+
className: 'Example.view.MainViewController'
|
187
|
+
}
|
188
|
+
foo(data){
|
189
|
+
Neo.Main.log('foo' + {value:data.value}
|
190
|
+
}
|
191
|
+
|
192
|
+
// This is a controller lifecycle method run after the controller's view has been constructed
|
193
|
+
onComponentConstructed(){
|
194
|
+
// Note the use of this.getReference() -- that's used to get a component reference with the specified name
|
195
|
+
this.getReference('nameTextfield').on('change', this.foo, this)
|
196
|
+
}
|
197
|
+
}
|
198
|
+
Neo.setupClass(MainViewController);
|
199
|
+
|
200
|
+
|
201
|
+
import Container from '../../../../src/container/Base.mjs';
|
202
|
+
import TextField from '../../../../src/form/field/Text.mjs';
|
203
|
+
|
204
|
+
class MainView extends Container {
|
205
|
+
static config = {
|
206
|
+
controller: {
|
207
|
+
module: MainViewController
|
208
|
+
},
|
209
|
+
className: 'Example.view.MainView',
|
210
|
+
layout : {ntype:'vbox', align:'start'},
|
211
|
+
|
212
|
+
items: [{
|
213
|
+
module : TextField,
|
214
|
+
reference: 'nameTextfield', // This component can be fetched using this.getReference('nameTextfield')
|
215
|
+
labelText: 'Name'
|
216
|
+
}]
|
217
|
+
}
|
218
|
+
}
|
219
|
+
Neo.setupClass(MainView);
|
220
|
+
</pre>
|
98
221
|
|
99
222
|
|
100
223
|
|
@@ -1,55 +1,54 @@
|
|
1
1
|
.learnneo-header-toolbar {
|
2
|
-
|
2
|
+
border-bottom: 1px solid #f2f2f2;
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
}
|
7
|
-
|
8
|
-
.neo-button {
|
9
|
-
margin-left: 10px;
|
10
|
-
|
11
|
-
&.no-text {
|
12
|
-
margin-left: 0;
|
13
|
-
width: 1.2em;
|
14
|
-
|
15
|
-
&.github-button {
|
16
|
-
margin-left: 5em;
|
17
|
-
}
|
18
|
-
|
19
|
-
.neo-button-glyph {
|
20
|
-
font-size: 24px;
|
21
|
-
}
|
4
|
+
.logo {
|
5
|
+
margin-left: 1em;
|
22
6
|
}
|
23
7
|
|
24
|
-
.neo-button
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
8
|
+
.neo-button {
|
9
|
+
margin-left: 10px;
|
10
|
+
|
11
|
+
&.no-text {
|
12
|
+
margin-left: 0;
|
13
|
+
width : 1.2em;
|
14
|
+
|
15
|
+
&.github-button {
|
16
|
+
margin-left: 5em;
|
17
|
+
}
|
18
|
+
|
19
|
+
.neo-button-glyph {
|
20
|
+
font-size: 24px;
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
.neo-button-glyph {
|
25
|
+
&.neo-logo-blue {
|
26
|
+
background-image: url("../../../../../../resources/images/logo/neo_logo_primary.svg");
|
27
|
+
height : 24px;
|
28
|
+
width : 24px;
|
29
|
+
}
|
30
|
+
}
|
30
31
|
}
|
31
|
-
}
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
}
|
33
|
+
.separate-bar {
|
34
|
+
animation: fade-in-animation 200ms linear;
|
35
|
+
position: absolute;
|
36
|
+
right : 20px;
|
37
|
+
top : 60px;
|
38
|
+
transform: rotate(0);
|
39
|
+
width : 40px;
|
40
|
+
z-index : 9;
|
41
|
+
}
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
// find parallel class hide-sidebar
|
44
|
+
&:has(+div .hide-sidebar) .separate-bar {
|
45
|
+
animation: fade-animation 200ms linear forwards;
|
46
|
+
}
|
48
47
|
}
|
49
48
|
|
50
49
|
.vector {
|
51
|
-
|
52
|
-
|
50
|
+
animation: fade-and-scale-animation auto linear;
|
51
|
+
animation-timeline: --page-scroll;
|
53
52
|
}
|
54
53
|
|
55
54
|
//@scroll-timeline --page-scroll {
|
@@ -61,70 +60,71 @@
|
|
61
60
|
|
62
61
|
/* Style and position the progress bar */
|
63
62
|
#progress {
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
63
|
+
position: fixed;
|
64
|
+
z-index: 1000;
|
65
|
+
top: 0;
|
66
|
+
height: 2px;
|
67
|
+
width: 100%;
|
68
|
+
background: var(--button-background-color);
|
69
|
+
background: var(--sem-color-surface-primary-background);
|
71
70
|
|
72
|
-
|
73
|
-
|
71
|
+
scale: 0 1;
|
72
|
+
transform-origin: left;
|
74
73
|
|
75
|
-
|
76
|
-
|
77
|
-
|
74
|
+
/* Attach the animation using an anonymous Scroll Progress Timeline */
|
75
|
+
animation: grow-progress linear;
|
76
|
+
animation-timeline: --page-scroll;
|
78
77
|
}
|
79
78
|
|
80
79
|
@keyframes grow-progress {
|
81
|
-
|
80
|
+
to {
|
81
|
+
scale: 1 1;
|
82
|
+
}
|
82
83
|
}
|
83
84
|
|
84
85
|
.hello-world {
|
85
|
-
|
86
|
+
animation-timeline: view(block 100% -500%);
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
88
|
+
animation-name: appear-animation;
|
89
|
+
animation-fill-mode: both;
|
90
|
+
animation-duration: 1ms; /* Firefox requires this to apply the animation */
|
91
|
+
animation-timing-function: linear;
|
91
92
|
}
|
92
93
|
|
93
94
|
@keyframes appear-animation {
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
95
|
+
0% {
|
96
|
+
transform: translateX(-400%);
|
97
|
+
opacity : 0;
|
98
|
+
}
|
99
|
+
90% {
|
100
|
+
opacity: .3;
|
101
|
+
}
|
102
|
+
100% {
|
103
|
+
transform: translateX(0);
|
104
|
+
opacity : 1;
|
105
|
+
}
|
105
106
|
}
|
106
107
|
|
107
108
|
.cool-stuff {
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
animation-timing-function: linear;
|
109
|
+
animation-timeline : view(block 100% -500%);
|
110
|
+
animation-name : appear-cool-stuff;
|
111
|
+
animation-fill-mode : both;
|
112
|
+
animation-duration : 1ms; /* Firefox requires this to apply the animation */
|
113
|
+
animation-timing-function: linear;
|
114
114
|
}
|
115
115
|
|
116
116
|
@keyframes appear-cool-stuff {
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
117
|
+
0% {
|
118
|
+
transform: translateX(400%);
|
119
|
+
opacity : 0;
|
120
|
+
}
|
121
|
+
90% {
|
122
|
+
opacity: .3;
|
123
|
+
}
|
124
|
+
100% {
|
125
|
+
transform: translateX(0);
|
126
|
+
opacity : 1;
|
127
|
+
}
|
128
128
|
}
|
129
129
|
|
130
130
|
|
@@ -133,65 +133,83 @@
|
|
133
133
|
//}
|
134
134
|
|
135
135
|
.portal-home-maincontainer {
|
136
|
-
|
136
|
+
scroll-timeline: --page-scroll block;
|
137
137
|
}
|
138
138
|
|
139
139
|
@keyframes rotateAnimation {
|
140
|
-
|
141
|
-
|
140
|
+
from {
|
141
|
+
transform: rotate(0deg);
|
142
|
+
}
|
143
|
+
to {
|
144
|
+
transform: rotate(360deg);
|
145
|
+
}
|
142
146
|
}
|
143
147
|
|
144
148
|
@keyframes fade-and-scale-animation {
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
149
|
+
0% {
|
150
|
+
opacity : 1;
|
151
|
+
transform: scale(1);
|
152
|
+
}
|
153
|
+
12%, 100% {
|
154
|
+
opacity : 0;
|
155
|
+
transform: scale(1.5);
|
156
|
+
}
|
153
157
|
}
|
154
158
|
|
155
159
|
@keyframes fade-in-animation {
|
156
|
-
|
157
|
-
|
160
|
+
from {
|
161
|
+
opacity: 0;
|
162
|
+
right : -10px
|
163
|
+
}
|
164
|
+
to {
|
165
|
+
opacity: 1;
|
166
|
+
right : 20px;
|
167
|
+
}
|
158
168
|
}
|
169
|
+
|
159
170
|
@keyframes fade-animation {
|
160
|
-
|
161
|
-
|
171
|
+
from {
|
172
|
+
opacity: 1;
|
173
|
+
right : 20px;
|
174
|
+
}
|
175
|
+
to {
|
176
|
+
opacity: 0;
|
177
|
+
right : -10px
|
178
|
+
}
|
162
179
|
}
|
163
180
|
|
164
181
|
.button-group {
|
165
|
-
|
182
|
+
overflow: visible;
|
166
183
|
}
|
167
184
|
|
168
185
|
.get-started-button {
|
169
|
-
|
170
|
-
|
186
|
+
opacity : 0;
|
187
|
+
animation: show-get-started-button 400ms 1300ms linear forwards;
|
171
188
|
}
|
172
189
|
|
173
190
|
.neo-github {
|
174
|
-
|
175
|
-
|
191
|
+
opacity : 0;
|
192
|
+
animation: show-github-button 600ms 1150ms linear forwards;
|
176
193
|
}
|
177
194
|
|
178
195
|
@keyframes show-get-started-button {
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
196
|
+
from {
|
197
|
+
opacity : 0;
|
198
|
+
transform: translate(70px, 30px);
|
199
|
+
}
|
200
|
+
to {
|
201
|
+
opacity : 1;
|
202
|
+
transform: translate(0, 0);
|
203
|
+
}
|
187
204
|
}
|
205
|
+
|
188
206
|
@keyframes show-github-button {
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
207
|
+
from {
|
208
|
+
opacity : 0;
|
209
|
+
transform: translate(-70px, 50px);
|
210
|
+
}
|
211
|
+
to {
|
212
|
+
opacity : 1;
|
213
|
+
transform: translate(0, 0);
|
214
|
+
}
|
197
215
|
}
|
@@ -9,11 +9,17 @@
|
|
9
9
|
|
10
10
|
.neo-h1 {
|
11
11
|
font-size: min(max(5.5vw, 30px), 64px);
|
12
|
+
text-align : center;
|
13
|
+
margin : 0;
|
14
|
+
line-height : 1em;
|
12
15
|
}
|
13
16
|
|
14
17
|
.neo-h2 {
|
15
18
|
font-size: min(max(3.5vw, 24px), 44px);
|
16
|
-
|
19
|
+
text-align : center;
|
20
|
+
margin : 0;
|
21
|
+
line-height : 1em;
|
22
|
+
}
|
17
23
|
|
18
24
|
.neo-content {
|
19
25
|
font-size: min(max(2.3vw, 16px), 30px);
|
@@ -24,27 +30,8 @@
|
|
24
30
|
}
|
25
31
|
}
|
26
32
|
|
27
|
-
.button-group {
|
28
|
-
display : flex !important;
|
29
|
-
flex-direction: row-reverse !important;
|
30
|
-
gap : 8px !important;
|
31
|
-
}
|
32
|
-
|
33
33
|
.neo-h1 {
|
34
|
-
font-size
|
35
|
-
font-weight
|
36
|
-
text-align : center;
|
37
|
-
margin-bottom: 1.25em;
|
38
|
-
}
|
39
|
-
|
40
|
-
.vector {
|
41
|
-
background-image : url("../../../../../../../resources/images/logo/neo_logo_text_primary.svg");
|
42
|
-
background-position: center center;
|
43
|
-
background-repeat : no-repeat;
|
44
|
-
background-size : contain;
|
45
|
-
height : 10vW;
|
46
|
-
margin : 0 0 3rem 0;
|
47
|
-
max-height : 130px;
|
48
|
-
width : 100%;
|
34
|
+
font-size : 32px;
|
35
|
+
font-weight: 600;
|
49
36
|
}
|
50
37
|
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
.portal-home-main-neo.page {
|
2
|
+
.button-group {
|
3
|
+
display : flex !important;
|
4
|
+
flex-direction: row-reverse !important;
|
5
|
+
gap : 8px !important;
|
6
|
+
}
|
7
|
+
|
8
|
+
.neo-h1 {
|
9
|
+
margin-bottom: 1.25em;
|
10
|
+
}
|
11
|
+
|
12
|
+
.vector {
|
13
|
+
background-image : url("../../../../../../../../resources/images/logo/neo_logo_text_primary.svg");
|
14
|
+
background-position: center center;
|
15
|
+
background-repeat : no-repeat;
|
16
|
+
background-size : contain;
|
17
|
+
height : 10vW;
|
18
|
+
margin : 0 0 3rem 0;
|
19
|
+
max-height : 130px;
|
20
|
+
width : 100%;
|
21
|
+
}
|
22
|
+
}
|
package/src/DefaultConfig.mjs
CHANGED
@@ -260,12 +260,12 @@ const DefaultConfig = {
|
|
260
260
|
useVdomWorker: true,
|
261
261
|
/**
|
262
262
|
* buildScripts/injectPackageVersion.mjs will update this value
|
263
|
-
* @default '6.18.
|
263
|
+
* @default '6.18.1'
|
264
264
|
* @memberOf! module:Neo
|
265
265
|
* @name config.version
|
266
266
|
* @type String
|
267
267
|
*/
|
268
|
-
version: '6.18.
|
268
|
+
version: '6.18.1'
|
269
269
|
};
|
270
270
|
|
271
271
|
Object.assign(DefaultConfig, {
|
package/src/component/Base.mjs
CHANGED
@@ -13,8 +13,10 @@ import VDomUtil from '../util/VDom.mjs';
|
|
13
13
|
import VNodeUtil from '../util/VNode.mjs';
|
14
14
|
|
15
15
|
const
|
16
|
-
|
17
|
-
|
16
|
+
addUnits = value => value == null ? value : isNaN(value) ? value : `${value}px`,
|
17
|
+
closestController = Symbol.for('closestController'),
|
18
|
+
closestModel = Symbol.for('closestModel'),
|
19
|
+
lengthRE = /^\d+\w+$/;
|
18
20
|
|
19
21
|
/**
|
20
22
|
* @class Neo.component.Base
|
@@ -577,9 +579,11 @@ class Base extends CoreBase {
|
|
577
579
|
afterSetDomListeners(value, oldValue) {
|
578
580
|
let me = this;
|
579
581
|
|
580
|
-
|
582
|
+
if (value?.[0] || oldValue?.[0]) {
|
583
|
+
me.getController()?.parseDomListeners(me);
|
581
584
|
|
582
|
-
|
585
|
+
DomEventManager.updateDomListeners(me, value, oldValue)
|
586
|
+
}
|
583
587
|
}
|
584
588
|
|
585
589
|
/**
|
@@ -1240,7 +1244,7 @@ class Base extends CoreBase {
|
|
1240
1244
|
* Creates a KeyNavigation instance if needed.
|
1241
1245
|
* @param {Object} value
|
1242
1246
|
* @param {Object} oldValue
|
1243
|
-
* @returns {Neo.util.KeyNavigation}
|
1247
|
+
* @returns {Neo.util.KeyNavigation|null}
|
1244
1248
|
* @protected
|
1245
1249
|
*/
|
1246
1250
|
beforeSetKeys(value, oldValue) {
|
@@ -1503,10 +1507,10 @@ class Base extends CoreBase {
|
|
1503
1507
|
const result = [];
|
1504
1508
|
|
1505
1509
|
if (this.floating) {
|
1506
|
-
result.push('neo-floating')
|
1510
|
+
result.push('neo-floating')
|
1507
1511
|
}
|
1508
1512
|
|
1509
|
-
return result
|
1513
|
+
return result
|
1510
1514
|
}
|
1511
1515
|
|
1512
1516
|
/**
|
@@ -1543,7 +1547,24 @@ class Base extends CoreBase {
|
|
1543
1547
|
* @returns {Neo.controller.Component|null}
|
1544
1548
|
*/
|
1545
1549
|
getController(ntype) {
|
1546
|
-
|
1550
|
+
let me = this,
|
1551
|
+
controller;
|
1552
|
+
|
1553
|
+
if (!ntype) {
|
1554
|
+
controller = me[closestController];
|
1555
|
+
|
1556
|
+
if (controller) {
|
1557
|
+
return controller
|
1558
|
+
}
|
1559
|
+
}
|
1560
|
+
|
1561
|
+
controller = me.getConfigInstanceByNtype('controller', ntype);
|
1562
|
+
|
1563
|
+
if (!ntype) {
|
1564
|
+
me[closestController] = controller;
|
1565
|
+
}
|
1566
|
+
|
1567
|
+
return controller
|
1547
1568
|
}
|
1548
1569
|
|
1549
1570
|
/**
|
@@ -1553,7 +1574,7 @@ class Base extends CoreBase {
|
|
1553
1574
|
* @returns {Promise<Neo.util.Rectangle>}
|
1554
1575
|
*/
|
1555
1576
|
async getDomRect(id=this.id, appName=this.appName) {
|
1556
|
-
|
1577
|
+
let result = await Neo.main.DomAccess.getBoundingClientRect({appName, id, windowId: this.windowId});
|
1557
1578
|
|
1558
1579
|
if (Array.isArray(result)) {
|
1559
1580
|
return result.map(rect => Rectangle.clone(rect))
|
@@ -1572,7 +1593,24 @@ class Base extends CoreBase {
|
|
1572
1593
|
return null
|
1573
1594
|
}
|
1574
1595
|
|
1575
|
-
|
1596
|
+
let me = this,
|
1597
|
+
model;
|
1598
|
+
|
1599
|
+
if (!ntype) {
|
1600
|
+
model = me[closestModel];
|
1601
|
+
|
1602
|
+
if (model) {
|
1603
|
+
return model
|
1604
|
+
}
|
1605
|
+
}
|
1606
|
+
|
1607
|
+
model = me.getConfigInstanceByNtype('model', ntype);
|
1608
|
+
|
1609
|
+
if (!ntype) {
|
1610
|
+
me[closestModel] = model
|
1611
|
+
}
|
1612
|
+
|
1613
|
+
return model
|
1576
1614
|
}
|
1577
1615
|
|
1578
1616
|
/**
|
package/src/core/Observable.mjs
CHANGED
@@ -33,12 +33,28 @@ class Observable extends Base {
|
|
33
33
|
* @returns {String|null} eventId null in case an object gets passed as the name (multiple ids)
|
34
34
|
*/
|
35
35
|
addListener(name, opts, scope, eventId, data, order) {
|
36
|
-
let me
|
37
|
-
delay
|
38
|
-
|
39
|
-
|
36
|
+
let me = this,
|
37
|
+
delay = 0,
|
38
|
+
eventIdObject = typeof eventId === 'object',
|
39
|
+
nameObject = typeof name === 'object',
|
40
|
+
once = false,
|
41
|
+
optsType = typeof opts,
|
40
42
|
listener, existing, eventConfig;
|
41
43
|
|
44
|
+
/*
|
45
|
+
* let us support the following format too:
|
46
|
+
*
|
47
|
+
* currentWorker.on('connected', () => {
|
48
|
+
* Base.sendRemotes(className, remote)
|
49
|
+
* }, me, {once: true})
|
50
|
+
*/
|
51
|
+
if (eventIdObject && optsType === 'function') {
|
52
|
+
eventId.fn = opts;
|
53
|
+
opts = eventId;
|
54
|
+
optsType = 'object';
|
55
|
+
eventId = null;
|
56
|
+
}
|
57
|
+
|
42
58
|
if (nameObject) {
|
43
59
|
if (name.hasOwnProperty('delay')) {
|
44
60
|
delay = name.delay;
|
@@ -62,16 +78,16 @@ class Observable extends Base {
|
|
62
78
|
me.addListener(key, {delay, fn: value, once, scope})
|
63
79
|
}
|
64
80
|
})
|
65
|
-
} else if (
|
81
|
+
} else if (optsType === 'object') {
|
66
82
|
delay = delay || opts.delay;
|
67
83
|
eventId = eventId || opts.eventId;
|
68
84
|
listener = opts.fn;
|
69
85
|
once = once || opts.once;
|
70
86
|
order = order || opts.order;
|
71
87
|
scope = scope || opts.scope
|
72
|
-
} else if (
|
88
|
+
} else if (optsType === 'function') {
|
73
89
|
listener = opts
|
74
|
-
} else if (
|
90
|
+
} else if (optsType === 'string') {
|
75
91
|
listener = opts // VC hook, can get parsed after onConstructed in case the view uses the parent VC
|
76
92
|
} else {
|
77
93
|
throw new Error('Invalid addListener call: ' + name)
|
@@ -77,6 +77,25 @@ class NeoIntersectionObserver extends Base {
|
|
77
77
|
})
|
78
78
|
}
|
79
79
|
|
80
|
+
/**
|
81
|
+
* @param {IntersectionObserverEntry[]} entries
|
82
|
+
* @param {IntersectionObserver} observer
|
83
|
+
*/
|
84
|
+
isVisible(entries, observer) {
|
85
|
+
let me = this,
|
86
|
+
data, path, target;
|
87
|
+
|
88
|
+
entries.forEach(entry => {
|
89
|
+
target = entry.target;
|
90
|
+
data = target.dataset && {...target.dataset} || null;
|
91
|
+
path = DomEvents.getPathFromElement(entry.target).map(e => DomEvents.getTargetData(e));
|
92
|
+
|
93
|
+
if (entry.isIntersecting) {
|
94
|
+
me.sendMessage({data, id: observer.rootId, isIntersecting: true, path, targetId: target.id})
|
95
|
+
}
|
96
|
+
})
|
97
|
+
}
|
98
|
+
|
80
99
|
/**
|
81
100
|
* Add more or new items into an existing observer instance
|
82
101
|
* @param {Object} data
|
@@ -128,7 +147,7 @@ class NeoIntersectionObserver extends Base {
|
|
128
147
|
*/
|
129
148
|
register(data) {
|
130
149
|
let me = this,
|
131
|
-
cache
|
150
|
+
{cache} = me,
|
132
151
|
{id, observe} = data,
|
133
152
|
observer;
|
134
153
|
|
package/src/model/Component.mjs
CHANGED
@@ -153,12 +153,14 @@ class Component extends Base {
|
|
153
153
|
* @protected
|
154
154
|
*/
|
155
155
|
beforeSetStores(value, oldValue) {
|
156
|
-
|
156
|
+
if (value) {
|
157
|
+
let controller = this.component.getController();
|
157
158
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
159
|
+
Object.entries(value).forEach(([key, storeValue]) => {
|
160
|
+
controller?.parseConfig(storeValue);
|
161
|
+
value[key] = ClassSystemUtil.beforeSetInstance(storeValue)
|
162
|
+
})
|
163
|
+
}
|
162
164
|
|
163
165
|
return value
|
164
166
|
}
|
@@ -445,13 +447,13 @@ class Component extends Base {
|
|
445
447
|
* @returns {Neo.model.Component|null}
|
446
448
|
*/
|
447
449
|
getParent() {
|
448
|
-
let
|
450
|
+
let {parent} = this;
|
449
451
|
|
450
|
-
if (
|
451
|
-
return
|
452
|
+
if (parent) {
|
453
|
+
return parent
|
452
454
|
}
|
453
455
|
|
454
|
-
return
|
456
|
+
return this.component.parent?.getModel() || null
|
455
457
|
}
|
456
458
|
|
457
459
|
/**
|