trotl-table 1.0.11 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +217 -43
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +217 -43
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -9612,7 +9612,8 @@ const DraggableRow = ({
|
|
|
9612
9612
|
index,
|
|
9613
9613
|
moveRow,
|
|
9614
9614
|
children,
|
|
9615
|
-
|
|
9615
|
+
row,
|
|
9616
|
+
tableId,
|
|
9616
9617
|
enableDrag,
|
|
9617
9618
|
listRef
|
|
9618
9619
|
}) => {
|
|
@@ -9621,7 +9622,6 @@ const DraggableRow = ({
|
|
|
9621
9622
|
accept: ITEM_TYPE,
|
|
9622
9623
|
hover(draggedItem, monitor) {
|
|
9623
9624
|
if (!ref.current || !enableDrag) return;
|
|
9624
|
-
ref.current.getBoundingClientRect();
|
|
9625
9625
|
const clientOffset = monitor.getClientOffset();
|
|
9626
9626
|
|
|
9627
9627
|
// Auto-scroll logic
|
|
@@ -9651,23 +9651,31 @@ const DraggableRow = ({
|
|
|
9651
9651
|
}, drag] = reactDnd.useDrag({
|
|
9652
9652
|
type: ITEM_TYPE,
|
|
9653
9653
|
item: {
|
|
9654
|
-
index
|
|
9654
|
+
index,
|
|
9655
|
+
row,
|
|
9656
|
+
sourceTableId: tableId
|
|
9655
9657
|
},
|
|
9656
9658
|
canDrag: enableDrag,
|
|
9657
9659
|
collect: monitor => ({
|
|
9658
9660
|
isDragging: monitor.isDragging()
|
|
9659
9661
|
})
|
|
9660
9662
|
});
|
|
9661
|
-
drag
|
|
9663
|
+
// Compose drag & drop refs in effect to avoid reading ref during render
|
|
9664
|
+
const setRef = React.useCallback(node => {
|
|
9665
|
+
if (node) {
|
|
9666
|
+
ref.current = node;
|
|
9667
|
+
drag(drop(node));
|
|
9668
|
+
}
|
|
9669
|
+
}, [drag, drop]);
|
|
9662
9670
|
return /*#__PURE__*/React.createElement("div", {
|
|
9663
|
-
ref:
|
|
9671
|
+
ref: setRef,
|
|
9664
9672
|
style: {
|
|
9665
9673
|
opacity: isDragging ? 0.5 : 1,
|
|
9666
9674
|
cursor: enableDrag ? "move" : "default"
|
|
9667
9675
|
}
|
|
9668
9676
|
}, children);
|
|
9669
9677
|
};
|
|
9670
|
-
function
|
|
9678
|
+
function TableInner({
|
|
9671
9679
|
tableId = "default",
|
|
9672
9680
|
columns = [],
|
|
9673
9681
|
data = [],
|
|
@@ -9684,7 +9692,11 @@ function Table({
|
|
|
9684
9692
|
deleteCallback = null,
|
|
9685
9693
|
buttons = ["view", "edit", "delete"],
|
|
9686
9694
|
enableDragRow = false,
|
|
9687
|
-
enableSearchUrlParam = false
|
|
9695
|
+
enableSearchUrlParam = false,
|
|
9696
|
+
enableMultiSelect = false,
|
|
9697
|
+
enableExternalRowDrop = false,
|
|
9698
|
+
onExternalRowDrop = () => {},
|
|
9699
|
+
useExternalDndContext = false
|
|
9688
9700
|
}) {
|
|
9689
9701
|
// Local selection & sorting state (removed TableContext dependency)
|
|
9690
9702
|
const [selectedRows, setSelectedRows] = React.useState([]);
|
|
@@ -9822,7 +9834,7 @@ function Table({
|
|
|
9822
9834
|
const toggleGroup = gid => {
|
|
9823
9835
|
setExpandedGroups(prev => ({
|
|
9824
9836
|
...prev,
|
|
9825
|
-
[gid]: !
|
|
9837
|
+
[gid]: !prev[gid]
|
|
9826
9838
|
}));
|
|
9827
9839
|
};
|
|
9828
9840
|
React.useEffect(() => {
|
|
@@ -9935,40 +9947,90 @@ function Table({
|
|
|
9935
9947
|
const showDelete = buttons.includes("delete");
|
|
9936
9948
|
const showActions = showView || showEdit || showDelete;
|
|
9937
9949
|
|
|
9938
|
-
// MOVE ROW
|
|
9939
|
-
|
|
9950
|
+
// MOVE ROW (internal + between groups)
|
|
9951
|
+
// moveRow: allow toIndex to be null or an object { emptyGroupId } for empty group drop
|
|
9952
|
+
const moveRow = React.useCallback((fromIndex, toIndexOrGroup) => {
|
|
9940
9953
|
const from = tableDataFlat[fromIndex];
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9954
|
+
let to = null;
|
|
9955
|
+
let emptyGroupId = null;
|
|
9956
|
+
if (typeof toIndexOrGroup === 'object' && toIndexOrGroup && toIndexOrGroup.emptyGroupId) {
|
|
9957
|
+
emptyGroupId = toIndexOrGroup.emptyGroupId;
|
|
9958
|
+
} else {
|
|
9959
|
+
to = tableDataFlat[toIndexOrGroup];
|
|
9960
|
+
}
|
|
9961
|
+
if (!from || from.type !== "row" || toIndexOrGroup !== null && !to && !emptyGroupId) return;
|
|
9946
9962
|
setLocalData(prev => {
|
|
9947
9963
|
if (isGrouped) {
|
|
9948
|
-
//
|
|
9949
|
-
|
|
9950
|
-
|
|
9964
|
+
// Remove from old group
|
|
9965
|
+
let movedRow;
|
|
9966
|
+
const newGroups = prev.map(group => {
|
|
9951
9967
|
const groupId = group[groupKey] ?? group.groupId ?? group.groupName;
|
|
9952
|
-
if (groupId
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
|
|
9959
|
-
|
|
9960
|
-
|
|
9961
|
-
|
|
9962
|
-
}
|
|
9968
|
+
if (groupId === from.groupId) {
|
|
9969
|
+
const rows = [...group.rows];
|
|
9970
|
+
const fromPos = rows.findIndex(r => r.id === from.row.id);
|
|
9971
|
+
if (fromPos !== -1) {
|
|
9972
|
+
[movedRow] = rows.splice(fromPos, 1);
|
|
9973
|
+
}
|
|
9974
|
+
return {
|
|
9975
|
+
...group,
|
|
9976
|
+
rows
|
|
9977
|
+
};
|
|
9978
|
+
}
|
|
9979
|
+
return group;
|
|
9980
|
+
});
|
|
9981
|
+
if (!movedRow) return prev;
|
|
9982
|
+
// Insert into new group at correct position
|
|
9983
|
+
return newGroups.map(group => {
|
|
9984
|
+
const groupId = group[groupKey] ?? group.groupId ?? group.groupName;
|
|
9985
|
+
// If dropping into empty group
|
|
9986
|
+
if (emptyGroupId && groupId === emptyGroupId) {
|
|
9987
|
+
const rows = [...group.rows];
|
|
9988
|
+
if (groupKey && movedRow[groupKey] !== undefined) {
|
|
9989
|
+
movedRow = {
|
|
9990
|
+
...movedRow,
|
|
9991
|
+
[groupKey]: groupId
|
|
9992
|
+
};
|
|
9993
|
+
}
|
|
9994
|
+
rows.push(movedRow);
|
|
9995
|
+
return {
|
|
9996
|
+
...group,
|
|
9997
|
+
rows
|
|
9998
|
+
};
|
|
9999
|
+
}
|
|
10000
|
+
// Normal drop
|
|
10001
|
+
if (to && groupId === to.groupId) {
|
|
10002
|
+
const rows = [...group.rows];
|
|
10003
|
+
const toPos = rows.findIndex(r => r.id === to.row.id);
|
|
10004
|
+
if (groupKey && movedRow[groupKey] !== undefined) {
|
|
10005
|
+
movedRow = {
|
|
10006
|
+
...movedRow,
|
|
10007
|
+
[groupKey]: groupId
|
|
10008
|
+
};
|
|
10009
|
+
}
|
|
10010
|
+
if (toPos === -1) {
|
|
10011
|
+
rows.push(movedRow);
|
|
10012
|
+
} else {
|
|
10013
|
+
rows.splice(toPos, 0, movedRow);
|
|
10014
|
+
}
|
|
10015
|
+
return {
|
|
10016
|
+
...group,
|
|
10017
|
+
rows
|
|
10018
|
+
};
|
|
10019
|
+
}
|
|
10020
|
+
return group;
|
|
9963
10021
|
});
|
|
9964
10022
|
} else {
|
|
9965
10023
|
// Ungrouped: reorder the flat list
|
|
9966
10024
|
const arr = Array.isArray(prev) ? [...prev] : [];
|
|
9967
10025
|
const fromPos = arr.findIndex(r => r.id === from.row.id);
|
|
9968
|
-
const toPos = arr.findIndex(r => r.id === to.row.id);
|
|
9969
|
-
if (fromPos === -1 || toPos === -1) return prev;
|
|
10026
|
+
const toPos = to ? arr.findIndex(r => r.id === to.row.id) : -1;
|
|
10027
|
+
if (fromPos === -1 || to && toPos === -1) return prev;
|
|
9970
10028
|
const [moved] = arr.splice(fromPos, 1);
|
|
9971
|
-
|
|
10029
|
+
if (to) {
|
|
10030
|
+
arr.splice(toPos, 0, moved);
|
|
10031
|
+
} else {
|
|
10032
|
+
arr.push(moved);
|
|
10033
|
+
}
|
|
9972
10034
|
return arr;
|
|
9973
10035
|
}
|
|
9974
10036
|
});
|
|
@@ -9986,12 +10048,81 @@ function Table({
|
|
|
9986
10048
|
const gid = item.groupId;
|
|
9987
10049
|
const rows = groupRowsById[gid] || [];
|
|
9988
10050
|
const allSelected = rows.length > 0 && rows.every(r => selectedRows.includes(r.id));
|
|
10051
|
+
|
|
10052
|
+
// If expanded and group is empty and drag enabled, make the group header itself a drop target
|
|
10053
|
+
if (item.expanded && rows.length === 0 && enableDragRow) {
|
|
10054
|
+
// For empty group, drop target pushes into this group
|
|
10055
|
+
const GroupHeaderDrop = () => {
|
|
10056
|
+
const ref = React.useRef(null);
|
|
10057
|
+
const [, drop] = reactDnd.useDrop({
|
|
10058
|
+
accept: ITEM_TYPE,
|
|
10059
|
+
drop(draggedItem) {
|
|
10060
|
+
if (draggedItem && typeof draggedItem.index === "number") {
|
|
10061
|
+
moveRow(draggedItem.index, {
|
|
10062
|
+
emptyGroupId: gid
|
|
10063
|
+
});
|
|
10064
|
+
}
|
|
10065
|
+
},
|
|
10066
|
+
canDrop: () => true,
|
|
10067
|
+
collect: monitor => ({
|
|
10068
|
+
isOver: monitor.isOver(),
|
|
10069
|
+
canDrop: monitor.canDrop()
|
|
10070
|
+
})
|
|
10071
|
+
});
|
|
10072
|
+
drop(ref);
|
|
10073
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
10074
|
+
ref: ref,
|
|
10075
|
+
key: key,
|
|
10076
|
+
style: {
|
|
10077
|
+
...style,
|
|
10078
|
+
background: '#f6f6fa',
|
|
10079
|
+
border: '2px dashed #bbb',
|
|
10080
|
+
textAlign: 'center',
|
|
10081
|
+
color: '#888',
|
|
10082
|
+
minHeight: rowHeight,
|
|
10083
|
+
display: 'flex',
|
|
10084
|
+
alignItems: 'center'
|
|
10085
|
+
},
|
|
10086
|
+
className: "table-row group-row empty-group-drop",
|
|
10087
|
+
onClick: () => toggleGroup(gid)
|
|
10088
|
+
}, enableMultiSelect && showDelete && /*#__PURE__*/React.createElement("div", {
|
|
10089
|
+
className: "table-cell checkbox-cell"
|
|
10090
|
+
}, /*#__PURE__*/React.createElement("input", {
|
|
10091
|
+
type: "checkbox",
|
|
10092
|
+
checked: allSelected,
|
|
10093
|
+
onChange: e => {
|
|
10094
|
+
e.stopPropagation();
|
|
10095
|
+
const ids = rows.map(r => r.id);
|
|
10096
|
+
if (allSelected) {
|
|
10097
|
+
setSelectedRows(prev => prev.filter(id => !ids.includes(id)));
|
|
10098
|
+
} else {
|
|
10099
|
+
setSelectedRows(prev => [...prev, ...ids.filter(id => !prev.includes(id))]);
|
|
10100
|
+
}
|
|
10101
|
+
},
|
|
10102
|
+
onClick: e => e.stopPropagation()
|
|
10103
|
+
})), showKey && /*#__PURE__*/React.createElement("div", {
|
|
10104
|
+
className: "table-cell key-cell"
|
|
10105
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
10106
|
+
className: "table-cell group-header",
|
|
10107
|
+
style: {
|
|
10108
|
+
width: '100%'
|
|
10109
|
+
}
|
|
10110
|
+
}, item.expanded ? "▾" : "▸", " ", item.groupName, " (0) \u2014 Drop here to move into this group"), columns.slice(1).map((_, i) => /*#__PURE__*/React.createElement("div", {
|
|
10111
|
+
key: i,
|
|
10112
|
+
className: "table-cell"
|
|
10113
|
+
})), showActions && /*#__PURE__*/React.createElement("div", {
|
|
10114
|
+
className: "table-cell action-cell"
|
|
10115
|
+
}));
|
|
10116
|
+
};
|
|
10117
|
+
return /*#__PURE__*/React.createElement(GroupHeaderDrop, null);
|
|
10118
|
+
}
|
|
10119
|
+
// Default: normal group header
|
|
9989
10120
|
return /*#__PURE__*/React.createElement("div", {
|
|
9990
10121
|
key: key,
|
|
9991
10122
|
style: style,
|
|
9992
10123
|
className: "table-row group-row",
|
|
9993
10124
|
onClick: () => toggleGroup(gid)
|
|
9994
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
10125
|
+
}, enableMultiSelect && showDelete && /*#__PURE__*/React.createElement("div", {
|
|
9995
10126
|
className: "table-cell checkbox-cell"
|
|
9996
10127
|
}, /*#__PURE__*/React.createElement("input", {
|
|
9997
10128
|
type: "checkbox",
|
|
@@ -9999,7 +10130,11 @@ function Table({
|
|
|
9999
10130
|
onChange: e => {
|
|
10000
10131
|
e.stopPropagation();
|
|
10001
10132
|
const ids = rows.map(r => r.id);
|
|
10002
|
-
|
|
10133
|
+
if (allSelected) {
|
|
10134
|
+
setSelectedRows(prev => prev.filter(id => !ids.includes(id)));
|
|
10135
|
+
} else {
|
|
10136
|
+
setSelectedRows(prev => [...prev, ...ids.filter(id => !prev.includes(id))]);
|
|
10137
|
+
}
|
|
10003
10138
|
},
|
|
10004
10139
|
onClick: e => e.stopPropagation()
|
|
10005
10140
|
})), showKey && /*#__PURE__*/React.createElement("div", {
|
|
@@ -10019,7 +10154,7 @@ function Table({
|
|
|
10019
10154
|
key: key,
|
|
10020
10155
|
style: style,
|
|
10021
10156
|
className: "table-row"
|
|
10022
|
-
}, showDelete && /*#__PURE__*/React.createElement("div", {
|
|
10157
|
+
}, enableMultiSelect && showDelete && /*#__PURE__*/React.createElement("div", {
|
|
10023
10158
|
className: "table-cell checkbox-cell"
|
|
10024
10159
|
}, /*#__PURE__*/React.createElement("input", {
|
|
10025
10160
|
type: "checkbox",
|
|
@@ -10060,20 +10195,46 @@ function Table({
|
|
|
10060
10195
|
key: key,
|
|
10061
10196
|
index: index,
|
|
10062
10197
|
moveRow: moveRow,
|
|
10063
|
-
|
|
10198
|
+
row: row,
|
|
10199
|
+
tableId: tableId,
|
|
10064
10200
|
enableDrag: true,
|
|
10065
10201
|
listRef: listRef
|
|
10066
10202
|
}, content);
|
|
10067
10203
|
}
|
|
10068
10204
|
return content;
|
|
10069
|
-
}, [tableDataFlat, columns, selectedRows, toggleRowSelection, groupRowsById, renderCell, showActions, showDelete, showEdit, showKey, showView,
|
|
10205
|
+
}, [tableDataFlat, columns, selectedRows, toggleRowSelection, groupRowsById, renderCell, showActions, showDelete, showEdit, showKey, showView, viewCallback, editCallback, enableDragRow, moveRow, enableMultiSelect, rowHeight, tableId]);
|
|
10070
10206
|
const rowHeightGetter = ({
|
|
10071
10207
|
index
|
|
10072
10208
|
}) => tableDataFlat[index]?.type === "group" ? groupHeaderHeight : rowHeight;
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
|
|
10209
|
+
|
|
10210
|
+
// Table-level drop target only when using external DnD context
|
|
10211
|
+
const tableContainerRef = React.useRef(null);
|
|
10212
|
+
const [{
|
|
10213
|
+
isOver: isExternalOver,
|
|
10214
|
+
canDrop: canExternalDrop
|
|
10215
|
+
}, externalDrop] = reactDnd.useDrop({
|
|
10216
|
+
accept: ITEM_TYPE,
|
|
10217
|
+
drop: draggedItem => {
|
|
10218
|
+
if (!useExternalDndContext) return; // safety
|
|
10219
|
+
if (!enableExternalRowDrop || isGrouped) return;
|
|
10220
|
+
if (!draggedItem || draggedItem.sourceTableId === tableId) return;
|
|
10221
|
+
onExternalRowDrop(draggedItem.row, draggedItem.sourceTableId, tableId);
|
|
10222
|
+
}
|
|
10223
|
+
});
|
|
10224
|
+
const setTableRef = React.useCallback(node => {
|
|
10225
|
+
tableContainerRef.current = node;
|
|
10226
|
+
if (node && useExternalDndContext && enableExternalRowDrop) {
|
|
10227
|
+
externalDrop(node);
|
|
10228
|
+
}
|
|
10229
|
+
}, [useExternalDndContext, enableExternalRowDrop, externalDrop]);
|
|
10230
|
+
const tableMarkup = /*#__PURE__*/React.createElement("div", {
|
|
10231
|
+
className: "table-container",
|
|
10232
|
+
ref: setTableRef,
|
|
10233
|
+
style: useExternalDndContext && enableExternalRowDrop ? {
|
|
10234
|
+
transition: 'background 0.15s',
|
|
10235
|
+
background: isExternalOver && canExternalDrop ? 'rgba(100,108,255,0.15)' : undefined,
|
|
10236
|
+
outline: isExternalOver && canExternalDrop ? '2px dashed #646cff' : undefined
|
|
10237
|
+
} : undefined
|
|
10077
10238
|
}, /*#__PURE__*/React.createElement("div", {
|
|
10078
10239
|
className: "table-header",
|
|
10079
10240
|
style: {
|
|
@@ -10084,7 +10245,7 @@ function Table({
|
|
|
10084
10245
|
}
|
|
10085
10246
|
}, /*#__PURE__*/React.createElement("div", {
|
|
10086
10247
|
className: "table-row header-row"
|
|
10087
|
-
}, showDelete && /*#__PURE__*/React.createElement("div", {
|
|
10248
|
+
}, enableMultiSelect && showDelete && /*#__PURE__*/React.createElement("div", {
|
|
10088
10249
|
className: "table-cell checkbox-cell"
|
|
10089
10250
|
}, /*#__PURE__*/React.createElement("input", {
|
|
10090
10251
|
type: "checkbox",
|
|
@@ -10132,7 +10293,20 @@ function Table({
|
|
|
10132
10293
|
cancelLabel: "Cancel",
|
|
10133
10294
|
showCancel: true,
|
|
10134
10295
|
showConfirm: true
|
|
10135
|
-
}, /*#__PURE__*/React.createElement("p", null, "Are you sure you want to delete ", /*#__PURE__*/React.createElement("strong", null, pendingDelete?.name || pendingDelete?.id), "?")))
|
|
10296
|
+
}, /*#__PURE__*/React.createElement("p", null, "Are you sure you want to delete ", /*#__PURE__*/React.createElement("strong", null, pendingDelete?.name || pendingDelete?.id), "?")));
|
|
10297
|
+
return tableMarkup;
|
|
10298
|
+
}
|
|
10299
|
+
function Table(props) {
|
|
10300
|
+
const {
|
|
10301
|
+
useExternalDndContext = false
|
|
10302
|
+
} = props;
|
|
10303
|
+
if (useExternalDndContext) {
|
|
10304
|
+
return /*#__PURE__*/React.createElement(TableInner, props);
|
|
10305
|
+
}
|
|
10306
|
+
// Provide DnD context when not supplied externally
|
|
10307
|
+
return /*#__PURE__*/React.createElement(reactDnd.DndProvider, {
|
|
10308
|
+
backend: reactDndHtml5Backend.HTML5Backend
|
|
10309
|
+
}, /*#__PURE__*/React.createElement(TableInner, props));
|
|
10136
10310
|
}
|
|
10137
10311
|
|
|
10138
10312
|
// src/index.js
|