wunderbaum 0.10.0 → 0.11.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.
@@ -288,7 +288,7 @@ function throttle(func, wait = 0, options = {}) {
288
288
  /*!
289
289
  * Wunderbaum - util
290
290
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
291
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
291
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
292
292
  */
293
293
  /** @module util */
294
294
  /** Readable names for `MouseEvent.button` */
@@ -764,7 +764,7 @@ function extend(...args) {
764
764
  function isArray(obj) {
765
765
  return Array.isArray(obj);
766
766
  }
767
- /** Return true if `obj` is of type `Object` and has no propertied. */
767
+ /** Return true if `obj` is of type `Object` and has no properties. */
768
768
  function isEmptyObject(obj) {
769
769
  return Object.keys(obj).length === 0 && obj.constructor === Object;
770
770
  }
@@ -920,6 +920,11 @@ function getOption(opts, name, defaultValue = undefined) {
920
920
  // Use value from value options dict, fallback do default
921
921
  return value !== null && value !== void 0 ? value : defaultValue;
922
922
  }
923
+ /** Return the next value from a list of values (rotating). @since 0.11 */
924
+ function rotate(value, values) {
925
+ const idx = values.indexOf(value);
926
+ return values[(idx + 1) % values.length];
927
+ }
923
928
  /** Convert an Array or space-separated string to a Set. */
924
929
  function toSet(val) {
925
930
  if (val instanceof Set) {
@@ -943,15 +948,12 @@ function toSet(val) {
943
948
  *
944
949
  * Example:
945
950
  * ```js
946
- * const width = util.toPixel("123px", 100);
951
+ * let x = undefined;
952
+ * let y = "123px";
953
+ * const width = util.toPixel(x, y, 100); // returns 123
947
954
  * ```
948
955
  */
949
- function toPixel(
950
- // val: string | number | undefined | null,
951
- ...defaults) {
952
- // if (typeof val === "number") {
953
- // return val;
954
- // }
956
+ function toPixel(...defaults) {
955
957
  for (const d of defaults) {
956
958
  if (typeof d === "number") {
957
959
  return d;
@@ -963,19 +965,14 @@ function toPixel(
963
965
  }
964
966
  throw new Error(`Expected a string like '123px': ${defaults}`);
965
967
  }
966
- /** Evaluate a boolean value using default if undefined.
968
+ /** Return the the boolean value of the first non-null element.
967
969
  * Example:
968
970
  * ```js
969
971
  * const opts = { flag: true };
970
- * const value = util.toBool(opts.flag, otherVar, false);
972
+ * const value = util.toBool(opts.foo, opts.flag, false); // returns true
971
973
  * ```
972
974
  */
973
- function toBool(
974
- // val: boolean | undefined | null,
975
- ...boolDefaults) {
976
- // if (val != null) {
977
- // return !!val;
978
- // }
975
+ function toBool(...boolDefaults) {
979
976
  for (const d of boolDefaults) {
980
977
  if (d != null) {
981
978
  return !!d;
@@ -1119,6 +1116,7 @@ var util = /*#__PURE__*/Object.freeze({
1119
1116
  noop: noop,
1120
1117
  onEvent: onEvent,
1121
1118
  overrideMethod: overrideMethod,
1119
+ rotate: rotate,
1122
1120
  setElemDisplay: setElemDisplay,
1123
1121
  setTimeoutPromise: setTimeoutPromise,
1124
1122
  setValueToElem: setValueToElem,
@@ -1134,10 +1132,10 @@ var util = /*#__PURE__*/Object.freeze({
1134
1132
  /*!
1135
1133
  * Wunderbaum - types
1136
1134
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
1137
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
1135
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
1138
1136
  */
1139
1137
  /**
1140
- * Possible values for {@link WunderbaumNode.update()} and {@link Wunderbaum.update()}.
1138
+ * Possible values for {@link WunderbaumNode.update} and {@link Wunderbaum.update}.
1141
1139
  */
1142
1140
  var ChangeType;
1143
1141
  (function (ChangeType) {
@@ -1166,7 +1164,7 @@ var RenderFlag;
1166
1164
  RenderFlag["redraw"] = "redraw";
1167
1165
  RenderFlag["scroll"] = "scroll";
1168
1166
  })(RenderFlag || (RenderFlag = {}));
1169
- /** Possible values for {@link WunderbaumNode.setStatus()}. */
1167
+ /** Possible values for {@link WunderbaumNode.setStatus}. */
1170
1168
  var NodeStatusType;
1171
1169
  (function (NodeStatusType) {
1172
1170
  NodeStatusType["ok"] = "ok";
@@ -1198,7 +1196,7 @@ var NavModeEnum;
1198
1196
  /*!
1199
1197
  * Wunderbaum - wb_extension_base
1200
1198
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
1201
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
1199
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
1202
1200
  */
1203
1201
  class WunderbaumExtension {
1204
1202
  constructor(tree, id, defaults) {
@@ -1257,7 +1255,7 @@ class WunderbaumExtension {
1257
1255
  /*!
1258
1256
  * Wunderbaum - ext-filter
1259
1257
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
1260
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
1258
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
1261
1259
  */
1262
1260
  const START_MARKER = "\uFFF7";
1263
1261
  const END_MARKER = "\uFFF8";
@@ -1284,6 +1282,7 @@ class FilterExtension extends WunderbaumExtension {
1284
1282
  const connectInput = this.getPluginOption("connectInput");
1285
1283
  if (connectInput) {
1286
1284
  this.queryInput = elemFromSelector(connectInput);
1285
+ assert(this.queryInput, `Invalid 'filter.connectInput' option: ${connectInput}.`);
1287
1286
  onEvent(this.queryInput, "input", debounce((e) => {
1288
1287
  // this.tree.log("query", e);
1289
1288
  this.filterNodes(this.queryInput.value.trim(), {});
@@ -1581,7 +1580,7 @@ function _markFuzzyMatchedChars(text, matches, escapeTitles = true) {
1581
1580
  /*!
1582
1581
  * Wunderbaum - ext-keynav
1583
1582
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
1584
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
1583
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
1585
1584
  */
1586
1585
  const QUICKSEARCH_DELAY = 500;
1587
1586
  class KeynavExtension extends WunderbaumExtension {
@@ -1945,7 +1944,7 @@ class KeynavExtension extends WunderbaumExtension {
1945
1944
  /*!
1946
1945
  * Wunderbaum - ext-logger
1947
1946
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
1948
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
1947
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
1949
1948
  */
1950
1949
  class LoggerExtension extends WunderbaumExtension {
1951
1950
  constructor(tree) {
@@ -1987,7 +1986,7 @@ class LoggerExtension extends WunderbaumExtension {
1987
1986
  /*!
1988
1987
  * Wunderbaum - common
1989
1988
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
1990
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
1989
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
1991
1990
  */
1992
1991
  const DEFAULT_DEBUGLEVEL = 3; // Replaced by rollup script
1993
1992
  /**
@@ -2042,6 +2041,15 @@ const iconMaps = {
2042
2041
  folderOpen: "bi bi-folder2-open",
2043
2042
  folderLazy: "bi bi-folder-symlink",
2044
2043
  doc: "bi bi-file-earmark",
2044
+ colSortable: "bi bi-chevron-expand",
2045
+ // colSortable: "bi bi-arrow-down-up",
2046
+ // colSortAsc: "bi bi-chevron-down",
2047
+ // colSortDesc: "bi bi-chevron-up",
2048
+ colSortAsc: "bi bi-arrow-down",
2049
+ colSortDesc: "bi bi-arrow-up",
2050
+ colFilter: "bi bi-filter-circle",
2051
+ colFilterActive: "bi bi-filter-circle-fill wb-helper-invalid",
2052
+ colMenu: "bi bi-three-dots-vertical",
2045
2053
  },
2046
2054
  fontawesome6: {
2047
2055
  error: "fa-solid fa-triangle-exclamation",
@@ -2060,6 +2068,12 @@ const iconMaps = {
2060
2068
  folderOpen: "fa-regular fa-folder-open",
2061
2069
  folderLazy: "fa-solid fa-folder-plus",
2062
2070
  doc: "fa-regular fa-file",
2071
+ colSortable: "fa-solid fa-fw fa-sort",
2072
+ colSortAsc: "fa-solid fa-fw fa-sort-up",
2073
+ colSortDesc: "fa-solid fa-fw fa-sort-down",
2074
+ colFilter: "fa-solid fa-fw fa-filter",
2075
+ colFilterActive: "fa-solid fa-fw fa-filter wb-helper-invalid",
2076
+ colMenu: "fa-solid fa-fw fa-ellipsis-v",
2063
2077
  },
2064
2078
  };
2065
2079
  /** Dict keys that are evaluated by source loader (others are added to `tree.data` instead). */
@@ -2108,7 +2122,7 @@ const KEY_TO_ACTION_DICT = {
2108
2122
  };
2109
2123
  /** Return a callback that returns true if the node title matches the string
2110
2124
  * or regular expression.
2111
- * @see {@link WunderbaumNode.findAll()}
2125
+ * @see {@link WunderbaumNode.findAll}
2112
2126
  */
2113
2127
  function makeNodeTitleMatcher(match) {
2114
2128
  if (match instanceof RegExp) {
@@ -2312,7 +2326,7 @@ function decompressSourceData(source) {
2312
2326
  /*!
2313
2327
  * Wunderbaum - ext-dnd
2314
2328
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
2315
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
2329
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
2316
2330
  */
2317
2331
  const nodeMimeType = "application/x-wunderbaum-node";
2318
2332
  class DndExtension extends WunderbaumExtension {
@@ -2757,7 +2771,7 @@ class DndExtension extends WunderbaumExtension {
2757
2771
  /*!
2758
2772
  * Wunderbaum - drag_observer
2759
2773
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
2760
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
2774
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
2761
2775
  */
2762
2776
  /**
2763
2777
  * Convert mouse- and touch events to 'dragstart', 'drag', and 'dragstop'.
@@ -2906,7 +2920,7 @@ class DragObserver {
2906
2920
  /*!
2907
2921
  * Wunderbaum - ext-grid
2908
2922
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
2909
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
2923
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
2910
2924
  */
2911
2925
  class GridExtension extends WunderbaumExtension {
2912
2926
  constructor(tree) {
@@ -2923,7 +2937,7 @@ class GridExtension extends WunderbaumExtension {
2923
2937
  const colDef = info.colDef;
2924
2938
  const allow = colDef &&
2925
2939
  this.tree.element.contains(e.dragElem) &&
2926
- toBool(colDef.resizable, tree.options.resizableColumns, false);
2940
+ toBool(colDef.resizable, tree.options.columnsResizable, false);
2927
2941
  // this.tree.log("dragstart", colDef, e, info);
2928
2942
  this.tree.element.classList.toggle("wb-col-resizing", !!allow);
2929
2943
  info.colElem.classList.toggle("wb-col-resizing", !!allow);
@@ -2997,7 +3011,7 @@ class GridExtension extends WunderbaumExtension {
2997
3011
  /*!
2998
3012
  * Wunderbaum - deferred
2999
3013
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
3000
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
3014
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
3001
3015
  */
3002
3016
  /**
3003
3017
  * Implement a ES6 Promise, that exposes a resolve() and reject() method.
@@ -3050,7 +3064,7 @@ class Deferred {
3050
3064
  /*!
3051
3065
  * Wunderbaum - wunderbaum_node
3052
3066
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
3053
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
3067
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
3054
3068
  */
3055
3069
  /** WunderbaumNode properties that can be passed with source data.
3056
3070
  * (Any other source properties will be stored as `node.data.PROP`.)
@@ -3093,6 +3107,12 @@ class WunderbaumNode {
3093
3107
  * @see Use {@link setKey} to modify.
3094
3108
  */
3095
3109
  this.refKey = undefined;
3110
+ /**
3111
+ * Array of child nodes (null for leaf nodes).
3112
+ * For lazy nodes, this is `null` or ùndefined` until the children are loaded
3113
+ * and leaf nodes may be `[]` (empty array).
3114
+ * @see {@link hasChildren}, {@link addChildren}, {@link lazy}.
3115
+ */
3096
3116
  this.children = null;
3097
3117
  /** Additional classes added to `div.wb-row`.
3098
3118
  * @see {@link hasClass}, {@link setClass}. */
@@ -3680,7 +3700,7 @@ class WunderbaumNode {
3680
3700
  hasClass(className) {
3681
3701
  return this.classes ? this.classes.has(className) : false;
3682
3702
  }
3683
- /** Return true if node ist the currently focused node. */
3703
+ /** Return true if node ist the currently focused node. @since 0.9.0 */
3684
3704
  hasFocus() {
3685
3705
  return this.tree.focusNode === this;
3686
3706
  }
@@ -3902,6 +3922,8 @@ class WunderbaumNode {
3902
3922
  if (tree.options.selectMode === "hier") {
3903
3923
  this.fixSelection3FromEndNodes();
3904
3924
  }
3925
+ // Allow to un-sort nodes after sorting
3926
+ this.resetNativeChildOrder();
3905
3927
  this._callEvent("load");
3906
3928
  }
3907
3929
  async _fetchWithOptions(source) {
@@ -4845,7 +4867,7 @@ class WunderbaumNode {
4845
4867
  *
4846
4868
  * @param name name of the option property (on node and tree)
4847
4869
  * @param defaultValue return this if nothing else matched
4848
- * {@link Wunderbaum.getOption|Wunderbaum.getOption()}
4870
+ * {@link Wunderbaum.getOption|Wunderbaum.getOption}
4849
4871
  */
4850
4872
  getOption(name, defaultValue) {
4851
4873
  const tree = this.tree;
@@ -4881,7 +4903,7 @@ class WunderbaumNode {
4881
4903
  return value !== null && value !== void 0 ? value : defaultValue;
4882
4904
  }
4883
4905
  /** Make sure that this node is visible in the viewport.
4884
- * @see {@link Wunderbaum.scrollTo|Wunderbaum.scrollTo()}
4906
+ * @see {@link Wunderbaum.scrollTo|Wunderbaum.scrollTo}
4885
4907
  */
4886
4908
  async scrollIntoView(options) {
4887
4909
  const opts = Object.assign({ node: this }, options);
@@ -5020,9 +5042,9 @@ class WunderbaumNode {
5020
5042
  * and column content. It can be reduced to 'ChangeType.status' if only
5021
5043
  * active/focus/selected state has changed.
5022
5044
  *
5023
- * This method will eventually call {@link WunderbaumNode._render()} with
5045
+ * This method will eventually call {@link WunderbaumNode._render} with
5024
5046
  * default options, but may be more consistent with the tree's
5025
- * {@link Wunderbaum.update()} API.
5047
+ * {@link Wunderbaum.update} API.
5026
5048
  */
5027
5049
  update(change = ChangeType.data) {
5028
5050
  assert(change === ChangeType.status || change === ChangeType.data, `Invalid change type ${change}`);
@@ -5351,6 +5373,80 @@ class WunderbaumNode {
5351
5373
  this.tree.update(ChangeType.structure);
5352
5374
  // this.triggerModify("sort"); // TODO
5353
5375
  }
5376
+ /**
5377
+ * Renumber nodes `_nativeIndex`. This is useful to allow to restore the
5378
+ * order after sorting a column.
5379
+ * This method is automatically called after loading new child nodes.
5380
+ * @since 0.11.0
5381
+ */
5382
+ resetNativeChildOrder(options) {
5383
+ const { recursive = true, propName = "_nativeIndex" } = options !== null && options !== void 0 ? options : {};
5384
+ if (this.children) {
5385
+ this.children.forEach((child, i) => {
5386
+ child.data[propName] = i;
5387
+ if (recursive && child.children) {
5388
+ child.resetNativeChildOrder(options);
5389
+ }
5390
+ });
5391
+ }
5392
+ }
5393
+ /**
5394
+ * Convenience method to implement column sorting.
5395
+ * @since 0.11.0
5396
+ */
5397
+ sortByProperty(options) {
5398
+ var _a, _b, _c;
5399
+ const { caseInsensitive = true, deep = true, nativeOrderPropName = "_nativeIndex", updateColInfo = false, } = options;
5400
+ let order;
5401
+ let colDef;
5402
+ if (updateColInfo) {
5403
+ colDef = this.tree["_columnsById"][options.colId];
5404
+ assert(colDef, `Invalid colId specified: ${options.colId}`);
5405
+ order =
5406
+ (_a = options.order) !== null && _a !== void 0 ? _a : rotate(colDef.sortOrder, ["asc", "desc", undefined]);
5407
+ for (const col of this.tree.columns) {
5408
+ col.sortOrder = col === colDef ? order : undefined;
5409
+ }
5410
+ this.tree.update(ChangeType.colStructure);
5411
+ }
5412
+ else {
5413
+ order = (_b = options.order) !== null && _b !== void 0 ? _b : "asc";
5414
+ }
5415
+ let propName = (_c = options.propName) !== null && _c !== void 0 ? _c : (options.colId || "");
5416
+ if (propName === "*") {
5417
+ propName = "title";
5418
+ }
5419
+ if (order == null) {
5420
+ propName = nativeOrderPropName;
5421
+ order = "asc";
5422
+ }
5423
+ this.logDebug(`sortByProperty(), propName=${propName}, ${order}`, options);
5424
+ assert(propName, "No property name specified");
5425
+ const cmp = (a, b) => {
5426
+ let av, bv;
5427
+ if (NODE_DICT_PROPS.has(propName)) {
5428
+ av = a[propName];
5429
+ bv = b[propName];
5430
+ }
5431
+ else {
5432
+ av = a.data[propName];
5433
+ bv = b.data[propName];
5434
+ }
5435
+ if (caseInsensitive) {
5436
+ if (typeof av === "string") {
5437
+ av = av.toLowerCase();
5438
+ }
5439
+ if (typeof bv === "string") {
5440
+ bv = bv.toLowerCase();
5441
+ }
5442
+ }
5443
+ if (order === "desc") {
5444
+ return av === bv ? 0 : av > bv ? -1 : 1;
5445
+ }
5446
+ return av === bv ? 0 : av > bv ? 1 : -1;
5447
+ };
5448
+ return this.sortChildren(cmp, deep);
5449
+ }
5354
5450
  /**
5355
5451
  * Trigger `modifyChild` event on a parent to signal that a child was modified.
5356
5452
  * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
@@ -5459,7 +5555,7 @@ WunderbaumNode.sequence = 0;
5459
5555
  /*!
5460
5556
  * Wunderbaum - ext-edit
5461
5557
  * Copyright (c) 2021-2024, Martin Wendt. Released under the MIT license.
5462
- * v0.10.0, Mon, 24 Jun 2024 19:17:59 GMT (https://github.com/mar10/wunderbaum)
5558
+ * v0.11.0, Sun, 04 Aug 2024 15:35:53 GMT (https://github.com/mar10/wunderbaum)
5463
5559
  */
5464
5560
  // const START_MARKER = "\uFFF7";
5465
5561
  class EditExtension extends WunderbaumExtension {
@@ -5790,8 +5886,8 @@ class EditExtension extends WunderbaumExtension {
5790
5886
  * https://github.com/mar10/wunderbaum
5791
5887
  *
5792
5888
  * Released under the MIT license.
5793
- * @version v0.10.0
5794
- * @date Mon, 24 Jun 2024 19:17:59 GMT
5889
+ * @version v0.11.0
5890
+ * @date Sun, 04 Aug 2024 15:35:53 GMT
5795
5891
  */
5796
5892
  // import "./wunderbaum.scss";
5797
5893
  class WbSystemRoot extends WunderbaumNode {
@@ -5961,7 +6057,8 @@ class Wunderbaum {
5961
6057
  // Attach tree instance to <div>
5962
6058
  this.element._wb_tree = this;
5963
6059
  // Create header markup, or take it from the existing html
5964
- this.headerElement = this.element.querySelector("div.wb-header");
6060
+ this.headerElement =
6061
+ this.element.querySelector("div.wb-header");
5965
6062
  const wantHeader = opts.header == null ? this.columns.length > 1 : !!opts.header;
5966
6063
  if (this.headerElement) {
5967
6064
  // User existing header markup to define `this.columns`
@@ -5998,8 +6095,10 @@ class Wunderbaum {
5998
6095
  <div class="wb-node-list"></div>
5999
6096
  </div>`;
6000
6097
  this.listContainerElement = this.element.querySelector("div.wb-list-container");
6001
- this.nodeListElement = this.listContainerElement.querySelector("div.wb-node-list");
6002
- this.headerElement = this.element.querySelector("div.wb-header");
6098
+ this.nodeListElement =
6099
+ this.listContainerElement.querySelector("div.wb-node-list");
6100
+ this.headerElement =
6101
+ this.element.querySelector("div.wb-header");
6003
6102
  this.element.classList.toggle("wb-grid", this.columns.length > 1);
6004
6103
  this._initExtensions();
6005
6104
  // --- apply initial options
@@ -6056,6 +6155,16 @@ class Wunderbaum {
6056
6155
  this.update(ChangeType.resize);
6057
6156
  });
6058
6157
  this.resizeObserver.observe(this.element);
6158
+ onEvent(this.element, "click", ".wb-button,.wb-col-icon", (e) => {
6159
+ var _a, _b;
6160
+ const info = Wunderbaum.getEventInfo(e);
6161
+ const command = (_b = (_a = e.target) === null || _a === void 0 ? void 0 : _a.dataset) === null || _b === void 0 ? void 0 : _b.command;
6162
+ this._callEvent("buttonClick", {
6163
+ event: e,
6164
+ info: info,
6165
+ command: command,
6166
+ });
6167
+ });
6059
6168
  onEvent(this.nodeListElement, "click", "div.wb-row", (e) => {
6060
6169
  const info = Wunderbaum.getEventInfo(e);
6061
6170
  const node = info.node;
@@ -6636,7 +6745,7 @@ class Wunderbaum {
6636
6745
  }
6637
6746
  /** Run code, but defer rendering of viewport until done.
6638
6747
  *
6639
- * ```
6748
+ * ```js
6640
6749
  * tree.runWithDeferredUpdate(() => {
6641
6750
  * return someFuncThatWouldUpdateManyNodes();
6642
6751
  * });
@@ -7114,13 +7223,17 @@ class Wunderbaum {
7114
7223
  console.warn(this.toString(), ...args); // eslint-disable-line no-console
7115
7224
  }
7116
7225
  }
7117
- /** Reset column widths to default. */
7226
+ /** Reset column widths to default. @since 0.10.0 */
7118
7227
  resetColumns() {
7119
7228
  this.columns.forEach((col) => {
7120
7229
  delete col.customWidthPx;
7121
7230
  });
7122
7231
  this.update(ChangeType.colStructure);
7123
7232
  }
7233
+ // /** Renumber nodes `_nativeIndex`. @see {@link WunderbaumNode.resetNativeChildOrder} */
7234
+ // resetNativeChildOrder(options?: ResetOrderOptions) {
7235
+ // this.root.resetNativeChildOrder(options);
7236
+ // }
7124
7237
  /**
7125
7238
  * Make sure that this node is vertically scrolled into the viewport.
7126
7239
  *
@@ -7435,6 +7548,14 @@ class Wunderbaum {
7435
7548
  sortChildren(cmp = nodeTitleSorter, deep = false) {
7436
7549
  this.root.sortChildren(cmp, deep);
7437
7550
  }
7551
+ /**
7552
+ * Convenience method to implement column sorting.
7553
+ * @see {@link WunderbaumNode.sortByProperty}.
7554
+ * @since 0.11.0
7555
+ */
7556
+ sortByProperty(options) {
7557
+ this.root.sortByProperty(options);
7558
+ }
7438
7559
  /** Convert tree to an array of plain objects.
7439
7560
  *
7440
7561
  * @param callback is called for every node, in order to allow
@@ -7548,6 +7669,11 @@ class Wunderbaum {
7548
7669
  // }
7549
7670
  return modified;
7550
7671
  }
7672
+ _insertIcon(icon, elem) {
7673
+ const iconElem = document.createElement("i");
7674
+ iconElem.className = icon;
7675
+ elem.appendChild(iconElem);
7676
+ }
7551
7677
  /** Create/update header markup from `this.columns` definition.
7552
7678
  * @internal
7553
7679
  */
@@ -7558,6 +7684,7 @@ class Wunderbaum {
7558
7684
  if (!wantHeader) {
7559
7685
  return;
7560
7686
  }
7687
+ const iconMap = this.iconMap;
7561
7688
  const colCount = this.columns.length;
7562
7689
  const headerRow = this.headerElement.querySelector(".wb-row");
7563
7690
  assert(headerRow, "Expected a row in header element");
@@ -7576,23 +7703,54 @@ class Wunderbaum {
7576
7703
  else {
7577
7704
  col.classes ? colElem.classList.add(...col.classes.split(" ")) : 0;
7578
7705
  }
7579
- const title = escapeHtml(col.title || col.id);
7706
+ // Add tooltip to column title
7580
7707
  let tooltip = "";
7581
7708
  if (col.tooltip) {
7582
7709
  tooltip = escapeTooltip(col.tooltip);
7583
7710
  tooltip = ` title="${tooltip}"`;
7584
7711
  }
7585
- let resizer = "";
7712
+ // Add column header icons
7713
+ let addMarkup = "";
7714
+ // NOTE: we use CSS float: right to align icons, so they must be added in
7715
+ // reverse order
7716
+ if (toBool(col.menu, this.options.columnsMenu, false)) {
7717
+ const iconClass = "wb-col-icon-menu " + iconMap.colMenu;
7718
+ const icon = `<i data-command=menu class="wb-col-icon ${iconClass}"></i>`;
7719
+ addMarkup += icon;
7720
+ }
7721
+ if (toBool(col.sortable, this.options.columnsSortable, false)) {
7722
+ let iconClass = "wb-col-icon-sort " + iconMap.colSortable;
7723
+ if (col.sortOrder) {
7724
+ iconClass += `wb-col-sort-${col.sortOrder}`;
7725
+ iconClass +=
7726
+ col.sortOrder === "asc" ? iconMap.colSortAsc : iconMap.colSortDesc;
7727
+ }
7728
+ const icon = `<i data-command=sort class="wb-col-icon ${iconClass}"></i>`;
7729
+ addMarkup += icon;
7730
+ }
7731
+ if (toBool(col.filterable, this.options.columnsFilterable, false)) {
7732
+ colElem.classList.toggle("wb-col-filter", !!col.filterActive);
7733
+ let iconClass = "wb-col-icon-filter " + iconMap.colFilter;
7734
+ if (col.filterActive) {
7735
+ iconClass += iconMap.colFilterActive;
7736
+ }
7737
+ const icon = `<i data-command=filter class="wb-col-icon ${iconClass}"></i>`;
7738
+ addMarkup += icon;
7739
+ }
7740
+ // Add resizer to all but the last column
7586
7741
  if (i < colCount - 1) {
7587
- if (toBool(col.resizable, this.options.resizableColumns, false)) {
7588
- resizer =
7742
+ if (toBool(col.resizable, this.options.columnsResizable, false)) {
7743
+ addMarkup +=
7589
7744
  '<span class="wb-col-resizer wb-col-resizer-active"></span>';
7590
7745
  }
7591
7746
  else {
7592
- resizer = '<span class="wb-col-resizer"></span>';
7747
+ addMarkup += '<span class="wb-col-resizer"></span>';
7593
7748
  }
7594
7749
  }
7595
- colElem.innerHTML = `<span class="wb-col-title"${tooltip}>${title}</span>${resizer}`;
7750
+ // Create column header
7751
+ const title = escapeHtml(col.title || col.id);
7752
+ colElem.innerHTML = `<span class="wb-col-title"${tooltip}>${title}</span>${addMarkup}`;
7753
+ // Highlight active column
7596
7754
  if (this.isCellNav()) {
7597
7755
  colElem.classList.toggle("wb-active", i === this.activeColIdx);
7598
7756
  }
@@ -7671,6 +7829,7 @@ class Wunderbaum {
7671
7829
  // console.profileEnd(`_updateViewportImmediately()`)
7672
7830
  }
7673
7831
  if (this.options.connectTopBreadcrumb) {
7832
+ assert(this.options.connectTopBreadcrumb.textContent != null, `Invalid 'connectTopBreadcrumb' option (input element expected).`);
7674
7833
  let path = (_a = this.getTopmostVpNode(true)) === null || _a === void 0 ? void 0 : _a.getPath(false, "title", " > ");
7675
7834
  path = path ? path + " >" : "";
7676
7835
  this.options.connectTopBreadcrumb.textContent = path;
@@ -8008,6 +8167,7 @@ class Wunderbaum {
8008
8167
  /**
8009
8168
  * Return the number of nodes that match the current filter.
8010
8169
  * @see {@link Wunderbaum.filterNodes}
8170
+ * @since 0.9.0
8011
8171
  */
8012
8172
  countMatches() {
8013
8173
  return this.extensions.filter.countMatches();
@@ -8040,7 +8200,7 @@ class Wunderbaum {
8040
8200
  }
8041
8201
  Wunderbaum.sequence = 0;
8042
8202
  /** Wunderbaum release version number "MAJOR.MINOR.PATCH". */
8043
- Wunderbaum.version = "v0.10.0"; // Set to semver by 'grunt release'
8203
+ Wunderbaum.version = "v0.11.0"; // Set to semver by 'grunt release'
8044
8204
  /** Expose some useful methods of the util.ts module as `Wunderbaum.util`. */
8045
8205
  Wunderbaum.util = util;
8046
8206