carbon-components-svelte
Version:
Svelte implementation of the Carbon Design System
241 lines (215 loc) • 6.95 kB
TypeScript
import { SvelteComponentTyped } from "svelte";
import type { SvelteHTMLElements } from "svelte/elements";
export type TreeNode<Id = (string|number)> = {
id: Id;
text: any;
icon?: any;
/** Whether the node is disabled */
disabled?: boolean;
/** Optional URL the node links to */
href?: string;
/** Optional link target (e.g., "_blank") */
target?: string;
nodes?: TreeNode<Id>[];
};
export type ShowNodeOptions = {
/** Whether to expand the node and its ancestors (default: true) */
expand?: boolean;
/** Whether to select the node (default: true) */
select?: boolean;
/** Whether to focus the node (default: true) */
focus?: boolean;
};
export type TreeViewExpandedChange<Id = (string|number)> = {
/** The full set of expanded node ids after the change */
expandedIds: ReadonlyArray<Id>;
/** Node ids expanded since the previous change */
added: Array<Id>;
/** Node ids collapsed since the previous change */
removed: Array<Id>;
};
export type TreeViewSelectionChange<Id = (string|number)> = {
/** The full set of selected node ids after the change */
selectedIds: ReadonlyArray<Id>;
/** Node ids selected since the previous change */
added: Array<Id>;
/** Node ids deselected since the previous change */
removed: Array<Id>;
};
export type CarbonTreeViewContext<Node extends TreeNode<any> = TreeNode<any>> = {
treeId: any;
activeNodeId: import("svelte/store").Writable<Node["id"]>;
selectedNodeIds: import("svelte/store").Writable<ReadonlyArray<Node["id"]>>;
expandedNodeIds: import("svelte/store").Writable<ReadonlyArray<Node["id"]>>;
selectedIdsSetStore: import("svelte/store").Writable<Set<Node["id"]>>;
expandedIdsSetStore: import("svelte/store").Writable<Set<Node["id"]>>;
multiselectStore: import("svelte/store").Writable<boolean>;
clickNode: (node: Node, event?: Event) => void;
selectNode: (node: Node) => void;
expandNode: (node: Node, expanded: boolean) => void;
focusNode: (node: Node) => void;
toggleNode: (node: Node) => void;
};
type $RestProps = SvelteHTMLElements["ul"];
type $Props<Node extends TreeNode<any> = TreeNode<any>> = {
/**
* Provide an array of nodes to render.
* @default []
*/
nodes?: ReadonlyArray<Node>;
/**
* Set the current active node id.
* Only one node can be active.
* @default ""
*/
activeId?: Node["id"];
/**
* Set the node ids to be selected.
* @default []
*/
selectedIds?: ReadonlyArray<Node["id"]>;
/**
* Set the node ids to be expanded.
* @default []
*/
expandedIds?: ReadonlyArray<Node["id"]>;
/**
* Specify the TreeView size.
* @default "default"
*/
size?: "default" | "compact";
/**
* Specify the label text
* @default ""
*/
labelText?: string;
/**
* Set to `true` to visually hide the label text
* @default false
*/
hideLabel?: boolean;
/**
* Set to `true` to automatically collapse sibling nodes when expanding a node.
* When enabled, only one node at each level can be expanded at a time.
* @default false
*/
autoCollapse?: boolean;
/**
* Set to `true` to enable multi-select mode.
* Supports Ctrl/Cmd+Click (toggle) and Shift+Click (range select).
* @default false
*/
multiselect?: boolean;
/**
* When `multiselect` is true, `multiselectMode` controls how many nodes a selection gesture includes:
* - `'node'`: only the clicked/active node (default)
* - `'shallow'`: the node plus its direct non-disabled children
* - `'deep'`: the node plus all non-disabled descendants
* @default "node"
*/
multiselectMode?: 'node' | 'shallow' | 'deep';
labelChildren?: (this: void) => void;
children?: (this: void, ...args: [{
node: Node & {
expanded: boolean;
leaf: boolean;
selected: boolean;
}
}]) => void;
[key: `data-${string}`]: unknown;
};
export type TreeViewProps<Node extends TreeNode<any> = TreeNode<any>> = Omit<$RestProps, keyof $Props<Node>> & $Props<Node>;
export default class TreeView<Node extends TreeNode<any> = TreeNode<any>> extends SvelteComponentTyped<
TreeViewProps<Node>,
{
focus: CustomEvent<Node & {
expanded: boolean;
leaf: boolean;
selected: boolean
}>;
keydown: WindowEventMap["keydown"];
select: CustomEvent<Node & {
expanded: boolean;
leaf: boolean;
selected: boolean
}>;
"select:change": CustomEvent<TreeViewSelectionChange<Node["id"]>>;
toggle: CustomEvent<Node & {
expanded: boolean;
leaf: boolean;
selected: boolean
}>;
"toggle:change": CustomEvent<TreeViewExpandedChange<Node["id"]>>;
},
{
default: {
node: Node & {
expanded: boolean;
leaf: boolean;
selected: boolean;
}
};
labelChildren: Record<string, never>;
}
> {
/**
* Programmatically expand all nodes
* @example
* ```svelte
* <TreeView bind:this={treeView} {nodes} />
* <button on:click={() => treeView.expandAll()}>Expand All</button>
* ```
*/
expandAll: () => void;
/**
* Programmatically collapse all nodes
* @example
* ```svelte
* <TreeView bind:this={treeView} {nodes} />
* <button on:click={() => treeView.collapseAll()}>Collapse All</button>
* ```
*/
collapseAll: () => void;
/**
* Programmatically expand a subset of nodes.
* Expands all nodes if no argument is provided.
* Filter function should return `true` for nodes to expand. If not provided, expands all nodes.
* @example
* ```svelte
* <TreeView bind:this={treeView} {nodes} />
* <button on:click={() => treeView.expandNodes((node) => node.id.startsWith('folder-'))}>
* Expand Folders
* </button>
* ```
*/
expandNodes: (filterNode?: (node: Node) => boolean) => void;
/**
* Programmatically collapse a subset of nodes.
* Collapses all nodes if no argument is provided.
* Filter function should return `true` for nodes to collapse. If not provided, collapses all nodes.
* @example
* ```svelte
* <TreeView bind:this={treeView} {nodes} />
* <button on:click={() => treeView.collapseNodes((node) => node.id.startsWith('folder-'))}>
* Collapse Folders
* </button>
* ```
*/
collapseNodes: (filterNode?: (node: Node) => boolean) => void;
/**
* Programmatically show a node by `id`.
* By default, the matching node will be expanded, selected, and focused.
* Use the options parameter to customize this behavior.
* @example
* ```svelte
* <TreeView bind:this={treeView} {nodes} />
* <button on:click={() => treeView.showNode('node-123')}>
* Show Node
* </button>
* <button on:click={() => treeView.showNode('node-123', { expand: false, focus: false })}>
* Show Node (No Expand/Focus)
* </button>
* ```
*/
showNode: (id: Node["id"], options?: ShowNodeOptions) => void;
}