@hyddenlabs/hydn-ui 0.3.11 → 0.3.12

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.
@@ -134,6 +134,14 @@ export type DataGridProps<T> = {
134
134
  buttonText?: string;
135
135
  /** Click handler for the button in the empty state */
136
136
  onButtonClick?: () => void;
137
+ /** React Router path — renders the empty state button as a <Link>. Use instead of onButtonClick for in-app navigation. */
138
+ buttonTo?: string;
139
+ /** Plain URL — renders the empty state button as an <a> tag. Use for external links. */
140
+ buttonHref?: string;
141
+ /** Link target (e.g. "_blank") — only used with buttonTo or buttonHref */
142
+ buttonTarget?: ButtonProps['target'];
143
+ /** Rel attribute for the anchor (defaults to "noopener noreferrer" when buttonTarget="_blank") */
144
+ buttonRel?: string;
137
145
  };
138
146
  /** Initial sort configuration */
139
147
  initialSort?: {
@@ -181,6 +189,14 @@ export type HeaderAction = {
181
189
  ariaLabel?: string;
182
190
  /** Click handler invoked when the button is clicked */
183
191
  onClick?: () => void;
192
+ /** React Router path — renders the button as a <Link>. Use instead of onClick for in-app navigation. */
193
+ to?: string;
194
+ /** Plain URL — renders the button as an <a> tag. Use for external links. */
195
+ href?: string;
196
+ /** Link target (e.g. "_blank") — only used with to or href */
197
+ target?: ButtonProps['target'];
198
+ /** Rel attribute for the anchor (defaults to "noopener noreferrer" when target="_blank") */
199
+ rel?: string;
184
200
  /** Button variant (maps to Button `variant` prop) */
185
201
  variant?: ButtonProps['variant'];
186
202
  /** Button style (maps to Button `style` prop) */
@@ -1 +1 @@
1
- {"version":3,"file":"data-grid.d.ts","sourceRoot":"","sources":["../../../../src/components/data-display/data-grid/data-grid.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-grid.d.ts","sourceRoot":"","sources":["../../../../src/components/data-display/data-grid/data-grid.tsx"],"names":[],"mappings":"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"}
@@ -49,7 +49,11 @@ function DataGrid({
49
49
  title: "No data available",
50
50
  description: void 0,
51
51
  buttonText: void 0,
52
- onButtonClick: void 0
52
+ onButtonClick: void 0,
53
+ buttonTo: void 0,
54
+ buttonHref: void 0,
55
+ buttonTarget: void 0,
56
+ buttonRel: void 0
53
57
  },
54
58
  headerActions,
55
59
  title,
@@ -487,6 +491,10 @@ function DataGrid({
487
491
  Button,
488
492
  {
489
493
  onClick: act.onClick,
494
+ to: act.to,
495
+ href: act.href,
496
+ target: act.target,
497
+ rel: act.rel,
490
498
  variant: act.variant,
491
499
  style: act.style,
492
500
  size: act.size,
@@ -506,6 +514,10 @@ function DataGrid({
506
514
  Button,
507
515
  {
508
516
  onClick: act.onClick,
517
+ to: act.to,
518
+ href: act.href,
519
+ target: act.target,
520
+ rel: act.rel,
509
521
  variant: act.variant,
510
522
  style: act.style,
511
523
  size: act.size,
@@ -525,7 +537,11 @@ function DataGrid({
525
537
  title: emptyState.title,
526
538
  description: emptyState.description,
527
539
  buttonText: emptyState.buttonText,
528
- onButtonClick: emptyState.onButtonClick
540
+ onButtonClick: emptyState.onButtonClick,
541
+ buttonTo: emptyState.buttonTo,
542
+ buttonHref: emptyState.buttonHref,
543
+ buttonTarget: emptyState.buttonTarget,
544
+ buttonRel: emptyState.buttonRel
529
545
  }
530
546
  ) }) : filteredData.length === 0 && searchQuery.trim() ? /* @__PURE__ */ jsx("div", { className: "border border-border rounded-lg", children: /* @__PURE__ */ jsx(
531
547
  EmptyState,
@@ -1 +1 @@
1
- {"version":3,"file":"data-grid.js","sources":["../../../../src/components/data-display/data-grid/data-grid.tsx"],"sourcesContent":["import { ReactNode, useState, useEffect, useRef } from 'react';\nimport { Icon } from '../../system/icon/icon';\nimport IconButton from '../../forms/button/icon-button';\nimport Input from '../../forms/input/input';\nimport InputGroup from '../../forms/input-group/input-group';\n\nimport Checkbox from '../../forms/checkbox/checkbox';\nimport Button from '../../forms/button/button';\nimport Tooltip from '../../feedback/tooltip/tooltip';\nimport type { ButtonProps } from '../../forms/button/button';\nimport Stack from '../../layout/stack/stack';\nimport Badge from '../badge/badge';\nimport Text from '../../typography/text/text';\nimport { useTable, UseTableOptions } from '../data-table/use-table';\nimport { Size } from '@/theme/size-tokens';\nimport { ColorVariant } from '@/theme/tokens';\nimport EmptyState from '../empty-state/empty-state';\nimport StatusIndicator from '../status-indicator/status-indicator';\nimport { Link } from 'react-router-dom';\n\n/** Interactive element tags that should not trigger onRowClick callback */\nconst INTERACTIVE_TAGS = new Set(['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA', 'LABEL']);\n\n/** Check if an element or any of its ancestors (up to container) is interactive - used for onRowClick only */\nfunction isInteractiveElement(element: HTMLElement | null, container: HTMLElement | null): boolean {\n let current = element;\n while (current && current !== container) {\n if (INTERACTIVE_TAGS.has(current.tagName)) return true;\n if (current.getAttribute('role') === 'button') return true;\n current = current.parentElement;\n }\n return false;\n}\n\nexport type DataGridAction<T> = {\n /** Icon name for the action button */\n icon: string;\n /** Size of the icon */\n iconSize?: Size;\n /** Color variant for the icon */\n iconColor?: ColorVariant;\n /** Icon to display on hover (optional) */\n hoverIcon?: string;\n /** Accessible label for the action (shown in tooltip or screen readers) */\n label: string;\n /** Tooltip text to display on hover. If not provided, label will be used for aria-label only. */\n tooltip?: string;\n /** Callback when the action is clicked */\n onClick: (row: T, index: number) => void;\n /** Visual variant for the action button */\n variant?: 'primary' | 'accent' | 'neutral' | 'success' | 'warning' | 'error' | 'info';\n};\n\nexport type DataGridActionItem<T> = DataGridAction<T> | ReactNode;\n\nexport type DataGridColumnDef<T> = {\n /** Key of the data property to display in this column */\n key: keyof T;\n /** Column header label */\n label: string;\n /** Whether this column can be sorted */\n sortable?: boolean;\n /** CSS width class or value for the column (e.g., 'w-48', '200px', 'flex-1') */\n width?: string;\n /**\n * Minimum width in pixels for the column. When set:\n * - Column truncates but never shrinks below this width\n * - Column auto-hides if container can't fit it at this width\n * - No need to also set hidePriority (though you can for explicit hide ordering)\n *\n * @example minWidth: 120 // Hide if email would be squished below 120px\n */\n minWidth?: number;\n /**\n * Maximum width in pixels for the column. Prevents column from growing too wide.\n * Use for columns like status/role that don't need much space.\n *\n * @example maxWidth: 100 // Cap role column at 100px\n */\n maxWidth?: number;\n /** Text alignment for cells in this column */\n align?: 'left' | 'center' | 'right';\n /** Whether text should wrap instead of truncating (useful for long strings) */\n wrapText?: boolean;\n /** Optional priority for responsive hiding. Lower values hide first when container width shrinks. Columns without hidePriority or minWidth are never hidden. */\n hidePriority?: number;\n /** Whether to show this column's label in mobile/vertical layout (default: true) */\n showLabelOnMobile?: boolean;\n /** Custom render function for cell content (use as escape hatch when config options don't cover your use case) */\n render?: (value: T[keyof T], row: T, index: number) => ReactNode;\n\n // Config-driven rendering options (preferred over custom render)\n /** Pre-built formatter for common data types */\n format?: 'date' | 'currency' | 'number' | 'percent';\n /** Options for Intl formatters (NumberFormat or DateTimeFormat) */\n formatOptions?: Intl.NumberFormatOptions | Intl.DateTimeFormatOptions;\n /** Map values to badge variants. Unmatched values render with 'neutral' variant. Use '*' key to override the default fallback. */\n badgeMap?: {\n [key: string]: { variant?: ColorVariant; label?: string };\n };\n /** Map values to status dot colors. Renders text with a colored dot to the left. Lighter alternative to badges for status indicators. */\n statusDotMap?: {\n [key: string]: { color?: ColorVariant; label?: string };\n };\n /**\n * Render cell values as badges. When the value is an array, each item is rendered\n * as an individual badge; for scalar values, the value is wrapped in a single badge.\n */\n renderAsBadges?: boolean;\n /** Variant for badge rendering */\n badgeVariant?: ColorVariant;\n /** Size for badge rendering */\n componentSize?: 'sm' | 'md' | 'lg';\n /** Fallback value to display when cell value is null, undefined, or empty string */\n fallback?: string;\n};\n\nexport type DataGridProps<T> = {\n /** Array of data objects to display in the grid */\n data: T[];\n /** Column definitions specifying how to render each column */\n columns: DataGridColumnDef<T>[];\n /** Additional CSS classes to apply */\n className?: string;\n\n // Styling options\n /** Whether to apply striped row styling (alternating background) */\n striped?: boolean;\n /** Whether rows have hover effects */\n hoverable?: boolean;\n /** Whether to use compact spacing for dense data */\n compact?: boolean;\n\n // Features\n /** Whether columns can be sorted (can be overridden per column) */\n sortable?: boolean;\n /** Whether to enable client-side pagination */\n paginated?: boolean;\n /** Number of rows per page when pagination is enabled */\n pageSize?: number;\n /** Whether to show checkboxes for row selection */\n selectable?: boolean;\n /** Whether to enable search/filter functionality */\n searchable?: boolean;\n /** Specific keys to search within. If not provided, searches all fields. */\n searchKeys?: (keyof T)[];\n /** Placeholder text for the search input */\n searchPlaceholder?: string;\n /** Callback when search query changes */\n onSearchChange?: (query: string) => void;\n\n // Actions - either array of action configs/components OR function returning actions/render\n /** Action buttons, function returning actions based on row data, or custom render function for the actions column */\n actions?: DataGridActionItem<T>[] | ((row: T, index: number) => DataGridActionItem<T>[] | ReactNode);\n /** Label for the actions column header */\n actionsLabel?: string;\n\n // Row link - makes entire row clickable for navigation\n /** Function returning href for row navigation. When provided, entire row becomes a link. */\n rowHref?: (row: T, index: number) => string | undefined;\n\n // Callbacks\n /** Callback when a row is clicked (if rowHref not provided) */\n onRowClick?: (row: T, index: number) => void;\n /** Callback when row selection changes (provides array of selected row indices) */\n onSelectionChange?: (selectedIndices: number[]) => void;\n\n // Empty state\n emptyState?: {\n /** Message to display when there is no data */\n title?: string;\n /** Description to display when there is no data */\n description?: string;\n /** Text for the button in the empty state */\n buttonText?: string;\n /** Click handler for the button in the empty state */\n onButtonClick?: () => void;\n };\n\n // Initial state\n /** Initial sort configuration */\n initialSort?: { key: keyof T; direction: 'asc' | 'desc' };\n /** Title displayed above the grid (left side of header) */\n title?: string;\n /** Header actions displayed above the grid (right side of header). */\n headerActions?: HeaderAction[];\n\n // Responsive / list mode\n /**\n * Container width (px) below which the grid collapses into list mode.\n * Defaults to 480. Column hiding (via `hidePriority` / `minWidth`) still\n * runs for widths above this breakpoint.\n */\n listBreakpoint?: number;\n /**\n * Custom render function for list mode. When provided, each row is rendered\n * using this function instead of the default vertical-stack fallback.\n * Use this to create type-specific list layouts with the right fields,\n * actions, and visual hierarchy for the entity being displayed.\n *\n * @example\n * ```tsx\n * renderListItem={(row, index, { actions, isSelected, onToggleSelect }) => (\n * <div className=\"flex items-center gap-3\">\n * <Avatar name={row.name} />\n * <div className=\"flex-1 min-w-0\">\n * <Text weight=\"medium\" className=\"truncate\">{row.name}</Text>\n * <Text size=\"sm\" variant=\"muted\" className=\"truncate\">{row.email}</Text>\n * </div>\n * {actions}\n * </div>\n * )}\n * ```\n */\n renderListItem?: (row: T, index: number, context: DataGridListItemContext) => ReactNode;\n};\n\nexport type HeaderAction = {\n /** Button text; if omitted and `icon` provided, button will be icon-only */\n label?: string;\n /** Icon name to render inside the button (maps to library `Icon`) */\n icon?: string;\n /** Accessible label for screen readers. Required for icon-only buttons (when label is omitted). */\n ariaLabel?: string;\n /** Click handler invoked when the button is clicked */\n onClick?: () => void;\n /** Button variant (maps to Button `variant` prop) */\n variant?: ButtonProps['variant'];\n /** Button style (maps to Button `style` prop) */\n style?: ButtonProps['style'];\n /** Button size (maps to Button `size` prop) */\n size?: ButtonProps['size'];\n /** Additional className forwarded to the Button */\n className?: string;\n};\n\n/** Breakpoint width (in px) below which we switch to list mode */\nconst DEFAULT_LIST_BREAKPOINT = 480;\n\n/**\n * Context passed to `renderListItem` so list-mode renders can embed grid actions\n * and selection state without needing to manage them independently.\n */\nexport type DataGridListItemContext = {\n /** Pre-rendered action buttons derived from the `actions` prop */\n actions: ReactNode;\n /** Whether this row is currently selected */\n isSelected: boolean;\n /** Toggle selection for this row. Defined only when `selectable` is true. */\n onToggleSelect?: () => void;\n};\n\n/**\n * DataGrid - Responsive data display component with Vercel-style layout\n *\n * Features:\n * - Generic typed data and columns (same API as DataTable)\n * - Responsive layout: horizontal rows on desktop, vertical card-like on mobile\n * - Clickable rows via rowHref with interactive elements taking priority\n * - Client-side sorting, pagination, selection, and search\n * - Custom cell rendering with DataGridCell for multi-element stacking\n *\n * @example\n * ```tsx\n * <DataGrid\n * data={deployments}\n * columns={[\n * {\n * key: 'name',\n * label: 'Deployment',\n * render: (value, row) => (\n * <DataGridCell>\n * <Text weight=\"medium\">{row.name}</Text>\n * <Text size=\"sm\" variant=\"muted\">{row.url}</Text>\n * </DataGridCell>\n * )\n * },\n * { key: 'status', label: 'Status', badgeMap: { ready: { variant: 'success' } } },\n * { key: 'createdAt', label: 'Created', format: 'date' }\n * ]}\n * rowHref={(row) => `/deployments/${row.id}`}\n * hoverable\n * />\n * ```\n */\nfunction DataGrid<T>({\n data,\n columns,\n className = '',\n striped = false,\n hoverable = true,\n compact = false,\n sortable = true,\n paginated = false,\n pageSize = 10,\n selectable = false,\n searchable = false,\n searchKeys,\n searchPlaceholder = 'Search...',\n onSearchChange,\n actions,\n actionsLabel = 'Actions',\n rowHref,\n onRowClick,\n onSelectionChange,\n emptyState = {\n title: 'No data available',\n description: undefined,\n buttonText: undefined,\n onButtonClick: undefined\n },\n headerActions,\n title,\n initialSort,\n listBreakpoint = DEFAULT_LIST_BREAKPOINT,\n renderListItem\n}: DataGridProps<T>) {\n // Search state\n const [searchQuery, setSearchQuery] = useState('');\n\n // Layout state – true when container width is below listBreakpoint\n const [isListMode, setIsListMode] = useState(false);\n\n const handleSearchChange = (value: string) => {\n setSearchQuery(value);\n if (onSearchChange) {\n onSearchChange(value);\n }\n };\n\n // Container ref for responsive behavior\n const containerRef = useRef<HTMLDivElement>(null);\n const [visibleColumns, setVisibleColumns] = useState<DataGridColumnDef<T>[]>(() => columns);\n\n // Calculate minimum width needed for actions column based on max actions in any row\n const calculateActionsMinWidth = (): number => {\n if (!actions) return 0;\n\n let maxActionCount = 0;\n\n if (Array.isArray(actions)) {\n // Static actions - all rows have the same actions\n maxActionCount = actions.length;\n } else {\n // Dynamic actions - need to check all rows\n data.forEach((row, index) => {\n const result = actions(row, index);\n if (Array.isArray(result)) {\n maxActionCount = Math.max(maxActionCount, result.length);\n } else {\n // Custom render - assume it needs reasonable space (equivalent to 2 actions)\n maxActionCount = Math.max(maxActionCount, 2);\n }\n });\n }\n\n if (maxActionCount === 0) {\n // No actions, but we still need some minimum space in case actions appear\n return 60;\n }\n\n // Each action button takes ~36px (icon + button padding)\n // Stack spacing between actions is 8px (spacing=\"sm\")\n // Formula: (actionWidth * count) + (gap * (count - 1)) + extraPadding\n const actionWidth = 24;\n const gapWidth = 8;\n const extraPadding = 16; // breathing room\n\n return actionWidth * maxActionCount + gapWidth * Math.max(0, maxActionCount - 1) + extraPadding;\n };\n\n const actionsMinWidth = calculateActionsMinWidth();\n\n // ResizeObserver to handle responsive column hiding and mobile layout\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n // Check if any columns have hidePriority or minWidth set (both make columns hideable)\n const hasHideableColumns = columns.some((col) => col.hidePriority !== undefined || col.minWidth !== undefined);\n\n const updateLayout = () => {\n const containerWidth = container.offsetWidth;\n\n // Check if we should switch to list mode\n const nowListMode = containerWidth < listBreakpoint;\n setIsListMode(nowListMode);\n\n // In list mode, show all columns (either renderListItem handles layout\n // or the fallback vertical stack renders them all with labels).\n // Only apply responsive column hiding in grid mode.\n if (nowListMode || !hasHideableColumns) {\n setVisibleColumns(columns);\n return;\n }\n\n // Columns are hideable if they have hidePriority OR minWidth\n const isHideable = (col: DataGridColumnDef<T>) => col.hidePriority !== undefined || col.minWidth !== undefined;\n\n // Separate columns into hideable and non-hideable\n const hideableColumns = columns\n .map((col, index) => ({ col, originalIndex: index }))\n .filter(({ col }) => isHideable(col))\n .sort((a, b) => {\n // Sort by hidePriority if both have it (lower hides first)\n const aPriority = a.col.hidePriority;\n const bPriority = b.col.hidePriority;\n\n if (aPriority !== undefined && bPriority !== undefined) {\n if (aPriority !== bPriority) return aPriority - bPriority;\n }\n // Columns with explicit hidePriority hide before minWidth-only columns\n if (aPriority !== undefined && bPriority === undefined) return -1;\n if (aPriority === undefined && bPriority !== undefined) return 1;\n\n // For minWidth-only columns, larger minWidth hides first (needs more space)\n const aMin = a.col.minWidth ?? 0;\n const bMin = b.col.minWidth ?? 0;\n if (aMin !== bMin) return bMin - aMin;\n\n // Finally, later columns hide first (preserve leading columns)\n return b.originalIndex - a.originalIndex;\n });\n\n const nonHideableColumns = columns.filter((col) => !isHideable(col));\n\n // Estimate column width - use minWidth if set, otherwise parse width or default\n const estimateColumnWidth = (col: DataGridColumnDef<T>): number => {\n // Use minWidth if explicitly set (this is the minimum space the column needs)\n if (col.minWidth) return col.minWidth;\n\n if (col.width) {\n const match = col.width.match(/(\\d+)/);\n if (match) {\n const num = parseInt(match[1], 10);\n if (col.width.includes('px')) return num;\n return num * 4;\n }\n }\n return 150;\n };\n\n // Calculate horizontal padding (px-3 = 24px total, px-4 = 32px total)\n const horizontalPadding = compact ? 24 : 32;\n // Grid gap is 16px (gap-4) between each column\n const gridGap = 16;\n\n // Start with non-hideable columns\n let currentWidth = nonHideableColumns.reduce((sum, col) => sum + estimateColumnWidth(col), 0);\n let totalColumns = nonHideableColumns.length;\n\n // Account for selection and actions columns\n if (selectable) {\n currentWidth += 48;\n totalColumns += 1;\n }\n if (actions) {\n currentWidth += actionsMinWidth;\n totalColumns += 1;\n }\n\n // Add hideable columns until we run out of space\n const columnsToShow: DataGridColumnDef<T>[] = [...nonHideableColumns];\n\n for (const { col } of hideableColumns) {\n const colWidth = estimateColumnWidth(col);\n const newTotalColumns = totalColumns + 1;\n // Calculate total gaps needed with the new column (N columns = N-1 gaps)\n const totalGaps = Math.max(0, newTotalColumns - 1) * gridGap;\n const totalWidthNeeded = currentWidth + colWidth + totalGaps + horizontalPadding;\n\n if (totalWidthNeeded <= containerWidth) {\n columnsToShow.push(col);\n currentWidth += colWidth;\n totalColumns = newTotalColumns;\n }\n }\n\n // Restore original column order\n const orderedVisibleColumns = columns.filter((col) => columnsToShow.includes(col));\n setVisibleColumns(orderedVisibleColumns);\n };\n\n // Call once on mount\n updateLayout();\n\n // Set up observer\n const observer = new ResizeObserver(() => {\n updateLayout();\n });\n\n observer.observe(container);\n\n return () => {\n observer.disconnect();\n };\n }, [columns, selectable, actions, actionsMinWidth, compact, data, listBreakpoint]);\n\n // Use table hook for state management\n const effectiveSearchKeys = searchKeys || visibleColumns.map((col) => col.key);\n\n const tableOptions: UseTableOptions<T> = {\n data,\n initialSort,\n pageSize,\n searchQuery,\n searchKeys: effectiveSearchKeys\n };\n\n const {\n currentData,\n sortedData,\n filteredData,\n sortConfig,\n handleSort,\n currentPage,\n totalPages,\n nextPage,\n prevPage,\n canNextPage,\n canPrevPage,\n selectedRows,\n toggleRow,\n toggleAll,\n isRowSelected,\n isAllSelected\n } = useTable(tableOptions);\n\n // Display data (paginated uses currentData, non-paginated uses sortedData)\n const displayData = paginated ? currentData : sortedData;\n\n // Header title and actions\n const hasHeader = Boolean(\n (title && String(title).length > 0) ||\n (Array.isArray(headerActions) ? headerActions.length > 0 : headerActions) ||\n searchable\n );\n\n // Selection handlers\n const handleToggleRow = (index: number) => {\n toggleRow(index);\n if (onSelectionChange) {\n const newSelection = new Set(selectedRows);\n if (newSelection.has(index)) {\n newSelection.delete(index);\n } else {\n newSelection.add(index);\n }\n onSelectionChange(Array.from(newSelection));\n }\n };\n\n const handleToggleAll = () => {\n toggleAll();\n if (onSelectionChange) {\n if (isAllSelected) {\n onSelectionChange([]);\n } else {\n const startIndex = (currentPage - 1) * pageSize;\n const allIndices = displayData.map((_, idx) => startIndex + idx);\n onSelectionChange(allIndices);\n }\n }\n };\n\n // Format value based on column configuration\n const formatValue = (value: unknown, column: DataGridColumnDef<T>): string => {\n if (value == null) return '';\n\n switch (column.format) {\n case 'date': {\n const dateValue = value instanceof Date ? value : new Date(value as string | number);\n return new Intl.DateTimeFormat('en-US', column.formatOptions as Intl.DateTimeFormatOptions).format(dateValue);\n }\n\n case 'currency':\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n ...column.formatOptions\n } as Intl.NumberFormatOptions).format(Number(value));\n\n case 'number':\n return new Intl.NumberFormat('en-US', column.formatOptions as Intl.NumberFormatOptions).format(Number(value));\n\n case 'percent':\n return new Intl.NumberFormat('en-US', {\n style: 'percent',\n ...column.formatOptions\n } as Intl.NumberFormatOptions).format(Number(value));\n\n default:\n return String(value);\n }\n };\n\n const renderCellContent = (value: unknown, column: DataGridColumnDef<T>, row: T, rowIndex: number): ReactNode => {\n const isEmpty = value == null || value === '';\n\n if (isEmpty && column.fallback !== undefined) {\n return column.fallback;\n }\n\n if (column.render) {\n return column.render(value as T[keyof T], row, rowIndex);\n }\n\n if (column.badgeMap) {\n const stringValue = String(value);\n const badgeConfig = column.badgeMap[stringValue] || column.badgeMap['*'] || { variant: 'neutral' };\n\n return (\n <Badge variant={badgeConfig.variant || 'neutral'} size={column.componentSize || 'md'}>\n {badgeConfig.label || stringValue}\n </Badge>\n );\n }\n\n if (column.statusDotMap) {\n const stringValue = String(value);\n const dotConfig = column.statusDotMap[stringValue] || column.statusDotMap['*'] || { color: 'neutral' };\n\n return <StatusIndicator variant={dotConfig.color || 'neutral'}>{dotConfig.label || stringValue}</StatusIndicator>;\n }\n\n if (column.renderAsBadges) {\n if (Array.isArray(value)) {\n if (value.length === 0 && column.fallback !== undefined) {\n return column.fallback;\n }\n\n return (\n <Stack direction=\"horizontal\" spacing=\"xs\" wrap>\n {value.map((item, idx) => (\n <Badge key={idx} variant={column.badgeVariant || 'neutral'} size={column.componentSize || 'md'}>\n {String(item)}\n </Badge>\n ))}\n </Stack>\n );\n } else {\n return (\n <Badge variant={column.badgeVariant || 'neutral'} size={column.componentSize || 'md'}>\n {String(value)}\n </Badge>\n );\n }\n }\n\n if (column.format) {\n return formatValue(value, column);\n }\n\n return String(value ?? '');\n };\n\n // Render sort indicator\n const renderSortIcon = (columnKey: keyof T) => {\n if (!sortable) return null;\n\n const isSorted = sortConfig?.key === columnKey;\n\n if (!isSorted) {\n return <Icon name=\"selector\" size=\"xs\" color=\"neutral\" />;\n }\n\n if (sortConfig?.direction === 'asc') {\n return <Icon name=\"chevron-up\" size=\"xs\" color=\"primary\" />;\n }\n\n return <Icon name=\"chevron-down\" size=\"xs\" color=\"primary\" />;\n };\n\n // Render actions for a row\n const renderActions = (row: T, actualIndex: number) => {\n if (!actions) return null;\n\n let rowActions: DataGridActionItem<T>[] | ReactNode;\n\n if (Array.isArray(actions)) {\n rowActions = actions;\n } else {\n const result = actions(row, actualIndex);\n if (Array.isArray(result)) {\n rowActions = result;\n } else {\n return <div data-interactive>{result}</div>;\n }\n }\n\n return (\n <Stack direction=\"horizontal\" spacing=\"sm\" data-interactive>\n {(rowActions as DataGridActionItem<T>[]).map((action, actionIndex) => {\n if (action && typeof action === 'object' && 'onClick' in action) {\n const actionConfig = action as DataGridAction<T>;\n const button = (\n <IconButton\n key={actionIndex}\n icon={actionConfig.icon}\n iconSize={actionConfig.iconSize || 'md'}\n buttonStyle=\"ghost\"\n variant={actionConfig.variant || 'neutral'}\n iconColor={actionConfig.iconColor}\n hoverIcon={actionConfig.hoverIcon}\n ariaLabel={actionConfig.label}\n onClick={() => actionConfig.onClick(row, actualIndex)}\n noPadding\n />\n );\n\n return actionConfig.tooltip ? (\n <Tooltip key={actionIndex} content={actionConfig.tooltip}>\n {button}\n </Tooltip>\n ) : (\n button\n );\n } else {\n return (\n <div key={actionIndex} data-interactive>\n {action as ReactNode}\n </div>\n );\n }\n })}\n </Stack>\n );\n };\n\n // Row padding classes\n const rowPadding = compact ? 'py-2 px-3' : 'py-3 px-4';\n\n // Build grid template columns for desktop layout\n const buildGridTemplateColumns = () => {\n const parts: string[] = [];\n\n // Selection checkbox column - fixed width for consistency across rows\n if (selectable) {\n parts.push('24px');\n }\n\n // Data columns\n visibleColumns.forEach((col) => {\n if (col.width) {\n // Explicit width (Tailwind class won't work in grid-template-columns)\n // Try to extract pixel value or use minmax\n const widthMatch = col.width.match(/(\\d+)px/);\n if (widthMatch) {\n parts.push(`${widthMatch[1]}px`);\n } else {\n parts.push('1fr');\n }\n } else if (col.minWidth && col.maxWidth) {\n // Both min and max - constrained range\n parts.push(`minmax(${col.minWidth}px, ${col.maxWidth}px)`);\n } else if (col.minWidth) {\n // Min only - can grow but not shrink below\n parts.push(`minmax(${col.minWidth}px, 1fr)`);\n } else if (col.maxWidth) {\n // Max only - can shrink but not grow beyond\n parts.push(`minmax(auto, ${col.maxWidth}px)`);\n } else {\n parts.push('1fr');\n }\n });\n\n // Actions column - dynamically sized based on max actions across all rows\n // Allows growing to max-content to accommodate multiple action buttons\n if (actions) {\n parts.push(`minmax(${actionsMinWidth}px, max-content)`);\n }\n\n return parts.join(' ');\n };\n\n const gridTemplateColumns = !isListMode ? buildGridTemplateColumns() : undefined;\n\n // Render a single row\n const renderRow = (row: T, rowIndex: number) => {\n const actualIndex = paginated ? (currentPage - 1) * pageSize + rowIndex : rowIndex;\n const isSelected = isRowSelected(actualIndex);\n const href = rowHref?.(row, actualIndex);\n const hasHref = Boolean(href);\n const hasOnRowClick = Boolean(onRowClick);\n const isClickable = hasHref || hasOnRowClick;\n\n // Row styling - add relative for Link overlay positioning\n const rowClasses = [\n 'relative',\n 'border-b border-border/50',\n striped && rowIndex % 2 === 1 ? 'bg-muted/30' : '',\n hoverable && isClickable ? 'hover:bg-muted/50 transition-colors' : '',\n isSelected ? 'bg-primary/5' : ''\n ]\n .filter(Boolean)\n .join(' ');\n\n // Grid mode: CSS Grid for consistent column widths\n // List mode: vertical flex (fallback) or custom renderListItem\n const layoutClasses = isListMode ? 'flex flex-col gap-3' : 'grid items-center gap-4';\n\n // Grid style for grid mode only\n const rowStyle = !isListMode && gridTemplateColumns ? { gridTemplateColumns } : undefined;\n\n // ----------------------------------------------------------------\n // List mode with custom render – delegate layout to renderListItem\n // ----------------------------------------------------------------\n if (isListMode && renderListItem) {\n const actionsContent = renderActions(row, actualIndex);\n const listItemContent = renderListItem(row, actualIndex, {\n actions: actionsContent,\n isSelected,\n onToggleSelect: selectable ? () => handleToggleRow(actualIndex) : undefined\n });\n\n // Pointer-events wrapper mirrors the grid row behaviour\n const pointerClass = hasHref\n ? 'pointer-events-none [&_a]:pointer-events-auto [&_button]:pointer-events-auto [&_input]:pointer-events-auto [&_select]:pointer-events-auto [&_textarea]:pointer-events-auto [&_label]:pointer-events-auto [&_[data-interactive]]:pointer-events-auto'\n : '';\n\n const listRowClickProps =\n !hasHref && hasOnRowClick\n ? {\n onClick: (e: React.MouseEvent<HTMLDivElement>) => {\n if (isInteractiveElement(e.target as HTMLElement, e.currentTarget)) return;\n onRowClick?.(row, actualIndex);\n },\n onKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onRowClick?.(row, actualIndex);\n }\n },\n role: 'button' as const,\n tabIndex: 0,\n className: 'cursor-pointer'\n }\n : {};\n\n return (\n <div\n key={actualIndex}\n className={`relative ${rowPadding} ${rowClasses} ${listRowClickProps.className || ''}`}\n onClick={listRowClickProps.onClick}\n onKeyDown={listRowClickProps.onKeyDown}\n role={listRowClickProps.role}\n tabIndex={listRowClickProps.tabIndex}\n >\n {hasHref && href && (\n <Link to={href} className=\"absolute inset-0 z-1\" aria-label=\"View details\" tabIndex={0} />\n )}\n <div className={pointerClass}>{listItemContent}</div>\n </div>\n );\n }\n\n // ----------------------------------------------------------------\n // Props for onRowClick (when no href) - handlers are on the row div\n // Uses isInteractiveElement check to avoid triggering on links/buttons\n const rowClickProps =\n !hasHref && hasOnRowClick\n ? {\n onClick: (e: React.MouseEvent<HTMLDivElement>) => {\n // Don't trigger if clicked on an interactive element (links, buttons, etc.)\n if (isInteractiveElement(e.target as HTMLElement, e.currentTarget)) {\n return;\n }\n onRowClick?.(row, actualIndex);\n },\n onKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onRowClick?.(row, actualIndex);\n }\n },\n role: 'button' as const,\n tabIndex: 0,\n className: 'cursor-pointer'\n }\n : {};\n\n return (\n <div\n key={actualIndex}\n className={`${layoutClasses} ${rowPadding} ${rowClasses} ${rowClickProps.className || ''}`}\n style={rowStyle}\n onClick={rowClickProps.onClick}\n onKeyDown={rowClickProps.onKeyDown}\n role={rowClickProps.role}\n tabIndex={rowClickProps.tabIndex}\n >\n {/* Row link overlay - positioned behind content */}\n {hasHref && href && (\n <Link to={href} className=\"absolute inset-0 z-1\" aria-label={`View details`} tabIndex={0} />\n )}\n\n {/* Selection checkbox - above link layer */}\n {selectable && (\n <div className={`relative z-10 ${isListMode ? '' : 'shrink-0'}`}>\n <Checkbox\n checked={isSelected}\n onChange={() => handleToggleRow(actualIndex)}\n ariaLabel={`Select row ${actualIndex + 1}`}\n />\n </div>\n )}\n\n {/* Data cells - pointer-events-none lets clicks pass through to link layer */}\n {/* Interactive elements inside (links, buttons) keep their default pointer-events */}\n {visibleColumns.map((column) => {\n const value = row[column.key];\n const content = renderCellContent(value, column, row, actualIndex);\n const showLabel = isListMode && column.showLabelOnMobile !== false;\n\n // Alignment\n const alignClass =\n column.align === 'center' ? 'text-center' : column.align === 'right' ? 'text-right' : 'text-left';\n\n // Only disable pointer events when we have a link overlay\n const pointerClass = hasHref\n ? 'pointer-events-none [&_a]:pointer-events-auto [&_button]:pointer-events-auto [&_input]:pointer-events-auto [&_select]:pointer-events-auto [&_textarea]:pointer-events-auto [&_label]:pointer-events-auto [&_[data-interactive]]:pointer-events-auto'\n : '';\n\n return (\n <div\n key={String(column.key)}\n className={`${alignClass} ${isListMode ? 'flex flex-col gap-0.5' : 'min-w-0 overflow-hidden'} ${pointerClass}`}\n >\n {showLabel && (\n <Text size=\"xs\" variant=\"muted\" className=\"uppercase tracking-wide\">\n {column.label}\n </Text>\n )}\n <div className={column.wrapText ? '' : 'truncate'}>{content}</div>\n </div>\n );\n })}\n\n {/* Actions - above link layer */}\n {actions && (\n <div className={`relative z-10 shrink-0 ${isListMode ? 'flex justify-end pt-1' : 'justify-self-end'}`}>\n {renderActions(row, actualIndex)}\n </div>\n )}\n </div>\n );\n };\n\n return (\n <div ref={containerRef} className={`overflow-hidden ${className}`}>\n {/* Header with title, search, actions */}\n {hasHeader && (\n <div className=\"mb-3\">\n {searchable ? (\n <div className=\"flex flex-col gap-3\">\n {title && <h2 className=\"text-lg font-semibold text-foreground\">{title}</h2>}\n <div className=\"flex flex-col sm:flex-row items-stretch sm:items-center gap-3 sm:justify-between\">\n <div className=\"flex-1 sm:max-w-md\">\n <InputGroup prefix={<Icon name=\"search\" size=\"sm\" />} className=\"w-full\">\n <Input\n type=\"text\"\n value={searchQuery}\n onChange={(e) => handleSearchChange(e.target.value)}\n placeholder={searchPlaceholder}\n />\n </InputGroup>\n </div>\n\n {Array.isArray(headerActions) && headerActions.length > 0 && (\n <div className=\"flex items-center gap-2 flex-wrap sm:flex-nowrap ml-auto\">\n {headerActions.map((act, idx) => (\n <Button\n key={idx}\n onClick={act.onClick}\n variant={act.variant}\n style={act.style}\n size={act.size}\n className={act.className}\n ariaLabel={act.ariaLabel || (!act.label && act.icon ? 'Action' : undefined)}\n >\n {act.icon ? <Icon name={act.icon} size=\"sm\" /> : null}\n {act.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n </div>\n ) : (\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3\">\n <div className=\"flex-1\">\n {title && <h2 className=\"text-lg font-semibold text-foreground\">{title}</h2>}\n </div>\n\n {Array.isArray(headerActions) && headerActions.length > 0 && (\n <div className=\"flex items-center gap-2 flex-wrap sm:flex-nowrap\">\n {headerActions.map((act, idx) => (\n <Button\n key={idx}\n onClick={act.onClick}\n variant={act.variant}\n style={act.style}\n size={act.size}\n className={act.className}\n ariaLabel={act.ariaLabel || (!act.label && act.icon ? 'Action' : undefined)}\n >\n {act.icon ? <Icon name={act.icon} size=\"sm\" /> : null}\n {act.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n )}\n\n {/* Empty states */}\n {data.length === 0 ? (\n <div className=\"border border-border rounded-lg\">\n <EmptyState\n title={emptyState.title}\n description={emptyState.description}\n buttonText={emptyState.buttonText}\n onButtonClick={emptyState.onButtonClick}\n />\n </div>\n ) : filteredData.length === 0 && searchQuery.trim() ? (\n <div className=\"border border-border rounded-lg\">\n <EmptyState\n title=\"No results found\"\n description={`No items match \"${searchQuery}\". Try adjusting your search.`}\n />\n </div>\n ) : (\n <>\n {/* Column headers – grid mode only (hidden in list mode) */}\n {!isListMode && (\n <div\n className={`grid items-center gap-4 ${rowPadding} border-b border-border bg-muted/30`}\n style={gridTemplateColumns ? { gridTemplateColumns } : undefined}\n >\n {selectable && (\n <div>\n <Checkbox checked={isAllSelected} onChange={handleToggleAll} ariaLabel=\"Select all rows\" />\n </div>\n )}\n\n {visibleColumns.map((column) => {\n const alignClass =\n column.align === 'center' ? 'text-center' : column.align === 'right' ? 'text-right' : 'text-left';\n\n return (\n <div key={String(column.key)} className={`min-w-0 ${alignClass}`}>\n {column.sortable !== false && sortable ? (\n <button\n onClick={() => handleSort(column.key)}\n className=\"flex items-center gap-1 hover:text-foreground transition-colors font-medium text-sm text-muted-foreground\"\n type=\"button\"\n >\n {column.label}\n {renderSortIcon(column.key)}\n </button>\n ) : (\n <Text size=\"sm\" variant=\"muted\" weight=\"medium\">\n {column.label}\n </Text>\n )}\n </div>\n );\n })}\n\n {actions && (\n <div className=\"justify-self-end\">\n <Text size=\"sm\" variant=\"muted\" weight=\"medium\">\n {actionsLabel}\n </Text>\n </div>\n )}\n </div>\n )}\n\n {/* Select all checkbox (list mode fallback only – renderListItem handles its own selection UI) */}\n {isListMode && !renderListItem && selectable && (\n <div className={`flex items-center gap-2 ${rowPadding} border-b border-border`}>\n <Checkbox checked={isAllSelected} onChange={handleToggleAll} ariaLabel=\"Select all rows\" />\n <Text size=\"sm\" variant=\"muted\">\n Select all\n </Text>\n </div>\n )}\n\n {/* Rows */}\n <div className=\"divide-y divide-border/50\">{displayData.map((row, idx) => renderRow(row, idx))}</div>\n\n {/* Pagination controls */}\n {paginated && totalPages > 1 && (\n <div className=\"flex items-center justify-between px-4 py-3 border-t border-border\">\n <div className=\"text-sm text-muted-foreground\">\n Page {currentPage} of {totalPages} ({filteredData.length} {searchQuery.trim() ? 'filtered' : 'total'}{' '}\n rows\n {searchQuery.trim() && data.length !== filteredData.length ? ` of ${data.length}` : ''})\n </div>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" style=\"outline\" onClick={prevPage} disabled={!canPrevPage}>\n Previous\n </Button>\n <Button size=\"sm\" style=\"outline\" onClick={nextPage} disabled={!canNextPage}>\n Next\n </Button>\n </div>\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n\nDataGrid.displayName = 'DataGrid';\n\nexport default DataGrid;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-grid.js","sources":["../../../../src/components/data-display/data-grid/data-grid.tsx"],"sourcesContent":["import { ReactNode, useState, useEffect, useRef } from 'react';\nimport { Icon } from '../../system/icon/icon';\nimport IconButton from '../../forms/button/icon-button';\nimport Input from '../../forms/input/input';\nimport InputGroup from '../../forms/input-group/input-group';\n\nimport Checkbox from '../../forms/checkbox/checkbox';\nimport Button from '../../forms/button/button';\nimport Tooltip from '../../feedback/tooltip/tooltip';\nimport type { ButtonProps } from '../../forms/button/button';\nimport Stack from '../../layout/stack/stack';\nimport Badge from '../badge/badge';\nimport Text from '../../typography/text/text';\nimport { useTable, UseTableOptions } from '../data-table/use-table';\nimport { Size } from '@/theme/size-tokens';\nimport { ColorVariant } from '@/theme/tokens';\nimport EmptyState from '../empty-state/empty-state';\nimport StatusIndicator from '../status-indicator/status-indicator';\nimport { Link } from 'react-router-dom';\n\n/** Interactive element tags that should not trigger onRowClick callback */\nconst INTERACTIVE_TAGS = new Set(['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA', 'LABEL']);\n\n/** Check if an element or any of its ancestors (up to container) is interactive - used for onRowClick only */\nfunction isInteractiveElement(element: HTMLElement | null, container: HTMLElement | null): boolean {\n let current = element;\n while (current && current !== container) {\n if (INTERACTIVE_TAGS.has(current.tagName)) return true;\n if (current.getAttribute('role') === 'button') return true;\n current = current.parentElement;\n }\n return false;\n}\n\nexport type DataGridAction<T> = {\n /** Icon name for the action button */\n icon: string;\n /** Size of the icon */\n iconSize?: Size;\n /** Color variant for the icon */\n iconColor?: ColorVariant;\n /** Icon to display on hover (optional) */\n hoverIcon?: string;\n /** Accessible label for the action (shown in tooltip or screen readers) */\n label: string;\n /** Tooltip text to display on hover. If not provided, label will be used for aria-label only. */\n tooltip?: string;\n /** Callback when the action is clicked */\n onClick: (row: T, index: number) => void;\n /** Visual variant for the action button */\n variant?: 'primary' | 'accent' | 'neutral' | 'success' | 'warning' | 'error' | 'info';\n};\n\nexport type DataGridActionItem<T> = DataGridAction<T> | ReactNode;\n\nexport type DataGridColumnDef<T> = {\n /** Key of the data property to display in this column */\n key: keyof T;\n /** Column header label */\n label: string;\n /** Whether this column can be sorted */\n sortable?: boolean;\n /** CSS width class or value for the column (e.g., 'w-48', '200px', 'flex-1') */\n width?: string;\n /**\n * Minimum width in pixels for the column. When set:\n * - Column truncates but never shrinks below this width\n * - Column auto-hides if container can't fit it at this width\n * - No need to also set hidePriority (though you can for explicit hide ordering)\n *\n * @example minWidth: 120 // Hide if email would be squished below 120px\n */\n minWidth?: number;\n /**\n * Maximum width in pixels for the column. Prevents column from growing too wide.\n * Use for columns like status/role that don't need much space.\n *\n * @example maxWidth: 100 // Cap role column at 100px\n */\n maxWidth?: number;\n /** Text alignment for cells in this column */\n align?: 'left' | 'center' | 'right';\n /** Whether text should wrap instead of truncating (useful for long strings) */\n wrapText?: boolean;\n /** Optional priority for responsive hiding. Lower values hide first when container width shrinks. Columns without hidePriority or minWidth are never hidden. */\n hidePriority?: number;\n /** Whether to show this column's label in mobile/vertical layout (default: true) */\n showLabelOnMobile?: boolean;\n /** Custom render function for cell content (use as escape hatch when config options don't cover your use case) */\n render?: (value: T[keyof T], row: T, index: number) => ReactNode;\n\n // Config-driven rendering options (preferred over custom render)\n /** Pre-built formatter for common data types */\n format?: 'date' | 'currency' | 'number' | 'percent';\n /** Options for Intl formatters (NumberFormat or DateTimeFormat) */\n formatOptions?: Intl.NumberFormatOptions | Intl.DateTimeFormatOptions;\n /** Map values to badge variants. Unmatched values render with 'neutral' variant. Use '*' key to override the default fallback. */\n badgeMap?: {\n [key: string]: { variant?: ColorVariant; label?: string };\n };\n /** Map values to status dot colors. Renders text with a colored dot to the left. Lighter alternative to badges for status indicators. */\n statusDotMap?: {\n [key: string]: { color?: ColorVariant; label?: string };\n };\n /**\n * Render cell values as badges. When the value is an array, each item is rendered\n * as an individual badge; for scalar values, the value is wrapped in a single badge.\n */\n renderAsBadges?: boolean;\n /** Variant for badge rendering */\n badgeVariant?: ColorVariant;\n /** Size for badge rendering */\n componentSize?: 'sm' | 'md' | 'lg';\n /** Fallback value to display when cell value is null, undefined, or empty string */\n fallback?: string;\n};\n\nexport type DataGridProps<T> = {\n /** Array of data objects to display in the grid */\n data: T[];\n /** Column definitions specifying how to render each column */\n columns: DataGridColumnDef<T>[];\n /** Additional CSS classes to apply */\n className?: string;\n\n // Styling options\n /** Whether to apply striped row styling (alternating background) */\n striped?: boolean;\n /** Whether rows have hover effects */\n hoverable?: boolean;\n /** Whether to use compact spacing for dense data */\n compact?: boolean;\n\n // Features\n /** Whether columns can be sorted (can be overridden per column) */\n sortable?: boolean;\n /** Whether to enable client-side pagination */\n paginated?: boolean;\n /** Number of rows per page when pagination is enabled */\n pageSize?: number;\n /** Whether to show checkboxes for row selection */\n selectable?: boolean;\n /** Whether to enable search/filter functionality */\n searchable?: boolean;\n /** Specific keys to search within. If not provided, searches all fields. */\n searchKeys?: (keyof T)[];\n /** Placeholder text for the search input */\n searchPlaceholder?: string;\n /** Callback when search query changes */\n onSearchChange?: (query: string) => void;\n\n // Actions - either array of action configs/components OR function returning actions/render\n /** Action buttons, function returning actions based on row data, or custom render function for the actions column */\n actions?: DataGridActionItem<T>[] | ((row: T, index: number) => DataGridActionItem<T>[] | ReactNode);\n /** Label for the actions column header */\n actionsLabel?: string;\n\n // Row link - makes entire row clickable for navigation\n /** Function returning href for row navigation. When provided, entire row becomes a link. */\n rowHref?: (row: T, index: number) => string | undefined;\n\n // Callbacks\n /** Callback when a row is clicked (if rowHref not provided) */\n onRowClick?: (row: T, index: number) => void;\n /** Callback when row selection changes (provides array of selected row indices) */\n onSelectionChange?: (selectedIndices: number[]) => void;\n\n // Empty state\n emptyState?: {\n /** Message to display when there is no data */\n title?: string;\n /** Description to display when there is no data */\n description?: string;\n /** Text for the button in the empty state */\n buttonText?: string;\n /** Click handler for the button in the empty state */\n onButtonClick?: () => void;\n /** React Router path — renders the empty state button as a <Link>. Use instead of onButtonClick for in-app navigation. */\n buttonTo?: string;\n /** Plain URL — renders the empty state button as an <a> tag. Use for external links. */\n buttonHref?: string;\n /** Link target (e.g. \"_blank\") — only used with buttonTo or buttonHref */\n buttonTarget?: ButtonProps['target'];\n /** Rel attribute for the anchor (defaults to \"noopener noreferrer\" when buttonTarget=\"_blank\") */\n buttonRel?: string;\n };\n\n // Initial state\n /** Initial sort configuration */\n initialSort?: { key: keyof T; direction: 'asc' | 'desc' };\n /** Title displayed above the grid (left side of header) */\n title?: string;\n /** Header actions displayed above the grid (right side of header). */\n headerActions?: HeaderAction[];\n\n // Responsive / list mode\n /**\n * Container width (px) below which the grid collapses into list mode.\n * Defaults to 480. Column hiding (via `hidePriority` / `minWidth`) still\n * runs for widths above this breakpoint.\n */\n listBreakpoint?: number;\n /**\n * Custom render function for list mode. When provided, each row is rendered\n * using this function instead of the default vertical-stack fallback.\n * Use this to create type-specific list layouts with the right fields,\n * actions, and visual hierarchy for the entity being displayed.\n *\n * @example\n * ```tsx\n * renderListItem={(row, index, { actions, isSelected, onToggleSelect }) => (\n * <div className=\"flex items-center gap-3\">\n * <Avatar name={row.name} />\n * <div className=\"flex-1 min-w-0\">\n * <Text weight=\"medium\" className=\"truncate\">{row.name}</Text>\n * <Text size=\"sm\" variant=\"muted\" className=\"truncate\">{row.email}</Text>\n * </div>\n * {actions}\n * </div>\n * )}\n * ```\n */\n renderListItem?: (row: T, index: number, context: DataGridListItemContext) => ReactNode;\n};\n\nexport type HeaderAction = {\n /** Button text; if omitted and `icon` provided, button will be icon-only */\n label?: string;\n /** Icon name to render inside the button (maps to library `Icon`) */\n icon?: string;\n /** Accessible label for screen readers. Required for icon-only buttons (when label is omitted). */\n ariaLabel?: string;\n /** Click handler invoked when the button is clicked */\n onClick?: () => void;\n /** React Router path — renders the button as a <Link>. Use instead of onClick for in-app navigation. */\n to?: string;\n /** Plain URL — renders the button as an <a> tag. Use for external links. */\n href?: string;\n /** Link target (e.g. \"_blank\") — only used with to or href */\n target?: ButtonProps['target'];\n /** Rel attribute for the anchor (defaults to \"noopener noreferrer\" when target=\"_blank\") */\n rel?: string;\n /** Button variant (maps to Button `variant` prop) */\n variant?: ButtonProps['variant'];\n /** Button style (maps to Button `style` prop) */\n style?: ButtonProps['style'];\n /** Button size (maps to Button `size` prop) */\n size?: ButtonProps['size'];\n /** Additional className forwarded to the Button */\n className?: string;\n};\n\n/** Breakpoint width (in px) below which we switch to list mode */\nconst DEFAULT_LIST_BREAKPOINT = 480;\n\n/**\n * Context passed to `renderListItem` so list-mode renders can embed grid actions\n * and selection state without needing to manage them independently.\n */\nexport type DataGridListItemContext = {\n /** Pre-rendered action buttons derived from the `actions` prop */\n actions: ReactNode;\n /** Whether this row is currently selected */\n isSelected: boolean;\n /** Toggle selection for this row. Defined only when `selectable` is true. */\n onToggleSelect?: () => void;\n};\n\n/**\n * DataGrid - Responsive data display component with Vercel-style layout\n *\n * Features:\n * - Generic typed data and columns (same API as DataTable)\n * - Responsive layout: horizontal rows on desktop, vertical card-like on mobile\n * - Clickable rows via rowHref with interactive elements taking priority\n * - Client-side sorting, pagination, selection, and search\n * - Custom cell rendering with DataGridCell for multi-element stacking\n *\n * @example\n * ```tsx\n * <DataGrid\n * data={deployments}\n * columns={[\n * {\n * key: 'name',\n * label: 'Deployment',\n * render: (value, row) => (\n * <DataGridCell>\n * <Text weight=\"medium\">{row.name}</Text>\n * <Text size=\"sm\" variant=\"muted\">{row.url}</Text>\n * </DataGridCell>\n * )\n * },\n * { key: 'status', label: 'Status', badgeMap: { ready: { variant: 'success' } } },\n * { key: 'createdAt', label: 'Created', format: 'date' }\n * ]}\n * rowHref={(row) => `/deployments/${row.id}`}\n * hoverable\n * />\n * ```\n */\nfunction DataGrid<T>({\n data,\n columns,\n className = '',\n striped = false,\n hoverable = true,\n compact = false,\n sortable = true,\n paginated = false,\n pageSize = 10,\n selectable = false,\n searchable = false,\n searchKeys,\n searchPlaceholder = 'Search...',\n onSearchChange,\n actions,\n actionsLabel = 'Actions',\n rowHref,\n onRowClick,\n onSelectionChange,\n emptyState = {\n title: 'No data available',\n description: undefined,\n buttonText: undefined,\n onButtonClick: undefined,\n buttonTo: undefined,\n buttonHref: undefined,\n buttonTarget: undefined,\n buttonRel: undefined\n },\n headerActions,\n title,\n initialSort,\n listBreakpoint = DEFAULT_LIST_BREAKPOINT,\n renderListItem\n}: DataGridProps<T>) {\n // Search state\n const [searchQuery, setSearchQuery] = useState('');\n\n // Layout state – true when container width is below listBreakpoint\n const [isListMode, setIsListMode] = useState(false);\n\n const handleSearchChange = (value: string) => {\n setSearchQuery(value);\n if (onSearchChange) {\n onSearchChange(value);\n }\n };\n\n // Container ref for responsive behavior\n const containerRef = useRef<HTMLDivElement>(null);\n const [visibleColumns, setVisibleColumns] = useState<DataGridColumnDef<T>[]>(() => columns);\n\n // Calculate minimum width needed for actions column based on max actions in any row\n const calculateActionsMinWidth = (): number => {\n if (!actions) return 0;\n\n let maxActionCount = 0;\n\n if (Array.isArray(actions)) {\n // Static actions - all rows have the same actions\n maxActionCount = actions.length;\n } else {\n // Dynamic actions - need to check all rows\n data.forEach((row, index) => {\n const result = actions(row, index);\n if (Array.isArray(result)) {\n maxActionCount = Math.max(maxActionCount, result.length);\n } else {\n // Custom render - assume it needs reasonable space (equivalent to 2 actions)\n maxActionCount = Math.max(maxActionCount, 2);\n }\n });\n }\n\n if (maxActionCount === 0) {\n // No actions, but we still need some minimum space in case actions appear\n return 60;\n }\n\n // Each action button takes ~36px (icon + button padding)\n // Stack spacing between actions is 8px (spacing=\"sm\")\n // Formula: (actionWidth * count) + (gap * (count - 1)) + extraPadding\n const actionWidth = 24;\n const gapWidth = 8;\n const extraPadding = 16; // breathing room\n\n return actionWidth * maxActionCount + gapWidth * Math.max(0, maxActionCount - 1) + extraPadding;\n };\n\n const actionsMinWidth = calculateActionsMinWidth();\n\n // ResizeObserver to handle responsive column hiding and mobile layout\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n // Check if any columns have hidePriority or minWidth set (both make columns hideable)\n const hasHideableColumns = columns.some((col) => col.hidePriority !== undefined || col.minWidth !== undefined);\n\n const updateLayout = () => {\n const containerWidth = container.offsetWidth;\n\n // Check if we should switch to list mode\n const nowListMode = containerWidth < listBreakpoint;\n setIsListMode(nowListMode);\n\n // In list mode, show all columns (either renderListItem handles layout\n // or the fallback vertical stack renders them all with labels).\n // Only apply responsive column hiding in grid mode.\n if (nowListMode || !hasHideableColumns) {\n setVisibleColumns(columns);\n return;\n }\n\n // Columns are hideable if they have hidePriority OR minWidth\n const isHideable = (col: DataGridColumnDef<T>) => col.hidePriority !== undefined || col.minWidth !== undefined;\n\n // Separate columns into hideable and non-hideable\n const hideableColumns = columns\n .map((col, index) => ({ col, originalIndex: index }))\n .filter(({ col }) => isHideable(col))\n .sort((a, b) => {\n // Sort by hidePriority if both have it (lower hides first)\n const aPriority = a.col.hidePriority;\n const bPriority = b.col.hidePriority;\n\n if (aPriority !== undefined && bPriority !== undefined) {\n if (aPriority !== bPriority) return aPriority - bPriority;\n }\n // Columns with explicit hidePriority hide before minWidth-only columns\n if (aPriority !== undefined && bPriority === undefined) return -1;\n if (aPriority === undefined && bPriority !== undefined) return 1;\n\n // For minWidth-only columns, larger minWidth hides first (needs more space)\n const aMin = a.col.minWidth ?? 0;\n const bMin = b.col.minWidth ?? 0;\n if (aMin !== bMin) return bMin - aMin;\n\n // Finally, later columns hide first (preserve leading columns)\n return b.originalIndex - a.originalIndex;\n });\n\n const nonHideableColumns = columns.filter((col) => !isHideable(col));\n\n // Estimate column width - use minWidth if set, otherwise parse width or default\n const estimateColumnWidth = (col: DataGridColumnDef<T>): number => {\n // Use minWidth if explicitly set (this is the minimum space the column needs)\n if (col.minWidth) return col.minWidth;\n\n if (col.width) {\n const match = col.width.match(/(\\d+)/);\n if (match) {\n const num = parseInt(match[1], 10);\n if (col.width.includes('px')) return num;\n return num * 4;\n }\n }\n return 150;\n };\n\n // Calculate horizontal padding (px-3 = 24px total, px-4 = 32px total)\n const horizontalPadding = compact ? 24 : 32;\n // Grid gap is 16px (gap-4) between each column\n const gridGap = 16;\n\n // Start with non-hideable columns\n let currentWidth = nonHideableColumns.reduce((sum, col) => sum + estimateColumnWidth(col), 0);\n let totalColumns = nonHideableColumns.length;\n\n // Account for selection and actions columns\n if (selectable) {\n currentWidth += 48;\n totalColumns += 1;\n }\n if (actions) {\n currentWidth += actionsMinWidth;\n totalColumns += 1;\n }\n\n // Add hideable columns until we run out of space\n const columnsToShow: DataGridColumnDef<T>[] = [...nonHideableColumns];\n\n for (const { col } of hideableColumns) {\n const colWidth = estimateColumnWidth(col);\n const newTotalColumns = totalColumns + 1;\n // Calculate total gaps needed with the new column (N columns = N-1 gaps)\n const totalGaps = Math.max(0, newTotalColumns - 1) * gridGap;\n const totalWidthNeeded = currentWidth + colWidth + totalGaps + horizontalPadding;\n\n if (totalWidthNeeded <= containerWidth) {\n columnsToShow.push(col);\n currentWidth += colWidth;\n totalColumns = newTotalColumns;\n }\n }\n\n // Restore original column order\n const orderedVisibleColumns = columns.filter((col) => columnsToShow.includes(col));\n setVisibleColumns(orderedVisibleColumns);\n };\n\n // Call once on mount\n updateLayout();\n\n // Set up observer\n const observer = new ResizeObserver(() => {\n updateLayout();\n });\n\n observer.observe(container);\n\n return () => {\n observer.disconnect();\n };\n }, [columns, selectable, actions, actionsMinWidth, compact, data, listBreakpoint]);\n\n // Use table hook for state management\n const effectiveSearchKeys = searchKeys || visibleColumns.map((col) => col.key);\n\n const tableOptions: UseTableOptions<T> = {\n data,\n initialSort,\n pageSize,\n searchQuery,\n searchKeys: effectiveSearchKeys\n };\n\n const {\n currentData,\n sortedData,\n filteredData,\n sortConfig,\n handleSort,\n currentPage,\n totalPages,\n nextPage,\n prevPage,\n canNextPage,\n canPrevPage,\n selectedRows,\n toggleRow,\n toggleAll,\n isRowSelected,\n isAllSelected\n } = useTable(tableOptions);\n\n // Display data (paginated uses currentData, non-paginated uses sortedData)\n const displayData = paginated ? currentData : sortedData;\n\n // Header title and actions\n const hasHeader = Boolean(\n (title && String(title).length > 0) ||\n (Array.isArray(headerActions) ? headerActions.length > 0 : headerActions) ||\n searchable\n );\n\n // Selection handlers\n const handleToggleRow = (index: number) => {\n toggleRow(index);\n if (onSelectionChange) {\n const newSelection = new Set(selectedRows);\n if (newSelection.has(index)) {\n newSelection.delete(index);\n } else {\n newSelection.add(index);\n }\n onSelectionChange(Array.from(newSelection));\n }\n };\n\n const handleToggleAll = () => {\n toggleAll();\n if (onSelectionChange) {\n if (isAllSelected) {\n onSelectionChange([]);\n } else {\n const startIndex = (currentPage - 1) * pageSize;\n const allIndices = displayData.map((_, idx) => startIndex + idx);\n onSelectionChange(allIndices);\n }\n }\n };\n\n // Format value based on column configuration\n const formatValue = (value: unknown, column: DataGridColumnDef<T>): string => {\n if (value == null) return '';\n\n switch (column.format) {\n case 'date': {\n const dateValue = value instanceof Date ? value : new Date(value as string | number);\n return new Intl.DateTimeFormat('en-US', column.formatOptions as Intl.DateTimeFormatOptions).format(dateValue);\n }\n\n case 'currency':\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n ...column.formatOptions\n } as Intl.NumberFormatOptions).format(Number(value));\n\n case 'number':\n return new Intl.NumberFormat('en-US', column.formatOptions as Intl.NumberFormatOptions).format(Number(value));\n\n case 'percent':\n return new Intl.NumberFormat('en-US', {\n style: 'percent',\n ...column.formatOptions\n } as Intl.NumberFormatOptions).format(Number(value));\n\n default:\n return String(value);\n }\n };\n\n const renderCellContent = (value: unknown, column: DataGridColumnDef<T>, row: T, rowIndex: number): ReactNode => {\n const isEmpty = value == null || value === '';\n\n if (isEmpty && column.fallback !== undefined) {\n return column.fallback;\n }\n\n if (column.render) {\n return column.render(value as T[keyof T], row, rowIndex);\n }\n\n if (column.badgeMap) {\n const stringValue = String(value);\n const badgeConfig = column.badgeMap[stringValue] || column.badgeMap['*'] || { variant: 'neutral' };\n\n return (\n <Badge variant={badgeConfig.variant || 'neutral'} size={column.componentSize || 'md'}>\n {badgeConfig.label || stringValue}\n </Badge>\n );\n }\n\n if (column.statusDotMap) {\n const stringValue = String(value);\n const dotConfig = column.statusDotMap[stringValue] || column.statusDotMap['*'] || { color: 'neutral' };\n\n return <StatusIndicator variant={dotConfig.color || 'neutral'}>{dotConfig.label || stringValue}</StatusIndicator>;\n }\n\n if (column.renderAsBadges) {\n if (Array.isArray(value)) {\n if (value.length === 0 && column.fallback !== undefined) {\n return column.fallback;\n }\n\n return (\n <Stack direction=\"horizontal\" spacing=\"xs\" wrap>\n {value.map((item, idx) => (\n <Badge key={idx} variant={column.badgeVariant || 'neutral'} size={column.componentSize || 'md'}>\n {String(item)}\n </Badge>\n ))}\n </Stack>\n );\n } else {\n return (\n <Badge variant={column.badgeVariant || 'neutral'} size={column.componentSize || 'md'}>\n {String(value)}\n </Badge>\n );\n }\n }\n\n if (column.format) {\n return formatValue(value, column);\n }\n\n return String(value ?? '');\n };\n\n // Render sort indicator\n const renderSortIcon = (columnKey: keyof T) => {\n if (!sortable) return null;\n\n const isSorted = sortConfig?.key === columnKey;\n\n if (!isSorted) {\n return <Icon name=\"selector\" size=\"xs\" color=\"neutral\" />;\n }\n\n if (sortConfig?.direction === 'asc') {\n return <Icon name=\"chevron-up\" size=\"xs\" color=\"primary\" />;\n }\n\n return <Icon name=\"chevron-down\" size=\"xs\" color=\"primary\" />;\n };\n\n // Render actions for a row\n const renderActions = (row: T, actualIndex: number) => {\n if (!actions) return null;\n\n let rowActions: DataGridActionItem<T>[] | ReactNode;\n\n if (Array.isArray(actions)) {\n rowActions = actions;\n } else {\n const result = actions(row, actualIndex);\n if (Array.isArray(result)) {\n rowActions = result;\n } else {\n return <div data-interactive>{result}</div>;\n }\n }\n\n return (\n <Stack direction=\"horizontal\" spacing=\"sm\" data-interactive>\n {(rowActions as DataGridActionItem<T>[]).map((action, actionIndex) => {\n if (action && typeof action === 'object' && 'onClick' in action) {\n const actionConfig = action as DataGridAction<T>;\n const button = (\n <IconButton\n key={actionIndex}\n icon={actionConfig.icon}\n iconSize={actionConfig.iconSize || 'md'}\n buttonStyle=\"ghost\"\n variant={actionConfig.variant || 'neutral'}\n iconColor={actionConfig.iconColor}\n hoverIcon={actionConfig.hoverIcon}\n ariaLabel={actionConfig.label}\n onClick={() => actionConfig.onClick(row, actualIndex)}\n noPadding\n />\n );\n\n return actionConfig.tooltip ? (\n <Tooltip key={actionIndex} content={actionConfig.tooltip}>\n {button}\n </Tooltip>\n ) : (\n button\n );\n } else {\n return (\n <div key={actionIndex} data-interactive>\n {action as ReactNode}\n </div>\n );\n }\n })}\n </Stack>\n );\n };\n\n // Row padding classes\n const rowPadding = compact ? 'py-2 px-3' : 'py-3 px-4';\n\n // Build grid template columns for desktop layout\n const buildGridTemplateColumns = () => {\n const parts: string[] = [];\n\n // Selection checkbox column - fixed width for consistency across rows\n if (selectable) {\n parts.push('24px');\n }\n\n // Data columns\n visibleColumns.forEach((col) => {\n if (col.width) {\n // Explicit width (Tailwind class won't work in grid-template-columns)\n // Try to extract pixel value or use minmax\n const widthMatch = col.width.match(/(\\d+)px/);\n if (widthMatch) {\n parts.push(`${widthMatch[1]}px`);\n } else {\n parts.push('1fr');\n }\n } else if (col.minWidth && col.maxWidth) {\n // Both min and max - constrained range\n parts.push(`minmax(${col.minWidth}px, ${col.maxWidth}px)`);\n } else if (col.minWidth) {\n // Min only - can grow but not shrink below\n parts.push(`minmax(${col.minWidth}px, 1fr)`);\n } else if (col.maxWidth) {\n // Max only - can shrink but not grow beyond\n parts.push(`minmax(auto, ${col.maxWidth}px)`);\n } else {\n parts.push('1fr');\n }\n });\n\n // Actions column - dynamically sized based on max actions across all rows\n // Allows growing to max-content to accommodate multiple action buttons\n if (actions) {\n parts.push(`minmax(${actionsMinWidth}px, max-content)`);\n }\n\n return parts.join(' ');\n };\n\n const gridTemplateColumns = !isListMode ? buildGridTemplateColumns() : undefined;\n\n // Render a single row\n const renderRow = (row: T, rowIndex: number) => {\n const actualIndex = paginated ? (currentPage - 1) * pageSize + rowIndex : rowIndex;\n const isSelected = isRowSelected(actualIndex);\n const href = rowHref?.(row, actualIndex);\n const hasHref = Boolean(href);\n const hasOnRowClick = Boolean(onRowClick);\n const isClickable = hasHref || hasOnRowClick;\n\n // Row styling - add relative for Link overlay positioning\n const rowClasses = [\n 'relative',\n 'border-b border-border/50',\n striped && rowIndex % 2 === 1 ? 'bg-muted/30' : '',\n hoverable && isClickable ? 'hover:bg-muted/50 transition-colors' : '',\n isSelected ? 'bg-primary/5' : ''\n ]\n .filter(Boolean)\n .join(' ');\n\n // Grid mode: CSS Grid for consistent column widths\n // List mode: vertical flex (fallback) or custom renderListItem\n const layoutClasses = isListMode ? 'flex flex-col gap-3' : 'grid items-center gap-4';\n\n // Grid style for grid mode only\n const rowStyle = !isListMode && gridTemplateColumns ? { gridTemplateColumns } : undefined;\n\n // ----------------------------------------------------------------\n // List mode with custom render – delegate layout to renderListItem\n // ----------------------------------------------------------------\n if (isListMode && renderListItem) {\n const actionsContent = renderActions(row, actualIndex);\n const listItemContent = renderListItem(row, actualIndex, {\n actions: actionsContent,\n isSelected,\n onToggleSelect: selectable ? () => handleToggleRow(actualIndex) : undefined\n });\n\n // Pointer-events wrapper mirrors the grid row behaviour\n const pointerClass = hasHref\n ? 'pointer-events-none [&_a]:pointer-events-auto [&_button]:pointer-events-auto [&_input]:pointer-events-auto [&_select]:pointer-events-auto [&_textarea]:pointer-events-auto [&_label]:pointer-events-auto [&_[data-interactive]]:pointer-events-auto'\n : '';\n\n const listRowClickProps =\n !hasHref && hasOnRowClick\n ? {\n onClick: (e: React.MouseEvent<HTMLDivElement>) => {\n if (isInteractiveElement(e.target as HTMLElement, e.currentTarget)) return;\n onRowClick?.(row, actualIndex);\n },\n onKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onRowClick?.(row, actualIndex);\n }\n },\n role: 'button' as const,\n tabIndex: 0,\n className: 'cursor-pointer'\n }\n : {};\n\n return (\n <div\n key={actualIndex}\n className={`relative ${rowPadding} ${rowClasses} ${listRowClickProps.className || ''}`}\n onClick={listRowClickProps.onClick}\n onKeyDown={listRowClickProps.onKeyDown}\n role={listRowClickProps.role}\n tabIndex={listRowClickProps.tabIndex}\n >\n {hasHref && href && (\n <Link to={href} className=\"absolute inset-0 z-1\" aria-label=\"View details\" tabIndex={0} />\n )}\n <div className={pointerClass}>{listItemContent}</div>\n </div>\n );\n }\n\n // ----------------------------------------------------------------\n // Props for onRowClick (when no href) - handlers are on the row div\n // Uses isInteractiveElement check to avoid triggering on links/buttons\n const rowClickProps =\n !hasHref && hasOnRowClick\n ? {\n onClick: (e: React.MouseEvent<HTMLDivElement>) => {\n // Don't trigger if clicked on an interactive element (links, buttons, etc.)\n if (isInteractiveElement(e.target as HTMLElement, e.currentTarget)) {\n return;\n }\n onRowClick?.(row, actualIndex);\n },\n onKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onRowClick?.(row, actualIndex);\n }\n },\n role: 'button' as const,\n tabIndex: 0,\n className: 'cursor-pointer'\n }\n : {};\n\n return (\n <div\n key={actualIndex}\n className={`${layoutClasses} ${rowPadding} ${rowClasses} ${rowClickProps.className || ''}`}\n style={rowStyle}\n onClick={rowClickProps.onClick}\n onKeyDown={rowClickProps.onKeyDown}\n role={rowClickProps.role}\n tabIndex={rowClickProps.tabIndex}\n >\n {/* Row link overlay - positioned behind content */}\n {hasHref && href && (\n <Link to={href} className=\"absolute inset-0 z-1\" aria-label={`View details`} tabIndex={0} />\n )}\n\n {/* Selection checkbox - above link layer */}\n {selectable && (\n <div className={`relative z-10 ${isListMode ? '' : 'shrink-0'}`}>\n <Checkbox\n checked={isSelected}\n onChange={() => handleToggleRow(actualIndex)}\n ariaLabel={`Select row ${actualIndex + 1}`}\n />\n </div>\n )}\n\n {/* Data cells - pointer-events-none lets clicks pass through to link layer */}\n {/* Interactive elements inside (links, buttons) keep their default pointer-events */}\n {visibleColumns.map((column) => {\n const value = row[column.key];\n const content = renderCellContent(value, column, row, actualIndex);\n const showLabel = isListMode && column.showLabelOnMobile !== false;\n\n // Alignment\n const alignClass =\n column.align === 'center' ? 'text-center' : column.align === 'right' ? 'text-right' : 'text-left';\n\n // Only disable pointer events when we have a link overlay\n const pointerClass = hasHref\n ? 'pointer-events-none [&_a]:pointer-events-auto [&_button]:pointer-events-auto [&_input]:pointer-events-auto [&_select]:pointer-events-auto [&_textarea]:pointer-events-auto [&_label]:pointer-events-auto [&_[data-interactive]]:pointer-events-auto'\n : '';\n\n return (\n <div\n key={String(column.key)}\n className={`${alignClass} ${isListMode ? 'flex flex-col gap-0.5' : 'min-w-0 overflow-hidden'} ${pointerClass}`}\n >\n {showLabel && (\n <Text size=\"xs\" variant=\"muted\" className=\"uppercase tracking-wide\">\n {column.label}\n </Text>\n )}\n <div className={column.wrapText ? '' : 'truncate'}>{content}</div>\n </div>\n );\n })}\n\n {/* Actions - above link layer */}\n {actions && (\n <div className={`relative z-10 shrink-0 ${isListMode ? 'flex justify-end pt-1' : 'justify-self-end'}`}>\n {renderActions(row, actualIndex)}\n </div>\n )}\n </div>\n );\n };\n\n return (\n <div ref={containerRef} className={`overflow-hidden ${className}`}>\n {/* Header with title, search, actions */}\n {hasHeader && (\n <div className=\"mb-3\">\n {searchable ? (\n <div className=\"flex flex-col gap-3\">\n {title && <h2 className=\"text-lg font-semibold text-foreground\">{title}</h2>}\n <div className=\"flex flex-col sm:flex-row items-stretch sm:items-center gap-3 sm:justify-between\">\n <div className=\"flex-1 sm:max-w-md\">\n <InputGroup prefix={<Icon name=\"search\" size=\"sm\" />} className=\"w-full\">\n <Input\n type=\"text\"\n value={searchQuery}\n onChange={(e) => handleSearchChange(e.target.value)}\n placeholder={searchPlaceholder}\n />\n </InputGroup>\n </div>\n\n {Array.isArray(headerActions) && headerActions.length > 0 && (\n <div className=\"flex items-center gap-2 flex-wrap sm:flex-nowrap ml-auto\">\n {headerActions.map((act, idx) => (\n <Button\n key={idx}\n onClick={act.onClick}\n to={act.to}\n href={act.href}\n target={act.target}\n rel={act.rel}\n variant={act.variant}\n style={act.style}\n size={act.size}\n className={act.className}\n ariaLabel={act.ariaLabel || (!act.label && act.icon ? 'Action' : undefined)}\n >\n {act.icon ? <Icon name={act.icon} size=\"sm\" /> : null}\n {act.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n </div>\n ) : (\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3\">\n <div className=\"flex-1\">\n {title && <h2 className=\"text-lg font-semibold text-foreground\">{title}</h2>}\n </div>\n\n {Array.isArray(headerActions) && headerActions.length > 0 && (\n <div className=\"flex items-center gap-2 flex-wrap sm:flex-nowrap\">\n {headerActions.map((act, idx) => (\n <Button\n key={idx}\n onClick={act.onClick}\n to={act.to}\n href={act.href}\n target={act.target}\n rel={act.rel}\n variant={act.variant}\n style={act.style}\n size={act.size}\n className={act.className}\n ariaLabel={act.ariaLabel || (!act.label && act.icon ? 'Action' : undefined)}\n >\n {act.icon ? <Icon name={act.icon} size=\"sm\" /> : null}\n {act.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n )}\n\n {/* Empty states */}\n {data.length === 0 ? (\n <div className=\"border border-border rounded-lg\">\n <EmptyState\n title={emptyState.title}\n description={emptyState.description}\n buttonText={emptyState.buttonText}\n onButtonClick={emptyState.onButtonClick}\n buttonTo={emptyState.buttonTo}\n buttonHref={emptyState.buttonHref}\n buttonTarget={emptyState.buttonTarget}\n buttonRel={emptyState.buttonRel}\n />\n </div>\n ) : filteredData.length === 0 && searchQuery.trim() ? (\n <div className=\"border border-border rounded-lg\">\n <EmptyState\n title=\"No results found\"\n description={`No items match \"${searchQuery}\". Try adjusting your search.`}\n />\n </div>\n ) : (\n <>\n {/* Column headers – grid mode only (hidden in list mode) */}\n {!isListMode && (\n <div\n className={`grid items-center gap-4 ${rowPadding} border-b border-border bg-muted/30`}\n style={gridTemplateColumns ? { gridTemplateColumns } : undefined}\n >\n {selectable && (\n <div>\n <Checkbox checked={isAllSelected} onChange={handleToggleAll} ariaLabel=\"Select all rows\" />\n </div>\n )}\n\n {visibleColumns.map((column) => {\n const alignClass =\n column.align === 'center' ? 'text-center' : column.align === 'right' ? 'text-right' : 'text-left';\n\n return (\n <div key={String(column.key)} className={`min-w-0 ${alignClass}`}>\n {column.sortable !== false && sortable ? (\n <button\n onClick={() => handleSort(column.key)}\n className=\"flex items-center gap-1 hover:text-foreground transition-colors font-medium text-sm text-muted-foreground\"\n type=\"button\"\n >\n {column.label}\n {renderSortIcon(column.key)}\n </button>\n ) : (\n <Text size=\"sm\" variant=\"muted\" weight=\"medium\">\n {column.label}\n </Text>\n )}\n </div>\n );\n })}\n\n {actions && (\n <div className=\"justify-self-end\">\n <Text size=\"sm\" variant=\"muted\" weight=\"medium\">\n {actionsLabel}\n </Text>\n </div>\n )}\n </div>\n )}\n\n {/* Select all checkbox (list mode fallback only – renderListItem handles its own selection UI) */}\n {isListMode && !renderListItem && selectable && (\n <div className={`flex items-center gap-2 ${rowPadding} border-b border-border`}>\n <Checkbox checked={isAllSelected} onChange={handleToggleAll} ariaLabel=\"Select all rows\" />\n <Text size=\"sm\" variant=\"muted\">\n Select all\n </Text>\n </div>\n )}\n\n {/* Rows */}\n <div className=\"divide-y divide-border/50\">{displayData.map((row, idx) => renderRow(row, idx))}</div>\n\n {/* Pagination controls */}\n {paginated && totalPages > 1 && (\n <div className=\"flex items-center justify-between px-4 py-3 border-t border-border\">\n <div className=\"text-sm text-muted-foreground\">\n Page {currentPage} of {totalPages} ({filteredData.length} {searchQuery.trim() ? 'filtered' : 'total'}{' '}\n rows\n {searchQuery.trim() && data.length !== filteredData.length ? ` of ${data.length}` : ''})\n </div>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" style=\"outline\" onClick={prevPage} disabled={!canPrevPage}>\n Previous\n </Button>\n <Button size=\"sm\" style=\"outline\" onClick={nextPage} disabled={!canNextPage}>\n Next\n </Button>\n </div>\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n\nDataGrid.displayName = 'DataGrid';\n\nexport default DataGrid;\n"],"names":[],"mappings":"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"}
@@ -1,8 +1,18 @@
1
+ import { ButtonProps } from '../../forms/button/button';
1
2
  export type EmptyStateProps = {
2
3
  title?: string;
3
4
  description?: string;
4
5
  buttonText?: string;
6
+ /** Click handler for the action button. Used when navigation is handled externally. */
5
7
  onButtonClick?: () => void;
8
+ /** React Router path — renders the button as a <Link>. Use instead of onButtonClick for in-app navigation. */
9
+ buttonTo?: string;
10
+ /** Plain URL — renders the button as an <a> tag. Use for external links. */
11
+ buttonHref?: string;
12
+ /** Link target (e.g. "_blank") — only used with buttonTo or buttonHref */
13
+ buttonTarget?: ButtonProps['target'];
14
+ /** Rel attribute for the anchor (defaults to "noopener noreferrer" when buttonTarget="_blank") */
15
+ buttonRel?: string;
6
16
  };
7
- export default function EmptyState({ title, description, buttonText, onButtonClick }: EmptyStateProps): import("react/jsx-runtime").JSX.Element;
17
+ export default function EmptyState({ title, description, buttonText, onButtonClick, buttonTo, buttonHref, buttonTarget, buttonRel }: EmptyStateProps): import("react/jsx-runtime").JSX.Element;
8
18
  //# sourceMappingURL=empty-state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"empty-state.d.ts","sourceRoot":"","sources":["../../../../src/components/data-display/empty-state/empty-state.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,EAAE,eAAe,2CAoBpG"}
1
+ {"version":3,"file":"empty-state.d.ts","sourceRoot":"","sources":["../../../../src/components/data-display/empty-state/empty-state.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,8GAA8G;IAC9G,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACrC,kGAAkG;IAClG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EACjC,KAAK,EACL,WAAW,EACX,UAAU,EACV,aAAa,EACb,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,SAAS,EACV,EAAE,eAAe,2CA4BjB"}
@@ -2,13 +2,34 @@ import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import Stack from "../../layout/stack/stack.js";
3
3
  import Text from "../../typography/text/text.js";
4
4
  import Button from "../../forms/button/button.js";
5
- function EmptyState({ title, description, buttonText, onButtonClick }) {
5
+ function EmptyState({
6
+ title,
7
+ description,
8
+ buttonText,
9
+ onButtonClick,
10
+ buttonTo,
11
+ buttonHref,
12
+ buttonTarget,
13
+ buttonRel
14
+ }) {
15
+ const showButton = buttonText && (onButtonClick || buttonTo || buttonHref);
6
16
  return /* @__PURE__ */ jsxs(Stack, { direction: "vertical", spacing: "md", align: "center", className: "p-8", children: [
7
17
  /* @__PURE__ */ jsxs(Stack, { direction: "vertical", spacing: "sm", align: "center", children: [
8
18
  /* @__PURE__ */ jsx(Text, { size: "lg", weight: "bold", children: title }),
9
19
  description && /* @__PURE__ */ jsx(Text, { variant: "body", size: "base", className: "text-center max-w-md", children: description })
10
20
  ] }),
11
- buttonText && onButtonClick && /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: onButtonClick, children: buttonText })
21
+ showButton && /* @__PURE__ */ jsx(
22
+ Button,
23
+ {
24
+ variant: "primary",
25
+ onClick: onButtonClick,
26
+ to: buttonTo,
27
+ href: buttonHref,
28
+ target: buttonTarget,
29
+ rel: buttonRel,
30
+ children: buttonText
31
+ }
32
+ )
12
33
  ] });
13
34
  }
14
35
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"empty-state.js","sources":["../../../../src/components/data-display/empty-state/empty-state.tsx"],"sourcesContent":["import { Button, Stack, Text } from '@components';\n\nexport type EmptyStateProps = {\n title?: string;\n description?: string;\n buttonText?: string;\n onButtonClick?: () => void;\n};\n\nexport default function EmptyState({ title, description, buttonText, onButtonClick }: EmptyStateProps) {\n return (\n <Stack direction=\"vertical\" spacing=\"md\" align=\"center\" className=\"p-8\">\n <Stack direction=\"vertical\" spacing=\"sm\" align=\"center\">\n <Text size=\"lg\" weight=\"bold\">\n {title}\n </Text>\n {description && (\n <Text variant=\"body\" size=\"base\" className=\"text-center max-w-md\">\n {description}\n </Text>\n )}\n </Stack>\n {buttonText && onButtonClick && (\n <Button variant=\"primary\" onClick={onButtonClick}>\n {buttonText}\n </Button>\n )}\n </Stack>\n );\n}\n"],"names":[],"mappings":";;;;AASA,SAAwB,WAAW,EAAE,OAAO,aAAa,YAAY,iBAAkC;AACrG,SACE,qBAAC,SAAM,WAAU,YAAW,SAAQ,MAAK,OAAM,UAAS,WAAU,OAChE,UAAA;AAAA,IAAA,qBAAC,SAAM,WAAU,YAAW,SAAQ,MAAK,OAAM,UAC7C,UAAA;AAAA,MAAA,oBAAC,MAAA,EAAK,MAAK,MAAK,QAAO,QACpB,UAAA,OACH;AAAA,MACC,mCACE,MAAA,EAAK,SAAQ,QAAO,MAAK,QAAO,WAAU,wBACxC,UAAA,YAAA,CACH;AAAA,IAAA,GAEJ;AAAA,IACC,cAAc,iBACb,oBAAC,QAAA,EAAO,SAAQ,WAAU,SAAS,eAChC,UAAA,WAAA,CACH;AAAA,EAAA,GAEJ;AAEJ;"}
1
+ {"version":3,"file":"empty-state.js","sources":["../../../../src/components/data-display/empty-state/empty-state.tsx"],"sourcesContent":["import { Button, Stack, Text } from '@components';\nimport type { ButtonProps } from '../../forms/button/button';\n\nexport type EmptyStateProps = {\n title?: string;\n description?: string;\n buttonText?: string;\n /** Click handler for the action button. Used when navigation is handled externally. */\n onButtonClick?: () => void;\n /** React Router path — renders the button as a <Link>. Use instead of onButtonClick for in-app navigation. */\n buttonTo?: string;\n /** Plain URL — renders the button as an <a> tag. Use for external links. */\n buttonHref?: string;\n /** Link target (e.g. \"_blank\") — only used with buttonTo or buttonHref */\n buttonTarget?: ButtonProps['target'];\n /** Rel attribute for the anchor (defaults to \"noopener noreferrer\" when buttonTarget=\"_blank\") */\n buttonRel?: string;\n};\n\nexport default function EmptyState({\n title,\n description,\n buttonText,\n onButtonClick,\n buttonTo,\n buttonHref,\n buttonTarget,\n buttonRel\n}: EmptyStateProps) {\n const showButton = buttonText && (onButtonClick || buttonTo || buttonHref);\n return (\n <Stack direction=\"vertical\" spacing=\"md\" align=\"center\" className=\"p-8\">\n <Stack direction=\"vertical\" spacing=\"sm\" align=\"center\">\n <Text size=\"lg\" weight=\"bold\">\n {title}\n </Text>\n {description && (\n <Text variant=\"body\" size=\"base\" className=\"text-center max-w-md\">\n {description}\n </Text>\n )}\n </Stack>\n {showButton && (\n <Button\n variant=\"primary\"\n onClick={onButtonClick}\n to={buttonTo}\n href={buttonHref}\n target={buttonTarget}\n rel={buttonRel}\n >\n {buttonText}\n </Button>\n )}\n </Stack>\n );\n}\n"],"names":[],"mappings":";;;;AAmBA,SAAwB,WAAW;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoB;AAClB,QAAM,aAAa,eAAe,iBAAiB,YAAY;AAC/D,SACE,qBAAC,SAAM,WAAU,YAAW,SAAQ,MAAK,OAAM,UAAS,WAAU,OAChE,UAAA;AAAA,IAAA,qBAAC,SAAM,WAAU,YAAW,SAAQ,MAAK,OAAM,UAC7C,UAAA;AAAA,MAAA,oBAAC,MAAA,EAAK,MAAK,MAAK,QAAO,QACpB,UAAA,OACH;AAAA,MACC,mCACE,MAAA,EAAK,SAAQ,QAAO,MAAK,QAAO,WAAU,wBACxC,UAAA,YAAA,CACH;AAAA,IAAA,GAEJ;AAAA,IACC,cACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,SAAS;AAAA,QACT,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,KAAK;AAAA,QAEJ,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GAEJ;AAEJ;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyddenlabs/hydn-ui",
3
- "version": "0.3.11",
3
+ "version": "0.3.12",
4
4
  "private": false,
5
5
  "description": "A modern React component library built with TypeScript and Tailwind CSS",
6
6
  "main": "./dist/index.js",