neo.mjs 5.10.3 → 5.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.
Files changed (55) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/buildScripts/createClass.mjs +10 -2
  3. package/examples/ConfigurationViewport.mjs +6 -2
  4. package/examples/ServiceWorker.mjs +2 -2
  5. package/examples/component/process/MainContainer.mjs +90 -0
  6. package/examples/component/process/app.mjs +6 -0
  7. package/examples/component/process/index.html +11 -0
  8. package/examples/component/process/neo-config.json +6 -0
  9. package/examples/component/process/realWorldExample/MainContainer.mjs +334 -0
  10. package/examples/component/process/realWorldExample/RangeHeader.jpg +0 -0
  11. package/examples/component/process/realWorldExample/app.mjs +6 -0
  12. package/examples/component/process/realWorldExample/index.html +11 -0
  13. package/examples/component/process/realWorldExample/neo-config.json +6 -0
  14. package/examples/component/progress/MainContainer.mjs +71 -0
  15. package/examples/component/progress/app.mjs +6 -0
  16. package/examples/component/progress/index.html +11 -0
  17. package/examples/component/progress/neo-config.json +6 -0
  18. package/examples/component/toast/MainContainer.mjs +9 -6
  19. package/examples/component/toast/MainContainerController.mjs +5 -5
  20. package/examples/component/toast/neo-config.json +1 -1
  21. package/examples/container/accordion/MainContainer.mjs +123 -0
  22. package/examples/container/accordion/app.mjs +6 -0
  23. package/examples/container/accordion/index.html +11 -0
  24. package/examples/container/accordion/neo-config.json +6 -0
  25. package/package.json +3 -3
  26. package/resources/scss/src/component/Process.scss +2 -4
  27. package/resources/scss/src/component/Progress.scss +3 -0
  28. package/resources/scss/src/container/Accordion.scss +25 -0
  29. package/resources/scss/src/container/AccordionItem.scss +83 -0
  30. package/resources/scss/src/container/Dialog.scss +11 -1
  31. package/resources/scss/src/form/field/CheckBox.scss +1 -0
  32. package/resources/scss/src/form/field/Range.scss +1 -0
  33. package/resources/scss/theme-dark/component/Process.scss +8 -8
  34. package/resources/scss/theme-dark/component/Progress.scss +9 -0
  35. package/resources/scss/theme-dark/container/Accordion.scss +13 -0
  36. package/resources/scss/theme-dark/container/AccordionItem.scss +23 -0
  37. package/resources/scss/theme-light/component/Process.scss +7 -7
  38. package/resources/scss/theme-light/component/Progress.scss +9 -0
  39. package/resources/scss/theme-light/container/Accordion.scss +13 -0
  40. package/resources/scss/theme-light/container/AccordionItem.scss +23 -0
  41. package/src/DefaultConfig.mjs +2 -2
  42. package/src/component/Process.mjs +11 -7
  43. package/src/component/Progress.mjs +113 -0
  44. package/src/component/Splitter.mjs +5 -4
  45. package/src/component/Toast.mjs +2 -1
  46. package/src/container/Accordion.mjs +130 -0
  47. package/src/container/AccordionItem.mjs +178 -0
  48. package/src/container/Dialog.mjs +37 -54
  49. package/src/form/Container.mjs +42 -25
  50. package/src/form/field/Number.mjs +49 -37
  51. package/src/form/field/Range.mjs +31 -4
  52. package/src/form/field/TextArea.mjs +3 -2
  53. package/src/main/DomEvents.mjs +2 -1
  54. package/src/manager/Toast.mjs +5 -1
  55. package/src/util/String.mjs +56 -0
@@ -198,46 +198,63 @@ class Container extends BaseContainer {
198
198
  }
199
199
 
200
200
  /**
201
- * Set field values by field name or field id
202
- * @param {Object} values={}
201
+ * Set field configs by field name or field id
202
+ * @param {Object} configs={}
203
203
  * @param {Boolean} suspendEvents=false
204
204
  */
