@dynostack/react-grid 0.3.2 → 0.4.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/index.d.cts CHANGED
@@ -1,7 +1,6 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { Column, RowData, ColumnDef, SortingState, ColumnFiltersState, ColumnPinningState, VisibilityState, Table, CellContext, FilterFn } from '@tanstack/react-table';
3
1
  import * as React$1 from 'react';
4
2
  import { CSSProperties } from 'react';
3
+ import { Column, RowData, ColumnDef, SortingState, ColumnFiltersState, ColumnPinningState, VisibilityState, Table, CellContext, FilterFn } from '@tanstack/react-table';
5
4
 
6
5
  type RowActionId = "view" | "edit" | "duplicate" | "delete" | string;
7
6
  type CustomRowAction<TData> = {
@@ -20,7 +19,7 @@ type DataTableRowActionsProps<TData> = {
20
19
  onSaveEdit?: () => void;
21
20
  onCancelEdit?: () => void;
22
21
  };
23
- declare function DataTableRowActions<TData>({ row, actions, customActions, onAction, isEditing, onSaveEdit, onCancelEdit, }: DataTableRowActionsProps<TData>): react_jsx_runtime.JSX.Element;
22
+ declare function DataTableRowActions<TData>({ row, actions, customActions, onAction, isEditing, onSaveEdit, onCancelEdit, }: DataTableRowActionsProps<TData>): React$1.JSX.Element;
24
23
 
25
24
  /**
26
25
  * CSS variable overrides for a single DataTable instance.
@@ -357,6 +356,18 @@ type DataTableProps<TData extends {
357
356
  pageSizeOptions?: number[];
358
357
  initialColumnPinning?: ColumnPinningState;
359
358
  initialColumnVisibility?: VisibilityState;
359
+ /** Initial sort order. */
360
+ initialSorting?: SortingState;
361
+ /** Observe selected row objects (loaded rows only in server mode). */
362
+ onSelectionChange?: (rows: TData[]) => void;
363
+ /** Accessible table name. */
364
+ ariaLabel?: string;
365
+ /** Alternating row backgrounds. */
366
+ striped?: boolean;
367
+ /** Keep headers visible inside a vertically constrained table. */
368
+ stickyHeader?: boolean;
369
+ /** Scroll viewport height, e.g. "480px". */
370
+ maxHeight?: React.CSSProperties["maxHeight"];
360
371
  /** Optional controlled global filter (for cross-tab persistence). */
361
372
  globalFilter?: string;
362
373
  onGlobalFilterChange?: (value: string) => void;
@@ -396,7 +407,7 @@ type DataTableProps<TData extends {
396
407
  };
397
408
  declare function DataTable<TData extends {
398
409
  id: string | number;
399
- }>({ data, columns, dataSource, isLoading, isFetching, onRefresh, totalRecords, exportFileName, enableSelection, renderSubRow, getSubRows, rowActions, customRowActions, onRowAction, onCellEdit, onRowSave, onAddRow, onBulkDelete, initialPageSize, pageSizeOptions, initialColumnPinning, initialColumnVisibility, globalFilter: globalFilterProp, onGlobalFilterChange, className, toolbarSlot, features, labels: labelsProp, density, theme, isolate, onView, onDelete, viewSheet, confirmDelete, }: DataTableProps<TData>): react_jsx_runtime.JSX.Element;
410
+ }>({ data, columns, dataSource, isLoading, isFetching, onRefresh, totalRecords, exportFileName, enableSelection, renderSubRow, getSubRows, rowActions, customRowActions, onRowAction, onCellEdit, onRowSave, onAddRow, onBulkDelete, initialPageSize, pageSizeOptions, initialColumnPinning, initialColumnVisibility, initialSorting, onSelectionChange, ariaLabel, striped, stickyHeader, maxHeight, globalFilter: globalFilterProp, onGlobalFilterChange, className, toolbarSlot, features, labels: labelsProp, density, theme, isolate, onView, onDelete, viewSheet, confirmDelete, }: DataTableProps<TData>): React$1.JSX.Element;
400
411
 
