wunderbaum 0.3.2 → 0.3.4

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.
@@ -3,12 +3,17 @@
3
3
  * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
4
4
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
5
  */
6
+ // @use "sass:meta";
7
+
8
+ // ----------------------------------------------------------------------------
9
+ // --- Define default colors and settings
6
10
 
7
11
  $font-stack: Helvetica, sans-serif;
8
12
 
9
13
  // Basic Theme Colors
10
14
  $error-color: #b5373b;
11
15
  $node-text-color: #56534c;
16
+ $border-color: $node-text-color;
12
17
  $bg-highlight-color: #26a0da;
13
18
  $header-color: #dedede;
14
19
  $background-color: white;
@@ -17,7 +22,6 @@ $alternate-row-color-hover: #f3f3f3; //#f7fcfe;
17
22
  $focus-border-color: #275dc5;
18
23
 
19
24
  // derived
20
- $border-color: $node-text-color;
21
25
  $drop-source-color: adjust-color($node-text-color, $lightness: 50%);
22
26
  $drop-target-color: adjust-color($bg-highlight-color, $lightness: 40%);
23
27
  $dim-color: adjust-color($node-text-color, $lightness: 20%);
@@ -33,6 +37,11 @@ $active-hover-color: #dceff8;
33
37
  $active-hover-border-color: $bg-highlight-color;
34
38
  $active-column-color: $hover-color;
35
39
  $active-header-column-color: adjust-color($header-color, $lightness: -10%);
40
+ $active-color-grayscale: grayscale($active-color);
41
+ $active-border-color-grayscale: grayscale($active-border-color);
42
+ $active-hover-color-grayscale: grayscale($active-hover-color);
43
+ $active-cell-color-grayscale: grayscale($active-cell-color);
44
+ $grid-color-grayscale: grayscale($grid-color);
36
45
  // @debug $active-header-column-color;
37
46
  $filter-dim-color: #dedede;
38
47
  $filter-submatch-color: #868581;
@@ -61,19 +70,81 @@ $header-height: $row-outer-height;
61
70
  $level-rainbow: rgb(255, 255, 201), rgb(218, 255, 218), rgb(255, 217, 254),
62
71
  rgb(204, 250, 250);
63
72
 
