@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.js CHANGED
@@ -55,6 +55,7 @@ __export(index_exports, {
55
55
  useTableContext: () => useTableContext
56
56
  });
57
57
  module.exports = __toCommonJS(index_exports);
58
+ var import_styles = require("@forgedevstack/bear/styles.css");
58
59
 
59
60
  // src/components/GridTable/GridTable.tsx
60
61
  var import_react15 = require("react");
@@ -226,6 +227,10 @@ function reducer(state, action) {
226
227
  return { ...state, selectedIds: action.payload };
227
228
  case "SET_EXPANDED_IDS":
228
229
  return { ...state, expandedIds: action.payload };
230
+ case "SET_EXPANDED_CELL_IDS":
231
+ return { ...state, expandedCellIds: action.payload };
232
+ case "SET_AUTO_SIZED_COLUMN_IDS":
233
+ return { ...state, autoSizedColumnIds: action.payload };
229
234
  case "SET_COLUMN_STATES":
230
235
  return { ...state, columnStates: action.payload };
231
236
  case "SET_DRAGGING_COLUMN":
@@ -263,9 +268,24 @@ function TableProvider({
263
268
  sortConfig: _sortConfig,
264
269
  enableMultiSort = false,
265
270
  getRowId,
266
- onStateChange
271
+ onStateChange,
272
+ showOverflowTooltip = true,
273
+ enableCellAutoSizeOnDoubleClick = false,
274
+ subCellExpandTrigger = "both",
275
+ expandRowOnDoubleClick = false,
276
+ globalFilterColumns = void 0
267
277
  }) {
268
278
  var _a, _b;
279
+ const tableOptions = (0, import_react.useMemo)(
280
+ () => ({
281
+ showOverflowTooltip,
282
+ enableCellAutoSizeOnDoubleClick,
283
+ subCellExpandTrigger,
284
+ expandRowOnDoubleClick,
285
+ globalFilterColumns
286
+ }),
287
+ [showOverflowTooltip, enableCellAutoSizeOnDoubleClick, subCellExpandTrigger, expandRowOnDoubleClick, globalFilterColumns]
288
+ );
269
289
  const initialColumnStates = columns.map((col, index) => ({
270
290
  id: col.id,
271
291
  visible: !col.hidden,
@@ -294,6 +314,8 @@ function TableProvider({
294
314
  totalItems: data.length,
295
315
  selectedIds: /* @__PURE__ */ new Set(),
296
316
  expandedIds: /* @__PURE__ */ new Set(),
317
+ expandedCellIds: /* @__PURE__ */ new Set(),
318
+ autoSizedColumnIds: /* @__PURE__ */ new Set(),
297
319
  loading,
298
320
  error,
299
321
  theme: mergedTheme,
@@ -420,6 +442,25 @@ function TableProvider({
420
442
  actions.expandRow(id);
421
443
  }
422
444
  },
445
+ toggleCellExpansion: (rowId, columnId) => {
446
+ const key = `${String(rowId)}-${columnId}`;
447
+ const next = new Set(state.expandedCellIds);
448
+ if (next.has(key)) {
449
+ next.delete(key);
450
+ } else {
451
+ next.add(key);
452
+ }
453
+ dispatch({ type: "SET_EXPANDED_CELL_IDS", payload: next });
454
+ },
455
+ toggleColumnAutoSize: (columnId) => {
456
+ const next = new Set(state.autoSizedColumnIds);
457
+ if (next.has(columnId)) {
458
+ next.delete(columnId);
459
+ } else {
460
+ next.add(columnId);
461
+ }
462
+ dispatch({ type: "SET_AUTO_SIZED_COLUMN_IDS", payload: next });
463
+ },
423
464
  reorderColumn: (sourceId, targetId) => {
424
465
  const newStates = [...state.columnStates];
425
466
  const sourceIndex = newStates.findIndex((c) => c.id === sourceId);
@@ -458,6 +499,8 @@ function TableProvider({
458
499
  page: ONE,
459
500
  selectedIds: /* @__PURE__ */ new Set(),
460
501
  expandedIds: /* @__PURE__ */ new Set(),
502
+ expandedCellIds: /* @__PURE__ */ new Set(),
503
+ autoSizedColumnIds: /* @__PURE__ */ new Set(),
461
504
  columnStates: initialColumnStates
462
505
  }
463
506
  })
@@ -468,11 +511,15 @@ function TableProvider({
468
511
  let filteredData = [...state.data];
469
512
  if (state.globalFilter) {
470
513
  const searchLower = state.globalFilter.toLowerCase();
471
- filteredData = filteredData.filter(
472
- (row) => Object.values(row).some(
473
- (val) => String(val).toLowerCase().includes(searchLower)
474
- )
475
- );
514
+ const columnIds = tableOptions.globalFilterColumns;
515
+ filteredData = filteredData.filter((row) => {
516
+ const colsToSearch = columnIds && columnIds.length > 0 ? state.columns.filter((c) => columnIds.includes(c.id)) : state.columns;
517
+ return colsToSearch.some((col) => {
518
+ const accessor = col.accessor;
519
+ const value = typeof accessor === "function" ? accessor(row) : row[accessor];
520
+ return String(value != null ? value : "").toLowerCase().includes(searchLower);
521
+ });
522
+ });
476
523
  }
477
524
  state.filters.forEach((filter) => {
478
525
  const column = columns.find((c) => c.id === filter.columnId);
@@ -558,10 +605,11 @@ function TableProvider({
558
605
  isTablet,
559
606
  isDesktop
560
607
  };
561
- }, [state, columns]);
608
+ }, [state, columns, tableOptions]);
562
609
  const contextValue = {
563
610
  state,
564
611
  actions,
612
+ tableOptions,
565
613
  computed
566
614
  };
567
615
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableContext.Provider, { value: contextValue, children });
@@ -1050,6 +1098,7 @@ function useTable() {
1050
1098
 
1051
1099
  // src/components/GridHeader/GridHeader.tsx
1052
1100
  var import_react9 = require("react");
1101
+ var import_bear = require("@forgedevstack/bear");
1053
1102
 
1054
1103
  // src/components/FilterPopup/FilterPopup.tsx
1055
1104
  var import_react8 = require("react");
@@ -1133,7 +1182,7 @@ function FilterPopup({
1133
1182
  "div",
1134
1183
  {
1135
1184
  ref: popupRef,
1136
- className: `filter-popup absolute z-50 bg-theme-primary border border-theme-border rounded-lg shadow-xl min-w-[280px] ${className}`,
1185
+ className: `filter-popup ${className}`,
1137
1186
  style: {
1138
1187
  top: (_a = position == null ? void 0 : position.top) != null ? _a : "100%",
1139
1188
  left: (_b = position == null ? void 0 : position.left) != null ? _b : 0,
@@ -1141,44 +1190,44 @@ function FilterPopup({
1141
1190
  ...style
1142
1191
  },
1143
1192
  children: [
1144
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "filter-popup-header px-4 py-3 border-b border-theme-border", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between", children: [
1145
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium text-theme-primary", children: columnHeader }),
1193
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "filter-popup-header", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "header-content", children: [
1194
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "header-title", children: columnHeader }),
1146
1195
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1147
1196
  "button",
1148
1197
  {
1149
1198
  onClick: onClose,
1150
- className: "p-1 rounded hover:bg-theme-hover text-theme-muted",
1199
+ className: "header-close",
1151
1200
  "aria-label": "Close",
1152
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
1201
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
1153
1202
  }
1154
1203
  )
1155
1204
  ] }) }),
1156
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "filter-popup-body p-4 space-y-4", children: filterType === "select" && filterOptions ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1205
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "filter-popup-body", children: filterType === "select" && filterOptions ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1157
1206
  "select",
1158
1207
  {
1159
1208
  value: String(value),
1160
1209
  onChange: (e) => setValue(e.target.value),
1161
- 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",
1210
+ className: "w-full px-3 py-2 text-sm rounded",
1162
1211
  children: [
1163
1212
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "", children: "Select..." }),
1164
1213
  filterOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: String(opt.value), children: opt.label }, String(opt.value)))
1165
1214
  ]
1166
1215
  }
1167
1216
  ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1168
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1169
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs text-theme-muted mb-1", children: "Operator" }),
1217
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "filter-field", children: [
1218
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { children: "Operator" }),
1170
1219
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1171
1220
  "select",
1172
1221
  {
1173
1222
  value: operator,
1174
1223
  onChange: (e) => setOperator(e.target.value),
1175
- 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",
1224
+ className: "w-full px-3 py-2 text-sm rounded",
1176
1225
  children: operators.map((op) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: op, children: OPERATOR_LABELS[op] }, op))
1177
1226
  }
1178
1227
  )
1179
1228
  ] }),
1180
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1181
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs text-theme-muted mb-1", children: "Value" }),
1229
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "filter-field", children: [
1230
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { children: "Value" }),
1182
1231
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1183
1232
  "input",
1184
1233
  {
@@ -1187,18 +1236,18 @@ function FilterPopup({
1187
1236
  onChange: (e) => setValue(e.target.value),
1188
1237
  onKeyDown: handleKeyDown,
1189
1238
  placeholder: `Filter ${columnHeader}...`,
1190
- 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",
1239
+ className: "w-full px-3 py-2 text-sm rounded",
1191
1240
  autoFocus: true
1192
1241
  }
1193
1242
  )
1194
1243
  ] })
1195
1244
  ] }) }),
