neo.mjs 6.18.3 → 6.19.1

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.
Files changed (94) hide show
  1. package/README.md +28 -214
  2. package/apps/ServiceWorker.mjs +2 -2
  3. package/apps/colors/view/ViewportController.mjs +7 -3
  4. package/apps/portal/data/blog.json +13 -0
  5. package/apps/portal/view/HeaderToolbar.mjs +2 -2
  6. package/apps/portal/view/Viewport.mjs +4 -2
  7. package/apps/portal/view/ViewportController.mjs +88 -7
  8. package/apps/portal/view/blog/Container.mjs +8 -8
  9. package/apps/portal/view/blog/List.mjs +6 -6
  10. package/apps/portal/view/home/FooterContainer.mjs +123 -0
  11. package/apps/portal/view/home/MainContainer.mjs +3 -2
  12. package/apps/portal/view/home/parts/AfterMath.mjs +17 -24
  13. package/apps/portal/view/home/parts/Colors.mjs +2 -2
  14. package/apps/portal/view/home/parts/How.mjs +3 -3
  15. package/apps/portal/view/home/parts/MainNeo.mjs +6 -7
  16. package/apps/portal/view/home/parts/References.mjs +88 -0
  17. package/apps/portal/view/learn/MainContainer.mjs +3 -2
  18. package/apps/portal/view/learn/MainContainerController.mjs +11 -0
  19. package/apps/portal/view/learn/PageContainer.mjs +5 -3
  20. package/apps/portal/view/services/Component.mjs +73 -0
  21. package/apps/website/data/blog.json +13 -0
  22. package/examples/ServiceWorker.mjs +2 -2
  23. package/examples/component/carousel/MainContainer.mjs +42 -33
  24. package/examples/layout/cube/MainContainer.mjs +217 -0
  25. package/examples/layout/cube/app.mjs +6 -0
  26. package/examples/layout/cube/index.html +11 -0
  27. package/examples/layout/cube/neo-config.json +6 -0
  28. package/examples/model/twoWay/MainContainer.mjs +76 -0
  29. package/examples/model/twoWay/app.mjs +6 -0
  30. package/examples/model/twoWay/index.html +11 -0
  31. package/examples/model/twoWay/neo-config.json +6 -0
  32. package/package.json +7 -7
  33. package/resources/data/deck/learnneo/pages/Earthquakes-01-goals.md +32 -0
  34. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-01-generate-a-workspace.md +47 -0
  35. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-02-generate-the-starter-app.md +150 -0
  36. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-03-debugging.md +136 -0
  37. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-04-fetch-data.md +146 -0
  38. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-05-refactor-the-table.md +146 -0
  39. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-06-use-a-view-model.md +301 -0
  40. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-07-use-the-google-maps-addon.md +175 -0
  41. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-08-events.md +38 -0
  42. package/resources/data/deck/learnneo/pages/Earthquakes.md +8 -8
  43. package/resources/data/deck/learnneo/pages/Glossary.md +0 -0
  44. package/resources/data/deck/learnneo/pages/GuideEvents.md +80 -1
  45. package/resources/data/deck/learnneo/tree.json +2 -1
  46. package/resources/images/apps/portal/neo-references.png +0 -0
  47. package/resources/scss/src/apps/portal/Viewport.scss +18 -0
  48. package/resources/scss/src/apps/portal/blog/Container.scss +7 -7
  49. package/resources/scss/src/apps/portal/blog/List.scss +20 -16
  50. package/resources/scss/src/apps/portal/home/FooterContainer.scss +31 -0
  51. package/resources/scss/src/apps/portal/home/parts/AfterMath.scss +5 -0
  52. package/resources/scss/src/apps/portal/home/parts/MainNeo.scss +4 -5
  53. package/resources/scss/src/apps/portal/home/parts/References.scss +46 -0
  54. package/resources/scss/src/apps/portal/learn/ContentTreeList.scss +20 -0
  55. package/resources/scss/src/apps/portal/learn/ContentView.scss +4 -0
  56. package/resources/scss/src/apps/portal/learn/MainContainer.scss +1 -1
  57. package/resources/scss/src/apps/portal/learn/PageContainer.scss +22 -16
  58. package/resources/scss/src/apps/portal/services/Component.scss +20 -0
  59. package/resources/scss/src/component/Carousel.scss +21 -0
  60. package/resources/scss/src/examples/layout/cube/MainContainer.scss +7 -0
  61. package/resources/scss/src/layout/Cube.scss +80 -0
  62. package/resources/scss/src/tab/Container.scss +10 -10
  63. package/resources/scss/theme-neo-light/apps/portal/blog/Container.scss +3 -0
  64. package/resources/scss/theme-neo-light/form/field/Search.scss +1 -1
  65. package/resources/scss/theme-neo-light/tooltip/Base.scss +1 -1
  66. package/src/DefaultConfig.mjs +2 -2
  67. package/src/Main.mjs +15 -1
  68. package/src/Neo.mjs +14 -3
  69. package/src/calendar/view/MainContainer.mjs +8 -7
  70. package/src/component/Base.mjs +28 -8
  71. package/src/component/DateSelector.mjs +2 -2
  72. package/src/container/Base.mjs +3 -1
  73. package/src/dialog/Base.mjs +1 -2
  74. package/src/form/field/Time.mjs +18 -16
  75. package/src/layout/Base.mjs +43 -6
  76. package/src/layout/Card.mjs +21 -59
  77. package/src/layout/Cube.mjs +432 -0
  78. package/src/layout/Fit.mjs +9 -38
  79. package/src/layout/Flexbox.mjs +16 -17
  80. package/src/layout/Form.mjs +13 -70
  81. package/src/layout/Grid.mjs +6 -18
  82. package/src/list/Base.mjs +3 -3
  83. package/src/main/mixin/DeltaUpdates.mjs +16 -3
  84. package/src/model/Component.mjs +25 -6
  85. package/src/util/Array.mjs +36 -0
  86. package/src/vdom/Helper.mjs +338 -442
  87. package/src/vdom/VNode.mjs +12 -1
  88. package/test/siesta/siesta.js +16 -1
  89. package/test/siesta/tests/VdomCalendar.mjs +2193 -37
  90. package/test/siesta/tests/VdomHelper.mjs +287 -48
  91. package/test/siesta/tests/vdom/Advanced.mjs +368 -0
  92. package/test/siesta/tests/vdom/layout/Cube.mjs +189 -0
  93. package/test/siesta/tests/vdom/table/Container.mjs +133 -0
  94. package/resources/scss/theme-neo-light/apps/portal/learn/ContentTreeList.scss +0 -23
