@etsoo/materialui
Version:
TypeScript Material-UI Implementation
152 lines (151 loc) • 5.99 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DnDSortableItemStyle = void 0;
exports.DnDSortableList = DnDSortableList;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importDefault(require("react"));
const styles_1 = require("@mui/material/styles");
const sortable_1 = require("@dnd-kit/react/sortable");
const react_2 = require("@dnd-kit/react");
/**
* DnD sortable item default style
* @param index Item index
* @param isDragging Is dragging
* @param theme Theme
* @returns Style
*/
const DnDSortableItemStyle = (index, isDragging, theme) => ({
padding: theme.spacing(1),
transform: isDragging ? "scale(1.03)" : "none",
zIndex: isDragging ? 1 : "auto",
boxShadow: isDragging
? `-1px 0 8px 0 ${theme.palette.grey[400]}, 0px 8px 8px 0 ${theme.palette.grey[200]}`
: "none",
background: isDragging
? theme.palette.primary.light
: index % 2 === 0
? theme.palette.grey[100]
: theme.palette.grey[50]
});
exports.DnDSortableItemStyle = DnDSortableItemStyle;
function SortableItem(props) {
const theme = (0, styles_1.useTheme)();
const { id, data, index, itemRenderer, itemStyle = (index, isDragging) => (0, exports.DnDSortableItemStyle)(index, isDragging, theme) } = props;
const state = (0, sortable_1.useSortable)({ id, data, index });
const style = itemStyle(index, state.isDragging);
return itemRenderer(data, style, state);
}
/**
* DnD sortable list component
* @param props Props
* @returns Component
*/
function DnDSortableList(props) {
// Destruct
const Component = props.component || react_1.default.Fragment;
const { componentProps, idField, itemRenderer, itemStyle, labelField, mRef, onChange, onDragStart, onDragEnd } = props;
const idFn = typeof idField === "function"
? idField
: (item) => !idField
? Reflect.get(item, "id")
: item[idField];
const labelFn = react_1.default.useCallback(typeof labelField === "function"
? labelField
: (item) => item[labelField], [labelField]);
// States
const [items, setItems] = react_1.default.useState([]);
react_1.default.useEffect(() => {
setItems(props.items);
}, [props.items]);
const changeItems = react_1.default.useCallback((newItems) => {
// Possible to alter items with the handler
onChange?.(newItems);
// Update state
setItems(newItems);
}, [onChange]);
// Methods
react_1.default.useImperativeHandle(mRef, () => {
return {
addItem(newItem) {
// Existence check
if (items.some((item) => labelFn(item) === labelFn(newItem))) {
return false;
}
// Clone
const newItems = [newItem, ...items];
// Update the state
changeItems(newItems);
return true;
},
addItems(inputItems) {
// Clone
const newItems = [...items];
// Insert items
inputItems.forEach((newItem) => {
// Existence check
if (newItems.some((item) => labelFn(item) === labelFn(newItem))) {
return;
}
newItems.push(newItem);
});
// Update the state
changeItems(newItems);
return newItems.length - items.length;
},
editItem(newItem, index) {
// Existence check
const newIndex = items.findIndex((item) => labelFn(item) === labelFn(newItem));
if (newIndex >= 0 && newIndex !== index) {
// Label field is the same with a different item
return false;
}
// Clone
const newItems = [...items];
// Remove the item
newItems.splice(index, 1, newItem);
// Update the state
changeItems(newItems);
return true;
},
deleteItem(index) {
// Clone
const newItems = [...items];
// Remove the item
newItems.splice(index, 1);
// Update the state
changeItems(newItems);
},
getItems() {
return items;
}
};
}, [items, labelFn, changeItems]);
function handleDragEnd(...args) {
// Event
const event = args[0];
// Cancelled
if (event.canceled)
return;
if ((0, sortable_1.isSortableOperation)(event.operation) && event.operation.source) {
const { initialIndex, index } = event.operation.source;
if (initialIndex === index)
return;
// Clone
const newItems = [...items];
// Removed item
const [removed] = newItems.splice(initialIndex, 1);
// Insert to the destination index
newItems.splice(index, 0, removed);
changeItems(newItems);
// Drag end handler
onDragEnd?.(newItems, ...args);
}
}
return ((0, jsx_runtime_1.jsx)(react_2.DragDropProvider, { onDragStart: (event) => onDragStart?.(items, event), onDragEnd: (event, manager) => handleDragEnd(event, manager), children: (0, jsx_runtime_1.jsx)(Component, { ...componentProps, children: items.map((item, index) => {
const id = idFn(item);
return ((0, jsx_runtime_1.jsx)(SortableItem, { id: id, index: index, data: item, itemRenderer: itemRenderer, itemStyle: itemStyle }, id));
}) }) }));
}