flexi-datagrid 1.2.0 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,9 +2,12 @@
2
2
 
3
3
  A modern, highly customizable, and feature-rich React data grid component designed for speed and flexibility.
4
4
 
5
- ## ✨ Features
5
+ ## Features
6
6
 
7
- - **Column Pinning:** Easily pin important columns to the left side of the grid.
7
+ - **Column Pinning (Left & Right):** Pin important columns to either the left or right edge of the grid. Clicking the pin icon cycles a column through unpinned → pinned left → pinned right.
8
+ - **Pinned Bottom Rows (AG Grid-style):** Pass `pinnedBottomRowData` to render summary/total rows in a section fixed to the bottom of the grid, independent of your main `data` — no per-row pin buttons required.
9
+ - **Sticky Header:** The header row stays fixed in place while the body scrolls vertically — give the grid a bounded height via `containerStyle` to enable vertical scrolling.
10
+ - **Table Borders:** Optional full grid borders via the `bordered` prop for a classic spreadsheet look.
8
11
  - **Multi-State Sorting:** Clickable column headers that support Ascending (asc), Descending (desc), and Unsorted states.
9
12
  - **Built-in Filtering:** Filter rows instantly with a clean popup search and multi-select dropdown for unique column values. The popup renders through a portal so it always floats above your grid content instead of being clipped by the table's scroll container.
10
13
  - **Row Grouping (Drag-and-Drop):** Drag column headers into the grouping zone to group your dataset hierarchically with expand/collapse support.
@@ -15,7 +18,7 @@ A modern, highly customizable, and feature-rich React data grid component design
15
18
 
16
19
  ---
17
20
 
18
- ## 📦 Installation
21
+ ## Installation
19
22
 
20
23
  Install the package via npm:
21
24
 
@@ -33,7 +36,7 @@ import 'flexi-datagrid/dist/flexi-datagrid.css';
33
36
 
34
37
  ---
35
38
 
36
- ## 🚀 Quick Start
39
+ ## Quick Start
37
40
 
38
41
  ```tsx
39
42
  import { DataTable, type ColumnConfig } from 'flexi-datagrid';
@@ -55,13 +58,15 @@ const data: Employee[] = [
55
58
  ];
56
59
 
57
60
  const columns: ColumnConfig<Employee>[] = [
58
- { key: 'name', header: 'Name', sortable: true, filterable: true, pinned: true },
61
+ { key: 'name', header: 'Name', sortable: true, filterable: true, pinned: 'left',style: { width: "400px", backgroundColor: "#f9f9f9" },
62
+ headerStyle: { fontWeight: "bold", color: "#333" } },
59
63
  { key: 'department', header: 'Department', sortable: true, filterable: true },
60
64
  { key: 'role', header: 'Role', sortable: true, filterable: true },
61
65
  {
62
66
  key: 'salary',
63
67
  header: 'Salary',
64
68
  sortable: true,
69
+ pinned: 'right',
65
70
  render: (value) => `$${value.toLocaleString()}`,
66
71
  },
67
72
  ];
@@ -74,6 +79,11 @@ export default function EmployeeTable() {
74
79
  rowKey="id"
75
80
  groupBy
76
81
  defaultGroupBy={['department']}
82
+ bordered
83
+ pinnedBottomRowData={[
84
+ { id: -1, name: '', department: '', role: 'Total', salary: data.reduce((sum, r) => sum + r.salary, 0) },
85
+ ]}
86
+ containerStyle={{ maxHeight: 480 }}
77
87
  actions={(record) => (
78
88
  <button onClick={() => console.log('Edit', record.id)}>Edit</button>
79
89
  )}
@@ -84,7 +94,7 @@ export default function EmployeeTable() {
84
94
 
85
95
  ---
86
96
 
87
- ## ⚙️ How It Works
97
+ ## How It Works
88
98
 
89
99
  `DataTable` is a single, self-contained component: pass it `columns` and `data`, and it manages sorting, filtering, pinning, and grouping state internally.
90
100
 
@@ -102,7 +112,8 @@ Each entry in `columns` describes one column (or a group of columns, via `childr
102
112
  | `getValue` | `(record) => any` | Custom accessor used for sorting, filtering, and grouping when the value isn't a simple `record[key]` lookup. |
103
113
  | `filterable` | `boolean` | Shows a filter icon in the header that opens a multi-select popup of unique column values. |
104
114
  | `sortable` | `boolean` | Makes the header clickable, cycling through ascending → descending → unsorted. |
105
- | `pinned` | `boolean` | Pins the column to the left edge by default (still toggleable per-column from the UI). |
115
+ | `pinned` | `boolean \| 'left' \| 'right'` | Pins the column to an edge by default (`true` is shorthand for `'left'`). Still toggleable per-column from the UI. |
116
+ | `pinnedRender` | `(value, record) => ReactNode` | Overrides `render` specifically for rows supplied via `pinnedBottomRowData` (e.g. render a "Total" label or bold sum). Falls back to `render` when omitted. |
106
117
  | `children` | `ColumnConfig<T>[]` | Nest columns to render a grouped, multi-row header. Only leaf columns are sortable/filterable/pinnable. |
107
118
 
108
119
  ### Grid props (`DataTableProps<T>`)