1196
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "filter-popup-footer px-4 py-3 border-t border-theme-border flex items-center justify-between", children: [
1245
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "filter-popup-footer", children: [
1197
1246
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1198
1247
  "button",
1199
1248
  {
1200
1249
  onClick: handleClear,
1201
- className: "px-3 py-1.5 text-sm text-theme-muted hover:text-theme-primary transition-colors",
1250
+ className: "filter-clear",
1202
1251
  children: translations.clearFilter
1203
1252
  }
1204
1253
  ),
@@ -1206,7 +1255,7 @@ function FilterPopup({
1206
1255
  "button",
1207
1256
  {
1208
1257
  onClick: handleApply,
1209
- className: "px-4 py-1.5 text-sm bg-accent-primary text-white rounded hover:opacity-90 transition-opacity",
1258
+ className: "filter-apply",
1210
1259
  children: translations.apply
1211
1260
  }
1212
1261
  )
@@ -1221,7 +1270,7 @@ var import_jsx_runtime3 = require("react/jsx-runtime");
1221
1270
  var FilterIcon = ({ active = false }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1222
1271
  "svg",
1223
1272
  {
1224
- className: `w-3.5 h-3.5 ${active ? "text-accent-primary" : "text-theme-muted"}`,
1273
+ className: `icon-sm ${active ? "text-accent-primary" : "text-theme-muted"}`,
1225
1274
  fill: "none",
1226
1275
  viewBox: "0 0 24 24",
1227
1276
  stroke: "currentColor",
@@ -1239,7 +1288,7 @@ var FilterIcon = ({ active = false }) => /* @__PURE__ */ (0, import_jsx_runtime3
1239
1288
  var SortIcon = ({ direction }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1240
1289
  "svg",
1241
1290
  {
1242
- className: `w-3.5 h-3.5 ${direction ? "text-accent-primary" : "text-theme-muted"}`,
1291
+ className: `icon-sm ${direction ? "text-accent-primary" : "text-theme-muted"}`,
1243
1292
  fill: "none",
1244
1293
  viewBox: "0 0 24 24",
1245
1294
  stroke: "currentColor",
@@ -1265,6 +1314,7 @@ function HeaderCell({
1265
1314
  hasFilter = false,
1266
1315
  isDragging = false,
1267
1316
  isDragOver = false,
1317
+ isColumnAutoSized = false,
1268
1318
  onSort,
1269
1319
  onFilterOpen,
1270
1320
  onResizeStart,
@@ -1296,56 +1346,53 @@ function HeaderCell({
1296
1346
  const cellClasses = (0, import_react9.useMemo)(() => {
1297
1347
  const classes = [
1298
1348
  "grid-header-cell",
1299
- "relative",
1300
- "flex",
1301
- "items-center",
1302
- "gap-2",
1303
- "px-4",
1304
- "py-3",
1305
- "font-medium",
1306
- "text-sm",
1307
- "text-theme-secondary",
1308
- "select-none",
1309
- "border-b",
1310
- "border-theme-border",
1311
- "transition-colors",
1312
1349
  ALIGN_CLASSES[column.align || "left"]
1313
1350
  ];
1314
1351
  if (isSortable) {
1315
- classes.push("cursor-pointer", "hover:text-theme-primary", "hover:bg-theme-hover");
1352
+ classes.push("cursor-pointer");
1316
1353
  }
1317
1354
  if (isDragging) {
1318
1355
  classes.push("opacity-50");
1319
1356
  }
1320
1357
  if (isDragOver) {
1321
- classes.push("bg-accent-primary/10", "border-l-2", "border-l-accent-primary");
1358
+ classes.push("bg-accent-primary/10");
1322
1359
  }
1323
1360
  return classes.join(" ");
1324
1361
  }, [column.align, isSortable, isDragging, isDragOver]);
1362
+ const cellStyle = (0, import_react9.useMemo)(() => {
1363
+ const base = {
1364
+ flexShrink: 0,
1365
+ ...column.sticky && {
1366
+ position: "sticky",
1367
+ [column.sticky]: 0,
1368
+ zIndex: 2,
1369
+ backgroundColor: "var(--gt-bg-secondary, #2b2b2b)"
1370
+ },
1371
+ ...column.headerStyle
1372
+ };
1373
+ if (isColumnAutoSized) {
1374
+ base.width = "auto";
1375
+ base.minWidth = "max-content";
1376
+ base.maxWidth = "none";
1377
+ } else {
1378
+ base.width = typeof columnState.width === "number" ? `${columnState.width}px` : columnState.width;
1379
+ base.minWidth = column.minWidth || MIN_COLUMN_WIDTH;
1380
+ base.maxWidth = column.maxWidth || MAX_COLUMN_WIDTH;
1381
+ }
1382
+ return base;
1383
+ }, [column, columnState.width, isColumnAutoSized]);
1325
1384
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1326
1385
  "div",
1327
1386
  {
1328
- className: `${cellClasses} ${column.headerClassName || ""} ${column.sticky ? "shadow-[2px_0_4px_-2px_rgba(0,0,0,0.2)]" : ""}`,
1329
- style: {
1330
- width: columnState.width,
1331
- minWidth: column.minWidth || MIN_COLUMN_WIDTH,
1332
- maxWidth: column.maxWidth || MAX_COLUMN_WIDTH,
1333
- flexShrink: 0,
1334
- ...column.sticky && {
1335
- position: "sticky",
1336
- [column.sticky]: 0,
1337
- zIndex: 2,
1338
- backgroundColor: "var(--bg-secondary, #2b2b2b)"
1339
- },
1340
- ...column.headerStyle
1341
- },
1387
+ className: `${cellClasses} ${column.headerClassName || ""} ${column.sticky ? `sticky-${column.sticky}` : ""}`,
1388
+ style: cellStyle,
1342
1389
  role: "columnheader",
1343
1390
  "aria-sort": sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : "none",
1344
1391
  onClick: handleClick,
1345
1392
  ...isDraggable ? { ...dragHandleProps, ...dropTargetProps } : {},
1346
1393
  children: [
1347
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "grid-header-content truncate flex-1", children: headerContent }),
1348
- isSortable && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "grid-header-sort flex items-center gap-0.5", children: [
1394
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "grid-header-content", children: headerContent }),
1395
+ isSortable && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "grid-header-sort", children: [
1349
1396
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SortIcon, { direction: sortDirection != null ? sortDirection : null }),
1350
1397
  isMultiSort && sortIndex !== void 0 && sortIndex >= 0 && sortDirection && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-xs text-theme-muted", children: sortIndex + 1 })
1351
1398
  ] }),
@@ -1353,7 +1400,7 @@ function HeaderCell({
1353
1400
  "button",
1354
1401
  {
1355
1402
  onClick: handleFilterClick,
1356
- className: "grid-header-filter p-1 rounded hover:bg-theme-tertiary",
1403
+ className: "grid-header-filter",
1357
1404
  "aria-label": "Filter column",
1358
1405
  children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FilterIcon, { active: hasFilter })
1359
1406
  }
@@ -1361,7 +1408,7 @@ function HeaderCell({
1361
1408
  isResizable && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1362
1409
  "div",
1363
1410
  {
1364
- className: "grid-header-resize absolute right-0 top-0 bottom-0 w-1 cursor-col-resize hover:bg-accent-primary",
1411
+ className: "grid-header-resize",
1365
1412
  onMouseDown: onResizeStart,
1366
1413
  onClick: (e) => e.stopPropagation()
1367
1414
  }
@@ -1381,6 +1428,7 @@ function GridHeader({
1381
1428
  enableDragDrop = true,
1382
1429
  enableResize = true,
1383
1430
  enableSelection = false,
1431
+ enableExpansion = false,
1384
1432
  allSelected = false,
1385
1433
  someSelected = false,
1386
1434
  onSelectAll,
@@ -1452,19 +1500,17 @@ function GridHeader({
1452
1500
  return classes.join(" ");
1453
1501
  }, [sticky]);
1454
1502
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `${headerClasses} ${className}`, style, role: "row", children: [
1455
- enableSelection && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "grid-header-select flex items-center px-2 border-b border-theme-border", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1456
- "input",
1503
+ enableSelection && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "grid-header-select", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1504
+ import_bear.Checkbox,
1457
1505
  {
1458
- type: "checkbox",
1459
1506
  checked: allSelected,
1460
- ref: (el) => {
1461
- if (el) el.indeterminate = someSelected && !allSelected;
1462
- },
1463
- onChange: onSelectAll,
1464
- className: "w-4 h-4 rounded border-theme-border",
1507
+ indeterminate: someSelected && !allSelected,
1508
+ onChange: () => onSelectAll == null ? void 0 : onSelectAll(),
1509
+ size: "sm",
1465
1510
  "aria-label": "Select all rows"
1466
1511
  }
1467
1512
  ) }),
1513
+ enableExpansion && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "grid-header-expand-spacer", "aria-hidden": true }),
1468
1514
  visibleColumns.map((col, index) => {
1469
1515
  const colState = columnStates.find((cs) => cs.id === col.id) || {
1470
1516
  id: col.id,
@@ -1478,7 +1524,7 @@ function GridHeader({
1478
1524
  const hasFilter = state.filters.some((f) => f.columnId === col.id);
1479
1525
  const existingFilter = state.filters.find((f) => f.columnId === col.id);
1480
1526
  const headerText = typeof col.header === "string" ? col.header : col.id;
1481
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative", children: [
1527
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative", style: { position: "relative" }, children: [
1482
1528
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1483
1529
  HeaderCell,
1484
1530
  {
@@ -1494,6 +1540,7 @@ function GridHeader({
1494
1540
  hasFilter,
1495
1541
  isDragging: dragDrop.draggingColumnId === col.id,
1496
1542
  isDragOver: dragDrop.dragOverColumnId === col.id,
1543
+ isColumnAutoSized: state.autoSizedColumnIds.has(col.id),
1497
1544
  onSort: () => actions.toggleSorting(col.id),
1498
1545
  onFilterOpen: () => handleFilterClick(col.id),
1499
1546
  onResizeStart: handleResizeStart(col.id, colState.width),
@@ -1525,10 +1572,58 @@ var import_react12 = require("react");
1525
1572
 
1526
1573
  // src/components/GridRow/GridRow.tsx
1527
1574
  var import_react11 = require("react");
1575
+ var import_bear3 = require("@forgedevstack/bear");
1528
1576
 
1529
1577
  // src/components/GridCell/GridCell.tsx
1530
1578
  var import_react10 = require("react");
1579
+ var import_bear2 = require("@forgedevstack/bear");
1580
+
1581
+ // src/utils/highlight.utils.tsx
1531
1582
  var import_jsx_runtime4 = require("react/jsx-runtime");
1583
+ function highlightMatch(text, term) {
1584
+ if (!term.trim()) return text;
1585
+ const parts = text.split(new RegExp(`(${escapeRegex(term)})`, "gi"));
1586
+ return parts.map(
1587
+ (part, i) => part.toLowerCase() === term.toLowerCase() ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("mark", { className: "grid-cell-highlight", children: part }, i) : part
1588
+ );
1589
+ }
1590
+ function escapeRegex(s) {
1591
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1592
+ }
1593
+
1594
+ // src/utils/generateSampleData.ts
1595
+ function generateSampleData(columns, rowCount) {
1596
+ const ids = columns.map((c) => c.id);
1597
+ return Array.from({ length: rowCount }, (_, i) => {
1598
+ const row = {};
1599
+ ids.forEach((key) => {
1600
+ if (key === "id" || key === "idNumber") {
1601
+ row[key] = i + 1;
1602
+ } else if (key === "email") {
1603
+ row[key] = `user${i + 1}@example.com`;
1604
+ } else if (key === "name" || key === "firstName" || key === "title") {
1605
+ row[key] = `Sample ${i + 1}`;
1606
+ } else if (key === "status" || key === "role") {
1607
+ row[key] = ["active", "inactive", "pending"][i % 3];
1608
+ } else if (key === "date" || key === "joinDate" || key === "createdAt") {
1609
+ row[key] = new Date(2020 + i % 4, i % 12, i % 28 + 1).toISOString().slice(0, 10);
1610
+ } else if (key === "salary" || key === "amount" || key === "count") {
1611
+ row[key] = 1e3 * (i + 1) + i % 100;
1612
+ } else if (key === "department") {
1613
+ row[key] = ["Engineering", "Design", "Marketing", "Sales", "HR"][i % 5];
1614
+ } else {
1615
+ row[key] = `Value ${i + 1}`;
1616
+ }
1617
+ });
1618
+ if (!("id" in row) && ids.length > 0) {
1619
+ row.id = i + 1;
1620
+ }
1621
+ return row;
1622
+ });
1623
+ }
1624
+
1625
+ // src/components/GridCell/GridCell.tsx
1626
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1532
1627
  var ALIGN_CLASSES2 = {
1533
1628
  left: "text-left justify-start",
1534
1629
  center: "text-center justify-center",
@@ -1538,6 +1633,7 @@ function GridCell({
1538
1633
  column,
1539
1634
  row,
1540
1635
  rowIndex,
1636
+ rowId,
1541
1637
  value,
1542
1638
  width,
1543
1639
  align = "left",
@@ -1549,20 +1645,18 @@ function GridCell({
1549
1645
  stickyOffset = 0,
1550
1646
  onClick
1551
1647
  }) {
1552
- const handleClick = (0, import_react10.useCallback)(
1553
- (e) => {
1554
- if (onClick) {
1555
- e.stopPropagation();
1556
- onClick({
1557
- row,
1558
- rowIndex,
1559
- columnId: column.id,
1560
- value
1561
- });
1562
- }
1563
- },
1564
- [onClick, row, rowIndex, column.id, value]
1565
- );
1648
+ var _a, _b, _c;
1649
+ const valueRef = (0, import_react10.useRef)(null);
1650
+ const [overflowTitle, setOverflowTitle] = (0, import_react10.useState)(void 0);
1651
+ const { state, actions, tableOptions } = useTableContext();
1652
+ const showOverflowTooltip = ((_a = column.showOverflowTooltip) != null ? _a : tableOptions.showOverflowTooltip) !== false;
1653
+ const hasSubCell = Boolean(column.renderSubCell);
1654
+ const trigger = (_c = (_b = column.subCellExpandTrigger) != null ? _b : tableOptions.subCellExpandTrigger) != null ? _c : "both";
1655
+ const showArrow = hasSubCell && (trigger === "arrow" || trigger === "both");
1656
+ const enableCellAutoSize = tableOptions.enableCellAutoSizeOnDoubleClick === true;
1657
+ const cellKey = `${String(rowId)}-${column.id}`;
1658
+ const isSubCellExpanded = state.expandedCellIds.has(cellKey);
1659
+ const isAutoSized = state.autoSizedColumnIds.has(column.id);
1566
1660
  const formattedValue = (0, import_react10.useMemo)(() => {
1567
1661
  if (column.render) {
1568
1662
  return column.render(value, row, rowIndex);
@@ -1578,9 +1672,53 @@ function GridCell({
1578
1672
  }
1579
1673
  return String(value);
1580
1674
  }, [column, row, rowIndex, value]);
1675
+ (0, import_react10.useEffect)(() => {
1676
+ var _a2;
1677
+ if (!showOverflowTooltip || !valueRef.current) return;
1678
+ const el = valueRef.current;
1679
+ const truncated = el.scrollWidth > el.clientWidth;
1680
+ const raw = (_a2 = el.textContent) != null ? _a2 : "";
1681
+ setOverflowTitle(truncated && raw ? raw : void 0);
1682
+ }, [showOverflowTooltip, formattedValue]);
1683
+ const handleClick = (0, import_react10.useCallback)(
1684
+ (e) => {
1685
+ if (onClick) {
1686
+ e.stopPropagation();
1687
+ onClick({
1688
+ row,
1689
+ rowIndex,
1690
+ columnId: column.id,
1691
+ value
1692
+ });
1693
+ }
1694
+ },
1695
+ [onClick, row, rowIndex, column.id, value]
1696
+ );
1697
+ const handleDoubleClick = (0, import_react10.useCallback)(
1698
+ (e) => {
1699
+ e.stopPropagation();
1700
+ if (hasSubCell && (trigger === "doubleClick" || trigger === "both")) {
1701
+ actions.toggleCellExpansion(rowId, column.id);
1702
+ } else if (enableCellAutoSize) {
1703
+ actions.toggleColumnAutoSize(column.id);
1704
+ }
1705
+ },
1706
+ [hasSubCell, trigger, enableCellAutoSize, actions, rowId, column.id]
1707
+ );
1708
+ const handleExpandClick = (0, import_react10.useCallback)(
1709
+ (e) => {
1710
+ e.stopPropagation();
1711
+ actions.toggleCellExpansion(rowId, column.id);
1712
+ },
1713
+ [actions, rowId, column.id]
1714
+ );
1581
1715
  const cellStyle = (0, import_react10.useMemo)(() => {
1582
1716
  const baseStyle = { ...style };
1583
- if (width !== void 0) {
1717
+ if (isAutoSized) {
1718
+ baseStyle.width = "auto";
1719
+ baseStyle.minWidth = "max-content";
1720
+ baseStyle.maxWidth = "none";
1721
+ } else if (width !== void 0) {
1584
1722
  baseStyle.width = typeof width === "number" ? `${width}px` : width;
1585
1723
  baseStyle.minWidth = baseStyle.width;
1586
1724
  baseStyle.maxWidth = baseStyle.width;
@@ -1588,7 +1726,7 @@ function GridCell({
1588
1726
  if (sticky) {
1589
1727
  baseStyle.position = "sticky";
1590
1728
  baseStyle.zIndex = 1;
1591
- baseStyle.backgroundColor = "var(--bg-primary, #1e1e1e)";
1729
+ baseStyle.backgroundColor = "var(--gt-bg-primary, #1e1e1e)";
1592
1730
  if (sticky === "left") {
1593
1731
  baseStyle.left = stickyOffset;
1594
1732
  } else if (sticky === "right") {
@@ -1596,38 +1734,68 @@ function GridCell({
1596
1734
  }
1597
1735
  }
1598
1736
  return baseStyle;
1599
- }, [style, width, sticky, stickyOffset]);
1737
+ }, [style, width, sticky, stickyOffset, isAutoSized]);
1600
1738
  const alignClass = ALIGN_CLASSES2[align];
1601
- const stickyClasses = sticky ? "shadow-[2px_0_4px_-2px_rgba(0,0,0,0.2)]" : "";
1602
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1739
+ const stickyClass = sticky ? `sticky-${sticky}` : "";
1740
+ const shouldHighlight = state.globalFilter && typeof formattedValue === "string" && (!tableOptions.globalFilterColumns || tableOptions.globalFilterColumns.length === 0 || tableOptions.globalFilterColumns.includes(column.id));
1741
+ const cellContent = shouldHighlight ? highlightMatch(String(formattedValue), state.globalFilter) : formattedValue;
1742
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1603
1743
  "div",
1604
1744
  {
1605
1745
  className: `
1606
1746
  grid-cell
1607
- px-4 py-3
1608
- flex items-center
1609
1747
  ${alignClass}
1610
- ${stickyClasses}
1611
- ${onClick ? "cursor-pointer hover:bg-theme-hover" : ""}
1748
+ ${stickyClass}
1749
+ ${onClick ? "cursor-pointer" : ""}
1750
+ ${hasSubCell ? "grid-cell--has-sub" : ""}
1751
+ ${isAutoSized ? "grid-cell--auto-sized" : ""}
1612
1752
  ${column.cellClassName || ""}
1613
1753
  ${className}
1614
1754
  `.trim(),
1615
1755
  style: { ...cellStyle, ...column.cellStyle },
1616
1756
  role: "cell",
1617
1757
  onClick: onClick ? handleClick : void 0,
1758
+ onDoubleClick: handleDoubleClick,
1618
1759
  children: [
1619
- showLabel && labelText && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "grid-cell-label font-medium text-theme-muted mr-2 text-sm", children: [
1620
- labelText,
1621
- ":"
1760
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "grid-cell-inner", children: [
1761
+ showLabel && labelText && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_bear2.Typography, { component: "span", variant: "body2", color: "secondary", className: "grid-cell-label", children: [
1762
+ labelText,
1763
+ ":"
1764
+ ] }),
1765
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "grid-cell-value-wrapper", style: { minWidth: 0, overflow: "hidden" }, children: overflowTitle ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_bear2.Tooltip, { content: overflowTitle, placement: "top", delay: 200, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1766
+ "span",
1767
+ {
1768
+ ref: valueRef,
1769
+ className: `grid-cell-value ${isAutoSized ? "" : "grid-cell-value--truncate"}`,
1770
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_bear2.Typography, { component: "span", variant: "body2", className: "grid-cell-value-text", children: cellContent })
1771
+ }
1772
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1773
+ "span",
1774
+ {
1775
+ ref: valueRef,
1776
+ className: `grid-cell-value ${isAutoSized ? "" : "grid-cell-value--truncate"}`,
1777
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_bear2.Typography, { component: "span", variant: "body2", children: cellContent })
1778
+ }
1779
+ ) }),
1780
+ showArrow && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1781
+ "button",
1782
+ {
1783
+ type: "button",
1784
+ className: `grid-cell-expand-trigger ${isSubCellExpanded ? "grid-cell-expand-trigger--expanded" : ""}`,
1785
+ onClick: handleExpandClick,
1786
+ "aria-label": isSubCellExpanded ? "Collapse" : "Expand",
1787
+ "aria-expanded": isSubCellExpanded
1788
+ }
1789
+ )
1622
1790
  ] }),
1623
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "grid-cell-value truncate", children: formattedValue })
1791
+ hasSubCell && isSubCellExpanded && column.renderSubCell && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "grid-cell-subcell", children: column.renderSubCell(row) })
1624
1792
  ]
1625
1793
  }
1626
1794
  );
1627
1795
  }
1628
1796
 
1629
1797
  // src/components/GridRow/GridRow.tsx
1630
- var import_jsx_runtime5 = require("react/jsx-runtime");
1798
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1631
1799
  function GridRow({
1632
1800
  row,
1633
1801
  rowIndex,
@@ -1667,10 +1835,13 @@ function GridRow({
1667
1835
  },
1668
1836
  [onContextMenu, row, rowIndex, isDisabled]
1669
1837
  );
1670
- const handleSelectChange = (0, import_react11.useCallback)(() => {
1671
- if (isDisabled) return;
1672
- onSelect == null ? void 0 : onSelect(!isSelected);
1673
- }, [onSelect, isSelected, isDisabled]);
1838
+ const handleSelectChange = (0, import_react11.useCallback)(
1839
+ (selected) => {
1840
+ if (isDisabled) return;
1841
+ onSelect == null ? void 0 : onSelect(selected);
1842
+ },
1843
+ [onSelect, isDisabled]
1844
+ );
1674
1845
  const handleExpandToggle = (0, import_react11.useCallback)(() => {
1675
1846
  if (isDisabled) return;
1676
1847
  onExpand == null ? void 0 : onExpand(!isExpanded);
@@ -1724,8 +1895,8 @@ function GridRow({
1724
1895
  }
1725
1896
  return classes.join(" ");
1726
1897
  }, [isHovered, isSelected, isDisabled, onClick, isMobile]);
1727
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1728
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1898
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1899
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1729
1900
  "div",
1730
1901
  {
1731
1902
  className: `${rowClasses} ${className}`,
@@ -1739,26 +1910,25 @@ function GridRow({
1739
1910
  onMouseEnter: () => setIsHovered(true),
1740
1911
  onMouseLeave: () => setIsHovered(false),
1741
1912
  children: [
1742
- enableSelection && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "grid-row-select flex items-center px-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1743
- "input",
1913
+ enableSelection && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "grid-row-select", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1914
+ import_bear3.Checkbox,
1744
1915
  {
1745
- type: "checkbox",
1746
- checked: isSelected,
1747
- onChange: handleSelectChange,
1916
+ checked: isSelected != null ? isSelected : false,
1917
+ onChange: (e) => handleSelectChange(e.target.checked),
1748
1918
  disabled: isDisabled,
1749
- className: "w-4 h-4 rounded border-theme-border",
1919
+ size: "sm",
1750
1920
  "aria-label": "Select row"
1751
1921
  }
1752
1922
  ) }),
1753
- enableExpansion && renderExpansion && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "grid-row-expand flex items-center px-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1923
+ enableExpansion && renderExpansion && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "grid-row-expand", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1754
1924
  "button",
1755
1925
  {
1756
1926
  onClick: handleExpandToggle,
1757
1927
  disabled: isDisabled,
1758
- className: "w-6 h-6 flex items-center justify-center rounded hover:bg-theme-tertiary",
1928
+ className: "grid-row-expand-button",
1759
1929
  "aria-label": isExpanded ? "Collapse row" : "Expand row",
1760
1930
  "aria-expanded": isExpanded,
1761
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1931
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1762
1932
  "span",
1763
1933
  {
1764
1934
  className: `transform transition-transform duration-200 ${isExpanded ? "rotate-90" : ""}`,
@@ -1790,18 +1960,19 @@ function GridRow({
1790
1960
  }
1791
1961
  }
1792
1962
  }
1793
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1963
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1794
1964
  GridCell,
1795
1965
  {
1796
1966
  column: col,
1797
1967
  row,
1798
1968
  rowIndex,
1969
+ rowId: getRowId(row),
1799
1970
  value: getCellValue(col),
1800
1971
  width,
1801
1972
  align: col.align,
1802
1973
  showLabel: isMobile && showMobileLabels && col.showLabelOnMobile !== false,
1803
1974
  labelText: typeof col.header === "string" ? col.header : col.id,
1804
- className: isMobile ? "w-full sm:w-auto flex-shrink-0" : "flex-shrink-0",
1975
+ className: isMobile ? "w-full-sm flex-shrink-0" : "flex-shrink-0",
1805
1976
  sticky: col.sticky,
1806
1977
  stickyOffset,
1807
1978
  onClick: onCellClick
@@ -1812,12 +1983,12 @@ function GridRow({
1812
1983
  ]
1813
1984
  }
1814
1985
  ),
1815
- isExpanded && renderExpansion && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "grid-row-expansion border-b border-theme-border bg-theme-secondary p-4", children: renderExpansion(row) })
1986
+ isExpanded && renderExpansion && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "grid-row-expansion", children: renderExpansion(row, getRowId(row)) })
1816
1987
  ] });
1817
1988
  }
1818
1989
 
1819
1990
  // src/components/GridBody/GridBody.tsx
1820
- var import_jsx_runtime6 = require("react/jsx-runtime");
1991
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1821
1992
  function GridBody({
1822
1993
  data,
1823
1994
  columns,
@@ -1858,7 +2029,7 @@ function GridBody({
1858
2029
  if (data.length === 0) {
1859
2030
  return null;
1860
2031
  }
1861
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `grid-body ${className}`, style, role: "rowgroup", children: data.map((row, index) => {
2032
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `grid-body ${className}`, style, role: "rowgroup", children: data.map((row, index) => {
1862
2033
  var _a, _b;
1863
2034
  const rowId = getRowId(row);
1864
2035
  const isSelected = selectedIds.has(rowId);
@@ -1866,7 +2037,7 @@ function GridBody({
1866
2037
  const isDisabled = (_a = isRowDisabled == null ? void 0 : isRowDisabled(row)) != null ? _a : false;
1867
2038
  const rowClassName = (_b = getRowClassName == null ? void 0 : getRowClassName(row, index)) != null ? _b : "";
1868
2039
  const rowStyle = getRowStyle == null ? void 0 : getRowStyle(row, index);
1869
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2040
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1870
2041
  GridRow,
1871
2042
  {
1872
2043
  row,
@@ -1895,178 +2066,8 @@ function GridBody({
1895
2066
  }) });
1896
2067
  }
1897
2068
 
1898
- // src/components/Pagination/Pagination.tsx
1899
- var import_react13 = require("react");
1900
- var import_jsx_runtime7 = require("react/jsx-runtime");
1901
- function Pagination({
1902
- page,
1903
- pageSize,
1904
- totalItems,
1905
- totalPages,
1906
- pageSizeOptions = [10, 20, 50, 100],
1907
- showFirstLast = true,
1908
- showPageNumbers = true,
1909
- maxPageButtons = FIVE,
1910
- className = "",
1911
- style,
1912
- onPageChange,
1913
- onPageSizeChange
1914
- }) {
1915
- const { state } = useTableContext();
1916
- const { translations } = state;
1917
- const canGoPrevious = page > ONE;
1918
- const canGoNext = page < totalPages;
1919
- const startItem = (page - ONE) * pageSize + ONE;
1920
- const endItem = Math.min(page * pageSize, totalItems);
1921
- const handleFirstPage = (0, import_react13.useCallback)(() => {
1922
- onPageChange(ONE);
1923
- }, [onPageChange]);
1924
- const handlePreviousPage = (0, import_react13.useCallback)(() => {
1925
- if (canGoPrevious) {
1926
- onPageChange(page - ONE);
1927
- }
1928
- }, [canGoPrevious, page, onPageChange]);
1929
- const handleNextPage = (0, import_react13.useCallback)(() => {
1930
- if (canGoNext) {
1931
- onPageChange(page + ONE);
1932
- }
1933
- }, [canGoNext, page, onPageChange]);
1934
- const handleLastPage = (0, import_react13.useCallback)(() => {
1935
- onPageChange(totalPages);
1936
- }, [onPageChange, totalPages]);
1937
- const handlePageSizeChange = (0, import_react13.useCallback)(
1938
- (event) => {
1939
- onPageSizeChange(Number(event.target.value));
1940
- },
1941
- [onPageSizeChange]
1942
- );
1943
- const pageNumbers = (0, import_react13.useMemo)(() => {
1944
- if (!showPageNumbers || totalPages <= ONE) return [];
1945
- const pages = [];
1946
- const halfMax = Math.floor(maxPageButtons / 2);
1947
- let start = Math.max(ONE, page - halfMax);
1948
- let end = Math.min(totalPages, page + halfMax);
1949
- if (page <= halfMax) {
1950
- end = Math.min(totalPages, maxPageButtons);
1951
- }
1952
- if (page > totalPages - halfMax) {
1953
- start = Math.max(ONE, totalPages - maxPageButtons + ONE);
1954
- }
1955
- if (start > ONE) {
1956
- pages.push(ONE);
1957
- if (start > 2) {
1958
- pages.push("ellipsis");
1959
- }
1960
- }
1961
- for (let i = start; i <= end; i++) {
1962
- if (!pages.includes(i)) {
1963
- pages.push(i);
1964
- }
1965
- }
1966
- if (end < totalPages) {
1967
- if (end < totalPages - ONE) {
1968
- pages.push("ellipsis");
1969
- }
1970
- pages.push(totalPages);
1971
- }
1972
- return pages;
1973
- }, [page, totalPages, showPageNumbers, maxPageButtons]);
1974
- if (totalItems === 0) {
1975
- return null;
1976
- }
1977
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1978
- "div",
1979
- {
1980
- className: `grid-pagination flex flex-wrap items-center justify-between gap-4 px-4 py-3 border-t border-theme-border ${className}`,
1981
- style,
1982
- role: "navigation",
1983
- "aria-label": "Pagination",
1984
- children: [
1985
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "grid-pagination-info flex items-center gap-4", children: [
1986
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "grid-pagination-range text-sm text-theme-secondary", children: [
1987
- startItem,
1988
- "-",
1989
- endItem,
1990
- " ",
1991
- translations.of,
1992
- " ",
1993
- totalItems
1994
- ] }),
1995
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "grid-pagination-size flex items-center gap-2", children: [
1996
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { htmlFor: "page-size", className: "text-sm text-theme-muted", children: [
1997
- translations.rowsPerPage,
1998
- ":"
1999
- ] }),
2000
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2001
- "select",
2002
- {
2003
- id: "page-size",
2004
- value: pageSize,
2005
- onChange: handlePageSizeChange,
2006
- 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",
2007
- children: pageSizeOptions.map((size) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: size, children: size }, size))
2008
- }
2009
- )
2010
- ] })
2011
- ] }),
2012
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "grid-pagination-controls flex items-center gap-1", children: [
2013
- showFirstLast && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2014
- "button",
2015
- {
2016
- onClick: handleFirstPage,
2017
- disabled: !canGoPrevious,
2018
- className: "p-2 rounded hover:bg-theme-hover disabled:opacity-50 disabled:cursor-not-allowed text-theme-secondary",
2019
- "aria-label": translations.first,
2020
- children: "<<"
2021
- }
2022
- ),
2023
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2024
- "button",
2025
- {
2026
- onClick: handlePreviousPage,
2027
- disabled: !canGoPrevious,
2028
- className: "p-2 rounded hover:bg-theme-hover disabled:opacity-50 disabled:cursor-not-allowed text-theme-secondary",
2029
- "aria-label": translations.previous,
2030
- children: "<"
2031
- }
2032
- ),
2033
- showPageNumbers && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "grid-pagination-pages flex items-center gap-1", children: pageNumbers.map(
2034
- (pageNum, index) => pageNum === "ellipsis" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "px-2 text-theme-muted", children: "..." }, `ellipsis-${index}`) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2035
- "button",
2036
- {
2037
- onClick: () => onPageChange(pageNum),
2038
- 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"}`,
2039
- "aria-current": pageNum === page ? "page" : void 0,
2040
- children: pageNum
2041
- },
2042
- pageNum
2043
- )
2044
- ) }),
2045
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2046
- "button",
2047
- {
2048
- onClick: handleNextPage,
2049
- disabled: !canGoNext,
2050
- className: "p-2 rounded hover:bg-theme-hover disabled:opacity-50 disabled:cursor-not-allowed text-theme-secondary",
2051
- "aria-label": translations.next,
2052
- children: ">"
2053
- }
2054
- ),
2055
- showFirstLast && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2056
- "button",
2057
- {
2058
- onClick: handleLastPage,
2059
- disabled: !canGoNext,
2060
- className: "p-2 rounded hover:bg-theme-hover disabled:opacity-50 disabled:cursor-not-allowed text-theme-secondary",
2061
- "aria-label": translations.last,
2062
- children: ">>"
2063
- }
2064
- )
2065
- ] })
2066
- ]
2067
- }
2068
- );
2069
- }
2069
+ // src/components/GridTable/GridTable.tsx
2070
+ var import_bear5 = require("@forgedevstack/bear");
2070
2071
 