401
412
  /**
402
413
  * Shared portal container for every overlay inside a DataTable (popover,
@@ -426,13 +437,13 @@ type Props$2<TData, TValue> = {
426
437
  column: Column<TData, TValue>;
427
438
  title: string;
428
439
  };
429
- declare function DataTableColumnHeader<TData, TValue>({ column, title, }: Props$2<TData, TValue>): react_jsx_runtime.JSX.Element;
440
+ declare function DataTableColumnHeader<TData, TValue>({ column, title, }: Props$2<TData, TValue>): React$1.JSX.Element;
430
441
 
431
442
  type Props$1<TData> = {
432
443
  table: Table<TData>;
433
444
  pageSizeOptions?: number[];
434
445
  };
435
- declare function DataTablePagination<TData>({ table, pageSizeOptions, }: Props$1<TData>): react_jsx_runtime.JSX.Element;
446
+ declare function DataTablePagination<TData>({ table, pageSizeOptions, }: Props$1<TData>): React$1.JSX.Element;
436
447
 
437
448
  type ToolbarFeatureFlags = {
438
449
  search?: boolean;
@@ -468,7 +479,7 @@ type Props<TData> = {
468
479
  features?: ToolbarFeatureFlags;
469
480
  labels?: ToolbarLabels;
470
481
  };
471
- declare function DataTableToolbar<TData>({ table, totalRecords, isFetching, onRefresh, onAddRow, onBulkDelete, exportFileName, globalFilter, onGlobalFilterChange, toolbarSlot, features, labels: labelsProp, }: Props<TData>): react_jsx_runtime.JSX.Element;
482
+ declare function DataTableToolbar<TData>({ table, totalRecords, isFetching, onRefresh, onAddRow, onBulkDelete, exportFileName, globalFilter, onGlobalFilterChange, toolbarSlot, features, labels: labelsProp, }: Props<TData>): React$1.JSX.Element;
472
483
 
473
484
  type EditableCellProps<TData, TValue> = CellContext<TData, TValue> & {
474
485
  isEditing: boolean;
@@ -478,7 +489,7 @@ type EditableCellProps<TData, TValue> = CellContext<TData, TValue> & {
478
489
  onCancel: () => void;
479
490
  onStartEdit: () => void;
480
491
  };
481
- declare function EditableCell<TData, TValue>({ getValue, column, row, isEditing, autoOpen, onCommit, onCancel, onStartEdit, }: EditableCellProps<TData, TValue>): react_jsx_runtime.JSX.Element;
492
+ declare function EditableCell<TData, TValue>({ getValue, column, row, isEditing, autoOpen, onCommit, onCancel, onStartEdit, }: EditableCellProps<TData, TValue>): React$1.JSX.Element;
482
493
 
483
494
  type TextOp = "contains" | "notContains" | "equals" | "notEqual" | "startsWith" | "endsWith" | "blank" | "notBlank";
484
495
  type NumberOp = "equals" | "notEqual" | "lessThan" | "lessThanOrEqual" | "greaterThan" | "greaterThanOrEqual" | "inRange" | "blank" | "notBlank";
@@ -507,9 +518,11 @@ type CommonProps<TData, TValue> = {
507
518
  column: Column<TData, TValue>;
508
519
  onClose: () => void;
509
520
  };
510
- declare function ColumnFilterPanel<TData, TValue>(props: CommonProps<TData, TValue>): react_jsx_runtime.JSX.Element | null;
521
+ declare function ColumnFilterPanel<TData, TValue>(props: CommonProps<TData, TValue>): React$1.JSX.Element | null;
511
522
 
523
+ /** Neutralize spreadsheet formulas in untrusted text; preserve real numbers. */
524
+ declare function sanitizeSpreadsheetValue(value: unknown): string;
512
525
  declare function exportToCsv<TData>(table: Table<TData>, fileName?: string): void;
513
526
  declare function exportToExcel<TData>(table: Table<TData>, fileName?: string): void;
514
527
 
