Merge branch 'main' of https://github.com/openedx/frontend-lib-content-components into mashal-m/react-upgrade-to-v17
This commit is contained in:
73
src/editors/sharedComponents/DraggableList/DraggableList.jsx
Normal file
73
src/editors/sharedComponents/DraggableList/DraggableList.jsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
DndContext,
|
||||
closestCenter,
|
||||
KeyboardSensor,
|
||||
PointerSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
} from '@dnd-kit/core';
|
||||
import {
|
||||
arrayMove,
|
||||
SortableContext,
|
||||
sortableKeyboardCoordinates,
|
||||
verticalListSortingStrategy,
|
||||
} from '@dnd-kit/sortable';
|
||||
|
||||
const DraggableList = ({
|
||||
itemList,
|
||||
setState,
|
||||
updateOrder,
|
||||
children,
|
||||
}) => {
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
}),
|
||||
);
|
||||
|
||||
const handleDragEnd = (event) => {
|
||||
const { active, over } = event;
|
||||
if (active.id !== over.id) {
|
||||
let updatedArray;
|
||||
setState(() => {
|
||||
const [activeElement] = itemList.filter(item => item.id === active.id);
|
||||
const [overElement] = itemList.filter(item => item.id === over.id);
|
||||
const oldIndex = itemList.indexOf(activeElement);
|
||||
const newIndex = itemList.indexOf(overElement);
|
||||
updatedArray = arrayMove(itemList, oldIndex, newIndex);
|
||||
return updatedArray;
|
||||
});
|
||||
updateOrder()(updatedArray);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<SortableContext
|
||||
items={itemList}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
{children}
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
);
|
||||
};
|
||||
|
||||
DraggableList.propTypes = {
|
||||
itemList: PropTypes.arrayOf(PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
})).isRequired,
|
||||
setState: PropTypes.func.isRequired,
|
||||
updateOrder: PropTypes.func.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
export default DraggableList;
|
||||
63
src/editors/sharedComponents/DraggableList/SortableItem.jsx
Normal file
63
src/editors/sharedComponents/DraggableList/SortableItem.jsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { intlShape, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import { useSortable } from '@dnd-kit/sortable';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
import { Icon, IconButtonWithTooltip, Row } from '@edx/paragon';
|
||||
import { DragIndicator } from '@edx/paragon/icons';
|
||||
import messages from './messages';
|
||||
|
||||
const SortableItem = ({
|
||||
id,
|
||||
componentStyle,
|
||||
children,
|
||||
// injected
|
||||
intl,
|
||||
}) => {
|
||||
const {
|
||||
attributes,
|
||||
listeners,
|
||||
setNodeRef,
|
||||
transform,
|
||||
transition,
|
||||
} = useSortable({ id });
|
||||
|
||||
const style = {
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
...componentStyle,
|
||||
};
|
||||
|
||||
return (
|
||||
<Row
|
||||
ref={setNodeRef}
|
||||
style={style}
|
||||
className="mx-0"
|
||||
>
|
||||
{children}
|
||||
<IconButtonWithTooltip
|
||||
key="drag-to-reorder-icon"
|
||||
tooltipPlacement="top"
|
||||
tooltipContent={intl.formatMessage(messages.tooltipContent)}
|
||||
src={DragIndicator}
|
||||
iconAs={Icon}
|
||||
variant="secondary"
|
||||
alt={intl.formatMessage(messages.tooltipContent)}
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
/>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
SortableItem.defaultProps = {
|
||||
componentStyle: null,
|
||||
};
|
||||
SortableItem.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
componentStyle: PropTypes.shape({}),
|
||||
// injected
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(SortableItem);
|
||||
5
src/editors/sharedComponents/DraggableList/index.jsx
Normal file
5
src/editors/sharedComponents/DraggableList/index.jsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DraggableList from './DraggableList';
|
||||
import SortableItem from './SortableItem';
|
||||
|
||||
export { SortableItem };
|
||||
export default DraggableList;
|
||||
11
src/editors/sharedComponents/DraggableList/messages.js
Normal file
11
src/editors/sharedComponents/DraggableList/messages.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
tooltipContent: {
|
||||
id: 'authoring.draggableList.tooltip.content',
|
||||
defaultMessage: 'Drag to reorder',
|
||||
description: 'Tooltip content for drag indicator icon',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
Reference in New Issue
Block a user