neo.mjs 4.0.87 → 4.0.90

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.87",
3
+ "version": "4.0.90",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -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,3 @@
1
+ .neo-iframe {
2
+ border: none;
3
+ }
@@ -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
+ }
@@ -163,9 +163,9 @@ class Base extends CoreBase {
163
163
  /**
164
164
  * Used for hide and show and defines if the component
165
165
  * should use css visibility:'hidden' or vdom:removeDom
166
- * @member {String} hideMode_='visibility'
166
+ * @member {String} hideMode_='removeDom'
167
167
  */
168
- hideMode_: 'visibility',
168
+ hideMode_: 'removeDom',
169
169
  /**
170
170
  * The top level innerHTML of the component
171
171
  * @member {String|null} html_=null
@@ -1121,10 +1121,9 @@ class Base extends CoreBase {
1121
1121
  * @param {Number} timeout
1122
1122
  */
1123
1123
  hide(timeout) {
1124
- let me = this,
1125
- doRemove = me.hideMode !== 'visibility';
1124
+ let me = this;
1126
1125
 
1127
- if (doRemove) {
1126
+ if (me.hideMode !== 'visibility') {
1128
1127
  let removeFn = function() {
1129
1128
  let vdom = me.vdom;
1130
1129
  vdom.removeDom = true;
@@ -1142,7 +1141,7 @@ class Base extends CoreBase {
1142
1141
  me.style = style;
1143
1142
  }
1144
1143
 
1145
- this._hidden = true;
1144
+ me._hidden = true;
1146
1145
  }
1147
1146
 
1148
1147
  /**
@@ -1505,10 +1504,9 @@ class Base extends CoreBase {
1505
1504
  * hideMode: 'visibility' uses css visibility.
1506
1505
  */
1507
1506
  show() {
1508
- let me = this,
1509
- doAdd = me.hideMode !== 'visibility';
1507
+ let me = this;
1510
1508
 
1511
- if (doAdd) {
1509
+ if (me.hideMode !== 'visibility') {
1512
1510
  let vdom = me.vdom;
1513
1511
  vdom.removeDom = false;
1514
1512
  me.vdom = vdom;
@@ -1518,7 +1516,7 @@ class Base extends CoreBase {
1518
1516
  me.style = style;
1519
1517
  }
1520
1518
 
1521
- this._hidden = false;
1519
+ me._hidden = false;
1522
1520
  }
1523
1521
 
1524
1522
  /**
@@ -0,0 +1,42 @@
1
+ import Base from '../component/Base.mjs';
2
+
3
+ /**
4
+ * @class Neo.component.Iframe
5
+ * @extends Neo.component.Base
6
+ */
7
+ class Iframe extends Base {
8
+ static getConfig() {return {
9
+ /*
10
+ * @member {String} className='Neo.component.Iframe'
11
+ * @protected
12
+ */
13
+ className: 'Neo.component.Iframe',
14
+ /*
15
+ * @member {String[]} cls=['neo-iframe']
16
+ */
17
+ cls: ['neo-iframe'],
18
+ /*
19
+ * @member {String|null} src_=null
20
+ */
21
+ src_: null,
22
+ /*
23
+ * @member {Object} _vdom
24
+ */
25
+ _vdom:
26
+ {tag: 'iframe'}
27
+ }}
28
+
29
+ /**
30
+ * Triggered after the src config got changed
31
+ * @param {String|null} value
32
+ * @param {String|null} oldValue
33
+ * @protected
34
+ */
35
+ afterSetSrc(value, oldValue) {
36
+ this.changeVdomRootKey('src', value);
37
+ }
38
+ }
39
+
40
+ Neo.applyClassConfig(Iframe);
41
+
42
+ export default Iframe;
@@ -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, '');
package/src/list/Base.mjs CHANGED
@@ -405,9 +405,10 @@ class Base extends Component {
405
405
  getItemRecordId(vnodeId) {
406
406
  let itemId = vnodeId.split('__')[1],
407
407
  model = this.store.model,
408
- keyField = model?.getField(model.keyProperty);
408
+ keyField = model?.getField(model.keyProperty),
409
+ keyType = keyField?.type.toLowerCase();
409
410
 
410
- if (keyField?.type.toLowerCase() === 'integer' || keyField?.type.toLowerCase() === 'number') {
411
+ if (keyType === 'integer' || keyType === 'number') {
411
412
  itemId = parseInt(itemId);
412
413
  }
413
414
 
@@ -0,0 +1,227 @@
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
+ * @param {String} vnodeId
182
+ * @returns {String|Number} itemId
183
+ */
184
+ getItemRecordId(vnodeId) {
185
+ let itemId = vnodeId.split('__')[1],
186
+ model = this.store.model,
187
+ keyField = model?.getField(model.keyProperty),
188
+ keyType = keyField?.type.toLowerCase();
189
+
190
+ if (keyType === 'integer' || keyType === 'number') {
191
+ itemId = parseInt(itemId);
192
+ }
193
+
194
+ return itemId;
195
+ }
196
+
197
+ /**
198
+ * Override as needed
199
+ * @param {Object} data
200
+ */
201
+ onItemClick(data) {}
202
+
203
+ /**
204
+ *
205
+ */
206
+ onItemStoreFilter() {
207
+ this.createColumns();
208
+ }
209
+
210
+ /**
211
+ *
212
+ */
213
+ onItemStoreLoad() {
214
+ this.createColumns();
215
+ }
216
+
217
+ /**
218
+ *
219
+ */
220
+ onItemStoreRecordChange() {
221
+ this.createColumns();
222
+ }
223
+ }
224
+
225
+ Neo.applyClassConfig(Container);
226
+
227
+ 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;