neo.mjs 5.13.8 → 5.13.10

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.
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.13.8'
23
+ * @member {String} version='5.13.10'
24
24
  */
25
- version: '5.13.8'
25
+ version: '5.13.10'
26
26
  }
27
27
 
28
28
  /**
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.13.8'
23
+ * @member {String} version='5.13.10'
24
24
  */
25
- version: '5.13.8'
25
+ version: '5.13.10'
26
26
  }
27
27
 
28
28
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "5.13.8",
3
+ "version": "5.13.10",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -82,6 +82,12 @@
82
82
  }
83
83
  }
84
84
  }
85
+
86
+ &:not(.label-inline, .neo-input-wrapper) {
87
+ .neo-textfield-input {
88
+ border-color: v(textfield-border-color-invalid);
89
+ }
90
+ }
85
91
  }
86
92
 
87
93
  &.neo-invalid:not(.neo-disabled, .neo-has-content) {
@@ -267,6 +273,7 @@
267
273
  border-color : transparent;
268
274
  margin : 0; // important for Safari => #1125
269
275
  padding-left : 16px;
276
+ position : relative; // overwriting the browser default static, to ensure the z-index gets applied
270
277
  z-index : 1;
271
278
  }
272
279
 
@@ -245,12 +245,12 @@ const DefaultConfig = {
245
245
  useVdomWorker: true,
246
246
  /**
247
247
  * buildScripts/injectPackageVersion.mjs will update this value
248
- * @default '5.13.8'
248
+ * @default '5.13.10'
249
249
  * @memberOf! module:Neo
250
250
  * @name config.version
251
251
  * @type String
252
252
  */
253
- version: '5.13.8'
253
+ version: '5.13.10'
254
254
  };
255
255
 