2071
2072
  // src/components/Skeleton/Skeleton.tsx
2072
2073
  var import_jsx_runtime8 = require("react/jsx-runtime");
@@ -2080,7 +2081,7 @@ function SkeletonCell({ width = DEFAULT_COLUMN_WIDTH, height = 16, animate = tru
2080
2081
  children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2081
2082
  "div",
2082
2083
  {
2083
- className: `rounded bg-theme-tertiary ${animate ? "animate-pulse" : ""}`,
2084
+ className: `rounded ${animate ? "animate-pulse" : ""}`,
2084
2085
  style: { height: `${height}px`, width: "80%" }
2085
2086
  }
2086
2087
  )
@@ -2088,7 +2089,7 @@ function SkeletonCell({ width = DEFAULT_COLUMN_WIDTH, height = 16, animate = tru
2088
2089
  );
2089
2090
  }
2090
2091
  function SkeletonRow({ columns, columnWidths, height = 16, animate = true }) {
2091
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "grid-skeleton-row flex border-b border-theme-border", children: Array.from({ length: columns }).map((_, index) => {
2092
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "grid-skeleton-row", children: Array.from({ length: columns }).map((_, index) => {
2092
2093
  var _a;
2093
2094
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2094
2095
  SkeletonCell,
@@ -2112,7 +2113,7 @@ function Skeleton({
2112
2113
  animate = true
2113
2114
  }) {
2114
2115
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: `grid-skeleton ${className}`, style, role: "status", "aria-label": "Loading", children: [
2115
- showHeader && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "grid-skeleton-header flex border-b border-theme-border bg-theme-secondary", children: Array.from({ length: columns }).map((_, index) => {
2116
+ showHeader && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "grid-skeleton-header", children: Array.from({ length: columns }).map((_, index) => {
2116
2117
  var _a;
2117
2118
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2118
2119
  "div",
@@ -2122,7 +2123,7 @@ function Skeleton({
2122
2123
  children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2123
2124
  "div",
2124
2125
  {
2125
- className: `rounded bg-theme-tertiary ${animate ? "animate-pulse" : ""}`,
2126
+ className: `rounded ${animate ? "animate-pulse" : ""}`,
2126
2127
  style: { height: "12px", width: "60%" }
2127
2128
  }
2128
2129
  )
@@ -2143,8 +2144,203 @@ function Skeleton({
2143
2144
  ] });
2144
2145
  }
2145
2146
 
2146
- // src/components/EmptyState/EmptyState.tsx
2147
+ // src/components/TableStudioPanel/TableStudioPanel.tsx
2148
+ var import_react13 = require("react");
2149
+ var import_bear4 = require("@forgedevstack/bear");
2147
2150
  var import_jsx_runtime9 = require("react/jsx-runtime");
2151
+ var DEFAULT_ROW_COUNT = 10;
2152
+ function TableStudioPanel({
2153
+ data,
2154
+ columns,
2155
+ propsSnapshot,
2156
+ onDataChange,
2157
+ open = true,
2158
+ onOpenChange
2159
+ }) {
2160
+ const [activeTab, setActiveTab] = (0, import_react13.useState)("data");
2161
+ const [generateCount, setGenerateCount] = (0, import_react13.useState)(DEFAULT_ROW_COUNT);
2162
+ const handleGenerate = (0, import_react13.useCallback)(() => {
2163
+ if (!onDataChange) return;
2164
+ const count = Math.min(100, Math.max(1, generateCount));
2165
+ const generated = generateSampleData(columns, count);
2166
+ onDataChange(generated);
2167
+ setActiveTab("data");
2168
+ }, [columns, generateCount, onDataChange]);
2169
+ const panelContent = /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2170
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2171
+ "div",
2172
+ {
2173
+ style: {
2174
+ display: "flex",
2175
+ borderBottom: "1px solid var(--gt-border-color, rgba(0,0,0,0.08))",
2176
+ padding: "0.25rem 0",
2177
+ gap: 2
2178
+ },
2179
+ children: ["data", "props", "generate"].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2180
+ "button",
2181
+ {
2182
+ type: "button",
2183
+ onClick: () => setActiveTab(tab),
2184
+ style: {
2185
+ flex: 1,
2186
+ padding: "0.5rem 0.5rem",
2187
+ border: "none",
2188
+ borderRadius: 4,
2189
+ background: activeTab === tab ? "var(--gt-bg-tertiary)" : "transparent",
2190
+ color: "var(--gt-text-primary)",
2191
+ cursor: "pointer",
2192
+ fontWeight: activeTab === tab ? 600 : 400,
2193
+ fontSize: 12,
2194
+ textTransform: "capitalize"
2195
+ },
2196
+ children: tab
2197
+ },
2198
+ tab
2199
+ ))
2200
+ }
2201
+ ),
2202
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1, overflow: "auto", padding: "0.75rem" }, children: [
2203
+ activeTab === "data" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2204
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_bear4.Typography, { variant: "subtitle2", component: "h3", style: { marginBottom: "0.5rem" }, children: [
2205
+ "Data (",
2206
+ data.length,
2207
+ " rows)"
2208
+ ] }),
2209
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2210
+ "pre",
2211
+ {
2212
+ style: {
2213
+ margin: 0,
2214
+ fontSize: 11,
2215
+ fontFamily: "monospace",
2216
+ whiteSpace: "pre-wrap",
2217
+ wordBreak: "break-word",
2218
+ color: "var(--gt-text-primary)"
2219
+ },
2220
+ children: JSON.stringify(data, null, 2)
2221
+ }
2222
+ )
2223
+ ] }),
2224
+ activeTab === "props" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2225
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_bear4.Typography, { variant: "subtitle2", component: "h3", style: { marginBottom: "0.5rem" }, children: "Props" }),
2226
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("dl", { style: { margin: 0, fontSize: 13, color: "var(--gt-text-primary)" }, children: Object.entries(propsSnapshot).map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { marginBottom: "0.5rem" }, children: [
2227
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("dt", { style: { fontWeight: 600, marginBottom: 2 }, children: key }),
2228
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("dd", { style: { margin: 0, color: "var(--gt-text-secondary)" }, children: typeof value === "object" && value !== null ? JSON.stringify(value) : String(value) })
2229
+ ] }, key)) })
2230
+ ] }),
2231
+ activeTab === "generate" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2232
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_bear4.Typography, { variant: "subtitle2", component: "h3", style: { marginBottom: "0.5rem" }, children: "Generate sample data" }),
2233
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("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.)." }),
2234
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
2235
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { fontSize: 12, fontWeight: 500 }, children: [
2236
+ "Rows",
2237
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2238
+ "input",
2239
+ {
2240
+ type: "number",
2241
+ min: 1,
2242
+ max: 100,
2243
+ value: generateCount,
2244
+ onChange: (e) => setGenerateCount(Number(e.target.value) || 1),
2245
+ style: {
2246
+ display: "block",
2247
+ marginTop: 4,
2248
+ width: "100%",
2249
+ padding: "6px 8px",
2250
+ borderRadius: 4,
2251
+ border: "1px solid var(--gt-border-color)",
2252
+ background: "var(--gt-bg-primary)",
2253
+ color: "var(--gt-text-primary)"
2254
+ }
2255
+ }
2256
+ )
2257
+ ] }),
2258
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2259
+ "button",
2260
+ {
2261
+ type: "button",
2262
+ onClick: handleGenerate,
2263
+ disabled: !onDataChange,
2264
+ style: {
2265
+ padding: "8px 12px",
2266
+ borderRadius: 6,
2267
+ border: "none",
2268
+ background: onDataChange ? "var(--gt-accent-primary)" : "var(--gt-bg-tertiary)",
2269
+ color: onDataChange ? "#fff" : "var(--gt-text-muted)",
2270
+ cursor: onDataChange ? "pointer" : "not-allowed",
2271
+ fontWeight: 500,
2272
+ fontSize: 13
2273
+ },
2274
+ children: "Generate data"
2275
+ }
2276
+ ),
2277
+ !onDataChange && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: 11, color: "var(--gt-text-muted)" }, children: "Table must use studio with controllable data to generate." })
2278
+ ] })
2279
+ ] })
2280
+ ] })
2281
+ ] });
2282
+ const width = 320;
2283
+ const isCollapsed = !open;
2284
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2285
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2286
+ "button",
2287
+ {
2288
+ type: "button",
2289
+ onClick: () => onOpenChange == null ? void 0 : onOpenChange(!open),
2290
+ className: "grid-table-studio-toggle",
2291
+ style: {
2292
+ position: "fixed",
2293
+ right: open ? width : 0,
2294
+ top: "50%",
2295
+ transform: "translateY(-50%)",
2296
+ zIndex: 10001,
2297
+ width: 24,
2298
+ height: 48,
2299
+ border: "1px solid var(--gt-border-color, rgba(0,0,0,0.08))",
2300
+ borderRight: "none",
2301
+ borderRadius: "8px 0 0 8px",
2302
+ background: "var(--gt-bg-secondary, #f5f5f5)",
2303
+ color: "var(--gt-text-primary)",
2304
+ cursor: "pointer",
2305
+ display: "flex",
2306
+ alignItems: "center",
2307
+ justifyContent: "center",
2308
+ fontSize: 14,
2309
+ boxShadow: " -2px 0 8px rgba(0,0,0,0.08)"
2310
+ },
2311
+ "aria-label": open ? "Close studio panel" : "Open studio panel",
2312
+ children: open ? "\u203A" : "\u2039"
2313
+ }
2314
+ ),
2315
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2316
+ "aside",
2317
+ {
2318
+ className: "grid-table-studio-panel",
2319
+ style: {
2320
+ position: "fixed",
2321
+ top: 0,
2322
+ right: 0,
2323
+ bottom: 0,
2324
+ width: isCollapsed ? 0 : width,
2325
+ minWidth: isCollapsed ? 0 : 280,
2326
+ borderLeft: "1px solid var(--gt-border-color, rgba(0,0,0,0.08))",
2327
+ backgroundColor: "var(--gt-bg-secondary, #f5f5f5)",
2328
+ display: "flex",
2329
+ flexDirection: "column",
2330
+ overflow: "hidden",
2331
+ zIndex: 1e4,
2332
+ boxShadow: isCollapsed ? "none" : "-4px 0 12px rgba(0,0,0,0.08)",
2333
+ transition: "width 0.2s ease, box-shadow 0.2s ease"
2334
+ },
2335
+ "aria-label": "Table studio panel",
2336
+ children: !isCollapsed && panelContent
2337
+ }
2338
+ )
2339
+ ] });
2340
+ }
2341
+
2342
+ // src/components/EmptyState/EmptyState.tsx
2343
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2148
2344
  function EmptyState({
2149
2345
  title,
2150
2346
  description,
@@ -2157,22 +2353,22 @@ function EmptyState({
2157
2353
  const { translations } = state;
2158
2354
  const displayTitle = title != null ? title : translations.empty;
2159
2355
  const displayDescription = description != null ? description : translations.noResults;
2160
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2356
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2161
2357
  "div",
2162
2358
  {
2163
- className: `grid-empty-state flex flex-col items-center justify-center py-16 px-8 text-center ${className}`,
2359
+ className: `grid-empty-state ${className}`,
2164
2360
  style,
2165
2361
  role: "status",
2166
2362
  children: [
2167
- icon && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "grid-empty-icon mb-4 text-theme-muted text-4xl", children: icon }),
2168
- !icon && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "grid-empty-icon mb-4 text-theme-muted", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2363
+ icon && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "grid-empty-icon", children: icon }),
2364
+ !icon && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "grid-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2169
2365
  "svg",
2170
2366
  {
2171
- className: "w-16 h-16",
2367
+ className: "icon-lg",
2172
2368
  fill: "none",
2173
2369
  viewBox: "0 0 24 24",
2174
2370
  stroke: "currentColor",
2175
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2371
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2176
2372
  "path",
2177
2373
  {
2178
2374
  strokeLinecap: "round",
@@ -2183,9 +2379,9 @@ function EmptyState({
2183
2379
  )
2184
2380
  }
2185
2381
  ) }),
2186
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { className: "grid-empty-title text-lg font-medium text-theme-primary mb-2", children: displayTitle }),
2187
- displayDescription && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "grid-empty-description text-sm text-theme-muted max-w-sm mb-4", children: displayDescription }),
2188
- action && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "grid-empty-action", children: action })
2382
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "grid-empty-title", children: displayTitle }),
2383
+ displayDescription && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "grid-empty-description", children: displayDescription }),
2384
+ action && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "grid-empty-action", children: action })
2189
2385
  ]
