neo.mjs 6.8.3 → 6.9.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 (65) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/learnneo/view/home/MainContainer.mjs +4 -3
  3. package/apps/learnneo/view/home/MainContainerController.mjs +24 -2
  4. package/apps/route/app.mjs +6 -0
  5. package/apps/route/index.html +11 -0
  6. package/apps/route/neo-config.json +6 -0
  7. package/apps/route/view/ButtonBar.mjs +57 -0
  8. package/apps/route/view/CenterContainer.mjs +37 -0
  9. package/apps/route/view/FooterContainer.mjs +47 -0
  10. package/apps/route/view/HeaderContainer.mjs +47 -0
  11. package/apps/route/view/MainView.mjs +66 -0
  12. package/apps/route/view/MainViewController.mjs +210 -0
  13. package/apps/route/view/MetaContainer.mjs +52 -0
  14. package/apps/route/view/Viewport.mjs +15 -0
  15. package/apps/route/view/center/CardAdministration.mjs +36 -0
  16. package/apps/route/view/center/CardAdministrationDenied.mjs +26 -0
  17. package/apps/route/view/center/CardContact.mjs +29 -0
  18. package/apps/route/view/center/CardHome.mjs +26 -0
  19. package/apps/route/view/center/CardSection1.mjs +26 -0
  20. package/apps/route/view/center/CardSection2.mjs +27 -0
  21. package/examples/ConfigurationViewport.mjs +1 -1
  22. package/examples/ServiceWorker.mjs +2 -2
  23. package/examples/form/field/select/MainContainer.mjs +1 -2
  24. package/examples/table/container/MainContainer.mjs +4 -2
  25. package/examples/table/container/MainModel.mjs +3 -0
  26. package/examples/table/container/MainStore.mjs +10 -10
  27. package/examples/toolbar/paging/view/MainContainer.mjs +38 -3
  28. package/package.json +4 -4
  29. package/resources/data/learnneo/content.json +9 -9
  30. package/resources/data/learnneo/pages/whyneo.md +76 -0
  31. package/resources/scss/src/apps/route/CenterContainer.scss +29 -0
  32. package/resources/scss/src/apps/route/HeaderContainer.scss +122 -0
  33. package/resources/scss/src/apps/route/MainView.scss +3 -0
  34. package/resources/scss/src/apps/route/MetaContainer.scss +44 -0
  35. package/resources/scss/src/apps/route/_all.scss +1 -0
  36. package/resources/scss/src/component/Toast.scss +2 -2
  37. package/src/DefaultConfig.mjs +2 -2
  38. package/src/Neo.mjs +15 -14
  39. package/src/button/Base.mjs +2 -2
  40. package/src/collection/Filter.mjs +13 -2
  41. package/src/component/Base.mjs +41 -50
  42. package/src/component/Toast.mjs +2 -1
  43. package/src/container/Base.mjs +59 -2
  44. package/src/controller/Base.mjs +84 -4
  45. package/src/controller/Component.mjs +22 -7
  46. package/src/core/Observable.mjs +50 -9
  47. package/src/form/field/Range.mjs +8 -0
  48. package/src/form/field/Select.mjs +9 -10
  49. package/src/form/field/Text.mjs +13 -3
  50. package/src/form/field/trigger/Picker.mjs +1 -8
  51. package/src/main/DomEvents.mjs +9 -3
  52. package/src/manager/DomEvent.mjs +37 -24
  53. package/src/menu/List.mjs +1 -1
  54. package/src/table/View.mjs +78 -53
  55. package/src/toolbar/Paging.mjs +68 -76
  56. package/src/tooltip/Base.mjs +123 -11
  57. package/src/vdom/Helper.mjs +7 -0
  58. package/src/worker/App.mjs +4 -0
  59. package/test/components/app.mjs +8 -0
  60. package/test/components/files/button/Base.mjs +17 -0
  61. package/test/components/files/component/DateSelector.mjs +18 -0
  62. package/test/components/files/form/field/Select.mjs +35 -0
  63. package/test/components/index.html +17 -0
  64. package/test/components/neo-config.json +6 -0
  65. package/test/components/siesta.js +14 -0
