diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx index 64d6b626589..334cbd8a2b8 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx @@ -1,6 +1,7 @@ -import { Link, Menu, Plus, Settings, X } from 'lucide-react' +import { useSortable } from '@dnd-kit/sortable' +import { CSS } from '@dnd-kit/utilities' +import { GripVertical, Link, Plus, Settings, X } from 'lucide-react' import { useState } from 'react' -import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd' import { Badge, Button, @@ -56,7 +57,6 @@ interface ColumnProps { isNewRecord: boolean hasForeignKeys: boolean hasImportContent: boolean - dragHandleProps?: DraggableProvidedDragHandleProps | null onUpdateColumn: (changes: Partial) => void onRemoveColumn: () => void onEditForeignKey: (relation?: ForeignKey) => void @@ -69,7 +69,6 @@ export const Column = ({ isNewRecord = false, hasForeignKeys = false, hasImportContent = false, - dragHandleProps, onUpdateColumn, onRemoveColumn, onEditForeignKey, @@ -108,12 +107,28 @@ export const Column = ({ .map((r) => getRelationStatus(r)) .some((x) => x !== undefined) + const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition } = + useSortable({ + id: column.id, + }) + + const style = { + transform: CSS.Transform.toString(transform), + transition, + } + return ( -
+
-
- -
+
diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx index 77c3b277567..785255b4688 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx @@ -1,15 +1,22 @@ +import { + closestCenter, + DndContext, + DragEndEvent, + KeyboardSensor, + PointerSensor, + useSensor, + useSensors, +} from '@dnd-kit/core' +import { + arrayMove, + SortableContext, + sortableKeyboardCoordinates, + verticalListSortingStrategy, +} from '@dnd-kit/sortable' import { useParams } from 'common' import { isEmpty, noop, partition } from 'lodash' import { Edit, ExternalLink, HelpCircle, Key, Trash } from 'lucide-react' import { useState } from 'react' -import { - DragDropContext, - Draggable, - Droppable, - type DraggableProvided, - type DroppableProvided, - type DropResult, -} from 'react-beautiful-dnd' import { Alert_Shadcn_, AlertDescription_Shadcn_, @@ -115,29 +122,38 @@ export const ColumnManagement = ({ onColumnsUpdated(updatedColumns) } - const onSortColumns = (result: DropResult, type: 'pks' | 'others') => { + const onSortColumns = (result: DragEndEvent, type: 'pks' | 'others') => { // Dropped outside of the list - if (!result.destination) { + if (result.over == null) { return } if (type === 'pks') { - const updatedPrimaryKeyColumns = primaryKeyColumns.slice() - const [removed] = updatedPrimaryKeyColumns.splice(result.source.index, 1) - updatedPrimaryKeyColumns.splice(result.destination.index, 0, removed) + const activeIndex = primaryKeyColumns.findIndex((item) => item.id === result.active.id) + const overIndex = primaryKeyColumns.findIndex((item) => item.id === result.over!.id) + if (activeIndex === -1 || overIndex === -1) return + const updatedPrimaryKeyColumns = arrayMove(primaryKeyColumns, activeIndex, overIndex) const updatedColumns = updatedPrimaryKeyColumns.concat(otherColumns) return onColumnsUpdated(updatedColumns) } if (type === 'others') { - const updatedOtherColumns = otherColumns.slice() - const [removed] = updatedOtherColumns.splice(result.source.index, 1) - updatedOtherColumns.splice(result.destination.index, 0, removed) + const activeIndex = otherColumns.findIndex((item) => item.id === result.active.id) + const overIndex = otherColumns.findIndex((item) => item.id === result.over!.id) + if (activeIndex === -1 || overIndex === -1) return + const updatedOtherColumns = arrayMove(otherColumns, activeIndex, overIndex) const updatedColumns = primaryKeyColumns.concat(updatedOtherColumns) return onColumnsUpdated(updatedColumns) } } + const sensors = useSensors( + useSensor(PointerSensor), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + }) + ) + return ( <>
@@ -259,89 +275,71 @@ export const ColumnManagement = ({
{primaryKeyColumns.length > 0 && ( - onSortColumns(result, 'pks')}> - - {(droppableProvided: DroppableProvided) => ( -
- {primaryKeyColumns.map((column: ColumnField, index: number) => ( - - {(draggableProvided: DraggableProvided) => ( -
- { - return relation.columns.some((x) => x.source === column.name) - })} - enumTypes={enumTypes} - hasForeignKeys={checkIfHaveForeignKeys(column)} - isNewRecord={isNewRecord} - hasImportContent={hasImportContent} - dragHandleProps={draggableProvided.dragHandleProps} - onUpdateColumn={(changes) => onUpdateColumn(column, changes)} - onRemoveColumn={() => onRemoveColumn(column)} - onEditForeignKey={(fk) => { - setOpen(true) - setSelectedColumn(column) - if (fk) setSelectedFk(fk) - }} - /> -
- )} -
- ))} - {droppableProvided.placeholder} -
- )} -
-
- )} - - onSortColumns(result, 'others')}> - - {(droppableProvided: DroppableProvided) => ( + onSortColumns(result, 'pks')} + > +
- {otherColumns.map((column: ColumnField, index: number) => ( - - {(draggableProvided: DraggableProvided) => ( -
- { - return relation.columns.some((x) => x.source === column.name) - })} - enumTypes={enumTypes} - isNewRecord={isNewRecord} - hasForeignKeys={checkIfHaveForeignKeys(column)} - hasImportContent={hasImportContent} - dragHandleProps={draggableProvided.dragHandleProps} - onUpdateColumn={(changes) => onUpdateColumn(column, changes)} - onRemoveColumn={() => onRemoveColumn(column)} - onEditForeignKey={(fk) => { - setOpen(true) - setSelectedColumn(column) - if (fk) setSelectedFk(fk) - }} - /> -
- )} -
+ {primaryKeyColumns.map((column: ColumnField, index: number) => ( + { + return relation.columns.some((x) => x.source === column.name) + })} + enumTypes={enumTypes} + hasForeignKeys={checkIfHaveForeignKeys(column)} + isNewRecord={isNewRecord} + hasImportContent={hasImportContent} + onUpdateColumn={(changes) => onUpdateColumn(column, changes)} + onRemoveColumn={() => onRemoveColumn(column)} + onEditForeignKey={(fk) => { + setOpen(true) + setSelectedColumn(column) + if (fk) setSelectedFk(fk) + }} + /> ))} - {droppableProvided.placeholder}
- )} -
-
+ + + )} + onSortColumns(result, 'others')} + > + +
+ {otherColumns.map((column: ColumnField, index: number) => ( + { + return relation.columns.some((x) => x.source === column.name) + })} + enumTypes={enumTypes} + isNewRecord={isNewRecord} + hasForeignKeys={checkIfHaveForeignKeys(column)} + hasImportContent={hasImportContent} + onUpdateColumn={(changes) => onUpdateColumn(column, changes)} + onRemoveColumn={() => onRemoveColumn(column)} + onEditForeignKey={(fk) => { + setOpen(true) + setSelectedColumn(column) + if (fk) setSelectedFk(fk) + }} + /> + ))} +
+
+
{!hasImportContent && ( diff --git a/apps/studio/package.json b/apps/studio/package.json index 1b90622e2b6..15facdcbfbd 100644 --- a/apps/studio/package.json +++ b/apps/studio/package.json @@ -115,7 +115,6 @@ "pg-minify": "^1.6.3", "randombytes": "^2.1.0", "react": "catalog:", - "react-beautiful-dnd": "^13.1.0", "react-data-grid": "7.0.0-beta.47", "react-day-picker": "^9.11.1", "react-dnd": "^16.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 38f2cfbdd33..4f88430ce9b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1096,9 +1096,6 @@ importers: react: specifier: 'catalog:' version: 18.3.1 - react-beautiful-dnd: - specifier: ^13.1.0 - version: 13.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-data-grid: specifier: 7.0.0-beta.47 version: 7.0.0-beta.47(patch_hash=803f02d6cede565990ab9675326b93195b98bcc6477a4811715405892c257488)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -9413,9 +9410,6 @@ packages: '@types/react-grid-layout@1.3.3': resolution: {integrity: sha512-VLgUoEN0PaAL3GeRsmYbHuoN0tpDNoRhlkdzHK4Ll8shHW6e16YpNCZWb7P9vrlZdzFtY75cM/hPr8p0ukZQCw==} - '@types/react-redux@7.1.27': - resolution: {integrity: sha512-xj7d9z32p1K/eBmO+OEy+qfaWXtcPlN8f1Xk3Ne0p/ZRQ867RI5bQ/bpBtxbqU1AHNhKJSgGvld/P2myU2uYkg==} - '@types/react-simple-maps@3.0.4': resolution: {integrity: sha512-U9qnX0wVhxldrTpsase44fIoLpyO1OT/hgNMRoJTixj1qjpMRdSRIfih93mR3D/Tss/8CmM7dPwKMjtaGkDpmw==} @@ -11000,9 +10994,6 @@ packages: css-background-parser@0.1.0: resolution: {integrity: sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==} - css-box-model@1.2.1: - resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==} - css-box-shadow@1.0.0-3: resolution: {integrity: sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==} @@ -16178,9 +16169,6 @@ packages: radix3@1.1.2: resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} - raf-schd@4.0.3: - resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==} - railroad-diagrams@1.0.0: resolution: {integrity: sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==} @@ -16231,13 +16219,6 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-beautiful-dnd@13.1.1: - resolution: {integrity: sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==} - deprecated: 'react-beautiful-dnd is now deprecated. Context and options: https://github.com/atlassian/react-beautiful-dnd/issues/2672' - peerDependencies: - react: ^16.8.5 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.5 || ^17.0.0 || ^18.0.0 - react-compiler-runtime@19.1.0-rc.1: resolution: {integrity: sha512-wCt6g+cRh8g32QT18/9blfQHywGjYu+4FlEc3CW1mx3pPxYzZZl1y+VtqxRgnKKBCFLIGUYxog4j4rs5YS86hw==} peerDependencies: @@ -16386,18 +16367,6 @@ packages: react: ^16.8.0 || ^17 || ^18 react-dom: ^16.8.0 || ^17 || ^18 - react-redux@7.2.9: - resolution: {integrity: sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==} - peerDependencies: - react: ^16.8.3 || ^17 || ^18 - react-dom: '*' - react-native: '*' - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} @@ -18415,11 +18384,6 @@ packages: peerDependencies: react: '>=16.8.0' - use-memo-one@1.1.3: - resolution: {integrity: sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - use-sidecar@1.1.3: resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} engines: {node: '>=10'} @@ -27235,13 +27199,6 @@ snapshots: dependencies: '@types/react': 18.3.3 - '@types/react-redux@7.1.27': - dependencies: - '@types/hoist-non-react-statics': 3.3.2 - '@types/react': 18.3.3 - hoist-non-react-statics: 3.3.2 - redux: 4.2.1 - '@types/react-simple-maps@3.0.4': dependencies: '@types/d3-geo': 2.0.7 @@ -29176,10 +29133,6 @@ snapshots: css-background-parser@0.1.0: {} - css-box-model@1.2.1: - dependencies: - tiny-invariant: 1.3.3 - css-box-shadow@1.0.0-3: {} css-color-keywords@1.0.0: {} @@ -35473,8 +35426,6 @@ snapshots: radix3@1.1.2: {} - raf-schd@4.0.3: {} - railroad-diagrams@1.0.0: {} randexp@0.4.6: @@ -35536,20 +35487,6 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-beautiful-dnd@13.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.26.10 - css-box-model: 1.2.1 - memoize-one: 5.2.1 - raf-schd: 4.0.3 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-redux: 7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - redux: 4.2.1 - use-memo-one: 1.1.3(react@18.3.1) - transitivePeerDependencies: - - react-native - react-compiler-runtime@19.1.0-rc.1(react@18.3.1): dependencies: react: 18.3.1 @@ -35735,18 +35672,6 @@ snapshots: react-fast-compare: 3.2.2 warning: 4.0.3 - react-redux@7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.26.10 - '@types/react-redux': 7.1.27 - hoist-non-react-statics: 3.3.2 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 18.3.1 - react-is: 17.0.2 - optionalDependencies: - react-dom: 18.3.1(react@18.3.1) - react-refresh@0.14.2: {} react-remove-scroll-bar@2.3.8(@types/react@18.3.3)(react@18.3.1): @@ -38214,10 +38139,6 @@ snapshots: dependencies: react: 18.3.1 - use-memo-one@1.1.3(react@18.3.1): - dependencies: - react: 18.3.1 - use-sidecar@1.1.3(@types/react@18.3.3)(react@18.3.1): dependencies: detect-node-es: 1.1.0