@papernote/ui 2.0.4 → 2.0.5

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.esm.js CHANGED
@@ -14806,25 +14806,27 @@ function ActionMenu({ actions, item, }) {
14806
14806
  // Click outside handler
14807
14807
  useEffect(() => {
14808
14808
  const handleClickOutside = (event) => {
14809
- if (menuRef.current && !menuRef.current.contains(event.target) &&
14810
- buttonRef.current && !buttonRef.current.contains(event.target)) {
14809
+ if (menuRef.current &&
14810
+ !menuRef.current.contains(event.target) &&
14811
+ buttonRef.current &&
14812
+ !buttonRef.current.contains(event.target)) {
14811
14813
  setIsOpen(false);
14812
14814
  }
14813
14815
  };
14814
14816
  if (isOpen) {
14815
- document.addEventListener('mousedown', handleClickOutside);
14817
+ document.addEventListener("mousedown", handleClickOutside);
14816
14818
  }
14817
14819
  return () => {
14818
- document.removeEventListener('mousedown', handleClickOutside);
14820
+ document.removeEventListener("mousedown", handleClickOutside);
14819
14821
  };
14820
14822
  }, [isOpen]);
14821
- const visibleActions = actions.filter(action => !action.show || action.show(item));
14823
+ const visibleActions = actions.filter((action) => !action.show || action.show(item));
14822
14824
  if (visibleActions.length === 0)
14823
14825
  return null;
14824
14826
  const dropdownContent = isOpen && (jsx("div", { ref: menuRef, className: "fixed w-56 bg-white rounded-lg shadow-lg border border-paper-300 py-1", style: {
14825
14827
  zIndex: 999999,
14826
14828
  top: `${position.top}px`,
14827
- left: `${position.left}px`
14829
+ left: `${position.left}px`,
14828
14830
  }, children: visibleActions.map((action, idx) => {
14829
14831
  let iconElement = null;
14830
14832
  if (action.icon) {
@@ -14832,7 +14834,9 @@ function ActionMenu({ actions, item, }) {
14832
14834
  iconElement = action.icon;
14833
14835
  }
14834
14836
  else {
14835
- iconElement = React__default.createElement(action.icon, { className: 'h-4 w-4 flex-shrink-0' });
14837
+ iconElement = React__default.createElement(action.icon, {
14838
+ className: "h-4 w-4 flex-shrink-0",
14839
+ });
14836
14840
  }
14837
14841
  }
14838
14842
  return (jsxs("button", { type: "button", onClick: async (e) => {
@@ -14842,12 +14846,12 @@ function ActionMenu({ actions, item, }) {
14842
14846
  await action.onClick(item);
14843
14847
  }
14844
14848
  catch (error) {
14845
- console.error('DataTable action error:', error);
14849
+ console.error("DataTable action error:", error);
14846
14850
  }
14847
14851
  setIsOpen(false);
14848
- }, className: `w-full flex items-center gap-3 px-4 py-2.5 text-sm transition-colors ${action.variant === 'danger'
14849
- ? 'text-error-600 hover:bg-error-50 hover:text-error-700'
14850
- : 'text-ink-700 hover:bg-paper-50'}`, title: action.tooltip, children: [iconElement, jsx("span", { className: "flex-1 text-left", children: action.label })] }, idx));
14852
+ }, className: `w-full flex items-center gap-3 px-4 py-2.5 text-sm transition-colors ${action.variant === "danger"
14853
+ ? "text-error-600 hover:bg-error-50 hover:text-error-700"
14854
+ : "text-ink-700 hover:bg-paper-50"}`, title: action.tooltip, children: [iconElement, jsx("span", { className: "flex-1 text-left", children: action.label })] }, idx));
14851
14855
  }) }));
