x4js 1.4.9 → 1.4.12

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/lib/x4.css CHANGED
@@ -57,6 +57,103 @@
57
57
  --x4-icon-rectangle-times: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M448 32C483.3 32 512 60.65 512 96V416C512 451.3 483.3 480 448 480H64C28.65 480 0 451.3 0 416V96C0 60.65 28.65 32 64 32H448zM175 208.1L222.1 255.1L175 303C165.7 312.4 165.7 327.6 175 336.1C184.4 346.3 199.6 346.3 208.1 336.1L255.1 289.9L303 336.1C312.4 346.3 327.6 346.3 336.1 336.1C346.3 327.6 346.3 312.4 336.1 303L289.9 255.1L336.1 208.1C346.3 199.6 346.3 184.4 336.1 175C327.6 165.7 312.4 165.7 303 175L255.1 222.1L208.1 175C199.6 165.7 184.4 165.7 175 175C165.7 184.4 165.7 199.6 175 208.1V208.1z"/></svg>';
58
58
  --x4-icon-xmark: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" fill="currentColor"><path d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z"/></svg>';
59
59
  --x4-icon-angle-down: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" fill="currentColor"><path d="M192 384c-8.188 0-16.38-3.125-22.62-9.375l-160-160c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L192 306.8l137.4-137.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-160 160C208.4 380.9 200.2 384 192 384z"/></svg>';
