UNPKG

es-grid-template

Version:

es-grid-template

1,211 lines (1,151 loc) 45.7 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import React, { Fragment } from "react"; import TableBody from "./body/TableBody"; import TableHead from "./header/TableHead"; import { checkDecimalSeparator, checkThousandSeparator, detectSeparators, findItemByKey, flattenArray, flattenData, getAllRowKey, getColIdsBetween, getDefaultValue, getFormat, getRowIdsBetween, getSelectedCellMatrix, isEditable, isFormattedNumber, newGuid, sumSize, unFlattenData, updateArrayByKey, updateOrInsert } from "./hook/utils"; import { useVirtualizer } from "@tanstack/react-virtual"; import { useForm } from 'react-hook-form'; import { Button, Modal, Typography, Dropdown } from "antd"; import Pagination from "rc-master-ui/es/pagination"; import { removeNumericFormat } from "react-numeric-component"; import { TableContext } from "./useContext"; import { yupResolver } from "@hookform/resolvers/yup"; import { Toolbar } from "rc-master-ui"; import classNames from "classnames"; import { Maximize, Minimize } from "becoxy-icons"; import { ColumnsChoose } from "./ColumnsChoose"; const { Paragraph, Title } = Typography; const TableContainerEdit = props => { const { t, table, id, prefix, commandClick, editAble, rowKey, format, dataSource, originData, expandable, wrapSettings, recordDoubleClick, // triggerFilter, selectionSettings, setIsSelectionChange, onContextMenu, contextMenuItems, setSorterChange, setFilterChange, // tableHeight, onCellPaste, triggerPaste, validate, triggerChangeData, onCellChange, defaultValue, toolbarItems, mergedFilterKeys, setMergedFilterKeys, setExpanded, onBlur, fullScreen, pagination, showToolbar, actionTemplate, showColumnChoose, height } = props; const containerRef = React.useRef(null); const bottomToolbarRef = React.useRef(null); const topToolbarRef = React.useRef(null); const childrenColumnName = 'children'; // const visibleColumns = table.getVisibleLeafColumns() // //The virtualizers need to know the scrollable container element const tableContainerRef = React.useRef(null); const visibleColumns = table.getVisibleLeafColumns(); const fixedLeftColumns = table.getState().columnPinning.left ? visibleColumns.filter(vc => table.getState().columnPinning.left?.includes(vc.id)) : []; const fixedRightColumns = table.getState().columnPinning.right ? visibleColumns.filter(vc => table.getState().columnPinning.right?.includes(vc.id)) : []; //we are using a slightly different virtualization strategy for columns (compared to virtual rows) in order to support dynamic row heights const columnVirtualizer = useVirtualizer({ count: visibleColumns.length, estimateSize: index => visibleColumns[index].getSize(), //estimate width of each column for accurate scrollbar dragging getScrollElement: () => tableContainerRef.current, horizontal: true, // measureElement(element) { // return element?.getBoundingClientRect().width; // }, measureElement: typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') === -1 ? element => element?.getBoundingClientRect().height : undefined, overscan: 3 //how many columns to render on each side off screen each way (adjust this for performance) }); const columnSizingState = table.getState().columnSizing; const itemsAdd = React.useMemo(() => { return [{ key: '10', label: `10 ${t ? t('rows') : 'rows'}` }, { key: '50', label: `50 ${t ? t('rows') : 'rows'}` }, { key: '100', label: `100 ${t ? t('rows') : 'rows'}` }]; }, [t]); React.useEffect(() => { requestAnimationFrame(() => { columnVirtualizer.measure(); }); }, [columnSizingState, columnVirtualizer]); const virtualColumns = columnVirtualizer.getVirtualItems(); const cacheColumns = columnVirtualizer.measurementsCache; const rightCols = table.getState().columnPinning.right?.length ? [...cacheColumns].slice(-(table.getState().columnPinning.right?.length ?? 0)) : []; const leftCols = [...cacheColumns].slice(0, table.getState().columnPinning.left?.length ?? 0); const rightWidth = sumSize(rightCols); const leftWidth = sumSize(leftCols); //different virtualization strategy for columns - instead of absolute and translateY, we add empty columns to the left and right let virtualPaddingLeft; let virtualPaddingRight; const pdRight = columnVirtualizer.getTotalSize() - (virtualColumns[virtualColumns.length - 1]?.end ?? 0); if (columnVirtualizer && virtualColumns?.length) { virtualPaddingLeft = fixedLeftColumns && fixedLeftColumns.length > 0 ? (virtualColumns[0]?.start ?? 0) - leftWidth > 0 ? (virtualColumns[0]?.start ?? 0) - leftWidth : 0 : virtualColumns[0]?.start ?? 0; // virtualPaddingLeft = leftCols.length === rss.length ? (virtualColumns[0]?.start ?? 0) : 0; // columnVirtualizer.getTotalSize() - (virtualColumns[virtualColumns.length - 1]?.end ?? 0) - rightWidth > 0 ? columnVirtualizer.getTotalSize() - (virtualColumns[virtualColumns.length - 1]?.end ?? 0) - rightWidth : 0; virtualPaddingRight = fixedRightColumns && fixedRightColumns.length > 0 ? pdRight - rightWidth > 0 ? pdRight - rightWidth : 0 : pdRight; // virtualPaddingRight = columnVirtualizer.getTotalSize() - (virtualColumns[virtualColumns.length - 1]?.end ?? 0) } const [editingKey, setEditingKey] = React.useState(''); const [rangeState, setRangeState] = React.useState({ startRowIndex: undefined, endRowIndex: undefined, startColIndex: undefined, endColIndex: undefined, rowIds: [], colIds: [], colRange: [], rowRange: [] }); const [rangePasteState, setRangePasteState] = React.useState({ startRowIndex: undefined, endRowIndex: undefined, startColIndex: undefined, endColIndex: undefined, rowIds: [], colIds: [], colRange: [], rowRange: [] }); const [focusedCell, setFocusedCell] = React.useState(undefined); const [startCell, setStartCell] = React.useState(undefined); const [endCell, setEndCell] = React.useState(undefined); const [startPasteCell, setStartPasteCell] = React.useState(undefined); const [endPasteCell, setEndPasteCell] = React.useState(undefined); const [isSelecting, setIsSelecting] = React.useState(false); const [isPasting, setIsPasting] = React.useState(false); const [isFullScreen] = React.useState(false); const [tableHeight, settableHeight] = React.useState(0); const rowsFocus = React.useMemo(() => { return startCell && endCell ? getRowIdsBetween(table, startCell.rowId, endCell.rowId) : []; }, [endCell, startCell, table]); const copySelectionToClipboard = React.useCallback(() => { if (!startCell || !endCell) return; // const allRows = table.getRowModel().rows; const allRows = table.getRowModel().flatRows; // const allColumns = table.getAllLeafColumns(); const rowIds = getRowIdsBetween(table, startCell.rowId, endCell.rowId); const colIds = getColIdsBetween(table, startCell.colId, endCell.colId); const dataToCopy = []; rowIds.forEach(rowId => { const row = allRows.find(r => r.id === rowId); if (!row) return; const rowData = []; colIds.forEach(colId => { const cellll = row.getVisibleCells().find(c => c.column.id === colId); const value = cellll?.getValue(); rowData.push(value !== undefined ? String(value) : ''); }); dataToCopy.push(rowData); }); // Convert to TSV string const tsv = dataToCopy.map(row => row.join('\t')).join('\n'); // Copy to clipboard navigator.clipboard.writeText(tsv).then(() => {}); }, [startCell, endCell, table]); const handlePasted = React.useCallback(pasteData => { console.log('ooooooo'); if (!startCell) { return; } const rows = pasteData.slice(0, onCellPaste?.maxRowsPaste ?? 200); // const allRows = table.getRowModel().rows; const allRows = table.getRowModel().flatRows; const allCols = table.getVisibleLeafColumns(); const startRowIdx = allRows.findIndex(r => r.id === startCell.rowId); const startColIdx = allCols.findIndex(c => c.id === startCell.colId); // const record: any = allRows[startRowIdx].original const record = table.getRow(startCell.rowId).original; const row = table.getRow(startCell.rowId); if (!row.parentId) { // Cập nhật data mới const newData = flattenArray([...dataSource]); // Lấy vị trí bắt đầu // const startRow = newData.findIndex((it) => it[rowKey as any] === record[rowKey]) const startRow = startRowIdx; const startCol = startColIdx; const pastedRows = []; const pastedColumns = new Set(); rows.forEach((rowValues, rowIndex) => { const targetRow = startRow + rowIndex; // Nếu vượt quá số dòng hiện có, thêm dòng mới if (targetRow >= newData.length) { newData.push({ id: undefined, rowId: newGuid() }); } rowValues.forEach((cellValue, colIndex) => { const targetCol = startCol + colIndex; if (targetCol >= allCols.length) { // Không vượt quá số cột return; } const columnTarget = allCols[targetCol]; const columnOri = columnTarget.columnDef.meta ?? {}; const isEdit = typeof columnOri?.editEnable === 'function' ? columnOri.editEnable(newData[targetRow]) : columnOri.editEnable; if (isEdit) { const columnKey = allCols[targetCol].id; if (columnOri.type === 'number' && isFormattedNumber(cellValue.trim())) { const colFormat = typeof columnOri.format === 'function' ? columnOri.format(record) : columnOri.format; const valuePasteFormat = detectSeparators(cellValue.trim()); const cellFormat = getFormat(colFormat, format); const thousandSeparator = valuePasteFormat?.thousandSeparator ?? cellFormat?.thousandSeparator; const decimalSeparator = valuePasteFormat?.decimalSeparator ?? cellFormat?.decimalSeparator; const dec = cellFormat?.decimalScale; const numericFormatProps = { thousandSeparator: checkThousandSeparator(thousandSeparator, decimalSeparator), decimalSeparator: checkDecimalSeparator(thousandSeparator, decimalSeparator), allowNegative: cellFormat?.allowNegative ?? true, prefix: cellFormat?.prefix, suffix: cellFormat?.suffix, decimalScale: dec, fixedDecimalScale: cellFormat?.fixedDecimalScale ?? false }; const val = removeNumericFormat(cellValue.trim(), undefined, numericFormatProps); newData[targetRow] = { ...newData[targetRow], [columnKey]: Number(val) }; } else { newData[targetRow] = { ...newData[targetRow], [columnKey]: cellValue.trim() }; } pastedColumns.add(columnKey); } }); // Lưu dòng được paste pastedRows.push(newData[targetRow]); }); const pastedColumnsArray = Array.from(pastedColumns) ?? []; const rsFilterData = updateOrInsert(flattenArray([...originData]), newData); const rs = unFlattenData(rsFilterData); console.log('2'); triggerPaste?.(pastedRows, pastedColumnsArray, rs, []); } else { // const parent = findItemByKey(dataSource, rowKey as any, record.parentId) const parent = row.getParentRow()?.original; // Cập nhật childData mới const childData = parent?.children ? [...parent.children] : []; // Lấy vị trí bắt đầu // const { row: startRow, col: startCol } = selectedCell; const startRow = childData.findIndex(it => it[rowKey] === record[rowKey]); const startCol = startColIdx; const pastedRows = []; const pastedColumns = new Set(); rows.forEach((rowValues, rowIndex) => { const targetRow = startRow + rowIndex; // Nếu vượt quá số dòng hiện có, thêm dòng mới if (targetRow >= childData.length) { childData.push({ id: undefined, rowId: newGuid(), parentId: parent[rowKey ?? 'id'] }); } rowValues.forEach((cellValue, colIndex) => { const targetCol = startCol + colIndex; if (targetCol >= allCols.length) { // Không vượt quá số cột return; } const columnTarget = allCols[targetCol]; // const isEdit = typeof columnTarget.editEnable === 'function' ? columnTarget.editEnable(childData[targetRow]) : columnTarget.editEnable const columnOri = columnTarget.columnDef.meta ?? {}; const isEdit = typeof columnOri?.editEnable === 'function' ? columnOri.editEnable(childData[targetRow]) : columnOri.editEnable; if (isEdit) { const columnKey = allCols[targetCol].id; childData[targetRow] = { ...childData[targetRow], [columnKey]: cellValue.trim() }; pastedColumns.add(columnKey); } }); // Lưu dòng được paste pastedRows.push(childData[targetRow]); }); const pastedColumnsArray = Array.from(pastedColumns) ?? []; const newRowData = { ...parent, children: childData }; // item đã được filter const newDataSource = updateArrayByKey(originData, newRowData, rowKey); console.log('1'); triggerPaste?.(pastedRows, pastedColumnsArray, newDataSource, []); } }, [dataSource, format, onCellPaste?.maxRowsPaste, originData, rowKey, startCell, table, triggerPaste]); const handlePasteToTable = React.useCallback(pasteData => { if (!startCell) return; // const pastedRows = pasted.trim().split('\n').map(row => row.split('\t')); // Chuyển đổi dữ liệu từ clipboard thành mảng const rowsPasted = pasteData.split("\n").filter(row => row !== '').map(row => // const rows = pasteData.split("\n").map((row: any) => row.replace(/\r/g, "").split("\t")); if (rowsPasted.length > (onCellPaste?.maxRowsPaste ?? 200)) { // bật popup thông báo Modal.confirm({ content: /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Paragraph, { style: { marginBottom: '.25rem', fontSize: 14 } }, "D\u1EEF li\u1EC7u sao ch\xE9p v\u01B0\u1EE3t qu\xE1 s\u1ED1 d\xF2ng cho ph\xE9p (500 d\xF2ng).Ph\u1EA7n m\u1EC1n s\u1EBD ch\u1EC9 l\u1EA5y 500 d\xF2ng \u0111\u1EA7u ti\xEAn."), /*#__PURE__*/React.createElement(Title, { level: 5, style: { marginTop: '.75rem' } }, "B\u1EA1n c\xF3 mu\u1ED1n ti\u1EBFp t\u1EE5c sao ch\xE9p kh\xF4ng?")), centered: true, className: 'be-popup-container', onOk: () => { handlePasted(rowsPasted); } // footer: (_, { OkBtn, CancelBtn }) => ( // <> // <OkBtn /> // <CancelBtn /> // </> // ), }); } else { handlePasted(rowsPasted); } }, [handlePasted, onCellPaste?.maxRowsPaste, startCell]); React.useEffect(() => { // const handleKeyDown = (e: KeyboardEvent) => { // console.log('copySelectionToClipboard') // if (e.ctrlKey && e.key === 'c' && startCell && endCell) { // e.preventDefault(); // copySelectionToClipboard(); // } // }; // window.addEventListener('keydown', handleKeyDown); // return () => window.removeEventListener('keydown', handleKeyDown); }, [startCell, endCell, table, copySelectionToClipboard]); React.useEffect(() => { // console.log('handlePaste') // const handlePaste = (e: any) => { // if (startCell) { // e.preventDefault(); // Chặn hành vi mặc định // const clipboardText = e.clipboardData?.getData('text/plain') ?? ''; // handlePasteToTable(clipboardText); // } // }; // window.addEventListener('paste', handlePaste); // return () => window.removeEventListener('paste', handlePaste); }, [startCell, endCell, table, handlePasteToTable]); React.useEffect(() => { const handleClickOutside = event => { const element = event.target; const container = document.querySelector(".be-popup-container"); const containerContextMenu = document.querySelector(".popup-context-menu"); const tableBody = document.querySelector(`#${id} .ui-rc-grid-tbody`); const itemContainer = document.querySelector(`#${id} .ui-rc-toolbar-selection-overflow-item`); const itemHeader = document.querySelector(`#${id} .ui-rc-table-thead`); const isInsideContainer = element.closest(".be-popup-container") && container; const isInsideContainerContext = containerContextMenu && element.closest(".popup-context-menu"); const isInsideToolbar = element.closest(`.ui-rc-toolbar-selection-overflow-item`) && itemContainer; const isInsideHeader = itemHeader && itemHeader.contains(event.target); if (isInsideContainer || isInsideToolbar || isInsideHeader || isInsideContainerContext) { console.log('55555'); return; } if (containerRef.current && tableBody && !tableBody.contains(event.target)) { console.log('55555'); if (editingKey) { onBlur?.(dataSource); } setTimeout(() => { setEditingKey(''); // editingKey.current = '' }); setEndCell(undefined); setStartCell(undefined); setRangeState(undefined); } }; // document.addEventListener('click', handleClickOutside) document.addEventListener('mousedown', handleClickOutside); // document.addEventListener('touchstart', handleClickOutside) return () => { // document.removeEventListener('click', handleClickOutside) document.removeEventListener('mousedown', handleClickOutside); // document.removeEventListener('touchstart', handleClickOutside) }; }, [dataSource, editingKey, id, onBlur]); React.useEffect(() => { const totalHeight = height; if (totalHeight && topToolbarRef.current && bottomToolbarRef.current) { settableHeight(totalHeight - topToolbarRef.current.offsetHeight - bottomToolbarRef.current.offsetHeight); } }, [id, height]); const { control, handleSubmit, setValue, // trigger, getValues, // reset, formState: { errors } } = useForm({ mode: 'onChange', resolver: validate ? yupResolver(validate) : undefined }); const onSubmit = formData => { try { // const record = (await form.validateFields()) as RecordType; const row = { ...formData }; // const newData = [...dataSource] const newData = [...originData]; // @ts-ignore const index = flattenData(childrenColumnName, newData).findIndex(item => formData[rowKey] === item[rowKey]); const rs = updateArrayByKey(newData, row, rowKey); if (index > -1) { triggerChangeData?.(rs, 'onChange'); } } catch (errInfo) { console.log('Validate Failed:', errInfo); } }; const handleCellChange = args => { const { record, type: changeType, newState, prevState, option, field, indexCol, indexRow, key } = args; if (changeType === 'blur') { const handleChangeCallback = callbackData => { const callbackRecord = callbackData; Object.entries(callbackRecord).forEach(([name, value]) => { setValue(name, value); }); onSubmit(callbackRecord); }; if (onCellChange) { if (onCellChange.length > 1) { onCellChange({ field, indexCol, type: 'onChange', value: newState, option, indexRow, rowData: record, rowId: key, // rowsData: [...dataSource], rowsData: [...originData], sumValue: [] }, handleChangeCallback); } else { onCellChange({ field, indexCol, type: 'onChange', option, value: newState, indexRow, rowData: record, rowId: key, // rowsData: [...dataSource], rowsData: [...originData], sumValue: [] }, handleChangeCallback); onSubmit(record); } } } if (prevState && newState && prevState !== newState && changeType === 'enter') { onSubmit(record); } }; const handleAddMulti = React.useCallback((item, n, newId) => { if (item.onClick) { item.onClick({ toolbar: item }); } else { const defaultRowValue = getDefaultValue(defaultValue); const newRows = Array.from({ length: n }).map(() => defaultRowValue ? { ...defaultRowValue, id: undefined, rowId: n === 1 && newId ? newId : newGuid() } : { id: undefined, rowId: n === 1 && newId ? newId : newGuid() }); const kkk = getAllRowKey(newRows) ?? []; const rs = mergedFilterKeys ? [...mergedFilterKeys, ...kkk] : [...kkk]; setMergedFilterKeys?.(rs); const newData = dataSource.concat(newRows); triggerChangeData?.(newData, 'Add'); } }, [dataSource, defaultValue, mergedFilterKeys, setMergedFilterKeys, triggerChangeData]); const handleDuplicate = React.useCallback(() => { // không tính tree // Cập nhật data mới const newData = flattenArray([...dataSource]); // const duplicatedItems = rowsFocus.map(index => ({ ...newData[index], rowId: newGuid(), id: undefined, isDuplicate: true })) const duplicatedItem = table.getRowModel().flatRows.find(it => it.id === focusedCell?.rowId); setStartCell(focusedCell); setEndCell(focusedCell); setRangeState(getSelectedCellMatrix(table, focusedCell, focusedCell)); const duplicatedItems = [{ ...duplicatedItem?.original, rowId: newGuid(), id: undefined, isDuplicate: true }]; // Vị trí chèn là ngay sau phần tử lớn nhất trong rowsFocus // const insertAfter = Math.max(...rowsFocus) const insertAfter = newData.findIndex(it => it[rowKey] === focusedCell?.rowId); const rsFilter = [...newData.slice(0, insertAfter + 1), ...duplicatedItems, ...newData.slice(insertAfter + 1)]; // const rs = updateOrInsertInOrder(originData, rsFilter) const rs = updateOrInsert(originData, rsFilter); // const rs2 = mergeWithFilter(originData, rsFilter) triggerChangeData?.(rs, 'DUPLICATE'); }, [dataSource, focusedCell, originData, rowKey, table, triggerChangeData]); // thêm n dòng bên trên const handleInsertBefore = React.useCallback((item, n) => { const defaultRowValue = getDefaultValue(defaultValue); // const record: any = table.getRowModel().rows.find((it) => it.id === rowsFocus[rowsFocus.length - 1])?.original const record = table.getRowModel().flatRows.find(it => it.id === rowsFocus[rowsFocus.length - 1])?.original; if (item.onClick) { item.onClick({ toolbar: item }); } else { if (!record?.parentId) { // Cập nhật data mới const newData = [...originData]; const newRows = Array.from({ length: n }).map(() => defaultRowValue ? { ...defaultRowValue, id: undefined, rowId: newGuid() } : { id: undefined, rowId: newGuid() }); const kkk = getAllRowKey(newRows) ?? []; const rs = mergedFilterKeys ? [...mergedFilterKeys, ...kkk] : [...kkk]; setMergedFilterKeys?.(rs); const index = newData.findIndex(obj => obj[rowKey] === record[rowKey]); newData.splice(index, 0, ...newRows); triggerChangeData?.(newData, 'INSERT_BEFORE'); } else { const newData = [...originData]; const parent = findItemByKey(newData, rowKey, record.parentId); const newRows = Array.from({ length: n }).map(() => defaultRowValue ? { ...defaultRowValue, id: undefined, rowId: newGuid(), parentId: parent.rowId } : { id: undefined, rowId: newGuid(), parentId: parent.rowId }); // Cập nhật childData mới const childData = parent?.children ? [...parent.children] : []; const index = childData.findIndex(obj => obj[rowKey] === record[rowKey]); childData.splice(index, 0, ...newRows); const newRowData = { ...parent, children: childData }; const newDataSource = updateArrayByKey(newData, newRowData, rowKey); triggerChangeData?.(newDataSource, 'INSERT_BEFORE'); } } }, [defaultValue, mergedFilterKeys, originData, rowKey, rowsFocus, setMergedFilterKeys, table, triggerChangeData]); //thêm 1 dòng bên dưới const handleInsertAfter = React.useCallback((item, n) => { const defaultRowValue = getDefaultValue(defaultValue); // const insertAfter = Math.max(...rowsFocus) // const record: RecordType = flattenData(childrenColumnName, dataSource)[insertAfter] // const record: any = table.getRowModel().rows.find((it) => it.id === focusedCell?.rowId)?.original const record = table.getRowModel().flatRows.find(it => it.id === focusedCell?.rowId)?.original; if (item.onClick) { item.onClick({ toolbar: item }); } else { if (!record?.parentId) { // Cập nhật data mới const newData = [...originData]; const newRows = Array.from({ length: n }).map(() => defaultRowValue ? { ...defaultRowValue, id: undefined, rowId: newGuid() } : { id: undefined, rowId: newGuid() }); const kkk = getAllRowKey(newRows) ?? []; const rs = mergedFilterKeys ? [...mergedFilterKeys, ...kkk] : [...kkk]; setMergedFilterKeys?.(rs); const index = newData.findIndex(obj => obj[rowKey] === record[rowKey]); newData.splice(index + 1, 0, ...newRows); triggerChangeData?.(newData, 'INSERT_AFTER'); } else { const newData = [...originData]; const parent = findItemByKey(newData, rowKey, record.parentId); const newRows = Array.from({ length: n }).map(() => defaultRowValue ? { ...defaultRowValue, id: undefined, rowId: newGuid(), parentId: parent.rowId } : { id: undefined, rowId: newGuid(), parentId: parent.rowId }); const kkk = getAllRowKey(newRows) ?? []; const rs = mergedFilterKeys ? [...mergedFilterKeys, ...kkk] : [...kkk]; setMergedFilterKeys?.(rs); // Cập nhật childData mới const childData = parent?.children ? [...parent.children] : []; const index = childData.findIndex(obj => obj[rowKey] === record[rowKey]); childData.splice(index + 1, 0, ...newRows); const newRowData = { ...parent, children: childData }; const newDataSource = updateArrayByKey(newData, newRowData, rowKey); triggerChangeData?.(newDataSource, 'INSERT_BEFORE'); } } }, [defaultValue, table, focusedCell?.rowId, originData, mergedFilterKeys, setMergedFilterKeys, triggerChangeData, rowKey]); const handleInsertChild = React.useCallback(item => { const defaultRowValue = getDefaultValue(defaultValue); const rowId = newGuid(); const record = table.getRowModel().rows.find(it => it.id === focusedCell?.rowId)?.original; if (item.onClick) { item.onClick({ toolbar: item }); } else { // const newData = [...dataSource] const newData = [...originData]; let newElement; if (!record.children || record.children.length === 0) { newElement = { ...record, children: [{ ...defaultRowValue, parentId: record.rowId, rowId }] }; } else { newElement = { ...record, children: [...record.children, { ...defaultRowValue, parentId: record.rowId, rowId }] }; } const rs = mergedFilterKeys ? [...mergedFilterKeys, rowId] : [rowId]; setMergedFilterKeys?.(rs); const newDataSource = updateArrayByKey(newData, newElement, rowKey); triggerChangeData?.(newDataSource, 'INSERT_CHILDREN'); } setTimeout(() => { const row = table.getRowModel().rows.find(it => it.id === focusedCell?.rowId); if (row) { setExpanded(old => ({ ...old, [row.id]: true })); } }, 10); // const hasKey = mergedExpandedKeys.has(key) // if (!hasKey) { // const newExpandedKeys = [...mergedExpandedKeys, key] // setInnerExpandedKeys(newExpandedKeys) // } }, [defaultValue, focusedCell?.rowId, mergedFilterKeys, originData, rowKey, setExpanded, setMergedFilterKeys, table, triggerChangeData]); const handleDeleteRows = React.useCallback(item => { if (item.onClick) { item.onClick({ toolbar: item }); } else { const filterData = flattenArray([...originData]); const rs = filterData.filter(it => !rowsFocus.includes(it[rowKey])); const newDaa = unFlattenData(rs); triggerChangeData?.([...newDaa], 'DELETE_ROWS'); } }, [originData, rowKey, rowsFocus, triggerChangeData]); const handleDeleteAll = React.useCallback(() => { triggerChangeData?.([], 'INSERT_BEFORE'); }, [triggerChangeData]); const handleDeleteContent = React.useCallback(() => { if (startCell && endCell) { const tmpData = flattenArray([...dataSource]); const rs = tmpData.map(row => { if (!rangeState?.rowRange.includes(row.rowId)) { return row; } const updatedRow = { ...row }; for (const colId of rangeState.colRange) { const column = table.getVisibleFlatColumns().find(it => it.id === colId)?.columnDef.meta; if (isEditable(column, row)) { updatedRow[colId] = ''; } } return updatedRow; }); const newData = unFlattenData(rs); triggerChangeData?.([...newData], 'DELETE_CONTENT'); } }, [dataSource, endCell, rangeState, startCell, table, triggerChangeData]); const toolbarItemsBottom = React.useMemo(() => { if (!rowsFocus || rowsFocus.length === 0) { return toolbarItems?.filter(it => it.position === 'Bottom' && it.visible !== false && it.key !== 'DUPLICATE' && it.key !== 'INSERT_BEFORE' && it.key !== 'INSERT_AFTER' && it.key !== 'DELETE_ROWS' && it.key !== 'INSERT_CHILDREN').map(item => { if (item.key === 'ADD') { return { ...item, template: () => { return /*#__PURE__*/React.createElement(Fragment, null, item.key === 'ADD' && /*#__PURE__*/React.createElement("div", { className: classNames(`be-toolbar-item`, item?.className) }, /*#__PURE__*/React.createElement(Dropdown.Button, { overlayClassName: 'be-popup-container', trigger: ['click'], style: { color: '#28c76f', borderColor: '#28c76f' }, className: 'toolbar-button toolbar-dropdown-button', menu: { items: itemsAdd, onClick: e => handleAddMulti(item, Number(e.key)) } }, /*#__PURE__*/React.createElement("span", { style: { color: '#28c76f' }, onClick: () => handleAddMulti(item, 1) }, item.label ? t ? t(item.label) : item.label : t ? t('Add item') : 'Add item')))); } }; } if (item.key === 'DELETE') { return { ...item, template: () => { return /*#__PURE__*/React.createElement("div", { className: classNames(`be-toolbar-item`, item?.className) }, /*#__PURE__*/React.createElement(Button, { style: { color: '#eb4619', borderColor: '#eb4619' }, variant: 'outlined', onClick: handleDeleteAll, className: "d-flex toolbar-button" }, item.label ? t ? t(item.label) : item.label : t ? t('Delete all item') : 'Delete all item')); } }; } return { ...item }; }); } return toolbarItems?.filter(it => it.position === 'Bottom' && it.visible !== false).map(item => { if (item.key === 'ADD') { return { ...item, template: () => { return /*#__PURE__*/React.createElement(Fragment, null, item.key === 'ADD' && /*#__PURE__*/React.createElement("div", { className: classNames(`be-toolbar-item`, item?.className) }, /*#__PURE__*/React.createElement(Dropdown.Button, { overlayClassName: 'be-popup-container', style: { color: '#28c76f', borderColor: '#28c76f' }, className: 'toolbar-button toolbar-dropdown-button', menu: { items: itemsAdd, onClick: e => handleAddMulti(item, Number(e.key)) } }, /*#__PURE__*/React.createElement("span", { style: { color: '#28c76f' }, onClick: () => handleAddMulti(item, 1) }, item.label ? t ? t(item.label) : item.label : t ? t('Add item') : 'Add item')))); } }; } if (item.key === 'DUPLICATE') { return { ...item, template: () => { return /*#__PURE__*/React.createElement(Fragment, null, item.key === 'DUPLICATE' && item.visible !== false && rowsFocus.length > 0 && /*#__PURE__*/React.createElement("div", { className: classNames(`be-toolbar-item`, item?.className) }, /*#__PURE__*/React.createElement(Button, { style: { color: '#28c76f', borderColor: '#28c76f' }, variant: 'outlined', onClick: handleDuplicate, className: "d-flex toolbar-button" }, item.label ? t ? t(item.label) : item.label : t ? t('Duplicate') : 'Duplicate'))); } }; } if (item.key === 'INSERT_BEFORE') { return { ...item, template: () => { return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", { className: classNames(`be-toolbar-item`, item?.className) }, /*#__PURE__*/React.createElement(Dropdown.Button, { overlayClassName: 'be-popup-container', style: { color: '#28c76f', borderColor: '#28c76f' }, className: 'toolbar-button toolbar-dropdown-button', menu: { items: itemsAdd, onClick: e => handleInsertBefore(item, Number(e.key)) } }, /*#__PURE__*/React.createElement("span", { style: { color: '#28c76f' }, onClick: () => handleInsertBefore(item, 1) }, item.label ? t ? t(item.label) : item.label : t ? t('Insert item before') : 'Insert item before')))); } }; } if (item.key === 'INSERT_AFTER') { return { ...item, template: () => { return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", { className: classNames(`be-toolbar-item`, item?.className) }, /*#__PURE__*/React.createElement(Dropdown.Button, { overlayClassName: 'be-popup-container', style: { color: '#28c76f', borderColor: '#28c76f' }, className: 'toolbar-button toolbar-dropdown-button', menu: { items: itemsAdd, onClick: e => handleInsertAfter(item, Number(e.key)) } }, /*#__PURE__*/React.createElement("span", { style: { color: '#28c76f' }, onClick: () => handleInsertAfter(item, 1) }, item.label ? t ? t(item.label) : item.label : t ? t('Insert item after') : 'Insert item after')))); } }; } if (item.key === 'INSERT_CHILDREN') { return { ...item, template: () => { return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", { className: classNames(`be-toolbar-item`, item?.className) }, /*#__PURE__*/React.createElement(Button, { style: { color: '#28c76f', borderColor: '#28c76f' }, variant: 'outlined', onClick: () => handleInsertChild(item), className: "d-flex toolbar-button" }, item.label ? t ? t(item.label) : item.label : t ? t('Insert item children') : 'Insert item children'))); } }; } if (item.key === 'DELETE') { return { ...item, template: () => { return /*#__PURE__*/React.createElement("div", { className: classNames(`be-toolbar-item`, item?.className) }, /*#__PURE__*/React.createElement(Button, { style: { color: '#eb4619', borderColor: '#eb4619' }, variant: 'outlined', onClick: handleDeleteAll, className: "d-flex toolbar-button" }, item.label ? t ? t(item.label) : item.label : t ? t('Delete all item') : 'Delete all item')); } }; } if (item.key === 'DELETE_ROWS') { return { ...item, template: () => { return /*#__PURE__*/React.createElement("div", { className: classNames(`be-toolbar-item`, item?.className) }, /*#__PURE__*/React.createElement(Button, { style: { color: '#eb4619', borderColor: '#eb4619' }, variant: 'outlined', onClick: () => handleDeleteRows(item), className: "d-flex toolbar-button" }, t ? `${t('Delete')} ${rowsFocus.length} ${t('row')}` : `Delete ${rowsFocus.length} item`)); } }; } return { ...item }; }); }, [handleAddMulti, handleDeleteAll, handleDeleteRows, handleDuplicate, handleInsertAfter, handleInsertBefore, handleInsertChild, itemsAdd, rowsFocus, t, toolbarItems]); return /*#__PURE__*/React.createElement("div", { ref: containerRef, id: id }, (showToolbar !== false || fullScreen !== false) && /*#__PURE__*/React.createElement("div", { ref: topToolbarRef, className: classNames(`${prefix}-grid-top-toolbar`, {}) }, /*#__PURE__*/React.createElement("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '.75rem' } }, toolbarItems && toolbarItems?.length > 0 && /*#__PURE__*/React.createElement("div", { style: { flex: 1, overflow: 'hidden' } }, /*#__PURE__*/React.createElement(Toolbar, { items: (toolbarItems ?? []).filter(it => it.position !== 'Bottom'), mode: 'scroll' })), fullScreen !== false && (isFullScreen ? /*#__PURE__*/React.createElement(Minimize, { fontSize: 16 // onClick={() => handleFullScreen?.()} , "data-tooltip-id": "tooltip-icon", "data-tooltip-content": t ? t('Minimized') : 'Minimized' }) : /*#__PURE__*/React.createElement(Maximize, { fontSize: 16 // onClick={() => handleFullScreen?.()} , "data-tooltip-id": "tooltip-icon", "data-tooltip-content": t ? t('Full screen') : 'Full screen' })), /*#__PURE__*/React.createElement("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '.75rem' } }, pagination && pagination.onChange && pagination?.position && pagination?.position[0] === 'topRight' && /*#__PURE__*/React.createElement(Pagination, _extends({ showSizeChanger: true, responsive: true, size: 'small', rootClassName: 'top-pagination', showTotal: (total, range) => // @ts-ignore `${range[0]}-${range[1]} / ${total} ${t ? t(pagination?.locale?.items ?? 'items') : 'items'}` }, pagination)), typeof actionTemplate === 'function' ? actionTemplate() : actionTemplate, showColumnChoose && /*#__PURE__*/React.createElement(ColumnsChoose, { columns: [], t: t, columnsGroup: [] // triggerChangeColumns={triggerChangeColumns} })))), /*#__PURE__*/React.createElement("form", { onSubmit: handleSubmit(onSubmit) }, /*#__PURE__*/React.createElement("div", { // className="container" className: classNames(`${prefix}-grid-container`, { 'ui-rc-table-ping-right': tableContainerRef && (tableContainerRef.current?.scrollLeft ?? 0) >= 0 && (tableContainerRef.current?.scrollLeft ?? 0) + (tableContainerRef.current?.clientWidth ?? 0) < (tableContainerRef.current?.scrollWidth ?? 0), 'ui-rc-table-ping-left': tableContainerRef && (tableContainerRef.current?.scrollLeft ?? 0) > 0 }), ref: tableContainerRef, style: { overflow: 'auto', //our scrollable table container position: 'relative', //needed for sticky header height: tableHeight //should be a fixed height } }, /*#__PURE__*/React.createElement(TableContext.Provider, { value: { prefix, id, rowKey, format, expandable, dataSource, originData, wrapSettings, recordDoubleClick, selectionSettings, setIsSelectionChange, onContextMenu, setSorterChange, setFilterChange, rangeState, setRangeState, rangePasteState, setRangePasteState, focusedCell, setFocusedCell, startCell, editingKey, endCell, isSelecting, isPasting, startPasteCell, endPasteCell, setEditingKey, setEndCell, setIsSelecting, setStartCell, setIsPasting, setEndPasteCell, setStartPasteCell, // control, // trigger, errors, getValues, setValue, handleCellChange, triggerPaste, handleDeleteContent, handleAddMulti } }, /*#__PURE__*/React.createElement("table", { // className={`${prefix}-grid-container`} style: { display: 'grid', minWidth: table.getTotalSize() } }, /*#__PURE__*/React.createElement(TableHead, { tableContainerRef: tableContainerRef, columnVirtualizer: columnVirtualizer, table: table, virtualPaddingLeft: virtualPaddingLeft, virtualPaddingRight: virtualPaddingRight, fixedLeftColumns: fixedLeftColumns, fixedRightColumns: fixedRightColumns }), /*#__PURE__*/React.createElement(TableBody, { tableId: id, columnVirtualizer: columnVirtualizer, table: table, tableContainerRef: tableContainerRef, virtualPaddingLeft: virtualPaddingLeft, virtualPaddingRight: virtualPaddingRight, fixedLeftColumns: fixedLeftColumns, fixedRightColumns: fixedRightColumns, commandClick: commandClick, editAble: editAble, contextMenuItems: contextMenuItems }))))), /*#__PURE__*/React.createElement("div", { ref: bottomToolbarRef }, toolbarItemsBottom && toolbarItemsBottom.length > 0 && /*#__PURE__*/React.createElement("div", { className: 'ui-rc-toolbar-bottom' // style={{ border: '0 1px 1px 1px solid #e0e0e0' }} , style: { borderBottom: '1px solid #e0e0e0', borderRight: '1px solid #e0e0e0', borderLeft: '1px solid #e0e0e0' } }, /*#__PURE__*/React.createElement(Toolbar, { style: { width: '100%' }, items: toolbarItemsBottom ?? [], mode: 'scroll', onClick: ({}) => { setEditingKey(''); } })), pagination && /*#__PURE__*/React.createElement(Pagination // style={{padding: '0.75rem 1rem'}} , { rootClassName: 'pagination-template', showSizeChanger: true, responsive: true, size: 'small', total: pagination.total, pageSize: pagination.onChange ? pagination.pageSize : table.getState().pagination.pageSize, pageSizeOptions: [20, 50, 100, 1000, 10000], onChange: (page, pageSize) => { if (pagination.onChange) { pagination.onChange(page, pageSize); } else { table.setPageIndex(page - 1); table.setPageSize(pageSize); } } }))); }; export default TableContainerEdit;