import { __name } from '../chunk-PAWJFY3S.mjs';
import * as React from 'react';
import { createContext, memo, useRef, useCallback, useMemo, useEffect, useState, useReducer, Fragment as Fragment$1 } from 'react';
import { cn } from '@djangocfg/ui-core/lib';
import { getDialog } from '@djangocfg/ui-core/lib/dialog-service';
import { CornerUpLeft, Pencil, Copy, Scissors, Trash2, FilePlus, FolderPlus, ChevronDown, ChevronRight, FolderOpen, Folder, File, Loader2, Search, X, AlertCircle } from 'lucide-react';
import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuSeparator, ContextMenuItem, ContextMenuShortcut } from '@djangocfg/ui-core/components';
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, useDraggable, useDroppable } from '@dnd-kit/core';
import { useHotkey } from '@djangocfg/ui-core/hooks';

// src/tools/data/Tree/data/childCache.ts
var createChildCache = /* @__PURE__ */ __name(() => /* @__PURE__ */ new Map(), "createChildCache");
var resolveChildren = /* @__PURE__ */ __name((cache, node) => {
  if (Array.isArray(node.children)) {
    return { children: node.children, status: "loaded" };
  }
  const entry = cache.get(node.id);
  if (!entry) return { children: null, status: "idle" };
  if (entry.status === "loaded") {
    return { children: entry.children, status: "loaded" };
  }
  return { children: null, status: entry.status, error: entry.error };
}, "resolveChildren");

// src/tools/data/Tree/data/flatten.ts
var isNodeFolder = /* @__PURE__ */ __name((node) => {
  if (typeof node.isFolder === "boolean") return node.isFolder;
  return Array.isArray(node.children);
}, "isNodeFolder");
function flattenTree({
  roots,
  expandedIds,
  cache,
  filterNode
}) {
  const out = [];
  const walk = /* @__PURE__ */ __name((nodes, level, parentId) => {
    const visible = filterNode ? nodes.filter(filterNode) : nodes;
    const setSize = visible.length;
    visible.forEach((node, index) => {
      const isFolder = isNodeFolder(node);
      const isExpanded = expandedIds.has(node.id);
      const resolved = isFolder ? resolveChildren(cache, node) : { children: [], status: "loaded" };
      out.push({
        node,
        level,
        parentId,
        isFolder,
        isExpanded,
        isLoading: resolved.status === "loading",
        hasError: resolved.status === "error",
        posInSet: index + 1,
        setSize
      });
      if (isFolder && isExpanded && resolved.children) {
        walk(resolved.children, level + 1, node.id);
      }
    });
  }, "walk");
  walk(roots, 0, null);
  return out;
}
__name(flattenTree, "flattenTree");

// src/tools/data/Tree/data/persist.ts
var KEY_PREFIX = "@djangocfg/tree:";
var VERSION = 1;
function safeStorage() {
  if (typeof window === "undefined") return null;
  try {
    return window.localStorage;
  } catch {
    return null;
  }
}
__name(safeStorage, "safeStorage");
function loadTreeState(key) {
  const storage = safeStorage();
  if (!storage) return null;
  try {
    const raw = storage.getItem(KEY_PREFIX + key);
    if (!raw) return null;
    const parsed = JSON.parse(raw);
    if (parsed.version !== VERSION) return null;
    return {
      expandedItems: Array.isArray(parsed.expandedItems) ? parsed.expandedItems : [],
      selectedItems: Array.isArray(parsed.selectedItems) ? parsed.selectedItems : []
    };
  } catch {
    return null;
  }
}
__name(loadTreeState, "loadTreeState");
function saveTreeState(key, state) {
  const storage = safeStorage();
  if (!storage) return;
  try {
    const payload = { ...state, version: VERSION };
    storage.setItem(KEY_PREFIX + key, JSON.stringify(payload));
  } catch {
  }
}
__name(saveTreeState, "saveTreeState");
function clearTreeState(key) {
  const storage = safeStorage();
  if (!storage) return;
  try {
    storage.removeItem(KEY_PREFIX + key);
  } catch {
  }
}
__name(clearTreeState, "clearTreeState");

// src/tools/data/Tree/data/appearance.ts
var DENSITY_PRESETS = {
  compact: { rowHeight: 24, iconSize: 14, fontSize: 13, gap: 6 },
  cozy: { rowHeight: 28, iconSize: 16, fontSize: 13, gap: 8 },
  comfortable: { rowHeight: 32, iconSize: 16, fontSize: 14, gap: 8 }
};
var VARIANT_DEFAULTS = {
  explorer: {
    hideLeafIcons: false,
    hideFolderIcons: false,
    rowSizing: "fixed",
    showActiveIndicator: true
  },
  list: {
    hideLeafIcons: true,
    hideFolderIcons: true,
    rowSizing: "auto",
    showActiveIndicator: false
  }
};
var DEFAULT_TREE_APPEARANCE = {
  density: "cozy",
  ...DENSITY_PRESETS.cozy,
  iconStrokeWidth: 1.5,
  indent: 16,
  accent: "default",
  radius: "sm",
  indentGuideOpacity: 0.4,
  ...VARIANT_DEFAULTS.explorer
};
function resolveAppearance(input, outerIndent) {
  if (!input && outerIndent === void 0) return DEFAULT_TREE_APPEARANCE;
  const density = input?.density ?? "cozy";
  const preset = DENSITY_PRESETS[density];
  const variant = input?.variant ?? "explorer";
  const v = VARIANT_DEFAULTS[variant];
  return {
    density,
    rowHeight: input?.rowHeight ?? preset.rowHeight,
    iconSize: input?.iconSize ?? preset.iconSize,
    iconStrokeWidth: input?.iconStrokeWidth ?? DEFAULT_TREE_APPEARANCE.iconStrokeWidth,
    fontSize: input?.fontSize ?? preset.fontSize,
    gap: input?.gap ?? preset.gap,
    indent: input?.indent ?? outerIndent ?? DEFAULT_TREE_APPEARANCE.indent,
    accent: input?.accent ?? DEFAULT_TREE_APPEARANCE.accent,
    radius: input?.radius ?? DEFAULT_TREE_APPEARANCE.radius,
    indentGuideOpacity: input?.indentGuideOpacity ?? DEFAULT_TREE_APPEARANCE.indentGuideOpacity,
    showActiveIndicator: input?.showActiveIndicator ?? v.showActiveIndicator,
    hideLeafIcons: input?.hideLeafIcons ?? v.hideLeafIcons,
    hideFolderIcons: input?.hideFolderIcons ?? v.hideFolderIcons,
    rowSizing: input?.rowSizing ?? v.rowSizing
  };
}
__name(resolveAppearance, "resolveAppearance");
function appearanceToStyle(a) {
  return {
    ["--tree-row-height"]: `${a.rowHeight}px`,
    ["--tree-icon-size"]: `${a.iconSize}px`,
    ["--tree-icon-stroke"]: a.iconStrokeWidth,
    ["--tree-font-size"]: `${a.fontSize}px`,
    ["--tree-gap"]: `${a.gap}px`,
    ["--tree-indent"]: `${a.indent}px`,
    ["--tree-guide-opacity"]: a.indentGuideOpacity
  };
}
__name(appearanceToStyle, "appearanceToStyle");
var RADIUS_CLASS = {
  none: "rounded-none",
  sm: "rounded-sm",
  md: "rounded-md"
};
function radiusClass(a) {
  return RADIUS_CLASS[a.radius];
}
__name(radiusClass, "radiusClass");
var HOVER = {
  subtle: "hover:bg-foreground/[.03]",
  default: "hover:bg-foreground/[.06]",
  strong: "hover:bg-foreground/[.09]"
};
var FOCUSED_NOT_SELECTED = {
  subtle: "data-[focused=true]:bg-foreground/[.05]",
  default: "data-[focused=true]:bg-foreground/[.08]",
  strong: "data-[focused=true]:bg-foreground/[.12]"
};
var SELECTED_INACTIVE = {
  subtle: "data-[selected=true]:bg-foreground/[.06]",
  default: "data-[selected=true]:bg-foreground/[.10]",
  strong: "data-[selected=true]:bg-foreground/[.14]"
};
var SELECTED_ACTIVE = {
  subtle: "data-[selected=true]:group-focus-within/tree:bg-primary/10 data-[selected=true]:group-focus-within/tree:text-primary",
  default: "data-[selected=true]:group-focus-within/tree:bg-primary/15 data-[selected=true]:group-focus-within/tree:text-primary",
  strong: "data-[selected=true]:group-focus-within/tree:bg-primary/25 data-[selected=true]:group-focus-within/tree:text-primary"
};
function rowStateClasses(a) {
  return [
    HOVER[a.accent],
    FOCUSED_NOT_SELECTED[a.accent],
    SELECTED_INACTIVE[a.accent],
    SELECTED_ACTIVE[a.accent]
  ].join(" ");
}
__name(rowStateClasses, "rowStateClasses");

// src/tools/data/Tree/types/labels.ts
var DEFAULT_TREE_LABELS = {
  loading: "Loading\u2026",
  empty: "Nothing to show",
  error: "Failed to load",
  searchPlaceholder: "Search\u2026",
  searchMatches: /* @__PURE__ */ __name((n) => `${n} match${n === 1 ? "" : "es"}`, "searchMatches"),
  ariaLabel: "Tree",
  actionOpen: "Open",
  actionRename: "Rename",
  actionDuplicate: "Duplicate",
  actionCut: "Cut",
  actionCopy: "Copy",
  actionPaste: "Paste",
  actionDelete: "Delete",
  actionNewFile: "New file",
  actionNewFolder: "New folder",
  confirmDeleteTitle: /* @__PURE__ */ __name((n) => n === 1 ? "Delete item?" : `Delete ${n} items?`, "confirmDeleteTitle"),
  confirmDeleteMessage: /* @__PURE__ */ __name((names) => names.length === 1 ? `"${names[0]}" will be removed. This action cannot be undone.` : `${names.length} items will be removed. This action cannot be undone.`, "confirmDeleteMessage"),
  confirmDeleteOk: "Delete",
  confirmDeleteCancel: "Cancel",
  newFileTitle: "New file",
  newFileMessage: "File name",
  newFilePlaceholder: "untitled.txt",
  newFileDefault: "untitled.txt",
  newFolderTitle: "New folder",
  newFolderMessage: "Folder name",
  newFolderPlaceholder: "untitled folder",
  newFolderDefault: "untitled folder",
  renameTitle: "Rename",
  renameMessage: "New name",
  invalidNameEmpty: "Name cannot be empty",
  duplicateSuffix: /* @__PURE__ */ __name((name) => `${name} copy`, "duplicateSuffix")
};

// src/tools/data/Tree/context/state/reducer.ts
function reducer(state, action) {
  switch (action.type) {
    case "expand": {
      if (state.expanded.has(action.id)) return state;
      const next = new Set(state.expanded);
      next.add(action.id);
      return { ...state, expanded: next };
    }
    case "collapse": {
      if (!state.expanded.has(action.id)) return state;
      const next = new Set(state.expanded);
      next.delete(action.id);
      return { ...state, expanded: next };
    }
    case "toggle": {
      const next = new Set(state.expanded);
      if (next.has(action.id)) next.delete(action.id);
      else next.add(action.id);
      return { ...state, expanded: next };
    }
    case "set-expanded":
      return { ...state, expanded: new Set(action.ids) };
    case "select": {
      if (action.mode === "none") return state;
      if (action.mode === "single") {
        return {
          ...state,
          selected: /* @__PURE__ */ new Set([action.id]),
          anchor: action.id,
          focused: action.id
        };
      }
      const next = new Set(state.selected);
      if (next.has(action.id)) next.delete(action.id);
      else next.add(action.id);
      return { ...state, selected: next, anchor: action.id, focused: action.id };
    }
    case "select-many":
      return { ...state, selected: new Set(action.ids) };
    case "clear-selection":
      return { ...state, selected: /* @__PURE__ */ new Set(), anchor: null };
    case "selection-replace":
      return {
        ...state,
        selected: new Set(action.selected),
        anchor: action.anchor,
        focused: action.focused
      };
    case "set-anchor":
      return { ...state, anchor: action.id };
    case "focus":
      return { ...state, focused: action.id };
    case "set-query":
      return { ...state, query: action.q };
    case "start-rename":
      return { ...state, renaming: action.id };
    case "stop-rename":
      return state.renaming === null ? state : { ...state, renaming: null };
    case "clipboard-set":
      return { ...state, clipboard: action.payload };
    case "cache-tick":
      return { ...state, cacheTick: state.cacheTick + 1 };
    default:
      return state;
  }
}
__name(reducer, "reducer");

