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.umd.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
/*!
|
|
8
8
|
* Wunderbaum - debounce.ts
|
|
9
9
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
10
|
-
* v0.
|
|
10
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
11
11
|
*/
|
|
12
12
|
/*
|
|
13
13
|
* debounce & throttle, taken from https://github.com/lodash/lodash v4.17.21
|
|
@@ -299,7 +299,7 @@
|
|
|
299
299
|
/*!
|
|
300
300
|
* Wunderbaum - util
|
|
301
301
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
302
|
-
* v0.
|
|
302
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
303
303
|
*/
|
|
304
304
|
/** @module util */
|
|
305
305
|
/** Readable names for `MouseEvent.button` */
|
|
@@ -682,18 +682,6 @@
|
|
|
682
682
|
}
|
|
683
683
|
return obj;
|
|
684
684
|
}
|
|
685
|
-
// /** Return a EventTarget from selector or cast an existing element. */
|
|
686
|
-
// export function eventTargetFromSelector(
|
|
687
|
-
// obj: string | EventTarget
|
|
688
|
-
// ): EventTarget | null {
|
|
689
|
-
// if (!obj) {
|
|
690
|
-
// return null;
|
|
691
|
-
// }
|
|
692
|
-
// if (typeof obj === "string") {
|
|
693
|
-
// return document.querySelector(obj) as EventTarget;
|
|
694
|
-
// }
|
|
695
|
-
// return obj as EventTarget;
|
|
696
|
-
// }
|
|
697
685
|
/**
|
|
698
686
|
* Return a canonical descriptive string for a keyboard or mouse event.
|
|
699
687
|
*
|
|
@@ -1153,7 +1141,7 @@
|
|
|
1153
1141
|
/*!
|
|
1154
1142
|
* Wunderbaum - types
|
|
1155
1143
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
1156
|
-
* v0.
|
|
1144
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1157
1145
|
*/
|
|
1158
1146
|
/**
|
|
1159
1147
|
* Possible values for {@link WunderbaumNode.update} and {@link Wunderbaum.update}.
|
|
@@ -1221,7 +1209,7 @@
|
|
|
1221
1209
|
/*!
|
|
1222
1210
|
* Wunderbaum - wb_extension_base
|
|
1223
1211
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
1224
|
-
* v0.
|
|
1212
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1225
1213
|
*/
|
|
1226
1214
|
class WunderbaumExtension {
|
|
1227
1215
|
constructor(tree, id, defaults) {
|
|
@@ -1280,7 +1268,7 @@
|
|
|
1280
1268
|
/*!
|
|
1281
1269
|
* Wunderbaum - ext-filter
|
|
1282
1270
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
1283
|
-
* v0.
|
|
1271
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1284
1272
|
*/
|
|
1285
1273
|
const START_MARKER = "\uFFF7";
|
|
1286
1274
|
const END_MARKER = "\uFFF8";
|
|
@@ -1292,7 +1280,7 @@
|
|
|
1292
1280
|
autoApply: true, // Re-apply last filter if lazy data is loaded
|
|
1293
1281
|
autoExpand: false, // Expand all branches that contain matches while filtered
|
|
1294
1282
|
matchBranch: false, // Whether to implicitly match all children of matched nodes
|
|
1295
|
-
|
|
1283
|
+
connect: null, // Element or selector of an input control for filter query strings
|
|
1296
1284
|
fuzzy: false, // Match single characters in order, e.g. 'fb' will match 'FooBar'
|
|
1297
1285
|
hideExpanders: false, // Hide expanders if all child nodes are hidden by filter
|
|
1298
1286
|
highlight: true, // Highlight matches by wrapping inside <mark> tags
|
|
@@ -1300,36 +1288,117 @@
|
|
|
1300
1288
|
mode: "dim", // Grayout unmatched nodes (pass "hide" to remove unmatched node instead)
|
|
1301
1289
|
noData: true, // Display a 'no data' status node if result is empty
|
|
1302
1290
|
});
|
|
1291
|
+
this.queryInput = null;
|
|
1292
|
+
this.prevButton = null;
|
|
1293
|
+
this.nextButton = null;
|
|
1294
|
+
this.modeButton = null;
|
|
1295
|
+
this.matchInfoElem = null;
|
|
1303
1296
|
this.lastFilterArgs = null;
|
|
1304
1297
|
}
|
|
1305
1298
|
init() {
|
|
1306
1299
|
super.init();
|
|
1307
|
-
const
|
|
1308
|
-
if (
|
|
1309
|
-
this.
|
|
1310
|
-
assert(this.queryInput, `Invalid 'filter.connectInput' option: ${connectInput}.`);
|
|
1311
|
-
onEvent(this.queryInput, "input", debounce((e) => {
|
|
1312
|
-
// this.tree.log("query", e);
|
|
1313
|
-
this.filterNodes(this.queryInput.value.trim(), {});
|
|
1314
|
-
}, 700));
|
|
1300
|
+
const connect = this.getPluginOption("connect");
|
|
1301
|
+
if (connect) {
|
|
1302
|
+
this._connectControls();
|
|
1315
1303
|
}
|
|
1316
1304
|
}
|
|
1317
1305
|
setPluginOption(name, value) {
|
|
1318
|
-
// alert("filter opt=" + name + ", " + value)
|
|
1319
1306
|
super.setPluginOption(name, value);
|
|
1320
1307
|
switch (name) {
|
|
1321
1308
|
case "mode":
|
|
1322
|
-
this.tree.filterMode =
|
|
1309
|
+
this.tree.filterMode =
|
|
1310
|
+
value === "hide" ? "hide" : value === "mark" ? "mark" : "dim";
|
|
1323
1311
|
this.tree.updateFilter();
|
|
1324
1312
|
break;
|
|
1325
1313
|
}
|
|
1326
1314
|
}
|
|
1315
|
+
_updatedConnectedControls() {
|
|
1316
|
+
var _a;
|
|
1317
|
+
const filterActive = this.tree.filterMode !== null;
|
|
1318
|
+
const activeNode = this.tree.getActiveNode();
|
|
1319
|
+
const matchCount = filterActive ? this.countMatches() : 0;
|
|
1320
|
+
const strings = this.treeOpts.strings;
|
|
1321
|
+
let matchIdx = "?";
|
|
1322
|
+
if (this.matchInfoElem) {
|
|
1323
|
+
if (filterActive) {
|
|
1324
|
+
let info;
|
|
1325
|
+
if (matchCount === 0) {
|
|
1326
|
+
info = strings.noMatch;
|
|
1327
|
+
}
|
|
1328
|
+
else if (activeNode && activeNode.match >= 1) {
|
|
1329
|
+
matchIdx = (_a = activeNode.match) !== null && _a !== void 0 ? _a : "?";
|
|
1330
|
+
info = strings.matchIndex;
|
|
1331
|
+
}
|
|
1332
|
+
else {
|
|
1333
|
+
info = strings.queryResult;
|
|
1334
|
+
}
|
|
1335
|
+
info = info
|
|
1336
|
+
.replace("${count}", this.tree.count().toLocaleString())
|
|
1337
|
+
.replace("${match}", "" + matchIdx)
|
|
1338
|
+
.replace("${matches}", matchCount.toLocaleString());
|
|
1339
|
+
this.matchInfoElem.textContent = info;
|
|
1340
|
+
}
|
|
1341
|
+
else {
|
|
1342
|
+
this.matchInfoElem.textContent = "";
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
if (this.nextButton instanceof HTMLButtonElement) {
|
|
1346
|
+
this.nextButton.disabled = !matchCount;
|
|
1347
|
+
}
|
|
1348
|
+
if (this.prevButton instanceof HTMLButtonElement) {
|
|
1349
|
+
this.prevButton.disabled = !matchCount;
|
|
1350
|
+
}
|
|
1351
|
+
if (this.modeButton) {
|
|
1352
|
+
this.modeButton.disabled = !filterActive;
|
|
1353
|
+
this.modeButton.classList.toggle("wb-filter-hide", this.tree.filterMode === "hide");
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
_connectControls() {
|
|
1357
|
+
const tree = this.tree;
|
|
1358
|
+
const connect = this.getPluginOption("connect");
|
|
1359
|
+
if (!connect) {
|
|
1360
|
+
return;
|
|
1361
|
+
}
|
|
1362
|
+
this.queryInput = elemFromSelector(connect.inputElem);
|
|
1363
|
+
if (!this.queryInput) {
|
|
1364
|
+
throw new Error(`Invalid 'filter.connect' option: ${connect.inputElem}.`);
|
|
1365
|
+
}
|
|
1366
|
+
this.prevButton = elemFromSelector(connect.prevButton);
|
|
1367
|
+
this.nextButton = elemFromSelector(connect.nextButton);
|
|
1368
|
+
this.modeButton = elemFromSelector(connect.modeButton);
|
|
1369
|
+
this.matchInfoElem = elemFromSelector(connect.matchInfoElem);
|
|
1370
|
+
if (this.prevButton) {
|
|
1371
|
+
onEvent(this.prevButton, "click", () => {
|
|
1372
|
+
tree.findRelatedNode(tree.getActiveNode() || tree.getFirstChild(), "prevMatch");
|
|
1373
|
+
this._updatedConnectedControls();
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
if (this.nextButton) {
|
|
1377
|
+
onEvent(this.nextButton, "click", () => {
|
|
1378
|
+
tree.findRelatedNode(tree.getActiveNode() || tree.getFirstChild(), "nextMatch");
|
|
1379
|
+
this._updatedConnectedControls();
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
if (this.modeButton) {
|
|
1383
|
+
onEvent(this.modeButton, "click", (e) => {
|
|
1384
|
+
if (!this.tree.filterMode) {
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
this.setPluginOption("mode", tree.filterMode === "dim" ? "hide" : "dim");
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
onEvent(this.queryInput, "input", debounce((e) => {
|
|
1391
|
+
this.filterNodes(this.queryInput.value.trim(), {});
|
|
1392
|
+
}, 700));
|
|
1393
|
+
this._updatedConnectedControls();
|
|
1394
|
+
}
|
|
1327
1395
|
_applyFilterNoUpdate(filter, _opts) {
|
|
1328
1396
|
return this.tree.runWithDeferredUpdate(() => {
|
|
1329
1397
|
return this._applyFilterImpl(filter, _opts);
|
|
1330
1398
|
});
|
|
1331
1399
|
}
|
|
1332
1400
|
_applyFilterImpl(filter, _opts) {
|
|
1401
|
+
var _a;
|
|
1333
1402
|
let //temp,
|
|
1334
1403
|
count = 0;
|
|
1335
1404
|
const start = Date.now();
|
|
@@ -1411,11 +1480,11 @@
|
|
|
1411
1480
|
return !!res;
|
|
1412
1481
|
};
|
|
1413
1482
|
}
|
|
1414
|
-
tree.filterMode = opts.mode;
|
|
1483
|
+
tree.filterMode = (_a = opts.mode) !== null && _a !== void 0 ? _a : "dim";
|
|
1415
1484
|
// eslint-disable-next-line prefer-rest-params
|
|
1416
1485
|
this.lastFilterArgs = arguments;
|
|
1417
1486
|
tree.element.classList.toggle("wb-ext-filter-hide", !!hideMode);
|
|
1418
|
-
tree.element.classList.toggle("wb-ext-filter-dim",
|
|
1487
|
+
tree.element.classList.toggle("wb-ext-filter-dim", opts.mode === "dim");
|
|
1419
1488
|
tree.element.classList.toggle("wb-ext-filter-hide-expanders", !!opts.hideExpanders);
|
|
1420
1489
|
// Reset current filter
|
|
1421
1490
|
tree.root.subMatchCount = 0;
|
|
@@ -1424,10 +1493,6 @@
|
|
|
1424
1493
|
delete node.titleWithHighlight;
|
|
1425
1494
|
node.subMatchCount = 0;
|
|
1426
1495
|
});
|
|
1427
|
-
// statusNode = tree.root.findDirectChild(KEY_NODATA);
|
|
1428
|
-
// if (statusNode) {
|
|
1429
|
-
// statusNode.remove();
|
|
1430
|
-
// }
|
|
1431
1496
|
tree.setStatus(NodeStatusType.ok);
|
|
1432
1497
|
// Adjust node.hide, .match, and .subMatchCount properties
|
|
1433
1498
|
treeOpts.autoCollapse = false; // #528
|
|
@@ -1438,7 +1503,7 @@
|
|
|
1438
1503
|
let res = filter(node);
|
|
1439
1504
|
if (res === "skip") {
|
|
1440
1505
|
node.visit(function (c) {
|
|
1441
|
-
c.match =
|
|
1506
|
+
c.match = undefined;
|
|
1442
1507
|
}, true);
|
|
1443
1508
|
return "skip";
|
|
1444
1509
|
}
|
|
@@ -1449,7 +1514,7 @@
|
|
|
1449
1514
|
}
|
|
1450
1515
|
if (res) {
|
|
1451
1516
|
count++;
|
|
1452
|
-
node.match =
|
|
1517
|
+
node.match = count;
|
|
1453
1518
|
node.visitParents((p) => {
|
|
1454
1519
|
if (p !== node) {
|
|
1455
1520
|
p.subMatchCount += 1;
|
|
@@ -1476,6 +1541,7 @@
|
|
|
1476
1541
|
}
|
|
1477
1542
|
// Redraw whole tree
|
|
1478
1543
|
tree.logDebug(`Filter '${filter}' found ${count} nodes in ${Date.now() - start} ms.`);
|
|
1544
|
+
this._updatedConnectedControls();
|
|
1479
1545
|
return count;
|
|
1480
1546
|
}
|
|
1481
1547
|
/**
|
|
@@ -1520,34 +1586,22 @@
|
|
|
1520
1586
|
else {
|
|
1521
1587
|
tree.logWarn("updateFilter(): no filter active.");
|
|
1522
1588
|
}
|
|
1589
|
+
this._updatedConnectedControls();
|
|
1523
1590
|
}
|
|
1524
1591
|
/**
|
|
1525
1592
|
* [ext-filter] Reset the filter.
|
|
1526
1593
|
*/
|
|
1527
1594
|
clearFilter() {
|
|
1528
1595
|
const tree = this.tree;
|
|
1529
|
-
// statusNode = tree.root.findDirectChild(KEY_NODATA),
|
|
1530
|
-
// escapeTitles = tree.options.escapeTitles;
|
|
1531
1596
|
tree.enableUpdate(false);
|
|
1532
|
-
// if (statusNode) {
|
|
1533
|
-
// statusNode.remove();
|
|
1534
|
-
// }
|
|
1535
1597
|
tree.setStatus(NodeStatusType.ok);
|
|
1536
1598
|
// we also counted root node's subMatchCount
|
|
1537
1599
|
delete tree.root.match;
|
|
1538
1600
|
delete tree.root.subMatchCount;
|
|
1539
1601
|
tree.visit((node) => {
|
|
1540
|
-
// if (node.match && node._rowElem) {
|
|
1541
|
-
// let titleElem = node._rowElem.querySelector("span.wb-title")!;
|
|
1542
|
-
// node._callEvent("enhanceTitle", { titleElem: titleElem });
|
|
1543
|
-
// }
|
|
1544
1602
|
delete node.match;
|
|
1545
1603
|
delete node.subMatchCount;
|
|
1546
1604
|
delete node.titleWithHighlight;
|
|
1547
|
-
// if (node.subMatchBadge) {
|
|
1548
|
-
// node.subMatchBadge.remove();
|
|
1549
|
-
// delete node.subMatchBadge;
|
|
1550
|
-
// }
|
|
1551
1605
|
if (node._filterAutoExpanded && node.expanded) {
|
|
1552
1606
|
node.setExpanded(false, {
|
|
1553
1607
|
noAnimation: true,
|
|
@@ -1561,7 +1615,7 @@
|
|
|
1561
1615
|
tree.element.classList.remove(
|
|
1562
1616
|
// "wb-ext-filter",
|
|
1563
1617
|
"wb-ext-filter-dim", "wb-ext-filter-hide");
|
|
1564
|
-
|
|
1618
|
+
this._updatedConnectedControls();
|
|
1565
1619
|
tree.enableUpdate(true);
|
|
1566
1620
|
}
|
|
1567
1621
|
}
|
|
@@ -1605,7 +1659,7 @@
|
|
|
1605
1659
|
/*!
|
|
1606
1660
|
* Wunderbaum - ext-keynav
|
|
1607
1661
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
1608
|
-
* v0.
|
|
1662
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1609
1663
|
*/
|
|
1610
1664
|
const QUICKSEARCH_DELAY = 500;
|
|
1611
1665
|
class KeynavExtension extends WunderbaumExtension {
|
|
@@ -1969,7 +2023,7 @@
|
|
|
1969
2023
|
/*!
|
|
1970
2024
|
* Wunderbaum - ext-logger
|
|
1971
2025
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
1972
|
-
* v0.
|
|
2026
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
1973
2027
|
*/
|
|
1974
2028
|
class LoggerExtension extends WunderbaumExtension {
|
|
1975
2029
|
constructor(tree) {
|
|
@@ -2011,7 +2065,7 @@
|
|
|
2011
2065
|
/*!
|
|
2012
2066
|
* Wunderbaum - ext-dnd
|
|
2013
2067
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
2014
|
-
* v0.
|
|
2068
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2015
2069
|
*/
|
|
2016
2070
|
const nodeMimeType = "application/x-wunderbaum-node";
|
|
2017
2071
|
class DndExtension extends WunderbaumExtension {
|
|
@@ -2461,7 +2515,7 @@
|
|
|
2461
2515
|
/*!
|
|
2462
2516
|
* Wunderbaum - drag_observer
|
|
2463
2517
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
2464
|
-
* v0.
|
|
2518
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2465
2519
|
*/
|
|
2466
2520
|
/**
|
|
2467
2521
|
* Convert mouse- and touch events to 'dragstart', 'drag', and 'dragstop'.
|
|
@@ -2610,7 +2664,7 @@
|
|
|
2610
2664
|
/*!
|
|
2611
2665
|
* Wunderbaum - common
|
|
2612
2666
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
2613
|
-
* v0.
|
|
2667
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2614
2668
|
*/
|
|
2615
2669
|
const DEFAULT_DEBUGLEVEL = 3; // Replaced by rollup script
|
|
2616
2670
|
/**
|
|
@@ -2723,29 +2777,20 @@
|
|
|
2723
2777
|
// "Escape",
|
|
2724
2778
|
// ]);
|
|
2725
2779
|
/** Map `KeyEvent.key` to navigation action. */
|
|
2726
|
-
const
|
|
2727
|
-
" ": "toggleSelect",
|
|
2728
|
-
"+": "expand",
|
|
2729
|
-
Add: "expand",
|
|
2780
|
+
const KEY_TO_NAVIGATION_MAP = {
|
|
2730
2781
|
ArrowDown: "down",
|
|
2731
2782
|
ArrowLeft: "left",
|
|
2732
2783
|
ArrowRight: "right",
|
|
2733
2784
|
ArrowUp: "up",
|
|
2734
2785
|
Backspace: "parent",
|
|
2735
|
-
"/": "collapseAll",
|
|
2736
|
-
Divide: "collapseAll",
|
|
2737
2786
|
End: "lastCol",
|
|
2738
2787
|
Home: "firstCol",
|
|
2739
2788
|
"Control+End": "last",
|
|
2740
2789
|
"Control+Home": "first",
|
|
2741
2790
|
"Meta+ArrowDown": "last", // macOs
|
|
2742
2791
|
"Meta+ArrowUp": "first", // macOs
|
|
2743
|
-
"*": "expandAll",
|
|
2744
|
-
Multiply: "expandAll",
|
|
2745
2792
|
PageDown: "pageDown",
|
|
2746
2793
|
PageUp: "pageUp",
|
|
2747
|
-
"-": "collapse",
|
|
2748
|
-
Subtract: "collapse",
|
|
2749
2794
|
};
|
|
2750
2795
|
/** Return a callback that returns true if the node title matches the string
|
|
2751
2796
|
* or regular expression.
|
|
@@ -2969,7 +3014,7 @@
|
|
|
2969
3014
|
/*!
|
|
2970
3015
|
* Wunderbaum - ext-grid
|
|
2971
3016
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
2972
|
-
* v0.
|
|
3017
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
2973
3018
|
*/
|
|
2974
3019
|
class GridExtension extends WunderbaumExtension {
|
|
2975
3020
|
constructor(tree) {
|
|
@@ -3060,7 +3105,7 @@
|
|
|
3060
3105
|
/*!
|
|
3061
3106
|
* Wunderbaum - deferred
|
|
3062
3107
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
3063
|
-
* v0.
|
|
3108
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
3064
3109
|
*/
|
|
3065
3110
|
/**
|
|
3066
3111
|
* Implement a ES6 Promise, that exposes a resolve() and reject() method.
|
|
@@ -3113,7 +3158,7 @@
|
|
|
3113
3158
|
/*!
|
|
3114
3159
|
* Wunderbaum - wunderbaum_node
|
|
3115
3160
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
3116
|
-
* v0.
|
|
3161
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
3117
3162
|
*/
|
|
3118
3163
|
/** WunderbaumNode properties that can be passed with source data.
|
|
3119
3164
|
* (Any other source properties will be stored as `node.data.PROP`.)
|
|
@@ -3895,7 +3940,7 @@
|
|
|
3895
3940
|
isParentOf(other) {
|
|
3896
3941
|
return other && other.parent === this;
|
|
3897
3942
|
}
|
|
3898
|
-
/**
|
|
3943
|
+
/** Return true if this node is partially loaded. @experimental */
|
|
3899
3944
|
isPartload() {
|
|
3900
3945
|
return !!this._partload;
|
|
3901
3946
|
}
|
|
@@ -4353,10 +4398,11 @@
|
|
|
4353
4398
|
* @param options
|
|
4354
4399
|
*/
|
|
4355
4400
|
async navigate(where, options) {
|
|
4401
|
+
var _a;
|
|
4356
4402
|
// Allow to pass 'ArrowLeft' instead of 'left'
|
|
4357
|
-
|
|
4403
|
+
const navType = ((_a = KEY_TO_NAVIGATION_MAP[where]) !== null && _a !== void 0 ? _a : where);
|
|
4358
4404
|
// Otherwise activate or focus the related node
|
|
4359
|
-
const node = this.findRelatedNode(
|
|
4405
|
+
const node = this.findRelatedNode(navType);
|
|
4360
4406
|
if (!node) {
|
|
4361
4407
|
this.logWarn(`Could not find related node '${where}'.`);
|
|
4362
4408
|
return Promise.resolve(this);
|
|
@@ -4453,86 +4499,17 @@
|
|
|
4453
4499
|
renderColInfosById: renderColInfosById,
|
|
4454
4500
|
};
|
|
4455
4501
|
}
|
|
4456
|
-
_createIcon(
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
}
|
|
4462
|
-
else if (this._isLoading && showLoading) {
|
|
4463
|
-
// Status nodes, or nodes without expander (< minExpandLevel) should
|
|
4464
|
-
// display the 'loading' status with the i.wb-icon span
|
|
4465
|
-
icon = iconMap.loading;
|
|
4466
|
-
}
|
|
4467
|
-
if (icon === false) {
|
|
4468
|
-
return null; // explicitly disabled: don't try default icons
|
|
4469
|
-
}
|
|
4470
|
-
if (typeof icon === "string") ;
|
|
4471
|
-
else if (this.statusNodeType) {
|
|
4472
|
-
icon = iconMap[this.statusNodeType];
|
|
4473
|
-
}
|
|
4474
|
-
else if (this.expanded) {
|
|
4475
|
-
icon = iconMap.folderOpen;
|
|
4476
|
-
}
|
|
4477
|
-
else if (this.children) {
|
|
4478
|
-
icon = iconMap.folder;
|
|
4479
|
-
}
|
|
4480
|
-
else if (this.lazy) {
|
|
4481
|
-
icon = iconMap.folderLazy;
|
|
4482
|
-
}
|
|
4483
|
-
else {
|
|
4484
|
-
icon = iconMap.doc;
|
|
4485
|
-
}
|
|
4486
|
-
// this.log("_createIcon: " + icon);
|
|
4487
|
-
if (!icon) {
|
|
4488
|
-
iconSpan = document.createElement("i");
|
|
4489
|
-
iconSpan.className = "wb-icon";
|
|
4490
|
-
}
|
|
4491
|
-
else if (icon.indexOf("<") >= 0) {
|
|
4492
|
-
// HTML
|
|
4493
|
-
iconSpan = elemFromHtml(icon);
|
|
4494
|
-
}
|
|
4495
|
-
else if (TEST_IMG.test(icon)) {
|
|
4496
|
-
// Image URL
|
|
4497
|
-
iconSpan = elemFromHtml(`<i class="wb-icon" style="background-image: url('${icon}');">`);
|
|
4498
|
-
}
|
|
4499
|
-
else {
|
|
4500
|
-
// Class name
|
|
4501
|
-
iconSpan = document.createElement("i");
|
|
4502
|
-
iconSpan.className = "wb-icon " + icon;
|
|
4503
|
-
}
|
|
4504
|
-
if (replaceChild) {
|
|
4505
|
-
parentElem.replaceChild(iconSpan, replaceChild);
|
|
4506
|
-
}
|
|
4507
|
-
else {
|
|
4508
|
-
parentElem.appendChild(iconSpan);
|
|
4509
|
-
}
|
|
4510
|
-
// Event handler `tree.iconBadge` can return a badge text or HTMLSpanElement
|
|
4511
|
-
const cbRes = this._callEvent("iconBadge", { iconSpan: iconSpan });
|
|
4512
|
-
let badge = null;
|
|
4513
|
-
if (cbRes != null && cbRes !== false) {
|
|
4514
|
-
let classes = "";
|
|
4515
|
-
let tooltip = "";
|
|
4516
|
-
if (isPlainObject(cbRes)) {
|
|
4517
|
-
badge = "" + cbRes.badge;
|
|
4518
|
-
classes = cbRes.badgeClass ? " " + cbRes.badgeClass : "";
|
|
4519
|
-
tooltip = cbRes.badgeTooltip ? ` title="${cbRes.badgeTooltip}"` : "";
|
|
4520
|
-
}
|
|
4521
|
-
else if (typeof cbRes === "number") {
|
|
4522
|
-
badge = "" + cbRes;
|
|
4502
|
+
_createIcon(parentElem, replaceChild, showLoading) {
|
|
4503
|
+
const iconElem = this.tree._createNodeIcon(this, showLoading, true);
|
|
4504
|
+
if (iconElem) {
|
|
4505
|
+
if (replaceChild) {
|
|
4506
|
+
parentElem.replaceChild(iconElem, replaceChild);
|
|
4523
4507
|
}
|
|
4524
4508
|
else {
|
|
4525
|
-
|
|
4526
|
-
}
|
|
4527
|
-
if (typeof badge === "string") {
|
|
4528
|
-
badge = elemFromHtml(`<span class="wb-badge${classes}"${tooltip}>${escapeHtml(badge)}</span>`);
|
|
4529
|
-
}
|
|
4530
|
-
if (badge) {
|
|
4531
|
-
iconSpan.append(badge);
|
|
4509
|
+
parentElem.appendChild(iconElem);
|
|
4532
4510
|
}
|
|
4533
4511
|
}
|
|
4534
|
-
|
|
4535
|
-
return iconSpan;
|
|
4512
|
+
return iconElem;
|
|
4536
4513
|
}
|
|
4537
4514
|
/**
|
|
4538
4515
|
* Create a whole new `<div class="wb-row">` element.
|
|
@@ -4587,7 +4564,7 @@
|
|
|
4587
4564
|
}
|
|
4588
4565
|
// Render the icon (show a 'loading' icon if we do not have an expander that
|
|
4589
4566
|
// we would prefer).
|
|
4590
|
-
const iconSpan = this._createIcon(
|
|
4567
|
+
const iconSpan = this._createIcon(nodeElem, null, !expanderSpan);
|
|
4591
4568
|
if (iconSpan) {
|
|
4592
4569
|
ofsTitlePx += ICON_WIDTH;
|
|
4593
4570
|
}
|
|
@@ -4819,7 +4796,7 @@
|
|
|
4819
4796
|
// Update icon (if not opts.isNew, which would rebuild markup anyway)
|
|
4820
4797
|
const iconSpan = nodeElem.querySelector("i.wb-icon");
|
|
4821
4798
|
if (iconSpan) {
|
|
4822
|
-
this._createIcon(
|
|
4799
|
+
this._createIcon(nodeElem, iconSpan, !expanderSpan);
|
|
4823
4800
|
}
|
|
4824
4801
|
}
|
|
4825
4802
|
// Adjust column width
|
|
@@ -5368,7 +5345,7 @@
|
|
|
5368
5345
|
assert(data.statusNodeType, "Not a status node");
|
|
5369
5346
|
assert(!firstChild || !firstChild.isStatusNode(), "Child must not be a status node");
|
|
5370
5347
|
statusNode = this.addNode(data, "prependChild");
|
|
5371
|
-
statusNode.match =
|
|
5348
|
+
statusNode.match = -1; // Mark as 'match' to avoid hiding
|
|
5372
5349
|
tree.update(ChangeType.structure);
|
|
5373
5350
|
return statusNode;
|
|
5374
5351
|
};
|
|
@@ -5660,7 +5637,7 @@
|
|
|
5660
5637
|
/*!
|
|
5661
5638
|
* Wunderbaum - ext-edit
|
|
5662
5639
|
* Copyright (c) 2021-2025, Martin Wendt. Released under the MIT license.
|
|
5663
|
-
* v0.
|
|
5640
|
+
* v0.13.0, Sat, 08 Mar 2025 14:16:31 GMT (https://github.com/mar10/wunderbaum)
|
|
5664
5641
|
*/
|
|
5665
5642
|
// const START_MARKER = "\uFFF7";
|
|
5666
5643
|
class EditExtension extends WunderbaumExtension {
|
|
@@ -5979,7 +5956,7 @@
|
|
|
5979
5956
|
newNode.setClass("wb-edit-new");
|
|
5980
5957
|
this.relatedNode = node;
|
|
5981
5958
|
// Don't filter new nodes:
|
|
5982
|
-
newNode.match =
|
|
5959
|
+
newNode.match = -1;
|
|
5983
5960
|
newNode.makeVisible({ noAnimation: true }).then(() => {
|
|
5984
5961
|
this.startEditTitle(newNode);
|
|
5985
5962
|
});
|
|
@@ -5995,8 +5972,8 @@
|
|
|
5995
5972
|
* https://github.com/mar10/wunderbaum
|
|
5996
5973
|
*
|
|
5997
5974
|
* Released under the MIT license.
|
|
5998
|
-
* @version v0.
|
|
5999
|
-
* @date Sat,
|
|
5975
|
+
* @version v0.13.0
|
|
5976
|
+
* @date Sat, 08 Mar 2025 14:16:31 GMT
|
|
6000
5977
|
*/
|
|
6001
5978
|
// import "./wunderbaum.scss";
|
|
6002
5979
|
class WbSystemRoot extends WunderbaumNode {
|
|
@@ -6057,6 +6034,9 @@
|
|
|
6057
6034
|
// --- SELECT ---
|
|
6058
6035
|
// /** @internal */
|
|
6059
6036
|
// public selectRangeAnchor: WunderbaumNode | null = null;
|
|
6037
|
+
// --- BREADCRUMB ---
|
|
6038
|
+
/** Filter options (used as defaults for calls to {@link Wunderbaum.filterNodes} ) */
|
|
6039
|
+
this.breadcrumb = null;
|
|
6060
6040
|
// --- FILTER ---
|
|
6061
6041
|
/** Filter options (used as defaults for calls to {@link Wunderbaum.filterNodes} ) */
|
|
6062
6042
|
this.filterMode = null;
|
|
@@ -6091,10 +6071,10 @@
|
|
|
6091
6071
|
emptyChildListExpandable: false,
|
|
6092
6072
|
// updateThrottleWait: 200,
|
|
6093
6073
|
skeleton: false,
|
|
6094
|
-
connectTopBreadcrumb: null,
|
|
6074
|
+
connectTopBreadcrumb: null,
|
|
6095
6075
|
selectMode: "multi", // SelectModeType
|
|
6096
6076
|
// --- KeyNav ---
|
|
6097
|
-
navigationModeOption: null, // NavModeEnum
|
|
6077
|
+
navigationModeOption: null, // NavModeEnum,
|
|
6098
6078
|
quicksearch: true,
|
|
6099
6079
|
// --- Events ---
|
|
6100
6080
|
iconBadge: null,
|
|
@@ -6106,8 +6086,11 @@
|
|
|
6106
6086
|
strings: {
|
|
6107
6087
|
loadError: "Error",
|
|
6108
6088
|
loading: "Loading...",
|
|
6109
|
-
// loading: "Loading…",
|
|
6110
6089
|
noData: "No data",
|
|
6090
|
+
breadcrumbDelimiter: " » ",
|
|
6091
|
+
queryResult: "Found ${matches} of ${count}",
|
|
6092
|
+
noMatch: "No results",
|
|
6093
|
+
matchIndex: "${match} of ${matches}",
|
|
6111
6094
|
},
|
|
6112
6095
|
}, options));
|
|
6113
6096
|
const readyDeferred = new Deferred();
|
|
@@ -6213,6 +6196,19 @@
|
|
|
6213
6196
|
this.headerElement =
|
|
6214
6197
|
this.element.querySelector("div.wb-header");
|
|
6215
6198
|
this.element.classList.toggle("wb-grid", this.columns.length > 1);
|
|
6199
|
+
if (this.options.connectTopBreadcrumb) {
|
|
6200
|
+
this.breadcrumb = elemFromSelector(this.options.connectTopBreadcrumb);
|
|
6201
|
+
assert(!this.breadcrumb || this.breadcrumb.innerHTML != null, `Invalid 'connectTopBreadcrumb' option: ${this.breadcrumb}.`);
|
|
6202
|
+
this.breadcrumb.addEventListener("click", (e) => {
|
|
6203
|
+
// const node = Wunderbaum.getNode(e)!;
|
|
6204
|
+
const elem = e.target;
|
|
6205
|
+
if (elem && elem.matches("a.wb-breadcrumb")) {
|
|
6206
|
+
const node = this.keyMap.get(elem.dataset.key);
|
|
6207
|
+
node === null || node === void 0 ? void 0 : node.setActive();
|
|
6208
|
+
e.preventDefault();
|
|
6209
|
+
}
|
|
6210
|
+
});
|
|
6211
|
+
}
|
|
6216
6212
|
this._initExtensions();
|
|
6217
6213
|
// --- apply initial options
|
|
6218
6214
|
["enabled", "fixedCol"].forEach((optName) => {
|
|
@@ -6576,7 +6572,10 @@
|
|
|
6576
6572
|
});
|
|
6577
6573
|
return node;
|
|
6578
6574
|
}
|
|
6579
|
-
/** Return the topmost visible node in the viewport.
|
|
6575
|
+
/** Return the topmost visible node in the viewport.
|
|
6576
|
+
* @param complete If `false`, the node is considered visible if at least one
|
|
6577
|
+
* pixel is visible.
|
|
6578
|
+
*/
|
|
6580
6579
|
getTopmostVpNode(complete = true) {
|
|
6581
6580
|
const rowHeight = this.options.rowHeightPx;
|
|
6582
6581
|
const gracePx = 1; // ignore subpixel scrolling
|
|
@@ -6609,24 +6608,19 @@
|
|
|
6609
6608
|
bottomIdx = Math.min(bottomIdx, this.count(true) - 1);
|
|
6610
6609
|
return this._getNodeByRowIdx(bottomIdx);
|
|
6611
6610
|
}
|
|
6612
|
-
/** Return
|
|
6613
|
-
|
|
6611
|
+
/** Return following visible node in the viewport. */
|
|
6612
|
+
_getNextNodeInView(node, options) {
|
|
6613
|
+
let ofs = (options === null || options === void 0 ? void 0 : options.ofs) || 1;
|
|
6614
|
+
const reverse = !!(options === null || options === void 0 ? void 0 : options.reverse);
|
|
6614
6615
|
this.visitRows((n) => {
|
|
6615
6616
|
node = n;
|
|
6616
|
-
if (
|
|
6617
|
+
if ((options === null || options === void 0 ? void 0 : options.cb) && options.cb(n)) {
|
|
6617
6618
|
return false;
|
|
6618
6619
|
}
|
|
6619
|
-
}, { reverse: true, start: node || this.getActiveNode() });
|
|
6620
|
-
return node;
|
|
6621
|
-
}
|
|
6622
|
-
/** Return following visible node in the viewport. */
|
|
6623
|
-
_getNextNodeInView(node, ofs = 1) {
|
|
6624
|
-
this.visitRows((n) => {
|
|
6625
|
-
node = n;
|
|
6626
6620
|
if (ofs-- <= 0) {
|
|
6627
6621
|
return false;
|
|
6628
6622
|
}
|
|
6629
|
-
}, { reverse:
|
|
6623
|
+
}, { reverse: reverse, start: node || this.getActiveNode() });
|
|
6630
6624
|
return node;
|
|
6631
6625
|
}
|
|
6632
6626
|
/**
|
|
@@ -6746,9 +6740,11 @@
|
|
|
6746
6740
|
case "first":
|
|
6747
6741
|
case "last":
|
|
6748
6742
|
case "left":
|
|
6743
|
+
case "nextMatch":
|
|
6749
6744
|
case "pageDown":
|
|
6750
6745
|
case "pageUp":
|
|
6751
6746
|
case "parent":
|
|
6747
|
+
case "prevMatch":
|
|
6752
6748
|
case "right":
|
|
6753
6749
|
case "up":
|
|
6754
6750
|
return node.navigate(cmd);
|
|
@@ -6940,6 +6936,11 @@
|
|
|
6940
6936
|
count(visible = false) {
|
|
6941
6937
|
return visible ? this.treeRowCount : this.keyMap.size;
|
|
6942
6938
|
}
|
|
6939
|
+
/** Return the number of *unique* nodes in the data model, i.e. unique `node.refKey`.
|
|
6940
|
+
*/
|
|
6941
|
+
countUnique() {
|
|
6942
|
+
return this.refKeyMap.size;
|
|
6943
|
+
}
|
|
6943
6944
|
/** @internal sanity check. */
|
|
6944
6945
|
_check() {
|
|
6945
6946
|
let i = 0;
|
|
@@ -6998,12 +6999,14 @@
|
|
|
6998
6999
|
* and wrap-around at the end.
|
|
6999
7000
|
* Used by quicksearch and keyboard navigation.
|
|
7000
7001
|
*/
|
|
7001
|
-
findNextNode(match, startNode) {
|
|
7002
|
+
findNextNode(match, startNode, reverse = false) {
|
|
7002
7003
|
//, visibleOnly) {
|
|
7003
7004
|
let res = null;
|
|
7004
7005
|
const firstNode = this.getFirstChild();
|
|
7006
|
+
// Last visible node (calculation is expensive, so do only if we need it):
|
|
7007
|
+
const lastNode = reverse ? this.findRelatedNode(firstNode, "last") : null;
|
|
7005
7008
|
const matcher = typeof match === "string" ? makeNodeTitleStartMatcher(match) : match;
|
|
7006
|
-
startNode = startNode || firstNode;
|
|
7009
|
+
startNode = startNode || (reverse ? lastNode : firstNode);
|
|
7007
7010
|
function _checkNode(n) {
|
|
7008
7011
|
// console.log("_check " + n)
|
|
7009
7012
|
if (matcher(n)) {
|
|
@@ -7016,12 +7019,14 @@
|
|
|
7016
7019
|
this.visitRows(_checkNode, {
|
|
7017
7020
|
start: startNode,
|
|
7018
7021
|
includeSelf: false,
|
|
7022
|
+
reverse: reverse,
|
|
7019
7023
|
});
|
|
7020
7024
|
// Wrap around search
|
|
7021
7025
|
if (!res && startNode !== firstNode) {
|
|
7022
7026
|
this.visitRows(_checkNode, {
|
|
7023
|
-
start: firstNode,
|
|
7027
|
+
start: reverse ? lastNode : firstNode,
|
|
7024
7028
|
includeSelf: true,
|
|
7029
|
+
reverse: reverse,
|
|
7025
7030
|
});
|
|
7026
7031
|
}
|
|
7027
7032
|
return res;
|
|
@@ -7088,7 +7093,7 @@
|
|
|
7088
7093
|
// }
|
|
7089
7094
|
break;
|
|
7090
7095
|
case "up":
|
|
7091
|
-
res = this.
|
|
7096
|
+
res = this._getNextNodeInView(node, { reverse: true });
|
|
7092
7097
|
break;
|
|
7093
7098
|
case "down":
|
|
7094
7099
|
res = this._getNextNodeInView(node);
|
|
@@ -7101,7 +7106,10 @@
|
|
|
7101
7106
|
res = bottomNode;
|
|
7102
7107
|
}
|
|
7103
7108
|
else {
|
|
7104
|
-
res = this._getNextNodeInView(node,
|
|
7109
|
+
res = this._getNextNodeInView(node, {
|
|
7110
|
+
reverse: false,
|
|
7111
|
+
ofs: pageSize,
|
|
7112
|
+
});
|
|
7105
7113
|
}
|
|
7106
7114
|
}
|
|
7107
7115
|
break;
|
|
@@ -7116,10 +7124,23 @@
|
|
|
7116
7124
|
res = topNode;
|
|
7117
7125
|
}
|
|
7118
7126
|
else {
|
|
7119
|
-
res = this.
|
|
7127
|
+
res = this._getNextNodeInView(node, {
|
|
7128
|
+
reverse: true,
|
|
7129
|
+
ofs: pageSize,
|
|
7130
|
+
});
|
|
7120
7131
|
}
|
|
7121
7132
|
}
|
|
7122
7133
|
break;
|
|
7134
|
+
case "prevMatch":
|
|
7135
|
+
// fallthrough
|
|
7136
|
+
case "nextMatch":
|
|
7137
|
+
if (!this.isFilterActive) {
|
|
7138
|
+
this.logWarn(`${where}: Filter is not active.`);
|
|
7139
|
+
break;
|
|
7140
|
+
}
|
|
7141
|
+
res = this.findNextNode((n) => n.isMatched(), node, where === "prevMatch");
|
|
7142
|
+
res === null || res === void 0 ? void 0 : res.setActive();
|
|
7143
|
+
break;
|
|
7123
7144
|
default:
|
|
7124
7145
|
this.logWarn("Unknown relation '" + where + "'.");
|
|
7125
7146
|
}
|
|
@@ -7181,6 +7202,12 @@
|
|
|
7181
7202
|
getFirstChild() {
|
|
7182
7203
|
return this.root.getFirstChild();
|
|
7183
7204
|
}
|
|
7205
|
+
/**
|
|
7206
|
+
* Return the last top level node if any (not the invisible root node).
|
|
7207
|
+
*/
|
|
7208
|
+
getLastChild() {
|
|
7209
|
+
return this.root.getLastChild();
|
|
7210
|
+
}
|
|
7184
7211
|
/**
|
|
7185
7212
|
* Return the node that currently has keyboard focus or null.
|
|
7186
7213
|
* Alias for {@link Wunderbaum.focusNode}.
|
|
@@ -7508,6 +7535,51 @@
|
|
|
7508
7535
|
_setFocusNode(node) {
|
|
7509
7536
|
this._focusNode = node;
|
|
7510
7537
|
}
|
|
7538
|
+
/** Return the current selection/expansion/activation status. @experimental */
|
|
7539
|
+
getState(options) {
|
|
7540
|
+
var _a, _b;
|
|
7541
|
+
let expandedKeys = undefined;
|
|
7542
|
+
if (options.expandedKeys !== false) {
|
|
7543
|
+
expandedKeys = [];
|
|
7544
|
+
for (const node of this) {
|
|
7545
|
+
if (node.expanded) {
|
|
7546
|
+
expandedKeys.push(node.key);
|
|
7547
|
+
}
|
|
7548
|
+
}
|
|
7549
|
+
}
|
|
7550
|
+
const state = {
|
|
7551
|
+
activeKey: (_b = (_a = this.activeNode) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : null,
|
|
7552
|
+
activeColIdx: this.activeColIdx,
|
|
7553
|
+
selectedKeys: options.selectedKeys === false
|
|
7554
|
+
? undefined
|
|
7555
|
+
: this.getSelectedNodes().flatMap((n) => n.key),
|
|
7556
|
+
expandedKeys: expandedKeys,
|
|
7557
|
+
};
|
|
7558
|
+
return state;
|
|
7559
|
+
}
|
|
7560
|
+
/** Apply selection/expansion/activation status. @experimental */
|
|
7561
|
+
setState(state, options) {
|
|
7562
|
+
this.runWithDeferredUpdate(() => {
|
|
7563
|
+
var _a, _b;
|
|
7564
|
+
if (state.selectedKeys) {
|
|
7565
|
+
this.selectAll(false);
|
|
7566
|
+
for (const key of state.selectedKeys) {
|
|
7567
|
+
(_a = this.findKey(key)) === null || _a === void 0 ? void 0 : _a.setSelected(true);
|
|
7568
|
+
}
|
|
7569
|
+
}
|
|
7570
|
+
if (state.expandedKeys) {
|
|
7571
|
+
for (const key of state.expandedKeys) {
|
|
7572
|
+
(_b = this.findKey(key)) === null || _b === void 0 ? void 0 : _b.setExpanded(true);
|
|
7573
|
+
}
|
|
7574
|
+
}
|
|
7575
|
+
if (state.activeKey) {
|
|
7576
|
+
this.setActiveNode(state.activeKey);
|
|
7577
|
+
}
|
|
7578
|
+
if (state.activeColIdx != null) {
|
|
7579
|
+
this.setColumn(state.activeColIdx);
|
|
7580
|
+
}
|
|
7581
|
+
});
|
|
7582
|
+
}
|
|
7511
7583
|
update(change, node, options) {
|
|
7512
7584
|
// this.log(`update(${change}) node=${node}`);
|
|
7513
7585
|
if (!(node instanceof WunderbaumNode)) {
|
|
@@ -7789,11 +7861,11 @@
|
|
|
7789
7861
|
// }
|
|
7790
7862
|
return modified;
|
|
7791
7863
|
}
|
|
7792
|
-
_insertIcon(icon, elem) {
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
}
|
|
7864
|
+
// protected _insertIcon(icon: string, elem: HTMLElement) {
|
|
7865
|
+
// const iconElem = document.createElement("i");
|
|
7866
|
+
// iconElem.className = icon;
|
|
7867
|
+
// elem.appendChild(iconElem);
|
|
7868
|
+
// }
|
|
7797
7869
|
/** Create/update header markup from `this.columns` definition.
|
|
7798
7870
|
* @internal
|
|
7799
7871
|
*/
|
|
@@ -7891,6 +7963,104 @@
|
|
|
7891
7963
|
this._updateViewportImmediately();
|
|
7892
7964
|
}
|
|
7893
7965
|
}
|
|
7966
|
+
/** @internal */
|
|
7967
|
+
_createNodeIcon(node, showLoading, showBadge) {
|
|
7968
|
+
const iconMap = this.iconMap;
|
|
7969
|
+
let iconElem;
|
|
7970
|
+
let icon = node.getOption("icon");
|
|
7971
|
+
if (node._errorInfo) {
|
|
7972
|
+
icon = iconMap.error;
|
|
7973
|
+
}
|
|
7974
|
+
else if (node._isLoading && showLoading) {
|
|
7975
|
+
// Status nodes, or nodes without expander (< minExpandLevel) should
|
|
7976
|
+
// display the 'loading' status with the i.wb-icon span
|
|
7977
|
+
icon = iconMap.loading;
|
|
7978
|
+
}
|
|
7979
|
+
if (icon === false) {
|
|
7980
|
+
return null; // explicitly disabled: don't try default icons
|
|
7981
|
+
}
|
|
7982
|
+
if (typeof icon === "string") ;
|
|
7983
|
+
else if (node.statusNodeType) {
|
|
7984
|
+
icon = iconMap[node.statusNodeType];
|
|
7985
|
+
}
|
|
7986
|
+
else if (node.expanded) {
|
|
7987
|
+
icon = iconMap.folderOpen;
|
|
7988
|
+
}
|
|
7989
|
+
else if (node.children) {
|
|
7990
|
+
icon = iconMap.folder;
|
|
7991
|
+
}
|
|
7992
|
+
else if (node.lazy) {
|
|
7993
|
+
icon = iconMap.folderLazy;
|
|
7994
|
+
}
|
|
7995
|
+
else {
|
|
7996
|
+
icon = iconMap.doc;
|
|
7997
|
+
}
|
|
7998
|
+
if (!icon) {
|
|
7999
|
+
iconElem = document.createElement("i");
|
|
8000
|
+
iconElem.className = "wb-icon";
|
|
8001
|
+
}
|
|
8002
|
+
else if (icon.indexOf("<") >= 0) {
|
|
8003
|
+
// HTML
|
|
8004
|
+
iconElem = elemFromHtml(icon);
|
|
8005
|
+
}
|
|
8006
|
+
else if (TEST_IMG.test(icon)) {
|
|
8007
|
+
// Image URL
|
|
8008
|
+
iconElem = elemFromHtml(`<i class="wb-icon" style="background-image: url('${icon}');">`);
|
|
8009
|
+
}
|
|
8010
|
+
else {
|
|
8011
|
+
// Class name
|
|
8012
|
+
iconElem = document.createElement("i");
|
|
8013
|
+
iconElem.className = "wb-icon " + icon;
|
|
8014
|
+
}
|
|
8015
|
+
// Event handler `tree.iconBadge` can return a badge text or HTMLSpanElement
|
|
8016
|
+
const cbRes = showBadge && node._callEvent("iconBadge", { iconSpan: iconElem });
|
|
8017
|
+
let badge = null;
|
|
8018
|
+
if (cbRes != null && cbRes !== false) {
|
|
8019
|
+
let classes = "";
|
|
8020
|
+
let tooltip = "";
|
|
8021
|
+
if (isPlainObject(cbRes)) {
|
|
8022
|
+
badge = "" + cbRes.badge;
|
|
8023
|
+
classes = cbRes.badgeClass ? " " + cbRes.badgeClass : "";
|
|
8024
|
+
tooltip = cbRes.badgeTooltip ? ` title="${cbRes.badgeTooltip}"` : "";
|
|
8025
|
+
}
|
|
8026
|
+
else if (typeof cbRes === "number") {
|
|
8027
|
+
badge = "" + cbRes;
|
|
8028
|
+
}
|
|
8029
|
+
else {
|
|
8030
|
+
badge = cbRes; // string or HTMLSpanElement
|
|
8031
|
+
}
|
|
8032
|
+
if (typeof badge === "string") {
|
|
8033
|
+
badge = elemFromHtml(`<span class="wb-badge${classes}"${tooltip}>${escapeHtml(badge)}</span>`);
|
|
8034
|
+
}
|
|
8035
|
+
if (badge) {
|
|
8036
|
+
iconElem.append(badge);
|
|
8037
|
+
}
|
|
8038
|
+
}
|
|
8039
|
+
return iconElem;
|
|
8040
|
+
}
|
|
8041
|
+
_updateTopBreadcrumb() {
|
|
8042
|
+
const breadcrumb = this.breadcrumb;
|
|
8043
|
+
const topmost = this.getTopmostVpNode(true);
|
|
8044
|
+
const parentList = topmost === null || topmost === void 0 ? void 0 : topmost.getParentList(false, false);
|
|
8045
|
+
if (parentList === null || parentList === void 0 ? void 0 : parentList.length) {
|
|
8046
|
+
breadcrumb.innerHTML = "";
|
|
8047
|
+
for (const n of topmost.getParentList(false, false)) {
|
|
8048
|
+
const icon = this._createNodeIcon(n, false, false);
|
|
8049
|
+
if (icon) {
|
|
8050
|
+
breadcrumb.append(icon, " ");
|
|
8051
|
+
}
|
|
8052
|
+
const part = document.createElement("a");
|
|
8053
|
+
part.textContent = n.title;
|
|
8054
|
+
part.href = "#";
|
|
8055
|
+
part.classList.add("wb-breadcrumb");
|
|
8056
|
+
part.dataset.key = n.key;
|
|
8057
|
+
breadcrumb.append(part, this.options.strings.breadcrumbDelimiter);
|
|
8058
|
+
}
|
|
8059
|
+
}
|
|
8060
|
+
else {
|
|
8061
|
+
breadcrumb.innerHTML = " ";
|
|
8062
|
+
}
|
|
8063
|
+
}
|
|
7894
8064
|
/**
|
|
7895
8065
|
* This is the actual update method, which is wrapped inside a throttle method.
|
|
7896
8066
|
* It calls `updateColumns()` and `_updateRows()`.
|
|
@@ -7901,7 +8071,6 @@
|
|
|
7901
8071
|
* @internal
|
|
7902
8072
|
*/
|
|
7903
8073
|
_updateViewportImmediately() {
|
|
7904
|
-
var _a;
|
|
7905
8074
|
if (this._disableUpdateCount) {
|
|
7906
8075
|
this.log(`_updateViewportImmediately() IGNORED (disable level: ${this._disableUpdateCount}).`);
|
|
7907
8076
|
this._disableUpdateIgnoreCount++;
|
|
@@ -7948,11 +8117,8 @@
|
|
|
7948
8117
|
this._updateRows();
|
|
7949
8118
|
// console.profileEnd(`_updateViewportImmediately()`)
|
|
7950
8119
|
}
|
|
7951
|
-
if (this.
|
|
7952
|
-
|
|
7953
|
-
let path = (_a = this.getTopmostVpNode(true)) === null || _a === void 0 ? void 0 : _a.getPath(false, "title", " > ");
|
|
7954
|
-
path = path ? path + " >" : "";
|
|
7955
|
-
this.options.connectTopBreadcrumb.textContent = path;
|
|
8120
|
+
if (this.breadcrumb) {
|
|
8121
|
+
this._updateTopBreadcrumb();
|
|
7956
8122
|
}
|
|
7957
8123
|
this._callEvent("update");
|
|
7958
8124
|
}
|
|
@@ -8321,7 +8487,7 @@
|
|
|
8321
8487
|
}
|
|
8322
8488
|
Wunderbaum.sequence = 0;
|
|
8323
8489
|
/** Wunderbaum release version number "MAJOR.MINOR.PATCH". */
|
|
8324
|
-
Wunderbaum.version = "v0.
|
|
8490
|
+
Wunderbaum.version = "v0.13.0"; // Set to semver by 'grunt release'
|
|
8325
8491
|
/** Expose some useful methods of the util.ts module as `Wunderbaum.util`. */
|
|
8326
8492
|
Wunderbaum.util = util;
|
|
8327
8493
|
|