neo.mjs 4.4.16 → 4.4.18

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "4.4.16",
3
+ "version": "4.4.18",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,13 +1,15 @@
1
1
  .neo-pickerfield {
2
- .neo-picker-container {
3
- background-color: v(pickerfield-container-background-color);
4
- border : v(pickerfield-container-border);
5
- box-shadow : v(pickerfield-container-box-shadow);
6
- position : fixed;
7
- z-index : 20;
8
2
 
9
- &:focus {
10
- outline: none;
11
- }
3
+ }
4
+
5
+ .neo-picker-container {
6
+ background-color: v(pickerfield-container-background-color);
7
+ border : v(pickerfield-container-border);
8
+ box-shadow : v(pickerfield-container-box-shadow);
9
+ position : absolute;
10
+ z-index : 200;
11
+
12
+ &:focus {
13
+ outline: none;
12
14
  }
13
- }
15
+ }
@@ -24,6 +24,7 @@
24
24
  }
25
25
 
26
26
  .neo-list {
27
+ overflow-x: hidden;
27
28
  overflow-y: auto;
28
29
  text-align: left;
29
30
 
@@ -4,7 +4,7 @@ $neoMap: map-merge($neoMap, (
4
4
  'selectfield-list-search-background-color' : inherit,
5
5
  'selectfield-list-search-color' : #fff,
6
6
  'selectfield-list-search-color-selected' : #000,
7
- 'selectfield-picker-container-border' : none,
7
+ 'selectfield-picker-container-border' : 1px solid #bbb,
8
8
  'selectfield-picker-container-border-radius': 0
9
9
  ));
10
10
 
@@ -18,4 +18,4 @@ $neoMap: map-merge($neoMap, (
18
18
  --selectfield-picker-container-border : #{neo(selectfield-picker-container-border)};
19
19
  --selectfield-picker-container-border-radius: #{neo(selectfield-picker-container-border-radius)};
20
20
  }
21
- }
21
+ }
@@ -265,6 +265,12 @@ class Base extends CoreBase {
265
265
  * @member {Array|Object} tooltips_=null
266
266
  */
267
267
  tooltips_: null,
268
+ /**
269
+ * Add 'primary' and other attributes to make it
270
+ * an outstanding design
271
+ * @member {String|null} ui_=null
272
+ */
273
+ ui_: null,
268
274
  /**
269
275
  * The component vnode tree. Available after the component got rendered.
270
276
  * @member {Object} vnode_=null
@@ -648,6 +654,26 @@ class Base extends CoreBase {
648
654
  }
649
655
  }
650
656
 
657
+ /**
658
+ * For styling purposes only.
659
+ * To define button styles or component styles,
660
+ * this will add a css class: neo-ntype-value
661
+ * @param {String|null} value
662
+ * @param {String|null} oldValue
663
+ */
664
+ afterSetUi(value, oldValue) {
665
+ let me = this,
666
+ cls = me.cls;
667
+
668
+ NeoArray.remove(cls, `neo-${me.ntype}-${oldValue}`);
669
+
670
+ if (value && value !== '') {
671
+ NeoArray.add(cls, `neo-${me.ntype}-${value}`);
672
+ }
673
+
674
+ me.cls = cls;
675
+ }
676
+
651
677
  /**
652
678
  * Triggered after the vdom config got changed
653
679
  * @param {Object} value
@@ -235,6 +235,14 @@ class RecordFactory extends Base {
235
235
  * @returns {*}
236
236
  */
237
237
  parseRecordValue(record, field, value, recordConfig=null) {
238
+ if (field.calculate) {
239
+ return field.calculate(record, field, recordConfig);
240
+ }
241
+
242
+ if (field.convert) {
243
+ value = field.convert(value);
244
+ }
245
+
238
246
  let fieldName = field.name,
239
247
  mapping = field.mapping,
240
248
  maxLength = field.maxLength,
@@ -95,6 +95,12 @@ class Store extends Base {
95
95
  * @member {Boolean} remoteSort=false
96
96
  */
97
97
  remoteSort: false,
98
+ /**
99
+ * Add a path to the root of your data.
100
+ * If the responseRoot is 'data' this is optional.
101
+ * @member {String} responseRoot='data'
102
+ */
103
+ responseRoot: 'data',
98
104
  /**
99
105
  * @member {Number} totalCount=0
100
106
  */
@@ -340,9 +346,9 @@ class Store extends Base {
340
346
  }).catch(err => {
341
347
  console.log('Error for Neo.Xhr.request', err, me.id);
342
348
  }).then(data => {
343
- me.data = Array.isArray(data.json) ? data.json : data.json.data;
349
+ me.data = Neo.ns(me.responseRoot, false, data.json) || data.json;
344
350
  // we do not need to fire a load event => onCollectionMutate()
345
- });
351
+ })
346
352
  }
