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
package/README.md CHANGED
@@ -26,6 +26,98 @@ function App() {
26
26
  }
27
27
  ```
28
28
 
29
+ ## Customizing the Theme
30
+
31
+ Flikkui uses CSS variables for all theming. Override any variable in your own CSS to customize colors, spacing, border radius, and more.
32
+
33
+ ### Colors
34
+
35
+ Override semantic color palettes by redefining the CSS variables after importing the library styles:
36
+
37
+ ```css
38
+ :root {
39
+ /* Change the primary color to green */
40
+ --color-primary-50: oklch(0.982 0.018 155.826);
41
+ --color-primary-100: oklch(0.962 0.044 156.743);
42
+ --color-primary-200: oklch(0.925 0.084 155.995);
43
+ --color-primary-300: oklch(0.871 0.15 154.449);
44
+ --color-primary-400: oklch(0.792 0.209 151.711);
45
+ --color-primary-500: oklch(0.723 0.219 149.579);
46
+ --color-primary-600: oklch(0.627 0.194 149.214);
47
+ --color-primary-700: oklch(0.527 0.154 150.069);
48
+ --color-primary-800: oklch(0.448 0.119 151.328);
49
+ --color-primary-900: oklch(0.393 0.095 152.535);
50
+ --color-primary-950: oklch(0.266 0.065 152.934);
51
+
52
+ --color-primary: var(--color-primary-600);
53
+ }
54
+ ```
55
+
56
+ Available color palettes: `primary`, `danger`, `success`, `warning`. Each has shades from `50` to `950`.
57
+
58
+ ### Backgrounds & Borders
59
+
60
+ ```css
61
+ :root {
62
+ --color-background: oklch(98.5% 0.002 247.839);
63
+ --color-background-secondary: oklch(95% 0.002 247.839);
64
+ --color-background-tertiary: oklch(90% 0.002 247.839);
65
+ --color-border: oklch(92.2% 0 0);
66
+ }
67
+ ```
68
+
69
+ ### Form Elements
70
+
71
+ Control sizing, padding, and border radius for all form components:
72
+
73
+ ```css
74
+ :root {
75
+ /* Border radius */
76
+ --form-rounded: 0.5rem;
77
+
78
+ /* Heights */
79
+ --form-min-h-sm: 2rem;
80
+ --form-min-h-md: 2.5rem;
81
+ --form-min-h-lg: 3rem;
82
+
83
+ /* Horizontal padding */
84
+ --form-px-sm: 0.75rem;
85
+ --form-px-md: 0.875rem;
86
+ --form-px-lg: 1rem;
87
+
88
+ /* Font sizes */
89
+ --form-text-sm: 0.75rem;
90
+ --form-text-md: 0.875rem;
91
+ --form-text-lg: 1rem;
92
+ }
93
+ ```
94
+
95
+ Button, badge, segmented, and other component variables inherit from these form defaults but can be overridden individually (e.g. `--button-rounded`, `--badge-rounded`).
96
+
97
+ ### Dark Mode
98
+
99
+ Add the `dark` class to your `<html>` or any parent container. All components adapt automatically:
100
+
101
+ ```html
102
+ <html class="dark">
103
+ <!-- dark mode active -->
104
+ </html>
105
+ ```
106
+
107
+ The library ships with sensible dark mode defaults. To customize dark mode colors, override variables inside `.dark`:
108
+
109
+ ```css
110
+ .dark {
111
+ --color-background: oklch(14.5% 0 0);
112
+ --color-border: oklch(30% 0 0);
113
+ --color-primary: var(--color-primary-400);
114
+ }
115
+ ```
116
+
117
+ ### Full Variable Reference
118
+
119
+ See [`src/styles/theme.css`](src/styles/theme.css) for the complete list of available CSS variables.
120
+
29
121
  ## Documentation
30
122
 
31
123
  This package is currently in beta. Full documentation coming soon.
@@ -1,21 +1,10 @@
1
1
  import { Variants } from "motion/react";
2
2
  /**
3
- * Get table row animation variants for row transitions (selection, expansion, etc.)
3
+ * Container animation for row expansion (height: 0 -> auto with opacity)
4
+ * Uses the same easing curve pattern as Accordion for consistency
4
5
  */
5
- export declare const getTableRowVariants: (shouldReduceMotion: boolean | null) => Variants | undefined;
6
+ export declare const tableExpandAnimations: Variants;
6
7
  /**
7
- * Get table expanded row animation variants for row expansion
8
+ * Content slide-in animation for expanded row content (staggered after container)
8
9
  */
9
- export declare const getTableExpandedRowVariants: (shouldReduceMotion: boolean | null) => Variants | undefined;
10
- /**
11
- * Get table column manager slide animation variants
12
- */
13
- export declare const getTableColumnManagerVariants: (shouldReduceMotion: boolean | null) => Variants | undefined;
14
- /**
15
- * Get table loading state animation variants
16
- */
17
- export declare const getTableLoadingVariants: (shouldReduceMotion: boolean | null) => Variants | undefined;
18
- /**
19
- * Get table sort indicator animation variants
20
- */
21
- export declare const getTableSortVariants: (shouldReduceMotion: boolean | null) => Variants | undefined;
10
+ export declare const tableExpandContentAnimations: Variants;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Container animation for row expansion (height: 0 -> auto with opacity)
3
+ * Uses the same easing curve pattern as Accordion for consistency
4
+ */
5
+ const tableExpandAnimations = {
6
+ collapsed: {
7
+ height: 0,
8
+ opacity: 0,
9
+ transition: {
10
+ height: { duration: 0.3, ease: [0.04, 0.62, 0.23, 0.98] },
11
+ opacity: { duration: 0.25 },
12
+ },
13
+ },
14
+ expanded: {
15
+ height: 'auto',
16
+ opacity: 1,
17
+ transition: {
18
+ height: { duration: 0.4, ease: [0.04, 0.62, 0.23, 0.98] },
19
+ opacity: { duration: 0.3, delay: 0.1 },
20
+ },
21
+ },
22
+ };
23
+ /**
24
+ * Content slide-in animation for expanded row content (staggered after container)
25
+ */
26
+ const tableExpandContentAnimations = {
27
+ collapsed: {
28
+ opacity: 0,
29
+ y: -10,
30
+ transition: {
31
+ y: { duration: 0.2 },
32
+ opacity: { duration: 0.2 },
33
+ },
34
+ },
35
+ expanded: {
36
+ opacity: 1,
37
+ y: 0,
38
+ transition: {
39
+ delay: 0.15,
40
+ y: { duration: 0.3 },
41
+ opacity: { duration: 0.3 },
42
+ },
43
+ },
44
+ };
45
+
46
+ export { tableExpandAnimations, tableExpandContentAnimations };
@@ -17,33 +17,6 @@ declare const TableContext: React.Context<TableContextType>;
17
17
  * - Pagination support
18
18
  * - Full accessibility compliance (WCAG 2.1 AA)
19
19
  * - Theme customization with className overrides
20
- *
21
- * @example
22
- * // Data-driven API with stable row keys
23
- * <Table data={data} columns={columns} rowKey="id" sortable selectable />
24
- *
25
- * // Using a function for complex row keys
26
- * <Table
27
- * data={data}
28
- * columns={columns}
29
- * rowKey={(row, index) => `${row.category}-${row.id}`}
30
- * sortable
31
- * selectable
32
- * />
33
- *
34
- * // Declarative API
35
- * <Table>
36
- * <Table.Header>
37
- * <Table.Row>
38
- * <Table.HeaderCell>Name</Table.HeaderCell>
39
- * </Table.Row>
40
- * </Table.Header>
41
- * <Table.Body>
42
- * <Table.Row>
43
- * <Table.Cell>John Doe</Table.Cell>
44
- * </Table.Row>
45
- * </Table.Body>
46
- * </Table>
47
20
  */
48
21
  declare function TableComponent<T extends Record<string, any>>(props: TableProps<T>): React.ReactElement;
49
22
  declare namespace TableComponent {
@@ -1,15 +1,14 @@
1
- import React__default, { createContext, useState, useEffect } from 'react';
1
+ import React__default, { createContext, useMemo } from 'react';
2
2
  import { tableTheme } from './Table.theme.js';
3
3
  import { cn } from '../../../utils/cn.js';
4
- import { TableHeader } from './components/core/TableHeader.js';
5
- import { TableBody } from './components/core/TableBody.js';
6
- import { TableSelectionHeader } from './components/TableSelectionHeader/TableSelectionHeader.js';
7
- import { Popover } from '../Popover/Popover.js';
8
- import '../Popover/PopoverContext.js';
9
- import { Cog6ToothIcon } from '@heroicons/react/24/outline';
10
- import { Button } from '../Button/Button.js';
11
- import { Checkbox } from '../../forms/Checkbox/Checkbox.js';
12
- import { Sortable, SortableItem } from '../Sortable/Sortable.js';
4
+ import { TableHeader } from './TableHeader.js';
5
+ import { TableBody } from './TableBody.js';
6
+ import { TableSelectionHeader } from './TableSelectionHeader.js';
7
+ import { TableColumnManager } from './TableColumnManager.js';
8
+ import { TableFilter } from './TableFilter.js';
9
+ import { useTableColumns } from './hooks/useTableColumns.js';
10
+ import { useTableSelection } from './hooks/useTableSelection.js';
11
+ import { useTablePagination } from './hooks/useTablePagination.js';
13
12
 
14
13
  /**
15
14
  * Context for sharing table state across all table components
@@ -34,131 +33,61 @@ const TableContext = createContext({
34
33
  * - Pagination support
35
34
  * - Full accessibility compliance (WCAG 2.1 AA)
36
35
  * - Theme customization with className overrides
37
- *
38
- * @example
39
- * // Data-driven API with stable row keys
40
- * <Table data={data} columns={columns} rowKey="id" sortable selectable />
41
- *
42
- * // Using a function for complex row keys
43
- * <Table
44
- * data={data}
45
- * columns={columns}
46
- * rowKey={(row, index) => `${row.category}-${row.id}`}
47
- * sortable
48
- * selectable
49
- * />
50
- *
51
- * // Declarative API
52
- * <Table>
53
- * <Table.Header>
54
- * <Table.Row>
55
- * <Table.HeaderCell>Name</Table.HeaderCell>
56
- * </Table.Row>
57
- * </Table.Header>
58
- * <Table.Body>
59
- * <Table.Row>
60
- * <Table.Cell>John Doe</Table.Cell>
61
- * </Table.Row>
62
- * </Table.Body>
63
- * </Table>
64
36
  */
65
37
  function TableComponent(props) {
66
38
  var _a;
67
- const { data, columns, rowKey, variant = "default", theme: themeOverrides, className = "", freezeHeader = false, freezeFirstColumn = false, freezeLastColumn = false, sortable = false, sortConfig = [], onSortChange, filterable = false, filterConfig = [], onFilterChange, expandable = false, expandedRowRender, expandedRows = [], onExpandedRowsChange, selectable = false, selectionType = "checkbox", selectedRows = [], onSelectionChange, bulkActions = [], visibleColumns: initialVisibleColumns, onVisibleColumnsChange, onColumnReorder, pagination, children, } = props;
68
- // Store the initial state for reset functionality
69
- const defaultVisibleColumns = initialVisibleColumns || (columns ? columns.map((col) => col.id) : []);
70
- const defaultColumnOrder = columns ? columns.map((col) => col.id) : [];
71
- const [visibleColumns, setVisibleColumns] = useState(defaultVisibleColumns);
72
- const [columnOrder, setColumnOrder] = useState(defaultColumnOrder);
73
- // Sync column order when columns prop changes
74
- useEffect(() => {
75
- if (columns) {
76
- setColumnOrder(columns.map((col) => col.id));
77
- }
78
- }, [columns]);
39
+ const { data, columns, rowKey, variant = "default", theme: themeOverrides, className = "", freezeHeader = false, freezeFirstColumn = false, freezeLastColumn = false, sortable = false, sortConfig = [], onSortChange, filterable = false, filterConfig = [], onFilterChange, expandable = false, expandedRowRender, expandedRows = [], onExpandedRowsChange, selectable = false, selectionType = "checkbox", selectedRows = [], onSelectionChange, bulkActions = [], showColumnManager = false, visibleColumns: initialVisibleColumns, onVisibleColumnsChange, onColumnReorder, pagination, children, } = props;
40
+ // Column management hook
41
+ const { visibleColumns, columnOrder, visibleColumnsList, handleToggleColumn, handleColumnReorder, handleResetToDefault, } = useTableColumns({
42
+ columns,
43
+ initialVisibleColumns,
44
+ onVisibleColumnsChange,
45
+ onColumnReorder,
46
+ });
47
+ // Pagination hook
48
+ const { paginatedData } = useTablePagination({
49
+ data,
50
+ pagination,
51
+ });
52
+ // Selection hook (for clear selection in header)
53
+ const { handleClearSelection } = useTableSelection({
54
+ data: paginatedData,
55
+ rowKey,
56
+ selectionType,
57
+ selectedRows,
58
+ onSelectionChange,
59
+ });
79
60
  // Determine which API is being used (declarative vs data-driven)
80
61
  const isDeclarativeAPI = !!children;
81
62
  // Merge global theme with component-specific overrides
82
- const theme = {
63
+ const theme = useMemo(() => ({
83
64
  ...tableTheme,
84
65
  ...(themeOverrides || {}),
85
- };
66
+ }), [themeOverrides]);
86
67
  // Get base classes from theme
87
68
  const baseClasses = theme.baseStyle || "";
88
69
  const variantClasses = ((_a = theme.variants) === null || _a === void 0 ? void 0 : _a[variant]) || "";
89
- /**
90
- * Handle column visibility changes from the column manager
91
- * Updates both internal state and calls the external callback
92
- */
93
- const handleVisibleColumnsChange = (newVisibleColumns) => {
94
- setVisibleColumns(newVisibleColumns);
95
- onVisibleColumnsChange === null || onVisibleColumnsChange === void 0 ? void 0 : onVisibleColumnsChange(newVisibleColumns);
96
- };
97
- /**
98
- * Handle column reordering from the column manager
99
- * Updates column order and calls the external callback
100
- */
101
- const handleColumnReorder = (fromIndex, toIndex) => {
102
- const newColumnOrder = [...columnOrder];
103
- const [movedColumn] = newColumnOrder.splice(fromIndex, 1);
104
- newColumnOrder.splice(toIndex, 0, movedColumn);
105
- setColumnOrder(newColumnOrder);
106
- onColumnReorder === null || onColumnReorder === void 0 ? void 0 : onColumnReorder(fromIndex, toIndex);
107
- };
108
- /**
109
- * Handle column order reset from the column manager
110
- * Resets column order back to the original columns order
111
- */
112
- const handleColumnOrderReset = () => {
113
- if (columns) {
114
- const originalOrder = columns.map((col) => col.id);
115
- setColumnOrder(originalOrder);
116
- }
117
- };
118
- /**
119
- * Handle clearing all row selections
120
- */
121
- const handleClearSelection = () => {
122
- onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange([]);
123
- };
124
- /**
125
- * Handle toggling column visibility
126
- * Prevents toggling locked columns
127
- */
128
- const handleToggleColumn = (columnId) => {
129
- const column = columns === null || columns === void 0 ? void 0 : columns.find(col => col.id === columnId);
130
- if (column === null || column === void 0 ? void 0 : column.locked)
131
- return; // Prevent toggling locked columns
132
- const newVisibleColumns = visibleColumns.includes(columnId)
133
- ? visibleColumns.filter((id) => id !== columnId)
134
- : [...visibleColumns, columnId];
135
- handleVisibleColumnsChange(newVisibleColumns);
136
- };
137
- /**
138
- * Handle resetting columns to default visibility and order
139
- */
140
- const handleResetToDefault = () => {
141
- // Get all locked column IDs to ensure they remain visible
142
- const lockedColumnIds = (columns === null || columns === void 0 ? void 0 : columns.filter(col => col.locked).map(col => col.id)) || [];
143
- // Combine initial visible columns with locked columns (remove duplicates)
144
- const resetVisibleColumns = Array.from(new Set([...defaultVisibleColumns, ...lockedColumnIds]));
145
- // Reset to initial visible columns with locked columns guaranteed to be visible
146
- handleVisibleColumnsChange(resetVisibleColumns);
147
- // Reset column order to default
148
- handleColumnOrderReset();
149
- };
150
- // Filter and order columns based on column order and visibility settings
151
- const visibleColumnsList = columns && columnOrder.length > 0
152
- ? columnOrder
153
- .map(colId => columns.find(col => col.id === colId))
154
- .filter((col) => col !== undefined && visibleColumns.includes(col.id))
155
- : (columns ? columns.filter((col) => visibleColumns.includes(col.id)) : []);
156
- // Calculate paginated data slice based on current page and page size
157
- const paginatedData = pagination && data
158
- ? data.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize)
159
- : data || [];
160
- // Create context value with all table configuration and callbacks
161
- const contextValue = {
70
+ // Memoize context value to prevent unnecessary re-renders in consumers
71
+ const contextValue = useMemo(() => ({
72
+ theme,
73
+ variant,
74
+ freezeHeader,
75
+ freezeFirstColumn,
76
+ freezeLastColumn,
77
+ sortable,
78
+ sortConfig,
79
+ onSortChange,
80
+ filterable,
81
+ filterConfig,
82
+ onFilterChange,
83
+ expandable,
84
+ expandedRows,
85
+ onExpandedRowsChange,
86
+ selectable,
87
+ selectionType,
88
+ selectedRows,
89
+ onSelectionChange,
90
+ }), [
162
91
  theme,
163
92
  variant,
164
93
  freezeHeader,
@@ -177,47 +106,20 @@ function TableComponent(props) {
177
106
  selectionType,
178
107
  selectedRows,
179
108
  onSelectionChange,
180
- };
109
+ ]);
181
110
  return (React__default.createElement(TableContext.Provider, { value: contextValue },
182
111
  React__default.createElement("div", { className: "relative" },
183
- !isDeclarativeAPI && columns && (React__default.createElement("div", { className: theme.columnManagerContainer },
184
- React__default.createElement(Popover, { placement: "bottom-end", offset: 8 },
185
- React__default.createElement(Popover.Trigger, null,
186
- React__default.createElement(Button, { color: "neutral", variant: "filled", "aria-label": "Manage column visibility" },
187
- React__default.createElement(Cog6ToothIcon, { className: "size-5", "aria-hidden": "true" }),
188
- "Manage Columns")),
189
- React__default.createElement(Popover.Content, { className: "p-0" },
190
- 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" },
191
- React__default.createElement("div", { id: "column-manager-title", className: "text-xs uppercase font-bold mb-3 text-[var(--color-text-placeholder)]" }, "Manage Columns"),
192
- 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."),
193
- React__default.createElement("div", { className: "space-y-0.5", role: "group", "aria-label": "Column visibility options" }, onColumnReorder ? (React__default.createElement(Sortable, { onReorder: handleColumnReorder, showDragHandle: true, className: "space-y-0.5" }, (columnOrder.length > 0
194
- ? columnOrder.map(colId => columns.find(col => col.id === colId)).filter(Boolean)
195
- : columns).map((column) => {
196
- const isVisible = visibleColumns.includes(column.id);
197
- const isLocked = column.locked === true;
198
- const displayName = typeof column.header === "string" ? column.header : column.id;
199
- return (React__default.createElement(SortableItem, { key: column.id, id: column.id, disabled: isLocked, className: `bg-white hover:bg-[var(--color-background-tertiary)] rounded-lg p-1.5 transition-colors ${isLocked ? "bg-gray-50" : ""}` },
200
- React__default.createElement(Checkbox, { id: `column-checkbox-${column.id}`, name: `column-${column.id}`, value: column.id, checked: isVisible, onChange: () => handleToggleColumn(column.id), "aria-label": `Toggle visibility for ${displayName} column`, label: displayName, state: isLocked ? "disabled" : "default" })));
201
- }))) : ((columnOrder.length > 0
202
- ? columnOrder.map(colId => columns.find(col => col.id === colId)).filter(Boolean)
203
- : columns).map((column) => {
204
- const isVisible = visibleColumns.includes(column.id);
205
- const isLocked = column.locked === true;
206
- const displayName = typeof column.header === "string" ? column.header : column.id;
207
- return (React__default.createElement("div", { key: column.id, className: `bg-white hover:bg-[var(--color-background-tertiary)] rounded-lg p-1.5 transition-colors ${isLocked ? "bg-gray-50" : ""}` },
208
- React__default.createElement(Checkbox, { id: `column-checkbox-${column.id}`, name: `column-${column.id}`, value: column.id, checked: isVisible, onChange: () => handleToggleColumn(column.id), "aria-label": `Toggle visibility for ${displayName} column`, label: displayName, state: isLocked ? "disabled" : "default" })));
209
- }))),
210
- React__default.createElement("div", { className: "mt-3 flex justify-end" },
211
- React__default.createElement(Button, { color: "neutral", variant: "filled", className: "w-full", onClick: handleResetToDefault }, "Reset to Default"))))))),
112
+ !isDeclarativeAPI && columns && showColumnManager && (React__default.createElement("div", { className: theme.columnManagerContainer },
113
+ React__default.createElement(TableColumnManager, { columns: columns, visibleColumns: visibleColumns, columnOrder: columnOrder, onToggleColumn: handleToggleColumn, onResetToDefault: handleResetToDefault, onColumnReorder: onColumnReorder ? handleColumnReorder : undefined }))),
114
+ !isDeclarativeAPI && filterable && onFilterChange && columns && (React__default.createElement("div", { className: "mb-3" },
115
+ React__default.createElement(TableFilter, { columns: columns, filterConfig: filterConfig, onFilterChange: onFilterChange }))),
212
116
  !isDeclarativeAPI && selectable && selectedRows.length > 0 && (React__default.createElement(TableSelectionHeader, { selectedCount: selectedRows.length, totalCount: paginatedData.length, selectedRows: selectedRows, bulkActions: bulkActions, onClearSelection: handleClearSelection })),
213
117
  React__default.createElement("div", { className: "overflow-x-auto" },
214
118
  React__default.createElement("table", { className: cn(baseClasses, variantClasses, className), role: "table", "aria-label": isDeclarativeAPI ? "Data table" : `Data table with ${paginatedData.length} rows`, "aria-rowcount": pagination ? pagination.totalItems : data === null || data === void 0 ? void 0 : data.length, "aria-colcount": visibleColumnsList.length }, isDeclarativeAPI ? (children) : (React__default.createElement(React__default.Fragment, null,
215
119
  React__default.createElement(TableHeader, { columns: visibleColumnsList, sortConfig: sortConfig, onSortChange: onSortChange, filterConfig: filterConfig, onFilterChange: onFilterChange, freezeHeader: freezeHeader, freezeFirstColumn: freezeFirstColumn, freezeLastColumn: freezeLastColumn, expandable: expandable, expandedRowRender: expandedRowRender, selectable: selectable, selectionType: selectionType, selectedRows: selectedRows, onSelectionChange: onSelectionChange, totalRowCount: paginatedData.length, theme: theme, data: paginatedData, rowKey: rowKey }),
216
120
  React__default.createElement(TableBody, { data: paginatedData, columns: visibleColumnsList, rowKey: rowKey, expandedRowRender: expandedRowRender, expandedRows: expandedRows, onExpandedRowsChange: onExpandedRowsChange, selectable: selectable, selectionType: selectionType, selectedRows: selectedRows, onSelectionChange: onSelectionChange, freezeFirstColumn: freezeFirstColumn, freezeLastColumn: freezeLastColumn, theme: theme }))))))));
217
121
  }
218
- // Set display name for dev tools and Storybook
219
122
  TableComponent.displayName = "Table";
220
- // Export as default
221
123
  const Table = TableComponent;
222
124
 
223
125
  export { Table, TableContext };
@@ -1,7 +1,9 @@
1
1
  const tableTheme = {
2
2
  // Base styles for the table
3
+ // Uses border-separate so sticky cells keep their borders (border-collapse
4
+ // paints borders on the table grid, which sticky cells float above)
3
5
  // Light: white background | Dark: neutral-900 background
4
- baseStyle: "w-full border-collapse text-sm " +
6
+ baseStyle: "w-full border-separate border-spacing-0 text-sm " +
5
7
  "bg-white dark:bg-[var(--color-neutral-900)]",
6
8
  // Variant styles
7
9
  // Each variant gets dark mode border colors and alternate row colors
@@ -11,8 +13,8 @@ const tableTheme = {
11
13
  striped: "border-[var(--color-border)] dark:border-[var(--color-neutral-700)] " +
12
14
  "[&>tbody>tr:nth-child(odd)]:bg-[var(--color-neutral-50)] dark:[&>tbody>tr:nth-child(odd)]:bg-[var(--color-neutral-800)] " +
13
15
  "[&_td]:px-3 [&_td]:py-2.5 [&_th]:px-3 [&_th]:py-2.5",
14
- bordered: "border border-[var(--color-border)] dark:border-[var(--color-neutral-700)] " +
15
- "[&_td]:border [&_th]:border " +
16
+ bordered: "border-t border-l border-[var(--color-border)] dark:border-[var(--color-neutral-700)] " +
17
+ "[&_td]:border-b [&_td]:border-r [&_th]:border-b [&_th]:border-r " +
16
18
  "[&_td]:border-[var(--color-border)] [&_th]:border-[var(--color-border)] " +
17
19
  "dark:[&_td]:border-[var(--color-neutral-700)] dark:[&_th]:border-[var(--color-neutral-700)] " +
18
20
  "[&_td]:px-3 [&_td]:py-2.5 [&_th]:px-3 [&_th]:py-2.5",
@@ -24,29 +26,36 @@ const tableTheme = {
24
26
  headerStyle: "text-left font-medium sticky top-0 border-b " +
25
27
  "text-[var(--color-text-primary)] border-[var(--color-border)] " +
26
28
  "dark:text-[var(--color-neutral-200)] dark:border-[var(--color-neutral-700)]",
27
- // Cell styles
28
- // Light: primary text, light border | Dark: neutral-300 text, neutral-700 border
29
- cellStyle: "border-t " +
30
- "text-[var(--color-text-primary)] border-[var(--color-border)] " +
31
- "dark:text-[var(--color-neutral-300)] dark:border-[var(--color-neutral-700)]",
32
- // Row styles
29
+ // Cell styles — borders on cells (not rows) so sticky columns keep them
30
+ // Light: primary text | Dark: neutral-300 text
31
+ cellStyle: "border-b border-b-[var(--color-border)] " +
32
+ "text-[var(--color-text-primary)] " +
33
+ "dark:border-b-[var(--color-neutral-700)] dark:text-[var(--color-neutral-300)]",
34
+ // Row styles — hover and layout only (borders moved to cells)
33
35
  // Light: neutral-50 hover | Dark: neutral-800 hover
34
- rowStyle: "transition-all duration-300 relative " +
35
- "hover:bg-[var(--color-neutral-50)] dark:hover:bg-[var(--color-neutral-800)]",
36
+ rowStyle: "group transition-all duration-300 relative " +
37
+ "hover:bg-[var(--color-neutral-50)] " +
38
+ "dark:hover:bg-[var(--color-neutral-800)]",
36
39
  // Selected row styles
37
40
  // Light: primary-50 background | Dark: primary-900/50 background with adjusted shadow
38
41
  selectedRowStyle: "shadow-[inset_3px_0_0_0_var(--color-primary)] " +
39
42
  "bg-[var(--color-primary-50)]/50 hover:bg-[var(--color-primary-50)] " +
40
43
  "dark:bg-[var(--color-primary-900)]/30 dark:hover:bg-[var(--color-primary-900)]/50",
41
44
  hoverRowStyle: "cursor-pointer",
42
- // Frozen column styles
43
- // Light: white/80 with light outline | Dark: neutral-900/80 with dark outline
44
- frozenColumnStyle: "sticky left-0 z-10 backdrop-blur-sm shadow-l-xl outline outline-1 " +
45
- "bg-white/80 outline-[var(--color-neutral-200)] " +
46
- "dark:bg-[var(--color-neutral-900)]/80 dark:outline-[var(--color-neutral-700)]",
47
- lastFrozenColumnStyle: "sticky right-0 z-10 backdrop-blur-sm shadow-r-xl outline outline-1 " +
48
- "bg-white/80 outline-[var(--color-neutral-200)] " +
49
- "dark:bg-[var(--color-neutral-900)]/80 dark:outline-[var(--color-neutral-700)]",
45
+ // Frozen column styles — borders are on the cell (via cellStyle) so they
46
+ // travel with the sticky element. Only need vertical separator borders here.
47
+ frozenColumnStyle: "sticky left-0 z-10 backdrop-blur-sm shadow-l-xl " +
48
+ "border-r border-r-[var(--color-neutral-200)] " +
49
+ "bg-white/80 " +
50
+ "group-hover:bg-[var(--color-neutral-50)] " +
51
+ "dark:bg-[var(--color-neutral-900)]/80 dark:border-r-[var(--color-neutral-700)] " +
52
+ "dark:group-hover:bg-[var(--color-neutral-800)]",
53
+ lastFrozenColumnStyle: "sticky right-0 z-10 backdrop-blur-sm shadow-r-xl " +
54
+ "border-l border-l-[var(--color-neutral-200)] " +
55
+ "bg-white/80 " +
56
+ "group-hover:bg-[var(--color-neutral-50)] " +
57
+ "dark:bg-[var(--color-neutral-900)]/80 dark:border-l-[var(--color-neutral-700)] " +
58
+ "dark:group-hover:bg-[var(--color-neutral-800)]",
50
59
  frozenHeaderStyle: "sticky top-0 z-20 " +
51
60
  "shadow-lg shadow-[var(--color-neutral-200)]/50 " +
52
61
  "dark:shadow-[var(--color-neutral-900)]/50",