60
+ --x4-icon-calendar-days: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M160 32V64H288V32C288 14.33 302.3 0 320 0C337.7 0 352 14.33 352 32V64H400C426.5 64 448 85.49 448 112V160H0V112C0 85.49 21.49 64 48 64H96V32C96 14.33 110.3 0 128 0C145.7 0 160 14.33 160 32zM0 192H448V464C448 490.5 426.5 512 400 512H48C21.49 512 0 490.5 0 464V192zM64 304C64 312.8 71.16 320 80 320H112C120.8 320 128 312.8 128 304V272C128 263.2 120.8 256 112 256H80C71.16 256 64 263.2 64 272V304zM192 304C192 312.8 199.2 320 208 320H240C248.8 320 256 312.8 256 304V272C256 263.2 248.8 256 240 256H208C199.2 256 192 263.2 192 272V304zM336 256C327.2 256 320 263.2 320 272V304C320 312.8 327.2 320 336 320H368C376.8 320 384 312.8 384 304V272C384 263.2 376.8 256 368 256H336zM64 432C64 440.8 71.16 448 80 448H112C120.8 448 128 440.8 128 432V400C128 391.2 120.8 384 112 384H80C71.16 384 64 391.2 64 400V432zM208 384C199.2 384 192 391.2 192 400V432C192 440.8 199.2 448 208 448H240C248.8 448 256 440.8 256 432V400C256 391.2 248.8 384 240 384H208zM320 432C320 440.8 327.2 448 336 448H368C376.8 448 384 440.8 384 432V400C384 391.2 376.8 384 368 384H336C327.2 384 320 391.2 320 400V432z"/></svg>';
61
+ --x4-icon-tip: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 464c-114.7 0-208-93.31-208-208S141.3 48 256 48s208 93.31 208 208S370.7 464 256 464zM296 336h-16V248C280 234.8 269.3 224 256 224H224C210.8 224 200 234.8 200 248S210.8 272 224 272h8v64h-16C202.8 336 192 346.8 192 360S202.8 384 216 384h80c13.25 0 24-10.75 24-24S309.3 336 296 336zM256 192c17.67 0 32-14.33 32-32c0-17.67-14.33-32-32-32S224 142.3 224 160C224 177.7 238.3 192 256 192z"/></svg>';
62
+ }
63
+ /* source: https://tailwindcss.com/docs/customizing-colors/#default-color-palette */
64
+ :root {
65
+ --black: #000000;
66
+ --white: #ffffff;
67
+ --gray-100: #f7fafc;
68
+ --gray-200: #edf2f7;
69
+ --gray-300: #e2e8f0;
70
+ --gray-400: #cbd5e0;
71
+ --gray-500: #a0aec0;
72
+ --gray-600: #718096;
73
+ --gray-700: #4a5568;
74
+ --gray-800: #2d3748;
75
+ --gray-900: #1a202c;
76
+ --red-100: #fff5f5;
77
+ --red-200: #fed7d7;
78
+ --red-300: #feb2b2;
79
+ --red-400: #fc8181;
80
+ --red-500: #f56565;
81
+ --red-600: #e53e3e;
82
+ --red-700: #c53030;
83
+ --red-800: #9b2c2c;
84
+ --red-900: #742a2a;
85
+ --orange-100: #fffaf0;
86
+ --orange-200: #feebc8;
87
+ --orange-300: #fbd38d;
88
+ --orange-400: #f6ad55;
89
+ --orange-500: #ed8936;
90
+ --orange-600: #dd6b20;
91
+ --orange-700: #c05621;
92
+ --orange-800: #9c4221;
93
+ --orange-900: #7b341e;
94
+ --yellow-100: #fffff0;
95
+ --yellow-200: #fefcbf;
96
+ --yellow-300: #faf089;
97
+ --yellow-400: #f6e05e;
98
+ --yellow-500: #ecc94b;
99
+ --yellow-600: #d69e2e;
100
+ --yellow-700: #b7791f;
101
+ --yellow-800: #975a16;
102
+ --yellow-900: #744210;
103
+ --green-100: #f0fff4;
104
+ --green-200: #c6f6d5;
105
+ --green-300: #9ae6b4;
106
+ --green-400: #68d391;
107
+ --green-500: #48bb78;
108
+ --green-600: #38a169;
109
+ --green-700: #2f855a;
110
+ --green-800: #276749;
111
+ --green-900: #22543d;
112
+ --teal-100: #e6fffa;
113
+ --teal-200: #b2f5ea;
114
+ --teal-300: #81e6d9;
115
+ --teal-400: #4fd1c5;
116
+ --teal-500: #38b2ac;
117
+ --teal-600: #319795;
118
+ --teal-700: #2c7a7b;
119
+ --teal-800: #285e61;
120
+ --teal-900: #234e52;
121
+ --blue-100: #ebf8ff;
122
+ --blue-200: #bee3f8;
123
+ --blue-300: #90cdf4;
124
+ --blue-400: #63b3ed;
125
+ --blue-500: #4299e1;
126
+ --blue-600: #3182ce;
127
+ --blue-700: #2b6cb0;
128
+ --blue-800: #2c5282;
129
+ --blue-900: #2a4365;
130
+ --indigo-100: #ebf4ff;
131
+ --indigo-200: #c3dafe;
132
+ --indigo-300: #a3bffa;
133
+ --indigo-400: #7f9cf5;
134
+ --indigo-500: #667eea;
135
+ --indigo-600: #5a67d8;
136
+ --indigo-700: #4c51bf;
137
+ --indigo-800: #434190;
138
+ --indigo-900: #3c366b;
139
+ --purple-100: #faf5ff;
140
+ --purple-200: #e9d8fd;
141
+ --purple-300: #d6bcfa;
142
+ --purple-400: #b794f4;
143
+ --purple-500: #9f7aea;
144
+ --purple-600: #805ad5;
145
+ --purple-700: #6b46c1;
146
+ --purple-800: #553c9a;
147
+ --purple-900: #44337a;
148
+ --pink-100: #fff5f7;
149
+ --pink-200: #fed7e2;
150
+ --pink-300: #fbb6ce;
151
+ --pink-400: #f687b3;
152
+ --pink-500: #ed64a6;
153
+ --pink-600: #d53f8c;
154
+ --pink-700: #b83280;
155
+ --pink-800: #97266d;
156
+ --pink-900: #702459;
60
157
  }