// src/tools/data/Tree/context/state/initial.ts
function createInitialState(input) {
  const { persisted, initialExpandedIds, initialSelectedIds, persistSelection } = input;
  const initialSelected = new Set(
    (persistSelection ? persisted?.selectedItems : void 0) ?? initialSelectedIds ?? []
  );
  const initialAnchor = initialSelected.size > 0 ? initialSelected.values().next().value : null;
  return {
    expanded: new Set(persisted?.expandedItems ?? initialExpandedIds ?? []),
    selected: initialSelected,
    anchor: initialAnchor,
    focused: null,
    query: "",
    renaming: null,
    clipboard: null,
    cacheTick: 0
  };
}
__name(createInitialState, "createInitialState");

// src/tools/data/Tree/context/async-children/collect-ids.ts
function collectAllFolderIds(roots, cache, out) {
  for (const node of roots) {
    if (Array.isArray(node.children)) {
      out.push(node.id);
      collectAllFolderIds(node.children, cache, out);
    } else if (node.isFolder) {
      out.push(node.id);
      const entry = cache.get(node.id);
      if (entry?.children) collectAllFolderIds(entry.children, cache, out);
    }
  }
}
__name(collectAllFolderIds, "collectAllFolderIds");

// src/tools/data/Tree/context/async-children/use-async-children.ts
function useAsyncChildren({
  data,
  loadChildren,
  expanded,
  cacheTick,
  bumpCacheTick
}) {
  const cacheRef = useRef(createChildCache());
  const inflightRef = useRef(/* @__PURE__ */ new Map());
  const fetchChildren = useCallback(
    async (node) => {
      if (!loadChildren) return;
      if (Array.isArray(node.children)) return;
      const existing = cacheRef.current.get(node.id);
      if (existing?.status === "loaded" || existing?.status === "loading") return;
      const inflight = inflightRef.current.get(node.id);
      if (inflight) return inflight;
      cacheRef.current.set(node.id, { status: "loading", children: [] });
      bumpCacheTick();
      const promise = (async () => {
        try {
          const children = await loadChildren(node);
          cacheRef.current.set(node.id, { status: "loaded", children });
        } catch (err) {
          cacheRef.current.set(node.id, {
            status: "error",
            children: [],
            error: err instanceof Error ? err.message : String(err)
          });
        } finally {
          inflightRef.current.delete(node.id);
          bumpCacheTick();
        }
      })();
      inflightRef.current.set(node.id, promise);
      return promise;
    },
    [loadChildren, bumpCacheTick]
  );
  const nodeById = useMemo(() => {
    const map = /* @__PURE__ */ new Map();
    const walk = /* @__PURE__ */ __name((nodes) => {
      for (const n of nodes) {
        map.set(n.id, n);
        if (Array.isArray(n.children)) walk(n.children);
        else {
          const entry = cacheRef.current.get(n.id);
          if (entry?.children) walk(entry.children);
        }
      }
    }, "walk");
    walk(data);
    return map;
  }, [data, cacheTick]);
  useEffect(() => {
    if (!loadChildren) return;
    for (const id of expanded) {
      const node = nodeById.get(id);
      if (!node) continue;
      void fetchChildren(node);
    }
  }, [loadChildren, expanded, cacheTick, nodeById, fetchChildren]);
  const refresh = useCallback(
    async (id) => {
      const node = nodeById.get(id);
      if (!node || !loadChildren) return;
      cacheRef.current.delete(id);
      bumpCacheTick();
      await fetchChildren(node);
    },
    [nodeById, loadChildren, fetchChildren, bumpCacheTick]
  );
  const refreshAll = useCallback(async () => {
    cacheRef.current.clear();
    bumpCacheTick();
    if (!loadChildren) return;
    await Promise.all(
      [...expanded].map((id) => {
        const node = nodeById.get(id);
        return node ? fetchChildren(node) : void 0;
      })
    );
  }, [loadChildren, expanded, nodeById, fetchChildren, bumpCacheTick]);
  const collectFolderIds = useCallback(() => {
    const ids = [];
    collectAllFolderIds(data, cacheRef.current, ids);
    return ids;
  }, [data]);
  return {
    cache: cacheRef.current,
    nodeById,
    fetchChildren,
    refresh,
    refreshAll,
    collectFolderIds
  };
}
__name(useAsyncChildren, "useAsyncChildren");
function useExpansion({
  dispatch,
  collectFolderIds
}) {
  const expand = useCallback(
    (id) => dispatch({ type: "expand", id }),
    [dispatch]
  );
  const collapse = useCallback(
    (id) => dispatch({ type: "collapse", id }),
    [dispatch]
  );
  const toggle = useCallback(
    (id) => dispatch({ type: "toggle", id }),
    [dispatch]
  );
  const expandAll = useCallback(() => {
    dispatch({ type: "set-expanded", ids: collectFolderIds() });
  }, [dispatch, collectFolderIds]);
  const collapseAll = useCallback(
    () => dispatch({ type: "set-expanded", ids: [] }),
    [dispatch]
  );
  return { expand, collapse, toggle, expandAll, collapseAll };
}
__name(useExpansion, "useExpansion");

// src/tools/data/Tree/data/selection.ts
function indexOf(rows, id) {
  if (id == null) return -1;
  for (let i = 0; i < rows.length; i++) {
    if (rows[i].node.id === id) return i;
  }
  return -1;
}
__name(indexOf, "indexOf");
function computeRange(rows, fromId, toId) {
  if (fromId == null || toId == null) return [];
  const a = indexOf(rows, fromId);
  const b = indexOf(rows, toId);
  if (a < 0 || b < 0) return [];
  const [lo, hi] = a <= b ? [a, b] : [b, a];
  const out = [];
  for (let i = lo; i <= hi; i++) out.push(rows[i].node.id);
  return out;
}
__name(computeRange, "computeRange");
function selectionFromClick(state, rows, id, mods, multi) {
  if (!multi) {
    return { selected: /* @__PURE__ */ new Set([id]), anchor: id, focused: id };
  }
  if (mods.shift && mods.meta) {
    const anchor = state.anchor ?? state.focused ?? id;
    const range = computeRange(rows, anchor, id);
    const next = new Set(state.selected);
    for (const r of range) next.add(r);
    return { selected: next, anchor: state.anchor ?? id, focused: id };
  }
  if (mods.shift) {
    const anchor = state.anchor ?? state.focused ?? id;
    const range = computeRange(rows, anchor, id);
    return {
      selected: new Set(range.length > 0 ? range : [id]),
      anchor: state.anchor ?? anchor,
      focused: id
    };
  }
  if (mods.meta) {
    const next = new Set(state.selected);
    if (next.has(id)) next.delete(id);
    else next.add(id);
    return { selected: next, anchor: id, focused: id };
  }
  return { selected: /* @__PURE__ */ new Set([id]), anchor: id, focused: id };
}
__name(selectionFromClick, "selectionFromClick");
function selectionFromMove(state, rows, nextFocusedId, extend, multi) {
  if (!multi || !extend) {
    return { selected: /* @__PURE__ */ new Set([nextFocusedId]), anchor: nextFocusedId, focused: nextFocusedId };
  }
  const anchor = state.anchor ?? state.focused ?? nextFocusedId;
  const range = computeRange(rows, anchor, nextFocusedId);
  return {
    selected: new Set(range.length > 0 ? range : [nextFocusedId]),
    anchor,
    focused: nextFocusedId
  };
}
__name(selectionFromMove, "selectionFromMove");
function selectionSelectAll(rows, focused) {
  if (rows.length === 0) {
    return { selected: /* @__PURE__ */ new Set(), anchor: null, focused };
  }
  const ids = rows.map((r) => r.node.id);
  return {
    selected: new Set(ids),
    anchor: ids[0],
    focused: focused ?? ids[0]
  };
}
__name(selectionSelectAll, "selectionSelectAll");

