neo.mjs 6.3.11 → 6.4.0

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 (38) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/examples/ConfigurationViewport.mjs +21 -9
  3. package/examples/ServiceWorker.mjs +2 -2
  4. package/examples/container/dialog/MainContainerController.mjs +20 -16
  5. package/examples/dialog/DemoDialog.mjs +24 -3
  6. package/examples/form/field/select/MainContainer.mjs +28 -6
  7. package/package.json +1 -1
  8. package/resources/scss/src/component/Base.scss +26 -0
  9. package/resources/scss/src/form/field/Picker.scss +0 -3
  10. package/resources/scss/src/menu/List.scss +4 -8
  11. package/resources/scss/theme-dark/menu/List.scss +2 -1
  12. package/resources/scss/theme-light/menu/List.scss +1 -0
  13. package/src/DefaultConfig.mjs +2 -2
  14. package/src/button/Base.mjs +41 -6
  15. package/src/component/Base.mjs +236 -44
  16. package/src/container/Dialog.mjs +3 -3
  17. package/src/core/Base.mjs +20 -0
  18. package/src/form/Container.mjs +2 -0
  19. package/src/form/field/Picker.mjs +30 -47
  20. package/src/form/field/Time.mjs +8 -8
  21. package/src/form/field/trigger/Base.mjs +1 -1
  22. package/src/form/field/trigger/CopyToClipboard.mjs +5 -1
  23. package/src/grid/View.mjs +5 -2
  24. package/src/grid/header/Button.mjs +10 -10
  25. package/src/list/Base.mjs +17 -14
  26. package/src/list/plugin/Animate.mjs +3 -3
  27. package/src/main/DomAccess.mjs +272 -28
  28. package/src/menu/List.mjs +35 -102
  29. package/src/table/Container.mjs +2 -2
  30. package/src/table/header/Button.mjs +21 -23
  31. package/src/tree/Accordion.mjs +1 -1
  32. package/src/util/Array.mjs +4 -18
  33. package/src/util/Css.mjs +6 -8
  34. package/src/util/HashHistory.mjs +10 -3
  35. package/src/util/Rectangle.mjs +444 -7
  36. package/test/siesta/siesta-node.js +2 -1
  37. package/test/siesta/siesta.js +1 -0
  38. package/test/siesta/tests/Rectangle.mjs +409 -0
