neo.mjs 4.0.48 → 4.0.51

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.
@@ -0,0 +1,270 @@
1
+ import chalk from 'chalk';
2
+ import { Command } from 'commander/esm.mjs';
3
+ import envinfo from 'envinfo';
4
+ import fs from 'fs-extra';
5
+ import inquirer from 'inquirer';
6
+ import os from 'os';
7
+ import path from 'path';
8
+
9
+ const __dirname = path.resolve(),
10
+ cwd = process.cwd(),
11
+ requireJson = path => JSON.parse(fs.readFileSync((path))),
12
+ packageJson = requireJson(path.join(__dirname, 'package.json')),
13
+ insideNeo = packageJson.name === 'neo.mjs',
14
+ program = new Command(),
15
+ programName = `${packageJson.name} create-class`,
16
+ questions = [];
17
+
18
+ program
19
+ .name(programName)
20
+ .version(packageJson.version)
21
+ .option('-i, --info', 'print environment debug info')
22
+ .option('-b, --baseClass <value>')
23
+ .option('-c, --className <value>')
24
+ .allowUnknownOption()
25
+ .on('--help', () => {
26
+ console.log('\nIn case you have any issues, please create a ticket here:');
27
+ console.log(chalk.cyan(process.env.npm_package_bugs_url));
28
+ })
29
+ .parse(process.argv);
30
+
31
+ const programOpts = program.opts();
32
+
33
+ if (programOpts.info) {
34
+ console.log(chalk.bold('\nEnvironment Info:'));
35
+ console.log(`\n current version of ${packageJson.name}: ${packageJson.version}`);
36
+ console.log(` running from ${__dirname}`);
37
+
38
+ envinfo
39
+ .run({
40
+ System : ['OS', 'CPU'],
41
+ Binaries : ['Node', 'npm', 'Yarn'],
42
+ Browsers : ['Chrome', 'Edge', 'Firefox', 'Safari'],
43
+ npmPackages: ['neo.mjs']
44
+ }, {
45
+ duplicates : true,
46
+ showNotFound: true
47
+ })
48
+ .then(console.log);
49
+ } else {
50
+ console.log(chalk.green(programName));
51
+
52
+ if (!programOpts.className) {
53
+ questions.push({
54
+ type : 'input',
55
+ name : 'className',
56
+ message: 'Please choose the namespace for your class:',
57
+ default: 'Covid.view.HeaderContainerController'
58
+ });
59
+ }
60
+
61
+ if (!programOpts.baseClass) {
62
+ questions.push({
63
+ type : 'list',
64
+ name : 'baseClass',
65
+ message: 'Please pick the base class, which you want to extend:',
66
+ choices: ['component.Base', 'container.Base', 'controller.Component', 'core.Base'],
67
+ default: 'container.Base'
68
+ });
69
+ }
70
+
71
+ inquirer.prompt(questions).then(answers => {
72
+ let baseClass = programOpts.baseClass || answers.baseClass,
73
+ className = programOpts.className || answers.className,
74
+ startDate = new Date(),
75
+ classFolder, file, folderDelta, index, ns, root, rootLowerCase, viewFile;
76
+
77
+ if (className.endsWith('.mjs')) {
78
+ className = className.slice(0, -4);
79
+ }
80
+
81
+ ns = className.split('.');
82
+ file = ns.pop();
83
+ root = ns.shift();
84
+ rootLowerCase = root.toLowerCase();
85
+
86
+ if (root === 'Neo') {
87
+ console.log('todo: create the file inside the src folder');
88
+ } else {
89
+ if (fs.existsSync(path.resolve(cwd, 'apps', rootLowerCase))) {
90
+ classFolder = path.resolve(cwd, 'apps', rootLowerCase, ns.join('/'));
91
+ folderDelta = ns.length + 2;
92
+
93
+ fs.mkdirpSync(classFolder);
94
+
95
+ fs.writeFileSync(path.join(classFolder, file + '.mjs'), createContent({baseClass, className, file, folderDelta, ns, root}));
96
+
97
+ if (baseClass === 'controller.Component') {
98
+ index = file.indexOf('Controller');
99
+
100
+ if (index > 0) {
101
+ viewFile = path.join(classFolder, file.substr(0, index) + '.mjs');
102
+
103
+ if (fs.existsSync(viewFile)) {
104
+ adjustView({file, viewFile});
105
+ }
106
+ }
107
+ }
108
+ } else {
109
+ console.log('\nNon existing neo app name:', chalk.red(root));
110
+ process.exit(1);
111
+ }
112
+ }
113
+
114
+ const processTime = (Math.round((new Date - startDate) * 100) / 100000).toFixed(2);
115
+ console.log(`\nTotal time for ${programName}: ${processTime}s`);
116
+
117
+ process.exit();
118
+ });
119
+
120
+ /**
121
+ * Adds a comma to the last element of the contentArray
122
+ * @param {String[]} contentArray
123
+ * @returns {String[]}
124
+ */
125
+ function addComma(contentArray) {
126
+ contentArray[contentArray.length - 1] += ',';
127
+ return contentArray;
128
+ }
129
+
130
+ /**
131
+ * Adjusts the views related to controller.Component or model.Component
132
+ * @param {Object} opts
133
+ * @param {String} opts.file
134
+ * @param {String} opts.viewFile
135
+ */
136
+ function adjustView(opts) {
137
+ let file = opts.file,
138
+ viewFile = opts.viewFile,
139
+ content = fs.readFileSync(viewFile).toString().split(os.EOL),
140
+ fromMaxPosition = 0,
141
+ i = 0,
142
+ len = content.length,
143
+ adjustSpaces, codeLine, fromPosition, importLength, importName, j, spaces;
144
+
145
+ // find the index where we want to insert our import statement
146
+ for (; i < len; i++) {
147
+ codeLine = content[i];
148
+
149
+ if (codeLine === '') {
150
+ break;
151
+ }
152
+
153
+ importName = codeLine.substr(7);
154
+ importName = importName.substr(0, importName.indexOf(' '));
155
+ importLength = importName.length;
156
+
157
+ if (importName > file) {
158
+ break;
159
+ }
160
+ }
161
+
162
+ content.splice(i, 0, `import ${file} from './${file}.mjs';`);
163
+
164
+ // find the longest import module name
165
+ for (i=0; i < len; i++) {
166
+ codeLine = content[i];
167
+
168
+ if (codeLine === '') {
169
+ break;
170
+ }
171
+
172
+ fromMaxPosition = Math.max(fromMaxPosition, codeLine.indexOf('from'));
173
+ }
174
+
175
+ // adjust the block-formatting for imports
176
+ for (i=0; i < len; i++) {
177
+ codeLine = content[i];
178
+
179
+ if (codeLine === '') {
180
+ break;
181
+ }
182
+
183
+ fromPosition = codeLine.indexOf('from');
184
+ adjustSpaces = fromMaxPosition - fromPosition;
185
+
186
+ if (adjustSpaces > 0) {
187
+ spaces = '';
188
+
189
+ for (j=0; j < adjustSpaces; j++) {
190
+ spaces += ' ';
191
+ }
192
+
193
+ content[i] = codeLine.substr(0, fromPosition) + spaces + codeLine.substr(fromPosition);
194
+ }
195
+ }
196
+
197
+ fs.writeFileSync(viewFile, content.join(os.EOL));
198
+
199
+ console.log(i, opts.file);
200
+ console.log(content);
201
+ }
202
+
203
+ /**
204
+ * Creates the content of the neo-class .mjs file
205
+ * @param {Object} opts
206
+ * @param {String} opts.baseClass
207
+ * @param {String} opts.className
208
+ * @param {String} opts.file
209
+ * @param {String} opts.folderDelta
210
+ * @param {String} opts.ns
211
+ * @param {String} opts.root
212
+ * @returns {String}
213
+ */
214
+ function createContent(opts) {
215
+ let baseClass = opts.baseClass,
216
+ baseClassNs = baseClass.split('.'),
217
+ baseFileName = baseClassNs.pop(),
218
+ className = opts.className,
219
+ file = opts.file,
220
+ i = 0,
221
+ importDelta = '';
222
+
223
+ for (; i < opts.folderDelta; i++) {
224
+ importDelta += '../';
225
+ }
226
+
227
+ let classContent = [
228
+ `import ${baseFileName} from '${importDelta}${(insideNeo ? '' : 'node_modules/neo.mjs/')}src/${baseClassNs.join('/')}/${baseFileName}.mjs';`,
229
+ "",
230
+ "/**",
231
+ ` * @class ${className}`,
232
+ ` * @extends Neo.${baseClass}`,
233
+ " */",
234
+ `class ${file} extends ${baseFileName} {`,
235
+ " static getConfig() {return {",
236
+ " /*",
237
+ ` * @member {String} className='${className}'`,
238
+ " * @protected",
239
+ " */",
240
+ ` className: '${className}'`
241
+ ];
242
+
243
+ baseClass === 'container.Base' && addComma(classContent).push(
244
+ " /*",
245
+ " * @member {Object[]} items",
246
+ " */",
247
+ " items: []"
248
+ );
249
+
250
+ baseClass === 'component.Base' && addComma(classContent).push(
251
+ " /*",
252
+ " * @member {Object} _vdom",
253
+ " */",
254
+ " _vdom:",
255
+ " {}"
256
+ );
257
+
258
+ classContent.push(
259
+ " }}",
260
+ "}",
261
+ "",
262
+ `Neo.applyClassConfig(${file});`,
263
+ "",
264
+ `export default ${file};`,
265
+ ""
266
+ );
267
+
268
+ return classContent.join(os.EOL);
269
+ }
270
+ }
@@ -16,7 +16,8 @@ const cwd = process.cwd(),
16
16
  regexTrimEnd = /\s+$/gm,