// src/tools/data/Tree/context/selection/use-selection.ts
function useSelection({
  dispatch,
  selectionMode,
  flatRows,
  selected,
  anchor,
  focused
}) {
  const flatRowsRef = useRef(flatRows);
  flatRowsRef.current = flatRows;
  const selectionRef = useRef({ selected, anchor, focused });
  selectionRef.current = { selected, anchor, focused };
  const select = useCallback(
    (id) => dispatch({ type: "select", id, mode: selectionMode }),
    [dispatch, selectionMode]
  );
  const setSelectedIds = useCallback(
    (ids) => dispatch({ type: "select-many", ids }),
    [dispatch]
  );
  const clearSelection = useCallback(
    () => dispatch({ type: "clear-selection" }),
    [dispatch]
  );
  const setFocus = useCallback(
    (id) => dispatch({ type: "focus", id }),
    [dispatch]
  );
  const clickSelect = useCallback(
    (id, mods) => {
      if (selectionMode === "none") return;
      if (selectionMode === "single") {
        dispatch({ type: "select", id, mode: "single" });
        return;
      }
      const next = selectionFromClick(
        selectionRef.current,
        flatRowsRef.current,
        id,
        mods,
        true
      );
      dispatch({
        type: "selection-replace",
        selected: [...next.selected],
        anchor: next.anchor,
        focused: next.focused
      });
    },
    [dispatch, selectionMode]
  );
  const moveSelect = useCallback(
    (id, opts) => {
      if (selectionMode !== "multiple" || !opts.extend) {
        dispatch({ type: "focus", id });
        return;
      }
      const next = selectionFromMove(
        selectionRef.current,
        flatRowsRef.current,
        id,
        true,
        true
      );
      dispatch({
        type: "selection-replace",
        selected: [...next.selected],
        anchor: next.anchor,
        focused: next.focused
      });
    },
    [dispatch, selectionMode]
  );
  const selectAll = useCallback(() => {
    if (selectionMode !== "multiple") return;
    const next = selectionSelectAll(
      flatRowsRef.current,
      selectionRef.current.focused
    );
    dispatch({
      type: "selection-replace",
      selected: [...next.selected],
      anchor: next.anchor,
      focused: next.focused
    });
  }, [dispatch, selectionMode]);
  return {
    select,
    setSelectedIds,
    clearSelection,
    clickSelect,
    moveSelect,
    selectAll,
    setFocus
  };
}
__name(useSelection, "useSelection");
function useRename({
  dispatch,
  adapter,
  enableInlineRename,
  nodeById,
  getItemName,
  labels
}) {
  const enabled = enableInlineRename && !!adapter?.rename;
  const startRename = useCallback(
    (id) => {
      if (!enableInlineRename) return;
      if (!adapter?.rename) {
        if (process.env.NODE_ENV !== "production") {
          console.warn(
            "[Tree] startRename called but adapter.rename is not defined."
          );
        }
        return;
      }
      dispatch({ type: "start-rename", id });
    },
    [dispatch, enableInlineRename, adapter]
  );
  const cancelRename = useCallback(
    () => dispatch({ type: "stop-rename" }),
    [dispatch]
  );
  const commitRename = useCallback(
    async (id, nextName) => {
      if (!adapter?.rename) {
        dispatch({ type: "stop-rename" });
        return false;
      }
      const node = nodeById.get(id);
      if (!node) {
        dispatch({ type: "stop-rename" });
        return false;
      }
      const trimmed = nextName.trim();
      if (trimmed === getItemName(node)) {
        dispatch({ type: "stop-rename" });
        return true;
      }
      let err = null;
      if (trimmed === "") err = labels.invalidNameEmpty;
      else err = adapter.validateName?.(trimmed, { node }) ?? null;
      if (err) {
        const dialog = getDialog();
        await dialog?.alert({ title: labels.error, message: err });
        return false;
      }
      try {
        await adapter.rename(node, trimmed);
      } catch (e) {
        const dialog = getDialog();
        await dialog?.alert({
          title: labels.error,
          message: e instanceof Error ? e.message : String(e)
        });
        return false;
      }
      dispatch({ type: "stop-rename" });
      return true;
    },
    [dispatch, adapter, nodeById, getItemName, labels]
  );
  return { enabled, startRename, cancelRename, commitRename };
}
__name(useRename, "useRename");
function useClipboard({
  dispatch,
  clipboard,
  adapter,
  nodeById,
  labels
}) {
  const clipboardRef = useRef(clipboard);
  clipboardRef.current = clipboard;
  const cutToClipboard = useCallback(
    (ids) => {
      if (ids.length === 0) return;
      dispatch({ type: "clipboard-set", payload: { kind: "cut", ids } });
    },
    [dispatch]
  );
  const copyToClipboard = useCallback(
    (ids) => {
      if (ids.length === 0) return;
      dispatch({ type: "clipboard-set", payload: { kind: "copy", ids } });
    },
    [dispatch]
  );
  const clearClipboard = useCallback(
    () => dispatch({ type: "clipboard-set", payload: null }),
    [dispatch]
  );
  const pasteFromClipboard = useCallback(
    async (target, position = "inside") => {
      const cb = clipboardRef.current;
      if (!cb || cb.ids.length === 0) return;
      if (!adapter) return;
      const nodes = cb.ids.map((id) => nodeById.get(id)).filter((n) => !!n);
      if (nodes.length === 0) {
        dispatch({ type: "clipboard-set", payload: null });
        return;
      }
      try {
        if (cb.kind === "cut") {
          if (!adapter.move) return;
          await adapter.move(nodes, target, position);
          dispatch({ type: "clipboard-set", payload: null });
        } else {
          if (!adapter.copy) return;
          await adapter.copy(nodes, target, position);
        }
      } catch (e) {
        const dialog = getDialog();
        await dialog?.alert({
          title: labels.error,
          message: e instanceof Error ? e.message : String(e)
        });
      }
    },
    [dispatch, adapter, nodeById, labels]
  );
  return {
    cutToClipboard,
    copyToClipboard,
    pasteFromClipboard,
    clearClipboard
  };
}
__name(useClipboard, "useClipboard");
async function confirmDelete(ctx) {
  const dialog = getDialog();
  if (!dialog) return false;
  const { selectedNodes, labels, getName } = ctx;
  return dialog.confirm({
    title: labels.confirmDeleteTitle(selectedNodes.length),
    message: labels.confirmDeleteMessage(selectedNodes.map(getName)),
    confirmText: labels.confirmDeleteOk,
    cancelText: labels.confirmDeleteCancel,
    variant: "destructive"
  });
}
__name(confirmDelete, "confirmDelete");
async function promptName(ctx, spec) {
  const dialog = getDialog();
  if (!dialog) return null;
  return dialog.prompt({
    title: spec.title,
    message: spec.message,
    placeholder: spec.placeholder,
    defaultValue: spec.defaultValue
  });
}
__name(promptName, "promptName");
async function alertError(ctx, message) {
  const dialog = getDialog();
  if (!dialog) return;
  await dialog.alert({ message, title: ctx.labels.error });
}
__name(alertError, "alertError");
function validateName(ctx, name, validateCtx) {
  if (name.trim() === "") return ctx.labels.invalidNameEmpty;
  return ctx.adapter.validateName?.(name, validateCtx) ?? null;
}
__name(validateName, "validateName");
var BUILTIN_ACTIONS = [
  {
    id: "open",
    label: /* @__PURE__ */ __name((ctx) => ctx.labels.actionOpen, "label"),
    icon: CornerUpLeft,
    available: /* @__PURE__ */ __name(() => false, "available"),
    // wired by Tree on activate; not in menu by default
    run: /* @__PURE__ */ __name(() => {
    }, "run")
  },
  {
    id: "rename",
    label: /* @__PURE__ */ __name((ctx) => ctx.labels.actionRename, "label"),
    icon: Pencil,
    shortcut: "F2",
    available: /* @__PURE__ */ __name((ctx) => !!ctx.adapter.rename && ctx.selectedNodes.length === 1 && !ctx.selectedNodes[0].disabled, "available"),
    run: /* @__PURE__ */ __name(async (ctx) => {
      const node = ctx.selectedNodes[0];
      if (ctx.startInlineRename) {
        ctx.startInlineRename(node.id);
        return;
      }
      const name = await promptName(ctx, {
        title: ctx.labels.renameTitle,
        message: ctx.labels.renameMessage,
        placeholder: ctx.getName(node),
        defaultValue: ctx.getName(node)
      });
      if (name === null) return;
      const err = validateName(ctx, name, { node });
      if (err) return alertError(ctx, err);
      await ctx.adapter.rename(node, name);
    }, "run")
  },
  {
    id: "duplicate",
    label: /* @__PURE__ */ __name((ctx) => ctx.labels.actionDuplicate, "label"),
    icon: Copy,
    shortcut: "\u2318D",
    available: /* @__PURE__ */ __name((ctx) => !!ctx.adapter.duplicate && ctx.selectedNodes.length > 0, "available"),
    run: /* @__PURE__ */ __name((ctx) => ctx.adapter.duplicate(ctx.selectedNodes), "run")
  },
  {
    id: "cut",
    label: /* @__PURE__ */ __name((ctx) => ctx.labels.actionCut, "label"),
    icon: Scissors,
    shortcut: "\u2318X",
    // Only meaningful when the adapter supports `move` (paste-after-cut)
    // AND Tree provided a clipboard binding.
    available: /* @__PURE__ */ __name((ctx) => !!ctx.adapter.move && !!ctx.clipboard && ctx.selectedNodes.length > 0, "available"),
    run: /* @__PURE__ */ __name((ctx) => {
      ctx.clipboard?.cut(ctx.selectedNodes.map((n) => n.id));
    }, "run")
  },
  {
    id: "copy",
    label: /* @__PURE__ */ __name((ctx) => ctx.labels.actionCopy, "label"),
    icon: Copy,
    shortcut: "\u2318C",
    available: /* @__PURE__ */ __name((ctx) => !!ctx.adapter.copy && !!ctx.clipboard && ctx.selectedNodes.length > 0, "available"),
    run: /* @__PURE__ */ __name((ctx) => {
      ctx.clipboard?.copy(ctx.selectedNodes.map((n) => n.id));
    }, "run")
  },
  {
    id: "paste",
    label: /* @__PURE__ */ __name((ctx) => ctx.labels.actionPaste, "label"),
    icon: CornerUpLeft,
    shortcut: "\u2318V",
    available: /* @__PURE__ */ __name((ctx) => !!ctx.clipboard?.hasItems, "available"),
    run: /* @__PURE__ */ __name(async (ctx) => {
      await ctx.clipboard?.paste();
    }, "run")
  },
  {
    id: "delete",
    label: /* @__PURE__ */ __name((ctx) => ctx.labels.actionDelete, "label"),
    icon: Trash2,
    shortcut: "\u2318\u232B",
    destructive: true,
    available: /* @__PURE__ */ __name((ctx) => !!ctx.adapter.remove && ctx.selectedNodes.length > 0, "available"),
    run: /* @__PURE__ */ __name(async (ctx) => {
      const ok = await confirmDelete(ctx);
      if (!ok) return;
      await ctx.adapter.remove(ctx.selectedNodes);
    }, "run")
  },
  {
    id: "new-file",
    label: /* @__PURE__ */ __name((ctx) => ctx.labels.actionNewFile, "label"),
    icon: FilePlus,
    available: /* @__PURE__ */ __name((ctx) => !!ctx.adapter.createFile, "available"),
    run: /* @__PURE__ */ __name(async (ctx) => {
      const parent = resolveParentForCreate(ctx);
      const name = await promptName(ctx, {
        title: ctx.labels.newFileTitle,
        message: ctx.labels.newFileMessage,
        placeholder: ctx.labels.newFilePlaceholder,
        defaultValue: ctx.labels.newFileDefault
      });
      if (name === null) return;
      const err = validateName(ctx, name, { parent });
      if (err) return alertError(ctx, err);
      await ctx.adapter.createFile(parent, name);
    }, "run")
  },
  {
    id: "new-folder",
    label: /* @__PURE__ */ __name((ctx) => ctx.labels.actionNewFolder, "label"),
    icon: FolderPlus,
    shortcut: "\u2318\u21E7N",
    available: /* @__PURE__ */ __name((ctx) => !!ctx.adapter.createFolder, "available"),
    run: /* @__PURE__ */ __name(async (ctx) => {
      const parent = resolveParentForCreate(ctx);
      const name = await promptName(ctx, {
        title: ctx.labels.newFolderTitle,
        message: ctx.labels.newFolderMessage,
        placeholder: ctx.labels.newFolderPlaceholder,
        defaultValue: ctx.labels.newFolderDefault
      });
      if (name === null) return;
      const err = validateName(ctx, name, { parent });
      if (err) return alertError(ctx, err);
      await ctx.adapter.createFolder(parent, name);
    }, "run")
  }
];
var DEFAULT_BUILTIN_MENU_ORDER = [
  "rename",
  "duplicate",
  "separator",
  "cut",
  "copy",
  "paste",
  "separator",
  "new-file",
  "new-folder",
  "separator",
  "delete"
];
function resolveParentForCreate(ctx) {
  const { targetNode } = ctx;
  if (!targetNode) return null;
  const isFolder = Array.isArray(targetNode.children) || !!targetNode.isFolder;
  return isFolder ? targetNode : null;
}
__name(resolveParentForCreate, "resolveParentForCreate");
function buildDefaultMenuItems(ctx, order = DEFAULT_BUILTIN_MENU_ORDER) {
  const items = [];
  let pendingSeparator = false;
  for (const entry of order) {
    if (entry === "separator") {
      pendingSeparator = items.length > 0;
      continue;
    }
    const desc = BUILTIN_ACTIONS.find((a) => a.id === entry);
    if (!desc) continue;
    if (!desc.available(ctx)) continue;
    if (pendingSeparator) {
      items.push("separator");
      pendingSeparator = false;
    }
    items.push({
      id: desc.id,
      label: desc.label(ctx),
      icon: desc.icon,
      shortcut: desc.shortcut,
      destructive: desc.destructive,
      onSelect: /* @__PURE__ */ __name(() => void desc.run(ctx), "onSelect")
    });
  }
  return items.length > 0 ? items : null;
}
__name(buildDefaultMenuItems, "buildDefaultMenuItems");
async function runBuiltinAction(id, ctx) {
  const desc = BUILTIN_ACTIONS.find((a) => a.id === id);
  if (!desc) return false;
  if (!desc.available(ctx)) return false;
  await desc.run(ctx);
  return true;
}
__name(runBuiltinAction, "runBuiltinAction");
function useResolvedMenu(opts) {
  const {
    adapter,
    contextMenuActions,
    defaultMenuItems,
    labels,
    selected,
    clipboard,
    nodeById,
    getItemName,
    enableInlineRename,
    startRename,
    cutToClipboard,
    copyToClipboard,
    pasteFromClipboard
  } = opts;
  return useMemo(() => {
    if (!adapter && !contextMenuActions) return void 0;
    return (rowProps) => {
      const selectedIds = selected.has(rowProps.node.id) ? [...selected] : [rowProps.node.id];
      const selectedNodes = selectedIds.map((id) => nodeById.get(id)).filter((n) => !!n);
      const builtin = adapter ? buildDefaultMenuItems(
        {
          adapter,
          labels,
          selectedNodes,
          targetNode: rowProps.node,
          getName: getItemName,
          startInlineRename: enableInlineRename && adapter.rename ? startRename : void 0,
          clipboard: {
            hasItems: !!clipboard && clipboard.ids.length > 0,
            cut: cutToClipboard,
            copy: copyToClipboard,
            paste: /* @__PURE__ */ __name(() => pasteFromClipboard(rowProps.node, "inside"), "paste")
          }
        },
        defaultMenuItems ? defaultMenuItems : void 0
      ) : null;
      const user = contextMenuActions?.({ ...rowProps, selectedNodes }) ?? null;
      if (!builtin && !user) return null;
      if (!user) return builtin;
      if (!builtin) return user;
      return [...builtin, "separator", ...user];
    };
  }, [
    adapter,
    contextMenuActions,
    defaultMenuItems,
    labels,
    selected,
    clipboard,
    nodeById,
    getItemName,
    enableInlineRename,
    startRename,
    cutToClipboard,
    copyToClipboard,
    pasteFromClipboard
  ]);
}
__name(useResolvedMenu, "useResolvedMenu");
function RowContextMenu({
  rowProps,
  items,
  trigger
}) {
  const [open, setOpen] = useState(false);
  return /* @__PURE__ */ jsxs(ContextMenu, { onOpenChange: setOpen, children: [
    /* @__PURE__ */ jsx(ContextMenuTrigger, { asChild: true, children: trigger }),
    open ? /* @__PURE__ */ jsx(ContextMenuContent, { children: items.map((item, idx) => {
      if (item === "separator") {
        return /* @__PURE__ */ jsx(ContextMenuSeparator, {}, `sep-${idx}`);
      }
      const Icon = item.icon;
      return /* @__PURE__ */ jsxs(
        ContextMenuItem,
        {
          disabled: item.disabled,
          variant: item.destructive ? "destructive" : void 0,
          onSelect: () => item.onSelect(rowProps),
          children: [
            Icon ? /* @__PURE__ */ jsx(Icon, {}) : null,
            item.label,
            item.shortcut ? /* @__PURE__ */ jsx(ContextMenuShortcut, { children: item.shortcut }) : null
          ]
        },
        item.id
      );
    }) }) : null
  ] });
}
__name(RowContextMenu, "RowContextMenu");
function renderItemsAsContextMenu(rowProps, items, trigger) {
  return /* @__PURE__ */ jsx(RowContextMenu, { rowProps, items, trigger });
}
__name(renderItemsAsContextMenu, "renderItemsAsContextMenu");
function tidyMenuItems(items) {
  const out = [];
  for (const it of items) {
    if (it === "separator") {
      if (out.length === 0) continue;
      if (out[out.length - 1] === "separator") continue;
      out.push(it);
    } else {
      out.push(it);
    }
  }
  while (out.length > 0 && out[out.length - 1] === "separator") out.pop();
  return out;
}
__name(tidyMenuItems, "tidyMenuItems");

