@forgedevstack/grid-table 1.0.1 → 1.0.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/dist/index.mjs CHANGED
@@ -1,5 +1,8 @@
1
+ // src/index.ts
2
+ import "@forgedevstack/bear/styles.css";
3
+
1
4
  // src/components/GridTable/GridTable.tsx
2
- import { useMemo as useMemo12, useCallback as useCallback13 } from "react";
5
+ import { useMemo as useMemo11, useCallback as useCallback13, useState as useState8, useEffect as useEffect6 } from "react";
3
6
 
4
7
  // src/context/TableContext.tsx
5
8
  import {
@@ -175,6 +178,10 @@ function reducer(state, action) {
175
178
  return { ...state, selectedIds: action.payload };
176
179
  case "SET_EXPANDED_IDS":
177
180
  return { ...state, expandedIds: action.payload };
181
+ case "SET_EXPANDED_CELL_IDS":
182
+ return { ...state, expandedCellIds: action.payload };
183
+ case "SET_AUTO_SIZED_COLUMN_IDS":
184
+ return { ...state, autoSizedColumnIds: action.payload };
178
185
  case "SET_COLUMN_STATES":
179
186
  return { ...state, columnStates: action.payload };
180
187
  case "SET_DRAGGING_COLUMN":
@@ -212,9 +219,24 @@ function TableProvider({
212
219
  sortConfig: _sortConfig,
213
220
  enableMultiSort = false,
214
221
  getRowId,
215
- onStateChange
222
+ onStateChange,
223
+ showOverflowTooltip = true,
224
+ enableCellAutoSizeOnDoubleClick = false,
225
+ subCellExpandTrigger = "both",
226
+ expandRowOnDoubleClick = false,
227
+ globalFilterColumns = void 0
216
228
  }) {
217
229
  var _a, _b;
230
+ const tableOptions = useMemo(
231
+ () => ({
232
+ showOverflowTooltip,
233
+ enableCellAutoSizeOnDoubleClick,
234
+ subCellExpandTrigger,
235
+ expandRowOnDoubleClick,
236
+ globalFilterColumns
237
+ }),
238
+ [showOverflowTooltip, enableCellAutoSizeOnDoubleClick, subCellExpandTrigger, expandRowOnDoubleClick, globalFilterColumns]
239
+ );
218
240
  const initialColumnStates = columns.map((col, index) => ({
219
241
  id: col.id,
220
242
  visible: !col.hidden,
@@ -243,6 +265,8 @@ function TableProvider({
243
265
  totalItems: data.length,
244
266
  selectedIds: /* @__PURE__ */ new Set(),
245
267
  expandedIds: /* @__PURE__ */ new Set(),
268
+ expandedCellIds: /* @__PURE__ */ new Set(),
269
+ autoSizedColumnIds: /* @__PURE__ */ new Set(),
246
270
  loading,
247
271
  error,
248
272
  theme: mergedTheme,
@@ -369,6 +393,25 @@ function TableProvider({
369
393
  actions.expandRow(id);
370
394
  }
371
395
  },
396
+ toggleCellExpansion: (rowId, columnId) => {
397
+ const key = `${String(rowId)}-${columnId}`;
398
+ const next = new Set(state.expandedCellIds);
399
+ if (next.has(key)) {
400
+ next.delete(key);
401
+ } else {
402
+ next.add(key);
403
+ }
404
+ dispatch({ type: "SET_EXPANDED_CELL_IDS", payload: next });
405
+ },
406
+ toggleColumnAutoSize: (columnId) => {
407
+ const next = new Set(state.autoSizedColumnIds);
408
+ if (next.has(columnId)) {
409
+ next.delete(columnId);
410
+ } else {
411
+ next.add(columnId);
412
+ }
413
+ dispatch({ type: "SET_AUTO_SIZED_COLUMN_IDS", payload: next });
414
+ },
372
415
  reorderColumn: (sourceId, targetId) => {
373
416
  const newStates = [...state.columnStates];
374
417
  const sourceIndex = newStates.findIndex((c) => c.id === sourceId);
@@ -407,6 +450,8 @@ function TableProvider({
407
450
  page: ONE,
408
451
  selectedIds: /* @__PURE__ */ new Set(),
409
452
  expandedIds: /* @__PURE__ */ new Set(),
453
+ expandedCellIds: /* @__PURE__ */ new Set(),
454
+ autoSizedColumnIds: /* @__PURE__ */ new Set(),
410
455
  columnStates: initialColumnStates
411
456
  }
412
457
  })
@@ -417,11 +462,15 @@ function TableProvider({
417
462
  let filteredData = [...state.data];
418
463
  if (state.globalFilter) {
419
464
  const searchLower = state.globalFilter.toLowerCase();
420
- filteredData = filteredData.filter(
421
- (row) => Object.values(row).some(
422
- (val) => String(val).toLowerCase().includes(searchLower)
423
- )
424
- );
465
+ const columnIds = tableOptions.globalFilterColumns;
466
+ filteredData = filteredData.filter((row) => {
467
+ const colsToSearch = columnIds && columnIds.length > 0 ? state.columns.filter((c) => columnIds.includes(c.id)) : state.columns;
468
+ return colsToSearch.some((col) => {
469
+ const accessor = col.accessor;
470
+ const value = typeof accessor === "function" ? accessor(row) : row[accessor];
471
+ return String(value != null ? value : "").toLowerCase().includes(searchLower);
472
+ });
473
+ });
425
474
  }
426
475
  state.filters.forEach((filter) => {
427
476
  const column = columns.find((c) => c.id === filter.columnId);
@@ -507,10 +556,11 @@ function TableProvider({
507
556
  isTablet,
508
557
  isDesktop
509
558
  };
510
- }, [state, columns]);
559
+ }, [state, columns, tableOptions]);
511
560
  const contextValue = {
512
561
  state,
513
562
  actions,
563
+ tableOptions,
514
564
  computed
515
565
  };
516
566
  return /* @__PURE__ */ jsx(TableContext.Provider, { value: contextValue, children });
@@ -999,6 +1049,7 @@ function useTable() {
999
1049
 
1000
1050
  // src/components/GridHeader/GridHeader.tsx
1001
1051
  import { useMemo as useMemo8, useCallback as useCallback7, useState as useState4, useRef as useRef3 } from "react";
1052
+ import { Checkbox } from "@forgedevstack/bear";
1002
1053
 
1003
1054
  // src/components/FilterPopup/FilterPopup.tsx
1004
1055
  import { useState as useState3, useCallback as useCallback6, useEffect as useEffect3, useRef as useRef2 } from "react";
@@ -1082,7 +1133,7 @@ function FilterPopup({
1082
1133
  "div",
1083
1134
  {
1084
1135
  ref: popupRef,
1085
- className: `filter-popup absolute z-50 bg-theme-primary border border-theme-border rounded-lg shadow-xl min-w-[280px] ${className}`,
1136
+ className: `filter-popup ${className}`,
1086
1137
  style: {
1087
1138
  top: (_a = position == null ? void 0 : position.top) != null ? _a : "100%",
1088
1139
  left: (_b = position == null ? void 0 : position.left) != null ? _b : 0,
@@ -1090,44 +1141,44 @@ function FilterPopup({
1090
1141
  ...style
1091
1142
  },
1092
1143
  children: [
1093
- /* @__PURE__ */ jsx2("div", { className: "filter-popup-header px-4 py-3 border-b border-theme-border", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1094
- /* @__PURE__ */ jsx2("span", { className: "font-medium text-theme-primary", children: columnHeader }),
1144
+ /* @__PURE__ */ jsx2("div", { className: "filter-popup-header", children: /* @__PURE__ */ jsxs("div", { className: "header-content", children: [
1145
+ /* @__PURE__ */ jsx2("span", { className: "header-title", children: columnHeader }),
1095
1146
  /* @__PURE__ */ jsx2(
1096
1147
  "button",
1097
1148
  {
1098
1149
  onClick: onClose,
1099
- className: "p-1 rounded hover:bg-theme-hover text-theme-muted",
1150
+ className: "header-close",
1100
1151
  "aria-label": "Close",
1101
- children: /* @__PURE__ */ jsx2("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
1152
+ children: /* @__PURE__ */ jsx2("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
1102
1153
  }
1103
1154
  )
1104
1155
  ] }) }),
1105
- /* @__PURE__ */ jsx2("div", { className: "filter-popup-body p-4 space-y-4", children: filterType === "select" && filterOptions ? /* @__PURE__ */ jsxs(
1156
+ /* @__PURE__ */ jsx2("div", { className: "filter-popup-body", children: filterType === "select" && filterOptions ? /* @__PURE__ */ jsxs(
1106
1157
  "select",
1107
1158
  {
1108
1159
  value: String(value),
1109
1160
  onChange: (e) => setValue(e.target.value),
1110
- className: "w-full px-3 py-2 text-sm rounded border border-theme-border bg-theme-secondary text-theme-primary focus:outline-none focus:ring-2 focus:ring-accent-primary",
1161
+ className: "w-full px-3 py-2 text-sm rounded",
1111
1162
  children: [
1112
1163
  /* @__PURE__ */ jsx2("option", { value: "", children: "Select..." }),
1113
1164
  filterOptions.map((opt) => /* @__PURE__ */ jsx2("option", { value: String(opt.value), children: opt.label }, String(opt.value)))
1114
1165
  ]
1115
1166
  }
1116
1167
  ) : /* @__PURE__ */ jsxs(Fragment, { children: [
1117
- /* @__PURE__ */ jsxs("div", { children: [
1118
- /* @__PURE__ */ jsx2("label", { className: "block text-xs text-theme-muted mb-1", children: "Operator" }),
1168
+ /* @__PURE__ */ jsxs("div", { className: "filter-field", children: [
1169
+ /* @__PURE__ */ jsx2("label", { children: "Operator" }),
1119
1170
  /* @__PURE__ */ jsx2(
1120
1171
  "select",
1121
1172
  {
1122
1173
  value: operator,
1123
1174
  onChange: (e) => setOperator(e.target.value),
1124
- className: "w-full px-3 py-2 text-sm rounded border border-theme-border bg-theme-secondary text-theme-primary focus:outline-none focus:ring-2 focus:ring-accent-primary",
1175
+ className: "w-full px-3 py-2 text-sm rounded",
1125
1176
  children: operators.map((op) => /* @__PURE__ */ jsx2("option", { value: op, children: OPERATOR_LABELS[op] }, op))
1126
1177
  }
1127
1178
  )
1128
1179
  ] }),
1129
- /* @__PURE__ */ jsxs("div", { children: [
1130
- /* @__PURE__ */ jsx2("label", { className: "block text-xs text-theme-muted mb-1", children: "Value" }),
1180
+ /* @__PURE__ */ jsxs("div", { className: "filter-field", children: [
1181
+ /* @__PURE__ */ jsx2("label", { children: "Value" }),
1131
1182
  /* @__PURE__ */ jsx2(
1132
1183
  "input",
1133
1184
  {
@@ -1136,18 +1187,18 @@ function FilterPopup({
1136
1187
  onChange: (e) => setValue(e.target.value),
1137
1188
  onKeyDown: handleKeyDown,
1138
1189
  placeholder: `Filter ${columnHeader}...`,
1139
- className: "w-full px-3 py-2 text-sm rounded border border-theme-border bg-theme-secondary text-theme-primary focus:outline-none focus:ring-2 focus:ring-accent-primary",
1190
+ className: "w-full px-3 py-2 text-sm rounded",
1140
1191
  autoFocus: true
1141
1192
  }
1142
1193
  )
1143
1194
  ] })
1144
1195
  ] }) }),
1145
- /* @__PURE__ */ jsxs("div", { className: "filter-popup-footer px-4 py-3 border-t border-theme-border flex items-center justify-between", children: [
1196
+ /* @__PURE__ */ jsxs("div", { className: "filter-popup-footer", children: [
1146
1197
  /* @__PURE__ */ jsx2(
1147
1198
  "button",
1148
1199
  {
1149
1200
  onClick: handleClear,
1150
- className: "px-3 py-1.5 text-sm text-theme-muted hover:text-theme-primary transition-colors",
1201
+ className: "filter-clear",
1151
1202
  children: translations.clearFilter
1152
1203
  }
1153
1204
  ),
@@ -1155,7 +1206,7 @@ function FilterPopup({
1155
1206
  "button",
1156
1207
  {
1157
1208
  onClick: handleApply,
1158
- className: "px-4 py-1.5 text-sm bg-accent-primary text-white rounded hover:opacity-90 transition-opacity",
1209
+ className: "filter-apply",
1159
1210
  children: translations.apply
1160
1211
  }
1161
1212
  )
@@ -1170,7 +1221,7 @@ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1170
1221
  var FilterIcon = ({ active = false }) => /* @__PURE__ */ jsx3(
1171
1222
  "svg",
1172
1223
  {
1173
- className: `w-3.5 h-3.5 ${active ? "text-accent-primary" : "text-theme-muted"}`,
1224
+ className: `icon-sm ${active ? "text-accent-primary" : "text-theme-muted"}`,
1174
1225
  fill: "none",
1175
1226
  viewBox: "0 0 24 24",
1176
1227
  stroke: "currentColor",
@@ -1188,7 +1239,7 @@ var FilterIcon = ({ active = false }) => /* @__PURE__ */ jsx3(
1188
1239
  var SortIcon = ({ direction }) => /* @__PURE__ */ jsx3(
1189
1240
  "svg",
1190
1241
  {
1191
- className: `w-3.5 h-3.5 ${direction ? "text-accent-primary" : "text-theme-muted"}`,
1242
+ className: `icon-sm ${direction ? "text-accent-primary" : "text-theme-muted"}`,
1192
1243
  fill: "none",
1193
1244
  viewBox: "0 0 24 24",
1194
1245
  stroke: "currentColor",
@@ -1214,6 +1265,7 @@ function HeaderCell({
1214
1265
  hasFilter = false,
1215
1266
  isDragging = false,
1216
1267
  isDragOver = false,
1268
+ isColumnAutoSized = false,
1217
1269
  onSort,
1218
1270
  onFilterOpen,
1219
1271
  onResizeStart,
@@ -1245,56 +1297,53 @@ function HeaderCell({
1245
1297
  const cellClasses = useMemo8(() => {
1246
1298
  const classes = [
1247
1299
  "grid-header-cell",
1248
- "relative",
1249
- "flex",
1250
- "items-center",
1251
- "gap-2",
1252
- "px-4",
1253
- "py-3",
1254
- "font-medium",
1255
- "text-sm",
1256
- "text-theme-secondary",
1257
- "select-none",
1258
- "border-b",
1259
- "border-theme-border",
1260
- "transition-colors",
1261
1300
  ALIGN_CLASSES[column.align || "left"]
1262
1301
  ];
1263
1302
  if (isSortable) {
1264
- classes.push("cursor-pointer", "hover:text-theme-primary", "hover:bg-theme-hover");
1303
+ classes.push("cursor-pointer");
1265
1304
  }
1266
1305
  if (isDragging) {
1267
1306
  classes.push("opacity-50");
1268
1307
  }
1269
1308
  if (isDragOver) {
1270
- classes.push("bg-accent-primary/10", "border-l-2", "border-l-accent-primary");
1309
+ classes.push("bg-accent-primary/10");
1271
1310
  }
1272
1311
  return classes.join(" ");
1273
1312
  }, [column.align, isSortable, isDragging, isDragOver]);
1313
+ const cellStyle = useMemo8(() => {
1314
+ const base = {
1315
+ flexShrink: 0,
1316
+ ...column.sticky && {
1317
+ position: "sticky",
1318
+ [column.sticky]: 0,
1319
+ zIndex: 2,
1320
+ backgroundColor: "var(--gt-bg-secondary, #2b2b2b)"
1321
+ },
1322
+ ...column.headerStyle
1323
+ };
1324
+ if (isColumnAutoSized) {
1325
+ base.width = "auto";
1326
+ base.minWidth = "max-content";
1327
+ base.maxWidth = "none";
1328
+ } else {
1329
+ base.width = typeof columnState.width === "number" ? `${columnState.width}px` : columnState.width;
1330
+ base.minWidth = column.minWidth || MIN_COLUMN_WIDTH;
1331
+ base.maxWidth = column.maxWidth || MAX_COLUMN_WIDTH;
1332
+ }
1333
+ return base;
1334
+ }, [column, columnState.width, isColumnAutoSized]);
1274
1335
  return /* @__PURE__ */ jsxs2(
1275
1336
  "div",
1276
1337
  {
1277
- className: `${cellClasses} ${column.headerClassName || ""} ${column.sticky ? "shadow-[2px_0_4px_-2px_rgba(0,0,0,0.2)]" : ""}`,
1278
- style: {
1279
- width: columnState.width,
1280
- minWidth: column.minWidth || MIN_COLUMN_WIDTH,
1281
- maxWidth: column.maxWidth || MAX_COLUMN_WIDTH,
1282
- flexShrink: 0,
1283
- ...column.sticky && {
1284
- position: "sticky",
1285
- [column.sticky]: 0,
1286
- zIndex: 2,
1287
- backgroundColor: "var(--bg-secondary, #2b2b2b)"
1288
- },
1289
- ...column.headerStyle
1290
- },
1338
+ className: `${cellClasses} ${column.headerClassName || ""} ${column.sticky ? `sticky-${column.sticky}` : ""}`,
1339
+ style: cellStyle,
1291
1340
  role: "columnheader",
1292
1341
  "aria-sort": sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : "none",
1293
1342
  onClick: handleClick,
1294
1343
  ...isDraggable ? { ...dragHandleProps, ...dropTargetProps } : {},
1295
1344
  children: [
1296
- /* @__PURE__ */ jsx3("span", { className: "grid-header-content truncate flex-1", children: headerContent }),
1297
- isSortable && /* @__PURE__ */ jsxs2("span", { className: "grid-header-sort flex items-center gap-0.5", children: [
1345
+ /* @__PURE__ */ jsx3("span", { className: "grid-header-content", children: headerContent }),
1346
+ isSortable && /* @__PURE__ */ jsxs2("span", { className: "grid-header-sort", children: [
1298
1347
  /* @__PURE__ */ jsx3(SortIcon, { direction: sortDirection != null ? sortDirection : null }),
1299
1348
  isMultiSort && sortIndex !== void 0 && sortIndex >= 0 && sortDirection && /* @__PURE__ */ jsx3("span", { className: "text-xs text-theme-muted", children: sortIndex + 1 })
1300
1349
  ] }),
@@ -1302,7 +1351,7 @@ function HeaderCell({
1302
1351
  "button",
1303
1352
  {
1304
1353
  onClick: handleFilterClick,
1305
- className: "grid-header-filter p-1 rounded hover:bg-theme-tertiary",
1354
+ className: "grid-header-filter",
1306
1355
  "aria-label": "Filter column",
1307
1356
  children: /* @__PURE__ */ jsx3(FilterIcon, { active: hasFilter })
1308
1357
  }
@@ -1310,7 +1359,7 @@ function HeaderCell({
1310
1359
  isResizable && /* @__PURE__ */ jsx3(
1311
1360
  "div",
1312
1361
  {
1313
- className: "grid-header-resize absolute right-0 top-0 bottom-0 w-1 cursor-col-resize hover:bg-accent-primary",
1362
+ className: "grid-header-resize",
1314
1363
  onMouseDown: onResizeStart,
1315
1364
  onClick: (e) => e.stopPropagation()
1316
1365
  }
@@ -1330,6 +1379,7 @@ function GridHeader({
1330
1379
  enableDragDrop = true,
1331
1380
  enableResize = true,
1332
1381
  enableSelection = false,
1382
+ enableExpansion = false,
1333
1383
  allSelected = false,
1334
1384
  someSelected = false,
1335
1385
  onSelectAll,
@@ -1401,19 +1451,17 @@ function GridHeader({
1401
1451
  return classes.join(" ");
1402
1452
  }, [sticky]);
1403
1453
  return /* @__PURE__ */ jsxs2("div", { className: `${headerClasses} ${className}`, style, role: "row", children: [
1404
- enableSelection && /* @__PURE__ */ jsx3("div", { className: "grid-header-select flex items-center px-2 border-b border-theme-border", children: /* @__PURE__ */ jsx3(
1405
- "input",
1454
+ enableSelection && /* @__PURE__ */ jsx3("div", { className: "grid-header-select", children: /* @__PURE__ */ jsx3(
1455
+ Checkbox,
1406
1456
  {
1407
- type: "checkbox",
1408
1457
  checked: allSelected,
1409
- ref: (el) => {
1410
- if (el) el.indeterminate = someSelected && !allSelected;
1411
- },
1412
- onChange: onSelectAll,
1413
- className: "w-4 h-4 rounded border-theme-border",
1458
+ indeterminate: someSelected && !allSelected,
1459
+ onChange: () => onSelectAll == null ? void 0 : onSelectAll(),
1460
+ size: "sm",
1414
1461
  "aria-label": "Select all rows"
1415
1462
  }
1416
1463
  ) }),
1464
+ enableExpansion && /* @__PURE__ */ jsx3("div", { className: "grid-header-expand-spacer", "aria-hidden": true }),
1417
1465
  visibleColumns.map((col, index) => {
1418
1466
  const colState = columnStates.find((cs) => cs.id === col.id) || {
1419
1467
  id: col.id,
@@ -1427,7 +1475,7 @@ function GridHeader({
1427
1475
  const hasFilter = state.filters.some((f) => f.columnId === col.id);
1428
1476
  const existingFilter = state.filters.find((f) => f.columnId === col.id);
1429
1477
  const headerText = typeof col.header === "string" ? col.header : col.id;
1430
- return /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
1478
+ return /* @__PURE__ */ jsxs2("div", { className: "relative", style: { position: "relative" }, children: [
1431
1479
  /* @__PURE__ */ jsx3(
1432
1480
  HeaderCell,
1433
1481
  {
@@ -1443,6 +1491,7 @@ function GridHeader({
1443
1491
  hasFilter,
1444
1492
  isDragging: dragDrop.draggingColumnId === col.id,
1445
1493
  isDragOver: dragDrop.dragOverColumnId === col.id,
1494
+ isColumnAutoSized: state.autoSizedColumnIds.has(col.id),
1446
1495
  onSort: () => actions.toggleSorting(col.id),
1447
1496
  onFilterOpen: () => handleFilterClick(col.id),
1448
1497
  onResizeStart: handleResizeStart(col.id, colState.width),
@@ -1473,11 +1522,59 @@ function GridHeader({
1473
1522
  import { useCallback as useCallback10 } from "react";
1474
1523
 
1475
1524
  // src/components/GridRow/GridRow.tsx
1476
- import { useCallback as useCallback9, useMemo as useMemo10, useState as useState5 } from "react";
1525
+ import { useCallback as useCallback9, useMemo as useMemo10, useState as useState6 } from "react";
1526
+ import { Checkbox as Checkbox2 } from "@forgedevstack/bear";
1477
1527
 
1478
1528
  // src/components/GridCell/GridCell.tsx
1479
- import { useMemo as useMemo9, useCallback as useCallback8 } from "react";
1480
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1529
+ import { useMemo as useMemo9, useCallback as useCallback8, useRef as useRef4, useEffect as useEffect4, useState as useState5 } from "react";
1530
+ import { Tooltip, Typography } from "@forgedevstack/bear";
1531
+
1532
+ // src/utils/highlight.utils.tsx
1533
+ import { jsx as jsx4 } from "react/jsx-runtime";
1534
+ function highlightMatch(text, term) {
1535
+ if (!term.trim()) return text;
1536
+ const parts = text.split(new RegExp(`(${escapeRegex(term)})`, "gi"));
1537
+ return parts.map(
1538
+ (part, i) => part.toLowerCase() === term.toLowerCase() ? /* @__PURE__ */ jsx4("mark", { className: "grid-cell-highlight", children: part }, i) : part
1539
+ );
1540
+ }
1541
+ function escapeRegex(s) {
1542
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1543
+ }
1544
+
1545
+ // src/utils/generateSampleData.ts
1546
+ function generateSampleData(columns, rowCount) {
1547
+ const ids = columns.map((c) => c.id);
1548
+ return Array.from({ length: rowCount }, (_, i) => {
1549
+ const row = {};
1550
+ ids.forEach((key) => {
1551
+ if (key === "id" || key === "idNumber") {
1552
+ row[key] = i + 1;
1553
+ } else if (key === "email") {
1554
+ row[key] = `user${i + 1}@example.com`;
1555
+ } else if (key === "name" || key === "firstName" || key === "title") {
1556
+ row[key] = `Sample ${i + 1}`;
1557
+ } else if (key === "status" || key === "role") {
1558
+ row[key] = ["active", "inactive", "pending"][i % 3];
1559
+ } else if (key === "date" || key === "joinDate" || key === "createdAt") {
1560
+ row[key] = new Date(2020 + i % 4, i % 12, i % 28 + 1).toISOString().slice(0, 10);
1561
+ } else if (key === "salary" || key === "amount" || key === "count") {
1562
+ row[key] = 1e3 * (i + 1) + i % 100;
1563
+ } else if (key === "department") {
1564
+ row[key] = ["Engineering", "Design", "Marketing", "Sales", "HR"][i % 5];
1565
+ } else {
1566
+ row[key] = `Value ${i + 1}`;
1567
+ }
1568
+ });
1569
+ if (!("id" in row) && ids.length > 0) {
1570
+ row.id = i + 1;
1571
+ }
1572
+ return row;
1573
+ });
1574
+ }
1575
+
1576
+ // src/components/GridCell/GridCell.tsx
1577
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1481
1578
  var ALIGN_CLASSES2 = {
1482
1579
  left: "text-left justify-start",
1483
1580
  center: "text-center justify-center",
@@ -1487,6 +1584,7 @@ function GridCell({
1487
1584
  column,
1488
1585
  row,
1489
1586
  rowIndex,
1587
+ rowId,
1490
1588
  value,
1491
1589
  width,
1492
1590
  align = "left",
@@ -1498,20 +1596,18 @@ function GridCell({
1498
1596
  stickyOffset = 0,
1499
1597
  onClick
1500
1598
  }) {
1501
- const handleClick = useCallback8(
1502
- (e) => {
1503
- if (onClick) {
1504
- e.stopPropagation();
1505
- onClick({
1506
- row,
1507
- rowIndex,
1508
- columnId: column.id,
1509
- value
1510
- });
1511
- }
1512
- },
1513
- [onClick, row, rowIndex, column.id, value]
1514
- );
1599
+ var _a, _b, _c;
1600
+ const valueRef = useRef4(null);
1601
+ const [overflowTitle, setOverflowTitle] = useState5(void 0);
1602
+ const { state, actions, tableOptions } = useTableContext();
1603
+ const showOverflowTooltip = ((_a = column.showOverflowTooltip) != null ? _a : tableOptions.showOverflowTooltip) !== false;
1604
+ const hasSubCell = Boolean(column.renderSubCell);
1605
+ const trigger = (_c = (_b = column.subCellExpandTrigger) != null ? _b : tableOptions.subCellExpandTrigger) != null ? _c : "both";
1606
+ const showArrow = hasSubCell && (trigger === "arrow" || trigger === "both");
1607
+ const enableCellAutoSize = tableOptions.enableCellAutoSizeOnDoubleClick === true;
1608
+ const cellKey = `${String(rowId)}-${column.id}`;
1609
+ const isSubCellExpanded = state.expandedCellIds.has(cellKey);
1610
+ const isAutoSized = state.autoSizedColumnIds.has(column.id);
1515
1611
  const formattedValue = useMemo9(() => {
1516
1612
  if (column.render) {
1517
1613
  return column.render(value, row, rowIndex);
@@ -1527,9 +1623,53 @@ function GridCell({
1527
1623
  }
1528
1624
  return String(value);
1529
1625
  }, [column, row, rowIndex, value]);
1626
+ useEffect4(() => {
1627
+ var _a2;
1628
+ if (!showOverflowTooltip || !valueRef.current) return;
1629
+ const el = valueRef.current;
1630
+ const truncated = el.scrollWidth > el.clientWidth;
1631
+ const raw = (_a2 = el.textContent) != null ? _a2 : "";
1632
+ setOverflowTitle(truncated && raw ? raw : void 0);
1633
+ }, [showOverflowTooltip, formattedValue]);
1634
+ const handleClick = useCallback8(
1635
+ (e) => {
1636
+ if (onClick) {
1637
+ e.stopPropagation();
1638
+ onClick({
1639
+ row,
1640
+ rowIndex,
1641
+ columnId: column.id,
1642
+ value
1643
+ });
1644
+ }
1645
+ },
1646
+ [onClick, row, rowIndex, column.id, value]
1647
+ );
1648
+ const handleDoubleClick = useCallback8(
1649
+ (e) => {
1650
+ e.stopPropagation();
1651
+ if (hasSubCell && (trigger === "doubleClick" || trigger === "both")) {
1652
+ actions.toggleCellExpansion(rowId, column.id);
1653
+ } else if (enableCellAutoSize) {
1654
+ actions.toggleColumnAutoSize(column.id);
1655
+ }
1656
+ },
1657
+ [hasSubCell, trigger, enableCellAutoSize, actions, rowId, column.id]
1658
+ );
1659
+ const handleExpandClick = useCallback8(
1660
+ (e) => {
1661
+ e.stopPropagation();
1662
+ actions.toggleCellExpansion(rowId, column.id);
1663
+ },
1664
+ [actions, rowId, column.id]
1665
+ );
1530
1666
  const cellStyle = useMemo9(() => {
1531
1667
  const baseStyle = { ...style };
1532
- if (width !== void 0) {
1668
+ if (isAutoSized) {
1669
+ baseStyle.width = "auto";
1670
+ baseStyle.minWidth = "max-content";
1671
+ baseStyle.maxWidth = "none";
1672
+ } else if (width !== void 0) {
1533
1673
  baseStyle.width = typeof width === "number" ? `${width}px` : width;
1534
1674
  baseStyle.minWidth = baseStyle.width;
1535
1675
  baseStyle.maxWidth = baseStyle.width;
@@ -1537,7 +1677,7 @@ function GridCell({
1537
1677
  if (sticky) {
1538
1678
  baseStyle.position = "sticky";
1539
1679
  baseStyle.zIndex = 1;
1540
- baseStyle.backgroundColor = "var(--bg-primary, #1e1e1e)";
1680
+ baseStyle.backgroundColor = "var(--gt-bg-primary, #1e1e1e)";
1541
1681
  if (sticky === "left") {
1542
1682
  baseStyle.left = stickyOffset;
1543
1683
  } else if (sticky === "right") {
@@ -1545,38 +1685,68 @@ function GridCell({
1545
1685
  }
1546
1686
  }
1547
1687
  return baseStyle;
1548
- }, [style, width, sticky, stickyOffset]);
1688
+ }, [style, width, sticky, stickyOffset, isAutoSized]);
1549
1689
  const alignClass = ALIGN_CLASSES2[align];
1550
- const stickyClasses = sticky ? "shadow-[2px_0_4px_-2px_rgba(0,0,0,0.2)]" : "";
1690
+ const stickyClass = sticky ? `sticky-${sticky}` : "";
1691
+ const shouldHighlight = state.globalFilter && typeof formattedValue === "string" && (!tableOptions.globalFilterColumns || tableOptions.globalFilterColumns.length === 0 || tableOptions.globalFilterColumns.includes(column.id));
1692
+ const cellContent = shouldHighlight ? highlightMatch(String(formattedValue), state.globalFilter) : formattedValue;
1551
1693
  return /* @__PURE__ */ jsxs3(
1552
1694
  "div",
1553
1695
  {
1554
1696
  className: `
1555
1697
  grid-cell
1556
- px-4 py-3
1557
- flex items-center
1558
1698
  ${alignClass}
1559
- ${stickyClasses}
1560
- ${onClick ? "cursor-pointer hover:bg-theme-hover" : ""}
1699
+ ${stickyClass}
1700
+ ${onClick ? "cursor-pointer" : ""}
1701
+ ${hasSubCell ? "grid-cell--has-sub" : ""}
1702
+ ${isAutoSized ? "grid-cell--auto-sized" : ""}
1561
1703
  ${column.cellClassName || ""}
1562
1704
  ${className}
1563
1705
  `.trim(),
1564
1706
  style: { ...cellStyle, ...column.cellStyle },
1565
1707
  role: "cell",
1566
1708
  onClick: onClick ? handleClick : void 0,
1709
+ onDoubleClick: handleDoubleClick,
1567
1710
  children: [
1568
- showLabel && labelText && /* @__PURE__ */ jsxs3("span", { className: "grid-cell-label font-medium text-theme-muted mr-2 text-sm", children: [
1569
- labelText,
1570
- ":"
1711
+ /* @__PURE__ */ jsxs3("div", { className: "grid-cell-inner", children: [
1712
+ showLabel && labelText && /* @__PURE__ */ jsxs3(Typography, { component: "span", variant: "body2", color: "secondary", className: "grid-cell-label", children: [
1713
+ labelText,
1714
+ ":"
1715
+ ] }),
1716
+ /* @__PURE__ */ jsx5("div", { className: "grid-cell-value-wrapper", style: { minWidth: 0, overflow: "hidden" }, children: overflowTitle ? /* @__PURE__ */ jsx5(Tooltip, { content: overflowTitle, placement: "top", delay: 200, children: /* @__PURE__ */ jsx5(
1717
+ "span",
1718
+ {
1719
+ ref: valueRef,
1720
+ className: `grid-cell-value ${isAutoSized ? "" : "grid-cell-value--truncate"}`,
1721
+ children: /* @__PURE__ */ jsx5(Typography, { component: "span", variant: "body2", className: "grid-cell-value-text", children: cellContent })
1722
+ }
1723
+ ) }) : /* @__PURE__ */ jsx5(
1724
+ "span",
1725
+ {
1726
+ ref: valueRef,
1727
+ className: `grid-cell-value ${isAutoSized ? "" : "grid-cell-value--truncate"}`,
1728
+ children: /* @__PURE__ */ jsx5(Typography, { component: "span", variant: "body2", children: cellContent })
1729
+ }
1730
+ ) }),
1731
+ showArrow && /* @__PURE__ */ jsx5(
1732
+ "button",
1733
+ {
1734
+ type: "button",
1735
+ className: `grid-cell-expand-trigger ${isSubCellExpanded ? "grid-cell-expand-trigger--expanded" : ""}`,
1736
+ onClick: handleExpandClick,
1737
+ "aria-label": isSubCellExpanded ? "Collapse" : "Expand",
1738
+ "aria-expanded": isSubCellExpanded
1739
+ }
1740
+ )
1571
1741
  ] }),
1572
- /* @__PURE__ */ jsx4("span", { className: "grid-cell-value truncate", children: formattedValue })
1742
+ hasSubCell && isSubCellExpanded && column.renderSubCell && /* @__PURE__ */ jsx5("div", { className: "grid-cell-subcell", children: column.renderSubCell(row) })
1573
1743
  ]
1574
1744
  }
1575
1745
  );
1576
1746
  }
1577
1747
 
1578
1748
  // src/components/GridRow/GridRow.tsx
1579
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1749
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1580
1750
  function GridRow({
1581
1751
  row,
1582
1752
  rowIndex,
@@ -1600,7 +1770,7 @@ function GridRow({
1600
1770
  renderExpansion,
1601
1771
  getRowId
1602
1772
  }) {
1603
- const [isHovered, setIsHovered] = useState5(false);
1773
+ const [isHovered, setIsHovered] = useState6(false);
1604
1774
  const handleClick = useCallback9(() => {
1605
1775
  if (isDisabled) return;
1606
1776
  onClick == null ? void 0 : onClick(row, rowIndex);
@@ -1616,10 +1786,13 @@ function GridRow({
1616
1786
  },
1617
1787
  [onContextMenu, row, rowIndex, isDisabled]
1618
1788
  );
1619
- const handleSelectChange = useCallback9(() => {
1620
- if (isDisabled) return;
1621
- onSelect == null ? void 0 : onSelect(!isSelected);
1622
- }, [onSelect, isSelected, isDisabled]);
1789
+ const handleSelectChange = useCallback9(
1790
+ (selected) => {
1791
+ if (isDisabled) return;
1792
+ onSelect == null ? void 0 : onSelect(selected);
1793
+ },
1794
+ [onSelect, isDisabled]
1795
+ );
1623
1796
  const handleExpandToggle = useCallback9(() => {
1624
1797
  if (isDisabled) return;
1625
1798
  onExpand == null ? void 0 : onExpand(!isExpanded);
@@ -1688,26 +1861,25 @@ function GridRow({
1688
1861
  onMouseEnter: () => setIsHovered(true),
1689
1862
  onMouseLeave: () => setIsHovered(false),
1690
1863
  children: [
1691
- enableSelection && /* @__PURE__ */ jsx5("div", { className: "grid-row-select flex items-center px-2", children: /* @__PURE__ */ jsx5(
1692
- "input",
1864
+ enableSelection && /* @__PURE__ */ jsx6("div", { className: "grid-row-select", children: /* @__PURE__ */ jsx6(
1865
+ Checkbox2,
1693
1866
  {
1694
- type: "checkbox",
1695
- checked: isSelected,
1696
- onChange: handleSelectChange,
1867
+ checked: isSelected != null ? isSelected : false,
1868
+ onChange: (e) => handleSelectChange(e.target.checked),
1697
1869
  disabled: isDisabled,
1698
- className: "w-4 h-4 rounded border-theme-border",
1870
+ size: "sm",
1699
1871
  "aria-label": "Select row"
1700
1872
  }
1701
1873
  ) }),
1702
- enableExpansion && renderExpansion && /* @__PURE__ */ jsx5("div", { className: "grid-row-expand flex items-center px-2", children: /* @__PURE__ */ jsx5(
1874
+ enableExpansion && renderExpansion && /* @__PURE__ */ jsx6("div", { className: "grid-row-expand", children: /* @__PURE__ */ jsx6(
1703
1875
  "button",
1704
1876
  {
1705
1877
  onClick: handleExpandToggle,
1706
1878
  disabled: isDisabled,
1707
- className: "w-6 h-6 flex items-center justify-center rounded hover:bg-theme-tertiary",
1879
+ className: "grid-row-expand-button",
1708
1880
  "aria-label": isExpanded ? "Collapse row" : "Expand row",
1709
1881
  "aria-expanded": isExpanded,
1710
- children: /* @__PURE__ */ jsx5(
1882
+ children: /* @__PURE__ */ jsx6(
1711
1883
  "span",
1712
1884
  {
1713
1885
  className: `transform transition-transform duration-200 ${isExpanded ? "rotate-90" : ""}`,
@@ -1739,18 +1911,19 @@ function GridRow({
1739
1911
  }
1740
1912
  }
1741
1913
  }
1742
- return /* @__PURE__ */ jsx5(
1914
+ return /* @__PURE__ */ jsx6(
1743
1915
  GridCell,
1744
1916
  {
1745
1917
  column: col,
1746
1918
  row,
1747
1919
  rowIndex,
1920
+ rowId: getRowId(row),
1748
1921
  value: getCellValue(col),
1749
1922
  width,
1750
1923
  align: col.align,
1751
1924
  showLabel: isMobile && showMobileLabels && col.showLabelOnMobile !== false,
1752
1925
  labelText: typeof col.header === "string" ? col.header : col.id,
1753
- className: isMobile ? "w-full sm:w-auto flex-shrink-0" : "flex-shrink-0",
1926
+ className: isMobile ? "w-full-sm flex-shrink-0" : "flex-shrink-0",
1754
1927
  sticky: col.sticky,
1755
1928
  stickyOffset,
1756
1929
  onClick: onCellClick
@@ -1761,12 +1934,12 @@ function GridRow({
1761
1934
  ]
1762
1935
  }
1763
1936
  ),
1764
- isExpanded && renderExpansion && /* @__PURE__ */ jsx5("div", { className: "grid-row-expansion border-b border-theme-border bg-theme-secondary p-4", children: renderExpansion(row) })
1937
+ isExpanded && renderExpansion && /* @__PURE__ */ jsx6("div", { className: "grid-row-expansion", children: renderExpansion(row, getRowId(row)) })
1765
1938
  ] });
1766
1939
  }
1767
1940
 
1768
1941
  // src/components/GridBody/GridBody.tsx
1769
- import { jsx as jsx6 } from "react/jsx-runtime";
1942
+ import { jsx as jsx7 } from "react/jsx-runtime";
1770
1943
  function GridBody({
1771
1944
  data,
1772
1945
  columns,
@@ -1807,7 +1980,7 @@ function GridBody({
1807
1980
  if (data.length === 0) {
1808
1981
  return null;
1809
1982
  }
1810
- return /* @__PURE__ */ jsx6("div", { className: `grid-body ${className}`, style, role: "rowgroup", children: data.map((row, index) => {
1983
+ return /* @__PURE__ */ jsx7("div", { className: `grid-body ${className}`, style, role: "rowgroup", children: data.map((row, index) => {
1811
1984
  var _a, _b;
1812
1985
  const rowId = getRowId(row);
1813
1986
  const isSelected = selectedIds.has(rowId);
@@ -1815,7 +1988,7 @@ function GridBody({
1815
1988
  const isDisabled = (_a = isRowDisabled == null ? void 0 : isRowDisabled(row)) != null ? _a : false;
1816
1989
  const rowClassName = (_b = getRowClassName == null ? void 0 : getRowClassName(row, index)) != null ? _b : "";
1817
1990
  const rowStyle = getRowStyle == null ? void 0 : getRowStyle(row, index);
1818
- return /* @__PURE__ */ jsx6(
1991
+ return /* @__PURE__ */ jsx7(
1819
1992
  GridRow,
1820
1993
  {
1821
1994
  row,
@@ -1844,181 +2017,11 @@ function GridBody({
1844
2017
  }) });
1845
2018
  }
1846
2019
 
1847
- // src/components/Pagination/Pagination.tsx
1848
- import { useMemo as useMemo11, useCallback as useCallback11 } from "react";
1849
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1850
- function Pagination({
1851
- page,
1852
- pageSize,
1853
- totalItems,
1854
- totalPages,
1855
- pageSizeOptions = [10, 20, 50, 100],
1856
- showFirstLast = true,
1857
- showPageNumbers = true,
1858
- maxPageButtons = FIVE,
1859
- className = "",
1860
- style,
1861
- onPageChange,
1862
- onPageSizeChange
1863
- }) {
1864
- const { state } = useTableContext();
1865
- const { translations } = state;
1866
- const canGoPrevious = page > ONE;
1867
- const canGoNext = page < totalPages;
1868
- const startItem = (page - ONE) * pageSize + ONE;
1869
- const endItem = Math.min(page * pageSize, totalItems);
1870
- const handleFirstPage = useCallback11(() => {
1871
- onPageChange(ONE);
1872
- }, [onPageChange]);
1873
- const handlePreviousPage = useCallback11(() => {
1874
- if (canGoPrevious) {
1875
- onPageChange(page - ONE);
1876
- }
1877
- }, [canGoPrevious, page, onPageChange]);
1878
- const handleNextPage = useCallback11(() => {
1879
- if (canGoNext) {
1880
- onPageChange(page + ONE);
1881
- }
1882
- }, [canGoNext, page, onPageChange]);
1883
- const handleLastPage = useCallback11(() => {
1884
- onPageChange(totalPages);
1885
- }, [onPageChange, totalPages]);
1886
- const handlePageSizeChange = useCallback11(
1887
- (event) => {
1888
- onPageSizeChange(Number(event.target.value));
1889
- },
1890
- [onPageSizeChange]
1891
- );
1892
- const pageNumbers = useMemo11(() => {
1893
- if (!showPageNumbers || totalPages <= ONE) return [];
1894
- const pages = [];
1895
- const halfMax = Math.floor(maxPageButtons / 2);
1896
- let start = Math.max(ONE, page - halfMax);
1897
- let end = Math.min(totalPages, page + halfMax);
1898
- if (page <= halfMax) {
1899
- end = Math.min(totalPages, maxPageButtons);
1900
- }
1901
- if (page > totalPages - halfMax) {
1902
- start = Math.max(ONE, totalPages - maxPageButtons + ONE);
1903
- }
1904
- if (start > ONE) {
1905
- pages.push(ONE);
1906
- if (start > 2) {
1907
- pages.push("ellipsis");
1908
- }
1909
- }
1910
- for (let i = start; i <= end; i++) {
1911
- if (!pages.includes(i)) {
1912
- pages.push(i);
1913
- }
1914
- }
1915
- if (end < totalPages) {
1916
- if (end < totalPages - ONE) {
1917
- pages.push("ellipsis");
1918
- }
1919
- pages.push(totalPages);
1920
- }
1921
- return pages;
1922
- }, [page, totalPages, showPageNumbers, maxPageButtons]);
1923
- if (totalItems === 0) {
1924
- return null;
1925
- }
1926
- return /* @__PURE__ */ jsxs5(
1927
- "div",
1928
- {
1929
- className: `grid-pagination flex flex-wrap items-center justify-between gap-4 px-4 py-3 border-t border-theme-border ${className}`,
1930
- style,
1931
- role: "navigation",
1932
- "aria-label": "Pagination",
1933
- children: [
1934
- /* @__PURE__ */ jsxs5("div", { className: "grid-pagination-info flex items-center gap-4", children: [
1935
- /* @__PURE__ */ jsxs5("div", { className: "grid-pagination-range text-sm text-theme-secondary", children: [
1936
- startItem,
1937
- "-",
1938
- endItem,
1939
- " ",
1940
- translations.of,
1941
- " ",
1942
- totalItems
1943
- ] }),
1944
- /* @__PURE__ */ jsxs5("div", { className: "grid-pagination-size flex items-center gap-2", children: [
1945
- /* @__PURE__ */ jsxs5("label", { htmlFor: "page-size", className: "text-sm text-theme-muted", children: [
1946
- translations.rowsPerPage,
1947
- ":"
1948
- ] }),
1949
- /* @__PURE__ */ jsx7(
1950
- "select",
1951
- {
1952
- id: "page-size",
1953
- value: pageSize,
1954
- onChange: handlePageSizeChange,
1955
- className: "px-2 py-1 text-sm rounded border border-theme-border bg-theme-primary text-theme-primary focus:outline-none focus:ring-2 focus:ring-accent-primary",
1956
- children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx7("option", { value: size, children: size }, size))
1957
- }
1958
- )
1959
- ] })
1960
- ] }),
1961
- /* @__PURE__ */ jsxs5("div", { className: "grid-pagination-controls flex items-center gap-1", children: [
1962
- showFirstLast && /* @__PURE__ */ jsx7(
1963
- "button",
1964
- {
1965
- onClick: handleFirstPage,
1966
- disabled: !canGoPrevious,
1967
- className: "p-2 rounded hover:bg-theme-hover disabled:opacity-50 disabled:cursor-not-allowed text-theme-secondary",
1968
- "aria-label": translations.first,
1969
- children: "<<"
1970
- }
1971
- ),
1972
- /* @__PURE__ */ jsx7(
1973
- "button",
1974
- {
1975
- onClick: handlePreviousPage,
1976
- disabled: !canGoPrevious,
1977
- className: "p-2 rounded hover:bg-theme-hover disabled:opacity-50 disabled:cursor-not-allowed text-theme-secondary",
1978
- "aria-label": translations.previous,
1979
- children: "<"
1980
- }
1981
- ),
1982
- showPageNumbers && /* @__PURE__ */ jsx7("div", { className: "grid-pagination-pages flex items-center gap-1", children: pageNumbers.map(
1983
- (pageNum, index) => pageNum === "ellipsis" ? /* @__PURE__ */ jsx7("span", { className: "px-2 text-theme-muted", children: "..." }, `ellipsis-${index}`) : /* @__PURE__ */ jsx7(
1984
- "button",
1985
- {
1986
- onClick: () => onPageChange(pageNum),
1987
- className: `min-w-[32px] h-8 px-2 rounded text-sm transition-colors ${pageNum === page ? "bg-accent-primary text-white" : "hover:bg-theme-hover text-theme-secondary"}`,
1988
- "aria-current": pageNum === page ? "page" : void 0,
1989
- children: pageNum
1990
- },
1991
- pageNum
1992
- )
1993
- ) }),
1994
- /* @__PURE__ */ jsx7(
1995
- "button",
1996
- {
1997
- onClick: handleNextPage,
1998
- disabled: !canGoNext,
1999
- className: "p-2 rounded hover:bg-theme-hover disabled:opacity-50 disabled:cursor-not-allowed text-theme-secondary",
2000
- "aria-label": translations.next,
2001
- children: ">"
2002
- }
2003
- ),
2004
- showFirstLast && /* @__PURE__ */ jsx7(
2005
- "button",
2006
- {
2007
- onClick: handleLastPage,
2008
- disabled: !canGoNext,
2009
- className: "p-2 rounded hover:bg-theme-hover disabled:opacity-50 disabled:cursor-not-allowed text-theme-secondary",
2010
- "aria-label": translations.last,
2011
- children: ">>"
2012
- }
2013
- )
2014
- ] })
2015
- ]
2016
- }
2017
- );
2018
- }
2020
+ // src/components/GridTable/GridTable.tsx
2021
+ import { Pagination as BearPagination, Typography as Typography3, Select, BearProvider } from "@forgedevstack/bear";
2019
2022
 
2020
2023
  // src/components/Skeleton/Skeleton.tsx
2021
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
2024
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
2022
2025
  function SkeletonCell({ width = DEFAULT_COLUMN_WIDTH, height = 16, animate = true }) {
2023
2026
  const widthStyle = typeof width === "number" ? `${width}px` : width;
2024
2027
  return /* @__PURE__ */ jsx8(
@@ -2029,7 +2032,7 @@ function SkeletonCell({ width = DEFAULT_COLUMN_WIDTH, height = 16, animate = tru
2029
2032
  children: /* @__PURE__ */ jsx8(
2030
2033
  "div",
2031
2034
  {
2032
- className: `rounded bg-theme-tertiary ${animate ? "animate-pulse" : ""}`,
2035
+ className: `rounded ${animate ? "animate-pulse" : ""}`,
2033
2036
  style: { height: `${height}px`, width: "80%" }
2034
2037
  }
2035
2038
  )
@@ -2037,7 +2040,7 @@ function SkeletonCell({ width = DEFAULT_COLUMN_WIDTH, height = 16, animate = tru
2037
2040
  );
2038
2041
  }
2039
2042
  function SkeletonRow({ columns, columnWidths, height = 16, animate = true }) {
2040
- return /* @__PURE__ */ jsx8("div", { className: "grid-skeleton-row flex border-b border-theme-border", children: Array.from({ length: columns }).map((_, index) => {
2043
+ return /* @__PURE__ */ jsx8("div", { className: "grid-skeleton-row", children: Array.from({ length: columns }).map((_, index) => {
2041
2044
  var _a;
2042
2045
  return /* @__PURE__ */ jsx8(
2043
2046
  SkeletonCell,
@@ -2060,8 +2063,8 @@ function Skeleton({
2060
2063
  showHeader = true,
2061
2064
  animate = true
2062
2065
  }) {
2063
- return /* @__PURE__ */ jsxs6("div", { className: `grid-skeleton ${className}`, style, role: "status", "aria-label": "Loading", children: [
2064
- showHeader && /* @__PURE__ */ jsx8("div", { className: "grid-skeleton-header flex border-b border-theme-border bg-theme-secondary", children: Array.from({ length: columns }).map((_, index) => {
2066
+ return /* @__PURE__ */ jsxs5("div", { className: `grid-skeleton ${className}`, style, role: "status", "aria-label": "Loading", children: [
2067
+ showHeader && /* @__PURE__ */ jsx8("div", { className: "grid-skeleton-header", children: Array.from({ length: columns }).map((_, index) => {
2065
2068
  var _a;
2066
2069
  return /* @__PURE__ */ jsx8(
2067
2070
  "div",
@@ -2071,7 +2074,7 @@ function Skeleton({
2071
2074
  children: /* @__PURE__ */ jsx8(
2072
2075
  "div",
2073
2076
  {
2074
- className: `rounded bg-theme-tertiary ${animate ? "animate-pulse" : ""}`,
2077
+ className: `rounded ${animate ? "animate-pulse" : ""}`,
2075
2078
  style: { height: "12px", width: "60%" }
2076
2079
  }
2077
2080
  )
@@ -2092,8 +2095,203 @@ function Skeleton({
2092
2095
  ] });
2093
2096
  }
2094
2097
 
2098
+ // src/components/TableStudioPanel/TableStudioPanel.tsx
2099
+ import { useState as useState7, useCallback as useCallback11 } from "react";
2100
+ import { Typography as Typography2 } from "@forgedevstack/bear";
2101
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
2102
+ var DEFAULT_ROW_COUNT = 10;
2103
+ function TableStudioPanel({
2104
+ data,
2105
+ columns,
2106
+ propsSnapshot,
2107
+ onDataChange,
2108
+ open = true,
2109
+ onOpenChange
2110
+ }) {
2111
+ const [activeTab, setActiveTab] = useState7("data");
2112
+ const [generateCount, setGenerateCount] = useState7(DEFAULT_ROW_COUNT);
2113
+ const handleGenerate = useCallback11(() => {
2114
+ if (!onDataChange) return;
2115
+ const count = Math.min(100, Math.max(1, generateCount));
2116
+ const generated = generateSampleData(columns, count);
2117
+ onDataChange(generated);
2118
+ setActiveTab("data");
2119
+ }, [columns, generateCount, onDataChange]);
2120
+ const panelContent = /* @__PURE__ */ jsxs6(Fragment3, { children: [
2121
+ /* @__PURE__ */ jsx9(
2122
+ "div",
2123
+ {
2124
+ style: {
2125
+ display: "flex",
2126
+ borderBottom: "1px solid var(--gt-border-color, rgba(0,0,0,0.08))",
2127
+ padding: "0.25rem 0",
2128
+ gap: 2
2129
+ },
2130
+ children: ["data", "props", "generate"].map((tab) => /* @__PURE__ */ jsx9(
2131
+ "button",
2132
+ {
2133
+ type: "button",
2134
+ onClick: () => setActiveTab(tab),
2135
+ style: {
2136
+ flex: 1,
2137
+ padding: "0.5rem 0.5rem",
2138
+ border: "none",
2139
+ borderRadius: 4,
2140
+ background: activeTab === tab ? "var(--gt-bg-tertiary)" : "transparent",
2141
+ color: "var(--gt-text-primary)",
2142
+ cursor: "pointer",
2143
+ fontWeight: activeTab === tab ? 600 : 400,
2144
+ fontSize: 12,
2145
+ textTransform: "capitalize"
2146
+ },
2147
+ children: tab
2148
+ },
2149
+ tab
2150
+ ))
2151
+ }
2152
+ ),
2153
+ /* @__PURE__ */ jsxs6("div", { style: { flex: 1, overflow: "auto", padding: "0.75rem" }, children: [
2154
+ activeTab === "data" && /* @__PURE__ */ jsxs6(Fragment3, { children: [
2155
+ /* @__PURE__ */ jsxs6(Typography2, { variant: "subtitle2", component: "h3", style: { marginBottom: "0.5rem" }, children: [
2156
+ "Data (",
2157
+ data.length,
2158
+ " rows)"
2159
+ ] }),
2160
+ /* @__PURE__ */ jsx9(
2161
+ "pre",
2162
+ {
2163
+ style: {
2164
+ margin: 0,
2165
+ fontSize: 11,
2166
+ fontFamily: "monospace",
2167
+ whiteSpace: "pre-wrap",
2168
+ wordBreak: "break-word",
2169
+ color: "var(--gt-text-primary)"
2170
+ },
2171
+ children: JSON.stringify(data, null, 2)
2172
+ }
2173
+ )
2174
+ ] }),
2175
+ activeTab === "props" && /* @__PURE__ */ jsxs6(Fragment3, { children: [
2176
+ /* @__PURE__ */ jsx9(Typography2, { variant: "subtitle2", component: "h3", style: { marginBottom: "0.5rem" }, children: "Props" }),
2177
+ /* @__PURE__ */ jsx9("dl", { style: { margin: 0, fontSize: 13, color: "var(--gt-text-primary)" }, children: Object.entries(propsSnapshot).map(([key, value]) => /* @__PURE__ */ jsxs6("div", { style: { marginBottom: "0.5rem" }, children: [
2178
+ /* @__PURE__ */ jsx9("dt", { style: { fontWeight: 600, marginBottom: 2 }, children: key }),
2179
+ /* @__PURE__ */ jsx9("dd", { style: { margin: 0, color: "var(--gt-text-secondary)" }, children: typeof value === "object" && value !== null ? JSON.stringify(value) : String(value) })
2180
+ ] }, key)) })
2181
+ ] }),
2182
+ activeTab === "generate" && /* @__PURE__ */ jsxs6(Fragment3, { children: [
2183
+ /* @__PURE__ */ jsx9(Typography2, { variant: "subtitle2", component: "h3", style: { marginBottom: "0.5rem" }, children: "Generate sample data" }),
2184
+ /* @__PURE__ */ jsx9("p", { style: { fontSize: 12, color: "var(--gt-text-secondary)", marginBottom: "0.75rem" }, children: "Create rows from column definitions. Uses placeholders for common fields (name, email, id, etc.)." }),
2185
+ /* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
2186
+ /* @__PURE__ */ jsxs6("label", { style: { fontSize: 12, fontWeight: 500 }, children: [
2187
+ "Rows",
2188
+ /* @__PURE__ */ jsx9(
2189
+ "input",
2190
+ {
2191
+ type: "number",
2192
+ min: 1,
2193
+ max: 100,
2194
+ value: generateCount,
2195
+ onChange: (e) => setGenerateCount(Number(e.target.value) || 1),
2196
+ style: {
2197
+ display: "block",
2198
+ marginTop: 4,
2199
+ width: "100%",
2200
+ padding: "6px 8px",
2201
+ borderRadius: 4,
2202
+ border: "1px solid var(--gt-border-color)",
2203
+ background: "var(--gt-bg-primary)",
2204
+ color: "var(--gt-text-primary)"
2205
+ }
2206
+ }
2207
+ )
2208
+ ] }),
2209
+ /* @__PURE__ */ jsx9(
2210
+ "button",
2211
+ {
2212
+ type: "button",
2213
+ onClick: handleGenerate,
2214
+ disabled: !onDataChange,
2215
+ style: {
2216
+ padding: "8px 12px",
2217
+ borderRadius: 6,
2218
+ border: "none",
2219
+ background: onDataChange ? "var(--gt-accent-primary)" : "var(--gt-bg-tertiary)",
2220
+ color: onDataChange ? "#fff" : "var(--gt-text-muted)",
2221
+ cursor: onDataChange ? "pointer" : "not-allowed",
2222
+ fontWeight: 500,
2223
+ fontSize: 13
2224
+ },
2225
+ children: "Generate data"
2226
+ }
2227
+ ),
2228
+ !onDataChange && /* @__PURE__ */ jsx9("span", { style: { fontSize: 11, color: "var(--gt-text-muted)" }, children: "Table must use studio with controllable data to generate." })
2229
+ ] })
2230
+ ] })
2231
+ ] })
2232
+ ] });
2233
+ const width = 320;
2234
+ const isCollapsed = !open;
2235
+ return /* @__PURE__ */ jsxs6(Fragment3, { children: [
2236
+ /* @__PURE__ */ jsx9(
2237
+ "button",
2238
+ {
2239
+ type: "button",
2240
+ onClick: () => onOpenChange == null ? void 0 : onOpenChange(!open),
2241
+ className: "grid-table-studio-toggle",
2242
+ style: {
2243
+ position: "fixed",
2244
+ right: open ? width : 0,
2245
+ top: "50%",
2246
+ transform: "translateY(-50%)",
2247
+ zIndex: 10001,
2248
+ width: 24,
2249
+ height: 48,
2250
+ border: "1px solid var(--gt-border-color, rgba(0,0,0,0.08))",
2251
+ borderRight: "none",
2252
+ borderRadius: "8px 0 0 8px",
2253
+ background: "var(--gt-bg-secondary, #f5f5f5)",
2254
+ color: "var(--gt-text-primary)",
2255
+ cursor: "pointer",
2256
+ display: "flex",
2257
+ alignItems: "center",
2258
+ justifyContent: "center",
2259
+ fontSize: 14,
2260
+ boxShadow: " -2px 0 8px rgba(0,0,0,0.08)"
2261
+ },
2262
+ "aria-label": open ? "Close studio panel" : "Open studio panel",
2263
+ children: open ? "\u203A" : "\u2039"
2264
+ }
2265
+ ),
2266
+ /* @__PURE__ */ jsx9(
2267
+ "aside",
2268
+ {
2269
+ className: "grid-table-studio-panel",
2270
+ style: {
2271
+ position: "fixed",
2272
+ top: 0,
2273
+ right: 0,
2274
+ bottom: 0,
2275
+ width: isCollapsed ? 0 : width,
2276
+ minWidth: isCollapsed ? 0 : 280,
2277
+ borderLeft: "1px solid var(--gt-border-color, rgba(0,0,0,0.08))",
2278
+ backgroundColor: "var(--gt-bg-secondary, #f5f5f5)",
2279
+ display: "flex",
2280
+ flexDirection: "column",
2281
+ overflow: "hidden",
2282
+ zIndex: 1e4,
2283
+ boxShadow: isCollapsed ? "none" : "-4px 0 12px rgba(0,0,0,0.08)",
2284
+ transition: "width 0.2s ease, box-shadow 0.2s ease"
2285
+ },
2286
+ "aria-label": "Table studio panel",
2287
+ children: !isCollapsed && panelContent
2288
+ }
2289
+ )
2290
+ ] });
2291
+ }
2292
+
2095
2293
  // src/components/EmptyState/EmptyState.tsx
2096
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
2294
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2097
2295
  function EmptyState({
2098
2296
  title,
2099
2297
  description,
@@ -2109,19 +2307,19 @@ function EmptyState({
2109
2307
  return /* @__PURE__ */ jsxs7(
2110
2308
  "div",
2111
2309
  {
2112
- className: `grid-empty-state flex flex-col items-center justify-center py-16 px-8 text-center ${className}`,
2310
+ className: `grid-empty-state ${className}`,
2113
2311
  style,
2114
2312
  role: "status",
2115
2313
  children: [
2116
- icon && /* @__PURE__ */ jsx9("div", { className: "grid-empty-icon mb-4 text-theme-muted text-4xl", children: icon }),
2117
- !icon && /* @__PURE__ */ jsx9("div", { className: "grid-empty-icon mb-4 text-theme-muted", children: /* @__PURE__ */ jsx9(
2314
+ icon && /* @__PURE__ */ jsx10("div", { className: "grid-empty-icon", children: icon }),
2315
+ !icon && /* @__PURE__ */ jsx10("div", { className: "grid-empty-icon", children: /* @__PURE__ */ jsx10(
2118
2316
  "svg",
2119
2317
  {
2120
- className: "w-16 h-16",
2318
+ className: "icon-lg",
2121
2319
  fill: "none",
2122
2320
  viewBox: "0 0 24 24",
2123
2321
  stroke: "currentColor",
2124
- children: /* @__PURE__ */ jsx9(
2322
+ children: /* @__PURE__ */ jsx10(
2125
2323
  "path",
2126
2324
  {
2127
2325
  strokeLinecap: "round",
@@ -2132,25 +2330,25 @@ function EmptyState({
2132
2330
  )
2133
2331
  }
2134
2332
  ) }),
2135
- /* @__PURE__ */ jsx9("h3", { className: "grid-empty-title text-lg font-medium text-theme-primary mb-2", children: displayTitle }),
2136
- displayDescription && /* @__PURE__ */ jsx9("p", { className: "grid-empty-description text-sm text-theme-muted max-w-sm mb-4", children: displayDescription }),
2137
- action && /* @__PURE__ */ jsx9("div", { className: "grid-empty-action", children: action })
2333
+ /* @__PURE__ */ jsx10("h3", { className: "grid-empty-title", children: displayTitle }),
2334
+ displayDescription && /* @__PURE__ */ jsx10("p", { className: "grid-empty-description", children: displayDescription }),
2335
+ action && /* @__PURE__ */ jsx10("div", { className: "grid-empty-action", children: action })
2138
2336
  ]
2139
2337
  }
2140
2338
  );
2141
2339
  }
2142
2340
 
2143
2341
  // src/components/MobileDrawer/MobileDrawer.tsx
2144
- import { useEffect as useEffect4, useCallback as useCallback12 } from "react";
2145
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
2342
+ import { useEffect as useEffect5, useCallback as useCallback12 } from "react";
2343
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
2146
2344
  function DrawerHeader({ title, onClose }) {
2147
- return /* @__PURE__ */ jsxs8("div", { className: "drawer-header flex items-center justify-between px-4 py-3 border-b border-theme-border", children: [
2148
- /* @__PURE__ */ jsx10("h3", { className: "text-lg font-medium text-theme-primary", children: title }),
2149
- /* @__PURE__ */ jsx10(
2345
+ return /* @__PURE__ */ jsxs8("div", { className: "drawer-header", children: [
2346
+ /* @__PURE__ */ jsx11("h3", { children: title }),
2347
+ /* @__PURE__ */ jsx11(
2150
2348
  "button",
2151
2349
  {
2152
2350
  onClick: onClose,
2153
- className: "p-2 rounded hover:bg-theme-hover text-theme-secondary",
2351
+ className: "p-2 rounded",
2154
2352
  "aria-label": "Close",
2155
2353
  children: "X"
2156
2354
  }
@@ -2163,30 +2361,30 @@ function FilterContent() {
2163
2361
  const handleClearAll = useCallback12(() => {
2164
2362
  actions.clearFilters();
2165
2363
  }, [actions]);
2166
- return /* @__PURE__ */ jsxs8("div", { className: "drawer-filter-content p-4 space-y-4", children: [
2167
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between mb-4", children: [
2364
+ return /* @__PURE__ */ jsxs8("div", { className: "drawer-filter-content", children: [
2365
+ /* @__PURE__ */ jsxs8("div", { children: [
2168
2366
  /* @__PURE__ */ jsxs8("span", { className: "text-sm text-theme-muted", children: [
2169
2367
  filters.length,
2170
2368
  " ",
2171
2369
  translations.filter,
2172
2370
  "(s) active"
2173
2371
  ] }),
2174
- filters.length > 0 && /* @__PURE__ */ jsx10(
2372
+ filters.length > 0 && /* @__PURE__ */ jsx11(
2175
2373
  "button",
2176
2374
  {
2177
2375
  onClick: handleClearAll,
2178
- className: "text-sm text-accent-primary hover:underline",
2376
+ className: "text-sm",
2179
2377
  children: translations.clearAll
2180
2378
  }
2181
2379
  )
2182
2380
  ] }),
2183
- /* @__PURE__ */ jsx10("div", { className: "space-y-3", children: columns.filter((col) => col.filterable !== false).map((col) => {
2381
+ /* @__PURE__ */ jsx11("div", { className: "space-y-3", children: columns.filter((col) => col.filterable !== false).map((col) => {
2184
2382
  var _a;
2185
2383
  const existingFilter = filters.find((f) => f.columnId === col.id);
2186
2384
  const headerText = typeof col.header === "string" ? col.header : col.id;
2187
2385
  return /* @__PURE__ */ jsxs8("div", { className: "filter-item", children: [
2188
- /* @__PURE__ */ jsx10("label", { className: "block text-sm font-medium text-theme-secondary mb-1", children: headerText }),
2189
- /* @__PURE__ */ jsx10(
2386
+ /* @__PURE__ */ jsx11("label", { className: "block text-sm font-medium text-theme-secondary mb-1", children: headerText }),
2387
+ /* @__PURE__ */ jsx11(
2190
2388
  "input",
2191
2389
  {
2192
2390
  type: "text",
@@ -2199,7 +2397,7 @@ function FilterContent() {
2199
2397
  }
2200
2398
  },
2201
2399
  placeholder: `${translations.filter} ${headerText}...`,
2202
- className: "w-full px-3 py-2 text-sm rounded border border-theme-border bg-theme-primary text-theme-primary focus:outline-none focus:ring-2 focus:ring-accent-primary"
2400
+ className: "w-full px-3 py-2 text-sm rounded"
2203
2401
  }
2204
2402
  )
2205
2403
  ] }, col.id);
@@ -2212,34 +2410,34 @@ function SortContent() {
2212
2410
  const handleClearAll = useCallback12(() => {
2213
2411
  actions.clearSorting();
2214
2412
  }, [actions]);
2215
- return /* @__PURE__ */ jsxs8("div", { className: "drawer-sort-content p-4 space-y-4", children: [
2216
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between mb-4", children: [
2413
+ return /* @__PURE__ */ jsxs8("div", { className: "drawer-sort-content", children: [
2414
+ /* @__PURE__ */ jsxs8("div", { children: [
2217
2415
  /* @__PURE__ */ jsxs8("span", { className: "text-sm text-theme-muted", children: [
2218
2416
  sorting.length,
2219
2417
  " ",
2220
2418
  translations.sort,
2221
2419
  "(s) active"
2222
2420
  ] }),
2223
- sorting.length > 0 && /* @__PURE__ */ jsx10(
2421
+ sorting.length > 0 && /* @__PURE__ */ jsx11(
2224
2422
  "button",
2225
2423
  {
2226
2424
  onClick: handleClearAll,
2227
- className: "text-sm text-accent-primary hover:underline",
2425
+ className: "text-sm",
2228
2426
  children: translations.clearAll
2229
2427
  }
2230
2428
  )
2231
2429
  ] }),
2232
- /* @__PURE__ */ jsx10("div", { className: "space-y-2", children: columns.filter((col) => col.sortable !== false).map((col) => {
2430
+ /* @__PURE__ */ jsx11("div", { className: "space-y-2", children: columns.filter((col) => col.sortable !== false).map((col) => {
2233
2431
  const sortItem = sorting.find((s) => s.columnId === col.id);
2234
2432
  const headerText = typeof col.header === "string" ? col.header : col.id;
2235
2433
  return /* @__PURE__ */ jsxs8(
2236
2434
  "button",
2237
2435
  {
2238
2436
  onClick: () => actions.toggleSorting(col.id),
2239
- className: `w-full flex items-center justify-between px-3 py-2 rounded border transition-colors ${sortItem ? "border-accent-primary bg-accent-primary/10" : "border-theme-border hover:bg-theme-hover"}`,
2437
+ className: `w-full px-3 py-2 rounded ${sortItem ? "active" : ""}`,
2240
2438
  children: [
2241
- /* @__PURE__ */ jsx10("span", { className: "text-sm text-theme-primary", children: headerText }),
2242
- /* @__PURE__ */ jsx10("span", { className: "text-xs text-theme-muted", children: (sortItem == null ? void 0 : sortItem.direction) === "asc" ? translations.sortAsc : (sortItem == null ? void 0 : sortItem.direction) === "desc" ? translations.sortDesc : "-" })
2439
+ /* @__PURE__ */ jsx11("span", { className: "text-sm text-theme-primary", children: headerText }),
2440
+ /* @__PURE__ */ jsx11("span", { className: "text-xs text-theme-muted", children: (sortItem == null ? void 0 : sortItem.direction) === "asc" ? translations.sortAsc : (sortItem == null ? void 0 : sortItem.direction) === "desc" ? translations.sortDesc : "-" })
2243
2441
  ]
2244
2442
  },
2245
2443
  col.id
@@ -2250,37 +2448,37 @@ function SortContent() {
2250
2448
  function ColumnsContent() {
2251
2449
  const { state, actions } = useTableContext();
2252
2450
  const { translations, columns, columnStates } = state;
2253
- return /* @__PURE__ */ jsxs8("div", { className: "drawer-columns-content p-4 space-y-4", children: [
2254
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between mb-4", children: [
2255
- /* @__PURE__ */ jsx10("span", { className: "text-sm text-theme-muted", children: translations.showColumns }),
2256
- /* @__PURE__ */ jsx10(
2451
+ return /* @__PURE__ */ jsxs8("div", { className: "drawer-columns-content", children: [
2452
+ /* @__PURE__ */ jsxs8("div", { children: [
2453
+ /* @__PURE__ */ jsx11("span", { className: "text-sm text-theme-muted", children: translations.showColumns }),
2454
+ /* @__PURE__ */ jsx11(
2257
2455
  "button",
2258
2456
  {
2259
2457
  onClick: actions.resetColumns,
2260
- className: "text-sm text-accent-primary hover:underline",
2458
+ className: "text-sm",
2261
2459
  children: translations.resetColumns
2262
2460
  }
2263
2461
  )
2264
2462
  ] }),
2265
- /* @__PURE__ */ jsx10("div", { className: "space-y-2", children: columns.map((col) => {
2463
+ /* @__PURE__ */ jsx11("div", { className: "space-y-2", children: columns.map((col) => {
2266
2464
  const colState = columnStates.find((cs) => cs.id === col.id);
2267
2465
  const isVisible = (colState == null ? void 0 : colState.visible) !== false;
2268
2466
  const headerText = typeof col.header === "string" ? col.header : col.id;
2269
2467
  return /* @__PURE__ */ jsxs8(
2270
2468
  "label",
2271
2469
  {
2272
- className: "flex items-center gap-3 px-3 py-2 rounded hover:bg-theme-hover cursor-pointer",
2470
+ className: "px-3 py-2 rounded cursor-pointer",
2273
2471
  children: [
2274
- /* @__PURE__ */ jsx10(
2472
+ /* @__PURE__ */ jsx11(
2275
2473
  "input",
2276
2474
  {
2277
2475
  type: "checkbox",
2278
2476
  checked: isVisible,
2279
2477
  onChange: () => actions.toggleColumnVisibility(col.id),
2280
- className: "w-4 h-4 rounded border-theme-border"
2478
+ className: "w-4 h-4 rounded"
2281
2479
  }
2282
2480
  ),
2283
- /* @__PURE__ */ jsx10("span", { className: "text-sm text-theme-primary", children: headerText })
2481
+ /* @__PURE__ */ jsx11("span", { className: "text-sm text-theme-primary", children: headerText })
2284
2482
  ]
2285
2483
  },
2286
2484
  col.id
@@ -2300,7 +2498,7 @@ function MobileDrawer({
2300
2498
  className = "",
2301
2499
  style
2302
2500
  }) {
2303
- useEffect4(() => {
2501
+ useEffect5(() => {
2304
2502
  if (isOpen) {
2305
2503
  document.body.style.overflow = "hidden";
2306
2504
  } else {
@@ -2310,7 +2508,7 @@ function MobileDrawer({
2310
2508
  document.body.style.overflow = "";
2311
2509
  };
2312
2510
  }, [isOpen]);
2313
- useEffect4(() => {
2511
+ useEffect5(() => {
2314
2512
  const handleEscape = (e) => {
2315
2513
  if (e.key === "Escape" && isOpen) {
2316
2514
  onClose();
@@ -2322,11 +2520,11 @@ function MobileDrawer({
2322
2520
  if (!isOpen || !content) {
2323
2521
  return null;
2324
2522
  }
2325
- return /* @__PURE__ */ jsxs8("div", { className: `mobile-drawer-container fixed inset-0 z-50 ${className}`, style, children: [
2326
- /* @__PURE__ */ jsx10(
2523
+ return /* @__PURE__ */ jsxs8("div", { className: `mobile-drawer-container ${className}`, style, children: [
2524
+ /* @__PURE__ */ jsx11(
2327
2525
  "div",
2328
2526
  {
2329
- className: "mobile-drawer-overlay absolute inset-0 bg-black transition-opacity",
2527
+ className: "mobile-drawer-overlay",
2330
2528
  style: {
2331
2529
  opacity: DRAWER_OVERLAY_OPACITY,
2332
2530
  transitionDuration: `${DRAWER_ANIMATION_DURATION}ms`
@@ -2338,7 +2536,7 @@ function MobileDrawer({
2338
2536
  /* @__PURE__ */ jsxs8(
2339
2537
  "div",
2340
2538
  {
2341
- className: "mobile-drawer absolute bottom-0 left-0 right-0 bg-theme-primary rounded-t-2xl shadow-2xl max-h-[80vh] overflow-hidden flex flex-col",
2539
+ className: "mobile-drawer",
2342
2540
  style: {
2343
2541
  transitionDuration: `${DRAWER_ANIMATION_DURATION}ms`
2344
2542
  },
@@ -2346,11 +2544,11 @@ function MobileDrawer({
2346
2544
  "aria-modal": "true",
2347
2545
  "aria-labelledby": "drawer-title",
2348
2546
  children: [
2349
- /* @__PURE__ */ jsx10(DrawerHeader, { title: DRAWER_TITLES[content], onClose }),
2350
- /* @__PURE__ */ jsxs8("div", { className: "drawer-content flex-1 overflow-y-auto", children: [
2351
- content === "filter" && /* @__PURE__ */ jsx10(FilterContent, {}),
2352
- content === "sort" && /* @__PURE__ */ jsx10(SortContent, {}),
2353
- content === "columns" && /* @__PURE__ */ jsx10(ColumnsContent, {})
2547
+ /* @__PURE__ */ jsx11(DrawerHeader, { title: DRAWER_TITLES[content], onClose }),
2548
+ /* @__PURE__ */ jsxs8("div", { className: "drawer-content", children: [
2549
+ content === "filter" && /* @__PURE__ */ jsx11(FilterContent, {}),
2550
+ content === "sort" && /* @__PURE__ */ jsx11(SortContent, {}),
2551
+ content === "columns" && /* @__PURE__ */ jsx11(ColumnsContent, {})
2354
2552
  ] })
2355
2553
  ]
2356
2554
  }
@@ -2359,7 +2557,7 @@ function MobileDrawer({
2359
2557
  }
2360
2558
 
2361
2559
  // src/components/GridTable/GridTable.tsx
2362
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2560
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
2363
2561
  function GridTableContent({
2364
2562
  data,
2365
2563
  columns,
@@ -2397,10 +2595,18 @@ function GridTableContent({
2397
2595
  renderHeader,
2398
2596
  renderFooter,
2399
2597
  className = "",
2400
- style
2598
+ style,
2599
+ showOverflowTooltip,
2600
+ enableCellAutoSizeOnDoubleClick,
2601
+ subCellExpandTrigger,
2602
+ expandRowOnDoubleClick,
2603
+ themeMode,
2604
+ paginationConfig
2401
2605
  }) {
2606
+ var _a, _b;
2402
2607
  const { state, actions, computed } = useTableContext();
2403
2608
  const { shouldShowMobileView, breakpointValue } = useBreakpoint();
2609
+ const themeClass = themeMode === "dark" ? "dark" : themeMode === "light" ? "light" : void 0;
2404
2610
  const getRowIdFn = useCallback13(
2405
2611
  (row) => {
2406
2612
  if (getRowId) return getRowId(row);
@@ -2429,6 +2635,22 @@ function GridTableContent({
2429
2635
  },
2430
2636
  [actions]
2431
2637
  );
2638
+ const handleRowDoubleClick = useCallback13(
2639
+ (row, index) => {
2640
+ if (expandRowOnDoubleClick) {
2641
+ actions.toggleRowExpansion(getRowIdFn(row));
2642
+ }
2643
+ onRowDoubleClick == null ? void 0 : onRowDoubleClick(row, index);
2644
+ },
2645
+ [expandRowOnDoubleClick, actions, getRowIdFn, onRowDoubleClick]
2646
+ );
2647
+ const handleSelectAll = useCallback13(() => {
2648
+ if (computed.allSelected) {
2649
+ actions.deselectAll();
2650
+ } else {
2651
+ actions.selectAll();
2652
+ }
2653
+ }, [computed.allSelected, actions]);
2432
2654
  const handleFilterOpen = useCallback13(
2433
2655
  (columnId) => {
2434
2656
  if (shouldShowMobileView) {
@@ -2439,7 +2661,7 @@ function GridTableContent({
2439
2661
  },
2440
2662
  [shouldShowMobileView, actions]
2441
2663
  );
2442
- const containerStyle = useMemo12(() => {
2664
+ const containerStyle = useMemo11(() => {
2443
2665
  const baseStyle = { ...style, ...styles.root };
2444
2666
  if (dimensions == null ? void 0 : dimensions.width) {
2445
2667
  baseStyle.width = breakpointValue(dimensions.width, "auto");
@@ -2452,24 +2674,24 @@ function GridTableContent({
2452
2674
  }
2453
2675
  return baseStyle;
2454
2676
  }, [style, styles.root, dimensions, breakpointValue]);
2455
- const columnWidths = useMemo12(() => {
2677
+ const columnWidths = useMemo11(() => {
2456
2678
  return state.columnStates.map((cs) => cs.width);
2457
2679
  }, [state.columnStates]);
2458
2680
  if (error) {
2459
2681
  const errorMessage = typeof error === "string" ? error : error.message;
2460
2682
  if (errorContent) {
2461
- return /* @__PURE__ */ jsx11("div", { className: `grid-table-error ${classNames.root || ""} ${className}`, style: containerStyle, children: typeof errorContent === "function" ? errorContent(error) : errorContent });
2683
+ return /* @__PURE__ */ jsx12("div", { className: `grid-table-error ${classNames.root || ""} ${className}`, style: containerStyle, children: typeof errorContent === "function" ? errorContent(error) : errorContent });
2462
2684
  }
2463
- return /* @__PURE__ */ jsx11("div", { className: `grid-table-error ${classNames.root || ""} ${className}`, style: containerStyle, children: /* @__PURE__ */ jsx11(
2685
+ return /* @__PURE__ */ jsx12("div", { className: `grid-table-error ${classNames.root || ""} ${className}`, style: containerStyle, children: /* @__PURE__ */ jsx12(
2464
2686
  EmptyState,
2465
2687
  {
2466
2688
  title: state.translations.errorLoading,
2467
2689
  description: errorMessage,
2468
- action: onRetry && /* @__PURE__ */ jsx11(
2690
+ action: onRetry && /* @__PURE__ */ jsx12(
2469
2691
  "button",
2470
2692
  {
2471
2693
  onClick: onRetry,
2472
- className: "px-4 py-2 bg-accent-primary text-white rounded hover:bg-accent-primary/90",
2694
+ className: "px-4 py-2 bg-accent-primary text-white rounded hover:opacity-90 cursor-pointer",
2473
2695
  children: state.translations.retry
2474
2696
  }
2475
2697
  )
@@ -2478,9 +2700,9 @@ function GridTableContent({
2478
2700
  }
2479
2701
  if (loading) {
2480
2702
  if (loadingContent) {
2481
- return /* @__PURE__ */ jsx11("div", { className: `grid-table-loading ${classNames.root || ""} ${className}`, style: containerStyle, children: loadingContent });
2703
+ return /* @__PURE__ */ jsx12("div", { className: `grid-table-loading ${classNames.root || ""} ${className}`, style: containerStyle, children: loadingContent });
2482
2704
  }
2483
- return /* @__PURE__ */ jsx11("div", { className: `grid-table-loading ${classNames.root || ""} ${className}`, style: containerStyle, children: /* @__PURE__ */ jsx11(
2705
+ return /* @__PURE__ */ jsx12("div", { className: `grid-table-loading ${classNames.root || ""} ${className}`, style: containerStyle, children: /* @__PURE__ */ jsx12(
2484
2706
  Skeleton,
2485
2707
  {
2486
2708
  rows: 5,
@@ -2494,44 +2716,44 @@ function GridTableContent({
2494
2716
  ) });
2495
2717
  }
2496
2718
  const isEmpty = computed.paginatedData.length === 0;
2497
- return /* @__PURE__ */ jsxs9(
2719
+ const tableContent = /* @__PURE__ */ jsxs9(
2498
2720
  "div",
2499
2721
  {
2500
- className: `grid-table bg-theme-primary rounded-lg border border-theme-border overflow-hidden ${classNames.root || ""} ${className}`,
2722
+ className: `grid-table rounded-lg border overflow-hidden ${classNames.root || ""} ${className}`,
2501
2723
  style: containerStyle,
2502
2724
  role: "table",
2503
2725
  children: [
2504
- renderHeader && /* @__PURE__ */ jsx11("div", { className: "grid-table-custom-header", children: renderHeader() }),
2505
- showGlobalFilter && /* @__PURE__ */ jsxs9("div", { className: "grid-table-toolbar flex items-center gap-4 px-4 py-3 border-b border-theme-border", children: [
2506
- /* @__PURE__ */ jsxs9("div", { className: "flex-1 relative", children: [
2507
- /* @__PURE__ */ jsx11(
2726
+ renderHeader && /* @__PURE__ */ jsx12("div", { className: "grid-table-custom-header", children: renderHeader() }),
2727
+ showGlobalFilter && /* @__PURE__ */ jsxs9("div", { className: "grid-table-toolbar", children: [
2728
+ /* @__PURE__ */ jsxs9("div", { className: "toolbar-search-wrapper", children: [
2729
+ /* @__PURE__ */ jsx12(
2508
2730
  "svg",
2509
2731
  {
2510
- className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-theme-muted",
2732
+ className: "search-icon",
2511
2733
  fill: "none",
2512
2734
  viewBox: "0 0 24 24",
2513
2735
  stroke: "currentColor",
2514
2736
  strokeWidth: 2,
2515
- children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" })
2737
+ children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" })
2516
2738
  }
2517
2739
  ),
2518
- /* @__PURE__ */ jsx11(
2740
+ /* @__PURE__ */ jsx12(
2519
2741
  "input",
2520
2742
  {
2521
2743
  type: "text",
2522
2744
  value: state.globalFilter,
2523
2745
  onChange: (e) => actions.setGlobalFilter(e.target.value),
2524
2746
  placeholder: state.translations.search,
2525
- className: "w-full pl-10 pr-3 py-2 text-sm rounded border border-theme-border bg-theme-secondary text-theme-primary focus:outline-none focus:ring-2 focus:ring-accent-primary"
2747
+ className: "w-full pl-10 pr-3 py-2 text-sm rounded"
2526
2748
  }
2527
2749
  ),
2528
- state.globalFilter && /* @__PURE__ */ jsx11(
2750
+ state.globalFilter && /* @__PURE__ */ jsx12(
2529
2751
  "button",
2530
2752
  {
2531
2753
  onClick: () => actions.setGlobalFilter(""),
2532
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-theme-muted hover:text-theme-primary",
2754
+ className: "clear-button",
2533
2755
  "aria-label": "Clear search",
2534
- children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) })
2756
+ children: /* @__PURE__ */ jsx12("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) })
2535
2757
  }
2536
2758
  )
2537
2759
  ] }),
@@ -2539,9 +2761,9 @@ function GridTableContent({
2539
2761
  "button",
2540
2762
  {
2541
2763
  onClick: () => actions.clearFilters(),
2542
- className: "flex items-center gap-2 px-3 py-2 text-sm rounded border border-theme-border hover:bg-theme-hover text-theme-secondary",
2764
+ className: "filter-badge",
2543
2765
  children: [
2544
- /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }),
2766
+ /* @__PURE__ */ jsx12("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }),
2545
2767
  /* @__PURE__ */ jsxs9("span", { children: [
2546
2768
  state.filters.length,
2547
2769
  " filter",
@@ -2550,38 +2772,38 @@ function GridTableContent({
2550
2772
  ]
2551
2773
  }
2552
2774
  ),
2553
- shouldShowMobileView && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
2554
- /* @__PURE__ */ jsx11(
2775
+ shouldShowMobileView && /* @__PURE__ */ jsxs9("div", { className: "toolbar-actions", children: [
2776
+ /* @__PURE__ */ jsx12(
2555
2777
  "button",
2556
2778
  {
2557
2779
  onClick: () => actions.openMobileDrawer("filter"),
2558
- className: "p-2 rounded border border-theme-border hover:bg-theme-hover",
2780
+ className: "toolbar-action-button",
2559
2781
  "aria-label": state.translations.filter,
2560
- children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" }) })
2782
+ children: /* @__PURE__ */ jsx12("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" }) })
2561
2783
  }
2562
2784
  ),
2563
- /* @__PURE__ */ jsx11(
2785
+ /* @__PURE__ */ jsx12(
2564
2786
  "button",
2565
2787
  {
2566
2788
  onClick: () => actions.openMobileDrawer("sort"),
2567
- className: "p-2 rounded border border-theme-border hover:bg-theme-hover",
2789
+ className: "toolbar-action-button",
2568
2790
  "aria-label": state.translations.sort,
2569
- children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) })
2791
+ children: /* @__PURE__ */ jsx12("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) })
2570
2792
  }
2571
2793
  ),
2572
- /* @__PURE__ */ jsx11(
2794
+ /* @__PURE__ */ jsx12(
2573
2795
  "button",
2574
2796
  {
2575
2797
  onClick: () => actions.openMobileDrawer("columns"),
2576
- className: "p-2 rounded border border-theme-border hover:bg-theme-hover",
2798
+ className: "toolbar-action-button",
2577
2799
  "aria-label": state.translations.columns,
2578
- children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" }) })
2800
+ children: /* @__PURE__ */ jsx12("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" }) })
2579
2801
  }
2580
2802
  )
2581
2803
  ] })
2582
2804
  ] }),
2583
2805
  /* @__PURE__ */ jsxs9("div", { className: "grid-table-container overflow-auto", children: [
2584
- !shouldShowMobileView && /* @__PURE__ */ jsx11(
2806
+ !shouldShowMobileView && /* @__PURE__ */ jsx12(
2585
2807
  GridHeader,
2586
2808
  {
2587
2809
  columns,
@@ -2594,24 +2816,25 @@ function GridTableContent({
2594
2816
  enableDragDrop,
2595
2817
  enableResize: enableColumnResize,
2596
2818
  enableSelection: enableRowSelection,
2819
+ enableExpansion: enableRowExpansion,
2597
2820
  allSelected: computed.allSelected,
2598
2821
  someSelected: computed.someSelected,
2599
- onSelectAll: actions.selectAll,
2822
+ onSelectAll: handleSelectAll,
2600
2823
  onFilterOpen: handleFilterOpen,
2601
2824
  getSortDirection: (colId) => {
2602
- var _a;
2825
+ var _a2;
2603
2826
  const sort = state.sorting.find((s) => s.columnId === colId);
2604
- return (_a = sort == null ? void 0 : sort.direction) != null ? _a : null;
2827
+ return (_a2 = sort == null ? void 0 : sort.direction) != null ? _a2 : null;
2605
2828
  }
2606
2829
  }
2607
2830
  ),
2608
- isEmpty ? emptyContent || /* @__PURE__ */ jsx11(
2831
+ isEmpty ? emptyContent || /* @__PURE__ */ jsx12(
2609
2832
  EmptyState,
2610
2833
  {
2611
2834
  className: classNames.empty,
2612
2835
  style: styles.empty
2613
2836
  }
2614
- ) : /* @__PURE__ */ jsx11(
2837
+ ) : /* @__PURE__ */ jsx12(
2615
2838
  GridBody,
2616
2839
  {
2617
2840
  data: computed.paginatedData,
@@ -2626,7 +2849,7 @@ function GridTableContent({
2626
2849
  selectedIds: state.selectedIds,
2627
2850
  expandedIds: state.expandedIds,
2628
2851
  onRowClick,
2629
- onRowDoubleClick,
2852
+ onRowDoubleClick: handleRowDoubleClick,
2630
2853
  onCellClick,
2631
2854
  onRowSelect: handleRowSelect,
2632
2855
  onRowExpand: handleRowExpand,
@@ -2638,27 +2861,50 @@ function GridTableContent({
2638
2861
  }
2639
2862
  )
2640
2863
  ] }),
2641
- showPagination && !isEmpty && /* @__PURE__ */ jsx11(
2642
- Pagination,
2643
- {
2644
- page: state.page,
2645
- pageSize: state.pageSize,
2646
- totalItems: computed.sortedData.length,
2647
- totalPages: computed.totalPages,
2648
- className: classNames.pagination,
2649
- style: styles.pagination,
2650
- onPageChange: (page) => {
2651
- actions.setPage(page);
2652
- onPageChange == null ? void 0 : onPageChange(page, state.pageSize);
2653
- },
2654
- onPageSizeChange: (pageSize) => {
2655
- actions.setPageSize(pageSize);
2656
- onPageChange == null ? void 0 : onPageChange(1, pageSize);
2864
+ showPagination && !isEmpty && /* @__PURE__ */ jsxs9("div", { className: `grid-pagination ${(_a = classNames.pagination) != null ? _a : ""}`, style: styles.pagination, role: "navigation", "aria-label": "Pagination", children: [
2865
+ /* @__PURE__ */ jsxs9("div", { className: "grid-pagination-info", children: [
2866
+ /* @__PURE__ */ jsxs9(Typography3, { component: "span", variant: "body2", color: "secondary", children: [
2867
+ (state.page - 1) * state.pageSize + 1,
2868
+ "-",
2869
+ Math.min(state.page * state.pageSize, computed.sortedData.length),
2870
+ " ",
2871
+ state.translations.of,
2872
+ " ",
2873
+ computed.sortedData.length
2874
+ ] }),
2875
+ /* @__PURE__ */ jsx12(Typography3, { component: "span", variant: "caption", color: "secondary", className: "bear-sr-only", children: state.translations.rowsPerPage }),
2876
+ /* @__PURE__ */ jsx12(
2877
+ Select,
2878
+ {
2879
+ value: String(state.pageSize),
2880
+ onChange: (value) => {
2881
+ const pageSize = Number(value);
2882
+ actions.setPageSize(pageSize);
2883
+ onPageChange == null ? void 0 : onPageChange(1, pageSize);
2884
+ },
2885
+ options: ((_b = paginationConfig == null ? void 0 : paginationConfig.pageSizeOptions) != null ? _b : [10, 20, 50, 100]).map((size) => ({ value: String(size), label: String(size) })),
2886
+ size: "sm"
2887
+ }
2888
+ )
2889
+ ] }),
2890
+ /* @__PURE__ */ jsx12("div", { className: "grid-pagination-controls", children: /* @__PURE__ */ jsx12(
2891
+ BearPagination,
2892
+ {
2893
+ count: Math.max(1, computed.totalPages),
2894
+ page: state.page,
2895
+ onChange: (page) => {
2896
+ actions.setPage(page);
2897
+ onPageChange == null ? void 0 : onPageChange(page, state.pageSize);
2898
+ },
2899
+ showFirstLast: true,
2900
+ showPrevNext: true,
2901
+ size: "sm",
2902
+ variant: "outlined"
2657
2903
  }
2658
- }
2659
- ),
2660
- renderFooter && /* @__PURE__ */ jsx11("div", { className: "grid-table-custom-footer", children: renderFooter() }),
2661
- /* @__PURE__ */ jsx11(
2904
+ ) })
2905
+ ] }),
2906
+ renderFooter && /* @__PURE__ */ jsx12("div", { className: "grid-table-custom-footer", children: renderFooter() }),
2907
+ /* @__PURE__ */ jsx12(
2662
2908
  MobileDrawer,
2663
2909
  {
2664
2910
  isOpen: state.showMobileDrawer,
@@ -2671,6 +2917,10 @@ function GridTableContent({
2671
2917
  ]
2672
2918
  }
2673
2919
  );
2920
+ if (themeClass) {
2921
+ return /* @__PURE__ */ jsx12("div", { className: themeClass, children: tableContent });
2922
+ }
2923
+ return tableContent;
2674
2924
  }
2675
2925
  function GridTable({
2676
2926
  data,
@@ -2685,12 +2935,26 @@ function GridTable({
2685
2935
  sortConfig,
2686
2936
  enableMultiSelect = false,
2687
2937
  getRowId,
2938
+ showOverflowTooltip,
2939
+ enableCellAutoSizeOnDoubleClick,
2940
+ subCellExpandTrigger,
2941
+ expandRowOnDoubleClick,
2942
+ themeMode,
2943
+ themeOverride,
2944
+ studio = false,
2688
2945
  ...props
2689
2946
  }) {
2690
- return /* @__PURE__ */ jsx11(
2947
+ var _a, _b;
2948
+ const [studioData, setStudioData] = useState8(data);
2949
+ const [studioOpen, setStudioOpen] = useState8(true);
2950
+ useEffect6(() => {
2951
+ if (studio) setStudioData(data);
2952
+ }, [data, studio]);
2953
+ const effectiveData = studio ? studioData : data;
2954
+ const tableContent = /* @__PURE__ */ jsx12(
2691
2955
  TableProvider,
2692
2956
  {
2693
- data,
2957
+ data: effectiveData,
2694
2958
  columns,
2695
2959
  loading,
2696
2960
  error,
@@ -2703,19 +2967,223 @@ function GridTable({
2703
2967
  enableMultiSort: sortConfig == null ? void 0 : sortConfig.multiSort,
2704
2968
  enableMultiSelect,
2705
2969
  getRowId,
2706
- children: /* @__PURE__ */ jsx11(
2970
+ showOverflowTooltip,
2971
+ enableCellAutoSizeOnDoubleClick,
2972
+ subCellExpandTrigger,
2973
+ expandRowOnDoubleClick,
2974
+ children: /* @__PURE__ */ jsx12(
2707
2975
  GridTableContent,
2708
2976
  {
2709
- data,
2977
+ data: effectiveData,
2710
2978
  columns,
2711
2979
  loading,
2712
2980
  error,
2713
2981
  getRowId,
2982
+ themeMode,
2983
+ paginationConfig,
2714
2984
  ...props
2715
2985
  }
2716
2986
  )
2717
2987
  }
2718
2988
  );
2989
+ const withTheme = themeOverride && Object.keys(themeOverride).length > 0 ? /* @__PURE__ */ jsx12(BearProvider, { theme: themeOverride, defaultMode: themeMode === "dark" ? "dark" : "light", children: tableContent }) : tableContent;
2990
+ if (studio) {
2991
+ return /* @__PURE__ */ jsxs9(Fragment4, { children: [
2992
+ /* @__PURE__ */ jsx12("div", { className: "grid-table-studio-main", style: { width: "100%" }, children: withTheme }),
2993
+ /* @__PURE__ */ jsx12(
2994
+ TableStudioPanel,
2995
+ {
2996
+ data: studioData,
2997
+ columns,
2998
+ propsSnapshot: {
2999
+ themeMode,
3000
+ themeOverride,
3001
+ showPagination: (_a = props.showPagination) != null ? _a : true,
3002
+ showGlobalFilter: (_b = props.showGlobalFilter) != null ? _b : true,
3003
+ enableRowSelection: props.enableRowSelection,
3004
+ enableRowExpansion: props.enableRowExpansion
3005
+ },
3006
+ onDataChange: setStudioData,
3007
+ open: studioOpen,
3008
+ onOpenChange: setStudioOpen
3009
+ }
3010
+ )
3011
+ ] });
3012
+ }
3013
+ return withTheme;
3014
+ }
3015
+
3016
+ // src/components/Pagination/Pagination.tsx
3017
+ import { useMemo as useMemo12, useCallback as useCallback14 } from "react";
3018
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
3019
+ function Pagination({
3020
+ page,
3021
+ pageSize,
3022
+ totalItems,
3023
+ totalPages,
3024
+ pageSizeOptions = [10, 20, 50, 100],
3025
+ showFirstLast = true,
3026
+ showPageNumbers = true,
3027
+ maxPageButtons = FIVE,
3028
+ className = "",
3029
+ style,
3030
+ onPageChange,
3031
+ onPageSizeChange
3032
+ }) {
3033
+ const { state } = useTableContext();
3034
+ const { translations } = state;
3035
+ const canGoPrevious = page > ONE;
3036
+ const canGoNext = page < totalPages;
3037
+ const startItem = (page - ONE) * pageSize + ONE;
3038
+ const endItem = Math.min(page * pageSize, totalItems);
3039
+ const handleFirstPage = useCallback14(() => {
3040
+ onPageChange(ONE);
3041
+ }, [onPageChange]);
3042
+ const handlePreviousPage = useCallback14(() => {
3043
+ if (canGoPrevious) {
3044
+ onPageChange(page - ONE);
3045
+ }
3046
+ }, [canGoPrevious, page, onPageChange]);
3047
+ const handleNextPage = useCallback14(() => {
3048
+ if (canGoNext) {
3049
+ onPageChange(page + ONE);
3050
+ }
3051
+ }, [canGoNext, page, onPageChange]);
3052
+ const handleLastPage = useCallback14(() => {
3053
+ onPageChange(totalPages);
3054
+ }, [onPageChange, totalPages]);
3055
+ const handlePageSizeChange = useCallback14(
3056
+ (event) => {
3057
+ onPageSizeChange(Number(event.target.value));
3058
+ },
3059
+ [onPageSizeChange]
3060
+ );
3061
+ const pageNumbers = useMemo12(() => {
3062
+ if (!showPageNumbers || totalPages <= ONE) return [];
3063
+ const pages = [];
3064
+ const halfMax = Math.floor(maxPageButtons / 2);
3065
+ let start = Math.max(ONE, page - halfMax);
3066
+ let end = Math.min(totalPages, page + halfMax);
3067
+ if (page <= halfMax) {
3068
+ end = Math.min(totalPages, maxPageButtons);
3069
+ }
3070
+ if (page > totalPages - halfMax) {
3071
+ start = Math.max(ONE, totalPages - maxPageButtons + ONE);
3072
+ }
3073
+ if (start > ONE) {
3074
+ pages.push(ONE);
3075
+ if (start > 2) {
3076
+ pages.push("ellipsis");
3077
+ }
3078
+ }
3079
+ for (let i = start; i <= end; i++) {
3080
+ if (!pages.includes(i)) {
3081
+ pages.push(i);
3082
+ }
3083
+ }
3084
+ if (end < totalPages) {
3085
+ if (end < totalPages - ONE) {
3086
+ pages.push("ellipsis");
3087
+ }
3088
+ pages.push(totalPages);
3089
+ }
3090
+ return pages;
3091
+ }, [page, totalPages, showPageNumbers, maxPageButtons]);
3092
+ if (totalItems === 0) {
3093
+ return null;
3094
+ }
3095
+ return /* @__PURE__ */ jsxs10(
3096
+ "div",
3097
+ {
3098
+ className: `grid-pagination ${className}`,
3099
+ style,
3100
+ role: "navigation",
3101
+ "aria-label": "Pagination",
3102
+ children: [
3103
+ /* @__PURE__ */ jsxs10("div", { className: "grid-pagination-info", children: [
3104
+ /* @__PURE__ */ jsxs10("div", { className: "grid-pagination-range", children: [
3105
+ startItem,
3106
+ "-",
3107
+ endItem,
3108
+ " ",
3109
+ translations.of,
3110
+ " ",
3111
+ totalItems
3112
+ ] }),
3113
+ /* @__PURE__ */ jsxs10("div", { className: "grid-pagination-size", children: [
3114
+ /* @__PURE__ */ jsxs10("label", { htmlFor: "page-size", children: [
3115
+ translations.rowsPerPage,
3116
+ ":"
3117
+ ] }),
3118
+ /* @__PURE__ */ jsx13(
3119
+ "select",
3120
+ {
3121
+ id: "page-size",
3122
+ value: pageSize,
3123
+ onChange: handlePageSizeChange,
3124
+ className: "px-2 py-1 text-sm rounded",
3125
+ children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx13("option", { value: size, children: size }, size))
3126
+ }
3127
+ )
3128
+ ] })
3129
+ ] }),
3130
+ /* @__PURE__ */ jsxs10("div", { className: "grid-pagination-controls", children: [
3131
+ showFirstLast && /* @__PURE__ */ jsx13(
3132
+ "button",
3133
+ {
3134
+ onClick: handleFirstPage,
3135
+ disabled: !canGoPrevious,
3136
+ className: "p-2 rounded text-theme-secondary",
3137
+ "aria-label": translations.first,
3138
+ children: "<<"
3139
+ }
3140
+ ),
3141
+ /* @__PURE__ */ jsx13(
3142
+ "button",
3143
+ {
3144
+ onClick: handlePreviousPage,
3145
+ disabled: !canGoPrevious,
3146
+ className: "p-2 rounded text-theme-secondary",
3147
+ "aria-label": translations.previous,
3148
+ children: "<"
3149
+ }
3150
+ ),
3151
+ showPageNumbers && /* @__PURE__ */ jsx13("div", { className: "grid-pagination-pages", children: pageNumbers.map(
3152
+ (pageNum, index) => pageNum === "ellipsis" ? /* @__PURE__ */ jsx13("span", { className: "px-2 text-theme-muted", children: "..." }, `ellipsis-${index}`) : /* @__PURE__ */ jsx13(
3153
+ "button",
3154
+ {
3155
+ onClick: () => onPageChange(pageNum),
3156
+ className: `min-w-[32px] h-8 px-2 rounded text-sm ${pageNum === page ? "active" : ""}`,
3157
+ "aria-current": pageNum === page ? "page" : void 0,
3158
+ children: pageNum
3159
+ },
3160
+ pageNum
3161
+ )
3162
+ ) }),
3163
+ /* @__PURE__ */ jsx13(
3164
+ "button",
3165
+ {
3166
+ onClick: handleNextPage,
3167
+ disabled: !canGoNext,
3168
+ className: "p-2 rounded text-theme-secondary",
3169
+ "aria-label": translations.next,
3170
+ children: ">"
3171
+ }
3172
+ ),
3173
+ showFirstLast && /* @__PURE__ */ jsx13(
3174
+ "button",
3175
+ {
3176
+ onClick: handleLastPage,
3177
+ disabled: !canGoNext,
3178
+ className: "p-2 rounded text-theme-secondary",
3179
+ "aria-label": translations.last,
3180
+ children: ">>"
3181
+ }
3182
+ )
3183
+ ] })
3184
+ ]
3185
+ }
3186
+ );
2719
3187
  }
2720
3188
  export {
2721
3189
  BREAKPOINTS,