Launch Week Day 5: Introducing Reachability for PHP.Learn More
Socket
Book a DemoSign in
Socket

@zag-js/tree-view

Package Overview
Dependencies
Maintainers
1
Versions
463
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@zag-js/tree-view - npm Package Compare versions

Comparing version
0.70.0
to
0.71.0
+64
-100
dist/index.js

@@ -1,32 +0,11 @@

"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
'use strict';
// src/index.ts
var src_exports = {};
__export(src_exports, {
anatomy: () => anatomy,
connect: () => connect,
machine: () => machine
});
module.exports = __toCommonJS(src_exports);
var anatomy$1 = require('@zag-js/anatomy');
var domEvent = require('@zag-js/dom-event');
var domQuery = require('@zag-js/dom-query');
var core = require('@zag-js/core');
var utils = require('@zag-js/utils');
// src/tree-view.anatomy.ts
var import_anatomy = require("@zag-js/anatomy");
var anatomy = (0, import_anatomy.createAnatomy)("tree-view").parts(
var anatomy = anatomy$1.createAnatomy("tree-view").parts(
"root",

@@ -46,10 +25,3 @@ "label",

var parts = anatomy.build();
// src/tree-view.connect.ts
var import_dom_event = require("@zag-js/dom-event");
var import_dom_query2 = require("@zag-js/dom-query");
// src/tree-view.dom.ts
var import_dom_query = require("@zag-js/dom-query");
var dom = (0, import_dom_query.createScope)({
var dom = domQuery.createScope({
getRootId: (ctx) => ctx.ids?.root ?? `tree-root:${ctx.id}`,

@@ -59,3 +31,3 @@ getLabelId: (ctx) => ctx.ids?.label ?? `tree-label:${ctx.id}`,

getNodeId(node) {
if (!(0, import_dom_query.isHTMLElement)(node)) return null;
if (!domQuery.isHTMLElement(node)) return null;
return node.dataset.branch ?? node.dataset.item ?? null;

@@ -66,3 +38,3 @@ },

if (node?.dataset.part === "branch") {
return (0, import_dom_query.query)(node, "[data-part=branch-control]");
return domQuery.query(node, "[data-part=branch-control]");
}

@@ -76,11 +48,11 @@ return node;

const selector = `[role=treeitem][data-branch="${id}"]`;
return (0, import_dom_query.query)(dom.getTreeEl(ctx), selector);
return domQuery.query(dom.getTreeEl(ctx), selector);
},
getItemEl(ctx, id) {
const selector = `[role=treeitem][data-item="${id}"]`;
return (0, import_dom_query.query)(dom.getTreeEl(ctx), selector);
return domQuery.query(dom.getTreeEl(ctx), selector);
},
getBranchControlEl(ctx, id) {
const selector = "[data-part=branch-control]";
return (0, import_dom_query.query)(dom.getBranchEl(ctx, id), selector);
return domQuery.query(dom.getBranchEl(ctx, id), selector);
},

@@ -92,3 +64,3 @@ getFocusedEl(ctx) {

focusNode(node, options) {
if ((0, import_dom_query.isHTMLElement)(node)) node.focus(options);
if (domQuery.isHTMLElement(node)) node.focus(options);
},

@@ -105,3 +77,3 @@ getNodeDepth(node) {

acceptNode(node) {
if (skipHidden && (0, import_dom_query.isHiddenElement)(node)) {
if (skipHidden && domQuery.isHiddenElement(node)) {
return NodeFilter.FILTER_REJECT;

@@ -124,6 +96,6 @@ }

while (node) {
if ((0, import_dom_query.isHTMLElement)(node)) elements.push(node);
if (domQuery.isHTMLElement(node)) elements.push(node);
node = walker.nextNode();
}
return (0, import_dom_query.getByTypeahead)(elements, {
return domQuery.getByTypeahead(elements, {
state: ctx.typeaheadState,

@@ -140,3 +112,3 @@ key,

while (node) {
if ((0, import_dom_query.isHTMLElement)(node)) {
if (domQuery.isHTMLElement(node)) {
nodes.push(node);

@@ -150,3 +122,3 @@ }

if (depth === -1) return [];
return (0, import_dom_query.queryAll)(dom.getTreeEl(ctx), `[role=treeitem][data-part=branch][data-depth="${depth}"]`);
return domQuery.queryAll(dom.getTreeEl(ctx), `[role=treeitem][data-part=branch][data-depth="${depth}"]`);
},

@@ -277,5 +249,5 @@ getNodesInRange(nodes, startNode, endNode) {

if (event.defaultPrevented) return;
if ((0, import_dom_query2.isComposingEvent)(event)) return;
const target = (0, import_dom_query2.getEventTarget)(event);
if ((0, import_dom_query2.isEditableElement)(target)) return;
if (domQuery.isComposingEvent(event)) return;
const target = domQuery.getEventTarget(event);
if (domQuery.isEditableElement(target)) return;
const node = target?.closest("[role=treeitem]");

@@ -291,3 +263,3 @@ if (!node) return;

ArrowDown(event2) {
if ((0, import_dom_event.isModifierKey)(event2)) return;
if (domEvent.isModifierKey(event2)) return;
event2.preventDefault();

@@ -297,3 +269,3 @@ send({ type: "ITEM.ARROW_DOWN", id: nodeId, shiftKey: event2.shiftKey });

ArrowUp(event2) {
if ((0, import_dom_event.isModifierKey)(event2)) return;
if (domEvent.isModifierKey(event2)) return;
event2.preventDefault();

@@ -303,3 +275,3 @@ send({ type: "ITEM.ARROW_UP", id: nodeId, shiftKey: event2.shiftKey });

ArrowLeft(event2) {
if ((0, import_dom_event.isModifierKey)(event2) || node.dataset.disabled) return;
if (domEvent.isModifierKey(event2) || node.dataset.disabled) return;
event2.preventDefault();

@@ -314,3 +286,3 @@ send({ type: isBranchNode ? "BRANCH.ARROW_LEFT" : "ITEM.ARROW_LEFT", id: nodeId });

Home(event2) {
if ((0, import_dom_event.isModifierKey)(event2)) return;
if (domEvent.isModifierKey(event2)) return;
event2.preventDefault();

@@ -320,3 +292,3 @@ send({ type: "ITEM.HOME", id: nodeId, shiftKey: event2.shiftKey });

End(event2) {
if ((0, import_dom_event.isModifierKey)(event2)) return;
if (domEvent.isModifierKey(event2)) return;
event2.preventDefault();

@@ -350,3 +322,3 @@ send({ type: "ITEM.END", id: nodeId, shiftKey: event2.shiftKey });

};
const key = (0, import_dom_event.getEventKey)(event, state.context);
const key = domEvent.getEventKey(event, state.context);
const exec = keyMap[key];

@@ -358,3 +330,3 @@ if (exec) {

if (!state.context.typeahead) return;
const isValidTypeahead = event.key.length === 1 && !(0, import_dom_event.isModifierKey)(event);
const isValidTypeahead = event.key.length === 1 && !domEvent.isModifierKey(event);
if (!isValidTypeahead) return;

@@ -365,3 +337,3 @@ send({ type: "TREE.TYPEAHEAD", key: event.key, id: nodeId });

onBlur(event) {
if ((0, import_dom_query2.contains)(event.currentTarget, event.relatedTarget)) return;
if (domQuery.contains(event.currentTarget, event.relatedTarget)) return;
send({ type: "TREE.BLUR" });

@@ -380,9 +352,9 @@ }

tabIndex: itemState.focused ? 0 : -1,
"data-focus": (0, import_dom_query2.dataAttr)(itemState.focused),
"data-focus": domQuery.dataAttr(itemState.focused),
role: "treeitem",
"aria-current": itemState.selected ? "true" : void 0,
"aria-selected": itemState.disabled ? void 0 : itemState.selected,
"data-selected": (0, import_dom_query2.dataAttr)(itemState.selected),
"data-selected": domQuery.dataAttr(itemState.selected),
"aria-disabled": itemState.disabled,
"data-disabled": (0, import_dom_query2.dataAttr)(itemState.disabled),
"data-disabled": domQuery.dataAttr(itemState.disabled),
"aria-level": props.depth,

@@ -411,5 +383,5 @@ "data-depth": props.depth,

...parts.itemText.attrs,
"data-disabled": (0, import_dom_query2.dataAttr)(itemState.disabled),
"data-selected": (0, import_dom_query2.dataAttr)(itemState.selected),
"data-focus": (0, import_dom_query2.dataAttr)(itemState.focused)
"data-disabled": domQuery.dataAttr(itemState.disabled),
"data-selected": domQuery.dataAttr(itemState.selected),
"data-focus": domQuery.dataAttr(itemState.focused)
});

@@ -422,5 +394,5 @@ },

"aria-hidden": true,
"data-disabled": (0, import_dom_query2.dataAttr)(itemState.disabled),
"data-selected": (0, import_dom_query2.dataAttr)(itemState.selected),
"data-focus": (0, import_dom_query2.dataAttr)(itemState.focused),
"data-disabled": domQuery.dataAttr(itemState.disabled),
"data-selected": domQuery.dataAttr(itemState.selected),
"data-focus": domQuery.dataAttr(itemState.focused),
hidden: !itemState.selected

@@ -441,7 +413,7 @@ });

"aria-selected": branchState.disabled ? void 0 : branchState.selected,
"data-selected": (0, import_dom_query2.dataAttr)(branchState.selected),
"data-selected": domQuery.dataAttr(branchState.selected),
"aria-expanded": branchState.expanded,
"data-state": branchState.expanded ? "open" : "closed",
"aria-disabled": branchState.disabled,
"data-disabled": (0, import_dom_query2.dataAttr)(branchState.disabled),
"data-disabled": domQuery.dataAttr(branchState.disabled),
style: {

@@ -458,5 +430,5 @@ "--depth": props.depth

"data-state": branchState.expanded ? "open" : "closed",
"data-disabled": (0, import_dom_query2.dataAttr)(branchState.disabled),
"data-selected": (0, import_dom_query2.dataAttr)(branchState.selected),
"data-focus": (0, import_dom_query2.dataAttr)(branchState.focused)
"data-disabled": domQuery.dataAttr(branchState.disabled),
"data-selected": domQuery.dataAttr(branchState.selected),
"data-focus": domQuery.dataAttr(branchState.focused)
});

@@ -470,3 +442,3 @@ },

dir: state.context.dir,
"data-disabled": (0, import_dom_query2.dataAttr)(branchState.disabled),
"data-disabled": domQuery.dataAttr(branchState.disabled),
"data-state": branchState.expanded ? "open" : "closed",

@@ -488,4 +460,4 @@ onClick(event) {

"data-state": branchState.expanded ? "open" : "closed",
"data-disabled": (0, import_dom_query2.dataAttr)(branchState.disabled),
"data-selected": (0, import_dom_query2.dataAttr)(branchState.selected),
"data-disabled": domQuery.dataAttr(branchState.disabled),
"data-selected": domQuery.dataAttr(branchState.selected),
"data-branch": branchState.value,

@@ -511,3 +483,3 @@ "data-depth": props.depth,

"data-branch": branchState.value,
"data-disabled": (0, import_dom_query2.dataAttr)(branchState.disabled),
"data-disabled": domQuery.dataAttr(branchState.disabled),
"data-state": branchState.expanded ? "open" : "closed"

@@ -529,11 +501,6 @@ });

}
// src/tree-view.machine.ts
var import_core = require("@zag-js/core");
var import_dom_query3 = require("@zag-js/dom-query");
var import_utils = require("@zag-js/utils");
var { and } = import_core.guards;
var { and } = core.guards;
function machine(userContext) {
const ctx = (0, import_utils.compact)(userContext);
return (0, import_core.createMachine)(
const ctx = utils.compact(userContext);
return core.createMachine(
{

@@ -550,3 +517,3 @@ id: "tree-view",

...ctx,
typeaheadState: import_dom_query3.getByTypeahead.defaultOptions
typeaheadState: domQuery.getByTypeahead.defaultOptions
},

@@ -702,6 +669,6 @@ computed: {

const treeEl = dom.getTreeEl(ctx2);
return (0, import_dom_query3.observeChildren)(treeEl, {
return domQuery.observeChildren(treeEl, {
callback(records) {
const removedNodes = records.flatMap((r) => Array.from(r.removedNodes)).filter((node) => {
if (!(0, import_dom_query3.isHTMLElement)(node)) return false;
if (!domQuery.isHTMLElement(node)) return false;
return node.matches("[role=treeitem]") || node.matches("[role=group]");

@@ -712,5 +679,5 @@ });

records.forEach((record) => {
if ((0, import_dom_query3.isHTMLElement)(record.nextSibling)) {
if (domQuery.isHTMLElement(record.nextSibling)) {
elementToFocus = record.nextSibling;
} else if ((0, import_dom_query3.isHTMLElement)(record.previousSibling)) {
} else if (domQuery.isHTMLElement(record.previousSibling)) {
elementToFocus = record.previousSibling;

@@ -725,3 +692,3 @@ }

const nodeId = dom.getNodeId(node);
if ((0, import_dom_query3.isHTMLElement)(node) && nodeId != null) {
if (domQuery.isHTMLElement(node) && nodeId != null) {
removedIds.add(nodeId);

@@ -747,3 +714,3 @@ }

const firstItem = walker.firstChild();
if (!(0, import_dom_query3.isHTMLElement)(firstItem)) return;
if (!domQuery.isHTMLElement(firstItem)) return;
ctx2.focusedValue = dom.getNodeId(firstItem);

@@ -843,3 +810,3 @@ },

const nodeId = dom.getNodeId(node);
if ((0, import_dom_query3.isHTMLElement)(node) && nodeId != null) {
if (domQuery.isHTMLElement(node) && nodeId != null) {
nextSet.add(nodeId);

@@ -873,3 +840,3 @@ }

const nodeId = dom.getNodeId(node);
if ((0, import_dom_query3.isHTMLElement)(node) && node.dataset.part === "branch-control" && nodeId != null) {
if (domQuery.isHTMLElement(node) && node.dataset.part === "branch-control" && nodeId != null) {
nextSet.add(nodeId);

@@ -985,8 +952,5 @@ }

};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
anatomy,
connect,
machine
});
//# sourceMappingURL=index.js.map
exports.anatomy = anatomy;
exports.connect = connect;
exports.machine = machine;

@@ -0,3 +1,8 @@

import { createAnatomy } from '@zag-js/anatomy';
import { getEventKey, isModifierKey } from '@zag-js/dom-event';
import { createScope, isHTMLElement, query, isHiddenElement, getByTypeahead, queryAll, isComposingEvent, getEventTarget, isEditableElement, contains, dataAttr, observeChildren } from '@zag-js/dom-query';
import { createMachine, guards } from '@zag-js/core';
import { compact } from '@zag-js/utils';
// src/tree-view.anatomy.ts
import { createAnatomy } from "@zag-js/anatomy";
var anatomy = createAnatomy("tree-view").parts(

@@ -18,9 +23,2 @@ "root",

var parts = anatomy.build();
// src/tree-view.connect.ts
import { getEventKey, isModifierKey } from "@zag-js/dom-event";
import { contains, dataAttr, getEventTarget, isComposingEvent, isEditableElement } from "@zag-js/dom-query";
// src/tree-view.dom.ts
import { createScope, getByTypeahead, isHTMLElement, isHiddenElement, query, queryAll } from "@zag-js/dom-query";
var dom = createScope({

@@ -476,7 +474,2 @@ getRootId: (ctx) => ctx.ids?.root ?? `tree-root:${ctx.id}`,

}
// src/tree-view.machine.ts
import { createMachine, guards } from "@zag-js/core";
import { getByTypeahead as getByTypeahead2, isHTMLElement as isHTMLElement2, observeChildren } from "@zag-js/dom-query";
import { compact } from "@zag-js/utils";
var { and } = guards;

@@ -497,3 +490,3 @@ function machine(userContext) {

...ctx,
typeaheadState: getByTypeahead2.defaultOptions
typeaheadState: getByTypeahead.defaultOptions
},

@@ -652,3 +645,3 @@ computed: {

const removedNodes = records.flatMap((r) => Array.from(r.removedNodes)).filter((node) => {
if (!isHTMLElement2(node)) return false;
if (!isHTMLElement(node)) return false;
return node.matches("[role=treeitem]") || node.matches("[role=group]");

@@ -659,5 +652,5 @@ });

records.forEach((record) => {
if (isHTMLElement2(record.nextSibling)) {
if (isHTMLElement(record.nextSibling)) {
elementToFocus = record.nextSibling;
} else if (isHTMLElement2(record.previousSibling)) {
} else if (isHTMLElement(record.previousSibling)) {
elementToFocus = record.previousSibling;

@@ -672,3 +665,3 @@ }

const nodeId = dom.getNodeId(node);
if (isHTMLElement2(node) && nodeId != null) {
if (isHTMLElement(node) && nodeId != null) {
removedIds.add(nodeId);

@@ -694,3 +687,3 @@ }

const firstItem = walker.firstChild();
if (!isHTMLElement2(firstItem)) return;
if (!isHTMLElement(firstItem)) return;
ctx2.focusedValue = dom.getNodeId(firstItem);

@@ -790,3 +783,3 @@ },

const nodeId = dom.getNodeId(node);
if (isHTMLElement2(node) && nodeId != null) {
if (isHTMLElement(node) && nodeId != null) {
nextSet.add(nodeId);

@@ -820,3 +813,3 @@ }

const nodeId = dom.getNodeId(node);
if (isHTMLElement2(node) && node.dataset.part === "branch-control" && nodeId != null) {
if (isHTMLElement(node) && node.dataset.part === "branch-control" && nodeId != null) {
nextSet.add(nodeId);

@@ -932,7 +925,3 @@ }

};
export {
anatomy,
connect,
machine
};
//# sourceMappingURL=index.mjs.map
export { anatomy, connect, machine };
{
"name": "@zag-js/tree-view",
"version": "0.70.0",
"version": "0.71.0",
"description": "Core logic for the tree-view widget implemented as a state machine",

@@ -21,4 +21,3 @@ "keywords": [

"files": [
"dist",
"src"
"dist"
],

@@ -32,8 +31,8 @@ "publishConfig": {

"dependencies": {
"@zag-js/anatomy": "0.70.0",
"@zag-js/core": "0.70.0",
"@zag-js/dom-query": "0.70.0",
"@zag-js/dom-event": "0.70.0",
"@zag-js/utils": "0.70.0",
"@zag-js/types": "0.70.0"
"@zag-js/anatomy": "0.71.0",
"@zag-js/core": "0.71.0",
"@zag-js/dom-query": "0.71.0",
"@zag-js/dom-event": "0.71.0",
"@zag-js/utils": "0.71.0",
"@zag-js/types": "0.71.0"
},

@@ -40,0 +39,0 @@ "devDependencies": {

{"version":3,"sources":["../src/index.ts","../src/tree-view.anatomy.ts","../src/tree-view.connect.ts","../src/tree-view.dom.ts","../src/tree-view.machine.ts"],"sourcesContent":["export { anatomy } from \"./tree-view.anatomy\"\nexport { connect } from \"./tree-view.connect\"\nexport { machine } from \"./tree-view.machine\"\nexport type {\n MachineApi as Api,\n BranchProps,\n BranchState,\n UserDefinedContext as Context,\n ElementIds,\n ExpandedChangeDetails,\n FocusChangeDetails,\n ItemProps,\n ItemState,\n SelectionChangeDetails,\n Service,\n} from \"./tree-view.types\"\n","import { createAnatomy } from \"@zag-js/anatomy\"\n\nexport const anatomy = createAnatomy(\"tree-view\").parts(\n \"root\",\n \"label\",\n \"tree\",\n \"item\",\n \"itemIndicator\",\n \"itemText\",\n \"branch\",\n \"branchControl\",\n \"branchTrigger\",\n \"branchContent\",\n \"branchText\",\n \"branchIndicator\",\n)\n\nexport const parts = anatomy.build()\n","import { getEventKey, isModifierKey, type EventKeyMap } from \"@zag-js/dom-event\"\nimport { contains, dataAttr, getEventTarget, isComposingEvent, isEditableElement } from \"@zag-js/dom-query\"\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\"\nimport { parts } from \"./tree-view.anatomy\"\nimport { dom } from \"./tree-view.dom\"\nimport type { BranchProps, BranchState, ItemProps, ItemState, MachineApi, Send, State } from \"./tree-view.types\"\n\nexport function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {\n const expandedValue = Array.from(state.context.expandedValue)\n const selectedValue = Array.from(state.context.selectedValue)\n const isTypingAhead = state.context.isTypingAhead\n const focusedValue = state.context.focusedValue\n\n function getItemState(props: ItemProps): ItemState {\n return {\n value: props.value,\n disabled: Boolean(props.disabled),\n focused: focusedValue === props.value,\n selected: selectedValue.includes(props.value),\n }\n }\n\n function getBranchState(props: BranchProps): BranchState {\n return {\n value: props.value,\n disabled: Boolean(props.disabled),\n focused: focusedValue === props.value,\n expanded: expandedValue.includes(props.value),\n selected: selectedValue.includes(props.value),\n }\n }\n\n return {\n expandedValue: expandedValue,\n selectedValue: selectedValue,\n expand(value) {\n if (!value) {\n send({ type: \"EXPANDED.ALL\" })\n return\n }\n const nextValue = new Set(expandedValue)\n value.forEach((id) => nextValue.add(id))\n send({ type: \"EXPANDED.SET\", value: nextValue, src: \"expand\" })\n },\n collapse(value) {\n if (!value) {\n send({ type: \"EXPANDED.SET\", value: new Set([]), src: \"collapseAll\" })\n return\n }\n const nextValue = new Set(expandedValue)\n value.forEach((id) => nextValue.delete(id))\n send({ type: \"EXPANDED.SET\", value: nextValue, src: \"collapse\" })\n },\n deselect(value) {\n if (!value) {\n send({ type: \"SELECTED.SET\", value: new Set([]), src: \"deselectAll\" })\n return\n }\n const nextValue = new Set(selectedValue)\n value.forEach((id) => nextValue.delete(id))\n send({ type: \"SELECTED.SET\", value: nextValue, src: \"deselect\" })\n },\n select(value) {\n if (!value) {\n send({ type: \"SELECTED.ALL\" })\n return\n }\n const nextValue = new Set()\n if (state.context.selectionMode === \"single\") {\n // For single selection, only add the last item\n if (value.length > 0) {\n nextValue.add(value[value.length - 1])\n }\n } else {\n // For multiple selection, add all items\n value.forEach((id) => nextValue.add(id))\n selectedValue.forEach((id) => nextValue.add(id))\n }\n send({ type: \"SELECTED.SET\", value: nextValue, src: \"select\" })\n },\n focusBranch(id) {\n dom.getBranchControlEl(state.context, id)?.focus()\n },\n focusItem(id) {\n dom.getItemEl(state.context, id)?.focus()\n },\n\n getRootProps() {\n return normalize.element({\n ...parts.root.attrs,\n id: dom.getRootId(state.context),\n dir: state.context.dir,\n })\n },\n\n getLabelProps() {\n return normalize.element({\n ...parts.label.attrs,\n id: dom.getLabelId(state.context),\n dir: state.context.dir,\n })\n },\n\n getTreeProps() {\n return normalize.element({\n ...parts.tree.attrs,\n id: dom.getTreeId(state.context),\n dir: state.context.dir,\n role: \"tree\",\n \"aria-label\": \"Tree View\",\n \"aria-labelledby\": dom.getLabelId(state.context),\n \"aria-multiselectable\": state.context.selectionMode === \"multiple\" || undefined,\n onKeyDown(event) {\n if (event.defaultPrevented) return\n if (isComposingEvent(event)) return\n\n const target = getEventTarget<HTMLElement>(event)\n // allow typing in input elements within the tree\n if (isEditableElement(target)) return\n\n const node = target?.closest<HTMLElement>(\"[role=treeitem]\")\n if (!node) return\n\n const nodeId = dom.getNodeId(node)\n if (nodeId == null) {\n console.warn(`Node id not found for node`, node)\n return\n }\n\n const isBranchNode = !!target?.dataset.branch\n\n const keyMap: EventKeyMap = {\n ArrowDown(event) {\n if (isModifierKey(event)) return\n event.preventDefault()\n send({ type: \"ITEM.ARROW_DOWN\", id: nodeId, shiftKey: event.shiftKey })\n },\n ArrowUp(event) {\n if (isModifierKey(event)) return\n event.preventDefault()\n send({ type: \"ITEM.ARROW_UP\", id: nodeId, shiftKey: event.shiftKey })\n },\n ArrowLeft(event) {\n if (isModifierKey(event) || node.dataset.disabled) return\n event.preventDefault()\n send({ type: isBranchNode ? \"BRANCH.ARROW_LEFT\" : \"ITEM.ARROW_LEFT\", id: nodeId })\n },\n ArrowRight(event) {\n if (!isBranchNode || node.dataset.disabled) return\n event.preventDefault()\n send({ type: \"BRANCH.ARROW_RIGHT\", id: nodeId })\n },\n Home(event) {\n if (isModifierKey(event)) return\n event.preventDefault()\n send({ type: \"ITEM.HOME\", id: nodeId, shiftKey: event.shiftKey })\n },\n End(event) {\n if (isModifierKey(event)) return\n event.preventDefault()\n send({ type: \"ITEM.END\", id: nodeId, shiftKey: event.shiftKey })\n },\n Space(event) {\n if (node.dataset.disabled) return\n\n if (isTypingAhead) {\n send({ type: \"TREE.TYPEAHEAD\", key: event.key })\n } else {\n keyMap.Enter?.(event)\n }\n },\n Enter(event) {\n if (node.dataset.disabled) return\n\n const isLink = target?.closest(\"a[href]\")\n if (!isLink) event.preventDefault()\n\n send({ type: isBranchNode ? \"BRANCH.CLICK\" : \"ITEM.CLICK\", id: nodeId, src: \"keyboard\" })\n },\n \"*\"(event) {\n if (node.dataset.disabled) return\n event.preventDefault()\n send({ type: \"EXPAND.SIBLINGS\", id: nodeId })\n },\n a(event) {\n if (!event.metaKey || node.dataset.disabled) return\n event.preventDefault()\n send({ type: \"SELECTED.ALL\", preventScroll: true, moveFocus: true })\n },\n }\n\n const key = getEventKey(event, state.context)\n const exec = keyMap[key]\n\n if (exec) {\n exec(event)\n return\n }\n\n if (!state.context.typeahead) return\n\n const isValidTypeahead = event.key.length === 1 && !isModifierKey(event)\n if (!isValidTypeahead) return\n\n send({ type: \"TREE.TYPEAHEAD\", key: event.key, id: nodeId })\n event.preventDefault()\n },\n onBlur(event) {\n if (contains(event.currentTarget, event.relatedTarget)) return\n send({ type: \"TREE.BLUR\" })\n },\n })\n },\n\n getItemState,\n getItemProps(props) {\n const itemState = getItemState(props)\n return normalize.element({\n ...parts.item.attrs,\n dir: state.context.dir,\n \"data-ownedby\": dom.getTreeId(state.context),\n \"data-item\": itemState.value,\n tabIndex: itemState.focused ? 0 : -1,\n \"data-focus\": dataAttr(itemState.focused),\n role: \"treeitem\",\n \"aria-current\": itemState.selected ? \"true\" : undefined,\n \"aria-selected\": itemState.disabled ? undefined : itemState.selected,\n \"data-selected\": dataAttr(itemState.selected),\n \"aria-disabled\": itemState.disabled,\n \"data-disabled\": dataAttr(itemState.disabled),\n \"aria-level\": props.depth,\n \"data-depth\": props.depth,\n style: {\n \"--depth\": props.depth,\n },\n onFocus(event) {\n event.stopPropagation()\n send({ type: \"ITEM.FOCUS\", id: itemState.value })\n },\n onClick(event) {\n if (itemState.disabled) return\n const isMetaKey = event.metaKey || event.ctrlKey\n send({ type: \"ITEM.CLICK\", id: itemState.value, shiftKey: event.shiftKey, ctrlKey: isMetaKey })\n event.stopPropagation()\n\n const isLink = event.currentTarget.matches(\"a[href]\")\n if (!isLink) event.preventDefault()\n },\n })\n },\n\n getItemTextProps(props) {\n const itemState = getItemState(props)\n return normalize.element({\n ...parts.itemText.attrs,\n \"data-disabled\": dataAttr(itemState.disabled),\n \"data-selected\": dataAttr(itemState.selected),\n \"data-focus\": dataAttr(itemState.focused),\n })\n },\n\n getItemIndicatorProps(props) {\n const itemState = getItemState(props)\n return normalize.element({\n ...parts.itemIndicator.attrs,\n \"aria-hidden\": true,\n \"data-disabled\": dataAttr(itemState.disabled),\n \"data-selected\": dataAttr(itemState.selected),\n \"data-focus\": dataAttr(itemState.focused),\n hidden: !itemState.selected,\n })\n },\n\n getBranchState,\n getBranchProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branch.attrs,\n \"data-depth\": props.depth,\n dir: state.context.dir,\n \"data-branch\": branchState.value,\n role: \"treeitem\",\n \"data-ownedby\": dom.getTreeId(state.context),\n \"aria-level\": props.depth,\n \"aria-selected\": branchState.disabled ? undefined : branchState.selected,\n \"data-selected\": dataAttr(branchState.selected),\n \"aria-expanded\": branchState.expanded,\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n \"aria-disabled\": branchState.disabled,\n \"data-disabled\": dataAttr(branchState.disabled),\n style: {\n \"--depth\": props.depth,\n },\n })\n },\n\n getBranchIndicatorProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branchIndicator.attrs,\n \"aria-hidden\": true,\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n \"data-disabled\": dataAttr(branchState.disabled),\n \"data-selected\": dataAttr(branchState.selected),\n \"data-focus\": dataAttr(branchState.focused),\n })\n },\n\n getBranchTriggerProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branchTrigger.attrs,\n role: \"button\",\n dir: state.context.dir,\n \"data-disabled\": dataAttr(branchState.disabled),\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n onClick(event) {\n if (branchState.disabled) return\n send({ type: \"BRANCH_TOGGLE.CLICK\", id: branchState.value })\n event.stopPropagation()\n },\n })\n },\n\n getBranchControlProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branchControl.attrs,\n role: \"button\",\n dir: state.context.dir,\n tabIndex: branchState.focused ? 0 : -1,\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n \"data-disabled\": dataAttr(branchState.disabled),\n \"data-selected\": dataAttr(branchState.selected),\n \"data-branch\": branchState.value,\n \"data-depth\": props.depth,\n onFocus(event) {\n send({ type: \"ITEM.FOCUS\", id: branchState.value })\n event.stopPropagation()\n },\n onClick(event) {\n if (branchState.disabled) return\n\n const isMetaKey = event.metaKey || event.ctrlKey\n send({ type: \"BRANCH.CLICK\", id: branchState.value, shiftKey: event.shiftKey, ctrlKey: isMetaKey })\n\n event.stopPropagation()\n },\n })\n },\n\n getBranchTextProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branchText.attrs,\n dir: state.context.dir,\n \"data-branch\": branchState.value,\n \"data-disabled\": dataAttr(branchState.disabled),\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n })\n },\n\n getBranchContentProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branchContent.attrs,\n role: \"group\",\n dir: state.context.dir,\n \"data-branch\": branchState.value,\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n hidden: !branchState.expanded,\n })\n },\n }\n}\n","import { createScope, getByTypeahead, isHTMLElement, isHiddenElement, query, queryAll } from \"@zag-js/dom-query\"\nimport type { MachineContext as Ctx } from \"./tree-view.types\"\n\ninterface TreeWalkerOpts {\n skipHidden?: boolean\n root?: HTMLElement | null\n}\n\nexport const dom = createScope({\n getRootId: (ctx: Ctx) => ctx.ids?.root ?? `tree-root:${ctx.id}`,\n getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `tree-label:${ctx.id}`,\n getTreeId: (ctx: Ctx) => ctx.ids?.tree ?? `tree-tree:${ctx.id}`,\n\n getNodeId(node: Node | null | undefined) {\n if (!isHTMLElement(node)) return null\n return node.dataset.branch ?? node.dataset.item ?? null\n },\n\n getNodeEl(ctx: Ctx, id: string) {\n const node = dom.getItemEl(ctx, id) ?? dom.getBranchEl(ctx, id)\n if (node?.dataset.part === \"branch\") {\n return query(node, \"[data-part=branch-control]\")\n }\n return node\n },\n\n getTreeEl(ctx: Ctx) {\n return dom.getById(ctx, dom.getTreeId(ctx))\n },\n\n getBranchEl(ctx: Ctx, id: string) {\n const selector = `[role=treeitem][data-branch=\"${id}\"]`\n return query(dom.getTreeEl(ctx), selector)\n },\n getItemEl(ctx: Ctx, id: string) {\n const selector = `[role=treeitem][data-item=\"${id}\"]`\n return query(dom.getTreeEl(ctx), selector)\n },\n getBranchControlEl(ctx: Ctx, id: string) {\n const selector = \"[data-part=branch-control]\"\n return query(dom.getBranchEl(ctx, id), selector)\n },\n\n getFocusedEl(ctx: Ctx) {\n if (!ctx.focusedValue) return null\n return dom.getById(ctx, ctx.focusedValue)\n },\n\n focusNode(node: Node | Element | null | undefined, options?: FocusOptions) {\n if (isHTMLElement(node)) node.focus(options)\n },\n\n getNodeDepth(node: HTMLElement | null) {\n return node?.dataset.depth ? Number(node.dataset.depth) : -1\n },\n\n getTreeWalker(ctx: Ctx, opts?: TreeWalkerOpts) {\n const { skipHidden = true, root } = opts ?? {}\n\n const treeEl = root || dom.getTreeEl(ctx)\n if (!treeEl) throw new Error(\"Tree or branch root not found\")\n\n const doc = dom.getDoc(ctx)\n\n return doc.createTreeWalker(treeEl, NodeFilter.SHOW_ELEMENT, {\n acceptNode(node: HTMLElement) {\n if (skipHidden && isHiddenElement(node)) {\n return NodeFilter.FILTER_REJECT\n }\n\n if (node.role === \"treeitem\" && node.dataset.part !== \"branch\") {\n return NodeFilter.FILTER_ACCEPT\n }\n\n if (node.role === \"button\" && node.dataset.part === \"branch-control\") {\n return NodeFilter.FILTER_ACCEPT\n }\n\n return NodeFilter.FILTER_SKIP\n },\n })\n },\n\n getMatchingEl(ctx: Ctx, key: string) {\n const walker = dom.getTreeWalker(ctx)\n\n const elements: HTMLElement[] = []\n let node = walker.firstChild()\n\n while (node) {\n if (isHTMLElement(node)) elements.push(node)\n node = walker.nextNode()\n }\n\n return getByTypeahead(elements, {\n state: ctx.typeaheadState,\n key,\n activeId: ctx.focusedValue,\n itemToId: (v) => dom.getNodeId(v) ?? v.id,\n })\n },\n\n getTreeNodes(ctx: Ctx, options: TreeWalkerOpts = {}) {\n const walker = dom.getTreeWalker(ctx, options)\n\n const nodes: HTMLElement[] = []\n let node = walker.firstChild()\n\n while (node) {\n if (isHTMLElement(node)) {\n nodes.push(node)\n }\n node = walker.nextNode()\n }\n\n return nodes\n },\n\n getBranchNodes(ctx: Ctx, depth: number | null) {\n if (depth === -1) return []\n return queryAll(dom.getTreeEl(ctx), `[role=treeitem][data-part=branch][data-depth=\"${depth}\"]`)\n },\n\n getNodesInRange(nodes: HTMLElement[], startNode: HTMLElement, endNode: HTMLElement) {\n const nextSet = new Set<string>()\n\n nodes.forEach((node) => {\n const nodeId = dom.getNodeId(node)\n if (nodeId == null) return\n\n // compare node position with firstSelectedEl and focusedEl\n // if node is between firstSelectedEl and focusedEl, add it to nextSet\n if (node === startNode || node === endNode) {\n nextSet.add(nodeId)\n return\n }\n\n // use node.compareDocumentPosition to compare node position\n // https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition\n\n const startPos = node.compareDocumentPosition(startNode)\n const endPos = node.compareDocumentPosition(endNode)\n\n // if node is before firstSelectedEl and after focusedEl, add it to nextSet\n if (startPos & Node.DOCUMENT_POSITION_FOLLOWING && endPos & Node.DOCUMENT_POSITION_PRECEDING) {\n nextSet.add(nodeId)\n return\n }\n\n // if node is after firstSelectedEl and before focusedEl, add it to nextSet\n if (startPos & Node.DOCUMENT_POSITION_PRECEDING && endPos & Node.DOCUMENT_POSITION_FOLLOWING) {\n nextSet.add(nodeId)\n return\n }\n })\n\n return Array.from(nextSet)\n },\n})\n","import { createMachine, guards } from \"@zag-js/core\"\nimport { getByTypeahead, isHTMLElement, observeChildren } from \"@zag-js/dom-query\"\nimport { compact } from \"@zag-js/utils\"\nimport { dom } from \"./tree-view.dom\"\nimport type { MachineContext, MachineState, UserDefinedContext } from \"./tree-view.types\"\n\nconst { and } = guards\n\nexport function machine(userContext: UserDefinedContext) {\n const ctx = compact(userContext)\n return createMachine<MachineContext, MachineState>(\n {\n id: \"tree-view\",\n initial: \"idle\",\n context: {\n expandedValue: [],\n selectedValue: [],\n focusedValue: null,\n expandOnClick: true,\n selectionMode: \"single\",\n typeahead: true,\n ...ctx,\n typeaheadState: getByTypeahead.defaultOptions,\n },\n\n computed: {\n isMultipleSelection: (ctx) => ctx.selectionMode === \"multiple\",\n },\n\n on: {\n \"EXPANDED.SET\": {\n actions: [\"setExpanded\"],\n },\n \"SELECTED.SET\": {\n actions: [\"setSelected\"],\n },\n \"SELECTED.ALL\": [\n {\n guard: and(\"isMultipleSelection\", \"moveFocus\"),\n actions: [\"selectAllItems\", \"focusTreeLastItem\"],\n },\n {\n guard: \"isMultipleSelection\",\n actions: [\"selectAllItems\"],\n },\n ],\n \"EXPANDED.ALL\": {\n actions: [\"expandAllBranches\"],\n },\n },\n\n activities: [\"trackChildrenMutation\"],\n\n entry: [\"setFocusableNode\"],\n\n states: {\n idle: {\n on: {\n \"ITEM.FOCUS\": {\n actions: [\"setFocusedItem\"],\n },\n \"ITEM.ARROW_DOWN\": [\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"focusTreeNextItem\", \"extendSelectionToNextItem\"],\n },\n {\n actions: [\"focusTreeNextItem\"],\n },\n ],\n \"ITEM.ARROW_UP\": [\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"focusTreePrevItem\", \"extendSelectionToPrevItem\"],\n },\n {\n actions: [\"focusTreePrevItem\"],\n },\n ],\n \"ITEM.ARROW_LEFT\": {\n actions: [\"focusBranchControl\"],\n },\n \"BRANCH.ARROW_LEFT\": [\n {\n guard: \"isBranchExpanded\",\n actions: [\"collapseBranch\"],\n },\n {\n actions: [\"focusBranchControl\"],\n },\n ],\n \"BRANCH.ARROW_RIGHT\": [\n {\n guard: and(\"isBranchFocused\", \"isBranchExpanded\"),\n actions: [\"focusBranchFirstItem\"],\n },\n {\n actions: [\"expandBranch\"],\n },\n ],\n \"EXPAND.SIBLINGS\": {\n actions: [\"expandSiblingBranches\"],\n },\n \"ITEM.HOME\": [\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"extendSelectionToFirstItem\", \"focusTreeFirstItem\"],\n },\n {\n actions: [\"focusTreeFirstItem\"],\n },\n ],\n \"ITEM.END\": [\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"extendSelectionToLastItem\", \"focusTreeLastItem\"],\n },\n {\n actions: [\"focusTreeLastItem\"],\n },\n ],\n \"ITEM.CLICK\": [\n {\n guard: and(\"isCtrlKey\", \"isMultipleSelection\"),\n actions: [\"addOrRemoveItemFromSelection\"],\n },\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"extendSelectionToItem\"],\n },\n {\n actions: [\"selectItem\"],\n },\n ],\n \"BRANCH.CLICK\": [\n {\n guard: and(\"isCtrlKey\", \"isMultipleSelection\"),\n actions: [\"addOrRemoveItemFromSelection\"],\n },\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"extendSelectionToItem\"],\n },\n {\n guard: \"openOnClick\",\n actions: [\"selectItem\", \"toggleBranch\"],\n },\n {\n actions: [\"selectItem\"],\n },\n ],\n \"BRANCH_TOGGLE.CLICK\": {\n actions: [\"toggleBranch\"],\n },\n \"TREE.TYPEAHEAD\": {\n actions: [\"focusMatchedItem\"],\n },\n \"TREE.BLUR\": {\n actions: [\"clearFocusedItem\", \"setFocusableNode\"],\n },\n },\n },\n },\n },\n {\n guards: {\n isBranchFocused: (ctx, evt) => ctx.focusedValue === evt.id,\n isBranchExpanded: (ctx, evt) => ctx.expandedValue.includes(evt.id),\n isShiftKey: (_ctx, evt) => evt.shiftKey,\n isCtrlKey: (_ctx, evt) => evt.ctrlKey,\n hasSelectedItems: (ctx) => ctx.selectedValue.length > 0,\n isMultipleSelection: (ctx) => ctx.isMultipleSelection,\n moveFocus: (_ctx, evt) => !!evt.moveFocus,\n openOnClick: (ctx) => !!ctx.expandOnClick,\n },\n activities: {\n trackChildrenMutation(ctx, _evt, { send }) {\n const treeEl = dom.getTreeEl(ctx)\n return observeChildren(treeEl, {\n callback(records) {\n const removedNodes = records\n .flatMap((r) => Array.from(r.removedNodes))\n .filter((node) => {\n if (!isHTMLElement(node)) return false\n return node.matches(\"[role=treeitem]\") || node.matches(\"[role=group]\")\n })\n\n if (!removedNodes.length) return\n\n let elementToFocus: HTMLElement | null = null\n records.forEach((record) => {\n if (isHTMLElement(record.nextSibling)) {\n elementToFocus = record.nextSibling\n } else if (isHTMLElement(record.previousSibling)) {\n elementToFocus = record.previousSibling\n }\n })\n\n if (elementToFocus) {\n dom.focusNode(elementToFocus)\n }\n\n const removedIds: Set<string> = new Set()\n removedNodes.forEach((node) => {\n const nodeId = dom.getNodeId(node)\n if (isHTMLElement(node) && nodeId != null) {\n removedIds.add(nodeId)\n }\n })\n\n const nextSet = new Set(ctx.selectedValue)\n removedIds.forEach((id) => nextSet.delete(id))\n send({ type: \"SELECTED.SET\", value: removedIds })\n },\n })\n },\n },\n actions: {\n setFocusableNode(ctx) {\n if (ctx.focusedValue) return\n\n if (ctx.selectedValue.length > 0) {\n const firstSelectedId = Array.from(ctx.selectedValue)[0]\n ctx.focusedValue = firstSelectedId\n return\n }\n\n const walker = dom.getTreeWalker(ctx)\n const firstItem = walker.firstChild()\n\n if (!isHTMLElement(firstItem)) return\n // don't use set.focused here because it will trigger focusChange event\n ctx.focusedValue = dom.getNodeId(firstItem)\n },\n selectItem(ctx, evt) {\n set.selected(ctx, [evt.id])\n },\n setFocusedItem(ctx, evt) {\n set.focused(ctx, evt.id)\n },\n clearFocusedItem(ctx) {\n set.focused(ctx, null)\n },\n clearSelectedItem(ctx) {\n set.selected(ctx, [])\n },\n toggleBranch(ctx, evt) {\n const nextSet = new Set(ctx.expandedValue)\n\n if (nextSet.has(evt.id)) {\n nextSet.delete(evt.id)\n // collapseEffect(ctx, evt)\n } else {\n nextSet.add(evt.id)\n }\n\n set.expanded(ctx, Array.from(nextSet))\n },\n expandBranch(ctx, evt) {\n const nextSet = new Set(ctx.expandedValue)\n nextSet.add(evt.id)\n set.expanded(ctx, Array.from(nextSet))\n },\n collapseBranch(ctx, evt) {\n const nextSet = new Set(ctx.expandedValue)\n nextSet.delete(evt.id)\n set.expanded(ctx, Array.from(nextSet))\n },\n setExpanded(ctx, evt) {\n set.expanded(ctx, evt.value)\n },\n setSelected(ctx, evt) {\n set.selected(ctx, evt.value)\n },\n focusTreeFirstItem(ctx) {\n const walker = dom.getTreeWalker(ctx)\n dom.focusNode(walker.firstChild())\n },\n focusTreeLastItem(ctx, evt) {\n const walker = dom.getTreeWalker(ctx)\n dom.focusNode(walker.lastChild(), { preventScroll: evt.preventScroll })\n },\n focusBranchFirstItem(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const walker = dom.getTreeWalker(ctx)\n\n walker.currentNode = focusedEl\n dom.focusNode(walker.nextNode())\n },\n focusTreeNextItem(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const walker = dom.getTreeWalker(ctx)\n\n if (ctx.focusedValue) {\n walker.currentNode = focusedEl\n const nextNode = walker.nextNode()\n dom.focusNode(nextNode)\n } else {\n dom.focusNode(walker.firstChild())\n }\n },\n focusTreePrevItem(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const walker = dom.getTreeWalker(ctx)\n\n if (ctx.focusedValue) {\n walker.currentNode = focusedEl\n const prevNode = walker.previousNode()\n dom.focusNode(prevNode)\n } else {\n dom.focusNode(walker.lastChild())\n }\n },\n focusBranchControl(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const parentDepth = Number(focusedEl.dataset.depth) - 1\n if (parentDepth < 0) return\n\n const branchSelector = `[data-part=branch][data-depth=\"${parentDepth}\"]`\n const closestBranch = focusedEl.closest(branchSelector)\n\n const branchControl = closestBranch?.querySelector(\"[data-part=branch-control]\")\n dom.focusNode(branchControl)\n },\n selectAllItems(ctx) {\n const nextSet = new Set<string>()\n const walker = dom.getTreeWalker(ctx)\n let node = walker.firstChild()\n while (node) {\n const nodeId = dom.getNodeId(node)\n if (isHTMLElement(node) && nodeId != null) {\n nextSet.add(nodeId)\n }\n node = walker.nextNode()\n }\n set.selected(ctx, Array.from(nextSet))\n },\n focusMatchedItem(ctx, evt) {\n dom.focusNode(dom.getMatchingEl(ctx, evt.key))\n },\n addOrRemoveItemFromSelection(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const nextSet = new Set(ctx.selectedValue)\n\n const nodeId = dom.getNodeId(focusedEl)\n if (nodeId == null) return\n\n if (nextSet.has(nodeId)) {\n nextSet.delete(nodeId)\n } else {\n nextSet.add(nodeId)\n }\n\n set.selected(ctx, Array.from(nextSet))\n },\n expandAllBranches(ctx) {\n const nextSet = new Set<string>()\n const walker = dom.getTreeWalker(ctx, { skipHidden: false })\n while (walker.nextNode()) {\n const node = walker.currentNode\n const nodeId = dom.getNodeId(node)\n if (isHTMLElement(node) && node.dataset.part === \"branch-control\" && nodeId != null) {\n nextSet.add(nodeId)\n }\n }\n set.expanded(ctx, Array.from(nextSet))\n },\n expandSiblingBranches(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n const nodes = dom.getBranchNodes(ctx, dom.getNodeDepth(focusedEl))\n\n const nextSet = new Set<string>()\n nodes.forEach((node) => {\n const nodeId = dom.getNodeId(node)\n if (nodeId == null) return\n nextSet.add(nodeId)\n })\n\n set.expanded(ctx, Array.from(nextSet))\n },\n extendSelectionToItem(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const nodes = dom.getTreeNodes(ctx)\n const selectedIds = Array.from(ctx.selectedValue)\n const anchorEl = dom.getNodeEl(ctx, selectedIds[0]) || nodes[0]\n\n const nextSet = dom.getNodesInRange(nodes, anchorEl, focusedEl)\n\n set.selected(ctx, nextSet)\n },\n extendSelectionToNextItem(ctx, evt) {\n const nodeId = evt.id\n\n const currentNode = dom.getNodeEl(ctx, nodeId)\n if (!currentNode) return\n\n const walker = dom.getTreeWalker(ctx)\n walker.currentNode = currentNode\n\n const nextNode = walker.nextNode()\n dom.focusNode(nextNode)\n\n // extend selection to nextNode (preserve the anchor node)\n const selectedIds = new Set(ctx.selectedValue)\n const nextNodeId = dom.getNodeId(nextNode)\n\n if (nextNodeId == null) return\n\n if (selectedIds.has(nodeId) && selectedIds.has(nextNodeId)) {\n selectedIds.delete(nodeId)\n } else if (!selectedIds.has(nextNodeId)) {\n selectedIds.add(nextNodeId)\n }\n\n set.selected(ctx, Array.from(selectedIds))\n },\n extendSelectionToPrevItem(ctx, evt) {\n const nodeId = evt.id\n\n const currentNode = dom.getNodeEl(ctx, nodeId)\n if (!currentNode) return\n\n const walker = dom.getTreeWalker(ctx)\n walker.currentNode = currentNode\n\n const prevNode = walker.previousNode()\n dom.focusNode(prevNode)\n\n // extend selection to prevNode (preserve the anchor node)\n const selectedIds = new Set(ctx.selectedValue)\n const prevNodeId = dom.getNodeId(prevNode)\n\n if (prevNodeId == null) return\n\n if (selectedIds.has(nodeId) && selectedIds.has(prevNodeId)) {\n selectedIds.delete(nodeId)\n } else if (!selectedIds.has(prevNodeId)) {\n selectedIds.add(prevNodeId)\n }\n\n set.selected(ctx, Array.from(selectedIds))\n },\n extendSelectionToFirstItem(ctx) {\n const nodes = dom.getTreeNodes(ctx)\n\n const anchorEl = dom.getNodeEl(ctx, [...ctx.selectedValue][0]) || nodes[0]\n const focusedEl = nodes[0]\n\n const selectedIds = dom.getNodesInRange(nodes, anchorEl, focusedEl)\n set.selected(ctx, selectedIds)\n },\n extendSelectionToLastItem(ctx) {\n const nodes = dom.getTreeNodes(ctx)\n\n const anchorEl = dom.getNodeEl(ctx, [...ctx.selectedValue][0]) || nodes[0]\n const focusedEl = nodes[nodes.length - 1]\n\n const selectedIds = dom.getNodesInRange(nodes, anchorEl, focusedEl)\n set.selected(ctx, selectedIds)\n },\n },\n },\n )\n}\n\nconst invoke = {\n focusChange(ctx: MachineContext) {\n ctx.onFocusChange?.({ focusedValue: ctx.focusedValue! })\n },\n expandedChange(ctx: MachineContext) {\n ctx.onExpandedChange?.({\n expandedValue: Array.from(ctx.expandedValue),\n focusedValue: ctx.focusedValue!,\n })\n },\n selectionChange(ctx: MachineContext) {\n ctx.onSelectionChange?.({\n selectedValue: Array.from(ctx.selectedValue),\n focusedValue: ctx.focusedValue,\n })\n },\n}\n\nconst set = {\n selected(ctx: MachineContext, value: string[]) {\n ctx.selectedValue = value\n invoke.selectionChange(ctx)\n },\n focused(ctx: MachineContext, value: string | null) {\n ctx.focusedValue = value\n invoke.focusChange(ctx)\n },\n expanded(ctx: MachineContext, value: string[]) {\n ctx.expandedValue = value\n invoke.expandedChange(ctx)\n },\n}\n"],"mappings":"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","names":["import_dom_query","event","import_dom_query","ctx"]}
{"version":3,"sources":["../src/tree-view.anatomy.ts","../src/tree-view.connect.ts","../src/tree-view.dom.ts","../src/tree-view.machine.ts"],"sourcesContent":["import { createAnatomy } from \"@zag-js/anatomy\"\n\nexport const anatomy = createAnatomy(\"tree-view\").parts(\n \"root\",\n \"label\",\n \"tree\",\n \"item\",\n \"itemIndicator\",\n \"itemText\",\n \"branch\",\n \"branchControl\",\n \"branchTrigger\",\n \"branchContent\",\n \"branchText\",\n \"branchIndicator\",\n)\n\nexport const parts = anatomy.build()\n","import { getEventKey, isModifierKey, type EventKeyMap } from \"@zag-js/dom-event\"\nimport { contains, dataAttr, getEventTarget, isComposingEvent, isEditableElement } from \"@zag-js/dom-query\"\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\"\nimport { parts } from \"./tree-view.anatomy\"\nimport { dom } from \"./tree-view.dom\"\nimport type { BranchProps, BranchState, ItemProps, ItemState, MachineApi, Send, State } from \"./tree-view.types\"\n\nexport function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {\n const expandedValue = Array.from(state.context.expandedValue)\n const selectedValue = Array.from(state.context.selectedValue)\n const isTypingAhead = state.context.isTypingAhead\n const focusedValue = state.context.focusedValue\n\n function getItemState(props: ItemProps): ItemState {\n return {\n value: props.value,\n disabled: Boolean(props.disabled),\n focused: focusedValue === props.value,\n selected: selectedValue.includes(props.value),\n }\n }\n\n function getBranchState(props: BranchProps): BranchState {\n return {\n value: props.value,\n disabled: Boolean(props.disabled),\n focused: focusedValue === props.value,\n expanded: expandedValue.includes(props.value),\n selected: selectedValue.includes(props.value),\n }\n }\n\n return {\n expandedValue: expandedValue,\n selectedValue: selectedValue,\n expand(value) {\n if (!value) {\n send({ type: \"EXPANDED.ALL\" })\n return\n }\n const nextValue = new Set(expandedValue)\n value.forEach((id) => nextValue.add(id))\n send({ type: \"EXPANDED.SET\", value: nextValue, src: \"expand\" })\n },\n collapse(value) {\n if (!value) {\n send({ type: \"EXPANDED.SET\", value: new Set([]), src: \"collapseAll\" })\n return\n }\n const nextValue = new Set(expandedValue)\n value.forEach((id) => nextValue.delete(id))\n send({ type: \"EXPANDED.SET\", value: nextValue, src: \"collapse\" })\n },\n deselect(value) {\n if (!value) {\n send({ type: \"SELECTED.SET\", value: new Set([]), src: \"deselectAll\" })\n return\n }\n const nextValue = new Set(selectedValue)\n value.forEach((id) => nextValue.delete(id))\n send({ type: \"SELECTED.SET\", value: nextValue, src: \"deselect\" })\n },\n select(value) {\n if (!value) {\n send({ type: \"SELECTED.ALL\" })\n return\n }\n const nextValue = new Set()\n if (state.context.selectionMode === \"single\") {\n // For single selection, only add the last item\n if (value.length > 0) {\n nextValue.add(value[value.length - 1])\n }\n } else {\n // For multiple selection, add all items\n value.forEach((id) => nextValue.add(id))\n selectedValue.forEach((id) => nextValue.add(id))\n }\n send({ type: \"SELECTED.SET\", value: nextValue, src: \"select\" })\n },\n focusBranch(id) {\n dom.getBranchControlEl(state.context, id)?.focus()\n },\n focusItem(id) {\n dom.getItemEl(state.context, id)?.focus()\n },\n\n getRootProps() {\n return normalize.element({\n ...parts.root.attrs,\n id: dom.getRootId(state.context),\n dir: state.context.dir,\n })\n },\n\n getLabelProps() {\n return normalize.element({\n ...parts.label.attrs,\n id: dom.getLabelId(state.context),\n dir: state.context.dir,\n })\n },\n\n getTreeProps() {\n return normalize.element({\n ...parts.tree.attrs,\n id: dom.getTreeId(state.context),\n dir: state.context.dir,\n role: \"tree\",\n \"aria-label\": \"Tree View\",\n \"aria-labelledby\": dom.getLabelId(state.context),\n \"aria-multiselectable\": state.context.selectionMode === \"multiple\" || undefined,\n onKeyDown(event) {\n if (event.defaultPrevented) return\n if (isComposingEvent(event)) return\n\n const target = getEventTarget<HTMLElement>(event)\n // allow typing in input elements within the tree\n if (isEditableElement(target)) return\n\n const node = target?.closest<HTMLElement>(\"[role=treeitem]\")\n if (!node) return\n\n const nodeId = dom.getNodeId(node)\n if (nodeId == null) {\n console.warn(`Node id not found for node`, node)\n return\n }\n\n const isBranchNode = !!target?.dataset.branch\n\n const keyMap: EventKeyMap = {\n ArrowDown(event) {\n if (isModifierKey(event)) return\n event.preventDefault()\n send({ type: \"ITEM.ARROW_DOWN\", id: nodeId, shiftKey: event.shiftKey })\n },\n ArrowUp(event) {\n if (isModifierKey(event)) return\n event.preventDefault()\n send({ type: \"ITEM.ARROW_UP\", id: nodeId, shiftKey: event.shiftKey })\n },\n ArrowLeft(event) {\n if (isModifierKey(event) || node.dataset.disabled) return\n event.preventDefault()\n send({ type: isBranchNode ? \"BRANCH.ARROW_LEFT\" : \"ITEM.ARROW_LEFT\", id: nodeId })\n },\n ArrowRight(event) {\n if (!isBranchNode || node.dataset.disabled) return\n event.preventDefault()\n send({ type: \"BRANCH.ARROW_RIGHT\", id: nodeId })\n },\n Home(event) {\n if (isModifierKey(event)) return\n event.preventDefault()\n send({ type: \"ITEM.HOME\", id: nodeId, shiftKey: event.shiftKey })\n },\n End(event) {\n if (isModifierKey(event)) return\n event.preventDefault()\n send({ type: \"ITEM.END\", id: nodeId, shiftKey: event.shiftKey })\n },\n Space(event) {\n if (node.dataset.disabled) return\n\n if (isTypingAhead) {\n send({ type: \"TREE.TYPEAHEAD\", key: event.key })\n } else {\n keyMap.Enter?.(event)\n }\n },\n Enter(event) {\n if (node.dataset.disabled) return\n\n const isLink = target?.closest(\"a[href]\")\n if (!isLink) event.preventDefault()\n\n send({ type: isBranchNode ? \"BRANCH.CLICK\" : \"ITEM.CLICK\", id: nodeId, src: \"keyboard\" })\n },\n \"*\"(event) {\n if (node.dataset.disabled) return\n event.preventDefault()\n send({ type: \"EXPAND.SIBLINGS\", id: nodeId })\n },\n a(event) {\n if (!event.metaKey || node.dataset.disabled) return\n event.preventDefault()\n send({ type: \"SELECTED.ALL\", preventScroll: true, moveFocus: true })\n },\n }\n\n const key = getEventKey(event, state.context)\n const exec = keyMap[key]\n\n if (exec) {\n exec(event)\n return\n }\n\n if (!state.context.typeahead) return\n\n const isValidTypeahead = event.key.length === 1 && !isModifierKey(event)\n if (!isValidTypeahead) return\n\n send({ type: \"TREE.TYPEAHEAD\", key: event.key, id: nodeId })\n event.preventDefault()\n },\n onBlur(event) {\n if (contains(event.currentTarget, event.relatedTarget)) return\n send({ type: \"TREE.BLUR\" })\n },\n })\n },\n\n getItemState,\n getItemProps(props) {\n const itemState = getItemState(props)\n return normalize.element({\n ...parts.item.attrs,\n dir: state.context.dir,\n \"data-ownedby\": dom.getTreeId(state.context),\n \"data-item\": itemState.value,\n tabIndex: itemState.focused ? 0 : -1,\n \"data-focus\": dataAttr(itemState.focused),\n role: \"treeitem\",\n \"aria-current\": itemState.selected ? \"true\" : undefined,\n \"aria-selected\": itemState.disabled ? undefined : itemState.selected,\n \"data-selected\": dataAttr(itemState.selected),\n \"aria-disabled\": itemState.disabled,\n \"data-disabled\": dataAttr(itemState.disabled),\n \"aria-level\": props.depth,\n \"data-depth\": props.depth,\n style: {\n \"--depth\": props.depth,\n },\n onFocus(event) {\n event.stopPropagation()\n send({ type: \"ITEM.FOCUS\", id: itemState.value })\n },\n onClick(event) {\n if (itemState.disabled) return\n const isMetaKey = event.metaKey || event.ctrlKey\n send({ type: \"ITEM.CLICK\", id: itemState.value, shiftKey: event.shiftKey, ctrlKey: isMetaKey })\n event.stopPropagation()\n\n const isLink = event.currentTarget.matches(\"a[href]\")\n if (!isLink) event.preventDefault()\n },\n })\n },\n\n getItemTextProps(props) {\n const itemState = getItemState(props)\n return normalize.element({\n ...parts.itemText.attrs,\n \"data-disabled\": dataAttr(itemState.disabled),\n \"data-selected\": dataAttr(itemState.selected),\n \"data-focus\": dataAttr(itemState.focused),\n })\n },\n\n getItemIndicatorProps(props) {\n const itemState = getItemState(props)\n return normalize.element({\n ...parts.itemIndicator.attrs,\n \"aria-hidden\": true,\n \"data-disabled\": dataAttr(itemState.disabled),\n \"data-selected\": dataAttr(itemState.selected),\n \"data-focus\": dataAttr(itemState.focused),\n hidden: !itemState.selected,\n })\n },\n\n getBranchState,\n getBranchProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branch.attrs,\n \"data-depth\": props.depth,\n dir: state.context.dir,\n \"data-branch\": branchState.value,\n role: \"treeitem\",\n \"data-ownedby\": dom.getTreeId(state.context),\n \"aria-level\": props.depth,\n \"aria-selected\": branchState.disabled ? undefined : branchState.selected,\n \"data-selected\": dataAttr(branchState.selected),\n \"aria-expanded\": branchState.expanded,\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n \"aria-disabled\": branchState.disabled,\n \"data-disabled\": dataAttr(branchState.disabled),\n style: {\n \"--depth\": props.depth,\n },\n })\n },\n\n getBranchIndicatorProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branchIndicator.attrs,\n \"aria-hidden\": true,\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n \"data-disabled\": dataAttr(branchState.disabled),\n \"data-selected\": dataAttr(branchState.selected),\n \"data-focus\": dataAttr(branchState.focused),\n })\n },\n\n getBranchTriggerProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branchTrigger.attrs,\n role: \"button\",\n dir: state.context.dir,\n \"data-disabled\": dataAttr(branchState.disabled),\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n onClick(event) {\n if (branchState.disabled) return\n send({ type: \"BRANCH_TOGGLE.CLICK\", id: branchState.value })\n event.stopPropagation()\n },\n })\n },\n\n getBranchControlProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branchControl.attrs,\n role: \"button\",\n dir: state.context.dir,\n tabIndex: branchState.focused ? 0 : -1,\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n \"data-disabled\": dataAttr(branchState.disabled),\n \"data-selected\": dataAttr(branchState.selected),\n \"data-branch\": branchState.value,\n \"data-depth\": props.depth,\n onFocus(event) {\n send({ type: \"ITEM.FOCUS\", id: branchState.value })\n event.stopPropagation()\n },\n onClick(event) {\n if (branchState.disabled) return\n\n const isMetaKey = event.metaKey || event.ctrlKey\n send({ type: \"BRANCH.CLICK\", id: branchState.value, shiftKey: event.shiftKey, ctrlKey: isMetaKey })\n\n event.stopPropagation()\n },\n })\n },\n\n getBranchTextProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branchText.attrs,\n dir: state.context.dir,\n \"data-branch\": branchState.value,\n \"data-disabled\": dataAttr(branchState.disabled),\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n })\n },\n\n getBranchContentProps(props) {\n const branchState = getBranchState(props)\n return normalize.element({\n ...parts.branchContent.attrs,\n role: \"group\",\n dir: state.context.dir,\n \"data-branch\": branchState.value,\n \"data-state\": branchState.expanded ? \"open\" : \"closed\",\n hidden: !branchState.expanded,\n })\n },\n }\n}\n","import { createScope, getByTypeahead, isHTMLElement, isHiddenElement, query, queryAll } from \"@zag-js/dom-query\"\nimport type { MachineContext as Ctx } from \"./tree-view.types\"\n\ninterface TreeWalkerOpts {\n skipHidden?: boolean\n root?: HTMLElement | null\n}\n\nexport const dom = createScope({\n getRootId: (ctx: Ctx) => ctx.ids?.root ?? `tree-root:${ctx.id}`,\n getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `tree-label:${ctx.id}`,\n getTreeId: (ctx: Ctx) => ctx.ids?.tree ?? `tree-tree:${ctx.id}`,\n\n getNodeId(node: Node | null | undefined) {\n if (!isHTMLElement(node)) return null\n return node.dataset.branch ?? node.dataset.item ?? null\n },\n\n getNodeEl(ctx: Ctx, id: string) {\n const node = dom.getItemEl(ctx, id) ?? dom.getBranchEl(ctx, id)\n if (node?.dataset.part === \"branch\") {\n return query(node, \"[data-part=branch-control]\")\n }\n return node\n },\n\n getTreeEl(ctx: Ctx) {\n return dom.getById(ctx, dom.getTreeId(ctx))\n },\n\n getBranchEl(ctx: Ctx, id: string) {\n const selector = `[role=treeitem][data-branch=\"${id}\"]`\n return query(dom.getTreeEl(ctx), selector)\n },\n getItemEl(ctx: Ctx, id: string) {\n const selector = `[role=treeitem][data-item=\"${id}\"]`\n return query(dom.getTreeEl(ctx), selector)\n },\n getBranchControlEl(ctx: Ctx, id: string) {\n const selector = \"[data-part=branch-control]\"\n return query(dom.getBranchEl(ctx, id), selector)\n },\n\n getFocusedEl(ctx: Ctx) {\n if (!ctx.focusedValue) return null\n return dom.getById(ctx, ctx.focusedValue)\n },\n\n focusNode(node: Node | Element | null | undefined, options?: FocusOptions) {\n if (isHTMLElement(node)) node.focus(options)\n },\n\n getNodeDepth(node: HTMLElement | null) {\n return node?.dataset.depth ? Number(node.dataset.depth) : -1\n },\n\n getTreeWalker(ctx: Ctx, opts?: TreeWalkerOpts) {\n const { skipHidden = true, root } = opts ?? {}\n\n const treeEl = root || dom.getTreeEl(ctx)\n if (!treeEl) throw new Error(\"Tree or branch root not found\")\n\n const doc = dom.getDoc(ctx)\n\n return doc.createTreeWalker(treeEl, NodeFilter.SHOW_ELEMENT, {\n acceptNode(node: HTMLElement) {\n if (skipHidden && isHiddenElement(node)) {\n return NodeFilter.FILTER_REJECT\n }\n\n if (node.role === \"treeitem\" && node.dataset.part !== \"branch\") {\n return NodeFilter.FILTER_ACCEPT\n }\n\n if (node.role === \"button\" && node.dataset.part === \"branch-control\") {\n return NodeFilter.FILTER_ACCEPT\n }\n\n return NodeFilter.FILTER_SKIP\n },\n })\n },\n\n getMatchingEl(ctx: Ctx, key: string) {\n const walker = dom.getTreeWalker(ctx)\n\n const elements: HTMLElement[] = []\n let node = walker.firstChild()\n\n while (node) {\n if (isHTMLElement(node)) elements.push(node)\n node = walker.nextNode()\n }\n\n return getByTypeahead(elements, {\n state: ctx.typeaheadState,\n key,\n activeId: ctx.focusedValue,\n itemToId: (v) => dom.getNodeId(v) ?? v.id,\n })\n },\n\n getTreeNodes(ctx: Ctx, options: TreeWalkerOpts = {}) {\n const walker = dom.getTreeWalker(ctx, options)\n\n const nodes: HTMLElement[] = []\n let node = walker.firstChild()\n\n while (node) {\n if (isHTMLElement(node)) {\n nodes.push(node)\n }\n node = walker.nextNode()\n }\n\n return nodes\n },\n\n getBranchNodes(ctx: Ctx, depth: number | null) {\n if (depth === -1) return []\n return queryAll(dom.getTreeEl(ctx), `[role=treeitem][data-part=branch][data-depth=\"${depth}\"]`)\n },\n\n getNodesInRange(nodes: HTMLElement[], startNode: HTMLElement, endNode: HTMLElement) {\n const nextSet = new Set<string>()\n\n nodes.forEach((node) => {\n const nodeId = dom.getNodeId(node)\n if (nodeId == null) return\n\n // compare node position with firstSelectedEl and focusedEl\n // if node is between firstSelectedEl and focusedEl, add it to nextSet\n if (node === startNode || node === endNode) {\n nextSet.add(nodeId)\n return\n }\n\n // use node.compareDocumentPosition to compare node position\n // https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition\n\n const startPos = node.compareDocumentPosition(startNode)\n const endPos = node.compareDocumentPosition(endNode)\n\n // if node is before firstSelectedEl and after focusedEl, add it to nextSet\n if (startPos & Node.DOCUMENT_POSITION_FOLLOWING && endPos & Node.DOCUMENT_POSITION_PRECEDING) {\n nextSet.add(nodeId)\n return\n }\n\n // if node is after firstSelectedEl and before focusedEl, add it to nextSet\n if (startPos & Node.DOCUMENT_POSITION_PRECEDING && endPos & Node.DOCUMENT_POSITION_FOLLOWING) {\n nextSet.add(nodeId)\n return\n }\n })\n\n return Array.from(nextSet)\n },\n})\n","import { createMachine, guards } from \"@zag-js/core\"\nimport { getByTypeahead, isHTMLElement, observeChildren } from \"@zag-js/dom-query\"\nimport { compact } from \"@zag-js/utils\"\nimport { dom } from \"./tree-view.dom\"\nimport type { MachineContext, MachineState, UserDefinedContext } from \"./tree-view.types\"\n\nconst { and } = guards\n\nexport function machine(userContext: UserDefinedContext) {\n const ctx = compact(userContext)\n return createMachine<MachineContext, MachineState>(\n {\n id: \"tree-view\",\n initial: \"idle\",\n context: {\n expandedValue: [],\n selectedValue: [],\n focusedValue: null,\n expandOnClick: true,\n selectionMode: \"single\",\n typeahead: true,\n ...ctx,\n typeaheadState: getByTypeahead.defaultOptions,\n },\n\n computed: {\n isMultipleSelection: (ctx) => ctx.selectionMode === \"multiple\",\n },\n\n on: {\n \"EXPANDED.SET\": {\n actions: [\"setExpanded\"],\n },\n \"SELECTED.SET\": {\n actions: [\"setSelected\"],\n },\n \"SELECTED.ALL\": [\n {\n guard: and(\"isMultipleSelection\", \"moveFocus\"),\n actions: [\"selectAllItems\", \"focusTreeLastItem\"],\n },\n {\n guard: \"isMultipleSelection\",\n actions: [\"selectAllItems\"],\n },\n ],\n \"EXPANDED.ALL\": {\n actions: [\"expandAllBranches\"],\n },\n },\n\n activities: [\"trackChildrenMutation\"],\n\n entry: [\"setFocusableNode\"],\n\n states: {\n idle: {\n on: {\n \"ITEM.FOCUS\": {\n actions: [\"setFocusedItem\"],\n },\n \"ITEM.ARROW_DOWN\": [\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"focusTreeNextItem\", \"extendSelectionToNextItem\"],\n },\n {\n actions: [\"focusTreeNextItem\"],\n },\n ],\n \"ITEM.ARROW_UP\": [\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"focusTreePrevItem\", \"extendSelectionToPrevItem\"],\n },\n {\n actions: [\"focusTreePrevItem\"],\n },\n ],\n \"ITEM.ARROW_LEFT\": {\n actions: [\"focusBranchControl\"],\n },\n \"BRANCH.ARROW_LEFT\": [\n {\n guard: \"isBranchExpanded\",\n actions: [\"collapseBranch\"],\n },\n {\n actions: [\"focusBranchControl\"],\n },\n ],\n \"BRANCH.ARROW_RIGHT\": [\n {\n guard: and(\"isBranchFocused\", \"isBranchExpanded\"),\n actions: [\"focusBranchFirstItem\"],\n },\n {\n actions: [\"expandBranch\"],\n },\n ],\n \"EXPAND.SIBLINGS\": {\n actions: [\"expandSiblingBranches\"],\n },\n \"ITEM.HOME\": [\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"extendSelectionToFirstItem\", \"focusTreeFirstItem\"],\n },\n {\n actions: [\"focusTreeFirstItem\"],\n },\n ],\n \"ITEM.END\": [\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"extendSelectionToLastItem\", \"focusTreeLastItem\"],\n },\n {\n actions: [\"focusTreeLastItem\"],\n },\n ],\n \"ITEM.CLICK\": [\n {\n guard: and(\"isCtrlKey\", \"isMultipleSelection\"),\n actions: [\"addOrRemoveItemFromSelection\"],\n },\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"extendSelectionToItem\"],\n },\n {\n actions: [\"selectItem\"],\n },\n ],\n \"BRANCH.CLICK\": [\n {\n guard: and(\"isCtrlKey\", \"isMultipleSelection\"),\n actions: [\"addOrRemoveItemFromSelection\"],\n },\n {\n guard: and(\"isShiftKey\", \"isMultipleSelection\"),\n actions: [\"extendSelectionToItem\"],\n },\n {\n guard: \"openOnClick\",\n actions: [\"selectItem\", \"toggleBranch\"],\n },\n {\n actions: [\"selectItem\"],\n },\n ],\n \"BRANCH_TOGGLE.CLICK\": {\n actions: [\"toggleBranch\"],\n },\n \"TREE.TYPEAHEAD\": {\n actions: [\"focusMatchedItem\"],\n },\n \"TREE.BLUR\": {\n actions: [\"clearFocusedItem\", \"setFocusableNode\"],\n },\n },\n },\n },\n },\n {\n guards: {\n isBranchFocused: (ctx, evt) => ctx.focusedValue === evt.id,\n isBranchExpanded: (ctx, evt) => ctx.expandedValue.includes(evt.id),\n isShiftKey: (_ctx, evt) => evt.shiftKey,\n isCtrlKey: (_ctx, evt) => evt.ctrlKey,\n hasSelectedItems: (ctx) => ctx.selectedValue.length > 0,\n isMultipleSelection: (ctx) => ctx.isMultipleSelection,\n moveFocus: (_ctx, evt) => !!evt.moveFocus,\n openOnClick: (ctx) => !!ctx.expandOnClick,\n },\n activities: {\n trackChildrenMutation(ctx, _evt, { send }) {\n const treeEl = dom.getTreeEl(ctx)\n return observeChildren(treeEl, {\n callback(records) {\n const removedNodes = records\n .flatMap((r) => Array.from(r.removedNodes))\n .filter((node) => {\n if (!isHTMLElement(node)) return false\n return node.matches(\"[role=treeitem]\") || node.matches(\"[role=group]\")\n })\n\n if (!removedNodes.length) return\n\n let elementToFocus: HTMLElement | null = null\n records.forEach((record) => {\n if (isHTMLElement(record.nextSibling)) {\n elementToFocus = record.nextSibling\n } else if (isHTMLElement(record.previousSibling)) {\n elementToFocus = record.previousSibling\n }\n })\n\n if (elementToFocus) {\n dom.focusNode(elementToFocus)\n }\n\n const removedIds: Set<string> = new Set()\n removedNodes.forEach((node) => {\n const nodeId = dom.getNodeId(node)\n if (isHTMLElement(node) && nodeId != null) {\n removedIds.add(nodeId)\n }\n })\n\n const nextSet = new Set(ctx.selectedValue)\n removedIds.forEach((id) => nextSet.delete(id))\n send({ type: \"SELECTED.SET\", value: removedIds })\n },\n })\n },\n },\n actions: {\n setFocusableNode(ctx) {\n if (ctx.focusedValue) return\n\n if (ctx.selectedValue.length > 0) {\n const firstSelectedId = Array.from(ctx.selectedValue)[0]\n ctx.focusedValue = firstSelectedId\n return\n }\n\n const walker = dom.getTreeWalker(ctx)\n const firstItem = walker.firstChild()\n\n if (!isHTMLElement(firstItem)) return\n // don't use set.focused here because it will trigger focusChange event\n ctx.focusedValue = dom.getNodeId(firstItem)\n },\n selectItem(ctx, evt) {\n set.selected(ctx, [evt.id])\n },\n setFocusedItem(ctx, evt) {\n set.focused(ctx, evt.id)\n },\n clearFocusedItem(ctx) {\n set.focused(ctx, null)\n },\n clearSelectedItem(ctx) {\n set.selected(ctx, [])\n },\n toggleBranch(ctx, evt) {\n const nextSet = new Set(ctx.expandedValue)\n\n if (nextSet.has(evt.id)) {\n nextSet.delete(evt.id)\n // collapseEffect(ctx, evt)\n } else {\n nextSet.add(evt.id)\n }\n\n set.expanded(ctx, Array.from(nextSet))\n },\n expandBranch(ctx, evt) {\n const nextSet = new Set(ctx.expandedValue)\n nextSet.add(evt.id)\n set.expanded(ctx, Array.from(nextSet))\n },\n collapseBranch(ctx, evt) {\n const nextSet = new Set(ctx.expandedValue)\n nextSet.delete(evt.id)\n set.expanded(ctx, Array.from(nextSet))\n },\n setExpanded(ctx, evt) {\n set.expanded(ctx, evt.value)\n },\n setSelected(ctx, evt) {\n set.selected(ctx, evt.value)\n },\n focusTreeFirstItem(ctx) {\n const walker = dom.getTreeWalker(ctx)\n dom.focusNode(walker.firstChild())\n },\n focusTreeLastItem(ctx, evt) {\n const walker = dom.getTreeWalker(ctx)\n dom.focusNode(walker.lastChild(), { preventScroll: evt.preventScroll })\n },\n focusBranchFirstItem(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const walker = dom.getTreeWalker(ctx)\n\n walker.currentNode = focusedEl\n dom.focusNode(walker.nextNode())\n },\n focusTreeNextItem(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const walker = dom.getTreeWalker(ctx)\n\n if (ctx.focusedValue) {\n walker.currentNode = focusedEl\n const nextNode = walker.nextNode()\n dom.focusNode(nextNode)\n } else {\n dom.focusNode(walker.firstChild())\n }\n },\n focusTreePrevItem(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const walker = dom.getTreeWalker(ctx)\n\n if (ctx.focusedValue) {\n walker.currentNode = focusedEl\n const prevNode = walker.previousNode()\n dom.focusNode(prevNode)\n } else {\n dom.focusNode(walker.lastChild())\n }\n },\n focusBranchControl(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const parentDepth = Number(focusedEl.dataset.depth) - 1\n if (parentDepth < 0) return\n\n const branchSelector = `[data-part=branch][data-depth=\"${parentDepth}\"]`\n const closestBranch = focusedEl.closest(branchSelector)\n\n const branchControl = closestBranch?.querySelector(\"[data-part=branch-control]\")\n dom.focusNode(branchControl)\n },\n selectAllItems(ctx) {\n const nextSet = new Set<string>()\n const walker = dom.getTreeWalker(ctx)\n let node = walker.firstChild()\n while (node) {\n const nodeId = dom.getNodeId(node)\n if (isHTMLElement(node) && nodeId != null) {\n nextSet.add(nodeId)\n }\n node = walker.nextNode()\n }\n set.selected(ctx, Array.from(nextSet))\n },\n focusMatchedItem(ctx, evt) {\n dom.focusNode(dom.getMatchingEl(ctx, evt.key))\n },\n addOrRemoveItemFromSelection(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const nextSet = new Set(ctx.selectedValue)\n\n const nodeId = dom.getNodeId(focusedEl)\n if (nodeId == null) return\n\n if (nextSet.has(nodeId)) {\n nextSet.delete(nodeId)\n } else {\n nextSet.add(nodeId)\n }\n\n set.selected(ctx, Array.from(nextSet))\n },\n expandAllBranches(ctx) {\n const nextSet = new Set<string>()\n const walker = dom.getTreeWalker(ctx, { skipHidden: false })\n while (walker.nextNode()) {\n const node = walker.currentNode\n const nodeId = dom.getNodeId(node)\n if (isHTMLElement(node) && node.dataset.part === \"branch-control\" && nodeId != null) {\n nextSet.add(nodeId)\n }\n }\n set.expanded(ctx, Array.from(nextSet))\n },\n expandSiblingBranches(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n const nodes = dom.getBranchNodes(ctx, dom.getNodeDepth(focusedEl))\n\n const nextSet = new Set<string>()\n nodes.forEach((node) => {\n const nodeId = dom.getNodeId(node)\n if (nodeId == null) return\n nextSet.add(nodeId)\n })\n\n set.expanded(ctx, Array.from(nextSet))\n },\n extendSelectionToItem(ctx, evt) {\n const focusedEl = dom.getNodeEl(ctx, evt.id)\n if (!focusedEl) return\n\n const nodes = dom.getTreeNodes(ctx)\n const selectedIds = Array.from(ctx.selectedValue)\n const anchorEl = dom.getNodeEl(ctx, selectedIds[0]) || nodes[0]\n\n const nextSet = dom.getNodesInRange(nodes, anchorEl, focusedEl)\n\n set.selected(ctx, nextSet)\n },\n extendSelectionToNextItem(ctx, evt) {\n const nodeId = evt.id\n\n const currentNode = dom.getNodeEl(ctx, nodeId)\n if (!currentNode) return\n\n const walker = dom.getTreeWalker(ctx)\n walker.currentNode = currentNode\n\n const nextNode = walker.nextNode()\n dom.focusNode(nextNode)\n\n // extend selection to nextNode (preserve the anchor node)\n const selectedIds = new Set(ctx.selectedValue)\n const nextNodeId = dom.getNodeId(nextNode)\n\n if (nextNodeId == null) return\n\n if (selectedIds.has(nodeId) && selectedIds.has(nextNodeId)) {\n selectedIds.delete(nodeId)\n } else if (!selectedIds.has(nextNodeId)) {\n selectedIds.add(nextNodeId)\n }\n\n set.selected(ctx, Array.from(selectedIds))\n },\n extendSelectionToPrevItem(ctx, evt) {\n const nodeId = evt.id\n\n const currentNode = dom.getNodeEl(ctx, nodeId)\n if (!currentNode) return\n\n const walker = dom.getTreeWalker(ctx)\n walker.currentNode = currentNode\n\n const prevNode = walker.previousNode()\n dom.focusNode(prevNode)\n\n // extend selection to prevNode (preserve the anchor node)\n const selectedIds = new Set(ctx.selectedValue)\n const prevNodeId = dom.getNodeId(prevNode)\n\n if (prevNodeId == null) return\n\n if (selectedIds.has(nodeId) && selectedIds.has(prevNodeId)) {\n selectedIds.delete(nodeId)\n } else if (!selectedIds.has(prevNodeId)) {\n selectedIds.add(prevNodeId)\n }\n\n set.selected(ctx, Array.from(selectedIds))\n },\n extendSelectionToFirstItem(ctx) {\n const nodes = dom.getTreeNodes(ctx)\n\n const anchorEl = dom.getNodeEl(ctx, [...ctx.selectedValue][0]) || nodes[0]\n const focusedEl = nodes[0]\n\n const selectedIds = dom.getNodesInRange(nodes, anchorEl, focusedEl)\n set.selected(ctx, selectedIds)\n },\n extendSelectionToLastItem(ctx) {\n const nodes = dom.getTreeNodes(ctx)\n\n const anchorEl = dom.getNodeEl(ctx, [...ctx.selectedValue][0]) || nodes[0]\n const focusedEl = nodes[nodes.length - 1]\n\n const selectedIds = dom.getNodesInRange(nodes, anchorEl, focusedEl)\n set.selected(ctx, selectedIds)\n },\n },\n },\n )\n}\n\nconst invoke = {\n focusChange(ctx: MachineContext) {\n ctx.onFocusChange?.({ focusedValue: ctx.focusedValue! })\n },\n expandedChange(ctx: MachineContext) {\n ctx.onExpandedChange?.({\n expandedValue: Array.from(ctx.expandedValue),\n focusedValue: ctx.focusedValue!,\n })\n },\n selectionChange(ctx: MachineContext) {\n ctx.onSelectionChange?.({\n selectedValue: Array.from(ctx.selectedValue),\n focusedValue: ctx.focusedValue,\n })\n },\n}\n\nconst set = {\n selected(ctx: MachineContext, value: string[]) {\n ctx.selectedValue = value\n invoke.selectionChange(ctx)\n },\n focused(ctx: MachineContext, value: string | null) {\n ctx.focusedValue = value\n invoke.focusChange(ctx)\n },\n expanded(ctx: MachineContext, value: string[]) {\n ctx.expandedValue = value\n invoke.expandedChange(ctx)\n },\n}\n"],"mappings":"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","names":["event","getByTypeahead","isHTMLElement","getByTypeahead","ctx","isHTMLElement"]}
export { anatomy } from "./tree-view.anatomy"
export { connect } from "./tree-view.connect"
export { machine } from "./tree-view.machine"
export type {
MachineApi as Api,
BranchProps,
BranchState,
UserDefinedContext as Context,
ElementIds,
ExpandedChangeDetails,
FocusChangeDetails,
ItemProps,
ItemState,
SelectionChangeDetails,
Service,
} from "./tree-view.types"
import { createAnatomy } from "@zag-js/anatomy"
export const anatomy = createAnatomy("tree-view").parts(
"root",
"label",
"tree",
"item",
"itemIndicator",
"itemText",
"branch",
"branchControl",
"branchTrigger",
"branchContent",
"branchText",
"branchIndicator",
)
export const parts = anatomy.build()
import { getEventKey, isModifierKey, type EventKeyMap } from "@zag-js/dom-event"
import { contains, dataAttr, getEventTarget, isComposingEvent, isEditableElement } from "@zag-js/dom-query"
import type { NormalizeProps, PropTypes } from "@zag-js/types"
import { parts } from "./tree-view.anatomy"
import { dom } from "./tree-view.dom"
import type { BranchProps, BranchState, ItemProps, ItemState, MachineApi, Send, State } from "./tree-view.types"
export function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {
const expandedValue = Array.from(state.context.expandedValue)
const selectedValue = Array.from(state.context.selectedValue)
const isTypingAhead = state.context.isTypingAhead
const focusedValue = state.context.focusedValue
function getItemState(props: ItemProps): ItemState {
return {
value: props.value,
disabled: Boolean(props.disabled),
focused: focusedValue === props.value,
selected: selectedValue.includes(props.value),
}
}
function getBranchState(props: BranchProps): BranchState {
return {
value: props.value,
disabled: Boolean(props.disabled),
focused: focusedValue === props.value,
expanded: expandedValue.includes(props.value),
selected: selectedValue.includes(props.value),
}
}
return {
expandedValue: expandedValue,
selectedValue: selectedValue,
expand(value) {
if (!value) {
send({ type: "EXPANDED.ALL" })
return
}
const nextValue = new Set(expandedValue)
value.forEach((id) => nextValue.add(id))
send({ type: "EXPANDED.SET", value: nextValue, src: "expand" })
},
collapse(value) {
if (!value) {
send({ type: "EXPANDED.SET", value: new Set([]), src: "collapseAll" })
return
}
const nextValue = new Set(expandedValue)
value.forEach((id) => nextValue.delete(id))
send({ type: "EXPANDED.SET", value: nextValue, src: "collapse" })
},
deselect(value) {
if (!value) {
send({ type: "SELECTED.SET", value: new Set([]), src: "deselectAll" })
return
}
const nextValue = new Set(selectedValue)
value.forEach((id) => nextValue.delete(id))
send({ type: "SELECTED.SET", value: nextValue, src: "deselect" })
},
select(value) {
if (!value) {
send({ type: "SELECTED.ALL" })
return
}
const nextValue = new Set()
if (state.context.selectionMode === "single") {
// For single selection, only add the last item
if (value.length > 0) {
nextValue.add(value[value.length - 1])
}
} else {
// For multiple selection, add all items
value.forEach((id) => nextValue.add(id))
selectedValue.forEach((id) => nextValue.add(id))
}
send({ type: "SELECTED.SET", value: nextValue, src: "select" })
},
focusBranch(id) {
dom.getBranchControlEl(state.context, id)?.focus()
},
focusItem(id) {
dom.getItemEl(state.context, id)?.focus()
},
getRootProps() {
return normalize.element({
...parts.root.attrs,
id: dom.getRootId(state.context),
dir: state.context.dir,
})
},
getLabelProps() {
return normalize.element({
...parts.label.attrs,
id: dom.getLabelId(state.context),
dir: state.context.dir,
})
},
getTreeProps() {
return normalize.element({
...parts.tree.attrs,
id: dom.getTreeId(state.context),
dir: state.context.dir,
role: "tree",
"aria-label": "Tree View",
"aria-labelledby": dom.getLabelId(state.context),
"aria-multiselectable": state.context.selectionMode === "multiple" || undefined,
onKeyDown(event) {
if (event.defaultPrevented) return
if (isComposingEvent(event)) return
const target = getEventTarget<HTMLElement>(event)
// allow typing in input elements within the tree
if (isEditableElement(target)) return
const node = target?.closest<HTMLElement>("[role=treeitem]")
if (!node) return
const nodeId = dom.getNodeId(node)
if (nodeId == null) {
console.warn(`Node id not found for node`, node)
return
}
const isBranchNode = !!target?.dataset.branch
const keyMap: EventKeyMap = {
ArrowDown(event) {
if (isModifierKey(event)) return
event.preventDefault()
send({ type: "ITEM.ARROW_DOWN", id: nodeId, shiftKey: event.shiftKey })
},
ArrowUp(event) {
if (isModifierKey(event)) return
event.preventDefault()
send({ type: "ITEM.ARROW_UP", id: nodeId, shiftKey: event.shiftKey })
},
ArrowLeft(event) {
if (isModifierKey(event) || node.dataset.disabled) return
event.preventDefault()
send({ type: isBranchNode ? "BRANCH.ARROW_LEFT" : "ITEM.ARROW_LEFT", id: nodeId })
},
ArrowRight(event) {
if (!isBranchNode || node.dataset.disabled) return
event.preventDefault()
send({ type: "BRANCH.ARROW_RIGHT", id: nodeId })
},
Home(event) {
if (isModifierKey(event)) return
event.preventDefault()
send({ type: "ITEM.HOME", id: nodeId, shiftKey: event.shiftKey })
},
End(event) {
if (isModifierKey(event)) return
event.preventDefault()
send({ type: "ITEM.END", id: nodeId, shiftKey: event.shiftKey })
},
Space(event) {
if (node.dataset.disabled) return
if (isTypingAhead) {
send({ type: "TREE.TYPEAHEAD", key: event.key })
} else {
keyMap.Enter?.(event)
}
},
Enter(event) {
if (node.dataset.disabled) return
const isLink = target?.closest("a[href]")
if (!isLink) event.preventDefault()
send({ type: isBranchNode ? "BRANCH.CLICK" : "ITEM.CLICK", id: nodeId, src: "keyboard" })
},
"*"(event) {
if (node.dataset.disabled) return
event.preventDefault()
send({ type: "EXPAND.SIBLINGS", id: nodeId })
},
a(event) {
if (!event.metaKey || node.dataset.disabled) return
event.preventDefault()
send({ type: "SELECTED.ALL", preventScroll: true, moveFocus: true })
},
}
const key = getEventKey(event, state.context)
const exec = keyMap[key]
if (exec) {
exec(event)
return
}
if (!state.context.typeahead) return
const isValidTypeahead = event.key.length === 1 && !isModifierKey(event)
if (!isValidTypeahead) return
send({ type: "TREE.TYPEAHEAD", key: event.key, id: nodeId })
event.preventDefault()
},
onBlur(event) {
if (contains(event.currentTarget, event.relatedTarget)) return
send({ type: "TREE.BLUR" })
},
})
},
getItemState,
getItemProps(props) {
const itemState = getItemState(props)
return normalize.element({
...parts.item.attrs,
dir: state.context.dir,
"data-ownedby": dom.getTreeId(state.context),
"data-item": itemState.value,
tabIndex: itemState.focused ? 0 : -1,
"data-focus": dataAttr(itemState.focused),
role: "treeitem",
"aria-current": itemState.selected ? "true" : undefined,
"aria-selected": itemState.disabled ? undefined : itemState.selected,
"data-selected": dataAttr(itemState.selected),
"aria-disabled": itemState.disabled,
"data-disabled": dataAttr(itemState.disabled),
"aria-level": props.depth,
"data-depth": props.depth,
style: {
"--depth": props.depth,
},
onFocus(event) {
event.stopPropagation()
send({ type: "ITEM.FOCUS", id: itemState.value })
},
onClick(event) {
if (itemState.disabled) return
const isMetaKey = event.metaKey || event.ctrlKey
send({ type: "ITEM.CLICK", id: itemState.value, shiftKey: event.shiftKey, ctrlKey: isMetaKey })
event.stopPropagation()
const isLink = event.currentTarget.matches("a[href]")
if (!isLink) event.preventDefault()
},
})
},
getItemTextProps(props) {
const itemState = getItemState(props)
return normalize.element({
...parts.itemText.attrs,
"data-disabled": dataAttr(itemState.disabled),
"data-selected": dataAttr(itemState.selected),
"data-focus": dataAttr(itemState.focused),
})
},
getItemIndicatorProps(props) {
const itemState = getItemState(props)
return normalize.element({
...parts.itemIndicator.attrs,
"aria-hidden": true,
"data-disabled": dataAttr(itemState.disabled),
"data-selected": dataAttr(itemState.selected),
"data-focus": dataAttr(itemState.focused),
hidden: !itemState.selected,
})
},
getBranchState,
getBranchProps(props) {
const branchState = getBranchState(props)
return normalize.element({
...parts.branch.attrs,
"data-depth": props.depth,
dir: state.context.dir,
"data-branch": branchState.value,
role: "treeitem",
"data-ownedby": dom.getTreeId(state.context),
"aria-level": props.depth,
"aria-selected": branchState.disabled ? undefined : branchState.selected,
"data-selected": dataAttr(branchState.selected),
"aria-expanded": branchState.expanded,
"data-state": branchState.expanded ? "open" : "closed",
"aria-disabled": branchState.disabled,
"data-disabled": dataAttr(branchState.disabled),
style: {
"--depth": props.depth,
},
})
},
getBranchIndicatorProps(props) {
const branchState = getBranchState(props)
return normalize.element({
...parts.branchIndicator.attrs,
"aria-hidden": true,
"data-state": branchState.expanded ? "open" : "closed",
"data-disabled": dataAttr(branchState.disabled),
"data-selected": dataAttr(branchState.selected),
"data-focus": dataAttr(branchState.focused),
})
},
getBranchTriggerProps(props) {
const branchState = getBranchState(props)
return normalize.element({
...parts.branchTrigger.attrs,
role: "button",
dir: state.context.dir,
"data-disabled": dataAttr(branchState.disabled),
"data-state": branchState.expanded ? "open" : "closed",
onClick(event) {
if (branchState.disabled) return
send({ type: "BRANCH_TOGGLE.CLICK", id: branchState.value })
event.stopPropagation()
},
})
},
getBranchControlProps(props) {
const branchState = getBranchState(props)
return normalize.element({
...parts.branchControl.attrs,
role: "button",
dir: state.context.dir,
tabIndex: branchState.focused ? 0 : -1,
"data-state": branchState.expanded ? "open" : "closed",
"data-disabled": dataAttr(branchState.disabled),
"data-selected": dataAttr(branchState.selected),
"data-branch": branchState.value,
"data-depth": props.depth,
onFocus(event) {
send({ type: "ITEM.FOCUS", id: branchState.value })
event.stopPropagation()
},
onClick(event) {
if (branchState.disabled) return
const isMetaKey = event.metaKey || event.ctrlKey
send({ type: "BRANCH.CLICK", id: branchState.value, shiftKey: event.shiftKey, ctrlKey: isMetaKey })
event.stopPropagation()
},
})
},
getBranchTextProps(props) {
const branchState = getBranchState(props)
return normalize.element({
...parts.branchText.attrs,
dir: state.context.dir,
"data-branch": branchState.value,
"data-disabled": dataAttr(branchState.disabled),
"data-state": branchState.expanded ? "open" : "closed",
})
},
getBranchContentProps(props) {
const branchState = getBranchState(props)
return normalize.element({
...parts.branchContent.attrs,
role: "group",
dir: state.context.dir,
"data-branch": branchState.value,
"data-state": branchState.expanded ? "open" : "closed",
hidden: !branchState.expanded,
})
},
}
}
import { createScope, getByTypeahead, isHTMLElement, isHiddenElement, query, queryAll } from "@zag-js/dom-query"
import type { MachineContext as Ctx } from "./tree-view.types"
interface TreeWalkerOpts {
skipHidden?: boolean
root?: HTMLElement | null
}
export const dom = createScope({
getRootId: (ctx: Ctx) => ctx.ids?.root ?? `tree-root:${ctx.id}`,
getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `tree-label:${ctx.id}`,
getTreeId: (ctx: Ctx) => ctx.ids?.tree ?? `tree-tree:${ctx.id}`,
getNodeId(node: Node | null | undefined) {
if (!isHTMLElement(node)) return null
return node.dataset.branch ?? node.dataset.item ?? null
},
getNodeEl(ctx: Ctx, id: string) {
const node = dom.getItemEl(ctx, id) ?? dom.getBranchEl(ctx, id)
if (node?.dataset.part === "branch") {
return query(node, "[data-part=branch-control]")
}
return node
},
getTreeEl(ctx: Ctx) {
return dom.getById(ctx, dom.getTreeId(ctx))
},
getBranchEl(ctx: Ctx, id: string) {
const selector = `[role=treeitem][data-branch="${id}"]`
return query(dom.getTreeEl(ctx), selector)
},
getItemEl(ctx: Ctx, id: string) {
const selector = `[role=treeitem][data-item="${id}"]`
return query(dom.getTreeEl(ctx), selector)
},
getBranchControlEl(ctx: Ctx, id: string) {
const selector = "[data-part=branch-control]"
return query(dom.getBranchEl(ctx, id), selector)
},
getFocusedEl(ctx: Ctx) {
if (!ctx.focusedValue) return null
return dom.getById(ctx, ctx.focusedValue)
},
focusNode(node: Node | Element | null | undefined, options?: FocusOptions) {
if (isHTMLElement(node)) node.focus(options)
},
getNodeDepth(node: HTMLElement | null) {
return node?.dataset.depth ? Number(node.dataset.depth) : -1
},
getTreeWalker(ctx: Ctx, opts?: TreeWalkerOpts) {
const { skipHidden = true, root } = opts ?? {}
const treeEl = root || dom.getTreeEl(ctx)
if (!treeEl) throw new Error("Tree or branch root not found")
const doc = dom.getDoc(ctx)
return doc.createTreeWalker(treeEl, NodeFilter.SHOW_ELEMENT, {
acceptNode(node: HTMLElement) {
if (skipHidden && isHiddenElement(node)) {
return NodeFilter.FILTER_REJECT
}
if (node.role === "treeitem" && node.dataset.part !== "branch") {
return NodeFilter.FILTER_ACCEPT
}
if (node.role === "button" && node.dataset.part === "branch-control") {
return NodeFilter.FILTER_ACCEPT
}
return NodeFilter.FILTER_SKIP
},
})
},
getMatchingEl(ctx: Ctx, key: string) {
const walker = dom.getTreeWalker(ctx)
const elements: HTMLElement[] = []
let node = walker.firstChild()
while (node) {
if (isHTMLElement(node)) elements.push(node)
node = walker.nextNode()
}
return getByTypeahead(elements, {
state: ctx.typeaheadState,
key,
activeId: ctx.focusedValue,
itemToId: (v) => dom.getNodeId(v) ?? v.id,
})
},
getTreeNodes(ctx: Ctx, options: TreeWalkerOpts = {}) {
const walker = dom.getTreeWalker(ctx, options)
const nodes: HTMLElement[] = []
let node = walker.firstChild()
while (node) {
if (isHTMLElement(node)) {
nodes.push(node)
}
node = walker.nextNode()
}
return nodes
},
getBranchNodes(ctx: Ctx, depth: number | null) {
if (depth === -1) return []
return queryAll(dom.getTreeEl(ctx), `[role=treeitem][data-part=branch][data-depth="${depth}"]`)
},
getNodesInRange(nodes: HTMLElement[], startNode: HTMLElement, endNode: HTMLElement) {
const nextSet = new Set<string>()
nodes.forEach((node) => {
const nodeId = dom.getNodeId(node)
if (nodeId == null) return
// compare node position with firstSelectedEl and focusedEl
// if node is between firstSelectedEl and focusedEl, add it to nextSet
if (node === startNode || node === endNode) {
nextSet.add(nodeId)
return
}
// use node.compareDocumentPosition to compare node position
// https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
const startPos = node.compareDocumentPosition(startNode)
const endPos = node.compareDocumentPosition(endNode)
// if node is before firstSelectedEl and after focusedEl, add it to nextSet
if (startPos & Node.DOCUMENT_POSITION_FOLLOWING && endPos & Node.DOCUMENT_POSITION_PRECEDING) {
nextSet.add(nodeId)
return
}
// if node is after firstSelectedEl and before focusedEl, add it to nextSet
if (startPos & Node.DOCUMENT_POSITION_PRECEDING && endPos & Node.DOCUMENT_POSITION_FOLLOWING) {
nextSet.add(nodeId)
return
}
})
return Array.from(nextSet)
},
})
import { createMachine, guards } from "@zag-js/core"
import { getByTypeahead, isHTMLElement, observeChildren } from "@zag-js/dom-query"
import { compact } from "@zag-js/utils"
import { dom } from "./tree-view.dom"
import type { MachineContext, MachineState, UserDefinedContext } from "./tree-view.types"
const { and } = guards
export function machine(userContext: UserDefinedContext) {
const ctx = compact(userContext)
return createMachine<MachineContext, MachineState>(
{
id: "tree-view",
initial: "idle",
context: {
expandedValue: [],
selectedValue: [],
focusedValue: null,
expandOnClick: true,
selectionMode: "single",
typeahead: true,
...ctx,
typeaheadState: getByTypeahead.defaultOptions,
},
computed: {
isMultipleSelection: (ctx) => ctx.selectionMode === "multiple",
},
on: {
"EXPANDED.SET": {
actions: ["setExpanded"],
},
"SELECTED.SET": {
actions: ["setSelected"],
},
"SELECTED.ALL": [
{
guard: and("isMultipleSelection", "moveFocus"),
actions: ["selectAllItems", "focusTreeLastItem"],
},
{
guard: "isMultipleSelection",
actions: ["selectAllItems"],
},
],
"EXPANDED.ALL": {
actions: ["expandAllBranches"],
},
},
activities: ["trackChildrenMutation"],
entry: ["setFocusableNode"],
states: {
idle: {
on: {
"ITEM.FOCUS": {
actions: ["setFocusedItem"],
},
"ITEM.ARROW_DOWN": [
{
guard: and("isShiftKey", "isMultipleSelection"),
actions: ["focusTreeNextItem", "extendSelectionToNextItem"],
},
{
actions: ["focusTreeNextItem"],
},
],
"ITEM.ARROW_UP": [
{
guard: and("isShiftKey", "isMultipleSelection"),
actions: ["focusTreePrevItem", "extendSelectionToPrevItem"],
},
{
actions: ["focusTreePrevItem"],
},
],
"ITEM.ARROW_LEFT": {
actions: ["focusBranchControl"],
},
"BRANCH.ARROW_LEFT": [
{
guard: "isBranchExpanded",
actions: ["collapseBranch"],
},
{
actions: ["focusBranchControl"],
},
],
"BRANCH.ARROW_RIGHT": [
{
guard: and("isBranchFocused", "isBranchExpanded"),
actions: ["focusBranchFirstItem"],
},
{
actions: ["expandBranch"],
},
],
"EXPAND.SIBLINGS": {
actions: ["expandSiblingBranches"],
},
"ITEM.HOME": [
{
guard: and("isShiftKey", "isMultipleSelection"),
actions: ["extendSelectionToFirstItem", "focusTreeFirstItem"],
},
{
actions: ["focusTreeFirstItem"],
},
],
"ITEM.END": [
{
guard: and("isShiftKey", "isMultipleSelection"),
actions: ["extendSelectionToLastItem", "focusTreeLastItem"],
},
{
actions: ["focusTreeLastItem"],
},
],
"ITEM.CLICK": [
{
guard: and("isCtrlKey", "isMultipleSelection"),
actions: ["addOrRemoveItemFromSelection"],
},
{
guard: and("isShiftKey", "isMultipleSelection"),
actions: ["extendSelectionToItem"],
},
{
actions: ["selectItem"],
},
],
"BRANCH.CLICK": [
{
guard: and("isCtrlKey", "isMultipleSelection"),
actions: ["addOrRemoveItemFromSelection"],
},
{
guard: and("isShiftKey", "isMultipleSelection"),
actions: ["extendSelectionToItem"],
},
{
guard: "openOnClick",
actions: ["selectItem", "toggleBranch"],
},
{
actions: ["selectItem"],
},
],
"BRANCH_TOGGLE.CLICK": {
actions: ["toggleBranch"],
},
"TREE.TYPEAHEAD": {
actions: ["focusMatchedItem"],
},
"TREE.BLUR": {
actions: ["clearFocusedItem", "setFocusableNode"],
},
},
},
},
},
{
guards: {
isBranchFocused: (ctx, evt) => ctx.focusedValue === evt.id,
isBranchExpanded: (ctx, evt) => ctx.expandedValue.includes(evt.id),
isShiftKey: (_ctx, evt) => evt.shiftKey,
isCtrlKey: (_ctx, evt) => evt.ctrlKey,
hasSelectedItems: (ctx) => ctx.selectedValue.length > 0,
isMultipleSelection: (ctx) => ctx.isMultipleSelection,
moveFocus: (_ctx, evt) => !!evt.moveFocus,
openOnClick: (ctx) => !!ctx.expandOnClick,
},
activities: {
trackChildrenMutation(ctx, _evt, { send }) {
const treeEl = dom.getTreeEl(ctx)
return observeChildren(treeEl, {
callback(records) {
const removedNodes = records
.flatMap((r) => Array.from(r.removedNodes))
.filter((node) => {
if (!isHTMLElement(node)) return false
return node.matches("[role=treeitem]") || node.matches("[role=group]")
})
if (!removedNodes.length) return
let elementToFocus: HTMLElement | null = null
records.forEach((record) => {
if (isHTMLElement(record.nextSibling)) {
elementToFocus = record.nextSibling
} else if (isHTMLElement(record.previousSibling)) {
elementToFocus = record.previousSibling
}
})
if (elementToFocus) {
dom.focusNode(elementToFocus)
}
const removedIds: Set<string> = new Set()
removedNodes.forEach((node) => {
const nodeId = dom.getNodeId(node)
if (isHTMLElement(node) && nodeId != null) {
removedIds.add(nodeId)
}
})
const nextSet = new Set(ctx.selectedValue)
removedIds.forEach((id) => nextSet.delete(id))
send({ type: "SELECTED.SET", value: removedIds })
},
})
},
},
actions: {
setFocusableNode(ctx) {
if (ctx.focusedValue) return
if (ctx.selectedValue.length > 0) {
const firstSelectedId = Array.from(ctx.selectedValue)[0]
ctx.focusedValue = firstSelectedId
return
}
const walker = dom.getTreeWalker(ctx)
const firstItem = walker.firstChild()
if (!isHTMLElement(firstItem)) return
// don't use set.focused here because it will trigger focusChange event
ctx.focusedValue = dom.getNodeId(firstItem)
},
selectItem(ctx, evt) {
set.selected(ctx, [evt.id])
},
setFocusedItem(ctx, evt) {
set.focused(ctx, evt.id)
},
clearFocusedItem(ctx) {
set.focused(ctx, null)
},
clearSelectedItem(ctx) {
set.selected(ctx, [])
},
toggleBranch(ctx, evt) {
const nextSet = new Set(ctx.expandedValue)
if (nextSet.has(evt.id)) {
nextSet.delete(evt.id)
// collapseEffect(ctx, evt)
} else {
nextSet.add(evt.id)
}
set.expanded(ctx, Array.from(nextSet))
},
expandBranch(ctx, evt) {
const nextSet = new Set(ctx.expandedValue)
nextSet.add(evt.id)
set.expanded(ctx, Array.from(nextSet))
},
collapseBranch(ctx, evt) {
const nextSet = new Set(ctx.expandedValue)
nextSet.delete(evt.id)
set.expanded(ctx, Array.from(nextSet))
},
setExpanded(ctx, evt) {
set.expanded(ctx, evt.value)
},
setSelected(ctx, evt) {
set.selected(ctx, evt.value)
},
focusTreeFirstItem(ctx) {
const walker = dom.getTreeWalker(ctx)
dom.focusNode(walker.firstChild())
},
focusTreeLastItem(ctx, evt) {
const walker = dom.getTreeWalker(ctx)
dom.focusNode(walker.lastChild(), { preventScroll: evt.preventScroll })
},
focusBranchFirstItem(ctx, evt) {
const focusedEl = dom.getNodeEl(ctx, evt.id)
if (!focusedEl) return
const walker = dom.getTreeWalker(ctx)
walker.currentNode = focusedEl
dom.focusNode(walker.nextNode())
},
focusTreeNextItem(ctx, evt) {
const focusedEl = dom.getNodeEl(ctx, evt.id)
if (!focusedEl) return
const walker = dom.getTreeWalker(ctx)
if (ctx.focusedValue) {
walker.currentNode = focusedEl
const nextNode = walker.nextNode()
dom.focusNode(nextNode)
} else {
dom.focusNode(walker.firstChild())
}
},
focusTreePrevItem(ctx, evt) {
const focusedEl = dom.getNodeEl(ctx, evt.id)
if (!focusedEl) return
const walker = dom.getTreeWalker(ctx)
if (ctx.focusedValue) {
walker.currentNode = focusedEl
const prevNode = walker.previousNode()
dom.focusNode(prevNode)
} else {
dom.focusNode(walker.lastChild())
}
},
focusBranchControl(ctx, evt) {
const focusedEl = dom.getNodeEl(ctx, evt.id)
if (!focusedEl) return
const parentDepth = Number(focusedEl.dataset.depth) - 1
if (parentDepth < 0) return
const branchSelector = `[data-part=branch][data-depth="${parentDepth}"]`
const closestBranch = focusedEl.closest(branchSelector)
const branchControl = closestBranch?.querySelector("[data-part=branch-control]")
dom.focusNode(branchControl)
},
selectAllItems(ctx) {
const nextSet = new Set<string>()
const walker = dom.getTreeWalker(ctx)
let node = walker.firstChild()
while (node) {
const nodeId = dom.getNodeId(node)
if (isHTMLElement(node) && nodeId != null) {
nextSet.add(nodeId)
}
node = walker.nextNode()
}
set.selected(ctx, Array.from(nextSet))
},
focusMatchedItem(ctx, evt) {
dom.focusNode(dom.getMatchingEl(ctx, evt.key))
},
addOrRemoveItemFromSelection(ctx, evt) {
const focusedEl = dom.getNodeEl(ctx, evt.id)
if (!focusedEl) return
const nextSet = new Set(ctx.selectedValue)
const nodeId = dom.getNodeId(focusedEl)
if (nodeId == null) return
if (nextSet.has(nodeId)) {
nextSet.delete(nodeId)
} else {
nextSet.add(nodeId)
}
set.selected(ctx, Array.from(nextSet))
},
expandAllBranches(ctx) {
const nextSet = new Set<string>()
const walker = dom.getTreeWalker(ctx, { skipHidden: false })
while (walker.nextNode()) {
const node = walker.currentNode
const nodeId = dom.getNodeId(node)
if (isHTMLElement(node) && node.dataset.part === "branch-control" && nodeId != null) {
nextSet.add(nodeId)
}
}
set.expanded(ctx, Array.from(nextSet))
},
expandSiblingBranches(ctx, evt) {
const focusedEl = dom.getNodeEl(ctx, evt.id)
const nodes = dom.getBranchNodes(ctx, dom.getNodeDepth(focusedEl))
const nextSet = new Set<string>()
nodes.forEach((node) => {
const nodeId = dom.getNodeId(node)
if (nodeId == null) return
nextSet.add(nodeId)
})
set.expanded(ctx, Array.from(nextSet))
},
extendSelectionToItem(ctx, evt) {
const focusedEl = dom.getNodeEl(ctx, evt.id)
if (!focusedEl) return
const nodes = dom.getTreeNodes(ctx)
const selectedIds = Array.from(ctx.selectedValue)
const anchorEl = dom.getNodeEl(ctx, selectedIds[0]) || nodes[0]
const nextSet = dom.getNodesInRange(nodes, anchorEl, focusedEl)
set.selected(ctx, nextSet)
},
extendSelectionToNextItem(ctx, evt) {
const nodeId = evt.id
const currentNode = dom.getNodeEl(ctx, nodeId)
if (!currentNode) return
const walker = dom.getTreeWalker(ctx)
walker.currentNode = currentNode
const nextNode = walker.nextNode()
dom.focusNode(nextNode)
// extend selection to nextNode (preserve the anchor node)
const selectedIds = new Set(ctx.selectedValue)
const nextNodeId = dom.getNodeId(nextNode)
if (nextNodeId == null) return
if (selectedIds.has(nodeId) && selectedIds.has(nextNodeId)) {
selectedIds.delete(nodeId)
} else if (!selectedIds.has(nextNodeId)) {
selectedIds.add(nextNodeId)
}
set.selected(ctx, Array.from(selectedIds))
},
extendSelectionToPrevItem(ctx, evt) {
const nodeId = evt.id
const currentNode = dom.getNodeEl(ctx, nodeId)
if (!currentNode) return
const walker = dom.getTreeWalker(ctx)
walker.currentNode = currentNode
const prevNode = walker.previousNode()
dom.focusNode(prevNode)
// extend selection to prevNode (preserve the anchor node)
const selectedIds = new Set(ctx.selectedValue)
const prevNodeId = dom.getNodeId(prevNode)
if (prevNodeId == null) return
if (selectedIds.has(nodeId) && selectedIds.has(prevNodeId)) {
selectedIds.delete(nodeId)
} else if (!selectedIds.has(prevNodeId)) {
selectedIds.add(prevNodeId)
}
set.selected(ctx, Array.from(selectedIds))
},
extendSelectionToFirstItem(ctx) {
const nodes = dom.getTreeNodes(ctx)
const anchorEl = dom.getNodeEl(ctx, [...ctx.selectedValue][0]) || nodes[0]
const focusedEl = nodes[0]
const selectedIds = dom.getNodesInRange(nodes, anchorEl, focusedEl)
set.selected(ctx, selectedIds)
},
extendSelectionToLastItem(ctx) {
const nodes = dom.getTreeNodes(ctx)
const anchorEl = dom.getNodeEl(ctx, [...ctx.selectedValue][0]) || nodes[0]
const focusedEl = nodes[nodes.length - 1]
const selectedIds = dom.getNodesInRange(nodes, anchorEl, focusedEl)
set.selected(ctx, selectedIds)
},
},
},
)
}
const invoke = {
focusChange(ctx: MachineContext) {
ctx.onFocusChange?.({ focusedValue: ctx.focusedValue! })
},
expandedChange(ctx: MachineContext) {
ctx.onExpandedChange?.({
expandedValue: Array.from(ctx.expandedValue),
focusedValue: ctx.focusedValue!,
})
},
selectionChange(ctx: MachineContext) {
ctx.onSelectionChange?.({
selectedValue: Array.from(ctx.selectedValue),
focusedValue: ctx.focusedValue,
})
},
}
const set = {
selected(ctx: MachineContext, value: string[]) {
ctx.selectedValue = value
invoke.selectionChange(ctx)
},
focused(ctx: MachineContext, value: string | null) {
ctx.focusedValue = value
invoke.focusChange(ctx)
},
expanded(ctx: MachineContext, value: string[]) {
ctx.expandedValue = value
invoke.expandedChange(ctx)
},
}
import { createProps } from "@zag-js/types"
import { createSplitProps } from "@zag-js/utils"
import type { ItemProps, UserDefinedContext } from "./tree-view.types"
export const props = createProps<UserDefinedContext>()([
"ids",
"dir",
"expandedValue",
"expandOnClick",
"focusedValue",
"getRootNode",
"id",
"onExpandedChange",
"onFocusChange",
"onSelectionChange",
"selectedValue",
"selectionMode",
"typeahead",
])
export const splitProps = createSplitProps<Partial<UserDefinedContext>>(props)
export const itemProps = createProps<ItemProps>()(["depth", "value", "disabled"])
export const splitItemProps = createSplitProps<ItemProps>(itemProps)
import type { Machine, StateMachine as S } from "@zag-js/core"
import type { TypeaheadState } from "@zag-js/dom-query"
import type { CommonProperties, DirectionProperty, PropTypes, RequiredBy } from "@zag-js/types"
/* -----------------------------------------------------------------------------
* Callback details
* -----------------------------------------------------------------------------*/
export interface FocusChangeDetails {
focusedValue: string | null
}
export interface ExpandedChangeDetails extends FocusChangeDetails {
expandedValue: string[]
}
export interface SelectionChangeDetails extends FocusChangeDetails {
selectedValue: string[]
}
export type ElementIds = Partial<{
root: string
tree: string
label: string
}>
/* -----------------------------------------------------------------------------
* Machine context
* -----------------------------------------------------------------------------*/
interface PublicContext extends DirectionProperty, CommonProperties {
/**
* The ids of the tree elements. Useful for composition.
*/
ids?: ElementIds
/**
* The id of the expanded nodes
*/
expandedValue: string[]
/**
* The id of the selected nodes
*/
selectedValue: string[]
/**
* The id of the focused node
*/
focusedValue: string | null
/**
* Whether the tree supports multiple selection
* - "single": only one node can be selected
* - "multiple": multiple nodes can be selected
*
* @default "single"
*/
selectionMode: "single" | "multiple"
/**
* Called when the tree is opened or closed
*/
onExpandedChange?: (details: ExpandedChangeDetails) => void
/**
* Called when the selection changes
*/
onSelectionChange?: (details: SelectionChangeDetails) => void
/**
* Called when the focused node changes
*/
onFocusChange?: (details: FocusChangeDetails) => void
/**
* Whether clicking on a branch should open it or not
* @default true
*/
expandOnClick?: boolean
/**
* Whether the tree supports typeahead search
* @default true
*/
typeahead?: boolean
}
interface PrivateContext {
/**
* @internal
* The typeahead state for faster keyboard navigation
*/
typeaheadState: TypeaheadState
}
type ComputedContext = Readonly<{
/**
* @computed
* Whether a typeahead search is ongoing
*/
isTypingAhead: boolean
/**
* @computed
* Whether the tree supports multiple selection
*/
isMultipleSelection: boolean
}>
export type UserDefinedContext = RequiredBy<PublicContext, "id">
export interface MachineContext extends PublicContext, PrivateContext, ComputedContext {}
export interface MachineState {
value: "idle"
}
export type State = S.State<MachineContext, MachineState>
export type Send = S.Send<S.AnyEventObject>
export type Service = Machine<MachineContext, MachineState, S.AnyEventObject>
/* -----------------------------------------------------------------------------
* Component API
* -----------------------------------------------------------------------------*/
export interface ItemProps {
/**
* The depth of the item or branch
*/
depth: number
/**
* The id of the item or branch
*/
value: string
/**
* Whether the item or branch is disabled
*/
disabled?: boolean
}
export interface BranchProps extends ItemProps {}
export interface ItemState {
/**
* The value of the tree item
*/
value: string
/**
* Whether the tree item is disabled
*/
disabled: boolean
/**
* Whether the tree item is selected
*/
selected: boolean
/**
* Whether the tree item is focused
*/
focused: boolean
}
export interface BranchState extends ItemState {
/**
* Whether the tree branch is expanded
*/
expanded: boolean
}
export interface MachineApi<T extends PropTypes = PropTypes> {
/**
* The id of the expanded nodes
*/
expandedValue: string[]
/**
* The id of the selected nodes
*/
selectedValue: string[]
/**
* Function to expand nodes.
* If no value is provided, all nodes will be expanded
*/
expand(value?: string[]): void
/**
* Function to collapse nodes
* If no value is provided, all nodes will be collapsed
*/
collapse(value?: string[]): void
/**
* Function to select nodes
* If no value is provided, all nodes will be selected
*/
select(value?: string[]): void
/**
* Function to deselect nodes
* If no value is provided, all nodes will be deselected
*/
deselect(value?: string[]): void
/**
* Function to focus a branch node
*/
focusBranch(value: string): void
/**
* Function to focus an item node
*/
focusItem(value: string): void
getRootProps(): T["element"]
getLabelProps(): T["element"]
getTreeProps(): T["element"]
getItemState(props: ItemProps): ItemState
getItemProps(props: ItemProps): T["element"]
getItemIndicatorProps(props: ItemProps): T["element"]
getItemTextProps(props: ItemProps): T["element"]
getBranchState(props: BranchProps): BranchState
getBranchProps(props: BranchProps): T["element"]
getBranchIndicatorProps(props: BranchProps): T["element"]
getBranchTriggerProps(props: BranchProps): T["element"]
getBranchControlProps(props: BranchProps): T["element"]
getBranchContentProps(props: BranchProps): T["element"]
getBranchTextProps(props: BranchProps): T["element"]
}