// src/tools/data/Tree/data/dnd.ts
function resolveDropZone(input) {
  const { pointerY, rowRect, isFolder } = input;
  const offset = pointerY - rowRect.top;
  const ratio = rowRect.height > 0 ? offset / rowRect.height : 0.5;
  if (isFolder) {
    if (ratio < 0.33) return "before";
    if (ratio > 0.66) return "after";
    return "inside";
  }
  return ratio < 0.5 ? "before" : "after";
}
__name(resolveDropZone, "resolveDropZone");
function defaultCanDrop(input) {
  const { source, target, position } = input;
  if (source.length === 0) return false;
  if (!target) return true;
  if (position === "inside") {
    const isFolder = Array.isArray(target.children) || !!target.isFolder;
    if (!isFolder) return false;
  }
  for (const node of source) {
    if (node.id === target.id) return false;
    if (isDescendant(node, target.id)) return false;
  }
  return true;
}
__name(defaultCanDrop, "defaultCanDrop");
function isDescendant(root, id) {
  if (!Array.isArray(root.children)) return false;
  for (const child of root.children) {
    if (child.id === id) return true;
    if (isDescendant(child, id)) return true;
  }
  return false;
}
__name(isDescendant, "isDescendant");
var TREE_DND_MIME = "application/x-djangocfg-tree";
var TREE_ROOT_DROP_ID = "__tree_root_drop__";

// src/tools/data/Tree/context/dnd/use-dnd.ts
function useDnd({
  enabled,
  adapter,
  nodeById,
  selected,
  labels,
  canDrop
}) {
  const active = enabled && !!adapter?.move;
  const [draggingIds, setDraggingIds] = useState(
    () => /* @__PURE__ */ new Set()
  );
  const [dropTarget, setDropTarget] = useState(null);
  const beginDrag = useCallback(
    (rowId) => {
      if (!active) return;
      const ids = selected.has(rowId) ? new Set(selected) : /* @__PURE__ */ new Set([rowId]);
      setDraggingIds(ids);
    },
    [active, selected]
  );
  const cancelDrag = useCallback(() => {
    setDraggingIds(/* @__PURE__ */ new Set());
    setDropTarget(null);
  }, []);
  const resolveSourceNodes = useCallback(() => {
    const out = [];
    for (const id of draggingIds) {
      const node = nodeById.get(id);
      if (node) out.push(node);
    }
    return out;
  }, [draggingIds, nodeById]);
  const isAllowedDrop = useCallback(
    (target, position) => {
      if (!active) return false;
      if (draggingIds.size === 0) return false;
      const source = resolveSourceNodes();
      if (!defaultCanDrop({
        source,
        target,
        position})) {
        return false;
      }
      return canDrop?.({ source, target, position }) ?? true;
    },
    [active, draggingIds, resolveSourceNodes, nodeById, canDrop]
  );
  const commitDrop = useCallback(async () => {
    if (!active || !adapter?.move) {
      cancelDrag();
      return;
    }
    const t = dropTarget;
    if (!t) {
      cancelDrag();
      return;
    }
    const targetNode = t.id ? nodeById.get(t.id) ?? null : null;
    const source = resolveSourceNodes();
    if (source.length === 0) {
      cancelDrag();
      return;
    }
    if (!isAllowedDrop(targetNode, t.position)) {
      cancelDrag();
      return;
    }
    try {
      await adapter.move(source, targetNode, t.position);
    } catch (e) {
      const dialog = getDialog();
      await dialog?.alert({
        title: labels.error,
        message: e instanceof Error ? e.message : String(e)
      });
    } finally {
      cancelDrag();
    }
  }, [
    active,
    adapter,
    cancelDrag,
    dropTarget,
    isAllowedDrop,
    labels,
    nodeById,
    resolveSourceNodes
  ]);
  return useMemo(
    () => ({
      active,
      draggingIds,
      dropTarget,
      beginDrag,
      setDropTarget,
      commitDrop,
      cancelDrag,
      isAllowedDrop
    }),
    [
      active,
      draggingIds,
      dropTarget,
      beginDrag,
      commitDrop,
      cancelDrag,
      isAllowedDrop
    ]
  );
}
__name(useDnd, "useDnd");
function usePersistSync({
  expanded,
  selected,
  persistKey,
  persistSelection,
  onSelectionChange,
  onExpansionChange
}) {
  const onSelectionChangeRef = useRef(onSelectionChange);
  const onExpansionChangeRef = useRef(onExpansionChange);
  onSelectionChangeRef.current = onSelectionChange;
  onExpansionChangeRef.current = onExpansionChange;
  const lastSelectedArrRef = useRef([...selected]);
  const lastExpandedArrRef = useRef([...expanded]);
  useEffect(() => {
    const arr = [...expanded];
    if (!setEqualsArr(expanded, lastExpandedArrRef.current)) {
      lastExpandedArrRef.current = arr;
      onExpansionChangeRef.current?.(arr);
      if (persistKey) {
        saveTreeState(persistKey, {
          expandedItems: arr,
          selectedItems: persistSelection ? [...selected] : []
        });
      }
    }
  }, [expanded, persistKey, persistSelection, selected]);
  useEffect(() => {
    const arr = [...selected];
    if (!setEqualsArr(selected, lastSelectedArrRef.current)) {
      lastSelectedArrRef.current = arr;
      onSelectionChangeRef.current?.(arr);
      if (persistKey && persistSelection) {
        saveTreeState(persistKey, {
          expandedItems: [...expanded],
          selectedItems: arr
        });
      }
    }
  }, [selected, persistKey, persistSelection, expanded]);
}
__name(usePersistSync, "usePersistSync");
function setEqualsArr(set, arr) {
  if (set.size !== arr.length) return false;
  for (const id of arr) if (!set.has(id)) return false;
  return true;
}
__name(setEqualsArr, "setEqualsArr");
var TreeContext = createContext(null);
function useTreeContext() {
  const ctx = React.useContext(TreeContext);
  if (!ctx) {
    throw new Error("useTreeContext must be used inside <TreeProvider>");
  }
  return ctx;
}
__name(useTreeContext, "useTreeContext");
function TreeProvider(props) {
  const {
    data,
    getItemName,
    loadChildren,
    selectionMode = "single",
    activationMode = "single-click",
    initialExpandedIds,
    initialSelectedIds,
    indent,
    appearance,
    onSelectionChange,
    onExpansionChange,
    onActivate,
    filterNode,
    enableSearch = false,
    showIndentGuides = false,
    renderIcon,
    renderLabel,
    renderActions,
    renderContextMenu,
    contextMenuActions,
    labels: labelsOverride,
    persistKey,
    persistSelection = false,
    adapter,
    defaultMenuItems,
    enableInlineRename = false,
    enableDnD = false,
    canDrop,
    children
  } = props;
  const labels = useMemo(
    () => ({ ...DEFAULT_TREE_LABELS, ...labelsOverride }),
    [labelsOverride]
  );
  const resolvedAppearance = useMemo(
    () => resolveAppearance(appearance, indent),
    [appearance, indent]
  );
  const persisted = useMemo(
    () => persistKey ? loadTreeState(persistKey) : null,
    [persistKey]
  );
  const [state, dispatch] = useReducer(
    reducer,
    void 0,
    () => createInitialState({
      persisted,
      initialExpandedIds,
      initialSelectedIds,
      persistSelection
    })
  );
  const bumpCacheTick = useCallback(() => dispatch({ type: "cache-tick" }), []);
  const {
    nodeById,
    refresh,
    refreshAll,
    collectFolderIds,
    cache
  } = useAsyncChildren({
    data,
    loadChildren,
    expanded: state.expanded,
    cacheTick: state.cacheTick,
    bumpCacheTick
  });
  const flatRows = useMemo(
    () => flattenTree({
      roots: data,
      expandedIds: state.expanded,
      cache,
      filterNode
    }),
    [data, state.expanded, state.cacheTick, cache, filterNode]
  );
  const matchingIds = useMemo(() => {
    const set = /* @__PURE__ */ new Set();
    if (!enableSearch || state.query.trim() === "") return set;
    const q = state.query.trim().toLowerCase();
    for (const row of flatRows) {
      if (getItemName(row.node).toLowerCase().includes(q)) {
        set.add(row.node.id);
      }
    }
    return set;
  }, [enableSearch, state.query, flatRows, getItemName]);
  const expansion = useExpansion({ dispatch, collectFolderIds });
  const selection = useSelection({
    dispatch,
    selectionMode,
    flatRows,
    selected: state.selected,
    anchor: state.anchor,
    focused: state.focused
  });
  const rename = useRename({
    dispatch,
    adapter,
    enableInlineRename,
    nodeById,
    getItemName,
    labels
  });
  const clipboard = useClipboard({
    dispatch,
    clipboard: state.clipboard,
    adapter,
    nodeById,
    labels
  });
  const dnd = useDnd({
    enabled: enableDnD,
    adapter,
    nodeById,
    selected: state.selected,
    labels,
    canDrop
  });
  const onActivateRef = useRef(onActivate);
  onActivateRef.current = onActivate;
  const activate = useCallback(
    (node, opts = { preview: false }) => onActivateRef.current?.(node, opts),
    []
  );
  const setQuery = useCallback(
    (q) => dispatch({ type: "set-query", q }),
    []
  );
  usePersistSync({
    expanded: state.expanded,
    selected: state.selected,
    persistKey,
    persistSelection,
    onSelectionChange,
    onExpansionChange
  });
  const resolvedContextMenuActions = useResolvedMenu({
    adapter,
    contextMenuActions,
    defaultMenuItems,
    labels,
    selected: state.selected,
    clipboard: state.clipboard,
    nodeById,
    getItemName,
    enableInlineRename,
    startRename: rename.startRename,
    cutToClipboard: clipboard.cutToClipboard,
    copyToClipboard: clipboard.copyToClipboard,
    pasteFromClipboard: clipboard.pasteFromClipboard
  });
  const finalRenderContextMenu = useMemo(
    () => {
      if (renderContextMenu) return renderContextMenu;
      const resolve = resolvedContextMenuActions;
      if (!resolve) return void 0;
      return (rowProps, trigger) => {
        const items = resolve(rowProps);
        const cleaned = items ? tidyMenuItems(items) : null;
        if (!cleaned || cleaned.length === 0) return trigger;
        return renderItemsAsContextMenu(rowProps, cleaned, trigger);
      };
    },
    [renderContextMenu, resolvedContextMenuActions]
  );
  const value = useMemo(
    () => ({
      // state
      expanded: state.expanded,
      selected: state.selected,
      anchor: state.anchor,
      focused: state.focused,
      query: state.query,
      renamingId: state.renaming,
      inlineRenameEnabled: rename.enabled,
      clipboard: state.clipboard,
      flatRows,
      matchingIds,
      // expansion
      ...expansion,
      // selection (note: `select` is from selection hook; expansion exports no `select`)
      ...selection,
      setQuery,
      // clipboard
      ...clipboard,
      // rename
      startRename: rename.startRename,
      cancelRename: rename.cancelRename,
      commitRename: rename.commitRename,
      // async
      refresh,
      refreshAll,
      activate,
      // config
      labels,
      appearance: resolvedAppearance,
      indent: resolvedAppearance.indent,
      selectionMode,
      activationMode,
      enableSearch,
      showIndentGuides,
      getItemName,
      // slots
      renderIcon,
      renderLabel,
      renderActions,
      renderContextMenu: finalRenderContextMenu,
      adapter,
      resolvedContextMenuActions,
      getNodeById: /* @__PURE__ */ __name((id) => nodeById.get(id), "getNodeById"),
      dnd
    }),
    [
      state.expanded,
      state.selected,
      state.anchor,
      state.focused,
      state.query,
      state.renaming,
      state.clipboard,
      rename.enabled,
      rename.startRename,
      rename.cancelRename,
      rename.commitRename,
      flatRows,
      matchingIds,
      expansion,
      selection,
      setQuery,
      clipboard,
      refresh,
      refreshAll,
      activate,
      labels,
      resolvedAppearance,
      selectionMode,
      activationMode,
      enableSearch,
      showIndentGuides,
      getItemName,
      renderIcon,
      renderLabel,
      renderActions,
      finalRenderContextMenu,
      adapter,
      resolvedContextMenuActions,
      nodeById,
      dnd
    ]
  );
  return /* @__PURE__ */ jsx(TreeContext.Provider, { value, children });
}
__name(TreeProvider, "TreeProvider");
function TreeDndProvider({ children }) {
  const ctx = useTreeContext();
  const { dnd } = ctx;
  const sensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),
    useSensor(KeyboardSensor)
  );
  const cursorYRef = useRef(0);
  const handleDragStart = useCallback(
    (e) => {
      dnd.beginDrag(e.active.id);
    },
    [dnd]
  );
  const handleDragMove = useCallback(
    (e) => {
      const overId = e.over?.id;
      if (overId === TREE_ROOT_DROP_ID) {
        const current2 = dnd.dropTarget;
        if (current2?.id !== null || current2?.position !== "inside") {
          dnd.setDropTarget({ id: null, position: "inside" });
        }
        return;
      }
      if (typeof overId !== "string") {
        if (dnd.dropTarget !== null) dnd.setDropTarget(null);
        return;
      }
      const rect = e.over?.rect;
      if (!rect) return;
      const el = document.querySelector(
        `[data-tree-row][data-id="${CSS.escape(overId)}"]`
      );
      const isFolder = el?.dataset.folder === "true";
      const position = resolveDropZone({
        pointerY: cursorYRef.current,
        rowRect: { top: rect.top, bottom: rect.top + rect.height, height: rect.height },
        isFolder
      });
      const current = dnd.dropTarget;
      if (current?.id !== overId || current.position !== position) {
        dnd.setDropTarget({ id: overId, position });
      }
    },
    [dnd]
  );
  const handleDragEnd = useCallback(
    async (_e) => {
      await dnd.commitDrop();
    },
    [dnd]
  );
  const handleDragCancel = useCallback(() => {
    dnd.cancelDrag();
  }, [dnd]);
  const handlePointerMove = useCallback((e) => {
    cursorYRef.current = e.clientY;
  }, []);
  if (!dnd.active) {
    return /* @__PURE__ */ jsx(Fragment, { children });
  }
  return /* @__PURE__ */ jsx(
    DndContext,
    {
      sensors,
      onDragStart: handleDragStart,
      onDragMove: handleDragMove,
      onDragEnd: handleDragEnd,
      onDragCancel: handleDragCancel,
      children: /* @__PURE__ */ jsx(
        "div",
        {
          onPointerMove: handlePointerMove,
          className: "contents",
          "data-tree-dnd-surface": "",
          children
        }
      )
    }
  );
}
__name(TreeDndProvider, "TreeDndProvider");
function TreeChevronRaw({ isExpanded, isFolder, className }) {
  const { appearance } = useTreeContext();
  const size = { width: "var(--tree-icon-size)", height: "var(--tree-icon-size)" };
  if (!isFolder) {
    return /* @__PURE__ */ jsx(
      "span",
      {
        "aria-hidden": true,
        style: size,
        className: cn("inline-block shrink-0", className)
      }
    );
  }
  const Icon = isExpanded ? ChevronDown : ChevronRight;
  return /* @__PURE__ */ jsx(
    Icon,
    {
      "aria-hidden": true,
      strokeWidth: appearance.iconStrokeWidth,
      style: size,
      className: cn(
        "shrink-0 text-muted-foreground/70 transition-transform",
        className
      )
    }
  );
}
__name(TreeChevronRaw, "TreeChevronRaw");
var TreeChevron = memo(TreeChevronRaw);
function TreeDropIndicator({
  position,
  indent,
  invalid = false
}) {
  if (position === "inside") {
    return /* @__PURE__ */ jsx(
      "span",
      {
        "aria-hidden": true,
        "data-tree-drop": "inside",
        className: cn(
          "pointer-events-none absolute inset-0 rounded-sm ring-1",
          invalid ? "bg-destructive/10 ring-destructive/40" : "bg-primary/10 ring-primary/40"
        )
      }
    );
  }
  const isBefore = position === "before";
  return /* @__PURE__ */ jsx(
    "span",
    {
      "aria-hidden": true,
      "data-tree-drop": position,
      style: { paddingLeft: indent },
      className: cn(
        "pointer-events-none absolute right-0 left-0 h-px",
        isBefore ? "top-0" : "bottom-0"
      ),
      children: /* @__PURE__ */ jsx(
        "span",
        {
          className: cn(
            "block h-0.5 rounded-full",
            invalid ? "bg-destructive/70" : "bg-primary"
          )
        }
      )
    }
  );
}
__name(TreeDropIndicator, "TreeDropIndicator");
function TreeIconRaw({ isFolder, isExpanded, className }) {
  const { appearance } = useTreeContext();
  const Icon = isFolder ? isExpanded ? FolderOpen : Folder : File;
  return /* @__PURE__ */ jsx(
    Icon,
    {
      "aria-hidden": true,
      strokeWidth: appearance.iconStrokeWidth,
      style: { width: "var(--tree-icon-size)", height: "var(--tree-icon-size)" },
      className: cn(
        "shrink-0",
        isFolder ? "text-foreground/70" : "text-muted-foreground/80",
        className
      )
    }
  );
}
__name(TreeIconRaw, "TreeIconRaw");
var TreeIcon = memo(TreeIconRaw);
function TreeIndentGuides({ level, indent }) {
  const { appearance } = useTreeContext();
  if (level <= 0) return null;
  return /* @__PURE__ */ jsx(
    "span",
    {
      "aria-hidden": true,
      className: "pointer-events-none absolute inset-y-0 left-0",
      style: { width: 8 + level * indent, opacity: appearance.indentGuideOpacity },
      children: Array.from({ length: level }).map((_, i) => /* @__PURE__ */ jsx(
        "span",
        {
          className: "absolute inset-y-0 w-px bg-border",
          style: { left: 8 + i * indent + indent / 2 - 0.5 }
        },
        i
      ))
    }
  );
}
__name(TreeIndentGuides, "TreeIndentGuides");
function TreeLabelRaw({ children, isMatchingSearch, className }) {
  return /* @__PURE__ */ jsx(
    "span",
    {
      style: { fontSize: "var(--tree-font-size)", color: "var(--foreground)" },
      className: cn(
        "truncate leading-tight tracking-[-0.005em]",
        isMatchingSearch && "font-medium",
        className
      ),
      children
    }
  );
}
__name(TreeLabelRaw, "TreeLabelRaw");
var TreeLabel = memo(TreeLabelRaw);