2190
2386
  }
2191
2387
  );
@@ -2193,15 +2389,15 @@ function EmptyState({
2193
2389
 
2194
2390
  // src/components/MobileDrawer/MobileDrawer.tsx
2195
2391
  var import_react14 = require("react");
2196
- var import_jsx_runtime10 = require("react/jsx-runtime");
2392
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2197
2393
  function DrawerHeader({ title, onClose }) {
2198
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "drawer-header flex items-center justify-between px-4 py-3 border-b border-theme-border", children: [
2199
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "text-lg font-medium text-theme-primary", children: title }),
2200
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2394
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "drawer-header", children: [
2395
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h3", { children: title }),
2396
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2201
2397
  "button",
2202
2398
  {
2203
2399
  onClick: onClose,
2204
- className: "p-2 rounded hover:bg-theme-hover text-theme-secondary",
2400
+ className: "p-2 rounded",
2205
2401
  "aria-label": "Close",
2206
2402
  children: "X"
2207
2403
  }
@@ -2214,30 +2410,30 @@ function FilterContent() {
2214
2410
  const handleClearAll = (0, import_react14.useCallback)(() => {
2215
2411
  actions.clearFilters();
2216
2412
  }, [actions]);
2217
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "drawer-filter-content p-4 space-y-4", children: [
2218
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
2219
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-sm text-theme-muted", children: [
2413
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "drawer-filter-content", children: [
2414
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2415
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-sm text-theme-muted", children: [
2220
2416
  filters.length,
2221
2417
  " ",
2222
2418
  translations.filter,
2223
2419
  "(s) active"
2224
2420
  ] }),
2225
- filters.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2421
+ filters.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2226
2422
  "button",
2227
2423
  {
2228
2424
  onClick: handleClearAll,
2229
- className: "text-sm text-accent-primary hover:underline",
2425
+ className: "text-sm",
2230
2426
  children: translations.clearAll
2231
2427
  }
2232
2428
  )
2233
2429
  ] }),