256
256
  Object.assign(DefaultConfig, {
@@ -1596,7 +1596,7 @@ class Base extends CoreBase {
1596
1596
  }
1597
1597
 
1598
1598
  return new Promise((resolve, reject) => {
1599
- if (me.mounted) {
1599
+ if (me.mounted && me.vnode) {
1600
1600
  me.updateVdom(vdom, vnode, resolve, reject);
1601
1601
  } else {
1602
1602
  me.update();
@@ -1837,22 +1837,24 @@ class Base extends CoreBase {
1837
1837
 
1838
1838
  // keep the vnode parent tree in sync
1839
1839
  ComponentManager.getParents(me).forEach((component, index) => {
1840
- if (!me.vnode) {
1841
- if (index === 0 && !VNodeUtil.removeChildVnode(component.vnode, me.id)) {
1842
- // This can fail, in case the vnode is already removed (not an issue, better safe than sorry)
1843
- // console.warn('syncVnodeTree: Could not remove the parent vnode for', me.id, component);
1840
+ if (component.vnode) {
1841
+ if (!me.vnode) {
1842
+ if (index === 0 && !VNodeUtil.removeChildVnode(component.vnode, me.id)) {
1843
+ // This can fail, in case the vnode is already removed (not an issue, better safe than sorry)
1844
+ // console.warn('syncVnodeTree: Could not remove the parent vnode for', me.id, component);
1845
+ }
1844
1846
  }
1845
- }
1846
1847
 
1847
- // check for dynamically rendered components which get inserted into the component tree
1848
- else if (index === 0 && me.vnode.outerHTML) {
1849
- // console.log('dyn item', me.vnode, me.parentIndex);
1850
- component.vnode.childNodes.splice(me.parentIndex || 0, 0, me.vnode);
1851
- }
1848
+ // check for dynamically rendered components which get inserted into the component tree
1849
+ else if (index === 0 && me.vnode.outerHTML) {
1850
+ // console.log('dyn item', me.vnode, me.parentIndex);
1851
+ component.vnode.childNodes.splice(me.parentIndex || 0, 0, me.vnode);
1852
+ }
1852
1853
 
1853
- else if (!VNodeUtil.replaceChildVnode(component.vnode, me.vnode.id, me.vnode)) {
1854
- // todo: can happen for dynamically inserted container items
1855
- // console.warn('syncVnodeTree: Could not replace the parent vnode for', me.vnode.id, component);
1854
+ else if (!VNodeUtil.replaceChildVnode(component.vnode, me.vnode.id, me.vnode)) {
1855
+ // todo: can happen for dynamically inserted container items
1856
+ // console.warn('syncVnodeTree: Could not replace the parent vnode for', me.vnode.id, component);
1857
+ }
1856
1858
  }
1857
1859
  });
1858
1860
 
@@ -2024,18 +2026,21 @@ class Base extends CoreBase {
2024
2026
 
2025
2027
  reject?.()
2026
2028
  }).then(data => {
2027
- // console.log('Component vnode updated', data);
2028
- me.vnode = data.vnode;
2029
- me.isVdomUpdating = false;
2030
-
2031
- deltas = data.deltas;
2032
-
2033
- if (!Neo.config.useVdomWorker && deltas.length > 0) {
2034
- Neo.applyDeltas(me.appName, deltas).then(() => {
2029
+ // checking if the component got destroyed before the update cycle is done
2030
+ if (me.id) {
2031
+ // console.log('Component vnode updated', data);
2032
+ me.vnode = data.vnode;
2033
+ me.isVdomUpdating = false;
2034
+
2035
+ deltas = data.deltas;
2036
+
2037
+ if (!Neo.config.useVdomWorker && deltas.length > 0) {
2038
+ Neo.applyDeltas(me.appName, deltas).then(() => {
2039
+ me.resolveVdomUpdate(resolve)
2040
+ });
2041
+ } else {
2035
2042
  me.resolveVdomUpdate(resolve)
2036
- });
2037
- } else {
2038
- me.resolveVdomUpdate(resolve)
2043
+ }
2039
2044
  }
2040
2045
  })
2041
2046
  }
@@ -6,6 +6,38 @@ import Base from '../core/Base.mjs';
6
6
  * @singleton
7
7
  */
8
8
  class Logger extends Base {
9
+ /**
10
+ * Colors
11
+ * @property {Object} colors
12
+ */
13
+ logColors = {
14
+ error: 'indianred',
15
+ info : '#acacac',
16
+ log : '#448888',
17
+ warn : '#6d6d00'
18
+ }
19
+ /**
20
+ * Character
21
+ * @property {Object} logChar
22
+ */
23
+ logChars = {
24
+ error: 'E',
25
+ info : 'I',
26
+ log : 'L',
27
+ warn : 'W'
28
+ }
29
+ /**
30
+ * LogLevels
31
+ * @property {String[]} logLevels
32
+ */
33
+ logLevels = ['info', 'log', 'warn', 'error']
34
+
35
+ /**
36
+ * Timeout
37
+ * @property {Number} timeToStart in ms
38
+ */
39
+ timeToStartComponentLogger = 1500
40
+
9
41
  static config = {
10
42
  /**
11
43
  * @member {String} className='Neo.util.Logger'
@@ -13,15 +45,33 @@ class Logger extends Base {
13
45
  */
14
46
  className: 'Neo.util.Logger',
15
47
  /**
16
- * Set this config to false to disable the logging
17
- * @member {boolean} enableLogs=true
48
+ * Set this config to false to disable the logging in production
49
+ * To change this on the fly use:
50
+ *
51
+ * Neo.util.Logger.enableLogsInProduction = true;
52
+ *
53
+ * @member {boolean} enableLogsInProduction=true
18
54
  */
19
- enableLogs: true,
55
+ enableLogsInProduction: false,
20
56
  /**
21
- * @member {String} level='log'
57
+ * Set this config to false to disable the component logging using Ctrl-Right Click
58
+ * To turn it on, add:
59
+ *
60
+ * Neo.util.Logger.enableComponentLogger = true;
61
+ *
62
+ * @member {boolean} enableComponentLogger_=true
63
+ */
64
+ enableComponentLogger_: true,
65
+ /**
66
+ * Set the minimum level, which you want to output.
67
+ * Change this at any time using a value of logLevels: ['info', 'log', 'warn', 'error']
68
+ *
69
+ * Neo.util.Logger.level = 'error'
70
+ *
71
+ * @member {String} level='info'
22
72
  * @protected
23
73
  */
24
- level: 'log',
74
+ level_: 'info',
25
75
  /**
26
76
  * @member {boolean} enableLogs=true
27
77
  * @protected
@@ -35,14 +85,75 @@ class Logger extends Base {
35
85
  construct(config) {
36
86
  super.construct(config);
37
87
 
88
+ const me = this;
89
+
38
90
  // aliases
39
- Neo.applyFromNs(Neo, this, {
91
+ Neo.applyFromNs(Neo, me, {
40
92
  error : 'error',
41
93
  info : 'info',
42
94
  log : 'log',
43
95
  logError: 'logError',
44
96
  warn : 'warn'
45
97
  }, true);
98
+
99
+ setTimeout(() => {
100
+ if (!me.enableLogsInProduction && Neo.config.environment === 'dist/production') {
101
+ me.write = Neo.emptyFn;
102
+ }
103
+ }, 50);
104
+ }
105
+
106
+ /**
107
+ * Ctrl-Right Click will show the current component
108
+ * @param {Boolean} value
109
+ * @param {Boolean} oldValue
110
+ */
111
+ afterSetEnableComponentLogger(value, oldValue) {
112
+ setTimeout(() => {
113
+ if (value) {
114
+ if (Neo.workerId !== 'app' || Neo.config.environment === 'dist/production') return;
115
+
116
+ const viewport = Neo.getComponent('neo-viewport-1') || Neo.getComponent('neo-configuration-viewport-1');
117
+ if (!viewport) {
118
+ console.warn('[LOGGER] could not find viewport.');
119
+ return;
120
+ }
121
+
122
+ viewport.addDomListeners({
123
+ contextmenu: (data) => {
124
+ if (data.ctrlKey) {
125
+ let isGroupSet = false;
126
+
127
+ data.path.forEach((item) => {
128
+ const component = Neo.getComponent(item.id);
129
+
130
+ if (component) {
131
+ if (!isGroupSet) {
132
+ isGroupSet = true;
133
+ console.group(item.id);
134
+ }
135
+ console.log(component);
136
+ }
137
+ });
138
+
139
+ if (isGroupSet) {
140
+ console.groupEnd();
141
+ }
142
+ }
143
+ }
144
+ });
145
+ }
146
+ }, this.timeToStartComponentLogger);
147
+ }
148
+
149
+ /**
150
+ * Set level to number based on position in logLevels
151
+ * @param {String} value
152
+ * @param {String|Number} oldValue
153
+ * @returns {number}
154
+ */
155
+ beforeSetLevel(value, oldValue) {
156
+ return this.logLevels.indexOf(value);
46
157
  }
47
158
 
48
159
  /**
@@ -56,42 +167,118 @@ class Logger extends Base {
56
167
  * @param args
57
168
  */
58
169
  info(...args) {
59
- this.level = 'info';
60
- this.write(...args);
170
+ args = this.resolveArgs(...args);
171
+ this.write(args, 'info');
61
172
  }
62
173
 
63
174
  /**
64
175
  * @param args
65
176
  */
66
177
  log(...args) {
67
- this.level = 'log';
68
- this.write(...args);
178
+ args = this.resolveArgs(...args);
179
+ this.write(args, 'log');
69
180
  }
70
181
 
71
182
  /**
72
183
  * @param args
73
184
  */
74
185
  logError(...args) {
75
- this.level = 'error';
76
- this.write(...args);
186
+ args = this.resolveArgs(...args);
187
+ this.write(args, 'error');
77
188
  }
78
189
 
79
190
  /**
80
191
  * @param args
81
192
  */
82
193
  warn(...args) {
83
- this.level = 'warn';
84
- this.write(...args);
194
+ args = this.resolveArgs(...args);
195
+ this.write(args, 'warn');
85
196
  }
86
197
 
87
198
  /**
199
+ * Output method
88
200
  * @param args
201
+ * @param {String} level
89
202
  * @protected
90
203
  */
91
- write(...args) {
92
- if (this.enableLogs === true) {
93
- console[this.level](...args);
204
+ write(args, level) {
205
+ const me = this;
206
+ if (me.beforeSetLevel(level) < me.level) return;
207
+
208
+ const logColor = me.logColors[level],
209
+ logChar = me.logChars[level],
210
+ bg = `background-color:${logColor}; color: white; font-weight: 900;`,
211
+ color = `color:${logColor};`,
212
+ msg = `[${me.getCaller()}] ${args.msg}`;
213
+
214
+ if (args.data) {
215
+ console.groupCollapsed(`%c ${logChar} %c ${msg}`, bg, color)
216
+ console.log(args.data);
217
+ console.groupEnd();
218
+ } else {
219
+ console.log(`%c ${logChar} %c ${msg}`, bg, color)
220
+ }
221
+ }
222
+
223
+ /**
224
+ * HELPER TO CATCH CALLER
225
+ * no known native way in modern JS to know what file that triggered the current method
226
+ * therefore we use Error, we can get the caller file from the stack trace string.
227
+ */
228
+ getCaller() {
229
+ let caller_path = undefined;
230
+
231
+ try {
232
+ throw Error();
233
+
234
+ } catch (err) {
235
+ const stack_lines = err.stack.split('\n');
236
+ let found_this = false;
237
+
238
+ for (let i in stack_lines) {
239
+ let line = stack_lines[i];
240
+
241
+ if (!found_this && /Logger\.mjs/.test(line)) {
242
+ found_this = true
243
+
244
+ } else if (found_this) {
245
+ if (!/Logger\.mjs/.test(line)) {
246
+ // remove the closing )
247
+ line = line.replace(')', '');
248
+ // get the part after the last /
249
+ caller_path = line.match(/([^\/]+)$/)[1].match(/([^ ]+)$/)[1];
250
+
251
+ break;
252
+ }
253
+ }
254
+
255
+ }
256
+
257
+ return caller_path
258
+ }
259
+ }
260
+
261
+ /**
262
+ * HELPER FOR ARGS
263
+ * @param {Array} args
264
+ * @return {Object}
265
+ */
266
+ resolveArgs(...args) {
267
+ const identifier = args[0];
268
+ let argsObject = {};
269
+
270
+ if (args.length === 1) {
271
+ if (Neo.isString(identifier)) {
272
+ argsObject.msg = args[0];
273
+ } else if (Neo.isObject(identifier)) {
274
+ argsObject = identifier;
275
+ }
276
+ } else if (args.length === 2) {
277
+ argsObject.msg = args[0];
278
+ argsObject.data = args[1];
94
279
  }
280
+
281
+ return argsObject
95
282
  }
96
283
  }
97
284