@open-mercato/ui 0.6.7-develop.6552.1.5208a19369 → 0.6.7-develop.6565.1.1026d85fff
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.
|
@@ -200,6 +200,8 @@ function resolveExportSections(config) {
|
|
|
200
200
|
}
|
|
201
201
|
const PERSPECTIVE_COOKIE_PREFIX = "om_table_perspective";
|
|
202
202
|
const PERSPECTIVE_STORAGE_PREFIX = "om_table_perspective_snapshot";
|
|
203
|
+
const COLUMN_MIN_WIDTH = 60;
|
|
204
|
+
const COLUMN_MAX_WIDTH = 900;
|
|
203
205
|
function formatDurationLabel(durationMs) {
|
|
204
206
|
if (durationMs == null) return "";
|
|
205
207
|
if (!Number.isFinite(durationMs)) return "";
|
|
@@ -271,6 +273,16 @@ function sanitizePerspectiveSettings(source) {
|
|
|
271
273
|
result.columnVisibility = visibility;
|
|
272
274
|
}
|
|
273
275
|
}
|
|
276
|
+
if (source.columnSizing && typeof source.columnSizing === "object") {
|
|
277
|
+
const sizing = {};
|
|
278
|
+
for (const [key, value] of Object.entries(source.columnSizing)) {
|
|
279
|
+
const id = typeof key === "string" ? key.trim() : "";
|
|
280
|
+
if (!id || forbidden.has(id)) continue;
|
|
281
|
+
if (typeof value !== "number" || !Number.isFinite(value)) continue;
|
|
282
|
+
sizing[id] = Math.max(COLUMN_MIN_WIDTH, Math.min(COLUMN_MAX_WIDTH, Math.round(value)));
|
|
283
|
+
}
|
|
284
|
+
if (Object.keys(sizing).length) result.columnSizing = sizing;
|
|
285
|
+
}
|
|
274
286
|
if (Array.isArray(source.sorting)) {
|
|
275
287
|
const sorting = source.sorting.map((item) => {
|
|
276
288
|
const id = typeof item?.id === "string" ? item.id.trim() : "";
|
|
@@ -487,7 +499,86 @@ function HeaderDndWrapper({ enabled, contextId, sensors, columnIds, onDragEnd, c
|
|
|
487
499
|
if (!enabled) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
488
500
|
return /* @__PURE__ */ jsx(DndContext, { id: contextId, sensors, collisionDetection: closestCenter, onDragEnd, children: /* @__PURE__ */ jsx(SortableContext, { items: columnIds, strategy: horizontalListSortingStrategy, children }) });
|
|
489
501
|
}
|
|
490
|
-
function
|
|
502
|
+
function ColumnResizeHandle({
|
|
503
|
+
columnId,
|
|
504
|
+
onResize,
|
|
505
|
+
onCommit,
|
|
506
|
+
onReset,
|
|
507
|
+
ariaLabel
|
|
508
|
+
}) {
|
|
509
|
+
const [active, setActive] = React.useState(false);
|
|
510
|
+
const dragCleanupRef = React.useRef(null);
|
|
511
|
+
React.useEffect(() => () => {
|
|
512
|
+
dragCleanupRef.current?.();
|
|
513
|
+
}, []);
|
|
514
|
+
const handlePointerDown = React.useCallback((event) => {
|
|
515
|
+
if (event.button !== 0) return;
|
|
516
|
+
event.preventDefault();
|
|
517
|
+
event.stopPropagation();
|
|
518
|
+
const headerCell = event.currentTarget.parentElement;
|
|
519
|
+
if (!headerCell) return;
|
|
520
|
+
const startX = event.clientX;
|
|
521
|
+
const startWidth = headerCell.getBoundingClientRect().width;
|
|
522
|
+
setActive(true);
|
|
523
|
+
let frame = 0;
|
|
524
|
+
let latest = startWidth;
|
|
525
|
+
const onMove = (moveEvent) => {
|
|
526
|
+
latest = Math.max(COLUMN_MIN_WIDTH, Math.min(COLUMN_MAX_WIDTH, Math.round(startWidth + (moveEvent.clientX - startX))));
|
|
527
|
+
if (frame) return;
|
|
528
|
+
frame = window.requestAnimationFrame(() => {
|
|
529
|
+
frame = 0;
|
|
530
|
+
onResize(columnId, latest);
|
|
531
|
+
});
|
|
532
|
+
};
|
|
533
|
+
const teardown = () => {
|
|
534
|
+
if (frame) window.cancelAnimationFrame(frame);
|
|
535
|
+
document.removeEventListener("pointermove", onMove);
|
|
536
|
+
document.removeEventListener("pointerup", onUp);
|
|
537
|
+
document.body.style.cursor = "";
|
|
538
|
+
document.body.style.userSelect = "";
|
|
539
|
+
dragCleanupRef.current = null;
|
|
540
|
+
};
|
|
541
|
+
const onUp = () => {
|
|
542
|
+
onResize(columnId, latest);
|
|
543
|
+
teardown();
|
|
544
|
+
setActive(false);
|
|
545
|
+
onCommit();
|
|
546
|
+
};
|
|
547
|
+
dragCleanupRef.current = teardown;
|
|
548
|
+
document.addEventListener("pointermove", onMove);
|
|
549
|
+
document.addEventListener("pointerup", onUp);
|
|
550
|
+
document.body.style.cursor = "col-resize";
|
|
551
|
+
document.body.style.userSelect = "none";
|
|
552
|
+
}, [columnId, onResize, onCommit]);
|
|
553
|
+
return /* @__PURE__ */ jsx(
|
|
554
|
+
"div",
|
|
555
|
+
{
|
|
556
|
+
role: "separator",
|
|
557
|
+
"aria-orientation": "vertical",
|
|
558
|
+
"aria-label": ariaLabel,
|
|
559
|
+
title: ariaLabel,
|
|
560
|
+
onPointerDown: handlePointerDown,
|
|
561
|
+
onClick: (event) => event.stopPropagation(),
|
|
562
|
+
onDoubleClick: (event) => {
|
|
563
|
+
event.preventDefault();
|
|
564
|
+
event.stopPropagation();
|
|
565
|
+
onReset(columnId);
|
|
566
|
+
},
|
|
567
|
+
className: "group/resize absolute right-0 top-0 z-10 flex h-full w-3 translate-x-1/2 cursor-col-resize touch-none select-none items-center justify-center",
|
|
568
|
+
children: /* @__PURE__ */ jsx(
|
|
569
|
+
"span",
|
|
570
|
+
{
|
|
571
|
+
"aria-hidden": true,
|
|
572
|
+
className: cn(
|
|
573
|
+
"w-0.5 rounded-full transition-all",
|
|
574
|
+
active ? "h-full bg-primary" : "h-3.5 bg-border group-hover:h-full group-hover:bg-border group-hover/resize:h-full group-hover/resize:bg-primary"
|
|
575
|
+
)
|
|
576
|
+
}
|
|
577
|
+
)
|
|
578
|
+
}
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
function SortableHeaderCell({ id, children, className, width }) {
|
|
491
582
|
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id });
|
|
492
583
|
const isSticky = typeof className === "string" && className.includes("sticky");
|
|
493
584
|
const style = {
|
|
@@ -495,7 +586,8 @@ function SortableHeaderCell({ id, children, className }) {
|
|
|
495
586
|
transition,
|
|
496
587
|
opacity: isDragging ? 0.5 : 1,
|
|
497
588
|
cursor: "grab",
|
|
498
|
-
position: isSticky ? "sticky" : "relative"
|
|
589
|
+
position: isSticky ? "sticky" : "relative",
|
|
590
|
+
...typeof width === "number" ? { width, minWidth: width, maxWidth: width } : {}
|
|
499
591
|
};
|
|
500
592
|
return /* @__PURE__ */ jsx(TableHead, { ref: setNodeRef, style, className, ...attributes, ...listeners, children });
|
|
501
593
|
}
|
|
@@ -716,6 +808,11 @@ function DataTable({
|
|
|
716
808
|
const [activePerspectiveId, setActivePerspectiveId] = React.useState(initialActiveId);
|
|
717
809
|
const [columnVisibility, setColumnVisibility] = React.useState(() => mergedInitialSettings?.columnVisibility ?? {});
|
|
718
810
|
const [columnOrder, setColumnOrder] = React.useState(() => mergedInitialSettings?.columnOrder ?? []);
|
|
811
|
+
const [columnSizing, setColumnSizing] = React.useState(() => mergedInitialSettings?.columnSizing ?? {});
|
|
812
|
+
const columnSizingRef = React.useRef(columnSizing);
|
|
813
|
+
React.useEffect(() => {
|
|
814
|
+
columnSizingRef.current = columnSizing;
|
|
815
|
+
}, [columnSizing]);
|
|
719
816
|
const [deletingIds, setDeletingIds] = React.useState([]);
|
|
720
817
|
const [roleClearingIds, setRoleClearingIds] = React.useState([]);
|
|
721
818
|
const [perspectiveApiMissing, setPerspectiveApiMissing] = React.useState(false);
|
|
@@ -1147,12 +1244,13 @@ function DataTable({
|
|
|
1147
1244
|
const candidate = {
|
|
1148
1245
|
columnOrder,
|
|
1149
1246
|
columnVisibility: visibility,
|
|
1247
|
+
columnSizing,
|
|
1150
1248
|
sorting,
|
|
1151
1249
|
filters: filtersPayload,
|
|
1152
1250
|
searchValue
|
|
1153
1251
|
};
|
|
1154
1252
|
return sanitizePerspectiveSettings(candidate) ?? {};
|
|
1155
|
-
}, [columnOrder, columnVisibility, sorting, filterValues, searchValue, advancedFilter]);
|
|
1253
|
+
}, [columnOrder, columnVisibility, columnSizing, sorting, filterValues, searchValue, advancedFilter]);
|
|
1156
1254
|
const applyPerspectiveSettings = React.useCallback((settings, nextId, options) => {
|
|
1157
1255
|
const normalized = sanitizePerspectiveSettings(settings) ?? {};
|
|
1158
1256
|
if (normalized.columnOrder && normalized.columnOrder.length) {
|
|
@@ -1174,6 +1272,13 @@ function DataTable({
|
|
|
1174
1272
|
setSorting([]);
|
|
1175
1273
|
onSortingChange?.([]);
|
|
1176
1274
|
}
|
|
1275
|
+
if (normalized.columnSizing) {
|
|
1276
|
+
setColumnSizing(normalized.columnSizing);
|
|
1277
|
+
columnSizingRef.current = normalized.columnSizing;
|
|
1278
|
+
} else {
|
|
1279
|
+
setColumnSizing({});
|
|
1280
|
+
columnSizingRef.current = {};
|
|
1281
|
+
}
|
|
1177
1282
|
if (!options?.preserveAdvancedFilter) {
|
|
1178
1283
|
const restoredTree = isPersistedFilterTree(normalized.filters) ? deserializeTreeFromPersist(normalized.filters) : null;
|
|
1179
1284
|
if (advancedFilter?.onApplyTree) {
|
|
@@ -1194,12 +1299,50 @@ function DataTable({
|
|
|
1194
1299
|
const snapshot = { perspectiveId: nextId, settings: normalized, updatedAt: Date.now() };
|
|
1195
1300
|
writePerspectiveSnapshot(perspectiveTableId, snapshot);
|
|
1196
1301
|
initialSnapshotRef.current = snapshot;
|
|
1302
|
+
} else if (normalized.columnSizing && Object.keys(normalized.columnSizing).length) {
|
|
1303
|
+
const snapshot = {
|
|
1304
|
+
perspectiveId: null,
|
|
1305
|
+
settings: { columnSizing: normalized.columnSizing },
|
|
1306
|
+
updatedAt: Date.now()
|
|
1307
|
+
};
|
|
1308
|
+
writePerspectiveSnapshot(perspectiveTableId, snapshot);
|
|
1309
|
+
initialSnapshotRef.current = snapshot;
|
|
1197
1310
|
} else {
|
|
1198
1311
|
writePerspectiveSnapshot(perspectiveTableId, null);
|
|
1199
1312
|
initialSnapshotRef.current = null;
|
|
1200
1313
|
}
|
|
1201
1314
|
}
|
|
1202
1315
|
}, [onFiltersApply, onSearchChange, onSortingChange, perspectiveTableId, table, advancedFilter]);
|
|
1316
|
+
const persistColumnSizingSnapshot = React.useCallback(() => {
|
|
1317
|
+
if (!perspectiveTableId) return;
|
|
1318
|
+
const sizing = columnSizingRef.current;
|
|
1319
|
+
const existing = readPerspectiveSnapshot(perspectiveTableId) ?? initialSnapshotRef.current;
|
|
1320
|
+
const baseSettings = existing?.settings ? { ...existing.settings } : mergedInitialSettings ? { ...mergedInitialSettings } : {};
|
|
1321
|
+
if (sizing && Object.keys(sizing).length) baseSettings.columnSizing = sizing;
|
|
1322
|
+
else delete baseSettings.columnSizing;
|
|
1323
|
+
const snapshot = {
|
|
1324
|
+
perspectiveId: existing?.perspectiveId ?? activePerspectiveId ?? null,
|
|
1325
|
+
settings: baseSettings,
|
|
1326
|
+
updatedAt: Date.now()
|
|
1327
|
+
};
|
|
1328
|
+
writePerspectiveSnapshot(perspectiveTableId, snapshot);
|
|
1329
|
+
initialSnapshotRef.current = snapshot;
|
|
1330
|
+
}, [perspectiveTableId, activePerspectiveId, mergedInitialSettings]);
|
|
1331
|
+
const handleColumnResize = React.useCallback((colId, width) => {
|
|
1332
|
+
const next = { ...columnSizingRef.current, [colId]: width };
|
|
1333
|
+
columnSizingRef.current = next;
|
|
1334
|
+
setColumnSizing(next);
|
|
1335
|
+
}, []);
|
|
1336
|
+
const commitColumnSizing = React.useCallback(() => {
|
|
1337
|
+
persistColumnSizingSnapshot();
|
|
1338
|
+
}, [persistColumnSizingSnapshot]);
|
|
1339
|
+
const resetColumnSize = React.useCallback((colId) => {
|
|
1340
|
+
const next = { ...columnSizingRef.current };
|
|
1341
|
+
delete next[colId];
|
|
1342
|
+
columnSizingRef.current = next;
|
|
1343
|
+
setColumnSizing(next);
|
|
1344
|
+
persistColumnSizingSnapshot();
|
|
1345
|
+
}, [persistColumnSizingSnapshot]);
|
|
1203
1346
|
React.useLayoutEffect(() => {
|
|
1204
1347
|
if (!perspectiveTableId) return;
|
|
1205
1348
|
if (snapshotHydratedTableRef.current === perspectiveTableId) return;
|
|
@@ -1470,6 +1613,7 @@ function DataTable({
|
|
|
1470
1613
|
}, [table]);
|
|
1471
1614
|
const dndSensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 5 } }));
|
|
1472
1615
|
const enableHeaderDnd = Boolean(columnChooser);
|
|
1616
|
+
const enableColumnResize = perspectiveEnabled;
|
|
1473
1617
|
const stableDndContextId = React.useMemo(
|
|
1474
1618
|
() => sanitizeDndContextId(
|
|
1475
1619
|
extensionTableId ?? perspectiveTableId ?? resolvedReplacementHandle ?? (typeof title === "string" && title.trim().length > 0 ? title : "data-table")
|
|
@@ -2177,7 +2321,33 @@ function DataTable({
|
|
|
2177
2321
|
]
|
|
2178
2322
|
}
|
|
2179
2323
|
);
|
|
2180
|
-
|
|
2324
|
+
const columnId = header.column.id;
|
|
2325
|
+
const sizedWidth = enableColumnResize && columnId ? columnSizing[columnId] : void 0;
|
|
2326
|
+
const resizeHandle = enableColumnResize && !header.isPlaceholder && columnId ? /* @__PURE__ */ jsx(
|
|
2327
|
+
ColumnResizeHandle,
|
|
2328
|
+
{
|
|
2329
|
+
columnId,
|
|
2330
|
+
onResize: handleColumnResize,
|
|
2331
|
+
onCommit: commitColumnSizing,
|
|
2332
|
+
onReset: resetColumnSize,
|
|
2333
|
+
ariaLabel: t("ui.dataTable.resizeColumn", "Resize column")
|
|
2334
|
+
}
|
|
2335
|
+
) : null;
|
|
2336
|
+
return enableHeaderDnd ? /* @__PURE__ */ jsxs(SortableHeaderCell, { id: header.id, width: sizedWidth, className: cn("group", responsiveClass(priority, columnMeta?.hidden) + stickyClass), children: [
|
|
2337
|
+
headerCellContent,
|
|
2338
|
+
resizeHandle
|
|
2339
|
+
] }, header.id) : /* @__PURE__ */ jsxs(
|
|
2340
|
+
TableHead,
|
|
2341
|
+
{
|
|
2342
|
+
className: cn("group relative", responsiveClass(priority, columnMeta?.hidden) + stickyClass),
|
|
2343
|
+
style: typeof sizedWidth === "number" ? { width: sizedWidth, minWidth: sizedWidth, maxWidth: sizedWidth } : void 0,
|
|
2344
|
+
children: [
|
|
2345
|
+
headerCellContent,
|
|
2346
|
+
resizeHandle
|
|
2347
|
+
]
|
|
2348
|
+
},
|
|
2349
|
+
header.id
|
|
2350
|
+
);
|
|
2181
2351
|
}),
|
|
2182
2352
|
rowActions || injectedRowActions.length > 0 ? /* @__PURE__ */ jsx(
|
|
2183
2353
|
TableHead,
|
|
@@ -2259,8 +2429,18 @@ function DataTable({
|
|
|
2259
2429
|
} else {
|
|
2260
2430
|
tooltipText = cellValue != null ? String(cellValue) : void 0;
|
|
2261
2431
|
}
|
|
2262
|
-
const
|
|
2263
|
-
|
|
2432
|
+
const sizedWidth = enableColumnResize && columnId ? columnSizing[columnId] : void 0;
|
|
2433
|
+
const effectiveMaxWidth = typeof sizedWidth === "number" ? `${sizedWidth}px` : maxWidth;
|
|
2434
|
+
const wrappedContent = shouldTruncate ? /* @__PURE__ */ jsx(TruncatedCell, { maxWidth: effectiveMaxWidth, tooltipContent: tooltipText, children: content }) : content;
|
|
2435
|
+
return /* @__PURE__ */ jsx(
|
|
2436
|
+
TableCell,
|
|
2437
|
+
{
|
|
2438
|
+
className: responsiveClass(priority, columnMeta?.hidden) + (isStickyCell ? ` md:sticky md:left-0 md:z-10 md:bg-background ${STICKY_LEFT_SHADOW_CLASS}` : ""),
|
|
2439
|
+
style: typeof sizedWidth === "number" ? { width: sizedWidth, minWidth: sizedWidth, maxWidth: sizedWidth } : void 0,
|
|
2440
|
+
children: wrappedContent
|
|
2441
|
+
},
|
|
2442
|
+
cell.id
|
|
2443
|
+
);
|
|
2264
2444
|
}),
|
|
2265
2445
|
rowActions || injectedRowActions.length > 0 ? /* @__PURE__ */ jsx(
|
|
2266
2446
|
TableCell,
|
|
@@ -2353,6 +2533,7 @@ function DataTable({
|
|
|
2353
2533
|
export {
|
|
2354
2534
|
DataTable,
|
|
2355
2535
|
readPerspectiveSnapshot,
|
|
2536
|
+
sanitizePerspectiveSettings,
|
|
2356
2537
|
withDataTableNamespaces,
|
|
2357
2538
|
writePerspectiveSnapshot
|
|
2358
2539
|
};
|