2234
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "space-y-3", children: columns.filter((col) => col.filterable !== false).map((col) => {
2430
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "space-y-3", children: columns.filter((col) => col.filterable !== false).map((col) => {
2235
2431
  var _a;
2236
2432
  const existingFilter = filters.find((f) => f.columnId === col.id);
2237
2433
  const headerText = typeof col.header === "string" ? col.header : col.id;
2238
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "filter-item", children: [
2239
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "block text-sm font-medium text-theme-secondary mb-1", children: headerText }),
2240
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2434
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "filter-item", children: [
2435
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("label", { className: "block text-sm font-medium text-theme-secondary mb-1", children: headerText }),
2436
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2241
2437
  "input",
2242
2438
  {
2243
2439
  type: "text",
@@ -2250,7 +2446,7 @@ function FilterContent() {
2250
2446
  }
2251
2447
  },
2252
2448
  placeholder: `${translations.filter} ${headerText}...`,
2253
- 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"
2449
+ className: "w-full px-3 py-2 text-sm rounded"
2254
2450
  }
2255
2451
  )
2256
2452
  ] }, col.id);
@@ -2263,34 +2459,34 @@ function SortContent() {
2263
2459
  const handleClearAll = (0, import_react14.useCallback)(() => {
2264
2460
  actions.clearSorting();
2265
2461
  }, [actions]);
2266
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "drawer-sort-content p-4 space-y-4", children: [
2267
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
2268
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-sm text-theme-muted", children: [
2462
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "drawer-sort-content", children: [
2463
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2464
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-sm text-theme-muted", children: [
2269
2465
  sorting.length,
2270
2466
  " ",
2271
2467
  translations.sort,
2272
2468
  "(s) active"
2273
2469
  ] }),
