wunderbaum 0.3.4 → 0.4.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/src/wb_options.ts CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  DndOptionsType,
11
11
  NavModeEnum,
12
12
  NodeTypeDefinitionMap,
13
+ SelectModeType,
13
14
  WbActivateEventType,
14
15
  WbChangeEventType,
15
16
  WbClickEventType,
@@ -161,10 +162,10 @@ export interface WunderbaumOptions {
161
162
  * Default: false.
162
163
  */
163
164
  checkbox?: boolean | "radio" | BoolOptionResolver;
164
- /**
165
- * Default: 200
166
- */
167
- updateThrottleWait?: number;
165
+ // /**
166
+ // * Default: 200
167
+ // */
168
+ // updateThrottleWait?: number;
168
169
  /**
169
170
  * Default: true
170
171
  */
@@ -174,6 +175,12 @@ export interface WunderbaumOptions {
174
175
  */
175
176
  fixedCol?: boolean;
176
177
 
178
+ // --- Selection ---
179
+ /**
180
+ * Default: "multi"
181
+ */
182
+ selectMode?: SelectModeType;
183
+
177
184
  // --- KeyNav ---
178
185
  /**
179
186
  * Default: true
@@ -16,7 +16,7 @@ $node-text-color: #56534c;
16
16
  $border-color: $node-text-color;
17
17
  $bg-highlight-color: #26a0da;
18
18
  $header-color: #dedede;
19
- $background-color: white;
19
+ $background-color: #ffffff;
20
20
  $alternate-row-color: #f7f7f7; // #fcfcfc;
21
21
  $alternate-row-color-hover: #f3f3f3; //#f7fcfe;
22
22
  $focus-border-color: #275dc5;
@@ -48,15 +48,15 @@ $filter-submatch-color: #868581;
48
48
 
49
49
  $row-outer-height: 22px;
50
50
  $row-inner-height: $row-outer-height - 2; // outer height minus border size
51
- $row-padding-y: ($row-outer-height - $row-inner-height) / 2;
51
+ $row-padding-y: calc(($row-outer-height - $row-inner-height) / 2);
52
52
  $col-padding-x: 2px; // on each side within span.wb-col
53
53
 
54
54
  $icon-outer-height: $row-inner-height;
55
55
  $icon-outer-width: 20px;
56
56
  $icon-height: 16px;
57
57
  $icon-width: 16px;
58
- $icon-padding-y: ($icon-outer-height - $icon-height) / 2;
59
- $icon-padding-x: ($icon-outer-width - $icon-width) / 2;
58
+ $icon-padding-y: calc(($icon-outer-height - $icon-height) / 2);
59
+ $icon-padding-x: calc(($icon-outer-width - $icon-width) / 2);
60
60
 
61
61
  $header-height: $row-outer-height;
62
62
 
@@ -74,6 +74,7 @@ $level-rainbow: rgb(255, 255, 201), rgb(218, 255, 218), rgb(255, 217, 254),
74
74
  // --- Define CSS variables with calculated default values
75
75
 
76
76
  :root {
77
+ // TODO: do we need to use 'meta.inspect' in case a font name contains spaces?
77
78
  // --wb-font-stack: #{meta.inspect($font-stack)};
78
79
  --wb-font-stack: #{$font-stack};
79
80
 
@@ -197,7 +198,7 @@ div.wunderbaum {
197
198
 
198
199
  /* Fixed column must be opaque, i.e. have the bg color set. */
199
200
  &.wb-fixed-col {
200
- /* Sticky firdt column (header and nodes) */
201
+ // Sticky first column (header and nodes)
201
202
  span.wb-col:first-of-type {
202
203
  position: sticky;
203
204
  left: 0;
@@ -327,8 +328,8 @@ div.wunderbaum {
327
328
  // $hover-color 3.88px,
328
329
  transparent,
329
330
  transparent 3.88px,
330
- $grid-color 3.88px,
331
- $grid-color 7.78px
331
+ var(--wb-grid-color) 3.88px,
332
+ var(--wb-grid-color) 7.78px
332
333
  );
333
334
  animation: wb-busy-animation 2s linear infinite;
334
335
  }
@@ -386,8 +387,8 @@ div.wunderbaum {
386
387
  overflow: hidden;
387
388
  height: var(--wb-row-inner-height);
388
389
  line-height: var(--wb-row-inner-height);
389
- padding: 0 $col-padding-x;
390
- border-right: 1px solid $grid-color;
390
+ padding: 0 val(--wb-col-padding-x);
391
+ border-right: 1px solid var(--wb-grid-color);
391
392
  white-space: nowrap;
392
393
 
393
394
  &:last-of-type {
@@ -481,7 +482,7 @@ div.wunderbaum {
481
482
  }
482
483
 
483
484
  span.wb-col {
484
- border-right: 1px solid $grid-color;
485
+ border-right: 1px solid var(--wb-grid-color);
485
486
 
486
487
  input.wb-input-edit,
487
488
  > input[type="color"],
@@ -617,7 +618,7 @@ div.wunderbaum {
617
618
  z-index: 1000;
618
619
  content: url(../docs/assets/drop_marker_16x32.png);
619
620
  left: 0; //-$icon-outer-width;
620
- top: ($row-outer-height - 16) / 2;
621
+ top: calc(($row-outer-height - --wb-icon-height) / 2);
621
622
  }
622
623
  }
623
624
  }
@@ -637,11 +638,15 @@ div.wunderbaum {
637
638
  div.wb-row.wb-drop-target.wb-drop-after .wb-node .wb-icon::after {
638
639
  content: url(../docs/assets/drop_marker_insert_16x64.png);
639
640
  left: 0; // $icon-outer-width * 1.5;
640
- top: ($row-outer-height - 16) / 2 - $row-outer-height / 2;
641
+ top: calc(
642
+ ($row-outer-height - --wb-icon-height) / 2 - $row-outer-height / 2
643
+ );
641
644
  }
642
645
 
643
646
  div.wb-row.wb-drop-target.wb-drop-after .wb-node .wb-icon::after {
644
- top: ($row-outer-height - 16) / 2 + $row-outer-height / 2;
647
+ top: calc(
648
+ ($row-outer-height - --wb-icon-height) / 2 + $row-outer-height / 2
649
+ );
645
650
  }
646
651
 
647
652
  /* --- SPECIAL EFFECTS --- */
package/src/wunderbaum.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  * @date @DATE
12
12
  */
13
13
 
14
- import "./wunderbaum.scss";
14
+ // import "./wunderbaum.scss";
15
15
  import * as util from "./util";
16
16
  import { FilterExtension } from "./wb_ext_filter";
17
17
  import { KeynavExtension } from "./wb_ext_keynav";
@@ -32,7 +32,7 @@ import {
32
32
  NodeTypeDefinitionMap,
33
33
  ScrollToOptions,
34
34
  SetActiveOptions,
35
- SetModifiedOptions,
35
+ UpdateOptions,
36
36
  SetStatusOptions,
37
37
  NodeRegion,
38
38
  WbEventInfo,
@@ -134,6 +134,10 @@ export class Wunderbaum {
134
134
  /** Expose some useful methods of the util.ts module as `tree._util`. */
135
135
  public _util = util;
136
136
 
137
+ // --- SELECT ---
138
+ // /** @internal */
139
+ // public selectRangeAnchor: WunderbaumNode | null = null;
140
+
137
141
  // --- FILTER ---
138
142
  public filterMode: FilterModeType = null;
139
143
 
@@ -169,9 +173,10 @@ export class Wunderbaum {
169
173
  checkbox: false,
170
174
  minExpandLevel: 0,
171
175
  emptyChildListExpandable: false,
172
- updateThrottleWait: 200,
176
+ // updateThrottleWait: 200,
173
177
  skeleton: false,
174
178
  connectTopBreadcrumb: null, // HTMLElement that receives the top nodes breadcrumb
179
+ selectMode: "multi", // SelectModeType
175
180
  // --- KeyNav ---
176
181
  navigationModeOption: null, // NavModeEnum.startRow,
177
182
  quicksearch: true,
@@ -363,24 +368,30 @@ export class Wunderbaum {
363
368
 
364
369
  // Async mode is sometimes required, because this.element.clientWidth
365
370
  // has a wrong value at start???
366
- this.setModified(ChangeType.any);
371
+ this.update(ChangeType.any);
367
372
 
368
373
  // --- Bind listeners
369
374
  this.element.addEventListener("scroll", (e: Event) => {
370
375
  // this.log(`scroll, scrollTop:${e.target.scrollTop}`, e);
371
- this.setModified(ChangeType.scroll);
376
+ this.update(ChangeType.scroll);
372
377
  });
373
378
 
374
379
  this.resizeObserver = new ResizeObserver((entries) => {
375
380
  // this.log("ResizeObserver: Size changed", entries);
376
- this.setModified(ChangeType.resize);
381
+ this.update(ChangeType.resize);
377
382
  });
378
383
  this.resizeObserver.observe(this.element);
379
384
 
380
385
  util.onEvent(this.nodeListElement, "click", "div.wb-row", (e) => {
381
386
  const info = Wunderbaum.getEventInfo(e);
382
387
  const node = info.node;
383
- // this.log("click", info, e);
388
+ const mouseEvent = e as MouseEvent;
389
+
390
+ // this.log("click", info);
391
+
392
+ // if (this._selectRange(info) === false) {
393
+ // return;
394
+ // }
384
395
 
385
396
  if (
386
397
  this._callEvent("click", { event: e, node: node, info: info }) === false
@@ -389,6 +400,10 @@ export class Wunderbaum {
389
400
  return false;
390
401
  }
391
402
  if (node) {
403
+ if (mouseEvent.ctrlKey) {
404
+ node.toggleSelected();
405
+ return;
406
+ }
392
407
  // Edit title if 'clickActive' is triggered:
393
408
  const trigger = this.getOption("edit.trigger");
394
409
  const slowClickDelay = this.getOption("edit.slowClickDelay");
@@ -410,7 +425,7 @@ export class Wunderbaum {
410
425
  if (info.region === NodeRegion.expander) {
411
426
  node.setExpanded(!node.isExpanded());
412
427
  } else if (info.region === NodeRegion.checkbox) {
413
- node.setSelected(!node.isSelected());
428
+ node.toggleSelected();
414
429
  }
415
430
  }
416
431
  this.lastClickTime = Date.now();
@@ -921,7 +936,7 @@ export class Wunderbaum {
921
936
  // public cellNavMode = false;
922
937
  // public lastQuicksearchTime = 0;
923
938
  // public lastQuicksearchTerm = "";
924
- this.setModified(ChangeType.structure);
939
+ this.update(ChangeType.structure);
925
940
  }
926
941
 
927
942
  /**
@@ -984,7 +999,7 @@ export class Wunderbaum {
984
999
  (this.options as any)[name] = value;
985
1000
  switch (name) {
986
1001
  case "checkbox":
987
- this.setModified(ChangeType.any);
1002
+ this.update(ChangeType.any);
988
1003
  break;
989
1004
  case "enabled":
990
1005
  this.setEnabled(!!value);
@@ -1010,8 +1025,15 @@ export class Wunderbaum {
1010
1025
  return this.isGrid() ? header !== false : !!header;
1011
1026
  }
1012
1027
 
1013
- /** Run code, but defer rendering of viewport until done. */
1014
- runWithoutUpdate(func: () => any, hint = null): void {
1028
+ /** Run code, but defer rendering of viewport until done.
1029
+ *
1030
+ * ```
1031
+ * tree.runWithDeferredUpdate(() => {
1032
+ * return someFuncThatWouldUpdateManyNodes();
1033
+ * });
1034
+ * ```
1035
+ */
1036
+ runWithDeferredUpdate(func: () => any, hint = null): void {
1015
1037
  try {
1016
1038
  this.enableUpdate(false);
1017
1039
  const res = func();
@@ -1022,30 +1044,72 @@ export class Wunderbaum {
1022
1044
  }
1023
1045
  }
1024
1046
 
1025
- /** Recursively expand all expandable nodes (triggers lazy load id needed). */
1047
+ /** Recursively expand all expandable nodes (triggers lazy load if needed). */
1026
1048
  async expandAll(flag: boolean = true, options?: ExpandAllOptions) {
1027
1049
  await this.root.expandAll(flag, options);
1028
1050
  }
1029
1051
 
1030
1052
  /** Recursively select all nodes. */
1031
1053
  selectAll(flag: boolean = true) {
1032
- try {
1033
- this.enableUpdate(false);
1034
- this.visit((node) => {
1035
- node.setSelected(flag);
1036
- });
1037
- } finally {
1038
- this.enableUpdate(true);
1039
- }
1054
+ return this.root.setSelected(flag, { propagateDown: true });
1055
+ }
1056
+
1057
+ /** Toggle select all nodes. */
1058
+ toggleSelect() {
1059
+ this.selectAll(this.root._anySelectable());
1060
+ }
1061
+
1062
+ /**
1063
+ * Return an array of selected nodes.
1064
+ * @param stopOnParents only return the topmost selected node (useful with selectMode 'hier')
1065
+ */
1066
+ getSelectedNodes(stopOnParents: boolean = false): WunderbaumNode[] {
1067
+ return this.root.getSelectedNodes(stopOnParents);
1068
+ }
1069
+
1070
+ /*
1071
+ * Return an array of selected nodes.
1072
+ */
1073
+ protected _selectRange(eventInfo: WbEventInfo): false | void {
1074
+ this.logDebug("_selectRange", eventInfo);
1075
+ util.error("Not yet implemented.");
1076
+ // const mode = this.options.selectMode!;
1077
+ // if (mode !== "multi") {
1078
+ // this.logDebug(`Range selection only available for selectMode 'multi'`);
1079
+ // return;
1080
+ // }
1081
+
1082
+ // if (eventInfo.canonicalName === "Meta+click") {
1083
+ // eventInfo.node?.toggleSelected();
1084
+ // return false; // don't
1085
+ // } else if (eventInfo.canonicalName === "Shift+click") {
1086
+ // let from = this.activeNode;
1087
+ // let to = eventInfo.node;
1088
+ // if (!from || !to || from === to) {
1089
+ // return;
1090
+ // }
1091
+ // this.runWithDeferredUpdate(() => {
1092
+ // this.visitRows(
1093
+ // (node) => {
1094
+ // node.setSelected();
1095
+ // },
1096
+ // {
1097
+ // includeHidden: true,
1098
+ // includeSelf: false,
1099
+ // start: from,
1100
+ // reverse: from!._rowIdx! > to!._rowIdx!,
1101
+ // }
1102
+ // );
1103
+ // });
1104
+ // return false;
1105
+ // }
1040
1106
  }
1041
1107
 
1042
- /** Return the number of nodes in the data model.*/
1108
+ /** Return the number of nodes in the data model.
1109
+ * @param visible if true, nodes that are hidden due to collapsed parents are ignored.
1110
+ */
1043
1111
  count(visible = false): number {
1044
- if (visible) {
1045
- return this.treeRowCount;
1046
- // return this.viewNodes.size;
1047
- }
1048
- return this.keyMap.size;
1112
+ return visible ? this.treeRowCount : this.keyMap.size;
1049
1113
  }
1050
1114
 
1051
1115
  /** @internal sanity check. */
@@ -1152,7 +1216,7 @@ export class Wunderbaum {
1152
1216
  break;
1153
1217
  case "first":
1154
1218
  // First visible node
1155
- this.visit(function (n) {
1219
+ this.visit((n) => {
1156
1220
  if (n.isVisible()) {
1157
1221
  res = n;
1158
1222
  return false;
@@ -1160,7 +1224,7 @@ export class Wunderbaum {
1160
1224
  });
1161
1225
  break;
1162
1226
  case "last":
1163
- this.visit(function (n) {
1227
+ this.visit((n) => {
1164
1228
  // last visible node
1165
1229
  if (n.isVisible()) {
1166
1230
  res = n;
@@ -1306,6 +1370,8 @@ export class Wunderbaum {
1306
1370
  node = Wunderbaum.getNode(target),
1307
1371
  tree = node ? node.tree : Wunderbaum.getTree(event),
1308
1372
  res: WbEventInfo = {
1373
+ event: <MouseEvent>event,
1374
+ canonicalName: util.eventToString(event),
1309
1375
  tree: tree!,
1310
1376
  node: node,
1311
1377
  region: NodeRegion.unknown,
@@ -1490,7 +1556,7 @@ export class Wunderbaum {
1490
1556
  // Make sure the topNode is always visible
1491
1557
  this.scrollTo(topNode);
1492
1558
  }
1493
- // this.setModified(ChangeType.scroll);
1559
+ // this.update(ChangeType.scroll);
1494
1560
  }
1495
1561
  }
1496
1562
 
@@ -1521,7 +1587,7 @@ export class Wunderbaum {
1521
1587
  `scrollToHorz(${this.activeColIdx}): ${colLeft}..${colRight}, fixedOfs=${fixedWidth}, vpWidth=${vpWidth}, curLeft=${scrollLeft} -> ${newLeft}`
1522
1588
  );
1523
1589
  this.element.scrollLeft = newLeft;
1524
- // this.setModified(ChangeType.scroll);
1590
+ // this.update(ChangeType.scroll);
1525
1591
  }
1526
1592
  /**
1527
1593
  * Set column #colIdx to 'active'.
@@ -1544,7 +1610,7 @@ export class Wunderbaum {
1544
1610
  }
1545
1611
  }
1546
1612
 
1547
- this.activeNode?.setModified(ChangeType.status);
1613
+ this.activeNode?.update(ChangeType.status);
1548
1614
 
1549
1615
  // Update `wb-active` class for all cell spans
1550
1616
  for (let rowDiv of this.nodeListElement.children) {
@@ -1573,40 +1639,49 @@ export class Wunderbaum {
1573
1639
  }
1574
1640
  }
1575
1641
 
1642
+ /**
1643
+ * @deprecated since v0.3.6: use `update()` instead.
1644
+ */
1645
+ setModified(change: ChangeType, ...args: any[]): void {
1646
+ this.logWarn("setModified() is deprecated: use update() instead.");
1647
+ // @ts-ignore
1648
+ // (!) TS2556: A spread argument must either have a tuple type or be passed to a rest parameter.
1649
+ return this.update.call(this, change, ...args);
1650
+ }
1576
1651
  /**
1577
1652
  * Schedule an update request to reflect a tree change.
1578
1653
  * The render operation is async and debounced unless the `immediate` option
1579
1654
  * is set.
1580
- * Use {@link WunderbaumNode.setModified()} if only a single node has changed,
1581
- * or {@link WunderbaumNode.render()}) to pass special options.
1655
+ * Use {@link WunderbaumNode.update()} if only a single node has changed,
1656
+ * or {@link WunderbaumNode._render()}) to pass special options.
1582
1657
  */
1583
- setModified(change: ChangeType, options?: SetModifiedOptions): void;
1658
+ update(change: ChangeType, options?: UpdateOptions): void;
1584
1659
 
1585
1660
  /**
1586
1661
  * Update a row to reflect a single node's modification.
1587
1662
  *
1588
- * @see {@link WunderbaumNode.setModified()}, {@link WunderbaumNode.render()}
1663
+ * @see {@link WunderbaumNode.update()}, {@link WunderbaumNode._render()}
1589
1664
  */
1590
- setModified(
1665
+ update(
1591
1666
  change: ChangeType,
1592
1667
  node: WunderbaumNode,
1593
- options?: SetModifiedOptions
1668
+ options?: UpdateOptions
1594
1669
  ): void;
1595
1670
 
1596
- setModified(
1671
+ update(
1597
1672
  change: ChangeType,
1598
1673
  node?: WunderbaumNode | any,
1599
- options?: SetModifiedOptions
1674
+ options?: UpdateOptions
1600
1675
  ): void {
1601
1676
  if (this._disableUpdateCount) {
1602
1677
  // Assuming that we redraw all when enableUpdate() is re-enabled.
1603
1678
  // this.log(
1604
- // `IGNORED setModified(${change}) node=${node} (disable level ${this._disableUpdateCount})`
1679
+ // `IGNORED update(${change}) node=${node} (disable level ${this._disableUpdateCount})`
1605
1680
  // );
1606
1681
  this._disableUpdateIgnoreCount++;
1607
1682
  return;
1608
1683
  }
1609
- // this.log(`setModified(${change}) node=${node}`);
1684
+ // this.log(`update(${change}) node=${node}`);
1610
1685
  if (!(node instanceof WunderbaumNode)) {
1611
1686
  options = node;
1612
1687
  node = null;
@@ -1641,7 +1716,7 @@ export class Wunderbaum {
1641
1716
  // Single nodes are immediately updated if already inside the viewport
1642
1717
  // (otherwise we can ignore)
1643
1718
  if (node._rowElem) {
1644
- node.render({ change: change });
1719
+ node._render({ change: change });
1645
1720
  }
1646
1721
  break;
1647
1722
  default:
@@ -1704,7 +1779,7 @@ export class Wunderbaum {
1704
1779
  this.setColumn(0);
1705
1780
  }
1706
1781
  this.element.classList.toggle("wb-cell-mode", flag);
1707
- this.activeNode?.setModified(ChangeType.status);
1782
+ this.activeNode?.update(ChangeType.status);
1708
1783
  }
1709
1784
 
1710
1785
  /** Set the tree's navigation mode option. */
@@ -1886,7 +1961,7 @@ export class Wunderbaum {
1886
1961
  // if (modified) {
1887
1962
  // this._renderHeaderMarkup();
1888
1963
  // if (options.renderMarkup) {
1889
- // this.setModified(ChangeType.header, { removeMarkup: true });
1964
+ // this.update(ChangeType.header, { removeMarkup: true });
1890
1965
  // } else if (options.updateRows) {
1891
1966
  // this._updateRows();
1892
1967
  // }
@@ -1916,7 +1991,13 @@ export class Wunderbaum {
1916
1991
  colElem.style.left = col._ofsPx + "px";
1917
1992
  colElem.style.width = col._widthPx + "px";
1918
1993
  // Add classes from `columns` definition to `<div.wb-col>` cells
1919
- col.classes ? colElem.classList.add(...col.classes.split(" ")) : 0;
1994
+ if (typeof col.headerClasses === "string") {
1995
+ col.headerClasses
1996
+ ? colElem.classList.add(...col.headerClasses.split(" "))
1997
+ : 0;
1998
+ } else {
1999
+ col.classes ? colElem.classList.add(...col.classes.split(" ")) : 0;
2000
+ }
1920
2001
 
1921
2002
  const title = util.escapeHtml(col.title || col.id);
1922
2003
  let tooltip = "";
@@ -1936,11 +2017,11 @@ export class Wunderbaum {
1936
2017
  }
1937
2018
 
1938
2019
  /**
1939
- * Render pending changes that were scheduled using {@link WunderbaumNode.setModified} if any.
2020
+ * Render pending changes that were scheduled using {@link WunderbaumNode.update} if any.
1940
2021
  *
1941
2022
  * This is hardly ever neccessary, since we normally either
1942
- * - call `setModified(ChangeType.TYPE)` (async, throttled), or
1943
- * - call `setModified(ChangeType.TYPE, {immediate: true})` (synchronous)
2023
+ * - call `update(ChangeType.TYPE)` (async, throttled), or
2024
+ * - call `update(ChangeType.TYPE, {immediate: true})` (synchronous)
1944
2025
  *
1945
2026
  * `updatePendingModifications()` will only force immediate execution of
1946
2027
  * pending async changes if any.
@@ -1956,7 +2037,7 @@ export class Wunderbaum {
1956
2037
  * It calls `updateColumns()` and `_updateRows()`.
1957
2038
  *
1958
2039
  * This protected method should not be called directly but via
1959
- * {@link WunderbaumNode.setModified}`, {@link Wunderbaum.setModified},
2040
+ * {@link WunderbaumNode.update}`, {@link Wunderbaum.update},
1960
2041
  * or {@link Wunderbaum.updatePendingModifications}.
1961
2042
  * @internal
1962
2043
  */
@@ -2126,7 +2207,7 @@ export class Wunderbaum {
2126
2207
  if (rowDiv) {
2127
2208
  rowDiv.style.top = idx * ROW_HEIGHT + "px";
2128
2209
  }
2129
- node.render({ top: top, after: prevElem });
2210
+ node._render({ top: top, after: prevElem });
2130
2211
  // node.log("render", top, prevElem, "=>", node._rowElem);
2131
2212
  prevElem = node._rowElem!;
2132
2213
  }
@@ -2227,7 +2308,7 @@ export class Wunderbaum {
2227
2308
  node.children.length &&
2228
2309
  (includeHidden || node.expanded)
2229
2310
  ) {
2230
- res = node.visit(function (n: WunderbaumNode) {
2311
+ res = node.visit((n: WunderbaumNode) => {
2231
2312
  if (n === stopNode) {
2232
2313
  return false;
2233
2314
  }
@@ -2366,7 +2447,7 @@ export class Wunderbaum {
2366
2447
  `enableUpdate(): active again. Re-painting to catch up with ${this._disableUpdateIgnoreCount} ignored update requests...`
2367
2448
  );
2368
2449
  this._disableUpdateIgnoreCount = 0;
2369
- this.setModified(ChangeType.any, { immediate: true });
2450
+ this.update(ChangeType.any, { immediate: true });
2370
2451
  }
2371
2452
  } else {
2372
2453
  this._disableUpdateCount++;