// src/tools/data/Tree/data/renameUtils.ts
function splitFileName(name) {
  if (name.length === 0) return { base: "", ext: "" };
  if (name.startsWith(".")) {
    const rest = name.slice(1);
    const dot2 = rest.lastIndexOf(".");
    if (dot2 < 0) return { base: name, ext: "" };
    return { base: "." + rest.slice(0, dot2), ext: rest.slice(dot2) };
  }
  const dot = name.lastIndexOf(".");
  if (dot <= 0) return { base: name, ext: "" };
  return { base: name.slice(0, dot), ext: name.slice(dot) };
}
__name(splitFileName, "splitFileName");
function autoSelectRange(name, isFolder) {
  if (isFolder) return [0, name.length];
  const { base } = splitFileName(name);
  return [0, base.length];
}
__name(autoSelectRange, "autoSelectRange");
function TreeRenameInput({
  initialValue,
  isFolder,
  onCommit,
  onCancel,
  className
}) {
  const [value, setValue] = useState(initialValue);
  const inputRef = useRef(null);
  const settledRef = useRef(false);
  useEffect(() => {
    const el = inputRef.current;
    if (!el) return;
    el.focus();
    const [start, end] = autoSelectRange(initialValue, isFolder);
    requestAnimationFrame(() => {
      try {
        el.setSelectionRange(start, end);
      } catch {
      }
    });
  }, []);
  const commit = /* @__PURE__ */ __name(() => {
    if (settledRef.current) return;
    settledRef.current = true;
    void onCommit(value);
  }, "commit");
  const cancel = /* @__PURE__ */ __name(() => {
    if (settledRef.current) return;
    settledRef.current = true;
    onCancel();
  }, "cancel");
  return /* @__PURE__ */ jsx(
    "input",
    {
      ref: inputRef,
      type: "text",
      value,
      onKeyDown: (e) => {
        e.stopPropagation();
        if (e.key === "Enter") {
          e.preventDefault();
          commit();
        } else if (e.key === "Escape") {
          e.preventDefault();
          cancel();
        }
      },
      onChange: (e) => setValue(e.target.value),
      onBlur: commit,
      onClick: (e) => e.stopPropagation(),
      onDoubleClick: (e) => e.stopPropagation(),
      onMouseDown: (e) => e.stopPropagation(),
      onContextMenu: (e) => e.stopPropagation(),
      className: cn(
        "min-w-0 flex-1 rounded-sm border border-primary/50 bg-background",
        "px-1 py-0 text-foreground outline-none",
        "focus:ring-1 focus:ring-primary/40",
        className
      ),
      style: {
        // Match the row's font metrics so the input doesn't visibly jolt.
        fontSize: "var(--tree-font-size)",
        height: "calc(var(--tree-row-height) - 4px)"
      }
    }
  );
}
__name(TreeRenameInput, "TreeRenameInput");
function TreeRowRaw({ row, className }) {
  const ctx = useTreeContext();
  const {
    appearance,
    activationMode,
    showIndentGuides,
    selected,
    focused,
    matchingIds,
    select,
    setSelectedIds,
    clickSelect,
    toggle,
    setFocus,
    activate,
    getItemName,
    renderIcon,
    renderLabel,
    renderActions,
    renderContextMenu,
    renamingId,
    commitRename,
    cancelRename,
    clipboard,
    dnd
  } = ctx;
  const { node, level, isFolder, isExpanded, isLoading, posInSet, setSize } = row;
  const isSelected = selected.has(node.id);
  const isFocused = focused === node.id;
  const isMatchingSearch = matchingIds.has(node.id);
  const isMultiSelect = ctx.selectionMode === "multiple";
  const isCut = clipboard?.kind === "cut" && clipboard.ids.includes(node.id);
  const slot = {
    node,
    level,
    isSelected,
    isExpanded,
    isFocused,
    isFolder,
    isLoading,
    isMatchingSearch
  };
  const isRenaming = renamingId === node.id;
  const isDragging = dnd.draggingIds.has(node.id);
  const dropTarget = dnd.dropTarget;
  const isDropTarget = dropTarget?.id === node.id;
  const dropPosition = isDropTarget ? dropTarget.position : null;
  const dndDisabled = !dnd.active || isRenaming || node.disabled;
  const draggable = useDraggable({ id: node.id, disabled: dndDisabled });
  const droppable = useDroppable({ id: node.id, disabled: dndDisabled });
  const setRowEl = useCallback(
    (el) => {
      draggable.setNodeRef(el);
      droppable.setNodeRef(el);
    },
    [draggable, droppable]
  );
  const isAllowedDrop = dropPosition && !isDragging ? dnd.isAllowedDrop(node, dropPosition) : true;
  const handleClick = /* @__PURE__ */ __name((e) => {
    if (node.disabled || isRenaming) return;
    setFocus(node.id);
    if (isMultiSelect) {
      clickSelect(node.id, { shift: e.shiftKey, meta: e.metaKey || e.ctrlKey });
    } else {
      select(node.id);
    }
    if (isFolder) {
      if (e.shiftKey || e.metaKey || e.ctrlKey) return;
      toggle(node.id);
    } else if (activationMode === "single-click") {
      if (e.shiftKey || e.metaKey || e.ctrlKey) return;
      activate(node, { preview: false });
    } else if (activationMode === "single-click-preview") {
      if (e.shiftKey || e.metaKey || e.ctrlKey) return;
      activate(node, { preview: true });
    }
  }, "handleClick");
  const handleDoubleClick = /* @__PURE__ */ __name(() => {
    if (node.disabled || isRenaming) return;
    if (isFolder) return;
    activate(node, { preview: false });
  }, "handleDoubleClick");
  const handleContextMenu = /* @__PURE__ */ __name(() => {
    if (node.disabled || isRenaming) return;
    setFocus(node.id);
    if (!isSelected) {
      setSelectedIds([node.id]);
    }
  }, "handleContextMenu");
  const trigger = /* @__PURE__ */ jsxs(
    "div",
    {
      ref: dnd.active ? setRowEl : void 0,
      id: treeRowDomId(node.id),
      role: "treeitem",
      "aria-level": level + 1,
      "aria-posinset": posInSet,
      "aria-setsize": setSize,
      "aria-expanded": isFolder ? isExpanded : void 0,
      "aria-selected": ctx.selectionMode === "none" ? void 0 : isSelected,
      "aria-disabled": node.disabled || void 0,
      "data-tree-row": "",
      "data-id": node.id,
      "data-activation-mode": activationMode,
      "data-selected": isSelected ? "true" : void 0,
      "data-clipboard": isCut ? "cut" : void 0,
      "data-dragging": isDragging ? "true" : void 0,
      "data-focused": isFocused && !isSelected ? "true" : void 0,
      "data-folder": isFolder || void 0,
      "data-expanded": isExpanded || void 0,
      tabIndex: -1,
      style: {
        paddingLeft: 6 + level * appearance.indent,
        // `auto` sizing lets a multi-line label (e.g. title + meta in a
        // chat-history list) grow the row instead of overflowing a fixed
        // height. `fixed` keeps the classic single-line explorer row.
        ...appearance.rowSizing === "auto" ? {
          minHeight: "var(--tree-row-height)",
          paddingTop: 4,
          paddingBottom: 4
        } : { height: "var(--tree-row-height)" },
        gap: "var(--tree-gap)"
      },
      ...dnd.active ? draggable.listeners : {},
      ...dnd.active ? draggable.attributes : {},
      onClick: handleClick,
      onDoubleClick: handleDoubleClick,
      onContextMenu: handleContextMenu,
      onFocus: () => setFocus(node.id),
      className: cn(
        "group/row relative flex w-full select-none items-center pr-2 text-left",
        "transition-colors outline-none",
        node.disabled ? "cursor-not-allowed" : "cursor-pointer",
        radiusClass(appearance),
        rowStateClasses(appearance),
        "focus-visible:ring-1 focus-visible:ring-ring/50",
        isMatchingSearch && "ring-1 ring-primary/30",
        isCut && "opacity-60",
        isDragging && "opacity-40",
        node.disabled && "opacity-50",
        className
      ),
      children: [
        appearance.showActiveIndicator && isSelected ? /* @__PURE__ */ jsx(
          "span",
          {
            "aria-hidden": true,
            className: cn(
              "absolute left-0 top-1 bottom-1 w-0.5 rounded-r-full",
              "bg-foreground/30 group-focus-within/tree:bg-primary"
            )
          }
        ) : null,
        dropPosition && !isDragging ? /* @__PURE__ */ jsx(
          TreeDropIndicator,
          {
            position: dropPosition,
            indent: 6 + level * appearance.indent,
            invalid: !isAllowedDrop
          }
        ) : null,
        showIndentGuides && level > 0 ? /* @__PURE__ */ jsx(TreeIndentGuides, { level, indent: appearance.indent }) : null,
        /* @__PURE__ */ jsx(TreeChevron, { isExpanded, isFolder }),
        isLoading ? /* @__PURE__ */ jsx(
          Loader2,
          {
            "aria-hidden": true,
            strokeWidth: appearance.iconStrokeWidth,
            style: { width: "var(--tree-icon-size)", height: "var(--tree-icon-size)" },
            className: "shrink-0 animate-spin text-muted-foreground/70"
          }
        ) : renderIcon ? renderIcon(slot) : (isFolder ? appearance.hideFolderIcons : appearance.hideLeafIcons) ? null : /* @__PURE__ */ jsx(TreeIcon, { isFolder, isExpanded }),
        /* @__PURE__ */ jsx(
          "span",
          {
            className: "flex min-w-0 flex-1 items-center",
            style: { gap: "var(--tree-gap)" },
            children: renamingId === node.id ? /* @__PURE__ */ jsx(
              TreeRenameInput,
              {
                initialValue: getItemName(node),
                isFolder,
                onCommit: (next) => commitRename(node.id, next),
                onCancel: cancelRename
              }
            ) : renderLabel ? renderLabel(slot) : /* @__PURE__ */ jsx(TreeLabel, { isMatchingSearch, children: getItemName(node) })
          }
        ),
        renderActions ? /* @__PURE__ */ jsx(
          "span",
          {
            className: "ml-auto flex shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover/row:opacity-100 group-focus-within/row:opacity-100",
            onClick: (e) => e.stopPropagation(),
            children: renderActions(slot)
          }
        ) : null
      ]
    }
  );
  if (renderContextMenu) {
    return /* @__PURE__ */ jsx(Fragment, { children: renderContextMenu(slot, trigger) });
  }
  return trigger;
}
__name(TreeRowRaw, "TreeRowRaw");
var TreeRow = memo(TreeRowRaw);
function TreeEmpty({ children, className }) {
  return /* @__PURE__ */ jsx(
    "div",
    {
      className: cn(
        "flex h-full min-h-32 items-center justify-center px-4 py-6 text-sm text-muted-foreground",
        className
      ),
      children
    }
  );
}
__name(TreeEmpty, "TreeEmpty");
var treeRowDomId = /* @__PURE__ */ __name((id) => `tree-row-${id}`, "treeRowDomId");
function TreeContent({
  children,
  className,
  ariaLabel,
  role = "tree"
}) {
  const { flatRows, labels, selected, focused, matchingIds, appearance, selectionMode } = useTreeContext();
  if (flatRows.length === 0) {
    return /* @__PURE__ */ jsx(TreeEmpty, { children: labels.empty });
  }
  const isTree = role === "tree";
  return /* @__PURE__ */ jsx(
    "div",
    {
      role,
      "aria-label": isTree ? ariaLabel ?? labels.ariaLabel : void 0,
      "aria-multiselectable": isTree && selectionMode === "multiple" ? true : void 0,
      className: cn("relative flex flex-col py-1", className),
      style: appearanceToStyle(appearance),
      children: flatRows.map((row) => {
        const slot = {
          node: row.node,
          level: row.level,
          isSelected: selected.has(row.node.id),
          isExpanded: row.isExpanded,
          isFocused: focused === row.node.id,
          isFolder: row.isFolder,
          isLoading: row.isLoading,
          isMatchingSearch: matchingIds.has(row.node.id)
        };
        const node = children ? children(slot) : /* @__PURE__ */ jsx(TreeRow, { row });
        return /* @__PURE__ */ jsx(Fragment$1, { children: node }, row.node.id);
      })
    }
  );
}
__name(TreeContent, "TreeContent");
function TreeEmptyArea({ className }) {
  const ctx = useTreeContext();
  const {
    adapter,
    labels,
    getItemName,
    clipboard,
    cutToClipboard,
    copyToClipboard,
    pasteFromClipboard,
    startRename,
    inlineRenameEnabled,
    dnd
  } = ctx;
  const { setNodeRef: setDroppableRef, isOver } = useDroppable({
    id: TREE_ROOT_DROP_ID,
    disabled: !dnd.active
  });
  const items = useMemo(() => {
    if (!adapter) return null;
    const builtinCtx = {
      adapter,
      labels,
      selectedNodes: [],
      targetNode: null,
      getName: getItemName,
      startInlineRename: inlineRenameEnabled ? startRename : void 0,
      clipboard: {
        hasItems: !!clipboard && clipboard.ids.length > 0,
        cut: cutToClipboard,
        copy: copyToClipboard,
        paste: /* @__PURE__ */ __name(() => pasteFromClipboard(null, "inside"), "paste")
      }
    };
    return buildDefaultMenuItems(builtinCtx);
  }, [
    adapter,
    labels,
    getItemName,
    inlineRenameEnabled,
    startRename,
    clipboard,
    cutToClipboard,
    copyToClipboard,
    pasteFromClipboard
  ]);
  const surface = /* @__PURE__ */ jsx(
    "div",
    {
      ref: dnd.active ? setDroppableRef : void 0,
      "data-tree-empty-area": "",
      "data-drop-active": dnd.active && isOver ? "true" : void 0,
      className: cn(
        // Soaks up the remaining vertical space inside the scroll
        // container so right-click on whitespace lands here, not on
        // the scroll viewport.
        "min-h-[2.5rem] flex-1",
        dnd.active && isOver && "bg-primary/5 rounded-sm ring-1 ring-primary/30",
        className
      )
    }
  );
  if (!items || items.length === 0) {
    return surface;
  }
  return /* @__PURE__ */ jsxs(ContextMenu, { children: [
    /* @__PURE__ */ jsx(ContextMenuTrigger, { asChild: true, children: surface }),
    /* @__PURE__ */ jsx(ContextMenuContent, { children: items.map((item, idx) => {
      if (item === "separator") {
        return /* @__PURE__ */ jsx(ContextMenuSeparator, {}, `sep-${idx}`);
      }
      const Icon = item.icon;
      return /* @__PURE__ */ jsxs(
        ContextMenuItem,
        {
          disabled: item.disabled,
          variant: item.destructive ? "destructive" : void 0,
          onSelect: () => item.onSelect({
            node: void 0,
            level: 0,
            isSelected: false,
            isExpanded: false,
            isFocused: false,
            isFolder: false,
            isLoading: false,
            isMatchingSearch: false
          }),
          children: [
            Icon ? /* @__PURE__ */ jsx(Icon, {}) : null,
            item.label,
            item.shortcut ? /* @__PURE__ */ jsx(ContextMenuShortcut, { children: item.shortcut }) : null
          ]
        },
        item.id
      );
    }) })
  ] });
}
__name(TreeEmptyArea, "TreeEmptyArea");
function useTreeLabels() {
  return useTreeContext().labels;
}
__name(useTreeLabels, "useTreeLabels");
function useTreeRows() {
  return useTreeContext().flatRows;
}
__name(useTreeRows, "useTreeRows");
function useTreeSelection() {
  const ctx = useTreeContext();
  const selectedIds = useMemo(() => [...ctx.selected], [ctx.selected]);
  const isSelected = useCallback(
    (id) => ctx.selected.has(id),
    [ctx.selected]
  );
  return useMemo(
    () => ({
      selectedIds,
      anchor: ctx.anchor,
      select: ctx.select,
      setSelectedIds: ctx.setSelectedIds,
      clear: ctx.clearSelection,
      clickSelect: ctx.clickSelect,
      moveSelect: ctx.moveSelect,
      selectAll: ctx.selectAll,
      isSelected
    }),
    [
      selectedIds,
      ctx.anchor,
      ctx.select,
      ctx.setSelectedIds,
      ctx.clearSelection,
      ctx.clickSelect,
      ctx.moveSelect,
      ctx.selectAll,
      isSelected
    ]
  );
}
__name(useTreeSelection, "useTreeSelection");
function useTreeExpansion() {
  const ctx = useTreeContext();
  const expandedIds = useMemo(() => [...ctx.expanded], [ctx.expanded]);
  const isExpanded = useCallback(
    (id) => ctx.expanded.has(id),
    [ctx.expanded]
  );
  return useMemo(
    () => ({
      expandedIds,
      expand: ctx.expand,
      collapse: ctx.collapse,
      toggle: ctx.toggle,
      expandAll: ctx.expandAll,
      collapseAll: ctx.collapseAll,
      isExpanded
    }),
    [
      expandedIds,
      ctx.expand,
      ctx.collapse,
      ctx.toggle,
      ctx.expandAll,
      ctx.collapseAll,
      isExpanded
    ]
  );
}
__name(useTreeExpansion, "useTreeExpansion");
function useTreeFocus() {
  const ctx = useTreeContext();
  return useMemo(
    () => ({ focusedId: ctx.focused, setFocus: ctx.setFocus }),
    [ctx.focused, ctx.setFocus]
  );
}
__name(useTreeFocus, "useTreeFocus");
function useTreeSearch() {
  const ctx = useTreeContext();
  return useMemo(
    () => ({
      isOpen: ctx.enableSearch,
      query: ctx.query,
      setQuery: ctx.setQuery,
      matchingIds: ctx.matchingIds,
      matchCount: ctx.matchingIds.size
    }),
    [ctx.enableSearch, ctx.query, ctx.setQuery, ctx.matchingIds]
  );
}
__name(useTreeSearch, "useTreeSearch");
function useTreeDnd() {
  const ctx = useTreeContext();
  return ctx.dnd;
}
__name(useTreeDnd, "useTreeDnd");
function useTreeClipboard() {
  const ctx = useTreeContext();
  const isCut = useCallback(
    (id) => ctx.clipboard?.kind === "cut" && ctx.clipboard.ids.includes(id),
    [ctx.clipboard]
  );
  return useMemo(
    () => ({
      clipboard: ctx.clipboard,
      isCut,
      cut: ctx.cutToClipboard,
      copy: ctx.copyToClipboard,
      paste: ctx.pasteFromClipboard,
      clear: ctx.clearClipboard
    }),
    [
      ctx.clipboard,
      isCut,
      ctx.cutToClipboard,
      ctx.copyToClipboard,
      ctx.pasteFromClipboard,
      ctx.clearClipboard
    ]
  );
}
__name(useTreeClipboard, "useTreeClipboard");
function useTreeRename() {
  const ctx = useTreeContext();
  return useMemo(
    () => ({
      /** True when the host allowed inline rename AND the adapter exposes `rename`. */
      enabled: ctx.inlineRenameEnabled,
      /** Currently renaming id, or `null`. */
      renamingId: ctx.renamingId,
      startRename: ctx.startRename,
      cancelRename: ctx.cancelRename,
      commitRename: ctx.commitRename
    }),
    [
      ctx.inlineRenameEnabled,
      ctx.renamingId,
      ctx.startRename,
      ctx.cancelRename,
      ctx.commitRename
    ]
  );
}
__name(useTreeRename, "useTreeRename");
function useTreeActions() {
  const ctx = useTreeContext();
  return useMemo(
    () => ({
      expand: ctx.expand,
      collapse: ctx.collapse,
      toggle: ctx.toggle,
      expandAll: ctx.expandAll,
      collapseAll: ctx.collapseAll,
      refresh: ctx.refresh,
      refreshAll: ctx.refreshAll,
      activate: ctx.activate
    }),
    [
      ctx.expand,
      ctx.collapse,
      ctx.toggle,
      ctx.expandAll,
      ctx.collapseAll,
      ctx.refresh,
      ctx.refreshAll,
      ctx.activate
    ]
  );
}
__name(useTreeActions, "useTreeActions");
function TreeSearchInput({ className, showMatches = true }) {
  const { labels } = useTreeContext();
  const { query, setQuery, matchCount } = useTreeSearch();
  return /* @__PURE__ */ jsxs(
    "div",
    {
      className: cn(
        "flex items-center gap-2 rounded-md border border-border bg-background px-2",
        className
      ),
      children: [
        /* @__PURE__ */ jsx(Search, { "aria-hidden": true, className: "size-3.5 shrink-0 text-muted-foreground" }),
        /* @__PURE__ */ jsx(
          "input",
          {
            type: "search",
            value: query,
            onChange: (e) => setQuery(e.target.value),
            placeholder: labels.searchPlaceholder,
            className: "h-7 w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground"
          }
        ),
        showMatches && query.trim().length > 0 ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs text-muted-foreground", children: labels.searchMatches(matchCount) }) : null,
        query.length > 0 ? /* @__PURE__ */ jsx(
          "button",
          {
            type: "button",
            onClick: () => setQuery(""),
            "aria-label": "Clear search",
            className: "shrink-0 rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground",
            children: /* @__PURE__ */ jsx(X, { "aria-hidden": true, className: "size-3.5" })
          }
        ) : null
      ]
    }
  );
}
__name(TreeSearchInput, "TreeSearchInput");

