flikkui 0.2.0-beta.4 → 0.2.0-beta.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.
Files changed (59) hide show
  1. package/README.md +92 -0
  2. package/dist/components/core/Table/Table.animations.d.ts +5 -16
  3. package/dist/components/core/Table/Table.animations.js +46 -0
  4. package/dist/components/core/Table/Table.d.ts +0 -27
  5. package/dist/components/core/Table/Table.js +58 -156
  6. package/dist/components/core/Table/Table.theme.js +28 -19
  7. package/dist/components/core/Table/Table.types.d.ts +95 -8
  8. package/dist/components/core/Table/Table.utils.d.ts +7 -0
  9. package/dist/components/core/Table/Table.utils.js +11 -1
  10. package/dist/components/core/Table/{components/TableActions/TableActions.d.ts → TableActions.d.ts} +3 -3
  11. package/dist/components/core/Table/{components/TableActions/TableActions.js → TableActions.js} +14 -24
  12. package/dist/components/core/Table/{components/TableActions/TableActionsMenu.d.ts → TableActionsMenu.d.ts} +1 -1
  13. package/dist/components/core/Table/{components/TableActions/TableActionsMenu.js → TableActionsMenu.js} +4 -4
  14. package/dist/components/core/Table/{components/core/TableBody.d.ts → TableBody.d.ts} +1 -1
  15. package/dist/components/core/Table/{components/core/TableBody.js → TableBody.js} +14 -20
  16. package/dist/components/core/Table/{components/core/TableCell.d.ts → TableCell.d.ts} +1 -9
  17. package/dist/components/core/Table/{components/core/TableCell.js → TableCell.js} +5 -13
  18. package/dist/components/core/Table/TableColumnManager.d.ts +3 -0
  19. package/dist/components/core/Table/TableColumnManager.js +34 -0
  20. package/dist/components/core/Table/{components/DeclarativeComponents.d.ts → TableDeclarative.d.ts} +1 -1
  21. package/dist/components/core/Table/{components/DeclarativeComponents.js → TableDeclarative.js} +6 -56
  22. package/dist/components/core/Table/TableFilter.d.ts +3 -0
  23. package/dist/components/core/Table/TableFilter.js +122 -0
  24. package/dist/components/core/Table/{components/core/TableHeader.d.ts → TableHeader.d.ts} +1 -1
  25. package/dist/components/core/Table/{components/core/TableHeader.js → TableHeader.js} +15 -29
  26. package/dist/components/core/Table/TablePagination.d.ts +7 -0
  27. package/dist/components/core/Table/{components/TablePagination/TablePagination.js → TablePagination.js} +5 -16
  28. package/dist/components/core/Table/TableRow.d.ts +8 -0
  29. package/dist/components/core/Table/TableRow.js +45 -0
  30. package/dist/components/core/Table/TableSelectionHeader.d.ts +7 -0
  31. package/dist/components/core/Table/{components/TableSelectionHeader/TableSelectionHeader.js → TableSelectionHeader.js} +4 -5
  32. package/dist/components/core/Table/hooks/index.d.ts +10 -0
  33. package/dist/components/core/Table/hooks/useTableColumns.d.ts +16 -0
  34. package/dist/components/core/Table/hooks/useTableColumns.js +67 -0
  35. package/dist/components/core/Table/hooks/useTableExpansion.d.ts +8 -0
  36. package/dist/components/core/Table/hooks/useTableExpansion.js +15 -0
  37. package/dist/components/core/Table/hooks/useTableFilter.d.ts +12 -0
  38. package/dist/components/core/Table/hooks/useTableFilter.js +37 -0
  39. package/dist/components/core/Table/hooks/useTablePagination.d.ts +12 -0
  40. package/dist/components/core/Table/hooks/useTablePagination.js +13 -0
  41. package/dist/components/core/Table/hooks/useTableSelection.d.ts +17 -0
  42. package/dist/components/core/Table/hooks/useTableSelection.js +40 -0
  43. package/dist/components/core/Table/index.d.ts +9 -8
  44. package/dist/components/core/Table/index.js +7 -5
  45. package/dist/components/core/index.js +9 -3
  46. package/dist/index.js +9 -3
  47. package/dist/styles.css +1 -1
  48. package/package.json +1 -1
  49. package/dist/components/core/Table/components/TableActions/TableActions.types.d.ts +0 -40
  50. package/dist/components/core/Table/components/TableActions/index.d.ts +0 -3
  51. package/dist/components/core/Table/components/TableActionsMenu.d.ts +0 -6
  52. package/dist/components/core/Table/components/TablePagination/TablePagination.d.ts +0 -17
  53. package/dist/components/core/Table/components/TablePagination/TablePagination.types.d.ts +0 -21
  54. package/dist/components/core/Table/components/TablePagination/index.d.ts +0 -2
  55. package/dist/components/core/Table/components/TableSelectionHeader/TableSelectionHeader.d.ts +0 -15
  56. package/dist/components/core/Table/components/TableSelectionHeader/index.d.ts +0 -3
  57. package/dist/components/core/Table/components/core/TableRow.d.ts +0 -3
  58. package/dist/components/core/Table/components/core/TableRow.js +0 -44
  59. package/dist/components/core/Table/components/core/index.d.ts +0 -4
