wunderbaum 0.3.4 → 0.3.5

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.
@@ -369,781 +369,770 @@ declare module "deferred" {
369
369
  finally(cb: finallyCallbackType): Promise<any>;
370
370
  }
371
371
  }
372
- declare module "wb_options" {
372
+ declare module "wb_node" {
373
373
  /*!
374
- * Wunderbaum - utils
374
+ * Wunderbaum - wunderbaum_node
375
375
  * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
376
376
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
377
377
  */
378
- import { BoolOptionResolver, ColumnDefinitionList, DndOptionsType, NavModeEnum, NodeTypeDefinitionMap, WbActivateEventType, WbChangeEventType, WbClickEventType, WbDeactivateEventType, WbEnhanceTitleEventType, WbErrorEventType, WbInitEventType, WbKeydownEventType, WbNodeEventType, WbReceiveEventType, WbRenderEventType, WbTreeEventType } from "types";
379
- export interface WbNodeData {
380
- title: string;
381
- key?: string;
382
- refKey?: string;
383
- expanded?: boolean;
384
- selected?: boolean;
385
- checkbox?: boolean | string;
386
- colspan?: boolean;
387
- children?: Array<WbNodeData>;
388
- }
378
+ import "./wunderbaum.scss";
379
+ import { Wunderbaum } from "wunderbaum";
380
+ import { AddChildrenOptions, InsertNodeType, ApplyCommandOptions, ApplyCommandType, ChangeType, ExpandAllOptions, MakeVisibleOptions, MatcherCallback, NavigateOptions, NodeAnyCallback, NodeStatusType, NodeStringCallback, NodeVisitCallback, NodeVisitResponse, RenderOptions, ScrollIntoViewOptions, SetActiveOptions, SetExpandedOptions, SetSelectedOptions, SetStatusOptions, SortCallback, NodeToDictCallback, WbNodeData } from "types";
389
381
  /**
390
- * Available options for [[Wunderbaum]].
391
- *
392
- * Options are passed to the constructor as plain object:
393
- *
394
- * ```js
395
- * const tree = new mar10.Wunderbaum({
396
- * id: "demo",
397
- * element: document.getElementById("demo-tree"),
398
- * source: "url/of/data/request",
399
- * ...
400
- * });
401
- * ```
402
- *
403
- * Event handlers are also passed as callbacks
382
+ * A single tree node.
404
383
  *
405
- * ```js
406
- * const tree = new mar10.Wunderbaum({
407
- * ...
408
- * init: (e) => {
409
- * console.log(`Tree ${e.tree} was initialized and loaded.`)
410
- * },
411
- * activate: (e) => {
412
- * console.log(`Node ${e.node} was activated.`)
413
- * },
414
- * ...
415
- * });
416
- * ```
384
+ * **NOTE:** <br>
385
+ * Generally you should not modify properties directly, since this may break
386
+ * the internal bookkeeping.
417
387
  */
418
- export interface WunderbaumOptions {
388
+ export class WunderbaumNode {
389
+ static sequence: number;
390
+ /** Reference to owning tree. */
391
+ tree: Wunderbaum;
392
+ /** Parent node (null for the invisible root node `tree.root`). */
393
+ parent: WunderbaumNode;
394
+ /** Name of the node.
395
+ * @see Use {@link setTitle} to modify. */
396
+ title: string;
397
+ /** Unique key. Passed with constructor or defaults to `SEQUENCE`.
398
+ * @see Use {@link setKey} to modify. */
399
+ readonly key: string;
400
+ /** Reference key. Unlike {@link key}, a `refKey` may occur multiple
401
+ * times within a tree (in this case we have 'clone nodes').
402
+ * @see Use {@link setKey} to modify.
403
+ */
404
+ readonly refKey: string | undefined;
405
+ children: WunderbaumNode[] | null;
406
+ checkbox?: boolean;
407
+ /** If true, (in grid mode) no cells are rendered, except for the node title.*/
408
+ colspan?: boolean;
409
+ icon?: boolean | string;
410
+ lazy: boolean;
411
+ /** Expansion state.
412
+ * @see {@link isExpandable}, {@link isExpanded}, {@link setExpanded}. */
413
+ expanded: boolean;
414
+ /** Selection state.
415
+ * @see {@link isSelected}, {@link setSelected}. */
416
+ selected: boolean;
417
+ type?: string;
418
+ tooltip?: string;
419
+ /** Additional classes added to `div.wb-row`.
420
+ * @see {@link hasClass}, {@link setClass}. */
421
+ classes: Set<string> | null;
422
+ /** Custom data that was passed to the constructor */
423
+ data: any;
424
+ statusNodeType?: string;
425
+ _isLoading: boolean;
426
+ _requestId: number;
427
+ _errorInfo: any | null;
428
+ _partsel: boolean;
429
+ _partload: boolean;
430
+ match?: boolean;
431
+ subMatchCount?: number;
432
+ subMatchBadge?: HTMLElement;
433
+ /** @internal */
434
+ titleWithHighlight?: string;
435
+ _filterAutoExpanded?: boolean;
436
+ _rowIdx: number | undefined;
437
+ _rowElem: HTMLDivElement | undefined;
438
+ constructor(tree: Wunderbaum, parent: WunderbaumNode, data: any);
419
439
  /**
420
- * The target `div` element (or selector) that shall become a Wunderbaum.
440
+ * Return readable string representation for this instance.
441
+ * @internal
421
442
  */
422
- element: string | HTMLDivElement;
443
+ toString(): string;
423
444
  /**
424
- * The identifier of this tree. Used to reference the instance, especially
425
- * when multiple trees are present (e.g. `tree = mar10.Wunderbaum.getTree("demo")`).
445
+ * Iterate all descendant nodes depth-first, pre-order using `for ... of ...` syntax.
446
+ * More concise, but slightly slower than {@link WunderbaumNode.visit}.
426
447
  *
427
- * Default: `"wb_" + COUNTER`.
448
+ * Example:
449
+ * ```js
450
+ * for(const n of node) {
451
+ * ...
452
+ * }
453
+ * ```
428
454
  */
429
- id?: string;
455
+ [Symbol.iterator](): IterableIterator<WunderbaumNode>;
456
+ /** Call event handler if defined in tree.options.
457
+ * Example:
458
+ * ```js
459
+ * node._callEvent("edit.beforeEdit", {foo: 42})
460
+ * ```
461
+ */
462
+ _callEvent(type: string, extra?: any): any;
430
463
  /**
431
- * Define the initial tree data. Typically a URL of an endpoint that serves
432
- * a JSON formatted structure, but also a callback, Promise, or static data
433
- * is allowed.
464
+ * Append (or insert) a list of child nodes.
434
465
  *
435
- * Default: `{}`.
466
+ * Tip: pass `{ before: 0 }` to prepend new nodes as first children.
467
+ *
468
+ * @returns first child added
436
469
  */
437
- source?: string | Array<WbNodeData>;
470
+ addChildren(nodeData: WbNodeData | WbNodeData[], options?: AddChildrenOptions): WunderbaumNode;
438
471
  /**
439
- * Define shared attributes for multiple nodes of the same type.
440
- * This allows for more compact data models. Type definitions can be passed
441
- * as tree option, or be part of a `source` response.
472
+ * Append or prepend a node, or append a child node.
442
473
  *
443
- * Default: `{}`.
474
+ * This a convenience function that calls addChildren()
475
+ *
476
+ * @param nodeData node definition
477
+ * @param [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child')
478
+ * @returns new node
444
479
  */
445
- types?: NodeTypeDefinitionMap;
480
+ addNode(nodeData: WbNodeData, mode?: InsertNodeType): WunderbaumNode;
446
481
  /**
447
- * A list of maps that define column headers. If this option is set,
448
- * Wunderbaum becomes a treegrid control instead of a plain tree.
449
- * Column definitions can be passed as tree option, or be part of a `source`
450
- * response.
451
- * Default: `[]` meaning this is a plain tree.
482
+ * Apply a modification (or navigation) operation.
483
+ *
484
+ * @see {@link Wunderbaum.applyCommand}
452
485
  */
453
- columns?: ColumnDefinitionList;
486
+ applyCommand(cmd: ApplyCommandType, options: ApplyCommandOptions): any;
454
487
  /**
455
- * If true, add a `wb-skeleton` class to all nodes, that will result in a
456
- * 'glow' effect. Typically used with initial dummy nodes, while loading the
457
- * real data.
458
- * Default: false.
488
+ * Add/remove one or more classes to `<div class='wb-row'>`.
489
+ *
490
+ * This also maintains `node.classes`, so the class will survive a re-render.
491
+ *
492
+ * @param className one or more class names. Multiple classes can be passed
493
+ * as space-separated string, array of strings, or set of strings.
459
494
  */
460
- skeleton?: boolean;
495
+ setClass(className: string | string[] | Set<string>, flag?: boolean): void;
496
+ /** Call `setExpanded()` on all descendant nodes. */
497
+ expandAll(flag?: boolean, options?: ExpandAllOptions): Promise<void>;
461
498
  /**
462
- * Translation map for some system messages.
499
+ * Find all descendant nodes that match condition (excluding self).
500
+ *
501
+ * If `match` is a string, search for exact node title.
502
+ * If `match` is a RegExp expression, apply it to node.title, using
503
+ * [RegExp.test()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test).
504
+ * If `match` is a callback, match all nodes for that the callback(node) returns true.
505
+ *
506
+ * Returns an empty array if no nodes were found.
507
+ *
508
+ * Examples:
509
+ * ```js
510
+ * // Match all node titles that match exactly 'Joe':
511
+ * nodeList = node.findAll("Joe")
512
+ * // Match all node titles that start with 'Joe' case sensitive:
513
+ * nodeList = node.findAll(/^Joe/)
514
+ * // Match all node titles that contain 'oe', case insensitive:
515
+ * nodeList = node.findAll(/oe/i)
516
+ * // Match all nodes with `data.price` >= 99:
517
+ * nodeList = node.findAll((n) => {
518
+ * return n.data.price >= 99;
519
+ * })
520
+ * ```
463
521
  */
464
- strings?: any;
522
+ findAll(match: string | RegExp | MatcherCallback): WunderbaumNode[];
523
+ /** Return the direct child with a given key, index or null. */
524
+ findDirectChild(ptr: number | string | WunderbaumNode): WunderbaumNode | null;
465
525
  /**
466
- * 0:quiet, 1:errors, 2:warnings, 3:info, 4:verbose
467
- * Default: 3 (4 in local debug environment)
526
+ * Find first descendant node that matches condition (excluding self) or null.
527
+ *
528
+ * @see {@link WunderbaumNode.findAll} for examples.
468
529
  */
469
- debugLevel?: number;
470
- /**
471
- * Number of levels that are forced to be expanded, and have no expander icon.
472
- * E.g. 1 would keep all toplevel nodes expanded.
473
- * Default: 0
530
+ findFirst(match: string | RegExp | MatcherCallback): WunderbaumNode | null;
531
+ /** Find a node relative to self.
532
+ *
533
+ * @see {@link Wunderbaum.findRelatedNode|tree.findRelatedNode()}
474
534
  */
475
- minExpandLevel?: number;
535
+ findRelatedNode(where: string, includeHidden?: boolean): any;
476
536
  /**
477
- * If true, allow to expand parent nodes, even if `node.children` conatains
478
- * an empty array (`[]`). This is the the behavior of macOS Finder, for example.
479
- * Default: false
537
+ * Iterator version of {@link WunderbaumNode.format}.
480
538
  */
481
- emptyChildListExpandable?: boolean;
539
+ format_iter(name_cb?: NodeStringCallback, connectors?: string[]): IterableIterator<string>;
482
540
  /**
483
- * Height of a node row div.
484
- * Default: 22
541
+ * Return a multiline string representation of a node/subnode hierarchy.
542
+ * Mostly useful for debugging.
543
+ *
544
+ * Example:
545
+ * ```js
546
+ * console.info(tree.getActiveNode().format((n)=>n.title));
547
+ * ```
548
+ * logs
549
+ * ```
550
+ * Books
551
+ * ├─ Art of War
552
+ * ╰─ Don Quixote
553
+ * ```
554
+ * @see {@link WunderbaumNode.format_iter}
485
555
  */
486
- rowHeightPx?: number;
487
- /**
488
- * Collapse siblings when a node is expanded.
489
- * Default: false
556
+ format(name_cb?: NodeStringCallback, connectors?: string[]): string;
557
+ /** Return the `<span class='wb-col'>` element with a given index or id.
558
+ * @returns {WunderbaumNode | null}
490
559
  */
491
- autoCollapse?: boolean;
492
- /**
493
- * HTMLElement that receives the top nodes breadcrumb.
494
- * Default: undefined
560
+ getColElem(colIdx: number | string): HTMLSpanElement;
561
+ /** Return the first child node or null.
562
+ * @returns {WunderbaumNode | null}
495
563
  */
496
- connectTopBreadcrumb?: HTMLElement;
497
- /**
498
- * Default: NavModeEnum.startRow
564
+ getFirstChild(): WunderbaumNode;
565
+ /** Return the last child node or null.
566
+ * @returns {WunderbaumNode | null}
499
567
  */
500
- navigationModeOption?: NavModeEnum;
501
- /**
502
- * Show/hide header (default: null)
503
- * null: assume false for plain tree and true for grids.
504
- * string: use text as header (only for plain trees)
505
- * true: display a header (use tree's id as text for plain trees)
506
- * false: do not display a header
568
+ getLastChild(): WunderbaumNode;
569
+ /** Return node depth (starting with 1 for top level nodes). */
570
+ getLevel(): number;
571
+ /** Return the successive node (under the same parent) or null. */
572
+ getNextSibling(): WunderbaumNode | null;
573
+ /** Return the parent node (null for the system root node). */
574
+ getParent(): WunderbaumNode | null;
575
+ /** Return an array of all parent nodes (top-down).
576
+ * @param includeRoot Include the invisible system root node.
577
+ * @param includeSelf Include the node itself.
507
578
  */
508
- header?: boolean | string | null;
509
- /**
510
- *
579
+ getParentList(includeRoot?: boolean, includeSelf?: boolean): any[];
580
+ /** Return a string representing the hierachical node path, e.g. "a/b/c".
581
+ * @param includeSelf
582
+ * @param node property name or callback
583
+ * @param separator
511
584
  */
512
- showSpinner?: boolean;
513
- /**
514
- * If true, render a checkbox before the node tile to allow selection with the
515
- * mouse.
516
- * Default: false.
585
+ getPath(includeSelf?: boolean, part?: keyof WunderbaumNode | NodeAnyCallback, separator?: string): string;
586
+ /** Return the preceeding node (under the same parent) or null. */
587
+ getPrevSibling(): WunderbaumNode | null;
588
+ /** Return true if node has children.
589
+ * Return undefined if not sure, i.e. the node is lazy and not yet loaded.
517
590
  */
518
- checkbox?: boolean | "radio" | BoolOptionResolver;
519
- /**
520
- * Default: 200
591
+ hasChildren(): boolean;
592
+ /** Return true if node has className set. */
593
+ hasClass(className: string): boolean;
594
+ /** Return true if this node is the currently active tree node. */
595
+ isActive(): boolean;
596
+ /** Return true if this node is a direct or indirect parent of `other`.
597
+ * (See also [[isParentOf]].)
521
598
  */
522
- updateThrottleWait?: number;
523
- /**
524
- * Default: true
599
+ isAncestorOf(other: WunderbaumNode): boolean;
600
+ /** Return true if this node is a **direct** subnode of `other`.
601
+ * (See also [[isDescendantOf]].)
525
602
  */
526
- enabled?: boolean;
527
- /**
528
- * Default: false
603
+ isChildOf(other: WunderbaumNode): boolean;
604
+ /** Return true if this node's title spans all columns, i.e. the node has no
605
+ * grid cells.
529
606
  */
530
- fixedCol?: boolean;
531
- /**
532
- * Default: true
607
+ isColspan(): boolean;
608
+ /** Return true if this node is a direct or indirect subnode of `other`.
609
+ * (See also [[isChildOf]].)
533
610
  */
534
- quicksearch?: boolean;
535
- dnd?: DndOptionsType;
536
- edit?: any;
537
- filter?: any;
538
- grid?: any;
539
- /**
540
- *
541
- * @category Callback
611
+ isDescendantOf(other: WunderbaumNode): boolean;
612
+ /** Return true if this node has children, i.e. the node is generally expandable.
613
+ * If `andCollapsed` is set, we also check if this node is collapsed, i.e.
614
+ * an expand operation is currently possible.
542
615
  */
543
- activate?: (e: WbActivateEventType) => void;
544
- /**
545
- *
546
- * Return `false` to prevent default handling, e.g. activating the node.
547
- * @category Callback
616
+ isExpandable(andCollapsed?: boolean): boolean;
617
+ /** Return true if this node is currently in edit-title mode. */
618
+ isEditing(): boolean;
619
+ /** Return true if this node is currently expanded. */
620
+ isExpanded(): boolean;
621
+ /** Return true if this node is the first node of its parent's children. */
622
+ isFirstSibling(): boolean;
623
+ /** Return true if this node is the last node of its parent's children. */
624
+ isLastSibling(): boolean;
625
+ /** Return true if this node is lazy (even if data was already loaded) */
626
+ isLazy(): boolean;
627
+ /** Return true if node is lazy and loaded. For non-lazy nodes always return true. */
628
+ isLoaded(): boolean;
629
+ /** Return true if node is currently loading, i.e. a GET request is pending. */
630
+ isLoading(): boolean;
631
+ /** Return true if this node is a temporarily generated status node of type 'paging'. */
632
+ isPagingNode(): boolean;
633
+ /** Return true if this node is a **direct** parent of `other`.
634
+ * (See also [[isAncestorOf]].)
548
635
  */
549
- beforeActivate?: (e: WbActivateEventType) => void;
550
- /**
551
- *
552
- * @category Callback
636
+ isParentOf(other: WunderbaumNode): boolean;
637
+ /** (experimental) Return true if this node is partially loaded. */
638
+ isPartload(): boolean;
639
+ /** Return true if this node is partially selected (tri-state). */
640
+ isPartsel(): boolean;
641
+ /** Return true if this node has DOM representaion, i.e. is displayed in the viewport. */
642
+ isRendered(): boolean;
643
+ /** Return true if this node is the (invisible) system root node.
644
+ * (See also [[isTopLevel()]].)
553
645
  */
554
- change?: (e: WbChangeEventType) => void;
555
- /**
646
+ isRootNode(): boolean;
647
+ /** Return true if this node is selected, i.e. the checkbox is set. */
648
+ isSelected(): boolean;
649
+ /** Return true if this node is a temporarily generated system node like
650
+ * 'loading', 'paging', or 'error' (node.statusNodeType contains the type).
651
+ */
652
+ isStatusNode(): boolean;
653
+ /** Return true if this a top level node, i.e. a direct child of the (invisible) system root node. */
654
+ isTopLevel(): boolean;
655
+ /** Return true if node is marked lazy but not yet loaded.
656
+ * For non-lazy nodes always return false.
657
+ */
658
+ isUnloaded(): boolean;
659
+ /** Return true if all parent nodes are expanded. Note: this does not check
660
+ * whether the node is scrolled into the visible part of the screen or viewport.
661
+ */
662
+ isVisible(): boolean;
663
+ protected _loadSourceObject(source: any, level?: number): void;
664
+ _fetchWithOptions(source: any): Promise<any>;
665
+ /** Download data from the cloud, then call `.update()`. */
666
+ load(source: any): Promise<void>;
667
+ /**Load content of a lazy node. */
668
+ loadLazy(forceReload?: boolean): Promise<void>;
669
+ /** Alias for `logDebug` */
670
+ log(...args: any[]): void;
671
+ logDebug(...args: any[]): void;
672
+ logError(...args: any[]): void;
673
+ logInfo(...args: any[]): void;
674
+ logWarn(...args: any[]): void;
675
+ /** Expand all parents and optionally scroll into visible area as neccessary.
676
+ * Promise is resolved, when lazy loading and animations are done.
677
+ * @param {object} [options] passed to `setExpanded()`.
678
+ * Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
679
+ */
680
+ makeVisible(options?: MakeVisibleOptions): Promise<any>;
681
+ /** Move this node to targetNode. */
682
+ moveTo(targetNode: WunderbaumNode, mode?: InsertNodeType, map?: NodeAnyCallback): void;
683
+ /** Set focus relative to this node and optionally activate.
556
684
  *
557
- * Return `false` to prevent default handling, e.g. activating the node.
558
- * @category Callback
685
+ * 'left' collapses the node if it is expanded, or move to the parent
686
+ * otherwise.
687
+ * 'right' expands the node if it is collapsed, or move to the first
688
+ * child otherwise.
689
+ *
690
+ * @param where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'.
691
+ * (Alternatively the `event.key` that would normally trigger this move,
692
+ * e.g. `ArrowLeft` = 'left'.
693
+ * @param options
559
694
  */
560
- click?: (e: WbClickEventType) => void;
695
+ navigate(where: string, options?: NavigateOptions): Promise<any>;
696
+ /** Delete this node and all descendants. */
697
+ remove(): void;
698
+ /** Remove all descendants of this node. */
699
+ removeChildren(): void;
700
+ /** Remove all HTML markup from the DOM. */
701
+ removeMarkup(): void;
702
+ protected _getRenderInfo(): any;
703
+ protected _createIcon(parentElem: HTMLElement, replaceChild: HTMLElement | null, showLoading: boolean): HTMLElement | null;
561
704
  /**
562
- *
563
- * @category Callback
705
+ * Create a whole new `<div class="wb-row">` element.
706
+ * @see {@link WunderbaumNode.render}
564
707
  */
565
- dblclick?: (e: WbClickEventType) => void;
708
+ protected _render_markup(opts: RenderOptions): void;
566
709
  /**
710
+ * Render `node.title`, `.icon` into an existing row.
567
711
  *
568
- * Return `false` to prevent default handling, e.g. deactivating the node
569
- * and activating the next.
570
- * @category Callback
712
+ * @see {@link WunderbaumNode.render}
571
713
  */
572
- deactivate?: (e: WbDeactivateEventType) => void;
714
+ protected _render_data(opts: RenderOptions): void;
573
715
  /**
574
- *
575
- * @category Callback
716
+ * Update row classes to reflect active, focuses, etc.
717
+ * @see {@link WunderbaumNode.render}
576
718
  */
577
- discard?: (e: WbNodeEventType) => void;
719
+ protected _render_status(opts: RenderOptions): void;
578
720
  /**
721
+ * Create or update node's markup.
579
722
  *
580
- * @category Callback
723
+ * `options.change` defaults to ChangeType.data, which updates the title,
724
+ * icon, and status. It also triggers the `render` event, that lets the user
725
+ * create or update the content of embeded cell elements.
726
+ *
727
+ * If only the status or other class-only modifications have changed,
728
+ * `options.change` should be set to ChangeType.status instead for best
729
+ * efficiency.
730
+ *
731
+ * Calling `setModified` instead may be a better alternative.
732
+ * @see {@link WunderbaumNode.setModified}
581
733
  */
582
- enhanceTitle?: (e: WbEnhanceTitleEventType) => void;
734
+ render(options?: RenderOptions): void;
583
735
  /**
736
+ * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad
737
+ * event is triggered on next expand.
738
+ */
739
+ resetLazy(): void;
740
+ /** Convert node (or whole branch) into a plain object.
584
741
  *
585
- * @category Callback
742
+ * The result is compatible with node.addChildren().
743
+ *
744
+ * @param include child nodes
745
+ * @param callback(dict, node) is called for every node, in order to allow
746
+ * modifications.
747
+ * Return `false` to ignore this node or `"skip"` to include this node
748
+ * without its children.
749
+ * @see {@link Wunderbaum.toDictArray}.
586
750
  */
587
- error?: (e: WbErrorEventType) => void;
588
- /**
751
+ toDict(recursive?: boolean, callback?: NodeToDictCallback): WbNodeData;
752
+ /** Return an option value that has a default, but may be overridden by a
753
+ * callback or a node instance attribute.
589
754
  *
590
- * Check `e.flag` for status.
591
- * @category Callback
755
+ * Evaluation sequence:
756
+ *
757
+ * - If `tree.options.<name>` is a callback that returns something, use that.
758
+ * - Else if `node.<name>` is defined, use that.
759
+ * - Else if `tree.types[<node.type>]` is a value, use that.
760
+ * - Else if `tree.options.<name>` is a value, use that.
761
+ * - Else use `defaultValue`.
762
+ *
763
+ * @param name name of the option property (on node and tree)
764
+ * @param defaultValue return this if nothing else matched
765
+ * {@link Wunderbaum.getOption|Wunderbaum.getOption()}
592
766
  */
593
- focus?: (e: WbTreeEventType) => void;
594
- /**
595
- * Fires when the tree markup was created and the initial source data was loaded.
596
- * Typical use cases would be activating a node, setting focus, enabling other
597
- * controls on the page, etc.<br>
598
- * Check `e.error` for status.
599
- * @category Callback
767
+ getOption(name: string, defaultValue?: any): any;
768
+ /** Make sure that this node is visible in the viewport.
769
+ * @see {@link Wunderbaum.scrollTo|Wunderbaum.scrollTo()}
600
770
  */
601
- init?: (e: WbInitEventType) => void;
771
+ scrollIntoView(options?: ScrollIntoViewOptions): Promise<void>;
602
772
  /**
603
- *
604
- * @category Callback
773
+ * Activate this node, deactivate previous, send events, activate column and scroll int viewport.
605
774
  */
606
- keydown?: (e: WbKeydownEventType) => void;
775
+ setActive(flag?: boolean, options?: SetActiveOptions): Promise<any>;
607
776
  /**
608
- * Fires when a node that was marked 'lazy', is expanded for the first time.
609
- * Typically we return an endpoint URL or the Promise of a fetch request that
610
- * provides a (potentially nested) list of child nodes.
611
- * @category Callback
777
+ * Expand or collapse this node.
612
778
  */
613
- lazyLoad?: (e: WbNodeEventType) => void;
779
+ setExpanded(flag?: boolean, options?: SetExpandedOptions): Promise<void>;
614
780
  /**
615
- * Fires when data was loaded (initial request, reload, or lazy loading),
616
- * after the data is applied and rendered.
617
- * @category Callback
781
+ * Set keyboard focus here.
782
+ * @see {@link setActive}
618
783
  */
619
- load?: (e: WbNodeEventType) => void;
784
+ setFocus(flag?: boolean): void;
785
+ /** Set a new icon path or class. */
786
+ setIcon(icon: string): void;
787
+ /** Change node's {@link key} and/or {@link refKey}. */
788
+ setKey(key: string | null, refKey: string | null): void;
620
789
  /**
621
- * @category Callback
790
+ * Trigger a repaint, typically after a status or data change.
791
+ *
792
+ * `change` defaults to 'data', which handles modifcations of title, icon,
793
+ * and column content. It can be reduced to 'ChangeType.status' if only
794
+ * active/focus/selected state has changed.
795
+ *
796
+ * This method will eventually call {@link WunderbaumNode.render()} with
797
+ * default options, but may be more consistent with the tree's
798
+ * {@link Wunderbaum.setModified()} API.
622
799
  */
623
- modifyChild?: (e: WbNodeEventType) => void;
800
+ setModified(change?: ChangeType): void;
801
+ /** Modify the check/uncheck state. */
802
+ setSelected(flag?: boolean, options?: SetSelectedOptions): void;
803
+ /** Display node status (ok, loading, error, noData) using styles and a dummy child node. */
804
+ setStatus(status: NodeStatusType, options?: SetStatusOptions): WunderbaumNode | null;
805
+ /** Rename this node. */
806
+ setTitle(title: string): void;
807
+ _sortChildren(cmp: SortCallback, deep: boolean): void;
624
808
  /**
625
- * Fires when data was fetched (initial request, reload, or lazy loading),
626
- * but before the data is applied and rendered.
627
- * Here we can modify and adjust the received data, for example to convert an
628
- * external response to native Wunderbaum syntax.
629
- * @category Callback
809
+ * Sort child list by title or custom criteria.
810
+ * @param {function} cmp custom compare function(a, b) that returns -1, 0, or 1
811
+ * (defaults to sorting by title).
812
+ * @param {boolean} deep pass true to sort all descendant nodes recursively
630
813
  */
631
- receive?: (e: WbReceiveEventType) => void;
814
+ sortChildren(cmp?: SortCallback | null, deep?: boolean): void;
632
815
  /**
633
- * Fires when a node is about to be displayed.
634
- * The default HTML markup is already created, but not yet added to the DOM.
635
- * Now we can tweak the markup, create HTML elements in this node's column
636
- * cells, etc.
637
- * See also `Custom Rendering` for details.
638
- * @category Callback
816
+ * Trigger `modifyChild` event on a parent to signal that a child was modified.
817
+ * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
639
818
  */
640
- render?: (e: WbRenderEventType) => void;
819
+ triggerModifyChild(operation: string, child: WunderbaumNode | null, extra?: any): void;
641
820
  /**
821
+ * Trigger `modifyChild` event on node.parent(!).
822
+ * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
823
+ * @param {object} [extra]
824
+ */
825
+ triggerModify(operation: string, extra?: any): void;
826
+ /**
827
+ * Call `callback(node)` for all child nodes in hierarchical order (depth-first, pre-order).
642
828
  *
643
- * @category Callback
829
+ * Stop iteration, if fn() returns false. Skip current branch, if fn()
830
+ * returns "skip".<br>
831
+ * Return false if iteration was stopped.
832
+ *
833
+ * @param {function} callback the callback function.
834
+ * Return false to stop iteration, return "skip" to skip this node and
835
+ * its children only.
836
+ * @see {@link IterableIterator<WunderbaumNode>}, {@link Wunderbaum.visit}.
644
837
  */
645
- renderStatusNode?: (e: WbRenderEventType) => void;
838
+ visit(callback: NodeVisitCallback, includeSelf?: boolean): NodeVisitResponse;
839
+ /** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br>
840
+ * Stop iteration, if callback() returns false.<br>
841
+ * Return false if iteration was stopped.
842
+ *
843
+ * @param callback the callback function. Return false to stop iteration
844
+ */
845
+ visitParents(callback: (node: WunderbaumNode) => boolean | void, includeSelf?: boolean): boolean;
646
846
  /**
847
+ * Call fn(node) for all sibling nodes.<br>
848
+ * Stop iteration, if fn() returns false.<br>
849
+ * Return false if iteration was stopped.
647
850
  *
648
- * Check `e.flag` for status.
649
- * @category Callback
851
+ * @param {function} fn the callback function.
852
+ * Return false to stop iteration.
650
853
  */
651
- select?: (e: WbNodeEventType) => void;
854
+ visitSiblings(callback: (node: WunderbaumNode) => boolean | void, includeSelf?: boolean): boolean;
652
855
  /**
653
- * Fires when the viewport content was updated, after scroling, expanding etc.
654
- * @category Callback
856
+ * [ext-filter] Return true if this node is matched by current filter (or no filter is active).
655
857
  */
656
- update?: (e: WbTreeEventType) => void;
858
+ isMatched(): boolean;
657
859
  }
658
860
  }
659
- declare module "wb_node" {
861
+ declare module "wb_options" {
660
862
  /*!
661
- * Wunderbaum - wunderbaum_node
863
+ * Wunderbaum - utils
662
864
  * Copyright (c) 2021-2023, Martin Wendt. Released under the MIT license.
663
865
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
664
866
  */
665
- import "./wunderbaum.scss";
666
- import { Wunderbaum } from "wunderbaum";
667
- import { AddChildrenOptions, InsertNodeType, ApplyCommandOptions, ApplyCommandType, ChangeType, ExpandAllOptions, MakeVisibleOptions, MatcherCallback, NavigateOptions, NodeAnyCallback, NodeStatusType, NodeStringCallback, NodeVisitCallback, NodeVisitResponse, RenderOptions, ScrollIntoViewOptions, SetActiveOptions, SetExpandedOptions, SetSelectedOptions, SetStatusOptions, SortCallback } from "types";
668
- import { WbNodeData } from "wb_options";
867
+ import { BoolOptionResolver, ColumnDefinitionList, DndOptionsType, NavModeEnum, NodeTypeDefinitionMap, WbActivateEventType, WbChangeEventType, WbClickEventType, WbDeactivateEventType, WbEnhanceTitleEventType, WbErrorEventType, WbInitEventType, WbKeydownEventType, WbNodeData, WbNodeEventType, WbReceiveEventType, WbRenderEventType, WbTreeEventType } from "types";
669
868
  /**
670
- * A single tree node.
869
+ * Available options for [[Wunderbaum]].
671
870
  *
672
- * **NOTE:** <br>
673
- * Generally you should not modify properties directly, since this may break
674
- * the internal bookkeeping.
871
+ * Options are passed to the constructor as plain object:
872
+ *
873
+ * ```js
874
+ * const tree = new mar10.Wunderbaum({
875
+ * id: "demo",
876
+ * element: document.getElementById("demo-tree"),
877
+ * source: "url/of/data/request",
878
+ * ...
879
+ * });
880
+ * ```
881
+ *
882
+ * Event handlers are also passed as callbacks
883
+ *
884
+ * ```js
885
+ * const tree = new mar10.Wunderbaum({
886
+ * ...
887
+ * init: (e) => {
888
+ * console.log(`Tree ${e.tree} was initialized and loaded.`)
889
+ * },
890
+ * activate: (e) => {
891
+ * console.log(`Node ${e.node} was activated.`)
892
+ * },
893
+ * ...
894
+ * });
895
+ * ```
675
896
  */
676
- export class WunderbaumNode {
677
- static sequence: number;
678
- /** Reference to owning tree. */
679
- tree: Wunderbaum;
680
- /** Parent node (null for the invisible root node `tree.root`). */
681
- parent: WunderbaumNode;
682
- /** Name of the node.
683
- * @see Use {@link setTitle} to modify. */
684
- title: string;
685
- /** Unique key. Passed with constructor or defaults to `SEQUENCE`.
686
- * @see Use {@link setKey} to modify. */
687
- readonly key: string;
688
- /** Reference key. Unlike {@link key}, a `refKey` may occur multiple
689
- * times within a tree (in this case we have 'clone nodes').
690
- * @see Use {@link setKey} to modify.
691
- */
692
- readonly refKey: string | undefined;
693
- children: WunderbaumNode[] | null;
694
- checkbox?: boolean;
695
- /** If true, (in grid mode) no cells are rendered, except for the node title.*/
696
- colspan?: boolean;
697
- icon?: boolean | string;
698
- lazy: boolean;
699
- /** Expansion state.
700
- * @see {@link isExpandable}, {@link isExpanded}, {@link setExpanded}. */
701
- expanded: boolean;
702
- /** Selection state.
703
- * @see {@link isSelected}, {@link setSelected}. */
704
- selected: boolean;
705
- type?: string;
706
- tooltip?: string;
707
- /** Additional classes added to `div.wb-row`.
708
- * @see {@link hasClass}, {@link setClass}. */
709
- classes: Set<string> | null;
710
- /** Custom data that was passed to the constructor */
711
- data: any;
712
- statusNodeType?: string;
713
- _isLoading: boolean;
714
- _requestId: number;
715
- _errorInfo: any | null;
716
- _partsel: boolean;
717
- _partload: boolean;
718
- match?: boolean;
719
- subMatchCount?: number;
720
- subMatchBadge?: HTMLElement;
721
- /** @internal */
722
- titleWithHighlight?: string;
723
- _filterAutoExpanded?: boolean;
724
- _rowIdx: number | undefined;
725
- _rowElem: HTMLDivElement | undefined;
726
- constructor(tree: Wunderbaum, parent: WunderbaumNode, data: any);
897
+ export interface WunderbaumOptions {
727
898
  /**
728
- * Return readable string representation for this instance.
729
- * @internal
899
+ * The target `div` element (or selector) that shall become a Wunderbaum.
730
900
  */
731
- toString(): string;
901
+ element: string | HTMLDivElement;
732
902
  /**
733
- * Iterate all descendant nodes depth-first, pre-order using `for ... of ...` syntax.
734
- * More concise, but slightly slower than {@link WunderbaumNode.visit}.
903
+ * The identifier of this tree. Used to reference the instance, especially
904
+ * when multiple trees are present (e.g. `tree = mar10.Wunderbaum.getTree("demo")`).
735
905
  *
736
- * Example:
737
- * ```js
738
- * for(const n of node) {
739
- * ...
740
- * }
741
- * ```
742
- */
743
- [Symbol.iterator](): IterableIterator<WunderbaumNode>;
744
- /** Call event handler if defined in tree.options.
745
- * Example:
746
- * ```js
747
- * node._callEvent("edit.beforeEdit", {foo: 42})
748
- * ```
906
+ * Default: `"wb_" + COUNTER`.
749
907
  */
750
- _callEvent(type: string, extra?: any): any;
908
+ id?: string;
751
909
  /**
752
- * Append (or insert) a list of child nodes.
753
- *
754
- * Tip: pass `{ before: 0 }` to prepend new nodes as first children.
910
+ * Define the initial tree data. Typically a URL of an endpoint that serves
911
+ * a JSON formatted structure, but also a callback, Promise, or static data
912
+ * is allowed.
755
913
  *
756
- * @returns first child added
914
+ * Default: `{}`.
757
915
  */
758
- addChildren(nodeData: WbNodeData | WbNodeData[], options?: AddChildrenOptions): WunderbaumNode;
916
+ source?: string | Array<WbNodeData>;
759
917
  /**
760
- * Append or prepend a node, or append a child node.
761
- *
762
- * This a convenience function that calls addChildren()
918
+ * Define shared attributes for multiple nodes of the same type.
919
+ * This allows for more compact data models. Type definitions can be passed
920
+ * as tree option, or be part of a `source` response.
763
921
  *
764
- * @param {NodeData} node node definition
765
- * @param [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child')
766
- * @returns new node
922
+ * Default: `{}`.
767
923
  */
768
- addNode(nodeData: WbNodeData, mode?: InsertNodeType): WunderbaumNode;
924
+ types?: NodeTypeDefinitionMap;
769
925
  /**
770
- * Apply a modification (or navigation) operation.
771
- *
772
- * @see {@link Wunderbaum.applyCommand}
926
+ * A list of maps that define column headers. If this option is set,
927
+ * Wunderbaum becomes a treegrid control instead of a plain tree.
928
+ * Column definitions can be passed as tree option, or be part of a `source`
929
+ * response.
930
+ * Default: `[]` meaning this is a plain tree.
773
931
  */
774
- applyCommand(cmd: ApplyCommandType, options: ApplyCommandOptions): any;
932
+ columns?: ColumnDefinitionList;
775
933
  /**
776
- * Add/remove one or more classes to `<div class='wb-row'>`.
777
- *
778
- * This also maintains `node.classes`, so the class will survive a re-render.
779
- *
780
- * @param className one or more class names. Multiple classes can be passed
781
- * as space-separated string, array of strings, or set of strings.
934
+ * If true, add a `wb-skeleton` class to all nodes, that will result in a
935
+ * 'glow' effect. Typically used with initial dummy nodes, while loading the
936
+ * real data.
937
+ * Default: false.
782
938
  */
783
- setClass(className: string | string[] | Set<string>, flag?: boolean): void;
784
- /** Call `setExpanded()` on all descendant nodes. */
785
- expandAll(flag?: boolean, options?: ExpandAllOptions): Promise<void>;
939
+ skeleton?: boolean;
786
940
  /**
787
- * Find all descendant nodes that match condition (excluding self).
788
- *
789
- * If `match` is a string, search for exact node title.
790
- * If `match` is a RegExp expression, apply it to node.title, using
791
- * [RegExp.test()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test).
792
- * If `match` is a callback, match all nodes for that the callback(node) returns true.
793
- *
794
- * Returns an empty array if no nodes were found.
795
- *
796
- * Examples:
797
- * ```js
798
- * // Match all node titles that match exactly 'Joe':
799
- * nodeList = node.findAll("Joe")
800
- * // Match all node titles that start with 'Joe' case sensitive:
801
- * nodeList = node.findAll(/^Joe/)
802
- * // Match all node titles that contain 'oe', case insensitive:
803
- * nodeList = node.findAll(/oe/i)
804
- * // Match all nodes with `data.price` >= 99:
805
- * nodeList = node.findAll((n) => {
806
- * return n.data.price >= 99;
807
- * })
808
- * ```
941
+ * Translation map for some system messages.
809
942
  */
810
- findAll(match: string | RegExp | MatcherCallback): WunderbaumNode[];
811
- /** Return the direct child with a given key, index or null. */
812
- findDirectChild(ptr: number | string | WunderbaumNode): WunderbaumNode | null;
943
+ strings?: any;
813
944
  /**
814
- * Find first descendant node that matches condition (excluding self) or null.
815
- *
816
- * @see {@link WunderbaumNode.findAll} for examples.
817
- */
818
- findFirst(match: string | RegExp | MatcherCallback): WunderbaumNode | null;
819
- /** Find a node relative to self.
820
- *
821
- * @see {@link Wunderbaum.findRelatedNode|tree.findRelatedNode()}
945
+ * 0:quiet, 1:errors, 2:warnings, 3:info, 4:verbose
946
+ * Default: 3 (4 in local debug environment)
822
947
  */
823
- findRelatedNode(where: string, includeHidden?: boolean): any;
948
+ debugLevel?: number;
824
949
  /**
825
- * Iterator version of {@link WunderbaumNode.format}.
950
+ * Number of levels that are forced to be expanded, and have no expander icon.
951
+ * E.g. 1 would keep all toplevel nodes expanded.
952
+ * Default: 0
826
953
  */
827
- format_iter(name_cb?: NodeStringCallback, connectors?: string[]): IterableIterator<string>;
954
+ minExpandLevel?: number;
828
955
  /**
829
- * Return a multiline string representation of a node/subnode hierarchy.
830
- * Mostly useful for debugging.
831
- *
832
- * Example:
833
- * ```js
834
- * console.info(tree.getActiveNode().format((n)=>n.title));
835
- * ```
836
- * logs
837
- * ```
838
- * Books
839
- * ├─ Art of War
840
- * ╰─ Don Quixote
841
- * ```
842
- * @see {@link WunderbaumNode.format_iter}
843
- */
844
- format(name_cb?: NodeStringCallback, connectors?: string[]): string;
845
- /** Return the `<span class='wb-col'>` element with a given index or id.
846
- * @returns {WunderbaumNode | null}
847
- */
848
- getColElem(colIdx: number | string): HTMLSpanElement;
849
- /** Return the first child node or null.
850
- * @returns {WunderbaumNode | null}
851
- */
852
- getFirstChild(): WunderbaumNode;
853
- /** Return the last child node or null.
854
- * @returns {WunderbaumNode | null}
855
- */
856
- getLastChild(): WunderbaumNode;
857
- /** Return node depth (starting with 1 for top level nodes). */
858
- getLevel(): number;
859
- /** Return the successive node (under the same parent) or null. */
860
- getNextSibling(): WunderbaumNode | null;
861
- /** Return the parent node (null for the system root node). */
862
- getParent(): WunderbaumNode | null;
863
- /** Return an array of all parent nodes (top-down).
864
- * @param includeRoot Include the invisible system root node.
865
- * @param includeSelf Include the node itself.
866
- */
867
- getParentList(includeRoot?: boolean, includeSelf?: boolean): any[];
868
- /** Return a string representing the hierachical node path, e.g. "a/b/c".
869
- * @param includeSelf
870
- * @param node property name or callback
871
- * @param separator
872
- */
873
- getPath(includeSelf?: boolean, part?: keyof WunderbaumNode | NodeAnyCallback, separator?: string): string;
874
- /** Return the preceeding node (under the same parent) or null. */
875
- getPrevSibling(): WunderbaumNode | null;
876
- /** Return true if node has children.
877
- * Return undefined if not sure, i.e. the node is lazy and not yet loaded.
878
- */
879
- hasChildren(): boolean;
880
- /** Return true if node has className set. */
881
- hasClass(className: string): boolean;
882
- /** Return true if this node is the currently active tree node. */
883
- isActive(): boolean;
884
- /** Return true if this node is a direct or indirect parent of `other`.
885
- * (See also [[isParentOf]].)
886
- */
887
- isAncestorOf(other: WunderbaumNode): boolean;
888
- /** Return true if this node is a **direct** subnode of `other`.
889
- * (See also [[isDescendantOf]].)
890
- */
891
- isChildOf(other: WunderbaumNode): boolean;
892
- /** Return true if this node's title spans all columns, i.e. the node has no
893
- * grid cells.
894
- */
895
- isColspan(): boolean;
896
- /** Return true if this node is a direct or indirect subnode of `other`.
897
- * (See also [[isChildOf]].)
898
- */
899
- isDescendantOf(other: WunderbaumNode): boolean;
900
- /** Return true if this node has children, i.e. the node is generally expandable.
901
- * If `andCollapsed` is set, we also check if this node is collapsed, i.e.
902
- * an expand operation is currently possible.
903
- */
904
- isExpandable(andCollapsed?: boolean): boolean;
905
- /** Return true if this node is currently in edit-title mode. */
906
- isEditing(): boolean;
907
- /** Return true if this node is currently expanded. */
908
- isExpanded(): boolean;
909
- /** Return true if this node is the first node of its parent's children. */
910
- isFirstSibling(): boolean;
911
- /** Return true if this node is the last node of its parent's children. */
912
- isLastSibling(): boolean;
913
- /** Return true if this node is lazy (even if data was already loaded) */
914
- isLazy(): boolean;
915
- /** Return true if node is lazy and loaded. For non-lazy nodes always return true. */
916
- isLoaded(): boolean;
917
- /** Return true if node is currently loading, i.e. a GET request is pending. */
918
- isLoading(): boolean;
919
- /** Return true if this node is a temporarily generated status node of type 'paging'. */
920
- isPagingNode(): boolean;
921
- /** Return true if this node is a **direct** parent of `other`.
922
- * (See also [[isAncestorOf]].)
956
+ * If true, allow to expand parent nodes, even if `node.children` conatains
957
+ * an empty array (`[]`). This is the the behavior of macOS Finder, for example.
958
+ * Default: false
923
959
  */
924
- isParentOf(other: WunderbaumNode): boolean;
925
- /** (experimental) Return true if this node is partially loaded. */
926
- isPartload(): boolean;
927
- /** Return true if this node is partially selected (tri-state). */
928
- isPartsel(): boolean;
929
- /** Return true if this node has DOM representaion, i.e. is displayed in the viewport. */
930
- isRendered(): boolean;
931
- /** Return true if this node is the (invisible) system root node.
932
- * (See also [[isTopLevel()]].)
960
+ emptyChildListExpandable?: boolean;
961
+ /**
962
+ * Height of a node row div.
963
+ * Default: 22
933
964
  */
934
- isRootNode(): boolean;
935
- /** Return true if this node is selected, i.e. the checkbox is set. */
936
- isSelected(): boolean;
937
- /** Return true if this node is a temporarily generated system node like
938
- * 'loading', 'paging', or 'error' (node.statusNodeType contains the type).
965
+ rowHeightPx?: number;
966
+ /**
967
+ * Collapse siblings when a node is expanded.
968
+ * Default: false
939
969
  */
940
- isStatusNode(): boolean;
941
- /** Return true if this a top level node, i.e. a direct child of the (invisible) system root node. */
942
- isTopLevel(): boolean;
943
- /** Return true if node is marked lazy but not yet loaded.
944
- * For non-lazy nodes always return false.
970
+ autoCollapse?: boolean;
971
+ /**
972
+ * HTMLElement that receives the top nodes breadcrumb.
973
+ * Default: undefined
945
974
  */
946
- isUnloaded(): boolean;
947
- /** Return true if all parent nodes are expanded. Note: this does not check
948
- * whether the node is scrolled into the visible part of the screen or viewport.
975
+ connectTopBreadcrumb?: HTMLElement;
976
+ /**
977
+ * Default: NavModeEnum.startRow
949
978
  */
950
- isVisible(): boolean;
951
- protected _loadSourceObject(source: any, level?: number): void;
952
- _fetchWithOptions(source: any): Promise<any>;
953
- /** Download data from the cloud, then call `.update()`. */
954
- load(source: any): Promise<void>;
955
- /**Load content of a lazy node. */
956
- loadLazy(forceReload?: boolean): Promise<void>;
957
- /** Alias for `logDebug` */
958
- log(...args: any[]): void;
959
- logDebug(...args: any[]): void;
960
- logError(...args: any[]): void;
961
- logInfo(...args: any[]): void;
962
- logWarn(...args: any[]): void;
963
- /** Expand all parents and optionally scroll into visible area as neccessary.
964
- * Promise is resolved, when lazy loading and animations are done.
965
- * @param {object} [options] passed to `setExpanded()`.
966
- * Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
979
+ navigationModeOption?: NavModeEnum;
980
+ /**
981
+ * Show/hide header (default: null)
982
+ * null: assume false for plain tree and true for grids.
983
+ * string: use text as header (only for plain trees)
984
+ * true: display a header (use tree's id as text for plain trees)
985
+ * false: do not display a header
967
986
  */
968
- makeVisible(options?: MakeVisibleOptions): Promise<any>;
969
- /** Move this node to targetNode. */
970
- moveTo(targetNode: WunderbaumNode, mode?: InsertNodeType, map?: NodeAnyCallback): void;
971
- /** Set focus relative to this node and optionally activate.
972
- *
973
- * 'left' collapses the node if it is expanded, or move to the parent
974
- * otherwise.
975
- * 'right' expands the node if it is collapsed, or move to the first
976
- * child otherwise.
987
+ header?: boolean | string | null;
988
+ /**
977
989
  *
978
- * @param where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'.
979
- * (Alternatively the `event.key` that would normally trigger this move,
980
- * e.g. `ArrowLeft` = 'left'.
981
- * @param options
982
990
  */
983
- navigate(where: string, options?: NavigateOptions): Promise<any>;
984
- /** Delete this node and all descendants. */
985
- remove(): void;
986
- /** Remove all descendants of this node. */
987
- removeChildren(): void;
988
- /** Remove all HTML markup from the DOM. */
989
- removeMarkup(): void;
990
- protected _getRenderInfo(): any;
991
- protected _createIcon(parentElem: HTMLElement, replaceChild: HTMLElement | null, showLoading: boolean): HTMLElement | null;
991
+ showSpinner?: boolean;
992
992
  /**
993
- * Create a whole new `<div class="wb-row">` element.
994
- * @see {@link WunderbaumNode.render}
993
+ * If true, render a checkbox before the node tile to allow selection with the
994
+ * mouse.
995
+ * Default: false.
995
996
  */
996
- protected _render_markup(opts: RenderOptions): void;
997
+ checkbox?: boolean | "radio" | BoolOptionResolver;
997
998
  /**
998
- * Render `node.title`, `.icon` into an existing row.
999
- *
1000
- * @see {@link WunderbaumNode.render}
999
+ * Default: 200
1001
1000
  */
1002
- protected _render_data(opts: RenderOptions): void;
1001
+ updateThrottleWait?: number;
1003
1002
  /**
1004
- * Update row classes to reflect active, focuses, etc.
1005
- * @see {@link WunderbaumNode.render}
1003
+ * Default: true
1006
1004
  */
1007
- protected _render_status(opts: RenderOptions): void;
1005
+ enabled?: boolean;
1008
1006
  /**
1009
- * Create or update node's markup.
1010
- *
1011
- * `options.change` defaults to ChangeType.data, which updates the title,
1012
- * icon, and status. It also triggers the `render` event, that lets the user
1013
- * create or update the content of embeded cell elements.
1014
- *
1015
- * If only the status or other class-only modifications have changed,
1016
- * `options.change` should be set to ChangeType.status instead for best
1017
- * efficiency.
1018
- *
1019
- * Calling `setModified` instead may be a better alternative.
1020
- * @see {@link WunderbaumNode.setModified}
1007
+ * Default: false
1021
1008
  */
1022
- render(options?: RenderOptions): void;
1009
+ fixedCol?: boolean;
1023
1010
  /**
1024
- * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad
1025
- * event is triggered on next expand.
1011
+ * Default: true
1026
1012
  */
1027
- resetLazy(): void;
1028
- /** Convert node (or whole branch) into a plain object.
1013
+ quicksearch?: boolean;
1014
+ dnd?: DndOptionsType;
1015
+ edit?: any;
1016
+ filter?: any;
1017
+ grid?: any;
1018
+ /**
1029
1019
  *
1030
- * The result is compatible with node.addChildren().
1020
+ * @category Callback
1021
+ */
1022
+ activate?: (e: WbActivateEventType) => void;
1023
+ /**
1031
1024
  *
1032
- * @param include child nodes
1033
- * @param callback(dict, node) is called for every node, in order to allow
1034
- * modifications.
1035
- * Return `false` to ignore this node or `"skip"` to include this node
1036
- * without its children.
1037
- * @returns {NodeData}
1025
+ * Return `false` to prevent default handling, e.g. activating the node.
1026
+ * @category Callback
1038
1027
  */
1039
- toDict(recursive?: boolean, callback?: any): any;
1040
- /** Return an option value that has a default, but may be overridden by a
1041
- * callback or a node instance attribute.
1028
+ beforeActivate?: (e: WbActivateEventType) => void;
1029
+ /**
1042
1030
  *
1043
- * Evaluation sequence:
1031
+ * @category Callback
1032
+ */
1033
+ change?: (e: WbChangeEventType) => void;
1034
+ /**
1044
1035
  *
1045
- * - If `tree.options.<name>` is a callback that returns something, use that.
1046
- * - Else if `node.<name>` is defined, use that.
1047
- * - Else if `tree.types[<node.type>]` is a value, use that.
1048
- * - Else if `tree.options.<name>` is a value, use that.
1049
- * - Else use `defaultValue`.
1036
+ * Return `false` to prevent default handling, e.g. activating the node.
1037
+ * @category Callback
1038
+ */
1039
+ click?: (e: WbClickEventType) => void;
1040
+ /**
1050
1041
  *
1051
- * @param name name of the option property (on node and tree)
1052
- * @param defaultValue return this if nothing else matched
1053
- * {@link Wunderbaum.getOption|Wunderbaum.getOption()}
1042
+ * @category Callback
1054
1043
  */
1055
- getOption(name: string, defaultValue?: any): any;
1056
- /** Make sure that this node is visible in the viewport.
1057
- * @see {@link Wunderbaum.scrollTo|Wunderbaum.scrollTo()}
1044
+ dblclick?: (e: WbClickEventType) => void;
1045
+ /**
1046
+ *
1047
+ * Return `false` to prevent default handling, e.g. deactivating the node
1048
+ * and activating the next.
1049
+ * @category Callback
1058
1050
  */
1059
- scrollIntoView(options?: ScrollIntoViewOptions): Promise<void>;
1051
+ deactivate?: (e: WbDeactivateEventType) => void;
1060
1052
  /**
1061
- * Activate this node, deactivate previous, send events, activate column and scroll int viewport.
1053
+ *
1054
+ * @category Callback
1062
1055
  */
1063
- setActive(flag?: boolean, options?: SetActiveOptions): Promise<any>;
1056
+ discard?: (e: WbNodeEventType) => void;
1064
1057
  /**
1065
- * Expand or collapse this node.
1058
+ *
1059
+ * @category Callback
1066
1060
  */
1067
- setExpanded(flag?: boolean, options?: SetExpandedOptions): Promise<void>;
1061
+ enhanceTitle?: (e: WbEnhanceTitleEventType) => void;
1068
1062
  /**
1069
- * Set keyboard focus here.
1070
- * @see {@link setActive}
1063
+ *
1064
+ * @category Callback
1071
1065
  */
1072
- setFocus(flag?: boolean): void;
1073
- /** Set a new icon path or class. */
1074
- setIcon(icon: string): void;
1075
- /** Change node's {@link key} and/or {@link refKey}. */
1076
- setKey(key: string | null, refKey: string | null): void;
1066
+ error?: (e: WbErrorEventType) => void;
1077
1067
  /**
1078
- * Trigger a repaint, typically after a status or data change.
1079
1068
  *
1080
- * `change` defaults to 'data', which handles modifcations of title, icon,
1081
- * and column content. It can be reduced to 'ChangeType.status' if only
1082
- * active/focus/selected state has changed.
1069
+ * Check `e.flag` for status.
1070
+ * @category Callback
1071
+ */
1072
+ focus?: (e: WbTreeEventType) => void;
1073
+ /**
1074
+ * Fires when the tree markup was created and the initial source data was loaded.
1075
+ * Typical use cases would be activating a node, setting focus, enabling other
1076
+ * controls on the page, etc.<br>
1077
+ * Check `e.error` for status.
1078
+ * @category Callback
1079
+ */
1080
+ init?: (e: WbInitEventType) => void;
1081
+ /**
1083
1082
  *
1084
- * This method will eventually call {@link WunderbaumNode.render()} with
1085
- * default options, but may be more consistent with the tree's
1086
- * {@link Wunderbaum.setModified()} API.
1083
+ * @category Callback
1087
1084
  */
1088
- setModified(change?: ChangeType): void;
1089
- /** Modify the check/uncheck state. */
1090
- setSelected(flag?: boolean, options?: SetSelectedOptions): void;
1091
- /** Display node status (ok, loading, error, noData) using styles and a dummy child node. */
1092
- setStatus(status: NodeStatusType, options?: SetStatusOptions): WunderbaumNode | null;
1093
- /** Rename this node. */
1094
- setTitle(title: string): void;
1095
- _sortChildren(cmp: SortCallback, deep: boolean): void;
1085
+ keydown?: (e: WbKeydownEventType) => void;
1096
1086
  /**
1097
- * Sort child list by title or custom criteria.
1098
- * @param {function} cmp custom compare function(a, b) that returns -1, 0, or 1
1099
- * (defaults to sorting by title).
1100
- * @param {boolean} deep pass true to sort all descendant nodes recursively
1087
+ * Fires when a node that was marked 'lazy', is expanded for the first time.
1088
+ * Typically we return an endpoint URL or the Promise of a fetch request that
1089
+ * provides a (potentially nested) list of child nodes.
1090
+ * @category Callback
1101
1091
  */
1102
- sortChildren(cmp?: SortCallback | null, deep?: boolean): void;
1092
+ lazyLoad?: (e: WbNodeEventType) => void;
1103
1093
  /**
1104
- * Trigger `modifyChild` event on a parent to signal that a child was modified.
1105
- * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
1094
+ * Fires when data was loaded (initial request, reload, or lazy loading),
1095
+ * after the data is applied and rendered.
1096
+ * @category Callback
1106
1097
  */
1107
- triggerModifyChild(operation: string, child: WunderbaumNode | null, extra?: any): void;
1098
+ load?: (e: WbNodeEventType) => void;
1108
1099
  /**
1109
- * Trigger `modifyChild` event on node.parent(!).
1110
- * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
1111
- * @param {object} [extra]
1100
+ * @category Callback
1112
1101
  */
1113
- triggerModify(operation: string, extra?: any): void;
1102
+ modifyChild?: (e: WbNodeEventType) => void;
1114
1103
  /**
1115
- * Call `callback(node)` for all child nodes in hierarchical order (depth-first, pre-order).
1116
- *
1117
- * Stop iteration, if fn() returns false. Skip current branch, if fn()
1118
- * returns "skip".<br>
1119
- * Return false if iteration was stopped.
1120
- *
1121
- * @param {function} callback the callback function.
1122
- * Return false to stop iteration, return "skip" to skip this node and
1123
- * its children only.
1124
- * @see {@link IterableIterator<WunderbaumNode>}, {@link Wunderbaum.visit}.
1104
+ * Fires when data was fetched (initial request, reload, or lazy loading),
1105
+ * but before the data is applied and rendered.
1106
+ * Here we can modify and adjust the received data, for example to convert an
1107
+ * external response to native Wunderbaum syntax.
1108
+ * @category Callback
1125
1109
  */
1126
- visit(callback: NodeVisitCallback, includeSelf?: boolean): NodeVisitResponse;
1127
- /** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br>
1128
- * Stop iteration, if callback() returns false.<br>
1129
- * Return false if iteration was stopped.
1110
+ receive?: (e: WbReceiveEventType) => void;
1111
+ /**
1112
+ * Fires when a node is about to be displayed.
1113
+ * The default HTML markup is already created, but not yet added to the DOM.
1114
+ * Now we can tweak the markup, create HTML elements in this node's column
1115
+ * cells, etc.
1116
+ * See also `Custom Rendering` for details.
1117
+ * @category Callback
1118
+ */
1119
+ render?: (e: WbRenderEventType) => void;
1120
+ /**
1130
1121
  *
1131
- * @param callback the callback function. Return false to stop iteration
1122
+ * @category Callback
1132
1123
  */
1133
- visitParents(callback: (node: WunderbaumNode) => boolean | void, includeSelf?: boolean): boolean;
1124
+ renderStatusNode?: (e: WbRenderEventType) => void;
1134
1125
  /**
1135
- * Call fn(node) for all sibling nodes.<br>
1136
- * Stop iteration, if fn() returns false.<br>
1137
- * Return false if iteration was stopped.
1138
1126
  *
1139
- * @param {function} fn the callback function.
1140
- * Return false to stop iteration.
1127
+ * Check `e.flag` for status.
1128
+ * @category Callback
1141
1129
  */
1142
- visitSiblings(callback: (node: WunderbaumNode) => boolean | void, includeSelf?: boolean): boolean;
1130
+ select?: (e: WbNodeEventType) => void;
1143
1131
  /**
1144
- * [ext-filter] Return true if this node is matched by current filter (or no filter is active).
1132
+ * Fires when the viewport content was updated, after scroling, expanding etc.
1133
+ * @category Callback
1145
1134
  */
1146
- isMatched(): boolean;
1135
+ update?: (e: WbTreeEventType) => void;
1147
1136
  }
1148
1137
  }
1149
1138
  declare module "types" {
@@ -1162,10 +1151,28 @@ declare module "types" {
1162
1151
  export type BoolOptionResolver = (node: WunderbaumNode) => boolean;
1163
1152
  /** When set as option, called when the value is needed (e.g. `icon` type definition). */
1164
1153
  export type BoolOrStringOptionResolver = (node: WunderbaumNode) => boolean | string;
1154
+ /** A callback that receives a node instance and returns an arbitrary value type. */
1165
1155
  export type NodeAnyCallback = (node: WunderbaumNode) => any;
1156
+ /** A callback that receives a node instance and returns a string value. */
1166
1157
  export type NodeStringCallback = (node: WunderbaumNode) => string;
1167
- export type NodeVisitResponse = "skip" | boolean | void;
1158
+ /** A callback that receives a node instance and returns an iteration modifier. */
1168
1159
  export type NodeVisitCallback = (node: WunderbaumNode) => NodeVisitResponse;
1160
+ /** A callback that receives a node instance and returns a string value. */
1161
+ export type NodeVisitResponse = "skip" | boolean | void;
1162
+ /** A callback that receives a node-data dictionary and a node instance and returns an iteration modifier. */
1163
+ export type NodeToDictCallback = (dict: WbNodeData, node: WunderbaumNode) => NodeVisitResponse;
1164
+ /** A plain object (dictionary) that represents a node instance. */
1165
+ export interface WbNodeData {
1166
+ title: string;
1167
+ key?: string;
1168
+ refKey?: string;
1169
+ expanded?: boolean;
1170
+ selected?: boolean;
1171
+ checkbox?: boolean | string;
1172
+ colspan?: boolean;
1173
+ children?: Array<WbNodeData>;
1174
+ treeId?: string;
1175
+ }
1169
1176
  export interface WbTreeEventType {
1170
1177
  /** Name of the event. */
1171
1178
  type: string;
@@ -1301,8 +1308,14 @@ declare module "types" {
1301
1308
  * Default: `4px`.
1302
1309
  */
1303
1310
  minWidth?: string | number;
1304
- /** Optional class names that are added to all `span.wb-col` elements of that column.*/
1311
+ /** Optional class names that are added to all `span.wb-col` header AND data
1312
+ * elements of that column.
1313
+ */
1305
1314
  classes?: string;
1315
+ /** If `headerClasses` is a string, it will be used for the header element,
1316
+ * while `classes` is used for data elements.
1317
+ */
1318
+ headerClasses?: string;
1306
1319
  /** Optional HTML content that is rendered into all `span.wb-col` elements of that column.*/
1307
1320
  html?: string;
1308
1321
  _weight?: number;
@@ -1981,8 +1994,7 @@ declare module "wb_ext_edit" {
1981
1994
  import { Wunderbaum } from "wunderbaum";
1982
1995
  import { WunderbaumExtension } from "wb_extension_base";
1983
1996
  import { WunderbaumNode } from "wb_node";
1984
- import { InsertNodeType } from "types";
1985
- import { WbNodeData } from "wb_options";
1997
+ import { InsertNodeType, WbNodeData } from "types";
1986
1998
  export class EditExtension extends WunderbaumExtension {
1987
1999
  protected debouncedOnChange: (e: Event) => void;
1988
2000
  protected curEditNode: WunderbaumNode | null;
@@ -2025,7 +2037,7 @@ declare module "wunderbaum" {
2025
2037
  import "./wunderbaum.scss";
2026
2038
  import * as util from "util";
2027
2039
  import { ExtensionsDict, WunderbaumExtension } from "wb_extension_base";
2028
- import { ApplyCommandType, ChangeType, ColumnDefinitionList, ExpandAllOptions, FilterModeType, MatcherCallback, NavModeEnum, NodeStatusType, NodeStringCallback, NodeTypeDefinitionMap, ScrollToOptions, SetActiveOptions, SetModifiedOptions, SetStatusOptions, WbEventInfo, ApplyCommandOptions, AddChildrenOptions, VisitRowsOptions, NodeFilterCallback, FilterNodesOptions, RenderFlag, NodeVisitCallback, SortCallback } from "types";
2040
+ import { ApplyCommandType, ChangeType, ColumnDefinitionList, ExpandAllOptions, FilterModeType, MatcherCallback, NavModeEnum, NodeStatusType, NodeStringCallback, NodeTypeDefinitionMap, ScrollToOptions, SetActiveOptions, SetModifiedOptions, SetStatusOptions, WbEventInfo, ApplyCommandOptions, AddChildrenOptions, VisitRowsOptions, NodeFilterCallback, FilterNodesOptions, RenderFlag, NodeVisitCallback, SortCallback, NodeToDictCallback, WbNodeData } from "types";
2029
2041
  import { WunderbaumNode } from "wb_node";
2030
2042
  import { WunderbaumOptions } from "wb_options";
2031
2043
  /**
@@ -2391,6 +2403,15 @@ declare module "wunderbaum" {
2391
2403
  * @param {boolean} deep pass true to sort all descendant nodes recursively
2392
2404
  */
2393
2405
  sortChildren(cmp?: SortCallback | null, deep?: boolean): void;
2406
+ /** Convert tree to an array of plain objects.
2407
+ *
2408
+ * @param callback(dict, node) is called for every node, in order to allow
2409
+ * modifications.
2410
+ * Return `false` to ignore this node or `"skip"` to include this node
2411
+ * without its children.
2412
+ * @see {@link WunderbaumNode.toDict}.
2413
+ */
2414
+ toDictArray(callback?: NodeToDictCallback): Array<WbNodeData>;
2394
2415
  /**
2395
2416
  * Update column headers and column width.
2396
2417
  * Return true if at least one column width changed.