From 5955de3145f355e511295c71e081833eb3f23994 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 17 Nov 2025 03:54:44 +0000 Subject: [PATCH 1/5] Initial plan From f1efe5b1d3361ab824203e81581cb5376ef6e470 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 17 Nov 2025 04:08:13 +0000 Subject: [PATCH 2/5] Implement Pragmatic Drag and Drop for matrix reordering Co-authored-by: bschlenk <1390303+bschlenk@users.noreply.github.com> --- package.json | 1 + pnpm-lock.yaml | 28 +++++++++++++++ src/app.tsx | 20 ++++------- src/components/matrix.module.css | 12 +++++++ src/components/matrix.tsx | 61 +++++++++++++++++++++++++++----- 5 files changed, 99 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 4ae6ac7..b5ba48d 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "@atlaskit/pragmatic-drag-and-drop": "^1.7.7", "@bschlenk/mat": "^0.0.11", "@bschlenk/util": "^0.0.2", "@bschlenk/vec": "^0.0.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea5de1d..20a7a06 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@atlaskit/pragmatic-drag-and-drop': + specifier: ^1.7.7 + version: 1.7.7 '@bschlenk/mat': specifier: ^0.0.11 version: 0.0.11 @@ -58,6 +61,9 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@atlaskit/pragmatic-drag-and-drop@1.7.7': + resolution: {integrity: sha512-jX+68AoSTqO/fhCyJDTZ38Ey6/wyL2Iq+J/moanma0YyktpnoHxevjY1UNJHYp0NCburdQDZSL1ZFac1mO1osQ==} + '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -125,6 +131,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/runtime@7.28.4': + resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} + engines: {node: '>=6.9.0'} + '@babel/template@7.25.9': resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} engines: {node: '>=6.9.0'} @@ -615,6 +625,9 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + bind-event-listener@3.0.0: + resolution: {integrity: sha512-PJvH288AWQhKs2v9zyfYdPzlPqf5bXbGMmhmUIY9x4dAUGIWgomO771oBQNwJnMQSnUIXhKu6sgzpBRXTlvb8Q==} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -1284,6 +1297,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + raf-schd@4.0.3: + resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==} + react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: @@ -1541,6 +1557,12 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 + '@atlaskit/pragmatic-drag-and-drop@1.7.7': + dependencies: + '@babel/runtime': 7.28.4 + bind-event-listener: 3.0.0 + raf-schd: 4.0.3 + '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 @@ -1628,6 +1650,8 @@ snapshots: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/runtime@7.28.4': {} + '@babel/template@7.25.9': dependencies: '@babel/code-frame': 7.26.2 @@ -2104,6 +2128,8 @@ snapshots: balanced-match@1.0.2: {} + bind-event-listener@3.0.0: {} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -2879,6 +2905,8 @@ snapshots: queue-microtask@1.2.3: {} + raf-schd@4.0.3: {} + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 diff --git a/src/app.tsx b/src/app.tsx index c096338..2812813 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef } from 'react' import * as mat from '@bschlenk/mat' import { Canvas } from './canvas' @@ -8,7 +8,6 @@ import { UseMatricesDispatch, WrappedMatrix, } from './hooks/use-matrices' -import { childIndex } from './lib/dom' import { setRef } from './lib/set-ref' import styles from './app.module.css' @@ -56,7 +55,9 @@ interface MatrixControlsProps { } function MatrixControls({ matrices, matrix, dispatch }: MatrixControlsProps) { - const [dragging, setDragging] = useState(null) + const handleReorder = (fromIndex: number, toIndex: number) => { + dispatch({ type: 'move', from: fromIndex, to: toIndex }) + } return (
@@ -64,6 +65,7 @@ function MatrixControls({ matrices, matrix, dispatch }: MatrixControlsProps) { {matrices.map(({ id, visible, value }, i) => ( { @@ -82,17 +84,7 @@ function MatrixControls({ matrices, matrix, dispatch }: MatrixControlsProps) { cloneMatrix={() => { dispatch({ type: 'insert', value, after: matrices[i] }) }} - onDragStart={(e) => { - setDragging(e.target as HTMLElement) - }} - onDragEnter={(e) => { - if (e.target !== e.currentTarget) return - - const from = childIndex(dragging!) - const to = childIndex(e.target as HTMLElement) - - dispatch({ type: 'move', from, to }) - }} + onReorder={handleReorder} /> ))}