205
- async setValues(values={}, suspendEvents=false) {
205
+ async setConfigs(configs={}, suspendEvents=false) {
206
206
  let me = this,
207
207
  fields = await me.getFields(),
208
- isCheckBox, isRadio, path, value;
208
+ fieldConfigs, isCheckBox, isRadio, path, value;
209
209
 
210
210
  fields.forEach(item => {
211
- if (suspendEvents) {
212
- item.suspendEvents = true;
213
- }
211
+ path = me.getFieldPath(item);
212
+ fieldConfigs = Neo.nsWithArrays(path, false, configs);
213
+
214
+ if (fieldConfigs) {
215
+ if (suspendEvents) {
216
+ item.suspendEvents = true;
217
+ }
218
+
219
+ isCheckBox = Neo.form.field?.CheckBox && item instanceof Neo.form.field.CheckBox;
220
+ value = fieldConfigs.value;
214
221
 
215
- isCheckBox = Neo.form.field?.CheckBox && item instanceof Neo.form.field.CheckBox;
216
- path = me.getFieldPath(item);
217
- value = Neo.nsWithArrays(path, false, values);
222
+ if (isCheckBox) {
223
+ if (Neo.typeOf(value) === 'Array') {
224
+ if (value.includes(item.value)) {
225
+ fieldConfigs.checked = true
226
+ }
227
+ } else {
228
+ fieldConfigs.checked = item.value === value
229
+ }
230
+ } else if (value !== undefined) {
231
+ isRadio = Neo.form.field?.Radio && item instanceof Neo.form.field.Radio;
218
232
 
219
- if (isCheckBox) {
220
- if (Neo.typeOf(value) === 'Array') {
221
- if (value.includes(item.value)) {
222
- item.checked = true
233
+ if (isRadio) {
234
+ fieldConfigs.checked = item.value === value
223
235
  }
224
- } else {
225
- item.checked = item.value === value
226
236
  }
227
- } else if (value !== undefined) {
228
- isRadio = Neo.form.field?.Radio && item instanceof Neo.form.field.Radio;
229
237
 
230
- if (isRadio) {
231
- item.checked = item.value === value
232
- } else {
233
- item.value = value
238
+ item.set(fieldConfigs)
239
+
240
+ if (suspendEvents) {
241
+ delete item.suspendEvents;
234
242
  }
235
243
  }
244
+ })
245
+ }
236
246
 
237
- if (suspendEvents) {
238
- delete item.suspendEvents;
239
- }
247
+ /**
248
+ * Set field values by field name or field id
249
+ * @param {Object} values={}
250
+ * @param {Boolean} suspendEvents=false
251
+ */
252
+ async setValues(values={}, suspendEvents=false) {
253
+ Object.entries(values).forEach(([key, value]) => {
254
+ values[key] = {value}
240
255
  })
256
+
257
+ await this.setConfigs(values, suspendEvents)
241
258
  }
242
259
 
243
260
  /**
@@ -148,7 +148,7 @@ class Number extends Text {
148
148
 
149
149
  me.changeInputElKey('step', value);
150
150
 
151
- stepSizeString = String(this.stepSize);
151
+ stepSizeString = String(value);
152
152
 
153
153
  me.stepSizeDigits = stepSizeString.includes('.') ? stepSizeString.split('.')[1].length : 0;
154
154
 
@@ -157,16 +157,44 @@ class Number extends Text {
157
157
 
158
158
  if (modulo !== 0) { // find the closest valid value
159
159
  if (modulo / value > 0.5) {
160
- if (val + value - modulo < me.maxValue) {me.value = val + value - modulo;}
161
- else if (val - modulo > me.minValue) {me.value = val - modulo;}
160
+ if (val + value - modulo < me.maxValue) {
161
+ me.value = val + value - modulo;
162
+ } else if (val - modulo > me.minValue) {
163
+ me.value = val - modulo;
164
+ }
162
165
  } else {
163
- if (val - modulo > me.minValue) {me.value = val - modulo;}
164
- else if (val + value - modulo < me.maxValue) {me.value = val + value - modulo;}
166
+ if (val - modulo > me.minValue) {
167
+ me.value = val - modulo;
168
+ } else if (val + value - modulo < me.maxValue) {
169
+ me.value = val + value - modulo;
170
+ }
165
171
  }
166
172
  }
167
173
  }
168
174
  }
169
175
 
176
+ /**
177
+ * Triggered after the triggerPosition config got changed
178
+ * @param {String} value
179
+ * @param {String} oldValue
180
+ * @protected
181
+ */
182
+ afterSetTriggerPosition(value, oldValue) {
183
+ oldValue && this.updateTriggers();
184
+ }
185
+
186
+ /**
187
+ * Triggered after the useSpinButtons config got changed
188
+ * @param {Boolean} value
189
+ * @param {Boolean} oldValue
190
+ * @protected
191
+ */
192
+ afterSetUseSpinButtons(value, oldValue) {
193
+ if (typeof oldValue === 'boolean') {
194
+ this.updateTriggers();
195
+ }
196
+ }
197
+
170
198
  /**
171
199
  * Triggered before the maxLength config gets changed
172
200
  * @param {Number|null} value
@@ -195,28 +223,6 @@ class Number extends Text {
195
223
  return null;
196
224
  }
197
225
 
198
- /**
199
- * Triggered after the triggerPosition config got changed
200
- * @param {String} value
201
- * @param {String} oldValue
202
- * @protected
203
- */
204
- afterSetTriggerPosition(value, oldValue) {
205
- oldValue && this.updateTriggers();
206
- }
207
-
208
- /**
209
- * Triggered after the useSpinButtons config got changed
210
- * @param {Boolean} value
211
- * @param {Boolean} oldValue
212
- * @protected
213
- */
214
- afterSetUseSpinButtons(value, oldValue) {
215
- if (typeof oldValue === 'boolean') {
216
- this.updateTriggers();
217
- }
218
- }
219
-
220
226
  /**
221
227
  * Triggered before the triggerPosition config gets changed
222
228
  * @param {String} value
@@ -229,18 +235,24 @@ class Number extends Text {
229
235
 
230
236
  /**
231
237
  * Triggered before the value config gets changed
232
- * @param {Number} value
238
+ * @param {Number|String} value
233
239
  * @param {Number} oldValue
234
240
  * @protected
235
241
  */
236
242
  beforeSetValue(value, oldValue) {
237
- if (Neo.isNumber(value) && this.stepSizeDigits > 0) {
238
- return +value.toFixed(this.stepSizeDigits)
239
- } else if (value === '') {
240
- return null
243
+ if (value === null || value === '') {
244
+ return null;
245
+ }
246
+
247
+ if (!Neo.isNumber(value)) {
248
+ value = +value;
249
+ }
250
+
251
+ if (this.stepSizeDigits > 0) {
252
+ value = +value.toFixed(this.stepSizeDigits);
241
253
  }
242
254
 
243
- return value
255
+ return value;
244
256
  }
245
257
 
246
258
  /**
@@ -366,7 +378,7 @@ class Number extends Text {
366
378
  }
367
379
 
368
380
  me.removeTrigger('spindown', true, triggers);
369
- me.removeTrigger('spinup', true, triggers);
381
+ me.removeTrigger('spinup', true, triggers);
370
382
  } else {
371
383
  if (!me.hasTrigger('spindown')) {
372
384
  triggers.push(SpinDownTrigger);
@@ -379,8 +391,8 @@ class Number extends Text {
379
391
  me.removeTrigger('spinupdown', true, triggers);
380
392
  }
381
393
  } else {
382
- me.removeTrigger('spindown', true, triggers);
383
- me.removeTrigger('spinup', true, triggers);
394
+ me.removeTrigger('spindown', true, triggers);
395
+ me.removeTrigger('spinup', true, triggers);
384
396
  me.removeTrigger('spinupdown', true, triggers);
385
397
  }
386
398
 
@@ -392,7 +404,7 @@ class Number extends Text {
392
404
  * @param {Boolean} silent=true
393
405
  * @returns {Boolean} Returns true in case there are no client-side errors
394
406
  */
395
- validate(silent=true) {
407
+ validate(silent = true) {
396
408
  let me = this,
397
409
  value = me.value,
398
410
  isNumber = Neo.isNumber(value),
@@ -30,6 +30,11 @@ class Range extends Number {
30
30
  * @member {String} inputType='range'
31
31
  */
32
32
  inputType: 'range',
33
+ /**
34
+ * If true, shows the result of the slider in the label
35
+ * @member {Boolean} showResultInLabel=false
36
+ */
37
+ showResultInLabel: false,
33
38
  /**
34
39
  * @member {Array} tickmarks_=[]
35
40
  */
@@ -37,7 +42,7 @@ class Range extends Number {
37
42
  /**
38
43
  * @member {Boolean} useInputEvent=false
39
44
  */
40
- useInputEvent : false,
45
+ useInputEvent: false,
41
46
  /**
42
47
  * Disables the field.Number buttons
43
48
  * @member {Boolean} useInputEvent=false
@@ -57,14 +62,16 @@ class Range extends Number {
57
62
  if (me.useInputEvent) {
58
63
  me.addDomListeners({
59
64
  input: {
60
- fn : me.onInputValueChange,
61
- id : me.vdom.cn[2].id,
62
- scope : me
65
+ fn : me.onInputValueChange,
66
+ id : me.vdom.cn[2].id,
67
+ scope: me
63
68
  }
64
69
  });
65
70
  }
66
71
 
67
72
  inputEl.cls = ['neo-rangefield-input']; // replace neo-textfield-input
73
+
74
+ me.addValueToLabel();
68
75
  }
69
76
 
70
77
  /**
@@ -76,6 +83,26 @@ class Range extends Number {
76
83
  afterSetTickmarks(value, oldValue) {
77
84
  // todo
78
85
  }
86
+
87
+ /**
88
+ * Override the NumberField implementation
89
+ * @param {Object} data
90
+ */
91
+ afterSetValue(value, oldValue) {
92
+ this.addValueToLabel();
93
+ super.afterSetValue(value, oldValue);
94
+ }
95
+
96
+ /**
97
+ * Update label with value
98
+ */
99
+ addValueToLabel() {
100
+ const me = this;
101
+
102
+ if (me.showResultInLabel) {
103
+ me.getLabelEl().innerHTML = `[${me.value}] ` + me.labelText;
104
+ }
105
+ }
79
106
  }
80
107
 
81
108
  Neo.applyClassConfig(Range);
@@ -1,4 +1,5 @@
1
- import Text from './Text.mjs';
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);
@@ -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
@@ -204,7 +204,11 @@ class Toast extends Base {
204
204
  component.style = moveObj;
205
205
  component.update();
206
206
 
207
- acc = acc + rects[index].height;
207
+ // Sometimes the index is already reduced
208
+ // so the last index might not be available
209
+ if(rects[index]) {
210
+ acc = acc + rects[index].height;
211
+ }
208
212
  }
209
213
  }
210
214
  }
@@ -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
+ '&': '&amp;',
18
+ '<': '&lt;',
19
+ '>': '&gt;',
20
+ '"': '&quot;',
21
+ '\'': '&#039;'
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(/(&amp;)|(&lt;)|(&gt;)|(&quot;)|(&#039;)/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;