wunderbaum 0.2.0 → 0.3.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/types.ts CHANGED
@@ -1,14 +1,16 @@
1
1
  /*!
2
2
  * Wunderbaum - types
3
- * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
3
+ * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
4
4
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
5
  */
6
6
 
7
7
  import { WunderbaumNode } from "./wb_node";
8
8
  import { Wunderbaum } from "./wunderbaum";
9
9
 
10
- /** Passed to find... methods. Should return true if node matches. */
10
+ /** Passed to `find...()` methods. Should return true if node matches. */
11
11
  export type MatcherCallback = (node: WunderbaumNode) => boolean;
12
+ /** Passed to `sortChildren()` methods. Should return -1, 0, or 1. */
13
+ export type SortCallback = (a: WunderbaumNode, b: WunderbaumNode) => number;
12
14
  /** When set as option, called when the value is needed (e.g. `colspan` type definition). */
13
15
  export type BoolOptionResolver = (node: WunderbaumNode) => boolean;
14
16
  /** When set as option, called when the value is needed (e.g. `icon` type definition). */
@@ -33,9 +35,11 @@ export interface WbTreeEventType {
33
35
  type: string;
34
36
  /** The affected tree instance. */
35
37
  tree: Wunderbaum;
36
- /** Exposed utility module methods. */
38
+ /** Exposed utility module methods
39
+ * (see [API docs](https://mar10.github.io/wunderbaum/api/modules/util.html)).
40
+ */
37
41
  util: any;
38
- /** Originating HTML event, e.g. `click` if any. */
42
+ /** Originating HTML event if any (e.g. `click`). */
39
43
  event?: Event;
40
44
  // [key: string]: unknown;
41
45
  }