// src/tools/data/Tree/hooks/keyboard/arrow-nav.ts
function nextRowId(rows, idx) {
  if (rows.length === 0) return null;
  const next = rows[Math.min(idx + 1, rows.length - 1)] ?? rows[0];
  return next.node.id;
}
__name(nextRowId, "nextRowId");
function prevRowId(rows, idx) {
  if (rows.length === 0) return null;
  const prev = rows[Math.max(idx - 1, 0)] ?? rows[0];
  return prev.node.id;
}
__name(prevRowId, "prevRowId");
function edgeRowId(rows, edge) {
  if (rows.length === 0) return null;
  return edge === "first" ? rows[0].node.id : rows[rows.length - 1].node.id;
}
__name(edgeRowId, "edgeRowId");

// src/tools/data/Tree/hooks/keyboard/expand-collapse.ts
function resolveRightArrow(current, rows, idx) {
  if (!current) return { kind: "noop" };
  if (current.isFolder && !current.isExpanded) {
    return { kind: "expand", id: current.node.id };
  }
  if (current.isFolder && current.isExpanded) {
    const next = rows[idx + 1];
    return next ? { kind: "focus", id: next.node.id } : { kind: "noop" };
  }
  return { kind: "noop" };
}
__name(resolveRightArrow, "resolveRightArrow");
function resolveLeftArrow(current) {
  if (!current) return { kind: "noop" };
  if (current.isFolder && current.isExpanded) {
    return { kind: "collapse", id: current.node.id };
  }
  if (current.parentId) {
    return { kind: "focus", id: current.parentId };
  }
  return { kind: "noop" };
}
__name(resolveLeftArrow, "resolveLeftArrow");

