wunderbaum 0.0.6 → 0.0.7

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.
@@ -153,7 +153,7 @@ declare module "util" {
153
153
  * @param handler
154
154
  */
155
155
  export function onEvent(rootTarget: EventTarget | string, eventNames: string, selector: string, handler: EventCallbackType): void;
156
- /** Return a wrapped handler method, that provides `this._super`.
156
+ /** Return a wrapped handler method, that provides `this._super` and `this._superApply`.
157
157
  *
158
158
  * ```ts
159
159
  // Implement `opts.createNode` event to add the 'draggable' attribute
@@ -224,13 +224,32 @@ declare module "common" {
224
224
  */
225
225
  import { MatcherType } from "types";
226
226
  export const DEFAULT_DEBUGLEVEL = 4;
227
+ /**
228
+ * Fixed height of a row in pixel. Must match the SCSS variable `$row-outer-height`.
229
+ */
227
230
  export const ROW_HEIGHT = 22;
231
+ /**
232
+ * Fixed width of node icons in pixel. Must match the SCSS variable `$icon-outer-width`.
233
+ */
228
234
  export const ICON_WIDTH = 20;
229
- export const ROW_EXTRA_PAD = 7;
230
- export const RENDER_MIN_PREFETCH = 5;
235
+ /**
236
+ * Adjust the width of the title span, so overflow ellipsis work.
237
+ * (2 x `$col-padding-x` + 3px rounding errors).
238
+ */
239
+ export const TITLE_SPAN_PAD_Y = 7;
240
+ /** Render row markup for N nodes above and below the visible viewport. */
231
241
  export const RENDER_MAX_PREFETCH = 5;
242
+ /** Skip rendering new rows when we have at least N nodes rendeed above and below the viewport. */
243
+ export const RENDER_MIN_PREFETCH = 5;
244
+ /** Regular expression to detect if a string describes an image URL (in contrast
245
+ * to a class name). Strings are considered image urls if they contain '.' or '/'.
246
+ */
232
247
  export const TEST_IMG: RegExp;
233
- export let iconMap: {
248
+ /**
249
+ * Default node icons.
250
+ * Requires bootstrap icons https://icons.getbootstrap.com
251
+ */
252
+ export const iconMap: {
234
253
  error: string;
235
254
  loading: string;
236
255
  noData: string;
@@ -245,6 +264,7 @@ declare module "common" {
245
264
  radioUnknown: string;
246
265
  folder: string;
247
266
  folderOpen: string;
267
+ folderLazy: string;
248
268
  doc: string;
249
269
  };
250
270
  export const KEY_NODATA = "__not_found__";
@@ -255,8 +275,6 @@ declare module "common" {
255
275
  };
256
276
  /** Dict keys that are evaluated by source loader (others are added to `tree.data` instead). */
257
277
  export const RESERVED_TREE_SOURCE_KEYS: Set<string>;
258
- /** Key codes that trigger grid navigation, even when inside an input element. */
259
- export const INPUT_BREAKOUT_KEYS: Set<string>;
260
278
  /** Map `KeyEvent.key` to navigation action. */
261
279
  export const KEY_TO_ACTION_DICT: {
262
280
  [key: string]: string;
@@ -818,7 +836,7 @@ declare module "wb_node" {
818
836
  * whether the node is scrolled into the visible part of the screen or viewport.
819
837
  */
820
838
  isVisible(): boolean;
821
- protected _loadSourceObject(source: any): void;
839
+ protected _loadSourceObject(source: any, level?: number): void;
822
840
  /** Download data from the cloud, then call `.update()`. */
823
841
  load(source: any): Promise<void>;
824
842
  /**Load content of a lazy node. */
@@ -1998,6 +2016,9 @@ declare module "wunderbaum" {
1998
2016
  logWarn(...args: any[]): void;
1999
2017
  /**
2000
2018
  * Make sure that this node is vertically scrolled into the viewport.
2019
+ *
2020
+ * Nodes that are above the visible area become the top row, nodes that are
2021
+ * below the viewport become the bottom row.
2001
2022
  */
2002
2023
  scrollTo(nodeOrOpts: ScrollToOptions | WunderbaumNode): void;
2003
2024
  /**
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * Wunderbaum - util
3
3
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
4
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
4
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
5
5
  */
6
6
  /** @module util */
7
7
  /** Readable names for `MouseEvent.button` */
@@ -460,7 +460,7 @@ function onEvent(rootTarget, eventNames, selectorOrHandler, handlerOrNone) {
460
460
  });
461
461
  });
462
462
  }
463
- /** Return a wrapped handler method, that provides `this._super`.
463
+ /** Return a wrapped handler method, that provides `this._super` and `this._superApply`.
464
464
  *
465
465
  * ```ts
466
466
  // Implement `opts.createNode` event to add the 'draggable' attribute
@@ -701,7 +701,7 @@ var util = /*#__PURE__*/Object.freeze({
701
701
  /*!
702
702
  * Wunderbaum - types
703
703
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
704
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
704
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
705
705
  */
706
706
  /** Possible values for `setModified()`. */
707
707
  var ChangeType;
@@ -753,7 +753,7 @@ var NavigationOptions;
753
753
  /*!
754
754
  * Wunderbaum - wb_extension_base
755
755
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
756
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
756
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
757
757
  */
758
758
  class WunderbaumExtension {
759
759
  constructor(tree, id, defaults) {
@@ -1044,7 +1044,7 @@ function debounce(func, wait = 0, options = {}) {
1044
1044
  /*!
1045
1045
  * Wunderbaum - ext-filter
1046
1046
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
1047
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
1047
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
1048
1048
  */
1049
1049
  const START_MARKER = "\uFFF7";
1050
1050
  const END_MARKER = "\uFFF8";
@@ -1346,107 +1346,10 @@ function _markFuzzyMatchedChars(text, matches, escapeTitles = true) {
1346
1346
  return textPoses.join("");
1347
1347
  }
1348
1348
 
1349
- /*!
1350
- * Wunderbaum - common
1351
- * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
1352
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
1353
- */
1354
- const DEFAULT_DEBUGLEVEL = 4; // Replaced by rollup script
1355
- const ROW_HEIGHT = 22;
1356
- // export const HEADER_HEIGHT = ROW_HEIGHT;
1357
- const ICON_WIDTH = 20;
1358
- const ROW_EXTRA_PAD = 7; // 2x $col-padding-x + 3px rounding errors
1359
- const RENDER_MAX_PREFETCH = 5;
1360
- const TEST_IMG = new RegExp(/\.|\//); // strings are considered image urls if they contain '.' or '/'
1361
- // export const RECURSIVE_REQUEST_ERROR = "$recursive_request";
1362
- // export const INVALID_REQUEST_TARGET_ERROR = "$request_target_invalid";
1363
- let iconMap = {
1364
- error: "bi bi-exclamation-triangle",
1365
- // loading: "bi bi-hourglass-split wb-busy",
1366
- loading: "bi bi-chevron-right wb-busy",
1367
- // loading: "bi bi-arrow-repeat wb-spin",
1368
- // loading: '<div class="spinner-border spinner-border-sm" role="status"> <span class="visually-hidden">Loading...</span> </div>',
1369
- // noData: "bi bi-search",
1370
- noData: "bi bi-question-circle",
1371
- expanderExpanded: "bi bi-chevron-down",
1372
- // expanderExpanded: "bi bi-dash-square",
1373
- expanderCollapsed: "bi bi-chevron-right",
1374
- // expanderCollapsed: "bi bi-plus-square",
1375
- expanderLazy: "bi bi-chevron-right wb-helper-lazy-expander",
1376
- // expanderLazy: "bi bi-chevron-bar-right",
1377
- checkChecked: "bi bi-check-square",
1378
- checkUnchecked: "bi bi-square",
1379
- checkUnknown: "bi dash-square-dotted",
1380
- radioChecked: "bi bi-circle-fill",
1381
- radioUnchecked: "bi bi-circle",
1382
- radioUnknown: "bi bi-circle-dotted",
1383
- folder: "bi bi-folder2",
1384
- folderOpen: "bi bi-folder2-open",
1385
- doc: "bi bi-file-earmark",
1386
- };
1387
- /** Dict keys that are evaluated by source loader (others are added to `tree.data` instead). */
1388
- const RESERVED_TREE_SOURCE_KEYS = new Set([
1389
- "children",
1390
- "columns",
1391
- "format",
1392
- "keyMap",
1393
- "positional",
1394
- "typeList",
1395
- "types",
1396
- "version", // reserved for future use
1397
- ]);
1398
- /** Key codes that trigger grid navigation, even when inside an input element. */
1399
- const INPUT_BREAKOUT_KEYS = new Set([
1400
- // "ArrowDown",
1401
- // "ArrowUp",
1402
- "Enter",
1403
- "Escape",
1404
- ]);
1405
- /** Map `KeyEvent.key` to navigation action. */
1406
- const KEY_TO_ACTION_DICT = {
1407
- " ": "toggleSelect",
1408
- "+": "expand",
1409
- Add: "expand",
1410
- ArrowDown: "down",
1411
- ArrowLeft: "left",
1412
- ArrowRight: "right",
1413
- ArrowUp: "up",
1414
- Backspace: "parent",
1415
- "/": "collapseAll",
1416
- Divide: "collapseAll",
1417
- End: "lastCol",
1418
- Home: "firstCol",
1419
- "Control+End": "last",
1420
- "Control+Home": "first",
1421
- "Meta+ArrowDown": "last",
1422
- "Meta+ArrowUp": "first",
1423
- "*": "expandAll",
1424
- Multiply: "expandAll",
1425
- PageDown: "pageDown",
1426
- PageUp: "pageUp",
1427
- "-": "collapse",
1428
- Subtract: "collapse",
1429
- };
1430
- /** Return a callback that returns true if the node title contains a substring (case-insensitive). */
1431
- function makeNodeTitleMatcher(s) {
1432
- s = escapeRegex(s.toLowerCase());
1433
- return function (node) {
1434
- return node.title.toLowerCase().indexOf(s) >= 0;
1435
- };
1436
- }
1437
- /** Return a callback that returns true if the node title starts with a string (case-insensitive). */
1438
- function makeNodeTitleStartMatcher(s) {
1439
- s = escapeRegex(s);
1440
- const reMatch = new RegExp("^" + s, "i");
1441
- return function (node) {
1442
- return reMatch.test(node.title);
1443
- };
1444
- }
1445
-
1446
1349
  /*!
1447
1350
  * Wunderbaum - ext-keynav
1448
1351
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
1449
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
1352
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
1450
1353
  */
1451
1354
  const QUICKSEARCH_DELAY = 500;
1452
1355
  class KeynavExtension extends WunderbaumExtension {
@@ -1480,7 +1383,7 @@ class KeynavExtension extends WunderbaumExtension {
1480
1383
  const event = data.event, tree = this.tree, opts = data.options, activate = !event.ctrlKey || opts.autoActivate, curInput = this._getEmbeddedInputElem(event.target), navModeOption = opts.navigationModeOption;
1481
1384
  // isCellEditMode = tree.navMode === NavigationMode.cellEdit;
1482
1385
  let focusNode, eventName = eventToString(event), node = data.node, handled = true;
1483
- tree.log(`onKeyEvent: ${eventName}, curInput`, curInput);
1386
+ // tree.log(`onKeyEvent: ${eventName}, curInput`, curInput);
1484
1387
  if (!tree.isEnabled()) {
1485
1388
  // tree.logDebug(`onKeyEvent ignored for disabled tree: ${eventName}`);
1486
1389
  return false;
@@ -1603,10 +1506,11 @@ class KeynavExtension extends WunderbaumExtension {
1603
1506
  if (eventName === "Escape") {
1604
1507
  // Discard changes
1605
1508
  node.render();
1509
+ // } else if (!INPUT_BREAKOUT_KEYS.has(eventName)) {
1606
1510
  }
1607
- else if (!INPUT_BREAKOUT_KEYS.has(eventName)) {
1511
+ else if (eventName !== "Enter") {
1608
1512
  // Let current `<input>` handle it
1609
- node.logDebug(`Ignored ${eventName} inside input`);
1513
+ node.logDebug(`Ignored ${eventName} inside focused input`);
1610
1514
  return;
1611
1515
  }
1612
1516
  // const curInputType = curInput.type || curInput.tagName;
@@ -1677,24 +1581,24 @@ class KeynavExtension extends WunderbaumExtension {
1677
1581
  if (isColspan && node.isExpanded()) {
1678
1582
  node.setExpanded(false);
1679
1583
  }
1680
- else if (tree.activeColIdx > 0) {
1584
+ else if (!isColspan && tree.activeColIdx > 0) {
1681
1585
  tree.setColumn(tree.activeColIdx - 1);
1682
- handled = true;
1683
1586
  }
1684
1587
  else if (navModeOption !== NavigationOptions.cell) {
1685
1588
  tree.setCellNav(false); // row-nav mode
1686
- handled = true;
1687
1589
  }
1590
+ handled = true;
1688
1591
  break;
1689
1592
  case "ArrowRight":
1690
1593
  tree.setFocus(); // Blur prev. input if any
1691
1594
  if (isColspan && !node.isExpanded()) {
1692
1595
  node.setExpanded();
1693
1596
  }
1694
- else if (tree.activeColIdx < tree.columns.length - 1) {
1597
+ else if (!isColspan &&
1598
+ tree.activeColIdx < tree.columns.length - 1) {
1695
1599
  tree.setColumn(tree.activeColIdx + 1);
1696
- handled = true;
1697
1600
  }
1601
+ handled = true;
1698
1602
  break;
1699
1603
  case "ArrowDown":
1700
1604
  case "ArrowUp":
@@ -1727,7 +1631,7 @@ class KeynavExtension extends WunderbaumExtension {
1727
1631
  /*!
1728
1632
  * Wunderbaum - ext-logger
1729
1633
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
1730
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
1634
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
1731
1635
  */
1732
1636
  class LoggerExtension extends WunderbaumExtension {
1733
1637
  constructor(tree) {
@@ -1750,7 +1654,7 @@ class LoggerExtension extends WunderbaumExtension {
1750
1654
  if (ignoreEvents.has(name)) {
1751
1655
  return tree._superApply(arguments);
1752
1656
  }
1753
- let start = Date.now();
1657
+ const start = Date.now();
1754
1658
  const res = tree._superApply(arguments);
1755
1659
  console.debug(`${prefix}: callEvent('${name}') took ${Date.now() - start} ms.`, arguments[1]);
1756
1660
  return res;
@@ -1764,10 +1668,125 @@ class LoggerExtension extends WunderbaumExtension {
1764
1668
  }
1765
1669
  }
1766
1670
 
1671
+ /*!
1672
+ * Wunderbaum - common
1673
+ * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
1674
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
1675
+ */
1676
+ const DEFAULT_DEBUGLEVEL = 4; // Replaced by rollup script
1677
+ /**
1678
+ * Fixed height of a row in pixel. Must match the SCSS variable `$row-outer-height`.
1679
+ */
1680
+ const ROW_HEIGHT = 22;
1681
+ /**
1682
+ * Fixed width of node icons in pixel. Must match the SCSS variable `$icon-outer-width`.
1683
+ */
1684
+ const ICON_WIDTH = 20;
1685
+ /**
1686
+ * Adjust the width of the title span, so overflow ellipsis work.
1687
+ * (2 x `$col-padding-x` + 3px rounding errors).
1688
+ */
1689
+ const TITLE_SPAN_PAD_Y = 7;
1690
+ /** Render row markup for N nodes above and below the visible viewport. */
1691
+ const RENDER_MAX_PREFETCH = 5;
1692
+ /** Regular expression to detect if a string describes an image URL (in contrast
1693
+ * to a class name). Strings are considered image urls if they contain '.' or '/'.
1694
+ */
1695
+ const TEST_IMG = new RegExp(/\.|\//);
1696
+ // export const RECURSIVE_REQUEST_ERROR = "$recursive_request";
1697
+ // export const INVALID_REQUEST_TARGET_ERROR = "$request_target_invalid";
1698
+ /**
1699
+ * Default node icons.
1700
+ * Requires bootstrap icons https://icons.getbootstrap.com
1701
+ */
1702
+ const iconMap = {
1703
+ error: "bi bi-exclamation-triangle",
1704
+ // loading: "bi bi-hourglass-split wb-busy",
1705
+ loading: "bi bi-chevron-right wb-busy",
1706
+ // loading: "bi bi-arrow-repeat wb-spin",
1707
+ // loading: '<div class="spinner-border spinner-border-sm" role="status"> <span class="visually-hidden">Loading...</span> </div>',
1708
+ // noData: "bi bi-search",
1709
+ noData: "bi bi-question-circle",
1710
+ expanderExpanded: "bi bi-chevron-down",
1711
+ // expanderExpanded: "bi bi-dash-square",
1712
+ expanderCollapsed: "bi bi-chevron-right",
1713
+ // expanderCollapsed: "bi bi-plus-square",
1714
+ expanderLazy: "bi bi-chevron-right wb-helper-lazy-expander",
1715
+ // expanderLazy: "bi bi-chevron-bar-right",
1716
+ checkChecked: "bi bi-check-square",
1717
+ checkUnchecked: "bi bi-square",
1718
+ checkUnknown: "bi dash-square-dotted",
1719
+ radioChecked: "bi bi-circle-fill",
1720
+ radioUnchecked: "bi bi-circle",
1721
+ radioUnknown: "bi bi-circle-dotted",
1722
+ folder: "bi bi-folder2",
1723
+ folderOpen: "bi bi-folder2-open",
1724
+ folderLazy: "bi bi-folder-symlink",
1725
+ doc: "bi bi-file-earmark",
1726
+ };
1727
+ /** Dict keys that are evaluated by source loader (others are added to `tree.data` instead). */
1728
+ const RESERVED_TREE_SOURCE_KEYS = new Set([
1729
+ "children",
1730
+ "columns",
1731
+ "format",
1732
+ "keyMap",
1733
+ "positional",
1734
+ "typeList",
1735
+ "types",
1736
+ "version", // reserved for future use
1737
+ ]);
1738
+ // /** Key codes that trigger grid navigation, even when inside an input element. */
1739
+ // export const INPUT_BREAKOUT_KEYS: Set<string> = new Set([
1740
+ // // "ArrowDown",
1741
+ // // "ArrowUp",
1742
+ // "Enter",
1743
+ // "Escape",
1744
+ // ]);
1745
+ /** Map `KeyEvent.key` to navigation action. */
1746
+ const KEY_TO_ACTION_DICT = {
1747
+ " ": "toggleSelect",
1748
+ "+": "expand",
1749
+ Add: "expand",
1750
+ ArrowDown: "down",
1751
+ ArrowLeft: "left",
1752
+ ArrowRight: "right",
1753
+ ArrowUp: "up",
1754
+ Backspace: "parent",
1755
+ "/": "collapseAll",
1756
+ Divide: "collapseAll",
1757
+ End: "lastCol",
1758
+ Home: "firstCol",
1759
+ "Control+End": "last",
1760
+ "Control+Home": "first",
1761
+ "Meta+ArrowDown": "last",
1762
+ "Meta+ArrowUp": "first",
1763
+ "*": "expandAll",
1764
+ Multiply: "expandAll",
1765
+ PageDown: "pageDown",
1766
+ PageUp: "pageUp",
1767
+ "-": "collapse",
1768
+ Subtract: "collapse",
1769
+ };
1770
+ /** Return a callback that returns true if the node title contains a substring (case-insensitive). */
1771
+ function makeNodeTitleMatcher(s) {
1772
+ s = escapeRegex(s.toLowerCase());
1773
+ return function (node) {
1774
+ return node.title.toLowerCase().indexOf(s) >= 0;
1775
+ };
1776
+ }
1777
+ /** Return a callback that returns true if the node title starts with a string (case-insensitive). */
1778
+ function makeNodeTitleStartMatcher(s) {
1779
+ s = escapeRegex(s);
1780
+ const reMatch = new RegExp("^" + s, "i");
1781
+ return function (node) {
1782
+ return reMatch.test(node.title);
1783
+ };
1784
+ }
1785
+
1767
1786
  /*!
1768
1787
  * Wunderbaum - ext-dnd
1769
1788
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
1770
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
1789
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
1771
1790
  */
1772
1791
  const nodeMimeType = "application/x-wunderbaum-node";
1773
1792
  class DndExtension extends WunderbaumExtension {
@@ -2035,7 +2054,7 @@ class DndExtension extends WunderbaumExtension {
2035
2054
  /*!
2036
2055
  * Wunderbaum - drag_observer
2037
2056
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
2038
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
2057
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
2039
2058
  */
2040
2059
  /**
2041
2060
  * Convert mouse- and touch events to 'dragstart', 'drag', and 'dragstop'.
@@ -2169,7 +2188,7 @@ class DragObserver {
2169
2188
  /*!
2170
2189
  * Wunderbaum - ext-grid
2171
2190
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
2172
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
2191
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
2173
2192
  */
2174
2193
  class GridExtension extends WunderbaumExtension {
2175
2194
  constructor(tree) {
@@ -2206,7 +2225,7 @@ class GridExtension extends WunderbaumExtension {
2206
2225
  /*!
2207
2226
  * Wunderbaum - deferred
2208
2227
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
2209
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
2228
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
2210
2229
  */
2211
2230
  /**
2212
2231
  * Implement a ES6 Promise, that exposes a resolve() and reject() method.
@@ -2259,7 +2278,7 @@ class Deferred {
2259
2278
  /*!
2260
2279
  * Wunderbaum - wunderbaum_node
2261
2280
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
2262
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
2281
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
2263
2282
  */
2264
2283
  /** Top-level properties that can be passed with `data`. */
2265
2284
  const NODE_PROPS = new Set([
@@ -2407,23 +2426,28 @@ class WunderbaumNode {
2407
2426
  * @returns first child added
2408
2427
  */
2409
2428
  addChildren(nodeData, options) {
2429
+ const tree = this.tree;
2430
+ const level = options ? options.level : this.getLevel();
2410
2431
  let insertBefore = options
2411
2432
  ? options.before
2412
2433
  : null,
2413
2434
  // redraw = options ? options.redraw !== false : true,
2414
2435
  nodeList = [];
2415
2436
  try {
2416
- this.tree.enableUpdate(false);
2437
+ tree.enableUpdate(false);
2417
2438
  if (isPlainObject(nodeData)) {
2418
2439
  nodeData = [nodeData];
2419
2440
  }
2441
+ const forceExpand = level < tree.options.minExpandLevel;
2420
2442
  for (let child of nodeData) {
2421
2443
  let subChildren = child.children;
2422
2444
  delete child.children;
2423
- let n = new WunderbaumNode(this.tree, this, child);
2445
+ let n = new WunderbaumNode(tree, this, child);
2446
+ if (forceExpand && !n.lazy)
2447
+ n.expanded = true;
2424
2448
  nodeList.push(n);
2425
2449
  if (subChildren) {
2426
- n.addChildren(subChildren, { redraw: false });
2450
+ n.addChildren(subChildren, { redraw: false, level: level + 1 });
2427
2451
  }
2428
2452
  }
2429
2453
  if (!this.children) {
@@ -2441,15 +2465,15 @@ class WunderbaumNode {
2441
2465
  this.children.splice(pos, 0, ...nodeList);
2442
2466
  }
2443
2467
  // TODO:
2444
- // if (this.tree.options.selectMode === 3) {
2468
+ // if (tree.options.selectMode === 3) {
2445
2469
  // this.fixSelection3FromEndNodes();
2446
2470
  // }
2447
2471
  // this.triggerModifyChild("add", nodeList.length === 1 ? nodeList[0] : null);
2448
- this.tree.setModified(ChangeType.structure);
2472
+ tree.setModified(ChangeType.structure);
2449
2473
  return nodeList[0];
2450
2474
  }
2451
2475
  finally {
2452
- this.tree.enableUpdate(true);
2476
+ tree.enableUpdate(true);
2453
2477
  }
2454
2478
  }
2455
2479
  /**
@@ -2841,8 +2865,9 @@ class WunderbaumNode {
2841
2865
  // this.debug("isVisible: VISIBLE");
2842
2866
  return true;
2843
2867
  }
2844
- _loadSourceObject(source) {
2868
+ _loadSourceObject(source, level) {
2845
2869
  const tree = this.tree;
2870
+ level !== null && level !== void 0 ? level : (level = this.getLevel());
2846
2871
  // Let caller modify the parsed JSON response:
2847
2872
  this._callEvent("receive", { response: source });
2848
2873
  if (isArray(source)) {
@@ -2862,7 +2887,6 @@ class WunderbaumNode {
2862
2887
  tree.updateColumns({ calculateCols: false });
2863
2888
  }
2864
2889
  this.addChildren(source.children);
2865
- delete source.columns;
2866
2890
  // Add extra data to `tree.data`
2867
2891
  for (const [key, value] of Object.entries(source)) {
2868
2892
  if (!RESERVED_TREE_SOURCE_KEYS.has(key)) {
@@ -3261,6 +3285,9 @@ class WunderbaumNode {
3261
3285
  else if (this.children) {
3262
3286
  icon = iconMap.folder;
3263
3287
  }
3288
+ else if (this.lazy) {
3289
+ icon = iconMap.folderLazy;
3290
+ }
3264
3291
  else {
3265
3292
  icon = iconMap.doc;
3266
3293
  }
@@ -3424,13 +3451,13 @@ class WunderbaumNode {
3424
3451
  if (isColspan) {
3425
3452
  let vpWidth = tree.element.clientWidth;
3426
3453
  titleSpan.style.width =
3427
- vpWidth - nodeElem._ofsTitlePx - ROW_EXTRA_PAD + "px";
3454
+ vpWidth - nodeElem._ofsTitlePx - TITLE_SPAN_PAD_Y + "px";
3428
3455
  }
3429
3456
  else {
3430
3457
  titleSpan.style.width =
3431
3458
  columns[0]._widthPx -
3432
3459
  nodeElem._ofsTitlePx -
3433
- ROW_EXTRA_PAD +
3460
+ TITLE_SPAN_PAD_Y +
3434
3461
  "px";
3435
3462
  }
3436
3463
  }
@@ -3759,6 +3786,12 @@ class WunderbaumNode {
3759
3786
  this.expanded = flag;
3760
3787
  const updateOpts = { immediate: !!getOption(options, "immediate") };
3761
3788
  this.tree.setModified(ChangeType.structure, updateOpts);
3789
+ if (getOption(options, "scrollIntoView") !== false) {
3790
+ const lastChild = this.getLastChild();
3791
+ if (lastChild) {
3792
+ lastChild.scrollIntoView({ topNode: this });
3793
+ }
3794
+ }
3762
3795
  }
3763
3796
  /**
3764
3797
  * Set keyboard focus here.
@@ -3987,7 +4020,7 @@ WunderbaumNode.sequence = 0;
3987
4020
  /*!
3988
4021
  * Wunderbaum - ext-edit
3989
4022
  * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
3990
- * v0.0.6, Sat, 10 Sep 2022 19:29:21 GMT (https://github.com/mar10/wunderbaum)
4023
+ * v0.0.7, Sun, 11 Sep 2022 16:02:08 GMT (https://github.com/mar10/wunderbaum)
3991
4024
  */
3992
4025
  // const START_MARKER = "\uFFF7";
3993
4026
  class EditExtension extends WunderbaumExtension {
@@ -4133,8 +4166,9 @@ class EditExtension extends WunderbaumExtension {
4133
4166
  node.logInfo("beforeEdit canceled operation.");
4134
4167
  return;
4135
4168
  }
4136
- // `beforeEdit(e)` may return an input HTML string. Otherwise use a default:
4137
- if (!inputHtml) {
4169
+ // `beforeEdit(e)` may return an input HTML string. Otherwise use a default.
4170
+ // (we also treat a `true` return value as 'use default'):
4171
+ if (inputHtml === true || !inputHtml) {
4138
4172
  const title = escapeHtml(node.title);
4139
4173
  inputHtml = `<input type=text class="wb-input-edit" value="${title}" required autocorrect=off>`;
4140
4174
  }
@@ -4279,8 +4313,8 @@ class EditExtension extends WunderbaumExtension {
4279
4313
  * https://github.com/mar10/wunderbaum
4280
4314
  *
4281
4315
  * Released under the MIT license.
4282
- * @version v0.0.6
4283
- * @date Sat, 10 Sep 2022 19:29:21 GMT
4316
+ * @version v0.0.7
4317
+ * @date Sun, 11 Sep 2022 16:02:08 GMT
4284
4318
  */
4285
4319
  class WbSystemRoot extends WunderbaumNode {
4286
4320
  constructor(tree) {
@@ -5434,6 +5468,9 @@ class Wunderbaum {
5434
5468
  }
5435
5469
  /**
5436
5470
  * Make sure that this node is vertically scrolled into the viewport.
5471
+ *
5472
+ * Nodes that are above the visible area become the top row, nodes that are
5473
+ * below the viewport become the bottom row.
5437
5474
  */
5438
5475
  scrollTo(nodeOrOpts) {
5439
5476
  const PADDING = 2; // leave some pixels between viewport bounds
@@ -5455,6 +5492,7 @@ class Wunderbaum {
5455
5492
  const vpTop = headerHeight;
5456
5493
  const vpRowTop = rowTop - scrollTop;
5457
5494
  const vpRowBottom = vpRowTop + ROW_HEIGHT;
5495
+ const topNode = opts === null || opts === void 0 ? void 0 : opts.topNode;
5458
5496
  // this.log( `scrollTo(${node.title}), vpTop:${vpTop}px, scrollTop:${scrollTop}, vpHeight:${vpHeight}, rowTop:${rowTop}, vpRowTop:${vpRowTop}`, nodeOrOpts );
5459
5497
  let newScrollTop = null;
5460
5498
  if (vpRowTop >= vpTop) {
@@ -5462,17 +5500,21 @@ class Wunderbaum {
5462
5500
  else {
5463
5501
  // Node is below viewport
5464
5502
  // this.log("Below viewport");
5465
- newScrollTop = rowTop + ROW_HEIGHT - vpHeight + PADDING; // leave some pixels between vieeport bounds
5503
+ newScrollTop = rowTop + ROW_HEIGHT - vpHeight + PADDING; // leave some pixels between viewport bounds
5466
5504
  }
5467
5505
  }
5468
5506
  else {
5469
5507
  // Node is above viewport
5470
5508
  // this.log("Above viewport");
5471
- newScrollTop = rowTop - vpTop - PADDING; // leave some pixels between vieeport bounds
5509
+ newScrollTop = rowTop - vpTop - PADDING; // leave some pixels between viewport bounds
5472
5510
  }
5473
5511
  if (newScrollTop != null) {
5474
5512
  this.log(`scrollTo(${rowTop}): ${scrollTop} => ${newScrollTop}`);
5475
5513
  scrollParent.scrollTop = newScrollTop;
5514
+ if (topNode) {
5515
+ // Make sure the topNode is always visible
5516
+ this.scrollTo(topNode);
5517
+ }
5476
5518
  // this.setModified(ChangeType.vscroll);
5477
5519
  }
5478
5520
  }
@@ -5501,10 +5543,9 @@ class Wunderbaum {
5501
5543
  newLeft = colRight - vpWidth;
5502
5544
  }
5503
5545
  // util.assert(node._rowIdx != null);
5504
- // const curLeft = this.scrollContainer.scrollLeft;
5505
- this.log(`scrollToHorz(${this.activeColIdx}): ${colLeft}..${colRight}, fixedOfs=${fixedWidth}, vpWidth=${vpWidth}, curLeft=${scrollLeft} -> ${newLeft}`);
5506
- // const nodeOfs = node._rowIdx * ROW_HEIGHT;
5507
- // let newLeft;
5546
+ // this.log(
5547
+ // `scrollToHorz(${this.activeColIdx}): ${colLeft}..${colRight}, fixedOfs=${fixedWidth}, vpWidth=${vpWidth}, curLeft=${scrollLeft} -> ${newLeft}`
5548
+ // );
5508
5549
  this.element.scrollLeft = newLeft;
5509
5550
  // this.setModified(ChangeType.vscroll);
5510
5551
  // }
@@ -5915,6 +5956,7 @@ class Wunderbaum {
5915
5956
  const row_height = ROW_HEIGHT;
5916
5957
  const vp_height = this.element.clientHeight;
5917
5958
  const prefetch = RENDER_MAX_PREFETCH;
5959
+ // const grace_prefetch = RENDER_MAX_PREFETCH - RENDER_MIN_PREFETCH;
5918
5960
  const ofs = this.element.scrollTop;
5919
5961
  let startIdx = Math.max(0, ofs / row_height - prefetch);
5920
5962
  startIdx = Math.floor(startIdx);
@@ -6210,7 +6252,7 @@ class Wunderbaum {
6210
6252
  }
6211
6253
  Wunderbaum.sequence = 0;
6212
6254
  /** Wunderbaum release version number "MAJOR.MINOR.PATCH". */
6213
- Wunderbaum.version = "v0.0.6"; // Set to semver by 'grunt release'
6255
+ Wunderbaum.version = "v0.0.7"; // Set to semver by 'grunt release'
6214
6256
  /** Expose some useful methods of the util.ts module as `Wunderbaum.util`. */
6215
6257
  Wunderbaum.util = util;
6216
6258