14852
14856
  return (jsxs(Fragment, { children: [jsx("button", { ref: buttonRef, onClick: (e) => {
14853
14857
  e.stopPropagation();
@@ -14864,13 +14868,20 @@ function getColumnStyle(column, dynamicWidth) {
14864
14868
  style.width = `${dynamicWidth}px`;
14865
14869
  }
14866
14870
  else if (column.width !== undefined) {
14867
- style.width = typeof column.width === 'number' ? `${column.width}px` : column.width;
14871
+ style.width =
14872
+ typeof column.width === "number" ? `${column.width}px` : column.width;
14868
14873
  }
14869
14874
  if (column.minWidth !== undefined) {
14870
- style.minWidth = typeof column.minWidth === 'number' ? `${column.minWidth}px` : column.minWidth;
14875
+ style.minWidth =
14876
+ typeof column.minWidth === "number"
14877
+ ? `${column.minWidth}px`
14878
+ : column.minWidth;
14871
14879
  }
14872
14880
  if (column.maxWidth !== undefined) {
14873
- style.maxWidth = typeof column.maxWidth === 'number' ? `${column.maxWidth}px` : column.maxWidth;
14881
+ style.maxWidth =
14882
+ typeof column.maxWidth === "number"
14883
+ ? `${column.maxWidth}px`
14884
+ : column.maxWidth;
14874
14885
  }
14875
14886
  if (column.flex !== undefined) {
14876
14887
  style.flexGrow = column.flex;
@@ -14929,13 +14940,13 @@ function getColumnStyle(column, dynamicWidth) {
14929
14940
  * />
14930
14941
  * ```
14931
14942
  */
14932
- function DataTable({ data, columns, loading = false, error = null, emptyMessage = 'No data available', loadingRows = 5, className = '', onSortChange, currentSort = null, onEdit, onDelete, actions = [], enableContextMenu = true, onRowClick, onRowDoubleClick, selectable = false, selectedRows: externalSelectedRows, onRowSelect, keyExtractor, expandable = false, expandedRows: externalExpandedRows, renderExpandedRow, expandedRowConfig, showExpandChevron = false,
14943
+ function DataTable({ data, columns, loading = false, error = null, emptyMessage = "No data available", loadingRows = 5, className = "", onSortChange, currentSort = null, onEdit, onDelete, actions = [], enableContextMenu = true, onRowClick, onRowDoubleClick, selectable = false, selectedRows: externalSelectedRows, onRowSelect, keyExtractor, expandable = false, expandedRows: externalExpandedRows, renderExpandedRow, expandedRowConfig, showExpandChevron = false,
14933
14944
  // Visual customization props
14934
- striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, highlightedRowId, highlightedRows = [], highlightDuration = 2000, bordered = false, borderColor = 'border-paper-200', disableHover = false, hiddenColumns = [], headerClassName = '', renderEmptyState: customRenderEmptyState, resizable = false, onColumnResize, reorderable = false, onColumnReorder, virtualized = false, virtualHeight = '600px', virtualRowHeight = 60,
14945
+ striped = false, stripedColor, density = "normal", rowClassName, rowHighlight, highlightedRowId, highlightedRows = [], highlightDuration = 2000, bordered = false, borderColor = "border-paper-200", disableHover = false, hiddenColumns = [], headerClassName = "", renderEmptyState: customRenderEmptyState, resizable = false, onColumnResize, reorderable = false, onColumnReorder, virtualized = false, virtualHeight = "600px", virtualRowHeight = 60,
14935
14946
  // Pagination props
14936
14947
  paginated = false, currentPage = 1, pageSize = 10, totalItems, onPageChange, pageSizeOptions = [10, 25, 50, 100], onPageSizeChange, showPageSizeSelector = true,
14937
14948
  // Mobile view props
14938
- mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
14949
+ mobileView = "auto", cardConfig, cardGap = "md", cardClassName, }) {
14939
14950
  // Mobile detection for auto mode
14940
14951
  const isMobileViewport = useIsMobile();
14941
14952
  // Column resizing state
@@ -14954,7 +14965,7 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
14954
14965
  const [hoveredRowKey, setHoveredRowKey] = useState(null);
14955
14966
  // Keyboard navigation state
14956
14967
  const [focusedCell, setFocusedCell] = useState(null);
14957
- const [announcement, setAnnouncement] = useState('');
14968
+ const [announcement, setAnnouncement] = useState("");
14958
14969
  const tableBodyRef = useRef(null);
14959
14970
  // Temporary row highlight state (for flash animation)
14960
14971
  const [flashingRows, setFlashingRows] = useState(new Set());
@@ -14966,18 +14977,18 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
14966
14977
  item: null,
14967
14978
  });
14968
14979
  // Filter columns based on hiddenColumns
14969
- const baseVisibleColumns = columns.filter(col => !hiddenColumns.includes(String(col.key)));
14980
+ const baseVisibleColumns = columns.filter((col) => !hiddenColumns.includes(String(col.key)));
14970
14981
  // Initialize column order on mount or when columns change
14971
14982
  useEffect(() => {
14972
14983
  if (columnOrder.length === 0) {
14973
- setColumnOrder(baseVisibleColumns.map(col => String(col.key)));
14984
+ setColumnOrder(baseVisibleColumns.map((col) => String(col.key)));
14974
14985
  }
14975
14986
  }, [baseVisibleColumns, columnOrder.length]);
14976
14987
  // Handle temporary row highlighting (flash animation)
14977
14988
  useEffect(() => {
14978
14989
  if (highlightedRows.length > 0) {
14979
14990
  // Add new highlighted rows to flashing set
14980
- const newFlashingRows = new Set(highlightedRows.map(id => String(id)));
14991
+ const newFlashingRows = new Set(highlightedRows.map((id) => String(id)));
14981
14992
  setFlashingRows(newFlashingRows);
14982
14993
  // Clear any existing timeout
14983
14994
  if (flashTimeoutRef.current) {
@@ -14997,25 +15008,25 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
14997
15008
  // Apply column order
14998
15009
  const visibleColumns = reorderable && columnOrder.length > 0
14999
15010
  ? columnOrder
15000
- .map(key => baseVisibleColumns.find(col => String(col.key) === key))
15011
+ .map((key) => baseVisibleColumns.find((col) => String(col.key) === key))
15001
15012
  .filter((col) => col !== undefined)
15002
15013
  : baseVisibleColumns;
15003
15014
  // Density classes
15004
15015
  const densityClasses = {
15005
15016
  compact: {
15006
- cell: 'px-3 py-1',
15007
- text: 'text-xs',
15008
- header: 'px-3 py-2',
15017
+ cell: "px-3 py-1",
15018
+ text: "text-xs",
15019
+ header: "px-3 py-2",
15009
15020
  },
15010
15021
  normal: {
15011
- cell: 'px-6 py-1.5',
15012
- text: 'text-sm',
15013
- header: 'px-6 py-3',
15022
+ cell: "px-6 py-1.5",
15023
+ text: "text-sm",
15024
+ header: "px-6 py-3",
15014
15025
  },
15015
15026
  comfortable: {
15016
- cell: 'px-6 py-3',
15017
- text: 'text-base',
15018
- header: 'px-6 py-4',
15027
+ cell: "px-6 py-3",
15028
+ text: "text-base",
15029
+ header: "px-6 py-4",
15019
15030
  },
15020
15031
  };
15021
15032
  const currentDensity = densityClasses[density];
@@ -15023,20 +15034,25 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15023
15034
  const getRowKey = keyExtractor || ((row) => String(row.id));
15024
15035
  // Calculate if there are any actions (for keyboard navigation column calculation)
15025
15036
  // This is computed early so it can be used in keyboard handlers
15026
- const hasAnyActions = !!(onEdit || onDelete || actions.length > 0 ||
15027
- expandedRowConfig?.edit || expandedRowConfig?.details ||
15028
- expandedRowConfig?.addRelated?.length || expandedRowConfig?.manageRelated?.length);
15037
+ const hasAnyActions = !!(onEdit ||
15038
+ onDelete ||
15039
+ actions.length > 0 ||
15040
+ expandedRowConfig?.edit ||
15041
+ expandedRowConfig?.details ||
15042
+ expandedRowConfig?.addRelated?.length ||
15043
+ expandedRowConfig?.manageRelated?.length);
15029
15044
  // Get row background class based on striping and highlighting
15030
15045
  const getRowBackgroundClass = (item, index) => {
15031
15046
  const classes = [];
15032
15047
  const rowKey = getRowKey(item);
15033
15048
  // Check for temporary flash highlight (takes priority)
15034
15049
  if (flashingRows.has(rowKey)) {
15035
- classes.push('animate-row-flash');
15050
+ classes.push("animate-row-flash");
15036
15051
  }
15037
15052
  // Check for highlighted row
15038
- else if (highlightedRowId !== undefined && rowKey === String(highlightedRowId)) {
15039
- classes.push('bg-accent-100');
15053
+ else if (highlightedRowId !== undefined &&
15054
+ rowKey === String(highlightedRowId)) {
15055
+ classes.push("bg-accent-100");
15040
15056
  }
15041
15057
  // Check for custom row highlight
15042
15058
  else if (rowHighlight) {
@@ -15048,24 +15064,27 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15048
15064
  // Check for striping
15049
15065
  else if (striped) {
15050
15066
  const isOdd = index % 2 === 0; // 0-indexed, so even index = odd row
15051
- const shouldStripe = striped === true ? isOdd :
15052
- striped === 'odd' ? isOdd :
15053
- striped === 'even' ? !isOdd :
15054
- false;
15067
+ const shouldStripe = striped === true
15068
+ ? isOdd
15069
+ : striped === "odd"
15070
+ ? isOdd
15071
+ : striped === "even"
15072
+ ? !isOdd
15073
+ : false;
15055
15074
  if (shouldStripe) {
15056
- classes.push(stripedColor || 'bg-paper-50');
15075
+ classes.push(stripedColor || "bg-paper-50");
15057
15076
  }
15058
15077
  }
15059
15078
  // Add custom row class
15060
15079
  if (rowClassName) {
15061
- if (typeof rowClassName === 'string') {
15080
+ if (typeof rowClassName === "string") {
15062
15081
  classes.push(rowClassName);
15063
15082
  }
15064
15083
  else {
15065
15084
  classes.push(rowClassName(item, index));
15066
15085
  }
15067
15086
  }
15068
- return classes.join(' ');
15087
+ return classes.join(" ");
15069
15088
  };
15070
15089
  // NEW: Expansion mode state management (for expandedRowConfig)
15071
15090
  const [expansionState, setExpansionState] = useState(null);
@@ -15080,12 +15099,12 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15080
15099
  // Column reorder handlers
15081
15100
  const handleDragStart = (e, columnKey) => {
15082
15101
  setDraggingColumn(columnKey);
15083
- e.dataTransfer.effectAllowed = 'move';
15084
- e.dataTransfer.setData('text/html', columnKey);
15102
+ e.dataTransfer.effectAllowed = "move";
15103
+ e.dataTransfer.setData("text/html", columnKey);
15085
15104
  };
15086
15105
  const handleDragOver = (e, columnKey) => {
15087
15106
  e.preventDefault();
15088
- e.dataTransfer.dropEffect = 'move';
15107
+ e.dataTransfer.dropEffect = "move";
15089
15108
  if (draggingColumn && draggingColumn !== columnKey) {
15090
15109
  setDragOverColumn(columnKey);
15091
15110
  }
@@ -15116,7 +15135,7 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15116
15135
  const handleMouseMove = (e) => {
15117
15136
  const delta = e.clientX - resizeStartX;
15118
15137
  const newWidth = Math.max(50, resizeStartWidth + delta); // Min width 50px
15119
- setColumnWidths(prev => ({
15138
+ setColumnWidths((prev) => ({
15120
15139
  ...prev,
15121
15140
  [resizingColumn]: newWidth,
15122
15141
  }));
@@ -15127,56 +15146,62 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15127
15146
  }
15128
15147
  setResizingColumn(null);
15129
15148
  };
15130
- document.addEventListener('mousemove', handleMouseMove);
15131
- document.addEventListener('mouseup', handleMouseUp);
15149
+ document.addEventListener("mousemove", handleMouseMove);
15150
+ document.addEventListener("mouseup", handleMouseUp);
15132
15151
  return () => {
15133
- document.removeEventListener('mousemove', handleMouseMove);
15134
- document.removeEventListener('mouseup', handleMouseUp);
15152
+ document.removeEventListener("mousemove", handleMouseMove);
15153
+ document.removeEventListener("mouseup", handleMouseUp);
15135
15154
  };
15136
- }, [resizingColumn, resizeStartX, resizeStartWidth, columnWidths, onColumnResize]);
15155
+ }, [
15156
+ resizingColumn,
15157
+ resizeStartX,
15158
+ resizeStartWidth,
15159
+ columnWidths,
15160
+ onColumnResize,
15161
+ ]);
15137
15162
  // Build combined actions: built-in edit/delete + custom actions + expansion mode actions
15138
15163
  const builtInActions = [];
15139
15164
  // Legacy onEdit (still supported)
15140
15165
  if (onEdit) {
15141
15166
  builtInActions.push({
15142
- label: 'Edit',
15167
+ label: "Edit",
15143
15168
  icon: Edit,
15144
15169
  onClick: onEdit,
15145
- variant: 'secondary',
15146
- tooltip: 'Edit item'
15170
+ variant: "secondary",
15171
+ tooltip: "Edit item",
15147
15172
  });
15148
15173
  }
15149
15174
  // NEW: Edit mode from expandedRowConfig
15150
15175
  if (expandedRowConfig?.edit && !onEdit) {
15151
15176
  const editConfig = expandedRowConfig.edit;
15152
15177
  builtInActions.push({
15153
- label: editConfig.menuLabel || 'Edit',
15178
+ label: editConfig.menuLabel || "Edit",
15154
15179
  icon: editConfig.menuIcon || Edit,
15155
15180
  onClick: (item) => {
15156
15181
  const rowKey = getRowKey(item);
15157
- handleExpansionWithMode(rowKey, 'edit');
15182
+ handleExpansionWithMode(rowKey, "edit");
15158
15183
  },
15159
- variant: 'secondary',
15160
- tooltip: 'Edit inline'
15184
+ variant: "secondary",
15185
+ tooltip: "Edit inline",
15161
15186
  });
15162
15187
  }
15163
15188
  // NEW: View details mode from expandedRowConfig
15164
15189
  if (expandedRowConfig?.details) {
15165
15190
  const detailsConfig = expandedRowConfig.details;
15166
15191
  builtInActions.push({
15167
- label: detailsConfig.menuLabel || 'View Details',
15192
+ label: detailsConfig.menuLabel || "View Details",
15168
15193
  icon: detailsConfig.menuIcon,
15169
15194
  onClick: (item) => {
15170
15195
  const rowKey = getRowKey(item);
15171
- handleExpansionWithMode(rowKey, 'details');
15196
+ handleExpansionWithMode(rowKey, "details");
15172
15197
  },
15173
- variant: 'ghost',
15174
- tooltip: 'View details'
15198
+ variant: "ghost",
15199
+ tooltip: "View details",
15175
15200
  });
15176
15201
  }
15177
15202
  // NEW: Add related modes from expandedRowConfig
15178
15203
  if (expandedRowConfig?.addRelated) {
15179
- expandedRowConfig.addRelated.forEach(config => {
15204
+ expandedRowConfig.addRelated.forEach((config) => {
15180
15205
  if (config.showInMenu !== false) {
15181
15206
  builtInActions.push({
15182
15207
  label: config.label,
@@ -15185,15 +15210,15 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15185
15210
  const rowKey = getRowKey(item);
15186
15211
  handleExpansionWithMode(rowKey, `addRelated-${config.key}`);
15187
15212
  },
15188
- variant: 'secondary',
15189
- tooltip: config.label
15213
+ variant: "secondary",
15214
+ tooltip: config.label,
15190
15215
  });
15191
15216
  }
15192
15217
  });
15193
15218
  }
15194
15219
  // NEW: Manage related modes from expandedRowConfig
15195
15220
  if (expandedRowConfig?.manageRelated) {
15196
- expandedRowConfig.manageRelated.forEach(config => {
15221
+ expandedRowConfig.manageRelated.forEach((config) => {
15197
15222
  if (config.showInMenu !== false) {
15198
15223
  builtInActions.push({
15199
15224
  label: config.label,
@@ -15202,8 +15227,8 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15202
15227
  const rowKey = getRowKey(item);
15203
15228
  handleExpansionWithMode(rowKey, `manageRelated-${config.key}`);
15204
15229
  },
15205
- variant: 'ghost',
15206
- tooltip: config.label
15230
+ variant: "ghost",
15231
+ tooltip: config.label,
15207
15232
  });
15208
15233
  }
15209
15234
  });
@@ -15213,11 +15238,11 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15213
15238
  let deleteAction = null;
15214
15239
  if (onDelete) {
15215
15240
  deleteAction = {
15216
- label: 'Delete',
15241
+ label: "Delete",
15217
15242
  icon: Trash,
15218
15243
  onClick: onDelete,
15219
- variant: 'danger',
15220
- tooltip: 'Delete item'
15244
+ variant: "danger",
15245
+ tooltip: "Delete item",
15221
15246
  };
15222
15247
  }
15223
15248
  // Build final actions array with consistent ordering:
@@ -15230,11 +15255,11 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15230
15255
  const allActions = [
15231
15256
  ...builtInActions,
15232
15257
  ...actions,
15233
- ...(deleteAction ? [deleteAction] : [])
15258
+ ...(deleteAction ? [deleteAction] : []),
15234
15259
  ];
15235
15260
  // Convert actions to menu items for context menu
15236
15261
  const convertActionsToMenuItems = (item) => {
15237
- const visibleActions = allActions.filter(action => !action.show || action.show(item));
15262
+ const visibleActions = allActions.filter((action) => !action.show || action.show(item));
15238
15263
  return visibleActions.map((action, idx) => {
15239
15264
  let iconElement = null;
15240
15265
  if (action.icon) {
@@ -15242,7 +15267,9 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15242
15267
  iconElement = action.icon;
15243
15268
  }
15244
15269
  else {
15245
- iconElement = React__default.createElement(action.icon, { className: 'h-4 w-4' });
15270
+ iconElement = React__default.createElement(action.icon, {
15271
+ className: "h-4 w-4",
15272
+ });
15246
15273
  }
15247
15274
  }
15248
15275
  return {
@@ -15250,7 +15277,7 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15250
15277
  label: action.label,
15251
15278
  icon: iconElement,
15252
15279
  onClick: () => action.onClick(item),
15253
- danger: action.variant === 'danger',
15280
+ danger: action.variant === "danger",
15254
15281
  };
15255
15282
  });
15256
15283
  };
@@ -15259,7 +15286,9 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15259
15286
  // Expansion state management
15260
15287
  const [internalExpandedRows, setInternalExpandedRows] = useState(new Set());
15261
15288
  // Use external selection if provided, otherwise internal
15262
- const selectedRowsSet = externalSelectedRows !== undefined ? externalSelectedRows : internalSelectedRows;
15289
+ const selectedRowsSet = externalSelectedRows !== undefined
15290
+ ? externalSelectedRows
15291
+ : internalSelectedRows;
15263
15292
  const setSelectedRows = (newSet) => {
15264
15293
  if (externalSelectedRows !== undefined) {
15265
15294
  // Controlled component - notify parent
@@ -15293,7 +15322,9 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15293
15322
  }
15294
15323
  };
15295
15324
  // Use external expansion if provided, otherwise internal
15296
- const expandedRowsSet = externalExpandedRows !== undefined ? externalExpandedRows : internalExpandedRows;
15325
+ const expandedRowsSet = externalExpandedRows !== undefined
15326
+ ? externalExpandedRows
15327
+ : internalExpandedRows;
15297
15328
  const setExpandedRows = (newSet) => {
15298
15329
  if (externalExpandedRows !== undefined) ;
15299
15330
  else {
@@ -15335,10 +15366,10 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15335
15366
  const totalCols = visibleColumns.length;
15336
15367
  // If no cell is focused, focus first data cell on first arrow key
15337
15368
  if (!focusedCell) {
15338
- if (['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
15369
+ if (["ArrowDown", "ArrowUp", "ArrowLeft", "ArrowRight"].includes(e.key)) {
15339
15370
  e.preventDefault();
15340
15371
  setFocusedCell({ row: 0, col: 0 });
15341
- const colHeader = visibleColumns[0]?.header || 'first column';
15372
+ const colHeader = visibleColumns[0]?.header || "first column";
15342
15373
  setAnnouncement(`Row 1, ${colHeader}`);
15343
15374
  return;
15344
15375
  }
@@ -15346,73 +15377,73 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15346
15377
  }
15347
15378
  const { row, col } = focusedCell;
15348
15379
  switch (e.key) {
15349
- case 'ArrowDown':
15380
+ case "ArrowDown":
15350
15381
  e.preventDefault();
15351
15382
  if (row < totalRows - 1) {
15352
15383
  const newRow = row + 1;
15353
15384
  setFocusedCell({ row: newRow, col });
15354
15385
  const rowItem = data[newRow];
15355
- const colHeader = visibleColumns[col]?.header || '';
15386
+ const colHeader = visibleColumns[col]?.header || "";
15356
15387
  const cellValue = rowItem[visibleColumns[col]?.key];
15357
- setAnnouncement(`Row ${newRow + 1}, ${colHeader}: ${cellValue || 'empty'}`);
15388
+ setAnnouncement(`Row ${newRow + 1}, ${colHeader}: ${cellValue || "empty"}`);
15358
15389
  }
15359
15390
  break;
15360
- case 'ArrowUp':
15391
+ case "ArrowUp":
15361
15392
  e.preventDefault();
15362
15393
  if (row > 0) {
15363
15394
  const newRow = row - 1;
15364
15395
  setFocusedCell({ row: newRow, col });
15365
15396
  const rowItem = data[newRow];
15366
- const colHeader = visibleColumns[col]?.header || '';
15397
+ const colHeader = visibleColumns[col]?.header || "";
15367
15398
  const cellValue = rowItem[visibleColumns[col]?.key];
15368
- setAnnouncement(`Row ${newRow + 1}, ${colHeader}: ${cellValue || 'empty'}`);
15399
+ setAnnouncement(`Row ${newRow + 1}, ${colHeader}: ${cellValue || "empty"}`);
15369
15400
  }
15370
15401
  break;
15371
- case 'ArrowRight':
15402
+ case "ArrowRight":
15372
15403
  e.preventDefault();
15373
15404
  if (col < totalCols - 1) {
15374
15405
  const newCol = col + 1;
15375
15406
  setFocusedCell({ row, col: newCol });
15376
15407
  const rowItem = data[row];
15377
- const colHeader = visibleColumns[newCol]?.header || '';
15408
+ const colHeader = visibleColumns[newCol]?.header || "";
15378
15409
  const cellValue = rowItem[visibleColumns[newCol]?.key];
15379
- setAnnouncement(`${colHeader}: ${cellValue || 'empty'}`);
15410
+ setAnnouncement(`${colHeader}: ${cellValue || "empty"}`);
15380
15411
  }
15381
15412
  break;
15382
- case 'ArrowLeft':
15413
+ case "ArrowLeft":
15383
15414
  e.preventDefault();
15384
15415
  if (col > 0) {
15385
15416
  const newCol = col - 1;
15386
15417
  setFocusedCell({ row, col: newCol });
15387
15418
  const rowItem = data[row];
15388
- const colHeader = visibleColumns[newCol]?.header || '';
15419
+ const colHeader = visibleColumns[newCol]?.header || "";
15389
15420
  const cellValue = rowItem[visibleColumns[newCol]?.key];
15390
- setAnnouncement(`${colHeader}: ${cellValue || 'empty'}`);
15421
+ setAnnouncement(`${colHeader}: ${cellValue || "empty"}`);
15391
15422
  }
15392
15423
  break;
15393
- case 'Home':
15424
+ case "Home":
15394
15425
  e.preventDefault();
15395
15426
  if (e.ctrlKey) {
15396
15427
  // Ctrl+Home: Go to first cell
15397
15428
  setFocusedCell({ row: 0, col: 0 });
15398
- setAnnouncement(`First cell, Row 1, ${visibleColumns[0]?.header || ''}`);
15429
+ setAnnouncement(`First cell, Row 1, ${visibleColumns[0]?.header || ""}`);
15399
15430
  }
15400
15431
  else {
15401
15432
  // Home: Go to first cell in current row
15402
15433
  setFocusedCell({ row, col: 0 });
15403
15434
  const rowItem = data[row];
15404
15435
  const cellValue = rowItem[visibleColumns[0]?.key];
15405
- setAnnouncement(`${visibleColumns[0]?.header || ''}: ${cellValue || 'empty'}`);
15436
+ setAnnouncement(`${visibleColumns[0]?.header || ""}: ${cellValue || "empty"}`);
15406
15437
  }
15407
15438
  break;
15408
- case 'End':
15439
+ case "End":
15409
15440
  e.preventDefault();
15410
15441
  if (e.ctrlKey) {
15411
15442
  // Ctrl+End: Go to last cell
15412
15443
  const lastRow = totalRows - 1;
15413
15444
  const lastCol = totalCols - 1;
15414
15445
  setFocusedCell({ row: lastRow, col: lastCol });
15415
- setAnnouncement(`Last cell, Row ${lastRow + 1}, ${visibleColumns[lastCol]?.header || ''}`);
15446
+ setAnnouncement(`Last cell, Row ${lastRow + 1}, ${visibleColumns[lastCol]?.header || ""}`);
15416
15447
  }
15417
15448
  else {
15418
15449
  // End: Go to last cell in current row
@@ -15420,10 +15451,10 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15420
15451
  setFocusedCell({ row, col: lastCol });
15421
15452
  const rowItem = data[row];
15422
15453
  const cellValue = rowItem[visibleColumns[lastCol]?.key];
15423
- setAnnouncement(`${visibleColumns[lastCol]?.header || ''}: ${cellValue || 'empty'}`);
15454
+ setAnnouncement(`${visibleColumns[lastCol]?.header || ""}: ${cellValue || "empty"}`);
15424
15455
  }
15425
15456
  break;
15426
- case 'Enter':
15457
+ case "Enter":
15427
15458
  e.preventDefault();
15428
15459
  {
15429
15460
  const rowItem = data[row];
@@ -15431,27 +15462,27 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15431
15462
  // Priority: Edit mode > Details mode > Row double-click handler
15432
15463
  if (onEdit) {
15433
15464
  onEdit(rowItem);
15434
- setAnnouncement('Opening edit mode');
15465
+ setAnnouncement("Opening edit mode");
15435
15466
  }
15436
15467
  else if (expandedRowConfig?.edit) {
15437
- handleExpansionWithMode(rowKey, 'edit');
15438
- setAnnouncement('Opening inline edit');
15468
+ handleExpansionWithMode(rowKey, "edit");
15469
+ setAnnouncement("Opening inline edit");
15439
15470
  }
15440
15471
  else if (expandedRowConfig?.details) {
15441
- handleExpansionWithMode(rowKey, 'details');
15442
- setAnnouncement('Opening details view');
15472
+ handleExpansionWithMode(rowKey, "details");
15473
+ setAnnouncement("Opening details view");
15443
15474
  }
15444
15475
  else if (onRowDoubleClick) {
15445
15476
  onRowDoubleClick(rowItem);
15446
- setAnnouncement('Activating row');
15477
+ setAnnouncement("Activating row");
15447
15478
  }
15448
15479
  else if (onRowClick) {
15449
15480
  onRowClick(rowItem);
15450
- setAnnouncement('Row selected');
15481
+ setAnnouncement("Row selected");
15451
15482
  }
15452
15483
  }
15453
15484
  break;
15454
- case ' ':
15485
+ case " ":
15455
15486
  // Space: Toggle selection if selectable
15456
15487
  if (selectable) {
15457
15488
  e.preventDefault();
@@ -15459,60 +15490,82 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15459
15490
  const rowKey = getRowKey(rowItem);
15460
15491
  handleRowSelect(rowKey);
15461
15492
  const isNowSelected = !selectedRowsSet.has(rowKey);
15462
- setAnnouncement(isNowSelected ? 'Row selected' : 'Row deselected');
15493
+ setAnnouncement(isNowSelected ? "Row selected" : "Row deselected");
15463
15494
  }
15464
15495
  break;
15465
- case 'Escape':
15496
+ case "Escape":
15466
15497
  e.preventDefault();
15467
15498
  setFocusedCell(null);
15468
- setAnnouncement('Table navigation exited');
15499
+ setAnnouncement("Table navigation exited");
15469
15500
  // Return focus to table container
15470
- tableBodyRef.current?.closest('table')?.focus();
15501
+ tableBodyRef.current?.closest("table")?.focus();
15471
15502
  break;
15472
- case 'PageDown':
15503
+ case "PageDown":
15473
15504
  e.preventDefault();
15474
15505
  {
15475
15506
  const jumpSize = 10;
15476
15507
  const newRow = Math.min(row + jumpSize, totalRows - 1);
15477
15508
  setFocusedCell({ row: newRow, col });
15478
- const colHeader = visibleColumns[col]?.header || '';
15509
+ const colHeader = visibleColumns[col]?.header || "";
15479
15510
  setAnnouncement(`Row ${newRow + 1} of ${totalRows}, ${colHeader}`);
15480
15511
  }
15481
15512
  break;
15482
- case 'PageUp':
15513
+ case "PageUp":
15483
15514
  e.preventDefault();
15484
15515
  {
15485
15516
  const jumpSize = 10;
15486
15517
  const newRow = Math.max(row - jumpSize, 0);
15487
15518
  setFocusedCell({ row: newRow, col });
15488
- const colHeader = visibleColumns[col]?.header || '';
15519
+ const colHeader = visibleColumns[col]?.header || "";
15489
15520
  setAnnouncement(`Row ${newRow + 1} of ${totalRows}, ${colHeader}`);
15490
15521
  }
15491
15522
  break;
15492
15523
  }
15493
- }, [data, visibleColumns, focusedCell, selectable, expandedRowConfig, onEdit, onRowDoubleClick, onRowClick, getRowKey, handleExpansionWithMode, handleRowSelect, selectedRowsSet]);
15524
+ }, [
15525
+ data,
15526
+ visibleColumns,
15527
+ focusedCell,
15528
+ selectable,
15529
+ expandedRowConfig,
15530
+ onEdit,
15531
+ onRowDoubleClick,
15532
+ onRowClick,
15533
+ getRowKey,
15534
+ handleExpansionWithMode,
15535
+ handleRowSelect,
15536
+ selectedRowsSet,
15537
+ ]);
15494
15538
  // Focus the appropriate cell when focusedCell changes
15495
15539
  useEffect(() => {
15496
15540
  if (focusedCell && tableBodyRef.current) {
15497
15541
  const { row, col } = focusedCell;
15498
- const rows = tableBodyRef.current.querySelectorAll('tr[data-row-index]');
15542
+ const rows = tableBodyRef.current.querySelectorAll("tr[data-row-index]");
15499
15543
  const targetRow = rows[row];
15500
15544
  if (targetRow) {
15501
15545
  // Calculate actual column index including extra columns
15502
15546
  const hasSelectionCol = selectable;
15503
15547
  const hasExpandCol = (expandable || expandedRowConfig) && showExpandChevron;
15504
15548
  const hasActionsCol = hasAnyActions;
15505
- const extraColsBefore = (hasSelectionCol ? 1 : 0) + (hasExpandCol ? 1 : 0) + (hasActionsCol ? 1 : 0);
15506
- const cells = targetRow.querySelectorAll('td');
15549
+ const extraColsBefore = (hasSelectionCol ? 1 : 0) +
15550
+ (hasExpandCol ? 1 : 0) +
15551
+ (hasActionsCol ? 1 : 0);
15552
+ const cells = targetRow.querySelectorAll("td");
15507
15553
  const targetCell = cells[col + extraColsBefore];
15508
15554
  if (targetCell) {
15509
15555
  targetCell.focus();
15510
15556
  // Scroll into view if needed
15511
- targetCell.scrollIntoView({ block: 'nearest', inline: 'nearest' });
15557
+ targetCell.scrollIntoView({ block: "nearest", inline: "nearest" });
15512
15558
  }
15513
15559
  }
15514
15560
  }
15515
- }, [focusedCell, selectable, expandable, expandedRowConfig, showExpandChevron, hasAnyActions]);
15561
+ }, [
15562
+ focusedCell,
15563
+ selectable,
15564
+ expandable,
15565
+ expandedRowConfig,
15566
+ showExpandChevron,
15567
+ hasAnyActions,
15568
+ ]);
15516
15569
  // Handle column header click for sorting
15517
15570
  const handleSort = (column) => {
15518
15571
  if (!column.sortable || !onSortChange)
@@ -15520,8 +15573,12 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15520
15573
  const columnKey = String(column.key);
15521
15574
  // If clicking the same column, toggle direction
15522
15575
  if (currentSort?.key === columnKey) {
15523
- if (currentSort.direction === 'asc') {
15524
- onSortChange({ key: columnKey, direction: 'desc', label: column.header });
15576
+ if (currentSort.direction === "asc") {
15577
+ onSortChange({
15578
+ key: columnKey,
15579
+ direction: "desc",
15580
+ label: column.header,
15581
+ });
15525
15582
  }
15526
15583
  else {
15527
15584
  // Remove sort on third click
@@ -15530,7 +15587,7 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15530
15587
  }
15531
15588
  else {
15532
15589
  // New column - start with ascending
15533
- onSortChange({ key: columnKey, direction: 'asc', label: column.header });
15590
+ onSortChange({ key: columnKey, direction: "asc", label: column.header });
15534
15591
  }
15535
15592
  };
15536
15593
  // Get sort icon SVG for column (matches reference ui-preview.html)
@@ -15539,7 +15596,7 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15539
15596
  return null;
15540
15597
  const columnKey = String(column.key);
15541
15598
  const isActive = currentSort?.key === columnKey;
15542
- const isAscending = currentSort?.direction === 'asc';
15599
+ const isAscending = currentSort?.direction === "asc";
15543
15600
  // Inactive state - show neutral up/down arrows
15544
15601
  if (!isActive) {
15545
15602
  return (jsx("svg", { className: "ml-2 w-4 h-4 text-ink-400 group-hover:text-ink-700", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) }));
@@ -15552,17 +15609,23 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15552
15609
  return (jsx("svg", { className: "ml-2 w-4 h-4 text-accent-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 17l-4 4m0 0l-4-4m4 4V3" }) }));
15553
15610
  };
15554
15611
  // Render loading skeleton
15555
- const renderLoadingSkeleton = () => (jsx(Fragment, { children: Array.from({ length: loadingRows }, (_, i) => (jsxs("tr", { className: `animate-pulse table-row-stable ${bordered ? `border-b ${borderColor}` : ''}`, children: [selectable && (jsx("td", { className: `sticky left-0 bg-white ${currentDensity.cell} border-b ${borderColor} z-10 align-middle`, children: jsx("div", { className: "h-4 w-4 bg-paper-200 rounded" }) })), expandable && (jsx("td", { className: `sticky left-0 bg-white px-2 ${currentDensity.cell} border-b ${borderColor} z-10`, children: jsx("div", { className: "h-4 w-4 bg-paper-200 rounded" }) })), allActions.length > 0 && (jsx("td", { className: `sticky left-0 bg-white px-2 ${currentDensity.cell} border-b ${borderColor} z-10`, children: jsx("div", { className: "h-8 w-8 bg-paper-200 rounded" }) })), visibleColumns.map((column, colIndex) => {
15612
+ const renderLoadingSkeleton = () => (jsx(Fragment, { children: Array.from({ length: loadingRows }, (_, i) => (jsxs("tr", { className: `animate-pulse table-row-stable ${bordered ? `border-b ${borderColor}` : ""}`, children: [selectable && (jsx("td", { className: `sticky left-0 bg-white ${currentDensity.cell} border-b ${borderColor} z-10 align-middle`, children: jsx("div", { className: "h-4 w-4 bg-paper-200 rounded" }) })), expandable && (jsx("td", { className: `sticky left-0 bg-white px-2 ${currentDensity.cell} border-b ${borderColor} z-10`, children: jsx("div", { className: "h-4 w-4 bg-paper-200 rounded" }) })), allActions.length > 0 && (jsx("td", { className: `sticky left-0 bg-white px-2 ${currentDensity.cell} border-b ${borderColor} z-10`, children: jsx("div", { className: "h-8 w-8 bg-paper-200 rounded" }) })), visibleColumns.map((column, colIndex) => {
15556
15613
  const columnKey = String(column.key);
15557
15614
  const dynamicWidth = columnWidths[columnKey];
15558
- return (jsxs("td", { className: `${currentDensity.cell} whitespace-nowrap table-row-stable ${bordered ? `border ${borderColor}` : ''}`, style: getColumnStyle(column, dynamicWidth), children: [jsx("div", { className: "h-4 bg-paper-200 rounded mb-1" }), jsx("div", { className: "h-3 bg-paper-200 rounded w-3/4" })] }, `loading-${i}-${colIndex}`));
15615
+ return (jsxs("td", { className: `${currentDensity.cell} whitespace-nowrap table-row-stable ${bordered ? `border ${borderColor}` : ""}`, style: getColumnStyle(column, dynamicWidth), children: [jsx("div", { className: "h-4 bg-paper-200 rounded mb-1" }), jsx("div", { className: "h-3 bg-paper-200 rounded w-3/4" })] }, `loading-${i}-${colIndex}`));
15559
15616
  })] }, `loading-${i}`))) }));
15560
15617
  // Render empty state
15561
15618
  const renderEmptyStateContent = () => {
15562
15619
  if (customRenderEmptyState) {
15563
- return (jsx("tr", { children: jsx("td", { colSpan: visibleColumns.length + (allActions.length > 0 ? 1 : 0) + (selectable ? 1 : 0) + (expandable ? 1 : 0), children: customRenderEmptyState() }) }));
15620
+ return (jsx("tr", { children: jsx("td", { colSpan: visibleColumns.length +
15621
+ (allActions.length > 0 ? 1 : 0) +
15622
+ (selectable ? 1 : 0) +
15623
+ (expandable ? 1 : 0), children: customRenderEmptyState() }) }));
15564
15624
  }
15565
- return (jsx("tr", { children: jsx("td", { colSpan: visibleColumns.length + (allActions.length > 0 ? 1 : 0) + (selectable ? 1 : 0) + (expandable ? 1 : 0), className: `${currentDensity.cell} py-8 text-center text-ink-500`, children: error || emptyMessage }) }));
15625
+ return (jsx("tr", { children: jsx("td", { colSpan: visibleColumns.length +
15626
+ (allActions.length > 0 ? 1 : 0) +
15627
+ (selectable ? 1 : 0) +
15628
+ (expandable ? 1 : 0), className: `${currentDensity.cell} py-8 text-center text-ink-500`, children: error || emptyMessage }) }));
15566
15629
  };
15567
15630
  // Virtual scrolling calculations
15568
15631
  const getVisibleRange = () => {
@@ -15592,14 +15655,18 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15592
15655
  const isSelected = selectedRowsSet.has(rowKey);
15593
15656
  const isExpanded = expandedRowsSet.has(rowKey);
15594
15657
  const rowBgClass = getRowBackgroundClass(item, index);
15595
- const borderClass = bordered ? `border-b ${borderColor}` : (!visibleColumns.some(col => !!col.renderSecondary) ? `border-b ${borderColor}` : '');
15596
- const hasSecondaryRow = visibleColumns.some(col => !!col.renderSecondary);
15658
+ const borderClass = bordered
15659
+ ? `border-b ${borderColor}`
15660
+ : !visibleColumns.some((col) => !!col.renderSecondary)
15661
+ ? `border-b ${borderColor}`
15662
+ : "";
15663
+ const hasSecondaryRow = visibleColumns.some((col) => !!col.renderSecondary);
15597
15664
  // Hover state for row pair (primary + secondary)
15598
15665
  const isHovered = hoveredRowKey === rowKey;
15599
- const hoverClass = disableHover ? '' : (isHovered ? 'bg-paper-100' : '');
15666
+ const hoverClass = disableHover ? "" : isHovered ? "bg-paper-100" : "";
15600
15667
  // Check if this row is keyboard-focused
15601
15668
  const isKeyboardFocused = focusedCell?.row === index;
15602
- return (jsxs(React__default.Fragment, { children: [jsxs("tr", { "data-row-index": index, className: `table-row-stable ${onRowDoubleClick || onRowClick || onEdit || expandedRowConfig?.edit || expandedRowConfig?.details || expandedRowConfig?.addRelated?.length || expandedRowConfig?.manageRelated?.length ? 'cursor-pointer' : ''} ${isSelected ? 'bg-accent-50 border-l-2 border-accent-500' : hoverClass || rowBgClass} ${borderClass} ${isKeyboardFocused ? 'ring-2 ring-inset ring-accent-400' : ''}`, onMouseEnter: () => !disableHover && setHoveredRowKey(rowKey), onMouseLeave: () => !disableHover && setHoveredRowKey(null), onClick: () => onRowClick?.(item), onContextMenu: (e) => {
15669
+ return (jsxs(React__default.Fragment, { children: [jsxs("tr", { "data-row-index": index, className: `table-row-stable ${onRowDoubleClick || onRowClick || onEdit || expandedRowConfig?.edit || expandedRowConfig?.details || expandedRowConfig?.addRelated?.length || expandedRowConfig?.manageRelated?.length ? "cursor-pointer" : ""} ${isSelected ? "bg-accent-50 border-l-2 border-accent-500" : hoverClass || rowBgClass} ${borderClass} ${isKeyboardFocused ? "ring-2 ring-inset ring-accent-400" : ""}`, onMouseEnter: () => !disableHover && setHoveredRowKey(rowKey), onMouseLeave: () => !disableHover && setHoveredRowKey(null), onClick: () => onRowClick?.(item), onContextMenu: (e) => {
15603
15670
  if (enableContextMenu && allActions.length > 0) {
15604
15671
  e.preventDefault();
15605
15672
  e.stopPropagation();
@@ -15618,109 +15685,146 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15618
15685
  }
15619
15686
  // Priority 2: If there's an expandable edit mode, trigger it
15620
15687
  else if (expandedRowConfig?.edit) {
15621
- handleExpansionWithMode(rowKey, 'edit');
15688
+ handleExpansionWithMode(rowKey, "edit");
15622
15689
  }
15623
15690
  // Priority 3: If there's an expandable details mode, trigger it
15624
15691
  else if (expandedRowConfig?.details) {
15625
- handleExpansionWithMode(rowKey, 'details');
15692
+ handleExpansionWithMode(rowKey, "details");
15626
15693
  }
15627
15694
  // Priority 4: If there's any addRelated mode, trigger the first one
15628
- else if (expandedRowConfig?.addRelated && expandedRowConfig.addRelated.length > 0) {
15695
+ else if (expandedRowConfig?.addRelated &&
15696
+ expandedRowConfig.addRelated.length > 0) {
15629
15697
  handleExpansionWithMode(rowKey, `addRelated-${expandedRowConfig.addRelated[0].key}`);
15630
15698
  }
15631
15699
  // Priority 5: If there's any manageRelated mode, trigger the first one
15632
- else if (expandedRowConfig?.manageRelated && expandedRowConfig.manageRelated.length > 0) {
15700
+ else if (expandedRowConfig?.manageRelated &&
15701
+ expandedRowConfig.manageRelated.length > 0) {
15633
15702
  handleExpansionWithMode(rowKey, `manageRelated-${expandedRowConfig.manageRelated[0].key}`);
15634
15703
  }
15635
15704
  // Priority 6: Legacy onRowDoubleClick handler
15636
15705
  else {
15637
15706
  onRowDoubleClick?.(item);
15638
15707
  }
15639
- }, title: onEdit ? 'Double-click to edit' :
15640
- expandedRowConfig?.edit ? 'Double-click to edit inline' :
15641
- expandedRowConfig?.details ? 'Double-click to view details' :
15642
- expandedRowConfig?.addRelated && expandedRowConfig.addRelated.length > 0 ? `Double-click to ${expandedRowConfig.addRelated[0].label}` :
15643
- expandedRowConfig?.manageRelated && expandedRowConfig.manageRelated.length > 0 ? `Double-click to ${expandedRowConfig.manageRelated[0].label}` :
15644
- onRowDoubleClick ? 'Double-click for details' :
15645
- onRowClick ? 'Click to select' :
15646
- undefined, children: [selectable && (jsx("td", { className: `sticky left-0 z-10 ${bordered ? `border ${borderColor}` : ''}`, style: {
15647
- backgroundColor: 'inherit',
15648
- verticalAlign: 'middle',
15649
- padding: '0.375rem 0.75rem',
15650
- textAlign: 'center'
15651
- }, rowSpan: hasSecondaryRow ? 2 : 1, children: jsx("input", { type: "checkbox", checked: isSelected, onChange: () => handleRowSelect(rowKey), className: "w-4 h-4 text-accent-600 border-paper-300 rounded focus:ring-accent-400", "aria-label": `Select row ${rowKey}` }) })), ((expandable || expandedRowConfig) && showExpandChevron) && (jsx("td", { className: `sticky left-0 px-2 ${currentDensity.cell} z-10 ${bordered ? `border ${borderColor}` : ''}`, style: { backgroundColor: 'inherit', verticalAlign: 'middle' }, rowSpan: hasSecondaryRow ? 2 : 1, children: jsx("button", { onClick: () => {
15708
+ }, title: onEdit
15709
+ ? "Double-click to edit"
15710
+ : expandedRowConfig?.edit
15711
+ ? "Double-click to edit inline"
15712
+ : expandedRowConfig?.details
15713
+ ? "Double-click to view details"
15714
+ : expandedRowConfig?.addRelated &&
15715
+ expandedRowConfig.addRelated.length > 0
15716
+ ? `Double-click to ${expandedRowConfig.addRelated[0].label}`
15717
+ : expandedRowConfig?.manageRelated &&
15718
+ expandedRowConfig.manageRelated.length > 0
15719
+ ? `Double-click to ${expandedRowConfig.manageRelated[0].label}`
15720
+ : onRowDoubleClick
15721
+ ? "Double-click for details"
15722
+ : onRowClick
15723
+ ? "Click to select"
15724
+ : undefined, children: [selectable && (jsx("td", { className: `sticky left-0 z-10 ${bordered ? `border ${borderColor}` : ""}`, style: {
15725
+ backgroundColor: "inherit",
15726
+ verticalAlign: "middle",
15727
+ padding: "0.375rem 0.75rem",
15728
+ textAlign: "center",
15729
+ }, rowSpan: hasSecondaryRow ? 2 : 1, children: jsx("input", { type: "checkbox", checked: isSelected, onChange: () => handleRowSelect(rowKey), className: "w-4 h-4 text-accent-600 border-paper-300 rounded focus:ring-accent-400", "aria-label": `Select row ${rowKey}` }) })), (expandable || expandedRowConfig) && showExpandChevron && (jsx("td", { className: `sticky left-0 px-2 ${currentDensity.cell} z-10 ${bordered ? `border ${borderColor}` : ""}`, style: { backgroundColor: "inherit", verticalAlign: "middle" }, rowSpan: hasSecondaryRow ? 2 : 1, children: jsx("button", { onClick: () => {
15652
15730
  // NEW: Enhanced logic for expandedRowConfig
15653
- if (expandedRowConfig?.details && expandedRowConfig.details.triggerOnExpand !== false) {
15731
+ if (expandedRowConfig?.details &&
15732
+ expandedRowConfig.details.triggerOnExpand !== false) {
15654
15733
  // Trigger details mode if configured
15655
- handleExpansionWithMode(rowKey, 'details');
15734
+ handleExpansionWithMode(rowKey, "details");
15656
15735
  }
15657
- else if (expandedRowConfig?.edit && expandedRowConfig.edit.triggerOnDoubleClick !== false) {
15736
+ else if (expandedRowConfig?.edit &&
15737
+ expandedRowConfig.edit.triggerOnDoubleClick !== false) {
15658
15738
  // Fallback to edit mode if no details but edit is available
15659
- handleExpansionWithMode(rowKey, 'edit');
15739
+ handleExpansionWithMode(rowKey, "edit");
15660
15740
  }
15661
15741
  else {
15662
15742
  // Legacy: use handleRowExpand
15663
15743
  handleRowExpand(rowKey);
15664
15744
  }
15665
- }, className: "text-ink-500 hover:text-ink-900 transition-colors", "aria-label": isExpanded || (expansionState?.rowKey === rowKey) ? 'Collapse row' : 'Expand row', children: isExpanded || (expansionState?.rowKey === rowKey) ? (jsx(ChevronDown, { className: "h-4 w-4" })) : (jsx(ChevronRight, { className: "h-4 w-4" })) }) })), allActions.length > 0 && (jsx("td", { className: "sticky left-0 whitespace-nowrap shadow-[4px_0_6px_-2px_rgba(0,0,0,0.1)] z-10", style: {
15666
- width: '28px',
15667
- padding: '0',
15668
- backgroundColor: 'inherit',
15669
- verticalAlign: 'middle'
15670
- }, onClick: (e) => e.stopPropagation(), rowSpan: hasSecondaryRow ? 2 : 1, children: jsx("div", { style: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: '28px' }, children: jsx(ActionMenu, { actions: allActions, item: item }) }) })), visibleColumns.map((column, colIdx) => {
15745
+ }, className: "text-ink-500 hover:text-ink-900 transition-colors", "aria-label": isExpanded || expansionState?.rowKey === rowKey
15746
+ ? "Collapse row"
15747
+ : "Expand row", children: isExpanded || expansionState?.rowKey === rowKey ? (jsx(ChevronDown, { className: "h-4 w-4" })) : (jsx(ChevronRight, { className: "h-4 w-4" })) }) })), allActions.length > 0 && (jsx("td", { className: "sticky left-0 whitespace-nowrap shadow-[4px_0_6px_-2px_rgba(0,0,0,0.1)] z-10", style: {
15748
+ width: "28px",
15749
+ padding: "0",
15750
+ backgroundColor: "inherit",
15751
+ verticalAlign: "middle",
15752
+ }, onClick: (e) => e.stopPropagation(), rowSpan: hasSecondaryRow ? 2 : 1, children: jsx("div", { style: {
15753
+ display: "inline-flex",
15754
+ alignItems: "center",
15755
+ justifyContent: "center",
15756
+ width: "28px",
15757
+ }, children: jsx(ActionMenu, { actions: allActions, item: item }) }) })), visibleColumns.map((column, colIdx) => {
15671
15758
  const columnKey = String(column.key);
15672
15759
  const dynamicWidth = columnWidths[columnKey];
15673
- const value = typeof column.key === 'string'
15760
+ const value = typeof column.key === "string"
15674
15761
  ? item[column.key]
15675
15762
  : item[column.key];
15676
- const primaryContent = column.render ? column.render(item, value) : String(value || '');
15763
+ const primaryContent = column.render
15764
+ ? column.render(item, value)
15765
+ : String(value || "");
15766
+ // Tooltip: caller-provided > raw value stringified. Empty
15767
+ // strings get dropped so we don't render an empty title
15768
+ // attribute (which the browser would still show as a
15769
+ // 0-width tooltip box on hover).
15770
+ const primaryTooltipText = column.tooltip
15771
+ ? column.tooltip(item, value)
15772
+ : value !== null && value !== undefined && value !== ""
15773
+ ? String(value)
15774
+ : undefined;
15677
15775
  // Reduce left padding on first column when there are action buttons
15678
15776
  const isFirstColumn = colIdx === 0;
15679
- const paddingClass = isFirstColumn && allActions.length > 0 ? 'pl-3' : '';
15777
+ const paddingClass = isFirstColumn && allActions.length > 0 ? "pl-3" : "";
15680
15778
  // Check if this cell is keyboard-focused
15681
15779
  const isCellFocused = focusedCell?.row === index && focusedCell?.col === colIdx;
15682
- return (jsx("td", { className: `${currentDensity.cell} ${paddingClass} ${column.className || ''} ${bordered ? `border ${borderColor}` : ''} ${isCellFocused ? 'outline outline-2 outline-accent-500 outline-offset-[-2px]' : ''}`, style: getColumnStyle(column, dynamicWidth), tabIndex: isCellFocused ? 0 : -1, role: "gridcell", "aria-colindex": colIdx + 1, children: jsx("div", { className: `${currentDensity.text} leading-tight`, children: primaryContent }) }, `${item.id}-${columnKey}`));
15683
- })] }), hasSecondaryRow && (jsx("tr", { className: `secondary-row ${isSelected ? 'bg-accent-50 border-l-2 border-accent-500' : hoverClass || rowBgClass} border-b ${borderColor}`, onMouseEnter: () => !disableHover && setHoveredRowKey(rowKey), onMouseLeave: () => !disableHover && setHoveredRowKey(null), children: visibleColumns.map((column, colIdx) => {
15780
+ return (jsx("td", { className: `${currentDensity.cell} ${paddingClass} ${column.className || ""} ${bordered ? `border ${borderColor}` : ""} ${isCellFocused ? "outline outline-2 outline-accent-500 outline-offset-[-2px]" : ""}`, style: getColumnStyle(column, dynamicWidth), tabIndex: isCellFocused ? 0 : -1, role: "gridcell", "aria-colindex": colIdx + 1, children: jsx("div", { className: `${currentDensity.text} leading-tight`, title: primaryTooltipText, children: primaryContent }) }, `${item.id}-${columnKey}`));
15781
+ })] }), hasSecondaryRow && (jsx("tr", { className: `secondary-row ${isSelected ? "bg-accent-50 border-l-2 border-accent-500" : hoverClass || rowBgClass} border-b ${borderColor}`, onMouseEnter: () => !disableHover && setHoveredRowKey(rowKey), onMouseLeave: () => !disableHover && setHoveredRowKey(null), children: visibleColumns.map((column, colIdx) => {
15684
15782
  const columnKey = String(column.key);
15685
15783
  const dynamicWidth = columnWidths[columnKey];
15686
- const value = typeof column.key === 'string'
15784
+ const value = typeof column.key === "string"
15687
15785
  ? item[column.key]
15688
15786
  : item[column.key];
15689
- const secondaryContent = column.renderSecondary ? column.renderSecondary(item, value) : null;
15787
+ const secondaryContent = column.renderSecondary
15788
+ ? column.renderSecondary(item, value)
15789
+ : null;
15790
+ // Tooltip on the secondary row prefixes the field label when
15791
+ // available so the otherwise-unlabeled second row stays
15792
+ // self-describing on hover. Caller can override entirely
15793
+ // via `secondaryTooltip`.
15794
+ const hasSecondaryValue = value !== null && value !== undefined && value !== "";
15795
+ let secondaryTooltipText;
15796
+ if (column.secondaryTooltip) {
15797
+ secondaryTooltipText = column.secondaryTooltip(item, value);
15798
+ }
15799
+ else if (hasSecondaryValue) {
15800
+ secondaryTooltipText = column.secondaryHeader
15801
+ ? `${column.secondaryHeader}: ${value}`
15802
+ : String(value);
15803
+ }
15804
+ else if (column.secondaryHeader) {
15805
+ secondaryTooltipText = column.secondaryHeader;
15806
+ }
15690
15807
  // Reduce left padding on first column when there are action buttons
15691
15808
  const isFirstColumn = colIdx === 0;
15692
- const paddingClass = isFirstColumn && allActions.length > 0 ? 'pl-3' : '';
15693
- return (jsx("td", { className: `${currentDensity.cell} py-0.5 ${paddingClass} ${column.className || ''} ${bordered ? `border ${borderColor}` : ''}`, style: getColumnStyle(column, dynamicWidth), children: jsx("div", { className: "text-xs text-ink-500 leading-tight", children: secondaryContent || jsx("span", { className: "invisible", children: "\u2014" }) }) }, `${item.id}-${columnKey}-secondary`));
15809
+ const paddingClass = isFirstColumn && allActions.length > 0 ? "pl-3" : "";
15810
+ return (jsx("td", { className: `${currentDensity.cell} py-0.5 ${paddingClass} ${column.className || ""} ${bordered ? `border ${borderColor}` : ""}`, style: getColumnStyle(column, dynamicWidth), children: jsx("div", { className: "text-xs text-ink-500 leading-tight", title: secondaryTooltipText, children: secondaryContent || jsx("span", { className: "invisible", children: "\u2014" }) }) }, `${item.id}-${columnKey}-secondary`));
15694
15811
  }) })), expandable && isExpanded && renderExpandedRow && (jsx("tr", { children: jsx("td", { colSpan: visibleColumns.length +
15695
15812
  (selectable ? 1 : 0) +
15696
- (((expandable || expandedRowConfig) && showExpandChevron) ? 1 : 0) +
15697
- (allActions.length > 0 ? 1 : 0), className: `${currentDensity.cell} py-4 bg-paper-50`, children: renderExpandedRow(item) }) })), expansionState && expansionState.rowKey === rowKey && expandedRowConfig && (() => {
15698
- const mode = expansionState.mode;
15699
- let content = null;
15700
- let bgColorClass = 'bg-paper-50'; // Default
15701
- // Edit mode
15702
- if (mode === 'edit' && expandedRowConfig.edit) {
15703
- bgColorClass = 'bg-paper-100/80 border-t border-b border-paper-300/80';
15704
- content = expandedRowConfig.edit.render(item, async (_updated) => {
15705
- // Handle save
15706
- handleCollapseExpansion();
15707
- }, () => {
15708
- // Handle cancel
15709
- handleCollapseExpansion();
15710
- });
15711
- }
15712
- // Details mode
15713
- else if (mode === 'details' && expandedRowConfig.details) {
15714
- bgColorClass = 'bg-primary-50/80 border-t border-b border-primary-200/80';
15715
- content = expandedRowConfig.details.render(item);
15716
- }
15717
- // Add related modes
15718
- else if (mode.startsWith('addRelated-') && expandedRowConfig.addRelated) {
15719
- const key = mode.replace('addRelated-', '');
15720
- const config = expandedRowConfig.addRelated.find(c => c.key === key);
15721
- if (config) {
15722
- bgColorClass = 'bg-success-50/80 border-t border-b border-success-200/80';
15723
- content = config.render(item, async (_newItem) => {
15813
+ ((expandable || expandedRowConfig) && showExpandChevron
15814
+ ? 1
15815
+ : 0) +
15816
+ (allActions.length > 0 ? 1 : 0), className: `${currentDensity.cell} py-4 bg-paper-50`, children: renderExpandedRow(item) }) })), expansionState &&
15817
+ expansionState.rowKey === rowKey &&
15818
+ expandedRowConfig &&
15819
+ (() => {
15820
+ const mode = expansionState.mode;
15821
+ let content = null;
15822
+ let bgColorClass = "bg-paper-50"; // Default
15823
+ // Edit mode
15824
+ if (mode === "edit" && expandedRowConfig.edit) {
15825
+ bgColorClass =
15826
+ "bg-paper-100/80 border-t border-b border-paper-300/80";
15827
+ content = expandedRowConfig.edit.render(item, async (_updated) => {
15724
15828
  // Handle save
15725
15829
  handleCollapseExpansion();
15726
15830
  }, () => {
@@ -15728,31 +15832,57 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15728
15832
  handleCollapseExpansion();
15729
15833
  });
15730
15834
  }
15731
- }
15732
- // Manage related modes
15733
- else if (mode.startsWith('manageRelated-') && expandedRowConfig.manageRelated) {
15734
- const key = mode.replace('manageRelated-', '');
15735
- const config = expandedRowConfig.manageRelated.find(c => c.key === key);
15736
- if (config) {
15737
- bgColorClass = 'bg-slate-50/80 border-t border-b border-slate-200/80';
15738
- const handleClose = () => setExpansionState(null);
15739
- content = config.render(item, handleClose);
15835
+ // Details mode
15836
+ else if (mode === "details" && expandedRowConfig.details) {
15837
+ bgColorClass =
15838
+ "bg-primary-50/80 border-t border-b border-primary-200/80";
15839
+ content = expandedRowConfig.details.render(item);
15740
15840
  }
15741
- }
15742
- if (!content)
15743
- return null;
15744
- return (jsx("tr", { children: jsx("td", { colSpan: visibleColumns.length +
15745
- (selectable ? 1 : 0) +
15746
- (((expandable || expandedRowConfig) && showExpandChevron) ? 1 : 0) +
15747
- (allActions.length > 0 ? 1 : 0), className: `${currentDensity.cell} py-4 ${bgColorClass} animate-expand`, children: content }) }, `expanded-${rowKey}`));
15748
- })()] }, rowKey));
15841
+ // Add related modes
15842
+ else if (mode.startsWith("addRelated-") &&
15843
+ expandedRowConfig.addRelated) {
15844
+ const key = mode.replace("addRelated-", "");
15845
+ const config = expandedRowConfig.addRelated.find((c) => c.key === key);
15846
+ if (config) {
15847
+ bgColorClass =
15848
+ "bg-success-50/80 border-t border-b border-success-200/80";
15849
+ content = config.render(item, async (_newItem) => {
15850
+ // Handle save
15851
+ handleCollapseExpansion();
15852
+ }, () => {
15853
+ // Handle cancel
15854
+ handleCollapseExpansion();
15855
+ });
15856
+ }
15857
+ }
15858
+ // Manage related modes
15859
+ else if (mode.startsWith("manageRelated-") &&
15860
+ expandedRowConfig.manageRelated) {
15861
+ const key = mode.replace("manageRelated-", "");
15862
+ const config = expandedRowConfig.manageRelated.find((c) => c.key === key);
15863
+ if (config) {
15864
+ bgColorClass =
15865
+ "bg-slate-50/80 border-t border-b border-slate-200/80";
15866
+ const handleClose = () => setExpansionState(null);
15867
+ content = config.render(item, handleClose);
15868
+ }
15869
+ }
15870
+ if (!content)
15871
+ return null;
15872
+ return (jsx("tr", { children: jsx("td", { colSpan: visibleColumns.length +
15873
+ (selectable ? 1 : 0) +
15874
+ ((expandable || expandedRowConfig) && showExpandChevron
15875
+ ? 1
15876
+ : 0) +
15877
+ (allActions.length > 0 ? 1 : 0), className: `${currentDensity.cell} py-4 ${bgColorClass} animate-expand`, children: content }) }, `expanded-${rowKey}`));
15878
+ })()] }, rowKey));
15749
15879
  });
15750
15880
  };
15751
- const tableContent = (jsxs("div", { className: `bg-white rounded-lg shadow border-2 ${borderColor} ${virtualized ? 'overflow-hidden' : 'overflow-x-auto overflow-y-visible'} ${className}`, style: { position: 'relative' }, children: [loading && data.length > 0 && (jsx("div", { className: "absolute inset-0 bg-white/75 flex items-center justify-center z-20", style: { backdropFilter: 'blur(2px)' }, children: jsxs("div", { className: "flex flex-col items-center gap-3", children: [jsx("div", { className: "loading-spinner", style: { width: '32px', height: '32px', borderWidth: '3px' } }), jsx("span", { className: "text-sm font-medium text-ink-600", children: "Loading..." })] }) })), jsxs("table", { className: `table-stable w-full ${bordered ? 'border-collapse' : ''}`, role: "grid", "aria-label": "Data table", "aria-rowcount": data.length, "aria-colcount": visibleColumns.length, children: [jsxs("colgroup", { children: [selectable && jsx("col", { className: "w-12" }), ((expandable || expandedRowConfig) && showExpandChevron) && jsx("col", { className: "w-10" }), allActions.length > 0 && jsx("col", { style: { width: '28px' } }), visibleColumns.map((column, index) => {
15881
+ const tableContent = (jsxs("div", { className: `bg-white rounded-lg shadow border-2 ${borderColor} ${virtualized ? "overflow-hidden" : "overflow-x-auto overflow-y-visible"} ${className}`, style: { position: "relative" }, children: [loading && data.length > 0 && (jsx("div", { className: "absolute inset-0 bg-white/75 flex items-center justify-center z-20", style: { backdropFilter: "blur(2px)" }, children: jsxs("div", { className: "flex flex-col items-center gap-3", children: [jsx("div", { className: "loading-spinner", style: { width: "32px", height: "32px", borderWidth: "3px" } }), jsx("span", { className: "text-sm font-medium text-ink-600", children: "Loading..." })] }) })), jsxs("table", { className: `table-stable w-full ${bordered ? "border-collapse" : ""}`, role: "grid", "aria-label": "Data table", "aria-rowcount": data.length, "aria-colcount": visibleColumns.length, children: [jsxs("colgroup", { children: [selectable && jsx("col", { className: "w-12" }), (expandable || expandedRowConfig) && showExpandChevron && (jsx("col", { className: "w-10" })), allActions.length > 0 && jsx("col", { style: { width: "28px" } }), visibleColumns.map((column, index) => {
15752
15882
  const columnKey = String(column.key);
15753
15883
  const dynamicWidth = columnWidths[columnKey];
15754
15884
  return (jsx("col", { style: getColumnStyle(column, dynamicWidth) }, index));
15755
- })] }), jsx("thead", { className: `bg-paper-100 sticky top-0 z-10 ${headerClassName}`, children: jsxs("tr", { className: "table-header-row", children: [selectable && (jsx("th", { className: `sticky left-0 bg-paper-100 ${currentDensity.header} border-b ${borderColor} z-20 w-12 ${bordered ? `border ${borderColor}` : ''}`, children: jsx("input", { type: "checkbox", checked: selectedRowsSet.size === data.length && data.length > 0, onChange: handleSelectAll, className: "w-4 h-4 text-accent-600 border-paper-300 rounded focus:ring-accent-400", "aria-label": "Select all rows" }) })), ((expandable || expandedRowConfig) && showExpandChevron) && (jsx("th", { className: `sticky left-0 bg-paper-100 px-2 ${currentDensity.header} border-b ${borderColor} z-19 w-10 ${bordered ? `border ${borderColor}` : ''}` })), allActions.length > 0 && (jsx("th", { className: `sticky left-0 bg-paper-100 text-center text-xs font-medium text-ink-700 uppercase tracking-wider border-b ${borderColor} z-20 ${bordered ? `border ${borderColor}` : ''}`, style: { width: '28px', padding: '0' } })), visibleColumns.map((column, colIdx) => {
15885
+ })] }), jsx("thead", { className: `bg-paper-100 sticky top-0 z-10 ${headerClassName}`, children: jsxs("tr", { className: "table-header-row", children: [selectable && (jsx("th", { className: `sticky left-0 bg-paper-100 ${currentDensity.header} border-b ${borderColor} z-20 w-12 ${bordered ? `border ${borderColor}` : ""}`, children: jsx("input", { type: "checkbox", checked: selectedRowsSet.size === data.length && data.length > 0, onChange: handleSelectAll, className: "w-4 h-4 text-accent-600 border-paper-300 rounded focus:ring-accent-400", "aria-label": "Select all rows" }) })), (expandable || expandedRowConfig) && showExpandChevron && (jsx("th", { className: `sticky left-0 bg-paper-100 px-2 ${currentDensity.header} border-b ${borderColor} z-19 w-10 ${bordered ? `border ${borderColor}` : ""}` })), allActions.length > 0 && (jsx("th", { className: `sticky left-0 bg-paper-100 text-center text-xs font-medium text-ink-700 uppercase tracking-wider border-b ${borderColor} z-20 ${bordered ? `border ${borderColor}` : ""}`, style: { width: "28px", padding: "0" } })), visibleColumns.map((column, colIdx) => {
15756
15886
  const columnKey = String(column.key);
15757
15887
  const dynamicWidth = columnWidths[columnKey];
15758
15888
  const thRef = useRef(null);
@@ -15760,24 +15890,28 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15760
15890
  const isDragOver = dragOverColumn === columnKey;
15761
15891
  // Reduce left padding on first column when there are action buttons (match body cells)
15762
15892
  const isFirstColumn = colIdx === 0;
15763
- const headerPaddingClass = isFirstColumn && allActions.length > 0 ? 'pl-3' : '';
15893
+ const headerPaddingClass = isFirstColumn && allActions.length > 0 ? "pl-3" : "";
15764
15894
  return (jsxs("th", { ref: thRef, draggable: reorderable, onDragStart: (e) => reorderable && handleDragStart(e, columnKey), onDragOver: (e) => reorderable && handleDragOver(e, columnKey), onDragEnd: handleDragEnd, onDrop: (e) => reorderable && handleDrop(e, columnKey), className: `
15765
- ${currentDensity.header} ${headerPaddingClass} text-left border-b ${borderColor} ${bordered ? `border ${borderColor}` : ''} relative
15766
- ${reorderable ? 'cursor-move' : ''}
15767
- ${isDragging ? 'opacity-50' : ''}
15768
- ${isDragOver ? 'bg-accent-100' : ''}
15895
+ ${currentDensity.header} ${headerPaddingClass} text-left border-b ${borderColor} ${bordered ? `border ${borderColor}` : ""} relative
15896
+ ${reorderable ? "cursor-move" : ""}
15897
+ ${isDragging ? "opacity-50" : ""}
15898
+ ${isDragOver ? "bg-accent-100" : ""}
15769
15899
  `, style: getColumnStyle(column, dynamicWidth), children: [column.sortable ? (jsxs("button", { onClick: () => handleSort(column), className: "group inline-flex items-center text-xs font-medium text-ink-500 uppercase tracking-wider hover:text-ink-900 transition-colors", children: [jsx("span", { children: column.header }), getSortIcon(column)] })) : (jsx("span", { className: "text-xs font-medium text-ink-500 uppercase tracking-wider", children: column.header })), resizable && (jsx("div", { className: "absolute right-0 top-0 bottom-0 w-1 cursor-col-resize hover:bg-accent-400 group", onMouseDown: (e) => {
15770
15900
  const currentWidth = thRef.current?.offsetWidth || 100;
15771
15901
  handleResizeStart(e, columnKey, currentWidth);
15772
15902
  }, children: jsx("div", { className: "absolute right-0 top-0 bottom-0 w-1 bg-paper-300 group-hover:bg-accent-400 transition-colors" }) }))] }, columnKey));
15773
- })] }) }), jsx("tbody", { ref: tableBodyRef, className: "bg-white table-loading transition-opacity duration-200", onKeyDown: handleKeyboardNavigation, tabIndex: 0, role: "rowgroup", "aria-label": "Table data", children: loading && data.length === 0 ? (renderLoadingSkeleton()) : data.length === 0 ? (renderEmptyStateContent()) : (renderDataRows()) })] })] }));
15903
+ })] }) }), jsx("tbody", { ref: tableBodyRef, className: "bg-white table-loading transition-opacity duration-200", onKeyDown: handleKeyboardNavigation, tabIndex: 0, role: "rowgroup", "aria-label": "Table data", children: loading && data.length === 0
15904
+ ? renderLoadingSkeleton()
15905
+ : data.length === 0
15906
+ ? renderEmptyStateContent()
15907
+ : renderDataRows() })] })] }));
15774
15908
  // Wrap in scrollable container if virtualized
15775
- const finalContent = virtualized ? (jsx("div", { ref: tableContainerRef, onScroll: handleScroll, style: { height: virtualHeight, overflow: 'auto' }, className: "rounded-lg", children: tableContent })) : tableContent;
15909
+ const finalContent = virtualized ? (jsx("div", { ref: tableContainerRef, onScroll: handleScroll, style: { height: virtualHeight, overflow: "auto" }, className: "rounded-lg", children: tableContent })) : (tableContent);
15776
15910
  // Calculate pagination values
15777
15911
  const effectiveTotalItems = totalItems ?? data.length;
15778
15912
  const totalPages = Math.ceil(effectiveTotalItems / pageSize);
15779
15913
  // Page size selector options
15780
- const pageSizeSelectOptions = pageSizeOptions.map(size => ({
15914
+ const pageSizeSelectOptions = pageSizeOptions.map((size) => ({
15781
15915
  value: String(size),
15782
15916
  label: `${size} per page`,
15783
15917
  }));
@@ -15785,17 +15919,20 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15785
15919
  const renderPaginationControls = () => {
15786
15920
  if (!paginated)
15787
15921
  return null;
15788
- return (jsxs("div", { className: "flex items-center justify-between mb-4 px-1", children: [jsxs("div", { className: "flex items-center gap-4", children: [showPageSizeSelector && onPageSizeChange && (jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm text-ink-600", children: "Show:" }), jsx(Select, { options: pageSizeSelectOptions, value: String(pageSize), onChange: (value) => onPageSizeChange?.(Number(value)) })] })), jsx("span", { className: "text-sm text-ink-600", children: effectiveTotalItems > 0 ? (jsxs(Fragment, { children: ["Showing ", ((currentPage - 1) * pageSize) + 1, " - ", Math.min(currentPage * pageSize, effectiveTotalItems), " of ", effectiveTotalItems] })) : ('No items') })] }), totalPages > 1 && onPageChange && (jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: onPageChange }))] }));
15922
+ return (jsxs("div", { className: "flex items-center justify-between mb-4 px-1", children: [jsxs("div", { className: "flex items-center gap-4", children: [showPageSizeSelector && onPageSizeChange && (jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm text-ink-600", children: "Show:" }), jsx(Select, { options: pageSizeSelectOptions, value: String(pageSize), onChange: (value) => onPageSizeChange?.(Number(value)) })] })), jsx("span", { className: "text-sm text-ink-600", children: effectiveTotalItems > 0 ? (jsxs(Fragment, { children: ["Showing ", (currentPage - 1) * pageSize + 1, " -", " ", Math.min(currentPage * pageSize, effectiveTotalItems), " of", " ", effectiveTotalItems] })) : ("No items") })] }), totalPages > 1 && onPageChange && (jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: onPageChange }))] }));
15789
15923
  };
15790
15924
  // Determine if we should show card view
15791
- const shouldShowCardView = mobileView === 'card' ||
15792
- (mobileView === 'auto' && isMobileViewport);
15925
+ const shouldShowCardView = mobileView === "card" || (mobileView === "auto" && isMobileViewport);
15793
15926
  // Card view content
15794
15927
  const cardViewContent = shouldShowCardView ? (jsx(DataTableCardView, { data: data, columns: visibleColumns, cardConfig: cardConfig, loading: loading, loadingRows: loadingRows, emptyMessage: emptyMessage, onCardClick: onRowClick, onCardLongPress: (item, event) => {
15795
15928
  if (enableContextMenu && allActions.length > 0) {
15796
15929
  event.preventDefault();
15797
- const clientX = 'touches' in event ? event.touches[0].clientX : event.clientX;
15798
- const clientY = 'touches' in event ? event.touches[0].clientY : event.clientY;
15930
+ const clientX = "touches" in event
15931
+ ? event.touches[0].clientX
15932
+ : event.clientX;
15933
+ const clientY = "touches" in event
15934
+ ? event.touches[0].clientY
15935
+ : event.clientY;
15799
15936
  setContextMenuState({
15800
15937
  isOpen: true,
15801
15938
  position: { x: clientX, y: clientY },
@@ -15804,7 +15941,11 @@ mobileView = 'auto', cardConfig, cardGap = 'md', cardClassName, }) {
15804
15941
  }
15805
15942
  }, selectable: selectable, selectedRows: selectedRowsSet, onSelectionChange: onRowSelect ? (rows) => onRowSelect(rows) : undefined, keyExtractor: getRowKey, actions: allActions, onEdit: onEdit, onDelete: onDelete, className: className, cardClassName: cardClassName, gap: cardGap })) : null;
15806
15943
  // Render with context menu
15807
- return (jsxs(Fragment, { children: [jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: announcement }), renderPaginationControls(), shouldShowCardView ? cardViewContent : finalContent, contextMenuState.isOpen && contextMenuState.item && (jsx(Menu, { items: convertActionsToMenuItems(contextMenuState.item), position: contextMenuState.position, onClose: () => setContextMenuState({ isOpen: false, position: { x: 0, y: 0 }, item: null }) }))] }));
15944
+ return (jsxs(Fragment, { children: [jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: announcement }), renderPaginationControls(), shouldShowCardView ? cardViewContent : finalContent, contextMenuState.isOpen && contextMenuState.item && (jsx(Menu, { items: convertActionsToMenuItems(contextMenuState.item), position: contextMenuState.position, onClose: () => setContextMenuState({
15945
+ isOpen: false,
15946
+ position: { x: 0, y: 0 },
15947
+ item: null,
15948
+ }) }))] }));
15808
15949
  }
15809
15950
 
15810
15951
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -15843,52 +15984,44 @@ function getAugmentedNamespace(n) {
15843
15984
  * (A1, A1:C5, ...)
15844
15985
  */
15845
15986
 
15846
- var collection;
15847
- var hasRequiredCollection;
15848
-
15849
- function requireCollection () {
15850
- if (hasRequiredCollection) return collection;
15851
- hasRequiredCollection = 1;
15852
- class Collection {
15987
+ let Collection$3 = class Collection {
15853
15988
 
15854
- constructor(data, refs) {
15855
- if (data == null && refs == null) {
15856
- this._data = [];
15857
- this._refs = [];
15858
- } else {
15859
- if (data.length !== refs.length)
15860
- throw Error('Collection: data length should match references length.');
15861
- this._data = data;
15862
- this._refs = refs;
15863
- }
15864
- }
15989
+ constructor(data, refs) {
15990
+ if (data == null && refs == null) {
15991
+ this._data = [];
15992
+ this._refs = [];
15993
+ } else {
15994
+ if (data.length !== refs.length)
15995
+ throw Error('Collection: data length should match references length.');
15996
+ this._data = data;
15997
+ this._refs = refs;
15998
+ }
15999
+ }
15865
16000
 
15866
- get data() {
15867
- return this._data;
15868
- }
16001
+ get data() {
16002
+ return this._data;
16003
+ }
15869
16004
 
15870
- get refs() {
15871
- return this._refs;
15872
- }
16005
+ get refs() {
16006
+ return this._refs;
16007
+ }
15873
16008
 
15874
- get length() {
15875
- return this._data.length;
15876
- }
16009
+ get length() {
16010
+ return this._data.length;
16011
+ }
15877
16012
 
15878
- /**
15879
- * Add data and references to this collection.
15880
- * @param {{}} obj - data
15881
- * @param {{}} ref - reference
15882
- */
15883
- add(obj, ref) {
15884
- this._data.push(obj);
15885
- this._refs.push(ref);
15886
- }
15887
- }
16013
+ /**
16014
+ * Add data and references to this collection.
16015
+ * @param {{}} obj - data
16016
+ * @param {{}} ref - reference
16017
+ */
16018
+ add(obj, ref) {
16019
+ this._data.push(obj);
16020
+ this._refs.push(ref);
16021
+ }
16022
+ };
15888
16023
 
15889
- collection = Collection;
15890
- return collection;
15891
- }
16024
+ var collection = Collection$3;
15892
16025
 
15893
16026
  var helpers;
15894
16027
  var hasRequiredHelpers;
@@ -15897,7 +16030,7 @@ function requireHelpers () {
15897
16030
  if (hasRequiredHelpers) return helpers;
15898
16031
  hasRequiredHelpers = 1;
15899
16032
  const FormulaError = requireError();
15900
- const Collection = requireCollection();
16033
+ const Collection = collection;
15901
16034
 
15902
16035
  const Types = {
15903
16036
  NUMBER: 0,
@@ -25551,7 +25684,7 @@ var engineering = EngineeringFunctions;
25551
25684
 
25552
25685
  const FormulaError$b = requireError();
25553
25686
  const {FormulaHelpers: FormulaHelpers$8, Types: Types$6, WildCard, Address: Address$3} = requireHelpers();
25554
- const Collection$2 = requireCollection();
25687
+ const Collection$2 = collection;
25555
25688
  const H$5 = FormulaHelpers$8;
25556
25689
 
25557
25690
  const ReferenceFunctions$1 = {
@@ -37179,7 +37312,7 @@ var parsing = {
37179
37312
  const FormulaError$4 = requireError();
37180
37313
  const {Address: Address$1} = requireHelpers();
37181
37314
  const {Prefix: Prefix$1, Postfix: Postfix$1, Infix: Infix$1, Operators: Operators$1} = operators;
37182
- const Collection$1 = requireCollection();
37315
+ const Collection$1 = collection;
37183
37316
  const MAX_ROW$1 = 1048576, MAX_COLUMN$1 = 16384;
37184
37317
  const {NotAllInputParsedException} = require$$4;
37185
37318
 
@@ -37941,7 +38074,7 @@ var hooks$1 = {
37941
38074
  const FormulaError$2 = requireError();
37942
38075
  const {FormulaHelpers: FormulaHelpers$1, Types, Address} = requireHelpers();
37943
38076
  const {Prefix, Postfix, Infix, Operators} = operators;
37944
- const Collection = requireCollection();
38077
+ const Collection = collection;
37945
38078
  const MAX_ROW = 1048576, MAX_COLUMN = 16384;
37946
38079
 
37947
38080
  let Utils$1 = class Utils {