{"_id":"@elham-en/drag-n-drop-engine","_rev":"5-5eed183a785fcc76e13606dcafe247ab","name":"@elham-en/drag-n-drop-engine","dist-tags":{"latest":"1.0.4"},"versions":{"1.0.0":{"name":"@elham-en/drag-n-drop-engine","version":"1.0.0","keywords":["react-native","drag-and-drop","reanimated","gesture-handler","reorder","new-architecture"],"author":{"name":"Elham Najeebullah"},"license":"MIT","_id":"@elham-en/drag-n-drop-engine@1.0.0","maintainers":[{"name":"elham-en","email":"ilhamrezaie@gmail.com"}],"homepage":"https://github.com/Elham-EN/drag-n-drop-engine#readme","bugs":{"url":"https://github.com/Elham-EN/drag-n-drop-engine/issues"},"dist":{"shasum":"6bc7d54a658ebb2d6f09c49cdd733888105fbb34","tarball":"https://registry.npmjs.org/@elham-en/drag-n-drop-engine/-/drag-n-drop-engine-1.0.0.tgz","fileCount":70,"integrity":"sha512-wFWm26mpe7QAH6RodgQMyenOsp9UpptGtm/w54nWQ79HhygMkvU4Tt1btRM9Ka/gIwFPD8Ed44WlIzvzIpj3BQ==","signatures":[{"sig":"MEQCIFD2cs7oMYXGv2wbb+jwVLJ5+b8MJA4J1H8SmMj1ffSnAiBxsAWoyCkACl8J2zXsjgFU7veEsHlnMY6cn9cHTqgB/w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":216712},"main":"./lib/commonjs/index.js","types":"./lib/typescript/commonjs/src/index.d.ts","module":"./lib/module/index.js","exports":{".":{"import":{"types":"./lib/typescript/module/src/index.d.ts","default":"./lib/module/index.js"},"source":"./src/index.ts","require":{"types":"./lib/typescript/commonjs/src/index.d.ts","default":"./lib/commonjs/index.js"}},"./package.json":"./package.json"},"gitHead":"fd35937400a65352c03eb5726597f4d3667ae665","scripts":{"lint":"eslint \"src/**/*.{ts,tsx}\"","build":"bob build","prepare":"bob build","typecheck":"tsc --noEmit"},"_npmUser":{"name":"elham-en","email":"ilhamrezaie@gmail.com"},"repository":{"url":"git+https://github.com/Elham-EN/drag-n-drop-engine.git","type":"git"},"_npmVersion":"11.6.2","description":"React Native drag-and-drop engine for reordering and moving items across lists. Built on Reanimated 4, Gesture Handler, and react-native-worklets.","directories":{},"_nodeVersion":"22.17.0","react-native":"./src/index.ts","_hasShrinkwrap":false,"devDependencies":{"react":"19.1.0","eslint":"^9.25.0","typescript":"~5.9.2","@types/react":"~19.1.0","react-native":"0.81.5","eslint-config-expo":"~10.0.0","react-native-builder-bob":"^0.40.0"},"peerDependencies":{"react":">=19.0.0","expo-haptics":">=15.0.0","react-native":">=0.76.0","react-native-worklets":">=0.4.0","react-native-reanimated":">=4.0.0","react-native-gesture-handler":">=2.20.0"},"_npmOperationalInternal":{"tmp":"tmp/drag-n-drop-engine_1.0.0_1772625938790_0.8123158768248173","host":"s3://npm-registry-packages-npm-production"},"react-native-builder-bob":{"output":"lib","source":"src","targets":[["commonjs",{"esm":true}],["module",{"esm":true}],["typescript",{"project":"tsconfig.build.json"}]]}},"1.0.1":{"name":"@elham-en/drag-n-drop-engine","version":"1.0.1","keywords":["react-native","drag-and-drop","reanimated","gesture-handler","reorder","new-architecture"],"author":{"name":"Elham Najeebullah"},"license":"MIT","_id":"@elham-en/drag-n-drop-engine@1.0.1","maintainers":[{"name":"elham-en","email":"ilhamrezaie@gmail.com"}],"homepage":"https://github.com/Elham-EN/drag-n-drop-engine#readme","bugs":{"url":"https://github.com/Elham-EN/drag-n-drop-engine/issues"},"dist":{"shasum":"2a03c28c68befc0d398c0b977f60b2f6d31ae9f4","tarball":"https://registry.npmjs.org/@elham-en/drag-n-drop-engine/-/drag-n-drop-engine-1.0.1.tgz","fileCount":70,"integrity":"sha512-BRBZX7IJWyFQHyVEURUZyaO7y7mitHU1EZO7ZPTBBnwQUcE3CTrAiRcL/vZryZdG8L/IKha2cmVoWPjurO8j/Q==","signatures":[{"sig":"MEUCIQCg6TbJy3bXWmZa/Gx98kas49iahedBqwuLjMnJfMcafAIgN800WrGiHmRyN9s2HkUhWpyrCxqPBQc6uq3w3loiDz8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":221368},"main":"./lib/commonjs/index.js","types":"./lib/typescript/commonjs/src/index.d.ts","module":"./lib/module/index.js","exports":{".":{"import":{"types":"./lib/typescript/module/src/index.d.ts","default":"./lib/module/index.js"},"source":"./src/index.ts","require":{"types":"./lib/typescript/commonjs/src/index.d.ts","default":"./lib/commonjs/index.js"}},"./package.json":"./package.json"},"gitHead":"fd35937400a65352c03eb5726597f4d3667ae665","scripts":{"lint":"eslint \"src/**/*.{ts,tsx}\"","build":"bob build","prepare":"bob build","typecheck":"tsc --noEmit"},"_npmUser":{"name":"elham-en","email":"ilhamrezaie@gmail.com"},"repository":{"url":"git+https://github.com/Elham-EN/drag-n-drop-engine.git","type":"git"},"_npmVersion":"11.6.2","description":"React Native drag-and-drop engine for reordering and moving items across lists. Built on Reanimated 4, Gesture Handler, and react-native-worklets.","directories":{},"_nodeVersion":"22.17.0","react-native":"./src/index.ts","_hasShrinkwrap":false,"devDependencies":{"react":"19.1.0","eslint":"^9.25.0","typescript":"~5.9.2","@types/react":"~19.1.0","react-native":"0.81.5","eslint-config-expo":"~10.0.0","react-native-builder-bob":"^0.40.0"},"peerDependencies":{"react":">=19.0.0","expo-haptics":">=15.0.0","react-native":">=0.76.0","react-native-worklets":">=0.4.0","react-native-reanimated":">=4.0.0","react-native-gesture-handler":">=2.20.0"},"_npmOperationalInternal":{"tmp":"tmp/drag-n-drop-engine_1.0.1_1772626171886_0.9063576337821346","host":"s3://npm-registry-packages-npm-production"},"react-native-builder-bob":{"output":"lib","source":"src","targets":[["commonjs",{"esm":true}],["module",{"esm":true}],["typescript",{"project":"tsconfig.build.json"}]]}},"1.0.2":{"name":"@elham-en/drag-n-drop-engine","version":"1.0.2","keywords":["react-native","drag-and-drop","reanimated","gesture-handler","reorder","new-architecture"],"author":{"name":"Elham Najeebullah"},"license":"MIT","_id":"@elham-en/drag-n-drop-engine@1.0.2","maintainers":[{"name":"elham-en","email":"ilhamrezaie@gmail.com"}],"homepage":"https://github.com/Elham-EN/drag-n-drop-engine#readme","bugs":{"url":"https://github.com/Elham-EN/drag-n-drop-engine/issues"},"dist":{"shasum":"b7e97e85df46a5fbd63cd47a5d5314b5e052f6fa","tarball":"https://registry.npmjs.org/@elham-en/drag-n-drop-engine/-/drag-n-drop-engine-1.0.2.tgz","fileCount":70,"integrity":"sha512-QdWsihANYeSxsOZ/WEpZoxVta+szpdjexZiXwyKbyy/J7YWQOrHvdCvsXC04VDJPOZROYLh0Vwnwp8b/ecaYsQ==","signatures":[{"sig":"MEUCIQCNYOpFd1ymjx7vSX9gcs9yW0TVHNm3hWOHsZ6OTLYtwwIgQBORVzHAswxycrMprkk8DA8mthYR8Vi05UDuZFCvmI0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":221368},"main":"./lib/commonjs/index.js","types":"./lib/typescript/commonjs/src/index.d.ts","module":"./lib/module/index.js","exports":{".":{"import":{"types":"./lib/typescript/module/src/index.d.ts","default":"./lib/module/index.js"},"source":"./src/index.ts","require":{"types":"./lib/typescript/commonjs/src/index.d.ts","default":"./lib/commonjs/index.js"}},"./package.json":"./package.json"},"gitHead":"e57b70f3a705b16fd7591a7d7e527bd96c3558a5","scripts":{"lint":"eslint \"src/**/*.{ts,tsx}\"","build":"bob build","prepare":"bob build","typecheck":"tsc --noEmit"},"_npmUser":{"name":"elham-en","email":"ilhamrezaie@gmail.com"},"repository":{"url":"git+https://github.com/Elham-EN/drag-n-drop-engine.git","type":"git"},"_npmVersion":"11.6.2","description":"React Native drag-and-drop engine for reordering and moving items across lists. Built on Reanimated 4, Gesture Handler, and react-native-worklets.","directories":{},"_nodeVersion":"22.17.0","react-native":"./src/index.ts","_hasShrinkwrap":false,"devDependencies":{"react":"19.1.0","eslint":"^9.25.0","typescript":"~5.9.2","@types/react":"~19.1.0","react-native":"0.81.5","eslint-config-expo":"~10.0.0","react-native-builder-bob":"^0.40.0"},"peerDependencies":{"react":">=19.0.0","expo-haptics":">=15.0.0","react-native":">=0.76.0","react-native-worklets":">=0.4.0","react-native-reanimated":">=4.0.0","react-native-gesture-handler":">=2.20.0"},"_npmOperationalInternal":{"tmp":"tmp/drag-n-drop-engine_1.0.2_1772626398186_0.9583500675699876","host":"s3://npm-registry-packages-npm-production"},"react-native-builder-bob":{"output":"lib","source":"src","targets":[["commonjs",{"esm":true}],["module",{"esm":true}],["typescript",{"project":"tsconfig.build.json"}]]}},"1.0.3":{"name":"@elham-en/drag-n-drop-engine","version":"1.0.3","keywords":["react-native","drag-and-drop","reanimated","gesture-handler","reorder","new-architecture"],"author":{"name":"Elham Najeebullah"},"license":"MIT","_id":"@elham-en/drag-n-drop-engine@1.0.3","maintainers":[{"name":"elham-en","email":"ilhamrezaie@gmail.com"}],"homepage":"https://github.com/Elham-EN/drag-n-drop-engine#readme","bugs":{"url":"https://github.com/Elham-EN/drag-n-drop-engine/issues"},"dist":{"shasum":"e9a49df88fad639b011941584184fea4d05e3914","tarball":"https://registry.npmjs.org/@elham-en/drag-n-drop-engine/-/drag-n-drop-engine-1.0.3.tgz","fileCount":70,"integrity":"sha512-nJ70i/O5x3lcilF2vwzIVHFK2VylzFGc1mBBQfbNJV8UNBaUsnU5Zssx11tdD/6BtpXDoWrrF+TXnGr+ljhCOA==","signatures":[{"sig":"MEYCIQCCFvKxRBTrHXSqtXjlr8himU82npGBE3RrW4ZKzCFCCQIhAO1CRcyBBLKui9FyXZmMab175WtkZj810gqwFYKdMocY","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":221368},"main":"./lib/commonjs/index.js","types":"./lib/typescript/commonjs/src/index.d.ts","module":"./lib/module/index.js","exports":{".":{"import":{"types":"./lib/typescript/module/src/index.d.ts","default":"./lib/module/index.js"},"source":"./src/index.ts","require":{"types":"./lib/typescript/commonjs/src/index.d.ts","default":"./lib/commonjs/index.js"}},"./package.json":"./package.json"},"gitHead":"ad6e47b28af81c7a99123ff5f920c28d653e3520","scripts":{"lint":"eslint \"src/**/*.{ts,tsx}\"","build":"bob build","prepare":"bob build","typecheck":"tsc --noEmit"},"_npmUser":{"name":"elham-en","email":"ilhamrezaie@gmail.com"},"repository":{"url":"git+https://github.com/Elham-EN/drag-n-drop-engine.git","type":"git"},"_npmVersion":"11.6.2","description":"React Native drag-and-drop engine for reordering and moving items across lists. Built on Reanimated 4, Gesture Handler, and react-native-worklets.","directories":{},"_nodeVersion":"22.17.0","react-native":"./src/index.ts","_hasShrinkwrap":false,"devDependencies":{"react":"19.1.0","eslint":"^9.25.0","typescript":"~5.9.2","@types/react":"~19.1.0","react-native":"0.81.5","eslint-config-expo":"~10.0.0","react-native-builder-bob":"^0.40.0"},"peerDependencies":{"react":">=19.0.0","expo-haptics":">=15.0.0","react-native":">=0.76.0","react-native-worklets":">=0.4.0","react-native-reanimated":">=4.0.0","react-native-gesture-handler":">=2.20.0"},"_npmOperationalInternal":{"tmp":"tmp/drag-n-drop-engine_1.0.3_1772626968899_0.5810641981358922","host":"s3://npm-registry-packages-npm-production"},"react-native-builder-bob":{"output":"lib","source":"src","targets":[["commonjs",{"esm":true}],["module",{"esm":true}],["typescript",{"project":"tsconfig.build.json"}]]}},"1.0.4":{"name":"@elham-en/drag-n-drop-engine","version":"1.0.4","description":"React Native drag-and-drop engine for reordering and moving items across lists. Built on Reanimated 4, Gesture Handler, and react-native-worklets.","main":"./lib/commonjs/index.js","module":"./lib/module/index.js","types":"./lib/typescript/commonjs/src/index.d.ts","react-native":"./src/index.ts","exports":{".":{"source":"./src/index.ts","import":{"types":"./lib/typescript/module/src/index.d.ts","default":"./lib/module/index.js"},"require":{"types":"./lib/typescript/commonjs/src/index.d.ts","default":"./lib/commonjs/index.js"}},"./package.json":"./package.json"},"scripts":{"build":"bob build","prepare":"bob build","lint":"eslint \"src/**/*.{ts,tsx}\"","typecheck":"tsc --noEmit"},"keywords":["react-native","drag-and-drop","reanimated","gesture-handler","reorder","new-architecture"],"license":"MIT","author":{"name":"Elham Najeebullah"},"repository":{"type":"git","url":"git+https://github.com/Elham-EN/new-RN-dragNdrop-engine.git"},"peerDependencies":{"expo-haptics":">=15.0.0","react":">=19.0.0","react-native":">=0.76.0","react-native-gesture-handler":">=2.20.0","react-native-reanimated":">=4.0.0","react-native-worklets":">=0.4.0"},"devDependencies":{"@types/react":"~19.1.0","eslint":"^9.25.0","eslint-config-expo":"~10.0.0","react":"19.1.0","react-native":"0.81.5","react-native-builder-bob":"^0.40.0","typescript":"~5.9.2"},"react-native-builder-bob":{"source":"src","output":"lib","targets":[["commonjs",{"esm":true}],["module",{"esm":true}],["typescript",{"project":"tsconfig.build.json"}]]},"gitHead":"b9c6cb9a8f93b2646e16ec32b3029c6fcc60a91e","_id":"@elham-en/drag-n-drop-engine@1.0.4","bugs":{"url":"https://github.com/Elham-EN/new-RN-dragNdrop-engine/issues"},"homepage":"https://github.com/Elham-EN/new-RN-dragNdrop-engine#readme","_nodeVersion":"22.17.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-xGzKpNWY5yKTMZdl7XHiS99cGH5iix8tuujqVlO82rCYhY1iwFiWtc8FeK7Xbm2HaCWYqAsMjzOn6gj4eVSK3w==","shasum":"804f38a35e4e4205af0b7b858d597b80b840082c","tarball":"https://registry.npmjs.org/@elham-en/drag-n-drop-engine/-/drag-n-drop-engine-1.0.4.tgz","fileCount":70,"unpackedSize":221378,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIH7sMDj5NSW+rDkGfOcSFAgvNBpSemHPiLDCFfg4BtQTAiBkQadCGG6CdyAL01AFnzIxYSIDMeRjjQtrElMGN5YXOQ=="}]},"_npmUser":{"name":"elham-en","email":"ilhamrezaie@gmail.com"},"directories":{},"maintainers":[{"name":"elham-en","email":"ilhamrezaie@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/drag-n-drop-engine_1.0.4_1772627104775_0.33664088750668886"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-04T12:05:38.669Z","modified":"2026-03-04T12:25:05.058Z","1.0.0":"2026-03-04T12:05:38.954Z","1.0.1":"2026-03-04T12:09:32.054Z","1.0.2":"2026-03-04T12:13:18.356Z","1.0.3":"2026-03-04T12:22:49.063Z","1.0.4":"2026-03-04T12:25:04.930Z"},"bugs":{"url":"https://github.com/Elham-EN/new-RN-dragNdrop-engine/issues"},"author":{"name":"Elham Najeebullah"},"license":"MIT","homepage":"https://github.com/Elham-EN/new-RN-dragNdrop-engine#readme","keywords":["react-native","drag-and-drop","reanimated","gesture-handler","reorder","new-architecture"],"repository":{"type":"git","url":"git+https://github.com/Elham-EN/new-RN-dragNdrop-engine.git"},"description":"React Native drag-and-drop engine for reordering and moving items across lists. Built on Reanimated 4, Gesture Handler, and react-native-worklets.","maintainers":[{"name":"elham-en","email":"ilhamrezaie@gmail.com"}],"readme":"# @elham-en/drag-n-drop-engine\n\nA custom-built drag-and-drop engine for reordering and moving items across lists in React Native. Built from scratch because existing third-party drag-and-drop libraries are outdated, relying on the old React Native architecture and deprecated APIs that no longer align with the modern ecosystem.\n\n## Table of Contents\n\n- [@elham-en/drag-n-drop-engine](#elham-endrag-n-drop-engine)\n  - [Table of Contents](#table-of-contents)\n  - [Demo](#demo)\n  - [Why Build This?](#why-build-this)\n  - [Installation](#installation)\n  - [Peer Dependencies](#peer-dependencies)\n  - [Usage](#usage)\n  - [API](#api)\n  - [Tech Stack](#tech-stack)\n  - [Features](#features)\n  - [Architecture](#architecture)\n    - [1. Shared State (`DragContext`)](#1-shared-state-dragcontext)\n    - [2. Gesture \\& Hit-Test (`DragItemComponent`)](#2-gesture--hit-test-dragitemcomponent)\n    - [3. Layout Registry (`DragItemComponent` + `DragList`)](#3-layout-registry-dragitemcomponent--draglist)\n    - [Threading Model](#threading-model)\n  - [How It Works](#how-it-works)\n  - [Contributing](#contributing)\n    - [How to Contribute](#how-to-contribute)\n    - [Guidelines](#guidelines)\n    - [Ideas for Contribution](#ideas-for-contribution)\n  - [License](#license)\n\n## Demo\n\n<img src=\"https://raw.githubusercontent.com/Elham-EN/new-RN-dragNdrop-engine/main/example/assets/preview3.gif\" width=\"300\" alt=\"Drag and drop demo\" />\n\n## Why Build This?\n\nThird-party drag-and-drop libraries for React Native have not kept pace with the platform. Most still target the legacy architecture (Bridge-based) and depend on older versions of Reanimated, Gesture Handler, and lack support for the new worklets threading model. This leads to:\n\n- **Dropped frames during drag** — gesture callbacks crossing the JS bridge introduce latency that breaks smooth 60/120fps tracking.\n- **Stale layout data** — libraries that measure positions on the JS thread get out-of-date values when the UI thread has already moved on.\n- **Incompatibility with New Architecture** — the Bridgeless mode, Fabric renderer, and TurboModules require libraries to adopt new threading patterns that most drag-and-drop solutions haven't adopted yet.\n\nThis engine was built to run entirely on the **New Architecture** with the latest stable releases of its core dependencies.\n\n## Installation\n\n```bash\nnpm install @elham-en/drag-n-drop-engine\n```\n\n## Peer Dependencies\n\nInstall these alongside the library:\n\n```bash\nnpm install react-native-reanimated react-native-gesture-handler react-native-worklets expo-haptics\n```\n\n| Package | Minimum Version |\n|---------|----------------|\n| `react` | `>=19.0.0` |\n| `react-native` | `>=0.76.0` |\n| `react-native-reanimated` | `>=4.0.0` |\n| `react-native-gesture-handler` | `>=2.20.0` |\n| `react-native-worklets` | `>=0.4.0` |\n| `expo-haptics` | `>=15.0.0` |\n\nYou must also wrap your app root with `GestureHandlerRootView` from `react-native-gesture-handler` and follow the [Reanimated setup guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/).\n\n## Usage\n\n```tsx\nimport React, { useState } from \"react\";\nimport { View } from \"react-native\";\nimport {\n  DragProvider,\n  DragList,\n  DragGhost,\n  DragScrollView,\n  DragItem,\n} from \"@elham-en/drag-n-drop-engine\";\n\n// Your items must satisfy the DragItem shape\ntype Task = DragItem; // or extend it: type Task = DragItem & { priority: string }\n\nconst INITIAL_TASKS: Task[] = [\n  { taskId: \"t1\", listId: \"list1\", order: 0, title: \"Buy groceries\", description: \"Milk and eggs\" },\n  { taskId: \"t2\", listId: \"list1\", order: 1, title: \"Team standup\", description: \"9am daily sync\" },\n  { taskId: \"t3\", listId: \"list2\", order: 0, title: \"Write tests\",  description: \"Cover main components\" },\n];\n\nexport default function App() {\n  const [tasks, setTasks] = useState<Task[]>(INITIAL_TASKS);\n\n  // Filter and sort tasks for a given list\n  function getTasksForList(listId: string) {\n    return tasks\n      .filter((t) => t.listId === listId)\n      .sort((a, b) => a.order - b.order);\n  }\n\n  return (\n    // DragProvider owns all drag state — pass setTasks so it can commit drops\n    <DragProvider setTasks={setTasks}>\n      <View style={{ flex: 1 }}>\n\n        {/* DragScrollView wires up the scroll ref and auto-scroll logic */}\n        <DragScrollView>\n          <DragList\n            listId=\"list1\"\n            listName=\"Inbox\"\n            listIconLeft={<Text>📥</Text>}\n            tasks={getTasksForList(\"list1\")}\n          />\n          <DragList\n            listId=\"list2\"\n            listName=\"Today\"\n            listIconLeft={<Text>📅</Text>}\n            tasks={getTasksForList(\"list2\")}\n          />\n        </DragScrollView>\n\n        {/* DragGhost must be outside DragScrollView so it floats above everything */}\n        <DragGhost />\n\n      </View>\n    </DragProvider>\n  );\n}\n```\n\n## API\n\n### `DragProvider`\n\nWraps the screen and creates all shared drag state. Required parent for all other components.\n\n| Prop | Type | Required | Description |\n|------|------|----------|-------------|\n| `setTasks` | `React.Dispatch<React.SetStateAction<T[]>>` | Yes | Called after a drop to commit the new item order into React state |\n| `children` | `React.ReactNode` | Yes | Screen content |\n\nGeneric over `T extends DragItem` — pass your extended item type to `setTasks` for full type safety.\n\n---\n\n### `DragList`\n\nA collapsible list container that accepts draggable items.\n\n| Prop | Type | Required | Description |\n|------|------|----------|-------------|\n| `listId` | `string` | Yes | Unique identifier for this list |\n| `listName` | `string` | Yes | Display name in the list header |\n| `listIconLeft` | `React.ReactNode` | Yes | Icon element rendered to the left of the list name |\n| `tasks` | `DragItem[]` | Yes | Pre-filtered and sorted items for this list |\n\n---\n\n### `DragScrollView`\n\nA pre-wired `ScrollView` that connects the scroll ref, scroll enabled state, and current scroll offset to the drag context. Wrap your `DragList` components inside this.\n\nNo props required — it reads everything it needs from `DragProvider`.\n\n---\n\n### `DragGhost`\n\nThe floating visual copy of the dragged item that follows the finger. Renders above all other content.\n\nPlace this **outside** `DragScrollView` (but inside `DragProvider`) so it is never clipped.\n\nNo props required.\n\n---\n\n### `DragItem` type\n\nThe minimum shape your items must satisfy:\n\n```typescript\ntype DragItem = {\n  taskId: string;      // unique ID\n  listId: string;      // which list this item belongs to\n  order: number;       // position within the list — used for sorting\n  title: string;       // displayed in the item row and ghost\n  description: string; // displayed below the title\n};\n```\n\nYou can extend it with additional fields:\n\n```typescript\ntype MyTask = DragItem & {\n  priority: \"low\" | \"medium\" | \"high\";\n  dueDate: string;\n};\n```\n\n## Tech Stack\n\n| Dependency            | Version | Role                                                                  |\n| --------------------- | ------- | --------------------------------------------------------------------- |\n| React Native          | 0.81    | New Architecture (Bridgeless, Fabric)                                 |\n| Reanimated 4          | ~4.1.1  | Shared values, `useAnimatedStyle`, `measure()` on UI thread           |\n| Gesture Handler       | ~2.28.0 | Pan gesture with long-press activation, simultaneous gesture handling |\n| React Native Worklets | 0.5.1   | `scheduleOnUI` / `scheduleOnRN` for cross-thread communication        |\n| Expo Haptics          | ~15.0.8 | Tactile feedback on pickup, slot change, and drop                     |\n\n## Features\n\n- **Within-list reorder** — long-press an item, drag it to a new position in the same list, and drop it. The list reorders instantly.\n- **Cross-list move** — drag an item from one list and drop it into any other list at any position.\n- **Visual drop indicator** — a blue insertion line appears at the exact gap where the item will land, updating in real-time as you drag.\n- **Floating ghost** — a scaled-down copy of the dragged item follows the finger, rendered above all other content so it's never clipped by scroll containers.\n- **Auto-scroll** — when dragging near the top or bottom edge of the ScrollView, the list scrolls automatically at a speed proportional to how close the finger is to the edge.\n- **Haptic feedback** — four distinct haptic responses: medium impact on pickup, selection tick on slot change, success notification on valid drop, warning notification on invalid drop.\n- **Collapsible lists** — each list can be expanded or collapsed with a smooth height animation. The drag engine respects collapsed state and only targets expanded lists.\n- **Dynamic list sizing** — list containers grow and shrink automatically as items are added or removed via drag.\n- **Scroll-corrected hit-testing** — layout measurements are captured with the scroll offset at measure time, and the hit-test worklet corrects for any scroll that happened since, so positions are always accurate.\n\n## Architecture\n\nThe engine is split into three layers:\n\n### 1. Shared State (`DragContext`)\n\nA React context that holds all Reanimated shared values: drag identity, ghost position, drop target tracking, scroll control, and the layout registry. Every component reads from and writes to these values during a drag.\n\n### 2. Gesture & Hit-Test (`DragItemComponent`)\n\nEach task item owns a Pan gesture (activated after a 400ms long-press). All gesture callbacks (`onBegin`, `onStart`, `onUpdate`, `onEnd`, `onFinalize`) run as **worklets on the UI thread** for zero-latency tracking. The hit-test function runs every frame during drag — it walks the layout registry, corrects for scroll offset, and determines which list and slot the finger is over.\n\n### 3. Layout Registry (`DragItemComponent` + `DragList`)\n\nBoth items and lists register their absolute screen positions into shared value arrays via `scheduleOnUI` + `measure()`. This runs on the UI thread so measurements are always frame-accurate. The registry is the single source of truth for hit-testing.\n\n### Threading Model\n\n```\nUI Thread (worklets)          RN/JS Thread\n├── Gesture callbacks         ├── commitDrop (React setState)\n├── Hit-test every frame      ├── Haptic feedback calls\n├── Ghost position updates    └── Layout registration triggers\n├── Auto-scroll via scrollTo\n└── measure() for layout\n```\n\n`scheduleOnRN` bridges from UI to JS thread for state commits and haptics. `scheduleOnUI` bridges from JS to UI thread for layout measurements. No legacy bridge involved.\n\n## How It Works\n\n1. **Long-press (400ms)** activates the drag. The item's position is measured, the ghost is placed over it, and the item becomes invisible.\n2. **Drag** — every frame, the ghost follows the finger, the hit-test worklet determines the target list and insertion slot, and the insertion line updates.\n3. **Drop** — if the finger is over a valid slot, `commitDrop` is called on the JS thread. It updates React state in a single `setTasks` call, handling both same-list reorder and cross-list move. If the drop is invalid, the ghost springs back to its origin.\n4. **Cleanup** — scroll is re-enabled, drop indicators are cleared, and the item's opacity is restored.\n\n## Contributing\n\nContributions are welcome! This project is open source under the [MIT License](LICENSE).\n\n### How to Contribute\n\n1. **Fork** the repository\n2. **Create a branch** for your feature or fix\n   ```bash\n   git checkout -b feature/your-feature-name\n   ```\n3. **Make your changes** — follow the existing code style and comment conventions\n4. **Test on a real device** — drag-and-drop behaviour can differ between simulators and physical devices, so always verify on hardware\n5. **Commit** with a clear message describing what changed and why\n6. **Push** your branch and open a **Pull Request** against `main`\n\n### Guidelines\n\n- **Keep it simple** — avoid over-engineering. Only add what is needed for the feature or fix.\n- **Comment your code** — every function and significant variable should have a short comment explaining what it does and why.\n- **UI thread awareness** — gesture callbacks and hit-test logic run as worklets. Any new logic in these paths must use the `\"worklet\"` directive and avoid JS-thread APIs. Use `scheduleOnRN` to call JS-thread functions from worklets.\n- **Test across lists** — verify within-list reorder, cross-list move, empty list drops, and auto-scroll behaviour.\n- **No breaking changes** without discussion — if your change affects the public API or drag behaviour, open an issue first to discuss the approach.\n\n### Ideas for Contribution\n\n- Drag handle support (drag from a specific grip icon instead of long-press anywhere)\n- Animated item reflow (items slide apart to make room for the dragged item)\n- Horizontal list support\n- Accessibility improvements (screen reader announcements during drag)\n- Performance profiling and optimisation for very long lists (100+ items)\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE).\n","readmeFilename":"README.md"}