@@ -22,6 +22,15 @@ export type TableVariant = 'default' | 'striped' | 'bordered' | 'compact';
22
22
  export type TableAlignment = 'left' | 'center' | 'right';
23
23
  /** Selection control types for row selection */
24
24
  export type SelectionType = 'checkbox' | 'radio';
25
+ /** Filter operator types for column filtering */
26
+ export type FilterOperator = 'equals' | 'contains' | 'startsWith' | 'endsWith' | 'greaterThan' | 'lessThan';
27
+ /** Filter type for column filter UI */
28
+ export type FilterType = 'text' | 'select' | 'number';
29
+ /** Option for select-type filter columns */
30
+ export interface FilterOption {
31
+ label: string;
32
+ value: string;
33
+ }
25
34
  /**
26
35
  * Column definition for table data display and behavior
27
36
  */
@@ -38,6 +47,10 @@ export interface Column<T = any> {
38
47
  sortable?: boolean;
39
48
  /** Enable filtering for this column */
40
49
  filterable?: boolean;
50
+ /** Type of filter UI to display */
51
+ filterType?: FilterType;
52
+ /** Options for select-type filter columns */
53
+ filterOptions?: FilterOption[];
41
54
  /** Truncate long content with ellipsis */
42
55
  ellipsis?: boolean;
43
56
  /** Show tooltip on hover - boolean or function returning tooltip text */
@@ -70,6 +83,8 @@ export interface FilterConfig {
70
83
  columnId: string;
71
84
  /** Filter value - type depends on column data type */
72
85
  value: any;
86
+ /** Filter operator for comparison */
87
+ operator?: FilterOperator;
73
88
  }
74
89
  export interface TableThemeOverrides {
75
90
  baseStyle?: string;
@@ -120,13 +135,6 @@ export interface TableProps<T = any> {
120
135
  /**
121
136
  * Property name or function to extract stable row identifiers for React keys and selection.
122
137
  * Provides consistent component identity during row reordering or updates.
123
- *
124
- * @example
125
- * // Using a property name
126
- * rowKey="id"
127
- *
128
- * // Using a function for complex keys
129
- * rowKey={(row, index) => `${row.category}-${row.id}`}
130
138
  */
131
139
  rowKey?: keyof T | ((row: T, index: number) => string | number);
132
140
  /** Visual variant for different table styles */
@@ -228,7 +236,6 @@ export interface InternalTableHeaderProps<T> {
228
236
  export interface InternalTableBodyProps<T> {
229
237
  data: T[];
230
238
  columns: Column<T>[];
231
- /** Row key extractor for stable row identification */
232
239
  rowKey?: keyof T | ((row: T, index: number) => string | number);
233
240
  expandedRowRender?: (row: T) => ReactNode;
234
241
  expandedRows?: string[];
@@ -266,3 +273,83 @@ export interface InternalTableCellProps<T> {
266
273
  theme?: TableThemeOverrides;
267
274
  children?: ReactNode;
268
275
  }
276
+ export type ActionVariant = 'default' | 'danger';
277
+ export type ActionPriority = 'high' | 'normal';
278
+ export interface ActionItem<T = any> {
279
+ /** Unique identifier for the action */
280
+ id: string;
281
+ /** Display label for the action */
282
+ label: string;
283
+ /** Icon component to display */
284
+ icon: React.ComponentType<{
285
+ className?: string;
286
+ }>;
287
+ /** Click handler that receives the row data */
288
+ onClick: (row: T) => void;
289
+ /** Visual variant for styling (default: 'default') */
290
+ variant?: ActionVariant;
291
+ /** Priority level for display ordering (default: 'normal') */
292
+ priority?: ActionPriority;
293
+ /** Function to determine if action should be disabled */
294
+ disabled?: (row: T) => boolean;
295
+ }
296
+ export interface TableActionsProps<T = any> {
297
+ /** Array of action items to display */
298
+ actions: ActionItem<T>[];
299
+ /** Row data to pass to action handlers */
300
+ row: T;
301
+ /** Maximum number of actions to show inline before using menu (default: 2) */
302
+ maxVisibleActions?: number;
303
+ /** Additional CSS class name */
304
+ className?: string;
305
+ }
306
+ export interface TableActionsMenuProps<T = any> {
307
+ /** Array of action items to display in menu */
308
+ actions: ActionItem<T>[];
309
+ /** Row data to pass to action handlers */
310
+ row: T;
311
+ /** Function to close the menu */
312
+ onClose: () => void;
313
+ /** Additional CSS class name */
314
+ className?: string;
315
+ }
316
+ export interface TablePaginationProps {
317
+ /** Current active page number (1-based) */
318
+ currentPage: number;
319
+ /** Total number of items across all pages */
320
+ totalItems: number;
321
+ /** Number of items per page */
322
+ pageSize: number;
323
+ /** Available page size options */
324
+ pageSizeOptions?: number[];
325
+ /** Callback when page changes */
326
+ onPageChange: (page: number) => void;
327
+ /** Callback when page size changes */
328
+ onPageSizeChange: (pageSize: number) => void;
329
+ /** Whether to show the page size selector */
330
+ showPageSizeSelector?: boolean;
331
+ /** Additional CSS classes */
332
+ className?: string;
333
+ }
334
+ export interface TableSelectionHeaderProps {
335
+ selectedCount: number;
336
+ totalCount: number;
337
+ selectedRows: string[];
338
+ bulkActions?: BulkAction[];
339
+ onClearSelection: () => void;
340
+ className?: string;
341
+ }
342
+ export interface TableColumnManagerProps<T = any> {
343
+ columns: Column<T>[];
344
+ visibleColumns: string[];
345
+ columnOrder: string[];
346
+ onToggleColumn: (columnId: string) => void;
347
+ onResetToDefault: () => void;
348
+ onColumnReorder?: (fromIndex: number, toIndex: number) => void;
349
+ }
350
+ export interface TableFilterProps<T = any> {
351
+ columns: Column<T>[];
352
+ filterConfig: FilterConfig[];
353
+ onFilterChange: (filterConfig: FilterConfig[]) => void;
354
+ className?: string;
355
+ }
@@ -1,3 +1,10 @@
1
+ import { TableAlignment } from './Table.types';
2
+ /** Constant for the utility column ID used in selection/expansion columns */
3
+ export declare const UTILITY_COLUMN_ID = "utility";
4
+ /** Width value for the utility column (1px + nowrap = shrink-to-content) */
5
+ export declare const UTILITY_COLUMN_WIDTH = 1;
6
+ /** Tailwind JIT-safe alignment class mapping */
7
+ export declare const alignmentClasses: Record<TableAlignment, string>;
1
8
  /**
2
9
  * Generate a stable row identifier for React keys and row IDs
3
10
  * @param row - The data row object
@@ -1,3 +1,13 @@
1
+ /** Constant for the utility column ID used in selection/expansion columns */
2
+ const UTILITY_COLUMN_ID = 'utility';
3
+ /** Width value for the utility column (1px + nowrap = shrink-to-content) */
4
+ const UTILITY_COLUMN_WIDTH = 1;
5
+ /** Tailwind JIT-safe alignment class mapping */
6
+ const alignmentClasses = {
7
+ left: 'text-left',
8
+ center: 'text-center',
9
+ right: 'text-right',
10
+ };
1
11
  /**
2
12
  * Generate a stable row identifier for React keys and row IDs
3
13
  * @param row - The data row object
@@ -27,4 +37,4 @@ function getRowId(row, index, rowKey) {
27
37
  return `row-${key}`;
28
38
  }
29
39
 
30
- export { getRowId };
40
+ export { UTILITY_COLUMN_ID, UTILITY_COLUMN_WIDTH, alignmentClasses, getRowId };
@@ -1,8 +1,8 @@
1
1
  import React from "react";
2
- import { TableActionsProps } from "./TableActions.types";
2
+ import { TableActionsProps } from "./Table.types";
3
3
  /**
4
4
  * TableActions component with smart display logic
5
- * - 2 actions: Show as individual icon buttons
6
- * - 3 actions: Show all actions in overflow menu using Dropdown
5
+ * - <=2 actions: Show as individual icon buttons
6
+ * - >=3 actions: Show all actions in overflow menu using Dropdown
7
7
  */
8
8
  export declare const TableActions: <T>({ actions, row, maxVisibleActions, className, }: TableActionsProps<T>) => React.JSX.Element;
@@ -1,21 +1,20 @@
1
1
  import React__default, { useMemo } from 'react';
2
2
  import { EllipsisVerticalIcon } from '@heroicons/react/24/outline';
3
- import { cn } from '../../../../../utils/cn.js';
4
- import { Dropdown } from '../../../Dropdown/Dropdown.js';
5
- import '../../../Dropdown/DropdownTrigger.js';
6
- import '../../../Dropdown/DropdownMenu.js';
7
- import '../../../Dropdown/DropdownItem.js';
8
- import '../../../Dropdown/DropdownSection.js';
9
- import '../../../Dropdown/DropdownSeparator.js';
10
- import { Button } from '../../../Button/Button.js';
3
+ import { cn } from '../../../utils/cn.js';
4
+ import { Dropdown } from '../Dropdown/Dropdown.js';
5
+ import '../Dropdown/DropdownTrigger.js';
6
+ import '../Dropdown/DropdownMenu.js';
7
+ import '../Dropdown/DropdownItem.js';
8
+ import '../Dropdown/DropdownSection.js';
9
+ import '../Dropdown/DropdownSeparator.js';
10
+ import { Button } from '../Button/Button.js';
11
11
 
12
12
  /**
13
13
  * TableActions component with smart display logic
14
- * - 2 actions: Show as individual icon buttons
15
- * - 3 actions: Show all actions in overflow menu using Dropdown
14
+ * - <=2 actions: Show as individual icon buttons
15
+ * - >=3 actions: Show all actions in overflow menu using Dropdown
16
16
  */
17
17
  const TableActions = ({ actions, row, maxVisibleActions = 2, className, }) => {
18
- // Sort actions by priority (high priority first)
19
18
  const sortedActions = useMemo(() => {
20
19
  return [...actions].sort((a, b) => {
21
20
  const priorityOrder = { high: 0, normal: 1 };
@@ -24,15 +23,12 @@ const TableActions = ({ actions, row, maxVisibleActions = 2, className, }) => {
24
23
  return aPriority - bPriority;
25
24
  });
26
25
  }, [actions]);
27
- // Determine display strategy
28
26
  const shouldUseMenu = actions.length > maxVisibleActions;
29
- // Get disabled keys for Dropdown
30
27
  const disabledKeys = useMemo(() => {
31
28
  return sortedActions
32
29
  .filter((action) => { var _a; return (_a = action.disabled) === null || _a === void 0 ? void 0 : _a.call(action, row); })
33
30
  .map((action) => action.id);
34
31
  }, [sortedActions, row]);
35
- // Handle action click from Dropdown
36
32
  const handleAction = (key) => {
37
33
  var _a;
38
34
  const action = sortedActions.find((a) => a.id === key);
@@ -40,34 +36,28 @@ const TableActions = ({ actions, row, maxVisibleActions = 2, className, }) => {
40
36
  action.onClick(row);
41
37
  }
42
38
  };
43
- // Render individual action buttons
44
39
  const renderInlineActions = (actionsToRender) => {
45
40
  return actionsToRender.map((action) => {
46
41
  var _a;
47
42
  const isDisabled = (_a = action.disabled) === null || _a === void 0 ? void 0 : _a.call(action, row);
48
43
  const Icon = action.icon;
49
44
  return (React__default.createElement(Button, { key: action.id, color: "primary", variant: "link", iconOnly: true, onClick: () => action.onClick(row), disabled: isDisabled, "aria-label": action.label, className: cn(action.variant === "danger"
50
- ? "text-red-400 hover:text-red-600 dark:text-red-400 dark:hover:text-red-300"
51
- : "text-neutral-400 hover:text-neutral-700 dark:text-neutral-500 dark:hover:text-neutral-300") },
45
+ ? "text-[var(--color-danger-400)] hover:text-[var(--color-danger)] dark:text-[var(--color-danger-400)] dark:hover:text-[var(--color-danger-300)]"
46
+ : "text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] dark:text-[var(--color-text-muted)] dark:hover:text-[var(--color-text-secondary)]") },
52
47
  React__default.createElement(Icon, { className: "size-4" })));
53
48
  });
54
49
  };
55
- // Render overflow menu using Dropdown
56
50
  const renderOverflowMenu = () => {
57
51
  return (React__default.createElement(Dropdown, { placement: "bottom-end", offset: 4, disabledKeys: disabledKeys, onAction: handleAction },
58
52
  React__default.createElement(Dropdown.Trigger, null,
59
- React__default.createElement(Button, { color: "neutral", variant: "filled", size: "sm", iconOnly: true, "aria-label": "More actions", className: "text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)]" },
53
+ React__default.createElement(Button, { color: "neutral", variant: "outline", size: "sm", iconOnly: true, "aria-label": "More actions", className: "text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)]" },
60
54
  React__default.createElement(EllipsisVerticalIcon, { className: "size-4" }))),
61
55
  React__default.createElement(Dropdown.Menu, { "aria-label": "Row actions" }, sortedActions.map((action) => {
62
56
  const Icon = action.icon;
63
57
  return (React__default.createElement(Dropdown.Item, { key: action.id, itemKey: action.id, isDanger: action.variant === "danger", startContent: React__default.createElement(Icon, { className: "size-4" }) }, action.label));
64
58
  }))));
65
59
  };
66
- return (React__default.createElement("div", { className: cn("flex items-center justify-end", className) }, shouldUseMenu
67
- ? // All actions in overflow menu
68
- renderOverflowMenu()
69
- : // Show actions inline
70
- renderInlineActions(sortedActions)));
60
+ return (React__default.createElement("div", { className: cn("flex items-center justify-end", className) }, shouldUseMenu ? renderOverflowMenu() : renderInlineActions(sortedActions)));
71
61
  };
72
62
 
73
63
  export { TableActions };
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { TableActionsMenuProps } from './TableActions.types';
2
+ import { TableActionsMenuProps } from './Table.types';
3
3
  /**
4
4
  * TableActionsMenu component for displaying actions in an overflow menu
5
5
  */
@@ -1,5 +1,5 @@
1
1
  import React__default from 'react';
2
- import { cn } from '../../../../../utils/cn.js';
2
+ import { cn } from '../../../utils/cn.js';
3
3
 
4
4
  /**
5
5
  * TableActionsMenu component for displaying actions in an overflow menu
@@ -12,12 +12,12 @@ const TableActionsMenu = ({ actions, row, onClose, className, }) => {
12
12
  action.onClick(row);
13
13
  onClose();
14
14
  };
15
- return (React__default.createElement("div", { className: cn(" min-w-[180px] p-1", className), role: "menu", "aria-label": "Row actions" }, actions.map((action, index) => {
15
+ return (React__default.createElement("div", { className: cn("min-w-[180px] p-1", className), role: "menu", "aria-label": "Row actions" }, actions.map((action) => {
16
16
  var _a;
17
17
  const isDisabled = (_a = action.disabled) === null || _a === void 0 ? void 0 : _a.call(action, row);
18
18
  const Icon = action.icon;
19
- return (React__default.createElement("button", { key: action.id, onClick: () => handleActionClick(action), disabled: isDisabled, className: cn("w-full flex items-center gap-3 px-3 py-2 text-sm font-medium text-left transition-all duration-300", "hover:bg-neutral-100 focus:bg-neutral-100 focus:outline-none rounded-sm cursor-pointer", action.variant === 'danger'
20
- ? "text-danger-600 hover:bg-danger-50 focus:bg-danger-50"
19
+ return (React__default.createElement("button", { key: action.id, onClick: () => handleActionClick(action), disabled: isDisabled, className: cn("w-full flex items-center gap-3 px-3 py-2 text-sm font-medium text-left transition-all duration-300", "hover:bg-[var(--color-background-secondary)] focus:bg-[var(--color-background-secondary)] focus:outline-none rounded-sm cursor-pointer", action.variant === 'danger'
20
+ ? "text-[var(--color-danger)] hover:bg-[var(--color-danger-50)] focus:bg-[var(--color-danger-50)]"
21
21
  : "text-[var(--color-text-primary)]", isDisabled && "opacity-50 cursor-not-allowed hover:bg-transparent"), role: "menuitem", "aria-label": action.label },
22
22
  React__default.createElement(Icon, { className: "size-4 flex-shrink-0" }),
23
23
  React__default.createElement("span", null, action.label)));
@@ -1,3 +1,3 @@
1
1
  import React from 'react';
2
- import { InternalTableBodyProps } from '../../Table.types';
2
+ import { InternalTableBodyProps } from './Table.types';
3
3
  export declare const TableBody: <T extends Record<string, any>>(props: InternalTableBodyProps<T>) => React.ReactElement;
@@ -1,32 +1,26 @@
1
1
  import React__default from 'react';
2
2
  import { TableRow } from './TableRow.js';
3
- import { getRowId } from '../../Table.utils.js';
3
+ import { getRowId } from './Table.utils.js';
4
+ import { useTableExpansion } from './hooks/useTableExpansion.js';
5
+ import { useTableSelection } from './hooks/useTableSelection.js';
4
6
 
5
7
  function TableBodyComponent({ data, columns, rowKey, expandedRowRender, expandedRows = [], onExpandedRowsChange, selectable, selectionType, selectedRows = [], onSelectionChange, freezeFirstColumn, freezeLastColumn, theme, }) {
6
- const handleExpandChange = (rowId, expanded) => {
7
- if (!onExpandedRowsChange)
8
- return;
9
- const newExpandedRows = expanded
10
- ? [...expandedRows, rowId]
11
- : expandedRows.filter(id => id !== rowId);
12
- onExpandedRowsChange(newExpandedRows);
13
- };
14
- const handleSelectionChange = (rowId, selected) => {
15
- if (!onSelectionChange)
16
- return;
17
- const newSelectedRows = selectionType === 'checkbox'
18
- ? selected
19
- ? [...selectedRows, rowId]
20
- : selectedRows.filter(id => id !== rowId)
21
- : selected ? [rowId] : [];
22
- onSelectionChange(newSelectedRows);
23
- };
8
+ const { handleExpandChange } = useTableExpansion({
9
+ expandedRows,
10
+ onExpandedRowsChange,
11
+ });
12
+ const { handleSelectionChange } = useTableSelection({
13
+ data,
14
+ rowKey,
15
+ selectionType,
16
+ selectedRows,
17
+ onSelectionChange,
18
+ });
24
19
  return (React__default.createElement("tbody", null, data.map((row, index) => {
25
20
  const rowId = getRowId(row, index, rowKey);
26
21
  return (React__default.createElement(TableRow, { key: rowId, row: row, rowId: rowId, columns: columns, expandedRowRender: expandedRowRender, isExpanded: expandedRows.includes(rowId), onExpandChange: (expanded) => handleExpandChange(rowId, expanded), selectable: selectable, selectionType: selectionType, isSelected: selectedRows.includes(rowId), onSelectionChange: (selected) => handleSelectionChange(rowId, selected), freezeFirstColumn: freezeFirstColumn, freezeLastColumn: freezeLastColumn, theme: theme }));
27
22
  })));
28
23
  }
29
- // Export with proper type annotation
30
24
  const TableBody = TableBodyComponent;
31
25
 
32
26
  export { TableBody };
@@ -1,17 +1,9 @@
1
1
  import React from 'react';
2
- import { InternalTableCellProps } from '../../Table.types';
2
+ import { InternalTableCellProps } from './Table.types';
3
3
  /**
4
4
  * Internal TableCell component used by the data-driven API
5
5
  * Handles both header and data cells with proper theming and accessibility
6
6
  *
7
- * Features:
8
- * - Dynamic cell type (th/td) based on isHeader prop
9
- * - Frozen column support with visual indicators
10
- * - Custom cell rendering via column.cell function
11
- * - Tooltip support for truncated content
12
- * - Alignment and width customization
13
- * - Full accessibility with proper ARIA attributes
14
- *
15
7
  * @internal This component is used internally by the Table component
16
8
  */
17
9
  declare function TableCellComponent<T extends Record<string, any>>({ column, row, rowId, isHeader, isFrozen, isLastFrozen, theme, children, }: InternalTableCellProps<T>): React.ReactElement;
@@ -1,25 +1,19 @@
1
1
  import React__default from 'react';
2
- import { cn } from '../../../../../utils/cn.js';
2
+ import { cn } from '../../../utils/cn.js';
3
+ import { UTILITY_COLUMN_ID, alignmentClasses } from './Table.utils.js';
3
4
 
4
5
  /**
5
6
  * Internal TableCell component used by the data-driven API
6
7
  * Handles both header and data cells with proper theming and accessibility
7
8
  *
8
- * Features:
9
- * - Dynamic cell type (th/td) based on isHeader prop
10
- * - Frozen column support with visual indicators
11
- * - Custom cell rendering via column.cell function
12
- * - Tooltip support for truncated content
13
- * - Alignment and width customization
14
- * - Full accessibility with proper ARIA attributes
15
- *
16
9
  * @internal This component is used internally by the Table component
17
10
  */
18
11
  function TableCellComponent({ column, row, rowId, isHeader = false, isFrozen = false, isLastFrozen = false, theme, children, }) {
19
12
  const Cell = isHeader ? 'th' : 'td';
13
+ const isUtilityColumn = column.id === UTILITY_COLUMN_ID;
20
14
  // For header cells, render the column header content
21
15
  if (isHeader) {
22
- const cellClasses = cn(theme === null || theme === void 0 ? void 0 : theme.headerStyle, isFrozen && (theme === null || theme === void 0 ? void 0 : theme.frozenColumnStyle), isLastFrozen && (theme === null || theme === void 0 ? void 0 : theme.lastFrozenColumnStyle), column.align && `text-${column.align}`);
16
+ const cellClasses = cn(theme === null || theme === void 0 ? void 0 : theme.headerStyle, isFrozen && (theme === null || theme === void 0 ? void 0 : theme.frozenColumnStyle), isLastFrozen && (theme === null || theme === void 0 ? void 0 : theme.lastFrozenColumnStyle), column.align && alignmentClasses[column.align], isUtilityColumn && 'whitespace-nowrap');
23
17
  return (React__default.createElement(Cell, { className: cellClasses, "data-frozen": isFrozen ? 'true' : isLastFrozen ? 'last' : undefined, style: { width: column.width }, role: "columnheader", "aria-label": typeof column.header === 'string' ? column.header : column.id }, children || column.header));
24
18
  }
25
19
  // For data cells, extract value using accessor (string key or function)
@@ -34,12 +28,10 @@ function TableCellComponent({ column, row, rowId, isHeader = false, isFrozen = f
34
28
  : column.tooltip
35
29
  ? String(value)
36
30
  : undefined;
37
- const cellClasses = cn(theme === null || theme === void 0 ? void 0 : theme.cellStyle, isFrozen && (theme === null || theme === void 0 ? void 0 : theme.frozenColumnStyle), isLastFrozen && (theme === null || theme === void 0 ? void 0 : theme.lastFrozenColumnStyle), column.align && `text-${column.align}`, column.ellipsis && 'truncate');
31
+ const cellClasses = cn(theme === null || theme === void 0 ? void 0 : theme.cellStyle, isFrozen && (theme === null || theme === void 0 ? void 0 : theme.frozenColumnStyle), isLastFrozen && (theme === null || theme === void 0 ? void 0 : theme.lastFrozenColumnStyle), column.align && alignmentClasses[column.align], column.ellipsis && 'truncate', isUtilityColumn && 'whitespace-nowrap');
38
32
  return (React__default.createElement(Cell, { className: cellClasses, "data-frozen": isFrozen ? 'true' : isLastFrozen ? 'last' : undefined, style: { width: column.width }, title: tooltipContent, role: "cell" }, children || content));
39
33
  }
40
- // Set display name for dev tools
41
34
  TableCellComponent.displayName = 'TableCell';
42
- // Memoize component to prevent unnecessary re-renders when props haven't changed
43
35
  const TableCell = React__default.memo(TableCellComponent);
44
36
 
45
37
  export { TableCell };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import { TableColumnManagerProps } from './Table.types';
3
+ export declare const TableColumnManager: <T extends Record<string, any>>(props: TableColumnManagerProps<T>) => React.ReactElement;
@@ -0,0 +1,34 @@
1
+ import React__default from 'react';
2
+ import { Popover } from '../Popover/Popover.js';
3
+ import '../Popover/PopoverContext.js';
4
+ import { Cog6ToothIcon } from '@heroicons/react/24/outline';
5
+ import { Button } from '../Button/Button.js';
6
+ import { Checkbox } from '../../forms/Checkbox/Checkbox.js';
7
+ import { Sortable, SortableItem } from '../Sortable/Sortable.js';
8
+
9
+ function TableColumnManagerComponent({ columns, visibleColumns, columnOrder, onToggleColumn, onResetToDefault, onColumnReorder, }) {
10
+ const orderedColumns = columnOrder.length > 0
11
+ ? columnOrder.map(colId => columns.find(col => col.id === colId)).filter(Boolean)
12
+ : columns;
13
+ const renderColumnItem = (column) => {
14
+ const isVisible = visibleColumns.includes(column.id);
15
+ const isLocked = column.locked === true;
16
+ const displayName = typeof column.header === 'string' ? column.header : column.id;
17
+ return (React__default.createElement(Checkbox, { id: `column-checkbox-${column.id}`, name: `column-${column.id}`, value: column.id, checked: isVisible, onChange: () => onToggleColumn(column.id), "aria-label": `Toggle visibility for ${displayName} column`, label: displayName, state: isLocked ? 'disabled' : 'default' }));
18
+ };
19
+ return (React__default.createElement(Popover, { placement: "bottom-end", offset: 8 },
20
+ React__default.createElement(Popover.Trigger, null,
21
+ React__default.createElement(Button, { color: "neutral", variant: "filled", "aria-label": "Manage column visibility" },
22
+ React__default.createElement(Cog6ToothIcon, { className: "size-5", "aria-hidden": "true" }),
23
+ "Manage Columns")),
24
+ React__default.createElement(Popover.Content, { className: "p-0" },
25
+ React__default.createElement("div", { className: "w-64 p-3 overflow-hidden bg-white", role: "dialog", "aria-labelledby": "column-manager-title", "aria-describedby": "column-manager-description", "aria-modal": "true" },
26
+ React__default.createElement("div", { id: "column-manager-title", className: "text-xs uppercase font-bold mb-3 text-[var(--color-text-placeholder)]" }, "Manage Columns"),
27
+ React__default.createElement("div", { id: "column-manager-description", className: "sr-only" }, "Use checkboxes to control which columns are visible in the table. Locked columns cannot be hidden."),
28
+ React__default.createElement("div", { className: "space-y-0.5", role: "group", "aria-label": "Column visibility options" }, onColumnReorder ? (React__default.createElement(Sortable, { onReorder: onColumnReorder, showDragHandle: true, className: "space-y-0.5" }, orderedColumns.map((column) => (React__default.createElement(SortableItem, { key: column.id, id: column.id, disabled: column.locked === true, className: `bg-white hover:bg-[var(--color-background-tertiary)] rounded-lg p-1.5 transition-colors ${column.locked ? 'bg-[var(--color-background-secondary)]' : ''}` }, renderColumnItem(column)))))) : (orderedColumns.map((column) => (React__default.createElement("div", { key: column.id, className: `bg-white hover:bg-[var(--color-background-tertiary)] rounded-lg p-1.5 transition-colors ${column.locked ? 'bg-[var(--color-background-secondary)]' : ''}` }, renderColumnItem(column)))))),
29
+ React__default.createElement("div", { className: "mt-3 flex justify-end" },
30
+ React__default.createElement(Button, { color: "neutral", variant: "filled", className: "w-full", onClick: onResetToDefault }, "Reset to Default"))))));
31
+ }
32
+ const TableColumnManager = TableColumnManagerComponent;
33
+
34
+ export { TableColumnManager };
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { TableHeaderProps, TableBodyProps, TableRowProps, TableCellProps, TableHeaderCellProps } from '../Table.types';
2
+ import { TableHeaderProps, TableBodyProps, TableRowProps, TableCellProps, TableHeaderCellProps } from './Table.types';
3
3
  export declare const Header: React.NamedExoticComponent<TableHeaderProps>;
4
4
  export declare const Body: React.NamedExoticComponent<TableBodyProps>;
5
5
  export declare const Row: React.NamedExoticComponent<TableRowProps>;
@@ -1,19 +1,10 @@
1
1
  import React__default, { useContext } from 'react';
2
- import { TableContext } from '../Table.js';
3
- import { cn } from '../../../../utils/cn.js';
2
+ import { TableContext } from './Table.js';
3
+ import { cn } from '../../../utils/cn.js';
4
+ import { alignmentClasses } from './Table.utils.js';
4
5
 
5
6
  /**
6
7
  * Declarative Table Header component
7
- * Used within the declarative API for flexible table composition
8
- *
9
- * @example
10
- * <Table>
11
- * <Table.Header freezeHeader>
12
- * <Table.Row>
13
- * <Table.HeaderCell>Name</Table.HeaderCell>
14
- * </Table.Row>
15
- * </Table.Header>
16
- * </Table>
17
8
  */
18
9
  const HeaderComponent = ({ children, freezeHeader, className = '' }) => {
19
10
  const contextValue = useContext(TableContext);
@@ -23,37 +14,19 @@ const HeaderComponent = ({ children, freezeHeader, className = '' }) => {
23
14
  : (contextValue.freezeHeader ? theme === null || theme === void 0 ? void 0 : theme.frozenHeaderStyle : ''), className);
24
15
  return (React__default.createElement("thead", { className: headerClasses, "data-freeze": freezeHeader ? 'true' : undefined }, children));
25
16
  };
26
- // Set display name for dev tools
27
17
  HeaderComponent.displayName = 'Table.Header';
28
- // Memoize component to prevent unnecessary re-renders
29
18
  const Header = React__default.memo(HeaderComponent);
30
19
  /**
31
20
  * Declarative Table Body component
32
- * Container for table rows in the declarative API
33
- *
34
- * @example
35
- * <Table.Body>
36
- * <Table.Row>
37
- * <Table.Cell>Data</Table.Cell>
38
- * </Table.Row>
39
- * </Table.Body>
40
21
  */
41
22
  const BodyComponent = ({ children, className = '', }) => {
42
23
  const { theme } = useContext(TableContext);
43
24
  return (React__default.createElement("tbody", { className: cn(theme === null || theme === void 0 ? void 0 : theme.bodyStyle, className) }, children));
44
25
  };
45
- // Set display name for dev tools
46
26
  BodyComponent.displayName = 'Table.Body';
47
- // Memoize component to prevent unnecessary re-renders
48
27
  const Body = React__default.memo(BodyComponent);
49
28
  /**
50
29
  * Declarative Table Row component
51
- * Supports selection, expansion, and custom styling
52
- *
53
- * @example
54
- * <Table.Row isSelected onSelectToggle={() => setSelected(!selected)}>
55
- * <Table.Cell>Data</Table.Cell>
56
- * </Table.Row>
57
30
  */
58
31
  const RowComponent = ({ children, isExpandable = false, isExpanded = false, onExpandToggle, isSelected = false, onSelectToggle, className = '', }) => {
59
32
  const { theme } = useContext(TableContext);
@@ -65,53 +38,30 @@ const RowComponent = ({ children, isExpandable = false, isExpanded = false, onEx
65
38
  };
66
39
  return (React__default.createElement("tr", { className: rowClasses, "data-selected": isSelected ? 'true' : undefined, "data-expanded": isExpandable && isExpanded ? 'true' : undefined, onClick: onSelectToggle ? handleRowClick : undefined, role: "row", "aria-selected": isSelected, "aria-expanded": isExpandable ? isExpanded : undefined }, children));
67
40
  };
68
- // Set display name for dev tools
69
41
  RowComponent.displayName = 'Table.Row';
70
- // Memoize component to prevent unnecessary re-renders
71
42
  const Row = React__default.memo(RowComponent);
72
43
  /**
73
44
  * Declarative Table Cell component
74
- * Standard data cell with alignment, width, and frozen column support
75
- *
76
- * @example
77
- * <Table.Cell align="right" width="200px" isFrozen>
78
- * $1,234.56
79
- * </Table.Cell>
80
45
  */
81
46
  const CellComponent = ({ children, isFrozen = false, isLastFrozen = false, align, width, className = '', colSpan, }) => {
82
47
  const { theme } = useContext(TableContext);
83
- const cellClasses = cn(theme === null || theme === void 0 ? void 0 : theme.cellStyle, isFrozen && (theme === null || theme === void 0 ? void 0 : theme.frozenColumnStyle), isLastFrozen && (theme === null || theme === void 0 ? void 0 : theme.lastFrozenColumnStyle), align && `text-${align}`, className);
48
+ const cellClasses = cn(theme === null || theme === void 0 ? void 0 : theme.cellStyle, isFrozen && (theme === null || theme === void 0 ? void 0 : theme.frozenColumnStyle), isLastFrozen && (theme === null || theme === void 0 ? void 0 : theme.lastFrozenColumnStyle), align && alignmentClasses[align], className);
84
49
  return (React__default.createElement("td", { className: cellClasses, "data-frozen": isFrozen ? 'true' : isLastFrozen ? 'last' : undefined, style: { width }, colSpan: colSpan, role: "cell" }, children));
85
50
  };
86
- // Set display name for dev tools
87
51
  CellComponent.displayName = 'Table.Cell';
88
- // Memoize component to prevent unnecessary re-renders
89
52
  const Cell = React__default.memo(CellComponent);
90
53
  /**
91
54
  * Declarative Table Header Cell component
92
- * Header cell with sorting functionality and alignment options
93
- *
94
- * @example
95
- * <Table.HeaderCell
96
- * isSortable
97
- * sortDirection="asc"
98
- * onSort={() => handleSort('name')}
99
- * align="left"
100
- * >
101
- * Name
102
- * </Table.HeaderCell>
103
55
  */
104
56
  const HeaderCellComponent = ({ children, isFrozen = false, isLastFrozen = false, isSortable = false, sortDirection, onSort, align = 'left', width, className = '', }) => {
105
57
  const { theme } = useContext(TableContext);
106
- const headerCellClasses = cn(theme === null || theme === void 0 ? void 0 : theme.headerStyle, isFrozen && (theme === null || theme === void 0 ? void 0 : theme.frozenColumnStyle), isLastFrozen && (theme === null || theme === void 0 ? void 0 : theme.lastFrozenColumnStyle), align && `text-${align}`, isSortable && 'cursor-pointer', className);
58
+ const headerCellClasses = cn(theme === null || theme === void 0 ? void 0 : theme.headerStyle, isFrozen && (theme === null || theme === void 0 ? void 0 : theme.frozenColumnStyle), isLastFrozen && (theme === null || theme === void 0 ? void 0 : theme.lastFrozenColumnStyle), align && alignmentClasses[align], isSortable && 'cursor-pointer', className);
107
59
  return (React__default.createElement("th", { className: headerCellClasses, "data-frozen": isFrozen ? 'true' : isLastFrozen ? 'last' : undefined, onClick: isSortable && onSort ? onSort : undefined, style: { width }, role: "columnheader", "aria-sort": sortDirection ? (sortDirection === 'asc' ? 'ascending' : 'descending') : undefined },
108
60
  React__default.createElement("div", { className: "flex items-center" },
109
61
  children,
110
- isSortable && sortDirection && (React__default.createElement("span", { className: "ml-1" }, sortDirection === 'asc' ? '' : '')))));
62
+ isSortable && sortDirection && (React__default.createElement("span", { className: "ml-1" }, sortDirection === 'asc' ? '\u2191' : '\u2193')))));
111
63
  };
112
- // Set display name for dev tools
113
64
  HeaderCellComponent.displayName = 'Table.HeaderCell';
114
- // Memoize component to prevent unnecessary re-renders
115
65
  const HeaderCell = React__default.memo(HeaderCellComponent);
116
66
 
117
67
  export { Body, Cell, Header, HeaderCell, Row };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import { TableFilterProps } from './Table.types';
3
+ export declare function TableFilter<T>({ columns, filterConfig, onFilterChange, className, }: TableFilterProps<T>): React.JSX.Element | null;