UNPKG

@keycloakify/keycloak-admin-ui

Version:
134 lines 6.04 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import styles from "@patternfly/react-styles/css/components/DataList/data-list"; import { ActionsColumn, Table, Tbody, Td, Th, Thead, Tr, } from "@patternfly/react-table"; import { get } from "lodash-es"; import { useMemo, useRef, useState, } from "react"; import { useTranslation } from "react-i18next"; export function DraggableTable({ keyField, columns, data, actions, onDragFinish, ...props }) { const { t } = useTranslation(); const bodyRef = useRef(null); const [state, setState] = useState({ draggedItemId: "", draggingToItemIndex: -1, dragging: false, tempItemOrder: [""], }); const itemOrder = useMemo(() => data.map((d) => get(d, keyField)), [data]); const onDragStart = (evt) => { evt.dataTransfer.effectAllowed = "move"; evt.dataTransfer.setData("text/plain", evt.currentTarget.id); const draggedItemId = evt.currentTarget.id; evt.currentTarget.classList.add(styles.modifiers.ghostRow); evt.currentTarget.setAttribute("aria-grabbed", "true"); setState({ ...state, draggedItemId, dragging: true }); }; const moveItem = (arr, i1, toIndex) => { const fromIndex = arr.indexOf(i1); if (fromIndex === toIndex) { return arr; } const temp = arr.splice(fromIndex, 1); arr.splice(toIndex, 0, temp[0]); return arr; }; const move = (itemOrder) => { if (!bodyRef.current) return; const ulNode = bodyRef.current; const nodes = Array.from(ulNode.children); if (nodes.map((node) => node.id).every((id, i) => id === itemOrder[i])) { return; } while (ulNode.firstChild) { ulNode.removeChild(ulNode.lastChild); } itemOrder.forEach((id) => { ulNode.appendChild(nodes.find((n) => n.id === id)); }); }; const onDragCancel = () => { var _a; Array.from(((_a = bodyRef.current) === null || _a === void 0 ? void 0 : _a.children) || []).forEach((el) => { el.classList.remove(styles.modifiers.ghostRow); el.setAttribute("aria-grabbed", "false"); }); setState({ ...state, draggedItemId: "", draggingToItemIndex: -1, dragging: false, }); }; const onDragLeave = (evt) => { if (!isValidDrop(evt)) { move(itemOrder); setState({ ...state, draggingToItemIndex: -1 }); } }; const isValidDrop = (evt) => { const ulRect = bodyRef.current.getBoundingClientRect(); return (evt.clientX > ulRect.x && evt.clientX < ulRect.x + ulRect.width && evt.clientY > ulRect.y && evt.clientY < ulRect.y + ulRect.height); }; const onDrop = (evt) => { if (isValidDrop(evt)) { onDragFinish(state.draggedItemId, state.tempItemOrder); } else { onDragCancel(); } }; const onDragOver = (evt) => { var _a; evt.preventDefault(); const td = evt.target; const curListItem = td.closest("tr"); if (!curListItem || (bodyRef.current && !bodyRef.current.contains(curListItem)) || curListItem.id === state.draggedItemId) { return null; } else { const dragId = curListItem.id; const draggingToItemIndex = Array.from(((_a = bodyRef.current) === null || _a === void 0 ? void 0 : _a.children) || []).findIndex((item) => item.id === dragId); if (draggingToItemIndex !== state.draggingToItemIndex) { const tempItemOrder = moveItem(itemOrder, state.draggedItemId, draggingToItemIndex); move(tempItemOrder); setState({ ...state, draggingToItemIndex, tempItemOrder, }); } } }; const onDragEnd = (evt) => { const tr = evt.target; tr.classList.remove(styles.modifiers.ghostRow); tr.setAttribute("aria-grabbed", "false"); setState({ ...state, draggedItemId: "", draggingToItemIndex: -1, dragging: false, }); }; const thInfo = (column) => { if (!column.thTooltipText) return undefined; return { popover: _jsx("div", { children: t(column.thTooltipText) }), ariaLabel: t(column.thTooltipText), }; }; return (_jsxs(Table, { "aria-label": "Draggable table", className: state.dragging ? styles.modifiers.dragOver : "", ...props, children: [_jsx(Thead, { children: _jsxs(Tr, { children: [_jsx(Th, { "aria-hidden": "true" }), columns.map((column) => (_jsx(Th, { info: thInfo(column), width: column.width, modifier: "fitContent", children: t(column.displayKey || column.name) }, column.name)))] }) }), _jsx(Tbody, { ref: bodyRef, onDragOver: onDragOver, onDrop: onDragOver, onDragLeave: onDragLeave, children: data.map((row) => (_jsxs(Tr, { id: get(row, keyField), draggable: true, onDrop: onDrop, onDragEnd: onDragEnd, onDragStart: onDragStart, children: [_jsx(Td, { draggableRow: { id: `draggable-row-${get(row, keyField)}`, } }), columns.map((column) => (_jsx(Td, { dataLabel: column.name, children: column.cellRenderer ? column.cellRenderer(row) : get(row, column.name) }, `${get(row, keyField)}_${column.name}`))), actions && (_jsx(Td, { isActionCell: true, children: _jsx(ActionsColumn, { items: actions.map(({ isActionable, ...action }) => isActionable ? { ...action, isDisabled: !isActionable(row) } : action), rowData: row }) }))] }, get(row, keyField)))) })] })); } //# sourceMappingURL=DraggableTable.js.map