@@ -13,10 +13,11 @@ import VDomUtil from '../util/VDom.mjs';
13
13
  import VNodeUtil from '../util/VNode.mjs';
14
14
 
15
15
  const
16
- addUnits = value => value == null ? value : isNaN(value) ? value : `${value}px`,
17
- closestController = Symbol.for('closestController'),
18
- closestModel = Symbol.for('closestModel'),
19
- lengthRE = /^\d+\w+$/;
16
+ addUnits = value => value == null ? value : isNaN(value) ? value : `${value}px`,
17
+ closestController = Symbol.for('closestController'),
18
+ closestModel = Symbol.for('closestModel'),
19
+ lengthRE = /^\d+\w+$/,
20
+ twoWayBindingSymbol = Symbol.for('twoWayBinding');
20
21
 
21
22
  /**
22
23
  * @class Neo.component.Base
@@ -333,6 +334,13 @@ class Base extends CoreBase {
333
334
  * @member {String|null} theme_=null
334
335
  */
335
336
  theme_: null,
337
+ /**
338
+ * While it is recommended to define tags inside the vdom of classes,
339
+ * this shortcut enables us to change the vdom root tag on instance level.
340
+ * Use cases: switch a Toolbar to a "nav" tag, switch a SideNav to an "aside" tag.
341
+ * @member {String|null} tag_=null
342
+ */
343
+ tag_: null,
336
344
  /**
337
345
  * Add tooltip config object or a string containing the display text
338
346
  * See tooltip/Base.mjs
@@ -548,11 +556,13 @@ class Base extends CoreBase {
548
556
  * @protected
549
557
  */
550
558
  afterSetConfig(key, value, oldValue) {
551
- if (Neo.currentWorker.isUsingViewModels && oldValue !== undefined) {
552
- let binding = this.bind?.[key];
559
+ let me = this;
560
+
561
+ if (Neo.currentWorker.isUsingViewModels && me[twoWayBindingSymbol] && oldValue !== undefined) {
562
+ let binding = me.bind?.[key];
553
563
 
554
564
  if (binding?.twoWay) {
555
- this.getModel()?.setData(key, value)
565
+ this.getModel()?.setData(binding.key, value)
556
566
  }
557
567
  }
558
568
  }
@@ -920,6 +930,16 @@ class Base extends CoreBase {
920
930
  }
921
931
  }
