neo.mjs 6.10.3 → 6.10.5
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/form/model/SideNav.mjs +3 -3
- package/apps/form/view/SideNavList.mjs +8 -3
- package/apps/form/view/ViewportController.mjs +6 -7
- package/apps/portal/Overwrites.mjs +21 -0
- package/apps/portal/app.mjs +7 -0
- package/apps/portal/data/blog.json +743 -0
- package/apps/portal/index.html +15 -0
- package/apps/portal/model/BlogPost.mjs +59 -0
- package/apps/{learnneo → portal}/model/Content.mjs +3 -3
- package/apps/{learnneo → portal}/neo-config.json +1 -1
- package/apps/portal/store/BlogPosts.mjs +43 -0
- package/apps/{learnneo → portal}/store/Content.mjs +2 -5
- package/apps/portal/view/HeaderToolbar.mjs +65 -0
- package/apps/portal/view/Viewport.mjs +59 -0
- package/apps/portal/view/ViewportController.mjs +79 -0
- package/apps/portal/view/blog/Container.mjs +50 -0
- package/apps/portal/view/blog/List.mjs +173 -0
- package/apps/{newwebsite/view/Viewport.mjs → portal/view/home/MainContainer.mjs} +7 -8
- package/apps/{learnneo/view/home → portal/view/learn}/ContentTreeList.mjs +6 -6
- package/apps/{learnneo/view/home → portal/view/learn}/ContentView.mjs +3 -3
- package/apps/{learnneo/view → portal/view/learn}/LivePreview.mjs +32 -19
- package/apps/{learnneo/view/home → portal/view/learn}/MainContainer.mjs +27 -31
- package/apps/{learnneo/view/home → portal/view/learn}/MainContainerController.mjs +3 -3
- package/apps/{learnneo/view/home → portal/view/learn}/MainContainerModel.mjs +3 -3
- package/apps/website/Overwrites.mjs +16 -0
- package/apps/website/app.mjs +2 -1
- package/apps/website/view/blog/List.mjs +1 -1
- package/buildScripts/webpack/development/webpack.config.appworker.mjs +3 -1
- package/buildScripts/webpack/json/myApps.template.json +1 -1
- package/buildScripts/webpack/production/webpack.config.appworker.mjs +3 -1
- package/examples/ServiceWorker.mjs +2 -2
- package/package.json +2 -2
- package/resources/data/deck/learnneo/p/stylesheet.md +4 -1
- 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/examples/data/formSideNav.json +19 -19
- package/resources/scss/src/apps/portal/blog/Container.scss +18 -0
- package/resources/scss/src/apps/portal/blog/List.scss +183 -0
- package/resources/scss/src/apps/{newwebsite/Viewport.scss → portal/home/MainContainer.scss} +1 -1
- package/resources/scss/src/tab/Strip.scss +1 -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 +24 -20
- 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/tab/header/Button.scss +8 -7
- 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 +5 -0
- package/src/component/Toast.mjs +5 -2
- package/src/container/Base.mjs +14 -0
- package/src/controller/Application.mjs +2 -1
- package/src/controller/Base.mjs +14 -3
- package/src/controller/Component.mjs +1 -1
- package/src/core/Base.mjs +7 -5
- package/src/core/Observable.mjs +15 -15
- package/src/data/RecordFactory.mjs +3 -3
- package/src/form/Container.mjs +50 -0
- package/src/form/field/Text.mjs +2 -2
- package/src/form/field/TextArea.mjs +5 -0
- package/src/main/addon/WindowPosition.mjs +72 -34
- package/src/tab/Strip.mjs +21 -36
- package/src/tab/header/Button.mjs +5 -7
- package/src/worker/App.mjs +26 -1
- package/src/worker/Base.mjs +41 -29
- package/src/worker/Canvas.mjs +4 -4
- package/src/worker/Manager.mjs +4 -3
- package/src/worker/mixin/RemoteMethodAccess.mjs +20 -18
- package/apps/learnneo/app.mjs +0 -6
- package/apps/learnneo/index.html +0 -21
- package/apps/learnneo/view/Viewport.mjs +0 -52
- package/apps/learnneo/view/ViewportController.mjs +0 -19
- package/apps/learnneo/view/home/HeaderToolbar.mjs +0 -47
- package/apps/newwebsite/app.mjs +0 -6
- package/apps/newwebsite/index.html +0 -13
- package/apps/newwebsite/neo-config.json +0 -7
- /package/resources/scss/src/apps/{learnneo/home → portal}/HeaderToolbar.scss +0 -0
- /package/resources/scss/src/apps/{learnneo → portal}/Viewport.scss +0 -0
- /package/resources/scss/src/apps/{learnneo/home → portal/learn}/ContentTreeList.scss +0 -0
- /package/resources/scss/src/apps/{learnneo/home → portal/learn}/ContentView.scss +0 -0
- /package/resources/scss/src/apps/{learnneo/home → portal/learn}/MainContainer.scss +0 -0
@@ -19,7 +19,7 @@
|
|
19
19
|
}
|
20
20
|
|
21
21
|
.vector {
|
22
|
-
background-image : url("
|
22
|
+
background-image : url("../../../../../../../resources/images/Neo_Vector.svg");
|
23
23
|
background-position: center center;
|
24
24
|
background-repeat : no-repeat;
|
25
25
|
background-size : contain;
|
@@ -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
|
+
}
|
@@ -4,7 +4,6 @@ $border-color : #ddd;
|
|
4
4
|
$border-style : solid;
|
5
5
|
$border-width : 1px;
|
6
6
|
|
7
|
-
|
8
7
|
:root .neo-theme-neo-light { // .neo-button
|
9
8
|
--button-background-color : var(--cmp-button-primary-bg-default);
|
10
9
|
--button-background-color-active : var(--cmp-button-primary-bg-active);
|
@@ -45,28 +44,28 @@ $border-width : 1px;
|
|
45
44
|
--button-use-gradients : false;
|
46
45
|
|
47
46
|
// {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-
|
47
|
+
--button-ghost-background-color : var(--cmp-button-ghost-bg-default);
|
48
|
+
--button-ghost-background-color-active : var(--cmp-button-ghost-bg-active);
|
49
|
+
--button-ghost-background-color-disabled : var(--cmp-button-ghost-bg-disabled);
|
50
|
+
--button-ghost-background-color-hover : var(--cmp-button-ghost-bg-hover);
|
52
51
|
--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 :
|
52
|
+
--button-ghost-badge-background-color : transparent;
|
53
|
+
--button-ghost-badge-color : transparent;
|
54
|
+
--button-ghost-border : none;
|
55
|
+
--button-ghost-border-active : none;
|
57
56
|
--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 :
|
57
|
+
--button-ghost-border-hover : none;
|
58
|
+
--button-ghost-border-pressed : none;
|
59
|
+
--button-ghost-glyph-color : var(--cmp-button-ghost-fg-default);
|
60
|
+
--button-ghost-glyph-color-active : inherit;
|
61
|
+
--button-ghost-glyph-color-disabled : var(--cmp-button-ghost-fg-disabled);
|
62
|
+
--button-ghost-glyph-color-hover : inherit;
|
63
|
+
--button-ghost-opacity-disabled : inherit;
|
65
64
|
--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 :
|
65
|
+
--button-ghost-text-color : var(--cmp-button-ghost-fg-default);
|
66
|
+
--button-ghost-text-color-active : inherit;
|
67
|
+
--button-ghost-text-color-disabled : var(--cmp-button-ghost-fg-disabled);
|
68
|
+
--button-ghost-text-color-hover : inherit;
|
70
69
|
|
71
70
|
// {module: Button; ui: --secondary}
|
72
71
|
--button-secondary-background-color : var(--cmp-button-secondary-bg-default);
|
@@ -115,4 +114,9 @@ $border-width : 1px;
|
|
115
114
|
--button-tertiary-text-color-active : var(--button-text-color);
|
116
115
|
--button-tertiary-text-color-disabled : inherit;
|
117
116
|
--button-tertiary-text-color-hover : var(--button-text-color);
|
117
|
+
|
118
|
+
// custom overrides
|
119
|
+
.neo-button {
|
120
|
+
min-width: var(--cmp-button-height);
|
121
|
+
}
|
118
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
|
}
|
@@ -27,15 +27,16 @@
|
|
27
27
|
--tab-button-padding : 7px var(--cmp-tab-spacinghorizontal) 6px;
|
28
28
|
--tab-button-text-color : var(--sem-color-fg-neutral-subdued);
|
29
29
|
--tab-button-text-transform : uppercase;
|
30
|
-
}
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
// custom overrides
|
32
|
+
.neo-button-text {
|
33
|
+
font-size: var(--sem-typo-label-regular-fontSize) !important;
|
34
|
+
}
|
35
35
|
|
36
|
-
.pressed {
|
37
|
-
|
38
|
-
|
36
|
+
.pressed {
|
37
|
+
.neo-button-glyph, .neo-button-text {
|
38
|
+
color: var(--sem-color-fg-neutral-contrast) !important;
|
39
|
+
}
|
39
40
|
}
|
40
41
|
}
|
41
42
|
|
@@ -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.5'
|
240
240
|
* @memberOf! module:Neo
|
241
241
|
* @name config.version
|
242
242
|
* @type String
|
243
243
|
*/
|
244
|
-
version: '6.10.
|
244
|
+
version: '6.10.5'
|
245
245
|
};
|
246
246
|
|
247
247
|
Object.assign(DefaultConfig, {
|
package/src/Main.mjs
CHANGED
package/src/component/Base.mjs
CHANGED
@@ -335,6 +335,11 @@ class Base extends CoreBase {
|
|
335
335
|
* @member {Number|String|null} width_=null
|
336
336
|
*/
|
337
337
|
width_: null,
|
338
|
+
/**
|
339
|
+
* The custom windowIs (timestamp) this component belongs to
|
340
|
+
* @member {Number|null} windowId_=null
|
341
|
+
*/
|
342
|
+
windowId_: null,
|
338
343
|
/**
|
339
344
|
* @member {String[]|null} wrapperCls_=null
|
340
345
|
*/
|
package/src/component/Toast.mjs
CHANGED
@@ -56,6 +56,10 @@ class Toast extends Base {
|
|
56
56
|
* @member {Boolean} closable=false
|
57
57
|
*/
|
58
58
|
closable_: false,
|
59
|
+
/**
|
60
|
+
* @member {Boolean} floating=true
|
61
|
+
*/
|
62
|
+
floating: true,
|
59
63
|
/**
|
60
64
|
* If set, it shows this icon in front of the text
|
61
65
|
* e.g. 'fa fa-cog'
|
@@ -107,8 +111,7 @@ class Toast extends Base {
|
|
107
111
|
]},
|
108
112
|
{cls: ['neo-toast-close', 'fa', 'fa-close'], removeDom: true}
|
109
113
|
]
|
110
|
-
}]}
|
111
|
-
floating : true
|
114
|
+
}]}
|
112
115
|
}
|
113
116
|
|
114
117
|
/**
|
package/src/container/Base.mjs
CHANGED
@@ -217,6 +217,20 @@ class Base extends Component {
|
|
217
217
|
}
|
218
218
|
}
|
219
219
|
|
220
|
+
/**
|
221
|
+
* Triggered after the windowId config got changed
|
222
|
+
* @param {Number|null} value
|
223
|
+
* @param {Number|null} oldValue
|
224
|
+
* @protected
|
225
|
+
*/
|
226
|
+
afterSetWindowId(value, oldValue) {
|
227
|
+
value && this.items?.forEach(item => {
|
228
|
+
if (Neo.isObject(item)) {
|
229
|
+
item.windowId = value
|
230
|
+
}
|
231
|
+
})
|
232
|
+
}
|
233
|
+
|
220
234
|
/**
|
221
235
|
* Convert items object to an array for onward storage as _items
|
222
236
|
* @param {Object|Object[]} value
|
package/src/controller/Base.mjs
CHANGED
@@ -21,6 +21,12 @@ class Base extends CoreBase {
|
|
21
21
|
* @protected
|
22
22
|
*/
|
23
23
|
ntype: 'controller',
|
24
|
+
/**
|
25
|
+
* If the URL does not contain a hash value when creating this controller instance,
|
26
|
+
* neo will set this hash value for us.
|
27
|
+
* @member {String|null} defaultHash=null
|
28
|
+
*/
|
29
|
+
defaultHash: null,
|
24
30
|
/**
|
25
31
|
* @member {String|null} defaultRoute=null
|
26
32
|
*/
|
@@ -90,9 +96,14 @@ class Base extends CoreBase {
|
|
90
96
|
*
|
91
97
|
*/
|
92
98
|
onConstructed() {
|
93
|
-
let currentHash = HashHistory.first()
|
99
|
+
let currentHash = HashHistory.first(),
|
100
|
+
defaultHash = this.defaultHash;
|
94
101
|
|
95
|
-
|
102
|
+
if (currentHash) {
|
103
|
+
this.onHashChange(currentHash, null)
|
104
|
+
} else if (defaultHash) {
|
105
|
+
Neo.Main.setRoute({value: defaultHash})
|
106
|
+
}
|
96
107
|
}
|
97
108
|
|
98
109
|
/**
|
@@ -185,7 +196,7 @@ class Base extends CoreBase {
|
|
185
196
|
* @returns {Number}
|
186
197
|
*/
|
187
198
|
#sortRoutes(route1, route2) {
|
188
|
-
return route1.match(amountSlashesRegex).length - route2.match(amountSlashesRegex).length
|
199
|
+
return (route1.match(amountSlashesRegex) || []).length - (route2.match(amountSlashesRegex)|| []).length
|
189
200
|
}
|
190
201
|
}
|
191
202
|
|
@@ -189,7 +189,7 @@ class Component extends Base {
|
|
189
189
|
handlerScope = me.getHandlerScope(eventHandler, component);
|
190
190
|
|
191
191
|
if (!handlerScope) {
|
192
|
-
|
192
|
+
console.error('Unknown event handler for', eventHandler, component)
|
193
193
|
} else if (handlerScope !== true) {
|
194
194
|
listener.fn = handlerScope[eventHandler].bind(handlerScope)
|
195
195
|
}
|
package/src/core/Base.mjs
CHANGED
@@ -189,12 +189,14 @@ class Base {
|
|
189
189
|
delayable = me.delayable ? Neo.merge({}, me.delayable, ctorDelayable) : ctorDelayable;
|
190
190
|
|
191
191
|
Object.entries(delayable).forEach(([key, value]) => {
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
192
|
+
if (value) {
|
193
|
+
let map = {
|
194
|
+
debounce() {me[key] = new debounce(me[key], me, value.timer)},
|
195
|
+
throttle() {me[key] = new throttle(me[key], me, value.timer)}
|
196
|
+
};
|
196
197
|
|
197
|
-
|
198
|
+
map[value.type]?.()
|
199
|
+
}
|
198
200
|
})
|
199
201
|
}
|
200
202
|
|
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
|
*/
|
@@ -68,6 +68,9 @@ class RecordFactory extends Base {
|
|
68
68
|
properties;
|
69
69
|
|
70
70
|
Object.defineProperties(me, {
|
71
|
+
[Symbol.for('isRecord')]: {
|
72
|
+
value: true
|
73
|
+
},
|
71
74
|
_isModified: {
|
72
75
|
value : false,
|
73
76
|
writable: true
|
@@ -87,9 +90,6 @@ class RecordFactory extends Base {
|
|
87
90
|
parsedValue = instance.parseRecordValue(me, field, value, config);
|
88
91
|
|
89
92
|
properties = {
|
90
|
-
[Symbol.for('isRecord')]: {
|
91
|
-
value: true
|
92
|
-
},
|
93
93
|
[symbol]: {
|
94
94
|
value : parsedValue,
|
95
95
|
writable: true
|
package/src/form/Container.mjs
CHANGED
@@ -136,6 +136,56 @@ class Container extends BaseContainer {
|
|
136
136
|
return fields
|
137
137
|
}
|
138
138
|
|
139
|
+
|
140
|
+
/**
|
141
|
+
* This function will return one of the following states:
|
142
|
+
* - clean => all fields are clean (untouched)
|
143
|
+
* - invalid => at least one field is invalid
|
144
|
+
* - valid => all required fields are valid
|
145
|
+
* - inProgress => at least one field is valid, at least one field is clean
|
146
|
+
* @returns {Promise<String>}
|
147
|
+
*/
|
148
|
+
async getFormState() {
|
149
|
+
let fields = await this.getFields(),
|
150
|
+
i = 0,
|
151
|
+
hasCleanFields = false,
|
152
|
+
hasInvalidFields = false,
|
153
|
+
hasUncleanFields = false,
|
154
|
+
hasValidFields = false,
|
155
|
+
len = fields.length,
|
156
|
+
field, isClean, isValid;
|
157
|
+
|
158
|
+
for (; i < len; i++) {
|
159
|
+
field = fields[i];
|
160
|
+
isClean = field.clean;
|
161
|
+
isValid = field.isValid();
|
162
|
+
|
163
|
+
if (!isClean && !isValid) {
|
164
|
+
return 'invalid'
|
165
|
+
} else if (isValid) {
|
166
|
+
hasValidFields = true
|
167
|
+
} else if (!isValid) {
|
168
|
+
hasInvalidFields = true
|
169
|
+
}
|
170
|
+
|
171
|
+
if (isClean) {
|
172
|
+
hasCleanFields = true
|
173
|
+
} else {
|
174
|
+
hasUncleanFields = true
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
if (!hasInvalidFields) {
|
179
|
+
return 'valid'
|
180
|
+
}
|
181
|
+
|
182
|
+
if (hasCleanFields && !hasUncleanFields) {
|
183
|
+
return 'clean'
|
184
|
+
}
|
185
|
+
|
186
|
+
return 'inProgress'
|
187
|
+
}
|
188
|
+
|
139
189
|
/**
|
140
190
|
* @returns {Promise<Object>}
|
141
191
|
*/
|
package/src/form/field/Text.mjs
CHANGED
@@ -703,7 +703,7 @@ class Text extends Base {
|
|
703
703
|
|
704
704
|
me.silentVdomUpdate = true;
|
705
705
|
|
706
|
-
me.validate(
|
706
|
+
oldValue !== undefined && me.validate(me.clean);
|
707
707
|
me.changeInputElKey('required', value ? value : null);
|
708
708
|
me.labelText = me.labelText; // apply the optional text if needed
|
709
709
|
|
@@ -1279,7 +1279,7 @@ class Text extends Base {
|
|
1279
1279
|
cls;
|
1280
1280
|
|
1281
1281
|
if (!me.readOnly) {
|
1282
|
-
me.validate();
|
1282
|
+
me.validate(false);
|
1283
1283
|
|
1284
1284
|
cls = me.cls; // has to get set after validate()
|
1285
1285
|
|
@@ -37,6 +37,11 @@ class TextArea extends Text {
|
|
37
37
|
* @member {String[]} baseCls=['neo-textarea','neo-textfield']
|
38
38
|
*/
|
39
39
|
baseCls: ['neo-textarea', 'neo-textfield'],
|
40
|
+
/**
|
41
|
+
* True shows a clear trigger in case the field has a non-empty value.
|
42
|
+
* @member {Boolean} clearable=false
|
43
|
+
*/
|
44
|
+
clearable: false,
|
40
45
|
/**
|
41
46
|
* The visible width of the text control, in average character widths.
|
42
47
|
* If it is specified, it must be a positive integer.
|