@@ -1,6 +1,8 @@
1
1
  import Container from '../container/Base.mjs';
2
2
  import Label from '../component/Label.mjs';
3
3
 
4
+ let singletons = {};
5
+
4
6
  /**
5
7
  * Base class for component tooltips
6
8
  * @class Neo.tooltip.Base
@@ -44,6 +46,10 @@ class Base extends Container {
44
46
  * @protected
45
47
  */
46
48
  dismissDelayTaskId: null,
49
+ /**
50
+ * @member {Boolean} floating=true
51
+ */
52
+ floating: true,
47
53
  /**
48
54
  * The delay in ms before the tooltip gets shown
49
55
  * @member {Number|null} hideDelay=400
@@ -78,6 +84,18 @@ class Base extends Container {
78
84
  text_: null
79
85
  }
80
86
 
87
+ /**
88
+ * @param {String} id
89
+ * @param {Function} callback
90
+ * @param {Number} delay
91
+ */
92
+ addTimeout(id, callback, delay) {
93
+ id += 'DelayTaskId';
94
+
95
+ this.clearTimeout(this[id]);
96
+ this[id] = setTimeout(callback, delay);
97
+ }
98
+
81
99
  /**
82
100
  * Triggered after the componentId config got changed
83
101
  * @param {String} value
@@ -93,8 +111,8 @@ class Base extends Container {
93
111
  let me = this;
94
112
 
95
113
  Neo.getComponent(value).addDomListeners({
96
- mouseenter: me.showDelayed,
97
- mouseleave: me.hideDelayed,
114
+ mouseenter: me.onDelegateMouseEnter,
115
+ mouseleave: me.onDelegateMouseLeave,
98
116
  delegate : me.delegate,
99
117
  scope : me
100
118
  })
@@ -137,12 +155,10 @@ class Base extends Container {
137
155
  if (item?.ntype === 'label') {
138
156
  item.text = value;
139
157
  } else {
140
- items.push({
158
+ me.add({
141
159
  module: Label,
142
160
  text : value
143
161
  });
144
-
145
- me.items = items;
146
162
  }
147
163
  }
148
164
  }
@@ -169,11 +185,49 @@ class Base extends Container {
169
185
  });
170
186
  }
171
187
 
188
+ /**
189
+ * @param {Neo.controller.Application} app
190
+ * @returns {Neo.tooltip.Base}
191
+ */
192
+ static createSingleton(app) {
193
+ if (!singletons[app.name]) {
194
+ singletons[app.name] = Neo.create('Neo.tooltip.Base', {
195
+ appName : app.name,
196
+ componentId : app.mainView.id,
197
+ resetCfg : {},
198
+ isShared : true,
199
+ delegate : this.delegateFilter,
200
+ listeners : {
201
+ // Reconfigure on over a target
202
+ async targetOver({ target, data }) {
203
+ // Revert last pointerOver config set to initial setting.
204
+ this.set(this.resetCfg);
205
+ this.resetCfg = {};
206
+
207
+ // Use the tooltip config block that the target was configured with
208
+ // to reconfigure this instance, or if there was none, check the
209
+ // data-neo-tooltip property for a text string.
210
+ const config = target?._tooltip || { text : data.target.data.neoTooltip };
211
+
212
+ // Cache things we have to reset
213
+ for (const key in config) {
214
+ this.resetCfg[key] = this[key];
215
+ }
216
+
217
+ // Set ourself up as the target wants
218
+ this.set(config);
219
+ }
220
+ }
221
+ });
222
+ }
223
+
224
+ return singletons[app.name];
225
+ }
226
+
172
227
  /**
173
228
  * Instantly hides the tooltip
174
- * @param {Object|null} data
175
229
  */
