neo.mjs 6.8.2 → 6.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/PULL_REQUEST_TEMPLATE.md +1 -1
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/learnneo/app.mjs +6 -0
- package/apps/learnneo/index.html +11 -0
- package/apps/learnneo/model/Content.mjs +44 -0
- package/apps/learnneo/neo-config.json +6 -0
- package/apps/learnneo/store/Content.mjs +24 -0
- package/apps/learnneo/view/Viewport.mjs +34 -0
- package/apps/learnneo/view/ViewportController.mjs +19 -0
- package/apps/learnneo/view/home/ContentTreeList.mjs +41 -0
- package/apps/learnneo/view/home/MainContainer.mjs +51 -0
- package/apps/learnneo/view/home/MainContainerController.mjs +50 -0
- package/apps/route/app.mjs +6 -0
- package/apps/route/index.html +11 -0
- package/apps/route/neo-config.json +6 -0
- package/apps/route/view/ButtonBar.mjs +57 -0
- package/apps/route/view/CenterContainer.mjs +37 -0
- package/apps/route/view/FooterContainer.mjs +47 -0
- package/apps/route/view/HeaderContainer.mjs +47 -0
- package/apps/route/view/MainView.mjs +66 -0
- package/apps/route/view/MainViewController.mjs +210 -0
- package/apps/route/view/MetaContainer.mjs +52 -0
- package/apps/route/view/Viewport.mjs +15 -0
- package/apps/route/view/center/CardAdministration.mjs +36 -0
- package/apps/route/view/center/CardAdministrationDenied.mjs +26 -0
- package/apps/route/view/center/CardContact.mjs +29 -0
- package/apps/route/view/center/CardHome.mjs +26 -0
- package/apps/route/view/center/CardSection1.mjs +26 -0
- package/apps/route/view/center/CardSection2.mjs +27 -0
- package/examples/ConfigurationViewport.mjs +1 -1
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/form/field/select/MainContainer.mjs +7 -2
- package/examples/table/container/MainContainer.mjs +4 -2
- package/examples/table/container/MainModel.mjs +3 -0
- package/examples/table/container/MainStore.mjs +10 -10
- package/examples/todoList/version1/MainComponent.mjs +5 -5
- package/examples/toolbar/paging/view/MainContainer.mjs +31 -3
- package/package.json +1 -1
- package/resources/data/learnneo/content.json +27 -0
- package/resources/data/learnneo/pages/whyneo.md +76 -0
- package/resources/scss/src/apps/route/CenterContainer.scss +29 -0
- package/resources/scss/src/apps/route/HeaderContainer.scss +122 -0
- package/resources/scss/src/apps/route/MainView.scss +3 -0
- package/resources/scss/src/apps/route/MetaContainer.scss +44 -0
- package/resources/scss/src/apps/route/_all.scss +1 -0
- package/resources/scss/src/form/field/Picker.scss +0 -1
- package/src/DefaultConfig.mjs +2 -2
- package/src/Neo.mjs +15 -14
- package/src/button/Base.mjs +2 -2
- package/src/component/Base.mjs +41 -50
- package/src/container/Base.mjs +59 -2
- package/src/controller/Base.mjs +84 -4
- package/src/controller/Component.mjs +22 -7
- package/src/core/Observable.mjs +50 -9
- package/src/dialog/Base.mjs +1 -4
- package/src/form/field/FileUpload.mjs +11 -0
- package/src/form/field/Picker.mjs +0 -17
- package/src/form/field/Range.mjs +8 -0
- package/src/form/field/Text.mjs +29 -0
- package/src/form/field/trigger/Picker.mjs +7 -0
- package/src/main/DomEvents.mjs +9 -3
- package/src/manager/DomEvent.mjs +3 -0
- package/src/menu/List.mjs +1 -1
- package/src/table/View.mjs +78 -53
- package/src/toolbar/Paging.mjs +68 -76
- package/src/tooltip/Base.mjs +111 -11
@@ -0,0 +1,27 @@
|
|
1
|
+
{
|
2
|
+
"data": [{
|
3
|
+
"id" : 1,
|
4
|
+
"isLeaf" : true,
|
5
|
+
"name" : "Why neo.mjs",
|
6
|
+
"parentId": null,
|
7
|
+
"path" : "whyneo.md"
|
8
|
+
}, {
|
9
|
+
"id" : 2,
|
10
|
+
"isLeaf" : false,
|
11
|
+
"name" : "Class Definitions and Config",
|
12
|
+
"parentId": null,
|
13
|
+
"path" : null
|
14
|
+
}, {
|
15
|
+
"id" : 3,
|
16
|
+
"isLeaf" : false,
|
17
|
+
"name" : "Class Basics",
|
18
|
+
"parentId": 2,
|
19
|
+
"path" : null
|
20
|
+
}, {
|
21
|
+
"id" : 4,
|
22
|
+
"isLeaf" : true,
|
23
|
+
"name" : "Classes, Properties, and Methods",
|
24
|
+
"parentId": 3,
|
25
|
+
"path" : null
|
26
|
+
}]
|
27
|
+
}
|
@@ -0,0 +1,76 @@
|
|
1
|
+
Neo.mjs is a framework used to create browser-based applications.
|
2
|
+
|
3
|
+
Some key features and benefits of Neo.mjs are:
|
4
|
+
|
5
|
+
<div type="expander" caption="Multi-Threaded">
|
6
|
+
<p>
|
7
|
+
When a Neo.mjs application starts, the framework spawns three web-workers.
|
8
|
+
Web-workers are each run in their own thread. As a result, a typical Neo.mjs application
|
9
|
+
has four threads:
|
10
|
+
<ol>
|
11
|
+
<li>The _main_ thread, where DOM updates are applied
|
12
|
+
<li>An _application_ web-worker where normal application locic is run
|
13
|
+
<li>A _data_ web-worker were HTTP and socket calls are run
|
14
|
+
<li>A _view_ web-worker that manages delta updates
|
15
|
+
</ol>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<div type="expander" caption="Extreme Speed">
|
19
|
+
<p>
|
20
|
+
The Neo.mjs web-worker proccesses are automatically run in parallel, on separate CPU cores.
|
21
|
+
</p>
|
22
|
+
<p>
|
23
|
+
By contrast, other JavaScript frameworks run in a single thread. That means
|
24
|
+
in a typical framework all business logic, data handling, and DOM rendering compete for
|
25
|
+
CPU reasources.
|
26
|
+
</p>
|
27
|
+
<p>
|
28
|
+
This means Neo.mjs applications run and render faster. This is
|
29
|
+
particularly beneficial for processor- and data-intensive applications,
|
30
|
+
and applications that need to rapidly update what's viewed. In testing, Neo.mjs applications
|
31
|
+
easily apply over 20,000 DOM updates per second.
|
32
|
+
</p>
|
33
|
+
<p>
|
34
|
+
If the default four threads aren't enough, you're free to launch additional web-worker threads
|
35
|
+
to run other specialized logic.
|
36
|
+
</p>
|
37
|
+
</div>
|
38
|
+
|
39
|
+
<div type="expander" caption="Quick Application Development">
|
40
|
+
<p>
|
41
|
+
Neo.js classes let you specify properties in a way that allows code to detect "before" and "after"
|
42
|
+
changes. This makes it easy to handle value validation and transformation, and react to changes.
|
43
|
+
</p>
|
44
|
+
<p>
|
45
|
+
Neo.mjs also has elegant yet powerful state management features that make it easy to create shared,
|
46
|
+
bindable data. For example, if two components are bound to the same propery, a change to the
|
47
|
+
property will automatically be applied to both components.
|
48
|
+
</p>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<div type="expander" caption="Multi-Window Applications">
|
52
|
+
<p>
|
53
|
+
Neo.mjs applications can also launch as _shared web workers_, which allows you to have a single
|
54
|
+
application run in multiple browser windows; those windows could be moved to multiple monitors.
|
55
|
+
</p>
|
56
|
+
<p>
|
57
|
+
For example, you can have a data analysis application with a control panel on one monitor,
|
58
|
+
tabular data in another, and charts on another — all sharing the same data, handling events
|
59
|
+
across windows, running seamlessly as a single application.
|
60
|
+
</p>
|
61
|
+
</div>
|
62
|
+
|
63
|
+
<div type="expander" caption="Open-Source and Standards-Based">
|
64
|
+
<p>
|
65
|
+
Neo.mjs is an open-source library. Features needed for the community can be added to the
|
66
|
+
library via pull-requests. And since Neo.mjs uses the standard JavaScript class system,
|
67
|
+
all Neo.mjs classes can be extended.
|
68
|
+
</p>
|
69
|
+
<p>
|
70
|
+
Neo.mjs uses standard modular JavaScript, so developers don't need to learn non-standard language
|
71
|
+
syntax, and there's no need for special pre-compilers or WebPack modules.
|
72
|
+
That means fewer dependencies and easier configuration. Furthermore, the use of
|
73
|
+
standard JavaScript makes debugging easier: any statement you write while developing your
|
74
|
+
applcation can also be run in the debugging console.
|
75
|
+
</p>
|
76
|
+
</div>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
.route {
|
2
|
+
|
3
|
+
background-color: white;
|
4
|
+
|
5
|
+
.route_center {
|
6
|
+
|
7
|
+
max-width: 95%;
|
8
|
+
|
9
|
+
margin-left: 20px;
|
10
|
+
margin-right: 20px;
|
11
|
+
margin-top: 0px;
|
12
|
+
margin-bottom: 10px;
|
13
|
+
|
14
|
+
border-top-width: .5px;
|
15
|
+
border-top-color: #757575;
|
16
|
+
border-top-style: solid;
|
17
|
+
|
18
|
+
border-bottom-width: .5px;
|
19
|
+
border-bottom-color: #757575;
|
20
|
+
border-bottom-style: solid;
|
21
|
+
|
22
|
+
.route_card_simple_page {
|
23
|
+
text-align: center;
|
24
|
+
}
|
25
|
+
|
26
|
+
}
|
27
|
+
|
28
|
+
|
29
|
+
}
|
@@ -0,0 +1,122 @@
|
|
1
|
+
.route {
|
2
|
+
.route_header {
|
3
|
+
height: 242px;
|
4
|
+
}
|
5
|
+
|
6
|
+
.center {
|
7
|
+
display: inline-block;
|
8
|
+
margin-left: auto;
|
9
|
+
margin-right: auto;
|
10
|
+
width: 50%;
|
11
|
+
}
|
12
|
+
|
13
|
+
.centerPanel {
|
14
|
+
margin-left: auto;
|
15
|
+
margin-right: auto;
|
16
|
+
width: auto;
|
17
|
+
min-height: 50px;
|
18
|
+
}
|
19
|
+
|
20
|
+
.headline-caption {
|
21
|
+
color: #535353;
|
22
|
+
font-family: 'Georgia', 'Times New Roman', serif;
|
23
|
+
font-size: 32px;
|
24
|
+
font-weight: normal;
|
25
|
+
text-align: center;
|
26
|
+
margin-top: 32px;
|
27
|
+
max-height: 70px;
|
28
|
+
}
|
29
|
+
|
30
|
+
.route_buttonbar {
|
31
|
+
min-height: 70px;
|
32
|
+
}
|
33
|
+
|
34
|
+
.route_button {
|
35
|
+
height: 50px;
|
36
|
+
min-width: 150px;
|
37
|
+
border: none;
|
38
|
+
margin-left: 10px;
|
39
|
+
float: left;
|
40
|
+
|
41
|
+
.neo-button-text {
|
42
|
+
color: #535353;
|
43
|
+
font-family: 'Georgia', 'Times New Roman', serif !important;
|
44
|
+
font-weight: normal;
|
45
|
+
font-size: 14px;
|
46
|
+
text-align: center;
|
47
|
+
text-transform: none;
|
48
|
+
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
.route_button_selected {
|
53
|
+
border-bottom: 1px;
|
54
|
+
border-bottom-style: solid;
|
55
|
+
border-bottom-left-radius: 0;
|
56
|
+
border-bottom-right-radius: 0;
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
.iconTischtennis {
|
61
|
+
background: url('../../../../../../resources/images/route/tischtennis_40.png');
|
62
|
+
background-position: 0 0;
|
63
|
+
background-repeat: no-repeat;
|
64
|
+
width: 32px;
|
65
|
+
height: 32px;
|
66
|
+
|
67
|
+
}
|
68
|
+
|
69
|
+
.iconFussball {
|
70
|
+
margin-top: 4px !important;
|
71
|
+
background: url('../../../../../../resources/images/route/fussball_38.png');
|
72
|
+
background-position: 0 0;
|
73
|
+
background-repeat: no-repeat;
|
74
|
+
background-size: 26px;
|
75
|
+
width: 32px;
|
76
|
+
height: 32px;
|
77
|
+
|
78
|
+
}
|
79
|
+
|
80
|
+
.iconLeichtathletik {
|
81
|
+
margin-top: 2px !important;
|
82
|
+
background: url('../../../../../../resources/images/route/leichtathletik_37.png');
|
83
|
+
background-position: 0 0;
|
84
|
+
background-repeat: no-repeat;
|
85
|
+
background-size: 30px;
|
86
|
+
width: 32px;
|
87
|
+
height: 32px;
|
88
|
+
|
89
|
+
}
|
90
|
+
|
91
|
+
.iconSchach {
|
92
|
+
background: url('../../../../../../resources/images/route/schach_17.png');
|
93
|
+
background-position: 0 0;
|
94
|
+
background-repeat: no-repeat;
|
95
|
+
width: 17px;
|
96
|
+
height: 28px;
|
97
|
+
|
98
|
+
}
|
99
|
+
|
100
|
+
.iconLogo {
|
101
|
+
margin-top: 2px !important;
|
102
|
+
background: url('../../../../../../resources/images/route/logo.jpg');
|
103
|
+
background-position: 0 0;
|
104
|
+
background-repeat: no-repeat;
|
105
|
+
background-size: 30px;
|
106
|
+
width: 32px;
|
107
|
+
height: 32px;
|
108
|
+
|
109
|
+
}
|
110
|
+
|
111
|
+
.iconBogen {
|
112
|
+
margin-top: 2px !important;
|
113
|
+
background: url('../../../../../../resources/images/route/bogen.png');
|
114
|
+
background-position: 0 0;
|
115
|
+
background-repeat: no-repeat;
|
116
|
+
background-size: 30px;
|
117
|
+
width: 32px;
|
118
|
+
height: 32px;
|
119
|
+
|
120
|
+
}
|
121
|
+
|
122
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
.route {
|
2
|
+
.route_meta {
|
3
|
+
height: 100px !important;
|
4
|
+
margin: 5px;
|
5
|
+
padding: 25px;
|
6
|
+
border-style: solid;
|
7
|
+
}
|
8
|
+
.route_meta_center {
|
9
|
+
display: inline-block;
|
10
|
+
margin-left: auto;
|
11
|
+
margin-right: auto;
|
12
|
+
width: 50%;
|
13
|
+
}
|
14
|
+
|
15
|
+
.route_meta_color {
|
16
|
+
background-color: lightblue;
|
17
|
+
}
|
18
|
+
|
19
|
+
.route_meta_button_grant{
|
20
|
+
height: 50px;
|
21
|
+
min-width: 150px;
|
22
|
+
margin: 0px;
|
23
|
+
border: 0px;
|
24
|
+
float: left;
|
25
|
+
background-color: lightgreen;
|
26
|
+
margin-left: 5px;
|
27
|
+
|
28
|
+
}
|
29
|
+
|
30
|
+
.route_meta_button_grant_selected{
|
31
|
+
background-color: greenyellow !important;
|
32
|
+
}
|
33
|
+
|
34
|
+
.route_meta_button_remove{
|
35
|
+
height: 50px;
|
36
|
+
min-width: 150px;
|
37
|
+
margin: 0px;
|
38
|
+
border: 0px;
|
39
|
+
float: left;
|
40
|
+
background-color: lightcoral;
|
41
|
+
margin-left: 50px;
|
42
|
+
}
|
43
|
+
|
44
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
|
package/src/DefaultConfig.mjs
CHANGED
@@ -236,12 +236,12 @@ const DefaultConfig = {
|
|
236
236
|
useVdomWorker: true,
|
237
237
|
/**
|
238
238
|
* buildScripts/injectPackageVersion.mjs will update this value
|
239
|
-
* @default '6.
|
239
|
+
* @default '6.9.0'
|
240
240
|
* @memberOf! module:Neo
|
241
241
|
* @name config.version
|
242
242
|
* @type String
|
243
243
|
*/
|
244
|
-
version: '6.
|
244
|
+
version: '6.9.0'
|
245
245
|
};
|
246
246
|
|
247
247
|
Object.assign(DefaultConfig, {
|
package/src/Neo.mjs
CHANGED
@@ -1,7 +1,19 @@
|
|
1
1
|
import DefaultConfig from './DefaultConfig.mjs';
|
2
2
|
|
3
3
|
const configSymbol = Symbol.for('configSymbol'),
|
4
|
-
getSetCache = Symbol('getSetCache')
|
4
|
+
getSetCache = Symbol('getSetCache'),
|
5
|
+
typeDetector = {
|
6
|
+
function: (item) => {
|
7
|
+
if (item.prototype?.constructor.isClass) {
|
8
|
+
return 'NeoClass'
|
9
|
+
}
|
10
|
+
},
|
11
|
+
object: (item) => {
|
12
|
+
if (item.constructor.isClass && item instanceof Neo.core.Base) {
|
13
|
+
return 'NeoInstance'
|
14
|
+
}
|
15
|
+
}
|
16
|
+
};
|
5
17
|
|
6
18
|
/**
|
7
19
|
* The base module to enhance classes, create instances and the Neo namespace
|
@@ -375,7 +387,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
375
387
|
const value = source[key];
|
376
388
|
|
377
389
|
if (Neo.typeOf(value) === 'Object') {
|
378
|
-
target[key] = Neo.merge(target[key], value);
|
390
|
+
target[key] = Neo.merge(target[key] || {}, value);
|
379
391
|
} else {
|
380
392
|
target[key] = value;
|
381
393
|
}
|
@@ -492,18 +504,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
492
504
|
return null
|
493
505
|
}
|
494
506
|
|
495
|
-
return
|
496
|
-
function: () => {
|
497
|
-
if (item.prototype?.constructor.isClass) {
|
498
|
-
return 'NeoClass'
|
499
|
-
}
|
500
|
-
},
|
501
|
-
object: () => {
|
502
|
-
if (item.constructor.isClass && item instanceof Neo.core.Base) {
|
503
|
-
return 'NeoInstance'
|
504
|
-
}
|
505
|
-
}
|
506
|
-
}[typeof item]?.() || item.constructor.name
|
507
|
+
return typeDetector[typeof item]?.(item) || item.constructor.name
|
507
508
|
}
|
508
509
|
}, Neo);
|
509
510
|
|
package/src/button/Base.mjs
CHANGED
@@ -51,7 +51,7 @@ class Base extends Component {
|
|
51
51
|
editRoute: true,
|
52
52
|
/**
|
53
53
|
* Shortcut for domListeners={click:handler}
|
54
|
-
* A string based value assumes that the handlerFn lives inside a
|
54
|
+
* A string based value assumes that the handlerFn lives inside a controller.Component
|
55
55
|
* @member {Function|String|null} handler_=null
|
56
56
|
*/
|
57
57
|
handler_: null,
|
@@ -487,7 +487,7 @@ class Base extends Component {
|
|
487
487
|
onClick(data) {
|
488
488
|
let me = this;
|
489
489
|
|
490
|
-
me.
|
490
|
+
me.callback(me.handler, me.handlerScope || me, [data]);
|
491
491
|
|
492
492
|
me.menu && me.toggleMenu();
|
493
493
|
me.route && me.changeRoute();
|
package/src/component/Base.mjs
CHANGED
@@ -302,11 +302,17 @@ class Base extends CoreBase {
|
|
302
302
|
*/
|
303
303
|
theme_: null,
|
304
304
|
/**
|
305
|
-
* Add tooltip config
|
305
|
+
* Add tooltip config object or a string containing the display text
|
306
306
|
* See tooltip/Base.mjs
|
307
|
-
*
|
307
|
+
*
|
308
|
+
* By default, a single, shared Tooltip instance is used for all widgets which request
|
309
|
+
* a tooltip. It reconfigures itself from the widget's definition just before showing.
|
310
|
+
*
|
311
|
+
* If a widget needs its own instance for any reason, inslude the property `ownInstance : true`
|
312
|
+
* in the tooltip config object.
|
313
|
+
* @member {Object|String} tooltip_=null
|
308
314
|
*/
|
309
|
-
|
315
|
+
tooltip_: null,
|
310
316
|
/**
|
311
317
|
* Add 'primary' and other attributes to make it an outstanding design
|
312
318
|
* @member {String|null} ui_=null
|
@@ -771,21 +777,21 @@ class Base extends CoreBase {
|
|
771
777
|
}
|
772
778
|
|
773
779
|
/**
|
774
|
-
* Triggered after the
|
775
|
-
* @param {
|
776
|
-
* @param {
|
780
|
+
* Triggered after the tooltip config got changed
|
781
|
+
* @param {Object|String} value
|
782
|
+
* @param {Object|String} oldValue
|
777
783
|
* @protected
|
778
784
|
*/
|
779
|
-
|
780
|
-
|
781
|
-
let me = this;
|
785
|
+
afterSetTooltip(value, oldValue) {
|
786
|
+
oldValue?.destroy();
|
782
787
|
|
788
|
+
if (value) {
|
783
789
|
if (Neo.ns('Neo.tooltip.Base')) {
|
784
|
-
|
790
|
+
this.createTooltip(value);
|
785
791
|
} else {
|
786
|
-
import('../tooltip/Base.mjs').then((
|
787
|
-
|
788
|
-
})
|
792
|
+
import('../tooltip/Base.mjs').then(() => {
|
793
|
+
this.createTooltip(value);
|
794
|
+
});
|
789
795
|
}
|
790
796
|
}
|
791
797
|
}
|
@@ -1129,24 +1135,6 @@ class Base extends CoreBase {
|
|
1129
1135
|
return (Neo.isNumber(oldValue) && oldValue > 0) ? (oldValue - 1) : 0
|
1130
1136
|
}
|
1131
1137
|
|
1132
|
-
/**
|
1133
|
-
* Triggered before the style config gets changed.
|
1134
|
-
* @param {Object} value
|
1135
|
-
* @param {Object} oldValue
|
1136
|
-
* @returns {Object}
|
1137
|
-
* @protected
|
1138
|
-
*/
|
1139
|
-
beforeSetStyle(value, oldValue) {
|
1140
|
-
let me = this;
|
1141
|
-
|
1142
|
-
if (typeof value === 'object') {
|
1143
|
-
// merge the incoming style specification into the configured default
|
1144
|
-
value = Neo.merge(Neo.merge({}, me.constructor.config.style), value)
|
1145
|
-
}
|
1146
|
-
|
1147
|
-
return value
|
1148
|
-
}
|
1149
|
-
|
1150
1138
|
/**
|
1151
1139
|
* Changes the value of a vdom object attribute or removes it in case it has no value
|
1152
1140
|
* @param {String} key
|
@@ -1167,31 +1155,31 @@ class Base extends CoreBase {
|
|
1167
1155
|
|
1168
1156
|
/**
|
1169
1157
|
* Creates the tooltip instances
|
1170
|
-
* @param {
|
1158
|
+
* @param {Object|String} value
|
1171
1159
|
* @protected
|
1172
1160
|
*/
|
1173
|
-
|
1174
|
-
if (
|
1175
|
-
value =
|
1161
|
+
createTooltip(value) {
|
1162
|
+
if (typeof value === 'string') {
|
1163
|
+
value = {
|
1164
|
+
text : value
|
1165
|
+
};
|
1176
1166
|
}
|
1177
1167
|
|
1178
|
-
let me
|
1179
|
-
tooltips = [],
|
1180
|
-
tip;
|
1181
|
-
|
1182
|
-
value.forEach(item => {
|
1183
|
-
// todo: check for existing tooltips
|
1168
|
+
let me = this;
|
1184
1169
|
|
1185
|
-
|
1170
|
+
if (value.ownInstance) {
|
1171
|
+
me._tooltip = Neo.create('Neo.tooltip.Base', {
|
1172
|
+
...value,
|
1186
1173
|
appName : me.appName,
|
1187
|
-
componentId: me.id
|
1188
|
-
...item
|
1174
|
+
componentId: me.id
|
1189
1175
|
});
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1176
|
+
}
|
1177
|
+
else {
|
1178
|
+
me._tooltip = value;
|
1179
|
+
Neo.tooltip.Base.createSingleton(me.app);
|
1180
|
+
me.addCls('neo-uses-shared-tooltip');
|
1181
|
+
me.update();
|
1182
|
+
}
|
1195
1183
|
}
|
1196
1184
|
|
1197
1185
|
/**
|
@@ -1665,7 +1653,10 @@ class Base extends CoreBase {
|
|
1665
1653
|
// does not clone existing Neo instances
|
1666
1654
|
me._vdom = Neo.clone(vdom, true, true);
|
1667
1655
|
|
1668
|
-
|
1656
|
+
if (config.style) {
|
1657
|
+
// If we are passed an object, merge it with the class's own style
|
1658
|
+
me.style = Neo.typeOf(config.style) === 'Object' ? { ...config.style, ...me.constructor.config.style } : config.style;
|
1659
|
+
}
|
1669
1660
|
|
1670
1661
|
me.wrapperStyle = Neo.clone(config.wrapperStyle, false);
|
1671
1662
|
|
package/src/container/Base.mjs
CHANGED
@@ -8,6 +8,8 @@ import LayoutVBox from '../layout/VBox.mjs';
|
|
8
8
|
import Logger from '../util/Logger.mjs';
|
9
9
|
import NeoArray from '../util/Array.mjs';
|
10
10
|
|
11
|
+
const byWeight = ({ weight : lhs = 0 }, { weight : rhs = 0 }) => lhs - rhs;
|
12
|
+
|
11
13
|
/**
|
12
14
|
* @class Neo.container.Base
|
13
15
|
* @extends Neo.component.Base
|
@@ -33,10 +35,33 @@ class Base extends Component {
|
|
33
35
|
*/
|
34
36
|
itemDefaults_: null,
|
35
37
|
/**
|
36
|
-
* An array of config objects|instances|modules for each child component
|
38
|
+
* An array or an object of config objects|instances|modules for each child component
|
37
39
|
* @member {Object[]} items_=[]
|
38
40
|
* @example
|
39
41
|
* import Button from '../button/Base.mjs';
|
42
|
+
* import Toolbar from '../toolbar/Base.mjs';
|
43
|
+
*
|
44
|
+
* let myButton = Neo.create(Button, {
|
45
|
+
* text: 'Button1'
|
46
|
+
* });
|
47
|
+
*
|
48
|
+
* Neo.create(Toolbar, {
|
49
|
+
* //...
|
50
|
+
* items: {
|
51
|
+
* buttonRef : {
|
52
|
+
* ntype: 'button', // by ntype
|
53
|
+
* text : 'Button 2'
|
54
|
+
* },
|
55
|
+
* secondRef : {
|
56
|
+
* module: Button, // by imported module
|
57
|
+
* text : 'Button 3'
|
58
|
+
* }
|
59
|
+
* }
|
60
|
+
* });
|
61
|
+
*
|
62
|
+
* or
|
63
|
+
* @example
|
64
|
+
* import Button from '../button/Base.mjs';
|
40
65
|
* import MyRedButton from 'myapp/MyRedButton.mjs';
|
41
66
|
* import Toolbar from '../toolbar/Base.mjs';
|
42
67
|
*
|
@@ -192,6 +217,36 @@ class Base extends Component {
|
|
192
217
|
}
|
193
218
|
}
|
194
219
|
|
220
|
+
/**
|
221
|
+
* Convert items object to an array for onward storage as _items
|
222
|
+
* @param {Object|Object[]} value
|
223
|
+
* @param {Object|Object[]} oldValue
|
224
|
+
* @returns {Object[]}
|
225
|
+
* @protected
|
226
|
+
*/
|
227
|
+
beforeSetItems(value, oldValue) {
|
228
|
+
if (Neo.typeOf(value) === 'Object') {
|
229
|
+
const result = [];
|
230
|
+
|
231
|
+
let hasWeight;
|
232
|
+
|
233
|
+
for (const ref in value) {
|
234
|
+
const item = value[ref]
|
235
|
+
|
236
|
+
item.reference = ref;
|
237
|
+
result.push(item);
|
238
|
+
hasWeight ||= ('weight' in item);
|
239
|
+
}
|
240
|
+
|
241
|
+
if (hasWeight) {
|
242
|
+
result.sort(byWeight);
|
243
|
+
}
|
244
|
+
value = result;
|
245
|
+
}
|
246
|
+
|
247
|
+
return value;
|
248
|
+
}
|
249
|
+
|
195
250
|
/**
|
196
251
|
* @param {Object|String} value
|
197
252
|
* @param {Object|String|Neo.layout.Base} oldValue
|
@@ -446,7 +501,9 @@ class Base extends Component {
|
|
446
501
|
}
|
447
502
|
|
448
503
|
if (config.items) {
|
449
|
-
|
504
|
+
// If we are passed an object, merge the class's own items object into it
|
505
|
+
me.items = Neo.typeOf(config.items) === 'Object' ?
|
506
|
+
Neo.merge(Neo.clone(me.constructor.config.items), config.items) : config.items;
|
450
507
|
delete config.items
|
451
508
|
}
|
452
509
|
|