17
17
  regexTrimStart = /^\s+/gm;
18
18
 
19
- let config, examplesPath;
19
+ let contextAdjusted = false,
20
+ config, examplesPath;
20
21
 
21
22
  if (fs.existsSync(configPath)) {
22
23
  config = requireJson(configPath);
@@ -134,8 +135,11 @@ export default env => {
134
135
 
135
136
  plugins: [
136
137
  new webpack.ContextReplacementPlugin(/.*/, context => {
137
- if (!insideNeo && context.context.includes('/src/worker')) {
138
- context.request = '../../' + context.request;
138
+ let con = context.context;
139
+
140
+ if (!insideNeo && !contextAdjusted && (con.includes('/src/worker') || con.includes('\\src\\worker'))) {
141
+ context.request = path.join('../../', context.request);
142
+ contextAdjusted = true;
139
143
  }
140
144
  }),
141
145
  ...plugins
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "4.0.48",
3
+ "version": "4.0.51",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -14,6 +14,7 @@
14
14
  "build-themes": "node ./buildScripts/buildThemes.mjs -f",
15
15
  "build-threads": "node ./buildScripts/webpack/buildThreads.mjs -f",
16
16
  "create-app": "node ./buildScripts/createApp.mjs",
17
+ "create-class": "node ./buildScripts/createClass.mjs",
17
18
  "generate-docs-json": "node ./buildScripts/docs/jsdocx.mjs",
18
19
  "server-start": "webpack serve -c ./buildScripts/webpack/webpack.server.config.mjs --open",
19
20
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -42,11 +43,11 @@
42
43
  "chalk": "^5.0.1",
43
44
  "clean-webpack-plugin": "^4.0.0",
44
45
  "commander": "^9.3.0",
45
- "cssnano": "^5.1.11",
46
+ "cssnano": "^5.1.12",
46
47
  "envinfo": "^7.8.1",
47
48
  "fs-extra": "^10.1.0",
48
49
  "highlightjs-line-numbers.js": "^2.8.0",
49
- "inquirer": "^8.2.4",
50
+ "inquirer": "^9.0.0",
50
51
  "neo-jsdoc": "^1.0.1",
51
52
  "neo-jsdoc-x": "^1.0.4",
52
53
  "postcss": "^8.4.14",
@@ -326,8 +326,9 @@ class DateSelector extends Component {
326
326
  me.currentDate = new Date(`${value}T00:00:00`);
327
327
 
328
328
  me.fire('change', {
329
- oldValue: oldValue,
330
- value : value
329
+ component: me,
330
+ oldValue,
331
+ value
331
332
  });
332
333
  } else {
333
334
  me.cacheUpdate();
@@ -191,8 +191,8 @@ class TextField extends Component {
191
191
 
192
192
  me.fire('change', {
193
193
  component: me,
194
- oldValue : oldValue,
195
- value : value
194
+ oldValue,
195
+ value
196
196
  });
197
197
  }
198
198
 
@@ -325,8 +325,8 @@ class DragZone extends Base {
325
325
 
326
326
  Object.assign(me, {
327
327
  dragElementRect: rect,
328
- offsetX : offsetX,
329
- offsetY : offsetY
328
+ offsetX,
329
+ offsetY
330
330
  });
331
331
 
332
332
  me.createDragProxy(rect);
@@ -337,8 +337,8 @@ class DragZone extends Base {
337
337
  dragElementRect: rect,
338
338
  eventData : data,
339
339
  id : me.id,
340
- offsetX : offsetX,
341
- offsetY : offsetY
340
+ offsetX,
341
+ offsetY
342
342
  });
343
343
  }
344
344
 
@@ -45,8 +45,8 @@ class BooleanContainer extends Container {
45
45
  if (oldValue !== undefined) {
46
46
  this.fire('change', {
47
47
  component: this,
48
- oldValue : oldValue,
49
- value : value
48
+ oldValue,
49
+ value
50
50
  });
51
51
  }
52
52
  }
@@ -59,8 +59,8 @@ class NumberContainer extends Container {
59
59
  if (oldValue !== undefined) {
60
60
  this.fire('operatorChange', {
61
61
  component: this,
62
- oldValue : oldValue,
63
- value : value
62
+ oldValue,
63
+ value
64
64
  });
65
65
  }
66
66
  }
@@ -74,8 +74,8 @@ class NumberContainer extends Container {
74
74
  if (oldValue !== undefined) {
75
75
  this.fire('change', {
76
76
  component: this,
77
- oldValue : oldValue,
78
- value : value
77
+ oldValue,
78
+ value
79
79
  });
80
80
  }
81
81
  }
@@ -53,8 +53,8 @@ class ToggleOperatorsButton extends Button {
53
53
 
54
54
  me.fire('change', {
55
55
  component: me,
56
- oldValue : oldValue,
57
- value : value
56
+ oldValue,
57
+ value
58
58
  });
59
59
  }
60
60
  }
@@ -42,8 +42,8 @@ class Base extends Component {
42
42
  fireChangeEvent(value, oldValue) {
43
43
  this.fire('change', {
44
44
  component: this,
45
- oldValue : oldValue,
46
- value : value
45
+ oldValue,
46
+ value
47
47
  });
48
48
  }
49
49
 
@@ -174,6 +174,28 @@ class Number extends Text {
174
174
  return this.beforeSetEnumValue(value, oldValue, 'triggerPosition');
175
175
  }
176
176
 
177
+ /**
178
+ * @returns {Boolean}
179
+ */
180
+ isValid() {
181
+ let me = this,
182
+ value = me.value;
183
+
184
+ if (Neo.isNumber(me.maxValue) && value > me.maxValue) {
185
+ return false;
186
+ }
187
+
188
+ if (Neo.isNumber(me.minValue) && value < me.minValue) {
189
+ return false;
190
+ }
191
+
192
+ if (value % me.stepSize !== 0) {
193
+ return false;
194
+ }
195
+
196
+ return super.isValid();
197
+ }
198
+
177
199
  /**
178
200
  *
179
201
  */
@@ -93,6 +93,16 @@ class Text extends Base {
93
93
  * @member {Number|String} labelWidth_=150
94
94
  */
95
95
  labelWidth_: 150,
96
+ /**
97
+ * The maximum amount of chars which you can enter into this field
98
+ * @member {Number|null} maxLength_=null
99
+ */
100
+ maxLength_: null,
101
+ /**
102
+ * The minimum amount of chars which you can enter into this field
103
+ * @member {Number|null} minLength_=null
104
+ */
105
+ minLength_: null,
96
106
  /**
97
107
  * @member {String|null} placeholderText_=null
98
108
  */
@@ -358,6 +368,26 @@ class Text extends Base {
358
368
  }
359
369
  }
360
370
 
371
+ /**
372
+ * Triggered after the maxLength config got changed
373
+ * @param {Number|null} value
374
+ * @param {Number|null} oldValue
375
+ * @protected
376
+ */
377
+ afterSetMaxLength(value, oldValue) {
378
+ this.changeInputElKey('maxlength', value);
379
+ }
380
+
381
+ /**
382
+ * Triggered after the minLength config got changed
383
+ * @param {Number|null} value
384
+ * @param {Number|null} oldValue
385
+ * @protected
386
+ */
387
+ afterSetMinLength(value, oldValue) {
388
+ this.changeInputElKey('minlength', value);
389
+ }
390
+
361
391
  /**
362
392
  * Triggered after the mounted config got changed
363
393
  * @param {Boolean} value
@@ -776,9 +806,19 @@ class Text extends Base {
776
806
  * @returns {Boolean}
777
807
  */
778
808
  isValid() {
779
- let me = this;
809
+ let me = this,
810
+ value = me.value,
811
+ valueLength = value?.toString().length;
812
+
813
+ if (me.required && (!value || valueLength < 1)) {
814
+ return false;
815
+ }
816
+
817
+ if (Neo.isNumber(me.maxLength) && valueLength > me.maxLength) {
818
+ return false;
819
+ }
780
820
 
781
- if (me.required && (!me.value || me.value?.length < 1)) {
821
+ if (Neo.isNumber(me.minLength) && valueLength < me.minLength) {
782
822
  return false;
783
823
  }
784
824
 
@@ -230,7 +230,7 @@ class AmCharts extends Base {
230
230
  this.setProperty({
231
231
  id : data.id,
232
232
  path : key,
233
- value: value
233
+ value
234
234
  })
235
235
  });
236
236
  }
@@ -54,7 +54,6 @@ class TouchDomEvents extends Base {
54
54
  * @param {Object} event
55
55
  */
56
56
  onTouchStart(event) {
57
- console.log('onTouchStart', event);
58
57
  this.sendMessageToApp(this.getEventData(event));
59
58
  }
60
59
  }
@@ -140,7 +140,7 @@ class GalleryModel extends Model {
140
140
  me.select(record[store.keyProperty]);
141
141
 
142
142
  view.fire('select', {
143
- record: record
143
+ record
144
144
  });
145
145
  }
146
146
 
@@ -190,7 +190,7 @@ class GalleryModel extends Model {
190
190
  me.select(record[store.keyProperty]);
191
191
 
192
192
  view.fire('select', {
193
- record: record
193
+ record
194
194
  });
195
195
  }
196
196
 
@@ -154,7 +154,7 @@ class HelixModel extends Model {
154
154
  me.select(record[store.keyProperty]);
155
155
 
156
156
  view.fire('select', {
157
- record: record
157
+ record
158
158
  });
159
159
  }
160
160
 
@@ -186,7 +186,7 @@ class HelixModel extends Model {
186
186
  me.select(record[store.keyProperty]);
187
187
 
188
188
  view.fire('select', {
189
- record: record
189
+ record
190
190
  });
191
191
  }
192
192
 
@@ -259,7 +259,7 @@ class HelixModel extends Model {
259
259
  view.mounted && Neo.currentWorker.promiseMessage('main', {
260
260
  action : 'updateDom',
261
261
  appName: view.appName,
262
- deltas : deltas
262
+ deltas
263
263
  }).then(() => {
264
264
  view.onSelect?.(items);
265
265
  me.fire('selectionChange', items, oldItems);
@@ -80,7 +80,7 @@ class View extends Component {
80
80
  trCls.push('neo-selected');
81
81
 
82
82
  Neo.getComponent(me.containerId).fire('select', {
83
- record: record
83
+ record
84
84
  });
85
85
  }
86
86