@@ -0,0 +1,409 @@
1
+ import Rectangle from '../../../src/util/Rectangle.mjs';
2
+
3
+ // Maintainer:
4
+ // A good technique for debugging Rectangle code is to use the show(<colour>) method
5
+ // to visualize the Rectangles in the DOM.
6
+ //
7
+ // The following statements will reveal the state of the Rectangles used
8
+ // constrainingRect.show('#f1f1f1')
9
+ // target.show('red')
10
+ // subject.show('yellow')
11
+ // result.show('green')
12
+
13
+ StartTest(t => {
14
+ let constrainTo, subject, target, result;
15
+
16
+ t.it('contains', t => {
17
+ t.ok(new Rectangle(0, 0, 100, 100).contains(new Rectangle(10, 10, 80, 80)));
18
+ t.notOk(new Rectangle(0, 0, 100, 100).contains(new Rectangle(10, 10, 80, 110)));
19
+ t.notOk(new Rectangle(0, 0, 100, 100).contains(new Rectangle(10, 10, 110, 80)));
20
+ t.notOk(new Rectangle(0, 0, 100, 100).contains(new Rectangle(10, 10, 110, 110)));
21
+ t.notOk(new Rectangle(0, 0, 100, 100).contains(new Rectangle(-10, 10, 80, 80)));
22
+ t.notOk(new Rectangle(0, 0, 100, 100).contains(new Rectangle(10, -10, 80, 80)));
23
+ });
24
+
25
+ t.describe('constrain', t => {
26
+ t.describe('Should constrain fitting subject rectangle', t => {
27
+ constrainTo = new Rectangle(0, 0, 200, 200);
28
+
29
+ // Subject rect is below and to the right
30
+ result = new Rectangle(1000, 1000, 10, 10).constrainTo(constrainTo);
31
+ t.ok(result.equals(new Rectangle(190, 190, 10, 10)));
32
+
33
+ // Subject rect is to the right
34
+ result = new Rectangle(1000, 0, 10, 10).constrainTo(constrainTo);
35
+ t.ok(result.equals(new Rectangle(190, 0, 10, 10)));
36
+
37
+ // Subject rect is above and right
38
+ result = new Rectangle(1000, -1000, 10, 10).constrainTo(constrainTo);
39
+ t.ok(result.equals(new Rectangle(190, 0, 10, 10)));
40
+
41
+ // Subject rect is above
42
+ result = new Rectangle(0, -1000, 10, 10).constrainTo(constrainTo);
43
+ t.ok(result.equals(new Rectangle(0, 0, 10, 10)));
44
+
45
+ // Subject rect is above and to the left
46
+ result = new Rectangle(-1000, -1000, 10, 10).constrainTo(constrainTo);
47
+ t.ok(result.equals(new Rectangle(0, 0, 10, 10)));
48
+
49
+ // Subject rect is to the left
50
+ result = new Rectangle(-1000, 0, 10, 10).constrainTo(constrainTo);
51
+ t.ok(result.equals(new Rectangle(0, 0, 10, 10)));
52
+
53
+ // Subject rect is below and to the left
54
+ result = new Rectangle(-1000, 1000, 10, 10).constrainTo(constrainTo);
55
+ t.ok(result.equals(new Rectangle(0, 190, 10, 10)));
56
+
57
+ // Subject rect is below
58
+ result = new Rectangle(0, 1000, 10, 10).constrainTo(constrainTo);
59
+ t.ok(result.equals(new Rectangle(0, 190, 10, 10)));
60
+ });
61
+
62
+ t.describe('Should constrain non-fitting subject rectangle when minima allow', t => {
63
+ constrainTo = new Rectangle(0, 0, 200, 200);
64
+ subject = new Rectangle(1000, 1000, 210, 210);
65
+
66
+ // Subject Rectangle is willing to shrink to 200x200
67
+ subject.minWidth = subject.minHeight = 200;
68
+
69
+ // Subject rect is below and to the right
70
+ result = subject.constrainTo(constrainTo);
71
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
72
+
73
+ // Subject rect is to the right
74
+ subject.x = 1000; subject.y = 0;
75
+ result = subject.constrainTo(constrainTo);
76
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
77
+
78
+ // Subject rect is above and right
79
+ subject.x = 1000; subject.y = -1000;
80
+ result = subject.constrainTo(constrainTo);
81
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
82
+
83
+ // Subject rect is above
84
+ subject.x = 0; subject.y = -1000;
85
+ result = subject.constrainTo(constrainTo);
86
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
87
+
88
+ // Subject rect is above and to the left
89
+ subject.x = 1000; subject.y = -1000;
90
+ result = subject.constrainTo(constrainTo);
91
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
92
+
93
+ // Subject rect is to the left
94
+ subject.x = -1000; subject.y = 0;
95
+ result = subject.constrainTo(constrainTo);
96
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
97
+
98
+ // Subject rect is below and to the left
99
+ subject.x = -1000; subject.y = 1000;
100
+ result = subject.constrainTo(constrainTo);
101
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
102
+
103
+ // Subject rect is below
104
+ subject.x = 0; subject.y = 1000;
105
+ result = subject.constrainTo(constrainTo);
106
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
107
+ });
108
+
109
+ t.describe('Should constrain non-fitting subject rectangle when minima allow', t => {
110
+ constrainTo = new Rectangle(0, 0, 200, 200);
111
+ subject = new Rectangle(1000, 1000, 210, 210);
112
+
113
+ // Subject Rectangle is willing to shrink to 200x200
114
+ subject.minWidth = subject.minHeight = 200;
115
+
116
+ // Subject rect is below and to the right
117
+ result = subject.constrainTo(constrainTo);
118
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
119
+
120
+ // Subject rect is to the right
121
+ subject.x = 1000; subject.y = 0;
122
+ result = subject.constrainTo(constrainTo);
123
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
124
+
125
+ // Subject rect is above and right
126
+ subject.x = 1000; subject.y = -1000;
127
+ result = subject.constrainTo(constrainTo);
128
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
129
+
130
+ // Subject rect is above
131
+ subject.x = 0; subject.y = -1000;
132
+ result = subject.constrainTo(constrainTo);
133
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
134
+
135
+ // Subject rect is above and to the left
136
+ subject.x = 1000; subject.y = -1000;
137
+ result = subject.constrainTo(constrainTo);
138
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
139
+
140
+ // Subject rect is to the left
141
+ subject.x = -1000; subject.y = 0;
142
+ result = subject.constrainTo(constrainTo);
143
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
144
+
145
+ // Subject rect is below and to the left
146
+ subject.x = -1000; subject.y = 1000;
147
+ result = subject.constrainTo(constrainTo);
148
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
149
+
150
+ // Subject rect is below
151
+ subject.x = 0; subject.y = 1000;
152
+ result = subject.constrainTo(constrainTo);
153
+ t.ok(result.equals(new Rectangle(0, 0, 200, 200)));
154
+ });
155
+ });
156
+
157
+ t.it('expand should work', t => {
158
+ t.ok(new Rectangle(10, 10, 10, 10).expand(5).equals(new Rectangle(5, 5, 20, 20)));
159
+ t.ok(new Rectangle(10, 10, 10, 10).expand([5, 6]).equals(new Rectangle(4, 5, 22, 20)));
160
+ t.ok(new Rectangle(10, 10, 10, 10).expand([5, 6, 7]).equals(new Rectangle(4, 5, 22, 22)));
161
+ t.ok(new Rectangle(10, 10, 10, 10).expand([5, 6, 7, 8]).equals(new Rectangle(2, 5, 24, 22)));
162
+ });
163
+
164
+ t.describe('alignTo', t => {
165
+ t.describe('unconstrained', t => {
166
+ target = new Rectangle(100, 100, 100, 100);
167
+
168
+ result = new Rectangle(0, 0, 50, 50).alignTo({
169
+ target,
170
+ edgeAlign : 't-b'
171
+ });
172
+ t.ok(result.equals(new Rectangle(125, 200, 50, 50)));
173
+
174
+ result = new Rectangle(0, 0, 50, 50).alignTo({
175
+ target,
176
+ edgeAlign : 't0-b0'
177
+ });
178
+ t.ok(result.equals(new Rectangle(100, 200, 50, 50)));
179
+
180
+ result = new Rectangle(0, 0, 50, 50).alignTo({
181
+ target,
182
+ edgeAlign : 't100-b100'
183
+ });
184
+ t.ok(result.equals(new Rectangle(150, 200, 50, 50)));
185
+
186
+ result = new Rectangle(0, 0, 50, 50).alignTo({
187
+ target,
188
+ edgeAlign : 'b-t'
189
+ });
190
+ t.ok(result.equals(new Rectangle(125, 50, 50, 50)));
191
+
192
+ result = new Rectangle(0, 0, 50, 50).alignTo({
193
+ target,
194
+ edgeAlign : 'b0-t0'
195
+ });
196
+ t.ok(result.equals(new Rectangle(100, 50, 50, 50)));
197
+
198
+ result = new Rectangle(0, 0, 50, 50).alignTo({
199
+ target,
200
+ edgeAlign : 'b100-t100'
201
+ });
202
+ t.ok(result.equals(new Rectangle(150, 50, 50, 50)));
203
+
204
+ result = new Rectangle(0, 0, 50, 50).alignTo({
205
+ target,
206
+ edgeAlign : 'l-r'
207
+ });
208
+ t.ok(result.equals(new Rectangle(200, 125, 50, 50)));
209
+
210
+ result = new Rectangle(0, 0, 50, 50).alignTo({
211
+ target,
212
+ edgeAlign : 'l0-r0'
213
+ });
214
+ t.ok(result.equals(new Rectangle(200, 100, 50, 50)));
215
+
216
+ result = new Rectangle(0, 0, 50, 50).alignTo({
217
+ target,
218
+ edgeAlign : 'l100-r100'
219
+ });
220
+ t.ok(result.equals(new Rectangle(200, 150, 50, 50)));
221
+
222
+ result = new Rectangle(0, 0, 50, 50).alignTo({
223
+ target,
224
+ edgeAlign : 'r-l'
225
+ });
226
+ t.ok(result.equals(new Rectangle(50, 125, 50, 50)));
227
+
228
+ result = new Rectangle(0, 0, 50, 50).alignTo({
229
+ target,
230
+ edgeAlign : 'r0-l0'
231
+ });
232
+ t.ok(result.equals(new Rectangle(50, 100, 50, 50)));
233
+
234
+ result = new Rectangle(0, 0, 50, 50).alignTo({
235
+ target,
236
+ edgeAlign : 'r100-l100'
237
+ });
238
+ t.ok(result.equals(new Rectangle(50, 150, 50, 50)));
239
+ });
240
+
241
+ // The aligned edge of the subject must match the size of the edge of the target that it aligns to
242
+ t.describe('unconstrained width matchSize', t => {
243
+ target = new Rectangle(100, 100, 100, 100);
244
+
245
+ result = new Rectangle(0, 0, 50, 50).alignTo({
246
+ target,
247
+ edgeAlign : 't-b',
248
+ matchSize : true
249
+ });
250
+ t.ok(result.equals(new Rectangle(100, 200, 100, 50)));
251
+
252
+ result = new Rectangle(0, 0, 50, 50).alignTo({
253
+ target,
254
+ edgeAlign : 'b-t',
255
+ matchSize : true
256
+ });
257
+ t.ok(result.equals(new Rectangle(100, 50, 100, 50)));
258
+
259
+ result = new Rectangle(0, 0, 50, 50).alignTo({
260
+ target,
261
+ edgeAlign : 'l-r',
262
+ matchSize : true
263
+ });
264
+ t.ok(result.equals(new Rectangle(200, 100, 50, 100)));
265
+
266
+ result = new Rectangle(0, 0, 50, 50).alignTo({
267
+ target,
268
+ edgeAlign : 'r-l',
269
+ matchSize : true
270
+ });
271
+ t.ok(result.equals(new Rectangle(50, 100, 50, 100)));
272
+ });
273
+
274
+ // The subject must be pushed away from the target by the correct targetMargin
275
+ t.describe('unconstrained with targetMargin', async t => {
276
+ target = new Rectangle(110, 110, 80, 80);
277
+
278
+ result = new Rectangle(0, 0, 50, 50).alignTo({
279
+ target,
280
+ targetMargin : 10,
281
+ edgeAlign : 't-b'
282
+ });
283
+ t.ok(result.equals(new Rectangle(125, 200, 50, 50)));
284
+
285
+ result = new Rectangle(0, 0, 50, 50).alignTo({
286
+ target,
287
+ targetMargin : 10,
288
+ edgeAlign : 't0-b0'
289
+ });
290
+ t.ok(result.equals(new Rectangle(110, 200, 50, 50)));
291
+
292
+ result = new Rectangle(0, 0, 50, 50).alignTo({
293
+ target,
294
+ targetMargin : 10,
295
+ edgeAlign : 't100-b100'
296
+ });
297
+ t.ok(result.equals(new Rectangle(140, 200, 50, 50)));
298
+
299
+ result = new Rectangle(0, 0, 50, 50).alignTo({
300
+ target,
301
+ targetMargin : 10,
302
+ edgeAlign : 'b-t'
303
+ });
304
+ t.ok(result.equals(new Rectangle(125, 50, 50, 50)));
305
+
306
+ result = new Rectangle(0, 0, 50, 50).alignTo({
307
+ target,
308
+ targetMargin : 10,
309
+ edgeAlign : 'b0-t0'
310
+ });
311
+ t.ok(result.equals(new Rectangle(110, 50, 50, 50)));
312
+
313
+ result = new Rectangle(0, 0, 50, 50).alignTo({
314
+ target,
315
+ targetMargin : 10,
316
+ edgeAlign : 'b100-t100'
317
+ });
318
+ t.ok(result.equals(new Rectangle(140, 50, 50, 50)));
319
+
320
+ result = new Rectangle(0, 0, 50, 50).alignTo({
321
+ target,
322
+ targetMargin : 10,
323
+ edgeAlign : 'l-r'
324
+ });
325
+ t.ok(result.equals(new Rectangle(200, 125, 50, 50)));
326
+
327
+ result = new Rectangle(0, 0, 50, 50).alignTo({
328
+ target,
329
+ targetMargin : 10,
330
+ edgeAlign : 'l0-r0'
331
+ });
332
+ t.ok(result.equals(new Rectangle(200, 110, 50, 50)));
333
+
334
+ result = new Rectangle(0, 0, 50, 50).alignTo({
335
+ target,
336
+ targetMargin : 10,
337
+ edgeAlign : 'l100-r100'
338
+ });
339
+ t.ok(result.equals(new Rectangle(200, 140, 50, 50)));
340
+
341
+ result = new Rectangle(0, 0, 50, 50).alignTo({
342
+ target,
343
+ targetMargin : 10,
344
+ edgeAlign : 'r-l'
345
+ });
346
+ t.ok(result.equals(new Rectangle(50, 125, 50, 50)));
347
+
348
+ result = new Rectangle(0, 0, 50, 50).alignTo({
349
+ target,
350
+ targetMargin : 10,
351
+ edgeAlign : 'r0-l0'
352
+ });
353
+ t.ok(result.equals(new Rectangle(50, 110, 50, 50)));
354
+
355
+ result = new Rectangle(0, 0, 50, 50).alignTo({
356
+ target,
357
+ targetMargin : 10,
358
+ edgeAlign : 'r100-l100'
359
+ });
360
+ t.ok(result.equals(new Rectangle(50, 140, 50, 50)));
361
+ });
362
+
363
+ // Test the adaptation scenarios for the requested position being below the target.
364
+ // TODO: test constrain adaptation for all four edge alignment zones
365
+ t.describe('constrained, edgeAlign : "t-b"', t => {
366
+ constrainTo = new Rectangle(0, 0, 500, 500);
367
+ target = new Rectangle(200, 200, 100, 100);
368
+ subject = new Rectangle(0, 0, 10, 1000);
369
+
370
+ t.it('Subject shrinks to fit', t => {
371
+ subject.minHeight = 100;
372
+ result = subject.alignTo({
373
+ target,
374
+ constrainTo,
375
+ edgeAlign : 't-b'
376
+ });
377
+ t.ok(result.equals(new Rectangle(245, 300, 10, 200)));
378
+ });
379
+
380
+ subject = new Rectangle(0, 0, 10, 1000);
381
+ subject.minHeight = 100;
382
+
383
+ t.it('Subject shrinks to fit, cannot fit in first choice zone, flips edge and matches aligned edge size', t => {
384
+ result = subject.alignTo({
385
+ target,
386
+ constrainTo,
387
+ matchSize : true,
388
+ edgeAlign : 't-b'
389
+ });
390
+ t.ok(result.equals(new Rectangle(200, 300, 100, 200)));
391
+ });
392
+
393
+ t.it('Subject cannot shrink enough to fit at first choice moves to closest fitting zone', t => {
394
+ // Only 50px below. Should flip to top
395
+ target = new Rectangle(200, 350, 100, 100),
396
+ subject = new Rectangle(0, 0, 50, 200);
397
+ subject.minHeight = 100;
398
+
399
+ result = subject.alignTo({
400
+ target,
401
+ constrainTo,
402
+ matchSize : true,
403
+ edgeAlign : 't-b'
404
+ });
405
+ t.ok(result.equals(new Rectangle(150, 300, 50, 200)));
406
+ });
407
+ });
408
+ });
409
+ });