347
353
  }
348
354
 
@@ -0,0 +1,28 @@
1
+ import Base from './Base.mjs';
2
+ import ToastManager from '../manager/ToastDialog.mjs';
3
+
4
+ /**
5
+ * @class Neo.dialog.Toast
6
+ * @extends Neo.dialog.Base
7
+ */
8
+ class Toast extends Base {
9
+ static getConfig() {return {
10
+ /**
11
+ * @member {String} className='Neo.dialog.Toast'
12
+ * @protected
13
+ */
14
+ className: 'Neo.dialog.Toast'
15
+ }}
16
+
17
+ /**
18
+ * @param {Object} config
19
+ */
20
+ construct(config) {
21
+ super.construct(config);
22
+ ToastManager.register(this);
23
+ }
24
+ }
25
+
26
+ Neo.applyClassConfig(Toast);
27
+
28
+ export default Toast;
@@ -89,19 +89,19 @@ class Picker extends Text {
89
89
  applyClientRects(silent) {
90
90
  let me = this,
91
91
  rects = me.clientRects,
92
- bodyRect = rects[2],
93
92
  inputRect = rects[1],
93
+ parentRect = rects[2],
94
94
  triggerRect = rects[0],
95
95
  vdom = me.picker.vdom,
96
- width = me.matchPickerWidth ? (inputRect.width - 1) : me.pickerWidth;
96
+ width = me.matchPickerWidth ? inputRect.width : me.pickerWidth;
97
97
 
98
98
  me.pickerWidth = width;
99
99
 
100
100
  vdom.style = vdom.style || {};
101
101
 
102
102
  Object.assign(vdom.style, {
103
- left : `${triggerRect.left + triggerRect.width - width}px`,
104
- top : `${triggerRect.top + triggerRect.height + 1}px`,
103
+ left : `${inputRect.left}px`,
104
+ top : `${inputRect.bottom + 1}px`,
105
105
  width: `${width}px`
106
106
  });
107
107
 
@@ -124,7 +124,25 @@ class Picker extends Text {
124
124
  maxHeight: me.pickerMaxHeight,
125
125
  vdom : {cn: [], tabIndex: -1},
126
126
  width : me.pickerWidth,
127
- ...me.pickerConfig
127
+ ...me.pickerConfig,
128
+
129
+ // scoped to the field instance
130
+ onFocusLeave: data => {
131
+ let insideField = false,
132
+ item;
133
+
134
+ for (item of data.oldPath) {
135
+ if (item.id === me.id) {
136
+ insideField = true;
137
+ break;
138
+ }
139
+ }
140
+
141
+ if (!insideField) {
142
+ me.hidePicker();
143
+ super.onFocusLeave(data);
144
+ }
145
+ }
128
146
  });
129
147
  }
130
148
 