2274
- sorting.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2470
+ sorting.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2275
2471
  "button",
2276
2472
  {
2277
2473
  onClick: handleClearAll,
2278
- className: "text-sm text-accent-primary hover:underline",
2474
+ className: "text-sm",
2279
2475
  children: translations.clearAll
2280
2476
  }
2281
2477
  )
2282
2478
  ] }),
2283
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "space-y-2", children: columns.filter((col) => col.sortable !== false).map((col) => {
2479
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "space-y-2", children: columns.filter((col) => col.sortable !== false).map((col) => {
2284
2480
  const sortItem = sorting.find((s) => s.columnId === col.id);
2285
2481
  const headerText = typeof col.header === "string" ? col.header : col.id;
2286
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2482
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2287
2483
  "button",
2288
2484
  {
2289
2485
  onClick: () => actions.toggleSorting(col.id),
2290
- 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"}`,
2486
+ className: `w-full px-3 py-2 rounded ${sortItem ? "active" : ""}`,
2291
2487
  children: [
2292
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-sm text-theme-primary", children: headerText }),
2293
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("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 : "-" })
2488
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-sm text-theme-primary", children: headerText }),
2489
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("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 : "-" })
2294
2490
  ]
2295
2491
  },
2296
2492
  col.id
@@ -2301,37 +2497,37 @@ function SortContent() {
2301
2497
  function ColumnsContent() {
2302
2498
  const { state, actions } = useTableContext();
2303
2499
  const { translations, columns, columnStates } = state;
2304
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "drawer-columns-content p-4 space-y-4", children: [
2305
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
2306
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-sm text-theme-muted", children: translations.showColumns }),
2307
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2500
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "drawer-columns-content", children: [
2501
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2502
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-sm text-theme-muted", children: translations.showColumns }),
2503
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2308
2504
  "button",
2309
2505
  {
2310
2506
  onClick: actions.resetColumns,
2311
- className: "text-sm text-accent-primary hover:underline",
2507
+ className: "text-sm",
2312
2508
  children: translations.resetColumns
2313
2509
  }
2314
2510
  )
2315
2511
  ] }),
2316
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "space-y-2", children: columns.map((col) => {
2512
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "space-y-2", children: columns.map((col) => {
2317
2513
  const colState = columnStates.find((cs) => cs.id === col.id);
2318
2514
  const isVisible = (colState == null ? void 0 : colState.visible) !== false;
2319
2515
  const headerText = typeof col.header === "string" ? col.header : col.id;
2320
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2516
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2321
2517
  "label",
2322
2518
  {
2323
- className: "flex items-center gap-3 px-3 py-2 rounded hover:bg-theme-hover cursor-pointer",
2519
+ className: "px-3 py-2 rounded cursor-pointer",
2324
2520
  children: [
2325
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2521
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2326
2522
  "input",
2327
2523
  {
2328
2524
  type: "checkbox",
2329
2525
  checked: isVisible,
2330
2526
  onChange: () => actions.toggleColumnVisibility(col.id),
2331
- className: "w-4 h-4 rounded border-theme-border"
2527
+ className: "w-4 h-4 rounded"
2332
2528
  }
2333
2529
  ),
2334
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-sm text-theme-primary", children: headerText })
2530
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-sm text-theme-primary", children: headerText })
2335
2531
  ]
2336
2532
  },
2337
2533
  col.id
@@ -2373,11 +2569,11 @@ function MobileDrawer({
2373
2569
  if (!isOpen || !content) {
2374
2570
  return null;
2375
2571
  }
2376
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: `mobile-drawer-container fixed inset-0 z-50 ${className}`, style, children: [
2377
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2572
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `mobile-drawer-container ${className}`, style, children: [
2573
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2378
2574
  "div",
2379
2575
  {
2380
- className: "mobile-drawer-overlay absolute inset-0 bg-black transition-opacity",
2576
+ className: "mobile-drawer-overlay",
2381
2577
  style: {
2382
2578
  opacity: DRAWER_OVERLAY_OPACITY,
2383
2579
  transitionDuration: `${DRAWER_ANIMATION_DURATION}ms`
@@ -2386,10 +2582,10 @@ function MobileDrawer({
2386
2582
  "aria-hidden": "true"
2387
2583
  }
2388
2584
  ),
2389
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2585
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2390
2586
  "div",
2391
2587
  {
2392
- 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",
2588
+ className: "mobile-drawer",
2393
2589
  style: {
2394
2590
  transitionDuration: `${DRAWER_ANIMATION_DURATION}ms`
2395
2591
  },
@@ -2397,11 +2593,11 @@ function MobileDrawer({
2397
2593
  "aria-modal": "true",
2398
2594
  "aria-labelledby": "drawer-title",
2399
2595
  children: [
2400
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DrawerHeader, { title: DRAWER_TITLES[content], onClose }),
2401
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "drawer-content flex-1 overflow-y-auto", children: [
2402
- content === "filter" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(FilterContent, {}),
2403
- content === "sort" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SortContent, {}),
2404
- content === "columns" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ColumnsContent, {})
2596
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(DrawerHeader, { title: DRAWER_TITLES[content], onClose }),
2597
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "drawer-content", children: [
2598
+ content === "filter" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(FilterContent, {}),
2599
+ content === "sort" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SortContent, {}),
2600
+ content === "columns" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ColumnsContent, {})
2405
2601
  ] })
2406
2602
  ]
2407
2603
  }
@@ -2410,7 +2606,7 @@ function MobileDrawer({
2410
2606
  }
2411
2607
 
2412
2608
  // src/components/GridTable/GridTable.tsx
2413
- var import_jsx_runtime11 = require("react/jsx-runtime");
2609
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2414
2610
  function GridTableContent({
2415
2611
  data,
2416
2612
  columns,
@@ -2448,10 +2644,18 @@ function GridTableContent({
2448
2644
  renderHeader,
2449
2645
  renderFooter,
2450
2646
  className = "",
2451
- style
2647
+ style,
2648
+ showOverflowTooltip,
2649
+ enableCellAutoSizeOnDoubleClick,
2650
+ subCellExpandTrigger,
2651
+ expandRowOnDoubleClick,
2652
+ themeMode,
2653
+ paginationConfig
2452
2654
  }) {
2655
+ var _a, _b;
2453
2656
  const { state, actions, computed } = useTableContext();
2454
2657
  const { shouldShowMobileView, breakpointValue } = useBreakpoint();
2658
+ const themeClass = themeMode === "dark" ? "dark" : themeMode === "light" ? "light" : void 0;
2455
2659
  const getRowIdFn = (0, import_react15.useCallback)(
2456
2660
  (row) => {
2457
2661
  if (getRowId) return getRowId(row);
@@ -2480,6 +2684,22 @@ function GridTableContent({
2480
2684
  },
2481
2685
  [actions]
2482
2686
  );
2687
+ const handleRowDoubleClick = (0, import_react15.useCallback)(
2688
+ (row, index) => {
2689
+ if (expandRowOnDoubleClick) {
2690
+ actions.toggleRowExpansion(getRowIdFn(row));
2691
+ }
2692
+ onRowDoubleClick == null ? void 0 : onRowDoubleClick(row, index);
2693
+ },
2694
+ [expandRowOnDoubleClick, actions, getRowIdFn, onRowDoubleClick]
2695
+ );
2696
+ const handleSelectAll = (0, import_react15.useCallback)(() => {
2697
+ if (computed.allSelected) {
2698
+ actions.deselectAll();
2699
+ } else {
2700
+ actions.selectAll();
2701
+ }
2702
+ }, [computed.allSelected, actions]);
2483
2703
  const handleFilterOpen = (0, import_react15.useCallback)(
2484
2704
  (columnId) => {
2485
2705
  if (shouldShowMobileView) {
@@ -2509,18 +2729,18 @@ function GridTableContent({
2509
2729
  if (error) {
2510
2730
  const errorMessage = typeof error === "string" ? error : error.message;
2511
2731
  if (errorContent) {
2512
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `grid-table-error ${classNames.root || ""} ${className}`, style: containerStyle, children: typeof errorContent === "function" ? errorContent(error) : errorContent });
2732
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: `grid-table-error ${classNames.root || ""} ${className}`, style: containerStyle, children: typeof errorContent === "function" ? errorContent(error) : errorContent });
2513
2733
  }
2514
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `grid-table-error ${classNames.root || ""} ${className}`, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2734
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: `grid-table-error ${classNames.root || ""} ${className}`, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2515
2735
  EmptyState,
2516
2736
  {
2517
2737
  title: state.translations.errorLoading,
2518
2738
  description: errorMessage,
2519
- action: onRetry && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2739
+ action: onRetry && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2520
2740
  "button",
2521
2741
  {
2522
2742
  onClick: onRetry,
2523
- className: "px-4 py-2 bg-accent-primary text-white rounded hover:bg-accent-primary/90",
2743
+ className: "px-4 py-2 bg-accent-primary text-white rounded hover:opacity-90 cursor-pointer",
2524
2744
  children: state.translations.retry
2525
2745
  }
2526
2746
  )
@@ -2529,9 +2749,9 @@ function GridTableContent({
2529
2749
  }
2530
2750
  if (loading) {
2531
2751
  if (loadingContent) {
2532
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `grid-table-loading ${classNames.root || ""} ${className}`, style: containerStyle, children: loadingContent });
2752
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: `grid-table-loading ${classNames.root || ""} ${className}`, style: containerStyle, children: loadingContent });
2533
2753
  }
2534
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `grid-table-loading ${classNames.root || ""} ${className}`, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2754
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: `grid-table-loading ${classNames.root || ""} ${className}`, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2535
2755
  Skeleton,
2536
2756
  {
2537
2757
  rows: 5,
@@ -2545,55 +2765,55 @@ function GridTableContent({
2545
2765
  ) });
2546
2766
  }
2547
2767
  const isEmpty = computed.paginatedData.length === 0;
2548
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2768
+ const tableContent = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2549
2769
  "div",
2550
2770
  {
2551
- className: `grid-table bg-theme-primary rounded-lg border border-theme-border overflow-hidden ${classNames.root || ""} ${className}`,
2771
+ className: `grid-table rounded-lg border overflow-hidden ${classNames.root || ""} ${className}`,
2552
2772
  style: containerStyle,
2553
2773
  role: "table",
2554
2774
  children: [
2555
- renderHeader && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "grid-table-custom-header", children: renderHeader() }),
2556
- showGlobalFilter && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "grid-table-toolbar flex items-center gap-4 px-4 py-3 border-b border-theme-border", children: [
2557
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex-1 relative", children: [
2558
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2775
+ renderHeader && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "grid-table-custom-header", children: renderHeader() }),
2776
+ showGlobalFilter && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "grid-table-toolbar", children: [
2777
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "toolbar-search-wrapper", children: [
2778
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2559
2779
  "svg",
2560
2780
  {
2561
- className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-theme-muted",
2781
+ className: "search-icon",
2562
2782
  fill: "none",
2563
2783
  viewBox: "0 0 24 24",
2564
2784
  stroke: "currentColor",
2565
2785
  strokeWidth: 2,
2566
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" })
2786
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" })
2567
2787
  }
2568
2788
  ),
2569
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2789
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2570
2790
  "input",
2571
2791
  {
2572
2792
  type: "text",
2573
2793
  value: state.globalFilter,
2574
2794
  onChange: (e) => actions.setGlobalFilter(e.target.value),
2575
2795
  placeholder: state.translations.search,
2576
- 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"
2796
+ className: "w-full pl-10 pr-3 py-2 text-sm rounded"
2577
2797
  }
2578
2798
  ),
2579
- state.globalFilter && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2799
+ state.globalFilter && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2580
2800
  "button",
2581
2801
  {
2582
2802
  onClick: () => actions.setGlobalFilter(""),
2583
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-theme-muted hover:text-theme-primary",
2803
+ className: "clear-button",
2584
2804
  "aria-label": "Clear search",
2585
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) })
2805
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) })
2586
2806
  }
2587
2807
  )
2588
2808
  ] }),
2589
- state.filters.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2809
+ state.filters.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2590
2810
  "button",
2591
2811
  {
2592
2812
  onClick: () => actions.clearFilters(),
2593
- className: "flex items-center gap-2 px-3 py-2 text-sm rounded border border-theme-border hover:bg-theme-hover text-theme-secondary",
2813
+ className: "filter-badge",
2594
2814
  children: [
2595
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }),
2596
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { children: [
2815
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }),
2816
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
2597
2817
  state.filters.length,
2598
2818
  " filter",
2599
2819
  state.filters.length > 1 ? "s" : ""
@@ -2601,38 +2821,38 @@ function GridTableContent({
2601
2821
  ]
2602
2822
  }
2603
2823
  ),
2604
- shouldShowMobileView && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-2", children: [
2605
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2824
+ shouldShowMobileView && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "toolbar-actions", children: [
2825
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2606
2826
  "button",
2607
2827
  {
2608
2828
  onClick: () => actions.openMobileDrawer("filter"),
2609
- className: "p-2 rounded border border-theme-border hover:bg-theme-hover",
2829
+ className: "toolbar-action-button",
2610
2830
  "aria-label": state.translations.filter,
2611
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("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" }) })
2831
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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" }) })
2612
2832
  }
2613
2833
  ),
2614
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2834
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2615
2835
  "button",
2616
2836
  {
2617
2837
  onClick: () => actions.openMobileDrawer("sort"),
2618
- className: "p-2 rounded border border-theme-border hover:bg-theme-hover",
2838
+ className: "toolbar-action-button",
2619
2839
  "aria-label": state.translations.sort,
2620
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) })
2840
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) })
2621
2841
  }
