dnd-block-tree 0.2.0 → 0.3.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,5 +1,13 @@
1
1
  # dnd-block-tree
2
2
 
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
+ [![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)
10
+
3
11
  A headless React library for building hierarchical drag-and-drop interfaces. Bring your own components, we handle the complexity.
4
12
 
5
13
  ## Features
@@ -7,6 +15,7 @@ A headless React library for building hierarchical drag-and-drop interfaces. Bri
7
15
  - **Stable Drop Zones** - Zones render based on original block positions, not preview state, ensuring consistent drop targets during drag
8
16
  - **Ghost Preview** - Semi-transparent preview shows where blocks will land without affecting zone positions
9
17
  - **Depth-Aware Collision** - Smart algorithm prefers nested zones when cursor is at indented levels, with hysteresis to prevent flickering
18
+ - **Mobile & Touch Support** - Separate touch/pointer activation constraints prevent interference with scrolling on mobile devices
10
19
  - **8px Activation Distance** - Prevents accidental drags. Pointer must move 8px before drag starts, allowing normal clicks
11
20
  - **Snapshot-Based Computation** - State captured at drag start. All preview computations use snapshot, ensuring consistent behavior
12
21
  - **Debounced Preview** - 150ms debounced virtual state for smooth drag previews without jitter
package/dist/index.js CHANGED
@@ -122,23 +122,29 @@ function useConfiguredSensors(config = {}) {
122
122
  activationDelay,
123
123
  tolerance
124
124
  } = config;
125
- let activationConstraint;
125
+ let pointerConstraint;
126
+ let touchConstraint;
126
127
  if (activationDelay !== void 0) {
127
- activationConstraint = {
128
+ pointerConstraint = {
128
129
  delay: activationDelay,
129
130
  tolerance: tolerance ?? 5
130
131
  };
132
+ touchConstraint = pointerConstraint;
131
133
  } else {
132
- activationConstraint = {
134
+ pointerConstraint = {
133
135
  distance: activationDistance
134
136
  };
137
+ touchConstraint = {
138
+ delay: 200,
139
+ tolerance: 5
140
+ };
135
141
  }
136
142
  return core.useSensors(
137
143
  core.useSensor(core.PointerSensor, {
138
- activationConstraint
144
+ activationConstraint: pointerConstraint
139
145
  }),
140
146
  core.useSensor(core.TouchSensor, {
141
- activationConstraint
147
+ activationConstraint: touchConstraint
142
148
  }),
143
149
  core.useSensor(core.KeyboardSensor)
144
150
  );
@@ -232,7 +238,16 @@ function DraggableBlock({
232
238
  id: block.id,
233
239
  disabled
234
240
  });
235
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: setNodeRef, ...attributes, ...listeners, children: children({ isDragging }) });
241
+ return /* @__PURE__ */ jsxRuntime.jsx(
242
+ "div",
243
+ {
244
+ ref: setNodeRef,
245
+ ...attributes,
246
+ ...listeners,
247
+ style: { touchAction: "none", minWidth: 0 },
248
+ children: children({ isDragging })
249
+ }
250
+ );
236
251
  }
237
252
  function TreeRenderer({
238
253
  blocks,
@@ -257,7 +272,7 @@ function TreeRenderer({
257
272
  const filteredBlocks = items.filter((block) => block.id !== activeId);
258
273
  const showGhostHere = previewPosition?.parentId === parentId && draggedBlock;
259
274
  const containerClass = depth === 0 ? rootClassName : indentClassName;
260
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: containerClass, children: [
275
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: containerClass, style: { minWidth: 0 }, children: [
261
276
  /* @__PURE__ */ jsxRuntime.jsx(
262
277
  DropZone,
263
278
  {
@@ -283,7 +298,7 @@ function TreeRenderer({
283
298
  }
284
299
  const GhostRenderer = draggedBlock ? renderers[draggedBlock.type] : null;
285
300
  return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
286
- ghostBeforeThis && GhostRenderer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "opacity-50 pointer-events-none", children: GhostRenderer({
301
+ ghostBeforeThis && GhostRenderer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "opacity-50 pointer-events-none", style: { minWidth: 0 }, children: GhostRenderer({
287
302
  block: draggedBlock,
288
303
  isDragging: true,
289
304
  depth
@@ -342,7 +357,7 @@ function TreeRenderer({
342
357
  }),
343
358
  showGhostHere && previewPosition.index >= filteredBlocks.length && draggedBlock && (() => {
344
359
  const GhostRenderer = renderers[draggedBlock.type];
345
- return GhostRenderer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "opacity-50 pointer-events-none", children: GhostRenderer({
360
+ return GhostRenderer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "opacity-50 pointer-events-none", style: { minWidth: 0 }, children: GhostRenderer({
346
361
  block: draggedBlock,
347
362
  isDragging: true,
348
363
  depth
@@ -782,7 +797,7 @@ function BlockTree({
782
797
  onDragEnd: handleDragEnd,
783
798
  onDragCancel: handleDragCancel,
784
799
  children: [
785
- /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx(
800
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { minWidth: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(
786
801
  TreeRenderer,
787
802
  {
788
803
  blocks,