neo.mjs 4.1.2 → 4.2.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.
@@ -15,12 +15,12 @@ class FooterComponent extends Component {
15
15
  * @member {Object} _vdom
16
16
  */
17
17
  _vdom:
18
- {tag: 'footer', cn: [
19
- {cls: ['container'], cn: [
20
- {tag: 'a', cls: ['logo-font'], href: '#/', html: 'conduit'},
21
- {tag: 'span', cls: 'attribution', html: 'An interactive learning project from <a href="https://thinkster.io">Thinkster</a>. Code &amp; design licensed under MIT.'}
22
- ]}
18
+ {tag: 'footer', cn: [
19
+ {cls: ['container'], cn: [
20
+ {tag: 'a', cls: ['logo-font'], href: '#/', html: 'conduit'},
21
+ {tag: 'span', cls: 'attribution', html: 'An interactive learning project from <a href="https://thinkster.io">Thinkster</a>. Code &amp; design licensed under MIT.'}
23
22
  ]}
23
+ ]}
24
24
  }}
25
25
  }
26
26
 
@@ -36,40 +36,40 @@ class HeaderComponent extends Component {
36
36
  * @member {Object} _vdom
37
37
  */
38
38
  _vdom:
39
- {tag: 'nav', cls: ['navbar navbar-light'], cn: [
40
- {cls: ['container'], cn: [
41
- {tag: 'a', cls: ['navbar-brand'], href: '#/', html: 'conduit'},
42
- {tag: 'ul', cls: ['nav navbar-nav', 'pull-xs-right'], cn: [
43
- {tag: 'li', cls: ['nav-item'], cn: [
44
- {tag: 'a', cls: ['nav-link'], href: '#/', html: 'Home'}
45
- ]},
46
- {tag: 'li', cls: ['nav-item'], removeDom: true, cn: [
47
- {tag: 'a', cls: ['nav-link'], href: '#/editor', cn: [
48
- {tag: 'i', cls: 'ion-compose'},
49
- {vtype: 'text', html: '&nbsp;New Article'}
50
- ]}
51
- ]},
52
- {tag: 'li', cls: ['nav-item'], removeDom: true, cn: [
53
- {tag: 'a', cls: ['nav-link'], href: '#/settings', cn: [
54
- {tag: 'i', cls: 'ion-gear-a'},
55
- {vtype: 'text', html: '&nbsp;Settings'}
56
- ]}
57
- ]},
58
- {tag: 'li', cls: ['nav-item'], removeDom: true, cn: [
59
- {tag: 'a', cls : ['nav-link'], href: '#/profile', cn: [
60
- {tag: 'img', cls: ['user-pic']},
61
- {vtype: 'text', html: '&nbsp;Profile'}
62
- ]}
63
- ]},
64
- {tag: 'li', cls: ['nav-item'], cn: [
65
- {tag : 'a', cls : ['nav-link'], href: '#/login', html: 'Sign in'}
66
- ]},
67
- {tag: 'li', cls: ['nav-item'], cn: [
68
- {tag: 'a', cls : ['nav-link'], href: '#/register', html: 'Sign up'}
39
+ {tag: 'nav', cls: ['navbar navbar-light'], cn: [
40
+ {cls: ['container'], cn: [
41
+ {tag: 'a', cls: ['navbar-brand'], href: '#/', html: 'conduit'},
42
+ {tag: 'ul', cls: ['nav navbar-nav', 'pull-xs-right'], cn: [
43
+ {tag: 'li', cls: ['nav-item'], cn: [
44
+ {tag: 'a', cls: ['nav-link'], href: '#/', html: 'Home'}
45
+ ]},
46
+ {tag: 'li', cls: ['nav-item'], removeDom: true, cn: [
47
+ {tag: 'a', cls: ['nav-link'], href: '#/editor', cn: [
48
+ {tag: 'i', cls: 'ion-compose'},
49
+ {vtype: 'text', html: '&nbsp;New Article'}
69
50
  ]}
51
+ ]},
52
+ {tag: 'li', cls: ['nav-item'], removeDom: true, cn: [
53
+ {tag: 'a', cls: ['nav-link'], href: '#/settings', cn: [
54
+ {tag: 'i', cls: 'ion-gear-a'},
55
+ {vtype: 'text', html: '&nbsp;Settings'}
56
+ ]}
57
+ ]},
58
+ {tag: 'li', cls: ['nav-item'], removeDom: true, cn: [
59
+ {tag: 'a', cls : ['nav-link'], href: '#/profile', cn: [
60
+ {tag: 'img', cls: ['user-pic']},
61
+ {vtype: 'text', html: '&nbsp;Profile'}
62
+ ]}
63
+ ]},
64
+ {tag: 'li', cls: ['nav-item'], cn: [
65
+ {tag : 'a', cls : ['nav-link'], href: '#/login', html: 'Sign in'}
66
+ ]},
67
+ {tag: 'li', cls: ['nav-item'], cn: [
68
+ {tag: 'a', cls : ['nav-link'], href: '#/register', html: 'Sign up'}
70
69
  ]}
71
70
  ]}
72
71
  ]}
72
+ ]}
73
73
  }}
74
74
 
75
75
  /**
@@ -280,8 +280,8 @@ class HomeComponent extends Component {
280
280
  cls: ['nav-item'],
281
281
  id : me.id + '__nav-item_' + index,
282
282
  cn : [{
283
- tag: 'a',
284
- cls: cls,
283
+ tag : 'a',
284
+ cls : cls,
285
285
  href: '',
286
286
  html: item.name,
287
287
  id : me.id + '__nav-item-link_' + index,
@@ -447,12 +447,12 @@ class HomeComponent extends Component {
447
447
  if (feeds.length < 3) {
448
448
  feeds.push({
449
449
  active: true,
450
- name : name
450
+ name
451
451
  });
452
452
  } else {
453
453
  Object.assign(feeds[2], {
454
454
  active: true,
455
- name : name
455
+ name
456
456
  });
457
457
  }
458
458
 
@@ -144,7 +144,7 @@ class MainContainerController extends ComponentController {
144
144
  */
145
145
  getArticle(slug) {
146
146
  return ArticleApi.get({
147
- slug: slug
147
+ slug
148
148
  });
149
149
  }
150
150
 
@@ -406,9 +406,9 @@ class MainContainerController extends ComponentController {
406
406
  module = await module();
407
407
 
408
408
  me[key] = Neo.create({
409
- module : module.default,
410
- parentId : me.component.id,
411
- reference: reference
409
+ module : module.default,
410
+ parentId: me.component.id,
411
+ reference
412
412
  });
413
413
  }
414
414
 
@@ -233,8 +233,8 @@ class Component extends BaseComponent {
233
233
 
234
234
  VDomUtil.getByFlag(vdom, 'body').cn[0] = {
235
235
  cn: [{
236
- tag : 'p',
237
- html: html
236
+ tag: 'p',
237
+ html
238
238
  }]
239
239
  };
240
240
 
@@ -267,7 +267,7 @@ class PreviewComponent extends Component {
267
267
  favorited = !me.favorited;
268
268
 
269
269
  me.set({
270
- favorited : favorited,
270
+ favorited,
271
271
  favoritesCount: favorited ? (me.favoritesCount + 1) : (me.favoritesCount - 1)
272
272
  });
273
273
  }
@@ -78,8 +78,8 @@ class TagListComponent extends Component {
78
78
  afterSetActiveTag(value, oldValue) {
79
79
  if (oldValue !== undefined) {
80
80
  this.fire('tagChange', {
81
- oldValue: oldValue,
82
- value : value
81
+ oldValue,
82
+ value
83
83
  });
84
84
  }
85
85
  }
@@ -46,7 +46,7 @@ class MainContainer extends Viewport {
46
46
  ntype : 'container',
47
47
  flex : 1,
48
48
  items : [],
49
- layout : {ntype: 'card'},
49
+ layout : {ntype: 'card', activeIndex: null},
50
50
  reference: 'cards'
51
51
  }, {
52
52
  module: FooterComponent
@@ -209,8 +209,8 @@ class MainContainerController extends ComponentController {
209
209
 
210
210
  if (!card) {
211
211
  card = me.getReference('cards').add({
212
- module : module,
213
- reference: reference
212
+ module,
213
+ reference
214
214
  });
215
215
  }
216
216
 
@@ -1,4 +1,17 @@
1
1
  [
2
+ {
3
+ "author" : "Tobias Uhlig",
4
+ "authorImage" : "author_TobiasUhlig.jpeg",
5
+ "date" : "Sep 07, 2022",
6
+ "id" : 53,
7
+ "image" : "the-secret-of-successfully-using-multi-window-webgl-canvas.png",
8
+ "name" : "The secret of successfully using multi window WebGL Canvas",
9
+ "provider" : "Medium",
10
+ "publisher" : "",
11
+ "selectedInto": [],
12
+ "type" : "Blog Post",
13
+ "url" : "https://tobiasuhlig.medium.com/the-secret-of-successfully-using-multi-window-webgl-canvas-5a2d05555ad1?source=friends_link&sk=d24ec0ec25aa6678d5fd1f59aaf09007"
14
+ },
2
15
  {
3
16
  "author" : "Tobias Uhlig",
4
17
  "authorImage" : "author_TobiasUhlig.jpeg",
@@ -0,0 +1,400 @@
1
+ #!/usr/bin/env node
2
+
3
+ import chalk from 'chalk';
4
+ import { Command } from 'commander/esm.mjs';
5
+ import envinfo from 'envinfo';
6
+ import fs from 'fs-extra';
7
+ import inquirer from 'inquirer';
8
+ import os from 'os';
9
+ import path from 'path';
10
+
11
+ const
12
+ __dirname = path.resolve(),
13
+ cwd = process.cwd(),
14
+ requireJson = path => JSON.parse(fs.readFileSync((path))),
15
+ packageJson = requireJson(path.join(__dirname, 'package.json')),
16
+ program = new Command(),
17
+ programName = `${packageJson.name} add-config`;
18
+
19
+ /**
20
+ * Adds a comma to the last element of the contentArray
21
+ * @param {String[]} contentArray
22
+ * @param {Number} index=contentArray.length - 1
23
+ * @returns {String[]}
24
+ */
25
+ function addComma(contentArray, index=contentArray.length - 1) {
26
+ contentArray[index] += ',';
27
+ return contentArray;
28
+ }
29
+
30
+ /**
31
+ * Adds a config to the given index of the contentArray
32
+ * @param {Object} opts
33
+ * @param {String} opts.configName
34
+ * @param {String} opts.defaultValue
35
+ * @param {String[]} opts.contentArray
36
+ * @param {Boolean} opts.isLastConfig
37
+ * @param {Number} opts.index
38
+ * @param {String} opts.type
39
+ * @returns {String[]}
40
+ */
41
+ function addConfig(opts) {
42
+ if (opts.type === 'String' && opts.defaultValue !== 'null') {
43
+ opts.defaultValue = `'${opts.defaultValue}'`;
44
+ }
45
+
46
+ const config = [
47
+ ' /**',
48
+ ` * @member {${opts.type}} ${opts.configName}_=${opts.defaultValue}`,
49
+ ' */',
50
+ ` ${opts.configName}_: ${opts.defaultValue}`
51
+ ];
52
+
53
+ !opts.isLastConfig && addComma(config);
54
+
55
+ opts.contentArray.splice(opts.index, 0, config.join(os.EOL));
56
+ return opts.contentArray;
57
+ }
58
+
59
+ /**
60
+ * Adds a config hook at the matching index
61
+ * @param {Object} opts
62
+ * @param {String} opts.comment
63
+ * @param {String[]} opts.contentArray
64
+ * @param {String} opts.name
65
+ * @param {Boolean} opts.oldValueParam
66
+ * @param {Boolean} opts.returnValue
67
+ * @param {String} opts.type
68
+ * @returns {String[]}
69
+ */
70
+ function addHook(opts) {
71
+ let contentArray = opts.contentArray,
72
+ i = 0,
73
+ inserted = false,
74
+ name = opts.name,
75
+ len = contentArray.length,
76
+ type = opts.type,
77
+ j, methodName, nextLine,
78
+
79
+ method = [
80
+ '',
81
+ ' /**',
82
+ ` * ${opts.comment}`,
83
+ ` * @param {${type}} value`
84
+ ];
85
+
86
+ if (opts.oldValueParam) {
87
+ method.push(
88
+ ` * @param {${type}} oldValue`
89
+ );
90
+ }
91
+
92
+ if (opts.returnValue) {
93
+ method.push(
94
+ ` * @returns {${type}}`
95
+ );
96
+ }
97
+
98
+ method.push(
99
+ ' * @protected',
100
+ ' */'
101
+ );
102
+
103
+ if (opts.oldValueParam) {
104
+ method.push(
105
+ ` ${name}(value, oldValue) {`
106
+ );
107
+ } else {
108
+ method.push(
109
+ ` ${name}(value) {`
110
+ );
111
+ }
112
+
113
+ if (opts.returnValue) {
114
+ method.push(
115
+ ' return value;'
116
+ );
117
+ } else {
118
+ method.push(
119
+ ' '
120
+ );
121
+ }
122
+
123
+ method.push(
124
+ ' }'
125
+ );
126
+
127
+ for (; i < len; i++) {
128
+ if (contentArray[i].includes('}}')) {
129
+ break;
130
+ }
131
+ }
132
+
133
+ for (; i < len; i++) {
134
+ if (contentArray[i].includes('*/')) {
135
+ nextLine = contentArray[i + 1]
136
+ methodName = nextLine.substring(0, nextLine.indexOf('(')).trim();
137
+
138
+ if (methodName === 'construct') {
139
+ continue;
140
+ }
141
+
142
+ if (methodName > name) {
143
+ for (j=i; j > 0; j--) {
144
+ if (contentArray[j].includes('/**')) {
145
+ contentArray.splice(j - 1, 0, method.join(os.EOL));
146
+ inserted = true;
147
+ break;
148
+ }
149
+ }
150
+ break;
151
+ }
152
+ }
153
+ }
154
+
155
+ if (!inserted) {
156
+ for (i=contentArray.length - 1; i > 0; i--) {
157
+ if (contentArray[i].includes('}')) {
158
+ contentArray.splice(i, 0, method.join(os.EOL));
159
+ break;
160
+ }
161
+ }
162
+ }
163
+
164
+ return contentArray;
165
+ }
166
+
167
+
168
+ /**
169
+ * Makes the first character of a string uppercase
170
+ * @param {String} value
171
+ * @returns {Boolean|String} Returns false for non string inputs
172
+ */
173
+ function capitalize(value) {
174
+ return value[0].toUpperCase() + value.slice(1);
175
+ }
176
+
177
+ program
178
+ .name(programName)
179
+ .version(packageJson.version)
180
+ .option('-i, --info', 'print environment debug info')
181
+ .option('-c, --className <value>')
182
+ .option('-d, --defaultValue <value>')
183
+ .option('-h, --hooks <value>')
184
+ .option('-n, --configName <value>')
185
+ .option('-t, --type <value>')
186
+ .allowUnknownOption()
187
+ .on('--help', () => {
188
+ console.log('\nIn case you have any issues, please create a ticket here:');
189
+ console.log(chalk.cyan(process.env.npm_package_bugs_url));
190
+ })
191
+ .parse(process.argv);
192
+
193
+ const programOpts = program.opts();
194
+
195
+ if (programOpts.info) {
196
+ console.log(chalk.bold('\nEnvironment Info:'));
197
+ console.log(`\n current version of ${packageJson.name}: ${packageJson.version}`);
198
+ console.log(` running from ${cwd}`);
199
+
200
+ envinfo
201
+ .run({
202
+ System : ['OS', 'CPU'],
203
+ Binaries : ['Node', 'npm', 'Yarn'],
204
+ Browsers : ['Chrome', 'Edge', 'Firefox', 'Safari'],
205
+ npmPackages: ['neo.mjs']
206
+ }, {
207
+ duplicates : true,
208
+ showNotFound: true
209
+ })
210
+ .then(console.log);
211
+ } else {
212
+ console.log(chalk.green(programName));
213
+
214
+ let answers = {},
215
+ answer;
216
+
217
+ if (!programOpts.className) {
218
+ answer = await inquirer.prompt({
219
+ type : 'input',
220
+ name : 'className',
221
+ message: 'Please choose the namespace of your class:',
222
+ default: 'Covid.view.MainContainer'
223
+ });
224
+
225
+ Object.assign(answers, answer);
226
+ }
227
+
228
+ let className = programOpts.className || answers.className,
229
+ ns = className.split('.'),
230
+ root = ns.shift().toLowerCase(),
231
+ classPath = path.resolve(cwd, root === 'neo' ? 'src' : `apps/${root}`, `${ns.join('/')}.mjs`);
232
+
233
+ if (!fs.existsSync(path.resolve(classPath))) {
234
+ console.log(chalk.red(`File not found for ${className} => ${classPath}`));
235
+ process.exit(1);
236
+ }
237
+
238
+ if (!programOpts.configName) {
239
+ answer = await inquirer.prompt({
240
+ type : 'input',
241
+ name : 'configName',
242
+ message: 'Please enter a name for your class config:'
243
+ });
244
+
245
+ Object.assign(answers, answer);
246
+ }
247
+
248
+ let configName = programOpts.configName || answers.configName;
249
+
250
+ if (configName.endsWith('_')) {
251
+ configName = configName.slice(0, -1);
252
+ }
253
+
254
+ let uConfigName = capitalize(configName);
255
+
256
+ if (!programOpts.type) {
257
+ answer = await inquirer.prompt({
258
+ type : 'list',
259
+ name : 'type',
260
+ message: 'Please choose a type for your class config:',
261
+ default: 'Custom',
262
+ choices: [
263
+ 'Custom',
264
+ 'Object',
265
+ 'Object[]',
266
+ 'Number',
267
+ 'Number[]',
268
+ 'String',
269
+ 'String[]'
270
+ ]
271
+ });
272
+
273
+ Object.assign(answers, answer);
274
+ }
275
+
276
+ if (answers.type === 'Custom') {
277
+ answer = await inquirer.prompt({
278
+ type : 'input',
279
+ name : 'type',
280
+ message: 'Please enter the type for your class config:'
281
+ });
282
+
283
+ Object.assign(answers, answer);
284
+ }
285
+
286
+ if (!programOpts.defaultValue) {
287
+ answer = await inquirer.prompt({
288
+ type : 'input',
289
+ name : 'defaultValue',
290
+ message: 'Please enter a defaultValue:',
291
+ default: 'null'
292
+ });
293
+
294
+ Object.assign(answers, answer);
295
+ }
296
+
297
+ if (!programOpts.hooks) {
298
+ answer = await inquirer.prompt({
299
+ type : 'checkbox',
300
+ name : 'hooks',
301
+ message: 'Please choose the hooks for your class config:',
302
+ choices: [`afterSet${uConfigName}()`, `beforeGet${uConfigName}()`, `beforeSet${uConfigName}()`],
303
+ default: [`afterSet${uConfigName}()`]
304
+ });
305
+
306
+ Object.assign(answers, answer);
307
+ }
308
+
309
+ let defaultValue = programOpts.defaultValue || answers.defaultValue,
310
+ hooks = programOpts.hooks || answers.hooks,
311
+ type = programOpts.type || answers.type,
312
+ contentArray = fs.readFileSync(classPath).toString().split(os.EOL),
313
+ i = 0,
314
+ len = contentArray.length,
315
+ codeLine, existingConfigName, j, nextLine;
316
+
317
+ for (; i < len; i++) {
318
+ if (contentArray[i].includes('static getConfig')) {
319
+ break;
320
+ }
321
+ }
322
+
323
+ for (; i < len; i++) {
324
+ codeLine = contentArray[i];
325
+
326
+ if (codeLine.includes('}}')) {
327
+ addComma(contentArray, i - 1);
328
+ addConfig({
329
+ configName,
330
+ defaultValue,
331
+ contentArray,
332
+ index : i,
333
+ isLastConfig: true,
334
+ type
335
+ });
336
+ break;
337
+ }
338
+
339
+ if (codeLine.includes('*/')) {
340
+ nextLine = contentArray[i + 1]
341
+ existingConfigName = nextLine.substring(0, nextLine.indexOf(':')).trim();
342
+
343
+ if (existingConfigName === 'className' || existingConfigName === 'ntype') {
344
+ continue;
345
+ }
346
+
347
+ if (existingConfigName > configName) {
348
+ for (j=i; j > 0; j--) {
349
+ if (contentArray[j].includes('/**')) {
350
+ addConfig({
351
+ configName,
352
+ contentArray,
353
+ defaultValue,
354
+ index : j,
355
+ isLastConfig: false,
356
+ type
357
+ });
358
+ break;
359
+ }
360
+ }
361
+ break;
362
+ }
363
+ }
364
+ }
365
+
366
+ if (hooks.includes(`afterSet${uConfigName}()`)) {
367
+ addHook({
368
+ comment : `Triggered after the ${configName} config got changed`,
369
+ contentArray,
370
+ name : `afterSet${uConfigName}`,
371
+ oldValueParam: true,
372
+ returnValue : false,
373
+ type
374
+ });
375
+ }
376
+
377
+ if (hooks.includes(`beforeGet${uConfigName}()`)) {
378
+ addHook({
379
+ comment : `Gets triggered when accessing the value of the ${configName} config`,
380
+ contentArray,
381
+ name : `beforeGet${uConfigName}`,
382
+ oldValueParam: false,
383
+ returnValue : true,
384
+ type
385
+ });
386
+ }
387
+
388
+ if (hooks.includes(`beforeSet${uConfigName}()`)) {
389
+ addHook({
390
+ comment : `Triggered before the ${configName} config gets changed`,
391
+ contentArray,
392
+ name : `beforeSet${uConfigName}`,
393
+ oldValueParam: true,
394
+ returnValue : true,
395
+ type
396
+ });
397
+ }
398
+
399
+ fs.writeFileSync(classPath, contentArray.join(os.EOL));
400
+ }
@@ -114,6 +114,7 @@ if (programOpts.info) {
114
114
  choices: [
115
115
  'component.Base',
116
116
  'container.Base',
117
+ 'container.Viewport',
117
118
  'controller.Component',
118
119
  'core.Base',
119
120
  'data.Model',
@@ -583,6 +584,13 @@ if (programOpts.info) {
583
584
  ` className: '${className}'`
584
585
  );
585
586
 
587
+ baseClass === 'container.Viewport' && addComma(classContent).push(
588
+ " /**",
589
+ " * @member {Boolean} autoMount=true",
590
+ " */",
591
+ " autoMount: true"
592
+ );
593
+
586
594
  baseClass === 'table.Container' && addComma(classContent).push(
587
595
  " /**",
588
596
  " * @member {Object[]} columns",
@@ -0,0 +1,102 @@
1
+ import CellColumnModel from '../../../src/selection/grid/CellColumnModel.mjs';
2
+ import CellColumnRowModel from '../../../src/selection/grid/CellColumnRowModel.mjs';
3
+ import CellModel from '../../../src/selection/grid/CellModel.mjs';
4
+ import CellRowModel from '../../../src/selection/grid/CellRowModel.mjs';
5
+ import ConfigurationViewport from '../../ConfigurationViewport.mjs';
6
+ import ColumnModel from '../../../src/selection/grid/ColumnModel.mjs';
7
+ import GridContainer from '../../../src/grid/Container.mjs';
8
+ import MainStore from './MainStore.mjs';
9
+ import NumberField from '../../../src/form/field/Number.mjs';
10
+ import Radio from '../../../src/form/field/Radio.mjs';
11
+ import RowModel from '../../../src/selection/grid/RowModel.mjs';
12
+
13
+ /**
14
+ * @class Neo.examples.grid.container.MainContainer
15
+ * @extends Neo.examples.ConfigurationViewport
16
+ */
17
+ class MainContainer extends ConfigurationViewport {
18
+ static getConfig() {return {
19
+ className : 'Neo.examples.grid.container.MainContainer',
20
+ autoMount : true,
21
+ configItemLabelWidth: 130,
22
+ configPanelFlex : 1.5,
23
+ exampleComponentFlex: 3,
24
+ layout : {ntype: 'hbox', align: 'stretch'}
25
+ }}
26
+
27
+ createConfigurationComponents() {
28
+ let me = this;
29
+
30
+ const selectionModelRadioDefaults = {
31
+ module : Radio,
32
+ hideValueLabel: false,
33
+ labelText : '',
34
+ name : 'selectionModel',
35
+ width : 350
36
+ };
37
+
38
+ return [{
39
+ module : NumberField,
40
+ labelText: 'height',
41
+ listeners: {change: me.onConfigChange.bind(me, 'height')},
42
+ maxValue : 800,
43
+ minValue : 225,
44
+ stepSize : 5,
45
+ value : me.exampleComponent.height
46
+ }, {
47
+ ...selectionModelRadioDefaults,
48
+ checked : me.exampleComponent.selectionModel.ntype === 'selection-grid-cellmodel',
49
+ labelText : 'selectionModel',
50
+ listeners : {change: me.onRadioChange.bind(me, 'selectionModel', CellModel)},
51
+ style : {marginTop: '10px'},
52
+ valueLabelText: 'Cell'
53
+ }, {
54
+ ...selectionModelRadioDefaults,
55
+ checked : me.exampleComponent.selectionModel.ntype === 'selection-grid-columnmodel',
56
+ listeners : {change: me.onRadioChange.bind(me, 'selectionModel', ColumnModel)},
57
+ valueLabelText: 'Column'
58
+ }, {
59
+ ...selectionModelRadioDefaults,
60
+ checked : me.exampleComponent.selectionModel.ntype === 'selection-grid-rowmodel',
61
+ listeners : {change: me.onRadioChange.bind(me, 'selectionModel', RowModel)},
62
+ valueLabelText: 'Row'
63
+ }, {
64
+ ...selectionModelRadioDefaults,
65
+ checked : me.exampleComponent.selectionModel.ntype === 'selection-grid-cellcolumnmodel',
66
+ listeners : {change: me.onRadioChange.bind(me, 'selectionModel', CellColumnModel)},
67
+ valueLabelText: 'Cell & Column'
68
+ }, {
69
+ ...selectionModelRadioDefaults,
70
+ checked : me.exampleComponent.selectionModel.ntype === 'selection-grid-cellrowmodel',
71
+ listeners : {change: me.onRadioChange.bind(me, 'selectionModel', CellRowModel)},
72
+ valueLabelText: 'Cell & Row'
73
+ }, {
74
+ ...selectionModelRadioDefaults,
75
+ checked : me.exampleComponent.selectionModel.ntype === 'selection-grid-cellcolumnrowmodel',
76
+ listeners : {change: me.onRadioChange.bind(me, 'selectionModel', CellColumnRowModel)},
77
+ valueLabelText: 'Cell & Column & Row'
78
+ }];
79
+ }
80
+
81
+ createExampleComponent() {
82
+ return Neo.create(GridContainer, {
83
+ selectionModel: CellModel,
84
+ store : MainStore,
85
+
86
+ columnDefaults: {
87
+ width: 200
88
+ },
89
+
90
+ columns: [
91
+ {field: 'firstname', text: 'Firstname'},
92
+ {field: 'lastname', text: 'Lastname'},
93
+ {field: 'githubId', text: 'Github Id'},
94
+ {field: 'country', text: 'Country'}
95
+ ]
96
+ });
97
+ }
98
+ }
99
+
100
+ Neo.applyClassConfig(MainContainer);
101
+
102
+ export default MainContainer;
@@ -0,0 +1,29 @@
1
+ import Model from '../../../src/data/Model.mjs';
2
+
3
+ /**
4
+ * @class Neo.examples.grid.container.MainModel
5
+ * @extends Neo.data.Model
6
+ */
7
+ class MainModel extends Model {
8
+ static getConfig() {return {
9
+ className: 'Neo.examples.grid.container.MainModel',
10
+
11
+ fields: [{
12
+ name: 'country',
13
+ type: 'String'
14
+ }, {
15
+ name: 'firstname',
16
+ type: 'String'
17
+ }, {
18
+ name: 'githubId',
19
+ type: 'String'
20
+ }, {
21
+ name: 'lastname',
22
+ type: 'String'
23
+ }]
24
+ }}
25
+ }
26
+
27
+ Neo.applyClassConfig(MainModel);
28
+
29
+ export default MainModel;
@@ -0,0 +1,55 @@
1
+ import Store from '../../../src/data/Store.mjs';
2
+ import Model from './MainModel.mjs';
3
+
4
+ /**
5
+ * @class Neo.examples.grid.container.MainStore
6
+ * @extends Neo.data.Store
7
+ */
8
+ class MainStore extends Store {
9
+ static getConfig() {return {
10
+ className : 'Neo.examples.grid.container.MainStore',
11
+ keyProperty: 'githubId',
12
+ model : Model,
13
+
14
+ data: [{
15
+ country : 'Germany',
16
+ firstname: 'Tobias',
17
+ githubId : 'tobiu',
18
+ lastname : 'Uhlig'
19
+ },
20
+ {
21
+ country : 'USA',
22
+ firstname: 'Rich',
23
+ githubId : 'rwaters',
24
+ lastname : 'Waters'
25
+ },
26
+ {
27
+ country : 'Germany',
28
+ firstname: 'Nils',
29
+ githubId : 'mrsunshine',
30
+ lastname : 'Dehl'
31
+ },
32
+ {
33
+ country : 'USA',
34
+ firstname: 'Gerard',
35
+ githubId : 'camtnbikerrwc',
36
+ lastname : 'Horan'
37
+ },
38
+ {
39
+ country : 'Slovakia',
40
+ firstname: 'Jozef',
41
+ githubId : 'jsakalos',
42
+ lastname : 'Sakalos'
43
+ },
44
+ {
45
+ country : 'Germany',
46
+ firstname: 'Bastian',
47
+ githubId : 'bhaustein',
48
+ lastname : 'Haustein'
49
+ }]
50
+ }}
51
+ }
52
+
53
+ Neo.applyClassConfig(MainStore);
54
+
55
+ export default MainStore;
@@ -0,0 +1,6 @@
1
+ import MainContainer from './MainContainer.mjs';
2
+
3
+ export const onStart = () => Neo.app({
4
+ mainView: MainContainer,
5
+ name : 'Neo.examples.grid.container'
6
+ });
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE HTML>
2
+ <html>
3
+ <head>
4
+ <meta name="viewport" content="width=device-width, initial-scale=1">
5
+ <meta charset="UTF-8">
6
+ <title>Neo GridContainer</title>
7
+ </head>
8
+ <body>
9
+ <script src="../../../src/MicroLoader.mjs" type="module"></script>
10
+ </body>
11
+ </html>
@@ -0,0 +1,7 @@
1
+ {
2
+ "appPath" : "examples/grid/container/app.mjs",
3
+ "basePath" : "../../../",
4
+ "environment" : "development",
5
+ "mainPath" : "./Main.mjs",
6
+ "mainThreadAddons": ["Stylesheet"]
7
+ }
@@ -10,16 +10,16 @@ class MainModel extends Model {
10
10
 
11
11
  fields: [{
12
12
  name: 'country',
13
- type: 'string'
13
+ type: 'String'
14
14
  }, {
15
15
  name: 'firstname',
16
- type: 'string'
16
+ type: 'String'
17
17
  }, {
18
18
  name: 'githubId',
19
- type: 'string'
19
+ type: 'String'
20
20
  }, {
21
21
  name: 'lastname',
22
- type: 'string'
22
+ type: 'String'
23
23
  }]
24
24
  }}
25
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "4.1.2",
3
+ "version": "4.2.2",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -11,6 +11,7 @@
11
11
  "neo-cc": "./buildScripts/createClass.mjs"
12
12
  },
13
13
  "scripts": {
14
+ "add-config": "node ./buildScripts/addConfig.mjs",
14
15
  "build-all": "node ./buildScripts/buildAll.mjs -f -n",
15
16
  "build-all-questions": "node ./buildScripts/buildAll.mjs -f",
16
17
  "build-my-apps": "node ./buildScripts/webpack/buildMyApps.mjs -f",
@@ -1,6 +1,7 @@
1
1
  .neo-grid-container {
2
2
  border : 1px solid v(grid-container-border-color);
3
3
  border-spacing: 0;
4
+ color : v(grid-container-color);
4
5
  font-size : 13px;
5
6
  font-weight : 400;
6
7
  height : 100%;
@@ -32,7 +33,7 @@
32
33
 
33
34
  .neo-grid-row:nth-child(even) {
34
35
  .neo-grid-cell {
35
- background-color: #323232;
36
+ background-color: v(grid-container-cell-background-color-even);
36
37
  }
37
38
  }
38
39
 
@@ -56,8 +57,8 @@
56
57
  }
57
58
 
58
59
  .neo-grid-cell, .neo-grid-header-cell {
59
- border-bottom: 1px solid #2b2b2b;
60
- border-right : 1px solid #2b2b2b;
60
+ border-bottom: 1px solid v(grid-container-border-color);
61
+ border-right : 1px solid v(grid-container-border-color);
61
62
  height : inherit;
62
63
  min-width : 300px;
63
64
 
@@ -73,7 +74,7 @@
73
74
 
74
75
  .neo-grid-cell {
75
76
  align-items : center;
76
- background-color: #3c3f41;
77
+ background-color: v(grid-container-cell-background-color);
77
78
  display : flex;
78
79
  height : 32px !important;
79
80
  max-height : 32px !important;
@@ -17,6 +17,7 @@ class Socket extends Base {
17
17
  maxReconnectAttempts = 5
18
18
  /**
19
19
  * @member {Object} messageCallbacks={}
20
+ * @protected
20
21
  */
21
22
  messageCallbacks = {}
22
23
  /**
package/src/grid/View.mjs CHANGED
@@ -41,7 +41,7 @@ class View extends Component {
41
41
 
42
42
  // console.log('createViewData', me.id, inputData);
43
43
 
44
- if (container.selectionModel?.ntype === 'selection-table-rowmodel') {
44
+ if (container.selectionModel?.ntype === 'selection-grid-rowmodel') {
45
45
  selectedRows = container.selectionModel.items || [];
46
46
  }
47
47
 
@@ -16,6 +16,16 @@ class Button extends BaseButton {
16
16
  */
17
17
  field = null
18
18
 
19
+ static getStaticConfig() {return {
20
+ /**
21
+ * Valid values for align
22
+ * @member {String[]} alignValues: ['left', 'center', 'right']
23
+ * @protected
24
+ * @static
25
+ */
26
+ alignValues: ['left', 'center', 'right']
27
+ }}
28
+
19
29
  static getConfig() {return {
20
30
  /**
21
31
  * @member {String} className='Neo.grid.header.Button'
@@ -27,6 +37,11 @@ class Button extends BaseButton {
27
37
  * @protected
28
38
  */
29
39
  ntype: 'grid-header-button',
40
+ /**
41
+ * Alignment of the matching table cells. Valid values are left, center, right
42
+ * @member {String} align_='left'
43
+ */
44
+ align_: 'left',
30
45
  /**
31
46
  * @member {String[]} cls=['neo-grid-header-button']
32
47
  */
@@ -98,6 +113,16 @@ class Button extends BaseButton {
98
113
  });
99
114
  }
100
115
 
116
+ /**
117
+ * Triggered before the align config gets changed
118
+ * @param {String} value
119
+ * @param {String} oldValue
120
+ * @protected
121
+ */
122
+ beforeSetAlign(value, oldValue) {
123
+ return this.beforeSetEnumValue(value, oldValue, 'align', 'alignValues');
124
+ }
125
+
101
126
  /**
102
127
  * @protected
103
128
  */
@@ -66,13 +66,13 @@ class CellColumnModel extends CellModel {
66
66
  * @param {Object} data
67
67
  */
68
68
  onCellClick(data) {
69
- let me = this,
70
- id = ColumnModel.getCellId(data.path),
69
+ let me = this,
70
+ id = ColumnModel.getCellId(data.path),
71
71
  columnNodeIds, index, tbodyNode;
72
72
 
73
73
  if (id) {
74
74
  index = ColumnModel.getColumnIndex(id, me.view.items[0].items);
75
- tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {tag: 'tbody'}).vdom;
75
+ tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {cls: 'neo-grid-view'}).vdom;
76
76
  columnNodeIds = VDomUtil.getColumnNodesIds(tbodyNode, index);
77
77
 
78
78
  me.deselectAllCells(true);
@@ -91,15 +91,15 @@ class CellColumnModel extends CellModel {
91
91
  idArray = ColumnModel.getCellId(data.path).split('__'),
92
92
  currentColumn = idArray[2],
93
93
  view = me.view,
94
- dataFields = view.columns.map(c => c.dataField),
95
- newIndex = (dataFields.indexOf(currentColumn) + step) % dataFields.length,
94
+ fields = view.columns.map(c => c.field),
95
+ newIndex = (fields.indexOf(currentColumn) + step) % fields.length,
96
96
  columnNodeIds, tbodyNode;
97
97
 
98
98
  while (newIndex < 0) {
99
- newIndex += dataFields.length;
99
+ newIndex += fields.length;
100
100
  }
101
101
 
102
- tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {tag: 'tbody'}).vdom;
102
+ tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {cls: 'neo-grid-view'}).vdom;
103
103
  columnNodeIds = VDomUtil.getColumnNodesIds(tbodyNode, newIndex);
104
104
 
105
105
  me.deselectAllCells(true);
@@ -72,7 +72,7 @@ class CellColumnRowModel extends CellRowModel {
72
72
 
73
73
  if (id) {
74
74
  index = ColumnModel.getColumnIndex(id, me.view.items[0].items);
75
- tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {tag: 'tbody'}).vdom;
75
+ tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {cls: 'neo-grid-view'}).vdom;
76
76
  columnNodeIds = VDomUtil.getColumnNodesIds(tbodyNode, index);
77
77
 
78
78
  me.deselectAllCells(true);
@@ -91,15 +91,15 @@ class CellColumnRowModel extends CellRowModel {
91
91
  idArray = ColumnModel.getCellId(data.path).split('__'),
92
92
  currentColumn = idArray[2],
93
93
  view = me.view,
94
- dataFields = view.columns.map(c => c.dataField),
95
- newIndex = (dataFields.indexOf(currentColumn) + step) % dataFields.length,
94
+ fields = view.columns.map(c => c.field),
95
+ newIndex = (fields.indexOf(currentColumn) + step) % fields.length,
96
96
  columnNodeIds, tbodyNode;
97
97
 
98
98
  while (newIndex < 0) {
99
- newIndex += dataFields.length;
99
+ newIndex += fields.length;
100
100
  }
101
101
 
102
- tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {tag: 'tbody'}).vdom;
102
+ tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {cls: 'neo-grid-view'}).vdom;
103
103
  columnNodeIds = VDomUtil.getColumnNodesIds(tbodyNode, newIndex);
104
104
 
105
105
  me.deselectAllCells(true);
@@ -45,21 +45,19 @@ class CellModel extends Model {
45
45
  */
46
46
  onCellClick(data) {
47
47
  let me = this,
48
- id = null,
49
48
  path = data.path,
50
49
  i = 0,
51
- len = path.length;
50
+ len = path.length,
51
+ id;
52
52
 
53
53
  for (; i < len; i++) {
54
- if (path[i].tagName === 'td') {
54
+ if (path[i].cls.includes('neo-grid-cell')) {
55
55
  id = path[i].id;
56
56
  break;
57
57
  }
58
58
  }
59
59
 
60
- if (id) {
61
- me.toggleSelection(id);
62
- }
60
+ id && me.toggleSelection(id);
63
61
  }
64
62
 
65
63
  /**
@@ -99,7 +97,7 @@ class CellModel extends Model {
99
97
  view = me.view,
100
98
  idArray = data.path[0].id.split('__'),
101
99
  currentColumn = idArray[2],
102
- dataFields = view.columns.map(c => c.dataField),
100
+ dataFields = view.columns.map(c => c.field),
103
101
  newIndex = (dataFields.indexOf(currentColumn) + step) % dataFields.length,
104
102
  id;
105
103
 
@@ -148,14 +146,12 @@ class CellModel extends Model {
148
146
  id = me.id,
149
147
  view = me.view;
150
148
 
151
- if (view.keys) {
152
- view.keys._keys.push(
153
- {fn: 'onKeyDownDown' ,key: 'Down' ,scope: id},
154
- {fn: 'onKeyDownLeft' ,key: 'Left' ,scope: id},
155
- {fn: 'onKeyDownRight' ,key: 'Right' ,scope: id},
156
- {fn: 'onKeyDownUp' ,key: 'Up' ,scope: id}
157
- );
158
- }
149
+ view.keys?._keys.push(
150
+ {fn: 'onKeyDownDown' ,key: 'Down' ,scope: id},
151
+ {fn: 'onKeyDownLeft' ,key: 'Left' ,scope: id},
152
+ {fn: 'onKeyDownRight' ,key: 'Right' ,scope: id},
153
+ {fn: 'onKeyDownUp' ,key: 'Up' ,scope: id}
154
+ );
159
155
  }
160
156
 
161
157
  /**
@@ -166,14 +162,12 @@ class CellModel extends Model {
166
162
  id = me.id,
167
163
  view = me.view;
168
164
 
169
- if (view.keys) {
170
- view.keys.removeKeys([
171
- {fn: 'onKeyDownDown' ,key: 'Down' ,scope: id},
172
- {fn: 'onKeyDownLeft' ,key: 'Left' ,scope: id},
173
- {fn: 'onKeyDownRight' ,key: 'Right' ,scope: id},
174
- {fn: 'onKeyDownUp' ,key: 'Up' ,scope: id}
175
- ]);
176
- }
165
+ view.keys?.removeKeys([
166
+ {fn: 'onKeyDownDown' ,key: 'Down' ,scope: id},
167
+ {fn: 'onKeyDownLeft' ,key: 'Left' ,scope: id},
168
+ {fn: 'onKeyDownRight' ,key: 'Right' ,scope: id},
169
+ {fn: 'onKeyDownUp' ,key: 'Up' ,scope: id}
170
+ ]);
177
171
 
178
172
  super.unregister();
179
173
  }
@@ -51,7 +51,7 @@ class ColumnModel extends Model {
51
51
  len = eventPath.length;
52
52
 
53
53
  for (; i < len; i++) {
54
- if (eventPath[i].tagName === 'td') {
54
+ if (eventPath[i].cls.includes('neo-grid-cell')) {
55
55
  id = eventPath[i].id;
56
56
  break;
57
57
  }
@@ -61,15 +61,15 @@ class ColumnModel extends Model {
61
61
  }
62
62
 
63
63
  /**
64
- * todo: move to table.Container or view
64
+ * todo: move to grid.Container or view
65
65
  * @param {String} cellId
66
- * @param {Array} columns
66
+ * @param {Object[]} columns
67
67
  * @returns {Number} index
68
68
  */
69
69
  static getColumnIndex(cellId, columns) {
70
70
  let idArray = cellId.split('__'),
71
71
  currentColumn = idArray[2],
72
- dataFields = columns.map(c => c.dataField);
72
+ dataFields = columns.map(c => c.field);
73
73
 
74
74
  return dataFields.indexOf(currentColumn);
75
75
  }
@@ -78,13 +78,13 @@ class ColumnModel extends Model {
78
78
  * @param {Object} data
79
79
  */
80
80
  onCellClick(data) {
81
- let me = this,
82
- id = ColumnModel.getCellId(data.path),
81
+ let me = this,
82
+ id = ColumnModel.getCellId(data.path),
83
83
  columnNodeIds, index, tbodyNode;
84
84
 
85
85
  if (id) {
86
86
  index = ColumnModel.getColumnIndex(id, me.view.items[0].items);
87
- tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {tag: 'tbody'}).vdom;
87
+ tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {cls: 'neo-grid-view'}).vdom;
88
88
  columnNodeIds = VDomUtil.getColumnNodesIds(tbodyNode, index);
89
89
 
90
90
  me.select(columnNodeIds);
@@ -114,18 +114,18 @@ class ColumnModel extends Model {
114
114
  idArray = ColumnModel.getCellId(data.path).split('__'),
115
115
  currentColumn = idArray[2],
116
116
  view = me.view,
117
- dataFields = view.columns.map(c => c.dataField),
118
- newIndex = (dataFields.indexOf(currentColumn) + step) % dataFields.length,
117
+ fields = view.columns.map(c => c.field),
118
+ newIndex = (fields.indexOf(currentColumn) + step) % fields.length,
119
119
  columnNodeIds, id, tbodyNode;
120
120
 
121
121
  while (newIndex < 0) {
122
- newIndex += dataFields.length;
122
+ newIndex += fields.length;
123
123
  }
124
124
 
125
- idArray[2] = dataFields[newIndex];
125
+ idArray[2] = fields[newIndex];
126
126
  id = idArray.join('__');
127
127
 
128
- tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {tag: 'tbody'}).vdom;
128
+ tbodyNode = VDomUtil.findVdomChild(me.view.vdom, {cls: 'neo-grid-view'}).vdom;
129
129
  columnNodeIds = VDomUtil.getColumnNodesIds(tbodyNode, newIndex);
130
130
 
131
131
  me.select(columnNodeIds);
@@ -142,17 +142,15 @@ class ColumnModel extends Model {
142
142
  id = me.id,
143
143
  view = me.view;
144
144
 
145
- if (view.keys) {
146
- view.keys._keys.push({
147
- fn : 'onKeyDownLeft',
148
- key : 'Left',
149
- scope: id
150
- }, {
151
- fn : 'onKeyDownRight',
152
- key : 'Right',
153
- scope: id
154
- });
155
- }
145
+ view.keys?._keys.push({
146
+ fn : 'onKeyDownLeft',
147
+ key : 'Left',
148
+ scope: id
149
+ }, {
150
+ fn : 'onKeyDownRight',
151
+ key : 'Right',
152
+ scope: id
153
+ });
156
154
  }
157
155
 
158
156
 
@@ -164,17 +162,15 @@ class ColumnModel extends Model {
164
162
  id = me.id,
165
163
  view = me.view;
166
164
 
167
- if (view.keys) {
168
- view.keys.removeKeys([{
169
- fn : 'onKeyDownLeft',
170
- key : 'Left',
171
- scope: id
172
- }, {
173
- fn : 'onKeyDownRight',
174
- key : 'Right',
175
- scope: id
176
- }]);
177
- }
165
+ view.keys?.removeKeys([{
166
+ fn : 'onKeyDownLeft',
167
+ key : 'Left',
168
+ scope: id
169
+ }, {
170
+ fn : 'onKeyDownRight',
171
+ key : 'Right',
172
+ scope: id
173
+ }]);
178
174
 
179
175
  super.unregister();
180
176
  }