515
- export { type AdvFilter, type CellEditorType, ColumnFilterPanel, type Combine, type Condition, type ConfirmDeleteConfig, type ConfirmDeleteContext, type CustomRowAction, DataTable, type DataTableColumn, DataTableColumnHeader, type DataTableDataSource, type DataTableDataSourceResult, type DataTableDensity, type DataTableErrorContext, type DataTableFeatures, type DataTableFetchParams, type DataTableLabels, type DataTableModedTheme, DataTablePagination, type DataTableProps, DataTableRowActions, type DataTableRowActionsProps, type DataTableTheme, type DataTableThemeName, type DataTableTokens, DataTableToolbar, type DateOp, EditableCell, type FilterType, ISOLATE_DARK_TOKENS, ISOLATE_LIGHT_TOKENS, type NumberOp, PortalContainerContext, type RowAction, type RowActionId, type SelectOption, type SetFilter, type TextOp, type ViewSheetConfig, type ViewSheetDensity, type ViewSheetLabels, booleanFilterFn, buildPreset, dateFilterFn, exportToCsv, exportToExcel, isFilterActive, numberFilterFn, setFilterFn, splitTheme, textFilterFn, themePresets, themeToStyle, tokensToCssBlock, tokensToStyle, usePortalContainer };
528
+ export { type AdvFilter, type CellEditorType, ColumnFilterPanel, type Combine, type Condition, type ConfirmDeleteConfig, type ConfirmDeleteContext, type CustomRowAction, DataTable, type DataTableColumn, DataTableColumnHeader, type DataTableDataSource, type DataTableDataSourceResult, type DataTableDensity, type DataTableErrorContext, type DataTableFeatures, type DataTableFetchParams, type DataTableLabels, type DataTableModedTheme, DataTablePagination, type DataTableProps, DataTableRowActions, type DataTableRowActionsProps, type DataTableTheme, type DataTableThemeName, type DataTableTokens, DataTableToolbar, type DateOp, EditableCell, type FilterType, ISOLATE_DARK_TOKENS, ISOLATE_LIGHT_TOKENS, type NumberOp, PortalContainerContext, type RowAction, type RowActionId, type SelectOption, type SetFilter, type TextOp, type ViewSheetConfig, type ViewSheetDensity, type ViewSheetLabels, booleanFilterFn, buildPreset, dateFilterFn, exportToCsv, exportToExcel, isFilterActive, numberFilterFn, sanitizeSpreadsheetValue, setFilterFn, splitTheme, textFilterFn, themePresets, themeToStyle, tokensToCssBlock, tokensToStyle, usePortalContainer };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { Column, RowData, ColumnDef, SortingState, ColumnFiltersState, ColumnPinningState, VisibilityState, Table, CellContext, FilterFn } from '@tanstack/react-table';
3
1
  import * as React$1 from 'react';
4
2
  import { CSSProperties } from 'react';
3
+ import { Column, RowData, ColumnDef, SortingState, ColumnFiltersState, ColumnPinningState, VisibilityState, Table, CellContext, FilterFn } from '@tanstack/react-table';
5
4
 
6
5
  type RowActionId = "view" | "edit" | "duplicate" | "delete" | string;