61
158
  .x4-root-element {
62
159
  padding: 0;
@@ -195,10 +292,13 @@ textarea::selection {
195
292
  .x-icon:before {
196
293
  font-family: var(--x4-icon-font-family);
197
294
  }
198
- .x-icon.x-svg-icon,
199
- .x-icon svg {
200
- width: 1em;
201
- height: 1em;
295
+ .x-icon.x-svg-icon {
296
+ width: 1rem;
297
+ height: 1rem;
298
+ }
299
+ .x-icon.x-svg-icon > svg {
300
+ width: 100%;
301
+ height: 100%;
202
302
  }
203
303
  .x-base-button {
204
304
  display: flex;
@@ -326,7 +426,7 @@ textarea::selection {
326
426
  .x-text-edit > .x-label,
327
427
  .x-combo-box > .x-label {
328
428
  padding: 4px;
329
- color: rgba(0, 0, 0, 0.8);
429
+ color: var(--gray-900);
330
430
  margin-top: 1px;
331
431
  line-height: 1.3em;
332
432
  min-height: 2em;
@@ -344,8 +444,7 @@ textarea::selection {
344
444
  outline: none;
345
445
  border: none;
346
446
  padding: 4px;
347
- color: rgba(0, 0, 0, 0.9);
348
- background-color: rgba(255, 255, 255, 0.25);
447
+ color: var(--gray-900);
349
448
  border-bottom: 1px solid transparent;
350
449
  margin-top: 1px;
351
450
  line-height: 1.3em;
@@ -354,7 +453,7 @@ textarea::selection {
354
453
  .x-combo-box input::placeholder,
355
454
  .x-text-edit .x-fake-input::placeholder,
356
455
  .x-combo-box .x-fake-input::placeholder {
357
- color: rgba(255, 255, 255, 0.5);
456
+ color: var(--gray-800);
358
457
  }
359
458
  .x-text-edit input::selection,
360
459
  .x-combo-box input::selection,
@@ -377,13 +476,17 @@ textarea::selection {
377
476
  .x-combo-box .x-button.gadget {
378
477
  background-color: transparent;
379
478
  font-size: var(--x4-font-size);
380
- color: black;
479
+ color: var(--gray-900);
381
480
  border: none;
382
481
  margin: 0;
383
482
  padding: 0;
384
483
  height: 2em;
385
484
  margin-top: 1px;
386
485
  }
486
+ .x-text-edit .x-button.gadget:hover,
487
+ .x-combo-box .x-button.gadget:hover {
488
+ background-color: transparent;
489
+ }
387
490
  .x-text-edit .x-button.gadget:focus,
388
491
  .x-combo-box .x-button.gadget:focus {
389
492
  color: var(--x4-focus-color);
@@ -429,6 +532,10 @@ textarea::selection {
429
532
  border-bottom: none;
430
533
  border-left: 4px solid var(--x4-error-color);
431
534
  }
535
+ .x-text-edit .x-button.gadget {
536
+ margin-left: 1 px;
537
+ margin-right: 1 px;
538
+ }
432
539
  .x-combo-box > .x-label {
433
540
  border-top: 1px solid transparent;
434
541
  }
@@ -486,20 +593,24 @@ textarea::selection {
486
593
  .x-text-edit:focus .label1 {
487
594
  color: black;
488
595
  }
596
+ .x-radio-btn,
489
597
  .x-check-box {
490
598
  align-items: center;
491
- color: rgba(0, 0, 0, 0.8);
599
+ color: var(--gray-900);
492
600
  outline: none;
493
601
  padding: 4px 0;
494
602
  }
603
+ .x-radio-btn input,
495
604
  .x-check-box input {
496
605
  outline: none;
497
606
  margin: 4px;
498
607
  padding: 0;
499
608
  }
609
+ .x-radio-btn .x-label,
500
610
  .x-check-box .x-label {
501
611
  padding: 4px;
502
612
  }
613
+ .x-radio-btn:focus-within,
503
614
  .x-check-box:focus-within {
504
615
  text-decoration: underline;
505
616
  color: var(--x4-selection-color);
@@ -570,7 +681,7 @@ textarea::selection {
570
681
  align-items: center;
571
682
  outline: none;
572
683
  background-color: transparent;
573
- color: rgba(0, 0, 0, 0.8);
684
+ color: var(--gray-900);
574
685
  padding: 0px 8px;
575
686
  min-width: 120px;
576
687
  border: none;
@@ -578,17 +689,17 @@ textarea::selection {
578
689
  .x-menu-item .x-icon {
579
690
  width: 1em;
580
691
  margin-right: 8px;
581
- color: rgba(0, 0, 0, 0.3);
692
+ color: var(--gray-700);
582
693
  }
583
694
  .x-menu-item .x-label {
584
695
  padding: 4px;
585
696
  }
586
697
  .x-menu-item:hover {
587
698
  background-color: #c6d3d9;
588
- color: black;
699
+ color: var(--gray-900);
589
700
  }
590
701
  .x-menu-item:hover .x-icon {
591
- color: black;
702
+ color: var(--gray-900);
592
703
  }
593
704
  .x-menu-separator {
594
705
  margin-top: 4px;
@@ -702,7 +813,7 @@ textarea::selection {
702
813
  box-shadow: none;
703
814
  }
704
815
  .x-panel > .title > .x-button:focus {
705
- color: black;
816
+ color: var(--gray-900);
706
817
  }
707
818
  .x-panel > .body {
708
819
  padding: 8px;
@@ -839,13 +950,15 @@ textarea::selection {
839
950
  .x-form {
840
951
  background-color: var(--x4-form-color);
841
952
  margin-block-end: 0;
842
- padding: 8px;
953
+ padding: 8px 0;
843
954
  min-width: 250px;
844
955
  min-height: 50px;
845
- overflow: auto;
956
+ padding-right: 4px;
846
957
  }
847
958
  .x-form > .container {
848
959
  padding: 0px;
960
+ overflow: auto;
961
+ padding: 0 4px 0 8px;
849
962
  }
850
963
  .x-form > .footer {
851
964
  position: relative;
@@ -853,7 +966,7 @@ textarea::selection {
853
966
  bottom: 0;
854
967
  width: 100%;
855
968
  justify-content: flex-end;
856
- padding: 0px;
969
+ padding: 0px 4px 0 8px;
857
970
  margin-top: 8px;
858
971
  align-items: center;
859
972
  }
@@ -961,7 +1074,7 @@ textarea::selection {
961
1074
  overflow: hidden;
962
1075
  padding: 4px;
963
1076
  white-space: nowrap;
964
- color: black;
1077
+ color: var(--gray-900);
965
1078
  height: 2em;
966
1079
  }
967
1080
  .x-spreadsheet .x-footer,
@@ -983,25 +1096,25 @@ textarea::selection {
983
1096
  .x-grid-view .x-footer .x-cell,
984
1097
  .x-spreadsheet .x-header .x-cell,
985
1098
  .x-grid-view .x-header .x-cell {
986
- text-overflow: ellipsis;
987
1099
  border-right: 1px solid rgba(0, 0, 0, 0.1);
988
1100
  height: unset;
989
1101
  }
1102
+ .x-spreadsheet .x-footer .x-cell span,
1103
+ .x-grid-view .x-footer .x-cell span,
1104
+ .x-spreadsheet .x-header .x-cell span,
1105
+ .x-grid-view .x-header .x-cell span {
1106
+ min-width: 0;
1107
+ text-transform: uppercase;
1108
+ text-overflow: ellipsis;
1109
+ overflow: hidden;
1110
+ font-weight: bold;
1111
+ }
990
1112
  .x-spreadsheet .x-footer .x-cell.sort,
991
1113
  .x-grid-view .x-footer .x-cell.sort,
992
1114
  .x-spreadsheet .x-header .x-cell.sort,
993
1115
  .x-grid-view .x-header .x-cell.sort {
994
- background-image: var(--x4-icon-arrow-down-long);
995
- background-repeat: no-repeat;
996
- background-size: 1rem 1rem;
997
- background-position: right 0 top 6px;
998
- padding-right: calc(1rem + 4px);
999
- }
1000
- .x-spreadsheet .x-footer .x-cell.sort.desc,
1001
- .x-grid-view .x-footer .x-cell.sort.desc,
1002
- .x-spreadsheet .x-header .x-cell.sort.desc,
1003
- .x-grid-view .x-header .x-cell.sort.desc {
1004
- background-image: var(--x4-icon-arrow-up-long);
1116
+ height: 0.7rem;
1117
+ opacity: 0.7;
1005
1118
  }
1006
1119
  .x-spreadsheet .x-header .x-cell,
1007
1120
  .x-grid-view .x-header .x-cell {
@@ -1128,14 +1241,14 @@ textarea::selection {
1128
1241
  background-color: white;
1129
1242
  color: white;
1130
1243
  padding-left: 24px;
1131
- font-size: 0.8rem;
1132
- font-weight: 300;
1244
+ font-family: var(--x4-font);
1245
+ font-size: var(--x4-font-size);
1133
1246
  }
1134
1247
  .x-tooltip .x-icon {
1135
1248
  position: absolute;
1136
- left: 6px;
1249
+ left: 5px;
1137
1250
  top: 7px;
1138
- color: var(--x4-tip-background);
1251
+ color: var(--x4-selection-color);
1139
1252
  }
1140
1253
  .x-tooltip .x-label {
1141
1254
  background-color: var(--x4-selection-color);
@@ -1170,6 +1283,7 @@ textarea::selection {
1170
1283
  overflow-y: auto;
1171
1284
  }
1172
1285
  .x-popup-list-view {
1286
+ box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.4);
1173
1287
  background-color: white;
1174
1288
  }
1175
1289
  .x-popup-list-view .x-combo-popup {
@@ -1177,7 +1291,7 @@ textarea::selection {
1177
1291
  max-height: 400px;
1178
1292
  border: 1px solid #00000073;
1179
1293
  overflow: auto;
1180
- color: black;
1294
+ color: var(--gray-900);
1181
1295
  }
1182
1296
  .x-popup-list-view .x-combo-popup .x-list-item {
1183
1297
  height: 2em;
@@ -1212,18 +1326,19 @@ textarea::selection {
1212
1326
  }
1213
1327
  .x-calendar .month-sel .x-button {
1214
1328
  height: auto;
1215
- color: black;
1329
+ color: var(--gray-900);
1216
1330
  }
1217
1331
  .x-calendar .week {
1218
1332
  align-items: center;
1333
+ border: 1px solid transparent;
1219
1334
  }
1220
1335
  .x-calendar .week:hover {
1221
- background-color: var(--x4-hover-color);
1336
+ border-color: var(--x4-hover-color);
1222
1337
  border-radius: 4px;
1223
1338
  }
1224
1339
  .x-calendar .week .cell {
1225
1340
  height: 100%;
1226
- color: rgba(0, 0, 0, 0.7);
1341
+ color: var(--gray-900);
1227
1342
  text-align: center;
1228
1343
  }
1229
1344
  .x-calendar .week .cell span {
@@ -1253,7 +1368,7 @@ textarea::selection {
1253
1368
  color: white;
1254
1369
  }
1255
1370
  .x-calendar .header .cell {
1256
- color: rgba(0, 0, 0, 0.5);
1371
+ color: var(--gray-800);
1257
1372
  height: 1.5em;
1258
1373
  }
1259
1374
  .x-calendar .header:hover {
@@ -1527,7 +1642,7 @@ textarea::selection {
1527
1642
  width: 100%;
1528
1643
  color: transparent;
1529
1644
  background-color: transparent;
1530
- caret-color: black;
1645
+ color: var(--gray-900);
1531
1646
  -moz-tab-size: 4;
1532
1647
  -o-tab-size: 4;
1533
1648
  tab-size: 4;
@@ -1570,3 +1685,9 @@ textarea::selection {
1570
1685
  left: 0;
1571
1686
  right: 0;
1572
1687
  }
1688
+ .x-masonry {
1689
+ display: grid;
1690
+ grid-gap: 10px;
1691
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
1692
+ grid-auto-rows: 10px;
1693
+ }
@@ -248,7 +248,8 @@ export declare class EventSource<Q extends EventMap, T extends EventTypes = MapE
248
248
  * @param eventName - event name
249
249
  * @param callback - callback to remove (must be the same as in on )
250
250
  */
251
- off(eventName: string, callback: EventCallback): void;
251
+ off<K extends keyof Q>(type: K, callback: (ev: Q[K]) => any): void;
252
+ _off(eventName: string, callback: EventCallback): void;
252
253
  /**
253
254
  * remove all listeners for an event
254
255
  * @param eventName - event name
package/lib/x4_events.js CHANGED
@@ -236,11 +236,12 @@ class EventSource {
236
236
  * the system may overflow
237
237
  */
238
238
  once(type, callback) {
239
+ //@ts-ignore
239
240
  this._once(type, callback);
240
241
  }
241
242
  _once(eventName, callback) {
242
243
  const newCallback = (ev) => {
243
- this.off(eventName, newCallback);
244
+ this._off(eventName, newCallback);
244
245
  callback(ev);
245
246
  };
246
247
  this._on(eventName, newCallback);
@@ -317,6 +318,7 @@ class EventSource {
317
318
  * @param capturing - if true, capture event before other registred event handlers
318
319
  */
319
320
  on(type, callback) {
321
+ //@ts-ignore
320
322
  return this._on(type, callback);
321
323
  }
322
324
  _on(eventName, callback, capturing = false) {
@@ -337,7 +339,7 @@ class EventSource {
337
339
  }
338
340
  }
339
341
  return {
340
- dispose: () => { this.off(eventName, callback); }
342
+ dispose: () => { this._off(eventName, callback); }
341
343
  };
342
344
  }
343
345
  /**
@@ -345,7 +347,11 @@ class EventSource {
345
347
  * @param eventName - event name
346
348
  * @param callback - callback to remove (must be the same as in on )
347
349
  */
348
- off(eventName, callback) {
350
+ off(type, callback) {
351
+ //@ts-ignore
352
+ return this._off(type, callback);
353
+ }
354
+ _off(eventName, callback) {
349
355
  if (!this.m_eventRegistry) {
350
356
  return;
351
357
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x4js",
3
- "version": "1.4.9",
3
+ "version": "1.4.12",
4
4
  "description": "X4js core files",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
package/src/calendar.ts CHANGED
@@ -167,17 +167,21 @@ export class Calendar extends VLayout<CalendarProps, CalendarEventMap>
167
167
  cls += ' out';
168
168
  }
169
169
 
170
- days.push(new HLayout({
171
- cls,
172
- flex: 1,
173
- content: new Component({
174
- tag: 'span',
175
- content: formatIntlDate(dte, 'd'),
176
- }),
177
- dom_events: {
178
- click: () => this.select(dte.clone())
179
- }
180
- }));
170
+ const mkItem = ( dte ) => {
171
+ return new HLayout({
172
+ cls,
173
+ flex: 1,
174
+ content: new Component({
175
+ tag: 'span',
176
+ content: formatIntlDate(dte, 'd'),
177
+ }),
178
+ dom_events: {
179
+ click: () => this.select(dte)
180
+ }
181
+ })
182
+ }
183
+
184
+ days.push( mkItem( dte.clone() ) );
181
185
 
182
186
  dte.setDate(dte.getDate() + 1);
183
187
  first = false;
package/src/canvas.ts CHANGED
@@ -87,7 +87,7 @@ function mkPainter(c2d: CanvasRenderingContext2D, w: number, h: number): CanvasP
87
87
  return cp;
88
88
  }
89
89
 
90
- function smoothLine(points: any[], path: CanvasPath = null, move = true) {
90
+ function smoothLine( this: CanvasRenderingContext2D, points: any[], path: CanvasPath = null, move = true) {
91
91
  if (points.length < 2) {
92
92
  return;
93
93
  }
@@ -150,7 +150,7 @@ function smoothLine(points: any[], path: CanvasPath = null, move = true) {
150
150
  path.lineTo(p1.x, p1.y);
151
151
  }
152
152
 
153
- function smoothLineEx(_points: any[], tension: number = 0.5, numOfSeg: number = 10, path: CanvasPath = null, move = true, close = false) {
153
+ function smoothLineEx(this: CanvasRenderingContext2D, _points: any[], tension: number = 0.5, numOfSeg: number = 10, path: CanvasPath = null, move = true, close = false) {
154
154
 
155
155
  let points = [];
156
156
 
@@ -261,7 +261,7 @@ function smoothLineEx(_points: any[], tension: number = 0.5, numOfSeg: number =
261
261
  }
262
262
  }
263
263
 
264
- function line(x1: number, y1: number, x2: number, y2: number, color: string, lineWidth: number = 1) {
264
+ function line(this: CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number, color: string, lineWidth: number = 1) {
265
265
  this.save();
266
266
  this.beginPath();
267
267
  this.moveTo(x1, y1);
@@ -272,7 +272,7 @@ function line(x1: number, y1: number, x2: number, y2: number, color: string, lin
272
272
  this.restore();
273
273
  }
274
274
 
275
- function roundRect(x: number, y: number, width: number, height: number, radius: number) {
275
+ function roundRect(this: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius: number) {
276
276
  //this.beginPath( );
277
277
  this.moveTo(x + radius, y);
278
278
  this.lineTo(x + width - radius, y);
@@ -286,7 +286,7 @@ function roundRect(x: number, y: number, width: number, height: number, radius:
286
286
  this.closePath();
287
287
  }
288
288
 
289
- function calcTextSize(text: string, rounded = false): { width: number, height: number } {
289
+ function calcTextSize( this: CanvasRenderingContext2D, text: string, rounded = false): { width: number, height: number } {
290
290
 
291
291
  let fh = this.measureText(text);
292
292
  let lh = fh.fontBoundingBoxAscent + fh.fontBoundingBoxDescent;
@@ -299,12 +299,12 @@ function calcTextSize(text: string, rounded = false): { width: number, height: n
299
299
  }
300
300
  }
301
301
 
302
- function setFontSize(fs: number) {
302
+ function setFontSize( this: CanvasRenderingContext2D, fs: number) {
303
303
  let fsize = Math.round(fs) + 'px';
304
304
  this.font = this.font.replace(/\d+px/, fsize);
305
305
  }
306
306
 
307
- function circle(x: number, y: number, radius: number) {
307
+ function circle( this: CanvasRenderingContext2D, x: number, y: number, radius: number) {
308
308
  this.moveTo(x + radius, y);
309
309
  this.arc(x, y, radius, 0, Math.PI * 2);
310
310
  }
package/src/component.ts CHANGED
@@ -1562,8 +1562,9 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
1562
1562
  return result ? Component.getElement<T>(result) : null;
1563
1563
  }
1564
1564
 
1565
- public queryAll(selector: string, cb?: (el: Component) => void) {
1566
- const elements = this.m_dom.querySelectorAll(selector);
1565
+ public queryAll(selector: string, cb?: (el: Component) => void): HTMLElement[] {
1566
+ let elements:HTMLElement[] = Array.from( this.m_dom.querySelectorAll<HTMLElement>(selector) );
1567
+
1567
1568
  if( cb ) {
1568
1569
  elements.forEach((el) => {
1569
1570
  cb(flyWrap(el as HTMLElement));
package/src/datastore.ts CHANGED
@@ -442,7 +442,7 @@ export class Record {
442
442
 
443
443
  let fld = fields[idx];
444
444
  if( fld.calc!==undefined ) {
445
- return fld.calc.call( this );
445
+ return fld.calc( this );
446
446
  }
447
447
 
448
448
  return this[fld.name];
package/src/formatters.ts CHANGED
@@ -97,4 +97,7 @@ export function money_formatter_nz(input: any): string {
97
97
 
98
98
  export function bool_formatter(input: any): string {
99
99
  return input ? 'oui' : '-';
100
- }
100
+ }
101
+
102
+
103
+ setCurrencySymbol( null );
package/src/gridview.ts CHANGED
@@ -122,7 +122,7 @@ class ColHeader extends Component {
122
122
  }),
123
123
  new Icon( {
124
124
  ref: 'sorter',
125
- cls: '@hidden',
125
+ cls: '@hidden sort',
126
126
  icon: 'var( --x4-icon-arrow-down )'
127
127
  })
128
128
  ]);
package/src/layout.ts CHANGED
@@ -116,7 +116,7 @@ export class GridLayout<P extends GridLayoutProps = GridLayoutProps> extends Con
116
116
  constructor(props: GridLayoutProps) {
117
117
  /// @ts-ignore
118
118
  // Argument of type 'GridLayoutProps' is not assignable to parameter of type 'P'.
119
- // 'GridLayoutProps' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'GridLayoutProps'.
119
+ // 'GridLayoutProps' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'GridLayoutProps'.
120
120
  super(props);
121
121
  }
122
122
 
@@ -134,8 +134,8 @@ export class GridLayout<P extends GridLayoutProps = GridLayoutProps> extends Con
134
134
  this.setStyleValue('grid-gap', this.m_props.colGap);
135
135
  }
136
136
 
137
- if( this.m_props.template ) {
138
- this.setStyleValue('grid-template-areas', this.m_props.template.join('\n') );
137
+ if (this.m_props.template) {
138
+ this.setStyleValue('grid-template-areas', this.m_props.template.join('\n'));
139
139
  }
140
140
  }
141
141
  }
@@ -368,3 +368,54 @@ export class ScrollView extends Component<ScrollViewProps> {
368
368
  }
369
369
  }
370
370
  }
371
+
372
+
373
+ // :: MASONERY ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
374
+
375
+ // from a nice article of Andy Barefoot
376
+ // https://medium.com/@andybarefoot/a-masonry-style-layout-using-css-grid-8c663d355ebb
377
+
378
+ export class Masonry extends Container {
379
+
380
+ constructor(props) {
381
+ super(props);
382
+
383
+ this.setDomEvent('sizechange', () => {
384
+ this.resizeAllItems( );
385
+ });
386
+ }
387
+
388
+ resizeItem(item: Component) {
389
+
390
+ const style = this.getComputedStyle();
391
+
392
+ const rowHeight = style.parse('grid-auto-rows');
393
+ const rowGap = style.parse('grid-row-gap');
394
+
395
+ let content = item.queryItem('.content');
396
+ if( !content ) {
397
+ content = item;
398
+ }
399
+
400
+ if (content && (rowHeight + rowGap)) {
401
+ const rc = content.getBoundingRect();
402
+ const rowSpan = Math.ceil( (rc.height + rowGap) / (rowHeight + rowGap) );
403
+ item.setStyleValue('gridRowEnd', "span " + rowSpan);
404
+ }
405
+ }
406
+
407
+ resizeAllItems( ) {
408
+ this.queryAll( ".item", ( itm ) => {;
409
+ this.resizeItem( itm );
410
+ } );
411
+ }
412
+
413
+ addItem( itm: Component ) {
414
+ itm.addClass( 'content' );
415
+ this.appendChild( new Container( {
416
+ cls: 'item',
417
+ content: itm
418
+ }));
419
+ }
420
+ }
421
+