wunderbaum 0.11.1 → 0.12.1
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 +5 -5
- package/dist/wunderbaum.css +1 -1
- package/dist/wunderbaum.css.map +1 -1
- package/dist/wunderbaum.d.ts +111 -28
- package/dist/wunderbaum.esm.js +129 -78
- package/dist/wunderbaum.esm.min.js +35 -35
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +129 -78
- package/dist/wunderbaum.umd.min.js +40 -40
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +30 -28
- package/src/common.ts +31 -13
- package/src/debounce.ts +5 -0
- package/src/deferred.ts +1 -1
- package/src/drag_observer.ts +1 -1
- package/src/types.ts +76 -13
- package/src/util.ts +1 -1
- package/src/wb_ext_dnd.ts +3 -3
- package/src/wb_ext_edit.ts +1 -1
- package/src/wb_ext_filter.ts +2 -2
- package/src/wb_ext_grid.ts +1 -1
- package/src/wb_ext_keynav.ts +1 -1
- package/src/wb_ext_logger.ts +1 -1
- package/src/wb_extension_base.ts +1 -1
- package/src/wb_node.ts +63 -30
- package/src/wb_options.ts +9 -1
- package/src/wunderbaum.scss +21 -19
- package/src/wunderbaum.ts +14 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wunderbaum",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"title": "A treegrid control.",
|
|
5
5
|
"description": "JavaScript tree/grid/treegrid control.",
|
|
6
6
|
"homepage": "https://github.com/mar10/wunderbaum",
|
|
@@ -47,40 +47,42 @@
|
|
|
47
47
|
"control"
|
|
48
48
|
],
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@
|
|
51
|
-
"@
|
|
52
|
-
"@rollup/plugin-
|
|
53
|
-
"@
|
|
54
|
-
"@
|
|
55
|
-
"@
|
|
56
|
-
"
|
|
57
|
-
"eslint": "^8.
|
|
58
|
-
"
|
|
59
|
-
"eslint
|
|
60
|
-
"eslint-
|
|
50
|
+
"@eslint/eslintrc": "^3.2.0",
|
|
51
|
+
"@eslint/js": "^9.20.0",
|
|
52
|
+
"@rollup/plugin-replace": "^6.0.2",
|
|
53
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
54
|
+
"@rollup/plugin-typescript": "^12.1.2",
|
|
55
|
+
"@types/jest": "^29.5.14",
|
|
56
|
+
"@typescript-eslint/eslint-plugin": "^8.24.0",
|
|
57
|
+
"@typescript-eslint/parser": "^8.24.0",
|
|
58
|
+
"concurrently": "^9.1.2",
|
|
59
|
+
"eslint": "^9.20.1",
|
|
60
|
+
"eslint-config-jquery": "^3.0.2",
|
|
61
|
+
"eslint-config-prettier": "^10.0.1",
|
|
62
|
+
"eslint-plugin-prettier": "^5.2.3",
|
|
61
63
|
"grunt": "^1.6.1",
|
|
62
|
-
"grunt-contrib-connect": "^
|
|
64
|
+
"grunt-contrib-connect": "^5.0.1",
|
|
63
65
|
"grunt-contrib-qunit": "^10.1.1",
|
|
64
66
|
"grunt-contrib-watch": "^1.1.0",
|
|
65
67
|
"grunt-exec": "^3.0.0",
|
|
66
68
|
"grunt-yabs": "^1.3.0",
|
|
67
69
|
"http-server": "^14.1.1",
|
|
68
|
-
"nodemon": "^
|
|
69
|
-
"postcss": "^8.2
|
|
70
|
+
"nodemon": "^3.1.9",
|
|
71
|
+
"postcss": "^8.5.2",
|
|
70
72
|
"postcss-url": "^10.1.3",
|
|
71
|
-
"prettier": "^
|
|
72
|
-
"pretty-quick": "^
|
|
73
|
-
"puppeteer": "^
|
|
74
|
-
"qunit": "^2.
|
|
75
|
-
"rollup": "^
|
|
76
|
-
"rollup-plugin-scss": "^4.0.
|
|
77
|
-
"sass": "^1.
|
|
78
|
-
"terser": "^5.
|
|
79
|
-
"ts-jest": "^29.
|
|
80
|
-
"ts-node": "^10.9.
|
|
81
|
-
"tslib": "^2.
|
|
82
|
-
"typedoc": "^0.
|
|
83
|
-
"typescript": "^5.
|
|
73
|
+
"prettier": "^3.5.1",
|
|
74
|
+
"pretty-quick": "^4.0.0",
|
|
75
|
+
"puppeteer": "^24.2.0",
|
|
76
|
+
"qunit": "^2.24.1",
|
|
77
|
+
"rollup": "^4.34.6",
|
|
78
|
+
"rollup-plugin-scss": "^4.0.1",
|
|
79
|
+
"sass": "^1.84.0",
|
|
80
|
+
"terser": "^5.39.0",
|
|
81
|
+
"ts-jest": "^29.2.5",
|
|
82
|
+
"ts-node": "^10.9.2",
|
|
83
|
+
"tslib": "^2.8.1",
|
|
84
|
+
"typedoc": "^0.27.7",
|
|
85
|
+
"typescript": "^5.7",
|
|
84
86
|
"yarn-audit-fix": "^10.1.1"
|
|
85
87
|
},
|
|
86
88
|
"nodemonConfig": {
|
package/src/common.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Wunderbaum - common
|
|
3
|
-
* Copyright (c) 2021-
|
|
3
|
+
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
4
4
|
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -36,8 +36,11 @@ export const TEST_IMG = new RegExp(/\.|\//);
|
|
|
36
36
|
// export const INVALID_REQUEST_TARGET_ERROR = "$request_target_invalid";
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* Default node icons
|
|
40
|
-
*
|
|
39
|
+
* Default node icons for icon libraries
|
|
40
|
+
*
|
|
41
|
+
* - 'bootstrap': {@link https://icons.getbootstrap.com}
|
|
42
|
+
* - 'fontawesome6' {@link https://fontawesome.com/icons}
|
|
43
|
+
*
|
|
41
44
|
*/
|
|
42
45
|
export const iconMaps: { [key: string]: { [key: string]: string } } = {
|
|
43
46
|
bootstrap: {
|
|
@@ -205,10 +208,12 @@ export function nodeTitleSorter(a: WunderbaumNode, b: WunderbaumNode): number {
|
|
|
205
208
|
/**
|
|
206
209
|
* Convert 'flat' to 'nested' format.
|
|
207
210
|
*
|
|
208
|
-
*
|
|
209
|
-
* [
|
|
210
|
-
*
|
|
211
|
-
* [
|
|
211
|
+
* Flat node entry format:
|
|
212
|
+
* [PARENT_IDX, {KEY_VALUE_ARGS}]
|
|
213
|
+
* or, if N _positional re defined:
|
|
214
|
+
* [PARENT_IDX, POSITIONAL_ARG_1, POSITIONAL_ARG_2, ..., POSITIONAL_ARG_N]
|
|
215
|
+
* Even if _positional additional are defined, KEY_VALUE_ARGS can be appended:
|
|
216
|
+
* [PARENT_IDX, POSITIONAL_ARG_1, ..., {KEY_VALUE_ARGS}]
|
|
212
217
|
*
|
|
213
218
|
* 1. Parent-referencing list is converted to a list of nested dicts with
|
|
214
219
|
* optional `children` properties.
|
|
@@ -216,11 +221,12 @@ export function nodeTitleSorter(a: WunderbaumNode, b: WunderbaumNode): number {
|
|
|
216
221
|
*/
|
|
217
222
|
function unflattenSource(source: SourceObjectType): void {
|
|
218
223
|
const { _format, _keyMap = {}, _positional = [], children } = source;
|
|
224
|
+
const _positionalCount = _positional.length;
|
|
219
225
|
|
|
220
226
|
if (_format !== "flat") {
|
|
221
227
|
throw new Error(`Expected source._format: "flat", but got ${_format}`);
|
|
222
228
|
}
|
|
223
|
-
if (
|
|
229
|
+
if (_positionalCount && _positional.includes("children")) {
|
|
224
230
|
throw new Error(
|
|
225
231
|
`source._positional must not include "children": ${_positional}`
|
|
226
232
|
);
|
|
@@ -236,7 +242,7 @@ function unflattenSource(source: SourceObjectType): void {
|
|
|
236
242
|
longToShort[value] = key;
|
|
237
243
|
}
|
|
238
244
|
}
|
|
239
|
-
const positionalShort = _positional.map((e: string) => longToShort[e]);
|
|
245
|
+
const positionalShort = _positional.map((e: string) => longToShort[e] ?? e);
|
|
240
246
|
const newChildren: SourceListType = [];
|
|
241
247
|
const keyToNodeMap: { [key: string]: number } = {};
|
|
242
248
|
const indexToNodeMap: { [key: number]: any } = {};
|
|
@@ -247,21 +253,33 @@ function unflattenSource(source: SourceObjectType): void {
|
|
|
247
253
|
// Node entry format:
|
|
248
254
|
// [PARENT_ID, [POSITIONAL_ARGS]]
|
|
249
255
|
// or
|
|
250
|
-
// [PARENT_ID,
|
|
251
|
-
|
|
256
|
+
// [PARENT_ID, POSITIONAL_ARG_1, POSITIONAL_ARG_2, ..., {KEY_VALUE_ARGS}]
|
|
257
|
+
let kwargs;
|
|
258
|
+
const [parentId, ...args] = <any>nodeTuple;
|
|
259
|
+
if (args.length === _positionalCount) {
|
|
260
|
+
kwargs = {};
|
|
261
|
+
} else if (args.length === _positionalCount + 1) {
|
|
262
|
+
kwargs = args.pop();
|
|
263
|
+
if (typeof kwargs !== "object") {
|
|
264
|
+
throw new Error(
|
|
265
|
+
`unflattenSource: Expected dict as last tuple element: ${nodeTuple}`
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
} else {
|
|
269
|
+
throw new Error(`unflattenSource: unexpected tuple length: ${nodeTuple}`);
|
|
270
|
+
}
|
|
252
271
|
|
|
253
272
|
// Free up some memory as we go
|
|
254
273
|
nodeTuple[1] = null;
|
|
255
274
|
if (nodeTuple[2] != null) {
|
|
256
275
|
nodeTuple[2] = null;
|
|
257
276
|
}
|
|
258
|
-
// console.log("flatten", parentId, args, kwargs)
|
|
259
|
-
|
|
260
277
|
// We keep `kwargs` as our new node definition. Then we add all positional
|
|
261
278
|
// values to this object:
|
|
262
279
|
args.forEach((val: string, positionalIdx: number) => {
|
|
263
280
|
kwargs[positionalShort[positionalIdx]] = val;
|
|
264
281
|
});
|
|
282
|
+
args.length = 0;
|
|
265
283
|
|
|
266
284
|
// Find the parent node. `null` means 'toplevel'. PARENT_ID may be the numeric
|
|
267
285
|
// index of the source.children list. If PARENT_ID is a string, we search
|
package/src/debounce.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
|
+
* Wunderbaum - debounce.ts
|
|
3
|
+
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
4
|
+
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
|
+
*/
|
|
6
|
+
/*
|
|
2
7
|
* debounce & throttle, taken from https://github.com/lodash/lodash v4.17.21
|
|
3
8
|
* MIT License: https://raw.githubusercontent.com/lodash/lodash/4.17.21-npm/LICENSE
|
|
4
9
|
* Modified for TypeScript type annotations.
|
package/src/deferred.ts
CHANGED
package/src/drag_observer.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Wunderbaum - types
|
|
3
|
-
* Copyright (c) 2021-
|
|
3
|
+
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
4
4
|
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -22,7 +22,7 @@ export type SortOrderType = "asc" | "desc" | undefined;
|
|
|
22
22
|
* or a boolean value that indicates if the default icon should be used or hidden.
|
|
23
23
|
*/
|
|
24
24
|
export type IconOption = boolean | string;
|
|
25
|
-
/** Show/hide tooltip or display a string. */
|
|
25
|
+
/** Show/hide default tooltip or display a string. */
|
|
26
26
|
export type TooltipOption = boolean | string;
|
|
27
27
|
|
|
28
28
|
/*
|
|
@@ -93,7 +93,10 @@ export type NodeToDictCallback = (
|
|
|
93
93
|
dict: WbNodeData,
|
|
94
94
|
node: WunderbaumNode
|
|
95
95
|
) => NodeVisitResponse;
|
|
96
|
-
/**
|
|
96
|
+
/**
|
|
97
|
+
* A callback that receives a node instance and may returnsa `false` to prevent
|
|
98
|
+
* (de)selection.
|
|
99
|
+
*/
|
|
97
100
|
export type NodeSelectCallback = (node: WunderbaumNode) => boolean | void;
|
|
98
101
|
|
|
99
102
|
/**
|
|
@@ -113,23 +116,56 @@ export type DynamicTooltipOption = TooltipOption | BoolOrStringOptionResolver;
|
|
|
113
116
|
// type WithWildcards<T> = T & { [key: string]: unknown };
|
|
114
117
|
/** A plain object (dictionary) that represents a node instance. */
|
|
115
118
|
export interface WbNodeData {
|
|
119
|
+
/** Defines if the `selected` state is displayed as checkbox, radio button,
|
|
120
|
+
* or hidden.
|
|
121
|
+
* Defaults to {@link WunderbaumOptions.checkbox}.
|
|
122
|
+
*/
|
|
116
123
|
checkbox?: CheckboxOption;
|
|
124
|
+
/** Optional list of child nodes.
|
|
125
|
+
* If `children` is an empty array, the node is considered a leaf.
|
|
126
|
+
* If `lazy` is true and `children is undefined or null, the node, is
|
|
127
|
+
* considered unloaded. Otherwise, the node is considered a leaf.
|
|
128
|
+
*/
|
|
117
129
|
children?: Array<WbNodeData>;
|
|
130
|
+
/** Additional classes that are added to `<div class='wb-row'>`. */
|
|
118
131
|
classes?: string;
|
|
132
|
+
/** Only show title in a single, merged column. */
|
|
119
133
|
colspan?: boolean;
|
|
134
|
+
/** Expand this node. */
|
|
120
135
|
expanded?: boolean;
|
|
136
|
+
/** Defaults to standard icons (doc, folder, folderOpen, ...)
|
|
137
|
+
* from {@link WunderbaumOptions.iconMap}.
|
|
138
|
+
* Can be overridden by {@link WunderbaumOptions.icon}.
|
|
139
|
+
*/
|
|
121
140
|
icon?: IconOption;
|
|
141
|
+
/** Tooltip for the node icon only. Defaults to {@link WunderbaumOptions.iconTooltip}. */
|
|
122
142
|
iconTooltip?: TooltipOption;
|
|
143
|
+
/** The node's key. Must be unique for the whole tree. Defaults to a sequence number. */
|
|
123
144
|
key?: string;
|
|
145
|
+
/** If true (and children are undefined or null), the node is considered lazy
|
|
146
|
+
* and {@link WunderbaumOptions.lazyLoad} is called when expanded.
|
|
147
|
+
*/
|
|
124
148
|
lazy?: boolean;
|
|
125
149
|
/** Make child nodes single-select radio buttons. */
|
|
126
150
|
radiogroup?: boolean;
|
|
151
|
+
/** Node's reference key. Unlike {@link WunderbaumNode.key}, this value
|
|
152
|
+
* may be non-unique. Nodes within the tree that share the same refKey are considered
|
|
153
|
+
* clones.
|
|
154
|
+
*/
|
|
127
155
|
refKey?: string;
|
|
156
|
+
/** The node's selection status, typically displayed as a checkbox. */
|
|
128
157
|
selected?: boolean;
|
|
158
|
+
/** The node's status, typically displayed as merged single row.
|
|
159
|
+
* @see {@link Wunderbaum.setStatus}
|
|
160
|
+
*/
|
|
129
161
|
statusNodeType?: NodeStatusType;
|
|
162
|
+
/** The node's title. Will be html escaped to prevent XSS. */
|
|
130
163
|
title: string;
|
|
164
|
+
/** Pass true to set node tooltip to the node's title. Defaults to {@link WunderbaumOptions.tooltip}. */
|
|
131
165
|
tooltip?: TooltipOption;
|
|
166
|
+
/** Inherit shared settings from the matching entry in {@link WunderbaumOptions.types}. */
|
|
132
167
|
type?: string;
|
|
168
|
+
/** Set to `true` to prevent selection. Defaults to {@link WunderbaumOptions.unselectable}. */
|
|
133
169
|
unselectable?: boolean;
|
|
134
170
|
/** @internal */
|
|
135
171
|
_treeId?: string;
|
|
@@ -531,7 +567,7 @@ export enum ChangeType {
|
|
|
531
567
|
scroll = "scroll",
|
|
532
568
|
}
|
|
533
569
|
|
|
534
|
-
|
|
570
|
+
/** @internal */
|
|
535
571
|
export enum RenderFlag {
|
|
536
572
|
clearMarkup = "clearMarkup",
|
|
537
573
|
header = "header",
|
|
@@ -561,10 +597,14 @@ export enum NodeRegion {
|
|
|
561
597
|
|
|
562
598
|
/** Initial navigation mode and possible transition. */
|
|
563
599
|
export enum NavModeEnum {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
600
|
+
/** Start with row mode, but allow cell-nav mode */
|
|
601
|
+
startRow = "startRow",
|
|
602
|
+
/** Cell-nav mode only */
|
|
603
|
+
cell = "cell",
|
|
604
|
+
/** Start in cell-nav mode, but allow row mode */
|
|
605
|
+
startCell = "startCell",
|
|
606
|
+
/** Row mode only */
|
|
607
|
+
row = "row",
|
|
568
608
|
}
|
|
569
609
|
|
|
570
610
|
/* -----------------------------------------------------------------------------
|
|
@@ -594,12 +634,34 @@ export interface ApplyCommandOptions {
|
|
|
594
634
|
|
|
595
635
|
/** Possible values for {@link Wunderbaum.expandAll} and {@link WunderbaumNode.expandAll}. */
|
|
596
636
|
export interface ExpandAllOptions {
|
|
597
|
-
/** Restrict expand level @default 99 */
|
|
598
|
-
depth?: number;
|
|
599
637
|
/** Expand and load lazy nodes @default false */
|
|
600
638
|
loadLazy?: boolean;
|
|
601
|
-
/**
|
|
639
|
+
/** Unload lazily loaded children if any (if collapsing). @default false */
|
|
640
|
+
resetLazy?: boolean;
|
|
641
|
+
/** Ignore tree's `minExpandLevel` option @default false */
|
|
602
642
|
force?: boolean;
|
|
643
|
+
/** Restrict expand level.
|
|
644
|
+
* Pass 0 to make only toplevel nodes visible, 1 to expand one level deeper, etc.
|
|
645
|
+
* @default unset (unlimited)
|
|
646
|
+
*/
|
|
647
|
+
depth?: number;
|
|
648
|
+
/**
|
|
649
|
+
* Also collapse child nodes beyond the `depth` level.
|
|
650
|
+
* Otherwise only the `depth` level is collapsed and the expand state of the
|
|
651
|
+
* descendants is retained.
|
|
652
|
+
* Only in combination with collapse and `depth`.
|
|
653
|
+
* Expanding with `deep` option is not supported as recursion depth implied by
|
|
654
|
+
* the `depth` option. However a `deep` option will be considered if
|
|
655
|
+
* `collapseOthers` is set.
|
|
656
|
+
* @default false
|
|
657
|
+
*/
|
|
658
|
+
deep?: boolean;
|
|
659
|
+
/**
|
|
660
|
+
* Expand up to level=depth and collapse all other branches.
|
|
661
|
+
* Only in combination with `flag == true`, `depth > 0`.
|
|
662
|
+
* @default false
|
|
663
|
+
*/
|
|
664
|
+
collapseOthers?: boolean;
|
|
603
665
|
/** Keep active node visible @default true */
|
|
604
666
|
keepActiveNodeVisible?: boolean;
|
|
605
667
|
}
|
|
@@ -723,7 +785,7 @@ export interface SetColumnOptions {
|
|
|
723
785
|
|
|
724
786
|
/** Possible values for {@link WunderbaumNode.setExpanded} `options` argument. */
|
|
725
787
|
export interface SetExpandedOptions {
|
|
726
|
-
/** Ignore {@link WunderbaumOptions.minExpandLevel
|
|
788
|
+
/** Ignore {@link WunderbaumOptions}.minExpandLevel. @default false */
|
|
727
789
|
force?: boolean;
|
|
728
790
|
/** Immediately update viewport (async otherwise). @default false */
|
|
729
791
|
immediate?: boolean;
|
|
@@ -731,6 +793,8 @@ export interface SetExpandedOptions {
|
|
|
731
793
|
noAnimation?: boolean;
|
|
732
794
|
/** Do not send events. @default false */
|
|
733
795
|
noEvents?: boolean;
|
|
796
|
+
/** Unload lazily loaded children if any (if collapsing). @default false */
|
|
797
|
+
resetLazy?: boolean;
|
|
734
798
|
/** Scroll up to bring expanded nodes into viewport. @default false */
|
|
735
799
|
scrollIntoView?: boolean;
|
|
736
800
|
}
|
|
@@ -941,7 +1005,6 @@ export type InsertNodeType =
|
|
|
941
1005
|
| "after"
|
|
942
1006
|
| "prependChild"
|
|
943
1007
|
| "appendChild";
|
|
944
|
-
// export type DndModeType = "before" | "after" | "over";
|
|
945
1008
|
|
|
946
1009
|
export type DropEffectType = "none" | "copy" | "link" | "move";
|
|
947
1010
|
export type DropEffectAllowedType =
|
package/src/util.ts
CHANGED
package/src/wb_ext_dnd.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Wunderbaum - ext-dnd
|
|
3
|
-
* Copyright (c) 2021-
|
|
3
|
+
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
4
4
|
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
import * as util from "./util";
|
|
@@ -143,8 +143,8 @@ export class DndExtension extends WunderbaumExtension<DndOptionsType> {
|
|
|
143
143
|
return dy < 0.25 * rowHeight
|
|
144
144
|
? "before"
|
|
145
145
|
: dy > 0.75 * rowHeight
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
? "after"
|
|
147
|
+
: "over";
|
|
148
148
|
} else if (allowed.size === 1 && allowed.has("over")) {
|
|
149
149
|
return "over";
|
|
150
150
|
} else {
|
package/src/wb_ext_edit.ts
CHANGED
package/src/wb_ext_filter.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Wunderbaum - ext-filter
|
|
3
|
-
* Copyright (c) 2021-
|
|
3
|
+
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
4
4
|
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -177,7 +177,7 @@ export class FilterExtension extends WunderbaumExtension<FilterOptionsType> {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
tree.filterMode = opts.mode;
|
|
180
|
-
// eslint-disable-next-line prefer-rest-params
|
|
180
|
+
// eslint-disable-next-line prefer-rest-params
|
|
181
181
|
this.lastFilterArgs = arguments;
|
|
182
182
|
|
|
183
183
|
tree.element.classList.toggle("wb-ext-filter-hide", !!hideMode);
|
package/src/wb_ext_grid.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Wunderbaum - ext-grid
|
|
3
|
-
* Copyright (c) 2021-
|
|
3
|
+
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
4
4
|
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
import { Wunderbaum } from "./wunderbaum";
|
package/src/wb_ext_keynav.ts
CHANGED
package/src/wb_ext_logger.ts
CHANGED
package/src/wb_extension_base.ts
CHANGED
package/src/wb_node.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Wunderbaum - wunderbaum_node
|
|
3
|
-
* Copyright (c) 2021-
|
|
3
|
+
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
4
4
|
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -470,58 +470,78 @@ export class WunderbaumNode {
|
|
|
470
470
|
this.tree._callMethod("edit.startEditTitle", this);
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
-
/**
|
|
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
|
+
*/
|
|
474
481
|
async expandAll(flag: boolean = true, options?: ExpandAllOptions) {
|
|
475
482
|
const tree = this.tree;
|
|
476
|
-
const minExpandLevel = this.tree.options.minExpandLevel;
|
|
477
483
|
const {
|
|
478
|
-
|
|
479
|
-
|
|
484
|
+
collapseOthers,
|
|
485
|
+
deep,
|
|
486
|
+
depth,
|
|
480
487
|
force,
|
|
481
488
|
keepActiveNodeVisible = true,
|
|
489
|
+
loadLazy,
|
|
490
|
+
resetLazy,
|
|
482
491
|
} = options ?? {};
|
|
483
|
-
|
|
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);
|
|
484
495
|
const expandOpts = {
|
|
485
|
-
|
|
496
|
+
deep: deep,
|
|
486
497
|
force: force,
|
|
487
498
|
loadLazy: loadLazy,
|
|
499
|
+
resetLazy: resetLazy,
|
|
500
|
+
scrollIntoView: false, // don't scroll every node while iterating
|
|
488
501
|
};
|
|
489
502
|
|
|
490
|
-
|
|
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
|
+
|
|
491
510
|
// Expand all direct children in parallel:
|
|
492
|
-
async function _iter(n: WunderbaumNode, level: number
|
|
493
|
-
// n.logInfo(` _iter(
|
|
494
|
-
if (level === 0) {
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
// if (!flag && minExpandLevel && !force && n.getLevel() <= minExpandLevel) {
|
|
498
|
-
// return; // Do not collapse until minExpandLevel
|
|
499
|
-
// }
|
|
500
|
-
const level_1 = level == null ? null : level - 1;
|
|
511
|
+
async function _iter(n: WunderbaumNode, level: number) {
|
|
512
|
+
// n.logInfo(` _iter(level=${level})`);
|
|
501
513
|
const promises: Promise<unknown>[] = [];
|
|
502
514
|
n.children?.forEach((cn) => {
|
|
503
515
|
if (flag) {
|
|
504
|
-
if (
|
|
516
|
+
if (
|
|
517
|
+
!cn.expanded &&
|
|
518
|
+
(minLevel == null || level < minLevel) &&
|
|
519
|
+
(cn.children || (loadLazy && cn.lazy))
|
|
520
|
+
) {
|
|
505
521
|
// Node is collapsed and may be expanded (i.e. has children or is lazy)
|
|
506
522
|
// Expanding may be async, so we store the promise.
|
|
507
523
|
// Also the recursion is delayed until expansion finished.
|
|
508
524
|
const p = cn.setExpanded(true, expandOpts);
|
|
509
525
|
promises.push(p);
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
526
|
+
if (depth == null) {
|
|
527
|
+
p.then(async () => {
|
|
528
|
+
await _iter(cn, level + 1);
|
|
529
|
+
});
|
|
530
|
+
}
|
|
513
531
|
} else {
|
|
514
532
|
// We don't expand the node, but still visit descendants.
|
|
515
533
|
// There we may find lazy nodes, so we
|
|
516
|
-
promises.push(_iter(cn,
|
|
534
|
+
promises.push(_iter(cn, level + 1));
|
|
517
535
|
}
|
|
518
536
|
} else {
|
|
519
537
|
// Collapsing is always synchronous, so no promises required
|
|
520
|
-
|
|
521
|
-
|
|
538
|
+
// Do not collapse until minExpandLevel
|
|
539
|
+
if (minLevel == null || level >= minLevel) {
|
|
522
540
|
cn.setExpanded(false, expandOpts);
|
|
523
541
|
}
|
|
524
|
-
|
|
542
|
+
if ((minLevel != null && level < minLevel) || deep) {
|
|
543
|
+
_iter(cn, level + 1); // recursion, even if cn was already collapsed
|
|
544
|
+
}
|
|
525
545
|
}
|
|
526
546
|
});
|
|
527
547
|
return new Promise((resolve) => {
|
|
@@ -531,10 +551,20 @@ export class WunderbaumNode {
|
|
|
531
551
|
});
|
|
532
552
|
}
|
|
533
553
|
|
|
534
|
-
const tag = tree.logTime(`${this}.expandAll(${flag})`);
|
|
554
|
+
const tag = tree.logTime(`${this}.expandAll(${flag}, depth=${depth})`);
|
|
535
555
|
try {
|
|
536
556
|
tree.enableUpdate(false);
|
|
537
|
-
|
|
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
|
+
}
|
|
538
568
|
} finally {
|
|
539
569
|
tree.enableUpdate(true);
|
|
540
570
|
tree.logTimeEnd(tag);
|
|
@@ -2199,7 +2229,7 @@ export class WunderbaumNode {
|
|
|
2199
2229
|
const colIdx = options?.colIdx; // Default: null
|
|
2200
2230
|
const edit = options?.edit; // Default: false
|
|
2201
2231
|
|
|
2202
|
-
util.assert(!colIdx || tree.isCellNav(), "colIdx requires cellNav");
|
|
2232
|
+
// util.assert(!colIdx || tree.isCellNav(), "colIdx requires cellNav");
|
|
2203
2233
|
util.assert(!edit || colIdx != null, "edit requires colIdx");
|
|
2204
2234
|
|
|
2205
2235
|
if (!noEvents) {
|
|
@@ -2257,7 +2287,7 @@ export class WunderbaumNode {
|
|
|
2257
2287
|
* Expand or collapse this node.
|
|
2258
2288
|
*/
|
|
2259
2289
|
async setExpanded(flag: boolean = true, options?: SetExpandedOptions) {
|
|
2260
|
-
const { force, scrollIntoView, immediate } = options ?? {};
|
|
2290
|
+
const { force, scrollIntoView, immediate, resetLazy } = options ?? {};
|
|
2261
2291
|
const sendEvents = !options?.noEvents; // Default: send events
|
|
2262
2292
|
if (
|
|
2263
2293
|
!flag &&
|
|
@@ -2284,6 +2314,8 @@ export class WunderbaumNode {
|
|
|
2284
2314
|
}
|
|
2285
2315
|
if (flag && this.lazy && this.children == null) {
|
|
2286
2316
|
await this.loadLazy();
|
|
2317
|
+
} else if (!flag && resetLazy && this.lazy && this.children) {
|
|
2318
|
+
this.resetLazy();
|
|
2287
2319
|
}
|
|
2288
2320
|
this.expanded = flag;
|
|
2289
2321
|
const updateOpts = { immediate: immediate };
|
|
@@ -2405,7 +2437,8 @@ export class WunderbaumNode {
|
|
|
2405
2437
|
case undefined:
|
|
2406
2438
|
changed = this.selected || !this._partsel;
|
|
2407
2439
|
this.selected = false;
|
|
2408
|
-
|
|
2440
|
+
// #110: end nodess cannot have a `_partsel` flag
|
|
2441
|
+
this._partsel = this.hasChildren() ? true : false;
|
|
2409
2442
|
break;
|
|
2410
2443
|
default:
|
|
2411
2444
|
util.error(`Invalid state: ${state}`);
|
package/src/wb_options.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Wunderbaum - utils
|
|
3
|
-
* Copyright (c) 2021-
|
|
3
|
+
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
4
4
|
* @VERSION, @DATE (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -113,6 +113,14 @@ export interface WunderbaumOptions {
|
|
|
113
113
|
skeleton?: boolean;
|
|
114
114
|
/**
|
|
115
115
|
* Translation map for some system messages.
|
|
116
|
+
* Default:
|
|
117
|
+
* ```js
|
|
118
|
+
* strings: {
|
|
119
|
+
* loading: "Loading...",
|
|
120
|
+
* loadError: "Error",
|
|
121
|
+
* noData: "No data",
|
|
122
|
+
* }
|
|
123
|
+
* ```
|
|
116
124
|
*/
|
|
117
125
|
strings?: any; //[key: string] string;
|
|
118
126
|
/**
|