wunderbaum 0.11.0 → 0.12.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.
- package/README.md +4 -5
- package/dist/wunderbaum.css +10 -10
- package/dist/wunderbaum.css.map +1 -1
- package/dist/wunderbaum.d.ts +52 -12
- package/dist/wunderbaum.esm.js +712 -626
- package/dist/wunderbaum.esm.min.js +24 -24
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +712 -626
- package/dist/wunderbaum.umd.min.js +30 -30
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +7 -5
- package/src/common.ts +1 -1
- package/src/types.ts +32 -8
- package/src/util.ts +12 -0
- package/src/wb_ext_dnd.ts +9 -4
- package/src/wb_ext_edit.ts +4 -0
- package/src/wb_node.ts +108 -40
- package/src/wunderbaum.scss +18 -16
- package/src/wunderbaum.ts +38 -19
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wunderbaum",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"title": "A treegrid control.",
|
|
5
5
|
"description": "JavaScript tree/grid/treegrid control.",
|
|
6
6
|
"homepage": "https://github.com/mar10/wunderbaum",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"eslint-plugin-prettier": "^4.2.1",
|
|
61
61
|
"grunt": "^1.6.1",
|
|
62
62
|
"grunt-contrib-connect": "^3.0.0",
|
|
63
|
-
"grunt-contrib-qunit": "^
|
|
63
|
+
"grunt-contrib-qunit": "^10.1.1",
|
|
64
64
|
"grunt-contrib-watch": "^1.1.0",
|
|
65
65
|
"grunt-exec": "^3.0.0",
|
|
66
66
|
"grunt-yabs": "^1.3.0",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"postcss-url": "^10.1.3",
|
|
71
71
|
"prettier": "^2.8.8",
|
|
72
72
|
"pretty-quick": "^3.1.3",
|
|
73
|
-
"puppeteer": "^
|
|
73
|
+
"puppeteer": "^23.10.0",
|
|
74
74
|
"qunit": "^2.19.4",
|
|
75
75
|
"rollup": "^3.23.0",
|
|
76
76
|
"rollup-plugin-scss": "^4.0.0",
|
|
@@ -80,7 +80,8 @@
|
|
|
80
80
|
"ts-node": "^10.9.1",
|
|
81
81
|
"tslib": "^2.5.2",
|
|
82
82
|
"typedoc": "^0.25.2",
|
|
83
|
-
"typescript": "^5.2.2"
|
|
83
|
+
"typescript": "^5.2.2",
|
|
84
|
+
"yarn-audit-fix": "^10.1.1"
|
|
84
85
|
},
|
|
85
86
|
"nodemonConfig": {
|
|
86
87
|
"watch": [
|
|
@@ -131,5 +132,6 @@
|
|
|
131
132
|
"wunderbaum.umd.min.js.map"
|
|
132
133
|
]
|
|
133
134
|
}
|
|
134
|
-
]
|
|
135
|
+
],
|
|
136
|
+
"packageManager": "yarn@4.4.1+sha512.f825273d0689cc9ead3259c14998037662f1dcd06912637b21a450e8da7cfeb4b1965bbee73d16927baa1201054126bc385c6f43ff4aa705c8631d26e12460f1"
|
|
135
137
|
}
|
package/src/common.ts
CHANGED
|
@@ -12,7 +12,7 @@ export const DEFAULT_DEBUGLEVEL = 4; // Replaced by rollup script
|
|
|
12
12
|
/**
|
|
13
13
|
* Fixed height of a row in pixel. Must match the SCSS variable `$row-outer-height`.
|
|
14
14
|
*/
|
|
15
|
-
export const
|
|
15
|
+
export const DEFAULT_ROW_HEIGHT = 22;
|
|
16
16
|
/**
|
|
17
17
|
* Fixed width of node icons in pixel. Must match the SCSS variable `$icon-outer-width`.
|
|
18
18
|
*/
|
package/src/types.ts
CHANGED
|
@@ -119,7 +119,7 @@ export interface WbNodeData {
|
|
|
119
119
|
colspan?: boolean;
|
|
120
120
|
expanded?: boolean;
|
|
121
121
|
icon?: IconOption;
|
|
122
|
-
iconTooltip?:
|
|
122
|
+
iconTooltip?: TooltipOption;
|
|
123
123
|
key?: string;
|
|
124
124
|
lazy?: boolean;
|
|
125
125
|
/** Make child nodes single-select radio buttons. */
|
|
@@ -128,7 +128,7 @@ export interface WbNodeData {
|
|
|
128
128
|
selected?: boolean;
|
|
129
129
|
statusNodeType?: NodeStatusType;
|
|
130
130
|
title: string;
|
|
131
|
-
tooltip?:
|
|
131
|
+
tooltip?: TooltipOption;
|
|
132
132
|
type?: string;
|
|
133
133
|
unselectable?: boolean;
|
|
134
134
|
/** @internal */
|
|
@@ -335,8 +335,8 @@ export interface NodeTypeDefinition {
|
|
|
335
335
|
colspan?: boolean;
|
|
336
336
|
/** Default icon for matching nodes. */
|
|
337
337
|
icon?: IconOption;
|
|
338
|
-
/** Default icon for matching nodes. */
|
|
339
|
-
iconTooltip?:
|
|
338
|
+
/** Default icon tooltip for matching nodes. */
|
|
339
|
+
iconTooltip?: TooltipOption;
|
|
340
340
|
// and more
|
|
341
341
|
[key: string]: unknown;
|
|
342
342
|
}
|
|
@@ -594,12 +594,34 @@ export interface ApplyCommandOptions {
|
|
|
594
594
|
|
|
595
595
|
/** Possible values for {@link Wunderbaum.expandAll} and {@link WunderbaumNode.expandAll}. */
|
|
596
596
|
export interface ExpandAllOptions {
|
|
597
|
-
/** Restrict expand level @default 99 */
|
|
598
|
-
depth?: number;
|
|
599
597
|
/** Expand and load lazy nodes @default false */
|
|
600
598
|
loadLazy?: boolean;
|
|
601
|
-
/**
|
|
599
|
+
/** Unload lazily loaded children if any (if collapsing). @default false */
|
|
600
|
+
resetLazy?: boolean;
|
|
601
|
+
/** Ignore tree's `minExpandLevel` option @default false */
|
|
602
602
|
force?: boolean;
|
|
603
|
+
/** Restrict expand level.
|
|
604
|
+
* Pass 0 to make only toplevel nodes visible, 1 to expand one level deeper, etc.
|
|
605
|
+
* @default unset (unlimited)
|
|
606
|
+
*/
|
|
607
|
+
depth?: number;
|
|
608
|
+
/**
|
|
609
|
+
* Also collapse child nodes beyond the `depth` level.
|
|
610
|
+
* Otherwise only the `depth` level is collapsed and the expand state of the
|
|
611
|
+
* descendants is retained.
|
|
612
|
+
* Only in combination with collapse and `depth`.
|
|
613
|
+
* Expanding with `deep` option is not supported as recursion depth implied by
|
|
614
|
+
* the `depth` option. However a `deep` option will be considered if
|
|
615
|
+
* `collapseOthers` is set.
|
|
616
|
+
* @default false
|
|
617
|
+
*/
|
|
618
|
+
deep?: boolean;
|
|
619
|
+
/**
|
|
620
|
+
* Expand up to level=depth and collapse all other branches.
|
|
621
|
+
* Only in combination with `flag == true`, `depth > 0`.
|
|
622
|
+
* @default false
|
|
623
|
+
*/
|
|
624
|
+
collapseOthers?: boolean;
|
|
603
625
|
/** Keep active node visible @default true */
|
|
604
626
|
keepActiveNodeVisible?: boolean;
|
|
605
627
|
}
|
|
@@ -723,7 +745,7 @@ export interface SetColumnOptions {
|
|
|
723
745
|
|
|
724
746
|
/** Possible values for {@link WunderbaumNode.setExpanded} `options` argument. */
|
|
725
747
|
export interface SetExpandedOptions {
|
|
726
|
-
/** Ignore {@link WunderbaumOptions.minExpandLevel
|
|
748
|
+
/** Ignore {@link WunderbaumOptions}.minExpandLevel. @default false */
|
|
727
749
|
force?: boolean;
|
|
728
750
|
/** Immediately update viewport (async otherwise). @default false */
|
|
729
751
|
immediate?: boolean;
|
|
@@ -731,6 +753,8 @@ export interface SetExpandedOptions {
|
|
|
731
753
|
noAnimation?: boolean;
|
|
732
754
|
/** Do not send events. @default false */
|
|
733
755
|
noEvents?: boolean;
|
|
756
|
+
/** Unload lazily loaded children if any (if collapsing). @default false */
|
|
757
|
+
resetLazy?: boolean;
|
|
734
758
|
/** Scroll up to bring expanded nodes into viewport. @default false */
|
|
735
759
|
scrollIntoView?: boolean;
|
|
736
760
|
}
|
package/src/util.ts
CHANGED
|
@@ -814,6 +814,18 @@ export function toBool(
|
|
|
814
814
|
throw new Error("No default boolean value provided");
|
|
815
815
|
}
|
|
816
816
|
|
|
817
|
+
/**
|
|
818
|
+
* Return `val` unless `val` is a number in which case we convert to boolean.
|
|
819
|
+
* This is useful when a boolean value is stored as a 0/1 (e.g. in JSON) and
|
|
820
|
+
* we still want to maintain string values. null and undefined are returned as
|
|
821
|
+
* is. E.g. `checkbox` may be boolean or 'radio'.
|
|
822
|
+
*/
|
|
823
|
+
export function intToBool(
|
|
824
|
+
val: boolean | number | string | undefined
|
|
825
|
+
): boolean | string | undefined {
|
|
826
|
+
return typeof val === "number" ? !!val : val;
|
|
827
|
+
}
|
|
828
|
+
|
|
817
829
|
// /** Check if a string is contained in an Array or Set. */
|
|
818
830
|
// export function isAnyOf(s: string, items: Array<string>|Set<string>): boolean {
|
|
819
831
|
// return Array.prototype.includes.call(items, s)
|
package/src/wb_ext_dnd.ts
CHANGED
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
DropRegionType,
|
|
15
15
|
DropRegionTypeSet,
|
|
16
16
|
} from "./types";
|
|
17
|
-
import { ROW_HEIGHT } from "./common";
|
|
18
17
|
import { DebouncedFunction, throttle } from "./debounce";
|
|
19
18
|
|
|
20
19
|
const nodeMimeType = "application/x-wunderbaum-node";
|
|
@@ -135,21 +134,22 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
135
134
|
e: DragEvent,
|
|
136
135
|
allowed: DropRegionTypeSet | null
|
|
137
136
|
): DropRegionType | false {
|
|
137
|
+
const rowHeight = this.tree.options.rowHeightPx!;
|
|
138
138
|
const dy = e.offsetY;
|
|
139
139
|
|
|
140
140
|
if (!allowed) {
|
|
141
141
|
return false;
|
|
142
142
|
} else if (allowed.size === 3) {
|
|
143
|
-
return dy < 0.25 *
|
|
143
|
+
return dy < 0.25 * rowHeight
|
|
144
144
|
? "before"
|
|
145
|
-
: dy > 0.75 *
|
|
145
|
+
: dy > 0.75 * rowHeight
|
|
146
146
|
? "after"
|
|
147
147
|
: "over";
|
|
148
148
|
} else if (allowed.size === 1 && allowed.has("over")) {
|
|
149
149
|
return "over";
|
|
150
150
|
} else {
|
|
151
151
|
// Only 'before' and 'after':
|
|
152
|
-
return dy >
|
|
152
|
+
return dy > rowHeight / 2 ? "after" : "before";
|
|
153
153
|
}
|
|
154
154
|
// return "over";
|
|
155
155
|
}
|
|
@@ -452,7 +452,12 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
452
452
|
}
|
|
453
453
|
this.lastAllowedDropRegions = regionSet;
|
|
454
454
|
this.lastDropEffect = dt.dropEffect;
|
|
455
|
+
|
|
456
|
+
const region = this._calcDropRegion(e, this.lastAllowedDropRegions);
|
|
455
457
|
targetNode.setClass("wb-drop-target");
|
|
458
|
+
targetNode.setClass("wb-drop-over", region === "over");
|
|
459
|
+
targetNode.setClass("wb-drop-before", region === "before");
|
|
460
|
+
targetNode.setClass("wb-drop-after", region === "after");
|
|
456
461
|
|
|
457
462
|
e.preventDefault(); // Allow drop (Drop operation is denied by default)
|
|
458
463
|
return false;
|
package/src/wb_ext_edit.ts
CHANGED
|
@@ -213,6 +213,10 @@ export class EditExtension extends WunderbaumExtension<EditOptionsType> {
|
|
|
213
213
|
if (!node) {
|
|
214
214
|
return;
|
|
215
215
|
}
|
|
216
|
+
if (node.isStatusNode()) {
|
|
217
|
+
node.logWarn("Cannot edit status node.");
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
216
220
|
this.tree.logDebug(`startEditTitle(node=${node})`);
|
|
217
221
|
let inputHtml = node._callEvent("edit.beforeEdit");
|
|
218
222
|
if (inputHtml === false) {
|
package/src/wb_node.ts
CHANGED
|
@@ -50,7 +50,6 @@ import {
|
|
|
50
50
|
makeNodeTitleMatcher,
|
|
51
51
|
nodeTitleSorter,
|
|
52
52
|
RESERVED_TREE_SOURCE_KEYS,
|
|
53
|
-
ROW_HEIGHT,
|
|
54
53
|
TEST_IMG,
|
|
55
54
|
TITLE_SPAN_PAD_Y,
|
|
56
55
|
} from "./common";
|
|
@@ -83,6 +82,21 @@ const NODE_DICT_PROPS = new Set<string>(NODE_PROPS);
|
|
|
83
82
|
NODE_DICT_PROPS.delete("_partsel");
|
|
84
83
|
NODE_DICT_PROPS.delete("unselectable");
|
|
85
84
|
|
|
85
|
+
// /** Node properties that are of type bool (or boolean & string).
|
|
86
|
+
// * When parsing, we accept 0 for false and 1 for true for better JSON compression.
|
|
87
|
+
// */
|
|
88
|
+
// export const NODE_BOOL_PROPS: Set<string> = new Set([
|
|
89
|
+
// "checkbox",
|
|
90
|
+
// "colspan",
|
|
91
|
+
// "expanded",
|
|
92
|
+
// "icon",
|
|
93
|
+
// "iconTooltip",
|
|
94
|
+
// "radiogroup",
|
|
95
|
+
// "selected",
|
|
96
|
+
// "tooltip",
|
|
97
|
+
// "unselectable",
|
|
98
|
+
// ]);
|
|
99
|
+
|
|
86
100
|
/**
|
|
87
101
|
* A single tree node.
|
|
88
102
|
*
|
|
@@ -141,7 +155,9 @@ export class WunderbaumNode {
|
|
|
141
155
|
*/
|
|
142
156
|
public type?: string;
|
|
143
157
|
/** Tooltip definition (`true`: use node's title). */
|
|
144
|
-
public tooltip?:
|
|
158
|
+
public tooltip?: TooltipOption;
|
|
159
|
+
/** Icon tooltip definition (`true`: use node's title). */
|
|
160
|
+
public iconTooltip?: TooltipOption;
|
|
145
161
|
/** Additional classes added to `div.wb-row`.
|
|
146
162
|
* @see {@link hasClass}, {@link setClass}. */
|
|
147
163
|
public classes: Set<string> | null = null; //new Set<string>();
|
|
@@ -171,24 +187,30 @@ export class WunderbaumNode {
|
|
|
171
187
|
|
|
172
188
|
this.tree = tree;
|
|
173
189
|
this.parent = parent;
|
|
174
|
-
|
|
175
190
|
this.key = "" + (data.key ?? ++WunderbaumNode.sequence);
|
|
176
191
|
this.title = "" + (data.title ?? "<" + this.key + ">");
|
|
192
|
+
this.expanded = !!data.expanded;
|
|
193
|
+
this.lazy = !!data.lazy;
|
|
194
|
+
|
|
195
|
+
// We set the following node properties only if a matching data value is
|
|
196
|
+
// passed
|
|
177
197
|
data.refKey != null ? (this.refKey = "" + data.refKey) : 0;
|
|
178
198
|
data.type != null ? (this.type = "" + data.type) : 0;
|
|
179
|
-
this.
|
|
180
|
-
data.
|
|
181
|
-
|
|
199
|
+
data.icon != null ? (this.icon = util.intToBool(data.icon)) : 0;
|
|
200
|
+
data.tooltip != null ? (this.tooltip = util.intToBool(data.tooltip)) : 0;
|
|
201
|
+
data.iconTooltip != null
|
|
202
|
+
? (this.iconTooltip = util.intToBool(data.iconTooltip))
|
|
203
|
+
: 0;
|
|
182
204
|
data.statusNodeType != null
|
|
183
205
|
? (this.statusNodeType = ("" + data.statusNodeType) as NodeStatusType)
|
|
184
206
|
: 0;
|
|
185
207
|
data.colspan != null ? (this.colspan = !!data.colspan) : 0;
|
|
186
208
|
|
|
187
209
|
// Selection
|
|
188
|
-
data.checkbox != null ? (
|
|
210
|
+
data.checkbox != null ? util.intToBool(data.checkbox) : 0;
|
|
189
211
|
data.radiogroup != null ? (this.radiogroup = !!data.radiogroup) : 0;
|
|
190
|
-
this.selected = data.selected
|
|
191
|
-
data.unselectable
|
|
212
|
+
data.selected != null ? (this.selected = !!data.selected) : 0;
|
|
213
|
+
data.unselectable != null ? (this.unselectable = !!data.unselectable) : 0;
|
|
192
214
|
|
|
193
215
|
if (data.classes) {
|
|
194
216
|
this.setClass(data.classes);
|
|
@@ -448,58 +470,78 @@ export class WunderbaumNode {
|
|
|
448
470
|
this.tree._callMethod("edit.startEditTitle", this);
|
|
449
471
|
}
|
|
450
472
|
|
|
451
|
-
/**
|
|
473
|
+
/**
|
|
474
|
+
* Call `setExpanded()` on all descendant nodes.
|
|
475
|
+
*
|
|
476
|
+
* @param flag true to expand, false to collapse.
|
|
477
|
+
* @param options Additional options.
|
|
478
|
+
* @see {@link Wunderbaum.expandAll}
|
|
479
|
+
* @see {@link WunderbaumNode.setExpanded}
|
|
480
|
+
*/
|
|
452
481
|
async expandAll(flag: boolean = true, options?: ExpandAllOptions) {
|
|
453
482
|
const tree = this.tree;
|
|
454
|
-
const minExpandLevel = this.tree.options.minExpandLevel;
|
|
455
483
|
const {
|
|
456
|
-
|
|
457
|
-
|
|
484
|
+
collapseOthers,
|
|
485
|
+
deep,
|
|
486
|
+
depth,
|
|
458
487
|
force,
|
|
459
488
|
keepActiveNodeVisible = true,
|
|
489
|
+
loadLazy,
|
|
490
|
+
resetLazy,
|
|
460
491
|
} = options ?? {};
|
|
461
|
-
|
|
492
|
+
// limit expansion level to `depth` (or tree.minExpandLevel). Default: unlimited
|
|
493
|
+
const treeLevel = this.tree.options.minExpandLevel || null; // 0 -> null
|
|
494
|
+
const minLevel = depth ?? (force ? null : treeLevel);
|
|
462
495
|
const expandOpts = {
|
|
463
|
-
|
|
496
|
+
deep: deep,
|
|
464
497
|
force: force,
|
|
465
498
|
loadLazy: loadLazy,
|
|
499
|
+
resetLazy: resetLazy,
|
|
500
|
+
scrollIntoView: false, // don't scroll every node while iterating
|
|
466
501
|
};
|
|
467
502
|
|
|
468
|
-
|
|
503
|
+
this.logInfo(`expandAll(${flag}, depth=${depth}, minLevel=${minLevel})`);
|
|
504
|
+
|
|
505
|
+
util.assert(
|
|
506
|
+
!(flag && deep != null && !collapseOthers),
|
|
507
|
+
"Expanding with `deep` option is not supported (implied by the `depth` option)."
|
|
508
|
+
);
|
|
509
|
+
|
|
469
510
|
// Expand all direct children in parallel:
|
|
470
|
-
async function _iter(n: WunderbaumNode, level: number
|
|
471
|
-
// n.logInfo(` _iter(
|
|
472
|
-
if (level === 0) {
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
// if (!flag && minExpandLevel && !force && n.getLevel() <= minExpandLevel) {
|
|
476
|
-
// return; // Do not collapse until minExpandLevel
|
|
477
|
-
// }
|
|
478
|
-
const level_1 = level == null ? null : level - 1;
|
|
511
|
+
async function _iter(n: WunderbaumNode, level: number) {
|
|
512
|
+
// n.logInfo(` _iter(level=${level})`);
|
|
479
513
|
const promises: Promise<unknown>[] = [];
|
|
480
514
|
n.children?.forEach((cn) => {
|
|
481
515
|
if (flag) {
|
|
482
|
-
if (
|
|
516
|
+
if (
|
|
517
|
+
!cn.expanded &&
|
|
518
|
+
(minLevel == null || level < minLevel) &&
|
|
519
|
+
(cn.children || (loadLazy && cn.lazy))
|
|
520
|
+
) {
|
|
483
521
|
// Node is collapsed and may be expanded (i.e. has children or is lazy)
|
|
484
522
|
// Expanding may be async, so we store the promise.
|
|
485
523
|
// Also the recursion is delayed until expansion finished.
|
|
486
524
|
const p = cn.setExpanded(true, expandOpts);
|
|
487
525
|
promises.push(p);
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
526
|
+
if (depth == null) {
|
|
527
|
+
p.then(async () => {
|
|
528
|
+
await _iter(cn, level + 1);
|
|
529
|
+
});
|
|
530
|
+
}
|
|
491
531
|
} else {
|
|
492
532
|
// We don't expand the node, but still visit descendants.
|
|
493
533
|
// There we may find lazy nodes, so we
|
|
494
|
-
promises.push(_iter(cn,
|
|
534
|
+
promises.push(_iter(cn, level + 1));
|
|
495
535
|
}
|
|
496
536
|
} else {
|
|
497
537
|
// Collapsing is always synchronous, so no promises required
|
|
498
|
-
|
|
499
|
-
|
|
538
|
+
// Do not collapse until minExpandLevel
|
|
539
|
+
if (minLevel == null || level >= minLevel) {
|
|
500
540
|
cn.setExpanded(false, expandOpts);
|
|
501
541
|
}
|
|
502
|
-
|
|
542
|
+
if ((minLevel != null && level < minLevel) || deep) {
|
|
543
|
+
_iter(cn, level + 1); // recursion, even if cn was already collapsed
|
|
544
|
+
}
|
|
503
545
|
}
|
|
504
546
|
});
|
|
505
547
|
return new Promise((resolve) => {
|
|
@@ -509,10 +551,20 @@ export class WunderbaumNode {
|
|
|
509
551
|
});
|
|
510
552
|
}
|
|
511
553
|
|
|
512
|
-
const tag = tree.logTime(`${this}.expandAll(${flag})`);
|
|
554
|
+
const tag = tree.logTime(`${this}.expandAll(${flag}, depth=${depth})`);
|
|
513
555
|
try {
|
|
514
556
|
tree.enableUpdate(false);
|
|
515
|
-
|
|
557
|
+
|
|
558
|
+
await _iter(this, 0);
|
|
559
|
+
|
|
560
|
+
if (collapseOthers) {
|
|
561
|
+
util.assert(flag, "Option `collapseOthers` requires flag=true");
|
|
562
|
+
util.assert(
|
|
563
|
+
minLevel != null,
|
|
564
|
+
"Option `collapseOthers` requires `depth` or `minExpandLevel`"
|
|
565
|
+
);
|
|
566
|
+
this.expandAll(false, { depth: minLevel! });
|
|
567
|
+
}
|
|
516
568
|
} finally {
|
|
517
569
|
tree.enableUpdate(true);
|
|
518
570
|
tree.logTimeEnd(tag);
|
|
@@ -1140,9 +1192,9 @@ export class WunderbaumNode {
|
|
|
1140
1192
|
// Check for overlapping requests
|
|
1141
1193
|
if (this._requestId) {
|
|
1142
1194
|
this.logWarn(
|
|
1143
|
-
`Recursive load request #${requestId} while #${this._requestId} is pending
|
|
1195
|
+
`Recursive load request #${requestId} while #${this._requestId} is pending. ` +
|
|
1196
|
+
"The previous request will be ignored."
|
|
1144
1197
|
);
|
|
1145
|
-
// node.debug("Send load request #" + requestId);
|
|
1146
1198
|
}
|
|
1147
1199
|
this._requestId = requestId;
|
|
1148
1200
|
|
|
@@ -1660,6 +1712,7 @@ export class WunderbaumNode {
|
|
|
1660
1712
|
protected _render_markup(opts: RenderOptions) {
|
|
1661
1713
|
const tree = this.tree;
|
|
1662
1714
|
const treeOptions = tree.options;
|
|
1715
|
+
const rowHeight = treeOptions.rowHeightPx!;
|
|
1663
1716
|
const checkbox = this.getOption("checkbox");
|
|
1664
1717
|
const columns = tree.columns;
|
|
1665
1718
|
const level = this.getLevel();
|
|
@@ -1681,7 +1734,7 @@ export class WunderbaumNode {
|
|
|
1681
1734
|
rowDiv = document.createElement("div");
|
|
1682
1735
|
rowDiv.classList.add("wb-row");
|
|
1683
1736
|
|
|
1684
|
-
rowDiv.style.top = this._rowIdx! *
|
|
1737
|
+
rowDiv.style.top = this._rowIdx! * rowHeight + "px";
|
|
1685
1738
|
|
|
1686
1739
|
this._rowElem = rowDiv;
|
|
1687
1740
|
|
|
@@ -2176,7 +2229,7 @@ export class WunderbaumNode {
|
|
|
2176
2229
|
const colIdx = options?.colIdx; // Default: null
|
|
2177
2230
|
const edit = options?.edit; // Default: false
|
|
2178
2231
|
|
|
2179
|
-
util.assert(!colIdx || tree.isCellNav(), "colIdx requires cellNav");
|
|
2232
|
+
// util.assert(!colIdx || tree.isCellNav(), "colIdx requires cellNav");
|
|
2180
2233
|
util.assert(!edit || colIdx != null, "edit requires colIdx");
|
|
2181
2234
|
|
|
2182
2235
|
if (!noEvents) {
|
|
@@ -2234,7 +2287,7 @@ export class WunderbaumNode {
|
|
|
2234
2287
|
* Expand or collapse this node.
|
|
2235
2288
|
*/
|
|
2236
2289
|
async setExpanded(flag: boolean = true, options?: SetExpandedOptions) {
|
|
2237
|
-
const { force, scrollIntoView, immediate } = options ?? {};
|
|
2290
|
+
const { force, scrollIntoView, immediate, resetLazy } = options ?? {};
|
|
2238
2291
|
const sendEvents = !options?.noEvents; // Default: send events
|
|
2239
2292
|
if (
|
|
2240
2293
|
!flag &&
|
|
@@ -2261,6 +2314,8 @@ export class WunderbaumNode {
|
|
|
2261
2314
|
}
|
|
2262
2315
|
if (flag && this.lazy && this.children == null) {
|
|
2263
2316
|
await this.loadLazy();
|
|
2317
|
+
} else if (!flag && resetLazy && this.lazy && this.children) {
|
|
2318
|
+
this.resetLazy();
|
|
2264
2319
|
}
|
|
2265
2320
|
this.expanded = flag;
|
|
2266
2321
|
const updateOpts = { immediate: immediate };
|
|
@@ -2763,6 +2818,19 @@ export class WunderbaumNode {
|
|
|
2763
2818
|
av = a.data[propName];
|
|
2764
2819
|
bv = b.data[propName];
|
|
2765
2820
|
}
|
|
2821
|
+
if (av == null && bv == null) {
|
|
2822
|
+
return 0;
|
|
2823
|
+
}
|
|
2824
|
+
if (av == null) {
|
|
2825
|
+
av = typeof bv === "string" ? "" : 0;
|
|
2826
|
+
} else if (typeof av === "boolean") {
|
|
2827
|
+
av = av ? 1 : 0;
|
|
2828
|
+
}
|
|
2829
|
+
if (bv == null) {
|
|
2830
|
+
bv = typeof av === "string" ? "" : 0;
|
|
2831
|
+
} else if (typeof bv === "boolean") {
|
|
2832
|
+
bv = bv ? 1 : 0;
|
|
2833
|
+
}
|
|
2766
2834
|
if (caseInsensitive) {
|
|
2767
2835
|
if (typeof av === "string") {
|
|
2768
2836
|
av = av.toLowerCase();
|
package/src/wunderbaum.scss
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
// @use "sass:meta";
|
|
7
|
+
@use "sass:color";
|
|
8
|
+
@use "sass:list";
|
|
7
9
|
|
|
8
10
|
// ----------------------------------------------------------------------------
|
|
9
11
|
// --- Define default colors and settings
|
|
@@ -22,26 +24,26 @@ $alternate-row-color-hover: #f3f3f3; //#f7fcfe;
|
|
|
22
24
|
$focus-border-color: #275dc5;
|
|
23
25
|
|
|
24
26
|
// derived
|
|
25
|
-
$drop-source-color: adjust
|
|
26
|
-
$drop-target-color: adjust
|
|
27
|
-
$dim-color: adjust
|
|
28
|
-
$error-background-color: adjust
|
|
27
|
+
$drop-source-color: color.adjust($node-text-color, $lightness: 50%);
|
|
28
|
+
$drop-target-color: color.adjust($bg-highlight-color, $lightness: 40%);
|
|
29
|
+
$dim-color: color.adjust($node-text-color, $lightness: 20%);
|
|
30
|
+
$error-background-color: color.adjust($error-color, $lightness: 45%);
|
|
29
31
|
// @debug $dim-color;
|
|
30
|
-
$hover-color: adjust
|
|
32
|
+
$hover-color: color.adjust($bg-highlight-color, $lightness: 48%); // #f7f7f7;
|
|
31
33
|
$hover-border-color: $hover-color;
|
|
32
34
|
$grid-color: #dedede;
|
|
33
35
|
$active-color: #e5f3fb;
|
|
34
|
-
$active-cell-color: adjust
|
|
36
|
+
$active-cell-color: color.adjust($bg-highlight-color, $lightness: 20%);
|
|
35
37
|
$active-border-color: #70c0e7;
|
|
36
38
|
$active-hover-color: #dceff8;
|
|
37
39
|
$active-hover-border-color: $bg-highlight-color;
|
|
38
40
|
$active-column-color: $hover-color;
|
|
39
|
-
$active-header-column-color: adjust
|
|
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);
|
|
41
|
+
$active-header-column-color: color.adjust($header-color, $lightness: -10%);
|
|
42
|
+
$active-color-grayscale: color.grayscale($active-color);
|
|
43
|
+
$active-border-color-grayscale: color.grayscale($active-border-color);
|
|
44
|
+
$active-hover-color-grayscale: color.grayscale($active-hover-color);
|
|
45
|
+
$active-cell-color-grayscale: color.grayscale($active-cell-color);
|
|
46
|
+
$grid-color-grayscale: color.grayscale($grid-color);
|
|
45
47
|
// @debug $active-header-column-color;
|
|
46
48
|
$filter-dim-color: #dedede;
|
|
47
49
|
$filter-submatch-color: #868581;
|
|
@@ -696,10 +698,10 @@ div.wunderbaum {
|
|
|
696
698
|
|
|
697
699
|
/* Colorize indentation levels. */
|
|
698
700
|
&.wb-rainbow {
|
|
699
|
-
@for $i from 1 through length($level-rainbow) {
|
|
700
|
-
i.wb-expander:nth-child(#{length($level-rainbow)}n + #{$i}),
|
|
701
|
-
i.wb-indent:nth-child(#{length($level-rainbow)}n + #{$i}) {
|
|
702
|
-
background: nth($level-rainbow, $i);
|
|
701
|
+
@for $i from 1 through list.length($level-rainbow) {
|
|
702
|
+
i.wb-expander:nth-child(#{list.length($level-rainbow)}n + #{$i}),
|
|
703
|
+
i.wb-indent:nth-child(#{list.length($level-rainbow)}n + #{$i}) {
|
|
704
|
+
background: list.nth($level-rainbow, $i);
|
|
703
705
|
}
|
|
704
706
|
}
|
|
705
707
|
}
|