// src/tools/data/Tree/hooks/keyboard/activation.ts
function resolveActivate(current) {
  if (!current) return { kind: "noop" };
  if (current.isFolder) {
    return {
      kind: "toggle-folder",
      id: current.node.id,
      willExpand: !current.isExpanded
    };
  }
  return { kind: "activate-leaf", id: current.node.id };
}
__name(resolveActivate, "resolveActivate");

// src/tools/data/Tree/hooks/keyboard/use-tree-keyboard.ts
function useTreeKeyboard({
  rows,
  focusedId,
  enabled = true,
  multiSelect = false,
  onFocus,
  onSelect,
  onActivate,
  onExpand,
  onCollapse,
  onClearSelection,
  onSelectAll
}) {
  const rowsRef = useRef(rows);
  const focusedIdRef = useRef(focusedId);
  rowsRef.current = rows;
  focusedIdRef.current = focusedId;
  const getCurrent = /* @__PURE__ */ __name(() => {
    const r = rowsRef.current;
    const id = focusedIdRef.current;
    const idx = id ? r.findIndex((x) => x.node.id === id) : -1;
    return { rows: r, idx, current: idx >= 0 ? r[idx] : null };
  }, "getCurrent");
  const refDown = useHotkey(
    ["down", "shift+down"],
    (e) => {
      const { rows: r, idx } = getCurrent();
      const id = nextRowId(r, idx);
      if (id) onFocus(id, { extend: multiSelect && e.shiftKey });
    },
    { enabled, preventDefault: true, description: "Next row (Shift extends)" }
  );
  const refUp = useHotkey(
    ["up", "shift+up"],
    (e) => {
      const { rows: r, idx } = getCurrent();
      const id = prevRowId(r, idx);
      if (id) onFocus(id, { extend: multiSelect && e.shiftKey });
    },
    { enabled, preventDefault: true, description: "Previous row (Shift extends)" }
  );
  const refHome = useHotkey(
    ["home", "shift+home"],
    (e) => {
      const id = edgeRowId(rowsRef.current, "first");
      if (id) onFocus(id, { extend: multiSelect && e.shiftKey });
    },
    { enabled, preventDefault: true, description: "First row (Shift extends)" }
  );
  const refEnd = useHotkey(
    ["end", "shift+end"],
    (e) => {
      const id = edgeRowId(rowsRef.current, "last");
      if (id) onFocus(id, { extend: multiSelect && e.shiftKey });
    },
    { enabled, preventDefault: true, description: "Last row (Shift extends)" }
  );
  const refSelectAll = useHotkey(
    "mod+a",
    () => {
      if (!multiSelect) return;
      onSelectAll?.();
    },
    {
      enabled: enabled && multiSelect,
      preventDefault: true,
      description: "Select all visible rows"
    }
  );
  const refRight = useHotkey(
    "right",
    () => {
      const { rows: r, idx, current } = getCurrent();
      const out = resolveRightArrow(current, r, idx);
      switch (out.kind) {
        case "expand":
          onExpand(out.id);
          return;
        case "focus":
          onFocus(out.id, { extend: false });
          return;
        case "noop":
          return;
      }
    },
    { enabled, preventDefault: true, description: "Expand / first child" }
  );
  const refLeft = useHotkey(
    "left",
    () => {
      const { current } = getCurrent();
      const out = resolveLeftArrow(current);
      switch (out.kind) {
        case "collapse":
          onCollapse(out.id);
          return;
        case "focus":
          onFocus(out.id, { extend: false });
          return;
        case "noop":
          return;
      }
    },
    { enabled, preventDefault: true, description: "Collapse / parent" }
  );
  const refActivate = useHotkey(
    ["enter", "space"],
    () => {
      const { current } = getCurrent();
      const out = resolveActivate(current);
      if (out.kind === "noop") return;
      onSelect(out.kind === "activate-leaf" ? out.id : out.id);
      if (out.kind === "toggle-folder") {
        if (out.willExpand) onExpand(out.id);
        else onCollapse(out.id);
      } else {
        onActivate(out.id);
      }
    },
    { enabled, preventDefault: true, description: "Activate / toggle" }
  );
  const refEscape = useHotkey(
    "escape",
    () => onClearSelection(),
    { enabled, preventDefault: true, description: "Clear selection" }
  );
  const ref = useCallback(
    (instance) => {
      refDown(instance);
      refUp(instance);
      refHome(instance);
      refEnd(instance);
      refRight(instance);
      refLeft(instance);
      refActivate(instance);
      refEscape(instance);
      refSelectAll(instance);
    },
    [
      refDown,
      refUp,
      refHome,
      refEnd,
      refRight,
      refLeft,
      refActivate,
      refEscape,
      refSelectAll
    ]
  );
  return { ref };
}
__name(useTreeKeyboard, "useTreeKeyboard");

// src/tools/data/Tree/hooks/type-ahead/match-prefix.ts
function findRowByPrefix(rows, getName, prefix) {
  if (prefix.length === 0) return void 0;
  return rows.find((row) => getName(row.node).toLowerCase().startsWith(prefix));
}
__name(findRowByPrefix, "findRowByPrefix");
function isResetKey(key) {
  return key === "Escape" || key === "Enter" || key === "Tab" || key.startsWith("Arrow") || key === "Home" || key === "End" || key === "PageUp" || key === "PageDown";
}
__name(isResetKey, "isResetKey");
function isTypingTarget(target) {
  const el = target;
  if (!el) return false;
  const tag = el.tagName;
  if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
  return el.isContentEditable === true;
}
__name(isTypingTarget, "isTypingTarget");

// src/tools/data/Tree/hooks/type-ahead/use-tree-type-ahead.ts
var FLUSH_MS = 600;
function useTreeTypeAhead({
  rows,
  getItemName,
  containerRef,
  onMatch,
  enabled = true
}) {
  const bufferRef = useRef("");
  const timerRef = useRef(null);
  const rowsRef = useRef(rows);
  const getNameRef = useRef(getItemName);
  const onMatchRef = useRef(onMatch);
  rowsRef.current = rows;
  getNameRef.current = getItemName;
  onMatchRef.current = onMatch;
  useEffect(() => {
    if (!enabled) return;
    const target = containerRef.current;
    if (!target) return;
    const reset = /* @__PURE__ */ __name(() => {
      bufferRef.current = "";
      if (timerRef.current) {
        clearTimeout(timerRef.current);
        timerRef.current = null;
      }
    }, "reset");
    const handler = /* @__PURE__ */ __name((e) => {
      if (isTypingTarget(e.target)) return;
      if (e.metaKey || e.ctrlKey || e.altKey) return;
      if (isResetKey(e.key)) {
        reset();
        return;
      }
      if (e.key.length !== 1) return;
      bufferRef.current += e.key.toLowerCase();
      if (timerRef.current) clearTimeout(timerRef.current);
      timerRef.current = setTimeout(reset, FLUSH_MS);
      const hit = findRowByPrefix(
        rowsRef.current,
        getNameRef.current,
        bufferRef.current
      );
      if (hit) {
        e.preventDefault();
        onMatchRef.current(hit.node.id);
      }
    }, "handler");
    target.addEventListener("keydown", handler);
    return () => {
      target.removeEventListener("keydown", handler);
      reset();
    };
  }, [containerRef, enabled]);
}
__name(useTreeTypeAhead, "useTreeTypeAhead");

// src/tools/data/Tree/hooks/finder-hotkeys/build-ctx.ts
function buildBuiltinCtx(input) {
  if (!input.adapter) return null;
  const selectedNodes = [];
  for (const id of input.selected) {
    const n = input.getNodeById(id);
    if (n) selectedNodes.push(n);
  }
  const targetNode = input.focused ? input.getNodeById(input.focused) ?? null : null;
  return {
    adapter: input.adapter,
    labels: input.labels,
    selectedNodes,
    targetNode,
    getName: input.getItemName,
    startInlineRename: input.startInlineRename,
    clipboard: input.clipboard
  };
}
__name(buildBuiltinCtx, "buildBuiltinCtx");

