neo.mjs 6.10.2 → 6.10.4
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/learnneo/view/LivePreview.mjs +28 -15
- package/apps/learnneo/view/home/HeaderToolbar.mjs +16 -6
- package/examples/ServiceWorker.mjs +2 -2
- package/package.json +2 -2
- package/resources/data/deck/learnneo/p/stylesheet.md +4 -1
- package/resources/data/deck/learnneo/t.json +3 -3
- package/resources/design-tokens/json/component.json +22 -0
- package/resources/design-tokens/json/core.json +4 -0
- package/resources/design-tokens/json/semantic.json +8 -0
- package/resources/scss/src/component/Base.scss +26 -0
- package/resources/scss/src/tooltip/Base.scss +10 -6
- package/resources/scss/theme-dark/tooltip/Base.scss +10 -0
- package/resources/scss/theme-light/tooltip/Base.scss +10 -0
- package/resources/scss/theme-neo-light/button/Base.scss +23 -19
- package/resources/scss/theme-neo-light/design-tokens/Component.scss +6 -0
- package/resources/scss/theme-neo-light/design-tokens/Core.scss +2 -0
- package/resources/scss/theme-neo-light/design-tokens/Semantic.scss +4 -2
- package/resources/scss/theme-neo-light/tooltip/Base.scss +13 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/Main.mjs +1 -1
- package/src/component/Base.mjs +58 -14
- package/src/core/Observable.mjs +15 -15
- package/src/main/addon/WindowPosition.mjs +56 -28
- package/src/util/Array.mjs +2 -12
- package/src/worker/App.mjs +34 -3
- package/src/worker/Canvas.mjs +4 -4
- package/test/components/files/button/Base.mjs +41 -14
- package/test/components/files/form/field/Select.mjs +21 -29
- package/test/components/siesta.js +32 -2
package/apps/ServiceWorker.mjs
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import Base
|
1
|
+
import Base from '../../../src/container/Base.mjs';
|
2
2
|
import TabContainer from '../../../src/tab/Container.mjs';
|
3
|
-
import TextArea
|
3
|
+
import TextArea from '../../../src/form/field/TextArea.mjs';
|
4
4
|
|
5
5
|
/**
|
6
6
|
* @class LearnNeo.view.LivePreview
|
@@ -22,7 +22,9 @@ class LivePreview extends Base {
|
|
22
22
|
* @member {Object[]} items
|
23
23
|
*/
|
24
24
|
items: [{
|
25
|
-
module: TabContainer,
|
25
|
+
module : TabContainer,
|
26
|
+
reference: 'tab-container',
|
27
|
+
|
26
28
|
items: [{
|
27
29
|
module: TextArea,
|
28
30
|
hideLabel: true,
|
@@ -38,15 +40,7 @@ class LivePreview extends Base {
|
|
38
40
|
reference: 'preview',
|
39
41
|
ntype: 'container'
|
40
42
|
}]
|
41
|
-
}]
|
42
|
-
listeners: {
|
43
|
-
activeIndexChange: () => console.log('activeIndexChange')
|
44
|
-
}
|
45
|
-
}
|
46
|
-
onConstructed() {
|
47
|
-
console.log('constructed');
|
48
|
-
this.on('activeIndexChange', () => console.log('onConstructed'));
|
49
|
-
super.onConstructed();
|
43
|
+
}]
|
50
44
|
}
|
51
45
|
|
52
46
|
afterSetValue(value, oldValue) {
|
@@ -55,6 +49,14 @@ class LivePreview extends Base {
|
|
55
49
|
}
|
56
50
|
}
|
57
51
|
|
52
|
+
onConstructed() {
|
53
|
+
super.onConstructed();
|
54
|
+
|
55
|
+
let me = this;
|
56
|
+
|
57
|
+
me.getReference('tab-container').on('activeIndexChange', me.onActiveIndexChange, me)
|
58
|
+
}
|
59
|
+
|
58
60
|
doIt(button) {
|
59
61
|
let source = this.getReference('source').getValue();
|
60
62
|
|
@@ -92,7 +94,7 @@ class LivePreview extends Base {
|
|
92
94
|
});
|
93
95
|
var params = [];
|
94
96
|
var vars = [];
|
95
|
-
// Figure out the parts of the source we'll be running.
|
97
|
+
// Figure out the parts of the source we'll be running.
|
96
98
|
// o The promises/import() corresponding to the user's import statements
|
97
99
|
// o The vars holding the name of the imported module based on the module name for each import
|
98
100
|
// o The rest of the user-provided source
|
@@ -105,8 +107,8 @@ class LivePreview extends Base {
|
|
105
107
|
// const Button = ButtonModule.default;
|
106
108
|
// // Class declaration goes here...
|
107
109
|
// });
|
108
|
-
// Making the promise part of the eval seems weird, but it made it easier to
|
109
|
-
// set up the import vars.
|
110
|
+
// Making the promise part of the eval seems weird, but it made it easier to
|
111
|
+
// set up the import vars.
|
110
112
|
|
111
113
|
let promises = moduleNameAndPath.map(item => {
|
112
114
|
params.push(`${item.moduleName}Module`);
|
@@ -164,6 +166,17 @@ class LivePreview extends Base {
|
|
164
166
|
}
|
165
167
|
return null
|
166
168
|
}
|
169
|
+
|
170
|
+
/**
|
171
|
+
* @param {Object} data
|
172
|
+
* @param {Neo.component.Base} data.item
|
173
|
+
* @param {Number} data.oldValue
|
174
|
+
* @param {String} data.source
|
175
|
+
* @param {Number} data.value
|
176
|
+
*/
|
177
|
+
onActiveIndexChange(data) {
|
178
|
+
console.log('onActiveIndexChange', data)
|
179
|
+
}
|
167
180
|
}
|
168
181
|
|
169
182
|
Neo.applyClassConfig(LivePreview);
|
@@ -25,19 +25,29 @@ class HeaderToolbar extends Base {
|
|
25
25
|
text : 'neo.mjs'
|
26
26
|
}, '->', {
|
27
27
|
text: 'Docs',
|
28
|
-
ui : '
|
28
|
+
ui : 'ghost'
|
29
29
|
}, {
|
30
30
|
text: 'Learn',
|
31
|
-
ui : '
|
31
|
+
ui : 'ghost'
|
32
32
|
}, {
|
33
33
|
cls : ['github-button'],
|
34
34
|
iconCls: 'fa-brands fa-github',
|
35
|
-
ui : '
|
36
|
-
url : 'https://github.com/neomjs/neo'
|
35
|
+
ui : 'ghost',
|
36
|
+
url : 'https://github.com/neomjs/neo',
|
37
|
+
tooltip: {
|
38
|
+
html: 'GitHub',
|
39
|
+
showDelay: '0',
|
40
|
+
hideDelay: '0'
|
41
|
+
}
|
37
42
|
}, {
|
38
43
|
iconCls: 'fa-brands fa-slack',
|
39
|
-
ui : '
|
40
|
-
url : 'https://join.slack.com/t/neomjs/shared_invite/zt-6c50ueeu-3E1~M4T9xkNnb~M_prEEOA'
|
44
|
+
ui : 'ghost',
|
45
|
+
url : 'https://join.slack.com/t/neomjs/shared_invite/zt-6c50ueeu-3E1~M4T9xkNnb~M_prEEOA',
|
46
|
+
tooltip: {
|
47
|
+
html: 'Join Slack',
|
48
|
+
showDelay: '0',
|
49
|
+
hideDelay: '0'
|
50
|
+
}
|
41
51
|
}]
|
42
52
|
}
|
43
53
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "neo.mjs",
|
3
|
-
"version": "6.10.
|
3
|
+
"version": "6.10.4",
|
4
4
|
"description": "The webworkers driven UI framework",
|
5
5
|
"type": "module",
|
6
6
|
"repository": {
|
@@ -42,7 +42,7 @@
|
|
42
42
|
},
|
43
43
|
"homepage": "https://neomjs.github.io/pages/",
|
44
44
|
"devDependencies": {
|
45
|
-
"@fortawesome/fontawesome-free": "^6.5.
|
45
|
+
"@fortawesome/fontawesome-free": "^6.5.1",
|
46
46
|
"autoprefixer": "^10.4.16",
|
47
47
|
"chalk": "^5.3.0",
|
48
48
|
"clean-webpack-plugin": "^4.0.0",
|
@@ -18,7 +18,6 @@ and information is lost.
|
|
18
18
|
<br>
|
19
19
|
|
20
20
|
To show highlighted Neo.mjs source code use
|
21
|
-
<pre>
|
22
21
|
<pre data-javascript>
|
23
22
|
// Source code goes here
|
24
23
|
</pre>
|
@@ -52,3 +51,7 @@ This is the item contents.
|
|
52
51
|
This is the item contents.
|
53
52
|
</details>
|
54
53
|
|
54
|
+
<pre data-neo>
|
55
|
+
let a = 1;
|
56
|
+
</pre>
|
57
|
+
|
@@ -143,13 +143,13 @@
|
|
143
143
|
"name": "Main Thread Addons"
|
144
144
|
},
|
145
145
|
{
|
146
|
-
"id": "
|
146
|
+
"id": "MainThreadAddonIntro",
|
147
147
|
"parentId": "MainThreadAddons",
|
148
148
|
"isLeaf": true,
|
149
149
|
"name": "Introduction"
|
150
150
|
},
|
151
151
|
{
|
152
|
-
"id": "
|
152
|
+
"id": "MainThreadAddonExample",
|
153
153
|
"parentId": "MainThreadAddons",
|
154
154
|
"isLeaf": true,
|
155
155
|
"name": "Example"
|
@@ -214,4 +214,4 @@
|
|
214
214
|
"isLeaf": true
|
215
215
|
}
|
216
216
|
]
|
217
|
-
}
|
217
|
+
}
|
@@ -319,6 +319,28 @@
|
|
319
319
|
}
|
320
320
|
}
|
321
321
|
}
|
322
|
+
},
|
323
|
+
"tooltip": {
|
324
|
+
"height": {
|
325
|
+
"value": "{height.24}",
|
326
|
+
"type": "sizing"
|
327
|
+
},
|
328
|
+
"spacinghorizontal": {
|
329
|
+
"value": "{sem.spacing.xsmall}",
|
330
|
+
"type": "spacing"
|
331
|
+
},
|
332
|
+
"fg": {
|
333
|
+
"value": "{sem.color.fg.neutral.inverted}",
|
334
|
+
"type": "color"
|
335
|
+
},
|
336
|
+
"bg": {
|
337
|
+
"value": "{sem.color.bg.neutral.contrast}",
|
338
|
+
"type": "color"
|
339
|
+
},
|
340
|
+
"borderradius": {
|
341
|
+
"value": "{sem.borderradius.medium}",
|
342
|
+
"type": "borderRadius"
|
343
|
+
}
|
322
344
|
}
|
323
345
|
}
|
324
346
|
}
|
@@ -40,6 +40,10 @@
|
|
40
40
|
"disabled": {
|
41
41
|
"value": "{gray.200}",
|
42
42
|
"type": "color"
|
43
|
+
},
|
44
|
+
"contrast": {
|
45
|
+
"value": "{gray.900}",
|
46
|
+
"type": "color"
|
43
47
|
}
|
44
48
|
},
|
45
49
|
"primary": {
|
@@ -82,6 +86,10 @@
|
|
82
86
|
"disabled": {
|
83
87
|
"value": "{gray.300}",
|
84
88
|
"type": "color"
|
89
|
+
},
|
90
|
+
"inverted": {
|
91
|
+
"value": "{white}",
|
92
|
+
"type": "color"
|
85
93
|
}
|
86
94
|
},
|
87
95
|
"primary": {
|
@@ -25,3 +25,29 @@
|
|
25
25
|
top : -10000px;
|
26
26
|
z-index : 1000;
|
27
27
|
}
|
28
|
+
|
29
|
+
.neo-masked {
|
30
|
+
position : relative;
|
31
|
+
|
32
|
+
.neo-load-mask {
|
33
|
+
position : absolute;
|
34
|
+
inset : 0;
|
35
|
+
background-color : inherit;
|
36
|
+
z-index : 4;
|
37
|
+
display : grid;
|
38
|
+
justify-content : center;
|
39
|
+
align-content : center;
|
40
|
+
overflow : clip;
|
41
|
+
|
42
|
+
.neo-load-mask-body {
|
43
|
+
display : flex;
|
44
|
+
flex-flow : row nowrap;
|
45
|
+
gap : 0.7em;
|
46
|
+
|
47
|
+
.fa-spinner {
|
48
|
+
width : 1em;
|
49
|
+
height : 1em;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
@@ -1,7 +1,11 @@
|
|
1
1
|
.neo-tooltip {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
background-color: var(--tooltip-bg);
|
3
|
+
border : var(--tooltip-border);
|
4
|
+
border-radius : var(--tooltip-borderradius);
|
5
|
+
box-shadow : var(--tooltip-boxshadow);
|
6
|
+
color : var(--tooltip-color);
|
7
|
+
font-size : var(--tooltip-fontsize);
|
8
|
+
height : var(--tooltip-height);
|
9
|
+
padding : var(--tooltip-padding);
|
10
|
+
position : absolute;
|
11
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
:root .neo-theme-neo-light { // .neo-tooltip
|
2
|
+
--tooltip-bg : black;
|
3
|
+
--tooltip-border : grey;
|
4
|
+
--tooltip-borderradius : 4px;
|
5
|
+
--tooltip-boxshadow : none;
|
6
|
+
--tooltip-color : white;
|
7
|
+
--tooltip-fontsize : 14px;
|
8
|
+
--tooltip-height : 24px;
|
9
|
+
--tooltip-padding : 2px 8px 0;
|
10
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
:root .neo-theme-neo-light { // .neo-tooltip
|
2
|
+
--tooltip-bg : white;
|
3
|
+
--tooltip-border : lightgrey;
|
4
|
+
--tooltip-borderradius : 4px;
|
5
|
+
--tooltip-boxshadow : none;
|
6
|
+
--tooltip-color : black;
|
7
|
+
--tooltip-fontsize : 14px;
|
8
|
+
--tooltip-height : 24px;
|
9
|
+
--tooltip-padding : 2px 8px 0;
|
10
|
+
}
|
@@ -45,28 +45,28 @@ $border-width : 1px;
|
|
45
45
|
--button-use-gradients : false;
|
46
46
|
|
47
47
|
// {module: Button; ui: --ghost}
|
48
|
-
--button-ghost-background-color : var(--button-
|
49
|
-
--button-ghost-background-color-active :
|
50
|
-
--button-ghost-background-color-disabled :
|
51
|
-
--button-ghost-background-color-hover : var(--button-
|
48
|
+
--button-ghost-background-color : var(--cmp-button-ghost-bg-default);
|
49
|
+
--button-ghost-background-color-active : var(--cmp-button-ghost-bg-active);
|
50
|
+
--button-ghost-background-color-disabled : var(--cmp-button-ghost-bg-disabled);
|
51
|
+
--button-ghost-background-color-hover : var(--cmp-button-ghost-bg-hover);
|
52
52
|
--button-ghost-background-image : none;
|
53
|
-
--button-ghost-badge-background-color :
|
54
|
-
--button-ghost-badge-color :
|
55
|
-
--button-ghost-border :
|
56
|
-
--button-ghost-border-active :
|
53
|
+
--button-ghost-badge-background-color : transparent;
|
54
|
+
--button-ghost-badge-color : transparent;
|
55
|
+
--button-ghost-border : none;
|
56
|
+
--button-ghost-border-active : none;
|
57
57
|
--button-ghost-border-disabled : inherit;
|
58
|
-
--button-ghost-border-hover :
|
59
|
-
--button-ghost-border-pressed :
|
60
|
-
--button-ghost-glyph-color : var(--button-
|
61
|
-
--button-ghost-glyph-color-active :
|
62
|
-
--button-ghost-glyph-color-disabled :
|
63
|
-
--button-ghost-glyph-color-hover :
|
64
|
-
--button-ghost-opacity-disabled :
|
58
|
+
--button-ghost-border-hover : none;
|
59
|
+
--button-ghost-border-pressed : none;
|
60
|
+
--button-ghost-glyph-color : var(--cmp-button-ghost-fg-default);
|
61
|
+
--button-ghost-glyph-color-active : inherit;
|
62
|
+
--button-ghost-glyph-color-disabled : var(--cmp-button-ghost-fg-disabled);
|
63
|
+
--button-ghost-glyph-color-hover : inherit;
|
64
|
+
--button-ghost-opacity-disabled : inherit;
|
65
65
|
--button-ghost-ripple-background-color : inherit;
|
66
|
-
--button-ghost-text-color : var(--button-
|
67
|
-
--button-ghost-text-color-active :
|
68
|
-
--button-ghost-text-color-disabled :
|
69
|
-
--button-ghost-text-color-hover :
|
66
|
+
--button-ghost-text-color : var(--cmp-button-ghost-fg-default);
|
67
|
+
--button-ghost-text-color-active : inherit;
|
68
|
+
--button-ghost-text-color-disabled : var(--cmp-button-ghost-fg-disabled);
|
69
|
+
--button-ghost-text-color-hover : inherit;
|
70
70
|
|
71
71
|
// {module: Button; ui: --secondary}
|
72
72
|
--button-secondary-background-color : var(--cmp-button-secondary-bg-default);
|
@@ -116,3 +116,7 @@ $border-width : 1px;
|
|
116
116
|
--button-tertiary-text-color-disabled : inherit;
|
117
117
|
--button-tertiary-text-color-hover : var(--button-text-color);
|
118
118
|
}
|
119
|
+
|
120
|
+
.neo-button {
|
121
|
+
min-width: var(--cmp-button-height);
|
122
|
+
}
|
@@ -70,4 +70,10 @@
|
|
70
70
|
--cmp-tab-unselected-bg-active : var(--sem-color-bg-neutral-active);
|
71
71
|
--cmp-tab-unselected-bg-default : transparent;
|
72
72
|
--cmp-tab-unselected-bg-hover : var(--sem-color-bg-neutral-hover);
|
73
|
+
|
74
|
+
--cmp-tooltip-bg : var(--sem-color-bg-neutral-contrast);
|
75
|
+
--cmp-tooltip-borderradius : var(--sem-borderradius-medium);
|
76
|
+
--cmp-tooltip-fg : var(--sem-color-fg-neutral-inverted);
|
77
|
+
--cmp-tooltip-height : var(--height-24);
|
78
|
+
--cmp-tooltip-spacinghorizontal : var(--sem-spacing-xsmall);
|
73
79
|
}
|
@@ -6,6 +6,7 @@
|
|
6
6
|
--core-fontfamily-mono : 'Source Code Pro';
|
7
7
|
--core-fontfamily-sans : 'Source Sans 3';
|
8
8
|
--core-fontfamily-serif : 'Source Serif Pro';
|
9
|
+
--core-fontsize-label : 1rem;
|
9
10
|
--core-fontsize-body : 16px;
|
10
11
|
--core-fontsize-h1 : 2.5rem;
|
11
12
|
--core-fontsize-h2 : 1.75rem;
|
@@ -42,6 +43,7 @@
|
|
42
43
|
--height-48 : 48px;
|
43
44
|
--height-56 : 56px;
|
44
45
|
--height-8 : 8px;
|
46
|
+
--height-24 : 24px;
|
45
47
|
--purple-100 : #efe3ff;
|
46
48
|
--purple-200 : #d0aaff;
|
47
49
|
--purple-300 : #b071ff;
|
@@ -3,11 +3,11 @@
|
|
3
3
|
--sem-borderradius-medium : var(--borderradius-4);
|
4
4
|
--sem-borderradius-none : var(--borderradius-0);
|
5
5
|
--sem-borderwidth-focus : 3px;
|
6
|
-
--sem-color-bg-neutral-active :
|
6
|
+
--sem-color-bg-neutral-active : rgba(0, 0, 0, .1);
|
7
7
|
--sem-color-bg-neutral-default : var(--gray-50);
|
8
8
|
--sem-color-bg-neutral-disabled : var(--gray-200);
|
9
9
|
--sem-color-bg-neutral-highlighted : var(--white);
|
10
|
-
--sem-color-bg-neutral-hover :
|
10
|
+
--sem-color-bg-neutral-hover :rgba(0, 0, 0, .05);
|
11
11
|
--sem-color-bg-primary-active : var(--green-600);
|
12
12
|
--sem-color-bg-primary-background : var(--green-50);
|
13
13
|
--sem-color-bg-primary-default : var(--green-400);
|
@@ -64,4 +64,6 @@
|
|
64
64
|
--sem-typo-label-regular-fontFamily : var(--core-fontfamily-sans);
|
65
65
|
--sem-typo-label-regular-fontSize : var(--core-fontsize-body);
|
66
66
|
--sem-typo-label-regular-fontWeight : var(--core-fontweight-regular);
|
67
|
+
--sem-color-bg-neutral-contrast : var(--gray-900);
|
68
|
+
--sem-color-fg-neutral-inverted : var(--white);
|
67
69
|
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
:root .neo-theme-neo-light { // .neo-tooltip
|
2
|
+
--tooltip-bg : var(--cmp-tooltip-bg);
|
3
|
+
--tooltip-border : none;
|
4
|
+
--tooltip-borderradius : var(--cmp-tooltip-borderradius);
|
5
|
+
--tooltip-boxshadow : none;
|
6
|
+
--tooltip-color : var(--cmp-tooltip-fg);
|
7
|
+
--tooltip-fontsize : 14px;
|
8
|
+
--tooltip-height : var(--cmp-tooltip-height);
|
9
|
+
--tooltip-padding : 2px var(--cmp-tooltip-spacinghorizontal) 0;
|
10
|
+
}
|
11
|
+
|
12
|
+
|
13
|
+
// 3px 3px 4px rgba(0,0,0, .6);
|
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.10.
|
239
|
+
* @default '6.10.4'
|
240
240
|
* @memberOf! module:Neo
|
241
241
|
* @name config.version
|
242
242
|
* @type String
|
243
243
|
*/
|
244
|
-
version: '6.10.
|
244
|
+
version: '6.10.4'
|
245
245
|
};
|
246
246
|
|
247
247
|
Object.assign(DefaultConfig, {
|
package/src/Main.mjs
CHANGED
package/src/component/Base.mjs
CHANGED
@@ -199,6 +199,12 @@ class Base extends CoreBase {
|
|
199
199
|
* @member {String|null} html_=null
|
200
200
|
*/
|
201
201
|
html_: null,
|
202
|
+
/**
|
203
|
+
* Set to `true` to show a spinner centered in the component.
|
204
|
+
* Set to a string to show a message next to a spinner centered in the component.
|
205
|
+
* @member {Boolean|String} isLoading=false
|
206
|
+
*/
|
207
|
+
isLoading_: false,
|
202
208
|
/**
|
203
209
|
* Internal flag which will get set to true while an update request (worker messages) is in progress
|
204
210
|
* @member {Boolean} isVdomUpdating=false
|
@@ -653,6 +659,48 @@ class Base extends CoreBase {
|
|
653
659
|
ComponentManager.register(this)
|
654
660
|
}
|
655
661
|
|
662
|
+
/**
|
663
|
+
* Triggered after the isLoading config got changed
|
664
|
+
* @param {Boolean|String} value
|
665
|
+
* @param {Boolean|String} oldValue
|
666
|
+
* @protected
|
667
|
+
*/
|
668
|
+
afterSetIsLoading(value, oldValue) {
|
669
|
+
if (!(value === false && oldValue === undefined)) {
|
670
|
+
let me = this,
|
671
|
+
{ cls, vdom } = me,
|
672
|
+
maskIndex;
|
673
|
+
|
674
|
+
if (oldValue !== undefined && vdom.cn) {
|
675
|
+
maskIndex = vdom.cn.findIndex(c => c.cls.includes('neo-load-mask'));
|
676
|
+
|
677
|
+
// Remove the load mask
|
678
|
+
if (maskIndex !== -1) {
|
679
|
+
vdom.cn.splice(maskIndex, 1)
|
680
|
+
}
|
681
|
+
}
|
682
|
+
|
683
|
+
if (value) {
|
684
|
+
vdom.cn.push(me.loadMask = {
|
685
|
+
cls: ['neo-load-mask'],
|
686
|
+
cn : [{
|
687
|
+
cls: ['neo-load-mask-body'],
|
688
|
+
cn : [{
|
689
|
+
cls: ['fa', 'fa-spinner', 'fa-spin']
|
690
|
+
}, {
|
691
|
+
cls : ['neo-loading-message'],
|
692
|
+
html : value,
|
693
|
+
removeDom: !Neo.isString(value)
|
694
|
+
}]
|
695
|
+
}]
|
696
|
+
})
|
697
|
+
}
|
698
|
+
|
699
|
+
NeoArray.toggle(cls, 'neo-masked', value);
|
700
|
+
me.set({cls, vdom})
|
701
|
+
}
|
702
|
+
}
|
703
|
+
|
656
704
|
/**
|
657
705
|
* Triggered after the maxHeight config got changed
|
658
706
|
* @param {Number|String|null} value
|
@@ -1231,8 +1279,12 @@ class Base extends CoreBase {
|
|
1231
1279
|
* Triggers all stored resolve() callbacks
|
1232
1280
|
*/
|
1233
1281
|
doResolveUpdateCache() {
|
1234
|
-
|
1235
|
-
|
1282
|
+
let me = this;
|
1283
|
+
|
1284
|
+
if (me.resolveUpdateCache) {
|
1285
|
+
me.resolveUpdateCache.forEach(item => item());
|
1286
|
+
me.resolveUpdateCache = []
|
1287
|
+
}
|
1236
1288
|
}
|
1237
1289
|
|
1238
1290
|
/**
|
@@ -1959,10 +2011,11 @@ class Base extends CoreBase {
|
|
1959
2011
|
resolve?.();
|
1960
2012
|
|
1961
2013
|
if (me.needsVdomUpdate) {
|
1962
|
-
|
2014
|
+
// if a new update is scheduled, we can clear the cache => these updates are included
|
2015
|
+
me.childUpdateCache = [];
|
1963
2016
|
|
1964
2017
|
me.update()
|
1965
|
-
} else {
|
2018
|
+
} else if (me.childUpdateCache) {
|
1966
2019
|
[...me.childUpdateCache].forEach(id => {
|
1967
2020
|
Neo.getComponent(id)?.update();
|
1968
2021
|
NeoArray.remove(me.childUpdateCache, id)
|
@@ -2133,16 +2186,7 @@ class Base extends CoreBase {
|
|
2133
2186
|
me._hidden = true; // silent update
|
2134
2187
|
me.mounted = false;
|
2135
2188
|
|
2136
|
-
Neo.
|
2137
|
-
action : 'updateDom',
|
2138
|
-
appName: me.appName,
|
2139
|
-
deltas : [{
|
2140
|
-
action: 'removeNode',
|
2141
|
-
id : me.vdom.id
|
2142
|
-
}]
|
2143
|
-
}).catch(err => {
|
2144
|
-
console.log('Error attempting to unmount component', err, me)
|
2145
|
-
})
|
2189
|
+
Neo.applyDeltas(me.appName, {action: 'removeNode', id: me.vdom.id})
|
2146
2190
|
}
|
2147
2191
|
|
2148
2192
|
/**
|
package/src/core/Observable.mjs
CHANGED
@@ -91,6 +91,21 @@ class Observable extends Base {
|
|
91
91
|
return null;
|
92
92
|
}
|
93
93
|
|
94
|
+
/**
|
95
|
+
* Call the passed function, or a function by *name* which exists in the passed scope's
|
96
|
+
* or this component's ownership chain.
|
97
|
+
* @param {Function|String} fn A function, or the name of a function to find in the passed scope object/
|
98
|
+
* @param {Object} scope The scope to find the function in if it is specified as a string.
|
99
|
+
* @param {Array} args Arguments to pass to the callback.
|
100
|
+
*/
|
101
|
+
callback(fn, scope=this, args) {
|
102
|
+
if (fn) {
|
103
|
+
const handler = this.resolveCallback(fn, scope);
|
104
|
+
|
105
|
+
handler.fn.apply(handler.scope, args);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
94
109
|
/**
|
95
110
|
* @param name
|
96
111
|
*/
|
@@ -127,21 +142,6 @@ class Observable extends Base {
|
|
127
142
|
}
|
128
143
|
}
|
129
144
|
|
130
|
-
/**
|
131
|
-
* Call the passed function, or a function by *name* which exists in the passed scope's
|
132
|
-
* or this component's ownership chain.
|
133
|
-
* @param {Function|String} fn A function, or the name of a function to find in the passed scope object/
|
134
|
-
* @param {Object} scope The scope to find the function in if it is specified as a string.
|
135
|
-
* @param {Array} args Arguments to pass to the callback.
|
136
|
-
*/
|
137
|
-
callback(fn, scope=this, args) {
|
138
|
-
if (fn) {
|
139
|
-
const handler = this.resolveCallback(fn, scope);
|
140
|
-
|
141
|
-
handler.fn.apply(handler.scope, args);
|
142
|
-
}
|
143
|
-
}
|
144
|
-
|
145
145
|
/**
|
146
146
|
* @param {Object} config
|
147
147
|
*/
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import Base from '../../core/Base.mjs';
|
2
2
|
|
3
3
|
/**
|
4
|
-
*
|
5
4
|
* @class Neo.main.addon.WindowPosition
|
6
5
|
* @extends Neo.core.Base
|
7
6
|
* @singleton
|
@@ -13,14 +12,22 @@ class WindowPosition extends Base {
|
|
13
12
|
* @protected
|
14
13
|
*/
|
15
14
|
className: 'Neo.main.addon.WindowPosition',
|
15
|
+
/**
|
16
|
+
* @member {Boolean} adjustWindowPositions=true
|
17
|
+
*/
|
18
|
+
adjustWindowPositions: true,
|
16
19
|
/**
|
17
20
|
* @member {String|null} intervalId=null
|
18
21
|
*/
|
19
22
|
intervalId: null,
|
20
23
|
/**
|
21
|
-
* @member {Number} intervalTime=
|
24
|
+
* @member {Number} intervalTime=20
|
22
25
|
*/
|
23
26
|
intervalTime: 20,
|
27
|
+
/**
|
28
|
+
* @member {Boolean} observeResize_=true
|
29
|
+
*/
|
30
|
+
observeResize_: true,
|
24
31
|
/**
|
25
32
|
* Remote method access for other workers
|
26
33
|
* @member {Object} remote
|
@@ -29,6 +36,7 @@ class WindowPosition extends Base {
|
|
29
36
|
remote: {
|
30
37
|
app: [
|
31
38
|
'registerWindow',
|
39
|
+
'setConfigs',
|
32
40
|
'setDock',
|
33
41
|
'unregisterWindow'
|
34
42
|
]
|
@@ -65,8 +73,21 @@ class WindowPosition extends Base {
|
|
65
73
|
me.screenLeft = win.screenLeft;
|
66
74
|
me.screenTop = win.screenTop;
|
67
75
|
|
68
|
-
win.addEventListener('mouseout', me.onMouseOut.bind(me))
|
69
|
-
|
76
|
+
win.addEventListener('mouseout', me.onMouseOut.bind(me))
|
77
|
+
}
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Triggered after the observeResize config got changed
|
81
|
+
* @param {Boolean} value
|
82
|
+
* @param {Boolean} oldValue
|
83
|
+
* @protected
|
84
|
+
*/
|
85
|
+
afterSetObserveResize(value, oldValue) {
|
86
|
+
let me = this;
|
87
|
+
|
88
|
+
if (value) {
|
89
|
+
window[value ? 'addEventListener' : 'removeEventListener']('resize', me.onResize.bind(me))
|
90
|
+
}
|
70
91
|
}
|
71
92
|
|
72
93
|
/**
|
@@ -82,8 +103,8 @@ class WindowPosition extends Base {
|
|
82
103
|
windowName: key,
|
83
104
|
x : position.left,
|
84
105
|
y : position.top
|
85
|
-
})
|
86
|
-
})
|
106
|
+
})
|
107
|
+
})
|
87
108
|
}
|
88
109
|
|
89
110
|
/**
|
@@ -100,7 +121,7 @@ class WindowPosition extends Base {
|
|
100
121
|
if (me.screenLeft !== screenLeft || me.screenTop !== screenTop) {
|
101
122
|
winData = Neo.Main.getWindowData();
|
102
123
|
|
103
|
-
me.adjustPositions();
|
124
|
+
me.adjustWindowPositions && me.adjustPositions();
|
104
125
|
|
105
126
|
Manager.sendMessage('app', {
|
106
127
|
action: 'windowPositionChange',
|
@@ -111,7 +132,7 @@ class WindowPosition extends Base {
|
|
111
132
|
});
|
112
133
|
|
113
134
|
me.screenLeft = screenLeft;
|
114
|
-
me.screenTop = screenTop
|
135
|
+
me.screenTop = screenTop
|
115
136
|
}
|
116
137
|
}
|
117
138
|
|
@@ -124,7 +145,7 @@ class WindowPosition extends Base {
|
|
124
145
|
*/
|
125
146
|
dockDirectionChange(oldValue, newValue) {
|
126
147
|
return (oldValue === 'bottom' || oldValue === 'top') && (newValue === 'left' || newValue === 'right')
|
127
|
-
|| (newValue === 'bottom' || newValue === 'top') && (oldValue === 'left' || oldValue === 'right')
|
148
|
+
|| (newValue === 'bottom' || newValue === 'top') && (oldValue === 'left' || oldValue === 'right')
|
128
149
|
}
|
129
150
|
|
130
151
|
/**
|
@@ -134,29 +155,26 @@ class WindowPosition extends Base {
|
|
134
155
|
let win = window,
|
135
156
|
left, top;
|
136
157
|
|
137
|
-
switch
|
158
|
+
switch(data.dock) {
|
138
159
|
case 'bottom':
|
139
160
|
left = win.screenLeft;
|
140
161
|
top = win.outerHeight + win.screenTop - 50;
|
141
|
-
break
|
162
|
+
break
|
142
163
|
case 'left':
|
143
164
|
left = win.screenLeft - data.size;
|
144
165
|
top = win.screenTop + 28;
|
145
|
-
break
|
166
|
+
break
|
146
167
|
case 'right':
|
147
168
|
left = win.outerWidth + win.screenLeft;
|
148
169
|
top = win.screenTop + 28;
|
149
|
-
break
|
170
|
+
break
|
150
171
|
case 'top':
|
151
172
|
left = win.screenLeft;
|
152
173
|
top = win.screenTop - data.size + 78;
|
153
|
-
break
|
174
|
+
break
|
154
175
|
}
|
155
176
|
|
156
|
-
return {
|
157
|
-
left: left,
|
158
|
-
top : top
|
159
|
-
};
|
177
|
+
return {left, top}
|
160
178
|
}
|
161
179
|
|
162
180
|
/**
|
@@ -167,11 +185,11 @@ class WindowPosition extends Base {
|
|
167
185
|
|
168
186
|
if (!event.toElement) {
|
169
187
|
if (!me.intervalId) {
|
170
|
-
me.intervalId = setInterval(me.checkMovement.bind(me), me.intervalTime)
|
188
|
+
me.intervalId = setInterval(me.checkMovement.bind(me), me.intervalTime)
|
171
189
|
}
|
172
190
|
} else if (me.intervalId) {
|
173
191
|
clearInterval(me.intervalId);
|
174
|
-
me.intervalId = null
|
192
|
+
me.intervalId = null
|
175
193
|
}
|
176
194
|
}
|
177
195
|
|
@@ -188,21 +206,21 @@ class WindowPosition extends Base {
|
|
188
206
|
case 'bottom':
|
189
207
|
case 'top':
|
190
208
|
width = win.outerWidth;
|
191
|
-
break
|
209
|
+
break
|
192
210
|
case 'left':
|
193
211
|
case 'right':
|
194
212
|
height = win.outerHeight - 28;
|
195
|
-
break
|
213
|
+
break
|
196
214
|
}
|
197
215
|
|
198
216
|
Neo.Main.windowResizeTo({
|
199
217
|
height : height,
|
200
218
|
width : width,
|
201
219
|
windowName: key
|
202
|
-
})
|
220
|
+
})
|
203
221
|
});
|
204
222
|
|
205
|
-
me.adjustPositions()
|
223
|
+
me.adjustWindowPositions && me.adjustPositions()
|
206
224
|
}
|
207
225
|
|
208
226
|
/**
|
@@ -212,7 +230,17 @@ class WindowPosition extends Base {
|
|
212
230
|
* @param {Number} data.size
|
213
231
|
*/
|
214
232
|
registerWindow(data) {
|
215
|
-
this.windows[data.name] = data
|
233
|
+
this.windows[data.name] = data
|
234
|
+
}
|
235
|
+
|
236
|
+
/**
|
237
|
+
* Set configs from within the app worker
|
238
|
+
* @param {Object} data
|
239
|
+
* @param {String} data.appName
|
240
|
+
*/
|
241
|
+
setConfigs(data) {
|
242
|
+
delete data.appName;
|
243
|
+
this.set(data)
|
216
244
|
}
|
217
245
|
|
218
246
|
/**
|
@@ -239,14 +267,14 @@ class WindowPosition extends Base {
|
|
239
267
|
height : dock === 'bottom' || dock === 'top' ? win.size : window.outerHeight - 28,
|
240
268
|
width : dock === 'left' || dock === 'right' ? win.size : window.outerWidth,
|
241
269
|
windowName: name
|
242
|
-
})
|
270
|
+
})
|
243
271
|
}
|
244
272
|
|
245
273
|
Neo.Main.windowMoveTo({
|
246
274
|
windowName: name,
|
247
275
|
x : position.left,
|
248
276
|
y : position.top
|
249
|
-
})
|
277
|
+
})
|
250
278
|
}
|
251
279
|
}
|
252
280
|
|
@@ -255,7 +283,7 @@ class WindowPosition extends Base {
|
|
255
283
|
* @param {String} data.name
|
256
284
|
*/
|
257
285
|
unregisterWindow(data) {
|
258
|
-
delete this.windows[data.name]
|
286
|
+
delete this.windows[data.name]
|
259
287
|
}
|
260
288
|
}
|
261
289
|
|
package/src/util/Array.mjs
CHANGED
@@ -117,18 +117,8 @@ class NeoArray extends Base {
|
|
117
117
|
* @param {*} item
|
118
118
|
* @param {Boolean} [add]
|
119
119
|
*/
|
120
|
-
static toggle(arr, item, add) {
|
121
|
-
|
122
|
-
|
123
|
-
if (add === true) {
|
124
|
-
operation = 'add';
|
125
|
-
} else if (add === false) {
|
126
|
-
operation = 'remove';
|
127
|
-
} else {
|
128
|
-
operation = this.hasItem(arr, item) ? 'remove' : 'add';
|
129
|
-
}
|
130
|
-
|
131
|
-
this[operation](arr, item);
|
120
|
+
static toggle(arr, item, add = !this.hasItem(arr, item)) {
|
121
|
+
this[add ? 'add' : 'remove'](arr, item);
|
132
122
|
}
|
133
123
|
|
134
124
|
/**
|
package/src/worker/App.mjs
CHANGED
@@ -29,6 +29,7 @@ class App extends Base {
|
|
29
29
|
main: [
|
30
30
|
'createNeoInstance',
|
31
31
|
'destroyNeoInstance',
|
32
|
+
'fireEvent',
|
32
33
|
'setConfigs'
|
33
34
|
]
|
34
35
|
},
|
@@ -107,16 +108,22 @@ class App extends Base {
|
|
107
108
|
* }).then(id => console.log(id))
|
108
109
|
*
|
109
110
|
* @param {Object} config
|
111
|
+
* @param {String} [config.importPath] you can lazy load missing classes via this config. dev mode only.
|
110
112
|
* @param {String} [config.parentId] passing a parentId will put your instance into a container
|
111
113
|
* @param {Number} [config.parentIndex] if a parentId is passed, but no index, neo will use add()
|
112
114
|
* @returns {String} the instance id
|
113
115
|
*/
|
114
|
-
createNeoInstance(config) {
|
116
|
+
async createNeoInstance(config) {
|
117
|
+
if (config.importPath) {
|
118
|
+
await import(/* webpackIgnore: true */ config.importPath);
|
119
|
+
delete config.importPath
|
120
|
+
}
|
121
|
+
|
115
122
|
let appName = Object.keys(Neo.apps)[0], // fallback in case no appName was provided
|
116
123
|
Container = Neo.container?.Base,
|
117
124
|
index, instance, parent;
|
118
125
|
|
119
|
-
config = {appName
|
126
|
+
config = {appName, ...config};
|
120
127
|
|
121
128
|
if (config.parentId) {
|
122
129
|
parent = Neo.getComponent(config.parentId);
|
@@ -183,6 +190,30 @@ class App extends Base {
|
|
183
190
|
return false
|
184
191
|
}
|
185
192
|
|
193
|
+
/**
|
194
|
+
* Fires a custom event based on core.Observable on any app realm based Neo instance from main
|
195
|
+
* @param {Object} data
|
196
|
+
* @param {String} data.id
|
197
|
+
* @param {String} data.name
|
198
|
+
*/
|
199
|
+
fireEvent(data) {
|
200
|
+
let instance = Neo.get(data.id),
|
201
|
+
name;
|
202
|
+
|
203
|
+
if (instance) {
|
204
|
+
name = data.name;
|
205
|
+
|
206
|
+
delete data.id;
|
207
|
+
delete data.name;
|
208
|
+
|
209
|
+
instance.fire(name, data);
|
210
|
+
|
211
|
+
return true
|
212
|
+
}
|
213
|
+
|
214
|
+
return false
|
215
|
+
}
|
216
|
+
|
186
217
|
/**
|
187
218
|
* Only needed for the SharedWorkers context
|
188
219
|
* @param {String} eventName
|
@@ -190,7 +221,7 @@ class App extends Base {
|
|
190
221
|
*/
|
191
222
|
fireMainViewsEvent(eventName, data) {
|
192
223
|
this.ports.forEach(port => {
|
193
|
-
Neo.apps[port.appName].
|
224
|
+
Neo.apps[port.appName].mainView.fire(eventName, data)
|
194
225
|
})
|
195
226
|
}
|
196
227
|
|
package/src/worker/Canvas.mjs
CHANGED
@@ -45,7 +45,7 @@ class Canvas extends Base {
|
|
45
45
|
|
46
46
|
me.sendMessage('app', {action: 'registerPort', transfer: port2}, [port2]);
|
47
47
|
|
48
|
-
me.channelPorts.app = port1
|
48
|
+
me.channelPorts.app = port1
|
49
49
|
}
|
50
50
|
|
51
51
|
/**
|
@@ -58,7 +58,7 @@ class Canvas extends Base {
|
|
58
58
|
action : 'reply',
|
59
59
|
replyId: data.id,
|
60
60
|
success: true
|
61
|
-
})
|
61
|
+
})
|
62
62
|
}
|
63
63
|
|
64
64
|
/**
|
@@ -75,8 +75,8 @@ class Canvas extends Base {
|
|
75
75
|
/* webpackMode: "lazy" */
|
76
76
|
`../../${path}/canvas.mjs`
|
77
77
|
).then(module => {
|
78
|
-
module.onStart()
|
79
|
-
})
|
78
|
+
module.onStart()
|
79
|
+
})
|
80
80
|
}
|
81
81
|
}
|
82
82
|
|
@@ -1,17 +1,44 @@
|
|
1
1
|
StartTest(t => {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
2
|
+
let button;
|
3
|
+
|
4
|
+
t.beforeEach(async t => {
|
5
|
+
button && await Neo.worker.App.destroyNeoInstance(button);
|
6
|
+
});
|
7
|
+
|
8
|
+
t.it('Sanity', async t => {
|
9
|
+
button = await Neo.worker.App.createNeoInstance({
|
10
|
+
ntype : 'button',
|
11
|
+
iconCls: 'fa fa-home',
|
12
|
+
text : 'Hello Siesta'
|
13
|
+
});
|
14
|
+
});
|
15
|
+
|
16
|
+
t.it('Should show isLoading UI', async t => {
|
17
|
+
button = await Neo.worker.App.createNeoInstance({
|
18
|
+
ntype : 'button',
|
19
|
+
iconCls : 'fa fa-home',
|
20
|
+
text : 'Hello Siesta',
|
21
|
+
isLoading : 'Loading...'
|
22
|
+
});
|
23
|
+
|
24
|
+
// Spinner and text exist
|
25
|
+
await t.waitForSelector('button .fa-spinner.fa-spin');
|
26
|
+
t.selectorExists('button .neo-loading-message:contains(Loading...)');
|
27
|
+
|
28
|
+
await Neo.worker.App.setConfigs({ id: button, isLoading : true });
|
29
|
+
|
30
|
+
// Just a spinner now, no text
|
31
|
+
await t.waitForSelectorNotFound('button .neo-loading-message:contains(Loading...)');
|
32
|
+
t.selectorExists('button .fa-spinner');
|
33
|
+
|
34
|
+
await Neo.worker.App.setConfigs({ id: button, isLoading : 'New loading message' });
|
35
|
+
|
36
|
+
await t.waitForSelector('button .neo-loading-message:contains(New loading message)');
|
37
|
+
t.selectorExists('button .fa-spinner.fa-spin');
|
38
|
+
|
39
|
+
await Neo.worker.App.setConfigs({ id: button, isLoading : false });
|
40
|
+
|
41
|
+
// Not loading now
|
42
|
+
await t.waitForSelectorNotFound('button .fa-spinner');
|
16
43
|
});
|
17
44
|
});
|
@@ -1,35 +1,27 @@
|
|
1
1
|
StartTest(t => {
|
2
|
-
t.it('
|
3
|
-
|
4
|
-
|
2
|
+
t.it('Sanity', async t => {
|
3
|
+
Neo.worker.App.createNeoInstance({
|
4
|
+
ntype : 'selectfield',
|
5
|
+
labelPosition: 'inline',
|
6
|
+
labelText : 'US States',
|
7
|
+
labelWidth : 80,
|
8
|
+
width : 300,
|
5
9
|
|
6
|
-
|
7
|
-
|
10
|
+
store : {
|
11
|
+
autoLoad : true,
|
12
|
+
keyProperty: 'abbreviation',
|
13
|
+
url : '../../resources/examples/data/us_states.json',
|
8
14
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
store : {
|
18
|
-
autoLoad : true,
|
19
|
-
keyProperty: 'abbreviation',
|
20
|
-
url : '../../resources/examples/data/us_states.json',
|
21
|
-
|
22
|
-
model: {
|
23
|
-
fields: [{
|
24
|
-
name: 'abbreviation',
|
25
|
-
type: 'string'
|
26
|
-
}, {
|
27
|
-
name: 'name',
|
28
|
-
type: 'string'
|
29
|
-
}]
|
30
|
-
}
|
15
|
+
model: {
|
16
|
+
fields: [{
|
17
|
+
name: 'abbreviation',
|
18
|
+
type: 'string'
|
19
|
+
}, {
|
20
|
+
name: 'name',
|
21
|
+
type: 'string'
|
22
|
+
}]
|
31
23
|
}
|
32
|
-
}
|
33
|
-
}
|
24
|
+
}
|
25
|
+
});
|
34
26
|
});
|
35
27
|
});
|
@@ -1,8 +1,38 @@
|
|
1
1
|
const project = new Siesta.Project.Browser();
|
2
2
|
|
3
3
|
project.configure({
|
4
|
-
title
|
5
|
-
isEcmaModule: true
|
4
|
+
title : 'Neo Component Tests',
|
5
|
+
isEcmaModule : true,
|
6
|
+
preload : [{
|
7
|
+
type : 'js',
|
8
|
+
url : '../../src/MicroLoader.mjs',
|
9
|
+
isEcmaModule : true
|
10
|
+
}],
|
11
|
+
testClass : Class('My.Test.Class', {
|
12
|
+
isa : Siesta.Test.Browser,
|
13
|
+
override : {
|
14
|
+
setup(callback, errback) {
|
15
|
+
this.SUPER(function() {
|
16
|
+
// We need to call the startup callback only when we know we are
|
17
|
+
// ready to start testing.
|
18
|
+
const
|
19
|
+
{ global } = this,
|
20
|
+
startupTimer = setInterval(() => {
|
21
|
+
if (global.Neo?.worker?.App && global.Neo.worker.Manager && global.Neo.Main) {
|
22
|
+
clearInterval(startupTimer);
|
23
|
+
|
24
|
+
// TODO: Find what we actually need to wait for
|
25
|
+
setTimeout(callback, 300);
|
26
|
+
}
|
27
|
+
}, 100);
|
28
|
+
}, errback);
|
29
|
+
},
|
30
|
+
async beforeEach() {
|
31
|
+
this.SUPER(...arguments);
|
32
|
+
this.SUPER(t => t.waitFor(50));
|
33
|
+
}
|
34
|
+
}
|
35
|
+
})
|
6
36
|
});
|
7
37
|
|
8
38
|
project.plan(
|