/** Raw node data as provided by the consumer (JSON or parsed from HTML). */ export interface TreeNodeData { id: string; text: string; /** True (the theme icon, the default), false (none), or a class list or image URL. */ icon?: string | boolean | null; type?: string; children?: TreeNodeData[] | boolean; /** Layered over `data.jstree` and the defaults, as in jstree; any key is kept. */ state?: { opened?: boolean; selected?: boolean; disabled?: boolean; checked?: boolean; loaded?: boolean; [key: string]: unknown; }; li_attr?: Record; a_attr?: Record; /** User data. `get_json` reports it as `false` under `no_data`, as jstree does. */ data?: Record | false | null; [key: string]: unknown; } /** Internal node representation stored in the tree's flat map. */ export interface TreeNode { id: string; text: string; /** True for the theme icon, false for none, or a class list or image URL — as in jstree. */ icon: string | boolean; type: string; parent: string; parents: string[]; children: string[]; children_d: string[]; state: { opened: boolean; selected: boolean; disabled: boolean; loaded: boolean; loading: boolean; checked: boolean; hidden?: boolean; /** Set when the node's last load failed, as in jstree. */ failed?: boolean; /** Set by disable_checkbox, as in jstree. */ checkbox_disabled?: boolean; }; li_attr: Record; a_attr: Record; /** The user data from the node's JSON, or null when there was none — as in jstree. */ data: Record | null; original: TreeNodeData; } /** * `core.data` as a function, as in jstree: called with the tree as `this` and * the node to load; answer with its children — as JSON, or as an HTML string * of `
  • ` elements — or with `false` to fail the load. */ export type DataCallback = (this: MDFolderTree, node: TreeNode, callback: (data: TreeNodeData[] | string | false) => void) => void; /** * jstree's ajax config — for `core.data`, `search.ajax` and `massload` — * sent with `fetch` as `$.ajax` would send it. `url` and `data` may be * functions (of the node, or for massload the ids), called with the tree as * `this`. */ export interface AjaxConfig { url: string | ((this: MDFolderTree, arg: any) => string); data?: unknown; type?: string; method?: string; dataType?: string; contentType?: string | false; headers?: Record; cache?: boolean; xhrFields?: { withCredentials?: boolean; }; } export interface CoreConfig { /** * The nodes: an array, a function, an ajax config, or an HTML string (for * the root) — as jstree's `core.data`. Absent, the container's markup. */ data?: TreeNodeData[] | DataCallback | AjaxConfig | string | false; multiple?: boolean; animation?: number; themes?: ThemeConfig; /** * Validates structural operations, as jstree's: a boolean, a function, or a * map of operation names to booleans (`{ delete_node: false }`). */ check_callback?: boolean | CheckCallback | Partial>; expand_selected_onload?: boolean; force_text?: boolean; dblclick_toggle?: boolean; /** * Write `aria-setsize` and `aria-posinset` on every node, which some * browsers otherwise compute wrongly for screen readers (default false). */ compute_elements_positions?: boolean; worker?: boolean; /** Translations for UI strings: a map, or a function of the key (`this` is the tree). */ strings?: Record | ((this: MDFolderTree, key: string) => string); error?: (error: unknown) => void; loaded_state?: boolean; restore_focus?: boolean; allow_reselect?: boolean; /** * Shortcuts merged over jstree's defaults (`ctrl-space`, `enter`, the * arrows, `*`, `home`, `end`, `f2`). Keys are combos such as * `'ctrl-space'`; modifier order is irrelevant. A null entry disables that * default and `false` disables every shortcut. Returning false from a * handler prevents the default action. */ keyboard?: Record | boolean; sanitize_attrs?: boolean; } export interface ThemeConfig { name?: string | false; /** * The theme's stylesheet: a URL to inject, or `true` to build * `//style.css`. False (the default) when it is already included. */ url?: string | boolean; /** Where the themes live, for `url: true`. */ dir?: string | false; dots?: boolean; icons?: boolean; ellipsis?: boolean; stripes?: boolean; variant?: string | false; responsive?: boolean; } export interface TypeConfig { icon?: string | boolean; /** The most children a node of this type may hold; -1 (the default) for any number. */ max_children?: number; /** How deep below a node of this type nodes may go; -1 (the default) for any depth. */ max_depth?: number; /** The types this type accepts as children; -1 (the default) for any type. */ valid_children?: number | string[]; /** Attributes given to the `
  • ` of every node of this type. */ li_attr?: Record; /** Attributes given to the anchor of every node of this type. */ a_attr?: Record; [key: string]: unknown; } export interface CheckboxConfig { keep_selected_style?: boolean; visible?: boolean; three_state?: boolean; cascade?: string; tie_selection?: boolean; whole_node?: boolean; cascade_to_disabled?: boolean; cascade_to_hidden?: boolean; } export interface SearchConfig { show_only_matches?: boolean; show_only_matches_children?: boolean; close_opened_onclear?: boolean; case_sensitive?: boolean; fuzzy?: boolean; search_leaves_only?: boolean; /** Decides a match instead of the text matcher; called with the tree as `this`. */ search_callback?: (this: MDFolderTree, str: string, node: TreeNode) => boolean; /** * Names nodes to load before searching, as jstree's function form: called * with the tree as `this`, the string, a callback taking the ids (or * `{ d: ids }`) and the `inside` node's id. */ ajax?: false | AjaxConfig | ((this: MDFolderTree, str: string, callback: (ids: string[] | { d: string[]; }) => void, inside: string | null) => void); } /** What a context menu item's action, `_disabled` and `label` receive, as in jstree. */ export interface ContextMenuData { item: ContextMenuItem | string; /** The node's anchor; `tree.get_node(reference)` finds the node. */ reference: HTMLElement | null; /** The menu. */ element: HTMLElement | null; position?: { x: number; y: number; }; } /** A jstree context menu item. */ export interface ContextMenuItem { /** The label, drawn as text; or a function of the item's key and the reference. */ label?: string | ((data: ContextMenuData) => string); title?: string; /** A class list, or an image URL (containing '/' or '.'). */ icon?: string | false; /** Runs the item; returning false keeps the menu open. */ action?: false | ((data: ContextMenuData) => unknown); separator_before?: boolean; separator_after?: boolean; _disabled?: boolean | ((data: ContextMenuData) => boolean); _class?: string; /** A key code that runs the item while the menu is open. */ shortcut?: number; shortcut_label?: string; submenu?: Record; [key: string]: unknown; } export interface ContextMenuConfig { /** Activate the node on right-click (default true). */ select_node?: boolean; /** Open at the node rather than the pointer (default true). */ show_at_node?: boolean; /** * The items: an object, or a function of the node — called with the tree * as `this` — returning them or handing them to the callback. */ items?: Record | ((this: MDFolderTree, node: TreeNode, callback: (items: Record) => void) => Record | void); } export interface DndConfig { copy?: boolean; open_timeout?: number; /** Whether nodes may be dragged: a boolean, or called with the nodes and the event, the tree as `this`. */ is_draggable?: boolean | ((this: MDFolderTree, nodes: TreeNode[], e: Event) => boolean); check_while_dragging?: boolean; always_copy?: boolean; inside_pos?: number | "first" | "last"; drag_selection?: boolean; touch?: boolean | "selected"; large_drop_target?: boolean; large_drag_target?: boolean | string; /** * Drag with the browser's native drag and drop, as jstree's HTML5 backend, * where elements can be draggable (default false). */ use_html5?: boolean; blank_space_drop?: boolean; } /** * jstree's `massload`: called with the tree as `this` and the ids of several * nodes about to load, answering with a map of id to children — JSON, or an * HTML string. A node the answer leaves out loads through `core.data`. */ export type MassloadCallback = (this: MDFolderTree, ids: string[], callback: (data: Record | null | false) => void) => void; /** * @deprecated The earlier `{ url, data, callback }` form never ran; * `massload` is now jstree's function, typed as `MassloadCallback`. */ export type MassloadConfig = MassloadCallback; /** * A sort plugin comparator. As in jstree it receives two node ids, with the * tree as `this`, so it can call back into the API (`this.get_text(a)`). */ export type SortComparator = (this: MDFolderTree, a: string, b: string) => number; export interface StateConfig { /** The localStorage key; 'jstree' by default, as in jstree. */ key?: string; /** Events after which the state is saved (debounced by 100ms). */ events?: string; /** Milliseconds a saved state stays valid; false (the default) for ever. */ ttl?: number | false; /** Adjusts the state being restored; called with the tree as `this`. */ filter?: (this: MDFolderTree, state: TreeState) => TreeState; /** Keep `core.loaded` when saving and restoring. */ preserve_loaded?: boolean; } /** * jstree's state, as get_state reports it and set_state applies it. Plugins * add their own keys — the checkbox plugin its `checkbox` list. */ export interface TreeState { core?: { open?: string[]; loaded?: string[]; scroll?: { left?: number; top?: number; }; selected?: string[]; initial_selection?: string; }; checkbox?: string[]; [plugin: string]: unknown; } /** The `{ opened, selected }` state of earlier releases, which set_state still accepts. */ export interface LegacyTreeState { opened?: string[]; selected?: string[]; } export interface UniqueConfig { case_sensitive?: boolean; trim_whitespace?: boolean; /** Names a duplicate, called with the tree as `this` and a counter from 2. */ duplicate?: (this: MDFolderTree, name: string, counter: number) => string; } /** As in jstree, the callback is called with the tree as `this`. */ export type ConditionalSelectCallback = (this: MDFolderTree, node: TreeNode, event?: Event) => boolean; export interface TreeConfig { core?: CoreConfig; types?: Record; checkbox?: CheckboxConfig; search?: SearchConfig; contextmenu?: ContextMenuConfig; dnd?: DndConfig; massload?: MassloadCallback | AjaxConfig | null; sort?: SortComparator; state?: StateConfig; unique?: UniqueConfig; conditionalselect?: ConditionalSelectCallback; plugins?: string[]; } export interface TreePlugin { name: string; init(tree: TreePluginHost): void; destroy(): void; onNodeRender?(node: TreeNode, element: HTMLElement): void; onBeforeRender?(nodes: TreeNode[]): TreeNode[]; onBeforeActivate?(node: TreeNode, event?: Event): boolean; /** * Join jstree's `check`: consulted after the core rules pass, return true * to allow the operation, or a refusal — jstree's error `id` and `reason` * — which the core reports under the plugin's name. */ onCheck?(chk: string, node: TreeNode | TreeNodeData | null, parent: TreeNode | null, pos: unknown, more: CheckMore): true | { id: string; reason: string; }; } /** Subset of MDFolderTree exposed to plugins. */ export interface TreePluginHost { config: TreeConfig; getNode(id: string): TreeNode | null; getAllNodes(): TreeNode[]; getNodeChildren(id: string): TreeNode[]; getSelectedIds(): string[]; getOpenedIds(): string[]; selectNode(id: string, suppress?: boolean, preventOpen?: boolean, event?: ActivationEvent): void; deselectNode(id: string, suppress?: boolean, event?: ActivationEvent): void; /** * Change selection membership without events or opening ancestors — the * equivalent of jstree's checkbox cascade writing `_data.core.selected` * directly. The caller is responsible for repainting. */ applySelection(ids: string[], selected: boolean): void; selectAll(suppress?: boolean): void; deselectAll(suppress?: boolean): void; /** Open a node; `animation` ms of slide (the core.animation setting by default, 0 for none). */ openNode(id: string, suppress?: boolean, animation?: number | false): void; closeNode(id: string, suppress?: boolean, animation?: number | false): void; getContainer(): HTMLElement; on(event: string, handler: EventHandler): void; off(event: string, handler: EventHandler): void; emit(event: string, detail: unknown): void; redrawNode(id: string): void; redraw(): void; moveNode(id: string, parentId: string, position: number): boolean; copyNode(id: string, parentId: string, position: number): string | false; renameNode(id: string, text: string): boolean; deleteNode(id: string): boolean; createNode(parentId: string, data: TreeNodeData, position?: number): TreeNode | false; reorderChildren(parentId: string, childIds: string[]): void; /** Reorder a parent's children in the model only, without rendering. */ setChildOrder(parentId: string, childIds: string[]): void; getRootNodeIds(): string[]; } export type EventHandler = (event: CustomEvent) => void; /** * Modifier state consulted by `activate_node`. Any DOM `MouseEvent` or * `KeyboardEvent` satisfies it; programmatic callers may pass a plain object. */ /** * Anything jstree accepts where it expects a node, as resolved by `get_node`: * a node object, an object carrying an `id`, an id (optionally '#'-prefixed), * a jQuery-style wrapper, a DOM element inside a node, or the container * itself (the root). Unlike jstree, a string that is not an id is not tried * as a CSS selector. */ export type NodeRef = string | number | TreeNode | { id: string | number; } | Element | ArrayLike; /** Extra context jstree passes to `check_callback` for move_node / copy_node. */ export interface CheckMore { core?: boolean; origin?: unknown; is_multi?: boolean; is_foreign?: boolean; dnd?: boolean; [key: string]: unknown; } /** * `core.check_callback` as a function. As in jstree, `node` is the new node's * data for create_node, and `position` is the new text for rename_node and * the node's index for delete_node. Only a return of exactly `false` refuses. */ export type CheckCallback = (operation: string, node: TreeNode, parent: TreeNode, position: number | string, more: CheckMore) => boolean | void; /** A `core.keyboard` shortcut. As in jstree, `this` is the tree instance. */ export type KeyboardHandler = (this: MDFolderTree, e: KeyboardEvent) => boolean | void; export interface ActivationEvent { ctrlKey?: boolean; metaKey?: boolean; shiftKey?: boolean; target?: EventTarget | null; } export interface SelectNodeDetail { node: TreeNode; selected: string[]; event?: Event; } export interface DeselectNodeDetail { node: TreeNode; selected: string[]; event?: Event; } export interface ChangedDetail { action: string; node: TreeNode | null; selected: string[]; old_selection: string[]; changed?: { selected: string[]; deselected: string[]; }; /** The event that triggered the change, when there was one. */ event?: unknown; /** The parent a deleted node hung from, as jstree reports on `delete_node`. */ parent?: string; } export interface OpenNodeDetail { node: TreeNode; } export interface CloseNodeDetail { node: TreeNode; } export interface ReadyDetail { instance: unknown; } export interface DblClickDetail { node: TreeNode; event: MouseEvent; } /** What `get_buffer` reports, in jstree's shape. */ export interface ClipboardBuffer { mode: "move_node" | "copy_node" | false; node: TreeNode[] | false; inst: MDFolderTree | false; ids: string[]; } /** * The cut / copy / paste buffer behind `MDFolderTree`'s clipboard methods, * which delegate here. It reaches its tree through the public API alone, so * the two share no state beyond the tree itself. */ export declare class TreeClipboard { private readonly tree; constructor(tree: MDFolderTree); /** * jstree's `cut`: buffer the nodes -- the selection when given nothing -- * for paste to move. False when there is nothing to buffer. */ cut(obj?: NodeRef | NodeRef[]): false | void; /** jstree's `copy`: as `cut`, for paste to copy. */ copy(obj?: NodeRef | NodeRef[]): false | void; /** * jstree's `paste(obj, pos)`: move or copy the buffered nodes into `obj` * through move_node / copy_node, with the buffer's tree as the origin -- so * they keep their order, and may come from another tree -- emit `paste`, * and empty the buffer (without `clear_buffer`). Returns whether it pasted. */ paste(obj: NodeRef, pos?: number | string): boolean; /** The buffer, all false when empty. */ getBuffer(): ClipboardBuffer; /** Whether anything is buffered. */ canPaste(): boolean; /** Empty the buffer and emit `clear_buffer`. */ clearBuffer(): void; /** A destroyed tree's nodes can no longer be pasted. */ forget(): void; private fill; /** `get_node` without the DOM form, which this never asks for. */ private node; } /** Told how the edit ended: committed, dismissed, or cancelled outright. */ export type EditCallback = (node: TreeNode, status: boolean, cancel: boolean) => void; /** * Renaming a node in place: the text is swapped for an input carrying it, * which commits on Enter or blur and abandons on Escape. The rename itself * goes through `rename_node`, so the unique plugin and `check_callback` have * their say exactly as they would for any other rename. * * It reaches its tree through the public API alone. */ export declare class TreeInlineEditor { private readonly tree; constructor(tree: MDFolderTree); edit(obj: NodeRef, defaultText?: string, callback?: EditCallback): void; } export declare class MDFolderTree implements TreePluginHost { readonly config: TreeConfig; private element; private eventBus; private renderer; private selection; private store; private plugins; /** * The same plugins, under the names this tree built them by. A plugin's own * `name` is what it reports itself as -- in a refusal, say -- which is not * necessarily the name it was registered and listed under. */ private pluginsByName; /** Cut / copy / paste, over a buffer the whole page shares. */ private clipboard; /** Renaming a node in place. */ private inlineEditor; /** Keyboard navigation, and the virtual focus it moves. */ private keyboard; /** * The theme, its variant and the display flags. The renderer keeps its own * copy of the theme name, so it is handed a setter rather than exposed. */ private theme; private htmlParser; private destroyed; private idCounter; /** * Owns every listener bound directly to the container. `destroy()` aborts * it, which is the only way these come off — the event bus tracks just the * handlers registered through `on()`. */ private listeners; /** * Ordered container for top-level nodes. Deliberately kept out of the store * so `getAllNodes()` and every consumer of it stay unaffected, while * `'#'` still resolves to a real node with an ordered `children` array. */ private rootNode; /** * Anchor for shift-range selection, mirroring jstree's * `_data.core.last_clicked`. Revalidated on every activation. */ private lastClicked; /** Slides in progress, by node, each finishing itself when called. */ private slides; /** The worker's Blob URL, made once; loads wait their turn while one is in it. */ private workerUrl; private working; private workQueue; /** * Selection as of the last `changed` event. Diffs are computed against it, * as jstree's changed plugin does, so a suppressed intermediate step (such * as the `deselect_all(true)` inside a click) still shows in the next diff. */ private lastChangedSelection; /** * Whether any changed event has been emitted. The initial ready report * exists to seed the diff baseline, so it is skipped once something else * has seeded it: the tree loads synchronously, so a consumer can select a * node before the deferred ready report runs. */ private changedEmitted; /** The container's markup as first given, which jstree re-reads to reload the root of an HTML tree. */ private originalHtml; constructor(element: HTMLElement, config?: TreeConfig); /** * jstree's `get_node`: resolve any node reference (see `NodeRef`) to the * node, or with `asDom` to its element — the container for the root. * Returns false when nothing matches, as jstree does. */ get_node(obj: NodeRef, asDom?: boolean): TreeNode | HTMLElement | false; getNode(id: string): TreeNode | null; select_node(obj: NodeRef | NodeRef[], suppressEvent?: boolean, preventOpen?: boolean, event?: ActivationEvent): boolean | void; /** * Programmatic selection, matching jstree's `select_node`: it applies no * policy (`core.multiple` and `disabled` are enforced by `activate_node`, * not here), is a no-op for an already-selected node, and opens collapsed * ancestors unless `preventOpen`. `suppress` withholds only `changed`; * `select_node` is always emitted. */ selectNode(id: string, suppress?: boolean, preventOpen?: boolean, event?: ActivationEvent): void; deselect_node(obj: NodeRef | NodeRef[], suppressEvent?: boolean, event?: ActivationEvent): boolean | void; /** * Matches jstree's `deselect_node`: a no-op for a node that is not * selected; `suppress` withholds only `changed`. */ deselectNode(id: string, suppress?: boolean, event?: ActivationEvent): void; select_all(suppress?: boolean): void; deselect_all(suppress?: boolean): void; /** * jstree's `activate_node`: the entry point for user interaction (click, * Enter). Unlike the programmatic selection API it enforces * `core.multiple`, `disabled` and `allow_reselect`, toggles on ctrl/meta * and selects sibling ranges on shift. Returns false when refused. */ activate_node(obj: NodeRef, event?: ActivationEvent): boolean; /** Change selection membership silently; see `TreePluginHost.applySelection`. */ applySelection(ids: string[], selected: boolean): void; selectAll(suppress?: boolean): void; deselectAll(suppress?: boolean): void; get_selected(): string[]; getSelectedIds(): string[]; /** * jstree's `open_node(obj, callback, animation)`. Returns false for a * missing node, the root, or a node that is not closed — which emits * nothing — and true once it opens a node. An unloaded node is loaded first * and nothing is returned. The callback receives the node and whether it * was opened. */ open_node(obj: NodeRef | NodeRef[], callback?: (node: TreeNode, status: boolean) => void, animation?: number | false): boolean | void; /** * jstree's `close_node(obj, animation)`: false for a missing node, the * root, or a closed node, which emits nothing. */ close_node(obj: NodeRef | NodeRef[], animation?: number | false): boolean | void; /** * jstree's `open_all(obj, animation)`: open every closed node below `obj` * (the root by default) through open_node — loading lazy nodes and opening * what they load — then emit `open_all` with the node. */ open_all(obj?: NodeRef, animation?: number | false): boolean | void; /** * jstree's `close_all(obj, animation)`: close every open node below `obj` * (the root by default), deepest first, through close_node, then emit * `close_all` with the node. */ close_all(obj?: NodeRef, animation?: number | false): boolean | void; /** A node's descendants, in tree order. */ private descendantsOf; enable_node(obj: NodeRef | NodeRef[]): boolean | void; disable_node(obj: NodeRef | NodeRef[]): boolean | void; /** * jstree's `refresh_node`: reload the node and every open node inside it * through `core.data`, then reopen them, reselect the selected nodes that * still exist, and emit `refresh_node` with `{ node, nodes }` — the ids * that reloaded. */ refresh_node(obj: NodeRef): boolean; redrawNode(id: string): void; /** * The search plugin's `search(str, skip_async, show_only_matches, inside, * append, show_only_matches_children)`; returns the ids it matched. */ search(str: string | false, skipAsync?: boolean, showOnlyMatches?: boolean, inside?: NodeRef | null, append?: boolean, showOnlyMatchesChildren?: boolean): string[]; clear_search(): void; check_node(obj: NodeRef | NodeRef[]): boolean | void; uncheck_node(obj: NodeRef | NodeRef[]): boolean | void; check_all(): void; uncheck_all(): void; is_checked(obj: NodeRef): boolean; get_checked(): string[]; get_top_checked(): string[]; get_bottom_checked(): string[]; get_undetermined(): string[]; is_undetermined(obj: NodeRef): boolean; show_checkboxes(): void; hide_checkboxes(): void; toggle_checkboxes(): void; /** jstree's `disable_checkbox`: false for a missing node or the root. */ disable_checkbox(obj: NodeRef | NodeRef[]): boolean | void; /** jstree's `enable_checkbox`: false for a missing node or the root. */ enable_checkbox(obj: NodeRef | NodeRef[]): boolean | void; get_checked_descendants(obj: NodeRef): string[]; /** * jstree's `move_node(obj, par, pos, callback, is_loaded)`, returning the * node's id. `pos` defaults to 0 and takes create_node's forms; an index is * read against the children as they are before the move. An array's nodes * are placed one after another. An unloaded parent is loaded first, and the * callback receives the node, its new parent and its position. */ move_node(obj: NodeRef | NodeRef[], par: NodeRef, pos?: number | string, callback?: (node: TreeNode, parent: TreeNode, position: number) => void, isLoaded?: boolean, _skipRedraw?: boolean, origin?: MDFolderTree): string | boolean; /** * jstree's `copy_node(obj, par, pos, callback, is_loaded, skip_redraw, * origin)`, returning the copy's id; its arguments work as move_node's. */ copy_node(obj: NodeRef | NodeRef[], par: NodeRef, pos?: number | string, callback?: (node: TreeNode, parent: TreeNode, position: number) => void, isLoaded?: boolean, _skipRedraw?: boolean, origin?: MDFolderTree): string | boolean; /** The argument handling move_node and copy_node share, as in jstree. */ private transfer; /** * A node from another tree, as jstree's move / copy take one: copied in from * its JSON — without ids, data or state — once `check` allows it as * `is_multi`, then, for a move, deleted from its own tree. */ private transferIn; /** * jstree's `create_node(par, node, pos, callback, is_loaded)`, returning the * new node's id. A null `par` means the root. `node` may be a string (its * text) or omitted, and its text defaults to `get_string('New node')`. * `pos` defaults to 'last' (see `resolveInsertion` for the other forms). An * unloaded parent is loaded first, unless `is_loaded` says it already is. */ create_node(par: NodeRef | null, node?: TreeNodeData | string, pos?: number | string, callback?: (node: TreeNode) => void, isLoaded?: boolean): string | boolean; /** * The text of a node created without one: `get_string('New node')`, which * the unique plugin makes unique among `par`'s children, as jstree's does. */ private newNodeName; /** * jstree's position forms, relative to `par`: 'before' / 'after' place the * node beside it (first / last when `par` is the root), 'first' / 'inside' * at the start of its children, 'last' at the end, and an index — clamped * to the end — where it says. */ private resolveInsertion; rename_node(obj: NodeRef | NodeRef[], text: string): boolean; delete_node(obj: NodeRef | NodeRef[]): boolean; get_container(): HTMLElement; /** * jstree's `set_theme(name, url)`: swap the theme's classes and, given a * URL — or `true`, meaning `//style.css` — inject that * stylesheet, each one only once per page. */ set_theme(name: string, url?: string | boolean): void; get_theme(): string; set_theme_variant(variant: string | false): void; get_theme_variant(): string | false; /** * jstree's `hover_node`: mark a node hovered, dehovering any other first. * Returns false when the node is unknown or already hovered. Unlike jstree * it does not set `aria-activedescendant`, which here tracks keyboard focus. */ hover_node(obj: NodeRef): false | void; /** jstree's `dehover_node`; returns false when the node is not hovered. */ dehover_node(obj: NodeRef): false | void; /** jstree's `get_container_ul`: the root list element. */ get_container_ul(): HTMLElement | null; /** jstree's `get_string`: translate a UI string through `core.strings`. */ get_string(key: string): string; /** * jstree's `get_type`: the node's type, or with `rules` the type merged * with its `types` configuration. False for an unknown node. */ get_type(obj: NodeRef, rules?: boolean): string | Record | false; /** * jstree's `set_type`. Refuses a type absent from `types`. A node showing * its old type's icon adopts the new one; an icon set on the node itself is * kept, as in jstree. */ set_type(obj: NodeRef | NodeRef[], type: string): boolean; /** * The types plugin's `get_rules`: the node's type merged with its rules and * jstree's `-1` defaults for `max_depth`, `max_children` and * `valid_children`. False for an unknown node. */ get_rules(obj: NodeRef): Record | false; /** * The sort plugin's `sort(obj, deep)`: order a node's children in the model * (every descendant's too when `deep`). A no-op without the sort plugin. */ sort(obj: NodeRef, deep?: boolean): void; /** * A type's rules: from the types plugin when active (which, as jstree, * fills unset properties from 'default'), otherwise from `config.types`. */ private typeRules; /** jstree's `redraw_node`: re-render a node, returning its element. */ redraw_node(obj: NodeRef): HTMLElement | false; /** * jstree's `get_state`: `{ core: { open, loaded, scroll, selected } }` — * `loaded` only with `core.loaded_state` — plus the checked nodes as * `checkbox` while checking is not tied to selection. */ get_state(): TreeState; /** * jstree's `set_state`, applied step by step: `core.loaded` (with * `core.loaded_state`) and `core.open` are loaded — then the open ones * opened, without closing others — `core.scroll` is scrolled to, and * `core.selected` replaces the selection unless it changed since the call * began; the checkbox plugin's `checkbox` list is checked. Keys of plugins * not in use are dropped. Once done it calls back and emits `set_state`. * The `{ opened, selected }` state of earlier releases is accepted too. */ set_state(state: TreeState | LegacyTreeState | null | undefined, callback?: () => void): boolean; /** A state in jstree's shape, translating the earlier `{ opened, selected }`. */ private stateShape; private applyState; get_children_dom(obj: NodeRef): HTMLElement[]; is_loading(obj: NodeRef): boolean; private lastError; last_error(): unknown; destroy(): void; getContainer(): HTMLElement; on(event: string, handler: EventHandler): void; off(event: string, handler: EventHandler): void; emit(event: string, detail: unknown): void; getAllNodes(): TreeNode[]; getNodeChildren(id: string): TreeNode[]; getOpenedIds(): string[]; /** * Open a node, as jstree's open_node: `before_open` and `open_node` at * once, `after_open` when its children have slid down over `animation` ms * (the core.animation setting by default; 0 or false for none). */ openNode(id: string, suppress?: boolean, animation?: number | false): void; /** Close a node, as jstree's close_node: `close_node` at once, `after_close` once the slide ends. */ closeNode(id: string, suppress?: boolean, animation?: number | false): void; /** The slide length for an open or close: the argument, else core.animation; 0 for none. */ private animationFor; /** * jstree's slideDown / slideUp of a node's children over `ms`, then `done` * — at once without an animation or a rendered list. A new slide of the * same node finishes the previous one first, as jQuery's `.stop(true, true)` * does; a destroyed tree fires nothing more. */ private slide; redraw(): void; moveNode(id: string, parentId: string, position: number): boolean; copyNode(id: string, parentId: string, position: number): string | false; /** * Recursively duplicate `source` and its descendants under `parentId`, * minting a fresh id for every node and detaching all mutable objects from * the source. Returns the id of the new subtree root. */ private copySubtree; /** Deep-clone consumer-supplied node data, tolerating non-cloneable values. */ private cloneData; renameNode(id: string, text: string): boolean; deleteNode(id: string): boolean; createNode(parentId: string, data: TreeNodeData, position?: number): TreeNode | false; /** * Build `data` under `parent` at `position` (the end when omitted): from a * copy, so the caller's object is left alone, with nested children built as * a whole subtree through the same normalization as a load. As in jstree, * the node goes under `parent` whatever `parent` it names itself. */ private buildAt; /** * Reorder a parent's children in the model without rendering. Kept separate * from `reorderChildren` so render-time hooks can adjust ordering without * re-entering the renderer. */ setChildOrder(parentId: string, childIds: string[]): void; reorderChildren(parentId: string, childIds: string[]): void; getRootNodeIds(): string[]; get_parent(obj: NodeRef): string | null; get_path(obj: NodeRef, glue?: string | false, ids?: boolean): string | string[] | false; get_text(obj: NodeRef): string | false; set_text(obj: NodeRef | NodeRef[], text: string): boolean; /** * jstree's `get_json`: each node as `{ id, text, icon, li_attr, a_attr, * state, data, children }` — with `type` when the types plugin is active — * or, with `flat`, a pre-order list whose entries carry `parent` instead of * `children`. The root, or no argument, yields its children. `no_id` drops * ids (li_attr and a_attr ids too), `no_data` reports data as false, and * `no_state`, `no_children`, `no_li_attr` and `no_a_attr` drop those. */ get_json(obj?: NodeRef, options?: { flat?: boolean; no_state?: boolean; no_id?: boolean; no_children?: boolean; no_data?: boolean; no_li_attr?: boolean; no_a_attr?: boolean; }): TreeNodeData | TreeNodeData[] | false; is_selected(obj: NodeRef): boolean; /** * jstree's is_parent: a node with children, or a lazy node not yet loaded, * which may have children once it is. */ is_parent(obj: NodeRef): boolean; /** * jstree defines is_leaf as the negation of is_parent, so an unknown node * reports as a leaf. Kept literally, as part of the contract. */ is_leaf(obj: NodeRef): boolean; is_open(obj: NodeRef): boolean; /** jstree's is_closed: a parent (loaded or not) that is not open. */ is_closed(obj: NodeRef): boolean; is_disabled(obj: NodeRef): boolean; is_loaded(obj: NodeRef): boolean; toggle_node(obj: NodeRef | NodeRef[]): boolean | void; /** * The next visible node in document order; with `strict`, the next visible * sibling only. As in jstree, hidden nodes and the contents of collapsed * nodes are skipped. */ get_next_dom(obj: NodeRef, strict?: boolean): HTMLElement | null; /** The mirror image of `get_next_dom`. */ get_prev_dom(obj: NodeRef, strict?: boolean): HTMLElement | null; get_top_selected(): string[]; get_bottom_selected(): string[]; set_id(obj: NodeRef, newId: string): boolean; hide_node(obj: NodeRef | NodeRef[]): boolean | void; show_node(obj: NodeRef | NodeRef[]): boolean | void; /** jstree's `hide_all`: hide every node, returning — and emitting as `nodes` — the ids it hid. */ hide_all(_skipRedraw?: boolean): string[]; /** jstree's `show_all`: show every node, returning — and emitting as `nodes` — the ids it showed. */ show_all(_skipRedraw?: boolean): string[]; is_hidden(obj: NodeRef): boolean; show_stripes(): void; hide_stripes(): void; toggle_stripes(): void; show_dots(): void; hide_dots(): void; toggle_dots(): void; show_icons(): void; hide_icons(): void; toggle_icons(): void; show_ellipsis(): void; hide_ellipsis(): void; toggle_ellipsis(): void; /** * jstree's `set_icon`: true, null, undefined or '' restore the theme icon; * false hides it; a string sets a class list or image URL. */ set_icon(obj: NodeRef | NodeRef[], icon: string | boolean | null | undefined): boolean; get_icon(obj: NodeRef): string | boolean; /** * jstree's `hide_icon`: set the icon to false and hide the rendered one, * which keeps its `rel` for show_icon until the node is next redrawn. */ hide_icon(obj: NodeRef | NodeRef[]): boolean; /** * jstree's `show_icon`: restore the icon recorded in the rendered icon's * `rel`, or the theme icon when there is none. */ show_icon(obj: NodeRef | NodeRef[]): boolean; /** A node's rendered icon element, if the node is rendered. */ private themeIconOf; /** * jstree's `cut`: buffer the nodes — the selection when given nothing — for * paste to move. False when there is nothing to buffer. */ cut(obj?: NodeRef | NodeRef[]): false | void; /** jstree's `copy`: as `cut`, for paste to copy. */ copy(obj?: NodeRef | NodeRef[]): false | void; /** * jstree's `paste(obj, pos)`: move or copy the buffered nodes into `obj` * through move_node / copy_node, with the buffer's tree as the origin — so * they keep their order, and may come from another tree — emit `paste`, and * empty the buffer (without `clear_buffer`). Returns whether it pasted. */ paste(obj: NodeRef, pos?: number | string): boolean; /** * jstree's `get_buffer`: `{ mode, node, inst }` — 'move_node' or * 'copy_node', the nodes and their tree, all false when empty — with the * ids as `ids`, as earlier releases reported them. */ get_buffer(): ClipboardBuffer; /** jstree's `can_paste`: whether anything is buffered. */ can_paste(): boolean; /** jstree's `clear_buffer`: empty the buffer and emit `clear_buffer`. */ clear_buffer(): void; /** * jstree's `edit`: rename a node in place, starting from `defaultText` when * given one. The callback is told the node, whether it was renamed, and * whether Escape cancelled it. */ edit(obj: NodeRef, defaultText?: string, callback?: EditCallback): void; refresh(): void; /** * jstree's `load_node`: (re)load a node's children through `core.data`. * Returns true for any node that exists. A loaded node's descendants are * dropped when the reload starts; `load_node` is emitted with the outcome as * `status`, and the callback receives the node and that status. Given an * array, it loads the nodes not yet loaded and calls back once with the ids * that loaded. */ load_node(obj: NodeRef[], callback?: (nodes: string[]) => void): boolean; load_node(obj: NodeRef, callback?: (node: TreeNode, status: boolean) => void): boolean; /** * jstree's `_load_node`: fetch a node's children from `core.data` and add * them, reporting whether that succeeded. A function is called with the * tree as `this` and may answer `false`, JSON or HTML. An ajax config is * fetched for every node (`core_04` on failure). An array or object loads * only the root (`core_05` for any other node), as does an HTML string * (`core_06`); with no data the root re-reads the container's markup. */ private fetchChildren; /** * jstree's ajax `core.data`, fetched for each node load: `url` and `data` * may be functions of the node, called with the tree as `this`. */ private fetchAjax; /** * JSON nodes as jstree's `_append_json_data` takes them: a `{ d }` wrapper * (as ASP.NET sends) unwrapped, and a single node wrapped in an array. */ private asNodeList; /** * Replace a node's children with new data, as jstree's `_append_json_data` * (JSON, through the worker when there is one) or `_append_html_data` * (parsed markup, here and now), then `done`. */ private appendChildren; /** * jstree's `_append_json_data`: build `data` under `parentId` — in a Web * Worker made from `buildModel`'s source when `core.worker` allows and * workers exist, one load at a time, falling back to this thread when the * worker fails or the data cannot be sent to it — then `done`. */ private ingest; /** * jstree's `load_all(obj, callback)`: load every unloaded node below `obj` * (the root by default) together — so massload can batch them — and again * for whatever those loads reveal, then call back with the node and emit * `load_all`. Unlike jstree, a node that failed to load is not retried, * which would otherwise repeat forever. */ load_all(obj?: NodeRef, callback?: (node: TreeNode) => void): boolean | void; /** * Drop a node's descendants ahead of a reload, as jstree's `load_node` * does, emitting `changed` when any of them were selected. */ private dropDescendants; /** * jstree's `_load_nodes`: load every listed node that is unloaded and has * not failed — reloading, with `force`, the ones present at the start — * then call `done` once with the ids that ended up loaded. A node that a * parent's reload recreated loads only if it is unloaded. */ private loadNodes; private removeSubtree; static getInstance(element: HTMLElement): MDFolderTree | null; private mergeDefaults; /** * jstree's container flags, set as it initializes: `md-tree-rtl` when the * container computes to a right-to-left direction, and * `aria-multiselectable` while `core.multiple` allows more than one node. */ private applyContainerFlags; /** Plugin factories by the name a tree lists them under. */ private static readonly registry; /** * Register a plugin under the name trees list it by, replacing whatever * held that name. The built-ins register themselves this way * ([src/plugins/register.ts](src/plugins/register.ts)), so a consumer's own * plugin is built on exactly the same terms. */ static registerPlugin(name: string, factory: () => TreePlugin): void; /** The plugin this tree built under `name`, or null where it has none. */ getPlugin(name: string): T | null; private get checkboxPlugin(); private get searchPlugin(); private initPlugins; /** * @param options.onComplete Runs once the data is in the store. With a * `DataCallback` this is asynchronous, so callers that need to act on the * loaded tree must use it rather than the return of this method. * @param options.emitLifecycle Suppressed by `refresh()`, which emits its * own event; re-emitting `ready` would re-trigger plugins that restore state. */ private loadData; /** * jstree's initial node: a placeholder reading `get_string('Loading ...')`, * standing in until the root's nodes arrive, while the container reports * itself busy. */ private showRootLoading; /** The placeholder and the busy marks go as soon as the root has loaded. */ private clearRootLoading; /** * Materialize normalized data into the store beneath `parentId`. * * Runs in two passes so a node may name a parent that appears later in the * payload (jstree's flat format). Nested `children` arrays and flat `parent` * references are handled by the same code: a node's parent is whatever its * `parent` property says, defaulting to the enclosing `parentId`. */ private buildNodeTree; /** * Put what `buildModel` made into the tree: the nodes into the store, each * under its parent, the id counter advanced, the problems met reported, and * the nodes the data selects selected. */ private applyModel; private buildParentChain; /** * Rebuild derived ancestry (`parents`, `children_d`) for the whole tree. * * These were previously patched by hand at each mutation site, which drifted: * descendants kept stale ancestry after a move and `children_d` never held * anything deeper than direct children. A whole-tree pass is O(n) — the same * order as the re-render every structural change already performs. */ private reindex; /** * Refresh the `state.selected` mirror on every node from the authoritative * selection set. `TreeSelection` owns membership and enforces * `core.multiple`; the per-node flag is derived from it and must never be * written directly. */ private syncSelectionFlags; /** The node owning `target` when `target` is that node's anchor itself. */ private anchorNodeOf; /** Whether an activation originated on a checkbox icon rather than the label. */ private isCheckboxTarget; /** jstree's `_open_to`: open every collapsed ancestor so the node is visible. */ private openAncestors; /** The selection logic of jstree's `activate_node`, ported branch for branch. */ private applyActivation; /** * Resolve a node reference in any form jstree's `get_node` accepts. Order * follows jstree: an element's own id before its DOM position, an object's * `id`, then a plain id, or a '#'-prefixed id. Unlike jstree, a string * that is not an id is not tried as a CSS selector: that fallback is an * undocumented side effect of jstree's DOM branch, and it makes a lookup of * a missing id such as 'a' match every node's anchor element. Arrays are not references; array-capable methods iterate * them before resolving. */ private resolveNode; /** The id a reference resolves to — `'#'` for the root — or null. */ private resolveId; private lookupNode; /** * Resolve a parent id to its node, mapping the `'#'` sentinel to the * ordered root container. Returns null when the parent does not exist. */ private resolveParent; /** * Mint an id that is guaranteed not to collide with an existing node. * A monotonic counter is used rather than a timestamp, which repeats for * calls made within the same millisecond. */ private mintId; /** * True when re-parenting `id` under `parentId` would make the node an * ancestor of itself. */ private wouldCreateCycle; private getRootNodes; private createRootNode; private bindEvents; private emitChanged; /** * jstree's `model` event: nodes have entered the model and are about to be * rendered. The types plugin settles types and icons from it. */ private emitModel; /** * jstree's `expand_selected_onload`: open every ancestor of a selected * node, so the selection starts out visible. */ private openSelectedAncestors; /** * Record an error and surface it through the `core.error` callback. * Plugins report through it too. */ reportError(error: Record): void; /** * jstree's `check()`: validate a structural operation. Structural rules * come first — a node may not be moved or copied into itself or its own * descendant, nor moved to the position it already holds — then * `core.check_callback`, which may be a boolean, a function, or a map of * operation names to booleans. A refusal is recorded in `last_error()` in * jstree's shape and handed to `core.error`. */ check(chk: string, obj: NodeRef, par: NodeRef, pos?: number | string, more?: CheckMore): boolean; private invokeBeforeActivate; } /** * Main entry point — replaces `$(selector).jstree(...)` with `mdTree(selector, ...)`. * * Signatures: * - `mdTree(target)` — create with defaults or return existing instance * - `mdTree(target, config)` — create with config or return existing instance * - `mdTree(target, true)` — return existing instance (or undefined) * - `mdTree(target, 'method', ...args)` — call a method on the instance */ export declare function mdTree(target: string | HTMLElement, arg?: TreeConfig | string | boolean, ...rest: unknown[]): MDFolderTree | unknown | undefined; /** * Lightweight event bus that dispatches CustomEvents on a DOM element. * Supports namespaced events (e.g. "changed.MDFolderTree"), the namespace * being part of the type rather than a filter over it. */ export declare class TreeEventBus { private element; private handlers; constructor(element: HTMLElement); on(event: string, handler: EventHandler): void; off(event: string, handler: EventHandler): void; emit(event: string, detail: unknown): void; /** Remove all managed listeners. */ destroy(): void; } /** * Internal store for TreeNode objects, keyed by ID for O(1) lookup. */ export declare class TreeNodeStore { private nodes; set(id: string, node: TreeNode): void; get(id: string): TreeNode | null; has(id: string): boolean; delete(id: string): void; clear(): void; getAllIds(): string[]; getAll(): TreeNode[]; size(): number; } /** * DOM rendering engine. Produces md-tree-compatible class names so existing * CSS works without modification. * * All DOM construction uses `document.createElement` + `textContent` / * `setAttribute` — never `innerHTML`. */ export declare class TreeRenderer { private container; /** Node lookup for a child list, which the store already keys by id. */ private store; private plugins; private sanitizeAttrs; private computePositions; private themeName; private onError?; constructor(container: HTMLElement, store: TreeNodeStore, plugins?: TreePlugin[], sanitizeAttrs?: boolean, onError?: (error: Record) => void, computePositions?: boolean); /** * Run a plugin render hook. A throwing plugin must not abort the render and * leave the tree half-drawn, so failures are reported and skipped. */ private runHook; /** * Event-handler attributes execute consumer-supplied strings as script, so * they are stripped unless `core.sanitize_attrs` is explicitly disabled. * Other attributes are inert on the tags this renderer emits * (`li`, `a`, `i`, `span`, `ul`), and `href` is never taken from `a_attr`. */ private isUnsafeAttr; /** * Marks put on a node from outside the renderer, which nothing re-applies: * the cut marking on the node, and the focus ring and hover on its anchor. * * Each is tracked by node id -- the keyboard's focused id, the clipboard's * buffered nodes, the hovered anchor found by query -- so a mark restored * onto a new element still belongs to whoever set it. * `md-tree-context` is deliberately absent: the context menu holds the * anchor it marked and clears the mark through that reference, while its * items redraw the node before the menu closes, so a restored copy would * outlive the menu's ability to take it off. Search is absent too, the * plugin putting it back through `onNodeRender`, and the dnd marker sits on * the body rather than inside a node. */ private static readonly NODE_MARKS; private static readonly ANCHOR_MARKS; /** * The marks every node of a subtree carries, by id. A cascade redraws the * topmost ancestor, so a descendant's marks matter as much as the root's. */ private captureMarks; /** Put those marks back on the subtree that replaces it. */ private restoreMarks; /** Render the full tree from the root nodes. */ render(nodes: TreeNode[]): void; /** Re-render a single node and its children in-place. */ renderSingleNode(node: TreeNode): void; /** Add a space-separated class list, as jstree does for li_attr / a_attr. */ private addClasses; /** * Render one node. `index` and `total` are its place among its siblings, * which `aria-posinset` / `aria-setsize` report and `md-tree-last` uses. */ private renderNode; /** The theme class re-applied on every full render. */ setThemeName(name: string): void; setPlugins(plugins: TreePlugin[]): void; } /** * The set of selected node ids. * * Deliberately policy-free: `core.multiple` is not enforced here. As in * jstree, it constrains user interaction (see `MDFolderTree.activate_node`), * while the programmatic selection API may select any number of nodes. */ export declare class TreeSelection { private selected; /** * @param _multiple Ignored. Retained so existing callers still compile; * `core.multiple` is enforced on activation instead. */ constructor(_multiple?: boolean); select(id: string): string[]; deselect(id: string): string[]; selectAll(ids: string[]): string[]; deselectAll(): string[]; isSelected(id: string): boolean; getSelected(): string[]; /** @deprecated No-op; `core.multiple` is enforced on activation. */ setMultiple(_multiple: boolean): void; } /** * Keyboard navigation, and the virtual focus it moves. * * jstree gives the anchor itself the focus; here it is virtual -- the * container carries `aria-activedescendant` and the focused anchor carries * `md-tree-focused` -- so a keydown is presented to handlers as though it had * been delegated to that anchor, and runs with the tree as `this`, which is * what `core.keyboard` handlers are written against. * * It reaches its tree through the public API; the container listeners are * registered with the tree's own signal, so `destroy()` still takes them off. */ export declare class TreeKeyboard { private readonly tree; private focusedId; constructor(tree: MDFolderTree); /** * @param signal The tree's listener signal, so teardown stays in one place. * @param isDestroyed Guards a keystroke that arrives as the tree goes away. */ bind(signal: AbortSignal, isDestroyed: () => boolean): void; /** Move the virtual focus, marking the anchor and scrolling it into view. */ setFocused(id: string | null): void; private getFirstVisibleNodeId; private getLastVisibleNodeId; /** * The keydown as a jstree handler sees it. jstree delegates keydown to the * focused anchor, so `target` and `currentTarget` are that anchor -- handlers * conventionally call `this.get_node(e.currentTarget)` -- and, being a jQuery * event, it carries the native one as `originalEvent`. Focus here is * virtual, on the container, so the event is presented that way: its * properties read from the native event, and its methods act on it. */ private delegatedKeyEvent; /** * Resolve a keydown to a handler: jstree's defaults with `core.keyboard` * merged over them, read on every keystroke as jstree does. `false` * disables every shortcut; a null entry disables one. */ private keyboardHandlerFor; /** jstree 3.3's default shortcuts, ported to this tree's focus model. */ private defaultKeyboard; /** Arrow-key step: move to `target`, or to the first node when none is focused. */ private focusStep; /** jstree's enter / ctrl-space: a click on the focused node, keeping modifiers. */ private activateFocused; } /** * The theme a tree wears: its name and variant, the stylesheet behind * `themes.url`, and the dots / icons / stripes / ellipsis flags. * * It reaches its tree through the public API, save for the renderer's own * copy of the theme name, which is handed in as a setter so the renderer * stays private to the tree. */ export declare class TreeThemeController { private readonly tree; private readonly setRendererTheme; private name; private variant; constructor(tree: MDFolderTree, setRendererTheme: (name: string) => void); /** jstree's theme `init`: the theme, with `responsive`, and its variant. */ applyClasses(): void; /** * jstree's theme `loading`: the dots, icons, stripes and ellipsis flags, * applied through the show / hide methods so their events fire. */ applyFlags(): void; /** The classes this theme put on the container, taken off again. */ teardown(): void; /** * jstree's `set_theme(name, url)`: swap the theme's classes and, given a * URL -- or `true`, meaning `//style.css` -- inject that * stylesheet, each one only once per page. */ setTheme(name: string, url?: string | boolean): void; getTheme(): string; setThemeVariant(variant: string | false): void; getThemeVariant(): string | false; showStripes(): void; hideStripes(): void; toggleStripes(): void; showDots(): void; hideDots(): void; toggleDots(): void; showIcons(): void; hideIcons(): void; toggleIcons(): void; showEllipsis(): void; hideEllipsis(): void; toggleEllipsis(): void; /** Every display flag is one class and one event; only the sense differs. */ private flag; private has; /** The stylesheet behind `themes.url`, injected once. */ private loadStylesheet; } /** * Parse a flat or nested JSON array into normalized TreeNodeData[] — the * normalization the tree applies to every payload (see `buildModel`). */ export declare class JsonParser { private readonly generateId; private counter; /** * @param generateId Supplies ids for nodes that lack one; by default they * are `mdft_1`, `mdft_2`, and so on. */ constructor(generateId?: () => string); parse(data: TreeNodeData[]): TreeNodeData[]; } /** * Parse existing `
      /
    • ` HTML into TreeNodeData[], as jstree's * `_parse_model_from_html` does, under the names the migration codemod * produces (`jstree-*` → `md-tree-*`, `data-jstree` → `data-md-tree`): * * - `md-tree-open` on the `
    • ` opens it; `md-tree-closed` on an `
    • ` * without a child list makes it lazy (`children: true`). * - `md-tree-clicked` / `md-tree-disabled` on the anchor select / disable it. * - A rendered `.md-tree-themeicon` gives the icon: its `rel`, or false when * hidden. * - `data-*` attributes become `data`, converted as jQuery's `.data()` does, * with the `data-md-tree` payload under `data.jstree` — which, as in jstree, * overrides the state and icon read from the markup. */ export declare class HtmlParser { parse(container: HTMLElement): TreeNodeData[]; /** * Parse an HTML string as jstree's `_append_html_data` does: the items of * any top-level `
        `, otherwise every top-level element. The markup is * parsed in an inert document, so nothing in it loads or runs. */ parseFragment(html: string): TreeNodeData[]; private parseChildren; private parseLi; /** The data-md-tree payload (jstree's data-jstree), when it is a JSON object. */ private readPayload; /** * The element's data-* attributes, converted as jQuery's `.data()` does, * with the data-md-tree payload under `jstree`. */ private readData; private getAttributes; } /** * Types plugin, as jstree's: every node gets a configured type — an unknown * or missing type becomes 'default', and the root is always '#' — and a node * still showing the theme icon takes its type's icon, as its `li_attr` and * `a_attr` take the type's. This happens on the `model` event, before the * nodes render. * * A type's `max_children`, `valid_children` and `max_depth` join `check`, * refusing a create, move or copy that would break them. * * Config shape: * ``` * types: { * "default": { icon: "md-tree-folder" }, * "email": { icon: "md-tree-icon-email", max_children: 10 } * } * ``` * As in jstree, each type inherits any property it leaves unset from * `default`; the root type ('#') is left out of that merge. */ export declare class TypesPlugin implements TreePlugin { name: string; private tree; private api; private typeMap; private modelHandler; init(tree: TreePluginHost): void; destroy(): void; /** A type's rules, with unset properties filled from 'default'. */ rules(type: string): TypeConfig | undefined; /** A type's rules with jstree's `-1` defaults, as `get_rules` reports them. */ rulesWithDefaults(type: string): TypeConfig; /** The icon for a type, falling back to 'default'. Kept for compatibility. */ getIconForType(type: string): string | false; /** * jstree's types `check`: a create, move or copy must respect the target * parent's `max_children` and `valid_children`, and the depth the moved * subtree would reach must fit every ancestor's `max_depth`. As in jstree, * a move of a node already among the parent's children — a reorder — skips * all three, while a copy into that same parent does not. */ onCheck(chk: string, node: TreeNode | TreeNodeData | null, parent: TreeNode | null, _pos: unknown, _more: CheckMore): true | { id: string; reason: string; }; /** jstree's model handler: settle each node's type, then its icon and attributes. */ private applyTypes; /** * jstree's attribute merge: the type never supplies an `id`, a class list is * prepended to the node's own, an anchor's placeholder `href` ('#') gives * way to the type's, and anything the node does not set is copied over. */ private applyAttrs; /** The root's type, which jstree sets at init and after every model event. */ private typeRoot; } /** * Renders checkbox icons before the anchor and manages tri-state * (undetermined) for parent nodes. */ export declare class CheckboxPlugin implements TreePlugin { name: string; private tree; private config; private cascadeOnEvent; private cascadeOffEvent; private cascadeOnHandler; private cascadeOffHandler; private loadingHandler; private modelHandler; private deleteHandler; private moveHandler; init(tree: TreePluginHost): void; destroy(): void; onNodeRender(node: TreeNode, element: HTMLElement): void; /** * Re-derive `nodeId`'s checked state from its children, then its * ancestors', and repaint. Cascading normally happens automatically; this * remains for callers that mutate children directly. */ updateUndetermined(nodeId: string): void; /** Whether checking a node also selects it (jstree's `tie_selection`). */ private get tiesSelection(); /** * jstree's `check_node`. While tied to selection it *is* `select_node` * (without opening ancestors); otherwise it sets the checked state and * emits `check_node`. Cascading happens in the event listener either way. */ check_node(id: string, event?: ActivationEvent): void; /** jstree's `uncheck_node`; the mirror image of `check_node`. */ uncheck_node(id: string, event?: ActivationEvent): void; /** jstree's `check_all`: `select_all` while tied, otherwise every node. */ check_all(): void; /** jstree's `uncheck_all`: `deselect_all` while tied. */ uncheck_all(): void; is_checked(id: string): boolean; get_checked(): string[]; get_top_checked(): string[]; get_bottom_checked(): string[]; get_undetermined(): string[]; is_undetermined(id: string): boolean; /** jstree's `show_checkboxes`: a container class, so redraws keep it. */ show_checkboxes(): void; /** jstree's `hide_checkboxes`. */ hide_checkboxes(): void; toggle_checkboxes(): void; /** jstree's `disable_checkbox`: a flag on the node, drawn on every render. */ disable_checkbox(id: string): void; /** jstree's `enable_checkbox`. */ enable_checkbox(id: string): void; /** jstree's effective cascade: `three_state` means up+down+undetermined. */ private get cascadeMode(); /** Whether a node is checked — while tied to selection, selected. */ private isOn; /** * Partially checked, as jstree's get_undetermined reports it (only with * 'undetermined'): not checked itself, with a checked descendant — or with * an unloaded descendant, or itself unloaded, that the server marked * `state.undetermined`. */ private isUndetermined; private serverUndetermined; /** * Listener for check / select (and uncheck / deselect): cascade as the * configured directions say, then repaint. */ private cascade; /** * jstree's `_cascade_new_checked_state`: the ids in `id`'s subtree that end * up checked when it is checked (true) or unchecked (false). A node that * cascade_to_disabled / cascade_to_hidden exclude keeps its own state and * its checked descendants; any other node ends up checked only when being * checked and every child does too — so a partial node ends unchecked. */ private newCheckedState; /** jstree's cascade up on check: each ancestor whose children are all checked becomes checked. */ private checkUpward; /** jstree's cascade as nodes enter the model (load, create, copy). */ private cascadeLoaded; /** * jstree's cascade up after a node leaves `parentId` (delete, or the old * parent of a move): each unchecked ancestor whose remaining children are * all checked becomes checked. Returns whether anything changed. */ private recheckUp; /** * jstree's cascade up on a move's new parent: each ancestor follows its * children — checked when all are, unchecked when not. Returns whether * anything changed. */ private resyncUp; /** * Set checked state without emitting events. While tied, checked *is* * selected, so membership goes through the tree's silent selection path. */ private setChecked; /** Repaint the root-level subtree containing `node`, which spans all a cascade touched. */ private repaint; } /** * Search plugin, as jstree's. * * `search(str, skip_async, show_only_matches, inside, append, * show_only_matches_children)` matches the descendants of `inside` (or of the * root) that have text and are not hidden — with `search_leaves_only`, only * loaded childless ones — through `search_callback`, called with the tree as * `this`, or jstree's matcher (`fuzzy` for approximate matching). Every * match's ancestors are opened, and `clear_search` closes the ones it opened * unless `close_opened_onclear` is false. With `show_only_matches` * everything else is hidden, and with `show_only_matches_children` the * matches' descendants stay shown. `search.ajax` may name nodes to load * before searching. `search` and `clear_search` are emitted with jstree's * payloads. * * Matches are held on the plugin and re-applied through `onNodeRender`, so a * full render cannot erase the highlighting. */ export declare class SearchPlugin implements TreePlugin { name: string; private tree; private api; private config; private str; private res; private matched; private opened; private som; private smc; private hidden; private request; init(tree: TreePluginHost): void; destroy(): void; onNodeRender(node: TreeNode, element: HTMLElement): void; /** jstree's `search`; returns the ids this call matched. */ search(str: string | false, skipAsync?: boolean, showOnlyMatches?: boolean, inside?: NodeRef | null, append?: boolean, showOnlyMatchesChildren?: boolean): string[]; /** jstree's `clear_search`. */ clearSearch(): void; /** The descendants of `insideId`, or of the root, in tree order. */ private candidates; /** * jstree's show_only_matches: hide everything, then show the visible * matches, their ancestors and — with show_only_matches_children — their * visible descendants. */ private showOnlyMatches; private elements; } /** * ChangedPlugin - adds `changed.selected` and `changed.deselected` diff arrays * to the `changed.MDFolderTree` event data, matching jstree's "changed" plugin behavior. * * The core already emits `changed.MDFolderTree` with `selected` and `old_selection`. * This plugin is a no-op since the core now computes the diff inline. * It exists purely for API compatibility (consumers can include "changed" in plugins array). */ export declare class ChangedPlugin implements TreePlugin { readonly name = "changed"; init(_tree: TreePluginHost): void; destroy(): void; } /** * ConditionalSelectPlugin - allows preventing node selection via a callback. * Mirrors jstree's "conditionalselect" plugin. * * Config: `conditionalselect: (node, event) => boolean` * Return false from the callback to prevent the node from being selected. * As in jstree, it is called with the tree as `this`, so it may consult the * tree (`this.get_type(node)`) to decide. */ export declare class ConditionalSelectPlugin implements TreePlugin { readonly name = "conditionalselect"; private tree; init(tree: TreePluginHost): void; destroy(): void; onBeforeActivate(node: TreeNode, event?: Event): boolean; } /** * Wholerow plugin, as jstree's: a strip behind each node makes the whole row * the target. A click, double-click or right-click on the strip is forwarded * to that node's anchor — so clicking the blank part of a row selects it, * ctrl-click extends, and a right-click opens the node's menu — as is a click * on a leaf's open/close icon, which has nothing to toggle. Hovering the strip * or an icon hovers the node. * * The strip carries `md-tree-wholerow-clicked` while the node is selected and * `md-tree-wholerow-hovered` while it is hovered, and the theme's dots are * hidden while the plugin is on. */ export declare class WholerowPlugin implements TreePlugin { readonly name = "wholerow"; private tree; private api; private hovered; private clickHandler; private dblclickHandler; private contextHandler; private overHandler; private leaveHandler; private markHandler; private hoverHandler; private dehoverHandler; init(tree: TreePluginHost): void; destroy(): void; /** * jstree hides the dots on `ready`; our theme flags are applied after the * plugins start, so they are hidden as the tree draws instead — once, since * hide_dots emits. */ onBeforeRender(nodes: TreeNode[]): TreeNode[]; onNodeRender(node: TreeNode, element: HTMLElement): void; /** A click on the strip, or on a leaf's open/close icon, acts on the anchor. */ private onClick; /** As in jstree, the menu is only forwarded when the contextmenu plugin is on. */ private onContextMenu; private forwardFromStrip; /** Re-dispatch the event on the node's anchor, carrying the modifiers and the pointer. */ private forward; /** Hovering the strip, or any of the node's icons, hovers the node itself. */ private onOver; private onLeave; /** Mark the strips of the selected nodes, and only those. */ private refreshMarks; /** Only the row losing the mark and the one taking it are touched. */ private setHovered; } /** * SortPlugin - automatically sorts sibling nodes according to a comparator function. * Mirrors jstree's "sort" plugin. * * Config: `sort: (a: string, b: string) => number`, called with two node ids * and the tree as `this`. Defaults to jstree's case-sensitive text comparison. * * Ordering is applied at render time (`onBeforeRender`) and written back to * the model, so `node.children` and the rendered DOM cannot disagree. Reacting * to `create_node` / `move_node` instead would sort *after* the render that * those operations already performed. */ export declare class SortPlugin implements TreePlugin { readonly name = "sort"; private tree; private resortHandler; init(tree: TreePluginHost): void; destroy(): void; onBeforeRender(nodes: TreeNode[]): TreeNode[]; /** * jstree's `sort(obj, deep)`: order a node's children in the model and, * when `deep`, every descendant's as well. Like jstree it does not redraw. */ sortNode(id: string, deep?: boolean): void; /** * The comparator, over node ids with the tree as `this`, as jstree calls * it. The default is jstree's: a plain, case-sensitive text comparison. */ private getComparator; private sortIds; } /** * Unique plugin, as jstree's. It joins `check` to refuse a name a sibling * already has — `unique_01` for rename, `unique_02` copy, `unique_03` move (a * reorder within the parent is allowed) and `unique_04` create — comparing * case-insensitively unless `case_sensitive`, and ignoring surrounding * whitespace with `trim_whitespace`. It also names a node created without * text: `New node`, then `duplicate(name, counter)` from 2. */ export declare class UniquePlugin implements TreePlugin { readonly name = "unique"; private tree; init(tree: TreePluginHost): void; destroy(): void; /** jstree's unique `check`. */ onCheck(chk: string, node: TreeNode | TreeNodeData | null, parent: TreeNode | null, pos: unknown, more: CheckMore): true | { id: string; reason: string; }; /** * jstree's naming of a node created without text: `base`, then * `duplicate(base, counter)` from 2 until it is free among `par`'s children. */ newNodeName(par: TreeNode, base: string): string; private siblingNames; /** jstree's comparison form: lowercased unless case_sensitive, trimmed with trim_whitespace. */ private normalize; /** * Check if a name would be unique among siblings. * Called externally by the tree when validating rename/move operations. */ isUnique(parentId: string, name: string, excludeId?: string): boolean; /** * Generate a unique name using the duplicate function. */ getUniqueName(parentId: string, name: string, excludeId?: string): string; private getConfig; } /** * State plugin, as jstree's. It saves `get_state()` — as * `{ state, ttl, sec }` under `state.key` ('jstree' by default) — 100ms after * any of `state.events`, and restores it through `set_state` once the tree * is ready, emitting `restore_state`; saving starts after that, with * `state_ready`. `core.loaded` is kept only with `preserve_loaded`; `filter` * (called with the tree as `this`) adjusts the state being restored; a state * older than its `ttl` is ignored. States saved by earlier releases — * `{ opened, selected }` with `expires` — still restore. */ export declare class StatePlugin implements TreePlugin { readonly name = "state"; private tree; private api; private timer; private saveHandler; private readyHandler; private restoredHandler; private saving; init(tree: TreePluginHost): void; destroy(): void; /** jstree's `save_state`. */ save_state(): void; /** jstree's `restore_state`: true when a state was found and applied. */ restore_state(): boolean; /** jstree's `clear_state`. */ clear_state(): void; private startSaving; /** Whether a stored state has anything set_state would apply. */ private hasContent; private config; private events; } /** * Massload plugin, as jstree's. `massload(ids, callback)` — called with the * tree as `this` — fetches the children of several nodes in one call, * answering with a map of id to children (JSON, or an HTML string). The tree * asks it whenever it loads several nodes together — load_node with an array, * refresh_node, load_all — and each node then loads from the answer, or * through core.data when the answer leaves it out. A single load_node goes * straight to core.data, as in jstree. */ export declare class MassloadPlugin implements TreePlugin { readonly name = "massload"; private tree; private answers; init(tree: TreePluginHost): void; destroy(): void; /** * Fetch `ids` in one call — through the massload function, or its ajax * config (`url` / `data` may be functions of the ids) — then `proceed`; at * once without massload or ids, and without answers if the request fails. */ prefetch(ids: string[], proceed: () => void): void; /** The prefetched children of `id`, handed out once. */ take(id: string): TreeNodeData[] | string | undefined; } /** * Context menu, as jstree's contextmenu plugin with its `$.vakata.context` * menu. * * Right-clicking a node (or pressing it for 750ms on touch) activates it, * with `select_node`, and shows the menu — at the node with `show_at_node` * (the default), otherwise at the pointer — built from `items`: an object, or * `items(node, callback)`, called with the tree as `this`, answering at once * or through the callback. The menu is a `ul.vakata-context` of jstree's * markup; an item's `action` receives `{ item, reference, element, position }` * with the node's anchor as `reference`. A disabled item does nothing, and an * action returning false keeps the menu open. The menu is navigated with the * arrows, Enter / Space and Escape, and items' `shortcut` keys; it closes on a * click outside it or on a node. `show_contextmenu` fires on the tree, and * `context_show` / `context_hide` on the document, as jstree fires them. */ export declare class ContextMenuPlugin implements TreePlugin { readonly name = "contextmenu"; private tree; private api; private menu; private reference; private items; private position; private lastCtrl; private touchTimer; private touchStart; private contextHandler; private clickHandler; private pointerDownHandler; private pointerMoveHandler; private pointerEndHandler; private dismissHandler; private escapeHandler; init(tree: TreePluginHost): void; destroy(): void; /** * jstree's `show_contextmenu(obj, x, y, e)`: false for a missing node or the * root. */ show_contextmenu(obj: NodeRef, x?: number, y?: number, e?: Event): boolean | void; /** `$.vakata.context.hide()`: close the menu. */ hide(): void; private onContextMenu; /** A click on a node closes the menu, unless it is the ctrl+click that opened it. */ private onClick; /** jstree opens the menu on a 750ms touch press, cancelled by moving 10px. */ private onPointerDown; private onPointerMove; private clearTouch; /** jstree's `_show_contextmenu` with `$.vakata.context.show`. */ private showMenu; /** jstree's `$.vakata.context._parse`: draw the items into `ul`; false if there were none. */ private fill; private separator; private isDisabled; /** jstree's `_execute`: run an item's action unless it is disabled; false if none ran. */ private execute; private onMenuClick; private onMenuHover; /** Mark `li` (and the items leading to it) hovered, and show its submenu. */ private hover; /** jstree's menu keys: Enter / Space, the arrows, Escape, and item shortcuts. */ private onMenuKey; private itemData; private eventDetail; private anchorOf; /** jstree's default items: Create, Rename, Delete and the Edit submenu (cut, copy, paste). */ private defaultItems; private getConfig; } /** * Drag and drop, as jstree's dnd plugin — on pointer events, so mouse, pen * and touch drag alike. * * A drag starts on a node's anchor (anywhere on the node with * `large_drag_target`) with the primary button, or a touch as `touch` * allows. Dragging a selected node drags the top selected nodes (with * `drag_selection`, the default); `is_draggable(nodes, e)` may refuse. Once * the pointer moves past jstree's threshold, a helper follows it and * `dnd_start` is emitted with jstree's payload; the click that ends a drag is * swallowed, and Escape cancels. * * With `use_html5`, the browser's native drag and drop drives the drag * instead, as jstree's HTML5 backend: anchors (nodes, with * large_drag_target) are `draggable`, and dragstart, dragover and drop run the * same checks and drop rules. The browser draws the dragged image, so there * is no helper. */ export declare class DndPlugin implements TreePlugin { readonly name = "dnd"; private tree; private api; private dragging; private dragNode; private dragIds; private dragElement; private dragTarget; private dragText; private isTouch; private dragHelper; private marker; private dropTarget; private openTimeout; private startX; private startY; private swallow; private lastError; private hoverTarget; private lastPointer; private copyKey; private scroll; private scrollTimer; /** jstree's HTML5 backend, where elements can be draggable. */ private html5; private pointerDownHandler; private pointerMoveHandler; private pointerUpHandler; private pointerCancelHandler; private keyUpHandler; private keyDownHandler; private dragStartHandler; private dragOverHandler; private dropHandler; private dragEndHandler; private acceptHandler; init(tree: TreePluginHost): void; destroy(): void; /** * jstree's listeners while a drag is down. A native drag's end is heard on * the element it began on, which a redraw may have taken out of the page. */ private attachDocumentListeners; private detachDocumentListeners; private getConfig; /** jstree's draggable nodes under use_html5: the anchor, or with large_drag_target the node. */ onNodeRender(_node: TreeNode, li: HTMLElement): void; private onPointerDown; /** * jstree's dragstart (use_html5): the checks a pointer drag makes, then the * drag starts at once. */ private onDragStart; /** * The checks jstree makes as a drag begins, on either backend: on a node's * anchor (anywhere on the node with large_drag_target), by touch as `touch` * allows, dragging the top selected nodes for a selected node * (drag_selection), unless is_draggable refuses. Records the drag and * returns true when one may start. */ private prepare; private onPointerMove; private onPointerUp; /** * jstree's dragover (use_html5): a move, the element under the pointer * being the event's target. A drop the target may take is accepted, with * the copy or move effect. */ private onDragOver; /** jstree's drop (use_html5): as a pointer release. */ private onDrop; /** A native drag that ends without a drop is abandoned, as Escape abandons a pointer drag. */ private onDragEnd; /** jstree's dnd_stop: drop where the last move said, then say so. */ private drop; /** A cancelled pointer (gesture stolen, window blurred) abandons the drag. */ private onPointerCancel; /** jstree cancels a drag on Escape, without a drop or dnd_stop. */ private onKeyUp; /** As jstree, pressing or releasing ctrl / meta mid-drag re-evaluates the drop. */ private onModifier; /** jstree's dnd payload: `{ data: { jstree, origin, obj, nodes }, element, helper, event }`. */ private eventData; private startDrag; /** * jstree's helper, under the codemod's names: `#vakata-dnd` holding * `#md-tree-dnd` with the status icon, the text and the copy sign. */ private createHelper; private swallowClick; private releaseClick; private cancelDrag; /** Whether the drop copies: always_copy, or ctrl / meta with `copy` (on by default). */ private isCopy; /** The tree an element belongs to, as jstree's `$.jstree.reference`. */ private instanceAt; /** The tree under the pointer, if it takes drops (it has the dnd plugin). */ private treeAt; /** * jstree's dnd_move handler: find where the dragged nodes would drop — in * this tree or another — and show it through the marker, the helper's * status icon and copy sign, and the parent the drop goes into. The target * tree's own dnd settings apply there; the copy settings are this tree's. * `target` is the element under the pointer: by default, the one at its * coordinates, as a captured pointer's events target where the drag began. */ private updateDropTarget; /** * Over an anchor: the pointer's third orders before ('b'), inside ('i') and * after ('a'), and the first that every dragged node may take wins. */ private dropAt; private showMarker; private hideMarker; /** The helper's status icon: ok over a valid target, er otherwise. */ private setStatus; private setCopySign; /** jstree marks the node a drop goes into as `jstree-dnd-parent`. */ private markParent; private clearParentMark; /** * jstree's dnd_stop handler: move (or copy) the dragged nodes where the last * move said — into another tree too, with this tree as the origin — or * report why nothing may be dropped. Returns what earlier releases * reported in dnd_stop. */ private executeDrop; /** * jstree's drag auto-scroll: within 20px of the edge of the nearest * scrollable ancestor of the element under the pointer — or else of the * page — scroll it 10px every 100ms. */ private autoScroll; private scrollStep; private stopScrolling; } export {};