176
- hide(data) {
230
+ hide() {
177
231
  let me = this;
178
232
 
179
233
  me.clearTimeout(['dismiss', 'hide', 'show']);
@@ -188,12 +242,70 @@ class Base extends Container {
188
242
  let me = this;
189
243
 
190
244
  if (me.hideDelay) {
191
- me.hideDelayTaskId = setTimeout(me.hide.bind(me), me.hideDelay, data);
245
+ me.addTimeout('hide', me.hide.bind(me), me.hideDelay);
192
246
  } else {
193
247
  me.hide(data)
194
248
  }
195
249
  }
196
250
 
251
+ /**
252
+ * @param {Object} data
253
+ */
254
+ onDelegateMouseEnter(data) {
255
+ const
256
+ me = this,
257
+ {
258
+ currentTarget
259
+ } = data;
260
+
261
+ // If it's an internal move within the delegate, do nothing
262
+ if (currentTarget !== me.activeTarget?.id) {
263
+ me.activeTarget = Neo.get(currentTarget);
264
+ me.align.target = currentTarget;
265
+ me.align.targetMargin = 10;
266
+
267
+ me.fire('targetOver', {
268
+ target : me.activeTarget,
269
+ data
270
+ });
271
+
272
+ // Still visible, just realign
273
+ if (me.mounted) {
274
+ me.show();
275
+ me.alignTo();
276
+ }
277
+ else {
278
+ me.showDelayed(data);
279
+ }
280
+ }
281
+ }
282
+
283
+ // Used as a delegate filter to activate on targets which have a tooltip configuration
284
+ static delegateFilter(path) {
285
+ for (let i = 0, { length } = path; i < length; i++) {
286
+ if (path[i].cls.includes('neo-uses-shared-tooltip') || path[i].data['neoTooltip']) {
287
+ return i;
288
+ }
289
+ }
290
+ }
291
+
292
+ /**
293
+ * @param {Object} data
294
+ */
295
+ onDelegateMouseLeave(data) {
296
+ const me = this;
297
+
298
+ // If it's an internal move within the delegate, do nothing
299
+ if (data.currentTarget === me.activeTarget?.id) {
300
+ me.fire('targetOut', {
301
+ target : me.activeTarget,
302
+ data
303
+ });
304
+ me.activeTarget = null;
305
+ me.hideDelayed(data);
306
+ }
307
+ }
308
+
197
309
  /**
198
310
  * mouseenter event listener for the tooltip element
199
311
  * @param {Object} data
@@ -227,10 +339,10 @@ class Base extends Container {
227
339
 
228
340
  me.showDelayTaskId = null;
229
341
 
230
- me.clearTimeout('hide');
342
+ me.clearTimeout(['hide', 'dismiss']);
231
343
 
232
344
  if (me.dismissDelay) {
233
- me.dismissDelayTaskId = setTimeout(me.hide.bind(me), me.dismissDelay, data);
345
+ me.addTimeout('dismiss', me.hide.bind(me), me.dismissDelay, data);
234
346
  }
235
347
 
236
348
  !me.mounted && me.render(true)
@@ -244,7 +356,7 @@ class Base extends Container {
244
356
  let me = this;
245
357
 
246
358
  if (me.showDelay) {
247
- me.showDelayTaskId = setTimeout(me.show.bind(me), me.showDelay, data)
359
+ me.addTimeout('show', me.show.bind(me), me.showDelay)
248
360
  } else {
249
361
  me.show(data)
250
362
  }
@@ -750,6 +750,13 @@ class Helper extends Base {
750
750
  node.className = value;
751
751
  }
752
752
  break;
753
+ case 'data':
754
+ if (value && Neo.typeOf(value) === 'Object') {
755
+ Object.entries(value).forEach(([key, val]) => {
756
+ node.attributes[`data-${Neo.decamel(key)}`] = val
757
+ })
758
+ }
759
+ break;
753
760
  case 'height':
754
761
  case 'maxHeight':
755
762
  case 'maxWidth':
@@ -134,6 +134,10 @@ class App extends Base {
134
134
  }
135
135
  }
136
136
  } else {
137
+ // default parentId='document.body' => we want it to get shown
138
+ config.autoMount = true;
139
+ config.autoRender = true;
140
+
137
141
  instance = Neo[config.ntype ? 'ntype' : 'create'](config)
138
142
  }
139
143
 
@@ -0,0 +1,8 @@
1
+ // Important: You need to import all classes which you want to use inside tests here
2
+ // (excluding base classes (prototypes) of already imported classes)
3
+
4
+ import Button from '../../src/button/Base.mjs';
5
+ import DateSelector from '../../src/component/DateSelector.mjs';
6
+ import SelectField from '../../src/form/field/Select.mjs';
7
+
8
+ export const onStart = () => Neo.app({name: 'AppEmpty'})
@@ -0,0 +1,17 @@
1
+ StartTest(t => {
2
+ t.it('Checking if neo.mjs got started', async t => {
3
+ if (!globalThis.Neo?.Main) {
4
+ console.log('Starting the neo.mjs workers setup');
5
+
6
+ await import('../../../../src/MicroLoader.mjs');
7
+ }
8
+
9
+ setTimeout(() => {
10
+ Neo.worker.App.createNeoInstance({
11
+ ntype : 'button',
12
+ iconCls: 'fa fa-home',
13
+ text : 'Hello Siesta'
14
+ })
15
+ }, 300)
16
+ });
17
+ });
@@ -0,0 +1,18 @@
1
+ StartTest(t => {
2
+ t.it('Checking if neo.mjs got started', async t => {
3
+ if (!globalThis.Neo?.Main) {
4
+ console.log('Starting the neo.mjs workers setup');
5
+
6
+ await import('../../../../src/MicroLoader.mjs');
7
+ }
8
+
9
+ setTimeout(() => {
10
+ Neo.worker.App.createNeoInstance({
11
+ ntype : 'dateselector',
12
+ height: 250,
13
+ value : '2023-10-15',
14
+ width : 300
15
+ })
16
+ }, 300)
17
+ });
18
+ });
@@ -0,0 +1,35 @@
1
+ StartTest(t => {
2
+ t.it('Checking if neo.mjs got started', async t => {
3
+ if (!globalThis.Neo?.Main) {
4
+ console.log('Starting the neo.mjs workers setup');
5
+
6
+ await import('../../../../../src/MicroLoader.mjs');
7
+ }
8
+
9
+ setTimeout(() => {
10
+ Neo.worker.App.createNeoInstance({
11
+ ntype : 'selectfield',
12
+ labelPosition: 'inline',
13
+ labelText : 'US States',
14
+ labelWidth : 80,
15
+ width : 300,
16
+
17
+ store : {
18
+ autoLoad : true,
19
+ keyProperty: 'abbreviation',
20
+ url : '../../resources/examples/data/us_states.json',
21
+
22
+ model: {
23
+ fields: [{
24
+ name: 'abbreviation',
25
+ type: 'string'
26
+ }, {
27
+ name: 'name',
28
+ type: 'string'
29
+ }]
30
+ }
31
+ }
32
+ })
33
+ }, 300)
34
+ });
35
+ });
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
6
+
7
+ <!-- Web interface -->
8
+ <link rel="stylesheet" type="text/css" href="../../node_modules/siesta-lite/resources/css/siesta-all.css">
9
+ <script type="text/javascript" src="../../node_modules/siesta-lite/siesta-all.js"></script>
10
+
11
+ <!-- Project file -->
12
+ <script type="text/javascript" src="siesta.js"></script>
13
+ </head>
14
+
15
+ <body>
16
+ </body>
17
+ </html>
@@ -0,0 +1,6 @@
1
+ {
2
+ "appPath" : "test/components/app.mjs",
3
+ "basePath" : "../../",
4
+ "environment": "development",
5
+ "mainPath" : "./Main.mjs"
6
+ }
@@ -0,0 +1,14 @@
1
+ const project = new Siesta.Project.Browser();
2
+
3
+ project.configure({
4
+ title : 'Neo Component Tests',
5
+ isEcmaModule: true
6
+ });
7
+
8
+ project.plan(
9
+ 'files/button/Base.mjs',
10
+ 'files/component/DateSelector.mjs',
11
+ 'files/form/field/Select.mjs'
12
+ );
13
+
14
+ project.start();