@seedgrid/fe-components 2026.3.31-6 → 2026.3.31-7

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.
@@ -27,6 +27,7 @@ export type SgDatatableCellMeta<T extends SgDatatableRow> = {
27
27
  rowData: T;
28
28
  };
29
29
  export type SgDatatableColumn<T extends SgDatatableRow = SgDatatableRow> = {
30
+ columnId?: string;
30
31
  field?: string;
31
32
  header: React.ReactNode;
32
33
  body?: (rowData: T, meta: SgDatatableCellMeta<T>) => React.ReactNode;
@@ -43,6 +44,8 @@ export type SgDatatableColumn<T extends SgDatatableRow = SgDatatableRow> = {
43
44
  width?: number | string;
44
45
  minWidth?: number | string;
45
46
  hidden?: boolean;
47
+ hideable?: boolean;
48
+ reorderable?: boolean;
46
49
  className?: string;
47
50
  headerClassName?: string;
48
51
  bodyClassName?: string | ((rowData: T, rowIndex: number) => string | undefined);
@@ -97,6 +100,9 @@ export type SgDatatableProps<T extends SgDatatableRow = SgDatatableRow> = {
97
100
  groupBoxProps?: Omit<Partial<SgGroupBoxProps>, "children" | "title"> & {
98
101
  title?: string;
99
102
  };
103
+ showColumnManager?: boolean;
104
+ columnManagerLabel?: string;
105
+ columnManagerMaxHeight?: number | string;
100
106
  };
101
107
  export declare const SgDatatable: <T extends SgDatatableRow>(props: SgDatatableProps<T> & {
102
108
  ref?: React.Ref<SgDatatableRef<T>>;
@@ -1 +1 @@
1
- {"version":3,"file":"SgDatatable.d.ts","sourceRoot":"","sources":["../../src/inputs/SgDatatable.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SgDatatable.d.ts","sourceRoot":"","sources":["../../src/inputs/SgDatatable.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React from "react";
4
+ import { Check, GripVertical, SlidersHorizontal } from "lucide-react";
4
5
  import { SgButton } from "../buttons/SgButton";
5
6
  import { SgGroupBox } from "../layout/SgGroupBox";
6
7
  import { t, useComponentsI18n } from "../i18n";
@@ -112,6 +113,28 @@ function rowsAreEqual(rowA, rowB, dataKey) {
112
113
  return rowA === rowB;
113
114
  return getRowIdentity(rowA, dataKey) === getRowIdentity(rowB, dataKey);
114
115
  }
116
+ function getColumnKey(column, index) {
117
+ if (column.columnId?.trim())
118
+ return `columnId:${column.columnId.trim()}`;
119
+ if (column.field?.trim())
120
+ return `field:${column.field.trim()}`;
121
+ return `index:${index}`;
122
+ }
123
+ function moveItem(list, fromIndex, toIndex) {
124
+ if (fromIndex === toIndex)
125
+ return list;
126
+ if (fromIndex < 0 || fromIndex >= list.length)
127
+ return list;
128
+ if (toIndex < 0 || toIndex >= list.length)
129
+ return list;
130
+ const next = [...list];
131
+ const item = next[fromIndex];
132
+ if (item === undefined)
133
+ return list;
134
+ next.splice(fromIndex, 1);
135
+ next.splice(toIndex, 0, item);
136
+ return next;
137
+ }
115
138
  function resolveAlignmentClass(align) {
116
139
  if (align === "center")
117
140
  return "text-center";
@@ -121,7 +144,7 @@ function resolveAlignmentClass(align) {
121
144
  }
122
145
  function SgDatatableBase(props, imperativeRef) {
123
146
  const i18n = useComponentsI18n();
124
- const { id, title, value, columns, dataKey, lazy = false, totalRecords: controlledTotalRecords, paginator = false, rows = 10, first, rowsPerPageOptions, onPage, sortField, sortOrder, onSort, removableSort = true, selectionMode, selection, onSelectionChange, showGlobalFilter = false, globalFilter, globalFilterPlaceholder, onGlobalFilterChange, showColumnFilters = false, filters, onFilter, showClearFiltersButton = false, stripedRows = false, showGridlines = false, hoverableRows = true, loading = false, emptyMessage, className = "", style, tableClassName = "", rowClassName, groupBoxProps = {} } = props;
147
+ const { id, title, value, columns, dataKey, lazy = false, totalRecords: controlledTotalRecords, paginator = false, rows = 10, first, rowsPerPageOptions, onPage, sortField, sortOrder, onSort, removableSort = true, selectionMode, selection, onSelectionChange, showGlobalFilter = false, globalFilter, globalFilterPlaceholder, onGlobalFilterChange, showColumnFilters = false, filters, onFilter, showClearFiltersButton = false, stripedRows = false, showGridlines = false, hoverableRows = true, loading = false, emptyMessage, className = "", style, tableClassName = "", rowClassName, groupBoxProps = {}, showColumnManager = true, columnManagerLabel, columnManagerMaxHeight = 320 } = props;
125
148
  const isFirstControlled = first !== undefined;
126
149
  const isSortFieldControlled = sortField !== undefined;
127
150
  const isSortOrderControlled = sortOrder !== undefined;
@@ -135,6 +158,19 @@ function SgDatatableBase(props, imperativeRef) {
135
158
  const [internalSelection, setInternalSelection] = React.useState(null);
136
159
  const [internalGlobalFilter, setInternalGlobalFilter] = React.useState(globalFilter ?? "");
137
160
  const [internalFilters, setInternalFilters] = React.useState(() => normalizeFilters(filters));
161
+ const columnManagerRef = React.useRef(null);
162
+ const [isColumnManagerOpen, setIsColumnManagerOpen] = React.useState(false);
163
+ const [draggingColumnKey, setDraggingColumnKey] = React.useState(null);
164
+ const columnDescriptors = React.useMemo(() => columns.map((column, index) => ({
165
+ key: getColumnKey(column, index),
166
+ column,
167
+ originalIndex: index
168
+ })), [columns]);
169
+ const [columnOrder, setColumnOrder] = React.useState(() => columnDescriptors.map((item) => item.key));
170
+ const [hiddenColumnsMap, setHiddenColumnsMap] = React.useState(() => columnDescriptors.reduce((acc, item) => {
171
+ acc[item.key] = Boolean(item.column.hidden);
172
+ return acc;
173
+ }, {}));
138
174
  React.useEffect(() => {
139
175
  if (!isFirstControlled)
140
176
  return;
@@ -168,7 +204,42 @@ function SgDatatableBase(props, imperativeRef) {
168
204
  return;
169
205
  setInternalFilters(normalizeFilters(filters));
170
206
  }, [isFiltersControlled, filters]);
171
- const visibleColumns = React.useMemo(() => columns.filter((column) => !column.hidden), [columns]);
207
+ React.useEffect(() => {
208
+ const availableKeys = columnDescriptors.map((item) => item.key);
209
+ setColumnOrder((prev) => {
210
+ const kept = prev.filter((key) => availableKeys.includes(key));
211
+ const missing = availableKeys.filter((key) => !kept.includes(key));
212
+ return [...kept, ...missing];
213
+ });
214
+ setHiddenColumnsMap((prev) => {
215
+ const next = {};
216
+ for (const item of columnDescriptors) {
217
+ next[item.key] = prev[item.key] ?? Boolean(item.column.hidden);
218
+ }
219
+ return next;
220
+ });
221
+ }, [columnDescriptors]);
222
+ React.useEffect(() => {
223
+ if (!isColumnManagerOpen)
224
+ return;
225
+ const handlePointerDown = (event) => {
226
+ if (!columnManagerRef.current)
227
+ return;
228
+ if (columnManagerRef.current.contains(event.target))
229
+ return;
230
+ setIsColumnManagerOpen(false);
231
+ };
232
+ document.addEventListener("mousedown", handlePointerDown);
233
+ return () => document.removeEventListener("mousedown", handlePointerDown);
234
+ }, [isColumnManagerOpen]);
235
+ const orderedColumns = React.useMemo(() => {
236
+ const map = new Map(columnDescriptors.map((item) => [item.key, item]));
237
+ return columnOrder
238
+ .map((key) => map.get(key))
239
+ .filter((item) => Boolean(item));
240
+ }, [columnDescriptors, columnOrder]);
241
+ const visibleColumns = React.useMemo(() => orderedColumns.filter((item) => !hiddenColumnsMap[item.key]).map((item) => item.column), [orderedColumns, hiddenColumnsMap]);
242
+ const visibleColumnCount = React.useMemo(() => orderedColumns.filter((item) => !hiddenColumnsMap[item.key]).length, [orderedColumns, hiddenColumnsMap]);
172
243
  const currentFirst = isFirstControlled ? Math.max(0, first ?? 0) : internalFirst;
173
244
  const currentRows = Math.max(1, internalRows);
174
245
  const currentSortField = isSortFieldControlled ? sortField ?? null : internalSortField;
@@ -379,61 +450,129 @@ function SgDatatableBase(props, imperativeRef) {
379
450
  : [...previous, rowData];
380
451
  commitSelection(next);
381
452
  }, [selectionMode, currentSelection, dataKey, commitSelection]);
453
+ const resolvedColumnManagerLabel = columnManagerLabel ??
454
+ resolveMessage(t(i18n, "components.datatable.columns"), "components.datatable.columns", "Colunas");
455
+ const restoreColumnsLabel = resolveMessage(t(i18n, "components.datatable.restoreColumns"), "components.datatable.restoreColumns", "Restaurar padrão");
456
+ const showAllColumnsLabel = resolveMessage(t(i18n, "components.datatable.showAllColumns"), "components.datatable.showAllColumns", "Mostrar todas");
457
+ const dragHandleLabel = resolveMessage(t(i18n, "components.datatable.dragToReorder"), "components.datatable.dragToReorder", "Arrastar para reordenar");
458
+ const toggleColumnVisibility = React.useCallback((columnKey, forceVisible) => {
459
+ setHiddenColumnsMap((prev) => {
460
+ const isCurrentlyHidden = Boolean(prev[columnKey]);
461
+ const willHide = forceVisible === undefined ? !isCurrentlyHidden : !forceVisible;
462
+ if (willHide && visibleColumnCount <= 1) {
463
+ return prev;
464
+ }
465
+ return {
466
+ ...prev,
467
+ [columnKey]: willHide
468
+ };
469
+ });
470
+ }, [visibleColumnCount]);
471
+ const handleReorderColumn = React.useCallback((fromKey, toKey) => {
472
+ setColumnOrder((prev) => {
473
+ const fromIndex = prev.indexOf(fromKey);
474
+ const toIndex = prev.indexOf(toKey);
475
+ if (fromIndex < 0 || toIndex < 0)
476
+ return prev;
477
+ return moveItem(prev, fromIndex, toIndex);
478
+ });
479
+ }, []);
480
+ const restoreDefaultColumns = React.useCallback(() => {
481
+ setColumnOrder(columnDescriptors.map((item) => item.key));
482
+ setHiddenColumnsMap(columnDescriptors.reduce((acc, item) => {
483
+ acc[item.key] = Boolean(item.column.hidden);
484
+ return acc;
485
+ }, {}));
486
+ }, [columnDescriptors]);
487
+ const showAllColumns = React.useCallback(() => {
488
+ setHiddenColumnsMap((prev) => {
489
+ const next = { ...prev };
490
+ for (const item of columnDescriptors) {
491
+ next[item.key] = false;
492
+ }
493
+ return next;
494
+ });
495
+ }, [columnDescriptors]);
382
496
  const resolvedTitle = (groupBoxProps.title ?? title ?? "").trim() || " ";
383
- return (_jsx("div", { className: className, style: style, children: _jsx(SgGroupBox, { ...groupBoxProps, title: resolvedTitle, children: _jsxs("div", { className: "space-y-3", children: [shouldShowToolbar ? (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [showGlobalFilter ? (_jsx("input", { value: currentGlobalFilter, onChange: (event) => commitFilters(currentFilters, event.target.value), placeholder: globalFilterLabel, className: "min-w-[220px] flex-1 rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-input-bg,var(--sg-surface)))] px-3 py-2 text-sm text-[rgb(var(--sg-input-fg,var(--sg-text)))] placeholder:text-[rgb(var(--sg-input-placeholder,var(--sg-muted)))] outline-none focus:ring-2 focus:ring-[rgb(var(--sg-ring))]" })) : null, showClearFiltersButton ? (_jsx(SgButton, { size: "sm", appearance: "outline", onClick: clearFilters, children: clearFiltersLabel })) : null] })) : null, _jsx("div", { className: "relative", children: _jsx("div", { className: "overflow-x-auto rounded-lg border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface))]", children: _jsxs("table", { id: id, className: cn("min-w-full border-collapse text-sm", tableClassName), children: [_jsxs("thead", { children: [_jsx("tr", { className: "bg-[rgb(var(--sg-primary-50))]", children: visibleColumns.map((column, columnIndex) => {
384
- const sortCandidate = column.sortField ?? column.field;
385
- const isSorted = Boolean(sortCandidate) && sortCandidate === currentSortField;
386
- const sortIcon = !column.sortable
387
- ? null
388
- : isSorted
389
- ? currentSortOrder === 1
390
- ? " ^"
391
- : currentSortOrder === -1
392
- ? " v"
393
- : " <>"
394
- : " <>";
395
- return (_jsx("th", { className: cn("px-3 py-2 font-semibold text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]", column.headerClassName, column.className), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: column.sortable ? (_jsxs("button", { type: "button", onClick: () => handleHeaderSort(column), className: cn("inline-flex items-center gap-1 font-semibold", resolveAlignmentClass(column.align), "text-[rgb(var(--sg-text))] hover:text-[rgb(var(--sg-primary-600))]"), children: [_jsx("span", { children: column.header }), _jsx("span", { "aria-hidden": "true", children: sortIcon })] })) : (_jsx("span", { children: column.header })) }, `head-${column.field ?? columnIndex}`));
396
- }) }), shouldShowFiltersRow ? (_jsx("tr", { children: visibleColumns.map((column, columnIndex) => {
397
- const filterField = column.filterField ?? column.field;
398
- const filterValue = filterField ? currentFilters[filterField] ?? "" : "";
399
- return (_jsx("th", { className: cn("px-3 py-2 align-top", showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]"), children: column.filter && filterField ? (_jsx("input", { value: filterValue, onChange: (event) => {
400
- const nextFilters = {
401
- ...currentFilters,
402
- [filterField]: event.target.value
403
- };
404
- const normalized = normalizeFilters(nextFilters);
405
- commitFilters(normalized, currentGlobalFilter);
406
- }, placeholder: column.filterPlaceholder ?? t(i18n, "components.datatable.columnFilterPlaceholder", { column: String(column.header ?? "") }), className: "w-full rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-input-bg,var(--sg-surface)))] px-2 py-1 text-xs text-[rgb(var(--sg-input-fg,var(--sg-text)))] placeholder:text-[rgb(var(--sg-input-placeholder,var(--sg-muted)))] outline-none focus:ring-2 focus:ring-[rgb(var(--sg-ring))]" })) : null }, `filter-${column.field ?? columnIndex}`));
407
- }) })) : null] }), _jsx("tbody", { children: loading ? (_jsx("tr", { children: _jsx("td", { colSpan: Math.max(1, visibleColumns.length), className: "px-4 py-6 text-center text-sm text-[rgb(var(--sg-muted))]", children: loadingLabel }) })) : pagedRows.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: Math.max(1, visibleColumns.length), className: "px-4 py-6 text-center text-sm text-[rgb(var(--sg-muted))]", children: emptyLabel }) })) : (pagedRows.map((rowData, rowIndex) => {
408
- const absoluteRowIndex = safeFirst + rowIndex;
409
- const selected = isRowSelected(rowData);
410
- const customRowClass = typeof rowClassName === "function" ? rowClassName(rowData, absoluteRowIndex) : rowClassName;
411
- return (_jsx("tr", { "aria-selected": selected || undefined, onClick: (event) => {
412
- const target = event.target;
413
- if (target.closest("button,a,input,select,textarea,label,[data-sg-stop-row-select='true']")) {
414
- return;
415
- }
416
- handleRowSelection(rowData);
417
- }, className: cn(selectionMode ? "cursor-pointer" : "", stripedRows && absoluteRowIndex % 2 === 1 ? "bg-[rgb(var(--sg-primary-50))]" : "", hoverableRows ? "hover:bg-[rgb(var(--sg-primary-100))]" : "", selected ? "bg-[rgb(var(--sg-primary-100))]" : "", customRowClass), children: visibleColumns.map((column, columnIndex) => {
418
- const cellField = column.field;
419
- const cellValue = getFieldValue(rowData, cellField);
420
- const customCellClass = typeof column.bodyClassName === "function"
421
- ? column.bodyClassName(rowData, absoluteRowIndex)
422
- : column.bodyClassName;
423
- const renderedValue = column.body
424
- ? column.body(rowData, {
425
- rowData,
426
- rowIndex: absoluteRowIndex,
427
- field: cellField,
428
- value: cellValue
429
- })
430
- : (_jsx("span", { children: cellValue === null || cellValue === undefined ? "-" : String(cellValue) }));
431
- return (_jsx("td", { className: cn("px-3 py-2 text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]", column.className, customCellClass), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: renderedValue }, `cell-${cellField ?? columnIndex}-${absoluteRowIndex}`));
432
- }) }, String(getRowIdentity(rowData, dataKey) ?? absoluteRowIndex)));
433
- })) }), hasFooter ? (_jsx("tfoot", { children: _jsx("tr", { className: "bg-[rgb(var(--sg-primary-50))]", children: visibleColumns.map((column, columnIndex) => {
434
- const footerValue = typeof column.footer === "function" ? column.footer(sortedRows) : column.footer;
435
- return (_jsx("td", { className: cn("px-3 py-2 font-semibold text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-t border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-t border-[rgb(var(--sg-border))]", column.className), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: footerValue ?? null }, `foot-${column.field ?? columnIndex}`));
436
- }) }) })) : null] }) }) }), paginator ? (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(SgButton, { size: "sm", appearance: "outline", disabled: currentPage <= 1, onClick: () => goToPage(currentPage - 1), children: prevLabel }), pageWindow.map((pageNumber) => (_jsx(SgButton, { size: "sm", appearance: pageNumber === currentPage ? "solid" : "outline", onClick: () => goToPage(pageNumber), children: String(pageNumber) }, `page-${pageNumber}`))), _jsx(SgButton, { size: "sm", appearance: "outline", disabled: currentPage >= pageCount, onClick: () => goToPage(currentPage + 1), children: nextLabel }), _jsx("span", { className: "min-w-[180px] text-xs text-[rgb(var(--sg-muted))] md:ml-auto", children: pageReport }), rowsPerPageOptions && rowsPerPageOptions.length > 0 ? (_jsxs("label", { className: "ml-auto inline-flex items-center gap-2 text-xs text-[rgb(var(--sg-muted))] md:ml-0", children: [_jsx("span", { children: rowsPerPageLabel }), _jsx("select", { value: currentRows, onChange: (event) => {
497
+ return (_jsx("div", { className: className, style: style, children: _jsx(SgGroupBox, { ...groupBoxProps, title: resolvedTitle, children: _jsxs("div", { className: "space-y-3", children: [shouldShowToolbar ? (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [showGlobalFilter ? (_jsx("input", { value: currentGlobalFilter, onChange: (event) => commitFilters(currentFilters, event.target.value), placeholder: globalFilterLabel, className: "min-w-[220px] flex-1 rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-input-bg,var(--sg-surface)))] px-3 py-2 text-sm text-[rgb(var(--sg-input-fg,var(--sg-text)))] placeholder:text-[rgb(var(--sg-input-placeholder,var(--sg-muted)))] outline-none focus:ring-2 focus:ring-[rgb(var(--sg-ring))]" })) : null, showClearFiltersButton ? (_jsx(SgButton, { size: "sm", appearance: "outline", onClick: clearFilters, children: clearFiltersLabel })) : null] })) : null, _jsxs("div", { className: "relative", ref: columnManagerRef, children: [showColumnManager ? (_jsx("div", { className: "mb-2 flex items-center justify-start", children: _jsx("button", { type: "button", "aria-label": resolvedColumnManagerLabel, title: resolvedColumnManagerLabel, onClick: () => setIsColumnManagerOpen((prev) => !prev), className: "inline-flex h-9 w-9 items-center justify-center rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface))] text-[rgb(var(--sg-primary-600))] shadow-sm transition hover:bg-[rgb(var(--sg-primary-50))] hover:text-[rgb(var(--sg-primary-700))]", children: _jsx(SlidersHorizontal, { size: 18 }) }) })) : null, showColumnManager && isColumnManagerOpen ? (_jsxs("div", { className: "absolute left-0 top-11 z-30 w-[300px] rounded-xl border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface))] shadow-xl", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-[rgb(var(--sg-border))] px-4 py-3", children: [_jsx(SlidersHorizontal, { size: 18, className: "text-[rgb(var(--sg-primary-600))]" }), _jsx("span", { className: "text-sm font-semibold text-[rgb(var(--sg-text))]", children: resolvedColumnManagerLabel })] }), _jsx("div", { className: "overflow-y-auto px-2 py-2", style: { maxHeight: toCssSize(columnManagerMaxHeight) }, children: _jsx("div", { className: "space-y-1", children: orderedColumns.map((item) => {
498
+ const isHidden = Boolean(hiddenColumnsMap[item.key]);
499
+ const isHideable = item.column.hideable !== false;
500
+ const isReorderable = item.column.reorderable !== false;
501
+ const canHideThisColumn = isHideable && (!isHidden ? visibleColumnCount > 1 : true);
502
+ const columnLabel = typeof item.column.header === "string" || typeof item.column.header === "number"
503
+ ? String(item.column.header)
504
+ : item.column.field ?? item.key;
505
+ return (_jsxs("div", { draggable: isReorderable, onDragStart: () => setDraggingColumnKey(item.key), onDragOver: (event) => {
506
+ if (!isReorderable)
507
+ return;
508
+ event.preventDefault();
509
+ }, onDrop: (event) => {
510
+ event.preventDefault();
511
+ if (!isReorderable)
512
+ return;
513
+ if (!draggingColumnKey || draggingColumnKey === item.key)
514
+ return;
515
+ handleReorderColumn(draggingColumnKey, item.key);
516
+ setDraggingColumnKey(null);
517
+ }, onDragEnd: () => setDraggingColumnKey(null), className: cn("flex items-center gap-3 rounded-md px-2 py-2", draggingColumnKey === item.key ? "opacity-60" : "", "hover:bg-[rgb(var(--sg-primary-50))]"), children: [_jsx("button", { type: "button", disabled: !canHideThisColumn, onClick: () => toggleColumnVisibility(item.key), className: cn("inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md border transition", !isHidden
518
+ ? "border-[rgb(var(--sg-primary-600))] bg-[rgb(var(--sg-primary-600))] text-white"
519
+ : "border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface))] text-transparent", !canHideThisColumn ? "cursor-not-allowed opacity-50" : "hover:scale-[1.02]"), children: _jsx(Check, { size: 14 }) }), _jsx("button", { type: "button", disabled: !canHideThisColumn, onClick: () => toggleColumnVisibility(item.key), className: cn("flex-1 truncate text-left text-sm", isHidden
520
+ ? "text-[rgb(var(--sg-muted))]"
521
+ : "text-[rgb(var(--sg-text))]", !canHideThisColumn ? "cursor-not-allowed" : ""), children: columnLabel }), _jsx("div", { className: cn("inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-[rgb(var(--sg-muted))]", isReorderable ? "cursor-grab active:cursor-grabbing" : "opacity-40"), title: dragHandleLabel, children: _jsx(GripVertical, { size: 16 }) })] }, `manager-${item.key}`));
522
+ }) }) }), _jsxs("div", { className: "flex items-center gap-2 border-t border-[rgb(var(--sg-border))] px-3 py-3", children: [_jsx(SgButton, { size: "sm", appearance: "outline", onClick: restoreDefaultColumns, children: restoreColumnsLabel }), _jsx(SgButton, { size: "sm", appearance: "outline", onClick: showAllColumns, children: showAllColumnsLabel })] })] })) : null, _jsx("div", { className: "overflow-x-auto rounded-lg border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface))]", children: _jsxs("table", { id: id, className: cn("min-w-full border-collapse text-sm", tableClassName), children: [_jsxs("thead", { children: [_jsx("tr", { className: "bg-[rgb(var(--sg-primary-50))]", children: visibleColumns.map((column, columnIndex) => {
523
+ const sortCandidate = column.sortField ?? column.field;
524
+ const isSorted = Boolean(sortCandidate) && sortCandidate === currentSortField;
525
+ const sortIcon = !column.sortable
526
+ ? null
527
+ : isSorted
528
+ ? currentSortOrder === 1
529
+ ? " ^"
530
+ : currentSortOrder === -1
531
+ ? " v"
532
+ : " <>"
533
+ : " <>";
534
+ return (_jsx("th", { className: cn("px-3 py-2 font-semibold text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]", column.headerClassName, column.className), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: column.sortable ? (_jsxs("button", { type: "button", onClick: () => handleHeaderSort(column), className: cn("inline-flex items-center gap-1 font-semibold", resolveAlignmentClass(column.align), "text-[rgb(var(--sg-text))] hover:text-[rgb(var(--sg-primary-600))]"), children: [_jsx("span", { children: column.header }), _jsx("span", { "aria-hidden": "true", children: sortIcon })] })) : (_jsx("span", { children: column.header })) }, `head-${column.columnId ?? column.field ?? columnIndex}`));
535
+ }) }), shouldShowFiltersRow ? (_jsx("tr", { children: visibleColumns.map((column, columnIndex) => {
536
+ const filterField = column.filterField ?? column.field;
537
+ const filterValue = filterField ? currentFilters[filterField] ?? "" : "";
538
+ return (_jsx("th", { className: cn("px-3 py-2 align-top", showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]"), children: column.filter && filterField ? (_jsx("input", { value: filterValue, onChange: (event) => {
539
+ const nextFilters = {
540
+ ...currentFilters,
541
+ [filterField]: event.target.value
542
+ };
543
+ const normalized = normalizeFilters(nextFilters);
544
+ commitFilters(normalized, currentGlobalFilter);
545
+ }, placeholder: column.filterPlaceholder ?? t(i18n, "components.datatable.columnFilterPlaceholder", { column: String(column.header ?? "") }), className: "w-full rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-input-bg,var(--sg-surface)))] px-2 py-1 text-xs text-[rgb(var(--sg-input-fg,var(--sg-text)))] placeholder:text-[rgb(var(--sg-input-placeholder,var(--sg-muted)))] outline-none focus:ring-2 focus:ring-[rgb(var(--sg-ring))]" })) : null }, `filter-${column.columnId ?? column.field ?? columnIndex}`));
546
+ }) })) : null] }), _jsx("tbody", { children: loading ? (_jsx("tr", { children: _jsx("td", { colSpan: Math.max(1, visibleColumns.length), className: "px-4 py-6 text-center text-sm text-[rgb(var(--sg-muted))]", children: loadingLabel }) })) : pagedRows.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: Math.max(1, visibleColumns.length), className: "px-4 py-6 text-center text-sm text-[rgb(var(--sg-muted))]", children: emptyLabel }) })) : (pagedRows.map((rowData, rowIndex) => {
547
+ const absoluteRowIndex = safeFirst + rowIndex;
548
+ const selected = isRowSelected(rowData);
549
+ const customRowClass = typeof rowClassName === "function" ? rowClassName(rowData, absoluteRowIndex) : rowClassName;
550
+ return (_jsx("tr", { "aria-selected": selected || undefined, onClick: (event) => {
551
+ const target = event.target;
552
+ if (target.closest("button,a,input,select,textarea,label,[data-sg-stop-row-select='true']")) {
553
+ return;
554
+ }
555
+ handleRowSelection(rowData);
556
+ }, className: cn(selectionMode ? "cursor-pointer" : "", stripedRows && absoluteRowIndex % 2 === 1 ? "bg-[rgb(var(--sg-primary-50))]" : "", hoverableRows ? "hover:bg-[rgb(var(--sg-primary-100))]" : "", selected ? "bg-[rgb(var(--sg-primary-100))]" : "", customRowClass), children: visibleColumns.map((column, columnIndex) => {
557
+ const cellField = column.field;
558
+ const cellValue = getFieldValue(rowData, cellField);
559
+ const customCellClass = typeof column.bodyClassName === "function"
560
+ ? column.bodyClassName(rowData, absoluteRowIndex)
561
+ : column.bodyClassName;
562
+ const renderedValue = column.body
563
+ ? column.body(rowData, {
564
+ rowData,
565
+ rowIndex: absoluteRowIndex,
566
+ field: cellField,
567
+ value: cellValue
568
+ })
569
+ : (_jsx("span", { children: cellValue === null || cellValue === undefined ? "-" : String(cellValue) }));
570
+ return (_jsx("td", { className: cn("px-3 py-2 text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]", column.className, customCellClass), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: renderedValue }, `cell-${column.columnId ?? cellField ?? columnIndex}-${absoluteRowIndex}`));
571
+ }) }, String(getRowIdentity(rowData, dataKey) ?? absoluteRowIndex)));
572
+ })) }), hasFooter ? (_jsx("tfoot", { children: _jsx("tr", { className: "bg-[rgb(var(--sg-primary-50))]", children: visibleColumns.map((column, columnIndex) => {
573
+ const footerValue = typeof column.footer === "function" ? column.footer(sortedRows) : column.footer;
574
+ return (_jsx("td", { className: cn("px-3 py-2 font-semibold text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-t border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-t border-[rgb(var(--sg-border))]", column.className), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: footerValue ?? null }, `foot-${column.columnId ?? column.field ?? columnIndex}`));
575
+ }) }) })) : null] }) })] }), paginator ? (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(SgButton, { size: "sm", appearance: "outline", disabled: currentPage <= 1, onClick: () => goToPage(currentPage - 1), children: prevLabel }), pageWindow.map((pageNumber) => (_jsx(SgButton, { size: "sm", appearance: pageNumber === currentPage ? "solid" : "outline", onClick: () => goToPage(pageNumber), children: String(pageNumber) }, `page-${pageNumber}`))), _jsx(SgButton, { size: "sm", appearance: "outline", disabled: currentPage >= pageCount, onClick: () => goToPage(currentPage + 1), children: nextLabel }), _jsx("span", { className: "min-w-[180px] text-xs text-[rgb(var(--sg-muted))] md:ml-auto", children: pageReport }), rowsPerPageOptions && rowsPerPageOptions.length > 0 ? (_jsxs("label", { className: "ml-auto inline-flex items-center gap-2 text-xs text-[rgb(var(--sg-muted))] md:ml-0", children: [_jsx("span", { children: rowsPerPageLabel }), _jsx("select", { value: currentRows, onChange: (event) => {
437
576
  const nextRows = Number(event.target.value) || currentRows;
438
577
  commitPage(0, nextRows);
439
578
  }, className: "rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-input-bg,var(--sg-surface)))] px-2 py-1 text-xs text-[rgb(var(--sg-input-fg,var(--sg-text)))]", children: rowsPerPageOptions.map((option) => (_jsx("option", { value: option, children: option }, option))) })] })) : null] })) : null] }) }) }));