// src/tools/data/Tree/hooks/finder-hotkeys/use-tree-finder-hotkeys.ts
function useTreeFinderHotkeys(opts) {
  const optsRef = useRef(opts);
  optsRef.current = opts;
  const run = useCallback(async (action) => {
    const o = optsRef.current;
    if (o.paused) return;
    const ctx = buildBuiltinCtx({
      adapter: o.adapter,
      labels: o.labels,
      selected: o.selected,
      focused: o.focused,
      getNodeById: o.getNodeById,
      getItemName: o.getItemName,
      startInlineRename: o.startInlineRename,
      clipboard: o.clipboard
    });
    if (!ctx) return;
    await runBuiltinAction(action, ctx);
  }, []);
  const refDelete = useHotkey(
    ["mod+backspace", "delete"],
    () => void run("delete"),
    {
      enabled: opts.enabled,
      preventDefault: true,
      description: "Delete selected items",
      scope: "tree"
    }
  );
  const refRename = useHotkey("f2", () => void run("rename"), {
    enabled: opts.enabled,
    preventDefault: true,
    description: "Rename selected item",
    scope: "tree"
  });
  const refDuplicate = useHotkey("mod+d", () => void run("duplicate"), {
    enabled: opts.enabled,
    preventDefault: true,
    description: "Duplicate selected items",
    scope: "tree"
  });
  const refNewFolder = useHotkey("mod+shift+n", () => void run("new-folder"), {
    enabled: opts.enabled,
    preventDefault: true,
    description: "New folder",
    scope: "tree"
  });
  const refNewFile = useHotkey("mod+n", () => void run("new-file"), {
    enabled: opts.enabled,
    preventDefault: true,
    description: "New file",
    scope: "tree"
  });
  const refCut = useHotkey("mod+x", () => void run("cut"), {
    enabled: opts.enabled,
    preventDefault: true,
    description: "Cut",
    scope: "tree"
  });
  const refCopy = useHotkey("mod+c", () => void run("copy"), {
    enabled: opts.enabled,
    preventDefault: true,
    description: "Copy",
    scope: "tree"
  });
  const refPaste = useHotkey("mod+v", () => void run("paste"), {
    enabled: opts.enabled,
    preventDefault: true,
    description: "Paste",
    scope: "tree"
  });
  const ref = useCallback(
    (instance) => {
      refDelete(instance);
      refRename(instance);
      refDuplicate(instance);
      refNewFolder(instance);
      refNewFile(instance);
      refCut(instance);
      refCopy(instance);
      refPaste(instance);
    },
    [
      refDelete,
      refRename,
      refDuplicate,
      refNewFolder,
      refNewFile,
      refCut,
      refCopy,
      refPaste
    ]
  );
  return { ref };
}
__name(useTreeFinderHotkeys, "useTreeFinderHotkeys");
function TreeRoot(props) {
  const {
    data,
    getItemName,
    loadChildren,
    selectionMode,
    activationMode,
    initialExpandedIds,
    initialSelectedIds,
    indent,
    appearance,
    onSelectionChange,
    onExpansionChange,
    onActivate,
    filterNode,
    enableSearch = false,
    enableTypeAhead = true,
    showIndentGuides = false,
    enableInlineRename = false,
    enableFinderHotkeys = false,
    enableDnD = false,
    canDrop,
    renderRow,
    renderIcon,
    renderLabel,
    renderActions,
    renderContextMenu,
    contextMenuActions,
    labels,
    persistKey,
    persistSelection = false,
    adapter,
    defaultMenuItems,
    actionsRef,
    className,
    style
  } = props;
  return /* @__PURE__ */ jsx(
    TreeProvider,
    {
      data,
      getItemName,
      loadChildren,
      selectionMode,
      activationMode,
      initialExpandedIds,
      initialSelectedIds,
      indent,
      appearance,
      onSelectionChange,
      onExpansionChange,
      onActivate,
      filterNode,
      enableSearch,
      showIndentGuides,
      renderIcon,
      renderLabel,
      renderActions,
      renderContextMenu,
      contextMenuActions,
      adapter,
      defaultMenuItems,
      enableInlineRename,
      enableDnD,
      canDrop,
      labels,
      persistKey,
      persistSelection,
      children: /* @__PURE__ */ jsx(
        TreeRootShell,
        {
          className,
          style,
          enableSearch,
          enableTypeAhead,
          enableFinderHotkeys,
          renderRow,
          actionsRef
        }
      )
    }
  );
}
__name(TreeRoot, "TreeRoot");
function TreeRootShell({
  className,
  style,
  enableSearch,
  enableTypeAhead,
  enableFinderHotkeys,
  renderRow,
  actionsRef
}) {
  const containerRef = useRef(null);
  const ctx = useTreeContext();
  useEffect(() => {
    if (!actionsRef) return;
    actionsRef.current = {
      refresh: ctx.refresh,
      refreshAll: ctx.refreshAll,
      expandAll: ctx.expandAll,
      collapseAll: ctx.collapseAll
    };
    return () => {
      if (actionsRef.current) actionsRef.current = null;
    };
  }, [
    actionsRef,
    ctx.refresh,
    ctx.refreshAll,
    ctx.expandAll,
    ctx.collapseAll
  ]);
  const isMulti = ctx.selectionMode === "multiple";
  const { ref: keyboardRef } = useTreeKeyboard({
    rows: ctx.flatRows,
    focusedId: ctx.focused,
    multiSelect: isMulti,
    // Pause container hotkeys while inline rename is active so the
    // user can type freely (TreeRenameInput stops bubbling already, but
    // gating here is the cleaner second line of defence).
    enabled: ctx.renamingId === null,
    onFocus: /* @__PURE__ */ __name((id, { extend }) => {
      if (extend && isMulti) {
        ctx.moveSelect(id, { extend: true });
      } else {
        ctx.setFocus(id);
      }
    }, "onFocus"),
    onSelect: ctx.select,
    onActivate: /* @__PURE__ */ __name((id) => {
      const row = ctx.flatRows.find((r) => r.node.id === id);
      if (row) ctx.activate(row.node, { preview: false });
    }, "onActivate"),
    onExpand: ctx.expand,
    onCollapse: ctx.collapse,
    onClearSelection: ctx.clearSelection,
    onSelectAll: ctx.selectAll
  });
  const { ref: finderHotkeysRef } = useTreeFinderHotkeys({
    enabled: enableFinderHotkeys,
    paused: ctx.renamingId !== null,
    adapter: ctx.adapter,
    labels: ctx.labels,
    selected: ctx.selected,
    focused: ctx.focused,
    getNodeById: ctx.getNodeById,
    getItemName: ctx.getItemName,
    startInlineRename: ctx.inlineRenameEnabled ? ctx.startRename : void 0,
    clipboard: {
      hasItems: !!ctx.clipboard && ctx.clipboard.ids.length > 0,
      cut: ctx.cutToClipboard,
      copy: ctx.copyToClipboard,
      // Hotkey paste targets the currently focused row (or null = root).
      paste: /* @__PURE__ */ __name(() => {
        const target = ctx.focused ? ctx.getNodeById(ctx.focused) ?? null : null;
        return ctx.pasteFromClipboard(target, "inside");
      }, "paste")
    }
  });
  const setContainerRef = useCallback(
    (instance) => {
      containerRef.current = instance;
      keyboardRef(instance);
      finderHotkeysRef(instance);
    },
    [keyboardRef, finderHotkeysRef]
  );
  const focusedId = ctx.focused;
  useEffect(() => {
    if (!focusedId) return;
    const el = containerRef.current?.querySelector(
      `[data-tree-row][data-id="${CSS.escape(focusedId)}"]`
    );
    el?.scrollIntoView({ block: "nearest" });
  }, [focusedId]);
  const onTypeAheadMatch = useCallback(
    (id) => {
      ctx.setFocus(id);
    },
    [ctx]
  );
  useTreeTypeAhead({
    rows: ctx.flatRows,
    getItemName: ctx.getItemName,
    containerRef,
    onMatch: onTypeAheadMatch,
    enabled: enableTypeAhead
  });
  const treeBody = /* @__PURE__ */ jsxs(
    "div",
    {
      ref: setContainerRef,
      tabIndex: 0,
      role: "tree",
      "aria-label": ctx.labels.ariaLabel,
      "aria-multiselectable": ctx.selectionMode === "multiple" || void 0,
      "aria-activedescendant": focusedId ? treeRowDomId(focusedId) : void 0,
      className: cn(
        "group/tree flex h-full w-full flex-col gap-2 rounded-sm outline-none",
        "focus-visible:ring-1 focus-visible:ring-ring/50",
        className
      ),
      style: { ...appearanceToStyle(ctx.appearance), ...style },
      "data-tree-root": "",
      children: [
        enableSearch ? /* @__PURE__ */ jsx(TreeSearchInput, { className: "mx-2 mt-2" }) : null,
        /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col overflow-auto px-1", children: [
          /* @__PURE__ */ jsx(TreeContent, { role: "group", children: renderRow }),
          /* @__PURE__ */ jsx(TreeEmptyArea, {})
        ] })
      ]
    }
  );
  return /* @__PURE__ */ jsx(TreeDndProvider, { children: treeBody });
}
__name(TreeRootShell, "TreeRootShell");
var TreeRoot_default = TreeRoot;
function FinderTree(props) {
  return /* @__PURE__ */ jsx(
    TreeRoot,
    {
      selectionMode: "multiple",
      activationMode: "double-click",
      enableInlineRename: true,
      enableFinderHotkeys: true,
      enableDnD: true,
      enableTypeAhead: true,
      showIndentGuides: true,
      appearance: { density: "cozy" },
      ...props
    }
  );
}
__name(FinderTree, "FinderTree");
function TreeSkeleton({ rows = 6, className }) {
  return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-1 p-2", className), "aria-hidden": true, children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", style: { paddingLeft: i % 3 * 16 }, children: [
    /* @__PURE__ */ jsx("span", { className: "size-4 shrink-0 animate-pulse rounded bg-muted" }),
    /* @__PURE__ */ jsx("span", { className: "size-4 shrink-0 animate-pulse rounded bg-muted" }),
    /* @__PURE__ */ jsx("span", { className: "h-3 flex-1 animate-pulse rounded bg-muted" })
  ] }, i)) });
}
__name(TreeSkeleton, "TreeSkeleton");
function TreeError({ children, className }) {
  return /* @__PURE__ */ jsxs(
    "div",
    {
      className: cn(
        "flex items-start gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive",
        className
      ),
      role: "alert",
      children: [
        /* @__PURE__ */ jsx(AlertCircle, { "aria-hidden": true, className: "mt-0.5 size-4 shrink-0" }),
        /* @__PURE__ */ jsx("span", { children })
      ]
    }
  );
}
__name(TreeError, "TreeError");

// src/tools/data/Tree/data/createDemoTree.ts
function createDemoTree({
  depth = 3,
  breadth = 4,
  rootPrefix = "node"
} = {}) {
  const make = /* @__PURE__ */ __name((id, name, level) => {
    if (level >= depth) {
      return { id, data: { name } };
    }
    const children = [];
    for (let i = 0; i < breadth; i++) {
      const childId = `${id}/${i}`;
      children.push(make(childId, `${name}-${i}`, level + 1));
    }
    return { id, data: { name }, children };
  }, "make");
  const roots = [];
  for (let i = 0; i < breadth; i++) {
    roots.push(make(`${rootPrefix}-${i}`, `${rootPrefix} ${i}`, 1));
  }
  return roots;
}
__name(createDemoTree, "createDemoTree");

export { DEFAULT_TREE_APPEARANCE, DEFAULT_TREE_LABELS, FinderTree, TREE_DND_MIME, TreeRoot as Tree, TreeChevron, TreeContent, TreeDropIndicator, TreeEmpty, TreeEmptyArea, TreeError, TreeIcon, TreeIndentGuides, TreeLabel, TreeProvider, TreeRenameInput, TreeRoot, TreeRow, TreeSearchInput, TreeSkeleton, appearanceToStyle, autoSelectRange, clearTreeState, createChildCache, createDemoTree, TreeRoot_default as default, defaultCanDrop, flattenTree, loadTreeState, resolveAppearance, resolveChildren, resolveDropZone, saveTreeState, splitFileName, useTreeActions, useTreeClipboard, useTreeContext, useTreeDnd, useTreeExpansion, useTreeFinderHotkeys, useTreeFocus, useTreeKeyboard, useTreeLabels, useTreeRename, useTreeRows, useTreeSearch, useTreeSelection, useTreeTypeAhead };
//# sourceMappingURL=index.mjs.map
//# sourceMappingURL=index.mjs.map