@@ -238,51 +242,61 @@ export interface WbEventInfo {
238
242
 
239
243
  export type FilterModeType = null | "dim" | "hide";
240
244
  export type ApplyCommandType =
241
- | "moveUp"
242
- | "moveDown"
243
- | "indent"
244
- | "outdent"
245
- | "remove"
246
- | "rename"
247
245
  | "addChild"
248
246
  | "addSibling"
249
- | "cut"
250
247
  | "copy"
251
- | "paste"
248
+ | "cut"
252
249
  | "down"
253
250
  | "first"
251
+ | "indent"
254
252
  | "last"
255
253
  | "left"
254
+ | "moveDown"
255
+ | "moveUp"
256
+ | "outdent"
256
257
  | "pageDown"
257
258
  | "pageUp"
258
259
  | "parent"
260
+ | "paste"
261
+ | "remove"
262
+ | "rename"
259
263
  | "right"
260
264
  | "up";
261
265
 
262
266
  export type NodeFilterResponse = "skip" | "branch" | boolean | void;
263
267
  export type NodeFilterCallback = (node: WunderbaumNode) => NodeFilterResponse;
264
- export type AddNodeType = "before" | "after" | "prependChild" | "appendChild";
265
- export type DndModeType = "before" | "after" | "over";
266
268
 
267
- /** Possible values for `setModified()`. */
269
+ /**
270
+ * Possible values for {@link WunderbaumNode.setModified()} and {@link Wunderbaum.setModified()}.
271
+ */
268
272
  export enum ChangeType {
269
273
  /** Re-render the whole viewport, headers, and all rows. */
270
274
  any = "any",
271
- /** Update current row title, icon, columns, and status. */
275
+ /** A node's title, icon, columns, or status have changed. Update the existing row markup. */
272
276
  data = "data",
273
- /** Redraw the header and update the width of all row columns. */
274
- header = "header",
275
- /** Re-render the whole current row. */
277
+ /** The `tree.columns` definition has changed beyond simple width adjustments. */
278
+ colStructure = "colStructure",
279
+ /** The viewport/window was resized. Adjust layout attributes for all elements. */
280
+ resize = "resize",
281
+ /** A node's definition has changed beyond status and data. Re-render the whole row's markup. */
276
282
  row = "row",
277
- /** Alias for 'any'. */
283
+ /** Nodes have been added, removed, etc. Update markup. */
278
284
  structure = "structure",
279
- /** Update current row's classes, to reflect active, selected, ... */
285
+ /** A node's status has changed. Update current row's classes, to reflect active, selected, ... */
280
286
  status = "status",
281
- /** Update the 'top' property of all rows. */
282
- vscroll = "vscroll",
287
+ /** Vertical scroll event. Update the 'top' property of all rows. */
288
+ scroll = "scroll",
289
+ }
290
+
291
+ /* Internal use. */
292
+ export enum RenderFlag {
293
+ clearMarkup = "clearMarkup",
294
+ header = "header",
295
+ redraw = "redraw",
296
+ scroll = "scroll",
283
297
  }
284
298
 
285
- /** Possible values for `setStatus()`. */
299
+ /** Possible values for {@link WunderbaumNode.setStatus()}. */
286
300
  export enum NodeStatusType {
287
301
  ok = "ok",
288
302
  loading = "loading",
@@ -368,22 +382,31 @@ export interface MakeVisibleOptions {
368
382
 
369
383
  /** Possible values for {@link Wunderbaum.navigate()}. */
370
384
  export interface NavigateOptions {
385
+ /** Activate the new node (otherwise focus only). @default true */
371
386
  activate?: boolean;
387
+ /** Originating event (e.g. KeyboardEvent) if any. */
372
388
  event?: Event;
373
389
  }
374
390
 
375
391
  /** Possible values for {@link WunderbaumNode.render()}. */
376
392
  export interface RenderOptions {
393
+ /** Which parts need update? @default ChangeType.data */
377
394
  change?: ChangeType;
395
+ /** Where to append a new node. @default 'last' */
378
396
  after?: any;
397
+ /** @internal. @default false */
379
398
  isNew?: boolean;
399
+ /** @internal. @default false */
380
400
  preventScroll?: boolean;
401
+ /** @internal. @default false */
381
402
  isDataChange?: boolean;
403
+ /** @internal. @default false */
382
404
  top?: number;
405
+ /** @internal. @default true */
383
406
  resizeCols?: boolean;
384
407
  }
385
408
 
386
- /** Possible values for {@link scrollIntoView()}. */
409
+ /** Possible values for {@link scrollIntoView()} `options` argument. */
387
410
  export interface ScrollIntoViewOptions {
388
411
  /** Do not animate (currently not implemented). @default false */
389
412
  noAnimation?: boolean;
@@ -395,13 +418,13 @@ export interface ScrollIntoViewOptions {
395
418
  ofsY?: number;
396
419
  }
397
420
 
398
- /** Possible values for {@link Wunderbaum.scrollTo()}. */
421
+ /** Possible values for {@link Wunderbaum.scrollTo()} `options` argument. */
399
422
  export interface ScrollToOptions extends ScrollIntoViewOptions {
400
423
  /** Which node to scroll into the viewport.*/
401
424
  node: WunderbaumNode;
402
425
  }
403
426
 
404
- /** Possible values for `node.setActive()`. */
427
+ /** Possible values for {@link WunderbaumNode.setActive()} `options` argument. */
405
428
  export interface SetActiveOptions {
406
429
  /** Generate (de)activate event, even if node already has this status (default: false). */
407
430
  retrigger?: boolean;
@@ -417,7 +440,7 @@ export interface SetActiveOptions {
417
440
  colIdx?: number;
418
441
  }
419
442
 
420
- /** Possible values for `node.setExpanded()`. */
443
+ /** Possible values for {@link WunderbaumNode.setExpanded()} `options` argument. */
421
444
  export interface SetExpandedOptions {
422
445
  /** Ignore {@link minExpandLevel}. @default false */
423
446
  force?: boolean;
@@ -431,15 +454,15 @@ export interface SetExpandedOptions {
431
454
  scrollIntoView?: boolean;
432
455
  }
433
456
 
434
- /** Possible values for `node.setSetModified()`. */
457
+ /** Possible values for {@link WunderbaumNode.setModified()} `options` argument. */
435
458
  export interface SetModifiedOptions {
436
459
  /** Force immediate redraw instead of throttled/async mode. @default false */
437
460
  immediate?: boolean;
438
- /** Remove HTML markup of all rendered nodes before redraw. @default false */
439
- removeMarkup?: boolean;
461
+ // /** Remove HTML markup of all rendered nodes before redraw. @default false */
462
+ // removeMarkup?: boolean;
440
463
  }
441
464
 
442
- /** Possible values for `node.setSelected()`. */
465
+ /** Possible values for {@link WunderbaumNode.setSelected()} `options` argument. */
443
466
  export interface SetSelectedOptions {
444
467
  /** Ignore restrictions. @default false */
445
468
  force?: boolean;
@@ -447,7 +470,7 @@ export interface SetSelectedOptions {
447
470
  noEvents?: boolean;
448
471
  }
449
472
 
450
- /** Possible values for `node.setSetModified()`. */
473
+ /** Possible values for {@link WunderbaumNode.setStatus()} `options` argument. */
451
474
  export interface SetStatusOptions {
452
475
  /** Displayed as status node title. */
453
476
  message?: string;
@@ -455,25 +478,31 @@ export interface SetStatusOptions {
455
478
  details?: string;
456
479
  }
457
480
 
458
- /** Possible values for {@link Wunderbaum.updateColumns()}. */
459
- export interface UpdateColumnsOptions {
460
- calculateCols?: boolean;
461
- updateRows?: boolean;
462
- }
463
-
464
- /** Possible values for {@link Wunderbaum.visitRows()} and {@link Wunderbaum.visitRowsUp()}. */
481
+ /** Options passed to {@link Wunderbaum.visitRows()}. */
465
482
  export interface VisitRowsOptions {
466
- reverse?: boolean;
467
- includeSelf?: boolean;
483
+ /** Skip filtered nodes and children of collapsed nodes. @default false */
468
484
  includeHidden?: boolean;
469
- wrap?: boolean;
485
+ /** Return the start node as first result. @default true */
486
+ includeSelf?: boolean;
487
+ /** Traverse in opposite direction, i.e. bottom up. @default false */
488
+ reverse?: boolean;
489
+ /** Start traversal at this node @default first (topmost) tree node */
470
490
  start?: WunderbaumNode | null;
491
+ /** Wrap around at last node and continue at the top,
492
+ * until the start node is reached again @default false */
493
+ wrap?: boolean;
471
494
  }
472
495
 
473
496
  /* -----------------------------------------------------------------------------
474
497
  * wb_ext_dnd
475
498
  * ---------------------------------------------------------------------------*/
476
499
 
500
+ export type InsertNodeType =
501
+ | "before"
502
+ | "after"
503
+ | "prependChild"
504
+ | "appendChild";
505
+ // export type DndModeType = "before" | "after" | "over";
477
506
  export type DropRegionType = "over" | "before" | "after";
478
507
  export type DropRegionTypeSet = Set<DropRegionType>;
479
508
  // type AllowedDropRegionType =
@@ -490,140 +519,140 @@ export type DropRegionTypeSet = Set<DropRegionType>;
490
519
  export type DndOptionsType = {
491
520
  /**
492
521
  * Expand nodes after n milliseconds of hovering
493
- * Default: 1500
522
+ * @default 1500
494
523
  */
495
524
  autoExpandMS: 1500;
496
525
  // /**
497
526
  // * Additional offset for drop-marker with hitMode = "before"/"after"
498
- // * Default:
527
+ // * @default
499
528
  // */
500
529
  // dropMarkerInsertOffsetX: -16;
501
530
  // /**
502
531
  // * Absolute position offset for .fancytree-drop-marker relatively to ..fancytree-title (icon/img near a node accepting drop)
503
- // * Default:
532
+ // * @default
504
533
  // */
505
534
  // dropMarkerOffsetX: -24;
506
535
  // /**
507
536
  // * Root Container used for drop marker (could be a shadow root)
508
537
  // * (#1021 `document.body` is not available yet)
509
- // * Default:
538
+ // * @default
510
539
  // */
511
540
  // dropMarkerParent: "body";
512
541
  /**
513
542
  * true: Drag multiple (i.e. selected) nodes. Also a callback() is allowed
514
- * Default: false
543
+ * @default false
515
544
  */
516
545
  multiSource: false;
517
546
  /**
518
547
  * Restrict the possible cursor shapes and modifier operations (can also be set in the dragStart event)
519
- * Default: "all"
548
+ * @default "all"
520
549
  */
521
550
  effectAllowed: "all";
522
551
  // /**
523
552
  // * 'copy'|'link'|'move'|'auto'(calculate from `effectAllowed`+modifier keys) or callback(node, data) that returns such string.
524
- // * Default:
553
+ // * @default
525
554
  // */
526
555
  // dropEffect: "auto";
527
556
  /**
528
557
  * Default dropEffect ('copy', 'link', or 'move') when no modifier is pressed (overide in dragDrag, dragOver).
529
- * Default: "move"
558
+ * @default "move"
530
559
  */
531
560
  dropEffectDefault: string;
532
561
  /**
533
562
  * Prevent dropping nodes from different Wunderbaum trees
534
- * Default: false
563
+ * @default false
535
564
  */
536
565
  preventForeignNodes: boolean;
537
566
  /**
538
567
  * Prevent dropping items on unloaded lazy Wunderbaum tree nodes
539
- * Default: true
568
+ * @default true
540
569
  */
541
570
  preventLazyParents: boolean;
542
571
  /**
543
572
  * Prevent dropping items other than Wunderbaum tree nodes
544
- * Default: false
573
+ * @default false
545
574
  */
546
575
  preventNonNodes: boolean;
547
576
  /**
548
577
  * Prevent dropping nodes on own descendants
549
- * Default: true
578
+ * @default true
550
579
  */
551
580
  preventRecursion: boolean;
552
581
  /**
553
582
  * Prevent dropping nodes under same direct parent
554
- * Default: false
583
+ * @default false
555
584
  */
556
585
  preventSameParent: false;
557
586
  /**
558
587
  * Prevent dropping nodes 'before self', etc. (move only)
559
- * Default: true
588
+ * @default true
560
589
  */
561
590
  preventVoidMoves: boolean;
562
591
  /**
563
592
  * Enable auto-scrolling while dragging
564
- * Default: true
593
+ * @default true
565
594
  */
566
595
  scroll: boolean;
567
596
  /**
568
597
  * Active top/bottom margin in pixel
569
- * Default: 20
598
+ * @default 20
570
599
  */
571
600
  scrollSensitivity: 20;
572
601
  /**
573
602
  * Pixel per event
574
- * Default: 5
603
+ * @default 5
575
604
  */
576
605
  scrollSpeed: 5;
577
606
  // /**
578
607
  // * Allow dragging of nodes to different IE windows
579
- // * Default: false
608
+ // * @default false
580
609
  // */
581
610
  // setTextTypeJson: boolean;
582
611
  /**
583
612
  * Optional callback passed to `toDict` on dragStart @since 2.38
584
- * Default: null
613
+ * @default null
585
614
  */
586
615
  sourceCopyHook: null;
587
616
  // Events (drag support)
588
617
  /**
589
618
  * Callback(sourceNode, data), return true, to enable dnd drag
590
- * Default: null
619
+ * @default null
591
620
  */
592
621
  dragStart?: WbNodeEventType;
593
622
  /**
594
623
  * Callback(sourceNode, data)
595
- * Default: null
624
+ * @default null
596
625
  */
597
626
  dragDrag: null;
598
627
  /**
599
628
  * Callback(sourceNode, data)
600
- * Default: null
629
+ * @default null
601
630
  */
602
631
  dragEnd: null;
603
632
  // Events (drop support)
604
633
  /**
605
634
  * Callback(targetNode, data), return true, to enable dnd drop
606
- * Default: null
635
+ * @default null
607
636
  */
608
637
  dragEnter: null;
609
638
  /**
610
639
  * Callback(targetNode, data)
611
- * Default: null
640
+ * @default null
612
641
  */
613
642
  dragOver: null;
614
643
  /**
615
644
  * Callback(targetNode, data), return false to prevent autoExpand
616
- * Default: null
645
+ * @default null
617
646
  */
618
647
  dragExpand: null;
619
648
  /**
620
649
  * Callback(targetNode, data)
621
- * Default: null
650
+ * @default null
622
651
  */
623
652
  dragDrop: null;
624
653
  /**
625
654
  * Callback(targetNode, data)
626
- * Default: null
655
+ * @default null
627
656
  */
628
657
  dragLeave: null;
629
658
  };
package/src/util.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * Wunderbaum - util
3
- * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
3
+ * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
4
4
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
5
  */
6
6
  /** @module util */
@@ -202,17 +202,19 @@ export function extractHtmlText(s: string) {
202
202
  * the element is checked, unchecked, or indeterminate.
203
203
  * For datetime input control a numerical value is assumed, etc.
204
204
  *
205
- * Common use case: store the new user input in the `change` event:
205
+ * Common use case: store the new user input in a `change` event handler:
206
206
  *
207
207
  * ```ts
208
208
  * change: (e) => {
209
+ * const tree = e.tree;
210
+ * const node = e.node;
209
211
  * // Read the value from the input control that triggered the change event:
210
- * let value = e.tree.getValueFromElem(e.element);
211
- * //
212
- * e.node.data[]
212
+ * let value = tree.getValueFromElem(e.element);
213
+ * // and store it to the node model (assuming the column id matches the property name)
214
+ * node.data[e.info.colId] = value;
213
215
  * },
214
216
  * ```
215
- * @param elem `<input>` or `<select>` element Also a parent `span.wb-col` is accepted.
217
+ * @param elem `<input>` or `<select>` element. Also a parent `span.wb-col` is accepted.
216
218
  * @param coerce pass true to convert date/time inputs to `Date`.
217
219
  * @returns the value
218
220
  */
@@ -280,6 +282,23 @@ export function getValueFromElem(elem: HTMLElement, coerce = false): any {
280
282
  * value is truethy, falsy, or `null`.
281
283
  * For datetime input control a numerical value is assumed, etc.
282
284
  *
285
+ * Common use case: update embedded input controls in a `render` event handler:
286
+ *
287
+ * ```ts
288
+ * render: (e) => {
289
+ * // e.node.log(e.type, e, e.node.data);
290
+ *
291
+ * for (const col of Object.values(e.renderColInfosById)) {
292
+ * switch (col.id) {
293
+ * default:
294
+ * // Assumption: we named column.id === node.data.NAME
295
+ * util.setValueToElem(col.elem, e.node.data[col.id]);
296
+ * break;
297
+ * }
298
+ * }
299
+ * },
300
+ * ```
301
+ *
283
302
  * @param elem `<input>` or `<select>` element Also a parent `span.wb-col` is accepted.
284
303
  * @param value a value that matches the target element.
285
304
  */
@@ -313,7 +332,6 @@ export function setValueToElem(elem: HTMLElement, value: any): void {
313
332
  case "datetime":
314
333
  case "datetime-local":
315
334
  input.valueAsDate = new Date(value);
316
- // input.valueAsDate = value; // breaks in Edge?
317
335
  break;
318
336
  case "number":
319
337
  case "range":
@@ -324,7 +342,7 @@ export function setValueToElem(elem: HTMLElement, value: any): void {
324
342
  }
325
343
  break;
326
344
  case "radio":
327
- error("Not implemented");
345
+ error(`Not yet implemented: ${type}`);
328
346
  // const name = input.name;
329
347
  // const checked = input.parentElement!.querySelector(
330
348
  // `input[name="${name}"]:checked`
@@ -350,7 +368,7 @@ export function setValueToElem(elem: HTMLElement, value: any): void {
350
368
  }
351
369
  }
352
370
 
353
- /** Show/hide element by setting the `display`style to 'none'. */
371
+ /** Show/hide element by setting the `display` style to 'none'. */
354
372
  export function setElemDisplay(elem: string | Element, flag: boolean): void {
355
373
  const style = (<HTMLElement>elemFromSelector(elem)).style;
356
374
  if (flag) {
@@ -401,7 +419,23 @@ export function eventTargetFromSelector(
401
419
  * The result also contains a prefix for modifiers if any, for example
402
420
  * `"x"`, `"F2"`, `"Control+Home"`, or `"Shift+clickright"`.
403
421
  * This is especially useful in `switch` statements, to make sure that modifier
404
- * keys are considered and handled correctly.
422
+ * keys are considered and handled correctly:
423
+ * ```ts
424
+ * const eventName = util.eventToString(e);
425
+ * switch (eventName) {
426
+ * case "+":
427
+ * case "Add":
428
+ * ...
429
+ * break;
430
+ * case "Enter":
431
+ * case "End":
432
+ * case "Control+End":
433
+ * case "Meta+ArrowDown":
434
+ * case "PageDown":
435
+ * ...
436
+ * break;
437
+ * }
438
+ * ```
405
439
  */
406
440
  export function eventToString(event: Event): string {
407
441
  let key = (<KeyboardEvent>event).key,
@@ -706,6 +740,23 @@ export function toSet(val: any): Set<string> {
706
740
  throw new Error("Cannot convert to Set<string>: " + val);
707
741
  }
708
742
 
743
+ // /** Check if a string is contained in an Array or Set. */
744
+ // export function isAnyOf(s: string, items: Array<string>|Set<string>): boolean {
745
+ // return Array.prototype.includes.call(items, s)
746
+ // }
747
+
748
+ // /** Check if an Array or Set has at least one matching entry. */
749
+ // export function hasAnyOf(container: Array<string>|Set<string>, items: Array<string>): boolean {
750
+ // if (Array.isArray(container)) {
751
+ // return container.some(v => )
752
+ // }
753
+ // return container.some(v => {})
754
+ // // const container = toSet(items);
755
+ // // const itemSet = toSet(items);
756
+ // // Array.prototype.includes
757
+ // // throw new Error("Cannot convert to Set<string>: " + val);
758
+ // }
759
+
709
760
  /** Return a canonical string representation for an object's type (e.g. 'array', 'number', ...). */
710
761
  export function type(obj: any): string {
711
762
  return Object.prototype.toString
package/src/wb_ext_dnd.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * Wunderbaum - ext-dnd
3
- * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
3
+ * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
4
4
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
5
  */
6
6
  import * as util from "./util";
@@ -137,7 +137,7 @@ export class DndExtension extends WunderbaumExtension {
137
137
  // Only 'before' and 'after':
138
138
  return dy > ROW_HEIGHT / 2 ? "after" : "before";
139
139
  }
140
- return "over";
140
+ // return "over";
141
141
  }
142
142
 
143
143
  /* Implement auto scrolling when drag cursor is in top/bottom area of scroll parent. */
@@ -225,6 +225,8 @@ export class DndExtension extends WunderbaumExtension {
225
225
 
226
226
  protected onDropEvent(e: DragEvent) {
227
227
  // const isLink = event.dataTransfer.types.includes("text/uri-list");
228
+ const srcNode = this.srcNode;
229
+ const srcTree = srcNode ? srcNode.tree : null;
228
230
  const targetNode = Wunderbaum.getNode(e)!;
229
231
  const dndOpts = this.treeOpts.dnd;
230
232
  const dt = e.dataTransfer!;
@@ -233,7 +235,7 @@ export class DndExtension extends WunderbaumExtension {
233
235
  this._leaveNode();
234
236
  return;
235
237
  }
236
- if (e.type !== "dragover") {
238
+ if (!["dragenter", "dragover", "dragleave"].includes(e.type)) {
237
239
  this.tree.logDebug(
238
240
  "onDropEvent." +
239
241
  e.type +
@@ -261,13 +263,29 @@ export class DndExtension extends WunderbaumExtension {
261
263
  this.lastEnterStamp = Date.now();
262
264
 
263
265
  if (
264
- // Don't allow void operation ('drop on self')
265
- (dndOpts.preventVoidMoves && targetNode === this.srcNode) ||
266
- targetNode.isStatusNode()
266
+ // Don't drop on status node:
267
+ targetNode.isStatusNode() ||
268
+ // Prevent dropping nodes from different Wunderbaum trees:
269
+ (dndOpts.preventForeignNodes && targetNode.tree !== srcTree) ||
270
+ // Prevent dropping items on unloaded lazy Wunderbaum tree nodes:
271
+ (dndOpts.preventLazyParents && !targetNode.isLoaded()) ||
272
+ // Prevent dropping items other than Wunderbaum tree nodes:
273
+ (dndOpts.preventNonNodes && !srcNode) ||
274
+ // Prevent dropping nodes on own descendants:
275
+ (dndOpts.preventRecursion &&
276
+ srcNode &&
277
+ srcNode.isAncestorOf(targetNode)) ||
278
+ // Prevent dropping nodes under same direct parent:
279
+ (dndOpts.preventSameParent &&
280
+ srcNode &&
281
+ targetNode.parent === srcNode.parent) ||
282
+ // Don't allow void operation ('drop on self'): TODO: should be checke onn move only
283
+ (dndOpts.preventVoidMoves && targetNode === srcNode)
267
284
  ) {
268
285
  dt.dropEffect = "none";
269
286
  return true; // Prevent drop operation
270
287
  }
288
+
271
289
  // User may return a set of regions (or `false` to prevent drop)
272
290
  let regionSet = targetNode._callEvent("dnd.dragEnter", { event: e });
273
291
  //
@@ -321,9 +339,11 @@ export class DndExtension extends WunderbaumExtension {
321
339
  } else if (e.type === "drop") {
322
340
  e.stopPropagation(); // prevent browser from opening links?
323
341
  this._leaveNode();
342
+ const region = this.lastDropRegion;
324
343
  targetNode._callEvent("dnd.drop", {
325
344
  event: e,
326
- region: this.lastDropRegion,
345
+ region: region,
346
+ defaultDropMode: region === "over" ? "appendChild" : region,
327
347
  sourceNode: this.srcNode,
328
348
  });
329
349
  }
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * Wunderbaum - ext-edit
3
- * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
3
+ * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
4
4
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
5
  */
6
6
 
@@ -17,7 +17,7 @@ import {
17
17
  } from "./util";
18
18
  import { debounce } from "./debounce";
19
19
  import { WunderbaumNode } from "./wb_node";
20
- import { AddNodeType } from "./types";
20
+ import { InsertNodeType } from "./types";
21
21
  import { WbNodeData } from "./wb_options";
22
22
 
23
23
  // const START_MARKER = "\uFFF7";
@@ -310,7 +310,7 @@ export class EditExtension extends WunderbaumExtension {
310
310
  * Create a new child or sibling node and start edit mode.
311
311
  */
312
312
  createNode(
313
- mode: AddNodeType = "after",
313
+ mode: InsertNodeType = "after",
314
314
  node?: WunderbaumNode | null,
315
315
  init?: string | WbNodeData
316
316
  ) {
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * Wunderbaum - ext-filter
3
- * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
3
+ * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
4
4
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * Wunderbaum - ext-grid
3
- * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
3
+ * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
4
4
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
5
  */
6
6
  import { Wunderbaum } from "./wunderbaum";
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * Wunderbaum - ext-keynav
3
- * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
3
+ * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
4
4
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * Wunderbaum - ext-logger
3
- * Copyright (c) 2021-2022, Martin Wendt. Released under the MIT license.
3
+ * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
4
4
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
5
  */
6
6