From 5df1fe86a6866f2eb6ec4fcc5b4ad2c0c3b7e201 Mon Sep 17 00:00:00 2001 From: Leonhard Melzer Date: Tue, 17 Dec 2024 14:50:28 +0100 Subject: [PATCH 1/4] chore: ignore e2e screenshots in git --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4a03db7..1970e09 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ __diff_output__ /playwright-report/ /blob-report/ /playwright/.cache/ +/e2e/**/*.png \ No newline at end of file From 01338585f31919b53df62433b3dd66bb2cf50ade Mon Sep 17 00:00:00 2001 From: Leonhard Melzer Date: Tue, 17 Dec 2024 14:51:06 +0100 Subject: [PATCH 2/4] fix: use DOMRect instead of deprecated ClientRect --- README.md | 2 +- src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 548c1bb..1794334 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ An array of values. The value can be a string or any more complex object. The le ### onChange ```ts -onChange: (meta: { oldIndex: number; newIndex: number, targetRect: ClientRect }) => void +onChange: (meta: { oldIndex: number; newIndex: number, targetRect: DOMRect }) => void ``` Called when the item is dropped to a new location: diff --git a/src/types.ts b/src/types.ts index e3155f0..c963377 100644 --- a/src/types.ts +++ b/src/types.ts @@ -42,7 +42,7 @@ export interface BeforeDragParams { export interface OnChangeMeta { oldIndex: number; newIndex: number; - targetRect: ClientRect; + targetRect: DOMRect; } export interface IProps { From a8688c99fcdd860a336f1f32eb6fd0eb1a03cf60 Mon Sep 17 00:00:00 2001 From: Leonhard Melzer Date: Tue, 17 Dec 2024 14:51:28 +0100 Subject: [PATCH 3/4] feat: implement afterDrag --- README.md | 8 ++++++++ examples/TableAuto.tsx | 3 +++ src/List.tsx | 22 ++++++++++++++++------ src/index.ts | 2 ++ src/types.ts | 7 +++++++ 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1794334..848fb11 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,14 @@ beforeDrag?: (params: { elements: Element[]; index: number }) => void; Called when a valid drag is initiated. It provides a direct access to all list DOM elements and the index of dragged item. This can be useful when you need to do some upfront measurements like when building a [table with variable column widths](https://react-movable.netlify.app/?story=list--table-auto-cell-widths). +### afterDrag + +```ts +afterDrag?: (params: { elements: Element[]; oldIndex: number; newIndex: number }) => void; +``` + +Called when a drag is completed. It provides a direct access to all list DOM elements, the old as well as the new index of the dragged item. This can be useful when you need to perform some cleanup, e.g. in conjunction with `beforeDrag`. Please note this is different to `onChange`, which will _only_ fire when the drag results in a changed order. + ### removableByMove ```ts diff --git a/examples/TableAuto.tsx b/examples/TableAuto.tsx index f888394..344584e 100644 --- a/examples/TableAuto.tsx +++ b/examples/TableAuto.tsx @@ -59,6 +59,9 @@ const TableAuto: React.FC = () => { ); setWidths(widths); }} + afterDrag={() => { + setWidths([]); + }} values={items} onChange={({ oldIndex, newIndex }) => setItems(arrayMove(items, oldIndex, newIndex)) diff --git a/src/List.tsx b/src/List.tsx index e509a30..8d37320 100644 --- a/src/List.tsx +++ b/src/List.tsx @@ -477,16 +477,26 @@ class List extends React.Component> { finishDrop = () => { const removeItem = this.props.removableByMove && this.isDraggedItemOutOfBounds(); - if ( - removeItem || - (this.afterIndex > -2 && this.state.itemDragged !== this.afterIndex) - ) { + const oldIndex = this.state.itemDragged; + const hasChanged = this.afterIndex > -2 && oldIndex !== this.afterIndex; + const newIndex = hasChanged + ? removeItem + ? -1 + : Math.max(this.afterIndex, 0) + : oldIndex; + if (removeItem || hasChanged) { this.props.onChange({ - oldIndex: this.state.itemDragged, - newIndex: removeItem ? -1 : Math.max(this.afterIndex, 0), + oldIndex, + newIndex, targetRect: this.ghostRef.current!.getBoundingClientRect(), }); } + this.props.afterDrag && + this.props.afterDrag({ + elements: this.getChildren(), + oldIndex, + newIndex, + }); this.getChildren().forEach((item) => { setItemTransition(item, 0); transformItem(item, null); diff --git a/src/index.ts b/src/index.ts index f9db2b7..940cbb2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import type { RenderItemParams, RenderListParams, BeforeDragParams, + AfterDragParams, OnChangeMeta, IProps, TEvent, @@ -16,6 +17,7 @@ export type { RenderItemParams, RenderListParams, BeforeDragParams, + AfterDragParams, OnChangeMeta, IProps, TEvent, diff --git a/src/types.ts b/src/types.ts index c963377..12caca6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -39,6 +39,12 @@ export interface BeforeDragParams { index: number; } +export interface AfterDragParams { + elements: Element[]; + oldIndex: number; + newIndex: number; +} + export interface OnChangeMeta { oldIndex: number; newIndex: number; @@ -48,6 +54,7 @@ export interface OnChangeMeta { export interface IProps { disabled?: boolean; beforeDrag?: (params: BeforeDragParams) => void; + afterDrag?: (params: AfterDragParams) => void; renderItem: (params: RenderItemParams) => React.ReactNode; renderList: (props: RenderListParams) => React.ReactNode; values: Value[]; From 15d8290ad79b45ce53bda4fb49c729a9ed7d88e4 Mon Sep 17 00:00:00 2001 From: Leonhard Melzer Date: Tue, 17 Dec 2024 14:58:15 +0100 Subject: [PATCH 4/4] chore: add changeset --- .changeset/three-plants-bow.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/three-plants-bow.md diff --git a/.changeset/three-plants-bow.md b/.changeset/three-plants-bow.md new file mode 100644 index 0000000..b4828b8 --- /dev/null +++ b/.changeset/three-plants-bow.md @@ -0,0 +1,5 @@ +--- +"react-movable": minor +--- + +feat: implement afterDrag