@@ -138,12 +156,13 @@ class Picker extends Text {
138
156
 
139
157
  /**
140
158
  * @param {Function} [callback]
141
- * @param {Function} [callbackScope]
159
+ * @param {Object} [callbackScope]
142
160
  */
143
161
  getClientRectsThenShow(callback, callbackScope) {
144
- let me = this;
162
+ let me = this,
163
+ triggerId = me.getTriggerId('picker');
145
164
 
146
- me.getDomRect([me.id, me.getInputWrapperId(), 'body']).then(data => {
165
+ me.getDomRect([triggerId, me.getInputWrapperId(), me.parentId]).then(data => {
147
166
  me.clientRects = data;
148
167
  me.showPicker(callback, callbackScope);
149
168
  });
@@ -171,24 +190,18 @@ class Picker extends Text {
171
190
  }
172
191
 
173
192
  /**
174
- * @param {Boolean} [silent=false]
193
+ *
175
194
  */
176
- hidePicker(silent=false) {
195
+ async hidePicker() {
177
196
  let me = this,
178
- picker = me.getPicker(),
179
- vdom = me.vdom;
197
+ picker = me.getPicker();
180
198
 
181
- me.pickerIsMounted && VDomUtil.removeVdomChild(vdom, me.getPickerId());
199
+ // avoid breaking selection model cls updates
200
+ await Neo.timeout(30);
182
201
 
183
- me.pickerIsMounted = false;
202
+ me.pickerIsMounted && picker.unmount();
184
203
 
185
- if (silent) {
186
- picker.mounted = false;
187
- } else {
188
- me.promiseVdomUpdate().then(data => {
189
- picker.mounted = me.pickerIsMounted;
190
- });
191
- }
204
+ me.pickerIsMounted = false;
192
205
  }
193
206
 
194
207
  /**
@@ -196,22 +209,27 @@ class Picker extends Text {
196
209
  * @protected
197
210
  */
198
211
  onFocusLeave(data) {
199
- let me = this;
212
+ let me = this,
213
+ insidePicker = false,
214
+ item;
215
+
216
+ for (item of data.oldPath) {
217
+ if (item.id === me.getPickerId()) {
218
+ insidePicker = true;
219
+ break;
220
+ }
221
+ }
200
222
 
201
- // inline will trigger an vdom update, so hide picker should be silent
202
- if (me.labelPosition === 'inline' && (me.value === '' || me.value === null)) {
203
- me.hidePicker(true);
204
- } else {
223
+ if (!insidePicker) {
205
224
  me.hidePicker();
225
+ super.onFocusLeave(data);
206
226
  }
207
-
208
- super.onFocusLeave(data);
209
227
  }
210
228
 
211
229
  /**
212
230
  * @param {Object} data
213
231
  * @param {Function} [callback]
214
- * @param {Function} [callbackScope]
232
+ * @param {Object} [callbackScope]
215
233
  * @protected
216
234
  */
217
235
  onKeyDownEnter(data, callback, callbackScope) {
@@ -242,23 +260,23 @@ class Picker extends Text {
242
260
 
243
261
  /**
244
262
  * @param {Function} [callback]
245
- * @param {Function} [callbackScope]
263
+ * @param {Object} [callbackScope]
246
264
  */
247
265
  showPicker(callback, callbackScope) {
248
266
  let me = this,
249
267
  picker = me.getPicker(),
250
- vdom = me.vdom;
268
+ listenerId;
251
269
 
252
270
  me.applyClientRects(true);
253
- vdom.cn.push(picker.vdom);
254
271
 
255
- me.promiseVdomUpdate().then(data => {
256
- me.pickerIsMounted = true;
257
-
258
- picker.mounted = me.pickerIsMounted;
272
+ listenerId = picker.on('mounted', () => {
273
+ picker.un('mounted', listenerId);
259
274
 
275
+ me.pickerIsMounted = true;
260
276
  callback?.apply(callbackScope || me);
261
277
  });
278
+
279
+ picker.render(true);
262
280
  }
263
281
  }
264
282
 
@@ -132,7 +132,6 @@ class Select extends Picker {
132
132
  displayField : me.displayField,
133
133
  parentId : me.id,
134
134
  selectionModel: {stayInList: false},
135
- silentSelect : true,
136
135
  store : me.store,
137
136
  ...me.listConfig
138
137
  });
@@ -121,7 +121,7 @@ class Base extends Component {
121
121
  afterSetHidden(value, oldValue) {
122
122
  let style = this.style;
123
123
 
124
- style.display = value ? 'none' : 'inline-block';
124
+ style.display = value ? 'none' : 'inherit';
125
125
  this.style = style;
126
126
  }
127
127
 
@@ -0,0 +1,29 @@
1
+ import Base from '../manager/Base.mjs';
2
+
3
+ /**
4
+ * @class Neo.manager.ToastDialog
5
+ * @extends Neo.manager.Base
6
+ * @singleton
7
+ */
8
+ class ToastDialog extends Base {
9
+ static getConfig() {return {
10
+ /**
11
+ * @member {String} className='Neo.manager.ToastDialog'
12
+ * @protected
13
+ */
14
+ className: 'Neo.manager.ToastDialog',
15
+ /**
16
+ * @member {Boolean} singleton=true
17
+ * @protected
18
+ */
19
+ singleton: true
20
+ }}
21
+ }
22
+
23
+ Neo.applyClassConfig(ToastDialog);
24
+
25
+ let instance = Neo.create(ToastDialog);
26
+
27
+ Neo.applyToGlobalNs(instance);
28
+
29
+ export default instance;