64
- div.wunderbaum {
73
+ // ----------------------------------------------------------------------------
74
+ // --- Define CSS variables with calculated default values
75
+
76
+ :root {
77
+ // --wb-font-stack: #{meta.inspect($font-stack)};
78
+ --wb-font-stack: #{$font-stack};
79
+
80
+ // Basic Theme Colors
81
+ --wb-error-color: #{$error-color};
82
+ --wb-node-text-color: #{$node-text-color};
83
+ --wb-border-color: #{$border-color};
84
+ --wb-bg-highlight-color: #{$bg-highlight-color};
85
+ --wb-header-color: #{$header-color};
86
+ --wb-background-color: #{$background-color};
87
+ --wb-alternate-row-color: #{$alternate-row-color};
88
+ --wb-alternate-row-color-hover: #{$alternate-row-color-hover};
89
+ --wb-focus-border-color: #{$focus-border-color};
90
+
91
+ // derived
92
+ --wb-drop-source-color: #{$drop-source-color};
93
+ --wb-drop-target-color: #{$drop-target-color};
94
+ --wb-dim-color: #{$dim-color};
95
+ --wb-error-background-color: #{$error-background-color};
96
+ --wb-hover-color: #{$hover-color};
97
+ --wb-hover-border-color: #{$hover-border-color};
98
+ --wb-grid-color: #{$grid-color};
99
+ --wb-active-color: #{$active-color};
100
+ --wb-active-cell-color: #{$active-cell-color};
101
+ --wb-active-border-color: #{$active-border-color};
102
+ --wb-active-hover-color: #{$active-hover-color};
103
+ --wb-active-hover-border-color: #{$active-hover-border-color};
104
+ --wb-active-column-color: #{$active-column-color};
105
+ --wb-active-header-column-color: #{$active-header-column-color};
106
+ --wb-active-color-grayscale: #{$active-color-grayscale};
107
+ --wb-active-border-color-grayscale: #{$active-border-color-grayscale};
108
+ --wb-active-hover-color-grayscale: #{$active-hover-color-grayscale};
109
+ --wb-active-cell-color-grayscale: #{$active-cell-color-grayscale};
110
+ --wb-grid-color-grayscale: #{$grid-color-grayscale};
111
+
112
+ --wb-filter-dim-color: #{$filter-dim-color};
113
+ --wb-filter-submatch-color: #{$filter-submatch-color};
114
+
115
+ --wb-row-outer-height: #{$row-outer-height};
116
+ --wb-row-inner-height: #{$row-inner-height};
117
+ --wb-row-padding-y: #{$row-padding-y};
118
+ --wb-col-padding-x: #{$col-padding-x};
119
+
120
+ --wb-icon-outer-height: #{$icon-outer-height};
121
+ --wb-icon-outer-width: #{$icon-outer-width};
122
+ --wb-icon-height: #{$icon-height};
123
+ --wb-icon-width: #{$icon-width};
124
+ --wb-icon-padding-y: #{$icon-padding-y};
125
+ --wb-icon-padding-x: #{$icon-padding-x};
126
+
127
+ --wb-header-height: #{$header-height};
128
+ }
129
+
130
+ // ----------------------------------------------------------------------------
131
+ // --- SCSS Rules
132
+
133
+ div.wunderbaum * {
65
134
  box-sizing: border-box;
135
+ }
136
+ div.wunderbaum {
66
137
  height: 100%; // fill parent container
67
138
  min-height: 4px;
68
- background-color: $background-color;
139
+ background-color: var(--wb-background-color);
69
140
  margin: 0;
70
141
  padding: 0;
71
142
 
72
- font-family: $font-stack;
143
+ font-family: var(--wb-font-stack);
73
144
  font-size: 14px;
74
145
 
75
- color: $node-text-color;
76
- border: 2px solid $border-color;
146
+ color: var(--wb-node-text-color);
147
+ border: 2px solid var(--wb-border-color);
77
148
  border-radius: 4px;
78
149
  background-clip: content-box; // Keep bg color outside rounded borders?
79
150
  overflow-x: auto;
@@ -85,7 +156,7 @@ div.wunderbaum {
85
156
  // Focus border is generated by the browsers per default:
86
157
  &:focus,
87
158
  &:focus-within {
88
- border-color: $focus-border-color;
159
+ border-color: var(--wb-focus-border-color);
89
160
  // outline-style: none;
90
161
  }
91
162
 
@@ -119,8 +190,8 @@ div.wunderbaum {
119
190
  div.wb-row {
120
191
  position: absolute;
121
192
  width: 100%;
122
- height: $row-outer-height;
123
- line-height: $row-outer-height;
193
+ height: var(--wb-row-outer-height);
194
+ line-height: var(--wb-row-outer-height);
124
195
  border: 1px solid transparent;
125
196
  }
126
197
 
@@ -131,25 +202,25 @@ div.wunderbaum {
131
202
  position: sticky;
132
203
  left: 0;
133
204
  z-index: 1;
134
- background-color: $background-color;
205
+ background-color: var(--wb-background-color);
135
206
  }
136
207
 
137
208
  div.wb-header {
138
209
  span.wb-col:first-of-type {
139
- background-color: $header-color;
210
+ background-color: var(--wb-header-color);
140
211
  }
141
212
  }
142
213
  div.wb-node-list div.wb-row {
143
214
  &.wb-active span.wb-col:first-of-type,
144
215
  &.wb-selected span.wb-col:first-of-type {
145
- background-color: $active-color;
216
+ background-color: var(--wb-active-color);
146
217
  }
147
218
  &.wb-active:hover span.wb-col:first-of-type,
148
219
  &.wb-selected:hover span.wb-col:first-of-type {
149
- background-color: $active-hover-color;
220
+ background-color: var(--wb-active-hover-color);
150
221
  }
151
222
  &:hover span.wb-col:first-of-type {
152
- background-color: $hover-color;
223
+ background-color: var(--wb-hover-color);
153
224
  }
154
225
  }
155
226
 
@@ -158,10 +229,10 @@ div.wunderbaum {
158
229
  div.wb-node-list div.wb-row {
159
230
  &.wb-active span.wb-col:first-of-type,
160
231
  &.wb-selected span.wb-col:first-of-type {
161
- background-color: grayscale($active-color);
162
- border-color: grayscale($active-border-color);
232
+ background-color: var(--wb-active-color-grayscale);
233
+ border-color: var(--wb-active-border-color-grayscale);
163
234
  &:hover span.wb-col:first-of-type {
164
- background-color: grayscale($active-hover-color);
235
+ background-color: var(--wb-active-hover-color-grayscale);
165
236
  }
166
237
  }
167
238
  }
@@ -176,11 +247,11 @@ div.wunderbaum {
176
247
  div.wb-node-list div.wb-row {
177
248
  &.wb-active,
178
249
  &.wb-selected {
179
- background-color: grayscale($active-color);
180
- border-color: grayscale($active-border-color);
250
+ background-color: var(--wb-active-color-grayscale);
251
+ border-color: var(--wb-active-border-color-grayscale);
181
252
 
182
253
  &:hover {
183
- background-color: grayscale($active-hover-color);
254
+ background-color: var(--wb-active-hover-color-grayscale);
184
255
  }
185
256
  }
186
257
  }
@@ -188,10 +259,10 @@ div.wunderbaum {
188
259
 
189
260
  &.wb-alternate div.wb-node-list {
190
261
  div.wb-row:nth-of-type(even):not(.wb-active):not(.wb-selected) {
191
- background-color: $alternate-row-color;
262
+ background-color: var(--wb-alternate-row-color);
192
263
 
193
264
  &:hover {
194
- background-color: $alternate-row-color-hover;
265
+ background-color: var(--wb-alternate-row-color-hover);
195
266
  }
196
267
  }
197
268
  }
@@ -199,33 +270,33 @@ div.wunderbaum {
199
270
  div.wb-node-list {
200
271
  div.wb-row {
201
272
  &:hover {
202
- background-color: $hover-color;
273
+ background-color: var(--wb-hover-color);
203
274
  }
204
275
 
205
276
  &.wb-active,
206
277
  &.wb-selected {
207
- background-color: $active-color;
278
+ background-color: var(--wb-active-color);
208
279
 
209
- // border-color: $active-border-color;
280
+ // border-color: var(--wb-active-border-color);
210
281
  &:hover {
211
- background-color: $active-hover-color;
212
- // border-color: $active-hover-border-color;
282
+ background-color: var(--wb-active-hover-color);
283
+ // border-color: var(--wb-active-hover-border-color);
213
284
  }
214
285
  }
215
286
 
216
287
  &.wb-focus:not(.wb-active) {
217
288
  border-style: dotted;
218
- border-color: $active-border-color;
289
+ border-color: var(--wb-active-border-color);
219
290
  }
220
291
 
221
292
  &.wb-active {
222
- // background-color: $active-hover-color;
293
+ // background-color: var(--wb-active-hover-color);
223
294
  border-style: solid;
224
- border-color: $active-border-color;
295
+ border-color: var(--wb-active-border-color);
225
296
 
226
297
  &:hover {
227
- // background-color: $active-hover-color;
228
- border-color: $active-hover-border-color;
298
+ // background-color: var(--wb-active-hover-color);
299
+ border-color: var(--wb-active-hover-border-color);
229
300
  }
230
301
  }
231
302
 
@@ -264,7 +335,7 @@ div.wunderbaum {
264
335
 
265
336
  &.wb-error,
266
337
  &.wb-status-error {
267
- color: $error-color;
338
+ color: var(--wb-error-color);
268
339
  }
269
340
  }
270
341
  }
@@ -273,10 +344,10 @@ div.wunderbaum {
273
344
 
274
345
  div.wb-header {
275
346
  position: sticky;
276
- height: $header-height;
277
- border-bottom: 1px solid $border-color;
347
+ height: var(--wb-header-height);
348
+ border-bottom: 1px solid var(--wb-border-color);
278
349
  padding: 0;
279
- background-color: $header-color;
350
+ background-color: var(--wb-header-color);
280
351
 
281
352
  span.wb-col {
282
353
  font-weight: bold;
@@ -302,7 +373,7 @@ div.wunderbaum {
302
373
  width: 3px;
303
374
  // float: right;
304
375
  border: none;
305
- border-right: 2px solid $border-color;
376
+ border-right: 2px solid var(--wb-border-color);
306
377
  height: 100%;
307
378
  cursor: col-resize;
308
379
  }
@@ -313,8 +384,8 @@ div.wunderbaum {
313
384
  display: inline-block;
314
385
  // text-overflow: ellipsis;
315
386
  overflow: hidden;
316
- height: $row-inner-height;
317
- line-height: $row-inner-height;
387
+ height: var(--wb-row-inner-height);
388
+ line-height: var(--wb-row-inner-height);
318
389
  padding: 0 $col-padding-x;
319
390
  border-right: 1px solid $grid-color;
320
391
  white-space: nowrap;
@@ -334,9 +405,9 @@ div.wunderbaum {
334
405
  i.wb-expander,
335
406
  i.wb-icon,
336
407
  i.wb-indent {
337
- height: $icon-outer-height;
338
- width: $icon-outer-width;
339
- padding: $icon-padding-y $icon-padding-x;
408
+ height: var(--wb-icon-outer-height);
409
+ width: var(--wb-icon-outer-width);
410
+ padding: var(--wb-icon-padding) var(--wb-icon-padding-x);
340
411
  display: inline-block;
341
412
  }
342
413
 
@@ -346,10 +417,10 @@ div.wunderbaum {
346
417
  }
347
418
 
348
419
  img.wb-icon {
349
- width: $icon-width;
350
- height: $icon-height;
351
- padding: $icon-padding-y $icon-padding-x;
352
- // margin-top: $icon-padding-y;
420
+ width: var(--wb-icon-width);
421
+ height: var(--wb-icon-height);
422
+ padding: var(--wb-icon-padding-y) var(--wb-icon-padding-x);
423
+ // margin-top: var(--wb-icon-padding-y);
353
424
  }
354
425
 
355
426
  i.wb-indent {
@@ -385,7 +456,7 @@ div.wunderbaum {
385
456
  div.wb-row {
386
457
  span.wb-col {
387
458
  &:hover {
388
- background-color: $active-header-column-color;
459
+ background-color: var(--wb-active-header-column-color);
389
460
  }
390
461
  }
391
462
  }
@@ -393,20 +464,20 @@ div.wunderbaum {
393
464
 
394
465
  &.wb-cell-mode div.wb-header div.wb-row span.wb-col {
395
466
  &.wb-active {
396
- background-color: $active-hover-color;
467
+ background-color: var(--wb-active-hover-color);
397
468
  }
398
469
  }
399
470
 
400
471
  div.wb-node-list div.wb-row {
401
- border-bottom-color: $grid-color;
472
+ border-bottom-color: var(--wb-grid-color);
402
473
 
403
474
  &:hover:not(.wb-active):not(.wb-selected) {
404
- background-color: $hover-color;
405
- // border-color: $hover-border-color;
475
+ background-color: var(--wb-hover-color);
476
+ // border-color: var(--wb-hover-border-color);
406
477
  }
407
478
 
408
479
  &.wb-active {
409
- border-bottom-color: $active-border-color;
480
+ border-bottom-color: var(--wb-active-border-color);
410
481
  }
411
482
 
412
483
  span.wb-col {
@@ -429,7 +500,7 @@ div.wunderbaum {
429
500
  > input[type="week"],
430
501
  > select {
431
502
  width: 100%;
432
- max-height: $row-inner-height;
503
+ max-height: var(--wb-row-inner-height);
433
504
  border: none;
434
505
  }
435
506
 
@@ -450,7 +521,7 @@ div.wunderbaum {
450
521
  div.wb-row:not(.wb-colspan) {
451
522
  &.wb-active {
452
523
  span.wb-col.wb-active {
453
- background-color: grayscale($active-cell-color);
524
+ background-color: var(--wb-active-cell-color-grayscale);
454
525
  }
455
526
  }
456
527
  }
@@ -458,17 +529,17 @@ div.wunderbaum {
458
529
  &.wb-cell-mode:focus-within,
459
530
  &.wb-cell-mode:focus {
460
531
  div.wb-row:not(.wb-colspan):not(.wb-selected) {
461
- // background-color: $background-color;
532
+ // background-color: var(--wb-background-color);
462
533
 
463
534
  span.wb-col.wb-active {
464
- background-color: $active-column-color;
535
+ background-color: var(--wb-active-column-color);
465
536
  }
466
537
 
467
538
  &.wb-active {
468
- background-color: $active-column-color;
539
+ background-color: var(--wb-active-column-color);
469
540
 
470
541
  span.wb-col.wb-active {
471
- background-color: $active-cell-color;
542
+ background-color: var(--wb-active-cell-color);
472
543
  }
473
544
  }
474
545
  }
@@ -476,10 +547,10 @@ div.wunderbaum {
476
547
 
477
548
  &.wb-alternate div.wb-node-list {
478
549
  div.wb-row:nth-of-type(even):not(.wb-active):not(.wb-selected) {
479
- background-color: $alternate-row-color;
550
+ background-color: var(--wb-alternate-row-color);
480
551
 
481
552
  &:hover {
482
- background-color: $alternate-row-color-hover;
553
+ background-color: var(--wb-alternate-row-color-hover);
483
554
  }
484
555
  }
485
556
  }
@@ -488,7 +559,7 @@ div.wunderbaum {
488
559
  &:not(:focus-within),
489
560
  &:not(:focus) {
490
561
  div.wb-node-list div.wb-row {
491
- border-bottom-color: grayscale($grid-color);
562
+ border-bottom-color: var(--wb-grid-color-grayscale);
492
563
  }
493
564
  }
494
565
  }
@@ -498,14 +569,14 @@ div.wunderbaum {
498
569
  &.wb-ext-filter-dim,
499
570
  &.wb-ext-filter-hide {
500
571
  div.wb-node-list div.wb-row {
501
- color: $filter-dim-color;
572
+ color: var(--wb-filter-dim-color);
502
573
 
503
574
  &.wb-submatch {
504
- color: $filter-submatch-color;
575
+ color: var(--wb-filter-submatch-color);
505
576
  }
506
577
 
507
578
  &.wb-match {
508
- color: $node-text-color;
579
+ color: var(--wb-node-text-color);
509
580
  }
510
581
  }
511
582
  }
@@ -523,7 +594,7 @@ div.wunderbaum {
523
594
  opacity: 0.5;
524
595
 
525
596
  .wb-node {
526
- background-color: $drop-source-color;
597
+ background-color: var(--wb-drop-source-color);
527
598
  }
528
599
  }
529
600
 
@@ -531,7 +602,7 @@ div.wunderbaum {
531
602
  overflow: visible;
532
603
 
533
604
  .wb-node {
534
- background-color: $drop-target-color;
605
+ background-color: var(--wb-drop-target-color);
535
606
  overflow: visible;
536
607
 
537
608
  // z-index: 1000;
@@ -601,7 +672,7 @@ div.wunderbaum {
601
672
  &:focus-within i.wb-expander,
602
673
  [class*="wb-statusnode-"] i.wb-expander {
603
674
  transition: color 0.6s;
604
- color: $node-text-color;
675
+ color: var(--wb-node-text-color);
605
676
  }
606
677
  }
607
678
 
@@ -644,7 +715,7 @@ div.wunderbaum {
644
715
  }
645
716
 
646
717
  .wb-helper-disabled {
647
- color: $dim-color;
718
+ color: var(--wb-dim-color);
648
719
  }
649
720
 
650
721
  .wb-helper-hidden {
@@ -652,11 +723,11 @@ div.wunderbaum {
652
723
  }
653
724
 
654
725
  .wb-helper-invalid {
655
- color: $error-color;
726
+ color: var(--wb-error-color);
656
727
  }
657
728
 
658
729
  .wb-helper-lazy-expander {
659
- color: $bg-highlight-color;
730
+ color: var(--wb-bg-highlight-color);
660
731
  }
661
732
 
662
733
  .wb-helper-link {
@@ -707,14 +778,14 @@ div.wunderbaum {
707
778
  // }
708
779
  // tri-state checkbox in indeterminate state
709
780
  .wb-col input[type="checkbox"]:indeterminate {
710
- color: $dim-color;
781
+ color: var(--wb-dim-color);
711
782
  background-color: red;
712
783
  }
713
784
 
714
785
  .wb-col input:invalid {
715
- // border-color: $error-color;
716
- color: $error-color;
717
- background-color: $error-background-color;
786
+ // border-color: var(--wb-error-color);
787
+ color: var(--wb-error-color);
788
+ background-color: var(--wb-error-background-color);
718
789
  }
719
790
 
720
791
  @keyframes wb-spin-animation {
package/src/wunderbaum.ts CHANGED
@@ -44,6 +44,8 @@ import {
44
44
  RenderFlag,
45
45
  NodeVisitCallback,
46
46
  SortCallback,
47
+ NodeToDictCallback,
48
+ WbNodeData,
47
49
  } from "./types";
48
50
  import {
49
51
  DEFAULT_DEBUGLEVEL,
@@ -1772,6 +1774,19 @@ export class Wunderbaum {
1772
1774
  this.root.sortChildren(cmp, deep);
1773
1775
  }
1774
1776
 
1777
+ /** Convert tree to an array of plain objects.
1778
+ *
1779
+ * @param callback(dict, node) is called for every node, in order to allow
1780
+ * modifications.
1781
+ * Return `false` to ignore this node or `"skip"` to include this node
1782
+ * without its children.
1783
+ * @see {@link WunderbaumNode.toDict}.
1784
+ */
1785
+ toDictArray(callback?: NodeToDictCallback): Array<WbNodeData> {
1786
+ const res = this.root.toDict(true, callback);
1787
+ return res.children ?? [];
1788
+ }
1789
+
1775
1790
  /**
1776
1791
  * Update column headers and column width.
1777
1792
  * Return true if at least one column width changed.
@@ -1900,6 +1915,8 @@ export class Wunderbaum {
1900
1915
 
1901
1916
  colElem.style.left = col._ofsPx + "px";
1902
1917
  colElem.style.width = col._widthPx + "px";
1918
+ // Add classes from `columns` definition to `<div.wb-col>` cells
1919
+ col.classes ? colElem.classList.add(...col.classes.split(" ")) : 0;
1903
1920
 
1904
1921
  const title = util.escapeHtml(col.title || col.id);
1905
1922
  let tooltip = "";
@@ -2134,7 +2151,7 @@ export class Wunderbaum {
2134
2151
 
2135
2152
  /**
2136
2153
  * Call `callback(node)` for all nodes in hierarchical order (depth-first, pre-order).
2137
- * @see {@link Wunderbaum.*[Symbol.iterator]}, {@link WunderbaumNode.visit}.
2154
+ * @see {@link IterableIterator<WunderbaumNode>}, {@link WunderbaumNode.visit}.
2138
2155
  *
2139
2156
  * @param {function} callback the callback function.
2140
2157
  * Return false to stop iteration, return "skip" to skip this node and