7
6
  type CustomRowAction<TData> = {
@@ -20,7 +19,7 @@ type DataTableRowActionsProps<TData> = {
20
19
  onSaveEdit?: () => void;
21
20
  onCancelEdit?: () => void;
22
21
  };
23
- declare function DataTableRowActions<TData>({ row, actions, customActions, onAction, isEditing, onSaveEdit, onCancelEdit, }: DataTableRowActionsProps<TData>): react_jsx_runtime.JSX.Element;
22
+ declare function DataTableRowActions<TData>({ row, actions, customActions, onAction, isEditing, onSaveEdit, onCancelEdit, }: DataTableRowActionsProps<TData>): React$1.JSX.Element;
24
23
 
25
24
  /**
26
25
  * CSS variable overrides for a single DataTable instance.
@@ -357,6 +356,18 @@ type DataTableProps<TData extends {
357
356
  pageSizeOptions?: number[];
358
357
  initialColumnPinning?: ColumnPinningState;
359
358
  initialColumnVisibility?: VisibilityState;
359
+ /** Initial sort order. */
360
+ initialSorting?: SortingState;
361
+ /** Observe selected row objects (loaded rows only in server mode). */
362
+ onSelectionChange?: (rows: TData[]) => void;
363
+ /** Accessible table name. */
364
+ ariaLabel?: string;
365
+ /** Alternating row backgrounds. */
366
+ striped?: boolean;
367
+ /** Keep headers visible inside a vertically constrained table. */
368
+ stickyHeader?: boolean;
369
+ /** Scroll viewport height, e.g. "480px". */
370
+ maxHeight?: React.CSSProperties["maxHeight"];
360
371
  /** Optional controlled global filter (for cross-tab persistence). */
361
372
  globalFilter?: string;
362
373
  onGlobalFilterChange?: (value: string) => void;
@@ -396,7 +407,7 @@ type DataTableProps<TData extends {
396
407
  };
397
408
  declare function DataTable<TData extends {
398
409
  id: string | number;
399
- }>({ data, columns, dataSource, isLoading, isFetching, onRefresh, totalRecords, exportFileName, enableSelection, renderSubRow, getSubRows, rowActions, customRowActions, onRowAction, onCellEdit, onRowSave, onAddRow, onBulkDelete, initialPageSize, pageSizeOptions, initialColumnPinning, initialColumnVisibility, globalFilter: globalFilterProp, onGlobalFilterChange, className, toolbarSlot, features, labels: labelsProp, density, theme, isolate, onView, onDelete, viewSheet, confirmDelete, }: DataTableProps<TData>): react_jsx_runtime.JSX.Element;
410
+ }>({ data, columns, dataSource, isLoading, isFetching, onRefresh, totalRecords, exportFileName, enableSelection, renderSubRow, getSubRows, rowActions, customRowActions, onRowAction, onCellEdit, onRowSave, onAddRow, onBulkDelete, initialPageSize, pageSizeOptions, initialColumnPinning, initialColumnVisibility, initialSorting, onSelectionChange, ariaLabel, striped, stickyHeader, maxHeight, globalFilter: globalFilterProp, onGlobalFilterChange, className, toolbarSlot, features, labels: labelsProp, density, theme, isolate, onView, onDelete, viewSheet, confirmDelete, }: DataTableProps<TData>): React$1.JSX.Element;
400
411
 
401
412
  /**
402
413
  * Shared portal container for every overlay inside a DataTable (popover,
@@ -426,13 +437,13 @@ type Props$2<TData, TValue> = {
426
437
  column: Column<TData, TValue>;
427
438
  title: string;
428
439
  };
429
- declare function DataTableColumnHeader<TData, TValue>({ column, title, }: Props$2<TData, TValue>): react_jsx_runtime.JSX.Element;
440
+ declare function DataTableColumnHeader<TData, TValue>({ column, title, }: Props$2<TData, TValue>): React$1.JSX.Element;
430
441
 
431
442
  type Props$1<TData> = {
432
443
  table: Table<TData>;
433
444
  pageSizeOptions?: number[];
434
445
  };
435
- declare function DataTablePagination<TData>({ table, pageSizeOptions, }: Props$1<TData>): react_jsx_runtime.JSX.Element;
446
+ declare function DataTablePagination<TData>({ table, pageSizeOptions, }: Props$1<TData>): React$1.JSX.Element;
436
447
 
437
448
  type ToolbarFeatureFlags = {
438
449
  search?: boolean;
@@ -468,7 +479,7 @@ type Props<TData> = {
468
479
  features?: ToolbarFeatureFlags;
469
480
  labels?: ToolbarLabels;
470
481
  };
471
- declare function DataTableToolbar<TData>({ table, totalRecords, isFetching, onRefresh, onAddRow, onBulkDelete, exportFileName, globalFilter, onGlobalFilterChange, toolbarSlot, features, labels: labelsProp, }: Props<TData>): react_jsx_runtime.JSX.Element;
482
+ declare function DataTableToolbar<TData>({ table, totalRecords, isFetching, onRefresh, onAddRow, onBulkDelete, exportFileName, globalFilter, onGlobalFilterChange, toolbarSlot, features, labels: labelsProp, }: Props<TData>): React$1.JSX.Element;
472
483
 
473
484
  type EditableCellProps<TData, TValue> = CellContext<TData, TValue> & {
474
485
  isEditing: boolean;
@@ -478,7 +489,7 @@ type EditableCellProps<TData, TValue> = CellContext<TData, TValue> & {
478
489
  onCancel: () => void;
479
490
  onStartEdit: () => void;
480
491
  };
481
- declare function EditableCell<TData, TValue>({ getValue, column, row, isEditing, autoOpen, onCommit, onCancel, onStartEdit, }: EditableCellProps<TData, TValue>): react_jsx_runtime.JSX.Element;
492
+ declare function EditableCell<TData, TValue>({ getValue, column, row, isEditing, autoOpen, onCommit, onCancel, onStartEdit, }: EditableCellProps<TData, TValue>): React$1.JSX.Element;
482
493
 
483
494
  type TextOp = "contains" | "notContains" | "equals" | "notEqual" | "startsWith" | "endsWith" | "blank" | "notBlank";
484
495
  type NumberOp = "equals" | "notEqual" | "lessThan" | "lessThanOrEqual" | "greaterThan" | "greaterThanOrEqual" | "inRange" | "blank" | "notBlank";
@@ -507,9 +518,11 @@ type CommonProps<TData, TValue> = {
507
518
  column: Column<TData, TValue>;
508
519
  onClose: () => void;
509
520
  };
510
- declare function ColumnFilterPanel<TData, TValue>(props: CommonProps<TData, TValue>): react_jsx_runtime.JSX.Element | null;
521
+ declare function ColumnFilterPanel<TData, TValue>(props: CommonProps<TData, TValue>): React$1.JSX.Element | null;
511
522
 
523
+ /** Neutralize spreadsheet formulas in untrusted text; preserve real numbers. */
524
+ declare function sanitizeSpreadsheetValue(value: unknown): string;
512
525
  declare function exportToCsv<TData>(table: Table<TData>, fileName?: string): void;
