diff --git a/__mocks__/react-dnd-preview.ts b/__mocks__/react-dnd-preview.ts index 075a264..91d0b16 100644 --- a/__mocks__/react-dnd-preview.ts +++ b/__mocks__/react-dnd-preview.ts @@ -1,6 +1,8 @@ import {MockDragMonitor} from '@mocks/mocks' import type {PreviewProps, PreviewState, usePreviewState} from 'react-dnd-preview' +import type {JSX} from 'react' + const preview = jest.createMockFromModule>('react-dnd-preview') const state: PreviewState = { diff --git a/biome.json b/biome.json index 90088c3..0120809 100644 --- a/biome.json +++ b/biome.json @@ -24,6 +24,6 @@ } }, "files": { - "ignore": ["examples", "coverage", "packages/*/dist"] + "ignore": ["examples/*.js", "coverage", "packages/*/dist"] } } diff --git a/package-lock.json b/package-lock.json index 89998e6..44d7af5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,20 +16,21 @@ "@testing-library/react": "^16.1.0", "@types/jest": "^29.5.14", "@types/jsdom": "^21.1.7", - "@types/react-dom": "^18.3.5", + "@types/react": "^19.0.2", + "@types/react-dom": "^19.0.2", "esbuild": "^0.24", "esbuild-jest": "^0.5.0", - "esbuild-node-externals": "^1.15.0", + "esbuild-node-externals": "^1.16.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "node-notifier": "^10.0.1", - "react": "^18.3.1", + "react": "^19.0.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dnd-test-backend": "^16.0.1", "react-dnd-test-utils": "^16.0.1", "react-dnd-touch-backend": "^16.0.1", - "react-dom": "^18.3.1", + "react-dom": "^19.0.0", "typescript": "^5.7.2" }, "engines": { @@ -3220,32 +3221,24 @@ "undici-types": "~5.26.4" } }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "devOptional": true, - "peer": true - }, "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.2.tgz", + "integrity": "sha512-USU8ZI/xyKJwFTpjSVIrSeHBVAGagkHQKPNbxeWwql/vDmnTIBgx+TJnhFnj1NXgz8XfprU0egV2dROLGpsBEg==", "devOptional": true, - "peer": true, + "license": "MIT", "dependencies": { - "@types/prop-types": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", - "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.2.tgz", + "integrity": "sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==", "dev": true, "license": "MIT", "peerDependencies": { - "@types/react": "^18.0.0" + "@types/react": "^19.0.0" } }, "node_modules/@types/stack-utils": { @@ -4110,8 +4103,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true, - "peer": true + "devOptional": true }, "node_modules/data-urls": { "version": "3.0.2", @@ -4373,10 +4365,11 @@ } }, "node_modules/esbuild-node-externals": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/esbuild-node-externals/-/esbuild-node-externals-1.15.0.tgz", - "integrity": "sha512-lM5f3CQL9Ctv6mBwwYAEMcphK2qrjVRnemT1mufECpFaidZvFVvQDPcuno/MQfLVk4utVuSVxm1RHLyg/ONQ/A==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/esbuild-node-externals/-/esbuild-node-externals-1.16.0.tgz", + "integrity": "sha512-g16pp/yDFqBJ9/9D+UIWPj5uC8MPslMK62HmAXW+ZomZWJifOFTuJgado86UUiMeBrk03z2uvdS6cIGi0OTRcg==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^5.0.0", "tslib": "^2.4.1" @@ -8936,7 +8929,8 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "node_modules/js-yaml": { "version": "3.14.1", @@ -9065,17 +9059,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -9709,12 +9692,10 @@ "link": true }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9817,15 +9798,15 @@ } }, "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", + "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", + "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "scheduler": "^0.25.0" }, "peerDependencies": { - "react": "^18.3.1" + "react": "^19.0.0" } }, "node_modules/react-is": { @@ -10291,12 +10272,10 @@ } }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", + "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", @@ -11373,7 +11352,7 @@ } }, "packages/dnd-multi-backend": { - "version": "8.1.0", + "version": "8.1.2", "license": "MIT", "funding": { "type": "individual", @@ -11384,10 +11363,10 @@ } }, "packages/rdndmb-html5-to-touch": { - "version": "8.1.0", + "version": "8.1.2", "license": "MIT", "dependencies": { - "dnd-multi-backend": "^8.1.0", + "dnd-multi-backend": "^8.1.2", "react-dnd-html5-backend": "^16.0.1", "react-dnd-touch-backend": "^16.0.1" }, @@ -11397,11 +11376,11 @@ } }, "packages/react-dnd-multi-backend": { - "version": "8.1.0", + "version": "8.1.2", "license": "MIT", "dependencies": { - "dnd-multi-backend": "^8.1.0", - "react-dnd-preview": "^8.1.0" + "dnd-multi-backend": "^8.1.2", + "react-dnd-preview": "^8.1.2" }, "funding": { "type": "individual", @@ -11409,20 +11388,20 @@ }, "peerDependencies": { "dnd-core": "^16.0.1", - "react": "^16.14.0 || ^17.0.2 || ^18.0.0", + "react": "^16.14.0 || ^17.0.2 || ^18.0.0 || ^19.0.0", "react-dnd": "^16.0.1", - "react-dom": "^16.14.0 || ^17.0.2 || ^18.0.0" + "react-dom": "^16.14.0 || ^17.0.2 || ^18.0.0 || ^19.0.0" } }, "packages/react-dnd-preview": { - "version": "8.1.0", + "version": "8.1.2", "license": "MIT", "funding": { "type": "individual", "url": "https://github.com/sponsors/LouisBrunner" }, "peerDependencies": { - "react": "^16.14.0 || ^17.0.2 || ^18.0.0", + "react": "^16.14.0 || ^17.0.2 || ^18.0.0 || ^19.0.0", "react-dnd": "^16.0.1" } } diff --git a/package.json b/package.json index d3541fe..e39d090 100644 --- a/package.json +++ b/package.json @@ -39,20 +39,21 @@ "@testing-library/react": "^16.1.0", "@types/jest": "^29.5.14", "@types/jsdom": "^21.1.7", - "@types/react-dom": "^18.3.5", + "@types/react-dom": "^19.0.2", + "@types/react": "^19.0.2", "esbuild": "^0.24", "esbuild-jest": "^0.5.0", - "esbuild-node-externals": "^1.15.0", + "esbuild-node-externals": "^1.16.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "node-notifier": "^10.0.1", - "react": "^18.3.1", + "react": "^19.0.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dnd-test-backend": "^16.0.1", "react-dnd-test-utils": "^16.0.1", "react-dnd-touch-backend": "^16.0.1", - "react-dom": "^18.3.1", + "react-dom": "^19.0.0", "typescript": "^5.7.2" }, "workspaces": ["./packages/*"] diff --git a/packages/dnd-multi-backend/examples/Backends.ts b/packages/dnd-multi-backend/examples/Backends.ts index ad24529..dbf7500 100644 --- a/packages/dnd-multi-backend/examples/Backends.ts +++ b/packages/dnd-multi-backend/examples/Backends.ts @@ -1,7 +1,7 @@ -import {DragDropManager, DragDropActions, BackendFactory, Backend, Unsubscribe, Identifier} from 'dnd-core' +import type {Backend, BackendFactory, DragDropActions, DragDropManager, Identifier, Unsubscribe} from 'dnd-core' type Options = { - draggable?: boolean, + draggable?: boolean } class DnDBackend implements Backend { @@ -37,6 +37,7 @@ class DnDBackend implements Backend { } } + // biome-ignore lint/suspicious/noExplicitAny: interface is like that connectDragSource(sourceId: Identifier, nodeRaw?: any, _options?: any): Unsubscribe { const node = nodeRaw as Element @@ -49,7 +50,7 @@ class DnDBackend implements Backend { console.log(`${this.#label}: drag`) this.#actions.beginDrag([sourceId], { clientOffset: this.#getXY(node), - getSourceClientOffset: (_id: unknown): {x: number, y: number} => { + getSourceClientOffset: (_id: unknown): {x: number; y: number} => { return this.#getXY(node) }, }) @@ -74,13 +75,15 @@ class DnDBackend implements Backend { } } + // biome-ignore lint/suspicious/noExplicitAny: interface is like that connectDragPreview(_sourceId: any, _node?: any, _options?: any): Unsubscribe { - return () => { } + return () => {} } + // biome-ignore lint/suspicious/noExplicitAny: interface is like that connectDropTarget(targetId: Identifier, node?: Element, _options?: any): Unsubscribe { if (node === undefined) { - return () => { } + return () => {} } const hover = (e: Event) => { @@ -120,7 +123,7 @@ class DnDBackend implements Backend { this.#actions.endDrag() } - #getXY = (node: Element): {x: number, y: number} => { + #getXY = (node: Element): {x: number; y: number} => { const {top: x, left: y} = node.getBoundingClientRect() return {x, y} } diff --git a/packages/dnd-multi-backend/examples/DnD.ts b/packages/dnd-multi-backend/examples/DnD.ts index 0e35460..3bf01e5 100644 --- a/packages/dnd-multi-backend/examples/DnD.ts +++ b/packages/dnd-multi-backend/examples/DnD.ts @@ -1,8 +1,8 @@ -import {DragSource as IDragSource, DropTarget as IDropTarget, DragDropMonitor, Identifier} from 'dnd-core' +import type {DragDropMonitor, DragSource as IDragSource, DropTarget as IDropTarget, Identifier} from 'dnd-core' type createElementProps = { - text: string, - color: string, + text: string + color: string } const createElement = ({text, color}: createElementProps): Element => { @@ -28,7 +28,8 @@ export class DragSource implements IDragSource { beginDrag(_monitor: DragDropMonitor, _targetId: Identifier): void { // FIXME: the interface is actually wrong - return {color: this.#color} as unknown as void + // biome-ignore lint/correctness/noVoidTypeReturn: interface is wrong + return {color: this.#color} as unknown as undefined } endDrag(_monitor: DragDropMonitor, _targetId: Identifier): void {} @@ -42,11 +43,11 @@ export class DragSource implements IDragSource { } } -export class DropTarget implements IDropTarget { +export class DropTarget implements IDropTarget { #node: Element - #onDrop?: (r: any) => void + #onDrop?: (r: T) => void - constructor({text, color, onDrop}: createElementProps & {onDrop?: (r: any) => void}) { + constructor({text, color, onDrop}: createElementProps & {onDrop?: (r: T) => void}) { this.#node = createElement({text, color}) this.#onDrop = onDrop } @@ -61,7 +62,7 @@ export class DropTarget implements IDropTarget { hover(_monitor: DragDropMonitor, _targetId: Identifier): void {} - drop(monitor: DragDropMonitor, _targetId: Identifier): any { + drop(monitor: DragDropMonitor, _targetId: Identifier): void { this.#onDrop?.(monitor.getItem()) } } diff --git a/packages/dnd-multi-backend/examples/index.ts b/packages/dnd-multi-backend/examples/index.ts index 87db957..ce740c6 100644 --- a/packages/dnd-multi-backend/examples/index.ts +++ b/packages/dnd-multi-backend/examples/index.ts @@ -1,7 +1,7 @@ -import { createDragDropManager } from 'dnd-core' -import { MultiBackend, MouseTransition, TouchTransition } from '../src' -import { HTML5Backend, TouchBackend } from './Backends' -import { DragSource, DropTarget } from './DnD' +import {createDragDropManager} from 'dnd-core' +import {MouseTransition, MultiBackend, TouchTransition} from '../src' +import {HTML5Backend, TouchBackend} from './Backends' +import {DragSource, DropTarget} from './DnD' // Setup pipeline const pipeline = { @@ -26,10 +26,13 @@ const registry = manager.getRegistry() // Create logic const src = new DragSource({text: 'Source', color: 'red'}) -const dst = new DropTarget({text: 'Target', color: 'orange', onDrop: (itemRaw: any) => { - const item = itemRaw as {color: string} - console.log(`Dropped: ${item.color}`) -}}) +const dst = new DropTarget<{color: string}>({ + text: 'Target', + color: 'orange', + onDrop: (item) => { + console.log(`Dropped: ${item.color}`) + }, +}) const Item = 'item' diff --git a/packages/react-dnd-multi-backend/examples/App.tsx b/packages/react-dnd-multi-backend/examples/App.tsx index e4d2051..03d729e 100644 --- a/packages/react-dnd-multi-backend/examples/App.tsx +++ b/packages/react-dnd-multi-backend/examples/App.tsx @@ -1,24 +1,30 @@ -import { CSSProperties, RefObject, StrictMode, useContext, useRef, useState } from 'react' -import { DndProvider as ReactDndProvider } from 'react-dnd' +import {type CSSProperties, type JSX, type RefObject, StrictMode, useContext, useRef, useState} from 'react' +import {DndProvider as ReactDndProvider} from 'react-dnd' -import { MultiBackend, DndProvider, PreviewContext, usePreview, Preview, PreviewState } from '../src' -import { HTML5toTouch } from 'rdndmb-html5-to-touch' +import {HTML5toTouch} from 'rdndmb-html5-to-touch' +import {DndProvider, MultiBackend, Preview, PreviewContext, type PreviewState, usePreview} from '../src' -import {Card} from './Card' import {Basket} from './Basket' -import {MultiCard} from './MultiCard' +import {Card} from './Card' import {MultiBasket} from './MultiBasket' -import {DragContent} from './common' - -const Block = ({row, text, item, style}: {row: number, text: string, item: DragContent, style: CSSProperties}): JSX.Element => { - return
Generated {text}
+import {MultiCard} from './MultiCard' +import type {DragContent} from './common' + +const Block = ({row, text, item, style}: {row: number; text: string; item: DragContent; style: CSSProperties}): JSX.Element => { + return ( +
+ Generated {text} +
+ ) } const ContextPreview = ({text}: {text: string}): JSX.Element => { @@ -41,13 +47,15 @@ const HookPreview = ({text}: {text: string}): JSX.Element | null => { const ComponentPreview = ({text}: {text: string}): JSX.Element => { return ( - ): JSX.Element => { - return - }} /> + ): JSX.Element => { + return + }} + /> ) } -const Content = ({title, fref}: {title: string, fref: RefObject}) => { +const Content = ({title, fref}: {title: string; fref: RefObject}) => { return ( <>

{title} API

@@ -95,7 +103,14 @@ export const App = (): JSX.Element => { return (
- {setAPI(e.target.checked)}} /> + { + setAPI(e.target.checked) + }} + />
{useNew ? newAPI : oldAPI} diff --git a/packages/react-dnd-multi-backend/examples/Basket.tsx b/packages/react-dnd-multi-backend/examples/Basket.tsx index 1ef5f36..0c46bf4 100644 --- a/packages/react-dnd-multi-backend/examples/Basket.tsx +++ b/packages/react-dnd-multi-backend/examples/Basket.tsx @@ -1,9 +1,9 @@ -import {CSSProperties, RefObject} from 'react' -import { useDrop } from 'react-dnd' -import {DragContent} from './common' +import type {CSSProperties, JSX, RefObject} from 'react' +import {useDrop} from 'react-dnd' +import {type DragContent, useFixRDnDRef} from './common' -export const Basket = ({logs}: {logs: RefObject}): JSX.Element => { - const [collectedProps, drop] = useDrop({ +export const Basket = ({logs}: {logs: RefObject}): JSX.Element => { + const [collectedProps, drop] = useDrop({ accept: 'card', drop: (item) => { const message = `Dropped: ${item.color}` @@ -22,7 +22,7 @@ export const Basket = ({logs}: {logs: RefObject}): JSX.Element => { const isOver = collectedProps.isOver const canDrop = collectedProps.canDrop const style: CSSProperties = { - backgroundColor: (isOver && canDrop) ? '#f3f3f3' : '#cccccc', + backgroundColor: isOver && canDrop ? '#f3f3f3' : '#cccccc', border: '1px dashed black', display: 'inline-block', width: '100px', @@ -30,5 +30,6 @@ export const Basket = ({logs}: {logs: RefObject}): JSX.Element => { margin: '10px', } - return
+ const dropRef = useFixRDnDRef(drop) + return
} diff --git a/packages/react-dnd-multi-backend/examples/Card.tsx b/packages/react-dnd-multi-backend/examples/Card.tsx index bde4795..0e53820 100644 --- a/packages/react-dnd-multi-backend/examples/Card.tsx +++ b/packages/react-dnd-multi-backend/examples/Card.tsx @@ -1,5 +1,6 @@ -import {CSSProperties} from 'react' +import type {CSSProperties, JSX} from 'react' import {useDrag} from 'react-dnd' +import {useFixRDnDRef} from './common' export const Card = (props: {color: string}): JSX.Element => { const [collectedProps, drag] = useDrag({ @@ -21,5 +22,6 @@ export const Card = (props: {color: string}): JSX.Element => { margin: '10px', } - return
+ const dragRef = useFixRDnDRef(drag) + return
} diff --git a/packages/react-dnd-multi-backend/examples/MultiBasket.tsx b/packages/react-dnd-multi-backend/examples/MultiBasket.tsx index 969b29b..bfc2485 100644 --- a/packages/react-dnd-multi-backend/examples/MultiBasket.tsx +++ b/packages/react-dnd-multi-backend/examples/MultiBasket.tsx @@ -1,9 +1,15 @@ -import {CSSProperties, RefObject} from 'react' +import type {CSSProperties, JSX, RefObject} from 'react' import {useMultiDrop} from '../src' -import {DragContent} from './common' +import {type DragContent, useFixRDnDRef} from './common' -export const MultiBasket = ({logs}: {logs: RefObject}): JSX.Element => { - const [_, {html5: [html5Props, html5Drop], touch: [touchProps, touchDrop]}] = useMultiDrop({ +export const MultiBasket = ({logs}: {logs: RefObject}): JSX.Element => { + const [ + _, + { + html5: [html5Props, html5Drop], + touch: [touchProps, touchDrop], + }, + ] = useMultiDrop({ accept: 'card', drop: (item) => { const message = `Dropped: ${item.color}` @@ -26,7 +32,7 @@ export const MultiBasket = ({logs}: {logs: RefObject}): JSX.Element => margin: '10px', } const html5DropStyle: CSSProperties = { - backgroundColor: (html5Props.isOver && html5Props.canDrop) ? '#f3f3f3' : '#bbbbbb', + backgroundColor: html5Props.isOver && html5Props.canDrop ? '#f3f3f3' : '#bbbbbb', display: 'inline-block', margin: '5px', width: '90px', @@ -35,7 +41,7 @@ export const MultiBasket = ({logs}: {logs: RefObject}): JSX.Element => userSelect: 'none', } const touchDropStyle: CSSProperties = { - backgroundColor: (touchProps.isOver && touchProps.canDrop) ? '#f3f3f3' : '#bbbbbb', + backgroundColor: touchProps.isOver && touchProps.canDrop ? '#f3f3f3' : '#bbbbbb', display: 'inline-block', margin: '5px', width: '90px', @@ -43,10 +49,16 @@ export const MultiBasket = ({logs}: {logs: RefObject}): JSX.Element => textAlign: 'center', userSelect: 'none', } + const html5DropRef = useFixRDnDRef(html5Drop) + const touchDropRef = useFixRDnDRef(touchDrop) return (
-
HTML5
-
Touch
+
+ HTML5 +
+
+ Touch +
) } diff --git a/packages/react-dnd-multi-backend/examples/MultiCard.tsx b/packages/react-dnd-multi-backend/examples/MultiCard.tsx index ad84a85..7d4f8f7 100644 --- a/packages/react-dnd-multi-backend/examples/MultiCard.tsx +++ b/packages/react-dnd-multi-backend/examples/MultiCard.tsx @@ -1,9 +1,15 @@ -import {CSSProperties} from 'react' +import type {CSSProperties, JSX} from 'react' import {useMultiDrag} from '../src' -import {DragContent} from './common' +import {type DragContent, useFixRDnDRef} from './common' export const MultiCard = (props: {color: string}): JSX.Element => { - const [_, {html5: [html5Props, html5Drag], touch: [touchProps, touchDrag]}] = useMultiDrag({ + const [ + _, + { + html5: [html5Props, html5Drag], + touch: [touchProps, touchDrag], + }, + ] = useMultiDrag({ type: 'card', item: {color: props.color}, collect: (monitor) => { @@ -37,10 +43,16 @@ export const MultiCard = (props: {color: string}): JSX.Element => { textAlign: 'center', userSelect: 'none', } + const html5DragRef = useFixRDnDRef(html5Drag) + const touchDragRef = useFixRDnDRef(touchDrag) return (
-
HTML5
-
Touch
+
+ HTML5 +
+
+ Touch +
) } diff --git a/packages/react-dnd-multi-backend/examples/common.ts b/packages/react-dnd-multi-backend/examples/common.ts index e79c081..890028d 100644 --- a/packages/react-dnd-multi-backend/examples/common.ts +++ b/packages/react-dnd-multi-backend/examples/common.ts @@ -1,3 +1,16 @@ +import {useCallback} from 'react' +import type {ConnectDragSource, ConnectDropTarget} from 'react-dnd' + export type DragContent = { color: string } + +// FIXME: issue with react-dnd when using React v19 +export const useFixRDnDRef = (ref: ConnectDropTarget | ConnectDragSource) => { + return useCallback( + (node: T | null) => { + ref(node) + }, + [ref], + ) +} diff --git a/packages/react-dnd-multi-backend/examples/index.tsx b/packages/react-dnd-multi-backend/examples/index.tsx index b394187..e0d50c6 100644 --- a/packages/react-dnd-multi-backend/examples/index.tsx +++ b/packages/react-dnd-multi-backend/examples/index.tsx @@ -1,5 +1,9 @@ import {createRoot} from 'react-dom/client' import {App} from './App' -const root = createRoot(document.getElementById('root')!) -root.render(,) +const rootElement = document.getElementById('root') +if (!rootElement) { + throw new Error('could not find root element') +} +const root = createRoot(rootElement) +root.render() diff --git a/packages/react-dnd-multi-backend/package.json b/packages/react-dnd-multi-backend/package.json index f0d389d..1c5fa3e 100644 --- a/packages/react-dnd-multi-backend/package.json +++ b/packages/react-dnd-multi-backend/package.json @@ -26,8 +26,8 @@ }, "peerDependencies": { "dnd-core": "^16.0.1", - "react": "^16.14.0 || ^17.0.2 || ^18.0.0", + "react": "^16.14.0 || ^17.0.2 || ^18.0.0 || ^19.0.0", "react-dnd": "^16.0.1", - "react-dom": "^16.14.0 || ^17.0.2 || ^18.0.0" + "react-dom": "^16.14.0 || ^17.0.2 || ^18.0.0 || ^19.0.0" } } diff --git a/packages/react-dnd-multi-backend/src/components/DndProvider.tsx b/packages/react-dnd-multi-backend/src/components/DndProvider.tsx index 78be4aa..003c6e4 100644 --- a/packages/react-dnd-multi-backend/src/components/DndProvider.tsx +++ b/packages/react-dnd-multi-backend/src/components/DndProvider.tsx @@ -1,5 +1,5 @@ import {MultiBackend, type MultiBackendOptions} from 'dnd-multi-backend' -import {type ReactNode, createContext, useState} from 'react' +import {type JSX, type ReactNode, createContext, useState} from 'react' import {DndProvider as ReactDndProvider} from 'react-dnd' export const PreviewPortalContext = createContext(null) diff --git a/packages/react-dnd-multi-backend/src/components/Preview.tsx b/packages/react-dnd-multi-backend/src/components/Preview.tsx index 5199c9d..e609783 100644 --- a/packages/react-dnd-multi-backend/src/components/Preview.tsx +++ b/packages/react-dnd-multi-backend/src/components/Preview.tsx @@ -1,4 +1,4 @@ -import {useContext} from 'react' +import {type JSX, useContext} from 'react' import {Preview as DnDPreview, Context as PreviewContext, type PreviewProps, type PreviewState} from 'react-dnd-preview' import {createPortal} from 'react-dom' diff --git a/packages/react-dnd-multi-backend/src/components/__tests__/Preview.test.tsx b/packages/react-dnd-multi-backend/src/components/__tests__/Preview.test.tsx index 807439e..ce34697 100644 --- a/packages/react-dnd-multi-backend/src/components/__tests__/Preview.test.tsx +++ b/packages/react-dnd-multi-backend/src/components/__tests__/Preview.test.tsx @@ -1,6 +1,6 @@ import {MockMultiBackend, MockPreviewList, type MockedMultiBackend, type MockedPreviewList} from '@mocks/mocks' import {act, render, screen} from '@testing-library/react' -import {useState} from 'react' +import {type JSX, useState} from 'react' import {DndContext, type DndContextType} from 'react-dnd' import type {PreviewGenerator} from 'react-dnd-preview' import {PreviewPortalContext} from '../DndProvider' diff --git a/packages/react-dnd-preview/examples/main/App.tsx b/packages/react-dnd-preview/examples/main/App.tsx index 491b89e..e013893 100644 --- a/packages/react-dnd-preview/examples/main/App.tsx +++ b/packages/react-dnd-preview/examples/main/App.tsx @@ -1,9 +1,9 @@ -import { DndProvider } from 'react-dnd' -import { Components } from './methods/Components' -import { Hooks } from './methods/Hooks' -import { TouchBackend } from 'react-dnd-touch-backend' -import { Draggable } from '../shared' -import { StrictMode } from 'react' +import {type JSX, StrictMode} from 'react' +import {DndProvider} from 'react-dnd' +import {TouchBackend} from 'react-dnd-touch-backend' +import {Draggable} from '../shared' +import {Components} from './methods/Components' +import {Hooks} from './methods/Hooks' export const App = (): JSX.Element => { return ( diff --git a/packages/react-dnd-preview/examples/main/index.tsx b/packages/react-dnd-preview/examples/main/index.tsx index b394187..e0d50c6 100644 --- a/packages/react-dnd-preview/examples/main/index.tsx +++ b/packages/react-dnd-preview/examples/main/index.tsx @@ -1,5 +1,9 @@ import {createRoot} from 'react-dom/client' import {App} from './App' -const root = createRoot(document.getElementById('root')!) -root.render(,) +const rootElement = document.getElementById('root') +if (!rootElement) { + throw new Error('could not find root element') +} +const root = createRoot(rootElement) +root.render() diff --git a/packages/react-dnd-preview/examples/main/methods/Components.tsx b/packages/react-dnd-preview/examples/main/methods/Components.tsx index 31531a6..fa24140 100644 --- a/packages/react-dnd-preview/examples/main/methods/Components.tsx +++ b/packages/react-dnd-preview/examples/main/methods/Components.tsx @@ -1,15 +1,15 @@ -import { Preview, Context, PreviewState } from '../../../src' -import {DragContent} from '../../shared' -import { WithPropFunction, WithChildFunction, WithChildComponent, WithChildFunctionContext, GenPreviewLiteProps } from './common' +import {Context, Preview, type PreviewState} from '../../../src' +import type {DragContent} from '../../shared' +import {type GenPreviewLiteProps, WithChildComponent, WithChildFunction, WithChildFunctionContext, WithPropFunction} from './common' + +import type {JSX} from 'react' export const Components = ({title, col}: GenPreviewLiteProps): JSX.Element => { return ( <> - - {WithChildFunction({title, col})} - + {WithChildFunction({title, col})} diff --git a/packages/react-dnd-preview/examples/main/methods/Hooks.tsx b/packages/react-dnd-preview/examples/main/methods/Hooks.tsx index 6602d23..5457881 100644 --- a/packages/react-dnd-preview/examples/main/methods/Hooks.tsx +++ b/packages/react-dnd-preview/examples/main/methods/Hooks.tsx @@ -1,6 +1,8 @@ -import { usePreview } from '../../../src' -import {DragContent} from '../../shared' -import { generatePreview, GenPreviewLiteProps, GenPreviewProps } from './common' +import {usePreview} from '../../../src' +import type {DragContent} from '../../shared' +import {type GenPreviewLiteProps, type GenPreviewProps, generatePreview} from './common' + +import type {JSX} from 'react' const WithHook = (props: GenPreviewProps): JSX.Element | null => { const preview = usePreview() diff --git a/packages/react-dnd-preview/examples/main/methods/common.tsx b/packages/react-dnd-preview/examples/main/methods/common.tsx index 0b2fe57..ad8d07d 100644 --- a/packages/react-dnd-preview/examples/main/methods/common.tsx +++ b/packages/react-dnd-preview/examples/main/methods/common.tsx @@ -1,24 +1,29 @@ -import { useContext } from 'react' -import { Context, PreviewState, usePreviewStateContent } from '../../../src' -import { Shape, DragContent } from '../../shared' +import {type JSX, useContext} from 'react' +import {Context, type PreviewState, type usePreviewStateContent} from '../../../src' +import {type DragContent, Shape} from '../../shared' export type PreviewProps = usePreviewStateContent export type GenPreviewProps = { - row: number, - col: number, - title: string, - method: string, + row: number + col: number + title: string + method: string } export const generatePreview = ({itemType, item, style, ref}: PreviewProps, {row, col, title, method}: GenPreviewProps): JSX.Element => { return ( - + {title}
Generated {itemType?.toString()} diff --git a/packages/react-dnd-preview/examples/offset/App.tsx b/packages/react-dnd-preview/examples/offset/App.tsx index ad87cbd..f569fec 100644 --- a/packages/react-dnd-preview/examples/offset/App.tsx +++ b/packages/react-dnd-preview/examples/offset/App.tsx @@ -1,16 +1,16 @@ -import {CSSProperties, StrictMode, useState} from 'react' +import {type CSSProperties, type JSX, type Ref, StrictMode, useState} from 'react' import {DndProvider} from 'react-dnd' import {TouchBackend} from 'react-dnd-touch-backend' -import {usePreview, Point} from '../../src' +import {type Point, usePreview} from '../../src' import type {PreviewPlacement} from '../../src/' -import {Draggable, Shape, DragContent} from '../shared' +import {type DragContent, Draggable, Shape} from '../shared' type Kinds = 'default' | 'ref' | 'custom_client' | 'custom_source_client' type PreviewProps = { - kind: Kinds, - text: string, - placement?: PreviewPlacement, + kind: Kinds + text: string + placement?: PreviewPlacement padding?: Point } @@ -21,13 +21,15 @@ export const Preview = ({kind, text, placement, padding}: PreviewProps): JSX.Ele } const {style, ref, monitor} = preview - let finalRef, finalStyle: CSSProperties = {...style, opacity: 0.5, whiteSpace: 'nowrap'} + let finalRef: Ref | undefined + let finalStyle: CSSProperties = {...style, opacity: 0.5, whiteSpace: 'nowrap'} if (kind === 'default') { // Keep as-is } else if (kind === 'ref') { finalRef = ref } else { - let x, y + let x: number + let y: number if (kind === 'custom_client') { x = monitor.getClientOffset()?.x ?? 0 y = monitor.getClientOffset()?.y ?? 0 @@ -45,7 +47,11 @@ export const Preview = ({kind, text, placement, padding}: PreviewProps): JSX.Ele } } - return {text} + return ( + + {text} + + ) } export const App = (): JSX.Element => { @@ -85,27 +91,31 @@ export const App = (): JSX.Element => {

- +

- +

- { - setDebug(e.target.checked) - }} id="debug_mode"/> + { + setDebug(e.target.checked) + }} + id="debug_mode" + /> -

- - - + + + {debug ? ( <> - - + + ) : null} diff --git a/packages/react-dnd-preview/examples/offset/index.tsx b/packages/react-dnd-preview/examples/offset/index.tsx index b394187..e0d50c6 100644 --- a/packages/react-dnd-preview/examples/offset/index.tsx +++ b/packages/react-dnd-preview/examples/offset/index.tsx @@ -1,5 +1,9 @@ import {createRoot} from 'react-dom/client' import {App} from './App' -const root = createRoot(document.getElementById('root')!) -root.render(,) +const rootElement = document.getElementById('root') +if (!rootElement) { + throw new Error('could not find root element') +} +const root = createRoot(rootElement) +root.render() diff --git a/packages/react-dnd-preview/examples/shared.tsx b/packages/react-dnd-preview/examples/shared.tsx index 0b28639..82fcd46 100644 --- a/packages/react-dnd-preview/examples/shared.tsx +++ b/packages/react-dnd-preview/examples/shared.tsx @@ -1,32 +1,34 @@ -import {CSSProperties, forwardRef, ReactNode} from 'react' +import {type CSSProperties, type JSX, type ReactNode, type Ref, useCallback} from 'react' import {useDrag} from 'react-dnd' export type DragContent = { - type: string, - color: string, + type: string + color: string } export type ShapeProps = { - style: CSSProperties, - size: number, - color: string, + style: CSSProperties + size: number + color: string children?: ReactNode + ref?: Ref } -export const Shape = forwardRef(({style, size, color, children}, ref) => { +export const Shape = ({style, size, color, children, ref}: ShapeProps) => { return ( -
+
{children}
) -}) - -Shape.displayName = 'Shape' +} export const Draggable = (): JSX.Element => { const [_, drag] = useDrag({ @@ -35,5 +37,12 @@ export const Draggable = (): JSX.Element => { color: '#eedd00', }, }) - return + // FIXME: issue with react-dnd when using React v19 + const refTrampoline = useCallback( + (node: HTMLDivElement | null) => { + drag(node) + }, + [drag], + ) + return } diff --git a/packages/react-dnd-preview/package.json b/packages/react-dnd-preview/package.json index 5ed052a..1252862 100644 --- a/packages/react-dnd-preview/package.json +++ b/packages/react-dnd-preview/package.json @@ -21,7 +21,7 @@ "types": "dist/index.d.ts", "module": "dist/index.js", "peerDependencies": { - "react": "^16.14.0 || ^17.0.2 || ^18.0.0", + "react": "^16.14.0 || ^17.0.2 || ^18.0.0 || ^19.0.0", "react-dnd": "^16.0.1" } } diff --git a/packages/react-dnd-preview/src/Preview.tsx b/packages/react-dnd-preview/src/Preview.tsx index 891c60b..fd34c80 100644 --- a/packages/react-dnd-preview/src/Preview.tsx +++ b/packages/react-dnd-preview/src/Preview.tsx @@ -1,4 +1,4 @@ -import type {ReactNode} from 'react' +import type {JSX, ReactNode} from 'react' import {Context, type PreviewState} from './Context' import type {Point, PreviewPlacement} from './offsets' import {usePreview} from './usePreview' diff --git a/packages/react-dnd-preview/src/offsets.ts b/packages/react-dnd-preview/src/offsets.ts index 9ed73a7..0a4b4f9 100644 --- a/packages/react-dnd-preview/src/offsets.ts +++ b/packages/react-dnd-preview/src/offsets.ts @@ -69,7 +69,7 @@ const calculateYOffset = (placement: PreviewPlacement, bb: DOMRect): number => { } } -export const calculatePointerPosition = (monitor: DragLayerMonitor, childRef: RefObject, placement: PreviewPlacement = 'center', padding: Point = {x: 0, y: 0}): Point | null => { +export const calculatePointerPosition = (monitor: DragLayerMonitor, childRef: RefObject, placement: PreviewPlacement = 'center', padding: Point = {x: 0, y: 0}): Point | null => { const offset = monitor.getClientOffset() if (offset === null) { return null