@@ -116,10 +127,13 @@ Each entry in `columns` describes one column (or a group of columns, via `childr
116
127
  | `isLoading` | `boolean` | Shows a loading state in place of rows. |
117
128
  | `groupBy` | `boolean` | Enables drag-and-drop row grouping — drag a column header into the grouping zone above the grid. |
118
129
  | `defaultGroupBy` | `string[]` | Column keys the grid is grouped by on initial render (requires `groupBy`). |
119
- | `onPinChange` | `(columnKey, isPinned) => void` | Called whenever a column is pinned/unpinned. |
130
+ | `onPinChange` | `(columnKey, isPinned, side?) => void` | Called whenever a column is pinned/unpinned, with the side (`'left'` \| `'right'`) it was pinned to. |
120
131
  | `onGroupChange` | `(groupedKeys: string[]) => void` | Called whenever the set of grouped columns changes. |
121
- | `containerStyle` | `CSSProperties` | Inline styles for the scrollable table container. |
132
+ | `containerStyle` | `CSSProperties` | Inline styles for the scrollable table container. Set a `maxHeight` here to enable vertical scrolling with a sticky header and sticky bottom-pinned rows. |
122
133
  | `tableStyle` | `CSSProperties` | Inline styles for the `<table>` element itself. |
134
+ | `bordered` | `boolean` | Draws full grid borders (all four sides of every cell) instead of the default minimal row/column dividers. |
135
+ | `pinnedBottomRowData` | `T[]` | Rows rendered in a section fixed to the bottom of the grid (e.g. totals/summary rows). Independent of `data` — not affected by sorting, filtering, or grouping. |
136
+ | `pinnedRowClassName` | `string \| (record: T, index: number) => string` | Extra class name(s) applied to each pinned-bottom row, for styling a totals/summary template. |
123
137
 
124
138
  ### Filtering
125
139
 
@@ -135,7 +149,50 @@ Set `groupBy` to enable a drop zone above the table. Dragging a sortable/leaf co
135
149
 
136
150
  ### Column Pinning
137
151
 
138
- Hovering a header reveals a pin icon; pinning locks that column to the left with a sticky position and shadow so it stays visible while scrolling horizontally. Columns marked `pinned: true` start pinned.
152
+ Hovering a header reveals a pin icon. Clicking it cycles the column through unpinned → pinned left → pinned right → unpinned, locking it to the corresponding edge with a sticky position and shadow so it stays visible while scrolling horizontally. Columns marked `pinned: true` (or `pinned: 'left'`) start pinned left; `pinned: 'right'` starts pinned right.
153
+
154
+ ### Pinned Bottom Rows
155
+
156
+ Pass `pinnedBottomRowData` — a separate array of rows (e.g. one or more totals rows) — and they're rendered in a section sticky-pinned to the bottom of the scrollable body, always visible while the main rows scroll past. This mirrors AG Grid's `pinnedBottomRowData`: it's plain data, not part of `data`/sorting/filtering/grouping, and there's no per-row pin button to manage.
157
+
158
+ Use `pinnedRowClassName` (a string, or a `(record, index) => string` function) to style the template — e.g. bold text or a tinted background for a totals row — and `pinnedRender` on a `ColumnConfig` to override how a specific column renders for these rows only (falling back to `render` otherwise):
159
+
160
+ ```tsx
161
+ const columns: ColumnConfig<Employee>[] = [
162
+ { key: 'name', header: 'Name', pinnedRender: () => <strong>Total</strong> },
163
+ {
164
+ key: 'salary',
165
+ header: 'Salary',
166
+ render: (value) => `$${value.toLocaleString()}`,
167
+ pinnedRender: (value) => <strong>${value.toLocaleString()}</strong>,
168
+ },
169
+ ];
170
+
171
+ const totalsRow = {
172
+ name: '',
173
+ salary: data.reduce((sum, row) => sum + row.salary, 0),
174
+ };
175
+
176
+ <DataTable
177
+ columns={columns}
178
+ data={data}
179
+ rowKey="id"
180
+ pinnedBottomRowData={[totalsRow]}
181
+ pinnedRowClassName="my-totals-row"
182
+ />
183
+ ```
184
+
185
+ ### Many Columns
186
+
187
+ Header labels truncate with an ellipsis instead of overflowing into neighboring headers once a column becomes narrow (e.g. many columns, or an explicit small `style.width`) — no configuration needed.
188
+
189
+ ### Sticky Header
190
+
191
+ The header row is always fixed in place (`position: sticky; top: 0`) relative to the table's scroll container. To see it in action, give the grid a bounded height — e.g. `containerStyle={{ maxHeight: 480 }}` — so the body scrolls vertically while the header (and any bottom-pinned rows) stay put.
192
+
193
+ ### Table Borders
194
+
195
+ Pass `bordered` to draw full borders around every cell instead of the default minimal row/column dividers, for a classic spreadsheet look.
139
196
 
140
197
  ---
141
198
 
@@ -143,7 +200,7 @@ Hovering a header reveals a pin icon; pinning locks that column to the left with
143
200
 
144
201
  ```bash
145
202
  npm install
146
- npm run build # bundles the library to dist/ and emits type declarations
203
+ npm run build
147
204
  ```
148
205
 
149
206
  ## 📄 License
@@ -8,12 +8,14 @@ export interface ColumnConfig<T> {
8
8
  style?: CSSProperties;
9
9
  headerStyle?: CSSProperties;
10
10
  render?: (value: any, record: T) => ReactNode;
11
+ pinnedRender?: (value: any, record: T) => ReactNode;
11
12
  filterable?: boolean;
12
13
  sortable?: boolean;
13
- pinned?: boolean;
14
+ pinned?: boolean | 'left' | 'right';
14
15
  children?: ColumnConfig<T>[];
15
16
  getValue?: (record: T) => any;
16
17
  }
18
+ type PinSide = 'left' | 'right';
17
19
  interface DataTableProps<T> {
18
20
  columns: ColumnConfig<T>[];
19
21
  data: T[];
@@ -22,10 +24,13 @@ interface DataTableProps<T> {
22
24
  isLoading?: boolean;
23
25
  groupBy?: boolean;
24
26
  defaultGroupBy?: string[];
25
- onPinChange?: (columnKey: string, isPinned: boolean) => void;
27
+ onPinChange?: (columnKey: string, isPinned: boolean, side?: PinSide) => void;
26
28
  onGroupChange?: (groupedKeys: string[]) => void;
27
29
  containerStyle?: CSSProperties;
28
30
  tableStyle?: CSSProperties;
31
+ bordered?: boolean;
32
+ pinnedBottomRowData?: T[];
33
+ pinnedRowClassName?: string | ((record: T, index: number) => string);
29
34
  }
30
- export declare function DataTable<T>({ columns, data, rowKey, actions, isLoading, groupBy, defaultGroupBy, onPinChange, onGroupChange, containerStyle, tableStyle, }: DataTableProps<T>): React.JSX.Element;
35
+ export declare function DataTable<T>({ columns, data, rowKey, actions, isLoading, groupBy, defaultGroupBy, onPinChange, onGroupChange, containerStyle, tableStyle, bordered, pinnedBottomRowData, pinnedRowClassName, }: DataTableProps<T>): React.JSX.Element;
31
36
  export {};
@@ -1,2 +1,2 @@
1
- *,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.pointer-events-auto{pointer-events:auto}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.mb-1{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.mr-1{margin-right:.25rem}.mt-2{margin-top:.5rem}.block{display:block}.flex{display:flex}.table{display:table}.h-12{height:3rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.max-h-40{max-height:10rem}.min-h-\[52px\]{min-height:52px}.w-12{width:3rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-40{width:10rem}.w-52{width:13rem}.w-full{width:100%}.table-fixed{table-layout:fixed}.caption-bottom{caption-side:bottom}.border-collapse{border-collapse:collapse}.scale-\[0\.99\]{--tw-scale-x:.99;--tw-scale-y:.99;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;user-select:none}.resize{resize:both}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-slate-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(241 245 249/var(--tw-divide-opacity,1))}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.border-slate-100{--tw-border-opacity:1;border-color:rgb(241 245 249/var(--tw-border-opacity,1))}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.border-slate-300{--tw-border-opacity:1;border-color:rgb(203 213 225/var(--tw-border-opacity,1))}.bg-blue-50\/50{background-color:#eff6ff80}.bg-slate-200\/70{background-color:#e2e8f0b3}.bg-slate-50{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.bg-slate-50\/30{background-color:#f8fafc4d}.bg-slate-50\/50{background-color:#f8fafc80}.bg-slate-50\/60{background-color:#f8fafc99}.bg-slate-50\/90{background-color:#f8fafce6}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.p-0\.5{padding:.125rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-8{padding:2rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.pb-2{padding-bottom:.5rem}.pl-2{padding-left:.5rem}.pl-4{padding-left:1rem}.pr-1{padding-right:.25rem}.pt-1{padding-top:.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-sm{font-size:.875rem;line-height:1.25rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.tracking-wider{letter-spacing:.05em}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.text-slate-800{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity,1))}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow-\[-1px_0_0_rgba\(226\,232\,240\,1\)\]{--tw-shadow:-1px 0 0 #e2e8f0;--tw-shadow-colored:-1px 0 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.flexi-datagrid-scope button{appearance:none;cursor:pointer;font:inherit;background:0 0;border:none;margin:0;padding:0;line-height:normal}.flexi-datagrid-scope table{border-collapse:collapse;border-spacing:0}.flexi-datagrid-scope th,.flexi-datagrid-scope td{border-top:none!important}.flexi-datagrid-scope .opacity-0{opacity:0!important}.flexi-datagrid-scope .opacity-100,.flexi-datagrid-scope .group\/header:hover .group-hover\/header\:opacity-100,.flexi-datagrid-scope .group:hover .group-hover\:opacity-100{opacity:1!important}.hover\:bg-slate-100:hover{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.hover\:bg-slate-100\/80:hover{background-color:#f1f5f9cc}.hover\:bg-slate-200:hover{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity,1))}.hover\:bg-slate-50:hover{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.hover\:bg-slate-50\/80:hover{background-color:#f8fafccc}.hover\:text-blue-600:hover{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.focus\:outline-none:focus{outline-offset:2px;outline:2px solid #0000}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-400:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(96 165 250/var(--tw-ring-opacity,1))}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246/var(--tw-ring-opacity,1))}.active\:cursor-grabbing:active{cursor:grabbing}.group:hover .group-hover\:bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.group:hover .group-hover\:bg-slate-50\/80{background-color:#f8fafccc}.group\/header:hover .group-hover\/header\:opacity-100,.group:hover .group-hover\:opacity-100{opacity:1}
1
+ .flexi-root{width:100%;position:relative}.flexi-root>*+*{margin-top:.75rem}.flexi-groupzone{box-sizing:border-box;background-color:#f8fafc80;border:1px dashed #e2e8f0;border-radius:.75rem;align-items:center;gap:.5rem;width:100%;min-height:52px;padding:.5rem 1rem;transition:all .2s;display:flex}.flexi-groupzone--dragover{background-color:#eff6ff80;border:1px solid #3b82f6;transform:scale(.99)}.flexi-groupzone-hint{color:#64748b;-webkit-user-select:none;user-select:none;font-size:12px;font-weight:500}.flexi-groupzone-chips{flex-wrap:wrap;align-items:center;gap:.375rem;display:flex}.flexi-groupzone-label{text-transform:uppercase;letter-spacing:.05em;color:#64748b;margin-right:.25rem;font-size:11px;font-weight:700}.flexi-chip{color:#64748b;background-color:#fff;border:1px solid #e2e8f0;border-radius:.5rem;align-items:center;gap:.375rem;padding:.25rem .25rem .25rem .5rem;font-size:12px;font-weight:600;display:flex;box-shadow:0 1px 2px #0000000d}.flexi-chip-remove{border-radius:5px;width:18px;height:18px}.flexi-table-wrap{box-sizing:border-box;background-color:#fff;border:1px solid #f1f5f9;border-radius:.75rem;width:100%;overflow:auto;box-shadow:0 1px 2px #0000000d}.flexi-table{caption-side:bottom;border-collapse:collapse;border-spacing:0;table-layout:fixed;width:100%;font-size:.875rem;position:relative}.flexi-table--bordered th,.flexi-table--bordered td{border:1px solid #e2e8f0}.flexi-thead{-webkit-user-select:none;user-select:none;z-index:40;position:sticky}.flexi-header-row{border-bottom:1px solid #f1f5f9}.flexi-group-spacer-th{border-right:1px solid #f1f5f9;width:48px}.flexi-th{text-align:center;vertical-align:middle;z-index:25;background-color:#f8fafc;border-bottom:1px solid #f1f5f9;border-right:1px solid #f1f5f9;height:48px;padding:0 1rem;font-size:12px;font-weight:700;position:sticky;top:0}.flexi-th--draggable{cursor:grab}.flexi-th--draggable:active{cursor:grabbing}.flexi-th--pinned{background-color:#f8fafc}.flexi-th-inner{justify-content:space-between;align-items:center;gap:.25rem;width:100%;min-width:0;display:flex}.flexi-th-label{white-space:nowrap;text-overflow:ellipsis;flex:auto;align-items:center;gap:.375rem;min-width:0;display:flex;overflow:hidden}.flexi-th-label--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.flexi-th-label--sortable:hover{color:#2563eb}.flexi-th-text{white-space:nowrap;text-overflow:ellipsis;flex:auto;min-width:0;overflow:hidden}.flexi-sort-icon{color:#94a3b8;opacity:0;transition:color .15s,opacity .15s}.flexi-sort-icon--active{color:#2563eb;opacity:1}.flexi-th-inner:hover .flexi-sort-icon{opacity:1}.flexi-th-actions{flex:none;align-items:center;gap:2px;display:flex}.flexi-icon-btn{color:#64748b;background-color:#0000;border-radius:6px;justify-content:center;align-items:center;width:22px;height:22px;margin:0;padding:0;transition:background-color .15s,color .15s,transform .1s;display:inline-flex}.flexi-icon-btn:hover{color:#334155;background-color:#e2e8f0}.flexi-icon-btn:active{background-color:#cbd5e1;transform:scale(.92)}.flexi-icon-btn:focus-visible{outline-offset:1px;outline:2px solid #93c5fd}.flexi-filter-btn{color:#64748b;opacity:0}.flexi-filter-btn--active{color:#2563eb;opacity:1}.flexi-filter-btn--active:hover{color:#2563eb;background-color:#dbeafe}.flexi-pin-btn{color:#cbd5e1;opacity:0}.flexi-pin-btn--pinned{color:#3b82f6;opacity:1}.flexi-pin-btn--pinned:hover{color:#2563eb;background-color:#dbeafe}.flexi-th-inner:hover .flexi-filter-btn,.flexi-th-inner:hover .flexi-pin-btn{opacity:1}.flexi-actions-th{vertical-align:middle;text-align:right;height:48px;padding:0 1rem;font-size:12px;font-weight:700;box-shadow:-1px 0 #e2e8f0}.flexi-filter-dropdown{color:#334155;text-align:left;pointer-events:auto;background-color:#fff;border:1px solid #e2e8f0;border-radius:.5rem;flex-direction:column;width:13rem;padding:.5rem 0;font-weight:400;display:flex;position:absolute;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a}.flexi-filter-search{border-bottom:1px solid #f1f5f9;margin-bottom:.25rem;padding:0 .5rem .5rem}.flexi-input{color:#475569;box-sizing:border-box;border:1px solid #e2e8f0;border-radius:.25rem;width:100%;padding:.25rem .5rem;font-size:12px;font-weight:500}.flexi-input:focus{border-color:#3b82f6;outline:none}.flexi-filter-list{flex-direction:column;gap:.25rem;max-height:10rem;padding:0 .5rem;display:flex;overflow-y:auto}.flexi-filter-empty{color:#64748b;text-align:center;padding:.5rem;font-size:11px}.flexi-filter-option{cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:.25rem;align-items:center;gap:.5rem;padding:.375rem .5rem;font-size:12px;display:flex}.flexi-filter-option:hover{background-color:#f8fafc}.flexi-filter-option-text{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.flexi-checkbox{accent-color:#2563eb;border:1px solid #cbd5e1;border-radius:.25rem;width:.875rem;height:.875rem}.flexi-checkbox:focus{outline-offset:1px;outline:2px solid #3b82f6}.flexi-filter-footer{border-top:1px solid #f1f5f9;justify-content:flex-end;margin-top:.5rem;padding:.25rem .5rem 0;display:flex}.flexi-filter-clear{color:#ef4444;padding:.125rem .5rem;font-size:11px;font-weight:500}.flexi-filter-clear:hover{text-decoration:underline}.flexi-tbody{display:table-row-group}.flexi-tbody tr+tr{border-top:1px solid #f1f5f9}.flexi-empty-cell{text-align:center;color:#64748b;padding:2rem;font-size:12px;font-weight:500}.flexi-group-row{-webkit-user-select:none;user-select:none;background-color:#f8fafc99;transition:background-color .15s}.flexi-group-row:hover{background-color:#f1f5f9cc}.flexi-group-cell{color:#334155;border-right:1px solid #f1f5f9;padding:.75rem 1rem;font-size:12px;font-weight:600}.flexi-group-toggle{text-align:left;border-radius:6px;align-items:center;gap:.375rem;margin:-4px -8px -4px -4px;padding:4px 8px 4px 4px;transition:background-color .15s;display:flex}.flexi-group-toggle:hover{background-color:#e2e8f099}.flexi-group-toggle:focus-visible{outline-offset:1px;outline:2px solid #93c5fd}.flexi-icon-muted{color:#64748b}.flexi-group-value{color:#1e293b;white-space:nowrap;text-overflow:ellipsis;width:10rem;font-weight:700;overflow:hidden}.flexi-group-count{color:#64748b;background-color:#e2e8f0b3;border-radius:9999px;margin-left:.25rem;padding:.05rem .375rem;font-size:10px;font-weight:500}.flexi-group-filler{background-color:#f8fafc4d}.flexi-row{border-bottom:1px solid #f1f5f9;height:48px;transition:background-color .15s}.flexi-row:hover{background-color:#f8fafccc}.flexi-row-indent-cell{background-color:#fff;border-right:1px solid #f1f5f9;width:48px}.flexi-cell{vertical-align:middle;padding:.25rem 1rem;transition:background-color .15s}.flexi-row:hover .flexi-cell--pinned{background-color:#f1f5f9}.flexi-cell-text{color:#64748b;white-space:nowrap;text-overflow:ellipsis;font-size:12px;font-weight:500;display:block;overflow:hidden}.flexi-actions-cell{vertical-align:middle;text-align:right;background-color:#fff;padding:.25rem 1rem;box-shadow:-1px 0 #e2e8f0}.flexi-row:hover .flexi-actions-cell{background-color:#f8fafccc}.flexi-tbody--pinned-bottom{box-shadow:0 -2px 5px -2px #0000001a}.flexi-row--pinned-bottom{background-color:#f8fafc;font-weight:600}.flexi-row--pinned-bottom:hover,.flexi-row--pinned-bottom .flexi-cell,.flexi-row--pinned-bottom .flexi-actions-cell{background-color:#f8fafc}.flexi-row--pinned-bottom .flexi-cell-text{color:#334155}.flexi-actions-inner{opacity:0;justify-content:flex-end;gap:.25rem;transition:opacity .15s;display:flex}.flexi-row:hover .flexi-actions-inner{opacity:1}.flexi-icon-xs{width:.75rem;height:.75rem}.flexi-icon-sm{width:.875rem;height:.875rem}.flexi-icon-md{width:1rem;height:1rem}.flexi-root button{appearance:none;cursor:pointer;font:inherit;color:inherit;background:0 0;border:none;margin:0;padding:0;line-height:normal}.flexi-root input{font:inherit}.flexi-root table{border-collapse:collapse;border-spacing:0}
2
2
  /*$vite$:1*/
package/dist/index.es.js CHANGED
@@ -8,41 +8,53 @@ var h = (e) => {
8
8
  return e.forEach((e) => {
9
9
  e.children && e.children.length > 0 ? t.push(...h(e.children)) : t.push(e);
10
10
  }), t;
11
+ }, g = (...e) => e.filter(Boolean).join(" "), _ = (e) => {
12
+ if (e === !0) return "left";
13
+ if (e === "left" || e === "right") return e;
11
14
  };
12
- function g({ columns: g, data: _, rowKey: v, actions: y, isLoading: te, groupBy: b = !1, defaultGroupBy: ne = [], onPinChange: x, onGroupChange: S, containerStyle: C, tableStyle: re }) {
13
- let [w, T] = f(null), [E, D] = f({}), [O, k] = f(""), [A, ie] = f(null), j = d(/* @__PURE__ */ new Map()), [M, N] = f(ne), [P, F] = f({}), [ae, I] = f(!1), [L, oe] = f({
15
+ function v({ columns: v, data: y, rowKey: b, actions: x, isLoading: te, groupBy: S = !1, defaultGroupBy: ne = [], onPinChange: C, onGroupChange: w, containerStyle: re, tableStyle: ie, bordered: ae = !1, pinnedBottomRowData: T = [], pinnedRowClassName: E }) {
16
+ let [D, O] = f(null), [k, A] = f({}), [j, M] = f(""), [N, oe] = f(null), P = d(/* @__PURE__ */ new Map()), [F, I] = f(ne), [L, se] = f({}), [ce, R] = f(!1), [z, le] = f({
14
17
  key: null,
15
18
  direction: null
16
- }), R = u(() => h(g), [g]), [z, se] = f(R.filter((e) => e.pinned).map((e) => e.key)), B = u(() => {
17
- let e = (t) => [...t].sort((e, t) => {
18
- let n = z.includes(e.key), r = z.includes(t.key);
19
- return n && !r ? -1 : !n && r ? 1 : 0;
20
- }).map((t) => t.children && t.children.length > 0 ? {
21
- ...t,
22
- children: e(t.children)
23
- } : t);
24
- return e(g);
25
- }, [g, z]), V = u(() => {
26
- let e = h(B), t = b ? M : [];
19
+ }), B = u(() => h(v), [v]), [V, ue] = f(() => {
20
+ let e = {};
21
+ return B.forEach((t) => {
22
+ let n = _(t.pinned);
23
+ n && (e[t.key] = n);
24
+ }), e;
25
+ }), H = u(() => {
26
+ let e = (t) => {
27
+ let n = (e) => {
28
+ let t = V[e];
29
+ return t === "left" ? 0 : t === "right" ? 2 : 1;
30
+ };
31
+ return [...t].sort((e, t) => n(e.key) - n(t.key)).map((t) => t.children && t.children.length > 0 ? {
32
+ ...t,
33
+ children: e(t.children)
34
+ } : t);
35
+ };
36
+ return e(v);
37
+ }, [v, V]), U = u(() => {
38
+ let e = h(H), t = S ? F : [];
27
39
  return e.filter((e) => !t.includes(e.key));
28
40
  }, [
29
- B,
30
- M,
31
- b
32
- ]), H = d(null), U = d(null);
41
+ H,
42
+ F,
43
+ S
44
+ ]), W = d(null), G = d(null);
33
45
  l(() => {
34
46
  function e(e) {
35
- let t = e.target, n = w ? j.current.get(w) : null;
36
- U.current && !U.current.contains(t) && !(n && n.contains(t)) && (T(null), k(""));
47
+ let t = e.target, n = D ? P.current.get(D) : null;
48
+ G.current && !G.current.contains(t) && !(n && n.contains(t)) && (O(null), M(""));
37
49
  }
38
50
  return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
39
- }, [w]), l(() => {
40
- if (!w) return;
51
+ }, [D]), l(() => {
52
+ if (!D) return;
41
53
  let e = () => {
42
- let e = j.current.get(w), t = H.current;
54
+ let e = P.current.get(D), t = W.current;
43
55
  if (!e || !t) return;
44
56
  let n = e.getBoundingClientRect(), r = t.getBoundingClientRect();
45
- ie({
57
+ oe({
46
58
  top: n.bottom - r.top + 4,
47
59
  left: n.left - r.left
48
60
  });
@@ -50,35 +62,37 @@ function g({ columns: g, data: _, rowKey: v, actions: y, isLoading: te, groupBy:
50
62
  return e(), window.addEventListener("scroll", e, !0), window.addEventListener("resize", e), () => {
51
63
  window.removeEventListener("scroll", e, !0), window.removeEventListener("resize", e);
52
64
  };
53
- }, [w]);
54
- let W = (e) => typeof v == "function" ? v(e) : String(e[v]), G = (e) => {
55
- let t = z.includes(e);
56
- se(t ? z.filter((t) => t !== e) : [...z, e]), x && x(e, !t);
57
- }, ce = (e) => {
65
+ }, [D]);
66
+ let de = (e) => typeof b == "function" ? b(e) : String(e[b]), fe = (e) => {
67
+ ue((t) => {
68
+ let n = t[e], r = n ? n === "left" ? "right" : void 0 : "left", i = { ...t };
69
+ return r ? i[e] = r : delete i[e], C && C(e, !!r, r), i;
70
+ });
71
+ }, pe = (e) => {
58
72
  let t = "asc";
59
- L.key === e && (t = L.direction === "asc" ? "desc" : L.direction === "desc" ? null : "asc"), oe({
73
+ z.key === e && (t = z.direction === "asc" ? "desc" : z.direction === "desc" ? null : "asc"), le({
60
74
  key: t ? e : null,
61
75
  direction: t
62
76
  });
63
- }, le = (e, t) => {
64
- b && (e.dataTransfer.setData("text/plain", t), e.dataTransfer.effectAllowed = "move");
65
- }, ue = (e) => {
66
- e.preventDefault(), I(!1);
77
+ }, me = (e, t) => {
78
+ S && (e.dataTransfer.setData("text/plain", t), e.dataTransfer.effectAllowed = "move");
79
+ }, he = (e) => {
80
+ e.preventDefault(), R(!1);
67
81
  let t = e.dataTransfer.getData("text/plain");
68
- if (t && !M.includes(t)) {
69
- let e = [...M, t];
70
- N(e), S && S(e);
82
+ if (t && !F.includes(t)) {
83
+ let e = [...F, t];
84
+ I(e), w && w(e);
71
85
  }
72
- }, de = (e) => {
73
- let t = M.filter((t) => t !== e);
74
- N(t), F({}), S && S(t);
86
+ }, ge = (e) => {
87
+ let t = F.filter((t) => t !== e);
88
+ I(t), se({}), w && w(t);
75
89
  }, K = u(() => {
76
90
  let e = (t) => {
77
91
  let n = 0;
78
92
  return t.forEach((t) => {
79
93
  n = t.children && t.children.length > 0 ? Math.max(n, 1 + e(t.children)) : Math.max(n, 1);
80
94
  }), n;
81
- }, t = e(B), n = Array.from({ length: t }, () => []), r = (e) => !e.children || e.children.length === 0 ? M.includes(e.key) && b ? 0 : 1 : e.children.reduce((e, t) => e + r(t), 0), i = b ? M : [], a = (e, o) => {
95
+ }, t = e(H), n = Array.from({ length: t }, () => []), r = (e) => !e.children || e.children.length === 0 ? F.includes(e.key) && S ? 0 : 1 : e.children.reduce((e, t) => e + r(t), 0), i = S ? F : [], a = (e, o) => {
82
96
  e.forEach((e) => {
83
97
  if (i.includes(e.key)) return;
84
98
  let s = r(e);
@@ -93,55 +107,67 @@ function g({ columns: g, data: _, rowKey: v, actions: y, isLoading: te, groupBy:
93
107
  }));
94
108
  });
95
109
  };
96
- return a(B, 0), n.filter((e) => e.length > 0);
110
+ return a(H, 0), n.filter((e) => e.length > 0);
97
111
  }, [
98
- B,
99
- M,
100
- b
101
- ]), q = u(() => {
112
+ H,
113
+ F,
114
+ S
115
+ ]), q = (e) => {
116
+ let t = e.style?.width || e.headerStyle?.width || "150px";
117
+ return typeof t == "number" ? t : parseInt(String(t), 10) || 150;
118
+ }, _e = u(() => {
102
119
  let e = {}, t = 0;
103
- return b && M.length > 0 && (t += 48), V.forEach((n) => {
104
- if (z.includes(n.key)) {
105
- e[n.key] = t;
106
- let r = n.style?.width || n.headerStyle?.width || "150px";
107
- t += typeof r == "number" ? r : parseInt(String(r), 10) || 150;
108
- }
109
- }), e;
120
+ S && F.length > 0 && (t += 48), U.forEach((n) => {
121
+ V[n.key] === "left" && (e[n.key] = {
122
+ side: "left",
123
+ offset: t
124
+ }, t += q(n));
125
+ });
126
+ let n = x ? 100 : 0;
127
+ for (let t = U.length - 1; t >= 0; t--) {
128
+ let r = U[t];
129
+ V[r.key] === "right" && (e[r.key] = {
130
+ side: "right",
131
+ offset: n
132
+ }, n += q(r));
133
+ }
134
+ return e;
110
135
  }, [
136
+ U,
111
137
  V,
112
- z,
113
- M,
114
- b
115
- ]), fe = (e, t) => {
116
- D((n) => {
138
+ F,
139
+ S,
140
+ x
141
+ ]), ve = (e, t) => {
142
+ A((n) => {
117
143
  let r = n[e] || [], i = r.includes(t) ? r.filter((e) => e !== t) : [...r, t], a = {
118
144
  ...n,
119
145
  [e]: i
120
146
  };
121
147
  return a[e].length === 0 && delete a[e], a;
122
148
  });
123
- }, pe = (e) => {
124
- D((t) => {
149
+ }, ye = (e) => {
150
+ A((t) => {
125
151
  let n = { ...t };
126
152
  return delete n[e], n;
127
153
  });
128
154
  }, J = u(() => {
129
- if (!w) return [];
130
- let e = R.find((e) => e.key === w), t = _.map((t) => e?.getValue ? e.getValue(t) : t[w]), n = Array.from(new Set(t)).filter((e) => e != null);
131
- return O.trim() ? n.filter((e) => String(e).toLowerCase().includes(O.toLowerCase())) : n;
155
+ if (!D) return [];
156
+ let e = B.find((e) => e.key === D), t = y.map((t) => e?.getValue ? e.getValue(t) : t[D]), n = Array.from(new Set(t)).filter((e) => e != null);
157
+ return j.trim() ? n.filter((e) => String(e).toLowerCase().includes(j.toLowerCase())) : n;
132
158
  }, [
133
- _,
134
- w,
135
- O,
136
- R
159
+ y,
160
+ D,
161
+ j,
162
+ B
137
163
  ]), Y = u(() => {
138
- let e = _.filter((e) => Object.entries(E).every(([t, n]) => {
164
+ let e = y.filter((e) => Object.entries(k).every(([t, n]) => {
139
165
  if (!n || n.length === 0) return !0;
140
- let r = R.find((e) => e.key === t), i = r?.getValue ? r.getValue(e) : e[t];
166
+ let r = B.find((e) => e.key === t), i = r?.getValue ? r.getValue(e) : e[t];
141
167
  return n.includes(i);
142
168
  }));
143
- if (L.key && L.direction) {
144
- let { key: t, direction: n } = L, r = R.find((e) => e.key === t);
169
+ if (z.key && z.direction) {
170
+ let { key: t, direction: n } = z, r = B.find((e) => e.key === t);
145
171
  e = [...e].sort((e, i) => {
146
172
  let a = r?.getValue ? r.getValue(e) : e[t], o = r?.getValue ? r.getValue(i) : i[t];
147
173
  if (a === o) return 0;
@@ -156,15 +182,15 @@ function g({ columns: g, data: _, rowKey: v, actions: y, isLoading: te, groupBy:
156
182
  }
157
183
  return e;
158
184
  }, [
159
- _,
160
- E,
161
- L,
162
- R
185
+ y,
186
+ k,
187
+ z,
188
+ B
163
189
  ]), X = u(() => {
164
- if (!b || M.length === 0) return Y;
190
+ if (!S || F.length === 0) return Y;
165
191
  let e = (t, n, r = "") => {
166
- if (n >= M.length) return t;
167
- let i = M[n], a = R.find((e) => e.key === i), o = {};
192
+ if (n >= F.length) return t;
193
+ let i = F[n], a = B.find((e) => e.key === i), o = {};
168
194
  return t.forEach((e) => {
169
195
  let t = a?.getValue ? a.getValue(e) : e[i], n = String(t ?? "N/A");
170
196
  o[n] || (o[n] = []), o[n].push(e);
@@ -184,11 +210,11 @@ function g({ columns: g, data: _, rowKey: v, actions: y, isLoading: te, groupBy:
184
210
  return e(Y, 0);
185
211
  }, [
186
212
  Y,
187
- M,
188
- b,
189
- R
190
- ]), me = (e) => {
191
- F((t) => {
213
+ F,
214
+ S,
215
+ B
216
+ ]), be = (e) => {
217
+ se((t) => {
192
218
  let n = t[e] !== !1;
193
219
  return {
194
220
  ...t,
@@ -196,182 +222,193 @@ function g({ columns: g, data: _, rowKey: v, actions: y, isLoading: te, groupBy:
196
222
  };
197
223
  });
198
224
  }, Z = u(() => {
199
- if (!b || M.length === 0) return X;
225
+ if (!S || F.length === 0) return X;
200
226
  let e = [], t = (n) => {
201
227
  n.forEach((n) => {
202
- n.isGroupRow ? (e.push(n), P[n.path] !== !1 && t(n.children)) : e.push(n);
228
+ n.isGroupRow ? (e.push(n), L[n.path] !== !1 && t(n.children)) : e.push(n);
203
229
  });
204
230
  };
205
231
  return t(X), e;
206
232
  }, [
207
233
  X,
208
- P,
209
- M,
210
- b
211
- ]), Q = (e, t = !1, n) => z.includes(e) ? {
212
- position: "sticky",
213
- left: `${q[e]}px`,
214
- zIndex: t ? 30 : 20,
215
- backgroundColor: "#fff",
216
- boxShadow: "2px 0 5px -2px rgba(0,0,0,0.1)",
217
- ...n
218
- } : n || {}, $ = V.length + +!!y + (b && M.length > 0 ? 1 : 0);
234
+ L,
235
+ F,
236
+ S
237
+ ]), Q = (e, t = !1, n) => {
238
+ let r = _e[e];
239
+ if (!r) return n || {};
240
+ let i = r.side === "right";
241
+ return {
242
+ position: "sticky",
243
+ [i ? "right" : "left"]: `${r.offset}px`,
244
+ ...t ? { top: 0 } : {},
245
+ zIndex: t ? 30 : 20,
246
+ boxShadow: i ? "-2px 0 5px -2px rgba(0,0,0,0.1)" : "2px 0 5px -2px rgba(0,0,0,0.1)",
247
+ ...n
248
+ };
249
+ }, xe = u(() => T.map((e, t) => (T.length - 1 - t) * 48), [T]), $ = U.length + +!!x + (S && F.length > 0 ? 1 : 0);
219
250
  return /* @__PURE__ */ m("div", {
220
- ref: H,
221
- className: "w-full space-y-3 relative",
222
- children: [b && /* @__PURE__ */ p("div", {
251
+ ref: W,
252
+ className: "flexi-root",
253
+ children: [S && /* @__PURE__ */ p("div", {
223
254
  onDragOver: (e) => {
224
- e.preventDefault(), I(!0);
255
+ e.preventDefault(), R(!0);
225
256
  },
226
- onDragLeave: () => I(!1),
227
- onDrop: ue,
228
- className: `w-full min-h-[52px] px-4 py-2 border rounded-xl flex items-center gap-2 transition-all duration-200 ${ae ? "border-blue-500 bg-blue-50/50 scale-[0.99]" : "border-dashed border-slate-200 bg-slate-50/50"}`,
229
- children: M.length === 0 ? /* @__PURE__ */ p("span", {
230
- className: "text-[12px] text-muted-foreground font-medium select-none",
257
+ onDragLeave: () => R(!1),
258
+ onDrop: he,
259
+ className: g("flexi-groupzone", ce && "flexi-groupzone--dragover"),
260
+ children: F.length === 0 ? /* @__PURE__ */ p("span", {
261
+ className: "flexi-groupzone-hint",
231
262
  children: "Drag a column header here to group your records by that field"
232
263
  }) : /* @__PURE__ */ m("div", {
233
- className: "flex flex-wrap items-center gap-1.5",
264
+ className: "flexi-groupzone-chips",
234
265
  children: [/* @__PURE__ */ p("span", {
235
- className: "text-[11px] font-bold uppercase tracking-wider text-muted-foreground mr-1",
266
+ className: "flexi-groupzone-label",
236
267
  children: "Grouped By:"
237
- }), M.map((e) => /* @__PURE__ */ m("div", {
238
- className: "flex items-center gap-1.5 pl-2 pr-1 py-1 bg-white border border-slate-200 rounded-lg shadow-sm text-[12px] font-semibold text-muted-foreground",
239
- children: [/* @__PURE__ */ p("span", { children: R.find((t) => t.key === e)?.header || e }), /* @__PURE__ */ p("button", {
240
- onClick: () => de(e),
241
- className: "p-0.5 rounded-md hover:bg-slate-100 text-muted-foreground transition-colors",
242
- children: /* @__PURE__ */ p(c, { className: "w-3 h-3" })
268
+ }), F.map((e) => /* @__PURE__ */ m("div", {
269
+ className: "flexi-chip",
270
+ children: [/* @__PURE__ */ p("span", { children: B.find((t) => t.key === e)?.header || e }), /* @__PURE__ */ p("button", {
271
+ type: "button",
272
+ onClick: () => ge(e),
273
+ className: "flexi-icon-btn flexi-chip-remove",
274
+ children: /* @__PURE__ */ p(c, { className: "flexi-icon-xs" })
243
275
  })]
244
276
  }, e))]
245
277
  })
246
278
  }), /* @__PURE__ */ p("div", {
247
- className: "w-full overflow-x-auto border border-slate-100 rounded-xl bg-white shadow-sm",
248
- style: C,
279
+ className: "flexi-table-wrap",
280
+ style: re,
249
281
  children: /* @__PURE__ */ m("table", {
250
- className: "w-full caption-bottom text-sm border-collapse table-fixed",
251
- style: re,
282
+ className: g("flexi-table", ae && "flexi-table--bordered"),
283
+ style: ie,
252
284
  children: [
253
285
  /* @__PURE__ */ m("colgroup", { children: [
254
- b && M.length > 0 && /* @__PURE__ */ p("col", { style: { width: "48px" } }),
255
- V.map((e) => /* @__PURE__ */ p("col", { style: e.style }, e.key)),
256
- y && /* @__PURE__ */ p("col", { style: { width: "100px" } })
286
+ S && F.length > 0 && /* @__PURE__ */ p("col", { style: { width: "48px" } }),
287
+ U.map((e) => /* @__PURE__ */ p("col", { style: e.style }, e.key)),
288
+ x && /* @__PURE__ */ p("col", { style: { width: "100px" } })
257
289
  ] }),
258
290
  /* @__PURE__ */ p("thead", {
259
- className: "bg-slate-50 select-none",
291
+ className: "flexi-thead",
260
292
  children: K.map((r, i) => /* @__PURE__ */ m("tr", {
261
- className: "border-b border-slate-100",
293
+ className: "flexi-header-row",
262
294
  children: [
263
- i === 0 && b && M.length > 0 && /* @__PURE__ */ p("th", {
295
+ i === 0 && S && F.length > 0 && /* @__PURE__ */ p("th", {
264
296
  rowSpan: K.length,
265
- className: "w-12 border-r border-slate-100",
297
+ className: "flexi-group-spacer-th",
266
298
  style: {
267
299
  position: "sticky",
300
+ top: 0,
268
301
  left: 0,
269
302
  zIndex: 35,
270
303
  backgroundColor: "rgb(248, 250, 252)"
271
304
  }
272
305
  }),
273
306
  r.map(({ col: r, rowSpan: i, colSpan: c }) => {
274
- let l = (E[r.key]?.length || 0) > 0, u = z.includes(r.key), d = Q(r.key, !0, r.headerStyle), f = !r.children || r.children.length === 0, h = L.key === r.key;
307
+ let l = (k[r.key]?.length || 0) > 0, u = !!V[r.key], d = Q(r.key, !0, r.headerStyle), f = !r.children || r.children.length === 0, h = z.key === r.key, _ = !!(S && f);
275
308
  return /* @__PURE__ */ p("th", {
276
309
  rowSpan: i,
277
310
  colSpan: c,
278
- ...b && f ? {
311
+ ..._ ? {
279
312
  draggable: !0,
280
- onDragStart: (e) => le(e, r.key)
313
+ onDragStart: (e) => me(e, r.key)
281
314
  } : {},
282
- className: `h-12 text-center align-middle font-bold text-[12px] px-4 border-r border-b border-slate-100 relative ${b && f ? "cursor-grab active:cursor-grabbing" : ""} ${u ? "bg-slate-50/90" : ""} ${r.className || ""}`,
315
+ className: g("flexi-th", _ && "flexi-th--draggable", u && "flexi-th--pinned", r.className),
283
316
  style: d,
284
317
  children: /* @__PURE__ */ m("div", {
285
- className: "flex items-center gap-1 group/header w-full justify-between",
318
+ className: "flexi-th-inner",
286
319
  children: [
287
320
  /* @__PURE__ */ m("div", {
288
- className: `flex items-center gap-1.5 truncate w-full ${r.sortable && f ? "cursor-pointer select-none hover:text-blue-600" : ""}`,
289
- onClick: () => r.sortable && f && ce(r.key),
321
+ className: g("flexi-th-label", r.sortable && f && "flexi-th-label--sortable"),
322
+ onClick: () => r.sortable && f && pe(r.key),
290
323
  children: [/* @__PURE__ */ p("span", {
291
- className: "truncate",
324
+ className: "flexi-th-text",
292
325
  children: r.header
293
326
  }), f && r.sortable && /* @__PURE__ */ p("span", {
294
- className: `text-slate-400 transition-colors ${h ? "text-blue-600" : "opacity-0 group-hover/header:opacity-100"}`,
295
- children: h && L.direction === "asc" ? /* @__PURE__ */ p(t, { className: "w-3.5 h-3.5" }) : h && L.direction === "desc" ? /* @__PURE__ */ p(e, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ p(n, { className: "w-3.5 h-3.5" })
327
+ className: g("flexi-sort-icon", h && "flexi-sort-icon--active"),
328
+ children: h && z.direction === "asc" ? /* @__PURE__ */ p(t, { className: "flexi-icon-sm" }) : h && z.direction === "desc" ? /* @__PURE__ */ p(e, { className: "flexi-icon-sm" }) : /* @__PURE__ */ p(n, { className: "flexi-icon-sm" })
296
329
  })]
297
330
  }),
298
331
  /* @__PURE__ */ m("div", {
299
- className: "flex items-center gap-1",
332
+ className: "flexi-th-actions",
300
333
  children: [f && r.filterable && /* @__PURE__ */ p("button", {
334
+ type: "button",
301
335
  ref: (e) => {
302
- e ? j.current.set(r.key, e) : j.current.delete(r.key);
336
+ e ? P.current.set(r.key, e) : P.current.delete(r.key);
303
337
  },
304
338
  onClick: (e) => {
305
- e.stopPropagation(), k(""), T(w === r.key ? null : r.key);
339
+ e.stopPropagation(), M(""), O(D === r.key ? null : r.key);
306
340
  },
307
- className: `p-0.5 rounded hover:bg-slate-200 transition-colors ${l ? "text-blue-600" : "text-muted-foreground opacity-0 group-hover/header:opacity-100"}`,
308
- children: /* @__PURE__ */ p(a, { className: "w-3.5 h-3.5" })
341
+ className: g("flexi-icon-btn", "flexi-filter-btn", l && "flexi-filter-btn--active"),
342
+ children: /* @__PURE__ */ p(a, { className: "flexi-icon-sm" })
309
343
  }), f && /* @__PURE__ */ p("button", {
344
+ type: "button",
310
345
  onClick: (e) => {
311
- e.stopPropagation(), G(r.key);
346
+ e.stopPropagation(), fe(r.key);
312
347
  },
313
- className: `p-0.5 rounded hover:bg-slate-200 transition-colors opacity-0 group-hover/header:opacity-100 ${u ? "text-blue-500 opacity-100" : "text-slate-300"}`,
314
- title: u ? "Unpin column" : "Pin column",
315
- children: p(u ? s : o, { className: "w-3.5 h-3.5" })
348
+ className: g("flexi-icon-btn", "flexi-pin-btn", u && "flexi-pin-btn--pinned"),
349
+ title: V[r.key] === "left" ? "Pinned left (click to pin right)" : V[r.key] === "right" ? "Pinned right (click to unpin)" : "Pin column left",
350
+ children: p(u ? s : o, { className: "flexi-icon-sm" })
316
351
  })]
317
352
  }),
318
- w === r.key && f && A && H.current && ee(/* @__PURE__ */ m("div", {
319
- ref: U,
320
- className: "absolute w-52 bg-white border border-slate-200 rounded-lg shadow-lg py-2 flex flex-col font-normal text-slate-700 text-left pointer-events-auto",
353
+ D === r.key && f && N && W.current && ee(/* @__PURE__ */ m("div", {
354
+ ref: G,
355
+ className: "flexi-filter-dropdown",
321
356
  style: {
322
- top: A.top,
323
- left: A.left,
357
+ top: N.top,
358
+ left: N.left,
324
359
  zIndex: 9999
325
360
  },
326
361
  children: [
327
362
  /* @__PURE__ */ p("div", {
328
- className: "px-2 pb-2 mb-1 border-b border-slate-100",
363
+ className: "flexi-filter-search",
329
364
  children: /* @__PURE__ */ p("input", {
330
365
  type: "text",
331
366
  placeholder: "Search values...",
332
- value: O,
333
- onChange: (e) => k(e.target.value),
334
- className: "w-full px-2 py-1 text-[12px] border border-slate-200 rounded focus:outline-none focus:border-blue-500 font-medium text-slate-600",
367
+ value: j,
368
+ onChange: (e) => M(e.target.value),
369
+ className: "flexi-input",
335
370
  onClick: (e) => e.stopPropagation()
336
371
  })
337
372
  }),
338
373
  /* @__PURE__ */ p("div", {
339
- className: "max-h-40 overflow-y-auto px-2 space-y-1",
374
+ className: "flexi-filter-list",
340
375
  children: J.length === 0 ? /* @__PURE__ */ p("div", {
341
- className: "text-[11px] text-muted-foreground p-2 text-center",
376
+ className: "flexi-filter-empty",
342
377
  children: "No results found"
343
378
  }) : J.map((e, t) => /* @__PURE__ */ m("label", {
344
- className: "flex items-center gap-2 px-2 py-1.5 text-[12px] rounded hover:bg-slate-50 cursor-pointer select-none",
379
+ className: "flexi-filter-option",
345
380
  children: [/* @__PURE__ */ p("input", {
346
381
  type: "checkbox",
347
- className: "rounded border-slate-300 text-blue-600 focus:ring-blue-500 w-3.5 h-3.5",
348
- checked: E[r.key]?.includes(e) || !1,
349
- onChange: () => fe(r.key, e)
382
+ className: "flexi-checkbox",
383
+ checked: k[r.key]?.includes(e) || !1,
384
+ onChange: () => ve(r.key, e)
350
385
  }), /* @__PURE__ */ p("span", {
351
- className: "truncate",
386
+ className: "flexi-filter-option-text",
352
387
  children: String(e)
353
388
  })]
354
389
  }, t))
355
390
  }),
356
391
  l && /* @__PURE__ */ p("div", {
357
- className: "border-t border-slate-100 mt-2 pt-1 px-2 flex justify-end",
392
+ className: "flexi-filter-footer",
358
393
  children: /* @__PURE__ */ p("button", {
359
- onClick: () => pe(r.key),
360
- className: "text-[11px] text-red-500 hover:underline font-medium px-2 py-0.5",
394
+ type: "button",
395
+ onClick: () => ye(r.key),
396
+ className: "flexi-filter-clear",
361
397
  children: "Clear Filter"
362
398
  })
363
399
  })
364
400
  ]
365
- }), H.current)
401
+ }), W.current)
366
402
  ]
367
403
  })
368
404
  }, r.key);
369
405
  }),
370
- i === 0 && y && /* @__PURE__ */ p("th", {
406
+ i === 0 && x && /* @__PURE__ */ p("th", {
371
407
  rowSpan: K.length,
372
- className: "h-12 align-middle font-bold text-[12px] px-4 text-right shadow-[-1px_0_0_rgba(226,232,240,1)]",
408
+ className: "flexi-actions-th",
373
409
  style: {
374
410
  position: "sticky",
411
+ top: 0,
375
412
  right: 0,
376
413
  zIndex: 35,
377
414
  backgroundColor: "rgb(248, 250, 252)"
@@ -381,92 +418,142 @@ function g({ columns: g, data: _, rowKey: v, actions: y, isLoading: te, groupBy:
381
418
  }, `header-row-${i}`))
382
419
  }),
383
420
  /* @__PURE__ */ p("tbody", {
384
- className: "divide-y divide-slate-100",
421
+ className: "flexi-tbody",
385
422
  children: te ? /* @__PURE__ */ p("tr", { children: /* @__PURE__ */ p("td", {
386
423
  colSpan: $,
387
- className: "p-8 text-center text-muted-foreground text-[12px] font-medium",
424
+ className: "flexi-empty-cell",
388
425
  children: "Loading records..."
389
426
  }) }) : Z.length === 0 ? /* @__PURE__ */ p("tr", { children: /* @__PURE__ */ p("td", {
390
427
  colSpan: $,
391
- className: "p-8 text-center text-muted-foreground text-[12px] font-medium",
428
+ className: "flexi-empty-cell",
392
429
  children: "No records found matching criteria."
393
- }) }) : Z.map((e, t) => {
394
- if (e.isGroupRow) {
395
- let n = P[e.path] !== !1;
396
- return /* @__PURE__ */ m("tr", {
397
- className: "bg-slate-50/60 hover:bg-slate-100/80 transition-colors select-none",
398
- children: [/* @__PURE__ */ p("td", {
399
- className: "p-3 pl-4 font-semibold text-slate-700 text-[12px] border-r border-slate-100",
400
- style: {
401
- position: "sticky",
402
- left: 0,
403
- zIndex: 20,
404
- backgroundColor: "rgba(248, 250, 252, 0.9)",
405
- paddingLeft: `${e.depth * 12 + 16}px`
406
- },
407
- children: /* @__PURE__ */ m("button", {
408
- onClick: () => me(e.path),
409
- className: "flex items-center gap-1.5 text-left focus:outline-none focus:ring-1 focus:ring-blue-400 rounded p-0.5",
410
- children: [
411
- p(n ? r : i, { className: "w-4 h-4 text-slate-500" }),
412
- /* @__PURE__ */ p("span", {
413
- className: "text-slate-800 font-bold w-40 truncate",
414
- children: e.groupValue
415
- }),
416
- /* @__PURE__ */ p("span", {
417
- className: "bg-slate-200/70 text-muted-foreground font-medium text-[10px] px-1.5 py-0.2 rounded-full ml-1",
418
- children: e.totalItemsCount
419
- })
420
- ]
421
- })
422
- }), /* @__PURE__ */ p("td", {
423
- colSpan: $ - 1,
424
- className: "bg-slate-50/30"
425
- })]
426
- }, `group-header-${e.path}-${t}`);
427
- }
428
- return /* @__PURE__ */ m("tr", {
429
- className: "border-b border-slate-100 h-12 hover:bg-slate-50/80 transition-colors group",
430
- children: [
431
- b && M?.length > 0 && /* @__PURE__ */ p("td", {
432
- className: "w-12 bg-white border-r border-slate-100",
433
- style: {
434
- position: "sticky",
435
- left: 0,
436
- zIndex: 10
437
- }
438
- }),
439
- V?.map((t) => {
440
- let n = e[t.key], r = Q(t.key, !1, t.style);
441
- return /* @__PURE__ */ p("td", {
442
- className: `p-4 align-middle py-1 px-4 transition-colors ${z.includes(t.key) ? "group-hover:bg-slate-100" : ""} ${t.className || ""}`,
443
- style: r,
444
- children: t.render ? t.render(n, e) : /* @__PURE__ */ p("span", {
445
- className: "text-[12px] text-muted-foreground font-medium truncate block",
446
- children: n
447
- })
448
- }, t.key);
449
- }),
450
- y && /* @__PURE__ */ p("td", {
451
- className: "p-4 align-middle py-1 px-4 text-right bg-white shadow-[-1px_0_0_rgba(226,232,240,1)] group-hover:bg-slate-50/80",
452
- style: {
453
- position: "sticky",
454
- right: 0,
455
- zIndex: 20
456
- },
457
- children: /* @__PURE__ */ p("div", {
458
- className: "flex justify-end gap-1 opacity-0 group-hover:opacity-100 transition-opacity duration-150",
459
- children: y(e)
460
- })
461
- })
462
- ]
463
- }, W(e) ?? `row-${t}`);
464
- })
430
+ }) }) : Z.map((e, t) => Se(e, t))
431
+ }),
432
+ T.length > 0 && /* @__PURE__ */ p("tbody", {
433
+ className: "flexi-tbody flexi-tbody--pinned-bottom",
434
+ children: T.map((e, t) => Ce(e, t))
465
435
  })
466
436
  ]
467
437
  })
468
438
  })]
469
439
  });
440
+ function Se(e, t) {
441
+ if (e.isGroupRow) {
442
+ let n = L[e.path] !== !1;
443
+ return /* @__PURE__ */ m("tr", {
444
+ className: "flexi-group-row",
445
+ children: [/* @__PURE__ */ p("td", {
446
+ className: "flexi-group-cell",
447
+ style: {
448
+ position: "sticky",
449
+ left: 0,
450
+ zIndex: 20,
451
+ backgroundColor: "rgba(248, 250, 252, 0.9)",
452
+ paddingLeft: `${e.depth * 12 + 16}px`
453
+ },
454
+ children: /* @__PURE__ */ m("button", {
455
+ type: "button",
456
+ onClick: () => be(e.path),
457
+ className: "flexi-group-toggle",
458
+ children: [
459
+ p(n ? r : i, { className: "flexi-icon-md flexi-icon-muted" }),
460
+ /* @__PURE__ */ p("span", {
461
+ className: "flexi-group-value",
462
+ children: e.groupValue
463
+ }),
464
+ /* @__PURE__ */ p("span", {
465
+ className: "flexi-group-count",
466
+ children: e.totalItemsCount
467
+ })
468
+ ]
469
+ })
470
+ }), /* @__PURE__ */ p("td", {
471
+ colSpan: $ - 1,
472
+ className: "flexi-group-filler"
473
+ })]
474
+ }, `group-header-${e.path}-${t}`);
475
+ }
476
+ let n = de(e);
477
+ return /* @__PURE__ */ m("tr", {
478
+ className: "flexi-row",
479
+ children: [
480
+ S && F?.length > 0 && /* @__PURE__ */ p("td", {
481
+ className: "flexi-row-indent-cell",
482
+ style: {
483
+ position: "sticky",
484
+ left: 0,
485
+ zIndex: 10
486
+ }
487
+ }),
488
+ U?.map((t) => {
489
+ let n = e[t.key], r = Q(t.key, !1, t.style);
490
+ return /* @__PURE__ */ p("td", {
491
+ className: g("flexi-cell", !!V[t.key] && "flexi-cell--pinned", t.className),
492
+ style: r,
493
+ children: t.render ? t.render(n, e) : /* @__PURE__ */ p("span", {
494
+ className: "flexi-cell-text",
495
+ children: n
496
+ })
497
+ }, t.key);
498
+ }),
499
+ x && /* @__PURE__ */ p("td", {
500
+ className: "flexi-actions-cell",
501
+ style: {
502
+ position: "sticky",
503
+ right: 0
504
+ },
505
+ children: /* @__PURE__ */ p("div", {
506
+ className: "flexi-actions-inner",
507
+ children: x(e)
508
+ })
509
+ })
510
+ ]
511
+ }, n ?? `row-${t}`);
512
+ }
513
+ function Ce(e, t) {
514
+ let n = typeof E == "function" ? E(e, t) : E, r = {
515
+ position: "sticky",
516
+ bottom: `${xe[t]}px`,
517
+ background: "#",
518
+ zIndex: 45
519
+ };
520
+ return /* @__PURE__ */ m("tr", {
521
+ className: g("flexi-row", "flexi-row--pinned-bottom", n),
522
+ style: r,
523
+ children: [
524
+ S && F?.length > 0 && /* @__PURE__ */ p("td", {
525
+ className: "flexi-row-indent-cell",
526
+ style: {
527
+ position: "sticky",
528
+ left: 0,
529
+ zIndex: 10
530
+ }
531
+ }),
532
+ U?.map((t) => {
533
+ let n = e[t.key], r = Q(t.key, !1, t.style), i = !!V[t.key], a = t.pinnedRender ?? t.render;
534
+ return /* @__PURE__ */ p("td", {
535
+ className: g("flexi-cell", i && "flexi-cell--pinned", t.className),
536
+ style: r,
537
+ children: a ? a(n, e) : /* @__PURE__ */ p("span", {
538
+ className: "flexi-cell-text",
539
+ children: n
540
+ })
541
+ }, t.key);
542
+ }),
543
+ x && /* @__PURE__ */ p("td", {
544
+ className: "flexi-actions-cell",
545
+ style: {
546
+ position: "sticky",
547
+ right: 0
548
+ },
549
+ children: /* @__PURE__ */ p("div", {
550
+ className: "flexi-actions-inner",
551
+ children: x(e)
552
+ })
553
+ })
554
+ ]
555
+ }, `pinned-bottom-row-${t}`);
556
+ }
470
557
  }
471
558
  //#endregion
472
- export { g as DataTable };
559
+ export { v as DataTable };
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("lucide-react"),require("react"),require("react-dom"),require("react/jsx-runtime")):typeof define==`function`&&define.amd?define([`exports`,`lucide-react`,`react`,`react-dom`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.FlexiDataGrid={},e.LucideReact,e.React,e.ReactDOM,e.JSX))})(this,function(e,t,n,r,i){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var a=Object.create,o=Object.defineProperty,s=Object.getOwnPropertyDescriptor,c=Object.getOwnPropertyNames,l=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty,d=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=c(t),a=0,l=i.length,d;a<l;a++)d=i[a],!u.call(e,d)&&d!==n&&o(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=s(t,d))||r.enumerable});return e};n=((e,t,n)=>(n=e==null?{}:a(l(e)),d(t||!e||!e.__esModule?o(n,`default`,{value:e,enumerable:!0}):n,e)))(n,1);var f=e=>{let t=[];return e.forEach(e=>{e.children&&e.children.length>0?t.push(...f(e.children)):t.push(e)}),t};function p({columns:e,data:a,rowKey:o,actions:s,isLoading:c,groupBy:l=!1,defaultGroupBy:u=[],onPinChange:d,onGroupChange:p,containerStyle:ee,tableStyle:m}){let[h,g]=(0,n.useState)(null),[_,v]=(0,n.useState)({}),[y,b]=(0,n.useState)(``),[x,S]=(0,n.useState)(null),C=(0,n.useRef)(new Map),[w,T]=(0,n.useState)(u),[E,D]=(0,n.useState)({}),[O,k]=(0,n.useState)(!1),[A,te]=(0,n.useState)({key:null,direction:null}),j=(0,n.useMemo)(()=>f(e),[e]),[M,N]=(0,n.useState)(j.filter(e=>e.pinned).map(e=>e.key)),P=(0,n.useMemo)(()=>{let t=e=>[...e].sort((e,t)=>{let n=M.includes(e.key),r=M.includes(t.key);return n&&!r?-1:!n&&r?1:0}).map(e=>e.children&&e.children.length>0?{...e,children:t(e.children)}:e);return t(e)},[e,M]),F=(0,n.useMemo)(()=>{let e=f(P),t=l?w:[];return e.filter(e=>!t.includes(e.key))},[P,w,l]),I=(0,n.useRef)(null),L=(0,n.useRef)(null);(0,n.useEffect)(()=>{function e(e){let t=e.target,n=h?C.current.get(h):null;L.current&&!L.current.contains(t)&&!(n&&n.contains(t))&&(g(null),b(``))}return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[h]),(0,n.useEffect)(()=>{if(!h)return;let e=()=>{let e=C.current.get(h),t=I.current;if(!e||!t)return;let n=e.getBoundingClientRect(),r=t.getBoundingClientRect();S({top:n.bottom-r.top+4,left:n.left-r.left})};return e(),window.addEventListener(`scroll`,e,!0),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`scroll`,e,!0),window.removeEventListener(`resize`,e)}},[h]);let R=e=>typeof o==`function`?o(e):String(e[o]),z=e=>{let t=M.includes(e);N(t?M.filter(t=>t!==e):[...M,e]),d&&d(e,!t)},B=e=>{let t=`asc`;A.key===e&&(t=A.direction===`asc`?`desc`:A.direction===`desc`?null:`asc`),te({key:t?e:null,direction:t})},V=(e,t)=>{l&&(e.dataTransfer.setData(`text/plain`,t),e.dataTransfer.effectAllowed=`move`)},H=e=>{e.preventDefault(),k(!1);let t=e.dataTransfer.getData(`text/plain`);if(t&&!w.includes(t)){let e=[...w,t];T(e),p&&p(e)}},U=e=>{let t=w.filter(t=>t!==e);T(t),D({}),p&&p(t)},W=(0,n.useMemo)(()=>{let e=t=>{let n=0;return t.forEach(t=>{n=t.children&&t.children.length>0?Math.max(n,1+e(t.children)):Math.max(n,1)}),n},t=e(P),n=Array.from({length:t},()=>[]),r=e=>!e.children||e.children.length===0?w.includes(e.key)&&l?0:1:e.children.reduce((e,t)=>e+r(t),0),i=l?w:[],a=(e,o)=>{e.forEach(e=>{if(i.includes(e.key))return;let s=r(e);s!==0&&(e.children&&e.children.length>0?(n[o].push({col:e,rowSpan:1,colSpan:s}),a(e.children,o+1)):n[o].push({col:e,rowSpan:t-o,colSpan:1}))})};return a(P,0),n.filter(e=>e.length>0)},[P,w,l]),G=(0,n.useMemo)(()=>{let e={},t=0;return l&&w.length>0&&(t+=48),F.forEach(n=>{if(M.includes(n.key)){e[n.key]=t;let r=n.style?.width||n.headerStyle?.width||`150px`;t+=typeof r==`number`?r:parseInt(String(r),10)||150}}),e},[F,M,w,l]),K=(e,t)=>{v(n=>{let r=n[e]||[],i=r.includes(t)?r.filter(e=>e!==t):[...r,t],a={...n,[e]:i};return a[e].length===0&&delete a[e],a})},q=e=>{v(t=>{let n={...t};return delete n[e],n})},J=(0,n.useMemo)(()=>{if(!h)return[];let e=j.find(e=>e.key===h),t=a.map(t=>e?.getValue?e.getValue(t):t[h]),n=Array.from(new Set(t)).filter(e=>e!=null);return y.trim()?n.filter(e=>String(e).toLowerCase().includes(y.toLowerCase())):n},[a,h,y,j]),Y=(0,n.useMemo)(()=>{let e=a.filter(e=>Object.entries(_).every(([t,n])=>{if(!n||n.length===0)return!0;let r=j.find(e=>e.key===t),i=r?.getValue?r.getValue(e):e[t];return n.includes(i)}));if(A.key&&A.direction){let{key:t,direction:n}=A,r=j.find(e=>e.key===t);e=[...e].sort((e,i)=>{let a=r?.getValue?r.getValue(e):e[t],o=r?.getValue?r.getValue(i):i[t];if(a===o)return 0;if(a==null)return 1;if(o==null)return-1;let s=0;return s=typeof a==`number`&&typeof o==`number`?a-o:String(a).localeCompare(String(o),void 0,{numeric:!0,sensitivity:`base`}),n===`asc`?s:-s})}return e},[a,_,A,j]),X=(0,n.useMemo)(()=>{if(!l||w.length===0)return Y;let e=(t,n,r=``)=>{if(n>=w.length)return t;let i=w[n],a=j.find(e=>e.key===i),o={};return t.forEach(e=>{let t=a?.getValue?a.getValue(e):e[i],n=String(t??`N/A`);o[n]||(o[n]=[]),o[n].push(e)}),Object.entries(o).map(([t,a])=>{let o=r?`${r}➔${t}`:t;return{isGroupRow:!0,groupKey:i,groupValue:t,path:o,depth:n,children:e(a,n+1,o),totalItemsCount:a.length}})};return e(Y,0)},[Y,w,l,j]),ne=e=>{D(t=>{let n=t[e]!==!1;return{...t,[e]:!n}})},Z=(0,n.useMemo)(()=>{if(!l||w.length===0)return X;let e=[],t=n=>{n.forEach(n=>{n.isGroupRow?(e.push(n),E[n.path]!==!1&&t(n.children)):e.push(n)})};return t(X),e},[X,E,w,l]),Q=(e,t=!1,n)=>M.includes(e)?{position:`sticky`,left:`${G[e]}px`,zIndex:t?30:20,backgroundColor:`#fff`,boxShadow:`2px 0 5px -2px rgba(0,0,0,0.1)`,...n}:n||{},$=F.length+ +!!s+(l&&w.length>0?1:0);return(0,i.jsxs)(`div`,{ref:I,className:`w-full space-y-3 relative`,children:[l&&(0,i.jsx)(`div`,{onDragOver:e=>{e.preventDefault(),k(!0)},onDragLeave:()=>k(!1),onDrop:H,className:`w-full min-h-[52px] px-4 py-2 border rounded-xl flex items-center gap-2 transition-all duration-200 ${O?`border-blue-500 bg-blue-50/50 scale-[0.99]`:`border-dashed border-slate-200 bg-slate-50/50`}`,children:w.length===0?(0,i.jsx)(`span`,{className:`text-[12px] text-muted-foreground font-medium select-none`,children:`Drag a column header here to group your records by that field`}):(0,i.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,i.jsx)(`span`,{className:`text-[11px] font-bold uppercase tracking-wider text-muted-foreground mr-1`,children:`Grouped By:`}),w.map(e=>(0,i.jsxs)(`div`,{className:`flex items-center gap-1.5 pl-2 pr-1 py-1 bg-white border border-slate-200 rounded-lg shadow-sm text-[12px] font-semibold text-muted-foreground`,children:[(0,i.jsx)(`span`,{children:j.find(t=>t.key===e)?.header||e}),(0,i.jsx)(`button`,{onClick:()=>U(e),className:`p-0.5 rounded-md hover:bg-slate-100 text-muted-foreground transition-colors`,children:(0,i.jsx)(t.X,{className:`w-3 h-3`})})]},e))]})}),(0,i.jsx)(`div`,{className:`w-full overflow-x-auto border border-slate-100 rounded-xl bg-white shadow-sm`,style:ee,children:(0,i.jsxs)(`table`,{className:`w-full caption-bottom text-sm border-collapse table-fixed`,style:m,children:[(0,i.jsxs)(`colgroup`,{children:[l&&w.length>0&&(0,i.jsx)(`col`,{style:{width:`48px`}}),F.map(e=>(0,i.jsx)(`col`,{style:e.style},e.key)),s&&(0,i.jsx)(`col`,{style:{width:`100px`}})]}),(0,i.jsx)(`thead`,{className:`bg-slate-50 select-none`,children:W.map((e,n)=>(0,i.jsxs)(`tr`,{className:`border-b border-slate-100`,children:[n===0&&l&&w.length>0&&(0,i.jsx)(`th`,{rowSpan:W.length,className:`w-12 border-r border-slate-100`,style:{position:`sticky`,left:0,zIndex:35,backgroundColor:`rgb(248, 250, 252)`}}),e.map(({col:e,rowSpan:n,colSpan:a})=>{let o=(_[e.key]?.length||0)>0,s=M.includes(e.key),c=Q(e.key,!0,e.headerStyle),u=!e.children||e.children.length===0,d=A.key===e.key;return(0,i.jsx)(`th`,{rowSpan:n,colSpan:a,...l&&u?{draggable:!0,onDragStart:t=>V(t,e.key)}:{},className:`h-12 text-center align-middle font-bold text-[12px] px-4 border-r border-b border-slate-100 relative ${l&&u?`cursor-grab active:cursor-grabbing`:``} ${s?`bg-slate-50/90`:``} ${e.className||``}`,style:c,children:(0,i.jsxs)(`div`,{className:`flex items-center gap-1 group/header w-full justify-between`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-1.5 truncate w-full ${e.sortable&&u?`cursor-pointer select-none hover:text-blue-600`:``}`,onClick:()=>e.sortable&&u&&B(e.key),children:[(0,i.jsx)(`span`,{className:`truncate`,children:e.header}),u&&e.sortable&&(0,i.jsx)(`span`,{className:`text-slate-400 transition-colors ${d?`text-blue-600`:`opacity-0 group-hover/header:opacity-100`}`,children:d&&A.direction===`asc`?(0,i.jsx)(t.ArrowUp,{className:`w-3.5 h-3.5`}):d&&A.direction===`desc`?(0,i.jsx)(t.ArrowDown,{className:`w-3.5 h-3.5`}):(0,i.jsx)(t.ArrowUpDown,{className:`w-3.5 h-3.5`})})]}),(0,i.jsxs)(`div`,{className:`flex items-center gap-1`,children:[u&&e.filterable&&(0,i.jsx)(`button`,{ref:t=>{t?C.current.set(e.key,t):C.current.delete(e.key)},onClick:t=>{t.stopPropagation(),b(``),g(h===e.key?null:e.key)},className:`p-0.5 rounded hover:bg-slate-200 transition-colors ${o?`text-blue-600`:`text-muted-foreground opacity-0 group-hover/header:opacity-100`}`,children:(0,i.jsx)(t.Filter,{className:`w-3.5 h-3.5`})}),u&&(0,i.jsx)(`button`,{onClick:t=>{t.stopPropagation(),z(e.key)},className:`p-0.5 rounded hover:bg-slate-200 transition-colors opacity-0 group-hover/header:opacity-100 ${s?`text-blue-500 opacity-100`:`text-slate-300`}`,title:s?`Unpin column`:`Pin column`,children:s?(0,i.jsx)(t.PinOff,{className:`w-3.5 h-3.5`}):(0,i.jsx)(t.Pin,{className:`w-3.5 h-3.5`})})]}),h===e.key&&u&&x&&I.current&&(0,r.createPortal)((0,i.jsxs)(`div`,{ref:L,className:`absolute w-52 bg-white border border-slate-200 rounded-lg shadow-lg py-2 flex flex-col font-normal text-slate-700 text-left pointer-events-auto`,style:{top:x.top,left:x.left,zIndex:9999},children:[(0,i.jsx)(`div`,{className:`px-2 pb-2 mb-1 border-b border-slate-100`,children:(0,i.jsx)(`input`,{type:`text`,placeholder:`Search values...`,value:y,onChange:e=>b(e.target.value),className:`w-full px-2 py-1 text-[12px] border border-slate-200 rounded focus:outline-none focus:border-blue-500 font-medium text-slate-600`,onClick:e=>e.stopPropagation()})}),(0,i.jsx)(`div`,{className:`max-h-40 overflow-y-auto px-2 space-y-1`,children:J.length===0?(0,i.jsx)(`div`,{className:`text-[11px] text-muted-foreground p-2 text-center`,children:`No results found`}):J.map((t,n)=>(0,i.jsxs)(`label`,{className:`flex items-center gap-2 px-2 py-1.5 text-[12px] rounded hover:bg-slate-50 cursor-pointer select-none`,children:[(0,i.jsx)(`input`,{type:`checkbox`,className:`rounded border-slate-300 text-blue-600 focus:ring-blue-500 w-3.5 h-3.5`,checked:_[e.key]?.includes(t)||!1,onChange:()=>K(e.key,t)}),(0,i.jsx)(`span`,{className:`truncate`,children:String(t)})]},n))}),o&&(0,i.jsx)(`div`,{className:`border-t border-slate-100 mt-2 pt-1 px-2 flex justify-end`,children:(0,i.jsx)(`button`,{onClick:()=>q(e.key),className:`text-[11px] text-red-500 hover:underline font-medium px-2 py-0.5`,children:`Clear Filter`})})]}),I.current)]})},e.key)}),n===0&&s&&(0,i.jsx)(`th`,{rowSpan:W.length,className:`h-12 align-middle font-bold text-[12px] px-4 text-right shadow-[-1px_0_0_rgba(226,232,240,1)]`,style:{position:`sticky`,right:0,zIndex:35,backgroundColor:`rgb(248, 250, 252)`}})]},`header-row-${n}`))}),(0,i.jsx)(`tbody`,{className:`divide-y divide-slate-100`,children:c?(0,i.jsx)(`tr`,{children:(0,i.jsx)(`td`,{colSpan:$,className:`p-8 text-center text-muted-foreground text-[12px] font-medium`,children:`Loading records...`})}):Z.length===0?(0,i.jsx)(`tr`,{children:(0,i.jsx)(`td`,{colSpan:$,className:`p-8 text-center text-muted-foreground text-[12px] font-medium`,children:`No records found matching criteria.`})}):Z.map((e,n)=>{if(e.isGroupRow){let r=E[e.path]!==!1;return(0,i.jsxs)(`tr`,{className:`bg-slate-50/60 hover:bg-slate-100/80 transition-colors select-none`,children:[(0,i.jsx)(`td`,{className:`p-3 pl-4 font-semibold text-slate-700 text-[12px] border-r border-slate-100`,style:{position:`sticky`,left:0,zIndex:20,backgroundColor:`rgba(248, 250, 252, 0.9)`,paddingLeft:`${e.depth*12+16}px`},children:(0,i.jsxs)(`button`,{onClick:()=>ne(e.path),className:`flex items-center gap-1.5 text-left focus:outline-none focus:ring-1 focus:ring-blue-400 rounded p-0.5`,children:[r?(0,i.jsx)(t.ChevronDown,{className:`w-4 h-4 text-slate-500`}):(0,i.jsx)(t.ChevronRight,{className:`w-4 h-4 text-slate-500`}),(0,i.jsx)(`span`,{className:`text-slate-800 font-bold w-40 truncate`,children:e.groupValue}),(0,i.jsx)(`span`,{className:`bg-slate-200/70 text-muted-foreground font-medium text-[10px] px-1.5 py-0.2 rounded-full ml-1`,children:e.totalItemsCount})]})}),(0,i.jsx)(`td`,{colSpan:$-1,className:`bg-slate-50/30`})]},`group-header-${e.path}-${n}`)}return(0,i.jsxs)(`tr`,{className:`border-b border-slate-100 h-12 hover:bg-slate-50/80 transition-colors group`,children:[l&&w?.length>0&&(0,i.jsx)(`td`,{className:`w-12 bg-white border-r border-slate-100`,style:{position:`sticky`,left:0,zIndex:10}}),F?.map(t=>{let n=e[t.key],r=Q(t.key,!1,t.style);return(0,i.jsx)(`td`,{className:`p-4 align-middle py-1 px-4 transition-colors ${M.includes(t.key)?`group-hover:bg-slate-100`:``} ${t.className||``}`,style:r,children:t.render?t.render(n,e):(0,i.jsx)(`span`,{className:`text-[12px] text-muted-foreground font-medium truncate block`,children:n})},t.key)}),s&&(0,i.jsx)(`td`,{className:`p-4 align-middle py-1 px-4 text-right bg-white shadow-[-1px_0_0_rgba(226,232,240,1)] group-hover:bg-slate-50/80`,style:{position:`sticky`,right:0,zIndex:20},children:(0,i.jsx)(`div`,{className:`flex justify-end gap-1 opacity-0 group-hover:opacity-100 transition-opacity duration-150`,children:s(e)})})]},R(e)??`row-${n}`)})})]})})]})}e.DataTable=p});
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("lucide-react"),require("react"),require("react-dom"),require("react/jsx-runtime")):typeof define==`function`&&define.amd?define([`exports`,`lucide-react`,`react`,`react-dom`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.FlexiDataGrid={},e.LucideReact,e.React,e.ReactDOM,e.JSX))})(this,function(e,t,n,r,i){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var a=Object.create,o=Object.defineProperty,s=Object.getOwnPropertyDescriptor,c=Object.getOwnPropertyNames,l=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty,d=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=c(t),a=0,l=i.length,d;a<l;a++)d=i[a],!u.call(e,d)&&d!==n&&o(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=s(t,d))||r.enumerable});return e};n=((e,t,n)=>(n=e==null?{}:a(l(e)),d(t||!e||!e.__esModule?o(n,`default`,{value:e,enumerable:!0}):n,e)))(n,1);var f=e=>{let t=[];return e.forEach(e=>{e.children&&e.children.length>0?t.push(...f(e.children)):t.push(e)}),t},p=(...e)=>e.filter(Boolean).join(` `),m=e=>{if(e===!0)return`left`;if(e===`left`||e===`right`)return e};function h({columns:e,data:a,rowKey:o,actions:s,isLoading:c,groupBy:l=!1,defaultGroupBy:u=[],onPinChange:d,onGroupChange:h,containerStyle:g,tableStyle:ee,bordered:te=!1,pinnedBottomRowData:_=[],pinnedRowClassName:v}){let[y,b]=(0,n.useState)(null),[x,S]=(0,n.useState)({}),[C,w]=(0,n.useState)(``),[T,E]=(0,n.useState)(null),D=(0,n.useRef)(new Map),[O,k]=(0,n.useState)(u),[A,j]=(0,n.useState)({}),[ne,M]=(0,n.useState)(!1),[N,re]=(0,n.useState)({key:null,direction:null}),P=(0,n.useMemo)(()=>f(e),[e]),[F,ie]=(0,n.useState)(()=>{let e={};return P.forEach(t=>{let n=m(t.pinned);n&&(e[t.key]=n)}),e}),I=(0,n.useMemo)(()=>{let t=e=>{let n=e=>{let t=F[e];return t===`left`?0:t===`right`?2:1};return[...e].sort((e,t)=>n(e.key)-n(t.key)).map(e=>e.children&&e.children.length>0?{...e,children:t(e.children)}:e)};return t(e)},[e,F]),L=(0,n.useMemo)(()=>{let e=f(I),t=l?O:[];return e.filter(e=>!t.includes(e.key))},[I,O,l]),R=(0,n.useRef)(null),z=(0,n.useRef)(null);(0,n.useEffect)(()=>{function e(e){let t=e.target,n=y?D.current.get(y):null;z.current&&!z.current.contains(t)&&!(n&&n.contains(t))&&(b(null),w(``))}return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[y]),(0,n.useEffect)(()=>{if(!y)return;let e=()=>{let e=D.current.get(y),t=R.current;if(!e||!t)return;let n=e.getBoundingClientRect(),r=t.getBoundingClientRect();E({top:n.bottom-r.top+4,left:n.left-r.left})};return e(),window.addEventListener(`scroll`,e,!0),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`scroll`,e,!0),window.removeEventListener(`resize`,e)}},[y]);let ae=e=>typeof o==`function`?o(e):String(e[o]),oe=e=>{ie(t=>{let n=t[e],r=n?n===`left`?`right`:void 0:`left`,i={...t};return r?i[e]=r:delete i[e],d&&d(e,!!r,r),i})},B=e=>{let t=`asc`;N.key===e&&(t=N.direction===`asc`?`desc`:N.direction===`desc`?null:`asc`),re({key:t?e:null,direction:t})},V=(e,t)=>{l&&(e.dataTransfer.setData(`text/plain`,t),e.dataTransfer.effectAllowed=`move`)},H=e=>{e.preventDefault(),M(!1);let t=e.dataTransfer.getData(`text/plain`);if(t&&!O.includes(t)){let e=[...O,t];k(e),h&&h(e)}},U=e=>{let t=O.filter(t=>t!==e);k(t),j({}),h&&h(t)},W=(0,n.useMemo)(()=>{let e=t=>{let n=0;return t.forEach(t=>{n=t.children&&t.children.length>0?Math.max(n,1+e(t.children)):Math.max(n,1)}),n},t=e(I),n=Array.from({length:t},()=>[]),r=e=>!e.children||e.children.length===0?O.includes(e.key)&&l?0:1:e.children.reduce((e,t)=>e+r(t),0),i=l?O:[],a=(e,o)=>{e.forEach(e=>{if(i.includes(e.key))return;let s=r(e);s!==0&&(e.children&&e.children.length>0?(n[o].push({col:e,rowSpan:1,colSpan:s}),a(e.children,o+1)):n[o].push({col:e,rowSpan:t-o,colSpan:1}))})};return a(I,0),n.filter(e=>e.length>0)},[I,O,l]),G=e=>{let t=e.style?.width||e.headerStyle?.width||`150px`;return typeof t==`number`?t:parseInt(String(t),10)||150},K=(0,n.useMemo)(()=>{let e={},t=0;l&&O.length>0&&(t+=48),L.forEach(n=>{F[n.key]===`left`&&(e[n.key]={side:`left`,offset:t},t+=G(n))});let n=s?100:0;for(let t=L.length-1;t>=0;t--){let r=L[t];F[r.key]===`right`&&(e[r.key]={side:`right`,offset:n},n+=G(r))}return e},[L,F,O,l,s]),se=(e,t)=>{S(n=>{let r=n[e]||[],i=r.includes(t)?r.filter(e=>e!==t):[...r,t],a={...n,[e]:i};return a[e].length===0&&delete a[e],a})},q=e=>{S(t=>{let n={...t};return delete n[e],n})},J=(0,n.useMemo)(()=>{if(!y)return[];let e=P.find(e=>e.key===y),t=a.map(t=>e?.getValue?e.getValue(t):t[y]),n=Array.from(new Set(t)).filter(e=>e!=null);return C.trim()?n.filter(e=>String(e).toLowerCase().includes(C.toLowerCase())):n},[a,y,C,P]),Y=(0,n.useMemo)(()=>{let e=a.filter(e=>Object.entries(x).every(([t,n])=>{if(!n||n.length===0)return!0;let r=P.find(e=>e.key===t),i=r?.getValue?r.getValue(e):e[t];return n.includes(i)}));if(N.key&&N.direction){let{key:t,direction:n}=N,r=P.find(e=>e.key===t);e=[...e].sort((e,i)=>{let a=r?.getValue?r.getValue(e):e[t],o=r?.getValue?r.getValue(i):i[t];if(a===o)return 0;if(a==null)return 1;if(o==null)return-1;let s=0;return s=typeof a==`number`&&typeof o==`number`?a-o:String(a).localeCompare(String(o),void 0,{numeric:!0,sensitivity:`base`}),n===`asc`?s:-s})}return e},[a,x,N,P]),X=(0,n.useMemo)(()=>{if(!l||O.length===0)return Y;let e=(t,n,r=``)=>{if(n>=O.length)return t;let i=O[n],a=P.find(e=>e.key===i),o={};return t.forEach(e=>{let t=a?.getValue?a.getValue(e):e[i],n=String(t??`N/A`);o[n]||(o[n]=[]),o[n].push(e)}),Object.entries(o).map(([t,a])=>{let o=r?`${r}➔${t}`:t;return{isGroupRow:!0,groupKey:i,groupValue:t,path:o,depth:n,children:e(a,n+1,o),totalItemsCount:a.length}})};return e(Y,0)},[Y,O,l,P]),ce=e=>{j(t=>{let n=t[e]!==!1;return{...t,[e]:!n}})},Z=(0,n.useMemo)(()=>{if(!l||O.length===0)return X;let e=[],t=n=>{n.forEach(n=>{n.isGroupRow?(e.push(n),A[n.path]!==!1&&t(n.children)):e.push(n)})};return t(X),e},[X,A,O,l]),Q=(e,t=!1,n)=>{let r=K[e];if(!r)return n||{};let i=r.side===`right`;return{position:`sticky`,[i?`right`:`left`]:`${r.offset}px`,...t?{top:0}:{},zIndex:t?30:20,boxShadow:i?`-2px 0 5px -2px rgba(0,0,0,0.1)`:`2px 0 5px -2px rgba(0,0,0,0.1)`,...n}},le=(0,n.useMemo)(()=>_.map((e,t)=>(_.length-1-t)*48),[_]),$=L.length+ +!!s+(l&&O.length>0?1:0);return(0,i.jsxs)(`div`,{ref:R,className:`flexi-root`,children:[l&&(0,i.jsx)(`div`,{onDragOver:e=>{e.preventDefault(),M(!0)},onDragLeave:()=>M(!1),onDrop:H,className:p(`flexi-groupzone`,ne&&`flexi-groupzone--dragover`),children:O.length===0?(0,i.jsx)(`span`,{className:`flexi-groupzone-hint`,children:`Drag a column header here to group your records by that field`}):(0,i.jsxs)(`div`,{className:`flexi-groupzone-chips`,children:[(0,i.jsx)(`span`,{className:`flexi-groupzone-label`,children:`Grouped By:`}),O.map(e=>(0,i.jsxs)(`div`,{className:`flexi-chip`,children:[(0,i.jsx)(`span`,{children:P.find(t=>t.key===e)?.header||e}),(0,i.jsx)(`button`,{type:`button`,onClick:()=>U(e),className:`flexi-icon-btn flexi-chip-remove`,children:(0,i.jsx)(t.X,{className:`flexi-icon-xs`})})]},e))]})}),(0,i.jsx)(`div`,{className:`flexi-table-wrap`,style:g,children:(0,i.jsxs)(`table`,{className:p(`flexi-table`,te&&`flexi-table--bordered`),style:ee,children:[(0,i.jsxs)(`colgroup`,{children:[l&&O.length>0&&(0,i.jsx)(`col`,{style:{width:`48px`}}),L.map(e=>(0,i.jsx)(`col`,{style:e.style},e.key)),s&&(0,i.jsx)(`col`,{style:{width:`100px`}})]}),(0,i.jsx)(`thead`,{className:`flexi-thead`,children:W.map((e,n)=>(0,i.jsxs)(`tr`,{className:`flexi-header-row`,children:[n===0&&l&&O.length>0&&(0,i.jsx)(`th`,{rowSpan:W.length,className:`flexi-group-spacer-th`,style:{position:`sticky`,top:0,left:0,zIndex:35,backgroundColor:`rgb(248, 250, 252)`}}),e.map(({col:e,rowSpan:n,colSpan:a})=>{let o=(x[e.key]?.length||0)>0,s=!!F[e.key],c=Q(e.key,!0,e.headerStyle),u=!e.children||e.children.length===0,d=N.key===e.key,f=!!(l&&u);return(0,i.jsx)(`th`,{rowSpan:n,colSpan:a,...f?{draggable:!0,onDragStart:t=>V(t,e.key)}:{},className:p(`flexi-th`,f&&`flexi-th--draggable`,s&&`flexi-th--pinned`,e.className),style:c,children:(0,i.jsxs)(`div`,{className:`flexi-th-inner`,children:[(0,i.jsxs)(`div`,{className:p(`flexi-th-label`,e.sortable&&u&&`flexi-th-label--sortable`),onClick:()=>e.sortable&&u&&B(e.key),children:[(0,i.jsx)(`span`,{className:`flexi-th-text`,children:e.header}),u&&e.sortable&&(0,i.jsx)(`span`,{className:p(`flexi-sort-icon`,d&&`flexi-sort-icon--active`),children:d&&N.direction===`asc`?(0,i.jsx)(t.ArrowUp,{className:`flexi-icon-sm`}):d&&N.direction===`desc`?(0,i.jsx)(t.ArrowDown,{className:`flexi-icon-sm`}):(0,i.jsx)(t.ArrowUpDown,{className:`flexi-icon-sm`})})]}),(0,i.jsxs)(`div`,{className:`flexi-th-actions`,children:[u&&e.filterable&&(0,i.jsx)(`button`,{type:`button`,ref:t=>{t?D.current.set(e.key,t):D.current.delete(e.key)},onClick:t=>{t.stopPropagation(),w(``),b(y===e.key?null:e.key)},className:p(`flexi-icon-btn`,`flexi-filter-btn`,o&&`flexi-filter-btn--active`),children:(0,i.jsx)(t.Filter,{className:`flexi-icon-sm`})}),u&&(0,i.jsx)(`button`,{type:`button`,onClick:t=>{t.stopPropagation(),oe(e.key)},className:p(`flexi-icon-btn`,`flexi-pin-btn`,s&&`flexi-pin-btn--pinned`),title:F[e.key]===`left`?`Pinned left (click to pin right)`:F[e.key]===`right`?`Pinned right (click to unpin)`:`Pin column left`,children:s?(0,i.jsx)(t.PinOff,{className:`flexi-icon-sm`}):(0,i.jsx)(t.Pin,{className:`flexi-icon-sm`})})]}),y===e.key&&u&&T&&R.current&&(0,r.createPortal)((0,i.jsxs)(`div`,{ref:z,className:`flexi-filter-dropdown`,style:{top:T.top,left:T.left,zIndex:9999},children:[(0,i.jsx)(`div`,{className:`flexi-filter-search`,children:(0,i.jsx)(`input`,{type:`text`,placeholder:`Search values...`,value:C,onChange:e=>w(e.target.value),className:`flexi-input`,onClick:e=>e.stopPropagation()})}),(0,i.jsx)(`div`,{className:`flexi-filter-list`,children:J.length===0?(0,i.jsx)(`div`,{className:`flexi-filter-empty`,children:`No results found`}):J.map((t,n)=>(0,i.jsxs)(`label`,{className:`flexi-filter-option`,children:[(0,i.jsx)(`input`,{type:`checkbox`,className:`flexi-checkbox`,checked:x[e.key]?.includes(t)||!1,onChange:()=>se(e.key,t)}),(0,i.jsx)(`span`,{className:`flexi-filter-option-text`,children:String(t)})]},n))}),o&&(0,i.jsx)(`div`,{className:`flexi-filter-footer`,children:(0,i.jsx)(`button`,{type:`button`,onClick:()=>q(e.key),className:`flexi-filter-clear`,children:`Clear Filter`})})]}),R.current)]})},e.key)}),n===0&&s&&(0,i.jsx)(`th`,{rowSpan:W.length,className:`flexi-actions-th`,style:{position:`sticky`,top:0,right:0,zIndex:35,backgroundColor:`rgb(248, 250, 252)`}})]},`header-row-${n}`))}),(0,i.jsx)(`tbody`,{className:`flexi-tbody`,children:c?(0,i.jsx)(`tr`,{children:(0,i.jsx)(`td`,{colSpan:$,className:`flexi-empty-cell`,children:`Loading records...`})}):Z.length===0?(0,i.jsx)(`tr`,{children:(0,i.jsx)(`td`,{colSpan:$,className:`flexi-empty-cell`,children:`No records found matching criteria.`})}):Z.map((e,t)=>ue(e,t))}),_.length>0&&(0,i.jsx)(`tbody`,{className:`flexi-tbody flexi-tbody--pinned-bottom`,children:_.map((e,t)=>de(e,t))})]})})]});function ue(e,n){if(e.isGroupRow){let r=A[e.path]!==!1;return(0,i.jsxs)(`tr`,{className:`flexi-group-row`,children:[(0,i.jsx)(`td`,{className:`flexi-group-cell`,style:{position:`sticky`,left:0,zIndex:20,backgroundColor:`rgba(248, 250, 252, 0.9)`,paddingLeft:`${e.depth*12+16}px`},children:(0,i.jsxs)(`button`,{type:`button`,onClick:()=>ce(e.path),className:`flexi-group-toggle`,children:[r?(0,i.jsx)(t.ChevronDown,{className:`flexi-icon-md flexi-icon-muted`}):(0,i.jsx)(t.ChevronRight,{className:`flexi-icon-md flexi-icon-muted`}),(0,i.jsx)(`span`,{className:`flexi-group-value`,children:e.groupValue}),(0,i.jsx)(`span`,{className:`flexi-group-count`,children:e.totalItemsCount})]})}),(0,i.jsx)(`td`,{colSpan:$-1,className:`flexi-group-filler`})]},`group-header-${e.path}-${n}`)}let r=ae(e);return(0,i.jsxs)(`tr`,{className:`flexi-row`,children:[l&&O?.length>0&&(0,i.jsx)(`td`,{className:`flexi-row-indent-cell`,style:{position:`sticky`,left:0,zIndex:10}}),L?.map(t=>{let n=e[t.key],r=Q(t.key,!1,t.style);return(0,i.jsx)(`td`,{className:p(`flexi-cell`,!!F[t.key]&&`flexi-cell--pinned`,t.className),style:r,children:t.render?t.render(n,e):(0,i.jsx)(`span`,{className:`flexi-cell-text`,children:n})},t.key)}),s&&(0,i.jsx)(`td`,{className:`flexi-actions-cell`,style:{position:`sticky`,right:0},children:(0,i.jsx)(`div`,{className:`flexi-actions-inner`,children:s(e)})})]},r??`row-${n}`)}function de(e,t){let n=typeof v==`function`?v(e,t):v,r={position:`sticky`,bottom:`${le[t]}px`,background:`#`,zIndex:45};return(0,i.jsxs)(`tr`,{className:p(`flexi-row`,`flexi-row--pinned-bottom`,n),style:r,children:[l&&O?.length>0&&(0,i.jsx)(`td`,{className:`flexi-row-indent-cell`,style:{position:`sticky`,left:0,zIndex:10}}),L?.map(t=>{let n=e[t.key],r=Q(t.key,!1,t.style),a=!!F[t.key],o=t.pinnedRender??t.render;return(0,i.jsx)(`td`,{className:p(`flexi-cell`,a&&`flexi-cell--pinned`,t.className),style:r,children:o?o(n,e):(0,i.jsx)(`span`,{className:`flexi-cell-text`,children:n})},t.key)}),s&&(0,i.jsx)(`td`,{className:`flexi-actions-cell`,style:{position:`sticky`,right:0},children:(0,i.jsx)(`div`,{className:`flexi-actions-inner`,children:s(e)})})]},`pinned-bottom-row-${t}`)}}e.DataTable=h});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flexi-datagrid",
3
- "version": "1.2.0",
3
+ "version": "1.2.3",
4
4
  "description": "A powerful universal datagrid with tree-grouping, column pinning, and drag-and-drop.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.umd.js",
@@ -46,7 +46,6 @@
46
46
  "@vitejs/plugin-react": "^4.3.4",
47
47
  "autoprefixer": "^10.4.20",
48
48
  "postcss": "^8.5.1",
49
- "tailwindcss": "^3.4.17",
50
49
  "typescript": "^6.0.3",
51
50
  "vite": "^8.0.16",
52
51
  "vite-plugin-dts": "^4.5.0",