wunderbaum 0.12.1 → 0.13.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/dist/wunderbaum.css +9 -0
- package/dist/wunderbaum.css.map +1 -1
- package/dist/wunderbaum.d.ts +147 -44
- package/dist/wunderbaum.esm.js +353 -187
- package/dist/wunderbaum.esm.min.js +26 -26
- package/dist/wunderbaum.esm.min.js.map +1 -1
- package/dist/wunderbaum.umd.js +353 -187
- package/dist/wunderbaum.umd.min.js +29 -29
- package/dist/wunderbaum.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/common.ts +27 -3
- package/src/types.ts +115 -12
- package/src/util.ts +0 -13
- package/src/wb_ext_edit.ts +1 -1
- package/src/wb_ext_filter.ts +117 -42
- package/src/wb_extension_base.ts +3 -2
- package/src/wb_node.ts +24 -96
- package/src/wb_options.ts +6 -12
- package/src/wunderbaum.scss +9 -1
- package/src/wunderbaum.ts +264 -40
package/dist/wunderbaum.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Wunderbaum - debounce.ts
|
|
3
3
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
4
|
-
* v0.
|
|
4
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
5
5
|
*/
|
|
6
6
|
/*
|
|
7
7
|
* debounce & throttle, taken from https://github.com/lodash/lodash v4.17.21
|
|
@@ -293,7 +293,7 @@ function throttle(func, wait = 0, options = {}) {
|
|
|
293
293
|
/*!
|
|
294
294
|
* Wunderbaum - util
|
|
295
295
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
296
|
-
* v0.
|
|
296
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
297
297
|
*/
|
|
298
298
|
/** @module util */
|
|
299
299
|
/** Readable names for `MouseEvent.button` */
|
|
@@ -676,18 +676,6 @@ function elemFromSelector(obj) {
|
|
|
676
676
|
}
|
|
677
677
|
return obj;
|
|
678
678
|
}
|
|
679
|
-
// /** Return a EventTarget from selector or cast an existing element. */
|
|
680
|
-
// export function eventTargetFromSelector(
|
|
681
|
-
// obj: string | EventTarget
|
|
682
|
-
// ): EventTarget | null {
|
|
683
|
-
// if (!obj) {
|
|
684
|
-
// return null;
|
|
685
|
-
// }
|
|
686
|
-
// if (typeof obj === "string") {
|
|
687
|
-
// return document.querySelector(obj) as EventTarget;
|
|
688
|
-
// }
|
|
689
|
-
// return obj as EventTarget;
|
|
690
|
-
// }
|
|
691
679
|
/**
|
|
692
680
|
* Return a canonical descriptive string for a keyboard or mouse event.
|
|
693
681
|
*
|
|
@@ -1147,7 +1135,7 @@ var util = /*#__PURE__*/Object.freeze({
|
|
|
1147
1135
|
/*!
|
|
1148
1136
|
* Wunderbaum - types
|
|
1149
1137
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
1150
|
-
* v0.
|
|
1138
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1151
1139
|
*/
|
|
1152
1140
|
/**
|
|
1153
1141
|
* Possible values for {@link WunderbaumNode.update} and {@link Wunderbaum.update}.
|
|
@@ -1215,7 +1203,7 @@ var NavModeEnum;
|
|
|
1215
1203
|
/*!
|
|
1216
1204
|
* Wunderbaum - wb_extension_base
|
|
1217
1205
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
1218
|
-
* v0.
|
|
1206
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1219
1207
|
*/
|
|
1220
1208
|
class WunderbaumExtension {
|
|
1221
1209
|
constructor(tree, id, defaults) {
|
|
@@ -1274,7 +1262,7 @@ class WunderbaumExtension {
|
|
|
1274
1262
|
/*!
|
|
1275
1263
|
* Wunderbaum - ext-filter
|
|
1276
1264
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
1277
|
-
* v0.
|
|
1265
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1278
1266
|
*/
|
|
1279
1267
|
const START_MARKER = "\uFFF7";
|
|
1280
1268
|
const END_MARKER = "\uFFF8";
|
|
@@ -1286,7 +1274,7 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1286
1274
|
autoApply: true, // Re-apply last filter if lazy data is loaded
|
|
1287
1275
|
autoExpand: false, // Expand all branches that contain matches while filtered
|
|
1288
1276
|
matchBranch: false, // Whether to implicitly match all children of matched nodes
|
|
1289
|
-
|
|
1277
|
+
connect: null, // Element or selector of an input control for filter query strings
|
|
1290
1278
|
fuzzy: false, // Match single characters in order, e.g. 'fb' will match 'FooBar'
|
|
1291
1279
|
hideExpanders: false, // Hide expanders if all child nodes are hidden by filter
|
|
1292
1280
|
highlight: true, // Highlight matches by wrapping inside <mark> tags
|
|
@@ -1294,36 +1282,117 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1294
1282
|
mode: "dim", // Grayout unmatched nodes (pass "hide" to remove unmatched node instead)
|
|
1295
1283
|
noData: true, // Display a 'no data' status node if result is empty
|
|
1296
1284
|
});
|
|
1285
|
+
this.queryInput = null;
|
|
1286
|
+
this.prevButton = null;
|
|
1287
|
+
this.nextButton = null;
|
|
1288
|
+
this.modeButton = null;
|
|
1289
|
+
this.matchInfoElem = null;
|
|
1297
1290
|
this.lastFilterArgs = null;
|
|
1298
1291
|
}
|
|
1299
1292
|
init() {
|
|
1300
1293
|
super.init();
|
|
1301
|
-
const
|
|
1302
|
-
if (
|
|
1303
|
-
this.
|
|
1304
|
-
assert(this.queryInput, `Invalid 'filter.connectInput' option: ${connectInput}.`);
|
|
1305
|
-
onEvent(this.queryInput, "input", debounce((e) => {
|
|
1306
|
-
// this.tree.log("query", e);
|
|
1307
|
-
this.filterNodes(this.queryInput.value.trim(), {});
|
|
1308
|
-
}, 700));
|
|
1294
|
+
const connect = this.getPluginOption("connect");
|
|
1295
|
+
if (connect) {
|
|
1296
|
+
this._connectControls();
|
|
1309
1297
|
}
|
|
1310
1298
|
}
|
|
1311
1299
|
setPluginOption(name, value) {
|
|
1312
|
-
// alert("filter opt=" + name + ", " + value)
|
|
1313
1300
|
super.setPluginOption(name, value);
|
|
1314
1301
|
switch (name) {
|
|
1315
1302
|
case "mode":
|
|
1316
|
-
this.tree.filterMode =
|
|
1303
|
+
this.tree.filterMode =
|
|
1304
|
+
value === "hide" ? "hide" : value === "mark" ? "mark" : "dim";
|
|
1317
1305
|
this.tree.updateFilter();
|
|
1318
1306
|
break;
|
|
1319
1307
|
}
|
|
1320
1308
|
}
|
|
1309
|
+
_updatedConnectedControls() {
|
|
1310
|
+
var _a;
|
|
1311
|
+
const filterActive = this.tree.filterMode !== null;
|
|
1312
|
+
const activeNode = this.tree.getActiveNode();
|
|
1313
|
+
const matchCount = filterActive ? this.countMatches() : 0;
|
|
1314
|
+
const strings = this.treeOpts.strings;
|
|
1315
|
+
let matchIdx = "?";
|
|
1316
|
+
if (this.matchInfoElem) {
|
|
1317
|
+
if (filterActive) {
|
|
1318
|
+
let info;
|
|
1319
|
+
if (matchCount === 0) {
|
|
1320
|
+
info = strings.noMatch;
|
|
1321
|
+
}
|
|
1322
|
+
else if (activeNode && activeNode.match >= 1) {
|
|
1323
|
+
matchIdx = (_a = activeNode.match) !== null && _a !== void 0 ? _a : "?";
|
|
1324
|
+
info = strings.matchIndex;
|
|
1325
|
+
}
|
|
1326
|
+
else {
|
|
1327
|
+
info = strings.queryResult;
|
|
1328
|
+
}
|
|
1329
|
+
info = info
|
|
1330
|
+
.replace("${count}", this.tree.count().toLocaleString())
|
|
1331
|
+
.replace("${match}", "" + matchIdx)
|
|
1332
|
+
.replace("${matches}", matchCount.toLocaleString());
|
|
1333
|
+
this.matchInfoElem.textContent = info;
|
|
1334
|
+
}
|
|
1335
|
+
else {
|
|
1336
|
+
this.matchInfoElem.textContent = "";
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
if (this.nextButton instanceof HTMLButtonElement) {
|
|
1340
|
+
this.nextButton.disabled = !matchCount;
|
|
1341
|
+
}
|
|
1342
|
+
if (this.prevButton instanceof HTMLButtonElement) {
|
|
1343
|
+
this.prevButton.disabled = !matchCount;
|
|
1344
|
+
}
|
|
1345
|
+
if (this.modeButton) {
|
|
1346
|
+
this.modeButton.disabled = !filterActive;
|
|
1347
|
+
this.modeButton.classList.toggle("wb-filter-hide", this.tree.filterMode === "hide");
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
_connectControls() {
|
|
1351
|
+
const tree = this.tree;
|
|
1352
|
+
const connect = this.getPluginOption("connect");
|
|
1353
|
+
if (!connect) {
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
this.queryInput = elemFromSelector(connect.inputElem);
|
|
1357
|
+
if (!this.queryInput) {
|
|
1358
|
+
throw new Error(`Invalid 'filter.connect' option: ${connect.inputElem}.`);
|
|
1359
|
+
}
|
|
1360
|
+
this.prevButton = elemFromSelector(connect.prevButton);
|
|
1361
|
+
this.nextButton = elemFromSelector(connect.nextButton);
|
|
1362
|
+
this.modeButton = elemFromSelector(connect.modeButton);
|
|
1363
|
+
this.matchInfoElem = elemFromSelector(connect.matchInfoElem);
|
|
1364
|
+
if (this.prevButton) {
|
|
1365
|
+
onEvent(this.prevButton, "click", () => {
|
|
1366
|
+
tree.findRelatedNode(tree.getActiveNode() || tree.getFirstChild(), "prevMatch");
|
|
1367
|
+
this._updatedConnectedControls();
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
if (this.nextButton) {
|
|
1371
|
+
onEvent(this.nextButton, "click", () => {
|
|
1372
|
+
tree.findRelatedNode(tree.getActiveNode() || tree.getFirstChild(), "nextMatch");
|
|
1373
|
+
this._updatedConnectedControls();
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
if (this.modeButton) {
|
|
1377
|
+
onEvent(this.modeButton, "click", (e) => {
|
|
1378
|
+
if (!this.tree.filterMode) {
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
this.setPluginOption("mode", tree.filterMode === "dim" ? "hide" : "dim");
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1384
|
+
onEvent(this.queryInput, "input", debounce((e) => {
|
|
1385
|
+
this.filterNodes(this.queryInput.value.trim(), {});
|
|
1386
|
+
}, 700));
|
|
1387
|
+
this._updatedConnectedControls();
|
|
1388
|
+
}
|
|
1321
1389
|
_applyFilterNoUpdate(filter, _opts) {
|
|
1322
1390
|
return this.tree.runWithDeferredUpdate(() => {
|
|
1323
1391
|
return this._applyFilterImpl(filter, _opts);
|
|
1324
1392
|
});
|
|
1325
1393
|
}
|
|
1326
1394
|
_applyFilterImpl(filter, _opts) {
|
|
1395
|
+
var _a;
|
|
1327
1396
|
let //temp,
|
|
1328
1397
|
count = 0;
|
|
1329
1398
|
const start = Date.now();
|
|
@@ -1405,11 +1474,11 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1405
1474
|
return !!res;
|
|
1406
1475
|
};
|
|
1407
1476
|
}
|
|
1408
|
-
tree.filterMode = opts.mode;
|
|
1477
|
+
tree.filterMode = (_a = opts.mode) !== null && _a !== void 0 ? _a : "dim";
|
|
1409
1478
|
// eslint-disable-next-line prefer-rest-params
|
|
1410
1479
|
this.lastFilterArgs = arguments;
|
|
1411
1480
|
tree.element.classList.toggle("wb-ext-filter-hide", !!hideMode);
|
|
1412
|
-
tree.element.classList.toggle("wb-ext-filter-dim",
|
|
1481
|
+
tree.element.classList.toggle("wb-ext-filter-dim", opts.mode === "dim");
|
|
1413
1482
|
tree.element.classList.toggle("wb-ext-filter-hide-expanders", !!opts.hideExpanders);
|
|
1414
1483
|
// Reset current filter
|
|
1415
1484
|
tree.root.subMatchCount = 0;
|
|
@@ -1418,10 +1487,6 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1418
1487
|
delete node.titleWithHighlight;
|
|
1419
1488
|
node.subMatchCount = 0;
|
|
1420
1489
|
});
|
|
1421
|
-
// statusNode = tree.root.findDirectChild(KEY_NODATA);
|
|
1422
|
-
// if (statusNode) {
|
|
1423
|
-
// statusNode.remove();
|
|
1424
|
-
// }
|
|
1425
1490
|
tree.setStatus(NodeStatusType.ok);
|
|
1426
1491
|
// Adjust node.hide, .match, and .subMatchCount properties
|
|
1427
1492
|
treeOpts.autoCollapse = false; // #528
|
|
@@ -1432,7 +1497,7 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1432
1497
|
let res = filter(node);
|
|
1433
1498
|
if (res === "skip") {
|
|
1434
1499
|
node.visit(function (c) {
|
|
1435
|
-
c.match =
|
|
1500
|
+
c.match = undefined;
|
|
1436
1501
|
}, true);
|
|
1437
1502
|
return "skip";
|
|
1438
1503
|
}
|
|
@@ -1443,7 +1508,7 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1443
1508
|
}
|
|
1444
1509
|
if (res) {
|
|
1445
1510
|
count++;
|
|
1446
|
-
node.match =
|
|
1511
|
+
node.match = count;
|
|
1447
1512
|
node.visitParents((p) => {
|
|
1448
1513
|
if (p !== node) {
|
|
1449
1514
|
p.subMatchCount += 1;
|
|
@@ -1470,6 +1535,7 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1470
1535
|
}
|
|
1471
1536
|
// Redraw whole tree
|
|
1472
1537
|
tree.logDebug(`Filter '${filter}' found ${count} nodes in ${Date.now() - start} ms.`);
|
|
1538
|
+
this._updatedConnectedControls();
|
|
1473
1539
|
return count;
|
|
1474
1540
|
}
|
|
1475
1541
|
/**
|
|
@@ -1514,34 +1580,22 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1514
1580
|
else {
|
|
1515
1581
|
tree.logWarn("updateFilter(): no filter active.");
|
|
1516
1582
|
}
|
|
1583
|
+
this._updatedConnectedControls();
|
|
1517
1584
|
}
|
|
1518
1585
|
/**
|
|
1519
1586
|
* [ext-filter] Reset the filter.
|
|
1520
1587
|
*/
|
|
1521
1588
|
clearFilter() {
|
|
1522
1589
|
const tree = this.tree;
|
|
1523
|
-
// statusNode = tree.root.findDirectChild(KEY_NODATA),
|
|
1524
|
-
// escapeTitles = tree.options.escapeTitles;
|
|
1525
1590
|
tree.enableUpdate(false);
|
|
1526
|
-
// if (statusNode) {
|
|
1527
|
-
// statusNode.remove();
|
|
1528
|
-
// }
|
|
1529
1591
|
tree.setStatus(NodeStatusType.ok);
|
|
1530
1592
|
// we also counted root node's subMatchCount
|
|
1531
1593
|
delete tree.root.match;
|
|
1532
1594
|
delete tree.root.subMatchCount;
|
|
1533
1595
|
tree.visit((node) => {
|
|
1534
|
-
// if (node.match && node._rowElem) {
|
|
1535
|
-
// let titleElem = node._rowElem.querySelector("span.wb-title")!;
|
|
1536
|
-
// node._callEvent("enhanceTitle", { titleElem: titleElem });
|
|
1537
|
-
// }
|
|
1538
1596
|
delete node.match;
|
|
1539
1597
|
delete node.subMatchCount;
|
|
1540
1598
|
delete node.titleWithHighlight;
|
|
1541
|
-
// if (node.subMatchBadge) {
|
|
1542
|
-
// node.subMatchBadge.remove();
|
|
1543
|
-
// delete node.subMatchBadge;
|
|
1544
|
-
// }
|
|
1545
1599
|
if (node._filterAutoExpanded && node.expanded) {
|
|
1546
1600
|
node.setExpanded(false, {
|
|
1547
1601
|
noAnimation: true,
|
|
@@ -1555,7 +1609,7 @@ class FilterExtension extends WunderbaumExtension {
|
|
|
1555
1609
|
tree.element.classList.remove(
|
|
1556
1610
|
// "wb-ext-filter",
|
|
1557
1611
|
"wb-ext-filter-dim", "wb-ext-filter-hide");
|
|
1558
|
-
|
|
1612
|
+
this._updatedConnectedControls();
|
|
1559
1613
|
tree.enableUpdate(true);
|
|
1560
1614
|
}
|
|
1561
1615
|
}
|
|
@@ -1599,7 +1653,7 @@ function _markFuzzyMatchedChars(text, matches, escapeTitles = true) {
|
|
|
1599
1653
|
/*!
|
|
1600
1654
|
* Wunderbaum - ext-keynav
|
|
1601
1655
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
1602
|
-
* v0.
|
|
1656
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1603
1657
|
*/
|
|
1604
1658
|
const QUICKSEARCH_DELAY = 500;
|
|
1605
1659
|
class KeynavExtension extends WunderbaumExtension {
|
|
@@ -1963,7 +2017,7 @@ class KeynavExtension extends WunderbaumExtension {
|
|
|
1963
2017
|
/*!
|
|
1964
2018
|
* Wunderbaum - ext-logger
|
|
1965
2019
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
1966
|
-
* v0.
|
|
2020
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1967
2021
|
*/
|
|
1968
2022
|
class LoggerExtension extends WunderbaumExtension {
|
|
1969
2023
|
constructor(tree) {
|
|
@@ -2005,7 +2059,7 @@ class LoggerExtension extends WunderbaumExtension {
|
|
|
2005
2059
|
/*!
|
|
2006
2060
|
* Wunderbaum - ext-dnd
|
|
2007
2061
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
2008
|
-
* v0.
|
|
2062
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2009
2063
|
*/
|
|
2010
2064
|
const nodeMimeType = "application/x-wunderbaum-node";
|
|
2011
2065
|
class DndExtension extends WunderbaumExtension {
|
|
@@ -2455,7 +2509,7 @@ class DndExtension extends WunderbaumExtension {
|
|
|
2455
2509
|
/*!
|
|
2456
2510
|
* Wunderbaum - drag_observer
|
|
2457
2511
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
2458
|
-
* v0.
|
|
2512
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2459
2513
|
*/
|
|
2460
2514
|
/**
|
|
2461
2515
|
* Convert mouse- and touch events to 'dragstart', 'drag', and 'dragstop'.
|
|
@@ -2604,7 +2658,7 @@ class DragObserver {
|
|
|
2604
2658
|
/*!
|
|
2605
2659
|
* Wunderbaum - common
|
|
2606
2660
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
2607
|
-
* v0.
|
|
2661
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2608
2662
|
*/
|
|
2609
2663
|
const DEFAULT_DEBUGLEVEL = 3; // Replaced by rollup script
|
|
2610
2664
|
/**
|
|
@@ -2717,29 +2771,20 @@ const RESERVED_TREE_SOURCE_KEYS = new Set([
|
|
|
2717
2771
|
// "Escape",
|
|
2718
2772
|
// ]);
|
|
2719
2773
|
/** Map `KeyEvent.key` to navigation action. */
|
|
2720
|
-
const
|
|
2721
|
-
" ": "toggleSelect",
|
|
2722
|
-
"+": "expand",
|
|
2723
|
-
Add: "expand",
|
|
2774
|
+
const KEY_TO_NAVIGATION_MAP = {
|
|
2724
2775
|
ArrowDown: "down",
|
|
2725
2776
|
ArrowLeft: "left",
|
|
2726
2777
|
ArrowRight: "right",
|
|
2727
2778
|
ArrowUp: "up",
|
|
2728
2779
|
Backspace: "parent",
|
|
2729
|
-
"/": "collapseAll",
|
|
2730
|
-
Divide: "collapseAll",
|
|
2731
2780
|
End: "lastCol",
|
|
2732
2781
|
Home: "firstCol",
|
|
2733
2782
|
"Control+End": "last",
|
|
2734
2783
|
"Control+Home": "first",
|
|
2735
2784
|
"Meta+ArrowDown": "last", // macOs
|
|
2736
2785
|
"Meta+ArrowUp": "first", // macOs
|
|
2737
|
-
"*": "expandAll",
|
|
2738
|
-
Multiply: "expandAll",
|
|
2739
2786
|
PageDown: "pageDown",
|
|
2740
2787
|
PageUp: "pageUp",
|
|
2741
|
-
"-": "collapse",
|
|
2742
|
-
Subtract: "collapse",
|
|
2743
2788
|
};
|
|
2744
2789
|
/** Return a callback that returns true if the node title matches the string
|
|
2745
2790
|
* or regular expression.
|
|
@@ -2963,7 +3008,7 @@ function decompressSourceData(source) {
|
|
|
2963
3008
|
/*!
|
|
2964
3009
|
* Wunderbaum - ext-grid
|
|
2965
3010
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
2966
|
-
* v0.
|
|
3011
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2967
3012
|
*/
|
|
2968
3013
|
class GridExtension extends WunderbaumExtension {
|
|
2969
3014
|
constructor(tree) {
|
|
@@ -3054,7 +3099,7 @@ class GridExtension extends WunderbaumExtension {
|
|
|
3054
3099
|
/*!
|
|
3055
3100
|
* Wunderbaum - deferred
|
|
3056
3101
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
3057
|
-
* v0.
|
|
3102
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
3058
3103
|
*/
|
|
3059
3104
|
/**
|
|
3060
3105
|
* Implement a ES6 Promise, that exposes a resolve() and reject() method.
|
|
@@ -3107,7 +3152,7 @@ class Deferred {
|
|
|
3107
3152
|
/*!
|
|
3108
3153
|
* Wunderbaum - wunderbaum_node
|
|
3109
3154
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
3110
|
-
* v0.
|
|
3155
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
3111
3156
|
*/
|
|
3112
3157
|
/** WunderbaumNode properties that can be passed with source data.
|
|
3113
3158
|
* (Any other source properties will be stored as `node.data.PROP`.)
|
|
@@ -3889,7 +3934,7 @@ class WunderbaumNode {
|
|
|
3889
3934
|
isParentOf(other) {
|
|
3890
3935
|
return other && other.parent === this;
|
|
3891
3936
|
}
|
|
3892
|
-
/**
|
|
3937
|
+
/** Return true if this node is partially loaded. @experimental */
|
|
3893
3938
|
isPartload() {
|
|
3894
3939
|
return !!this._partload;
|
|
3895
3940
|
}
|
|
@@ -4347,10 +4392,11 @@ class WunderbaumNode {
|
|
|
4347
4392
|
* @param options
|
|
4348
4393
|
*/
|
|
4349
4394
|
async navigate(where, options) {
|
|
4395
|
+
var _a;
|
|
4350
4396
|
// Allow to pass 'ArrowLeft' instead of 'left'
|
|
4351
|
-
|
|
4397
|
+
const navType = ((_a = KEY_TO_NAVIGATION_MAP[where]) !== null && _a !== void 0 ? _a : where);
|
|
4352
4398
|
// Otherwise activate or focus the related node
|
|
4353
|
-
const node = this.findRelatedNode(
|
|
4399
|
+
const node = this.findRelatedNode(navType);
|
|
4354
4400
|
if (!node) {
|
|
4355
4401
|
this.logWarn(`Could not find related node '${where}'.`);
|
|
4356
4402
|
return Promise.resolve(this);
|
|
@@ -4447,86 +4493,17 @@ class WunderbaumNode {
|
|
|
4447
4493
|
renderColInfosById: renderColInfosById,
|
|
4448
4494
|
};
|
|
4449
4495
|
}
|
|
4450
|
-
_createIcon(
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
}
|
|
4456
|
-
else if (this._isLoading && showLoading) {
|
|
4457
|
-
// Status nodes, or nodes without expander (< minExpandLevel) should
|
|
4458
|
-
// display the 'loading' status with the i.wb-icon span
|
|
4459
|
-
icon = iconMap.loading;
|
|
4460
|
-
}
|
|
4461
|
-
if (icon === false) {
|
|
4462
|
-
return null; // explicitly disabled: don't try default icons
|
|
4463
|
-
}
|
|
4464
|
-
if (typeof icon === "string") ;
|
|
4465
|
-
else if (this.statusNodeType) {
|
|
4466
|
-
icon = iconMap[this.statusNodeType];
|
|
4467
|
-
}
|
|
4468
|
-
else if (this.expanded) {
|
|
4469
|
-
icon = iconMap.folderOpen;
|
|
4470
|
-
}
|
|
4471
|
-
else if (this.children) {
|
|
4472
|
-
icon = iconMap.folder;
|
|
4473
|
-
}
|
|
4474
|
-
else if (this.lazy) {
|
|
4475
|
-
icon = iconMap.folderLazy;
|
|
4476
|
-
}
|
|
4477
|
-
else {
|
|
4478
|
-
icon = iconMap.doc;
|
|
4479
|
-
}
|
|
4480
|
-
// this.log("_createIcon: " + icon);
|
|
4481
|
-
if (!icon) {
|
|
4482
|
-
iconSpan = document.createElement("i");
|
|
4483
|
-
iconSpan.className = "wb-icon";
|
|
4484
|
-
}
|
|
4485
|
-
else if (icon.indexOf("<") >= 0) {
|
|
4486
|
-
// HTML
|
|
4487
|
-
iconSpan = elemFromHtml(icon);
|
|
4488
|
-
}
|
|
4489
|
-
else if (TEST_IMG.test(icon)) {
|
|
4490
|
-
// Image URL
|
|
4491
|
-
iconSpan = elemFromHtml(`<i class="wb-icon" style="background-image: url('${icon}');">`);
|
|
4492
|
-
}
|
|
4493
|
-
else {
|
|
4494
|
-
// Class name
|
|
4495
|
-
iconSpan = document.createElement("i");
|
|
4496
|
-
iconSpan.className = "wb-icon " + icon;
|
|
4497
|
-
}
|
|
4498
|
-
if (replaceChild) {
|
|
4499
|
-
parentElem.replaceChild(iconSpan, replaceChild);
|
|
4500
|
-
}
|
|
4501
|
-
else {
|
|
4502
|
-
parentElem.appendChild(iconSpan);
|
|
4503
|
-
}
|
|
4504
|
-
// Event handler `tree.iconBadge` can return a badge text or HTMLSpanElement
|
|
4505
|
-
const cbRes = this._callEvent("iconBadge", { iconSpan: iconSpan });
|
|
4506
|
-
let badge = null;
|
|
4507
|
-
if (cbRes != null && cbRes !== false) {
|
|
4508
|
-
let classes = "";
|
|
4509
|
-
let tooltip = "";
|
|
4510
|
-
if (isPlainObject(cbRes)) {
|
|
4511
|
-
badge = "" + cbRes.badge;
|
|
4512
|
-
classes = cbRes.badgeClass ? " " + cbRes.badgeClass : "";
|
|
4513
|
-
tooltip = cbRes.badgeTooltip ? ` title="${cbRes.badgeTooltip}"` : "";
|
|
4514
|
-
}
|
|
4515
|
-
else if (typeof cbRes === "number") {
|
|
4516
|
-
badge = "" + cbRes;
|
|
4496
|
+
_createIcon(parentElem, replaceChild, showLoading) {
|
|
4497
|
+
const iconElem = this.tree._createNodeIcon(this, showLoading, true);
|
|
4498
|
+
if (iconElem) {
|
|
4499
|
+
if (replaceChild) {
|
|
4500
|
+
parentElem.replaceChild(iconElem, replaceChild);
|
|
4517
4501
|
}
|
|
4518
4502
|
else {
|
|
4519
|
-
|
|
4520
|
-
}
|
|
4521
|
-
if (typeof badge === "string") {
|
|
4522
|
-
badge = elemFromHtml(`<span class="wb-badge${classes}"${tooltip}>${escapeHtml(badge)}</span>`);
|
|
4523
|
-
}
|
|
4524
|
-
if (badge) {
|
|
4525
|
-
iconSpan.append(badge);
|
|
4503
|
+
parentElem.appendChild(iconElem);
|
|
4526
4504
|
}
|
|
4527
4505
|
}
|
|
4528
|
-
|
|
4529
|
-
return iconSpan;
|
|
4506
|
+
return iconElem;
|
|
4530
4507
|
}
|
|
4531
4508
|
/**
|
|
4532
4509
|
* Create a whole new `<div class="wb-row">` element.
|
|
@@ -4581,7 +4558,7 @@ class WunderbaumNode {
|
|
|
4581
4558
|
}
|
|
4582
4559
|
// Render the icon (show a 'loading' icon if we do not have an expander that
|
|
4583
4560
|
// we would prefer).
|
|
4584
|
-
const iconSpan = this._createIcon(
|
|
4561
|
+
const iconSpan = this._createIcon(nodeElem, null, !expanderSpan);
|
|
4585
4562
|
if (iconSpan) {
|
|
4586
4563
|
ofsTitlePx += ICON_WIDTH;
|
|
4587
4564
|
}
|
|
@@ -4813,7 +4790,7 @@ class WunderbaumNode {
|
|
|
4813
4790
|
// Update icon (if not opts.isNew, which would rebuild markup anyway)
|
|
4814
4791
|
const iconSpan = nodeElem.querySelector("i.wb-icon");
|
|
4815
4792
|
if (iconSpan) {
|
|
4816
|
-
this._createIcon(
|
|
4793
|
+
this._createIcon(nodeElem, iconSpan, !expanderSpan);
|
|
4817
4794
|
}
|
|
4818
4795
|
}
|
|
4819
4796
|
// Adjust column width
|
|
@@ -5362,7 +5339,7 @@ class WunderbaumNode {
|
|
|
5362
5339
|
assert(data.statusNodeType, "Not a status node");
|
|
5363
5340
|
assert(!firstChild || !firstChild.isStatusNode(), "Child must not be a status node");
|
|
5364
5341
|
statusNode = this.addNode(data, "prependChild");
|
|
5365
|
-
statusNode.match =
|
|
5342
|
+
statusNode.match = -1; // Mark as 'match' to avoid hiding
|
|
5366
5343
|
tree.update(ChangeType.structure);
|
|
5367
5344
|
return statusNode;
|
|
5368
5345
|
};
|
|
@@ -5654,7 +5631,7 @@ WunderbaumNode.sequence = 0;
|
|
|
5654
5631
|
/*!
|
|
5655
5632
|
* Wunderbaum - ext-edit
|
|
5656
5633
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
5657
|
-
* v0.
|
|
5634
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
5658
5635
|
*/
|
|
5659
5636
|
// const START_MARKER = "\uFFF7";
|
|
5660
5637
|
class EditExtension extends WunderbaumExtension {
|
|
@@ -5973,7 +5950,7 @@ class EditExtension extends WunderbaumExtension {
|
|
|
5973
5950
|
newNode.setClass("wb-edit-new");
|
|
5974
5951
|
this.relatedNode = node;
|
|
5975
5952
|
// Don't filter new nodes:
|
|
5976
|
-
newNode.match =
|
|
5953
|
+
newNode.match = -1;
|
|
5977
5954
|
newNode.makeVisible({ noAnimation: true }).then(() => {
|
|
5978
5955
|
this.startEditTitle(newNode);
|
|
5979
5956
|
});
|
|
@@ -5989,8 +5966,8 @@ class EditExtension extends WunderbaumExtension {
|
|
|
5989
5966
|
* https://github.com/mar10/wunderbaum
|
|
5990
5967
|
*
|
|
5991
5968
|
* Released under the MIT license.
|
|
5992
|
-
* @version v0.
|
|
5993
|
-
* @date Sat,
|
|
5969
|
+
* @version v0.13.0
|
|
5970
|
+
* @date Sat, 08 Mar 2025 14:16:31 GMT
|
|
5994
5971
|
*/
|
|
5995
5972
|
// import "./wunderbaum.scss";
|
|
5996
5973
|
class WbSystemRoot extends WunderbaumNode {
|
|
@@ -6051,6 +6028,9 @@ class Wunderbaum {
|
|
|
6051
6028
|
// --- SELECT ---
|
|
6052
6029
|
// /** @internal */
|
|
6053
6030
|
// public selectRangeAnchor: WunderbaumNode | null = null;
|
|
6031
|
+
// --- BREADCRUMB ---
|
|
6032
|
+
/** Filter options (used as defaults for calls to {@link Wunderbaum.filterNodes} ) */
|
|
6033
|
+
this.breadcrumb = null;
|
|
6054
6034
|
// --- FILTER ---
|
|
6055
6035
|
/** Filter options (used as defaults for calls to {@link Wunderbaum.filterNodes} ) */
|
|
6056
6036
|
this.filterMode = null;
|
|
@@ -6085,10 +6065,10 @@ class Wunderbaum {
|
|
|
6085
6065
|
emptyChildListExpandable: false,
|
|
6086
6066
|
// updateThrottleWait: 200,
|
|
6087
6067
|
skeleton: false,
|
|
6088
|
-
connectTopBreadcrumb: null,
|
|
6068
|
+
connectTopBreadcrumb: null,
|
|
6089
6069
|
selectMode: "multi", // SelectModeType
|
|
6090
6070
|
// --- KeyNav ---
|
|
6091
|
-
navigationModeOption: null, // NavModeEnum
|
|
6071
|
+
navigationModeOption: null, // NavModeEnum,
|
|
6092
6072
|
quicksearch: true,
|
|
6093
6073
|
// --- Events ---
|
|
6094
6074
|
iconBadge: null,
|
|
@@ -6100,8 +6080,11 @@ class Wunderbaum {
|
|
|
6100
6080
|
strings: {
|
|
6101
6081
|
loadError: "Error",
|
|
6102
6082
|
loading: "Loading...",
|
|
6103
|
-
// loading: "Loading…",
|
|
6104
6083
|
noData: "No data",
|
|
6084
|
+
breadcrumbDelimiter: " » ",
|
|
6085
|
+
queryResult: "Found ${matches} of ${count}",
|
|
6086
|
+
noMatch: "No results",
|
|
6087
|
+
matchIndex: "${match} of ${matches}",
|
|
6105
6088
|
},
|
|
6106
6089
|
}, options));
|
|
6107
6090
|
const readyDeferred = new Deferred();
|
|
@@ -6207,6 +6190,19 @@ class Wunderbaum {
|
|
|
6207
6190
|
this.headerElement =
|
|
6208
6191
|
this.element.querySelector("div.wb-header");
|
|
6209
6192
|
this.element.classList.toggle("wb-grid", this.columns.length > 1);
|
|
6193
|
+
if (this.options.connectTopBreadcrumb) {
|
|
6194
|
+
this.breadcrumb = elemFromSelector(this.options.connectTopBreadcrumb);
|
|
6195
|
+
assert(!this.breadcrumb || this.breadcrumb.innerHTML != null, `Invalid 'connectTopBreadcrumb' option: ${this.breadcrumb}.`);
|
|
6196
|
+
this.breadcrumb.addEventListener("click", (e) => {
|
|
6197
|
+
// const node = Wunderbaum.getNode(e)!;
|
|
6198
|
+
const elem = e.target;
|
|
6199
|
+
if (elem && elem.matches("a.wb-breadcrumb")) {
|
|
6200
|
+
const node = this.keyMap.get(elem.dataset.key);
|
|
6201
|
+
node === null || node === void 0 ? void 0 : node.setActive();
|
|
6202
|
+
e.preventDefault();
|
|
6203
|
+
}
|
|
6204
|
+
});
|
|
6205
|
+
}
|
|
6210
6206
|
this._initExtensions();
|
|
6211
6207
|
// --- apply initial options
|
|
6212
6208
|
["enabled", "fixedCol"].forEach((optName) => {
|
|
@@ -6570,7 +6566,10 @@ class Wunderbaum {
|
|
|
6570
6566
|
});
|
|
6571
6567
|
return node;
|
|
6572
6568
|
}
|
|
6573
|
-
/** Return the topmost visible node in the viewport.
|
|
6569
|
+
/** Return the topmost visible node in the viewport.
|
|
6570
|
+
* @param complete If `false`, the node is considered visible if at least one
|
|
6571
|
+
* pixel is visible.
|
|
6572
|
+
*/
|
|
6574
6573
|
getTopmostVpNode(complete = true) {
|
|
6575
6574
|
const rowHeight = this.options.rowHeightPx;
|
|
6576
6575
|
const gracePx = 1; // ignore subpixel scrolling
|
|
@@ -6603,24 +6602,19 @@ class Wunderbaum {
|
|
|
6603
6602
|
bottomIdx = Math.min(bottomIdx, this.count(true) - 1);
|
|
6604
6603
|
return this._getNodeByRowIdx(bottomIdx);
|
|
6605
6604
|
}
|
|
6606
|
-
/** Return
|
|
6607
|
-
|
|
6605
|
+
/** Return following visible node in the viewport. */
|
|
6606
|
+
_getNextNodeInView(node, options) {
|
|
6607
|
+
let ofs = (options === null || options === void 0 ? void 0 : options.ofs) || 1;
|
|
6608
|
+
const reverse = !!(options === null || options === void 0 ? void 0 : options.reverse);
|
|
6608
6609
|
this.visitRows((n) => {
|
|
6609
6610
|
node = n;
|
|
6610
|
-
if (
|
|
6611
|
+
if ((options === null || options === void 0 ? void 0 : options.cb) && options.cb(n)) {
|
|
6611
6612
|
return false;
|
|
6612
6613
|
}
|
|
6613
|
-
}, { reverse: true, start: node || this.getActiveNode() });
|
|
6614
|
-
return node;
|
|
6615
|
-
}
|
|
6616
|
-
/** Return following visible node in the viewport. */
|
|
6617
|
-
_getNextNodeInView(node, ofs = 1) {
|
|
6618
|
-
this.visitRows((n) => {
|
|
6619
|
-
node = n;
|
|
6620
6614
|
if (ofs-- <= 0) {
|
|
6621
6615
|
return false;
|
|
6622
6616
|
}
|
|
6623
|
-
}, { reverse:
|
|
6617
|
+
}, { reverse: reverse, start: node || this.getActiveNode() });
|
|
6624
6618
|
return node;
|
|
6625
6619
|
}
|
|
6626
6620
|
/**
|
|
@@ -6740,9 +6734,11 @@ class Wunderbaum {
|
|
|
6740
6734
|
case "first":
|
|
6741
6735
|
case "last":
|
|
6742
6736
|
case "left":
|
|
6737
|
+
case "nextMatch":
|
|
6743
6738
|
case "pageDown":
|
|
6744
6739
|
case "pageUp":
|
|
6745
6740
|
case "parent":
|
|
6741
|
+
case "prevMatch":
|
|
6746
6742
|
case "right":
|
|
6747
6743
|
case "up":
|
|
6748
6744
|
return node.navigate(cmd);
|
|
@@ -6934,6 +6930,11 @@ class Wunderbaum {
|
|
|
6934
6930
|
count(visible = false) {
|
|
6935
6931
|
return visible ? this.treeRowCount : this.keyMap.size;
|
|
6936
6932
|
}
|
|
6933
|
+
/** Return the number of *unique* nodes in the data model, i.e. unique `node.refKey`.
|
|
6934
|
+
*/
|
|
6935
|
+
countUnique() {
|
|
6936
|
+
return this.refKeyMap.size;
|
|
6937
|
+
}
|
|
6937
6938
|
/** @internal sanity check. */
|
|
6938
6939
|
_check() {
|
|
6939
6940
|
let i = 0;
|
|
@@ -6992,12 +6993,14 @@ class Wunderbaum {
|
|
|
6992
6993
|
* and wrap-around at the end.
|
|
6993
6994
|
* Used by quicksearch and keyboard navigation.
|
|
6994
6995
|
*/
|
|
6995
|
-
findNextNode(match, startNode) {
|
|
6996
|
+
findNextNode(match, startNode, reverse = false) {
|
|
6996
6997
|
//, visibleOnly) {
|
|
6997
6998
|
let res = null;
|
|
6998
6999
|
const firstNode = this.getFirstChild();
|
|
7000
|
+
// Last visible node (calculation is expensive, so do only if we need it):
|
|
7001
|
+
const lastNode = reverse ? this.findRelatedNode(firstNode, "last") : null;
|
|
6999
7002
|
const matcher = typeof match === "string" ? makeNodeTitleStartMatcher(match) : match;
|
|
7000
|
-
startNode = startNode || firstNode;
|
|
7003
|
+
startNode = startNode || (reverse ? lastNode : firstNode);
|
|
7001
7004
|
function _checkNode(n) {
|
|
7002
7005
|
// console.log("_check " + n)
|
|
7003
7006
|
if (matcher(n)) {
|
|
@@ -7010,12 +7013,14 @@ class Wunderbaum {
|
|
|
7010
7013
|
this.visitRows(_checkNode, {
|
|
7011
7014
|
start: startNode,
|
|
7012
7015
|
includeSelf: false,
|
|
7016
|
+
reverse: reverse,
|
|
7013
7017
|
});
|
|
7014
7018
|
// Wrap around search
|
|
7015
7019
|
if (!res && startNode !== firstNode) {
|
|
7016
7020
|
this.visitRows(_checkNode, {
|
|
7017
|
-
start: firstNode,
|
|
7021
|
+
start: reverse ? lastNode : firstNode,
|
|
7018
7022
|
includeSelf: true,
|
|
7023
|
+
reverse: reverse,
|
|
7019
7024
|
});
|
|
7020
7025
|
}
|
|
7021
7026
|
return res;
|
|
@@ -7082,7 +7087,7 @@ class Wunderbaum {
|
|
|
7082
7087
|
// }
|
|
7083
7088
|
break;
|
|
7084
7089
|
case "up":
|
|
7085
|
-
res = this.
|
|
7090
|
+
res = this._getNextNodeInView(node, { reverse: true });
|
|
7086
7091
|
break;
|
|
7087
7092
|
case "down":
|
|
7088
7093
|
res = this._getNextNodeInView(node);
|
|
@@ -7095,7 +7100,10 @@ class Wunderbaum {
|
|
|
7095
7100
|
res = bottomNode;
|
|
7096
7101
|
}
|
|
7097
7102
|
else {
|
|
7098
|
-
res = this._getNextNodeInView(node,
|
|
7103
|
+
res = this._getNextNodeInView(node, {
|
|
7104
|
+
reverse: false,
|
|
7105
|
+
ofs: pageSize,
|
|
7106
|
+
});
|
|
7099
7107
|
}
|
|
7100
7108
|
}
|
|
7101
7109
|
break;
|
|
@@ -7110,10 +7118,23 @@ class Wunderbaum {
|
|
|
7110
7118
|
res = topNode;
|
|
7111
7119
|
}
|
|
7112
7120
|
else {
|
|
7113
|
-
res = this.
|
|
7121
|
+
res = this._getNextNodeInView(node, {
|
|
7122
|
+
reverse: true,
|
|
7123
|
+
ofs: pageSize,
|
|
7124
|
+
});
|
|
7114
7125
|
}
|
|
7115
7126
|
}
|
|
7116
7127
|
break;
|
|
7128
|
+
case "prevMatch":
|
|
7129
|
+
// fallthrough
|
|
7130
|
+
case "nextMatch":
|
|
7131
|
+
if (!this.isFilterActive) {
|
|
7132
|
+
this.logWarn(`${where}: Filter is not active.`);
|
|
7133
|
+
break;
|
|
7134
|
+
}
|
|
7135
|
+
res = this.findNextNode((n) => n.isMatched(), node, where === "prevMatch");
|
|
7136
|
+
res === null || res === void 0 ? void 0 : res.setActive();
|
|
7137
|
+
break;
|
|
7117
7138
|
default:
|
|
7118
7139
|
this.logWarn("Unknown relation '" + where + "'.");
|
|
7119
7140
|
}
|
|
@@ -7175,6 +7196,12 @@ class Wunderbaum {
|
|
|
7175
7196
|
getFirstChild() {
|
|
7176
7197
|
return this.root.getFirstChild();
|
|
7177
7198
|
}
|
|
7199
|
+
/**
|
|
7200
|
+
* Return the last top level node if any (not the invisible root node).
|
|
7201
|
+
*/
|
|
7202
|
+
getLastChild() {
|
|
7203
|
+
return this.root.getLastChild();
|
|
7204
|
+
}
|
|
7178
7205
|
/**
|
|
7179
7206
|
* Return the node that currently has keyboard focus or null.
|
|
7180
7207
|
* Alias for {@link Wunderbaum.focusNode}.
|
|
@@ -7502,6 +7529,51 @@ class Wunderbaum {
|
|
|
7502
7529
|
_setFocusNode(node) {
|
|
7503
7530
|
this._focusNode = node;
|
|
7504
7531
|
}
|
|
7532
|
+
/** Return the current selection/expansion/activation status. @experimental */
|
|
7533
|
+
getState(options) {
|
|
7534
|
+
var _a, _b;
|
|
7535
|
+
let expandedKeys = undefined;
|
|
7536
|
+
if (options.expandedKeys !== false) {
|
|
7537
|
+
expandedKeys = [];
|
|
7538
|
+
for (const node of this) {
|
|
7539
|
+
if (node.expanded) {
|
|
7540
|
+
expandedKeys.push(node.key);
|
|
7541
|
+
}
|
|
7542
|
+
}
|
|
7543
|
+
}
|
|
7544
|
+
const state = {
|
|
7545
|
+
activeKey: (_b = (_a = this.activeNode) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : null,
|
|
7546
|
+
activeColIdx: this.activeColIdx,
|
|
7547
|
+
selectedKeys: options.selectedKeys === false
|
|
7548
|
+
? undefined
|
|
7549
|
+
: this.getSelectedNodes().flatMap((n) => n.key),
|
|
7550
|
+
expandedKeys: expandedKeys,
|
|
7551
|
+
};
|
|
7552
|
+
return state;
|
|
7553
|
+
}
|
|
7554
|
+
/** Apply selection/expansion/activation status. @experimental */
|
|
7555
|
+
setState(state, options) {
|
|
7556
|
+
this.runWithDeferredUpdate(() => {
|
|
7557
|
+
var _a, _b;
|
|
7558
|
+
if (state.selectedKeys) {
|
|
7559
|
+
this.selectAll(false);
|
|
7560
|
+
for (const key of state.selectedKeys) {
|
|
7561
|
+
(_a = this.findKey(key)) === null || _a === void 0 ? void 0 : _a.setSelected(true);
|
|
7562
|
+
}
|
|
7563
|
+
}
|
|
7564
|
+
if (state.expandedKeys) {
|
|
7565
|
+
for (const key of state.expandedKeys) {
|
|
7566
|
+
(_b = this.findKey(key)) === null || _b === void 0 ? void 0 : _b.setExpanded(true);
|
|
7567
|
+
}
|
|
7568
|
+
}
|
|
7569
|
+
if (state.activeKey) {
|
|
7570
|
+
this.setActiveNode(state.activeKey);
|
|
7571
|
+
}
|
|
7572
|
+
if (state.activeColIdx != null) {
|
|
7573
|
+
this.setColumn(state.activeColIdx);
|
|
7574
|
+
}
|
|
7575
|
+
});
|
|
7576
|
+
}
|
|
7505
7577
|
update(change, node, options) {
|
|
7506
7578
|
// this.log(`update(${change}) node=${node}`);
|
|
7507
7579
|
if (!(node instanceof WunderbaumNode)) {
|
|
@@ -7783,11 +7855,11 @@ class Wunderbaum {
|
|
|
7783
7855
|
// }
|
|
7784
7856
|
return modified;
|
|
7785
7857
|
}
|
|
7786
|
-
_insertIcon(icon, elem) {
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
}
|
|
7858
|
+
// protected _insertIcon(icon: string, elem: HTMLElement) {
|
|
7859
|
+
// const iconElem = document.createElement("i");
|
|
7860
|
+
// iconElem.className = icon;
|
|
7861
|
+
// elem.appendChild(iconElem);
|
|
7862
|
+
// }
|
|
7791
7863
|
/** Create/update header markup from `this.columns` definition.
|
|
7792
7864
|
* @internal
|
|
7793
7865
|
*/
|
|
@@ -7885,6 +7957,104 @@ class Wunderbaum {
|
|
|
7885
7957
|
this._updateViewportImmediately();
|
|
7886
7958
|
}
|
|
7887
7959
|
}
|
|
7960
|
+
/** @internal */
|
|
7961
|
+
_createNodeIcon(node, showLoading, showBadge) {
|
|
7962
|
+
const iconMap = this.iconMap;
|
|
7963
|
+
let iconElem;
|
|
7964
|
+
let icon = node.getOption("icon");
|
|
7965
|
+
if (node._errorInfo) {
|
|
7966
|
+
icon = iconMap.error;
|
|
7967
|
+
}
|
|
7968
|
+
else if (node._isLoading && showLoading) {
|
|
7969
|
+
// Status nodes, or nodes without expander (< minExpandLevel) should
|
|
7970
|
+
// display the 'loading' status with the i.wb-icon span
|
|
7971
|
+
icon = iconMap.loading;
|
|
7972
|
+
}
|
|
7973
|
+
if (icon === false) {
|
|
7974
|
+
return null; // explicitly disabled: don't try default icons
|
|
7975
|
+
}
|
|
7976
|
+
if (typeof icon === "string") ;
|
|
7977
|
+
else if (node.statusNodeType) {
|
|
7978
|
+
icon = iconMap[node.statusNodeType];
|
|
7979
|
+
}
|
|
7980
|
+
else if (node.expanded) {
|
|
7981
|
+
icon = iconMap.folderOpen;
|
|
7982
|
+
}
|
|
7983
|
+
else if (node.children) {
|
|
7984
|
+
icon = iconMap.folder;
|
|
7985
|
+
}
|
|
7986
|
+
else if (node.lazy) {
|
|
7987
|
+
icon = iconMap.folderLazy;
|
|
7988
|
+
}
|
|
7989
|
+
else {
|
|
7990
|
+
icon = iconMap.doc;
|
|
7991
|
+
}
|
|
7992
|
+
if (!icon) {
|
|
7993
|
+
iconElem = document.createElement("i");
|
|
7994
|
+
iconElem.className = "wb-icon";
|
|
7995
|
+
}
|
|
7996
|
+
else if (icon.indexOf("<") >= 0) {
|
|
7997
|
+
// HTML
|
|
7998
|
+
iconElem = elemFromHtml(icon);
|
|
7999
|
+
}
|
|
8000
|
+
else if (TEST_IMG.test(icon)) {
|
|
8001
|
+
// Image URL
|
|
8002
|
+
iconElem = elemFromHtml(`<i class="wb-icon" style="background-image: url('${icon}');">`);
|
|
8003
|
+
}
|
|
8004
|
+
else {
|
|
8005
|
+
// Class name
|
|
8006
|
+
iconElem = document.createElement("i");
|
|
8007
|
+
iconElem.className = "wb-icon " + icon;
|
|
8008
|
+
}
|
|
8009
|
+
// Event handler `tree.iconBadge` can return a badge text or HTMLSpanElement
|
|
8010
|
+
const cbRes = showBadge && node._callEvent("iconBadge", { iconSpan: iconElem });
|
|
8011
|
+
let badge = null;
|
|
8012
|
+
if (cbRes != null && cbRes !== false) {
|
|
8013
|
+
let classes = "";
|
|
8014
|
+
let tooltip = "";
|
|
8015
|
+
if (isPlainObject(cbRes)) {
|
|
8016
|
+
badge = "" + cbRes.badge;
|
|
8017
|
+
classes = cbRes.badgeClass ? " " + cbRes.badgeClass : "";
|
|
8018
|
+
tooltip = cbRes.badgeTooltip ? ` title="${cbRes.badgeTooltip}"` : "";
|
|
8019
|
+
}
|
|
8020
|
+
else if (typeof cbRes === "number") {
|
|
8021
|
+
badge = "" + cbRes;
|
|
8022
|
+
}
|
|
8023
|
+
else {
|
|
8024
|
+
badge = cbRes; // string or HTMLSpanElement
|
|
8025
|
+
}
|
|
8026
|
+
if (typeof badge === "string") {
|
|
8027
|
+
badge = elemFromHtml(`<span class="wb-badge${classes}"${tooltip}>${escapeHtml(badge)}</span>`);
|
|
8028
|
+
}
|
|
8029
|
+
if (badge) {
|
|
8030
|
+
iconElem.append(badge);
|
|
8031
|
+
}
|
|
8032
|
+
}
|
|
8033
|
+
return iconElem;
|
|
8034
|
+
}
|
|
8035
|
+
_updateTopBreadcrumb() {
|
|
8036
|
+
const breadcrumb = this.breadcrumb;
|
|
8037
|
+
const topmost = this.getTopmostVpNode(true);
|
|
8038
|
+
const parentList = topmost === null || topmost === void 0 ? void 0 : topmost.getParentList(false, false);
|
|
8039
|
+
if (parentList === null || parentList === void 0 ? void 0 : parentList.length) {
|
|
8040
|
+
breadcrumb.innerHTML = "";
|
|
8041
|
+
for (const n of topmost.getParentList(false, false)) {
|
|
8042
|
+
const icon = this._createNodeIcon(n, false, false);
|
|
8043
|
+
if (icon) {
|
|
8044
|
+
breadcrumb.append(icon, " ");
|
|
8045
|
+
}
|
|
8046
|
+
const part = document.createElement("a");
|
|
8047
|
+
part.textContent = n.title;
|
|
8048
|
+
part.href = "#";
|
|
8049
|
+
part.classList.add("wb-breadcrumb");
|
|
8050
|
+
part.dataset.key = n.key;
|
|
8051
|
+
breadcrumb.append(part, this.options.strings.breadcrumbDelimiter);
|
|
8052
|
+
}
|
|
8053
|
+
}
|
|
8054
|
+
else {
|
|
8055
|
+
breadcrumb.innerHTML = " ";
|
|
8056
|
+
}
|
|
8057
|
+
}
|
|
7888
8058
|
/**
|
|
7889
8059
|
* This is the actual update method, which is wrapped inside a throttle method.
|
|
7890
8060
|
* It calls `updateColumns()` and `_updateRows()`.
|
|
@@ -7895,7 +8065,6 @@ class Wunderbaum {
|
|
|
7895
8065
|
* @internal
|
|
7896
8066
|
*/
|
|
7897
8067
|
_updateViewportImmediately() {
|
|
7898
|
-
var _a;
|
|
7899
8068
|
if (this._disableUpdateCount) {
|
|
7900
8069
|
this.log(`_updateViewportImmediately() IGNORED (disable level: ${this._disableUpdateCount}).`);
|
|
7901
8070
|
this._disableUpdateIgnoreCount++;
|
|
@@ -7942,11 +8111,8 @@ class Wunderbaum {
|
|
|
7942
8111
|
this._updateRows();
|
|
7943
8112
|
// console.profileEnd(`_updateViewportImmediately()`)
|
|
7944
8113
|
}
|
|
7945
|
-
if (this.
|
|
7946
|
-
|
|
7947
|
-
let path = (_a = this.getTopmostVpNode(true)) === null || _a === void 0 ? void 0 : _a.getPath(false, "title", " > ");
|
|
7948
|
-
path = path ? path + " >" : "";
|
|
7949
|
-
this.options.connectTopBreadcrumb.textContent = path;
|
|
8114
|
+
if (this.breadcrumb) {
|
|
8115
|
+
this._updateTopBreadcrumb();
|
|
7950
8116
|
}
|
|
7951
8117
|
this._callEvent("update");
|
|
7952
8118
|
}
|
|
@@ -8315,7 +8481,7 @@ class Wunderbaum {
|
|
|
8315
8481
|
}
|
|
8316
8482
|
Wunderbaum.sequence = 0;
|
|
8317
8483
|
/** Wunderbaum release version number "MAJOR.MINOR.PATCH". */
|
|
8318
|
-
Wunderbaum.version = "v0.
|
|
8484
|
+
Wunderbaum.version = "v0.13.0"; // Set to semver by 'grunt release'
|
|
8319
8485
|
/** Expose some useful methods of the util.ts module as `Wunderbaum.util`. */
|
|
8320
8486
|
Wunderbaum.util = util;
|
|
8321
8487
|
|