dnd-block-tree 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,12 +1,8 @@
1
1
  # dnd-block-tree
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/dnd-block-tree.svg)](https://www.npmjs.com/package/dnd-block-tree)
4
- [![npm downloads](https://img.shields.io/npm/dm/dnd-block-tree.svg)](https://www.npmjs.com/package/dnd-block-tree)
5
- [![bundle size](https://img.shields.io/bundlephobia/minzip/dnd-block-tree)](https://bundlephobia.com/package/dnd-block-tree)
6
4
  [![CI](https://github.com/thesandybridge/dnd-block-tree/actions/workflows/ci.yml/badge.svg)](https://github.com/thesandybridge/dnd-block-tree/actions/workflows/ci.yml)
7
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue.svg)](https://www.typescriptlang.org/)
9
- [![demo](https://img.shields.io/badge/demo-live-brightgreen.svg)](https://dnd-block-tree.vercel.app)
5
+ [![demo](https://img.shields.io/badge/demo-live-brightgreen.svg)](https://blocktree.sandybridge.io)
10
6
 
11
7
  A headless React library for building hierarchical drag-and-drop interfaces. Bring your own components, we handle the complexity.
12
8
 
@@ -517,7 +513,7 @@ Enable accessible tree navigation with the `keyboardNavigation` prop:
517
513
  | Home | Focus first block |
518
514
  | End | Focus last block |
519
515
 
520
- Blocks receive `data-block-id` and `tabIndex` attributes for focus management, and the tree root gets `role="tree"`.
516
+ Blocks receive `data-block-id` and `tabIndex` attributes for focus management, and the tree root gets `role="tree"`. Each block element includes WAI-ARIA TreeView attributes: `aria-level`, `aria-posinset`, `aria-setsize`, `aria-expanded` (containers only), and `aria-selected`.
521
517
 
522
518
  ## Multi-Select Drag
523
519
 
@@ -689,6 +685,7 @@ import {
689
685
  deleteBlockAndDescendants, // Remove a block and all its descendants from index
690
686
  getBlockDepth, // Compute depth of a block (root = 1)
691
687
  getSubtreeDepth, // Max depth of a subtree (leaf = 1)
688
+ validateBlockTree, // Validate tree for cycles, orphans, stale refs
692
689
 
693
690
  // Serialization
694
691
  flatToNested, // Convert flat block array to nested tree
@@ -716,10 +713,19 @@ import {
716
713
  createStickyCollision, // Hysteresis wrapper with snapshot support
717
714
  type SnapshotRectsRef, // Ref type for frozen zone rects
718
715
 
716
+ // Internal helpers
717
+ cloneMap, // Clone a Map
718
+ cloneParentMap, // Deep clone a parent->children Map
719
+ debounce, // Debounce with cancel()
720
+
719
721
  // Hooks
722
+ createBlockState, // Factory for block state context + provider
723
+ createTreeState, // Factory for tree UI state context + provider
720
724
  useBlockHistory, // Undo/redo state management
721
725
  useLayoutAnimation, // FLIP-based reorder animations
722
726
  useVirtualTree, // Virtual scrolling primitives
727
+ useConfiguredSensors, // Configure dnd-kit sensors
728
+ getSensorConfig, // Get sensor config from SensorConfig
723
729
 
724
730
  // Components
725
731
  BlockTree, // Main drag-and-drop tree component
@@ -732,7 +738,7 @@ import {
732
738
 
733
739
  ## Demo
734
740
 
735
- Check out the [live demo](https://dnd-block-tree.vercel.app) to see the library in action with two example use cases:
741
+ Check out the [live demo](https://blocktree.sandybridge.io) to see the library in action with two example use cases:
736
742
 
737
743
  - **Productivity** - Sections, tasks, and notes with undo/redo, max depth control, and keyboard navigation
738
744
  - **File System** - Folders and files
package/dist/index.d.mts CHANGED
@@ -389,6 +389,78 @@ interface TreeStateProviderProps<T extends BaseBlock = BaseBlock> {
389
389
  blockMap: Map<string, T>;
390
390
  }
391
391
 
392
+ /**
393
+ * Clone a Map
394
+ */
395
+ declare function cloneMap<K, V>(map: Map<K, V>): Map<K, V>;
396
+ /**
397
+ * Clone a parent map with arrays
398
+ */
399
+ declare function cloneParentMap(map: Map<string | null, string[]>): Map<string | null, string[]>;
400
+ /**
401
+ * Compute normalized index from flat block array.
402
+ *
403
+ * With `orderingStrategy: 'fractional'`, siblings are sorted by their `order`
404
+ * field (lexicographic). With `'integer'` (default), the input order is preserved.
405
+ */
406
+ declare function computeNormalizedIndex<T extends BaseBlock>(blocks: T[], orderingStrategy?: OrderingStrategy): BlockIndex<T>;
407
+ /**
408
+ * Build ordered flat array from BlockIndex.
409
+ *
410
+ * With `'integer'` ordering (default), assigns sequential `order: 0, 1, 2, …`.
411
+ * With `'fractional'` ordering, preserves existing `order` values — the moved
412
+ * block already has its new fractional key set by `reparentBlockIndex`.
413
+ */
414
+ declare function buildOrderedBlocks<T extends BaseBlock>(index: BlockIndex<T>, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy): T[];
415
+ /**
416
+ * Reparent a block based on drop zone ID.
417
+ *
418
+ * @param state - Current block index
419
+ * @param activeId - ID of the dragged block
420
+ * @param targetZone - Drop zone ID (e.g., "after-uuid", "before-uuid", "into-uuid")
421
+ * @param containerTypes - Block types that can have children
422
+ * @param orderingStrategy - Whether to assign a fractional key to the moved block
423
+ */
424
+ declare function reparentBlockIndex<T extends BaseBlock>(state: BlockIndex<T>, activeId: UniqueIdentifier, targetZone: string, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy, maxDepth?: number): BlockIndex<T>;
425
+ /**
426
+ * Compute the depth of a block by walking its parentId chain.
427
+ * Root-level blocks have depth 1.
428
+ */
429
+ declare function getBlockDepth<T extends BaseBlock>(index: BlockIndex<T>, blockId: string): number;
430
+ /**
431
+ * Compute the maximum depth of a subtree rooted at blockId (inclusive).
432
+ * A leaf block returns 1.
433
+ */
434
+ declare function getSubtreeDepth<T extends BaseBlock>(index: BlockIndex<T>, blockId: string, visited?: Set<string>): number;
435
+ /**
436
+ * Get all descendant IDs of a block
437
+ */
438
+ declare function getDescendantIds<T extends BaseBlock>(state: BlockIndex<T>, parentId: string): Set<string>;
439
+ /**
440
+ * Reparent multiple blocks to a target zone, preserving their relative order.
441
+ * The first block in `blockIds` is treated as the primary (anchor) block.
442
+ */
443
+ declare function reparentMultipleBlocks<T extends BaseBlock>(state: BlockIndex<T>, blockIds: string[], targetZone: string, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy, maxDepth?: number): BlockIndex<T>;
444
+ /**
445
+ * Result of validating a block tree
446
+ */
447
+ interface TreeValidationResult {
448
+ valid: boolean;
449
+ issues: string[];
450
+ }
451
+ /**
452
+ * Validate a block tree index for structural integrity.
453
+ * Checks for cycles, orphans (parentId references non-existent block),
454
+ * and stale refs (byParent lists IDs not present in byId).
455
+ *
456
+ * Opt-in utility — not called automatically.
457
+ */
458
+ declare function validateBlockTree<T extends BaseBlock>(index: BlockIndex<T>): TreeValidationResult;
459
+ /**
460
+ * Delete a block and all its descendants
461
+ */
462
+ declare function deleteBlockAndDescendants<T extends BaseBlock>(state: BlockIndex<T>, id: string): BlockIndex<T>;
463
+
392
464
  type SnapshotRectsRef = {
393
465
  current: Map<UniqueIdentifier, DOMRect> | null;
394
466
  };
@@ -527,7 +599,8 @@ interface TreeRendererProps<T extends BaseBlock> {
527
599
  /**
528
600
  * Recursive tree renderer with smart drop zones
529
601
  */
530
- declare function TreeRenderer<T extends BaseBlock>({ blocks, blocksByParent, parentId, activeId, expandedMap, renderers, containerTypes, onHover, onToggleExpand, depth, dropZoneClassName, dropZoneActiveClassName, indentClassName, rootClassName, canDrag, previewPosition, draggedBlock, focusedId, selectedIds, onBlockClick, animation, virtualVisibleIds, }: TreeRendererProps<T>): react_jsx_runtime.JSX.Element;
602
+ declare function TreeRendererInner<T extends BaseBlock>({ blocks, blocksByParent, parentId, activeId, expandedMap, renderers, containerTypes, onHover, onToggleExpand, depth, dropZoneClassName, dropZoneActiveClassName, indentClassName, rootClassName, canDrag, previewPosition, draggedBlock, focusedId, selectedIds, onBlockClick, animation, virtualVisibleIds, }: TreeRendererProps<T>): react_jsx_runtime.JSX.Element;
603
+ declare const TreeRenderer: typeof TreeRendererInner;
531
604
 
532
605
  interface DropZoneProps {
533
606
  id: string;
@@ -672,63 +745,6 @@ interface UseVirtualTreeResult {
672
745
  */
673
746
  declare function useVirtualTree({ containerRef, itemCount, itemHeight, overscan, }: UseVirtualTreeOptions): UseVirtualTreeResult;
674
747
 
675
- /**
676
- * Clone a Map
677
- */
678
- declare function cloneMap<K, V>(map: Map<K, V>): Map<K, V>;
679
- /**
680
- * Clone a parent map with arrays
681
- */
682
- declare function cloneParentMap(map: Map<string | null, string[]>): Map<string | null, string[]>;
683
- /**
684
- * Compute normalized index from flat block array.
685
- *
686
- * With `orderingStrategy: 'fractional'`, siblings are sorted by their `order`
687
- * field (lexicographic). With `'integer'` (default), the input order is preserved.
688
- */
689
- declare function computeNormalizedIndex<T extends BaseBlock>(blocks: T[], orderingStrategy?: OrderingStrategy): BlockIndex<T>;
690
- /**
691
- * Build ordered flat array from BlockIndex.
692
- *
693
- * With `'integer'` ordering (default), assigns sequential `order: 0, 1, 2, …`.
694
- * With `'fractional'` ordering, preserves existing `order` values — the moved
695
- * block already has its new fractional key set by `reparentBlockIndex`.
696
- */
697
- declare function buildOrderedBlocks<T extends BaseBlock>(index: BlockIndex<T>, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy): T[];
698
- /**
699
- * Reparent a block based on drop zone ID.
700
- *
701
- * @param state - Current block index
702
- * @param activeId - ID of the dragged block
703
- * @param targetZone - Drop zone ID (e.g., "after-uuid", "before-uuid", "into-uuid")
704
- * @param containerTypes - Block types that can have children
705
- * @param orderingStrategy - Whether to assign a fractional key to the moved block
706
- */
707
- declare function reparentBlockIndex<T extends BaseBlock>(state: BlockIndex<T>, activeId: UniqueIdentifier, targetZone: string, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy, maxDepth?: number): BlockIndex<T>;
708
- /**
709
- * Compute the depth of a block by walking its parentId chain.
710
- * Root-level blocks have depth 1.
711
- */
712
- declare function getBlockDepth<T extends BaseBlock>(index: BlockIndex<T>, blockId: string): number;
713
- /**
714
- * Compute the maximum depth of a subtree rooted at blockId (inclusive).
715
- * A leaf block returns 1.
716
- */
717
- declare function getSubtreeDepth<T extends BaseBlock>(index: BlockIndex<T>, blockId: string): number;
718
- /**
719
- * Get all descendant IDs of a block
720
- */
721
- declare function getDescendantIds<T extends BaseBlock>(state: BlockIndex<T>, parentId: string): Set<string>;
722
- /**
723
- * Reparent multiple blocks to a target zone, preserving their relative order.
724
- * The first block in `blockIds` is treated as the primary (anchor) block.
725
- */
726
- declare function reparentMultipleBlocks<T extends BaseBlock>(state: BlockIndex<T>, blockIds: string[], targetZone: string, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy, maxDepth?: number): BlockIndex<T>;
727
- /**
728
- * Delete a block and all its descendants
729
- */
730
- declare function deleteBlockAndDescendants<T extends BaseBlock>(state: BlockIndex<T>, id: string): BlockIndex<T>;
731
-
732
748
  /**
733
749
  * Extract UUID from a zone ID by removing the prefix (before-, after-, into-, end-)
734
750
  */
@@ -749,6 +765,42 @@ declare function generateId(): string;
749
765
  */
750
766
  declare function triggerHaptic(durationMs?: number): void;
751
767
 
768
+ interface DevToolsEventEntry {
769
+ id: number;
770
+ timestamp: number;
771
+ type: 'dragStart' | 'dragEnd' | 'blockMove' | 'expandChange' | 'hoverChange';
772
+ summary: string;
773
+ }
774
+ interface DevToolsCallbacks<T extends BaseBlock = BaseBlock> {
775
+ onDragStart: NonNullable<BlockTreeCallbacks<T>['onDragStart']>;
776
+ onDragEnd: NonNullable<BlockTreeCallbacks<T>['onDragEnd']>;
777
+ onBlockMove: NonNullable<BlockTreeCallbacks<T>['onBlockMove']>;
778
+ onExpandChange: NonNullable<BlockTreeCallbacks<T>['onExpandChange']>;
779
+ onHoverChange: NonNullable<BlockTreeCallbacks<T>['onHoverChange']>;
780
+ }
781
+ interface BlockTreeDevToolsProps<T extends BaseBlock = BaseBlock> {
782
+ blocks: T[];
783
+ containerTypes?: readonly string[];
784
+ events: DevToolsEventEntry[];
785
+ onClearEvents: () => void;
786
+ /** Label function for diff view (default: block.type) */
787
+ getLabel?: (block: T) => string;
788
+ /** Initial open state (default: false) */
789
+ initialOpen?: boolean;
790
+ /** Position of the trigger button (default: 'bottom-left') */
791
+ position?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
792
+ /** Custom inline styles for the trigger button */
793
+ buttonStyle?: React.CSSProperties;
794
+ /** Custom inline styles for the card panel */
795
+ panelStyle?: React.CSSProperties;
796
+ }
797
+ declare function useDevToolsCallbacks<T extends BaseBlock = BaseBlock>(): {
798
+ callbacks: DevToolsCallbacks<T>;
799
+ events: DevToolsEventEntry[];
800
+ clearEvents: () => void;
801
+ };
802
+ declare function BlockTreeDevTools<T extends BaseBlock = BaseBlock>({ blocks, containerTypes, events, onClearEvents, getLabel, initialOpen, position, buttonStyle, panelStyle, }: BlockTreeDevToolsProps<T>): react_jsx_runtime.JSX.Element;
803
+
752
804
  /**
753
805
  * A nested/tree representation of a block.
754
806
  * Omits `parentId` and `order` since they are reconstructed during flattening.
@@ -817,4 +869,4 @@ declare function initFractionalOrder<T extends {
817
869
  order: number | string;
818
870
  }>(blocks: T[]): T[];
819
871
 
820
- export { type AnimationConfig, type AutoExpandConfig, type BaseBlock, type BlockAction, type BlockAddEvent, type BlockDeleteEvent, type BlockIndex, type BlockMoveEvent, type BlockPosition, type BlockRendererProps, type BlockRenderers, type BlockStateContextValue, type BlockStateProviderProps, BlockTree, type BlockTreeCallbacks, type BlockTreeConfig, type BlockTreeCustomization, type BlockTreeProps, BlockTreeSSR, type BlockTreeSSRProps, type CanDragFn, type CanDropFn, type ContainerRendererProps, type DragEndEvent, type DragMoveEvent, DragOverlay, type DragOverlayProps$1 as DragOverlayProps, type DragStartEvent, DropZone, type DropZoneConfig, type DropZoneProps, type DropZoneType, type ExpandChangeEvent, type HoverChangeEvent, type IdGeneratorFn, type InternalRenderers, type MoveOperation, type NestedBlock, type OrderingStrategy, type RendererPropsFor, type SensorConfig, type SnapshotRectsRef, TreeRenderer, type TreeRendererProps, type TreeStateContextValue, type TreeStateProviderProps, type UseBlockHistoryOptions, type UseBlockHistoryResult, type UseLayoutAnimationOptions, type UseVirtualTreeOptions, type UseVirtualTreeResult, buildOrderedBlocks, cloneMap, cloneParentMap, closestCenterCollision, compareFractionalKeys, computeNormalizedIndex, createBlockState, createStickyCollision, createTreeState, debounce, deleteBlockAndDescendants, extractBlockId, extractUUID, flatToNested, generateId, generateInitialKeys, generateKeyBetween, generateNKeysBetween, getBlockDepth, getDescendantIds, getDropZoneType, getSensorConfig, getSubtreeDepth, initFractionalOrder, nestedToFlat, reparentBlockIndex, reparentMultipleBlocks, triggerHaptic, useBlockHistory, useConfiguredSensors, useLayoutAnimation, useVirtualTree, weightedVerticalCollision };
872
+ export { type AnimationConfig, type AutoExpandConfig, type BaseBlock, type BlockAction, type BlockAddEvent, type BlockDeleteEvent, type BlockIndex, type BlockMoveEvent, type BlockPosition, type BlockRendererProps, type BlockRenderers, type BlockStateContextValue, type BlockStateProviderProps, BlockTree, type BlockTreeCallbacks, type BlockTreeConfig, type BlockTreeCustomization, BlockTreeDevTools, type BlockTreeDevToolsProps, type BlockTreeProps, BlockTreeSSR, type BlockTreeSSRProps, type CanDragFn, type CanDropFn, type ContainerRendererProps, type DevToolsCallbacks, type DevToolsEventEntry, type DragEndEvent, type DragMoveEvent, DragOverlay, type DragOverlayProps$1 as DragOverlayProps, type DragStartEvent, DropZone, type DropZoneConfig, type DropZoneProps, type DropZoneType, type ExpandChangeEvent, type HoverChangeEvent, type IdGeneratorFn, type InternalRenderers, type MoveOperation, type NestedBlock, type OrderingStrategy, type RendererPropsFor, type SensorConfig, type SnapshotRectsRef, TreeRenderer, type TreeRendererProps, type TreeStateContextValue, type TreeStateProviderProps, type TreeValidationResult, type UseBlockHistoryOptions, type UseBlockHistoryResult, type UseLayoutAnimationOptions, type UseVirtualTreeOptions, type UseVirtualTreeResult, buildOrderedBlocks, cloneMap, cloneParentMap, closestCenterCollision, compareFractionalKeys, computeNormalizedIndex, createBlockState, createStickyCollision, createTreeState, debounce, deleteBlockAndDescendants, extractBlockId, extractUUID, flatToNested, generateId, generateInitialKeys, generateKeyBetween, generateNKeysBetween, getBlockDepth, getDescendantIds, getDropZoneType, getSensorConfig, getSubtreeDepth, initFractionalOrder, nestedToFlat, reparentBlockIndex, reparentMultipleBlocks, triggerHaptic, useBlockHistory, useConfiguredSensors, useDevToolsCallbacks, useLayoutAnimation, useVirtualTree, validateBlockTree, weightedVerticalCollision };
package/dist/index.d.ts CHANGED
@@ -389,6 +389,78 @@ interface TreeStateProviderProps<T extends BaseBlock = BaseBlock> {
389
389
  blockMap: Map<string, T>;
390
390
  }
391
391
 
392
+ /**
393
+ * Clone a Map
394
+ */
395
+ declare function cloneMap<K, V>(map: Map<K, V>): Map<K, V>;
396
+ /**
397
+ * Clone a parent map with arrays
398
+ */
399
+ declare function cloneParentMap(map: Map<string | null, string[]>): Map<string | null, string[]>;
400
+ /**
401
+ * Compute normalized index from flat block array.
402
+ *
403
+ * With `orderingStrategy: 'fractional'`, siblings are sorted by their `order`
404
+ * field (lexicographic). With `'integer'` (default), the input order is preserved.
405
+ */
406
+ declare function computeNormalizedIndex<T extends BaseBlock>(blocks: T[], orderingStrategy?: OrderingStrategy): BlockIndex<T>;
407
+ /**
408
+ * Build ordered flat array from BlockIndex.
409
+ *
410
+ * With `'integer'` ordering (default), assigns sequential `order: 0, 1, 2, …`.
411
+ * With `'fractional'` ordering, preserves existing `order` values — the moved
412
+ * block already has its new fractional key set by `reparentBlockIndex`.
413
+ */
414
+ declare function buildOrderedBlocks<T extends BaseBlock>(index: BlockIndex<T>, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy): T[];
415
+ /**
416
+ * Reparent a block based on drop zone ID.
417
+ *
418
+ * @param state - Current block index
419
+ * @param activeId - ID of the dragged block
420
+ * @param targetZone - Drop zone ID (e.g., "after-uuid", "before-uuid", "into-uuid")
421
+ * @param containerTypes - Block types that can have children
422
+ * @param orderingStrategy - Whether to assign a fractional key to the moved block
423
+ */
424
+ declare function reparentBlockIndex<T extends BaseBlock>(state: BlockIndex<T>, activeId: UniqueIdentifier, targetZone: string, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy, maxDepth?: number): BlockIndex<T>;
425
+ /**
426
+ * Compute the depth of a block by walking its parentId chain.
427
+ * Root-level blocks have depth 1.
428
+ */
429
+ declare function getBlockDepth<T extends BaseBlock>(index: BlockIndex<T>, blockId: string): number;
430
+ /**
431
+ * Compute the maximum depth of a subtree rooted at blockId (inclusive).
432
+ * A leaf block returns 1.
433
+ */
434
+ declare function getSubtreeDepth<T extends BaseBlock>(index: BlockIndex<T>, blockId: string, visited?: Set<string>): number;
435
+ /**
436
+ * Get all descendant IDs of a block
437
+ */
438
+ declare function getDescendantIds<T extends BaseBlock>(state: BlockIndex<T>, parentId: string): Set<string>;
439
+ /**
440
+ * Reparent multiple blocks to a target zone, preserving their relative order.
441
+ * The first block in `blockIds` is treated as the primary (anchor) block.
442
+ */
443
+ declare function reparentMultipleBlocks<T extends BaseBlock>(state: BlockIndex<T>, blockIds: string[], targetZone: string, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy, maxDepth?: number): BlockIndex<T>;
444
+ /**
445
+ * Result of validating a block tree
446
+ */
447
+ interface TreeValidationResult {
448
+ valid: boolean;
449
+ issues: string[];
450
+ }
451
+ /**
452
+ * Validate a block tree index for structural integrity.
453
+ * Checks for cycles, orphans (parentId references non-existent block),
454
+ * and stale refs (byParent lists IDs not present in byId).
455
+ *
456
+ * Opt-in utility — not called automatically.
457
+ */
458
+ declare function validateBlockTree<T extends BaseBlock>(index: BlockIndex<T>): TreeValidationResult;
459
+ /**
460
+ * Delete a block and all its descendants
461
+ */
462
+ declare function deleteBlockAndDescendants<T extends BaseBlock>(state: BlockIndex<T>, id: string): BlockIndex<T>;
463
+
392
464
  type SnapshotRectsRef = {
393
465
  current: Map<UniqueIdentifier, DOMRect> | null;
394
466
  };
@@ -527,7 +599,8 @@ interface TreeRendererProps<T extends BaseBlock> {
527
599
  /**
528
600
  * Recursive tree renderer with smart drop zones
529
601
  */
530
- declare function TreeRenderer<T extends BaseBlock>({ blocks, blocksByParent, parentId, activeId, expandedMap, renderers, containerTypes, onHover, onToggleExpand, depth, dropZoneClassName, dropZoneActiveClassName, indentClassName, rootClassName, canDrag, previewPosition, draggedBlock, focusedId, selectedIds, onBlockClick, animation, virtualVisibleIds, }: TreeRendererProps<T>): react_jsx_runtime.JSX.Element;
602
+ declare function TreeRendererInner<T extends BaseBlock>({ blocks, blocksByParent, parentId, activeId, expandedMap, renderers, containerTypes, onHover, onToggleExpand, depth, dropZoneClassName, dropZoneActiveClassName, indentClassName, rootClassName, canDrag, previewPosition, draggedBlock, focusedId, selectedIds, onBlockClick, animation, virtualVisibleIds, }: TreeRendererProps<T>): react_jsx_runtime.JSX.Element;
603
+ declare const TreeRenderer: typeof TreeRendererInner;
531
604
 
532
605
  interface DropZoneProps {
533
606
  id: string;
@@ -672,63 +745,6 @@ interface UseVirtualTreeResult {
672
745
  */
673
746
  declare function useVirtualTree({ containerRef, itemCount, itemHeight, overscan, }: UseVirtualTreeOptions): UseVirtualTreeResult;
674
747
 
675
- /**
676
- * Clone a Map
677
- */
678
- declare function cloneMap<K, V>(map: Map<K, V>): Map<K, V>;
679
- /**
680
- * Clone a parent map with arrays
681
- */
682
- declare function cloneParentMap(map: Map<string | null, string[]>): Map<string | null, string[]>;
683
- /**
684
- * Compute normalized index from flat block array.
685
- *
686
- * With `orderingStrategy: 'fractional'`, siblings are sorted by their `order`
687
- * field (lexicographic). With `'integer'` (default), the input order is preserved.
688
- */
689
- declare function computeNormalizedIndex<T extends BaseBlock>(blocks: T[], orderingStrategy?: OrderingStrategy): BlockIndex<T>;
690
- /**
691
- * Build ordered flat array from BlockIndex.
692
- *
693
- * With `'integer'` ordering (default), assigns sequential `order: 0, 1, 2, …`.
694
- * With `'fractional'` ordering, preserves existing `order` values — the moved
695
- * block already has its new fractional key set by `reparentBlockIndex`.
696
- */
697
- declare function buildOrderedBlocks<T extends BaseBlock>(index: BlockIndex<T>, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy): T[];
698
- /**
699
- * Reparent a block based on drop zone ID.
700
- *
701
- * @param state - Current block index
702
- * @param activeId - ID of the dragged block
703
- * @param targetZone - Drop zone ID (e.g., "after-uuid", "before-uuid", "into-uuid")
704
- * @param containerTypes - Block types that can have children
705
- * @param orderingStrategy - Whether to assign a fractional key to the moved block
706
- */
707
- declare function reparentBlockIndex<T extends BaseBlock>(state: BlockIndex<T>, activeId: UniqueIdentifier, targetZone: string, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy, maxDepth?: number): BlockIndex<T>;
708
- /**
709
- * Compute the depth of a block by walking its parentId chain.
710
- * Root-level blocks have depth 1.
711
- */
712
- declare function getBlockDepth<T extends BaseBlock>(index: BlockIndex<T>, blockId: string): number;
713
- /**
714
- * Compute the maximum depth of a subtree rooted at blockId (inclusive).
715
- * A leaf block returns 1.
716
- */
717
- declare function getSubtreeDepth<T extends BaseBlock>(index: BlockIndex<T>, blockId: string): number;
718
- /**
719
- * Get all descendant IDs of a block
720
- */
721
- declare function getDescendantIds<T extends BaseBlock>(state: BlockIndex<T>, parentId: string): Set<string>;
722
- /**
723
- * Reparent multiple blocks to a target zone, preserving their relative order.
724
- * The first block in `blockIds` is treated as the primary (anchor) block.
725
- */
726
- declare function reparentMultipleBlocks<T extends BaseBlock>(state: BlockIndex<T>, blockIds: string[], targetZone: string, containerTypes?: readonly string[], orderingStrategy?: OrderingStrategy, maxDepth?: number): BlockIndex<T>;
727
- /**
728
- * Delete a block and all its descendants
729
- */
730
- declare function deleteBlockAndDescendants<T extends BaseBlock>(state: BlockIndex<T>, id: string): BlockIndex<T>;
731
-
732
748
  /**
733
749
  * Extract UUID from a zone ID by removing the prefix (before-, after-, into-, end-)
734
750
  */
@@ -749,6 +765,42 @@ declare function generateId(): string;
749
765
  */
750
766
  declare function triggerHaptic(durationMs?: number): void;
751
767
 
768
+ interface DevToolsEventEntry {
769
+ id: number;
770
+ timestamp: number;
771
+ type: 'dragStart' | 'dragEnd' | 'blockMove' | 'expandChange' | 'hoverChange';
772
+ summary: string;
773
+ }
774
+ interface DevToolsCallbacks<T extends BaseBlock = BaseBlock> {
775
+ onDragStart: NonNullable<BlockTreeCallbacks<T>['onDragStart']>;
776
+ onDragEnd: NonNullable<BlockTreeCallbacks<T>['onDragEnd']>;
777
+ onBlockMove: NonNullable<BlockTreeCallbacks<T>['onBlockMove']>;
778
+ onExpandChange: NonNullable<BlockTreeCallbacks<T>['onExpandChange']>;
779
+ onHoverChange: NonNullable<BlockTreeCallbacks<T>['onHoverChange']>;
780
+ }
781
+ interface BlockTreeDevToolsProps<T extends BaseBlock = BaseBlock> {
782
+ blocks: T[];
783
+ containerTypes?: readonly string[];
784
+ events: DevToolsEventEntry[];
785
+ onClearEvents: () => void;
786
+ /** Label function for diff view (default: block.type) */
787
+ getLabel?: (block: T) => string;
788
+ /** Initial open state (default: false) */
789
+ initialOpen?: boolean;
790
+ /** Position of the trigger button (default: 'bottom-left') */
791
+ position?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
792
+ /** Custom inline styles for the trigger button */
793
+ buttonStyle?: React.CSSProperties;
794
+ /** Custom inline styles for the card panel */
795
+ panelStyle?: React.CSSProperties;
796
+ }
797
+ declare function useDevToolsCallbacks<T extends BaseBlock = BaseBlock>(): {
798
+ callbacks: DevToolsCallbacks<T>;
799
+ events: DevToolsEventEntry[];
800
+ clearEvents: () => void;
801
+ };
802
+ declare function BlockTreeDevTools<T extends BaseBlock = BaseBlock>({ blocks, containerTypes, events, onClearEvents, getLabel, initialOpen, position, buttonStyle, panelStyle, }: BlockTreeDevToolsProps<T>): react_jsx_runtime.JSX.Element;
803
+
752
804
  /**
753
805
  * A nested/tree representation of a block.
754
806
  * Omits `parentId` and `order` since they are reconstructed during flattening.
@@ -817,4 +869,4 @@ declare function initFractionalOrder<T extends {
817
869
  order: number | string;
818
870
  }>(blocks: T[]): T[];
819
871
 
820
- export { type AnimationConfig, type AutoExpandConfig, type BaseBlock, type BlockAction, type BlockAddEvent, type BlockDeleteEvent, type BlockIndex, type BlockMoveEvent, type BlockPosition, type BlockRendererProps, type BlockRenderers, type BlockStateContextValue, type BlockStateProviderProps, BlockTree, type BlockTreeCallbacks, type BlockTreeConfig, type BlockTreeCustomization, type BlockTreeProps, BlockTreeSSR, type BlockTreeSSRProps, type CanDragFn, type CanDropFn, type ContainerRendererProps, type DragEndEvent, type DragMoveEvent, DragOverlay, type DragOverlayProps$1 as DragOverlayProps, type DragStartEvent, DropZone, type DropZoneConfig, type DropZoneProps, type DropZoneType, type ExpandChangeEvent, type HoverChangeEvent, type IdGeneratorFn, type InternalRenderers, type MoveOperation, type NestedBlock, type OrderingStrategy, type RendererPropsFor, type SensorConfig, type SnapshotRectsRef, TreeRenderer, type TreeRendererProps, type TreeStateContextValue, type TreeStateProviderProps, type UseBlockHistoryOptions, type UseBlockHistoryResult, type UseLayoutAnimationOptions, type UseVirtualTreeOptions, type UseVirtualTreeResult, buildOrderedBlocks, cloneMap, cloneParentMap, closestCenterCollision, compareFractionalKeys, computeNormalizedIndex, createBlockState, createStickyCollision, createTreeState, debounce, deleteBlockAndDescendants, extractBlockId, extractUUID, flatToNested, generateId, generateInitialKeys, generateKeyBetween, generateNKeysBetween, getBlockDepth, getDescendantIds, getDropZoneType, getSensorConfig, getSubtreeDepth, initFractionalOrder, nestedToFlat, reparentBlockIndex, reparentMultipleBlocks, triggerHaptic, useBlockHistory, useConfiguredSensors, useLayoutAnimation, useVirtualTree, weightedVerticalCollision };
872
+ export { type AnimationConfig, type AutoExpandConfig, type BaseBlock, type BlockAction, type BlockAddEvent, type BlockDeleteEvent, type BlockIndex, type BlockMoveEvent, type BlockPosition, type BlockRendererProps, type BlockRenderers, type BlockStateContextValue, type BlockStateProviderProps, BlockTree, type BlockTreeCallbacks, type BlockTreeConfig, type BlockTreeCustomization, BlockTreeDevTools, type BlockTreeDevToolsProps, type BlockTreeProps, BlockTreeSSR, type BlockTreeSSRProps, type CanDragFn, type CanDropFn, type ContainerRendererProps, type DevToolsCallbacks, type DevToolsEventEntry, type DragEndEvent, type DragMoveEvent, DragOverlay, type DragOverlayProps$1 as DragOverlayProps, type DragStartEvent, DropZone, type DropZoneConfig, type DropZoneProps, type DropZoneType, type ExpandChangeEvent, type HoverChangeEvent, type IdGeneratorFn, type InternalRenderers, type MoveOperation, type NestedBlock, type OrderingStrategy, type RendererPropsFor, type SensorConfig, type SnapshotRectsRef, TreeRenderer, type TreeRendererProps, type TreeStateContextValue, type TreeStateProviderProps, type TreeValidationResult, type UseBlockHistoryOptions, type UseBlockHistoryResult, type UseLayoutAnimationOptions, type UseVirtualTreeOptions, type UseVirtualTreeResult, buildOrderedBlocks, cloneMap, cloneParentMap, closestCenterCollision, compareFractionalKeys, computeNormalizedIndex, createBlockState, createStickyCollision, createTreeState, debounce, deleteBlockAndDescendants, extractBlockId, extractUUID, flatToNested, generateId, generateInitialKeys, generateKeyBetween, generateNKeysBetween, getBlockDepth, getDescendantIds, getDropZoneType, getSensorConfig, getSubtreeDepth, initFractionalOrder, nestedToFlat, reparentBlockIndex, reparentMultipleBlocks, triggerHaptic, useBlockHistory, useConfiguredSensors, useDevToolsCallbacks, useLayoutAnimation, useVirtualTree, validateBlockTree, weightedVerticalCollision };