Skip to content

Commit

Permalink
Refactor to use @dnd-kit as dnd library (#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
sneridagh authored Jun 9, 2023
1 parent b536b5d commit 3a0b1f3
Show file tree
Hide file tree
Showing 7 changed files with 334 additions and 183 deletions.
14 changes: 6 additions & 8 deletions acceptance/cypress/tests/blocks.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ context('Blocks Acceptance Tests', () => {
});
cy.findByText('2 columns').click();
cy.get(
'.teaserGrid.two [data-rbd-draggable-context-id]:first-child',
'.teaserGrid.two [aria-roledescription="sortable"]:first-child',
).click();
cy.get(
'#sidebar-properties .inline.field.text:first-of-type() .objectbrowser-field:first-of-type() .ui.button.action svg',
Expand All @@ -109,9 +109,7 @@ context('Blocks Acceptance Tests', () => {
'#sidebar-properties .inline.field.text:nth-of-type(5) .objectbrowser-field:first-of-type() .ui.button.action svg',
).click();
cy.findByText('My Image', { selector: 'span' }).click();
cy.get(
'.teaserGrid.two [data-rbd-draggable-context-id]:nth-child(2)',
).click();
cy.get('.teaserGrid.two .column:nth-child(2)').click();
cy.get(
'#sidebar-properties .inline.field.text:first-of-type() .objectbrowser-field:first-of-type() .ui.button.action svg',
).click();
Expand Down Expand Up @@ -142,20 +140,20 @@ context('Blocks Acceptance Tests', () => {
});
cy.findByText('2 columns').click();
cy.get(
'.imagesGrid.two [data-rbd-draggable-context-id]:first-child .toolbar-inner .buttons:first-child button',
'.imagesGrid.two [aria-roledescription="sortable"]:first-child .toolbar-inner .buttons:first-child button',
).click();
cy.findByLabelText('Select My Image').dblclick();
cy.get(
'.imagesGrid.two [data-rbd-draggable-context-id]:first-child',
'.imagesGrid.two [aria-roledescription="sortable"]:first-child',
).click();
cy.get('#field-alt').click().type('My Image');

cy.get(
'.imagesGrid.two [data-rbd-draggable-context-id]:last-child .toolbar-inner .buttons:first-child button',
'.imagesGrid.two [aria-roledescription="sortable"]:last-child .toolbar-inner .buttons:first-child button',
).click();
cy.findByLabelText('Select My Image').dblclick();
cy.get(
'.imagesGrid.two [data-rbd-draggable-context-id]:last-child',
'.imagesGrid.two [aria-roledescription="sortable"]:last-child',
).click();
cy.get('#field-alt').click().type('My Image');

Expand Down
11 changes: 11 additions & 0 deletions news/87.breaking
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Refactor to use `@dnd-kit` library for the internal drag and drop @sneridagh

## Breaking notes:

The Grid block edit component has been heavily refactored, we changed the drag and drop library that the block is using.
Instead of using `react-beautiful-dnd` library now it uses `@dnd-kit` library.
You should expect HTML structure and classe name changes inside this component due to this change.
Please make sure that you haven't customized anything relying in neither structure or class names (such as styling).
Also, we splitted the internal components below the edit component of the Grid block.
If you've customized any of them for some reason, your component should still work, but without the refactoring, it will be still using `react-beautiful-dnd` library.
If you want to update your customization, you'll need to update them appropiately following the changes made in the #87 PR.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@
]
}
},
"dependencies": {
"@dnd-kit/core": "6.0.8",
"@dnd-kit/sortable": "7.0.2"
},
"devDependencies": {
"@plone/scripts": "^2.3.0",
"release-it": "^15.6.0"
Expand Down
121 changes: 121 additions & 0 deletions src/components/Grid/Cells.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { Grid } from 'semantic-ui-react';
import {
DndContext,
closestCenter,
KeyboardSensor,
PointerSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
import {
SortableContext,
sortableKeyboardCoordinates,
horizontalListSortingStrategy,
} from '@dnd-kit/sortable';
import { SortableItem } from './SortableItem';
import { reorderArray } from '@plone/volto/helpers/Utils/Utils';

// Fix internal pointer sensors by adding a custom one that bails off given a exclusion list
// https://github.com/clauderic/dnd-kit/issues/477
class GridCellPointerSensor extends PointerSensor {
static activators = [
{
eventName: 'onPointerDown',
handler: ({ nativeEvent: event }) => {
if (
!event.isPrimary ||
event.button !== 0 ||
isInteractiveElement(event.target)
) {
return false;
}
// if (!isInteractiveElement(event.target)) {
// console.log(event.target);
// }
return true;
},
},
];
}

function isInteractiveElement(element) {
const interactiveElements = [
'button',
'input',
'textarea',
'select',
'option',
'svg',
'path',
];

if (interactiveElements.includes(element.tagName.toLowerCase())) {
return true;
}

return false;
}

const Cells = (props) => {
const { block, onChangeBlock, onChangeSelectedColumnItem, data } = props;

const columns = data.columns;

const sensors = useSensors(
useSensor(GridCellPointerSensor, {
// Require the mouse to move by 1 pixels before activating
activationConstraint: {
distance: 1,
},
}),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
}),
);

const onDragEnd = (event) => {
const { active, over } = event;

const indexActive = active.data.current.sortable.index;
const indexOver = over.data.current.sortable.index;

if (active.id !== over.id) {
onChangeBlock(block, {
...data,
columns: reorderArray(columns, indexActive, indexOver),
});

onChangeSelectedColumnItem(indexOver);
}
};

return (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={onDragEnd}
>
<SortableContext
items={columns?.map((item) => item.id) || []}
strategy={horizontalListSortingStrategy}
>
<Grid stackable stretched columns={columns ? columns.length : 0}>
{columns?.map((item, index) => {
item = { ...item, block: item.id };
return (
<SortableItem
{...props}
key={item.id}
id={item.id}
index={index}
item={item}
/>
);
})}
</Grid>
</SortableContext>
</DndContext>
);
};

export default Cells;
Loading

0 comments on commit 3a0b1f3

Please sign in to comment.