2622
2842
  ),
2623
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2843
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2624
2844
  "button",
2625
2845
  {
2626
2846
  onClick: () => actions.openMobileDrawer("columns"),
2627
- className: "p-2 rounded border border-theme-border hover:bg-theme-hover",
2847
+ className: "toolbar-action-button",
2628
2848
  "aria-label": state.translations.columns,
2629
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("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" }) })
2849
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { className: "icon-md", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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" }) })
2630
2850
  }
2631
2851
  )
2632
2852
  ] })
2633
2853
  ] }),
2634
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "grid-table-container overflow-auto", children: [
2635
- !shouldShowMobileView && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2854
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "grid-table-container overflow-auto", children: [
2855
+ !shouldShowMobileView && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2636
2856
  GridHeader,
2637
2857
  {
2638
2858
  columns,
@@ -2645,24 +2865,25 @@ function GridTableContent({
2645
2865
  enableDragDrop,
2646
2866
  enableResize: enableColumnResize,
2647
2867
  enableSelection: enableRowSelection,
2868
+ enableExpansion: enableRowExpansion,
2648
2869
  allSelected: computed.allSelected,
2649
2870
  someSelected: computed.someSelected,
2650
- onSelectAll: actions.selectAll,
2871
+ onSelectAll: handleSelectAll,
2651
2872
  onFilterOpen: handleFilterOpen,
2652
2873
  getSortDirection: (colId) => {
2653
- var _a;
2874
+ var _a2;
2654
2875
  const sort = state.sorting.find((s) => s.columnId === colId);
2655
- return (_a = sort == null ? void 0 : sort.direction) != null ? _a : null;
2876
+ return (_a2 = sort == null ? void 0 : sort.direction) != null ? _a2 : null;
2656
2877
  }
2657
2878
  }
2658
2879
  ),
2659
- isEmpty ? emptyContent || /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2880
+ isEmpty ? emptyContent || /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2660
2881
  EmptyState,
2661
2882
  {
2662
2883
  className: classNames.empty,
2663
2884
  style: styles.empty
2664
2885
  }
2665
- ) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2886
+ ) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2666
2887
  GridBody,
2667
2888
  {
2668
2889
  data: computed.paginatedData,
@@ -2677,7 +2898,7 @@ function GridTableContent({
2677
2898
  selectedIds: state.selectedIds,
2678
2899
  expandedIds: state.expandedIds,
2679
2900
  onRowClick,
2680
- onRowDoubleClick,
2901
+ onRowDoubleClick: handleRowDoubleClick,
2681
2902
  onCellClick,
2682
2903
  onRowSelect: handleRowSelect,
2683
2904
  onRowExpand: handleRowExpand,
@@ -2689,27 +2910,50 @@ function GridTableContent({
2689
2910
  }
2690
2911
  )
2691
2912
  ] }),
2692
- showPagination && !isEmpty && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2693
- Pagination,
2694
- {
2695
- page: state.page,
2696
- pageSize: state.pageSize,
2697
- totalItems: computed.sortedData.length,
2698
- totalPages: computed.totalPages,
2699
- className: classNames.pagination,
2700
- style: styles.pagination,
2701
- onPageChange: (page) => {
2702
- actions.setPage(page);
2703
- onPageChange == null ? void 0 : onPageChange(page, state.pageSize);
2704
- },
2705
- onPageSizeChange: (pageSize) => {
2706
- actions.setPageSize(pageSize);
2707
- onPageChange == null ? void 0 : onPageChange(1, pageSize);
2913
+ showPagination && !isEmpty && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `grid-pagination ${(_a = classNames.pagination) != null ? _a : ""}`, style: styles.pagination, role: "navigation", "aria-label": "Pagination", children: [
2914
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "grid-pagination-info", children: [
2915
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_bear5.Typography, { component: "span", variant: "body2", color: "secondary", children: [
2916
+ (state.page - 1) * state.pageSize + 1,
2917
+ "-",
2918
+ Math.min(state.page * state.pageSize, computed.sortedData.length),
2919
+ " ",
2920
+ state.translations.of,
2921
+ " ",
2922
+ computed.sortedData.length
2923
+ ] }),
2924
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_bear5.Typography, { component: "span", variant: "caption", color: "secondary", className: "bear-sr-only", children: state.translations.rowsPerPage }),
2925
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2926
+ import_bear5.Select,
2927
+ {
2928
+ value: String(state.pageSize),
2929
+ onChange: (value) => {
2930
+ const pageSize = Number(value);
2931
+ actions.setPageSize(pageSize);
2932
+ onPageChange == null ? void 0 : onPageChange(1, pageSize);
2933
+ },
2934
+ options: ((_b = paginationConfig == null ? void 0 : paginationConfig.pageSizeOptions) != null ? _b : [10, 20, 50, 100]).map((size) => ({ value: String(size), label: String(size) })),
2935
+ size: "sm"
2936
+ }
2937
+ )
2938
+ ] }),
2939
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "grid-pagination-controls", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2940
+ import_bear5.Pagination,
2941
+ {
2942
+ count: Math.max(1, computed.totalPages),
2943
+ page: state.page,
2944
+ onChange: (page) => {
2945
+ actions.setPage(page);
2946
+ onPageChange == null ? void 0 : onPageChange(page, state.pageSize);
2947
+ },
2948
+ showFirstLast: true,
2949
+ showPrevNext: true,
2950
+ size: "sm",
2951
+ variant: "outlined"
2708
2952
  }
