neo.mjs 4.0.86 → 4.0.89

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.
@@ -157,9 +157,15 @@ if (programOpts.info) {
157
157
  }
158
158
 
159
159
  if (root === 'Neo') {
160
- console.log('todo: create the file inside the src folder');
160
+ if (isDrop) {
161
+ console.log(chalk.red('Drop mode not yet supported for the neo framework scope'));
162
+ process.exit(1);
163
+ } else {
164
+ classFolder = path.join(cwd, '/src/', ns.join('/'));
165
+ folderDelta = ns.length;
166
+ }
161
167
  } else {
162
- if (isDrop === true) {
168
+ if (isDrop) {
163
169
  ns = [];
164
170
 
165
171
  let pathInfo = path.parse(cwd),
@@ -211,9 +217,7 @@ if (programOpts.info) {
211
217
  parts = delta.split(sep);
212
218
 
213
219
  folderDelta = parts.length;
214
- }
215
-
216
- if (isDrop !== true) {
220
+ } else {
217
221
  if (fs.existsSync(path.resolve(cwd, 'apps', rootLowerCase))) {
218
222
  classFolder = path.resolve(cwd, 'apps', rootLowerCase, ns.join('/'));
219
223
  } else {
@@ -221,24 +225,24 @@ if (programOpts.info) {
221
225
  process.exit(1);
222
226
  }
223
227
  }
228
+ }
224
229
 
225
- if (folderDelta === undefined) {
226
- folderDelta = ns.length + 2;
227
- }
228
-
229
- createClass({
230
- baseClass,
231
- className,
232
- isSingleton,
233
- file,
234
- folderDelta,
235
- ns,
236
- root
237
- });
230
+ if (folderDelta === undefined) {
231
+ folderDelta = ns.length + 2;
232
+ }
238
233
 
239
- if (baseClass === 'data.Model') {
240
- // todo: add a question for auto-generating a matching store
241
- }
234
+ createClass({
235
+ baseClass,
236
+ className,
237
+ isSingleton,
238
+ file,
239
+ folderDelta,
240
+ ns,
241
+ root
242
+ });
243
+
244
+ if (baseClass === 'data.Model') {
245
+ // todo: add a question for auto-generating a matching store
242
246
  }
243
247
 
244
248
  const processTime = (Math.round((new Date - startDate) * 100) / 100000).toFixed(2);
@@ -440,7 +444,7 @@ if (programOpts.info) {
440
444
  root
441
445
  } = opts, baseFileName;
442
446
 
443
- fs.mkdirpSync(classFolder);
447
+ fs.mkdirpSync(classFolder, {recursive: true});
444
448
 
445
449
  baseFileName = baseClass.split('.').pop();
446
450
 
@@ -534,7 +538,7 @@ if (programOpts.info) {
534
538
  * @param {String} opts.className
535
539
  * @param {Boolean} opts.isSingleton
536
540
  * @param {String} opts.file
537
- * @param {String} opts.folderDelta
541
+ * @param {Number} opts.folderDelta
538
542
  * @param {String} opts.ns
539
543
  * @param {String} opts.root
540
544
  * @returns {String}
@@ -544,6 +548,7 @@ if (programOpts.info) {
544
548
  baseFileName = opts.baseFileName,
545
549
  baseClassPath = baseClass.split('.').join('/'),
546
550
  className = opts.className,
551
+ importSrc = root === 'Neo' ? '' : 'src/',
547
552
  isSingleton = opts.isSingleton,
548
553
  file = opts.file,
549
554
  i = 0,
@@ -554,7 +559,7 @@ if (programOpts.info) {
554
559
  }
555
560
 
556
561
  let classContent = [
557
- `import ${baseFileName} from '${importDelta}${(insideNeo ? '' : 'node_modules/neo.mjs/')}src/${baseClassPath}.mjs';`,
562
+ `import ${baseFileName} from '${importDelta}${(insideNeo ? '' : 'node_modules/neo.mjs/')}${importSrc + baseClassPath}.mjs';`,
558
563
  "",
559
564
  "/**",
560
565
  ` * @class ${className}`,
@@ -0,0 +1,63 @@
1
+ import ConfigurationViewport from '../ConfigurationViewport.mjs';
2
+ import RangeField from '../../src/form/field/Range.mjs';
3
+ import SiteMapContainer from '../../src/sitemap/Container.mjs';
4
+
5
+ /**
6
+ * @class Neo.examples.sitemap.MainContainer
7
+ * @extends Neo.examples.ConfigurationViewport
8
+ */
9
+ class MainContainer extends ConfigurationViewport {
10
+ static getConfig() {return {
11
+ className: 'Neo.examples.sitemap.MainContainer',
12
+ autoMount: true,
13
+ layout : {ntype: 'hbox', align: 'stretch'}
14
+ }}
15
+
16
+ createConfigurationComponents() {
17
+ let me = this;
18
+
19
+ return [{
20
+ module : RangeField,
21
+ labelText : 'height',
22
+ listeners : {change: me.onConfigChange.bind(me, 'height')},
23
+ maxValue : 800,
24
+ minValue : 200,
25
+ stepSize : 1,
26
+ value : me.exampleComponent.height
27
+ }, {
28
+ module : RangeField,
29
+ labelText : 'width',
30
+ listeners : {change: me.onConfigChange.bind(me, 'width')},
31
+ maxValue : 800,
32
+ minValue : 200,
33
+ stepSize : 1,
34
+ value : me.exampleComponent.width
35
+ }]
36
+ }
37
+
38
+ createExampleComponent() {
39
+ return Neo.create(SiteMapContainer, {
40
+ height: 600,
41
+ width : 800,
42
+
43
+ itemStore: {
44
+ data: [
45
+ {id: 1, column: 0, name: 'Group 1', level: 0},
46
+ {id: 2, column: 0, name: 'Item 1', level: 1, action: 'item1'},
47
+ {id: 3, column: 0, name: 'Item 2', level: 1, action: 'item2'},
48
+ {id: 4, column: 0, name: 'Item 3', level: 2, action: 'https://github.com/neomjs/neo', actionType: 'url'},
49
+ {id: 5, column: 0, name: 'Item 4', level: 2, disabled: true},
50
+ {id: 6, column: 1, name: 'Group 2', level: 0},
51
+ {id: 7, column: 1, name: 'Item 1', level: 1},
52
+ {id: 8, column: 1, name: 'Item 2', level: 1, hidden: true},
53
+ {id: 9, column: 1, name: 'Item 3', level: 1},
54
+ {id: 10, column: 1, name: 'Item 4', level: 2}
55
+ ]
56
+ }
57
+ })
58
+ }
59
+ }
60
+
61
+ Neo.applyClassConfig(MainContainer);
62
+
63
+ export default MainContainer;
@@ -0,0 +1,6 @@
1
+ import MainContainer from './MainContainer.mjs';
2
+
3
+ export const onStart = () => Neo.app({
4
+ mainView: MainContainer,
5
+ name : 'Neo.examples.sitemap'
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 Sitemap</title>
7
+ </head>
8
+ <body>
9
+ <script src="../../src/MicroLoader.mjs" type="module"></script>
10
+ </body>
11
+ </html>
@@ -0,0 +1,6 @@
1
+ {
2
+ "appPath" : "examples/sitemap/app.mjs",
3
+ "basePath" : "../../",
4
+ "environment": "development",
5
+ "mainPath" : "./Main.mjs"
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "4.0.86",
3
+ "version": "4.0.89",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -50,11 +50,11 @@
50
50
  "envinfo": "^7.8.1",
51
51
  "fs-extra": "^10.1.0",
52
52
  "highlightjs-line-numbers.js": "^2.8.0",
53
- "inquirer": "^9.0.2",
53
+ "inquirer": "^9.1.0",
54
54
  "neo-jsdoc": "^1.0.1",
55
55
  "neo-jsdoc-x": "^1.0.4",
56
56
  "postcss": "^8.4.14",
57
- "sass": "^1.54.0",
57
+ "sass": "^1.54.3",
58
58
  "webpack": "^5.74.0",
59
59
  "webpack-cli": "^4.10.0",
60
60
  "webpack-dev-server": "4.9.3",
@@ -27,6 +27,10 @@ html, .neo-body-viewport {
27
27
  pointer-events: none;
28
28
  }
29
29
 
30
+ .neo-hidden {
31
+ visibility: hidden;
32
+ }
33
+
30
34
  .neo-link-color {
31
35
  color: v(neo-color);
32
36
 
@@ -0,0 +1,41 @@
1
+ .neo-sitemap {
2
+ border : 1px solid v(panel-border-color);
3
+ padding: 30px 100px 60px;
4
+
5
+ .neo-action {
6
+ color : inherit;
7
+ display : block;
8
+ margin : 1.1em 0;
9
+ text-decoration: none;
10
+ }
11
+
12
+ .neo-action[href] {
13
+ &:hover {
14
+ text-decoration: underline;
15
+ }
16
+ }
17
+
18
+ .neo-level-0 {
19
+ font-size : 16px/22px;
20
+ font-weight: 600;
21
+ }
22
+
23
+ .neo-level-1 {
24
+ margin-left: 1em;
25
+ }
26
+
27
+ .neo-level-2 {
28
+ margin-left: 2em;
29
+ }
30
+
31
+ .neo-level-3 {
32
+ margin-left: 3em;
33
+ }
34
+
35
+ .neo-sitemap-column {
36
+ &:not(:last-child) {
37
+ border-right: 1px solid v(panel-border-color);
38
+ margin-right: 25px;
39
+ }
40
+ }
41
+ }
@@ -414,7 +414,7 @@ class Base extends CoreBase {
414
414
  }, 50);
415
415
  });
416
416
  } else if (me.mounted) {
417
- me.updateVdom(vdom, me.vnode);
417
+ me.vnode && me.updateVdom(vdom, me.vnode);
418
418
  }
419
419
 
420
420
  me.hasUnmountedVdomChanges = !me.mounted && me.hasBeenMounted;
@@ -76,8 +76,15 @@ class RecordFactory extends Base {
76
76
 
77
77
  if (Array.isArray(model.fields)) {
78
78
  model.fields.forEach(field => {
79
- let parsedValue = instance.parseRecordValue(me, field, config[field.name], config),
80
- symbol = Symbol.for(field.name);
79
+ let value = config[field.name],
80
+ symbol = Symbol.for(field.name),
81
+ parsedValue;
82
+
83
+ if (!Object.hasOwn(config, field.name) && Object.hasOwn(field, 'defaultValue')) {
84
+ value = field.defaultValue;
85
+ }
86
+
87
+ parsedValue = instance.parseRecordValue(me, field, value, config);
81
88
 
82
89
  properties = {
83
90
  [Symbol.for('isRecord')]: {
@@ -271,6 +278,10 @@ class RecordFactory extends Base {
271
278
  return new Date(value);
272
279
  }
273
280
 
281
+ if (type === 'html' && value) {
282
+ value = value + '';
283
+ }
284
+
274
285
  if (type === 'string' && value) {
275
286
  value = value + '';
276
287
  value = value.replace(/(<([^>]+)>)/ig, '');
@@ -0,0 +1,210 @@
1
+ import Base from '../container/Base.mjs';
2
+ import ClassSystemUtil from '../util/ClassSystem.mjs';
3
+ import ItemStore from './store/Items.mjs';
4
+
5
+ /**
6
+ * @class Neo.sitemap.Container
7
+ * @extends Neo.container.Base
8
+ */
9
+ class Container extends Base {
10
+ static getStaticConfig() {return {
11
+ /**
12
+ * Valid values for itemHideMode
13
+ * @member {String[]} itemHideModes=['removeDom','visibility']
14
+ * @protected
15
+ * @static
16
+ */
17
+ itemHideModes: ['removeDom', 'visibility']
18
+ }}
19
+
20
+ static getConfig() {return {
21
+ /*
22
+ * @member {String} className='Neo.sitemap.Container'
23
+ * @protected
24
+ */
25
+ className: 'Neo.sitemap.Container',
26
+ /*
27
+ * @member {String} ntype='sitemap'
28
+ * @protected
29
+ */
30
+ ntype: 'sitemap',
31
+ /*
32
+ * @member {String[} cls=['neo-sitemap','neo-container']
33
+ */
34
+ cls: ['neo-sitemap', 'neo-container'],
35
+ /*
36
+ * @member {Object} itemDefaults
37
+ */
38
+ itemDefaults: {
39
+ ntype: 'component',
40
+ cls : ['neo-sitemap-column', 'neo-container']
41
+ },
42
+ /**
43
+ * Valid values: removeDom, visibility
44
+ * Defines if the component items should use css visibility:'hidden' or vdom:removeDom
45
+ * @member {String} hideMode_='removeDom'
46
+ */
47
+ itemHideMode_: 'removeDom',
48
+ /*
49
+ * @member {Neo.sitemap.store.Items|null} itemStore_=null
50
+ */
51
+ itemStore_: null,
52
+ /**
53
+ * @member {Object} layout={ntype:'hbox',align:'stretch'}
54
+ */
55
+ layout: {ntype: 'hbox', align: 'stretch'}
56
+ }}
57
+
58
+ /**
59
+ * @param {Object} config
60
+ */
61
+ construct(config) {
62
+ super.construct(config);
63
+
64
+ let me = this,
65
+ domListeners = me.domListeners;
66
+
67
+ domListeners.push({click: me.onItemClick, delegate: '.neo-action', scope: me});
68
+
69
+ me.domListeners = domListeners;
70
+ }
71
+
72
+ /**
73
+ * Triggered after the itemStore config got changed
74
+ * @param {Neo.sitemap.store.Items|null} value
75
+ * @param {Neo.sitemap.store.Items|null} oldValue
76
+ * @protected
77
+ */
78
+ afterSetItemStore(value, oldValue) {
79
+ let me = this;
80
+
81
+ value?.on({
82
+ filter : 'onItemStoreFilter',
83
+ load : 'onItemStoreLoad',
84
+ recordChange: 'onItemStoreRecordChange',
85
+ scope : me
86
+ });
87
+
88
+ value?.getCount() > 0 && me.createColumns();
89
+ }
90
+
91
+ /**
92
+ * Triggered before the itemHideMode config gets changed
93
+ * @param {String} value
94
+ * @param {String} oldValue
95
+ * @protected
96
+ */
97
+ beforeSetItemHideMode(value, oldValue) {
98
+ return this.beforeSetEnumValue(value, oldValue, 'itemHideMode');
99
+ }
100
+
101
+ /**
102
+ * Triggered before the itemStore config gets changed.
103
+ * @param {Object|Neo.data.Store} value
104
+ * @param {Object|Neo.data.Store} oldValue
105
+ * @returns {Neo.data.Store}
106
+ * @protected
107
+ */
108
+ beforeSetItemStore(value, oldValue) {
109
+ oldValue?.destroy();
110
+ return ClassSystemUtil.beforeSetInstance(value, ItemStore);
111
+ }
112
+
113
+ /**
114
+ *
115
+ */
116
+ createColumns() {
117
+ let me = this,
118
+ records = me.itemStore.items,
119
+ columnIndex = -1,
120
+ items = [],
121
+ action, column, item, record;
122
+
123
+ for (record of records) {
124
+ if (record.column !== columnIndex) {
125
+ columnIndex++;
126
+ column = {vdom: {cn: []}};
127
+ items.push(column);
128
+ }
129
+
130
+ action = record.action;
131
+
132
+ item = {
133
+ tag : 'a',
134
+ cls : ['neo-action', `neo-level-${record.level}`],
135
+ id : me.getItemId(record.id),
136
+ html: record.name
137
+ };
138
+
139
+ if (action && action !== '') {
140
+ switch (record.actionType) {
141
+ case 'handler': {
142
+ item.cls.push('neo-action-handler');
143
+ break;
144
+ }
145
+ case 'route': {
146
+ item.href = `#${record.action}`;
147
+ break;
148
+ }
149
+ case 'url': {
150
+ item.href = record.action;
151
+ item.target = '_blank';
152
+ }
153
+ }
154
+ }
155
+
156
+ record.disabled && item.cls.push('neo-disabled');
157
+
158
+ if (record.hidden) {
159
+ if (me.itemHideMode === 'removeDom') {
160
+ item.removeDom = true;
161
+ } else {
162
+ item.cls.push('neo-hidden');
163
+ }
164
+ }
165
+
166
+ column.vdom.cn.push(item);
167
+ }
168
+
169
+ me.items = items;
170
+ }
171
+
172
+ /**
173
+ * @param {Number|String} recordId
174
+ * @returns {String}
175
+ */
176
+ getItemId(recordId) {
177
+ return `${this.id}__${recordId}`;
178
+ }
179
+
180
+ /**
181
+ * Override as needed
182
+ * @param {Object} data
183
+ */
184
+ onItemClick(data) {}
185
+
186
+ /**
187
+ *
188
+ */
189
+ onItemStoreFilter() {
190
+ this.createColumns();
191
+ }
192
+
193
+ /**
194
+ *
195
+ */
196
+ onItemStoreLoad() {
197
+ this.createColumns();
198
+ }
199
+
200
+ /**
201
+ *
202
+ */
203
+ onItemStoreRecordChange() {
204
+ this.createColumns();
205
+ }
206
+ }
207
+
208
+ Neo.applyClassConfig(Container);
209
+
210
+ export default Container;
@@ -0,0 +1,51 @@
1
+ import Model from '../../data/Model.mjs';
2
+
3
+ /**
4
+ * @class Neo.sitemap.model.Item
5
+ * @extends Neo.data.Model
6
+ */
7
+ class Item extends Model {
8
+ static getConfig() {return {
9
+ /*
10
+ * @member {String} className='Neo.sitemap.model.Item'
11
+ * @protected
12
+ */
13
+ className: 'Neo.sitemap.model.Item',
14
+ /*
15
+ * @member {Object[]} fields
16
+ */
17
+ fields: [{
18
+ name: 'action',
19
+ type: 'String'
20
+ }, {
21
+ name : 'actionType',
22
+ defaultValue: 'route',
23
+ type : 'String'
24
+ }, {
25
+ name: 'column',
26
+ type: 'Number' // zero based
27
+ }, {
28
+ name : 'disabled',
29
+ defaultValue: false,
30
+ type : 'Boolean'
31
+ }, {
32
+ name : 'hidden',
33
+ defaultValue: false,
34
+ type : 'Boolean'
35
+ }, {
36
+ name: 'id',
37
+ type: 'Number'
38
+ }, {
39
+ name : 'level', // indentation
40
+ defaultValue: 0,
41
+ type : 'Number'
42
+ }, {
43
+ name: 'name',
44
+ type: 'Html'
45
+ }]
46
+ }}
47
+ }
48
+
49
+ Neo.applyClassConfig(Item);
50
+
51
+ export default Item;
@@ -0,0 +1,24 @@
1
+ import ItemModel from '../model/Item.mjs';
2
+ import Store from '../../data/Store.mjs';
3
+
4
+ /**
5
+ * @class Neo.sitemap.store.Items
6
+ * @extends Neo.data.Store
7
+ */
8
+ class Items extends Store {
9
+ static getConfig() {return {
10
+ /*
11
+ * @member {String} className='Neo.sitemap.store.Items'
12
+ * @protected
13
+ */
14
+ className: 'Neo.sitemap.store.Items',
15
+ /*
16
+ * @member {Neo.data.Model} model=ItemModel
17
+ */
18
+ model: ItemModel
19
+ }}
20
+ }
21
+
22
+ Neo.applyClassConfig(Items);
23
+
24
+ export default Items;