@ceed/cds 1.27.2 → 1.28.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/dist/components/DataTable/components.d.ts +3 -2
- package/dist/components/DataTable/hooks.d.ts +2 -0
- package/dist/components/DataTable/styled.d.ts +1 -1
- package/dist/components/DataTable/utils.d.ts +5 -0
- package/dist/index.browser.js +4 -4
- package/dist/index.browser.js.map +4 -4
- package/dist/index.cjs +186 -16
- package/dist/index.js +186 -16
- package/dist/libs/text-measurer.d.ts +8 -0
- package/framer/index.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2091,6 +2091,36 @@ var CurrencyInput_default = CurrencyInput;
|
|
|
2091
2091
|
var import_react28 = __toESM(require("react"));
|
|
2092
2092
|
var import_react_virtual2 = require("@tanstack/react-virtual");
|
|
2093
2093
|
|
|
2094
|
+
// src/libs/text-measurer.ts
|
|
2095
|
+
var TextMeasurer = class {
|
|
2096
|
+
constructor(font) {
|
|
2097
|
+
const canvas = document.createElement("canvas");
|
|
2098
|
+
this.ctx = canvas.getContext("2d");
|
|
2099
|
+
if (this.ctx && font) this.ctx.font = font;
|
|
2100
|
+
}
|
|
2101
|
+
setFont(font) {
|
|
2102
|
+
if (this.ctx) this.ctx.font = font;
|
|
2103
|
+
return this;
|
|
2104
|
+
}
|
|
2105
|
+
setFontFromElement(el) {
|
|
2106
|
+
if (this.ctx) this.ctx.font = getComputedStyle(el).font;
|
|
2107
|
+
return this;
|
|
2108
|
+
}
|
|
2109
|
+
measureText(text) {
|
|
2110
|
+
if (!this.ctx) return 0;
|
|
2111
|
+
return this.ctx.measureText(text).width;
|
|
2112
|
+
}
|
|
2113
|
+
measureMaxWidth(values) {
|
|
2114
|
+
if (!this.ctx) return 0;
|
|
2115
|
+
let max = 0;
|
|
2116
|
+
for (let i = 0; i < values.length; i++) {
|
|
2117
|
+
const w = this.ctx.measureText(values[i]).width;
|
|
2118
|
+
if (w > max) max = w;
|
|
2119
|
+
}
|
|
2120
|
+
return max;
|
|
2121
|
+
}
|
|
2122
|
+
};
|
|
2123
|
+
|
|
2094
2124
|
// src/components/DataTable/utils.ts
|
|
2095
2125
|
function extractFieldsFromGroupingModel(items) {
|
|
2096
2126
|
const fields = /* @__PURE__ */ new Set();
|
|
@@ -2212,6 +2242,71 @@ function getTextAlign(props) {
|
|
|
2212
2242
|
return !props.editMode && ["number", "date", "currency"].includes(props.type || "") ? "end" : "start";
|
|
2213
2243
|
}
|
|
2214
2244
|
var numberFormatter = (value) => "Intl" in window ? new Intl.NumberFormat().format(value) : value;
|
|
2245
|
+
function computeHeaderWidth(headerEl) {
|
|
2246
|
+
const thStyle = getComputedStyle(headerEl);
|
|
2247
|
+
const paddingX = parseFloat(thStyle.paddingLeft) + parseFloat(thStyle.paddingRight);
|
|
2248
|
+
const borderX = parseFloat(thStyle.borderLeftWidth) + parseFloat(thStyle.borderRightWidth);
|
|
2249
|
+
const stack = headerEl.firstElementChild;
|
|
2250
|
+
if (!stack) return paddingX;
|
|
2251
|
+
const stackStyle = getComputedStyle(stack);
|
|
2252
|
+
const gap = parseFloat(stackStyle.gap) || parseFloat(stackStyle.columnGap) || 0;
|
|
2253
|
+
let totalChildWidth = 0;
|
|
2254
|
+
let visibleChildCount = 0;
|
|
2255
|
+
for (const child of Array.from(stack.children)) {
|
|
2256
|
+
const el = child;
|
|
2257
|
+
if (!el.offsetWidth && !el.offsetHeight) continue;
|
|
2258
|
+
visibleChildCount++;
|
|
2259
|
+
const textEl = el.querySelector?.('[data-slot="header-text"]') || (el.dataset?.slot === "header-text" ? el : null);
|
|
2260
|
+
if (textEl) {
|
|
2261
|
+
const htmlEl = textEl;
|
|
2262
|
+
const isMultiLine = getComputedStyle(htmlEl).display === "-webkit-box";
|
|
2263
|
+
if (isMultiLine) {
|
|
2264
|
+
const measurer = new TextMeasurer();
|
|
2265
|
+
measurer.setFontFromElement(htmlEl);
|
|
2266
|
+
totalChildWidth += measurer.measureText(htmlEl.textContent || "");
|
|
2267
|
+
} else {
|
|
2268
|
+
totalChildWidth += htmlEl.scrollWidth;
|
|
2269
|
+
}
|
|
2270
|
+
} else {
|
|
2271
|
+
totalChildWidth += el.offsetWidth;
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
const totalGaps = visibleChildCount > 1 ? (visibleChildCount - 1) * gap : 0;
|
|
2275
|
+
return totalChildWidth + totalGaps + paddingX + borderX;
|
|
2276
|
+
}
|
|
2277
|
+
function computeBodyWidth(headerEl, table, field, dataInPage) {
|
|
2278
|
+
const headId = headerEl.id;
|
|
2279
|
+
const sampleTd = headId ? table.querySelector(`tbody td[headers="${CSS.escape(headId)}"]`) : null;
|
|
2280
|
+
const styleSource = sampleTd || headerEl;
|
|
2281
|
+
const tdStyle = getComputedStyle(styleSource);
|
|
2282
|
+
const bodyPaddingX = parseFloat(tdStyle.paddingLeft) + parseFloat(tdStyle.paddingRight);
|
|
2283
|
+
const bodyBorderX = parseFloat(tdStyle.borderLeftWidth) + parseFloat(tdStyle.borderRightWidth);
|
|
2284
|
+
const measurer = new TextMeasurer();
|
|
2285
|
+
measurer.setFont(tdStyle.font);
|
|
2286
|
+
const texts = [];
|
|
2287
|
+
for (let i = 0; i < dataInPage.length; i++) {
|
|
2288
|
+
const val = dataInPage[i][field];
|
|
2289
|
+
texts.push(val == null ? "" : String(val));
|
|
2290
|
+
}
|
|
2291
|
+
const maxTextWidth = measurer.measureMaxWidth(texts);
|
|
2292
|
+
return maxTextWidth + bodyPaddingX + bodyBorderX;
|
|
2293
|
+
}
|
|
2294
|
+
function computeAutoFitWidth(params) {
|
|
2295
|
+
const { headerEl, field, dataInPage } = params;
|
|
2296
|
+
const table = headerEl.closest("table");
|
|
2297
|
+
if (!table) return null;
|
|
2298
|
+
const headerWidth = computeHeaderWidth(headerEl);
|
|
2299
|
+
const bodyWidth = computeBodyWidth(headerEl, table, field, dataInPage);
|
|
2300
|
+
let finalWidth = Math.ceil(Math.max(headerWidth, bodyWidth));
|
|
2301
|
+
const thStyle = getComputedStyle(headerEl);
|
|
2302
|
+
const resolvedMin = thStyle.minWidth;
|
|
2303
|
+
const resolvedMax = thStyle.maxWidth;
|
|
2304
|
+
const minPx = resolvedMin !== "none" ? parseFloat(resolvedMin) : NaN;
|
|
2305
|
+
const maxPx = resolvedMax !== "none" ? parseFloat(resolvedMax) : NaN;
|
|
2306
|
+
if (!isNaN(minPx) && minPx > 0) finalWidth = Math.max(finalWidth, minPx);
|
|
2307
|
+
if (!isNaN(maxPx) && maxPx > 0) finalWidth = Math.min(finalWidth, maxPx);
|
|
2308
|
+
return finalWidth;
|
|
2309
|
+
}
|
|
2215
2310
|
|
|
2216
2311
|
// src/components/DataTable/styled.tsx
|
|
2217
2312
|
var import_react19 = __toESM(require("react"));
|
|
@@ -2322,7 +2417,7 @@ var StyledTd = (0, import_joy25.styled)("td")(({ theme }) => ({
|
|
|
2322
2417
|
var MotionSortIcon = (0, import_framer_motion17.motion)(import_ArrowUpwardRounded.default);
|
|
2323
2418
|
var DefaultLoadingOverlay = () => /* @__PURE__ */ import_react19.default.createElement(import_joy25.LinearProgress, { value: 8, variant: "plain" });
|
|
2324
2419
|
var DefaultNoRowsOverlay = () => /* @__PURE__ */ import_react19.default.createElement(import_joy25.Typography, { level: "body-sm", textColor: "text.tertiary" }, "No rows");
|
|
2325
|
-
var Resizer = (ref, targetRef = ref, onResizeStateChange) => /* @__PURE__ */ import_react19.default.createElement(
|
|
2420
|
+
var Resizer = (ref, targetRef = ref, onResizeStateChange, onAutoFit) => /* @__PURE__ */ import_react19.default.createElement(
|
|
2326
2421
|
Box_default,
|
|
2327
2422
|
{
|
|
2328
2423
|
sx: {
|
|
@@ -2330,24 +2425,67 @@ var Resizer = (ref, targetRef = ref, onResizeStateChange) => /* @__PURE__ */ imp
|
|
|
2330
2425
|
top: 0,
|
|
2331
2426
|
right: 0,
|
|
2332
2427
|
bottom: 0,
|
|
2333
|
-
width: "
|
|
2334
|
-
cursor: "col-resize"
|
|
2428
|
+
width: "7px",
|
|
2429
|
+
cursor: "col-resize",
|
|
2430
|
+
"&::after": {
|
|
2431
|
+
content: '""',
|
|
2432
|
+
position: "absolute",
|
|
2433
|
+
top: 0,
|
|
2434
|
+
bottom: 0,
|
|
2435
|
+
right: 0,
|
|
2436
|
+
width: "2px",
|
|
2437
|
+
bgcolor: "transparent",
|
|
2438
|
+
transition: "background-color 150ms ease"
|
|
2439
|
+
},
|
|
2440
|
+
"&:hover::after": {
|
|
2441
|
+
bgcolor: "primary.300"
|
|
2442
|
+
},
|
|
2443
|
+
"&[data-resizing]::after": {
|
|
2444
|
+
bgcolor: "primary.500"
|
|
2445
|
+
}
|
|
2335
2446
|
},
|
|
2336
2447
|
onClick: (e) => e.stopPropagation(),
|
|
2448
|
+
onDoubleClick: (e) => {
|
|
2449
|
+
e.stopPropagation();
|
|
2450
|
+
e.preventDefault();
|
|
2451
|
+
onAutoFit?.();
|
|
2452
|
+
},
|
|
2337
2453
|
onMouseDown: (e) => {
|
|
2454
|
+
if (e.detail >= 2) return;
|
|
2455
|
+
const resizerEl = e.currentTarget;
|
|
2456
|
+
resizerEl.dataset.resizing = "";
|
|
2338
2457
|
const initialX = e.clientX;
|
|
2339
2458
|
const initialWidth = ref.current?.getBoundingClientRect().width;
|
|
2340
|
-
|
|
2459
|
+
let activated = false;
|
|
2460
|
+
const DRAG_THRESHOLD = 3;
|
|
2461
|
+
const thStyle = ref.current ? getComputedStyle(ref.current) : null;
|
|
2462
|
+
const minW = thStyle ? parseFloat(thStyle.minWidth) : NaN;
|
|
2463
|
+
const maxW = thStyle ? parseFloat(thStyle.maxWidth) : NaN;
|
|
2341
2464
|
const onMouseMove = (e2) => {
|
|
2342
|
-
if (initialWidth
|
|
2343
|
-
|
|
2344
|
-
|
|
2465
|
+
if (!initialWidth) return;
|
|
2466
|
+
const delta = e2.clientX - initialX;
|
|
2467
|
+
if (!activated) {
|
|
2468
|
+
if (Math.abs(delta) < DRAG_THRESHOLD) return;
|
|
2469
|
+
activated = true;
|
|
2470
|
+
onResizeStateChange?.(true);
|
|
2471
|
+
}
|
|
2472
|
+
if (!ref.current || !targetRef.current) {
|
|
2473
|
+
onMouseUp();
|
|
2474
|
+
return;
|
|
2345
2475
|
}
|
|
2476
|
+
let newWidth = initialWidth + delta;
|
|
2477
|
+
if (!isNaN(minW) && minW > 0) newWidth = Math.max(newWidth, minW);
|
|
2478
|
+
if (!isNaN(maxW) && maxW > 0) newWidth = Math.min(newWidth, maxW);
|
|
2479
|
+
ref.current.style.width = `${newWidth}px`;
|
|
2480
|
+
targetRef.current.style.width = `${newWidth}px`;
|
|
2346
2481
|
};
|
|
2347
2482
|
const onMouseUp = () => {
|
|
2483
|
+
resizerEl.removeAttribute("data-resizing");
|
|
2348
2484
|
document.removeEventListener("mousemove", onMouseMove);
|
|
2349
2485
|
document.removeEventListener("mouseup", onMouseUp);
|
|
2350
|
-
|
|
2486
|
+
if (activated) {
|
|
2487
|
+
requestAnimationFrame(() => onResizeStateChange?.(false));
|
|
2488
|
+
}
|
|
2351
2489
|
};
|
|
2352
2490
|
document.addEventListener("mousemove", onMouseMove);
|
|
2353
2491
|
document.addEventListener("mouseup", onMouseUp);
|
|
@@ -2920,7 +3058,11 @@ function InfoSign(props) {
|
|
|
2920
3058
|
var InfoSign_default = InfoSign;
|
|
2921
3059
|
|
|
2922
3060
|
// src/components/DataTable/components.tsx
|
|
2923
|
-
var TextEllipsis = ({
|
|
3061
|
+
var TextEllipsis = ({
|
|
3062
|
+
children,
|
|
3063
|
+
lineClamp,
|
|
3064
|
+
...rest
|
|
3065
|
+
}) => {
|
|
2924
3066
|
const textRef = (0, import_react24.useRef)(null);
|
|
2925
3067
|
const [showTooltip, setShowTooltip] = (0, import_react24.useState)(false);
|
|
2926
3068
|
(0, import_react24.useLayoutEffect)(() => {
|
|
@@ -2935,7 +3077,7 @@ var TextEllipsis = ({ children, lineClamp }) => {
|
|
|
2935
3077
|
ro.observe(element);
|
|
2936
3078
|
return () => ro.disconnect();
|
|
2937
3079
|
}, [children, lineClamp]);
|
|
2938
|
-
return /* @__PURE__ */ import_react24.default.createElement(Tooltip_default, { title: showTooltip ? children : "", placement: "top" }, /* @__PURE__ */ import_react24.default.createElement(EllipsisDiv, { ref: textRef, lineClamp }, children));
|
|
3080
|
+
return /* @__PURE__ */ import_react24.default.createElement(Tooltip_default, { title: showTooltip ? children : "", placement: "top" }, /* @__PURE__ */ import_react24.default.createElement(EllipsisDiv, { ref: textRef, lineClamp, ...rest }, children));
|
|
2939
3081
|
};
|
|
2940
3082
|
var CellTextEllipsis = ({ children }) => {
|
|
2941
3083
|
const textRef = (0, import_react24.useRef)(null);
|
|
@@ -2987,7 +3129,8 @@ var HeadCell = (props) => {
|
|
|
2987
3129
|
headerRef,
|
|
2988
3130
|
tableColRef,
|
|
2989
3131
|
headerClassName,
|
|
2990
|
-
headerLineClamp
|
|
3132
|
+
headerLineClamp,
|
|
3133
|
+
onAutoFit
|
|
2991
3134
|
} = props;
|
|
2992
3135
|
const theme = (0, import_joy32.useTheme)();
|
|
2993
3136
|
const ref = headerRef;
|
|
@@ -3004,10 +3147,15 @@ var HeadCell = (props) => {
|
|
|
3004
3147
|
);
|
|
3005
3148
|
const isResizingRef = (0, import_react24.useRef)(false);
|
|
3006
3149
|
const resizer = (0, import_react24.useMemo)(
|
|
3007
|
-
() => resizable ?? true ? Resizer(
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3150
|
+
() => resizable ?? true ? Resizer(
|
|
3151
|
+
ref,
|
|
3152
|
+
colRef,
|
|
3153
|
+
(isResizing) => {
|
|
3154
|
+
isResizingRef.current = isResizing;
|
|
3155
|
+
},
|
|
3156
|
+
onAutoFit ? () => onAutoFit(field) : void 0
|
|
3157
|
+
) : null,
|
|
3158
|
+
[resizable, ref, colRef, onAutoFit, field]
|
|
3011
3159
|
);
|
|
3012
3160
|
const style = (0, import_react24.useMemo)(
|
|
3013
3161
|
() => ({
|
|
@@ -3095,7 +3243,7 @@ var HeadCell = (props) => {
|
|
|
3095
3243
|
initial: "initial",
|
|
3096
3244
|
className: computedHeaderClassName
|
|
3097
3245
|
},
|
|
3098
|
-
/* @__PURE__ */ import_react24.default.createElement(Stack_default, { gap: 1, direction: "row", justifyContent: textAlign, alignItems: "center", sx: { minWidth: 0 } }, textAlign === "end" && sortIcon, textAlign === "end" && infoSign, /* @__PURE__ */ import_react24.default.createElement(TextEllipsis, { lineClamp: headerLineClamp }, headerName ?? field, editMode && required && /* @__PURE__ */ import_react24.default.createElement(Asterisk, null, "*")), textAlign === "start" && infoSign, textAlign === "start" && sortIcon),
|
|
3246
|
+
/* @__PURE__ */ import_react24.default.createElement(Stack_default, { gap: 1, direction: "row", justifyContent: textAlign, alignItems: "center", sx: { minWidth: 0 } }, textAlign === "end" && sortIcon, textAlign === "end" && infoSign, /* @__PURE__ */ import_react24.default.createElement(TextEllipsis, { lineClamp: headerLineClamp, "data-slot": "header-text" }, headerName ?? field, editMode && required && /* @__PURE__ */ import_react24.default.createElement(Asterisk, null, "*")), textAlign === "start" && infoSign, textAlign === "start" && sortIcon),
|
|
3099
3247
|
resizer
|
|
3100
3248
|
);
|
|
3101
3249
|
};
|
|
@@ -3642,6 +3790,25 @@ function useDataTableRenderer({
|
|
|
3642
3790
|
prevRowsRef.current = _rows;
|
|
3643
3791
|
}
|
|
3644
3792
|
}, [_rows]);
|
|
3793
|
+
const handleAutoFit = (0, import_react25.useCallback)(
|
|
3794
|
+
(field) => {
|
|
3795
|
+
const colDef = visibleColumnsByField[field];
|
|
3796
|
+
if (!colDef?.headerRef.current) return;
|
|
3797
|
+
const column = allColumnsByField[field];
|
|
3798
|
+
const columnType = column && "type" in column ? column.type : void 0;
|
|
3799
|
+
if (columnType === "actions") return;
|
|
3800
|
+
const optimalWidth = computeAutoFitWidth({
|
|
3801
|
+
headerEl: colDef.headerRef.current,
|
|
3802
|
+
field,
|
|
3803
|
+
dataInPage
|
|
3804
|
+
});
|
|
3805
|
+
if (optimalWidth == null) return;
|
|
3806
|
+
const widthPx = `${optimalWidth}px`;
|
|
3807
|
+
colDef.headerRef.current.style.width = widthPx;
|
|
3808
|
+
if (colDef.tableColRef.current) colDef.tableColRef.current.style.width = widthPx;
|
|
3809
|
+
},
|
|
3810
|
+
[visibleColumnsByField, allColumnsByField, dataInPage]
|
|
3811
|
+
);
|
|
3645
3812
|
return {
|
|
3646
3813
|
rowCount,
|
|
3647
3814
|
selectableRowCount,
|
|
@@ -3653,6 +3820,7 @@ function useDataTableRenderer({
|
|
|
3653
3820
|
BodyRow,
|
|
3654
3821
|
dataInPage,
|
|
3655
3822
|
handleSortChange,
|
|
3823
|
+
handleAutoFit,
|
|
3656
3824
|
isAllSelected,
|
|
3657
3825
|
isTotalSelected,
|
|
3658
3826
|
isSelectedRow: (0, import_react25.useCallback)((model) => selectedModelSet.has(model), [selectedModelSet]),
|
|
@@ -4083,6 +4251,7 @@ function Component(props, apiRef) {
|
|
|
4083
4251
|
pageSize,
|
|
4084
4252
|
onPaginationModelChange,
|
|
4085
4253
|
handleSortChange,
|
|
4254
|
+
handleAutoFit,
|
|
4086
4255
|
dataInPage,
|
|
4087
4256
|
isTotalSelected,
|
|
4088
4257
|
focusedRowId,
|
|
@@ -4361,6 +4530,7 @@ function Component(props, apiRef) {
|
|
|
4361
4530
|
stickyHeader: props.stickyHeader,
|
|
4362
4531
|
editMode: !!c.isCellEditable,
|
|
4363
4532
|
onSortChange: handleSortChange,
|
|
4533
|
+
onAutoFit: handleAutoFit,
|
|
4364
4534
|
...c
|
|
4365
4535
|
}
|
|
4366
4536
|
)
|
package/dist/index.js
CHANGED
|
@@ -1965,6 +1965,36 @@ import React25, {
|
|
|
1965
1965
|
} from "react";
|
|
1966
1966
|
import { useVirtualizer as useVirtualizer2 } from "@tanstack/react-virtual";
|
|
1967
1967
|
|
|
1968
|
+
// src/libs/text-measurer.ts
|
|
1969
|
+
var TextMeasurer = class {
|
|
1970
|
+
constructor(font) {
|
|
1971
|
+
const canvas = document.createElement("canvas");
|
|
1972
|
+
this.ctx = canvas.getContext("2d");
|
|
1973
|
+
if (this.ctx && font) this.ctx.font = font;
|
|
1974
|
+
}
|
|
1975
|
+
setFont(font) {
|
|
1976
|
+
if (this.ctx) this.ctx.font = font;
|
|
1977
|
+
return this;
|
|
1978
|
+
}
|
|
1979
|
+
setFontFromElement(el) {
|
|
1980
|
+
if (this.ctx) this.ctx.font = getComputedStyle(el).font;
|
|
1981
|
+
return this;
|
|
1982
|
+
}
|
|
1983
|
+
measureText(text) {
|
|
1984
|
+
if (!this.ctx) return 0;
|
|
1985
|
+
return this.ctx.measureText(text).width;
|
|
1986
|
+
}
|
|
1987
|
+
measureMaxWidth(values) {
|
|
1988
|
+
if (!this.ctx) return 0;
|
|
1989
|
+
let max = 0;
|
|
1990
|
+
for (let i = 0; i < values.length; i++) {
|
|
1991
|
+
const w = this.ctx.measureText(values[i]).width;
|
|
1992
|
+
if (w > max) max = w;
|
|
1993
|
+
}
|
|
1994
|
+
return max;
|
|
1995
|
+
}
|
|
1996
|
+
};
|
|
1997
|
+
|
|
1968
1998
|
// src/components/DataTable/utils.ts
|
|
1969
1999
|
function extractFieldsFromGroupingModel(items) {
|
|
1970
2000
|
const fields = /* @__PURE__ */ new Set();
|
|
@@ -2086,6 +2116,71 @@ function getTextAlign(props) {
|
|
|
2086
2116
|
return !props.editMode && ["number", "date", "currency"].includes(props.type || "") ? "end" : "start";
|
|
2087
2117
|
}
|
|
2088
2118
|
var numberFormatter = (value) => "Intl" in window ? new Intl.NumberFormat().format(value) : value;
|
|
2119
|
+
function computeHeaderWidth(headerEl) {
|
|
2120
|
+
const thStyle = getComputedStyle(headerEl);
|
|
2121
|
+
const paddingX = parseFloat(thStyle.paddingLeft) + parseFloat(thStyle.paddingRight);
|
|
2122
|
+
const borderX = parseFloat(thStyle.borderLeftWidth) + parseFloat(thStyle.borderRightWidth);
|
|
2123
|
+
const stack = headerEl.firstElementChild;
|
|
2124
|
+
if (!stack) return paddingX;
|
|
2125
|
+
const stackStyle = getComputedStyle(stack);
|
|
2126
|
+
const gap = parseFloat(stackStyle.gap) || parseFloat(stackStyle.columnGap) || 0;
|
|
2127
|
+
let totalChildWidth = 0;
|
|
2128
|
+
let visibleChildCount = 0;
|
|
2129
|
+
for (const child of Array.from(stack.children)) {
|
|
2130
|
+
const el = child;
|
|
2131
|
+
if (!el.offsetWidth && !el.offsetHeight) continue;
|
|
2132
|
+
visibleChildCount++;
|
|
2133
|
+
const textEl = el.querySelector?.('[data-slot="header-text"]') || (el.dataset?.slot === "header-text" ? el : null);
|
|
2134
|
+
if (textEl) {
|
|
2135
|
+
const htmlEl = textEl;
|
|
2136
|
+
const isMultiLine = getComputedStyle(htmlEl).display === "-webkit-box";
|
|
2137
|
+
if (isMultiLine) {
|
|
2138
|
+
const measurer = new TextMeasurer();
|
|
2139
|
+
measurer.setFontFromElement(htmlEl);
|
|
2140
|
+
totalChildWidth += measurer.measureText(htmlEl.textContent || "");
|
|
2141
|
+
} else {
|
|
2142
|
+
totalChildWidth += htmlEl.scrollWidth;
|
|
2143
|
+
}
|
|
2144
|
+
} else {
|
|
2145
|
+
totalChildWidth += el.offsetWidth;
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
const totalGaps = visibleChildCount > 1 ? (visibleChildCount - 1) * gap : 0;
|
|
2149
|
+
return totalChildWidth + totalGaps + paddingX + borderX;
|
|
2150
|
+
}
|
|
2151
|
+
function computeBodyWidth(headerEl, table, field, dataInPage) {
|
|
2152
|
+
const headId = headerEl.id;
|
|
2153
|
+
const sampleTd = headId ? table.querySelector(`tbody td[headers="${CSS.escape(headId)}"]`) : null;
|
|
2154
|
+
const styleSource = sampleTd || headerEl;
|
|
2155
|
+
const tdStyle = getComputedStyle(styleSource);
|
|
2156
|
+
const bodyPaddingX = parseFloat(tdStyle.paddingLeft) + parseFloat(tdStyle.paddingRight);
|
|
2157
|
+
const bodyBorderX = parseFloat(tdStyle.borderLeftWidth) + parseFloat(tdStyle.borderRightWidth);
|
|
2158
|
+
const measurer = new TextMeasurer();
|
|
2159
|
+
measurer.setFont(tdStyle.font);
|
|
2160
|
+
const texts = [];
|
|
2161
|
+
for (let i = 0; i < dataInPage.length; i++) {
|
|
2162
|
+
const val = dataInPage[i][field];
|
|
2163
|
+
texts.push(val == null ? "" : String(val));
|
|
2164
|
+
}
|
|
2165
|
+
const maxTextWidth = measurer.measureMaxWidth(texts);
|
|
2166
|
+
return maxTextWidth + bodyPaddingX + bodyBorderX;
|
|
2167
|
+
}
|
|
2168
|
+
function computeAutoFitWidth(params) {
|
|
2169
|
+
const { headerEl, field, dataInPage } = params;
|
|
2170
|
+
const table = headerEl.closest("table");
|
|
2171
|
+
if (!table) return null;
|
|
2172
|
+
const headerWidth = computeHeaderWidth(headerEl);
|
|
2173
|
+
const bodyWidth = computeBodyWidth(headerEl, table, field, dataInPage);
|
|
2174
|
+
let finalWidth = Math.ceil(Math.max(headerWidth, bodyWidth));
|
|
2175
|
+
const thStyle = getComputedStyle(headerEl);
|
|
2176
|
+
const resolvedMin = thStyle.minWidth;
|
|
2177
|
+
const resolvedMax = thStyle.maxWidth;
|
|
2178
|
+
const minPx = resolvedMin !== "none" ? parseFloat(resolvedMin) : NaN;
|
|
2179
|
+
const maxPx = resolvedMax !== "none" ? parseFloat(resolvedMax) : NaN;
|
|
2180
|
+
if (!isNaN(minPx) && minPx > 0) finalWidth = Math.max(finalWidth, minPx);
|
|
2181
|
+
if (!isNaN(maxPx) && maxPx > 0) finalWidth = Math.min(finalWidth, maxPx);
|
|
2182
|
+
return finalWidth;
|
|
2183
|
+
}
|
|
2089
2184
|
|
|
2090
2185
|
// src/components/DataTable/styled.tsx
|
|
2091
2186
|
import React17 from "react";
|
|
@@ -2196,7 +2291,7 @@ var StyledTd = styled8("td")(({ theme }) => ({
|
|
|
2196
2291
|
var MotionSortIcon = motion17(SortIcon);
|
|
2197
2292
|
var DefaultLoadingOverlay = () => /* @__PURE__ */ React17.createElement(LinearProgress, { value: 8, variant: "plain" });
|
|
2198
2293
|
var DefaultNoRowsOverlay = () => /* @__PURE__ */ React17.createElement(Typography3, { level: "body-sm", textColor: "text.tertiary" }, "No rows");
|
|
2199
|
-
var Resizer = (ref, targetRef = ref, onResizeStateChange) => /* @__PURE__ */ React17.createElement(
|
|
2294
|
+
var Resizer = (ref, targetRef = ref, onResizeStateChange, onAutoFit) => /* @__PURE__ */ React17.createElement(
|
|
2200
2295
|
Box_default,
|
|
2201
2296
|
{
|
|
2202
2297
|
sx: {
|
|
@@ -2204,24 +2299,67 @@ var Resizer = (ref, targetRef = ref, onResizeStateChange) => /* @__PURE__ */ Rea
|
|
|
2204
2299
|
top: 0,
|
|
2205
2300
|
right: 0,
|
|
2206
2301
|
bottom: 0,
|
|
2207
|
-
width: "
|
|
2208
|
-
cursor: "col-resize"
|
|
2302
|
+
width: "7px",
|
|
2303
|
+
cursor: "col-resize",
|
|
2304
|
+
"&::after": {
|
|
2305
|
+
content: '""',
|
|
2306
|
+
position: "absolute",
|
|
2307
|
+
top: 0,
|
|
2308
|
+
bottom: 0,
|
|
2309
|
+
right: 0,
|
|
2310
|
+
width: "2px",
|
|
2311
|
+
bgcolor: "transparent",
|
|
2312
|
+
transition: "background-color 150ms ease"
|
|
2313
|
+
},
|
|
2314
|
+
"&:hover::after": {
|
|
2315
|
+
bgcolor: "primary.300"
|
|
2316
|
+
},
|
|
2317
|
+
"&[data-resizing]::after": {
|
|
2318
|
+
bgcolor: "primary.500"
|
|
2319
|
+
}
|
|
2209
2320
|
},
|
|
2210
2321
|
onClick: (e) => e.stopPropagation(),
|
|
2322
|
+
onDoubleClick: (e) => {
|
|
2323
|
+
e.stopPropagation();
|
|
2324
|
+
e.preventDefault();
|
|
2325
|
+
onAutoFit?.();
|
|
2326
|
+
},
|
|
2211
2327
|
onMouseDown: (e) => {
|
|
2328
|
+
if (e.detail >= 2) return;
|
|
2329
|
+
const resizerEl = e.currentTarget;
|
|
2330
|
+
resizerEl.dataset.resizing = "";
|
|
2212
2331
|
const initialX = e.clientX;
|
|
2213
2332
|
const initialWidth = ref.current?.getBoundingClientRect().width;
|
|
2214
|
-
|
|
2333
|
+
let activated = false;
|
|
2334
|
+
const DRAG_THRESHOLD = 3;
|
|
2335
|
+
const thStyle = ref.current ? getComputedStyle(ref.current) : null;
|
|
2336
|
+
const minW = thStyle ? parseFloat(thStyle.minWidth) : NaN;
|
|
2337
|
+
const maxW = thStyle ? parseFloat(thStyle.maxWidth) : NaN;
|
|
2215
2338
|
const onMouseMove = (e2) => {
|
|
2216
|
-
if (initialWidth
|
|
2217
|
-
|
|
2218
|
-
|
|
2339
|
+
if (!initialWidth) return;
|
|
2340
|
+
const delta = e2.clientX - initialX;
|
|
2341
|
+
if (!activated) {
|
|
2342
|
+
if (Math.abs(delta) < DRAG_THRESHOLD) return;
|
|
2343
|
+
activated = true;
|
|
2344
|
+
onResizeStateChange?.(true);
|
|
2345
|
+
}
|
|
2346
|
+
if (!ref.current || !targetRef.current) {
|
|
2347
|
+
onMouseUp();
|
|
2348
|
+
return;
|
|
2219
2349
|
}
|
|
2350
|
+
let newWidth = initialWidth + delta;
|
|
2351
|
+
if (!isNaN(minW) && minW > 0) newWidth = Math.max(newWidth, minW);
|
|
2352
|
+
if (!isNaN(maxW) && maxW > 0) newWidth = Math.min(newWidth, maxW);
|
|
2353
|
+
ref.current.style.width = `${newWidth}px`;
|
|
2354
|
+
targetRef.current.style.width = `${newWidth}px`;
|
|
2220
2355
|
};
|
|
2221
2356
|
const onMouseUp = () => {
|
|
2357
|
+
resizerEl.removeAttribute("data-resizing");
|
|
2222
2358
|
document.removeEventListener("mousemove", onMouseMove);
|
|
2223
2359
|
document.removeEventListener("mouseup", onMouseUp);
|
|
2224
|
-
|
|
2360
|
+
if (activated) {
|
|
2361
|
+
requestAnimationFrame(() => onResizeStateChange?.(false));
|
|
2362
|
+
}
|
|
2225
2363
|
};
|
|
2226
2364
|
document.addEventListener("mousemove", onMouseMove);
|
|
2227
2365
|
document.addEventListener("mouseup", onMouseUp);
|
|
@@ -2803,7 +2941,11 @@ function InfoSign(props) {
|
|
|
2803
2941
|
var InfoSign_default = InfoSign;
|
|
2804
2942
|
|
|
2805
2943
|
// src/components/DataTable/components.tsx
|
|
2806
|
-
var TextEllipsis = ({
|
|
2944
|
+
var TextEllipsis = ({
|
|
2945
|
+
children,
|
|
2946
|
+
lineClamp,
|
|
2947
|
+
...rest
|
|
2948
|
+
}) => {
|
|
2807
2949
|
const textRef = useRef5(null);
|
|
2808
2950
|
const [showTooltip, setShowTooltip] = useState8(false);
|
|
2809
2951
|
useLayoutEffect(() => {
|
|
@@ -2818,7 +2960,7 @@ var TextEllipsis = ({ children, lineClamp }) => {
|
|
|
2818
2960
|
ro.observe(element);
|
|
2819
2961
|
return () => ro.disconnect();
|
|
2820
2962
|
}, [children, lineClamp]);
|
|
2821
|
-
return /* @__PURE__ */ React22.createElement(Tooltip_default, { title: showTooltip ? children : "", placement: "top" }, /* @__PURE__ */ React22.createElement(EllipsisDiv, { ref: textRef, lineClamp }, children));
|
|
2963
|
+
return /* @__PURE__ */ React22.createElement(Tooltip_default, { title: showTooltip ? children : "", placement: "top" }, /* @__PURE__ */ React22.createElement(EllipsisDiv, { ref: textRef, lineClamp, ...rest }, children));
|
|
2822
2964
|
};
|
|
2823
2965
|
var CellTextEllipsis = ({ children }) => {
|
|
2824
2966
|
const textRef = useRef5(null);
|
|
@@ -2870,7 +3012,8 @@ var HeadCell = (props) => {
|
|
|
2870
3012
|
headerRef,
|
|
2871
3013
|
tableColRef,
|
|
2872
3014
|
headerClassName,
|
|
2873
|
-
headerLineClamp
|
|
3015
|
+
headerLineClamp,
|
|
3016
|
+
onAutoFit
|
|
2874
3017
|
} = props;
|
|
2875
3018
|
const theme = useTheme();
|
|
2876
3019
|
const ref = headerRef;
|
|
@@ -2887,10 +3030,15 @@ var HeadCell = (props) => {
|
|
|
2887
3030
|
);
|
|
2888
3031
|
const isResizingRef = useRef5(false);
|
|
2889
3032
|
const resizer = useMemo8(
|
|
2890
|
-
() => resizable ?? true ? Resizer(
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
3033
|
+
() => resizable ?? true ? Resizer(
|
|
3034
|
+
ref,
|
|
3035
|
+
colRef,
|
|
3036
|
+
(isResizing) => {
|
|
3037
|
+
isResizingRef.current = isResizing;
|
|
3038
|
+
},
|
|
3039
|
+
onAutoFit ? () => onAutoFit(field) : void 0
|
|
3040
|
+
) : null,
|
|
3041
|
+
[resizable, ref, colRef, onAutoFit, field]
|
|
2894
3042
|
);
|
|
2895
3043
|
const style = useMemo8(
|
|
2896
3044
|
() => ({
|
|
@@ -2978,7 +3126,7 @@ var HeadCell = (props) => {
|
|
|
2978
3126
|
initial: "initial",
|
|
2979
3127
|
className: computedHeaderClassName
|
|
2980
3128
|
},
|
|
2981
|
-
/* @__PURE__ */ React22.createElement(Stack_default, { gap: 1, direction: "row", justifyContent: textAlign, alignItems: "center", sx: { minWidth: 0 } }, textAlign === "end" && sortIcon, textAlign === "end" && infoSign, /* @__PURE__ */ React22.createElement(TextEllipsis, { lineClamp: headerLineClamp }, headerName ?? field, editMode && required && /* @__PURE__ */ React22.createElement(Asterisk, null, "*")), textAlign === "start" && infoSign, textAlign === "start" && sortIcon),
|
|
3129
|
+
/* @__PURE__ */ React22.createElement(Stack_default, { gap: 1, direction: "row", justifyContent: textAlign, alignItems: "center", sx: { minWidth: 0 } }, textAlign === "end" && sortIcon, textAlign === "end" && infoSign, /* @__PURE__ */ React22.createElement(TextEllipsis, { lineClamp: headerLineClamp, "data-slot": "header-text" }, headerName ?? field, editMode && required && /* @__PURE__ */ React22.createElement(Asterisk, null, "*")), textAlign === "start" && infoSign, textAlign === "start" && sortIcon),
|
|
2982
3130
|
resizer
|
|
2983
3131
|
);
|
|
2984
3132
|
};
|
|
@@ -3525,6 +3673,25 @@ function useDataTableRenderer({
|
|
|
3525
3673
|
prevRowsRef.current = _rows;
|
|
3526
3674
|
}
|
|
3527
3675
|
}, [_rows]);
|
|
3676
|
+
const handleAutoFit = useCallback10(
|
|
3677
|
+
(field) => {
|
|
3678
|
+
const colDef = visibleColumnsByField[field];
|
|
3679
|
+
if (!colDef?.headerRef.current) return;
|
|
3680
|
+
const column = allColumnsByField[field];
|
|
3681
|
+
const columnType = column && "type" in column ? column.type : void 0;
|
|
3682
|
+
if (columnType === "actions") return;
|
|
3683
|
+
const optimalWidth = computeAutoFitWidth({
|
|
3684
|
+
headerEl: colDef.headerRef.current,
|
|
3685
|
+
field,
|
|
3686
|
+
dataInPage
|
|
3687
|
+
});
|
|
3688
|
+
if (optimalWidth == null) return;
|
|
3689
|
+
const widthPx = `${optimalWidth}px`;
|
|
3690
|
+
colDef.headerRef.current.style.width = widthPx;
|
|
3691
|
+
if (colDef.tableColRef.current) colDef.tableColRef.current.style.width = widthPx;
|
|
3692
|
+
},
|
|
3693
|
+
[visibleColumnsByField, allColumnsByField, dataInPage]
|
|
3694
|
+
);
|
|
3528
3695
|
return {
|
|
3529
3696
|
rowCount,
|
|
3530
3697
|
selectableRowCount,
|
|
@@ -3536,6 +3703,7 @@ function useDataTableRenderer({
|
|
|
3536
3703
|
BodyRow,
|
|
3537
3704
|
dataInPage,
|
|
3538
3705
|
handleSortChange,
|
|
3706
|
+
handleAutoFit,
|
|
3539
3707
|
isAllSelected,
|
|
3540
3708
|
isTotalSelected,
|
|
3541
3709
|
isSelectedRow: useCallback10((model) => selectedModelSet.has(model), [selectedModelSet]),
|
|
@@ -3966,6 +4134,7 @@ function Component(props, apiRef) {
|
|
|
3966
4134
|
pageSize,
|
|
3967
4135
|
onPaginationModelChange,
|
|
3968
4136
|
handleSortChange,
|
|
4137
|
+
handleAutoFit,
|
|
3969
4138
|
dataInPage,
|
|
3970
4139
|
isTotalSelected,
|
|
3971
4140
|
focusedRowId,
|
|
@@ -4244,6 +4413,7 @@ function Component(props, apiRef) {
|
|
|
4244
4413
|
stickyHeader: props.stickyHeader,
|
|
4245
4414
|
editMode: !!c.isCellEditable,
|
|
4246
4415
|
onSortChange: handleSortChange,
|
|
4416
|
+
onAutoFit: handleAutoFit,
|
|
4247
4417
|
...c
|
|
4248
4418
|
}
|
|
4249
4419
|
)
|