922
932
 
933
+ /**
934
+ * Triggered after the tag config got changed
935
+ * @param {String|null} value
936
+ * @param {String|null} oldValue
937
+ * @protected
938
+ */
939
+ afterSetTag(value, oldValue) {
940
+ value && this.changeVdomRootKey('tag', value)
941
+ }
942
+
923
943
  /**
924
944
  * Triggered after the theme config got changed
925
945
  * @param {String|null} value
@@ -1459,7 +1479,7 @@ class Base extends CoreBase {
1459
1479
  // we can not set the config directly => it could already be false,
1460
1480
  // and we still want to pass it further into subtrees
1461
1481
  me._needsVdomUpdate = false;
1462
- me.afterSetNeedsVdomUpdate?.(false, true)
1482
+ me.afterSetNeedsVdomUpdate?.(false, true);
1463
1483
 
1464
1484
  Neo.vdom.Helper.update(opts).catch(err => {
1465
1485
  me.isVdomUpdating = false;
@@ -759,7 +759,7 @@ class DateSelector extends Component {
759
759
  */
760
760
  onComponentWheel(data) {
761
761
  let me = this,
762
- {deltaX, deltaY} = me,
762
+ {deltaX, deltaY} = data,
763
763
  wheelDelta = me.mouseWheelDelta,
764
764
  date, monthIncrement, yearIncrement;
765
765
 
@@ -830,7 +830,7 @@ class DateSelector extends Component {
830
830
  // using force => we do want to keep the same ids
831
831
  syncIds && me.syncVdomIds(me.vnode, me.vdom, true);
832
832
 
833
- me.triggerVdomUpdate(silent)
833
+ !silent && me.update()
834
834
  }
835
835
 
836
836
  /**
@@ -149,7 +149,9 @@ class Base extends Component {
149
149
  me.items.forEach((item, index) => {
150
150
  oldValue?.removeChildAttributes(item, index);
151
151
  value.applyChildAttributes(item, index)
152
- })
152
+ });
153
+
154
+ oldValue?.destroy()
153
155
  }
154
156
  }
155
157
 
@@ -363,12 +363,11 @@ class Base extends Panel {
363
363
  await me.render(true);
364
364
 
365
365
  let [dialogRect, bodyRect] = await me.getDomRect([me.id, 'document.body']);
366
- console.log(dialogRect, bodyRect);
367
366
 
368
367
  // Move to cover the animation target
369
368
  await Neo.applyDeltas(appName, {
370
369
  id,
371
- style : {
370
+ style: {
372
371
  height: `${rect.height}px`,
373
372
  left : `${rect.left }px`,
374
373
  top : `${rect.top }px`,
@@ -92,9 +92,7 @@ class Time extends Picker {
92
92
 
93
93
  me.originalConfig.value = me.formatTime(me.value);
94
94
 
95
- if (clearTrigger) {
96
- clearTrigger.onFieldChange();
97
- }
95
+ clearTrigger?.onFieldChange();
98
96
 
99
97
  me.collection = Neo.create({
100
98
  module : Collection,
@@ -115,9 +113,8 @@ class Time extends Picker {
115
113
  );
116
114
 
117
115
  me.list.on({
118
- itemClick : me.onListItemClick,
119
- itemNavigate: me.onListItemNavigate,
120
- scope : me
116
+ itemClick: me.onListItemClick,
117
+ scope : me
121
118
  })
122
119
  }
123
120
 
@@ -273,7 +270,8 @@ class Time extends Picker {
273
270
 
274
271
  while (currentDate <= endDate) {
275
272
  listItems.push({
276
- value: dt.format(currentDate)
273
+ isRecord: true,
274
+ value : dt.format(currentDate)
277
275
  });
278
276
 
279
277
  currentDate.setSeconds(currentDate.getSeconds() + me.stepSize)
@@ -350,10 +348,12 @@ class Time extends Picker {
350
348
  }
351
349
 
352
350
  /**
353
- * @param {Object} record
351
+ * @param {Object} data
352
+ * @param {Object} data.record
354
353
  */
355
- onListItemClick(record) {
354
+ onListItemClick(data) {
356
355
  let me = this,
356
+ {record} = data,
357
357
  oldValue = me.value,
358
358
  {value} = record;
359
359
 
@@ -365,13 +365,6 @@ class Time extends Picker {
365
365
  }
366
366
  }
367
367
 
368
- /**
369
- * @param {Object} record
370
- */
371
- onListItemNavigate(record) {
372
- this.onListItemClick(record)
373
- }
374
-
375
368
  /**
376
369
  *
377
370
  */
@@ -409,6 +402,15 @@ class Time extends Picker {
409
402
  list.selectionModel.select(id);
410
403
 
411
404
  if (!preventFocus) {
405
+
406
+ if (list.mounted) {
407
+ list.focus(id)
408
+ } else {
409
+ list.on('mounted', () => {
410
+ list.focus(id)
411
+ }, me, {once: true})
412
+ }
413
+
412
414
  list.focus(id)
413
415
  } else {
414
416
  Neo.main.DomAccess.scrollIntoView({
@@ -1,4 +1,5 @@
1
1
  import CoreBase from '../core/Base.mjs';
2
+ import NeoArray from '../util/Array.mjs';
2
3
 
3
4
  /**
4
5
  * The base class for all other layouts.
@@ -29,6 +30,12 @@ class Base extends CoreBase {
29
30
  * @protected
30
31
  */
31
32
  containerId: null,
33
+ /**
34
+ * A layout specific CSS selector which gets added to Container the layout is bound to.
35
+ * @member {String|null} containerCls_=null
36
+ * @protected
37
+ */
38
+ containerCls_: null,
32
39
  /**
33
40
  * Identifier for all classes that extend layout.Base
34
41
  * @member {Boolean} isLayout=true
@@ -45,7 +52,10 @@ class Base extends CoreBase {
45
52
  * @returns {Neo.container.Base|null}
46
53
  */
47
54
  get container() {
48
- return Neo.getComponent(this.containerId)
55
+ let {containerId} = this;
56
+
57
+ // the instance might not be registered yet
58
+ return Neo.getComponent(containerId) || Neo.get(containerId)
49
59
  }
50
60
 
51
61
  /**
@@ -67,10 +77,23 @@ class Base extends CoreBase {
67
77
  applyChildAttributes(item, index) {}
68
78
 
69
79
  /**
70
- * Placeholder method
71
80
  * @protected
72
81
  */
73
- applyRenderAttributes() {}
82
+ applyRenderAttributes() {
83
+ let me = this,
84
+ {container, containerCls} = me,
85
+ {wrapperCls} = container;
86
+
87
+ if (containerCls) {
88
+ if (!container) {
89
+ Neo.logError(me.className + ': applyRenderAttributes -> container not yet created', me.containerId)
90
+ }
91
+
92
+ NeoArray.add(wrapperCls, containerCls);
93
+
94
+ container.wrapperCls = wrapperCls
95
+ }
96
+ }
74
97
 
75
98
  /**
76
99
  *
@@ -108,15 +131,29 @@ class Base extends CoreBase {
108
131
  /**
109
132
  * Placeholder method
110
133
  * @param {Neo.component.Base} item
134
+ * @param {Number} index
111
135
  * @protected
112
136
  */
113
- removeChildAttributes(item) {}
137
+ removeChildAttributes(item, index) {}
114
138
 
115
139
  /**
116
- * Placeholder method
117
140
  * @protected
118
141
  */
119
- removeRenderAttributes() {}
142
+ removeRenderAttributes() {
143
+ let me = this,
144
+ {container, containerCls} = me,
145
+ {wrapperCls} = container;
146
+
147
+ if (containerCls) {
148
+ if (!container) {
149
+ Neo.logError(me.className + ': removeRenderAttributes -> container not yet created', me.containerId)
150
+ }
151
+
152
+ NeoArray.remove(wrapperCls, containerCls);
153
+
154
+ container.wrapperCls = wrapperCls
155
+ }
156
+ }
120
157
  }
121
158
 
122
159
  Neo.setupClass(Base);
@@ -49,6 +49,11 @@ class Card extends Base {
49
49
  * @member {Number} activeIndex_=0
50
50
  */
51
51
  activeIndex_: 0,
52
+ /**
53
+ * @member {String|null} containerCls='neo-layout-card'
54
+ * @protected
55
+ */
56
+ containerCls: 'neo-layout-card',
52
57
  /*
53
58
  * Remove the DOM of inactive cards.
54
59
  * This will keep the instances & vdom trees
@@ -72,8 +77,7 @@ class Card extends Base {
72
77
  */
73
78
  async afterSetActiveIndex(value, oldValue) {
74
79
  let me = this,
75
- {containerId, removeInactiveCards} = me,
76
- container = Neo.getComponent(containerId) || Neo.get(containerId), // the instance might not be registered yet
80
+ {container, removeInactiveCards} = me,
77
81
  sCfg = me.constructor,
78
82
  needsTransition = me.slideDirection && oldValue !== undefined,
79
83
  needsUpdate = false,
@@ -144,7 +148,7 @@ class Card extends Base {
144
148
  let me = this,
145
149
  isActiveIndex = me.activeIndex === index,
146
150
  sCfg = me.constructor,
147
- childCls = item.wrapperCls,
151
+ childCls = item.wrapperCls || [],
148
152
  {vdom} = item;
149
153
 
150
154
  NeoArray.add(childCls, sCfg.itemCls);
@@ -153,29 +157,12 @@ class Card extends Base {
153
157
  if (!keepInDom && me.removeInactiveCards) {
154
158
  vdom.removeDom = !isActiveIndex;
155
159
  item.wrapperCls = childCls;
156
- item.update()
160
+ item.update?.() // can get called for an item config
157
161
  } else {
158
162
  item.wrapperCls = childCls
159
163
  }
160
164
  }
161
165
 
162
- /**
163
- * Applies CSS classes to the container this layout is bound to
164
- */
165
- applyRenderAttributes() {
166
- let me = this,
167
- container = Neo.getComponent(me.containerId),
168
- wrapperCls = container?.wrapperCls || [];
169
-
170
- if (!container) {
171
- Neo.logError('layout.Card: applyRenderAttributes -> container not yet created', me.containerId)
172
- }
173
-
174
- NeoArray.add(wrapperCls, 'neo-layout-card');
175
-
176
- container.wrapperCls = wrapperCls
177
- }
178
-
179
166
  /**
180
167
  * Triggered before the slideDirection config gets changed
181
168
  * @param {String} value
@@ -194,14 +181,11 @@ class Card extends Base {
194
181
  * @returns {Neo.component.Base}
195
182
  */
196
183
  async loadModule(item, index) {
197
- let me = this,
198
- {containerId} = me,
199
- container = Neo.getComponent(containerId) || Neo.get(containerId), // the instance might not be registered yet
200
- items = container.items,
201
- sCfg = me.constructor,
202
- {vdom} = container,
203
- {module} = item,
204
- proto, wrapperCls;
184
+ let me = this,
185
+ {container} = me,
186
+ items = container.items,
187
+ {module} = item,
188
+ proto;
205
189
 
206
190
  if (!Neo.isNumber(index)) {
207
191
  index = items.indexOf(item)
@@ -209,49 +193,27 @@ class Card extends Base {
209
193
 
210
194
  item.isLoading = true; // prevent the item from getting queued multiple times inside form.Container
211
195
 
212
- module = await module();
213
- module = module.default;
214
- proto = module.prototype;
215
- wrapperCls = item.wrapperCls || proto.constructor.config.wrapperCls || [];
196
+ module = await module();
197
+ module = module.default;
198
+ proto = module.prototype;
199
+
200
+ item.className = proto.className;
201
+ item.module = module;
216
202
 
217
- item.className = proto.className;
218
- item.wrapperCls = [...wrapperCls, sCfg.itemCls];
219
- item.module = module;
203
+ me.applyChildAttributes(item, index);
220
204
 
221
205
  delete item.isLoading;
222
206
  delete item.vdom;
223
207
 
224
208
  items[index] = item = Neo.create(item);
225
209
 
226
- if (me.removeInactiveCards) {
227
- item.vdom.removeDom = true
228
- }
210
+ container.getVdomItemsRoot().cn[index] = item.vdom;
229
211
 
230
212
  container.fire('cardLoaded', {item});
231
213
 
232
- vdom.cn[index] = item.vdom;
233
-
234
214
  return item
235
215
  }
236
216
 
237
- /**
238
- * Removes all CSS rules from the container this layout is bound to.
239
- * Gets called when switching to a different layout.
240
- */
241
- removeRenderAttributes() {
242
- let me = this,
243
- container = Neo.getComponent(me.containerId),
244
- wrapperCls = container?.wrapperCls || [];
245
-
246
- if (!container) {
247
- Neo.logError('layout.Card: removeRenderAttributes -> container not yet created', me.containerId)
248
- }
249
-
250
- NeoArray.remove(wrapperCls, 'neo-layout-card');
251
-
252
- container.wrapperCls = wrapperCls
253
- }
254
-
255
217
  /**
256
218
  * @param {Number} index
257
219
  * @param {Number} oldIndex