513
526
  declare function exportToExcel<TData>(table: Table<TData>, fileName?: string): void;
514
527
 
515
- export { type AdvFilter, type CellEditorType, ColumnFilterPanel, type Combine, type Condition, type ConfirmDeleteConfig, type ConfirmDeleteContext, type CustomRowAction, DataTable, type DataTableColumn, DataTableColumnHeader, type DataTableDataSource, type DataTableDataSourceResult, type DataTableDensity, type DataTableErrorContext, type DataTableFeatures, type DataTableFetchParams, type DataTableLabels, type DataTableModedTheme, DataTablePagination, type DataTableProps, DataTableRowActions, type DataTableRowActionsProps, type DataTableTheme, type DataTableThemeName, type DataTableTokens, DataTableToolbar, type DateOp, EditableCell, type FilterType, ISOLATE_DARK_TOKENS, ISOLATE_LIGHT_TOKENS, type NumberOp, PortalContainerContext, type RowAction, type RowActionId, type SelectOption, type SetFilter, type TextOp, type ViewSheetConfig, type ViewSheetDensity, type ViewSheetLabels, booleanFilterFn, buildPreset, dateFilterFn, exportToCsv, exportToExcel, isFilterActive, numberFilterFn, setFilterFn, splitTheme, textFilterFn, themePresets, themeToStyle, tokensToCssBlock, tokensToStyle, usePortalContainer };
528
+ export { type AdvFilter, type CellEditorType, ColumnFilterPanel, type Combine, type Condition, type ConfirmDeleteConfig, type ConfirmDeleteContext, type CustomRowAction, DataTable, type DataTableColumn, DataTableColumnHeader, type DataTableDataSource, type DataTableDataSourceResult, type DataTableDensity, type DataTableErrorContext, type DataTableFeatures, type DataTableFetchParams, type DataTableLabels, type DataTableModedTheme, DataTablePagination, type DataTableProps, DataTableRowActions, type DataTableRowActionsProps, type DataTableTheme, type DataTableThemeName, type DataTableTokens, DataTableToolbar, type DateOp, EditableCell, type FilterType, ISOLATE_DARK_TOKENS, ISOLATE_LIGHT_TOKENS, type NumberOp, PortalContainerContext, type RowAction, type RowActionId, type SelectOption, type SetFilter, type TextOp, type ViewSheetConfig, type ViewSheetDensity, type ViewSheetLabels, booleanFilterFn, buildPreset, dateFilterFn, exportToCsv, exportToExcel, isFilterActive, numberFilterFn, sanitizeSpreadsheetValue, setFilterFn, splitTheme, textFilterFn, themePresets, themeToStyle, tokensToCssBlock, tokensToStyle, usePortalContainer };
package/dist/index.js CHANGED
@@ -281,15 +281,21 @@ function PopoverContent({
281
281
  }
282
282
 
283
283
  // src/export.ts
284
+ function sanitizeSpreadsheetValue(value) {
285
+ if (value == null) return "";
286
+ const text = String(value);
287
+ if (typeof value === "string" && (/^[\s\u0000-\u001f]*[=+\-@=+-@]/u.test(text) || /^[\t\r\n]/.test(text))) return `'${text}`;
288
+ return text;
289
+ }
284
290
  function escapeCsv(value) {
285
291
  if (value === null || value === void 0) return "";
286
- const s = String(value);
292
+ const s = sanitizeSpreadsheetValue(value);
287
293
  if (/[",\n\r]/.test(s)) return `"${s.replace(/"/g, '""')}"`;
288
294
  return s;
289
295
  }
290
296
  function escapeHtml(value) {
291
297
  if (value === null || value === void 0) return "";
292
- return String(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
298
+ return sanitizeSpreadsheetValue(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
293
299
  }
294
300
  function getExportRows(table) {
295
301
  const visible = table.getVisibleLeafColumns().filter((c) => {
@@ -1899,7 +1905,7 @@ function EditableCell({
1899
1905
  if (typeof flag === "function") return flag(row.original);
1900
1906
  return flag;
1901
1907
  })();
1902
- if (!isEditing) {
1908
+ if (!isEditing || !isEditable) {
1903
1909
  const display = renderDisplay(initial, editor, meta);
1904
1910
  return /* @__PURE__ */ jsx(
1905
1911
  "div",
@@ -1916,7 +1922,9 @@ function EditableCell({
1916
1922
  }
1917
1923
  );
1918
1924
  }
1919
- const commit = (value) => onCommit(value);
1925
+ const commit = (value) => {
1926
+ if (isEditable) onCommit(value);
1927
+ };
1920
1928
  const handleKey = (e) => {
1921
1929
  if (e.key === "Enter") commit(local);
1922
1930
  else if (e.key === "Escape") onCancel();
@@ -2046,6 +2054,9 @@ var TOKEN_TO_VAR = {
2046
2054
  radius: "--radius",
2047
2055
  fontFamily: "--font-family"
2048
2056
  };
2057
+ function isSafeToken(value) {
2058
+ return typeof value === "string" && !/[;{}<>@\\\u0000-\u001f]/.test(value) && !/\/\*|\*\/|url\s*\(|expression\s*\(/i.test(value);
2059
+ }
2049
2060
  function isModed(theme) {
2050
2061
  if (!theme) return false;
2051
2062
  return "light" in theme || "dark" in theme;
@@ -2054,8 +2065,8 @@ function tokensToStyle(tokens) {
2054
2065
  if (!tokens) return {};
2055
2066
  const out = {};
2056
2067
  for (const [k, v] of Object.entries(tokens)) {
2057
- if (v == null) continue;
2058
- const cssVar = TOKEN_TO_VAR[k];
2068
+ if (!isSafeToken(v)) continue;
2069
+ const cssVar = Object.prototype.hasOwnProperty.call(TOKEN_TO_VAR, k) ? TOKEN_TO_VAR[k] : void 0;
2059
2070
  if (cssVar) out[cssVar] = v;
2060
2071
  }
2061
2072
  return out;
@@ -2129,8 +2140,8 @@ function tokensToCssBlock(tokens) {
2129
2140
  if (!tokens) return "";
2130
2141
  const parts = [];
2131
2142
  for (const [k, v] of Object.entries(tokens)) {
2132
- if (v == null) continue;
2133
- const cssVar = TOKEN_TO_VAR[k];
2143
+ if (!isSafeToken(v)) continue;
2144
+ const cssVar = Object.prototype.hasOwnProperty.call(TOKEN_TO_VAR, k) ? TOKEN_TO_VAR[k] : void 0;
2134
2145
  if (cssVar) parts.push(`${cssVar}:${v}`);
2135
2146
  }
2136
2147
  return parts.join(";");
@@ -2554,6 +2565,10 @@ function useEditingContext() {
2554
2565
  if (!ctx) throw new Error("DataTable editing context missing");
2555
2566
  return ctx;
2556
2567
  }
2568
+ function DefaultCellHost(ctx) {
2569
+ const value = ctx.getValue();
2570
+ return value == null ? null : String(value);
2571
+ }
2557
2572
  function EditableCellHost(ctx) {
2558
2573
  const {
2559
2574
  editingCell,
@@ -2675,6 +2690,7 @@ var DENSITY_CLASS = {
2675
2690
  default: "",
2676
2691
  comfortable: "[&_tbody_td]:py-2"
2677
2692
  };
2693
+ var EMPTY_DATA = [];
2678
2694
  function DataTable({
2679
2695
  data,
2680
2696
  columns,
@@ -2698,6 +2714,12 @@ function DataTable({
2698
2714
  pageSizeOptions,
2699
2715
  initialColumnPinning,
2700
2716
  initialColumnVisibility,
2717
+ initialSorting,
2718
+ onSelectionChange,
2719
+ ariaLabel = "Data table",
2720
+ striped = false,
2721
+ stickyHeader = false,
2722
+ maxHeight,
2701
2723
  globalFilter: globalFilterProp,
2702
2724
  onGlobalFilterChange,
2703
2725
  className,
@@ -2774,7 +2796,7 @@ function DataTable({
2774
2796
  }
2775
2797
  setConfirmCtx(null);
2776
2798
  };
2777
- const [sorting, setSorting] = useState([]);
2799
+ const [sorting, setSorting] = useState(initialSorting ?? []);
2778
2800
  const [columnFilters, setColumnFilters] = useState([]);
2779
2801
  const [internalGlobalFilter, setInternalGlobalFilter] = useState("");
2780
2802
  const isControlledFilter = globalFilterProp !== void 0;
@@ -2870,7 +2892,7 @@ function DataTable({
2870
2892
  // eslint-disable-next-line react-hooks/exhaustive-deps
2871
2893
  ...dataSourceDeps
2872
2894
  ]);
2873
- const baseData = dataSourceEnabled ? sourceRows : data ?? [];
2895
+ const baseData = dataSourceEnabled ? sourceRows : data ?? EMPTY_DATA;
2874
2896
  const effectiveIsLoading = dataSourceEnabled ? sourceLoading : isLoading;
2875
2897
  const effectiveIsFetching = dataSourceEnabled ? sourceFetching : isFetching;
2876
2898
  const effectiveOnRefresh = dataSourceEnabled ? () => setSourceRefreshKey((key) => key + 1) : onRefresh;
@@ -2914,7 +2936,7 @@ function DataTable({
2914
2936
  title: headerLabel
2915
2937
  }
2916
2938
  ),
2917
- cell: hasEditor ? EditableCellHost : original
2939
+ cell: hasEditor ? EditableCellHost : original ?? DefaultCellHost
2918
2940
  };
2919
2941
  };
2920
2942
  const built = columns.map(wrap);
@@ -3026,10 +3048,10 @@ function DataTable({
3026
3048
  enableColumnFilters: f.filtering,
3027
3049
  enableColumnResizing: f.resizing,
3028
3050
  columnResizeMode: "onChange",
3029
- enableRowSelection: true,
3051
+ enableRowSelection: enableSelection,
3030
3052
  enableExpanding: !!(renderSubRow || getSubRows),
3031
3053
  enablePinning: f.pinning,
3032
- manualPagination: isServerSideDataSource,
3054
+ manualPagination: isServerSideDataSource || !f.pagination,
3033
3055
  manualSorting: isServerSideDataSource,
3034
3056
  manualFiltering: isServerSideDataSource,
3035
3057
  pageCount: isServerSideDataSource ? Math.max(1, Math.ceil(effectiveTotalRecords / pagination.pageSize)) : void 0,
@@ -3119,6 +3141,11 @@ function DataTable({
3119
3141
  setEditingRowId(tempId);
3120
3142
  } : void 0;
3121
3143
  const rows = table.getRowModel().rows;
3144
+ const selectionCallback = useRef(onSelectionChange);
3145
+ selectionCallback.current = onSelectionChange;
3146
+ useEffect(() => {
3147
+ selectionCallback.current?.(table.getSelectedRowModel().flatRows.map((row) => row.original));
3148
+ }, [rowSelection, mergedData, table]);
3122
3149
  const visibleLeafCount = table.getVisibleLeafColumns().length;
3123
3150
  const editingContextValue = useMemo(
3124
3151
  () => ({
@@ -3196,17 +3223,18 @@ function DataTable({
3196
3223
  labels
3197
3224
  }
3198
3225
  ),
3199
- /* @__PURE__ */ jsxs("div", { className: "relative w-full overflow-auto", children: [
3226
+ /* @__PURE__ */ jsxs("div", { className: "relative w-full overflow-auto", style: { maxHeight }, children: [
3200
3227
  /* @__PURE__ */ jsxs(
3201
3228
  "table",
3202
3229
  {
3203
- className: "w-full caption-bottom text-sm",
3230
+ "aria-label": ariaLabel,
3231
+ className: cn("w-full caption-bottom text-sm", striped && "[&_tbody>tr:nth-child(even)]:bg-muted/25"),
3204
3232
  style: {
3205
3233
  width: table.getCenterTotalSize() ? void 0 : "100%",
3206
3234
  minWidth: "100%"
3207
3235
  },
3208
3236
  children: [
3209
- /* @__PURE__ */ jsx("thead", { className: "sticky top-0 z-10 bg-card/95 backdrop-blur supports-[backdrop-filter]:bg-card/70", children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsx("tr", { className: "border-b", children: hg.headers.map((header) => {
3237
+ /* @__PURE__ */ jsx("thead", { className: cn("bg-card", stickyHeader && "sticky top-0 z-10"), children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsx("tr", { className: "border-b", children: hg.headers.map((header) => {
3210
3238
  const meta = header.column.columnDef.meta;
3211
3239
  const isUtility = header.column.id === "__select" || header.column.id === "__expand" || header.column.id === "__actions";
3212
3240
  const isPinned = !!header.column.getIsPinned();
@@ -3382,6 +3410,6 @@ function renderSkeleton(cols, rows) {
3382
3410
  return Array.from({ length: rows }).map((_, r) => /* @__PURE__ */ jsx("tr", { className: "border-b", children: Array.from({ length: cols }).map((__, c) => /* @__PURE__ */ jsx("td", { className: "px-2 py-2", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full" }) }, c)) }, r));
3383
3411
  }
3384
3412
 
3385
- export { ColumnFilterPanel, DataTable, DataTableColumnHeader, DataTablePagination, DataTableRowActions, DataTableToolbar, EditableCell, ISOLATE_DARK_TOKENS, ISOLATE_LIGHT_TOKENS, PortalContainerContext, booleanFilterFn, buildPreset, dateFilterFn, exportToCsv, exportToExcel, isFilterActive, numberFilterFn, setFilterFn, splitTheme, textFilterFn, themePresets, themeToStyle, tokensToCssBlock, tokensToStyle, usePortalContainer };
3413
+ export { ColumnFilterPanel, DataTable, DataTableColumnHeader, DataTablePagination, DataTableRowActions, DataTableToolbar, EditableCell, ISOLATE_DARK_TOKENS, ISOLATE_LIGHT_TOKENS, PortalContainerContext, booleanFilterFn, buildPreset, dateFilterFn, exportToCsv, exportToExcel, isFilterActive, numberFilterFn, sanitizeSpreadsheetValue, setFilterFn, splitTheme, textFilterFn, themePresets, themeToStyle, tokensToCssBlock, tokensToStyle, usePortalContainer };
3386
3414
  //# sourceMappingURL=index.js.map
3387
3415
  //# sourceMappingURL=index.js.map