neo.mjs 5.10.4 → 5.10.6
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/examples/ServiceWorker.mjs +2 -2
- package/examples/component/progress/MainContainer.mjs +71 -0
- package/examples/component/progress/app.mjs +6 -0
- package/examples/component/progress/index.html +11 -0
- package/examples/component/progress/neo-config.json +6 -0
- package/package.json +7 -7
- package/resources/scss/src/component/Progress.scss +3 -0
- package/resources/scss/src/container/Dialog.scss +11 -1
- package/resources/scss/theme-dark/component/Progress.scss +9 -0
- package/resources/scss/theme-light/component/Progress.scss +9 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/component/Progress.mjs +113 -0
- package/src/container/Dialog.mjs +37 -54
- package/src/form/field/TextArea.mjs +3 -2
- package/src/main/DomEvents.mjs +2 -1
- package/src/util/String.mjs +56 -0
package/apps/ServiceWorker.mjs
CHANGED
@@ -0,0 +1,71 @@
|
|
1
|
+
import ConfigurationViewport from '../../ConfigurationViewport.mjs';
|
2
|
+
import NumberField from '../../../src/form/field/Number.mjs';
|
3
|
+
import Progress from '../../../src/component/Progress.mjs';
|
4
|
+
import TextField from '../../../src/form/field/Text.mjs';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* @class Neo.examples.component.progress.MainContainer
|
8
|
+
* @extends Neo.examples.ConfigurationViewport
|
9
|
+
*/
|
10
|
+
class MainContainer extends ConfigurationViewport {
|
11
|
+
static config = {
|
12
|
+
className : 'Neo.examples.component.progress.MainContainer',
|
13
|
+
autoMount : true,
|
14
|
+
configItemLabelWidth: 110,
|
15
|
+
configItemWidth : 230,
|
16
|
+
layout : {ntype: 'hbox', align: 'stretch'}
|
17
|
+
}
|
18
|
+
|
19
|
+
createConfigurationComponents() {
|
20
|
+
let me = this;
|
21
|
+
|
22
|
+
return [{
|
23
|
+
module : NumberField,
|
24
|
+
clearable : true,
|
25
|
+
labelText : 'height',
|
26
|
+
listeners : {change: me.onConfigChange.bind(me, 'height')},
|
27
|
+
maxValue : 100,
|
28
|
+
minValue : 20,
|
29
|
+
stepSize : 2,
|
30
|
+
style : {marginTop: '10px'},
|
31
|
+
value : me.exampleComponent.height
|
32
|
+
}, {
|
33
|
+
module : TextField,
|
34
|
+
clearable : true,
|
35
|
+
labelText : 'labelText',
|
36
|
+
listeners : {change: me.onConfigChange.bind(me, 'labelText')},
|
37
|
+
style : {marginTop: '10px'},
|
38
|
+
value : me.exampleComponent.labelText
|
39
|
+
}, {
|
40
|
+
module : NumberField,
|
41
|
+
clearable : true,
|
42
|
+
labelText : 'width',
|
43
|
+
listeners : {change: me.onConfigChange.bind(me, 'width')},
|
44
|
+
maxValue : 300,
|
45
|
+
minValue : 100,
|
46
|
+
stepSize : 5,
|
47
|
+
value : me.exampleComponent.width
|
48
|
+
}, {
|
49
|
+
module : NumberField,
|
50
|
+
clearable : true,
|
51
|
+
labelText : 'value',
|
52
|
+
listeners : {change: me.onConfigChange.bind(me, 'value')},
|
53
|
+
maxValue : 100,
|
54
|
+
minValue : 0,
|
55
|
+
value : me.exampleComponent.value
|
56
|
+
}];
|
57
|
+
}
|
58
|
+
|
59
|
+
createExampleComponent() {
|
60
|
+
return Neo.create({
|
61
|
+
module : Progress,
|
62
|
+
height : 30,
|
63
|
+
labelText: 'Hello World',
|
64
|
+
value : 40
|
65
|
+
});
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
Neo.applyClassConfig(MainContainer);
|
70
|
+
|
71
|
+
export default MainContainer;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!DOCTYPE HTML>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
<title>Neo Progress</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<script src="../../../src/MicroLoader.mjs" type="module"></script>
|
10
|
+
</body>
|
11
|
+
</html>
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "neo.mjs",
|
3
|
-
"version": "5.10.
|
3
|
+
"version": "5.10.6",
|
4
4
|
"description": "The webworkers driven UI framework",
|
5
5
|
"type": "module",
|
6
6
|
"repository": {
|
@@ -52,14 +52,14 @@
|
|
52
52
|
"envinfo": "^7.8.1",
|
53
53
|
"fs-extra": "^11.1.1",
|
54
54
|
"highlightjs-line-numbers.js": "^2.8.0",
|
55
|
-
"inquirer": "^9.2.
|
55
|
+
"inquirer": "^9.2.7",
|
56
56
|
"neo-jsdoc": "^1.0.1",
|
57
57
|
"neo-jsdoc-x": "^1.0.5",
|
58
|
-
"postcss": "^8.4.
|
59
|
-
"sass": "
|
60
|
-
"webpack": "^5.
|
61
|
-
"webpack-cli": "^5.1.
|
62
|
-
"webpack-dev-server": "4.15.
|
58
|
+
"postcss": "^8.4.24",
|
59
|
+
"sass": "1.62.1",
|
60
|
+
"webpack": "^5.86.0",
|
61
|
+
"webpack-cli": "^5.1.4",
|
62
|
+
"webpack-dev-server": "4.15.1",
|
63
63
|
"webpack-hook-plugin": "^1.0.7",
|
64
64
|
"webpack-node-externals": "^3.0.0"
|
65
65
|
},
|
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 '5.10.
|
239
|
+
* @default '5.10.6'
|
240
240
|
* @memberOf! module:Neo
|
241
241
|
* @name config.version
|
242
242
|
* @type String
|
243
243
|
*/
|
244
|
-
version: '5.10.
|
244
|
+
version: '5.10.6'
|
245
245
|
};
|
246
246
|
|
247
247
|
Object.assign(DefaultConfig, {
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import Base from '../component/Base.mjs';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @class Neo.component.Progress
|
5
|
+
* @extends Neo.component.Base
|
6
|
+
*/
|
7
|
+
class Progress extends Base {
|
8
|
+
static config = {
|
9
|
+
/**
|
10
|
+
* @member {String} className='Neo.component.Progress'
|
11
|
+
* @protected
|
12
|
+
*/
|
13
|
+
className: 'Neo.component.Progress',
|
14
|
+
/**
|
15
|
+
* @member {String} ntype='progress'
|
16
|
+
* @protected
|
17
|
+
*/
|
18
|
+
ntype: 'progress',
|
19
|
+
/**
|
20
|
+
* @member {String[]} baseCls=['neo-progress-label']
|
21
|
+
* @protected
|
22
|
+
*/
|
23
|
+
baseCls: ['neo-progress'],
|
24
|
+
/**
|
25
|
+
* @member {String|null} labelText_=null
|
26
|
+
*/
|
27
|
+
labelText_: null,
|
28
|
+
/**
|
29
|
+
* @member {Number} max_=100
|
30
|
+
*/
|
31
|
+
max_: 100,
|
32
|
+
/**
|
33
|
+
* @member {Number|null} value_=null
|
34
|
+
*/
|
35
|
+
value_: null,
|
36
|
+
/**
|
37
|
+
* @member {Object} _vdom
|
38
|
+
*/
|
39
|
+
_vdom:
|
40
|
+
{tag: 'div', cls: ['neo-progress'], cn: [
|
41
|
+
{tag: 'label'},
|
42
|
+
{tag: 'progress'}
|
43
|
+
]}
|
44
|
+
}
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Triggered after the id config got changed
|
48
|
+
* @param {String} value
|
49
|
+
* @param {String} oldValue
|
50
|
+
* @protected
|
51
|
+
*/
|
52
|
+
afterSetId(value, oldValue) {
|
53
|
+
super.afterSetId(value, oldValue);
|
54
|
+
|
55
|
+
this.vdom.cn[0].for = value;
|
56
|
+
this.update()
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Triggered after the labelText config got changed
|
61
|
+
* @param {String|null} value
|
62
|
+
* @param {String|null} oldValue
|
63
|
+
* @protected
|
64
|
+
*/
|
65
|
+
afterSetLabelText(value, oldValue) {
|
66
|
+
this.vdom.cn[0].html = value;
|
67
|
+
this.update()
|
68
|
+
}
|
69
|
+
|
70
|
+
/**
|
71
|
+
* Triggered after the max config got changed
|
72
|
+
* @param {Number} value
|
73
|
+
* @param {Number} oldValue
|
74
|
+
* @protected
|
75
|
+
*/
|
76
|
+
afterSetMax(value, oldValue) {
|
77
|
+
this.vdom.cn[1].max = value;
|
78
|
+
this.update()
|
79
|
+
}
|
80
|
+
|
81
|
+
/**
|
82
|
+
* Triggered after the value config got changed
|
83
|
+
* @param {Number|null} value
|
84
|
+
* @param {Number|null} oldValue
|
85
|
+
* @protected
|
86
|
+
*/
|
87
|
+
afterSetValue(value, oldValue) {
|
88
|
+
this.vdom.cn[1].value = value;
|
89
|
+
this.update()
|
90
|
+
}
|
91
|
+
|
92
|
+
/**
|
93
|
+
* Specify a different vdom root if needed to apply the top level style attributes on a different level.
|
94
|
+
* Make sure to use getVnodeRoot() as well, to keep the vdom & vnode trees in sync.
|
95
|
+
* @returns {Object} The new vdom root
|
96
|
+
*/
|
97
|
+
getVdomRoot() {
|
98
|
+
return this.vdom.cn[1]
|
99
|
+
}
|
100
|
+
|
101
|
+
/**
|
102
|
+
* Specify a different vnode root if needed to apply the top level style attributes on a different level.
|
103
|
+
* Make sure to use getVdomRoot() as well, to keep the vdom & vnode trees in sync.
|
104
|
+
* @returns {Object} The new vnode root
|
105
|
+
*/
|
106
|
+
getVnodeRoot() {
|
107
|
+
return this.vnode.childNodes[1]
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
Neo.applyClassConfig(Progress);
|
112
|
+
|
113
|
+
export default Progress;
|
package/src/container/Dialog.mjs
CHANGED
@@ -21,9 +21,17 @@ class Dialog extends Base {
|
|
21
21
|
*/
|
22
22
|
ntype: 'container-dialog',
|
23
23
|
/**
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
* @member {Boolean} autoMount=true
|
25
|
+
*/
|
26
|
+
autoMount: true,
|
27
|
+
/**
|
28
|
+
* @member {Boolean} autoRender=true
|
29
|
+
*/
|
30
|
+
autoRender: true,
|
31
|
+
/**
|
32
|
+
* @member {String[]} baseCls=['neo-container-dialog', 'neo-panel', 'neo-container']
|
33
|
+
* @protected
|
34
|
+
*/
|
27
35
|
baseCls: ['neo-container-dialog', 'neo-panel', 'neo-container'],
|
28
36
|
/**
|
29
37
|
* @member {Object} headerConfig=null
|
@@ -34,10 +42,16 @@ class Dialog extends Base {
|
|
34
42
|
*/
|
35
43
|
headerToolbar: null,
|
36
44
|
/**
|
37
|
-
* The CSS class to use for an icon, e.g. 'fa fa-home'
|
38
|
-
* @member {String
|
45
|
+
* The CSS class to use for an icon, e.g. ['fa', 'fa-home']
|
46
|
+
* @member {String[]} [iconCls_=null]
|
39
47
|
*/
|
40
48
|
iconCls_: null,
|
49
|
+
/**
|
50
|
+
* @member {Object} itemDefaults
|
51
|
+
*/
|
52
|
+
itemDefaults: {
|
53
|
+
baseCls: ['neo-dialog-content']
|
54
|
+
},
|
41
55
|
/**
|
42
56
|
* @member {Object[]} items
|
43
57
|
*/
|
@@ -68,11 +82,9 @@ class Dialog extends Base {
|
|
68
82
|
* @protected
|
69
83
|
*/
|
70
84
|
afterSetIconCls(value, oldValue) {
|
71
|
-
console.log(value, oldValue)
|
72
|
-
|
73
85
|
if (!this.headers) { return }
|
74
|
-
let iconNode
|
75
|
-
|
86
|
+
let iconNode = this.headers.down({flag: 'dialog-header-icon'}),
|
87
|
+
iconNodeCls = [...iconNode.cls];
|
76
88
|
|
77
89
|
NeoArray.remove(iconNodeCls, oldValue);
|
78
90
|
NeoArray.add( iconNodeCls, value);
|
@@ -90,41 +102,11 @@ class Dialog extends Base {
|
|
90
102
|
* @protected
|
91
103
|
*/
|
92
104
|
afterSetTitle(value, oldValue) {
|
93
|
-
this.headerToolbar?.set({
|
94
|
-
|
105
|
+
this.headerToolbar?.down({flag: 'panel-header-title'}).set({
|
106
|
+
text: value
|
95
107
|
});
|
96
108
|
}
|
97
109
|
|
98
|
-
/**
|
99
|
-
* Converts the iconCls array into a string on beforeGet
|
100
|
-
* @returns {String}
|
101
|
-
* @protected
|
102
|
-
*/
|
103
|
-
beforeGetIconCls() {
|
104
|
-
let iconCls = this._iconCls;
|
105
|
-
|
106
|
-
if (Array.isArray(iconCls)) {
|
107
|
-
return iconCls.join(' ');
|
108
|
-
}
|
109
|
-
|
110
|
-
return iconCls;
|
111
|
-
}
|
112
|
-
|
113
|
-
/**
|
114
|
-
* Triggered before the iconCls config gets changed. Converts the string into an array if needed.
|
115
|
-
* @param {Array|String|null} value
|
116
|
-
* @param {Array|String|null} oldValue
|
117
|
-
* @returns {Array}
|
118
|
-
* @protected
|
119
|
-
*/
|
120
|
-
beforeSetIconCls(value, oldValue) {
|
121
|
-
if (value && !Array.isArray(value)) {
|
122
|
-
value = value.split(' ').filter(Boolean);
|
123
|
-
}
|
124
|
-
|
125
|
-
return value;
|
126
|
-
}
|
127
|
-
|
128
110
|
/**
|
129
111
|
* close the dialog in main thread
|
130
112
|
*/
|
@@ -141,15 +123,15 @@ class Dialog extends Base {
|
|
141
123
|
* @protected
|
142
124
|
*/
|
143
125
|
createHeader() {
|
144
|
-
let me
|
145
|
-
cls
|
146
|
-
headers
|
126
|
+
let me = this,
|
127
|
+
cls = ['neo-header-toolbar', 'neo-toolbar'],
|
128
|
+
headers = me.headers || [],
|
147
129
|
headerConfigCopy = {...me.headerConfig};
|
148
130
|
delete headerConfigCopy.items;
|
149
131
|
|
150
132
|
me.headerToolbar = Neo.create({
|
151
133
|
module : HeaderToolbar,
|
152
|
-
actions: [{action: 'close', iconCls: 'fa-solid fa-xmark'}],
|
134
|
+
actions : [{action: 'close', iconCls: 'fa-solid fa-xmark'}],
|
153
135
|
appName : me.appName,
|
154
136
|
cls,
|
155
137
|
dock : 'top',
|
@@ -157,15 +139,16 @@ class Dialog extends Base {
|
|
157
139
|
id : me.getHeaderToolbarId(),
|
158
140
|
listeners: {headerAction: me.executeHeaderAction, scope: me},
|
159
141
|
items : [{
|
160
|
-
|
161
|
-
|
142
|
+
ntype: '',
|
143
|
+
cls : ['neo-dialog-header-icon', ...me.iconCls],
|
144
|
+
flag : 'dialog-header-icon',
|
162
145
|
}, {
|
163
|
-
ntype
|
164
|
-
cls
|
165
|
-
flag
|
166
|
-
|
167
|
-
text
|
168
|
-
}, ...me.headerConfig.items],
|
146
|
+
ntype : 'label',
|
147
|
+
cls : ['neo-panel-header-text', 'neo-label'],
|
148
|
+
flag : 'panel-header-title',
|
149
|
+
hidden: !me.title,
|
150
|
+
text : me.title
|
151
|
+
}, ...me.headerConfig.items || []],
|
169
152
|
|
170
153
|
...headerConfigCopy
|
171
154
|
});
|
@@ -182,7 +165,7 @@ class Dialog extends Base {
|
|
182
165
|
let me = this,
|
183
166
|
|
184
167
|
map = {
|
185
|
-
close
|
168
|
+
close: me.close
|
186
169
|
};
|
187
170
|
|
188
171
|
map[data.action]?.call(me, data);
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import
|
1
|
+
import StringUtil from '../../util/String.mjs';
|
2
|
+
import Text from './Text.mjs';
|
2
3
|
|
3
4
|
/**
|
4
5
|
*
|
@@ -121,7 +122,7 @@ class TextArea extends Text {
|
|
121
122
|
let inputEl = this.getInputEl();
|
122
123
|
|
123
124
|
if (inputEl) {
|
124
|
-
inputEl.html = value;
|
125
|
+
inputEl.html = StringUtil.escapeHtml(value);
|
125
126
|
}
|
126
127
|
|
127
128
|
super.afterSetValue(value, oldValue);
|
package/src/main/DomEvents.mjs
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import Base from '../core/Base.mjs';
|
2
2
|
import Observable from '../core/Observable.mjs';
|
3
|
+
import StringUtil from '../util/String.mjs';
|
3
4
|
import TouchDomEvents from './mixin/TouchDomEvents.mjs';
|
4
5
|
|
5
6
|
const globalDomEvents = [
|
@@ -415,7 +416,7 @@ class DomEvents extends Base {
|
|
415
416
|
data = {
|
416
417
|
...this.getEventData(event),
|
417
418
|
valid: target.checkValidity(),
|
418
|
-
value: target.value
|
419
|
+
value: (target.tagName === 'INPUT') ? StringUtil.escapeHtml(target.value) : target.value
|
419
420
|
};
|
420
421
|
|
421
422
|
// input and change events can pass a FileList for input type file
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import Base from '../core/Base.mjs';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @class Neo.util.StringUtil
|
5
|
+
* @extends Neo.core.Base
|
6
|
+
*/
|
7
|
+
class StringUtil extends Base {
|
8
|
+
static config = {
|
9
|
+
/**
|
10
|
+
* @member {String} className='Neo.util.StringUtil'
|
11
|
+
* @protected
|
12
|
+
*/
|
13
|
+
className: 'Neo.util.StringUtil'
|
14
|
+
}
|
15
|
+
|
16
|
+
static escapedChars = {
|
17
|
+
'&': '&',
|
18
|
+
'<': '<',
|
19
|
+
'>': '>',
|
20
|
+
'"': '"',
|
21
|
+
'\'': '''
|
22
|
+
}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Escape HTML special characters
|
26
|
+
* @param {String} value
|
27
|
+
*/
|
28
|
+
static escapeHtml(value) {
|
29
|
+
if (Neo.typeOf(value) !== 'String') {
|
30
|
+
return value;
|
31
|
+
}
|
32
|
+
|
33
|
+
return value.replace(/[&<>"']/g, (char) => this.escapedChars[char] || char);
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Unescape HTML special characters
|
38
|
+
* @param {String} value
|
39
|
+
*/
|
40
|
+
static unescapeHtml(value) {
|
41
|
+
if (Neo.typeOf(value) !== 'String') {
|
42
|
+
return value;
|
43
|
+
}
|
44
|
+
|
45
|
+
return value.replace(/(&)|(<)|(>)|(")|(')/g, (entity) => this.getKeyByValue(entity) || entity);
|
46
|
+
}
|
47
|
+
|
48
|
+
static getKeyByValue(value) {
|
49
|
+
return Object.keys(this.escapedChars).find(key => this.escapedChars[key] === value);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
Neo.applyClassConfig(StringUtil);
|
55
|
+
|
56
|
+
export default StringUtil;
|