neo.mjs 5.0.1 → 5.0.3
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/.github/CODING_GUIDELINES.md +154 -0
- package/apps/ServiceWorker.mjs +9 -13
- package/apps/covid/view/AttributionComponent.mjs +1 -1
- package/apps/covid/view/MainContainerController.mjs +4 -6
- package/apps/covid/view/country/Gallery.mjs +1 -1
- package/apps/covid/view/country/Helix.mjs +1 -1
- package/apps/sharedcovid/view/AttributionComponent.mjs +1 -1
- package/apps/sharedcovid/view/MainContainerController.mjs +4 -6
- package/apps/sharedcovid/view/country/Gallery.mjs +34 -54
- package/apps/sharedcovid/view/country/Helix.mjs +1 -1
- package/apps/website/data/blog.json +15 -2
- package/examples/ServiceWorker.mjs +9 -13
- package/examples/component/coronaGallery/CountryGallery.mjs +1 -1
- package/examples/component/coronaHelix/CountryHelix.mjs +1 -1
- package/package.json +1 -1
- package/resources/scss/src/apps/website/HeaderContainer.scss +5 -4
- package/src/DefaultConfig.mjs +2 -2
- package/src/MicroLoader.mjs +1 -1
- package/src/Neo.mjs +32 -31
- package/src/core/Base.mjs +0 -1
- package/src/grid/View.mjs +28 -0
- package/src/table/View.mjs +28 -0
- package/resources/scss/src/form/field/Radio.scss +0 -3
@@ -0,0 +1,154 @@
|
|
1
|
+
# neo.mjs Coding Guidelines
|
2
|
+
|
3
|
+
Inside the neo repo the following coding guidelines are mandatory.
|
4
|
+
They ensure a high code quality and consistency.
|
5
|
+
We strongly recommend to also stick to them when creating your own workspaces and apps via `npx neo-app`.
|
6
|
+
|
7
|
+
## Content
|
8
|
+
1. Import statements
|
9
|
+
2. Anatomy of a neo class / JS module
|
10
|
+
|
11
|
+
|
12
|
+
## 1. import statements
|
13
|
+
```javascript
|
14
|
+
import Container from '../../../node_modules/neo.mjs/src/container/Base.mjs';
|
15
|
+
import EarthquakesTable from './earthquakes/Table.mjs';
|
16
|
+
import GoogleMapsComponent from '../../../node_modules/neo.mjs/src/component/wrapper/GoogleMaps.mjs';
|
17
|
+
import Toast from '../../../node_modules/neo.mjs/src/component/Toast.mjs';
|
18
|
+
import ViewController from './MainViewController.mjs';
|
19
|
+
import ViewModel from './MainViewModel.mjs';
|
20
|
+
```
|
21
|
+
* Use block formatting. This makes it easy to spot invalid paths.
|
22
|
+
* Use single quotes.
|
23
|
+
* Imports get sorted by module name. There are ongoing discussions if we should switch to a path based sorting instead.
|
24
|
+
* Feel free to rename module import names as needed. Neo classes are using the default export.
|
25
|
+
|
26
|
+
## 2. Anatomy of a neo class / JS module
|
27
|
+
```javascript
|
28
|
+
import Component from '../component/Base.mjs';
|
29
|
+
import NeoArray from '../util/Array.mjs';
|
30
|
+
|
31
|
+
/**
|
32
|
+
* @class Neo.button.Base
|
33
|
+
* @extends Neo.component.Base
|
34
|
+
*/
|
35
|
+
class Base extends Component {
|
36
|
+
/**
|
37
|
+
* Valid values for badgePosition
|
38
|
+
* @member {String[]} badgePositions=['bottom-left','bottom-right','top-left','top-right']
|
39
|
+
* @protected
|
40
|
+
* @static
|
41
|
+
*/
|
42
|
+
static badgePositions = ['bottom-left', 'bottom-right', 'top-left', 'top-right']
|
43
|
+
/**
|
44
|
+
* Valid values for iconPosition
|
45
|
+
* @member {String[]} iconPositions=['top','right','bottom','left']
|
46
|
+
* @protected
|
47
|
+
* @static
|
48
|
+
*/
|
49
|
+
static iconPositions = ['top', 'right', 'bottom', 'left']
|
50
|
+
|
51
|
+
static config = {
|
52
|
+
/**
|
53
|
+
* @member {String} className='Neo.button.Base'
|
54
|
+
* @protected
|
55
|
+
*/
|
56
|
+
className: 'Neo.button.Base',
|
57
|
+
/**
|
58
|
+
* @member {String} ntype='button'
|
59
|
+
* @protected
|
60
|
+
*/
|
61
|
+
ntype: 'button',
|
62
|
+
/**
|
63
|
+
* Change the browser hash value on click
|
64
|
+
* @member {String|null} route_=null
|
65
|
+
*/
|
66
|
+
route_: null,
|
67
|
+
/**
|
68
|
+
* True adds an expanding circle on click
|
69
|
+
* @member {Boolean} useRippleEffect_=true
|
70
|
+
*/
|
71
|
+
useRippleEffect_: true,
|
72
|
+
/**
|
73
|
+
* @member {Object} _vdom
|
74
|
+
*/
|
75
|
+
_vdom:
|
76
|
+
{tag: 'button', type: 'button', cn: [
|
77
|
+
{tag: 'span', cls: ['neo-button-glyph']},
|
78
|
+
{tag: 'span', cls: ['neo-button-text']},
|
79
|
+
{cls: ['neo-button-badge']},
|
80
|
+
{cls: ['neo-button-ripple-wrapper'], cn: [
|
81
|
+
{cls: ['neo-button-ripple']}
|
82
|
+
]}
|
83
|
+
]}
|
84
|
+
}
|
85
|
+
|
86
|
+
/**
|
87
|
+
* Time in ms for the ripple effect when clicking on the button.
|
88
|
+
* Only active if useRippleEffect is set to true.
|
89
|
+
* @member {Number} rippleEffectDuration=400
|
90
|
+
*/
|
91
|
+
rippleEffectDuration = 400
|
92
|
+
/**
|
93
|
+
* Internal flag to store the last setTimeout() id for ripple effect remove node callbacks
|
94
|
+
* @member {Number} #rippleTimeoutId=null
|
95
|
+
* @private
|
96
|
+
*/
|
97
|
+
#rippleTimeoutId = null
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Triggered after the route config got changed
|
101
|
+
* @param {String} value
|
102
|
+
* @param {String} oldValue
|
103
|
+
* @protected
|
104
|
+
*/
|
105
|
+
afterSetRoute(value, oldValue) {
|
106
|
+
let me = this;
|
107
|
+
|
108
|
+
value && me.addDomListeners({
|
109
|
+
click: me.changeRoute,
|
110
|
+
scope: me
|
111
|
+
});
|
112
|
+
}
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Triggered before the iconPosition config gets changed
|
116
|
+
* @param {String} value
|
117
|
+
* @param {String} oldValue
|
118
|
+
* @protected
|
119
|
+
*/
|
120
|
+
beforeSetIconPosition(value, oldValue) {
|
121
|
+
return this.beforeSetEnumValue(value, oldValue, 'iconPosition');
|
122
|
+
}
|
123
|
+
|
124
|
+
/**
|
125
|
+
* Convenience shortcut
|
126
|
+
* @returns {Object}
|
127
|
+
*/
|
128
|
+
getIconNode() {
|
129
|
+
return this.getVdomRoot().cn[0];
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
Neo.applyClassConfig(Base);
|
134
|
+
|
135
|
+
export default Base;
|
136
|
+
|
137
|
+
```
|
138
|
+
* Use JSDoc based comments for all top level items as well as top level configs
|
139
|
+
* Class content order:
|
140
|
+
- static configs (ordered chronologically)
|
141
|
+
- static config as the last item. This one does not need a comment, but is prefixed with an empty line.
|
142
|
+
- non-static class fields (ordered chronologically)
|
143
|
+
- construct() in case you are using it
|
144
|
+
- all other class methods are ordered chronologically
|
145
|
+
* Module order:
|
146
|
+
- Import statements formatted according to 1.
|
147
|
+
- empty line
|
148
|
+
- class definition
|
149
|
+
- empty line
|
150
|
+
- Neo.applyClassConfig(<ClassName>)
|
151
|
+
- empty line
|
152
|
+
- export statement
|
153
|
+
- empty line
|
154
|
+
|
package/apps/ServiceWorker.mjs
CHANGED
@@ -8,12 +8,6 @@ import ServiceBase from '../src/worker/ServiceBase.mjs';
|
|
8
8
|
* @singleton
|
9
9
|
*/
|
10
10
|
class ServiceWorker extends ServiceBase {
|
11
|
-
/**
|
12
|
-
* @member {String} workerId='service'
|
13
|
-
* @protected
|
14
|
-
*/
|
15
|
-
workerId = 'service'
|
16
|
-
|
17
11
|
static config = {
|
18
12
|
/**
|
19
13
|
* @member {String} className='Neo.ServiceWorker'
|
@@ -26,16 +20,18 @@ class ServiceWorker extends ServiceBase {
|
|
26
20
|
*/
|
27
21
|
singleton: true,
|
28
22
|
/**
|
29
|
-
* @member {String} version='5.0.
|
23
|
+
* @member {String} version='5.0.3'
|
30
24
|
*/
|
31
|
-
version: '5.0.
|
25
|
+
version: '5.0.3'
|
32
26
|
}
|
33
|
-
}
|
34
27
|
|
35
|
-
|
36
|
-
|
37
|
-
|
28
|
+
/**
|
29
|
+
* @member {String} workerId='service'
|
30
|
+
* @protected
|
31
|
+
*/
|
32
|
+
workerId = 'service'
|
33
|
+
}
|
38
34
|
|
39
|
-
Neo.
|
35
|
+
let instance = Neo.applyClassConfig(ServiceWorker);
|
40
36
|
|
41
37
|
export default instance;
|
@@ -20,7 +20,7 @@ class AttributionComponent extends Component {
|
|
20
20
|
* @member {Object} vdom
|
21
21
|
*/
|
22
22
|
vdom:
|
23
|
-
{
|
23
|
+
{style: {margin: '20px'}, cn: [
|
24
24
|
{tag: 'h2', html: 'Attribution'},
|
25
25
|
{tag: 'ul', cn: [
|
26
26
|
{tag: 'li', html: 'The logos were created by <a target="_blank" href="https://www.driefmeier.com/">Sebastian Driefmeier</a>. Thank you!'},
|
@@ -309,17 +309,15 @@ class MainContainerController extends ComponentController {
|
|
309
309
|
let table = this.getReference('table');
|
310
310
|
|
311
311
|
table.vdom.cn[0].cn[1].cn.push({
|
312
|
-
|
313
|
-
|
312
|
+
cls : ['neo-box-label', 'neo-label'],
|
313
|
+
style: {margin: '20px'},
|
314
|
+
|
314
315
|
html: [
|
315
316
|
'Summary data did not arrive after 2s.</br>',
|
316
317
|
'Please double-check if the API is offline:</br></br>',
|
317
318
|
'<a target="_blank" href="https://disease.sh/all">NovelCOVID/API all endpoint</a></br></br>',
|
318
319
|
'and if so please try again later.'
|
319
|
-
].join('')
|
320
|
-
style: {
|
321
|
-
margin: '20px'
|
322
|
-
}
|
320
|
+
].join('')
|
323
321
|
});
|
324
322
|
|
325
323
|
table.update();
|
@@ -38,7 +38,7 @@ class CountryGallery extends Gallery {
|
|
38
38
|
itemTpl:
|
39
39
|
{cls: ['neo-gallery-item', 'image-wrap', 'view', 'neo-transition-1000'], tabIndex: '-1', cn: [
|
40
40
|
{cls: ['neo-item-wrapper'], style: {}, cn: [
|
41
|
-
{
|
41
|
+
{cls: ['neo-country-gallery-item'], style: {}, cn: [
|
42
42
|
{cls: ['neo-item-header'], cn: [
|
43
43
|
{tag: 'img', cls: ['neo-flag']},
|
44
44
|
{}
|
@@ -38,7 +38,7 @@ class CountryHelix extends Helix {
|
|
38
38
|
itemTpl:
|
39
39
|
{cls: ['surface', 'neo-helix-item'], style: {}, tabIndex: '-1', cn: [
|
40
40
|
{cls: ['neo-item-wrapper'], style: {}, cn: [
|
41
|
-
{
|
41
|
+
{cls: ['neo-country-helix-item'], style: {}, cn: [
|
42
42
|
{cls: ['neo-item-header'], cn: [
|
43
43
|
{tag: 'img', cls: ['neo-flag']},
|
44
44
|
{}
|
@@ -20,7 +20,7 @@ class AttributionComponent extends Component {
|
|
20
20
|
* @member {Object} vdom
|
21
21
|
*/
|
22
22
|
vdom:
|
23
|
-
{
|
23
|
+
{style: {margin: '20px'}, cn: [
|
24
24
|
{tag: 'h2', html: 'Attribution'},
|
25
25
|
{tag: 'ul', cn: [
|
26
26
|
{tag: 'li', html: 'The logos were created by <a target="_blank" href="https://www.driefmeier.com/">Sebastian Driefmeier</a>. Thank you!'},
|
@@ -494,17 +494,15 @@ class MainContainerController extends ComponentController {
|
|
494
494
|
const table = this.getReference('table');
|
495
495
|
|
496
496
|
table.vdom.cn[0].cn[1].cn.push({
|
497
|
-
tag : 'div',
|
498
497
|
cls : ['neo-box-label', 'neo-label'],
|
499
|
-
|
498
|
+
style: {margin: '20px'},
|
499
|
+
|
500
|
+
html: [
|
500
501
|
'Summary data did not arrive after 2s.</br>',
|
501
502
|
'Please double-check if the API is offline:</br></br>',
|
502
503
|
'<a target="_blank" href="https://disease.sh/all">NovelCOVID/API all endpoint</a></br></br>',
|
503
504
|
'and if so please try again later.'
|
504
|
-
].join('')
|
505
|
-
style: {
|
506
|
-
margin: '20px'
|
507
|
-
}
|
505
|
+
].join('')
|
508
506
|
});
|
509
507
|
|
510
508
|
table.update();
|
@@ -35,60 +35,40 @@ class CountryGallery extends Gallery {
|
|
35
35
|
/**
|
36
36
|
* @member {Object} itemTpl_
|
37
37
|
*/
|
38
|
-
itemTpl:
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
cls
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
tag: '
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
{tag: 'td', html: 'Deaths'},
|
73
|
-
{tag: 'td', cls: ['neo-align-right', 'neo-content-deaths']},
|
74
|
-
{tag: 'td', style: {width: '100%'}},
|
75
|
-
{tag: 'td', html: 'Deaths today'},
|
76
|
-
{tag: 'td', cls: ['neo-align-right', 'neo-content-deaths']}
|
77
|
-
]
|
78
|
-
}, {
|
79
|
-
tag: 'tr',
|
80
|
-
cn : [
|
81
|
-
{tag: 'td', html: 'Recovered'},
|
82
|
-
{tag: 'td', cls: ['neo-align-right', 'neo-content-recovered']},
|
83
|
-
{tag: 'td', style: {width: '100%'}},
|
84
|
-
{tag: 'td', html: 'Critical'},
|
85
|
-
{tag: 'td', cls: ['neo-align-right', 'neo-content-critical']}
|
86
|
-
]
|
87
|
-
}]
|
88
|
-
}]
|
89
|
-
}]
|
90
|
-
}]
|
91
|
-
},
|
38
|
+
itemTpl:
|
39
|
+
{cls: ['neo-gallery-item', 'image-wrap', 'view', 'neo-transition-1000'], tabIndex: '-1', cn: [
|
40
|
+
{cls: ['neo-item-wrapper'], style: {}, cn: [
|
41
|
+
{cls: ['neo-country-gallery-item'], style: {}, cn: [
|
42
|
+
{cls: ['neo-item-header'], cn: [
|
43
|
+
{tag: 'img', cls: ['neo-flag']},
|
44
|
+
{}
|
45
|
+
]},
|
46
|
+
{tag: 'table', cls: ['neo-content-table'], cn: [
|
47
|
+
{tag: 'tr', cn: [
|
48
|
+
{tag: 'td', html: 'Cases'},
|
49
|
+
{tag: 'td', cls: ['neo-align-right']},
|
50
|
+
{tag: 'td', style: {width: '100%'}},
|
51
|
+
{tag: 'td', html: 'Cases today'},
|
52
|
+
{tag: 'td', cls: ['neo-align-right']}
|
53
|
+
]},
|
54
|
+
{tag: 'tr', cn: [
|
55
|
+
{tag: 'td', html: 'Deaths'},
|
56
|
+
{tag: 'td', cls: ['neo-align-right', 'neo-content-deaths']},
|
57
|
+
{tag: 'td', style: {width: '100%'}},
|
58
|
+
{tag: 'td', html: 'Deaths today'},
|
59
|
+
{tag: 'td', cls: ['neo-align-right', 'neo-content-deaths']}
|
60
|
+
]},
|
61
|
+
{tag: 'tr', cn: [
|
62
|
+
{tag: 'td', html: 'Recovered'},
|
63
|
+
{tag: 'td', cls: ['neo-align-right', 'neo-content-recovered']},
|
64
|
+
{tag: 'td', style: {width: '100%'}},
|
65
|
+
{tag: 'td', html: 'Critical'},
|
66
|
+
{tag: 'td', cls: ['neo-align-right', 'neo-content-critical']}
|
67
|
+
]}
|
68
|
+
]}
|
69
|
+
]}
|
70
|
+
]}
|
71
|
+
]},
|
92
72
|
/**
|
93
73
|
* The item width of the gallery
|
94
74
|
* @member {Number} itemWidth=320
|
@@ -38,7 +38,7 @@ class CountryHelix extends Helix {
|
|
38
38
|
itemTpl:
|
39
39
|
{cls: ['surface', 'neo-helix-item'], style: {}, tabIndex: '-1', cn: [
|
40
40
|
{cls: ['neo-item-wrapper'], style: {}, cn: [
|
41
|
-
{
|
41
|
+
{cls: ['neo-country-helix-item'], style: {}, cn: [
|
42
42
|
{cls: ['neo-item-header'], cn: [
|
43
43
|
{tag: 'img', cls: ['neo-flag']},
|
44
44
|
{}
|
@@ -1,4 +1,17 @@
|
|
1
1
|
[
|
2
|
+
{
|
3
|
+
"author" : "Torsten Dinkheller",
|
4
|
+
"authorImage" : "author_TorstenDinkheller.jpg",
|
5
|
+
"date" : "Jan 28, 2023",
|
6
|
+
"id" : 56,
|
7
|
+
"image" : "toast-tutorial-medium.jpg",
|
8
|
+
"name" : "Reusable Next Gen Toast — to Industry Standard",
|
9
|
+
"provider" : "Medium",
|
10
|
+
"publisher" : "ITNEXT",
|
11
|
+
"selectedInto": [],
|
12
|
+
"type" : "Blog Post",
|
13
|
+
"url" : "https://itnext.io/reusable-next-gen-toast-to-industry-standard-502d2950701f?source=friends_link&sk=f74ba5b5161986d9d8dec6e91ba11a5b"
|
14
|
+
},
|
2
15
|
{
|
3
16
|
"author" : "Tobias Uhlig",
|
4
17
|
"authorImage" : "author_TobiasUhlig.jpeg",
|
@@ -7,10 +20,10 @@
|
|
7
20
|
"image" : "the-next-generation-of-front-end-development.png",
|
8
21
|
"name" : "The Next Generation of Front-end Development",
|
9
22
|
"provider" : "Medium",
|
10
|
-
"publisher" : "",
|
23
|
+
"publisher" : "ITNEXT",
|
11
24
|
"selectedInto": [],
|
12
25
|
"type" : "Blog Post",
|
13
|
-
"url" : "https://
|
26
|
+
"url" : "https://itnext.io/the-next-generation-of-front-end-development-65887c59b173?source=friends_link&sk=51654f60033120e84454791015d8d205"
|
14
27
|
},
|
15
28
|
{
|
16
29
|
"author" : "Tobias Uhlig",
|
@@ -8,12 +8,6 @@ import ServiceBase from '../src/worker/ServiceBase.mjs';
|
|
8
8
|
* @singleton
|
9
9
|
*/
|
10
10
|
class ServiceWorker extends ServiceBase {
|
11
|
-
/**
|
12
|
-
* @member {String} workerId='service'
|
13
|
-
* @protected
|
14
|
-
*/
|
15
|
-
workerId = 'service'
|
16
|
-
|
17
11
|
static config = {
|
18
12
|
/**
|
19
13
|
* @member {String} className='Neo.ServiceWorker'
|
@@ -26,16 +20,18 @@ class ServiceWorker extends ServiceBase {
|
|
26
20
|
*/
|
27
21
|
singleton: true,
|
28
22
|
/**
|
29
|
-
* @member {String} version='5.0.
|
23
|
+
* @member {String} version='5.0.3'
|
30
24
|
*/
|
31
|
-
version: '5.0.
|
25
|
+
version: '5.0.3'
|
32
26
|
}
|
33
|
-
}
|
34
27
|
|
35
|
-
|
36
|
-
|
37
|
-
|
28
|
+
/**
|
29
|
+
* @member {String} workerId='service'
|
30
|
+
* @protected
|
31
|
+
*/
|
32
|
+
workerId = 'service'
|
33
|
+
}
|
38
34
|
|
39
|
-
Neo.
|
35
|
+
let instance = Neo.applyClassConfig(ServiceWorker);
|
40
36
|
|
41
37
|
export default instance;
|
@@ -64,7 +64,7 @@ class CountryGallery extends Gallery {
|
|
64
64
|
|
65
65
|
return {cls, id: me.getItemVnodeId(record[me.keyProperty]), tabIndex: '-1', cn: [
|
66
66
|
{cls: ['neo-item-wrapper'], style: {height: me.itemHeight + 'px'}, cn: [
|
67
|
-
{
|
67
|
+
{cls: ['neo-country-gallery-item'], style, cn: [
|
68
68
|
{cls: ['neo-item-header'], cn: [
|
69
69
|
{tag: 'img', cls: ['neo-flag'], src: me.getCountryFlagUrl(record.country)},
|
70
70
|
{html: record.country}
|
@@ -35,7 +35,7 @@ class CountryHelix extends Helix {
|
|
35
35
|
itemTpl:
|
36
36
|
{cls: ['surface', 'neo-helix-item'], style: {}, tabIndex: '-1', cn: [
|
37
37
|
{cls: ['neo-item-wrapper'], style: {}, cn: [
|
38
|
-
{
|
38
|
+
{cls: ['neo-country-helix-item'], style: {}, cn: [
|
39
39
|
{cls: ['neo-item-header'], cn: [
|
40
40
|
{tag: 'img', cls: ['neo-flag']},
|
41
41
|
{}
|
package/package.json
CHANGED
@@ -65,9 +65,10 @@
|
|
65
65
|
}
|
66
66
|
|
67
67
|
.website-header-buttons {
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
background-color: transparent;
|
69
|
+
position : absolute;
|
70
|
+
right : 0;
|
71
|
+
top : 0;
|
71
72
|
}
|
72
73
|
|
73
74
|
@media (max-height: 400px), (max-width: 600px) {
|
@@ -132,4 +133,4 @@
|
|
132
133
|
margin-right: 5px;
|
133
134
|
}
|
134
135
|
}
|
135
|
-
}
|
136
|
+
}
|
package/src/DefaultConfig.mjs
CHANGED
@@ -237,12 +237,12 @@ const DefaultConfig = {
|
|
237
237
|
useVdomWorker: true,
|
238
238
|
/**
|
239
239
|
* buildScripts/injectPackageVersion.mjs will update this value
|
240
|
-
* @default '5.0.
|
240
|
+
* @default '5.0.3'
|
241
241
|
* @memberOf! module:Neo
|
242
242
|
* @name config.version
|
243
243
|
* @type String
|
244
244
|
*/
|
245
|
-
version: '5.0.
|
245
|
+
version: '5.0.3'
|
246
246
|
};
|
247
247
|
|
248
248
|
Object.assign(DefaultConfig, {
|
package/src/MicroLoader.mjs
CHANGED
package/src/Neo.mjs
CHANGED
@@ -48,15 +48,16 @@ Neo = globalThis.Neo = Object.assign({
|
|
48
48
|
* @tutorial 02_ClassSystem
|
49
49
|
*/
|
50
50
|
applyClassConfig(cls) {
|
51
|
-
let baseCfg
|
52
|
-
|
53
|
-
|
51
|
+
let baseCfg = null,
|
52
|
+
ntypeMap = Neo.ntypeMap,
|
53
|
+
proto = cls.prototype || cls,
|
54
|
+
protos = [],
|
54
55
|
config, ctor, overrides;
|
55
56
|
|
56
57
|
while (proto.__proto__) {
|
57
58
|
ctor = proto.constructor;
|
58
59
|
|
59
|
-
if (
|
60
|
+
if (Object.hasOwn(ctor, 'classConfigApplied')) {
|
60
61
|
baseCfg = Neo.clone(ctor.config, true);
|
61
62
|
break;
|
62
63
|
}
|
@@ -73,40 +74,40 @@ Neo = globalThis.Neo = Object.assign({
|
|
73
74
|
let cfg = ctor.config || {},
|
74
75
|
mixins;
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
}
|
77
|
+
Object.entries(cfg).forEach(([key, value]) => {
|
78
|
+
if (key.slice(-1) === '_') {
|
79
|
+
delete cfg[key];
|
80
|
+
key = key.slice(0, -1);
|
81
|
+
cfg[key] = value;
|
82
|
+
autoGenerateGetSet(element, key);
|
83
|
+
}
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
}
|
85
|
+
// only apply properties which have no setters inside the prototype chain
|
86
|
+
// those will get applied on create (Neo.core.Base -> initConfig)
|
87
|
+
else if (!Neo.hasPropertySetter(element, key)) {
|
88
|
+
Object.defineProperty(element, key, {
|
89
|
+
enumerable: true,
|
90
|
+
value,
|
91
|
+
writable : true
|
92
|
+
});
|
93
|
+
}
|
94
|
+
});
|
96
95
|
|
97
|
-
if (
|
98
|
-
|
99
|
-
|
96
|
+
if (Object.hasOwn(cfg, 'ntype')) {
|
97
|
+
if (Object.hasOwn(ntypeMap, cfg.ntype)) {
|
98
|
+
throw new Error(`ntype conflict for '${cfg.ntype}' inside the classes:\n${ntypeMap[cfg.ntype]}\n${cfg.className}`);
|
99
|
+
}
|
100
100
|
|
101
|
-
|
101
|
+
ntypeMap[cfg.ntype] = cfg.className;
|
102
|
+
}
|
102
103
|
|
103
|
-
|
104
|
+
mixins = Object.hasOwn(config, 'mixins') && config.mixins || [];
|
104
105
|
|
105
106
|
if (ctor.observable) {
|
106
107
|
mixins.push('Neo.core.Observable');
|
107
108
|
}
|
108
109
|
|
109
|
-
if (
|
110
|
+
if (Object.hasOwn(cfg, 'mixins') && Array.isArray(cfg.mixins) && cfg.mixins.length > 0) {
|
110
111
|
mixins.push(...cfg.mixins);
|
111
112
|
}
|
112
113
|
|
@@ -208,7 +209,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
208
209
|
assignDefaults(target, defaults) {
|
209
210
|
if (target && Neo.typeOf(defaults) === 'Object') {
|
210
211
|
Object.entries(defaults).forEach(([key, value]) => {
|
211
|
-
if (!
|
212
|
+
if (!Object.hasOwn(target, key)) {
|
212
213
|
target[key] = value;
|
213
214
|
}
|
214
215
|
});
|
@@ -547,7 +548,7 @@ function autoGenerateGetSet(proto, key) {
|
|
547
548
|
get() {
|
548
549
|
let me = this,
|
549
550
|
beforeGet = `beforeGet${key[0].toUpperCase() + key.slice(1)}`,
|
550
|
-
hasNewKey = me[configSymbol]
|
551
|
+
hasNewKey = Object.hasOwn(me[configSymbol], key),
|
551
552
|
newKey = me[configSymbol][key],
|
552
553
|
value = hasNewKey ? newKey : me['_' + key];
|
553
554
|
|
package/src/core/Base.mjs
CHANGED
package/src/grid/View.mjs
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import Component from '../component/Base.mjs';
|
2
|
+
import VDomUtil from '../util/VDom.mjs';
|
2
3
|
|
3
4
|
/**
|
4
5
|
* @class Neo.grid.View
|
@@ -175,6 +176,33 @@ class View extends Component {
|
|
175
176
|
return this.id + '__' + record[this.store.keyProperty] + '__' + field;
|
176
177
|
}
|
177
178
|
|
179
|
+
/**
|
180
|
+
* Get the matching record by passing a row id, a cell id or an id inside a table cell.
|
181
|
+
* @param {String} nodeId
|
182
|
+
* @returns {Object|null}
|
183
|
+
*/
|
184
|
+
getRecord(nodeId) {
|
185
|
+
let me = this,
|
186
|
+
record = me.getRecordByRowId(nodeId),
|
187
|
+
node, parentNodes;
|
188
|
+
|
189
|
+
if (record) {
|
190
|
+
return record;
|
191
|
+
}
|
192
|
+
|
193
|
+
parentNodes = VDomUtil.getParentNodes(me.vdom, nodeId);
|
194
|
+
|
195
|
+
for (node of parentNodes) {
|
196
|
+
record = me.getRecordByRowId(node.id);
|
197
|
+
|
198
|
+
if (record) {
|
199
|
+
return record;
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
return null;
|
204
|
+
}
|
205
|
+
|
178
206
|
/**
|
179
207
|
* @param {String} rowId
|
180
208
|
* @returns {Object}
|
package/src/table/View.mjs
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import Component from '../component/Base.mjs';
|
2
|
+
import VDomUtil from '../util/VDom.mjs';
|
2
3
|
|
3
4
|
/**
|
4
5
|
* @class Neo.table.View
|
@@ -201,6 +202,33 @@ class View extends Component {
|
|
201
202
|
return this.id + '__' + record[this.store.keyProperty] + '__' + dataField;
|
202
203
|
}
|
203
204
|
|
205
|
+
/**
|
206
|
+
* Get the matching record by passing a row id, a cell id or an id inside a table cell.
|
207
|
+
* @param {String} nodeId
|
208
|
+
* @returns {Object|null}
|
209
|
+
*/
|
210
|
+
getRecord(nodeId) {
|
211
|
+
let me = this,
|
212
|
+
record = me.getRecordByRowId(nodeId),
|
213
|
+
node, parentNodes;
|
214
|
+
|
215
|
+
if (record) {
|
216
|
+
return record;
|
217
|
+
}
|
218
|
+
|
219
|
+
parentNodes = VDomUtil.getParentNodes(me.vdom, nodeId);
|
220
|
+
|
221
|
+
for (node of parentNodes) {
|
222
|
+
record = me.getRecordByRowId(node.id);
|
223
|
+
|
224
|
+
if (record) {
|
225
|
+
return record;
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
return null;
|
230
|
+
}
|
231
|
+
|
204
232
|
/**
|
205
233
|
* @param {String} rowId
|
206
234
|
* @returns {Object}
|