react-glide-table 2.2.1 → 2.3.0
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/README.md +33 -30
- package/dist/compound.cjs +561 -139
- package/dist/compound.d.cts +2 -2
- package/dist/compound.d.ts +2 -2
- package/dist/compound.js +465 -43
- package/dist/core.cjs +491 -137
- package/dist/core.d.cts +46 -7
- package/dist/core.d.ts +46 -7
- package/dist/core.js +378 -25
- package/dist/index.cjs +590 -166
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +466 -43
- package/dist/{types-CnsQ8GZb.d.cts → types-DdeVn-9s.d.cts} +23 -6
- package/dist/{types-CnsQ8GZb.d.ts → types-DdeVn-9s.d.ts} +23 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -750,6 +750,219 @@ function hasCellSelectionEdges(style) {
|
|
|
750
750
|
}
|
|
751
751
|
|
|
752
752
|
// src/components/ui/table/features/cell-selection/copyData.ts
|
|
753
|
+
import { isValidElement } from "react";
|
|
754
|
+
function isReactNodeIterable(node) {
|
|
755
|
+
return typeof node === "object" && node !== null && !isValidElement(node) && Symbol.iterator in node;
|
|
756
|
+
}
|
|
757
|
+
function getElementTypeName(type) {
|
|
758
|
+
if (typeof type === "string") return type;
|
|
759
|
+
if (typeof type === "function") {
|
|
760
|
+
const fn = type;
|
|
761
|
+
return fn.displayName || fn.name || "";
|
|
762
|
+
}
|
|
763
|
+
if (typeof type === "object" && type !== null) {
|
|
764
|
+
const component = type;
|
|
765
|
+
return component.displayName || component.render?.displayName || component.render?.name || "";
|
|
766
|
+
}
|
|
767
|
+
return "";
|
|
768
|
+
}
|
|
769
|
+
function isButtonReactElement(node) {
|
|
770
|
+
const typeName = getElementTypeName(node.type);
|
|
771
|
+
if (typeName === "button" || /button/i.test(typeName)) return true;
|
|
772
|
+
const props = node.props;
|
|
773
|
+
if (props.role === "button") return true;
|
|
774
|
+
if (typeName === "input" && props.type === "button") return true;
|
|
775
|
+
return false;
|
|
776
|
+
}
|
|
777
|
+
function isImageReactElement(node) {
|
|
778
|
+
const typeName = getElementTypeName(node.type);
|
|
779
|
+
return typeName === "img" || typeName === "image" || /image/i.test(typeName);
|
|
780
|
+
}
|
|
781
|
+
var IMAGE_URL_PROP_KEYS = ["src", "url", "href", "imageUrl", "srcUrl"];
|
|
782
|
+
function isLikelyUrl(value) {
|
|
783
|
+
const trimmed = value.trim();
|
|
784
|
+
if (!trimmed) return false;
|
|
785
|
+
if (/^(https?:|blob:|data:|\/\/)/i.test(trimmed)) return true;
|
|
786
|
+
if (trimmed.startsWith("/") && trimmed.includes("/")) return true;
|
|
787
|
+
return false;
|
|
788
|
+
}
|
|
789
|
+
function pickUrlFromUnknown(value) {
|
|
790
|
+
if (typeof value === "string") {
|
|
791
|
+
return isLikelyUrl(value) ? value.trim() : "";
|
|
792
|
+
}
|
|
793
|
+
if (Array.isArray(value)) {
|
|
794
|
+
return value.map((item) => pickUrlFromUnknown(item)).filter((item) => item.length > 0).join(", ");
|
|
795
|
+
}
|
|
796
|
+
if (value && typeof value === "object") {
|
|
797
|
+
const record = value;
|
|
798
|
+
for (const key of IMAGE_URL_PROP_KEYS) {
|
|
799
|
+
const candidate = record[key];
|
|
800
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
801
|
+
return candidate.trim();
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
return "";
|
|
806
|
+
}
|
|
807
|
+
function imageElementText(node) {
|
|
808
|
+
const props = node.props;
|
|
809
|
+
for (const key of IMAGE_URL_PROP_KEYS) {
|
|
810
|
+
const candidate = props[key];
|
|
811
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
812
|
+
return candidate.trim();
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
return "";
|
|
816
|
+
}
|
|
817
|
+
function reactNodeContainsImage(node) {
|
|
818
|
+
if (isValidElement(node)) {
|
|
819
|
+
if (isImageReactElement(node)) return true;
|
|
820
|
+
return reactNodeContainsImage(node.props.children);
|
|
821
|
+
}
|
|
822
|
+
if (isReactNodeIterable(node)) {
|
|
823
|
+
for (const child of node) {
|
|
824
|
+
if (reactNodeContainsImage(child)) return true;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
return false;
|
|
828
|
+
}
|
|
829
|
+
function readImgUrl(img) {
|
|
830
|
+
const attr = img.getAttribute("src")?.trim() ?? "";
|
|
831
|
+
if (attr) return attr;
|
|
832
|
+
if (img instanceof HTMLImageElement) {
|
|
833
|
+
const current = img.currentSrc?.trim() ?? "";
|
|
834
|
+
if (current && current !== img.baseURI) return current;
|
|
835
|
+
}
|
|
836
|
+
return "";
|
|
837
|
+
}
|
|
838
|
+
function readDomImageUrls(rowIndex, colIndex, root) {
|
|
839
|
+
const scope = root ?? (typeof document === "undefined" ? null : document);
|
|
840
|
+
if (!scope) return "";
|
|
841
|
+
const cells = scope.querySelectorAll(
|
|
842
|
+
`[data-row-index="${rowIndex}"][data-col-index="${colIndex}"]`
|
|
843
|
+
);
|
|
844
|
+
for (const cell of cells) {
|
|
845
|
+
const urls = Array.from(cell.querySelectorAll("img")).flatMap((img) => {
|
|
846
|
+
const url = readImgUrl(img);
|
|
847
|
+
return url ? [url] : [];
|
|
848
|
+
});
|
|
849
|
+
if (urls.length > 0) return urls.join(", ");
|
|
850
|
+
}
|
|
851
|
+
return "";
|
|
852
|
+
}
|
|
853
|
+
function reactNodeToText(node) {
|
|
854
|
+
if (node == null || typeof node === "boolean") return "";
|
|
855
|
+
if (typeof node === "string" || typeof node === "number" || typeof node === "bigint") {
|
|
856
|
+
return String(node);
|
|
857
|
+
}
|
|
858
|
+
if (isReactNodeIterable(node)) {
|
|
859
|
+
let text = "";
|
|
860
|
+
for (const child of node) {
|
|
861
|
+
text += reactNodeToText(child);
|
|
862
|
+
}
|
|
863
|
+
return text;
|
|
864
|
+
}
|
|
865
|
+
if (isValidElement(node)) {
|
|
866
|
+
if (isButtonReactElement(node)) return "";
|
|
867
|
+
const props = node.props;
|
|
868
|
+
const childText = reactNodeToText(props.children);
|
|
869
|
+
if (childText) return childText;
|
|
870
|
+
const fromImage = imageElementText(node);
|
|
871
|
+
if (fromImage) return fromImage;
|
|
872
|
+
if (isImageReactElement(node)) return "";
|
|
873
|
+
if (typeof props.alt === "string" && props.alt) return props.alt;
|
|
874
|
+
if (typeof props.title === "string" && props.title) return props.title;
|
|
875
|
+
return "";
|
|
876
|
+
}
|
|
877
|
+
return "";
|
|
878
|
+
}
|
|
879
|
+
function sanitizeClipboardCell(text) {
|
|
880
|
+
return text.replace(/\s+/g, " ").trim();
|
|
881
|
+
}
|
|
882
|
+
function createCopyRenderRow(rowData, index) {
|
|
883
|
+
return {
|
|
884
|
+
id: getOriginalRowId(rowData) || String(index),
|
|
885
|
+
index,
|
|
886
|
+
original: rowData,
|
|
887
|
+
getIsCellDragSelected: () => false
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
function buildVisibleRowLookup(visibleRows) {
|
|
891
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
892
|
+
for (const row of visibleRows) {
|
|
893
|
+
lookup.set(row.original, row);
|
|
894
|
+
}
|
|
895
|
+
return lookup;
|
|
896
|
+
}
|
|
897
|
+
function resolveCopyColumnId(cell) {
|
|
898
|
+
if (cell.column.id) return cell.column.id;
|
|
899
|
+
const columnDef = cell.column.columnDef;
|
|
900
|
+
if (columnDef.id) return columnDef.id;
|
|
901
|
+
if (columnDef.accessorKey != null && columnDef.accessorKey !== "") {
|
|
902
|
+
return String(columnDef.accessorKey);
|
|
903
|
+
}
|
|
904
|
+
return "";
|
|
905
|
+
}
|
|
906
|
+
function isPrimitiveCopyValue(value) {
|
|
907
|
+
return value == null || typeof value !== "object";
|
|
908
|
+
}
|
|
909
|
+
function extractRenderedCopyText(node, value, cellPosition, root) {
|
|
910
|
+
const rendered = sanitizeClipboardCell(reactNodeToText(node));
|
|
911
|
+
if (reactNodeContainsImage(node)) {
|
|
912
|
+
const fromDom = cellPosition != null ? sanitizeClipboardCell(
|
|
913
|
+
readDomImageUrls(cellPosition.rowIndex, cellPosition.colIndex, root)
|
|
914
|
+
) : "";
|
|
915
|
+
if (fromDom) return fromDom;
|
|
916
|
+
if (rendered && isLikelyUrl(rendered)) return rendered;
|
|
917
|
+
return sanitizeClipboardCell(pickUrlFromUnknown(value));
|
|
918
|
+
}
|
|
919
|
+
return rendered;
|
|
920
|
+
}
|
|
921
|
+
function formatCopyCellText(rowData, columnDef, columnId, visibleRow, fallbackIndex, sourceCell, cellPosition, options) {
|
|
922
|
+
const meta = columnDef.meta;
|
|
923
|
+
const value = sourceCell ? sourceCell.getValue() : readRowColumnValue(rowData, columnDef);
|
|
924
|
+
const cellRender = meta?.cellRender;
|
|
925
|
+
if (typeof cellRender === "function") {
|
|
926
|
+
try {
|
|
927
|
+
const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
|
|
928
|
+
const node = cellRender({
|
|
929
|
+
value,
|
|
930
|
+
row,
|
|
931
|
+
index: row.index,
|
|
932
|
+
columnId,
|
|
933
|
+
cellProps: meta?.cellProps,
|
|
934
|
+
update: () => {
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
return extractRenderedCopyText(node, value, cellPosition, options?.root);
|
|
938
|
+
} catch {
|
|
939
|
+
return formatCellValue(value);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
if (options?.registry && meta?.kind && isPrimitiveCopyValue(value)) {
|
|
943
|
+
try {
|
|
944
|
+
const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
|
|
945
|
+
const ctx = {
|
|
946
|
+
value,
|
|
947
|
+
row,
|
|
948
|
+
index: row.index,
|
|
949
|
+
columnId,
|
|
950
|
+
cellProps: meta.cellProps,
|
|
951
|
+
update: () => {
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
const renderer = resolveCellRenderer(options.registry, meta.kind, ctx);
|
|
955
|
+
if (renderer) {
|
|
956
|
+
const node = renderer.render(ctx);
|
|
957
|
+
const rendered = extractRenderedCopyText(node, value, cellPosition, options.root);
|
|
958
|
+
if (rendered) return rendered;
|
|
959
|
+
}
|
|
960
|
+
} catch {
|
|
961
|
+
return formatCellValue(value);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
return formatCellValue(value);
|
|
965
|
+
}
|
|
753
966
|
function formatPrimitive(value) {
|
|
754
967
|
if (value === null || value === void 0) return "";
|
|
755
968
|
if (typeof value === "string") return value;
|
|
@@ -855,37 +1068,47 @@ function collectCopyRowEntries(visibleRows, bounds, mode = "visible") {
|
|
|
855
1068
|
function collectCopyRows(visibleRows, bounds, mode = "visible") {
|
|
856
1069
|
return collectCopyRowEntries(visibleRows, bounds, mode).map((entry) => entry.row);
|
|
857
1070
|
}
|
|
858
|
-
function serializeCopyRowsToTSV(copyRows, visibleRows, bounds, depths) {
|
|
1071
|
+
function serializeCopyRowsToTSV(copyRows, visibleRows, bounds, depths, options) {
|
|
859
1072
|
if (copyRows.length === 0) return "";
|
|
860
1073
|
const { startCol, endCol } = bounds;
|
|
861
1074
|
const columnCells = visibleRows[0]?.getVisibleCells().slice(startCol, endCol + 1) ?? [];
|
|
862
1075
|
if (columnCells.length === 0) return "";
|
|
863
1076
|
const resolvedDepths = depths && depths.length === copyRows.length ? depths : copyRows.map((row) => getRowDepth(row));
|
|
864
1077
|
const minDepth = Math.min(...resolvedDepths);
|
|
1078
|
+
const visibleRowByOriginal = buildVisibleRowLookup(visibleRows);
|
|
865
1079
|
return copyRows.map((rowData, index) => {
|
|
866
1080
|
const relativeDepth = Math.max(0, (resolvedDepths[index] ?? 0) - minDepth);
|
|
867
|
-
const
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
1081
|
+
const visibleRow = visibleRowByOriginal.get(rowData);
|
|
1082
|
+
const matchingCells = visibleRow?.getVisibleCells().slice(startCol, endCol + 1);
|
|
1083
|
+
const line = columnCells.map((templateCell, colOffset) => {
|
|
1084
|
+
const sourceCell = matchingCells?.[colOffset];
|
|
1085
|
+
const column = sourceCell?.column ?? templateCell.column;
|
|
1086
|
+
return formatCopyCellText(
|
|
1087
|
+
rowData,
|
|
1088
|
+
column.columnDef,
|
|
1089
|
+
resolveCopyColumnId(sourceCell ?? templateCell),
|
|
1090
|
+
visibleRow,
|
|
1091
|
+
visibleRow?.index ?? index,
|
|
1092
|
+
sourceCell,
|
|
1093
|
+
visibleRow != null ? { rowIndex: visibleRow.index, colIndex: startCol + colOffset } : void 0,
|
|
1094
|
+
options
|
|
1095
|
+
);
|
|
1096
|
+
}).join(" ");
|
|
875
1097
|
return `${" ".repeat(relativeDepth)}${line}`;
|
|
876
1098
|
}).join("\n");
|
|
877
1099
|
}
|
|
878
|
-
function serializeSelectionToTSV(visibleRows, bounds, mode = "visible") {
|
|
1100
|
+
function serializeSelectionToTSV(visibleRows, bounds, mode = "visible", options) {
|
|
879
1101
|
const entries = collectCopyRowEntries(visibleRows, bounds, mode);
|
|
880
1102
|
return serializeCopyRowsToTSV(
|
|
881
1103
|
entries.map((entry) => entry.row),
|
|
882
1104
|
visibleRows,
|
|
883
1105
|
bounds,
|
|
884
|
-
entries.map((entry) => entry.depth)
|
|
1106
|
+
entries.map((entry) => entry.depth),
|
|
1107
|
+
options
|
|
885
1108
|
);
|
|
886
1109
|
}
|
|
887
|
-
async function writeSelectionToClipboard(visibleRows, bounds, mode = "visible") {
|
|
888
|
-
const text = serializeSelectionToTSV(visibleRows, bounds, mode);
|
|
1110
|
+
async function writeSelectionToClipboard(visibleRows, bounds, mode = "visible", options) {
|
|
1111
|
+
const text = serializeSelectionToTSV(visibleRows, bounds, mode, options);
|
|
889
1112
|
if (!text) return false;
|
|
890
1113
|
try {
|
|
891
1114
|
await navigator.clipboard.writeText(text);
|
|
@@ -1046,7 +1269,9 @@ function useCellSelection({
|
|
|
1046
1269
|
onDataChange,
|
|
1047
1270
|
onBatchChange,
|
|
1048
1271
|
onRowsPaste,
|
|
1049
|
-
onCellNavigate
|
|
1272
|
+
onCellNavigate,
|
|
1273
|
+
cellRendererRegistry,
|
|
1274
|
+
rootRef
|
|
1050
1275
|
}) {
|
|
1051
1276
|
const [dragState, setDragState] = useState2(INITIAL_DRAG_STATE);
|
|
1052
1277
|
const pendingPasteModeRef = useRef2(null);
|
|
@@ -1170,15 +1395,28 @@ function useCellSelection({
|
|
|
1170
1395
|
async (options) => {
|
|
1171
1396
|
if (!enabled || !activeSelectionBounds) return false;
|
|
1172
1397
|
const mode = options?.includeDescendants && enableSubtreeCopy ? "subtree" : "visible";
|
|
1173
|
-
return writeSelectionToClipboard(rows, activeSelectionBounds, mode
|
|
1398
|
+
return writeSelectionToClipboard(rows, activeSelectionBounds, mode, {
|
|
1399
|
+
registry: cellRendererRegistry,
|
|
1400
|
+
root: rootRef?.current
|
|
1401
|
+
});
|
|
1174
1402
|
},
|
|
1175
|
-
[
|
|
1403
|
+
[
|
|
1404
|
+
activeSelectionBounds,
|
|
1405
|
+
cellRendererRegistry,
|
|
1406
|
+
enableSubtreeCopy,
|
|
1407
|
+
enabled,
|
|
1408
|
+
rootRef,
|
|
1409
|
+
rows
|
|
1410
|
+
]
|
|
1176
1411
|
);
|
|
1177
1412
|
useEffect2(() => {
|
|
1178
1413
|
if (!enabled) return;
|
|
1179
1414
|
const handleKeyDown = (e) => {
|
|
1180
1415
|
if (!activeSelectionBounds) return;
|
|
1181
1416
|
if (!(e.ctrlKey || e.metaKey)) return;
|
|
1417
|
+
if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
1182
1420
|
const isSubtreeShortcut = enableSubtreeCopy && e.shiftKey && e.key.toLowerCase() === "c";
|
|
1183
1421
|
const isVisibleCopyShortcut = !e.shiftKey && e.key.toLowerCase() === "c";
|
|
1184
1422
|
if (!isSubtreeShortcut && !isVisibleCopyShortcut) return;
|
|
@@ -2433,6 +2671,10 @@ function useGlideTable(options) {
|
|
|
2433
2671
|
const [hoveredRowIndex, setHoveredRowIndex] = useState4(null);
|
|
2434
2672
|
const scrollRef = useRef5(null);
|
|
2435
2673
|
const rootRef = useRef5(null);
|
|
2674
|
+
const cellRendererRegistry = useMemo3(
|
|
2675
|
+
() => createCellRendererRegistry(cellRenderers),
|
|
2676
|
+
[cellRenderers]
|
|
2677
|
+
);
|
|
2436
2678
|
const shouldVirtualize = enableVirtualization && !enableRowSpan;
|
|
2437
2679
|
useEffect5(() => {
|
|
2438
2680
|
if (enableVirtualization && enableRowSpan) {
|
|
@@ -2616,7 +2858,9 @@ function useGlideTable(options) {
|
|
|
2616
2858
|
onDataChange,
|
|
2617
2859
|
onBatchChange,
|
|
2618
2860
|
onRowsPaste,
|
|
2619
|
-
onCellNavigate: handleCellNavigate
|
|
2861
|
+
onCellNavigate: handleCellNavigate,
|
|
2862
|
+
cellRendererRegistry,
|
|
2863
|
+
rootRef
|
|
2620
2864
|
});
|
|
2621
2865
|
const {
|
|
2622
2866
|
editingCell,
|
|
@@ -2626,10 +2870,6 @@ function useGlideTable(options) {
|
|
|
2626
2870
|
commitEdit,
|
|
2627
2871
|
cancelEdit
|
|
2628
2872
|
} = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
|
|
2629
|
-
const cellRendererRegistry = useMemo3(
|
|
2630
|
-
() => createCellRendererRegistry(cellRenderers),
|
|
2631
|
-
[cellRenderers]
|
|
2632
|
-
);
|
|
2633
2873
|
const commitRenderedCellValue = useCallback4(
|
|
2634
2874
|
(rowId, columnId, value) => commitCellValue({
|
|
2635
2875
|
data: tableData,
|
|
@@ -3011,7 +3251,9 @@ var DataTableContext = createContext(null);
|
|
|
3011
3251
|
function useDataTableRowContext() {
|
|
3012
3252
|
const context = use(DataTableContext);
|
|
3013
3253
|
if (!context) {
|
|
3014
|
-
throw new Error(
|
|
3254
|
+
throw new Error(
|
|
3255
|
+
"useDataTableRowContext must be used within a DataTableContextProvider"
|
|
3256
|
+
);
|
|
3015
3257
|
}
|
|
3016
3258
|
return context;
|
|
3017
3259
|
}
|
|
@@ -3056,8 +3298,105 @@ function ResolvedTableCell({
|
|
|
3056
3298
|
}
|
|
3057
3299
|
|
|
3058
3300
|
// src/components/ui/table/features/column-resize/columnResize.ts
|
|
3301
|
+
function clamp(value, min, max) {
|
|
3302
|
+
return Math.min(Math.max(value, min), max);
|
|
3303
|
+
}
|
|
3304
|
+
function floorOf(column) {
|
|
3305
|
+
return column.minWidth ?? 0;
|
|
3306
|
+
}
|
|
3307
|
+
function ceilOf(column) {
|
|
3308
|
+
return column.maxWidth ?? Number.POSITIVE_INFINITY;
|
|
3309
|
+
}
|
|
3310
|
+
function preferOf(column) {
|
|
3311
|
+
const floor = floorOf(column);
|
|
3312
|
+
const ceil = ceilOf(column);
|
|
3313
|
+
const preferred = column.maxWidth ?? column.minWidth ?? 0;
|
|
3314
|
+
return clamp(preferred, floor, Number.isFinite(ceil) ? ceil : preferred);
|
|
3315
|
+
}
|
|
3316
|
+
function resolveColumnLayoutWidths(containerWidth, columns) {
|
|
3317
|
+
const widths = /* @__PURE__ */ new Map();
|
|
3318
|
+
const fixed = [];
|
|
3319
|
+
const bounded = [];
|
|
3320
|
+
let flexCount = 0;
|
|
3321
|
+
for (const column of columns) {
|
|
3322
|
+
if (column.width != null) {
|
|
3323
|
+
fixed.push(column);
|
|
3324
|
+
} else if (column.minWidth != null || column.maxWidth != null) {
|
|
3325
|
+
bounded.push(column);
|
|
3326
|
+
} else {
|
|
3327
|
+
flexCount += 1;
|
|
3328
|
+
}
|
|
3329
|
+
}
|
|
3330
|
+
let used = 0;
|
|
3331
|
+
for (const column of fixed) {
|
|
3332
|
+
let size = column.width;
|
|
3333
|
+
if (column.minWidth != null) size = Math.max(size, column.minWidth);
|
|
3334
|
+
if (column.maxWidth != null) size = Math.min(size, column.maxWidth);
|
|
3335
|
+
widths.set(column.id, size);
|
|
3336
|
+
used += size;
|
|
3337
|
+
}
|
|
3338
|
+
if (bounded.length === 0) {
|
|
3339
|
+
return widths;
|
|
3340
|
+
}
|
|
3341
|
+
const boundedSizes = /* @__PURE__ */ new Map();
|
|
3342
|
+
let preferredSum = 0;
|
|
3343
|
+
let floorSum = 0;
|
|
3344
|
+
for (const column of bounded) {
|
|
3345
|
+
const preferred = preferOf(column);
|
|
3346
|
+
boundedSizes.set(column.id, preferred);
|
|
3347
|
+
preferredSum += preferred;
|
|
3348
|
+
floorSum += floorOf(column);
|
|
3349
|
+
}
|
|
3350
|
+
if (containerWidth > 0) {
|
|
3351
|
+
const remaining = Math.max(0, containerWidth - used);
|
|
3352
|
+
if (remaining >= preferredSum) {
|
|
3353
|
+
} else if (remaining >= floorSum) {
|
|
3354
|
+
let deficit = preferredSum - remaining;
|
|
3355
|
+
const open = bounded.map((column) => ({
|
|
3356
|
+
id: column.id,
|
|
3357
|
+
current: boundedSizes.get(column.id),
|
|
3358
|
+
floor: floorOf(column)
|
|
3359
|
+
}));
|
|
3360
|
+
while (deficit >= 1) {
|
|
3361
|
+
const shrinkable = open.filter((entry) => entry.current > entry.floor);
|
|
3362
|
+
if (shrinkable.length === 0) break;
|
|
3363
|
+
const portion = Math.floor(deficit / shrinkable.length);
|
|
3364
|
+
const rem = deficit % shrinkable.length;
|
|
3365
|
+
let consumed = 0;
|
|
3366
|
+
for (let index = 0; index < shrinkable.length; index += 1) {
|
|
3367
|
+
const entry = shrinkable[index];
|
|
3368
|
+
const reduce = Math.min(
|
|
3369
|
+
entry.current - entry.floor,
|
|
3370
|
+
portion + (index < rem ? 1 : 0)
|
|
3371
|
+
);
|
|
3372
|
+
entry.current -= reduce;
|
|
3373
|
+
consumed += reduce;
|
|
3374
|
+
}
|
|
3375
|
+
if (consumed === 0) break;
|
|
3376
|
+
deficit -= consumed;
|
|
3377
|
+
}
|
|
3378
|
+
for (const entry of open) {
|
|
3379
|
+
boundedSizes.set(entry.id, entry.current);
|
|
3380
|
+
}
|
|
3381
|
+
} else {
|
|
3382
|
+
for (const column of bounded) {
|
|
3383
|
+
boundedSizes.set(column.id, floorOf(column));
|
|
3384
|
+
}
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
for (const [id, size] of boundedSizes) {
|
|
3388
|
+
widths.set(id, Math.round(size));
|
|
3389
|
+
}
|
|
3390
|
+
return widths;
|
|
3391
|
+
}
|
|
3059
3392
|
function getColumnSizeStyle(size, options) {
|
|
3060
|
-
const {
|
|
3393
|
+
const {
|
|
3394
|
+
force = false,
|
|
3395
|
+
lockMax = false,
|
|
3396
|
+
minWidth,
|
|
3397
|
+
maxWidth,
|
|
3398
|
+
layoutWidth
|
|
3399
|
+
} = options ?? {};
|
|
3061
3400
|
if (lockMax) {
|
|
3062
3401
|
return {
|
|
3063
3402
|
width: size,
|
|
@@ -3065,14 +3404,27 @@ function getColumnSizeStyle(size, options) {
|
|
|
3065
3404
|
maxWidth: size
|
|
3066
3405
|
};
|
|
3067
3406
|
}
|
|
3407
|
+
if (layoutWidth != null) {
|
|
3408
|
+
return {
|
|
3409
|
+
width: layoutWidth,
|
|
3410
|
+
minWidth: layoutWidth,
|
|
3411
|
+
maxWidth: layoutWidth
|
|
3412
|
+
};
|
|
3413
|
+
}
|
|
3414
|
+
const resolvedSize = size;
|
|
3068
3415
|
const hasExplicitSize = force || size !== DATA_TABLE_COLUMN_SIZE;
|
|
3069
3416
|
if (!hasExplicitSize && minWidth == null && maxWidth == null) {
|
|
3070
3417
|
return void 0;
|
|
3071
3418
|
}
|
|
3072
3419
|
const style = {};
|
|
3073
3420
|
if (hasExplicitSize) {
|
|
3074
|
-
|
|
3075
|
-
|
|
3421
|
+
const used = minWidth != null || maxWidth != null ? clamp(
|
|
3422
|
+
resolvedSize,
|
|
3423
|
+
minWidth ?? Number.NEGATIVE_INFINITY,
|
|
3424
|
+
maxWidth ?? Number.POSITIVE_INFINITY
|
|
3425
|
+
) : resolvedSize;
|
|
3426
|
+
style.width = used;
|
|
3427
|
+
style.minWidth = minWidth ?? used;
|
|
3076
3428
|
} else if (minWidth != null) {
|
|
3077
3429
|
style.minWidth = minWidth;
|
|
3078
3430
|
}
|
|
@@ -3297,7 +3649,7 @@ function useColumnReorder(options) {
|
|
|
3297
3649
|
|
|
3298
3650
|
// src/components/ui/table/components/DataTable/DataTable.tsx
|
|
3299
3651
|
import { flexRender as flexRender2 } from "@tanstack/react-table";
|
|
3300
|
-
import { useMemo as useMemo4 } from "react";
|
|
3652
|
+
import { useEffect as useEffect8, useMemo as useMemo4, useState as useState6 } from "react";
|
|
3301
3653
|
|
|
3302
3654
|
// src/components/ui/table/components/DataTable/DataTableRow.tsx
|
|
3303
3655
|
import { flexRender } from "@tanstack/react-table";
|
|
@@ -3463,6 +3815,12 @@ function isInteractiveMouseTarget(target) {
|
|
|
3463
3815
|
].join(",");
|
|
3464
3816
|
return target.closest(interactiveSelector) !== null;
|
|
3465
3817
|
}
|
|
3818
|
+
function blurActiveElementOutside(container) {
|
|
3819
|
+
const active = document.activeElement;
|
|
3820
|
+
if (!(active instanceof HTMLElement) || active === document.body) return;
|
|
3821
|
+
if (container instanceof Node && container.contains(active)) return;
|
|
3822
|
+
active.blur();
|
|
3823
|
+
}
|
|
3466
3824
|
function resolveExpandCellIndex(cells, toggleField) {
|
|
3467
3825
|
if (!toggleField) return 0;
|
|
3468
3826
|
const matchedIndex = cells.findIndex(
|
|
@@ -3495,7 +3853,7 @@ function DataTableRow({
|
|
|
3495
3853
|
columnFreeze,
|
|
3496
3854
|
inlineSearch
|
|
3497
3855
|
} = useDataTableRowContext();
|
|
3498
|
-
const { enableColumnResize } = columnResize;
|
|
3856
|
+
const { enableColumnResize, layoutWidths } = columnResize;
|
|
3499
3857
|
const { enableColumnFreeze, offsets: freezeOffsets } = columnFreeze;
|
|
3500
3858
|
const {
|
|
3501
3859
|
enabled: enableInlineSearch,
|
|
@@ -3690,7 +4048,8 @@ function DataTableRow({
|
|
|
3690
4048
|
force: enableColumnResize,
|
|
3691
4049
|
lockMax: enableColumnResize,
|
|
3692
4050
|
minWidth: meta?.minWidth,
|
|
3693
|
-
maxWidth: meta?.maxWidth
|
|
4051
|
+
maxWidth: meta?.maxWidth,
|
|
4052
|
+
layoutWidth: layoutWidths?.get(columnId)
|
|
3694
4053
|
});
|
|
3695
4054
|
const freezeOffset = enableColumnFreeze ? freezeOffsets.get(columnId) : void 0;
|
|
3696
4055
|
const freezeStyle = getColumnFreezeStyle(freezeOffset);
|
|
@@ -3730,6 +4089,7 @@ function DataTableRow({
|
|
|
3730
4089
|
if (!enableCellSelection) return;
|
|
3731
4090
|
if (isInteractiveMouseTarget(event.target)) return;
|
|
3732
4091
|
event.preventDefault();
|
|
4092
|
+
blurActiveElementOutside(event.currentTarget);
|
|
3733
4093
|
onCellMouseDown(
|
|
3734
4094
|
resolveCellRowIndex(event.clientY, event.currentTarget),
|
|
3735
4095
|
cellIndex,
|
|
@@ -3893,6 +4253,7 @@ function DataTableRow({
|
|
|
3893
4253
|
onMouseDown: (event) => {
|
|
3894
4254
|
event.stopPropagation();
|
|
3895
4255
|
event.preventDefault();
|
|
4256
|
+
blurActiveElementOutside(event.currentTarget);
|
|
3896
4257
|
onFillHandleMouseDown(rowIndex, cellIndex);
|
|
3897
4258
|
}
|
|
3898
4259
|
}
|
|
@@ -4222,17 +4583,74 @@ function DataTable({
|
|
|
4222
4583
|
const RowSlot = slots?.Row ?? DataTableRow;
|
|
4223
4584
|
const PendingSlot = slots?.Pending ?? DefaultPending;
|
|
4224
4585
|
const EmptySlot = slots?.Empty ?? DefaultEmpty;
|
|
4225
|
-
const freezeOffsets = rowContextValue.columnFreeze.offsets;
|
|
4226
4586
|
const headerGroups = getMergedHeaderGroups(table.getHeaderGroups());
|
|
4227
4587
|
const leafColumnIds = table.getVisibleLeafColumns().map((column) => column.id);
|
|
4588
|
+
const columnLayoutMetaSignature = table.getVisibleLeafColumns().map((column) => {
|
|
4589
|
+
const meta = column.columnDef.meta;
|
|
4590
|
+
return `${column.id}:${meta?.width ?? ""}:${meta?.minWidth ?? ""}:${meta?.maxWidth ?? ""}`;
|
|
4591
|
+
}).join("|");
|
|
4228
4592
|
const { isReordering, draggingColumnId, dropTarget, onHeaderPointerDown } = useColumnReorder({
|
|
4229
4593
|
enabled: enableColumnReorder,
|
|
4230
4594
|
columnOrder: leafColumnIds,
|
|
4231
4595
|
onColumnOrderChange: setColumnOrder
|
|
4232
4596
|
});
|
|
4597
|
+
const [containerWidth, setContainerWidth] = useState6(0);
|
|
4598
|
+
useEffect8(() => {
|
|
4599
|
+
if (enableColumnResize || isPending) return;
|
|
4600
|
+
const element = scrollRef.current;
|
|
4601
|
+
if (!element) return;
|
|
4602
|
+
const updateWidth = () => {
|
|
4603
|
+
setContainerWidth(Math.floor(element.clientWidth));
|
|
4604
|
+
};
|
|
4605
|
+
updateWidth();
|
|
4606
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
4607
|
+
const observer = new ResizeObserver(() => {
|
|
4608
|
+
updateWidth();
|
|
4609
|
+
});
|
|
4610
|
+
observer.observe(element);
|
|
4611
|
+
return () => observer.disconnect();
|
|
4612
|
+
}, [enableColumnResize, isPending, scrollRef, rows.length, leafColumnIds.join("|")]);
|
|
4613
|
+
const layoutWidths = useMemo4(() => {
|
|
4614
|
+
if (enableColumnResize) return void 0;
|
|
4615
|
+
const columns = table.getVisibleLeafColumns().map((column) => ({
|
|
4616
|
+
id: column.id,
|
|
4617
|
+
width: column.columnDef.meta?.width,
|
|
4618
|
+
minWidth: column.columnDef.meta?.minWidth,
|
|
4619
|
+
maxWidth: column.columnDef.meta?.maxWidth
|
|
4620
|
+
}));
|
|
4621
|
+
return resolveColumnLayoutWidths(containerWidth, columns);
|
|
4622
|
+
}, [enableColumnResize, containerWidth, table, columnLayoutMetaSignature]);
|
|
4623
|
+
const freezeOffsets = useMemo4(() => {
|
|
4624
|
+
if (!enableColumnFreeze || enableColumnResize || !layoutWidths) {
|
|
4625
|
+
return rowContextValue.columnFreeze.offsets;
|
|
4626
|
+
}
|
|
4627
|
+
const columns = table.getVisibleLeafColumns().map((column) => ({
|
|
4628
|
+
id: column.id,
|
|
4629
|
+
size: layoutWidths.get(column.id) ?? column.getSize(),
|
|
4630
|
+
side: resolveColumnFreezeSide(column.columnDef.meta?.frozen)
|
|
4631
|
+
}));
|
|
4632
|
+
return buildColumnFreezeOffsets(columns);
|
|
4633
|
+
}, [
|
|
4634
|
+
enableColumnFreeze,
|
|
4635
|
+
enableColumnResize,
|
|
4636
|
+
layoutWidths,
|
|
4637
|
+
rowContextValue.columnFreeze.offsets,
|
|
4638
|
+
table
|
|
4639
|
+
]);
|
|
4233
4640
|
const contextValue = useMemo4(
|
|
4234
|
-
() => ({
|
|
4235
|
-
|
|
4641
|
+
() => ({
|
|
4642
|
+
...rowContextValue,
|
|
4643
|
+
classNames,
|
|
4644
|
+
columnFreeze: {
|
|
4645
|
+
...rowContextValue.columnFreeze,
|
|
4646
|
+
offsets: freezeOffsets
|
|
4647
|
+
},
|
|
4648
|
+
columnResize: {
|
|
4649
|
+
...rowContextValue.columnResize,
|
|
4650
|
+
layoutWidths
|
|
4651
|
+
}
|
|
4652
|
+
}),
|
|
4653
|
+
[rowContextValue, classNames, freezeOffsets, layoutWidths]
|
|
4236
4654
|
);
|
|
4237
4655
|
if (isPending) {
|
|
4238
4656
|
return /* @__PURE__ */ jsx7(
|
|
@@ -4313,7 +4731,8 @@ function DataTable({
|
|
|
4313
4731
|
force: enableColumnResize,
|
|
4314
4732
|
lockMax: enableColumnResize,
|
|
4315
4733
|
minWidth: header.column.columnDef.meta?.minWidth,
|
|
4316
|
-
maxWidth: header.column.columnDef.meta?.maxWidth
|
|
4734
|
+
maxWidth: header.column.columnDef.meta?.maxWidth,
|
|
4735
|
+
layoutWidth: layoutWidths?.get(header.column.id)
|
|
4317
4736
|
});
|
|
4318
4737
|
const freezeOffset = enableColumnFreeze ? resolveHeaderFreezeOffset(header.column, freezeOffsets) : void 0;
|
|
4319
4738
|
const freezeStyle = getColumnFreezeStyle(freezeOffset, {
|
|
@@ -4326,7 +4745,9 @@ function DataTable({
|
|
|
4326
4745
|
};
|
|
4327
4746
|
const isPlaceholder = header.isPlaceholder;
|
|
4328
4747
|
const leafColumns = header.column.getLeafColumns();
|
|
4329
|
-
const leafIds = leafColumns.map(
|
|
4748
|
+
const leafIds = leafColumns.map(
|
|
4749
|
+
(leafColumn) => leafColumn.id
|
|
4750
|
+
);
|
|
4330
4751
|
const isLeafHeader = !isPlaceholder && header.subHeaders.length === 0;
|
|
4331
4752
|
const canDrag = enableColumnReorder && !isPlaceholder && leafIds.length > 0 && leafColumns.every(
|
|
4332
4753
|
(leafColumn) => isColumnReorderable(leafColumn.columnDef.meta)
|
|
@@ -4482,7 +4903,7 @@ function DataTable({
|
|
|
4482
4903
|
}
|
|
4483
4904
|
|
|
4484
4905
|
// src/components/ui/table/components/Table/Table.tsx
|
|
4485
|
-
import { useCallback as useCallback7, useMemo as useMemo5, useState as
|
|
4906
|
+
import { useCallback as useCallback7, useMemo as useMemo5, useState as useState7 } from "react";
|
|
4486
4907
|
|
|
4487
4908
|
// src/components/ui/table/components/Table/buildColumnDef.tsx
|
|
4488
4909
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
@@ -4571,6 +4992,7 @@ function buildColumnDef(props, sort, onSort) {
|
|
|
4571
4992
|
cellRender: render,
|
|
4572
4993
|
frozen,
|
|
4573
4994
|
reorderable,
|
|
4995
|
+
width,
|
|
4574
4996
|
minWidth,
|
|
4575
4997
|
maxWidth,
|
|
4576
4998
|
className,
|
|
@@ -4618,10 +5040,10 @@ function countLeafColumns(nodes) {
|
|
|
4618
5040
|
}
|
|
4619
5041
|
|
|
4620
5042
|
// src/components/ui/table/components/Table/parseTableChildren.ts
|
|
4621
|
-
import { Children, isValidElement as
|
|
5043
|
+
import { Children, isValidElement as isValidElement3 } from "react";
|
|
4622
5044
|
|
|
4623
5045
|
// src/components/ui/table/components/Table/tableChildTypes.ts
|
|
4624
|
-
import { isValidElement } from "react";
|
|
5046
|
+
import { isValidElement as isValidElement2 } from "react";
|
|
4625
5047
|
var TABLE_HEADER_DISPLAY_NAME = "Table.Header";
|
|
4626
5048
|
var TABLE_BODY_DISPLAY_NAME = "Table.Body";
|
|
4627
5049
|
var TABLE_COLUMN_DISPLAY_NAME = "Table.Column";
|
|
@@ -4634,19 +5056,19 @@ function getComponentDisplayName(type) {
|
|
|
4634
5056
|
return void 0;
|
|
4635
5057
|
}
|
|
4636
5058
|
function isTableHeaderElement(child) {
|
|
4637
|
-
return
|
|
5059
|
+
return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
|
|
4638
5060
|
}
|
|
4639
5061
|
function isTableBodyElement(child) {
|
|
4640
|
-
return
|
|
5062
|
+
return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
|
|
4641
5063
|
}
|
|
4642
5064
|
function isTableColumnElement(child) {
|
|
4643
|
-
return
|
|
5065
|
+
return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
|
|
4644
5066
|
}
|
|
4645
5067
|
function isTableColumnGroupElement(child) {
|
|
4646
|
-
return
|
|
5068
|
+
return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
|
|
4647
5069
|
}
|
|
4648
5070
|
function isTablePaginationElement(child) {
|
|
4649
|
-
return
|
|
5071
|
+
return isValidElement2(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
|
|
4650
5072
|
}
|
|
4651
5073
|
|
|
4652
5074
|
// src/components/ui/table/components/Table/parseTableChildren.ts
|
|
@@ -4690,7 +5112,7 @@ function walkColumnTreeNodes(children) {
|
|
|
4690
5112
|
});
|
|
4691
5113
|
continue;
|
|
4692
5114
|
}
|
|
4693
|
-
if (
|
|
5115
|
+
if (isValidElement3(child)) {
|
|
4694
5116
|
const nested = child.props.children;
|
|
4695
5117
|
if (nested != null) {
|
|
4696
5118
|
result.push(...walkColumnTreeNodes(nested));
|
|
@@ -4820,7 +5242,7 @@ function TableRoot({
|
|
|
4820
5242
|
() => parseTableChildren(children),
|
|
4821
5243
|
[children]
|
|
4822
5244
|
);
|
|
4823
|
-
const [sort, setSort] =
|
|
5245
|
+
const [sort, setSort] = useState7(null);
|
|
4824
5246
|
const handleSort = useCallback7((field) => {
|
|
4825
5247
|
setSort((previous) => {
|
|
4826
5248
|
if (previous?.field !== field) {
|
|
@@ -4968,6 +5390,7 @@ export {
|
|
|
4968
5390
|
previousSearchIndex,
|
|
4969
5391
|
resolveCellRenderer,
|
|
4970
5392
|
resolveColumnFreezeSide,
|
|
5393
|
+
resolveColumnLayoutWidths,
|
|
4971
5394
|
resolveDataTableLabels,
|
|
4972
5395
|
resolveDropEdge,
|
|
4973
5396
|
resolveHeaderFreezeOffset,
|