neo.mjs 5.1.1 → 5.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/CODING_GUIDELINES.md +8 -5
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/website/data/blog.json +13 -0
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/toolbar/breadcrumb/view/MainContainer.mjs +31 -2
- package/package.json +1 -1
- package/resources/scss/src/form/field/Select.scss +1 -0
- package/resources/scss/src/form/field/Text.scss +1 -1
- package/resources/scss/src/toolbar/Breadcrumb.scss +17 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/container/Base.mjs +4 -0
- package/src/form/field/Number.mjs +2 -2
- package/src/form/field/Picker.mjs +22 -0
- package/src/form/field/Select.mjs +1 -1
- package/src/form/field/Text.mjs +19 -11
- package/src/main/DomEvents.mjs +13 -4
- package/src/toolbar/Breadcrumb.mjs +88 -0
@@ -419,18 +419,21 @@ fields: [{
|
|
419
419
|
* (39) `if (/**/) {` if, blank char, parenthesis, blank char, curly bracket
|
420
420
|
* (40) `for (/**/) {` for, blank char, parenthesis, blank char, curly bracket
|
421
421
|
* (41) `switch(/**/) {` switch, parenthesis, blank char, curly bracket `// could get changed to use a blank char as well
|
422
|
-
* (42)
|
422
|
+
* (42) `while (/**/) {` while, blank char, parenthesis, blank char, curly bracket
|
423
|
+
* (43) Use optional chaining => `?.` where it makes sense
|
423
424
|
+ Bad: `myView && myView.myFn && myView.myFn();`
|
424
425
|
+ Good: `myView?.myFn?.();`
|
425
426
|
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
|
426
|
-
* (
|
427
|
+
* (44) Use method definitions (meaning avoid using the term `function`)
|
427
428
|
+ Bad: `let obj = {a: function() {/**/}};`
|
428
429
|
+ Good: `let obj = {a() {/**/}};`
|
429
430
|
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions
|
430
|
-
* (
|
431
|
+
* (45) Use shorthand property names when possible
|
431
432
|
+ Bad: `let obj = {record: record}`
|
432
433
|
+ Good: `let obj = {record};`
|
433
434
|
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#property_definitions
|
434
|
-
* (
|
435
|
-
+ Bad: `let obj = {a: 1,}
|
435
|
+
* (46) Do not use killing commas (while IE6 is luckily no longer an issue => file size)
|
436
|
+
+ Bad: `let obj = {a: 1,};`
|
437
|
+
+ Bad: `let arr = [1,];`
|
436
438
|
+ Good: `let obj = {a: 1};`
|
439
|
+
+ Good: `let arr = [1];`
|
package/apps/ServiceWorker.mjs
CHANGED
@@ -1,4 +1,17 @@
|
|
1
1
|
[
|
2
|
+
{
|
3
|
+
"author" : "Torsten Dinkheller",
|
4
|
+
"authorImage" : "author_TorstenDinkheller.jpg",
|
5
|
+
"date" : "Feb 03, 2023",
|
6
|
+
"id" : 57,
|
7
|
+
"image" : "leveraging-overrides.jpg",
|
8
|
+
"name" : "Leveraging Overrides for Resilient Customizations and Effective Bugfixes in JavaScript Frameworks",
|
9
|
+
"provider" : "Medium",
|
10
|
+
"publisher" : "ITNEXT",
|
11
|
+
"selectedInto": [],
|
12
|
+
"type" : "Blog Post",
|
13
|
+
"url" : "https://itnext.io/leveraging-overrides-for-resilient-customizations-and-effective-bugfixes-in-javascript-frameworks-5b8ccfec0f8?source=friends_link&sk=790e868aac8b8570f0eee093adc30c00"
|
14
|
+
},
|
2
15
|
{
|
3
16
|
"author" : "Torsten Dinkheller",
|
4
17
|
"authorImage" : "author_TorstenDinkheller.jpg",
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import BreadcrumbToolbar from '../../../../src/toolbar/Breadcrumb.mjs';
|
2
|
+
import Store from '../../../../src/data/Store.mjs';
|
2
3
|
import Viewport from '../../../../src/container/Viewport.mjs';
|
3
4
|
|
4
5
|
/**
|
@@ -16,8 +17,36 @@ class MainContainer extends Viewport {
|
|
16
17
|
* @member {Object[]} items
|
17
18
|
*/
|
18
19
|
items: [{
|
19
|
-
module: BreadcrumbToolbar,
|
20
|
-
|
20
|
+
module : BreadcrumbToolbar,
|
21
|
+
activeKey: 2,
|
22
|
+
flex : 'none',
|
23
|
+
|
24
|
+
store: {
|
25
|
+
module: Store,
|
26
|
+
|
27
|
+
model: {
|
28
|
+
fields: [{
|
29
|
+
name: 'id',
|
30
|
+
type: 'Integer'
|
31
|
+
}, {
|
32
|
+
name: 'name',
|
33
|
+
type: 'String'
|
34
|
+
}, {
|
35
|
+
name: 'parentId',
|
36
|
+
type: 'Integer'
|
37
|
+
}, {
|
38
|
+
name: 'route',
|
39
|
+
type: 'String'
|
40
|
+
}]
|
41
|
+
},
|
42
|
+
|
43
|
+
data: [
|
44
|
+
{id: 1, name: 'Home', parentId: null, route: '/home/'},
|
45
|
+
{id: 2, name: 'Accessibility', parentId: 1, route: '/home/accessibility/'},
|
46
|
+
{id: 3, name: 'Imprint', parentId: 1, route: '/home/imprint/'},
|
47
|
+
{id: 4, name: 'News', parentId: 1, route: '/home/news/'},
|
48
|
+
]
|
49
|
+
}
|
21
50
|
}],
|
22
51
|
/**
|
23
52
|
* @member {Object} layout={ntype:'vbox',align:'stretch'}
|
package/package.json
CHANGED
@@ -309,7 +309,6 @@
|
|
309
309
|
flex-shrink : 1;
|
310
310
|
margin : 0; // important for Safari => #1125
|
311
311
|
min-height : v(textfield-input-height);
|
312
|
-
width : 30px;
|
313
312
|
}
|
314
313
|
}
|
315
314
|
|
@@ -331,6 +330,7 @@
|
|
331
330
|
min-width : 50px;
|
332
331
|
padding : v(textfield-input-padding);
|
333
332
|
transition : 250ms border-color cubic-bezier(0.4, 0, 0.2, 1);
|
333
|
+
width : 100%;
|
334
334
|
|
335
335
|
&:focus {
|
336
336
|
outline: none;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
.neo-breadcrumb-toolbar {
|
2
|
+
.neo-button {
|
3
|
+
&:not(:last-child) {
|
4
|
+
margin-right: 30px;
|
5
|
+
|
6
|
+
&::after {
|
7
|
+
color : v(button-text-color);
|
8
|
+
content : "\f105";
|
9
|
+
display : block;
|
10
|
+
font-family : "Font Awesome 5 Free";
|
11
|
+
font-weight : 600;
|
12
|
+
position : absolute;
|
13
|
+
right : -20px;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
package/src/DefaultConfig.mjs
CHANGED
@@ -237,12 +237,12 @@ const DefaultConfig = {
|
|
237
237
|
useVdomWorker: true,
|
238
238
|
/**
|
239
239
|
* buildScripts/injectPackageVersion.mjs will update this value
|
240
|
-
* @default '5.1.
|
240
|
+
* @default '5.1.2'
|
241
241
|
* @memberOf! module:Neo
|
242
242
|
* @name config.version
|
243
243
|
* @type String
|
244
244
|
*/
|
245
|
-
version: '5.1.
|
245
|
+
version: '5.1.2'
|
246
246
|
};
|
247
247
|
|
248
248
|
Object.assign(DefaultConfig, {
|
package/src/container/Base.mjs
CHANGED
@@ -215,7 +215,11 @@ class Base extends Component {
|
|
215
215
|
|
216
216
|
case 'NeoInstance': {
|
217
217
|
item.set(config);
|
218
|
+
|
219
|
+
// In case an item got created outside a VC or VM based hierarchy, there might be bindings or string
|
220
|
+
// based listeners which still need to get resolved.
|
218
221
|
item.getController()?.parseConfig(item);
|
222
|
+
item.getModel() ?.parseConfig(item);
|
219
223
|
break;
|
220
224
|
}
|
221
225
|
|
@@ -242,7 +242,7 @@ class Number extends Text {
|
|
242
242
|
value = (oldValue - stepSize) < me.minValue ? me.maxValue : (oldValue - stepSize);
|
243
243
|
|
244
244
|
if (me.excludedValues) {
|
245
|
-
while(me.excludedValues.includes(value)) {
|
245
|
+
while (me.excludedValues.includes(value)) {
|
246
246
|
value = Math.max(me.minValue, value - stepSize);
|
247
247
|
}
|
248
248
|
}
|
@@ -262,7 +262,7 @@ class Number extends Text {
|
|
262
262
|
value = (oldValue + stepSize) > me.maxValue ? me.minValue : (oldValue + stepSize);
|
263
263
|
|
264
264
|
if (me.excludedValues) {
|
265
|
-
while(me.excludedValues.includes(value)) {
|
265
|
+
while (me.excludedValues.includes(value)) {
|
266
266
|
value = Math.min(me.maxValue, value + stepSize);
|
267
267
|
}
|
268
268
|
}
|
@@ -115,6 +115,20 @@ class Picker extends Text {
|
|
115
115
|
this.cls = cls;
|
116
116
|
}
|
117
117
|
|
118
|
+
/**
|
119
|
+
* Triggered after the mounted config got changed
|
120
|
+
* @param {Boolean} value
|
121
|
+
* @param {Boolean} oldValue
|
122
|
+
* @protected
|
123
|
+
*/
|
124
|
+
afterSetMounted(value, oldValue) {
|
125
|
+
if (value === false && oldValue && this.pickerIsMounted) {
|
126
|
+
this.picker.hide();
|
127
|
+
}
|
128
|
+
|
129
|
+
super.afterSetMounted(value, oldValue);
|
130
|
+
}
|
131
|
+
|
118
132
|
/**
|
119
133
|
* @param {Boolean} silent
|
120
134
|
*/
|
@@ -186,6 +200,14 @@ class Picker extends Text {
|
|
186
200
|
return null;
|
187
201
|
}
|
188
202
|
|
203
|
+
/**
|
204
|
+
* @param args
|
205
|
+
*/
|
206
|
+
destroy(...args) {
|
207
|
+
this.picker?.destroy();
|
208
|
+
super.destroy(...args);
|
209
|
+
}
|
210
|
+
|
189
211
|
/**
|
190
212
|
* @param {Function} [callback]
|
191
213
|
* @param {Object} [callbackScope]
|
package/src/form/field/Text.mjs
CHANGED
@@ -530,7 +530,17 @@ class Text extends Base {
|
|
530
530
|
* @protected
|
531
531
|
*/
|
532
532
|
afterSetPlaceholderText(value, oldValue) {
|
533
|
-
this
|
533
|
+
let me = this,
|
534
|
+
cls = me.cls;
|
535
|
+
|
536
|
+
me.changeInputElKey('placeholder', value === '' ? null : value);
|
537
|
+
|
538
|
+
// a non-empty placeholder needs to keep the 'neo-has-content' rule
|
539
|
+
// => labelPosition: 'inline' should keep the label at the top
|
540
|
+
if (Neo.isEmpty(value) !== Neo.isEmpty(oldValue)) {
|
541
|
+
NeoArray[value !== null && value.toString().length > 0 ? 'add' : 'remove'](cls, 'neo-has-content');
|
542
|
+
me.cls = cls;
|
543
|
+
}
|
534
544
|
}
|
535
545
|
|
536
546
|
/**
|
@@ -686,21 +696,19 @@ class Text extends Base {
|
|
686
696
|
* @protected
|
687
697
|
*/
|
688
698
|
afterSetValue(value, oldValue) {
|
689
|
-
let me
|
690
|
-
cls
|
691
|
-
|
692
|
-
|
693
|
-
|
699
|
+
let me = this,
|
700
|
+
cls = me.cls,
|
701
|
+
placeholderText = me.placeholderText,
|
702
|
+
hasContent = placeholderText?.length > 0 || value !== null && value.toString().length > 0,
|
703
|
+
originalValue = me.originalConfig.value,
|
704
|
+
isDirty = value !== originalValue && Neo.isEmpty(value) !== Neo.isEmpty(originalValue);
|
694
705
|
|
695
706
|
me.silentVdomUpdate = true;
|
696
707
|
|
697
708
|
me.getInputEl().value = value;
|
698
709
|
|
699
|
-
|
700
|
-
|
701
|
-
}
|
702
|
-
|
703
|
-
NeoArray[isDirty ? 'add' : 'remove'](cls, 'neo-is-dirty');
|
710
|
+
NeoArray[hasContent ? 'add' : 'remove'](cls, 'neo-has-content');
|
711
|
+
NeoArray[isDirty ? 'add' : 'remove'](cls, 'neo-is-dirty');
|
704
712
|
me.cls = cls;
|
705
713
|
|
706
714
|
me.validate(); // silent
|
package/src/main/DomEvents.mjs
CHANGED
@@ -407,11 +407,20 @@ class DomEvents extends Base {
|
|
407
407
|
* @param {Object} event
|
408
408
|
*/
|
409
409
|
onChange(event) {
|
410
|
-
|
410
|
+
let target = event.target,
|
411
|
+
|
412
|
+
data = {
|
411
413
|
...this.getEventData(event),
|
412
|
-
valid:
|
413
|
-
value:
|
414
|
-
}
|
414
|
+
valid: target.checkValidity(),
|
415
|
+
value: target.value
|
416
|
+
};
|
417
|
+
|
418
|
+
// input and change events can pass a FileList for input type file
|
419
|
+
if (target.files) {
|
420
|
+
data.files = target.files;
|
421
|
+
}
|
422
|
+
|
423
|
+
this.sendMessageToApp(data);
|
415
424
|
}
|
416
425
|
|
417
426
|
/**
|
@@ -13,6 +13,19 @@ class Breadcrumb extends Toolbar {
|
|
13
13
|
* @protected
|
14
14
|
*/
|
15
15
|
className: 'Neo.toolbar.Breadcrumb',
|
16
|
+
/**
|
17
|
+
* @member {String} ntype='breadcrumb-toolbar'
|
18
|
+
* @protected
|
19
|
+
*/
|
20
|
+
ntype: 'breadcrumb-toolbar',
|
21
|
+
/**
|
22
|
+
* @member {String[]} baseCls=['neo-breadcrumb-toolbar','neo-toolbar']
|
23
|
+
*/
|
24
|
+
baseCls: ['neo-breadcrumb-toolbar', 'neo-toolbar'],
|
25
|
+
/**
|
26
|
+
* @member {Number|String|null} activeKey_=null
|
27
|
+
*/
|
28
|
+
activeKey_: null,
|
16
29
|
/**
|
17
30
|
* @member {Object[]} items
|
18
31
|
*/
|
@@ -23,6 +36,16 @@ class Breadcrumb extends Toolbar {
|
|
23
36
|
store_: null
|
24
37
|
}
|
25
38
|
|
39
|
+
/**
|
40
|
+
* Triggered after the activeKey config got changed
|
41
|
+
* @param {Number|String|null} value
|
42
|
+
* @param {Number|String|null} oldValue
|
43
|
+
* @protected
|
44
|
+
*/
|
45
|
+
afterSetActiveKey(value, oldValue) {
|
46
|
+
this.store.getCount?.() > 0 && this.updateItems()
|
47
|
+
}
|
48
|
+
|
26
49
|
/**
|
27
50
|
* Triggered after the store config got changed
|
28
51
|
* @param {Neo.data.Store|Object} value
|
@@ -30,7 +53,14 @@ class Breadcrumb extends Toolbar {
|
|
30
53
|
* @protected
|
31
54
|
*/
|
32
55
|
afterSetStore(value, oldValue) {
|
56
|
+
let me = this;
|
57
|
+
|
58
|
+
value.on({
|
59
|
+
load: this.onStoreLoad,
|
60
|
+
scope: me
|
61
|
+
});
|
33
62
|
|
63
|
+
value?.getCount() > 0 && me.onStoreLoad(value.items)
|
34
64
|
}
|
35
65
|
|
36
66
|
/**
|
@@ -44,6 +74,64 @@ class Breadcrumb extends Toolbar {
|
|
44
74
|
oldValue?.destroy();
|
45
75
|
return ClassSystemUtil.beforeSetInstance(value, Store);
|
46
76
|
}
|
77
|
+
|
78
|
+
/**
|
79
|
+
* @returns {Object[]}
|
80
|
+
*/
|
81
|
+
getPathItems() {
|
82
|
+
let items = [],
|
83
|
+
parentId = this.activeKey,
|
84
|
+
store = this.store,
|
85
|
+
item;
|
86
|
+
|
87
|
+
while (parentId !== null) {
|
88
|
+
item = store.get(parentId);
|
89
|
+
|
90
|
+
items.unshift(item);
|
91
|
+
|
92
|
+
parentId = item.parentId;
|
93
|
+
}
|
94
|
+
|
95
|
+
return items;
|
96
|
+
}
|
97
|
+
|
98
|
+
/**
|
99
|
+
* @param {Object[]} items
|
100
|
+
*/
|
101
|
+
onStoreLoad(items) {
|
102
|
+
this.activeKey !== null && this.updateItems()
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
*
|
107
|
+
*/
|
108
|
+
updateItems() {
|
109
|
+
let me = this,
|
110
|
+
items = me.items,
|
111
|
+
pathItems = me.getPathItems(),
|
112
|
+
i = 0,
|
113
|
+
len = pathItems.length,
|
114
|
+
newItems = [],
|
115
|
+
config, item
|
116
|
+
|
117
|
+
for (; i < len; i++) {
|
118
|
+
item = pathItems[i];
|
119
|
+
|
120
|
+
config = {
|
121
|
+
editRoute: false,
|
122
|
+
route : item.route,
|
123
|
+
text : item.name
|
124
|
+
};
|
125
|
+
|
126
|
+
if (items[i]) {
|
127
|
+
items[i].set(config);
|
128
|
+
} else {
|
129
|
+
newItems.push(config);
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
newItems.length > 0 && me.add(newItems);
|
134
|
+
}
|
47
135
|
}
|
48
136
|
|
49
137
|
Neo.applyClassConfig(Breadcrumb);
|