jameskerr/react-arborist
 Watch   
 Star   
 Fork   
6 hours ago
react-arborist

v4.0.0

Breaking Changes

  • react-dnd and react-dnd-html5-backend are now peer dependencies instead of bundled dependencies — install them alongside react-arborist (npm install react-arborist react-dnd react-dnd-html5-backend). This fixes a global singleton conflict (#319) where apps that also used react-dnd ended up with two independent copies of the library, causing drag-and-drop to silently break or throw "Cannot have two HTML5 backends at the same time." Both peers must be v16 (^16), and both are required even when you pass your own dndBackend / dndManager, because the drag preview calls into react-dnd-html5-backend on every drag. react-dnd v16 is ESM-only, and react-arborist now ships a single ESM build too (the CommonJS dist/main build is gone), so import and require load the same copy instead of two copies with separate React contexts. require("react-arborist") from CommonJS relies on require(esm), unflagged from Node 22.12 — now the engines.node floor, which package managers check at install time, so installing v4 requires Node ≥ 22.12 even for bundler and browser consumers. CommonJS TypeScript projects on Node module resolution need module: "nodenext" (TypeScript ≥ 5.8) or "node20" (TypeScript ≥ 5.9); "node16" and "node18" report TS1479. Jest users must add react-arborist to the transformIgnorePatterns exception list alongside react-dnd (see the README). The package also declares an exports map: react-arborist and react-arborist/package.json resolve as before, but deep imports such as react-arborist/dist/module/... are no longer resolvable. The react and react-dom peer floor rises from 16.14 to 18: the build now imports react/jsx-runtime and useSyncExternalStore directly from React, which older versions can't provide to ESM consumers. (#371)

Fixes

  • @types/react-window is now a regular dependency instead of a dev dependency. react-arborist's public type declarations reference react-window types (onScroll, outerElementType, innerElementType, tree.list, scroll alignment), so without it TypeScript reported TS7016 under skipLibCheck: false and silently typed those as any otherwise. (#371)
2026-07-26 03:11:01
react-arborist

v3.16.0

Features

  • Added a filteredCount getter to the tree API, reporting how many nodes match the current searchTerm across the whole tree (regardless of which folders are open), or 0 when there is no active search. Consumers can now render a match count or a "no results" message via isFiltered && filteredCount === 0 instead of inspecting visibleNodes (issues #112 and #256). (#383)

Fixes

  • The default searchMatch no longer searches a node's children. It previously stringified every value of the node's data, the children array included, so each ancestor of a match counted as a match itself, and terms like id or name matched every folder by hitting keys nested in the children data. The filtered list is unchanged — parents of a match are still shown to keep the tree's structure — but tree.filteredCount now reports real matches. (#383)
2026-07-22 09:31:56
react-arborist

v3.15.1

Fixes

  • Fixed the drag destination (willReceiveDrop, dragDestinationParent) reporting a parent the cursor forbids. The hover handlers recorded a destination on every hover — even where canDrop() was false — so dragging a folder toward its own subtree left the reported parent pointing at that folder while the cursor said "no drop." The consumer-facing destination and the cursor are now both gated on canDrop() and stay consistent; releasing over an invalid spot is still rejected rather than falling back to a root drop (the parentId half of issue #247). (#382)
2026-07-20 07:36:06
react-arborist

v3.15.0

Features

  • Added an adjustMoveIndex helper for custom onMove handlers. onMove's index is a pre-removal slot (it counts the destination rows as displayed, with the dragged rows still in place), which trips up handlers that splice the dragged rows out before inserting them — dragging a row just below itself would jump it past its neighbor. adjustMoveIndex({ index, dragIds, siblingIds }) returns the index to insert at after removal. SimpleTree/useSimpleTree are unaffected; they already insert before removing (issue #247). (#381)
2026-07-20 03:22:00
react-arborist

v3.14.0

Features

  • Dragging into the gap between an open folder and its first child now supports a horizontal slide, matching how items and closed folders already behave. Sliding right still drops the node as the folder's first child (the previous behavior); sliding left drops it as a sibling — or grandsibling — of the folder, bounded by the folder's ancestor chain. computeDrop previously hard-coded this gap to "first child," so the level was pinned and the slide never engaged (issue #330). (#378)
2026-07-06 05:55:55
react-arborist

v3.13.2

Fixes

  • Inputs rendered inside the tree (e.g. an <input> in a modal) can now receive Space characters again. The tree's keyboard handler no longer intercepts keystrokes that originate from a nested form field or contenteditable element. (#377)
2026-07-05 06:41:00
react-arborist

v3.13.1

Fixes

  • NodeApi action methods (toggle, select, activate, focus, edit, etc.) are now bound to the node, so passing them as callbacks — e.g. <Toggle onClick={node.toggle} /> — no longer throws "Cannot read properties of undefined (reading 'tree')" when invoked detached. (#374)
2026-07-04 10:20:51
react-arborist

v3.13.0

Features

  • useSimpleTree now accepts an onChange option, called with the full data array after any internal move/create/rename/delete — a single place to persist the whole tree without wiring up each handler yourself. (#373)
2026-06-29 05:55:08
react-arborist

v3.12.0

Features

  • Added a disableDeselectOnClick prop. By default, clicking the empty area below the rows clears the selection; setting this prop keeps the current selection intact instead (#245, #308). (#369)
2026-06-29 02:46:35
react-arborist

v3.11.0

Features

  • TreeApi now exposes scrollToOffset(offset) to scroll the list to an exact pixel offset from the top, and a scrollOffset getter to read the current position — the offset-based counterpart to scrollTo(id), useful for saving and restoring scroll position (#194). (#368)