dnd-block-tree 0.1.2 → 0.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 +7 -2
- package/dist/index.d.mts +198 -34
- package/dist/index.d.ts +198 -34
- package/dist/index.js +412 -118
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +413 -120
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -4,11 +4,13 @@ A headless React library for building hierarchical drag-and-drop interfaces. Bri
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
7
|
+
- **Stable Drop Zones** - Zones render based on original block positions, not preview state, ensuring consistent drop targets during drag
|
|
8
|
+
- **Ghost Preview** - Semi-transparent preview shows where blocks will land without affecting zone positions
|
|
9
|
+
- **Depth-Aware Collision** - Smart algorithm prefers nested zones when cursor is at indented levels, with hysteresis to prevent flickering
|
|
9
10
|
- **8px Activation Distance** - Prevents accidental drags. Pointer must move 8px before drag starts, allowing normal clicks
|
|
10
11
|
- **Snapshot-Based Computation** - State captured at drag start. All preview computations use snapshot, ensuring consistent behavior
|
|
11
12
|
- **Debounced Preview** - 150ms debounced virtual state for smooth drag previews without jitter
|
|
13
|
+
- **Customizable Drag Rules** - `canDrag` and `canDrop` filters for fine-grained control over drag behavior
|
|
12
14
|
|
|
13
15
|
## Installation
|
|
14
16
|
|
|
@@ -64,6 +66,9 @@ function App() {
|
|
|
64
66
|
| `dragOverlay` | `(block: T) => ReactNode` | - | Custom drag overlay renderer |
|
|
65
67
|
| `activationDistance` | `number` | `8` | Pixels to move before drag starts |
|
|
66
68
|
| `previewDebounce` | `number` | `150` | Debounce delay for preview updates |
|
|
69
|
+
| `showDropPreview` | `boolean` | `true` | Show live preview of block at drop position |
|
|
70
|
+
| `canDrag` | `(block: T) => boolean` | - | Filter which blocks can be dragged |
|
|
71
|
+
| `canDrop` | `(block, zone, target) => boolean` | - | Filter valid drop targets |
|
|
67
72
|
| `className` | `string` | - | Root container class |
|
|
68
73
|
| `dropZoneClassName` | `string` | - | Drop zone class |
|
|
69
74
|
| `dropZoneActiveClassName` | `string` | - | Active drop zone class |
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import * as _dnd_kit_core from '@dnd-kit/core';
|
|
4
|
-
import { UniqueIdentifier, CollisionDetection } from '@dnd-kit/core';
|
|
4
|
+
import { UniqueIdentifier, CollisionDetection, PointerActivationConstraint } from '@dnd-kit/core';
|
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -40,11 +40,6 @@ interface ContainerRendererProps<T extends BaseBlock = BaseBlock> extends BlockR
|
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* Get the appropriate props type for a renderer based on whether it's a container type
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* type SectionProps = RendererPropsFor<MyBlock, 'section', typeof CONTAINER_TYPES>
|
|
46
|
-
* // If CONTAINER_TYPES includes 'section', this is ContainerRendererProps
|
|
47
|
-
* // Otherwise, it's BlockRendererProps
|
|
48
43
|
*/
|
|
49
44
|
type RendererPropsFor<T extends BaseBlock, K extends T['type'], C extends readonly string[]> = K extends C[number] ? ContainerRendererProps<T & {
|
|
50
45
|
type: K;
|
|
@@ -53,14 +48,6 @@ type RendererPropsFor<T extends BaseBlock, K extends T['type'], C extends readon
|
|
|
53
48
|
}>;
|
|
54
49
|
/**
|
|
55
50
|
* Map of block types to their renderers with automatic container detection
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* const CONTAINER_TYPES = ['section'] as const
|
|
59
|
-
*
|
|
60
|
-
* const renderers: BlockRenderers<MyBlock, typeof CONTAINER_TYPES> = {
|
|
61
|
-
* section: (props) => <Section {...props} />, // props includes isExpanded, onToggleExpand
|
|
62
|
-
* task: (props) => <Task {...props} />, // props is BlockRendererProps
|
|
63
|
-
* }
|
|
64
51
|
*/
|
|
65
52
|
type BlockRenderers<T extends BaseBlock = BaseBlock, C extends readonly string[] = readonly string[]> = {
|
|
66
53
|
[K in T['type']]: (props: RendererPropsFor<T, K, C>) => ReactNode;
|
|
@@ -71,6 +58,167 @@ type BlockRenderers<T extends BaseBlock = BaseBlock, C extends readonly string[]
|
|
|
71
58
|
type InternalRenderers<T extends BaseBlock = BaseBlock> = {
|
|
72
59
|
[K in T['type']]: (props: BlockRendererProps<T> | ContainerRendererProps<T>) => ReactNode;
|
|
73
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Position info for a block
|
|
63
|
+
*/
|
|
64
|
+
interface BlockPosition {
|
|
65
|
+
parentId: string | null;
|
|
66
|
+
index: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Event fired when drag starts
|
|
70
|
+
*/
|
|
71
|
+
interface DragStartEvent<T extends BaseBlock = BaseBlock> {
|
|
72
|
+
block: T;
|
|
73
|
+
blockId: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Event fired during drag movement
|
|
77
|
+
*/
|
|
78
|
+
interface DragMoveEvent<T extends BaseBlock = BaseBlock> {
|
|
79
|
+
block: T;
|
|
80
|
+
blockId: string;
|
|
81
|
+
/** Current hover zone ID, if any */
|
|
82
|
+
overZone: string | null;
|
|
83
|
+
/** Pointer coordinates */
|
|
84
|
+
coordinates: {
|
|
85
|
+
x: number;
|
|
86
|
+
y: number;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Event fired when drag ends
|
|
91
|
+
*/
|
|
92
|
+
interface DragEndEvent<T extends BaseBlock = BaseBlock> {
|
|
93
|
+
block: T;
|
|
94
|
+
blockId: string;
|
|
95
|
+
/** Target zone where block was dropped */
|
|
96
|
+
targetZone: string | null;
|
|
97
|
+
/** Whether the drag was cancelled */
|
|
98
|
+
cancelled: boolean;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Event fired when a block is moved
|
|
102
|
+
*/
|
|
103
|
+
interface BlockMoveEvent<T extends BaseBlock = BaseBlock> {
|
|
104
|
+
block: T;
|
|
105
|
+
from: BlockPosition;
|
|
106
|
+
to: BlockPosition;
|
|
107
|
+
/** All blocks after the move */
|
|
108
|
+
blocks: T[];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Event fired when expand state changes
|
|
112
|
+
*/
|
|
113
|
+
interface ExpandChangeEvent<T extends BaseBlock = BaseBlock> {
|
|
114
|
+
block: T;
|
|
115
|
+
blockId: string;
|
|
116
|
+
expanded: boolean;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Event fired when hover zone changes
|
|
120
|
+
*/
|
|
121
|
+
interface HoverChangeEvent<T extends BaseBlock = BaseBlock> {
|
|
122
|
+
zoneId: string | null;
|
|
123
|
+
zoneType: DropZoneType | null;
|
|
124
|
+
/** Block being hovered over (if any) */
|
|
125
|
+
targetBlock: T | null;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* All available callback handlers for BlockTree
|
|
129
|
+
*/
|
|
130
|
+
interface BlockTreeCallbacks<T extends BaseBlock = BaseBlock> {
|
|
131
|
+
/** Called when drag starts. Return false to prevent drag. */
|
|
132
|
+
onDragStart?: (event: DragStartEvent<T>) => boolean | void;
|
|
133
|
+
/** Called during drag movement (debounced) */
|
|
134
|
+
onDragMove?: (event: DragMoveEvent<T>) => void;
|
|
135
|
+
/** Called when drag ends (success or cancel) */
|
|
136
|
+
onDragEnd?: (event: DragEndEvent<T>) => void;
|
|
137
|
+
/** Called when drag is cancelled */
|
|
138
|
+
onDragCancel?: (event: DragEndEvent<T>) => void;
|
|
139
|
+
/** Called after a block is moved to a new position */
|
|
140
|
+
onBlockMove?: (event: BlockMoveEvent<T>) => void;
|
|
141
|
+
/** Called when expand/collapse state changes */
|
|
142
|
+
onExpandChange?: (event: ExpandChangeEvent<T>) => void;
|
|
143
|
+
/** Called when hover zone changes during drag */
|
|
144
|
+
onHoverChange?: (event: HoverChangeEvent<T>) => void;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Filter function to determine if a block can be dragged
|
|
148
|
+
*/
|
|
149
|
+
type CanDragFn<T extends BaseBlock = BaseBlock> = (block: T) => boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Filter function to determine if a block can be dropped at a location
|
|
152
|
+
*/
|
|
153
|
+
type CanDropFn<T extends BaseBlock = BaseBlock> = (draggedBlock: T, targetZone: string, targetBlock: T | null) => boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Custom ID generator function
|
|
156
|
+
*/
|
|
157
|
+
type IdGeneratorFn = () => string;
|
|
158
|
+
/**
|
|
159
|
+
* Sensor configuration
|
|
160
|
+
*/
|
|
161
|
+
interface SensorConfig {
|
|
162
|
+
activationDistance?: number;
|
|
163
|
+
activationDelay?: number;
|
|
164
|
+
tolerance?: number;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Drop zone configuration
|
|
168
|
+
*/
|
|
169
|
+
interface DropZoneConfig {
|
|
170
|
+
/** Height of drop zones in pixels */
|
|
171
|
+
height?: number;
|
|
172
|
+
/** Gap between drop zones */
|
|
173
|
+
gap?: number;
|
|
174
|
+
/** Show drop zones inside empty containers */
|
|
175
|
+
showInEmptyContainers?: boolean;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Animation configuration
|
|
179
|
+
*/
|
|
180
|
+
interface AnimationConfig {
|
|
181
|
+
/** Duration for expand/collapse animations in ms */
|
|
182
|
+
expandDuration?: number;
|
|
183
|
+
/** Duration for drag overlay animation in ms */
|
|
184
|
+
dragOverlayDuration?: number;
|
|
185
|
+
/** Easing function (CSS timing function) */
|
|
186
|
+
easing?: string;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Auto-expand configuration for containers during drag
|
|
190
|
+
*/
|
|
191
|
+
interface AutoExpandConfig {
|
|
192
|
+
/** Enable auto-expand on hover */
|
|
193
|
+
enabled?: boolean;
|
|
194
|
+
/** Delay before expanding in ms */
|
|
195
|
+
delay?: number;
|
|
196
|
+
/** Auto-collapse when leaving */
|
|
197
|
+
collapseOnLeave?: boolean;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Full customization options for BlockTree
|
|
201
|
+
*/
|
|
202
|
+
interface BlockTreeCustomization<T extends BaseBlock = BaseBlock> {
|
|
203
|
+
/** Filter which blocks can be dragged */
|
|
204
|
+
canDrag?: CanDragFn<T>;
|
|
205
|
+
/** Filter valid drop targets */
|
|
206
|
+
canDrop?: CanDropFn<T>;
|
|
207
|
+
/** Custom collision detection algorithm */
|
|
208
|
+
collisionDetection?: CollisionDetection;
|
|
209
|
+
/** Sensor configuration */
|
|
210
|
+
sensors?: SensorConfig;
|
|
211
|
+
/** Drop zone configuration */
|
|
212
|
+
dropZones?: DropZoneConfig;
|
|
213
|
+
/** Animation configuration */
|
|
214
|
+
animation?: AnimationConfig;
|
|
215
|
+
/** Auto-expand containers during drag */
|
|
216
|
+
autoExpand?: AutoExpandConfig;
|
|
217
|
+
/** Custom ID generator */
|
|
218
|
+
idGenerator?: IdGeneratorFn;
|
|
219
|
+
/** Initially expanded block IDs */
|
|
220
|
+
initialExpanded?: string[] | 'all' | 'none';
|
|
221
|
+
}
|
|
74
222
|
/**
|
|
75
223
|
* Block action types for the reducer
|
|
76
224
|
*/
|
|
@@ -184,16 +332,33 @@ interface TreeStateProviderProps<T extends BaseBlock = BaseBlock> {
|
|
|
184
332
|
* - Returns single winner (lowest score)
|
|
185
333
|
*/
|
|
186
334
|
declare const weightedVerticalCollision: CollisionDetection;
|
|
335
|
+
/**
|
|
336
|
+
* Create a collision detection with hysteresis to prevent flickering
|
|
337
|
+
* between adjacent drop zones.
|
|
338
|
+
*
|
|
339
|
+
* @param threshold - Minimum score improvement required to switch zones (default: 15px)
|
|
340
|
+
*/
|
|
341
|
+
declare function createStickyCollision(threshold?: number): CollisionDetection & {
|
|
342
|
+
reset: () => void;
|
|
343
|
+
};
|
|
187
344
|
/**
|
|
188
345
|
* Simple closest center collision (fallback)
|
|
189
346
|
*/
|
|
190
347
|
declare const closestCenterCollision: CollisionDetection;
|
|
191
348
|
|
|
192
|
-
|
|
193
|
-
|
|
349
|
+
/**
|
|
350
|
+
* Return type for getSensorConfig
|
|
351
|
+
*/
|
|
352
|
+
interface SensorConfigResult {
|
|
353
|
+
pointer: {
|
|
354
|
+
activationConstraint: PointerActivationConstraint;
|
|
355
|
+
};
|
|
356
|
+
touch: {
|
|
357
|
+
activationConstraint: PointerActivationConstraint;
|
|
358
|
+
};
|
|
194
359
|
}
|
|
195
360
|
/**
|
|
196
|
-
* Create configured sensors with activation
|
|
361
|
+
* Create configured sensors with activation constraints.
|
|
197
362
|
* The activation distance prevents accidental drags while still allowing clicks.
|
|
198
363
|
*
|
|
199
364
|
* @param config - Sensor configuration
|
|
@@ -203,20 +368,9 @@ declare function useConfiguredSensors(config?: SensorConfig): _dnd_kit_core.Sens
|
|
|
203
368
|
/**
|
|
204
369
|
* Get sensor configuration for manual setup
|
|
205
370
|
*/
|
|
206
|
-
declare function getSensorConfig(
|
|
207
|
-
pointer: {
|
|
208
|
-
activationConstraint: {
|
|
209
|
-
distance: number;
|
|
210
|
-
};
|
|
211
|
-
};
|
|
212
|
-
touch: {
|
|
213
|
-
activationConstraint: {
|
|
214
|
-
distance: number;
|
|
215
|
-
};
|
|
216
|
-
};
|
|
217
|
-
};
|
|
371
|
+
declare function getSensorConfig(config?: SensorConfig): SensorConfigResult;
|
|
218
372
|
|
|
219
|
-
interface BlockTreeProps<T extends BaseBlock, C extends readonly T['type'][] = readonly T['type'][]> {
|
|
373
|
+
interface BlockTreeProps<T extends BaseBlock, C extends readonly T['type'][] = readonly T['type'][]> extends BlockTreeCallbacks<T>, BlockTreeCustomization<T> {
|
|
220
374
|
/** Current blocks array */
|
|
221
375
|
blocks: T[];
|
|
222
376
|
/** Block renderers for each type */
|
|
@@ -239,12 +393,14 @@ interface BlockTreeProps<T extends BaseBlock, C extends readonly T['type'][] = r
|
|
|
239
393
|
dropZoneActiveClassName?: string;
|
|
240
394
|
/** Indent className for nested items */
|
|
241
395
|
indentClassName?: string;
|
|
396
|
+
/** Show live preview of drop position during drag (default: true) */
|
|
397
|
+
showDropPreview?: boolean;
|
|
242
398
|
}
|
|
243
399
|
/**
|
|
244
400
|
* Main BlockTree component
|
|
245
401
|
* Provides drag-and-drop functionality for hierarchical block structures
|
|
246
402
|
*/
|
|
247
|
-
declare function BlockTree<T extends BaseBlock, C extends readonly T['type'][] = readonly T['type'][]>({ blocks, renderers, containerTypes, onChange, dragOverlay, activationDistance, previewDebounce, className, dropZoneClassName, dropZoneActiveClassName, indentClassName, }: BlockTreeProps<T, C>): react_jsx_runtime.JSX.Element;
|
|
403
|
+
declare function BlockTree<T extends BaseBlock, C extends readonly T['type'][] = readonly T['type'][]>({ blocks, renderers, containerTypes, onChange, dragOverlay, activationDistance, previewDebounce, className, dropZoneClassName, dropZoneActiveClassName, indentClassName, showDropPreview, onDragStart, onDragMove, onDragEnd, onDragCancel, onBlockMove, onExpandChange, onHoverChange, canDrag, canDrop, collisionDetection, sensors: sensorConfig, initialExpanded, }: BlockTreeProps<T, C>): react_jsx_runtime.JSX.Element;
|
|
248
404
|
|
|
249
405
|
interface TreeRendererProps<T extends BaseBlock> {
|
|
250
406
|
blocks: T[];
|
|
@@ -261,11 +417,19 @@ interface TreeRendererProps<T extends BaseBlock> {
|
|
|
261
417
|
dropZoneActiveClassName?: string;
|
|
262
418
|
indentClassName?: string;
|
|
263
419
|
rootClassName?: string;
|
|
420
|
+
canDrag?: CanDragFn<T>;
|
|
421
|
+
/** Preview position info - where to show the ghost */
|
|
422
|
+
previewPosition?: {
|
|
423
|
+
parentId: string | null;
|
|
424
|
+
index: number;
|
|
425
|
+
} | null;
|
|
426
|
+
/** The dragged block for rendering preview ghost */
|
|
427
|
+
draggedBlock?: T | null;
|
|
264
428
|
}
|
|
265
429
|
/**
|
|
266
430
|
* Recursive tree renderer with smart drop zones
|
|
267
431
|
*/
|
|
268
|
-
declare function TreeRenderer<T extends BaseBlock>({ blocks, blocksByParent, parentId, activeId, expandedMap, renderers, containerTypes, onHover, onToggleExpand, depth, dropZoneClassName, dropZoneActiveClassName, indentClassName, rootClassName, }: TreeRendererProps<T>): react_jsx_runtime.JSX.Element;
|
|
432
|
+
declare function TreeRenderer<T extends BaseBlock>({ blocks, blocksByParent, parentId, activeId, expandedMap, renderers, containerTypes, onHover, onToggleExpand, depth, dropZoneClassName, dropZoneActiveClassName, indentClassName, rootClassName, canDrag, previewPosition, draggedBlock, }: TreeRendererProps<T>): react_jsx_runtime.JSX.Element;
|
|
269
433
|
|
|
270
434
|
interface DropZoneProps {
|
|
271
435
|
id: string;
|
|
@@ -349,7 +513,7 @@ declare function getDescendantIds<T extends BaseBlock>(state: BlockIndex<T>, par
|
|
|
349
513
|
declare function deleteBlockAndDescendants<T extends BaseBlock>(state: BlockIndex<T>, id: string): BlockIndex<T>;
|
|
350
514
|
|
|
351
515
|
/**
|
|
352
|
-
* Extract UUID from a zone ID by removing the prefix (before-, after-, into-)
|
|
516
|
+
* Extract UUID from a zone ID by removing the prefix (before-, after-, into-, end-)
|
|
353
517
|
*/
|
|
354
518
|
declare function extractUUID(id: string, pattern?: string): string;
|
|
355
519
|
/**
|
|
@@ -363,4 +527,4 @@ declare function debounce<Args extends unknown[]>(fn: (...args: Args) => void, d
|
|
|
363
527
|
*/
|
|
364
528
|
declare function generateId(): string;
|
|
365
529
|
|
|
366
|
-
export { type BaseBlock, type BlockAction, type BlockIndex, type BlockRendererProps, type BlockRenderers, type BlockStateContextValue, type BlockStateProviderProps, BlockTree, type BlockTreeConfig, type BlockTreeProps, type ContainerRendererProps, DragOverlay, type DragOverlayProps$1 as DragOverlayProps, DropZone, type DropZoneProps, type DropZoneType, type RendererPropsFor, TreeRenderer, type TreeRendererProps, type TreeStateContextValue, type TreeStateProviderProps, buildOrderedBlocks, cloneMap, cloneParentMap, closestCenterCollision, computeNormalizedIndex, createBlockState, createTreeState, debounce, deleteBlockAndDescendants, extractBlockId, extractUUID, generateId, getDescendantIds, getDropZoneType, getSensorConfig, reparentBlockIndex, useConfiguredSensors, weightedVerticalCollision };
|
|
530
|
+
export { type AnimationConfig, type AutoExpandConfig, type BaseBlock, type BlockAction, type BlockIndex, type BlockMoveEvent, type BlockPosition, type BlockRendererProps, type BlockRenderers, type BlockStateContextValue, type BlockStateProviderProps, BlockTree, type BlockTreeCallbacks, type BlockTreeConfig, type BlockTreeCustomization, type BlockTreeProps, 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 RendererPropsFor, type SensorConfig, TreeRenderer, type TreeRendererProps, type TreeStateContextValue, type TreeStateProviderProps, buildOrderedBlocks, cloneMap, cloneParentMap, closestCenterCollision, computeNormalizedIndex, createBlockState, createStickyCollision, createTreeState, debounce, deleteBlockAndDescendants, extractBlockId, extractUUID, generateId, getDescendantIds, getDropZoneType, getSensorConfig, reparentBlockIndex, useConfiguredSensors, weightedVerticalCollision };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import * as _dnd_kit_core from '@dnd-kit/core';
|
|
4
|
-
import { UniqueIdentifier, CollisionDetection } from '@dnd-kit/core';
|
|
4
|
+
import { UniqueIdentifier, CollisionDetection, PointerActivationConstraint } from '@dnd-kit/core';
|
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -40,11 +40,6 @@ interface ContainerRendererProps<T extends BaseBlock = BaseBlock> extends BlockR
|
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* Get the appropriate props type for a renderer based on whether it's a container type
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* type SectionProps = RendererPropsFor<MyBlock, 'section', typeof CONTAINER_TYPES>
|
|
46
|
-
* // If CONTAINER_TYPES includes 'section', this is ContainerRendererProps
|
|
47
|
-
* // Otherwise, it's BlockRendererProps
|
|
48
43
|
*/
|
|
49
44
|
type RendererPropsFor<T extends BaseBlock, K extends T['type'], C extends readonly string[]> = K extends C[number] ? ContainerRendererProps<T & {
|
|
50
45
|
type: K;
|
|
@@ -53,14 +48,6 @@ type RendererPropsFor<T extends BaseBlock, K extends T['type'], C extends readon
|
|
|
53
48
|
}>;
|
|
54
49
|
/**
|
|
55
50
|
* Map of block types to their renderers with automatic container detection
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* const CONTAINER_TYPES = ['section'] as const
|
|
59
|
-
*
|
|
60
|
-
* const renderers: BlockRenderers<MyBlock, typeof CONTAINER_TYPES> = {
|
|
61
|
-
* section: (props) => <Section {...props} />, // props includes isExpanded, onToggleExpand
|
|
62
|
-
* task: (props) => <Task {...props} />, // props is BlockRendererProps
|
|
63
|
-
* }
|
|
64
51
|
*/
|
|
65
52
|
type BlockRenderers<T extends BaseBlock = BaseBlock, C extends readonly string[] = readonly string[]> = {
|
|
66
53
|
[K in T['type']]: (props: RendererPropsFor<T, K, C>) => ReactNode;
|
|
@@ -71,6 +58,167 @@ type BlockRenderers<T extends BaseBlock = BaseBlock, C extends readonly string[]
|
|
|
71
58
|
type InternalRenderers<T extends BaseBlock = BaseBlock> = {
|
|
72
59
|
[K in T['type']]: (props: BlockRendererProps<T> | ContainerRendererProps<T>) => ReactNode;
|
|
73
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Position info for a block
|
|
63
|
+
*/
|
|
64
|
+
interface BlockPosition {
|
|
65
|
+
parentId: string | null;
|
|
66
|
+
index: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Event fired when drag starts
|
|
70
|
+
*/
|
|
71
|
+
interface DragStartEvent<T extends BaseBlock = BaseBlock> {
|
|
72
|
+
block: T;
|
|
73
|
+
blockId: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Event fired during drag movement
|
|
77
|
+
*/
|
|
78
|
+
interface DragMoveEvent<T extends BaseBlock = BaseBlock> {
|
|
79
|
+
block: T;
|
|
80
|
+
blockId: string;
|
|
81
|
+
/** Current hover zone ID, if any */
|
|
82
|
+
overZone: string | null;
|
|
83
|
+
/** Pointer coordinates */
|
|
84
|
+
coordinates: {
|
|
85
|
+
x: number;
|
|
86
|
+
y: number;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Event fired when drag ends
|
|
91
|
+
*/
|
|
92
|
+
interface DragEndEvent<T extends BaseBlock = BaseBlock> {
|
|
93
|
+
block: T;
|
|
94
|
+
blockId: string;
|
|
95
|
+
/** Target zone where block was dropped */
|
|
96
|
+
targetZone: string | null;
|
|
97
|
+
/** Whether the drag was cancelled */
|
|
98
|
+
cancelled: boolean;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Event fired when a block is moved
|
|
102
|
+
*/
|
|
103
|
+
interface BlockMoveEvent<T extends BaseBlock = BaseBlock> {
|
|
104
|
+
block: T;
|
|
105
|
+
from: BlockPosition;
|
|
106
|
+
to: BlockPosition;
|
|
107
|
+
/** All blocks after the move */
|
|
108
|
+
blocks: T[];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Event fired when expand state changes
|
|
112
|
+
*/
|
|
113
|
+
interface ExpandChangeEvent<T extends BaseBlock = BaseBlock> {
|
|
114
|
+
block: T;
|
|
115
|
+
blockId: string;
|
|
116
|
+
expanded: boolean;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Event fired when hover zone changes
|
|
120
|
+
*/
|
|
121
|
+
interface HoverChangeEvent<T extends BaseBlock = BaseBlock> {
|
|
122
|
+
zoneId: string | null;
|
|
123
|
+
zoneType: DropZoneType | null;
|
|
124
|
+
/** Block being hovered over (if any) */
|
|
125
|
+
targetBlock: T | null;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* All available callback handlers for BlockTree
|
|
129
|
+
*/
|
|
130
|
+
interface BlockTreeCallbacks<T extends BaseBlock = BaseBlock> {
|
|
131
|
+
/** Called when drag starts. Return false to prevent drag. */
|
|
132
|
+
onDragStart?: (event: DragStartEvent<T>) => boolean | void;
|
|
133
|
+
/** Called during drag movement (debounced) */
|
|
134
|
+
onDragMove?: (event: DragMoveEvent<T>) => void;
|
|
135
|
+
/** Called when drag ends (success or cancel) */
|
|
136
|
+
onDragEnd?: (event: DragEndEvent<T>) => void;
|
|
137
|
+
/** Called when drag is cancelled */
|
|
138
|
+
onDragCancel?: (event: DragEndEvent<T>) => void;
|
|
139
|
+
/** Called after a block is moved to a new position */
|
|
140
|
+
onBlockMove?: (event: BlockMoveEvent<T>) => void;
|
|
141
|
+
/** Called when expand/collapse state changes */
|
|
142
|
+
onExpandChange?: (event: ExpandChangeEvent<T>) => void;
|
|
143
|
+
/** Called when hover zone changes during drag */
|
|
144
|
+
onHoverChange?: (event: HoverChangeEvent<T>) => void;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Filter function to determine if a block can be dragged
|
|
148
|
+
*/
|
|
149
|
+
type CanDragFn<T extends BaseBlock = BaseBlock> = (block: T) => boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Filter function to determine if a block can be dropped at a location
|
|
152
|
+
*/
|
|
153
|
+
type CanDropFn<T extends BaseBlock = BaseBlock> = (draggedBlock: T, targetZone: string, targetBlock: T | null) => boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Custom ID generator function
|
|
156
|
+
*/
|
|
157
|
+
type IdGeneratorFn = () => string;
|
|
158
|
+
/**
|
|
159
|
+
* Sensor configuration
|
|
160
|
+
*/
|
|
161
|
+
interface SensorConfig {
|
|
162
|
+
activationDistance?: number;
|
|
163
|
+
activationDelay?: number;
|
|
164
|
+
tolerance?: number;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Drop zone configuration
|
|
168
|
+
*/
|
|
169
|
+
interface DropZoneConfig {
|
|
170
|
+
/** Height of drop zones in pixels */
|
|
171
|
+
height?: number;
|
|
172
|
+
/** Gap between drop zones */
|
|
173
|
+
gap?: number;
|
|
174
|
+
/** Show drop zones inside empty containers */
|
|
175
|
+
showInEmptyContainers?: boolean;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Animation configuration
|
|
179
|
+
*/
|
|
180
|
+
interface AnimationConfig {
|
|
181
|
+
/** Duration for expand/collapse animations in ms */
|
|
182
|
+
expandDuration?: number;
|
|
183
|
+
/** Duration for drag overlay animation in ms */
|
|
184
|
+
dragOverlayDuration?: number;
|
|
185
|
+
/** Easing function (CSS timing function) */
|
|
186
|
+
easing?: string;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Auto-expand configuration for containers during drag
|
|
190
|
+
*/
|
|
191
|
+
interface AutoExpandConfig {
|
|
192
|
+
/** Enable auto-expand on hover */
|
|
193
|
+
enabled?: boolean;
|
|
194
|
+
/** Delay before expanding in ms */
|
|
195
|
+
delay?: number;
|
|
196
|
+
/** Auto-collapse when leaving */
|
|
197
|
+
collapseOnLeave?: boolean;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Full customization options for BlockTree
|
|
201
|
+
*/
|
|
202
|
+
interface BlockTreeCustomization<T extends BaseBlock = BaseBlock> {
|
|
203
|
+
/** Filter which blocks can be dragged */
|
|
204
|
+
canDrag?: CanDragFn<T>;
|
|
205
|
+
/** Filter valid drop targets */
|
|
206
|
+
canDrop?: CanDropFn<T>;
|
|
207
|
+
/** Custom collision detection algorithm */
|
|
208
|
+
collisionDetection?: CollisionDetection;
|
|
209
|
+
/** Sensor configuration */
|
|
210
|
+
sensors?: SensorConfig;
|
|
211
|
+
/** Drop zone configuration */
|
|
212
|
+
dropZones?: DropZoneConfig;
|
|
213
|
+
/** Animation configuration */
|
|
214
|
+
animation?: AnimationConfig;
|
|
215
|
+
/** Auto-expand containers during drag */
|
|
216
|
+
autoExpand?: AutoExpandConfig;
|
|
217
|
+
/** Custom ID generator */
|
|
218
|
+
idGenerator?: IdGeneratorFn;
|
|
219
|
+
/** Initially expanded block IDs */
|
|
220
|
+
initialExpanded?: string[] | 'all' | 'none';
|
|
221
|
+
}
|
|
74
222
|
/**
|
|
75
223
|
* Block action types for the reducer
|
|
76
224
|
*/
|
|
@@ -184,16 +332,33 @@ interface TreeStateProviderProps<T extends BaseBlock = BaseBlock> {
|
|
|
184
332
|
* - Returns single winner (lowest score)
|
|
185
333
|
*/
|
|
186
334
|
declare const weightedVerticalCollision: CollisionDetection;
|
|
335
|
+
/**
|
|
336
|
+
* Create a collision detection with hysteresis to prevent flickering
|
|
337
|
+
* between adjacent drop zones.
|
|
338
|
+
*
|
|
339
|
+
* @param threshold - Minimum score improvement required to switch zones (default: 15px)
|
|
340
|
+
*/
|
|
341
|
+
declare function createStickyCollision(threshold?: number): CollisionDetection & {
|
|
342
|
+
reset: () => void;
|
|
343
|
+
};
|
|
187
344
|
/**
|
|
188
345
|
* Simple closest center collision (fallback)
|
|
189
346
|
*/
|
|
190
347
|
declare const closestCenterCollision: CollisionDetection;
|
|
191
348
|
|
|
192
|
-
|
|
193
|
-
|
|
349
|
+
/**
|
|
350
|
+
* Return type for getSensorConfig
|
|
351
|
+
*/
|
|
352
|
+
interface SensorConfigResult {
|
|
353
|
+
pointer: {
|
|
354
|
+
activationConstraint: PointerActivationConstraint;
|
|
355
|
+
};
|
|
356
|
+
touch: {
|
|
357
|
+
activationConstraint: PointerActivationConstraint;
|
|
358
|
+
};
|
|
194
359
|
}
|
|
195
360
|
/**
|
|
196
|
-
* Create configured sensors with activation
|
|
361
|
+
* Create configured sensors with activation constraints.
|
|
197
362
|
* The activation distance prevents accidental drags while still allowing clicks.
|
|
198
363
|
*
|
|
199
364
|
* @param config - Sensor configuration
|
|
@@ -203,20 +368,9 @@ declare function useConfiguredSensors(config?: SensorConfig): _dnd_kit_core.Sens
|
|
|
203
368
|
/**
|
|
204
369
|
* Get sensor configuration for manual setup
|
|
205
370
|
*/
|
|
206
|
-
declare function getSensorConfig(
|
|
207
|
-
pointer: {
|
|
208
|
-
activationConstraint: {
|
|
209
|
-
distance: number;
|
|
210
|
-
};
|
|
211
|
-
};
|
|
212
|
-
touch: {
|
|
213
|
-
activationConstraint: {
|
|
214
|
-
distance: number;
|
|
215
|
-
};
|
|
216
|
-
};
|
|
217
|
-
};
|
|
371
|
+
declare function getSensorConfig(config?: SensorConfig): SensorConfigResult;
|
|
218
372
|
|
|
219
|
-
interface BlockTreeProps<T extends BaseBlock, C extends readonly T['type'][] = readonly T['type'][]> {
|
|
373
|
+
interface BlockTreeProps<T extends BaseBlock, C extends readonly T['type'][] = readonly T['type'][]> extends BlockTreeCallbacks<T>, BlockTreeCustomization<T> {
|
|
220
374
|
/** Current blocks array */
|
|
221
375
|
blocks: T[];
|
|
222
376
|
/** Block renderers for each type */
|
|
@@ -239,12 +393,14 @@ interface BlockTreeProps<T extends BaseBlock, C extends readonly T['type'][] = r
|
|
|
239
393
|
dropZoneActiveClassName?: string;
|
|
240
394
|
/** Indent className for nested items */
|
|
241
395
|
indentClassName?: string;
|
|
396
|
+
/** Show live preview of drop position during drag (default: true) */
|
|
397
|
+
showDropPreview?: boolean;
|
|
242
398
|
}
|
|
243
399
|
/**
|
|
244
400
|
* Main BlockTree component
|
|
245
401
|
* Provides drag-and-drop functionality for hierarchical block structures
|
|
246
402
|
*/
|
|
247
|
-
declare function BlockTree<T extends BaseBlock, C extends readonly T['type'][] = readonly T['type'][]>({ blocks, renderers, containerTypes, onChange, dragOverlay, activationDistance, previewDebounce, className, dropZoneClassName, dropZoneActiveClassName, indentClassName, }: BlockTreeProps<T, C>): react_jsx_runtime.JSX.Element;
|
|
403
|
+
declare function BlockTree<T extends BaseBlock, C extends readonly T['type'][] = readonly T['type'][]>({ blocks, renderers, containerTypes, onChange, dragOverlay, activationDistance, previewDebounce, className, dropZoneClassName, dropZoneActiveClassName, indentClassName, showDropPreview, onDragStart, onDragMove, onDragEnd, onDragCancel, onBlockMove, onExpandChange, onHoverChange, canDrag, canDrop, collisionDetection, sensors: sensorConfig, initialExpanded, }: BlockTreeProps<T, C>): react_jsx_runtime.JSX.Element;
|
|
248
404
|
|
|
249
405
|
interface TreeRendererProps<T extends BaseBlock> {
|
|
250
406
|
blocks: T[];
|
|
@@ -261,11 +417,19 @@ interface TreeRendererProps<T extends BaseBlock> {
|
|
|
261
417
|
dropZoneActiveClassName?: string;
|
|
262
418
|
indentClassName?: string;
|
|
263
419
|
rootClassName?: string;
|
|
420
|
+
canDrag?: CanDragFn<T>;
|
|
421
|
+
/** Preview position info - where to show the ghost */
|
|
422
|
+
previewPosition?: {
|
|
423
|
+
parentId: string | null;
|
|
424
|
+
index: number;
|
|
425
|
+
} | null;
|
|
426
|
+
/** The dragged block for rendering preview ghost */
|
|
427
|
+
draggedBlock?: T | null;
|
|
264
428
|
}
|
|
265
429
|
/**
|
|
266
430
|
* Recursive tree renderer with smart drop zones
|
|
267
431
|
*/
|
|
268
|
-
declare function TreeRenderer<T extends BaseBlock>({ blocks, blocksByParent, parentId, activeId, expandedMap, renderers, containerTypes, onHover, onToggleExpand, depth, dropZoneClassName, dropZoneActiveClassName, indentClassName, rootClassName, }: TreeRendererProps<T>): react_jsx_runtime.JSX.Element;
|
|
432
|
+
declare function TreeRenderer<T extends BaseBlock>({ blocks, blocksByParent, parentId, activeId, expandedMap, renderers, containerTypes, onHover, onToggleExpand, depth, dropZoneClassName, dropZoneActiveClassName, indentClassName, rootClassName, canDrag, previewPosition, draggedBlock, }: TreeRendererProps<T>): react_jsx_runtime.JSX.Element;
|
|
269
433
|
|
|
270
434
|
interface DropZoneProps {
|
|
271
435
|
id: string;
|
|
@@ -349,7 +513,7 @@ declare function getDescendantIds<T extends BaseBlock>(state: BlockIndex<T>, par
|
|
|
349
513
|
declare function deleteBlockAndDescendants<T extends BaseBlock>(state: BlockIndex<T>, id: string): BlockIndex<T>;
|
|
350
514
|
|
|
351
515
|
/**
|
|
352
|
-
* Extract UUID from a zone ID by removing the prefix (before-, after-, into-)
|
|
516
|
+
* Extract UUID from a zone ID by removing the prefix (before-, after-, into-, end-)
|
|
353
517
|
*/
|
|
354
518
|
declare function extractUUID(id: string, pattern?: string): string;
|
|
355
519
|
/**
|
|
@@ -363,4 +527,4 @@ declare function debounce<Args extends unknown[]>(fn: (...args: Args) => void, d
|
|
|
363
527
|
*/
|
|
364
528
|
declare function generateId(): string;
|
|
365
529
|
|
|
366
|
-
export { type BaseBlock, type BlockAction, type BlockIndex, type BlockRendererProps, type BlockRenderers, type BlockStateContextValue, type BlockStateProviderProps, BlockTree, type BlockTreeConfig, type BlockTreeProps, type ContainerRendererProps, DragOverlay, type DragOverlayProps$1 as DragOverlayProps, DropZone, type DropZoneProps, type DropZoneType, type RendererPropsFor, TreeRenderer, type TreeRendererProps, type TreeStateContextValue, type TreeStateProviderProps, buildOrderedBlocks, cloneMap, cloneParentMap, closestCenterCollision, computeNormalizedIndex, createBlockState, createTreeState, debounce, deleteBlockAndDescendants, extractBlockId, extractUUID, generateId, getDescendantIds, getDropZoneType, getSensorConfig, reparentBlockIndex, useConfiguredSensors, weightedVerticalCollision };
|
|
530
|
+
export { type AnimationConfig, type AutoExpandConfig, type BaseBlock, type BlockAction, type BlockIndex, type BlockMoveEvent, type BlockPosition, type BlockRendererProps, type BlockRenderers, type BlockStateContextValue, type BlockStateProviderProps, BlockTree, type BlockTreeCallbacks, type BlockTreeConfig, type BlockTreeCustomization, type BlockTreeProps, 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 RendererPropsFor, type SensorConfig, TreeRenderer, type TreeRendererProps, type TreeStateContextValue, type TreeStateProviderProps, buildOrderedBlocks, cloneMap, cloneParentMap, closestCenterCollision, computeNormalizedIndex, createBlockState, createStickyCollision, createTreeState, debounce, deleteBlockAndDescendants, extractBlockId, extractUUID, generateId, getDescendantIds, getDropZoneType, getSensorConfig, reparentBlockIndex, useConfiguredSensors, weightedVerticalCollision };
|