{"_id":"@avinash_ghosh/react-generic-dragdrop","_rev":"2-fb41db492f8a69dd7a243431334b8e7c","name":"@avinash_ghosh/react-generic-dragdrop","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@avinash_ghosh/react-generic-dragdrop","version":"1.0.0","keywords":["react","drag-and-drop","dnd","typescript","component","ui","kanban","sortable","reorderable"],"author":{"name":"Avinash Ghosh","email":"avinashghoshpullur@gmail.com"},"license":"MIT","_id":"@avinash_ghosh/react-generic-dragdrop@1.0.0","maintainers":[{"name":"avinash_ghosh","email":"avinashghoshpullur@gmail.com"}],"homepage":"https://github.com/your-username/react-generic-dragdrop#readme","bugs":{"url":"https://github.com/your-username/react-generic-dragdrop/issues"},"dist":{"shasum":"c15d497a4ce6ef775d828662f9777b1e7b69f3a1","tarball":"https://registry.npmjs.org/@avinash_ghosh/react-generic-dragdrop/-/react-generic-dragdrop-1.0.0.tgz","fileCount":14,"integrity":"sha512-cK0Bp5OSaKK2nhyTRdODCdlu0bhVCbgpBoZ5ppETRSr2xZKu6P+pUHqdRDB3QcVwOuq3gQ2rMeCoBF3ovqQsvQ==","signatures":[{"sig":"MEQCIDp94jqQ2E7St3RNnWJUUtdPrMpE414avsD38N57c1aJAiBeYE7JOD1kh0DPg/IhsSonwRuWiQvX5I5IZvOJE8z6zw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":126101},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.esm.js","engines":{"node":">=14.0.0"},"gitHead":"0a2c13323adcf762451be635c3ac5008c7eaccc0","scripts":{"test":"jest","build":"rollup -c","storybook":"storybook dev -p 6006","test:watch":"jest --watch","build:watch":"rollup -c -w","prepublishOnly":"npm run build","build-storybook":"storybook build"},"_npmUser":{"name":"avinash_ghosh","email":"avinashghoshpullur@gmail.com"},"repository":{"url":"git+https://github.com/your-username/react-generic-dragdrop.git","type":"git"},"_npmVersion":"10.9.2","description":"A flexible, reusable React drag and drop component with TypeScript support","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","react":"^18.2.0","rollup":"^4.6.1","react-dom":"^18.2.0","storybook":"^7.6.6","typescript":"^5.3.2","@types/jest":"^29.5.8","@types/react":"^18.2.42","@storybook/react":"^7.6.6","@types/react-dom":"^18.2.17","@storybook/blocks":"^7.6.6","rollup-plugin-dts":"^6.1.0","@storybook/react-vite":"^7.6.6","@storybook/addon-links":"^7.6.6","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-typescript":"^11.1.5","@storybook/testing-library":"^0.2.2","@rollup/plugin-node-resolve":"^15.2.3","@storybook/addon-essentials":"^7.6.6","@storybook/addon-interactions":"^7.6.6","rollup-plugin-peer-deps-external":"^2.2.4"},"peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"_npmOperationalInternal":{"tmp":"tmp/react-generic-dragdrop_1.0.0_1748422175799_0.7842762531930503","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@avinash_ghosh/react-generic-dragdrop","version":"1.0.1","description":"A flexible, reusable React drag and drop component with TypeScript support","main":"dist/index.js","module":"dist/index.esm.js","types":"dist/index.d.ts","scripts":{"build":"rollup -c","build:watch":"rollup -c -w","test":"jest","test:watch":"jest --watch","prepublishOnly":"npm run build","storybook":"storybook dev -p 6006","build-storybook":"storybook build"},"keywords":["react","drag-and-drop","dnd","typescript","component","ui","kanban","sortable","reorderable"],"author":{"name":"Avinash Ghosh","email":"avinashghoshpullur@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/your-username/react-generic-dragdrop.git"},"bugs":{"url":"https://github.com/your-username/react-generic-dragdrop/issues"},"homepage":"https://github.com/your-username/react-generic-dragdrop#readme","peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"devDependencies":{"@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-node-resolve":"^15.2.3","@rollup/plugin-typescript":"^11.1.5","@storybook/addon-essentials":"^7.6.6","@storybook/addon-interactions":"^7.6.6","@storybook/addon-links":"^7.6.6","@storybook/blocks":"^7.6.6","@storybook/react":"^7.6.6","@storybook/react-vite":"^7.6.6","@storybook/testing-library":"^0.2.2","@types/jest":"^29.5.8","@types/react":"^18.2.42","@types/react-dom":"^18.2.17","jest":"^29.7.0","react":"^18.2.0","react-dom":"^18.2.0","rollup":"^4.6.1","rollup-plugin-dts":"^6.1.0","rollup-plugin-peer-deps-external":"^2.2.4","storybook":"^7.6.6","typescript":"^5.3.2"},"engines":{"node":">=14.0.0"},"_id":"@avinash_ghosh/react-generic-dragdrop@1.0.1","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-XaVAkB3rBATgXycyRd318FRpsw97eFGqbxcB3ZflmAyC2F1XmdMEZp31ABS5HwUCHn7vLdsvCpATkEEqsln2Ow==","shasum":"d722b6414129b7206d3822508c0bb2274047386d","tarball":"https://registry.npmjs.org/@avinash_ghosh/react-generic-dragdrop/-/react-generic-dragdrop-1.0.1.tgz","fileCount":14,"unpackedSize":135805,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICa5+hITIONYw1gjiWQb7pakbT43Rn1jPHS3YAQAayPKAiAbmaS9IGVfgjxc9d+oR0T2V8wEsoYEfUT9PC+X9Aoi3w=="}]},"_npmUser":{"name":"avinash_ghosh","email":"avinashghoshpullur@gmail.com"},"directories":{},"maintainers":[{"name":"avinash_ghosh","email":"avinashghoshpullur@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react-generic-dragdrop_1.0.1_1748439037285_0.10175871260727742"},"_hasShrinkwrap":false}},"time":{"created":"2025-05-28T08:49:35.658Z","modified":"2025-05-28T13:30:37.638Z","1.0.0":"2025-05-28T08:49:35.996Z","1.0.1":"2025-05-28T13:30:37.462Z"},"bugs":{"url":"https://github.com/your-username/react-generic-dragdrop/issues"},"author":{"name":"Avinash Ghosh","email":"avinashghoshpullur@gmail.com"},"license":"MIT","homepage":"https://github.com/your-username/react-generic-dragdrop#readme","keywords":["react","drag-and-drop","dnd","typescript","component","ui","kanban","sortable","reorderable"],"repository":{"type":"git","url":"git+https://github.com/your-username/react-generic-dragdrop.git"},"description":"A flexible, reusable React drag and drop component with TypeScript support","maintainers":[{"name":"avinash_ghosh","email":"avinashghoshpullur@gmail.com"}],"readme":"# React Generic Drag & Drop\r\n\r\nA flexible, reusable React drag and drop component library with TypeScript support. Perfect for building Kanban boards, sortable lists, and any drag-and-drop interface.\r\n\r\n## ✨ Features\r\n\r\n- 🎯 **Generic & Flexible** - Works with any data type extending `DragDropItem`\r\n- 🔄 **Cross-Container Transfers** - Drag items between different containers\r\n- 🎨 **Customizable Styling** - Full control over appearance and animations\r\n- 📱 **TypeScript Support** - Complete type safety and IntelliSense\r\n- 🚀 **Performance Optimized** - Efficient state management with React Context\r\n- 🎪 **Visual Feedback** - Beautiful drop indicators and hover effects\r\n- 🔧 **Easy Integration** - Simple HOC pattern with minimal setup\r\n\r\n## 📦 Installation\r\n\r\n```bash\r\nnpm install @avinash_ghosh/react-generic-dragdrop\r\n```\r\n\r\n```bash\r\nyarn add @avinash_ghosh/react-generic-dragdrop\r\n```\r\n\r\n## 🚀 Quick Start\r\n\r\n```tsx\r\nimport React, { useState } from 'react';\r\nimport { DragDropProvider, DragDropContainer, DragDropItem } from '@avinash_ghosh/react-generic-dragdrop';\r\n\r\n// Define your item type\r\ninterface TaskItem extends DragDropItem {\r\n  title: string;\r\n  description: string;\r\n}\r\n\r\nfunction App() {\r\n  const [items, setItems] = useState<TaskItem[]>([\r\n    { id: '1', title: 'Task 1', description: 'First task' },\r\n    { id: '2', title: 'Task 2', description: 'Second task' },\r\n  ]);\r\n\r\n  // Custom render function\r\n  const renderItem = (item: TaskItem, index: number, isDragging: boolean) => (\r\n    <div style={{\r\n      padding: '12px',\r\n      backgroundColor: isDragging ? '#f0f0f0' : 'white',\r\n      border: '1px solid #ddd',\r\n      borderRadius: '4px',\r\n      opacity: isDragging ? 0.8 : 1,\r\n    }}>\r\n      <h4>{item.title}</h4>\r\n      <p>{item.description}</p>\r\n    </div>\r\n  );\r\n\r\n  return (\r\n    <DragDropProvider>\r\n      <DragDropContainer\r\n        id=\"my-container\"\r\n        items={items}\r\n        renderItem={renderItem}\r\n        onReorder={setItems}\r\n        title=\"My Tasks\"\r\n        containerStyles={{\r\n          backgroundColor: '#f8f9fa',\r\n          padding: '16px',\r\n          borderRadius: '8px',\r\n        }}\r\n      />\r\n    </DragDropProvider>\r\n  );\r\n}\r\n```\r\n\r\n## 🎯 Advanced Example - Kanban Board\r\n\r\n```tsx\r\nimport React, { useState } from 'react';\r\nimport { DragDropProvider, DragDropContainer, DragDropItem } from '@avinash_ghosh/react-generic-dragdrop';\r\n\r\ninterface Task extends DragDropItem {\r\n  title: string;\r\n  description: string;\r\n  priority: 'low' | 'medium' | 'high';\r\n  assignee: string;\r\n}\r\n\r\nfunction KanbanBoard() {\r\n  const [todoItems, setTodoItems] = useState<Task[]>([\r\n    { id: '1', title: 'Design Homepage', description: 'Create wireframes', priority: 'high', assignee: 'John' },\r\n    { id: '2', title: 'Setup Database', description: 'Configure PostgreSQL', priority: 'medium', assignee: 'Jane' },\r\n  ]);\r\n\r\n  const [inProgressItems, setInProgressItems] = useState<Task[]>([\r\n    { id: '3', title: 'Implement Auth', description: 'JWT authentication', priority: 'high', assignee: 'Bob' },\r\n  ]);\r\n\r\n  const [doneItems, setDoneItems] = useState<Task[]>([]);\r\n\r\n  const renderTask = (task: Task, index: number, isDragging: boolean) => {\r\n    const priorityColors = {\r\n      high: '#ff4444',\r\n      medium: '#ffaa00',\r\n      low: '#44aa44'\r\n    };\r\n\r\n    return (\r\n      <div style={{\r\n        padding: '12px',\r\n        backgroundColor: 'white',\r\n        borderRadius: '8px',\r\n        border: '2px solid transparent',\r\n        borderColor: isDragging ? '#007bff' : 'transparent',\r\n        boxShadow: isDragging ? '0 8px 16px rgba(0,0,0,0.2)' : '0 2px 4px rgba(0,0,0,0.1)',\r\n        transform: isDragging ? 'rotate(2deg) scale(1.02)' : 'none',\r\n        transition: 'all 0.2s ease',\r\n      }}>\r\n        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '8px' }}>\r\n          <span style={{ fontWeight: 'bold' }}>{task.title}</span>\r\n          <span style={{\r\n            padding: '2px 6px',\r\n            borderRadius: '12px',\r\n            backgroundColor: priorityColors[task.priority],\r\n            color: 'white',\r\n            fontSize: '10px',\r\n            textTransform: 'uppercase'\r\n          }}>\r\n            {task.priority}\r\n          </span>\r\n        </div>\r\n        <p style={{ margin: '8px 0', color: '#666' }}>{task.description}</p>\r\n        <div style={{ fontSize: '12px', color: '#888' }}>Assigned to: {task.assignee}</div>\r\n      </div>\r\n    );\r\n  };\r\n\r\n  const handleMoveItem = (item: Task, fromContainerId: string) => {\r\n    // Remove from source\r\n    if (fromContainerId === 'todo') setTodoItems(prev => prev.filter(i => i.id !== item.id));\r\n    if (fromContainerId === 'inprogress') setInProgressItems(prev => prev.filter(i => i.id !== item.id));\r\n    if (fromContainerId === 'done') setDoneItems(prev => prev.filter(i => i.id !== item.id));\r\n  };\r\n\r\n  const handleReceiveItem = (item: Task, fromContainerId: string, toIndex: number, toContainerId: string) => {\r\n    // Add to destination\r\n    if (toContainerId === 'todo') {\r\n      setTodoItems(prev => {\r\n        const newItems = [...prev];\r\n        newItems.splice(toIndex, 0, item);\r\n        return newItems;\r\n      });\r\n    }\r\n    if (toContainerId === 'inprogress') {\r\n      setInProgressItems(prev => {\r\n        const newItems = [...prev];\r\n        newItems.splice(toIndex, 0, item);\r\n        return newItems;\r\n      });\r\n    }\r\n    if (toContainerId === 'done') {\r\n      setDoneItems(prev => {\r\n        const newItems = [...prev];\r\n        newItems.splice(toIndex, 0, item);\r\n        return newItems;\r\n      });\r\n    }\r\n  };\r\n\r\n  return (\r\n    <DragDropProvider>\r\n      <div style={{ display: 'flex', gap: '20px', padding: '20px' }}>\r\n        <DragDropContainer\r\n          id=\"todo\"\r\n          items={todoItems}\r\n          renderItem={renderTask}\r\n          onReorder={setTodoItems}\r\n          onMoveItemOut={handleMoveItem}\r\n          onReceiveItemFromOutside={(item, fromId, toIndex) => handleReceiveItem(item, fromId, toIndex, 'todo')}\r\n          title=\"📋 To Do\"\r\n          containerStyles={{\r\n            backgroundColor: '#f8f9fa',\r\n            border: '2px dashed #dee2e6',\r\n            borderRadius: '12px',\r\n            padding: '16px',\r\n            minHeight: '400px',\r\n            width: '300px'\r\n          }}\r\n          gap=\"12px\"\r\n          emptyMessage=\"Drop tasks here\"\r\n        />\r\n\r\n        <DragDropContainer\r\n          id=\"inprogress\"\r\n          items={inProgressItems}\r\n          renderItem={renderTask}\r\n          onReorder={setInProgressItems}\r\n          onMoveItemOut={handleMoveItem}\r\n          onReceiveItemFromOutside={(item, fromId, toIndex) => handleReceiveItem(item, fromId, toIndex, 'inprogress')}\r\n          title=\"🚀 In Progress\"\r\n          containerStyles={{\r\n            backgroundColor: '#fff3cd',\r\n            border: '2px dashed #ffeaa7',\r\n            borderRadius: '12px',\r\n            padding: '16px',\r\n            minHeight: '400px',\r\n            width: '300px'\r\n          }}\r\n          gap=\"12px\"\r\n          emptyMessage=\"Drop tasks here\"\r\n        />\r\n\r\n        <DragDropContainer\r\n          id=\"done\"\r\n          items={doneItems}\r\n          renderItem={renderTask}\r\n          onReorder={setDoneItems}\r\n          onMoveItemOut={handleMoveItem}\r\n          onReceiveItemFromOutside={(item, fromId, toIndex) => handleReceiveItem(item, fromId, toIndex, 'done')}\r\n          title=\"✅ Done\"\r\n          containerStyles={{\r\n            backgroundColor: '#d4edda',\r\n            border: '2px dashed #c3e6cb',\r\n            borderRadius: '12px',\r\n            padding: '16px',\r\n            minHeight: '400px',\r\n            width: '300px'\r\n          }}\r\n          gap=\"12px\"\r\n          emptyMessage=\"Drop completed tasks here\"\r\n        />\r\n      </div>\r\n    </DragDropProvider>\r\n  );\r\n}\r\n```\r\n\r\n## 📚 API Reference\r\n\r\n### `DragDropProvider`\r\n\r\nContext provider that manages global drag state. Must wrap all `DragDropContainer` components.\r\n\r\n```tsx\r\n<DragDropProvider>\r\n  {/* Your drag drop containers */}\r\n</DragDropProvider>\r\n```\r\n\r\n### `DragDropContainer<T>`\r\n\r\nGeneric container component for drag and drop functionality.\r\n\r\n#### Props\r\n\r\n| Prop | Type | Required | Description |\r\n|------|------|----------|-------------|\r\n| `id` | `string` | ✅ | Unique identifier for the container |\r\n| `items` | `T[]` | ✅ | Array of items to display |\r\n| `renderItem` | `(item: T, index: number, isDragging: boolean) => ReactNode` | ✅ | Function to render each item |\r\n| `onReorder` | `(items: T[]) => void` | ❌ | Called when items are reordered within the same container |\r\n| `onMoveItemOut` | `(item: T, fromContainerId: string) => void` | ❌ | Called when an item is moved out of this container |\r\n| `onReceiveItemFromOutside` | `(item: T, fromContainerId: string, toIndex: number) => void` | ❌ | Called when an item is moved into this container |\r\n| `containerStyles` | `ContainerStyles` | ❌ | Custom styles for the container |\r\n| `gap` | `string` | ❌ | Gap between items (default: '8px') |\r\n| `className` | `string` | ❌ | CSS class name for the container |\r\n| `title` | `string` | ❌ | Title displayed at the top of the container |\r\n| `emptyMessage` | `string` | ❌ | Message shown when container is empty |\r\n| `disabled` | `boolean` | ❌ | Disable drag and drop functionality |\r\n\r\n### Types\r\n\r\n#### `DragDropItem`\r\n\r\nBase interface that all draggable items must extend:\r\n\r\n```tsx\r\ninterface DragDropItem {\r\n  id: string;\r\n  [key: string]: any; // Allow additional properties\r\n}\r\n```\r\n\r\n#### `ContainerStyles`\r\n\r\nStyling options for containers:\r\n\r\n```tsx\r\ninterface ContainerStyles {\r\n  backgroundColor?: string;\r\n  border?: string;\r\n  borderRadius?: string;\r\n  padding?: string;\r\n  minHeight?: string;\r\n  gap?: string;\r\n  [key: string]: any; // Allow any CSS properties\r\n}\r\n```\r\n\r\n## 🎨 Styling\r\n\r\nThe component provides default styling but is fully customizable:\r\n\r\n### Container Styling\r\n\r\n```tsx\r\n<DragDropContainer\r\n  containerStyles={{\r\n    backgroundColor: '#f8f9fa',\r\n    border: '2px dashed #dee2e6',\r\n    borderRadius: '12px',\r\n    padding: '20px',\r\n    minHeight: '300px',\r\n    boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',\r\n  }}\r\n/>\r\n```\r\n\r\n### Item Styling\r\n\r\nControl item appearance through your `renderItem` function:\r\n\r\n```tsx\r\nconst renderItem = (item, index, isDragging) => (\r\n  <div style={{\r\n    padding: '12px',\r\n    backgroundColor: isDragging ? '#e3f2fd' : 'white',\r\n    border: `2px solid ${isDragging ? '#2196f3' : '#e0e0e0'}`,\r\n    borderRadius: '8px',\r\n    transform: isDragging ? 'rotate(2deg) scale(1.05)' : 'none',\r\n    opacity: isDragging ? 0.8 : 1,\r\n    transition: 'all 0.2s ease',\r\n    cursor: 'grab',\r\n  }}>\r\n    {/* Your item content */}\r\n  </div>\r\n);\r\n```\r\n\r\n## 🔧 Development\r\n\r\n### Building the Package\r\n\r\n```bash\r\nnpm run build\r\n```\r\n\r\n### Running Tests\r\n\r\n```bash\r\nnpm test\r\n```\r\n\r\n### Development Mode\r\n\r\n```bash\r\nnpm run build:watch\r\n```\r\n\r\n## 📄 License\r\n\r\nMIT © [Your Name]\r\n\r\n## 🤝 Contributing\r\n\r\nContributions are welcome! Please feel free to submit a Pull Request.\r\n\r\n## 🐛 Issues\r\n\r\nIf you find a bug or have a feature request, please open an issue on [GitHub](https://github.com/avinash_ghosh/react-generic-dragdrop/issues).\r\n\r\n## 📈 Changelog\r\n\r\n### v1.0.0\r\n- Initial release\r\n- Generic drag and drop container\r\n- Cross-container transfers\r\n- TypeScript support\r\n- Customizable styling ","readmeFilename":"README.md"}