2709
- }
2710
- ),
2711
- renderFooter && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "grid-table-custom-footer", children: renderFooter() }),
2712
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2953
+ ) })
2954
+ ] }),
2955
+ renderFooter && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "grid-table-custom-footer", children: renderFooter() }),
2956
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2713
2957
  MobileDrawer,
2714
2958
  {
2715
2959
  isOpen: state.showMobileDrawer,
@@ -2722,6 +2966,10 @@ function GridTableContent({
2722
2966
  ]
2723
2967
  }
2724
2968
  );
2969
+ if (themeClass) {
2970
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: themeClass, children: tableContent });
2971
+ }
2972
+ return tableContent;
2725
2973
  }
2726
2974
  function GridTable({
2727
2975
  data,
@@ -2736,12 +2984,26 @@ function GridTable({
2736
2984
  sortConfig,
2737
2985
  enableMultiSelect = false,
2738
2986
  getRowId,
2987
+ showOverflowTooltip,
2988
+ enableCellAutoSizeOnDoubleClick,
2989
+ subCellExpandTrigger,
2990
+ expandRowOnDoubleClick,
2991
+ themeMode,
2992
+ themeOverride,
2993
+ studio = false,
2739
2994
  ...props
2740
2995
  }) {
2741
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2996
+ var _a, _b;
2997
+ const [studioData, setStudioData] = (0, import_react15.useState)(data);
2998
+ const [studioOpen, setStudioOpen] = (0, import_react15.useState)(true);
2999
+ (0, import_react15.useEffect)(() => {
3000
+ if (studio) setStudioData(data);
3001
+ }, [data, studio]);
3002
+ const effectiveData = studio ? studioData : data;
3003
+ const tableContent = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2742
3004
  TableProvider,
2743
3005
  {
2744
- data,
3006
+ data: effectiveData,
2745
3007
  columns,
2746
3008
  loading,
2747
3009
  error,
@@ -2754,19 +3016,223 @@ function GridTable({
2754
3016
  enableMultiSort: sortConfig == null ? void 0 : sortConfig.multiSort,
2755
3017
  enableMultiSelect,
2756
3018
  getRowId,
2757
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3019
+ showOverflowTooltip,
3020
+ enableCellAutoSizeOnDoubleClick,
3021
+ subCellExpandTrigger,
3022
+ expandRowOnDoubleClick,
3023
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2758
3024
  GridTableContent,
2759
3025
  {
2760
- data,
3026
+ data: effectiveData,
2761
3027
  columns,
2762
3028
  loading,
2763
3029
  error,
2764
3030
  getRowId,
3031
+ themeMode,
3032
+ paginationConfig,
2765
3033
  ...props
2766
3034
  }
2767
3035
  )
2768
3036
  }
2769
3037
  );
3038
+ const withTheme = themeOverride && Object.keys(themeOverride).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_bear5.BearProvider, { theme: themeOverride, defaultMode: themeMode === "dark" ? "dark" : "light", children: tableContent }) : tableContent;
3039
+ if (studio) {
3040
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3041
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "grid-table-studio-main", style: { width: "100%" }, children: withTheme }),
3042
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3043
+ TableStudioPanel,
3044
+ {
3045
+ data: studioData,
3046
+ columns,
3047
+ propsSnapshot: {
3048
+ themeMode,
3049
+ themeOverride,
3050
+ showPagination: (_a = props.showPagination) != null ? _a : true,
3051
+ showGlobalFilter: (_b = props.showGlobalFilter) != null ? _b : true,
3052
+ enableRowSelection: props.enableRowSelection,
3053
+ enableRowExpansion: props.enableRowExpansion
3054
+ },
3055
+ onDataChange: setStudioData,
3056
+ open: studioOpen,
3057
+ onOpenChange: setStudioOpen
3058
+ }
3059
+ )
3060
+ ] });
3061
+ }
3062
+ return withTheme;
3063
+ }
3064
+
3065
+ // src/components/Pagination/Pagination.tsx
3066
+ var import_react16 = require("react");
3067
+ var import_jsx_runtime13 = require("react/jsx-runtime");
3068
+ function Pagination({
3069
+ page,
3070
+ pageSize,
3071
+ totalItems,
3072
+ totalPages,
3073
+ pageSizeOptions = [10, 20, 50, 100],
3074
+ showFirstLast = true,
3075
+ showPageNumbers = true,
3076
+ maxPageButtons = FIVE,
3077
+ className = "",
3078
+ style,
3079
+ onPageChange,
3080
+ onPageSizeChange
3081
+ }) {
3082
+ const { state } = useTableContext();
3083
+ const { translations } = state;
3084
+ const canGoPrevious = page > ONE;
3085
+ const canGoNext = page < totalPages;
3086
+ const startItem = (page - ONE) * pageSize + ONE;
3087
+ const endItem = Math.min(page * pageSize, totalItems);
3088
+ const handleFirstPage = (0, import_react16.useCallback)(() => {
3089
+ onPageChange(ONE);
3090
+ }, [onPageChange]);
3091
+ const handlePreviousPage = (0, import_react16.useCallback)(() => {
3092
+ if (canGoPrevious) {
3093
+ onPageChange(page - ONE);
3094
+ }
3095
+ }, [canGoPrevious, page, onPageChange]);
3096
+ const handleNextPage = (0, import_react16.useCallback)(() => {
3097
+ if (canGoNext) {
3098
+ onPageChange(page + ONE);
3099
+ }
3100
+ }, [canGoNext, page, onPageChange]);
3101
+ const handleLastPage = (0, import_react16.useCallback)(() => {
3102
+ onPageChange(totalPages);
3103
+ }, [onPageChange, totalPages]);
3104
+ const handlePageSizeChange = (0, import_react16.useCallback)(
3105
+ (event) => {
3106
+ onPageSizeChange(Number(event.target.value));
3107
+ },
3108
+ [onPageSizeChange]
3109
+ );
3110
+ const pageNumbers = (0, import_react16.useMemo)(() => {
3111
+ if (!showPageNumbers || totalPages <= ONE) return [];
3112
+ const pages = [];
3113
+ const halfMax = Math.floor(maxPageButtons / 2);
3114
+ let start = Math.max(ONE, page - halfMax);
3115
+ let end = Math.min(totalPages, page + halfMax);
3116
+ if (page <= halfMax) {
3117
+ end = Math.min(totalPages, maxPageButtons);
3118
+ }
3119
+ if (page > totalPages - halfMax) {
3120
+ start = Math.max(ONE, totalPages - maxPageButtons + ONE);
3121
+ }
3122
+ if (start > ONE) {
3123
+ pages.push(ONE);
3124
+ if (start > 2) {
3125
+ pages.push("ellipsis");
3126
+ }
3127
+ }
3128
+ for (let i = start; i <= end; i++) {
3129
+ if (!pages.includes(i)) {
3130
+ pages.push(i);
3131
+ }
3132
+ }
3133
+ if (end < totalPages) {
3134
+ if (end < totalPages - ONE) {
3135
+ pages.push("ellipsis");
3136
+ }
3137
+ pages.push(totalPages);
3138
+ }
3139
+ return pages;
3140
+ }, [page, totalPages, showPageNumbers, maxPageButtons]);
3141
+ if (totalItems === 0) {
3142
+ return null;
3143
+ }
3144
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3145
+ "div",
3146
+ {
3147
+ className: `grid-pagination ${className}`,
3148
+ style,
3149
+ role: "navigation",
3150
+ "aria-label": "Pagination",
3151
+ children: [
3152
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid-pagination-info", children: [
3153
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid-pagination-range", children: [
3154
+ startItem,
3155
+ "-",
3156
+ endItem,
3157
+ " ",
3158
+ translations.of,
3159
+ " ",
3160
+ totalItems
3161
+ ] }),
3162
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid-pagination-size", children: [
3163
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { htmlFor: "page-size", children: [
3164
+ translations.rowsPerPage,
3165
+ ":"
3166
+ ] }),
3167
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3168
+ "select",
3169
+ {
3170
+ id: "page-size",
3171
+ value: pageSize,
3172
+ onChange: handlePageSizeChange,
3173
+ className: "px-2 py-1 text-sm rounded",
3174
+ children: pageSizeOptions.map((size) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: size, children: size }, size))
3175
+ }
3176
+ )
3177
+ ] })
3178
+ ] }),
3179
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid-pagination-controls", children: [
3180
+ showFirstLast && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3181
+ "button",
3182
+ {
3183
+ onClick: handleFirstPage,
3184
+ disabled: !canGoPrevious,
3185
+ className: "p-2 rounded text-theme-secondary",
3186
+ "aria-label": translations.first,
3187
+ children: "<<"
3188
+ }
3189
+ ),
3190
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3191
+ "button",
3192
+ {
3193
+ onClick: handlePreviousPage,
3194
+ disabled: !canGoPrevious,
3195
+ className: "p-2 rounded text-theme-secondary",
3196
+ "aria-label": translations.previous,
3197
+ children: "<"
3198
+ }
3199
+ ),
3200
+ showPageNumbers && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "grid-pagination-pages", children: pageNumbers.map(
3201
+ (pageNum, index) => pageNum === "ellipsis" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "px-2 text-theme-muted", children: "..." }, `ellipsis-${index}`) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3202
+ "button",
3203
+ {
3204
+ onClick: () => onPageChange(pageNum),
3205
+ className: `min-w-[32px] h-8 px-2 rounded text-sm ${pageNum === page ? "active" : ""}`,
3206
+ "aria-current": pageNum === page ? "page" : void 0,
3207
+ children: pageNum
3208
+ },
3209
+ pageNum
3210
+ )
3211
+ ) }),
3212
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3213
+ "button",
3214
+ {
3215
+ onClick: handleNextPage,
3216
+ disabled: !canGoNext,
3217
+ className: "p-2 rounded text-theme-secondary",
3218
+ "aria-label": translations.next,
3219
+ children: ">"
3220
+ }
3221
+ ),
3222
+ showFirstLast && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3223
+ "button",
3224
+ {
3225
+ onClick: handleLastPage,
3226
+ disabled: !canGoNext,
3227
+ className: "p-2 rounded text-theme-secondary",
3228
+ "aria-label": translations.last,
3229
+ children: ">>"
3230
+ }
3231
+ )
3232
+ ] })
3233
+ ]
3234
+ }
3235
+ );
2770
3236
  }
2771
3237
  // Annotate the CommonJS export names for ESM import in node:
2772
3238
  0 && (module.exports = {