@nexgrid/react 0.1.0 → 0.2.0

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
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- // src/nex-grid.tsx
3
+ // src/table-x.tsx
4
4
  import * as React4 from "react";
5
5
  import {
6
6
  DENSITIES,
@@ -16,6 +16,8 @@ import {
16
16
  getPageNumbers,
17
17
  getRecordRange,
18
18
  initialHiddenColumns,
19
+ isEditable,
20
+ isFilterable,
19
21
  isHideable,
20
22
  isPageSize,
21
23
  isSortable,
@@ -26,10 +28,13 @@ import {
26
28
  toExportColumns,
27
29
  totalPagesFor,
28
30
  visibleColumns,
31
+ withFilter,
29
32
  withPage,
30
33
  withPageSize,
31
34
  withSearch,
32
- withToggledSort
35
+ withToggledSort,
36
+ withToggledMultiSort,
37
+ copyToClipboard
33
38
  } from "@nexgrid/core";
34
39
 
35
40
  // src/icons.tsx
@@ -70,29 +75,22 @@ function XIcon(props) {
70
75
  /* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
71
76
  ] });
72
77
  }
73
- function SlidersIcon(props) {
78
+ function ColumnsIcon(props) {
74
79
  return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
75
- /* @__PURE__ */ jsx("line", { x1: "21", x2: "14", y1: "4", y2: "4" }),
76
- /* @__PURE__ */ jsx("line", { x1: "10", x2: "3", y1: "4", y2: "4" }),
77
- /* @__PURE__ */ jsx("line", { x1: "21", x2: "12", y1: "12", y2: "12" }),
78
- /* @__PURE__ */ jsx("line", { x1: "8", x2: "3", y1: "12", y2: "12" }),
79
- /* @__PURE__ */ jsx("line", { x1: "21", x2: "16", y1: "20", y2: "20" }),
80
- /* @__PURE__ */ jsx("line", { x1: "12", x2: "3", y1: "20", y2: "20" }),
81
- /* @__PURE__ */ jsx("line", { x1: "14", x2: "14", y1: "2", y2: "6" }),
82
- /* @__PURE__ */ jsx("line", { x1: "8", x2: "8", y1: "10", y2: "14" }),
83
- /* @__PURE__ */ jsx("line", { x1: "16", x2: "16", y1: "18", y2: "22" })
80
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
81
+ /* @__PURE__ */ jsx("path", { d: "M9 3v18" }),
82
+ /* @__PURE__ */ jsx("path", { d: "M15 3v18" })
84
83
  ] });
85
84
  }
86
- function FilterIcon(props) {
87
- return /* @__PURE__ */ jsx(Icon, { ...props, children: /* @__PURE__ */ jsx("polygon", { points: "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" }) });
88
- }
89
- function DownloadIcon(props) {
85
+ function DensityIcon(props) {
90
86
  return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
91
- /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
92
- /* @__PURE__ */ jsx("polyline", { points: "7 10 12 15 17 10" }),
93
- /* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "15", y2: "3" })
87
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "4.5", width: "18", height: "6", rx: "1.5" }),
88
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "13.5", width: "18", height: "6", rx: "1.5" })
94
89
  ] });
95
90
  }
91
+ function ChevronDownIcon(props) {
92
+ return /* @__PURE__ */ jsx(Icon, { ...props, children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) });
93
+ }
96
94
  function FileSpreadsheetIcon(props) {
97
95
  return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
98
96
  /* @__PURE__ */ jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
@@ -141,6 +139,26 @@ function ArrowUpDownIcon(props) {
141
139
  function CheckIcon(props) {
142
140
  return /* @__PURE__ */ jsx(Icon, { ...props, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
143
141
  }
142
+ function RotateCcwIcon(props) {
143
+ return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
144
+ /* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
145
+ /* @__PURE__ */ jsx("path", { d: "M3 3v5h5" })
146
+ ] });
147
+ }
148
+ function DownloadTrayIcon(props) {
149
+ return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
150
+ /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
151
+ /* @__PURE__ */ jsx("polyline", { points: "7 10 12 15 17 10" }),
152
+ /* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "15", y2: "3" })
153
+ ] });
154
+ }
155
+ function DotsVerticalIcon(props) {
156
+ return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
157
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "5", r: "1.5" }),
158
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1.5" }),
159
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "19", r: "1.5" })
160
+ ] });
161
+ }
144
162
 
145
163
  // src/render.tsx
146
164
  import * as React from "react";
@@ -176,9 +194,9 @@ function bodyCellStyle(col) {
176
194
  }
177
195
  function headerInnerClass(col) {
178
196
  const align = col.meta?.align;
179
- if (align === "center") return "nxg-th-inner nxg-th-inner--center";
180
- if (align === "right") return "nxg-th-inner nxg-th-inner--right";
181
- return "nxg-th-inner";
197
+ if (align === "center") return "tbx-th-inner tbx-th-inner--center";
198
+ if (align === "right") return "tbx-th-inner tbx-th-inner--right";
199
+ return "tbx-th-inner";
182
200
  }
183
201
  function renderTemplate(template, values) {
184
202
  const parts = [];
@@ -250,7 +268,7 @@ function useDropdown() {
250
268
  return { isOpen, toggle, close, containerRef, triggerRef };
251
269
  }
252
270
 
253
- // src/nex-grid.tsx
271
+ // src/table-x.tsx
254
272
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
255
273
  function defaultRowId(row) {
256
274
  const record = row;
@@ -262,37 +280,72 @@ var DENSITY_LABEL_KEY = {
262
280
  default: "densityDefault",
263
281
  comfortable: "densityComfortable"
264
282
  };
265
- function NexGrid({
266
- columns,
267
- data,
268
- total,
269
- query,
270
- onQueryChange,
271
- caption,
272
- density: initialDensity = "default",
273
- isLoading = false,
274
- error = false,
275
- onRetry,
276
- enableSelection = false,
277
- onSelectionChange,
278
- enableSearch = true,
279
- searchPlaceholder,
280
- toolbarActions,
281
- onRowClick,
282
- getRowId = defaultRowId,
283
- className,
284
- showSerialNumber = true,
285
- enableExport = true,
286
- exportFileName,
287
- onExportAll,
288
- fetchEndpoint,
289
- badgeRules,
290
- locale: localeOverrides,
291
- onNotify,
292
- theme = "light"
293
- }) {
283
+ function TableX(props) {
284
+ const {
285
+ columns,
286
+ data,
287
+ total,
288
+ query,
289
+ onQueryChange,
290
+ caption,
291
+ density: initialDensity = "default",
292
+ isLoading = false,
293
+ error = false,
294
+ onRetry,
295
+ enableSelection = false,
296
+ selectionMode = "multi",
297
+ enableColumnFilters = true,
298
+ enableColumnResize = true,
299
+ onSelectionChange,
300
+ enableSearch = true,
301
+ searchPlaceholder,
302
+ enableColumns = true,
303
+ showColumnsButton,
304
+ enableDensity = true,
305
+ showDensityButton,
306
+ enableExport = true,
307
+ showExportButton,
308
+ enableSorting = true,
309
+ enablePagination = true,
310
+ showPagination,
311
+ enableRowsPerPage = true,
312
+ showRowsPerPage,
313
+ enableJumpToPage = true,
314
+ showJumpToPage,
315
+ showToolbar = true,
316
+ showFooter = true,
317
+ renderExpandedRow,
318
+ enableBulkActions = true,
319
+ bulkActions,
320
+ enableSummaryRow,
321
+ enableColumnReorder = false,
322
+ onColumnOrderChange,
323
+ onCellEdit,
324
+ toolbarActions,
325
+ onRowClick,
326
+ getRowId = defaultRowId,
327
+ className,
328
+ showSerialNumber = true,
329
+ exportFileName,
330
+ onExportAll,
331
+ fetchEndpoint,
332
+ badgeRules,
333
+ locale: localeOverrides,
334
+ onNotify,
335
+ theme = "light"
336
+ } = props;
294
337
  const locale = resolveLocale(localeOverrides);
295
338
  const boolLabels = { yes: locale.booleanYes, no: locale.booleanNo };
339
+ const isColumnsVisible = enableColumns && showColumnsButton !== false;
340
+ const isDensityVisible = enableDensity && showDensityButton !== false;
341
+ const isExportVisible = enableExport && showExportButton !== false;
342
+ const isPaginationVisible = enablePagination && showPagination !== false;
343
+ const isRowsPerPageVisible = enableRowsPerPage && showRowsPerPage !== false;
344
+ const isJumpToPageVisible = enableJumpToPage && showJumpToPage !== false;
345
+ const [colList, setColList] = React4.useState(columns);
346
+ React4.useEffect(() => {
347
+ setColList(columns);
348
+ }, [columns]);
296
349
  const [density, setDensity] = React4.useState(initialDensity);
297
350
  const [hiddenCols, setHiddenCols] = React4.useState(
298
351
  () => initialHiddenColumns(columns)
@@ -300,7 +353,14 @@ function NexGrid({
300
353
  const [selectedIds, setSelectedIds] = React4.useState(
301
354
  () => /* @__PURE__ */ new Set()
302
355
  );
356
+ const [expandedRows, setExpandedRows] = React4.useState(
357
+ () => /* @__PURE__ */ new Set()
358
+ );
359
+ const [editingCell, setEditingCell] = React4.useState(null);
360
+ const [draggedColId, setDraggedColId] = React4.useState(null);
303
361
  const [isExporting, setIsExporting] = React4.useState(false);
362
+ const [openFilterCol, setOpenFilterCol] = React4.useState(null);
363
+ const [colWidths, setColWidths] = React4.useState({});
304
364
  const columnsMenu = useDropdown();
305
365
  const densityMenu = useDropdown();
306
366
  const exportMenu = useDropdown();
@@ -309,6 +369,7 @@ function NexGrid({
309
369
  const densityButtonId = `${instanceId}-density`;
310
370
  const exportButtonId = `${instanceId}-export`;
311
371
  const jumpInputId = `${instanceId}-jump`;
372
+ const rootRef = React4.useRef(null);
312
373
  const notify = (type, message) => {
313
374
  onNotify?.({ type, message });
314
375
  };
@@ -318,126 +379,185 @@ function NexGrid({
318
379
  const range = getRecordRange(currentPage, pageSize, total);
319
380
  const sort = primarySort(query);
320
381
  const visible = React4.useMemo(
321
- () => visibleColumns(columns, hiddenCols),
322
- [columns, hiddenCols]
382
+ () => visibleColumns(colList, hiddenCols),
383
+ [colList, hiddenCols]
323
384
  );
324
- const hideable = React4.useMemo(() => columns.filter(isHideable), [columns]);
385
+ const hideable = React4.useMemo(() => colList.filter(isHideable), [colList]);
325
386
  const pageItems = React4.useMemo(
326
387
  () => getPageNumbers(currentPage, totalPages),
327
388
  [currentPage, totalPages]
328
389
  );
329
390
  const pageRowIds = React4.useMemo(() => data.map((row) => getRowId(row)), [data, getRowId]);
330
- const columnCount = visible.length + (showSerialNumber ? 1 : 0) + (enableSelection ? 1 : 0);
391
+ const columnCount = visible.length + (renderExpandedRow ? 1 : 0) + (showSerialNumber ? 1 : 0) + (enableSelection ? 1 : 0);
392
+ const getPinnedOffsets = (visibleCols) => {
393
+ const leftOffsets2 = /* @__PURE__ */ new Map();
394
+ const rightOffsets2 = /* @__PURE__ */ new Map();
395
+ let currentLeft = 0;
396
+ let lastLeftPinnedId2 = null;
397
+ if (renderExpandedRow) {
398
+ leftOffsets2.set("__expand", currentLeft);
399
+ currentLeft += 40;
400
+ lastLeftPinnedId2 = "__expand";
401
+ }
402
+ if (enableSelection) {
403
+ leftOffsets2.set("__select", currentLeft);
404
+ currentLeft += 44;
405
+ lastLeftPinnedId2 = "__select";
406
+ }
407
+ if (showSerialNumber) {
408
+ leftOffsets2.set("__serial", currentLeft);
409
+ currentLeft += 56;
410
+ lastLeftPinnedId2 = "__serial";
411
+ }
412
+ for (const col of visibleCols) {
413
+ const id = getColumnId2(col);
414
+ const pin = col.meta?.pinned;
415
+ const width = colWidths[id] ?? col.meta?.width ?? 140;
416
+ if (pin === "left") {
417
+ leftOffsets2.set(id, currentLeft);
418
+ currentLeft += width;
419
+ lastLeftPinnedId2 = id;
420
+ }
421
+ }
422
+ let currentRight = 0;
423
+ let firstRightPinnedId2 = null;
424
+ for (let i = visibleCols.length - 1; i >= 0; i--) {
425
+ const col = visibleCols[i];
426
+ if (!col) continue;
427
+ const id = getColumnId2(col);
428
+ const pin = col.meta?.pinned;
429
+ const width = colWidths[id] ?? col.meta?.width ?? 140;
430
+ if (pin === "right") {
431
+ rightOffsets2.set(id, currentRight);
432
+ currentRight += width;
433
+ firstRightPinnedId2 = id;
434
+ }
435
+ }
436
+ return { leftOffsets: leftOffsets2, rightOffsets: rightOffsets2, lastLeftPinnedId: lastLeftPinnedId2, firstRightPinnedId: firstRightPinnedId2 };
437
+ };
438
+ const { leftOffsets, rightOffsets, lastLeftPinnedId, firstRightPinnedId } = getPinnedOffsets(visible);
331
439
  const [searchText, setSearchText] = useDebouncedSearch(query.q ?? "", (text) => {
332
440
  onQueryChange(withSearch(query, text));
333
441
  });
334
442
  const [jumpText, setJumpText] = React4.useState(() => String(currentPage));
335
443
  React4.useEffect(() => setJumpText(String(currentPage)), [currentPage]);
336
- const submitJump = (event) => {
337
- event?.preventDefault();
338
- const parsed = Number.parseInt(jumpText, 10);
339
- if (Number.isFinite(parsed) && parsed >= 1 && parsed <= totalPages) {
340
- setJumpText(String(parsed));
341
- if (parsed !== currentPage) onQueryChange(withPage(query, parsed, totalPages));
444
+ const submitJump = (raw) => {
445
+ const page = Number.parseInt(raw, 10);
446
+ if (Number.isNaN(page) || page < 1 || page > totalPages) {
447
+ setJumpText(String(currentPage));
342
448
  return;
343
449
  }
344
- setJumpText(String(currentPage));
450
+ if (page !== currentPage) {
451
+ onQueryChange(withPage(query, page, totalPages));
452
+ }
345
453
  };
346
- const toggleSort = (columnId) => {
347
- onQueryChange(withToggledSort(query, columnId));
454
+ const toggleSort = (field, multiSort = false) => {
455
+ const next = multiSort ? withToggledMultiSort(query, field) : withToggledSort(query, field);
456
+ onQueryChange(next);
348
457
  };
349
- const selectedOnPage = pageRowIds.filter((id) => selectedIds.has(id)).length;
350
- const allPageSelected = pageRowIds.length > 0 && selectedOnPage === pageRowIds.length;
351
- const somePageSelected = selectedOnPage > 0 && !allPageSelected;
352
- const commitSelection = (next) => {
458
+ const isSingleSelect = selectionMode === "single";
459
+ const allPageSelected = pageRowIds.length > 0 && pageRowIds.every((id) => selectedIds.has(id));
460
+ const somePageSelected = !allPageSelected && pageRowIds.some((id) => selectedIds.has(id));
461
+ const toggleSelectAll = () => {
462
+ if (isSingleSelect) return;
463
+ const next = new Set(selectedIds);
464
+ if (allPageSelected) {
465
+ for (const id of pageRowIds) next.delete(id);
466
+ } else {
467
+ for (const id of pageRowIds) next.add(id);
468
+ }
353
469
  setSelectedIds(next);
354
470
  onSelectionChange?.(Array.from(next), false);
355
471
  };
356
- const toggleSelectAll = () => {
357
- const next = new Set(selectedIds);
358
- for (const id of pageRowIds) {
359
- if (allPageSelected) next.delete(id);
472
+ const toggleSelectRow = (id) => {
473
+ const next = isSingleSelect ? selectedIds.has(id) ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([id]) : new Set(selectedIds);
474
+ if (!isSingleSelect) {
475
+ if (next.has(id)) next.delete(id);
360
476
  else next.add(id);
361
477
  }
362
- commitSelection(next);
478
+ setSelectedIds(next);
479
+ onSelectionChange?.(Array.from(next), false);
363
480
  };
364
- const toggleSelectRow = (id) => {
365
- const next = new Set(selectedIds);
366
- if (next.has(id)) next.delete(id);
367
- else next.add(id);
368
- commitSelection(next);
481
+ const deselectAll = () => {
482
+ setSelectedIds(/* @__PURE__ */ new Set());
483
+ onSelectionChange?.([], false);
484
+ };
485
+ const toggleExpandRow = (id) => {
486
+ setExpandedRows((prev) => {
487
+ const next = new Set(prev);
488
+ if (next.has(id)) next.delete(id);
489
+ else next.add(id);
490
+ return next;
491
+ });
369
492
  };
370
493
  const toggleColumn = (columnId) => {
371
494
  setHiddenCols((prev) => ({ ...prev, [columnId]: prev[columnId] !== true }));
372
495
  };
373
- const collectExportRows = async () => {
374
- if (data.length >= total || !fetchEndpoint) return data;
375
- notify("info", formatMessage(locale.exportFetchingAll, { total: total.toLocaleString() }));
376
- try {
377
- const result = await fetchAllPages(async (page, size) => {
378
- const url = buildQueryUrl(fetchEndpoint, {
379
- ...query,
380
- page,
381
- pageSize: isPageSize(size) ? size : query.pageSize
382
- });
383
- const response = await fetch(url, { cache: "no-store" });
384
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
385
- return await response.json();
386
- });
387
- return result.items;
388
- } catch {
389
- notify("error", locale.exportFetchFailed);
390
- return data;
391
- }
392
- };
393
496
  const handleExport = async (format) => {
394
497
  exportMenu.close();
395
498
  if (onExportAll) {
396
- void onExportAll();
499
+ try {
500
+ await onExportAll();
501
+ } catch (err) {
502
+ notify("error", err instanceof Error ? err.message : "Export failed");
503
+ }
397
504
  return;
398
505
  }
399
506
  setIsExporting(true);
507
+ notify("info", "Exporting...");
400
508
  try {
401
- const rows = await collectExportRows();
402
- if (rows.length === 0) {
403
- notify("error", locale.exportNoData);
404
- return;
509
+ let exportRows = data;
510
+ if (fetchEndpoint) {
511
+ const full = await fetchAllPages(async (page, size) => {
512
+ const url = buildQueryUrl(fetchEndpoint, {
513
+ ...query,
514
+ page,
515
+ pageSize: isPageSize(size) ? size : query.pageSize
516
+ });
517
+ const response = await fetch(url, { cache: "no-store" });
518
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
519
+ return await response.json();
520
+ });
521
+ exportRows = full.items;
405
522
  }
406
523
  const exportColumns = toExportColumns(visible, boolLabels);
407
524
  const prefix = exportFileName ?? filePrefixFromCaption(caption);
408
- if (format === "excel") {
409
- const count = downloadExcel({
525
+ if (format === "clipboard") {
526
+ const ok = await copyToClipboard(exportRows, exportColumns);
527
+ if (ok) notify("success", "Copied to clipboard");
528
+ else notify("error", "Failed to copy to clipboard");
529
+ } else if (format === "excel") {
530
+ downloadExcel({
410
531
  filename: prefix,
411
532
  caption,
412
- rows,
533
+ rows: exportRows,
413
534
  columns: exportColumns,
414
535
  badgeRules,
415
536
  serialHeader: locale.serialHeader
416
537
  });
417
- notify(
418
- "success",
419
- formatMessage(locale.exportExcelSuccess, { count: count.toLocaleString() })
420
- );
538
+ notify("success", "Excel downloaded");
421
539
  } else {
422
- const count = downloadCsv(timestampedFilename(prefix), rows, exportColumns);
423
- notify(
424
- "success",
425
- formatMessage(locale.exportCsvSuccess, { count: count.toLocaleString() })
426
- );
540
+ downloadCsv(timestampedFilename(prefix), exportRows, exportColumns);
541
+ notify("success", "CSV downloaded");
427
542
  }
543
+ } catch {
544
+ notify("error", "Export failed");
428
545
  } finally {
429
546
  setIsExporting(false);
430
547
  }
431
548
  };
432
- const rootClassName = [
433
- "nxg-root",
434
- theme === "dark" ? "nxg-dark" : theme === "auto" ? "nxg-auto" : void 0,
549
+ const rootClasses = [
550
+ "tbx-root",
551
+ theme === "dark" ? "tbx-dark" : theme === "auto" ? "tbx-auto" : void 0,
435
552
  className
436
- ].filter((part) => Boolean(part)).join(" ");
553
+ ].filter(Boolean);
437
554
  if (error) {
438
- return /* @__PURE__ */ jsx3("div", { className: rootClassName, "data-density": density, children: /* @__PURE__ */ jsxs2("div", { className: "nxg-state-card", children: [
439
- /* @__PURE__ */ jsx3("p", { className: "nxg-state-text", children: locale.errorText }),
440
- onRetry ? /* @__PURE__ */ jsx3("button", { type: "button", className: "nxg-btn", onClick: onRetry, children: locale.retryButton }) : null
555
+ return /* @__PURE__ */ jsx3("div", { className: rootClasses.join(" "), "data-density": density, children: /* @__PURE__ */ jsxs2("div", { className: "tbx-state-card", children: [
556
+ /* @__PURE__ */ jsx3("p", { className: "tbx-state-text", children: locale.errorText }),
557
+ onRetry ? /* @__PURE__ */ jsxs2("button", { type: "button", className: "tbx-btn", onClick: onRetry, children: [
558
+ /* @__PURE__ */ jsx3(RotateCcwIcon, { className: "tbx-icon" }),
559
+ /* @__PURE__ */ jsx3("span", { children: locale.retryButton })
560
+ ] }) : null
441
561
  ] }) });
442
562
  }
443
563
  const rowIsClickable = typeof onRowClick === "function";
@@ -449,56 +569,57 @@ function NexGrid({
449
569
  event.preventDefault();
450
570
  onRowClick?.(row);
451
571
  };
452
- return /* @__PURE__ */ jsxs2("div", { className: rootClassName, "data-density": density, children: [
453
- /* @__PURE__ */ jsxs2("div", { className: "nxg-toolbar", children: [
454
- /* @__PURE__ */ jsxs2("div", { className: "nxg-toolbar-group", children: [
455
- enableSearch ? /* @__PURE__ */ jsxs2("div", { className: "nxg-search", children: [
456
- /* @__PURE__ */ jsx3(SearchIcon, { className: "nxg-search-icon" }),
457
- /* @__PURE__ */ jsx3(
458
- "input",
459
- {
460
- type: "search",
461
- className: "nxg-search-input",
462
- value: searchText,
463
- onChange: (event) => setSearchText(event.target.value),
464
- placeholder: searchPlaceholder ?? locale.searchPlaceholder,
465
- "aria-label": `Search ${caption}`
466
- }
467
- ),
468
- searchText ? /* @__PURE__ */ jsxs2(
469
- "button",
470
- {
471
- type: "button",
472
- className: "nxg-search-clear",
473
- onClick: () => setSearchText(""),
474
- "aria-label": locale.clearSearch,
475
- children: [
476
- /* @__PURE__ */ jsx3(XIcon, { className: "nxg-icon" }),
477
- /* @__PURE__ */ jsx3("span", { className: "nxg-sr-only", children: locale.clearSearch })
478
- ]
479
- }
480
- ) : null
481
- ] }) : null,
482
- /* @__PURE__ */ jsxs2("div", { className: "nxg-menu-wrap", ref: columnsMenu.containerRef, children: [
572
+ const hasSummary = enableSummaryRow === true || visible.some((col) => col.meta?.aggregation !== void 0);
573
+ return /* @__PURE__ */ jsxs2("div", { className: rootClasses.join(" "), "data-density": density, ref: rootRef, children: [
574
+ showToolbar ? /* @__PURE__ */ jsxs2("div", { className: "tbx-toolbar", children: [
575
+ /* @__PURE__ */ jsx3("div", { className: "tbx-toolbar-group", children: enableSearch ? /* @__PURE__ */ jsxs2("div", { className: "tbx-search", children: [
576
+ /* @__PURE__ */ jsx3(SearchIcon, { className: "tbx-search-icon" }),
577
+ /* @__PURE__ */ jsx3(
578
+ "input",
579
+ {
580
+ type: "search",
581
+ className: "tbx-search-input",
582
+ value: searchText,
583
+ onChange: (event) => setSearchText(event.target.value),
584
+ placeholder: searchPlaceholder ?? locale.searchPlaceholder,
585
+ "aria-label": `Search ${caption}`
586
+ }
587
+ ),
588
+ searchText ? /* @__PURE__ */ jsxs2(
589
+ "button",
590
+ {
591
+ type: "button",
592
+ className: "tbx-search-clear",
593
+ onClick: () => setSearchText(""),
594
+ "aria-label": locale.clearSearch,
595
+ children: [
596
+ /* @__PURE__ */ jsx3(XIcon, { className: "tbx-icon" }),
597
+ /* @__PURE__ */ jsx3("span", { className: "tbx-sr-only", children: locale.clearSearch })
598
+ ]
599
+ }
600
+ ) : null
601
+ ] }) : null }),
602
+ /* @__PURE__ */ jsxs2("div", { className: "tbx-toolbar-group tbx-toolbar-group--end", children: [
603
+ isColumnsVisible ? /* @__PURE__ */ jsxs2("div", { className: "tbx-menu-wrap", ref: columnsMenu.containerRef, children: [
483
604
  /* @__PURE__ */ jsxs2(
484
605
  "button",
485
606
  {
486
607
  type: "button",
487
608
  id: columnsButtonId,
488
- className: "nxg-btn",
609
+ className: "tbx-btn",
489
610
  ref: columnsMenu.triggerRef,
490
611
  "aria-haspopup": "menu",
491
612
  "aria-expanded": columnsMenu.isOpen,
492
613
  onClick: columnsMenu.toggle,
493
614
  children: [
494
- /* @__PURE__ */ jsx3(SlidersIcon, { className: "nxg-icon" }),
615
+ /* @__PURE__ */ jsx3(ColumnsIcon, { className: "tbx-icon" }),
495
616
  /* @__PURE__ */ jsx3("span", { children: locale.columnsButton })
496
617
  ]
497
618
  }
498
619
  ),
499
- columnsMenu.isOpen ? /* @__PURE__ */ jsxs2("div", { className: "nxg-menu", role: "menu", "aria-labelledby": columnsButtonId, children: [
500
- /* @__PURE__ */ jsx3("div", { className: "nxg-menu-label", children: locale.toggleColumnsLabel }),
501
- /* @__PURE__ */ jsx3("div", { className: "nxg-menu-separator" }),
620
+ columnsMenu.isOpen ? /* @__PURE__ */ jsxs2("div", { className: "tbx-menu", role: "menu", "aria-labelledby": columnsButtonId, children: [
621
+ /* @__PURE__ */ jsx3("div", { className: "tbx-menu-label", children: locale.toggleColumnsLabel }),
622
+ /* @__PURE__ */ jsx3("div", { className: "tbx-menu-separator" }),
502
623
  hideable.map((col) => {
503
624
  const id = getColumnId2(col);
504
625
  const checked = hiddenCols[id] !== true;
@@ -506,12 +627,12 @@ function NexGrid({
506
627
  "button",
507
628
  {
508
629
  type: "button",
509
- className: "nxg-menu-item",
630
+ className: "tbx-menu-item",
510
631
  role: "menuitemcheckbox",
511
632
  "aria-checked": checked,
512
633
  onClick: () => toggleColumn(id),
513
634
  children: [
514
- /* @__PURE__ */ jsx3(CheckIcon, { className: "nxg-check" }),
635
+ /* @__PURE__ */ jsx3(CheckIcon, { className: "tbx-check" }),
515
636
  /* @__PURE__ */ jsx3("span", { children: getColumnTitle(col) || id })
516
637
  ]
517
638
  },
@@ -519,29 +640,29 @@ function NexGrid({
519
640
  );
520
641
  })
521
642
  ] }) : null
522
- ] }),
523
- /* @__PURE__ */ jsxs2("div", { className: "nxg-menu-wrap", ref: densityMenu.containerRef, children: [
643
+ ] }) : null,
644
+ isDensityVisible ? /* @__PURE__ */ jsxs2("div", { className: "tbx-menu-wrap", ref: densityMenu.containerRef, children: [
524
645
  /* @__PURE__ */ jsxs2(
525
646
  "button",
526
647
  {
527
648
  type: "button",
528
649
  id: densityButtonId,
529
- className: "nxg-btn nxg-capitalize",
650
+ className: "tbx-btn tbx-capitalize",
530
651
  ref: densityMenu.triggerRef,
531
652
  "aria-haspopup": "menu",
532
653
  "aria-expanded": densityMenu.isOpen,
533
654
  onClick: densityMenu.toggle,
534
655
  children: [
535
- /* @__PURE__ */ jsx3(FilterIcon, { className: "nxg-icon" }),
656
+ /* @__PURE__ */ jsx3(DensityIcon, { className: "tbx-icon" }),
536
657
  /* @__PURE__ */ jsx3("span", { children: formatMessage(locale.densityButton, { density }) })
537
658
  ]
538
659
  }
539
660
  ),
540
- densityMenu.isOpen ? /* @__PURE__ */ jsx3("div", { className: "nxg-menu", role: "menu", "aria-labelledby": densityButtonId, children: DENSITIES.map((option) => /* @__PURE__ */ jsxs2(
661
+ densityMenu.isOpen ? /* @__PURE__ */ jsx3("div", { className: "tbx-menu", role: "menu", "aria-labelledby": densityButtonId, children: DENSITIES.map((option) => /* @__PURE__ */ jsxs2(
541
662
  "button",
542
663
  {
543
664
  type: "button",
544
- className: "nxg-menu-item",
665
+ className: "tbx-menu-item",
545
666
  role: "menuitemcheckbox",
546
667
  "aria-checked": density === option,
547
668
  onClick: () => {
@@ -549,37 +670,36 @@ function NexGrid({
549
670
  densityMenu.close();
550
671
  },
551
672
  children: [
552
- /* @__PURE__ */ jsx3(CheckIcon, { className: "nxg-check" }),
673
+ /* @__PURE__ */ jsx3(CheckIcon, { className: "tbx-check" }),
553
674
  /* @__PURE__ */ jsx3("span", { children: locale[DENSITY_LABEL_KEY[option]] })
554
675
  ]
555
676
  },
556
677
  option
557
678
  )) }) : null
558
- ] })
559
- ] }),
560
- /* @__PURE__ */ jsxs2("div", { className: "nxg-toolbar-group nxg-toolbar-group--end", children: [
561
- enableExport ? /* @__PURE__ */ jsxs2("div", { className: "nxg-menu-wrap", ref: exportMenu.containerRef, children: [
679
+ ] }) : null,
680
+ isExportVisible ? /* @__PURE__ */ jsxs2("div", { className: "tbx-menu-wrap", ref: exportMenu.containerRef, children: [
562
681
  /* @__PURE__ */ jsxs2(
563
682
  "button",
564
683
  {
565
684
  type: "button",
566
685
  id: exportButtonId,
567
- className: "nxg-btn nxg-btn--export",
686
+ className: "tbx-btn tbx-btn--export",
568
687
  ref: exportMenu.triggerRef,
569
688
  disabled: isExporting,
570
689
  "aria-haspopup": "menu",
571
690
  "aria-expanded": exportMenu.isOpen,
572
691
  onClick: exportMenu.toggle,
573
692
  children: [
574
- /* @__PURE__ */ jsx3(DownloadIcon, { className: "nxg-icon" }),
575
- /* @__PURE__ */ jsx3("span", { children: isExporting ? locale.exportingButton : locale.exportButton })
693
+ /* @__PURE__ */ jsx3(DownloadTrayIcon, { className: "tbx-icon" }),
694
+ /* @__PURE__ */ jsx3("span", { children: isExporting ? locale.exportingButton : locale.exportButton }),
695
+ /* @__PURE__ */ jsx3(ChevronDownIcon, { className: "tbx-icon tbx-chevron" })
576
696
  ]
577
697
  }
578
698
  ),
579
699
  exportMenu.isOpen ? /* @__PURE__ */ jsxs2(
580
700
  "div",
581
701
  {
582
- className: "nxg-menu nxg-menu--end",
702
+ className: "tbx-menu tbx-menu--end",
583
703
  role: "menu",
584
704
  "aria-labelledby": exportButtonId,
585
705
  children: [
@@ -587,12 +707,12 @@ function NexGrid({
587
707
  "button",
588
708
  {
589
709
  type: "button",
590
- className: "nxg-menu-item",
710
+ className: "tbx-menu-item",
591
711
  role: "menuitem",
592
712
  onClick: () => void handleExport("excel"),
593
713
  children: [
594
- /* @__PURE__ */ jsx3(FileSpreadsheetIcon, { className: "nxg-icon--excel" }),
595
- /* @__PURE__ */ jsxs2("div", { className: "nxg-menu-item-title", children: [
714
+ /* @__PURE__ */ jsx3(FileSpreadsheetIcon, { className: "tbx-icon--excel" }),
715
+ /* @__PURE__ */ jsxs2("div", { className: "tbx-menu-item-title", children: [
596
716
  /* @__PURE__ */ jsx3("strong", { children: locale.exportExcelTitle }),
597
717
  /* @__PURE__ */ jsx3("small", { children: locale.exportExcelSubtitle })
598
718
  ] })
@@ -603,17 +723,33 @@ function NexGrid({
603
723
  "button",
604
724
  {
605
725
  type: "button",
606
- className: "nxg-menu-item",
726
+ className: "tbx-menu-item",
607
727
  role: "menuitem",
608
728
  onClick: () => void handleExport("csv"),
609
729
  children: [
610
- /* @__PURE__ */ jsx3(FileTextIcon, { className: "nxg-icon--csv" }),
611
- /* @__PURE__ */ jsxs2("div", { className: "nxg-menu-item-title", children: [
730
+ /* @__PURE__ */ jsx3(FileTextIcon, { className: "tbx-icon--csv" }),
731
+ /* @__PURE__ */ jsxs2("div", { className: "tbx-menu-item-title", children: [
612
732
  /* @__PURE__ */ jsx3("strong", { children: locale.exportCsvTitle }),
613
733
  /* @__PURE__ */ jsx3("small", { children: locale.exportCsvSubtitle })
614
734
  ] })
615
735
  ]
616
736
  }
737
+ ),
738
+ /* @__PURE__ */ jsxs2(
739
+ "button",
740
+ {
741
+ type: "button",
742
+ className: "tbx-menu-item",
743
+ role: "menuitem",
744
+ onClick: () => void handleExport("clipboard"),
745
+ children: [
746
+ /* @__PURE__ */ jsx3(FileTextIcon, { className: "tbx-icon--csv" }),
747
+ /* @__PURE__ */ jsxs2("div", { className: "tbx-menu-item-title", children: [
748
+ /* @__PURE__ */ jsx3("strong", { children: locale.exportClipboardTitle }),
749
+ /* @__PURE__ */ jsx3("small", { children: locale.exportClipboardSubtitle })
750
+ ] })
751
+ ]
752
+ }
617
753
  )
618
754
  ]
619
755
  }
@@ -621,137 +757,539 @@ function NexGrid({
621
757
  ] }) : null,
622
758
  toolbarActions
623
759
  ] })
624
- ] }),
625
- /* @__PURE__ */ jsx3("div", { className: "nxg-table-wrap", children: /* @__PURE__ */ jsxs2("table", { className: "nxg-table", "aria-label": caption, children: [
760
+ ] }) : null,
761
+ /* @__PURE__ */ jsx3("div", { className: "tbx-table-wrap", children: /* @__PURE__ */ jsxs2("table", { className: "tbx-table", "aria-label": caption, children: [
626
762
  /* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
627
- showSerialNumber ? /* @__PURE__ */ jsx3("th", { className: "nxg-th nxg-th--serial", scope: "col", children: locale.serialHeader }) : null,
628
- enableSelection ? /* @__PURE__ */ jsx3("th", { className: "nxg-th nxg-th--select", scope: "col", children: /* @__PURE__ */ jsx3(
629
- "input",
763
+ renderExpandedRow ? /* @__PURE__ */ jsx3(
764
+ "th",
765
+ {
766
+ className: [
767
+ "tbx-th tbx-th--expand",
768
+ leftOffsets.has("__expand") ? "tbx-th--pinned-left" : void 0,
769
+ lastLeftPinnedId === "__expand" ? "tbx-pinned-border-left" : void 0
770
+ ].filter(Boolean).join(" "),
771
+ style: {
772
+ width: "40px",
773
+ left: leftOffsets.get("__expand")
774
+ },
775
+ scope: "col"
776
+ }
777
+ ) : null,
778
+ enableSelection ? /* @__PURE__ */ jsx3(
779
+ "th",
780
+ {
781
+ className: [
782
+ "tbx-th tbx-th--select",
783
+ leftOffsets.has("__select") ? "tbx-th--pinned-left" : void 0,
784
+ lastLeftPinnedId === "__select" ? "tbx-pinned-border-left" : void 0
785
+ ].filter(Boolean).join(" "),
786
+ style: {
787
+ left: leftOffsets.get("__select")
788
+ },
789
+ scope: "col",
790
+ children: !isSingleSelect ? /* @__PURE__ */ jsx3(
791
+ "input",
792
+ {
793
+ type: "checkbox",
794
+ className: "tbx-checkbox",
795
+ checked: allPageSelected,
796
+ ref: (el) => {
797
+ if (el) el.indeterminate = somePageSelected;
798
+ },
799
+ onChange: toggleSelectAll,
800
+ "aria-label": locale.selectAllLabel
801
+ }
802
+ ) : null
803
+ }
804
+ ) : null,
805
+ showSerialNumber ? /* @__PURE__ */ jsx3(
806
+ "th",
630
807
  {
631
- type: "checkbox",
632
- className: "nxg-checkbox",
633
- checked: allPageSelected,
634
- ref: (el) => {
635
- if (el) el.indeterminate = somePageSelected;
808
+ className: [
809
+ "tbx-th tbx-th--serial",
810
+ leftOffsets.has("__serial") ? "tbx-th--pinned-left" : void 0,
811
+ lastLeftPinnedId === "__serial" ? "tbx-pinned-border-left" : void 0
812
+ ].filter(Boolean).join(" "),
813
+ style: {
814
+ left: leftOffsets.get("__serial")
636
815
  },
637
- onChange: toggleSelectAll,
638
- "aria-label": locale.selectAllLabel
816
+ scope: "col",
817
+ children: locale.serialHeader
639
818
  }
640
- ) }) : null,
819
+ ) : null,
641
820
  visible.map((col, index) => {
642
821
  const id = getColumnId2(col);
643
- const sortable = isSortable(col);
644
- const sorted = sortable && id !== "" && sort?.field === id;
822
+ const sortable = isSortable(col) && enableSorting !== false;
823
+ const sortIndex = query.sort.findIndex((s) => s.field === id);
824
+ const sortItem = sortIndex >= 0 ? query.sort[sortIndex] : void 0;
825
+ const sorted = sortable && sortItem !== void 0;
645
826
  const title = getColumnTitle(col) || id;
646
- return /* @__PURE__ */ jsx3(
827
+ const meta = col.meta;
828
+ const activeFilter = query.filter?.[id];
829
+ const isFilterActive = activeFilter !== void 0 && activeFilter !== "";
830
+ const customWidth = colWidths[id];
831
+ const baseStyle = headerCellStyle(col);
832
+ const thStyle = {
833
+ ...baseStyle,
834
+ ...customWidth !== void 0 ? { width: `${customWidth}px` } : {},
835
+ ...leftOffsets.has(id) ? { left: leftOffsets.get(id) } : {},
836
+ ...rightOffsets.has(id) ? { right: rightOffsets.get(id) } : {}
837
+ };
838
+ const startResize = (e) => {
839
+ e.preventDefault();
840
+ e.stopPropagation();
841
+ const startX = e.clientX;
842
+ const targetTh = e.currentTarget.parentElement || null;
843
+ const startWidth = targetTh ? targetTh.getBoundingClientRect().width : customWidth ?? meta?.width ?? 120;
844
+ const onMove = (moveEvent) => {
845
+ const nextW = Math.max(meta?.minWidth ?? 60, Math.round(startWidth + (moveEvent.clientX - startX)));
846
+ setColWidths((prev) => ({ ...prev, [id]: nextW }));
847
+ };
848
+ const onUp = () => {
849
+ document.removeEventListener("pointermove", onMove);
850
+ document.removeEventListener("pointerup", onUp);
851
+ document.body?.classList.remove("tbx-resizing");
852
+ };
853
+ document.body?.classList.add("tbx-resizing");
854
+ document.addEventListener("pointermove", onMove);
855
+ document.addEventListener("pointerup", onUp);
856
+ };
857
+ const isPinnedLeft = leftOffsets.has(id);
858
+ const isPinnedRight = rightOffsets.has(id);
859
+ const isLastLeft = lastLeftPinnedId === id;
860
+ const isFirstRight = firstRightPinnedId === id;
861
+ return /* @__PURE__ */ jsxs2(
647
862
  "th",
648
863
  {
649
864
  scope: "col",
650
- className: sortable ? "nxg-th nxg-th--sortable" : "nxg-th",
651
- style: headerCellStyle(col),
652
- "aria-sort": sorted ? sort?.dir === "asc" ? "ascending" : "descending" : sortable ? "none" : void 0,
865
+ className: [
866
+ "tbx-th",
867
+ sortable ? "tbx-th--sortable" : void 0,
868
+ enableColumnReorder ? "tbx-th--draggable" : void 0,
869
+ isPinnedLeft ? "tbx-th--pinned-left" : void 0,
870
+ isPinnedRight ? "tbx-th--pinned-right" : void 0,
871
+ isLastLeft ? "tbx-pinned-border-left" : void 0,
872
+ isFirstRight ? "tbx-pinned-border-right" : void 0
873
+ ].filter(Boolean).join(" "),
874
+ style: thStyle,
875
+ "aria-sort": sorted ? sortItem?.dir === "asc" ? "ascending" : "descending" : sortable ? "none" : void 0,
653
876
  "aria-label": title || void 0,
654
877
  tabIndex: sortable ? 0 : void 0,
655
- onClick: sortable ? () => toggleSort(id) : void 0,
878
+ draggable: enableColumnReorder,
879
+ onDragStart: enableColumnReorder ? (e) => {
880
+ setDraggedColId(id);
881
+ e.dataTransfer.setData("text/plain", id);
882
+ } : void 0,
883
+ onDragOver: enableColumnReorder ? (e) => {
884
+ e.preventDefault();
885
+ } : void 0,
886
+ onDrop: enableColumnReorder ? (e) => {
887
+ e.preventDefault();
888
+ if (!draggedColId || draggedColId === id) return;
889
+ const fromIdx = colList.findIndex((c) => getColumnId2(c) === draggedColId);
890
+ const toIdx = colList.findIndex((c) => getColumnId2(c) === id);
891
+ if (fromIdx >= 0 && toIdx >= 0) {
892
+ const nextCols = [...colList];
893
+ const moved = nextCols[fromIdx];
894
+ if (!moved) return;
895
+ nextCols.splice(fromIdx, 1);
896
+ nextCols.splice(toIdx, 0, moved);
897
+ setColList(nextCols);
898
+ onColumnOrderChange?.(nextCols.map(getColumnId2));
899
+ }
900
+ setDraggedColId(null);
901
+ } : void 0,
902
+ onClick: sortable ? (event) => {
903
+ const t = event.target;
904
+ if (t?.closest(".tbx-col-filter-wrap") || t?.closest(".tbx-resize-handle")) return;
905
+ toggleSort(id, event.shiftKey);
906
+ } : void 0,
656
907
  onKeyDown: sortable ? (event) => {
657
908
  if (event.key !== "Enter" && event.key !== " ") return;
909
+ const t = event.target;
910
+ if (t?.closest(".tbx-col-filter-wrap")) return;
658
911
  event.preventDefault();
659
- toggleSort(id);
912
+ toggleSort(id, event.shiftKey);
660
913
  } : void 0,
661
- children: /* @__PURE__ */ jsxs2("div", { className: headerInnerClass(col), children: [
662
- /* @__PURE__ */ jsx3("span", { children: renderColumnHeader(col) }),
663
- sortable ? /* @__PURE__ */ jsx3("span", { children: sorted ? sort?.dir === "asc" ? /* @__PURE__ */ jsx3(ArrowUpIcon, { className: "nxg-sort-icon" }) : /* @__PURE__ */ jsx3(ArrowDownIcon, { className: "nxg-sort-icon" }) : /* @__PURE__ */ jsx3(ArrowUpDownIcon, { className: "nxg-sort-icon nxg-sort-icon--idle" }) }) : null
664
- ] })
914
+ children: [
915
+ /* @__PURE__ */ jsxs2("div", { className: headerInnerClass(col), children: [
916
+ /* @__PURE__ */ jsx3("span", { children: renderColumnHeader(col) }),
917
+ sortable ? /* @__PURE__ */ jsxs2("span", { className: "tbx-sort-icon-wrap", children: [
918
+ sorted ? sortItem?.dir === "asc" ? /* @__PURE__ */ jsx3(ArrowUpIcon, { className: "tbx-sort-icon" }) : /* @__PURE__ */ jsx3(ArrowDownIcon, { className: "tbx-sort-icon" }) : /* @__PURE__ */ jsx3(ArrowUpDownIcon, { className: "tbx-sort-icon tbx-sort-icon--idle" }),
919
+ query.sort.length > 1 && sortIndex >= 0 ? /* @__PURE__ */ jsx3("span", { className: "tbx-sort-order", children: sortIndex + 1 }) : null
920
+ ] }) : null,
921
+ isFilterable(col, enableColumnFilters) ? /* @__PURE__ */ jsxs2("div", { className: "tbx-col-filter-wrap", children: [
922
+ /* @__PURE__ */ jsx3(
923
+ "button",
924
+ {
925
+ type: "button",
926
+ className: isFilterActive ? "tbx-col-filter-btn tbx-col-filter-btn--active" : "tbx-col-filter-btn",
927
+ "aria-label": `Filter ${title}`,
928
+ onClick: (e) => {
929
+ e.stopPropagation();
930
+ setOpenFilterCol(openFilterCol === id ? null : id);
931
+ },
932
+ children: /* @__PURE__ */ jsx3(DotsVerticalIcon, { className: "tbx-icon" })
933
+ }
934
+ ),
935
+ openFilterCol === id ? /* @__PURE__ */ jsxs2(
936
+ "div",
937
+ {
938
+ className: "tbx-filter-popover",
939
+ onClick: (e) => e.stopPropagation(),
940
+ children: [
941
+ /* @__PURE__ */ jsx3(
942
+ "input",
943
+ {
944
+ autoFocus: true,
945
+ type: "text",
946
+ className: "tbx-filter-popover-input",
947
+ defaultValue: activeFilter ?? "",
948
+ placeholder: meta?.filterPlaceholder || formatMessage(locale.filterColumnPlaceholder, { column: title }),
949
+ "aria-label": `Filter ${title}`,
950
+ onChange: (e) => {
951
+ const val = e.currentTarget.value.toLowerCase().trim();
952
+ const pop = e.currentTarget.closest(".tbx-filter-popover");
953
+ const opts = pop?.querySelectorAll(".tbx-filter-option:not(:first-child)");
954
+ opts?.forEach((opt) => {
955
+ const text = opt.textContent?.toLowerCase() ?? "";
956
+ opt.style.display = !val || text.includes(val) ? "" : "none";
957
+ });
958
+ },
959
+ onKeyDown: (e) => {
960
+ if (e.key === "Enter") {
961
+ e.preventDefault();
962
+ const val = e.currentTarget.value.trim();
963
+ setOpenFilterCol(null);
964
+ onQueryChange(withFilter(query, id, val || void 0));
965
+ } else if (e.key === "Escape") {
966
+ e.preventDefault();
967
+ setOpenFilterCol(null);
968
+ }
969
+ }
970
+ }
971
+ ),
972
+ meta?.filterOptions && meta.filterOptions.length > 0 ? /* @__PURE__ */ jsxs2("div", { className: "tbx-filter-popover-options", children: [
973
+ /* @__PURE__ */ jsx3(
974
+ "div",
975
+ {
976
+ className: !activeFilter ? "tbx-filter-option tbx-filter-option--selected" : "tbx-filter-option",
977
+ onClick: () => {
978
+ setOpenFilterCol(null);
979
+ onQueryChange(withFilter(query, id, void 0));
980
+ },
981
+ children: locale.filterAll
982
+ }
983
+ ),
984
+ meta.filterOptions.map((opt) => /* @__PURE__ */ jsx3(
985
+ "div",
986
+ {
987
+ className: activeFilter === opt ? "tbx-filter-option tbx-filter-option--selected" : "tbx-filter-option",
988
+ onClick: () => {
989
+ setOpenFilterCol(null);
990
+ onQueryChange(withFilter(query, id, opt));
991
+ },
992
+ children: opt
993
+ },
994
+ opt
995
+ ))
996
+ ] }) : null,
997
+ /* @__PURE__ */ jsxs2("div", { className: "tbx-filter-popover-actions", children: [
998
+ /* @__PURE__ */ jsxs2(
999
+ "button",
1000
+ {
1001
+ type: "button",
1002
+ className: "tbx-filter-popover-btn",
1003
+ onClick: (e) => {
1004
+ e.stopPropagation();
1005
+ setOpenFilterCol(null);
1006
+ onQueryChange(withFilter(query, id, void 0));
1007
+ },
1008
+ children: [
1009
+ /* @__PURE__ */ jsx3(RotateCcwIcon, { className: "tbx-icon" }),
1010
+ /* @__PURE__ */ jsx3("span", { children: locale.clearFilter })
1011
+ ]
1012
+ }
1013
+ ),
1014
+ /* @__PURE__ */ jsxs2(
1015
+ "button",
1016
+ {
1017
+ type: "button",
1018
+ className: "tbx-filter-popover-btn tbx-filter-popover-btn--primary",
1019
+ onClick: (e) => {
1020
+ e.stopPropagation();
1021
+ const parent = e.currentTarget.closest(".tbx-filter-popover");
1022
+ const inputEl = parent?.querySelector("input");
1023
+ const val = inputEl?.value.trim();
1024
+ setOpenFilterCol(null);
1025
+ onQueryChange(withFilter(query, id, val || void 0));
1026
+ },
1027
+ children: [
1028
+ /* @__PURE__ */ jsx3(CheckIcon, { className: "tbx-icon" }),
1029
+ /* @__PURE__ */ jsx3("span", { children: locale.applyFilter })
1030
+ ]
1031
+ }
1032
+ )
1033
+ ] })
1034
+ ]
1035
+ }
1036
+ ) : null
1037
+ ] }) : null
1038
+ ] }),
1039
+ enableColumnResize ? /* @__PURE__ */ jsx3("div", { className: "tbx-resize-handle", onPointerDown: startResize }) : null
1040
+ ]
665
1041
  },
666
1042
  id || `col-${index}`
667
1043
  );
668
1044
  })
669
1045
  ] }) }),
670
- /* @__PURE__ */ jsx3("tbody", { children: isLoading ? /* @__PURE__ */ jsx3("tr", { children: /* @__PURE__ */ jsxs2("td", { className: "nxg-state", colSpan: Math.max(1, columnCount), children: [
671
- /* @__PURE__ */ jsx3("span", { className: "nxg-spinner", "aria-hidden": "true" }),
672
- /* @__PURE__ */ jsx3("div", { "aria-live": "polite", children: locale.loadingText })
673
- ] }) }) : data.length === 0 ? /* @__PURE__ */ jsx3("tr", { children: /* @__PURE__ */ jsx3("td", { className: "nxg-state", colSpan: Math.max(1, columnCount), children: locale.emptyText }) }) : data.map((row, index) => {
1046
+ /* @__PURE__ */ jsx3("tbody", { children: isLoading ? /* @__PURE__ */ jsx3("tr", { children: /* @__PURE__ */ jsxs2("td", { className: "tbx-state", colSpan: Math.max(1, columnCount), children: [
1047
+ /* @__PURE__ */ jsxs2("div", { className: "tbx-dotted-loader", "aria-hidden": "true", children: [
1048
+ /* @__PURE__ */ jsx3("span", { className: "tbx-dot" }),
1049
+ /* @__PURE__ */ jsx3("span", { className: "tbx-dot" }),
1050
+ /* @__PURE__ */ jsx3("span", { className: "tbx-dot" }),
1051
+ /* @__PURE__ */ jsx3("span", { className: "tbx-dot" })
1052
+ ] }),
1053
+ /* @__PURE__ */ jsx3("div", { className: "tbx-loading-text", "aria-live": "polite", children: locale.loadingText })
1054
+ ] }) }) : data.length === 0 ? /* @__PURE__ */ jsx3("tr", { children: /* @__PURE__ */ jsx3("td", { className: "tbx-state", colSpan: Math.max(1, columnCount), children: locale.emptyText }) }) : data.map((row, index) => {
674
1055
  const id = pageRowIds[index] ?? String(index);
675
1056
  const isSelected = selectedIds.has(id);
676
- return /* @__PURE__ */ jsxs2(
677
- "tr",
678
- {
679
- className: [
680
- "nxg-row",
681
- isSelected ? "nxg-row--selected" : void 0,
682
- rowIsClickable ? "nxg-row--clickable" : void 0
683
- ].filter(Boolean).join(" "),
684
- onClick: rowIsClickable ? activateRow(row) : void 0,
685
- onKeyDown: rowIsClickable ? rowKeyDown(row) : void 0,
686
- tabIndex: rowIsClickable ? 0 : void 0,
687
- children: [
688
- showSerialNumber ? /* @__PURE__ */ jsx3("td", { className: "nxg-td nxg-td--serial", children: serialNumber(currentPage, pageSize, index) }) : null,
689
- enableSelection ? /* @__PURE__ */ jsx3(
690
- "td",
691
- {
692
- className: "nxg-td nxg-td--select",
693
- onClick: (event) => event.stopPropagation(),
694
- children: /* @__PURE__ */ jsx3(
695
- "input",
1057
+ const isExpanded = expandedRows.has(id);
1058
+ return /* @__PURE__ */ jsxs2(React4.Fragment, { children: [
1059
+ /* @__PURE__ */ jsxs2(
1060
+ "tr",
1061
+ {
1062
+ className: [
1063
+ "tbx-row",
1064
+ isSelected ? "tbx-row--selected" : void 0,
1065
+ isExpanded ? "tbx-row--expanded" : void 0,
1066
+ rowIsClickable ? "tbx-row--clickable" : void 0
1067
+ ].filter(Boolean).join(" "),
1068
+ onClick: rowIsClickable ? activateRow(row) : void 0,
1069
+ onKeyDown: rowIsClickable ? rowKeyDown(row) : void 0,
1070
+ tabIndex: rowIsClickable ? 0 : void 0,
1071
+ children: [
1072
+ renderExpandedRow ? /* @__PURE__ */ jsx3(
1073
+ "td",
1074
+ {
1075
+ className: [
1076
+ "tbx-td tbx-td--expand",
1077
+ leftOffsets.has("__expand") ? "tbx-td--pinned-left" : void 0,
1078
+ lastLeftPinnedId === "__expand" ? "tbx-pinned-border-left" : void 0
1079
+ ].filter(Boolean).join(" "),
1080
+ style: {
1081
+ width: "40px",
1082
+ left: leftOffsets.get("__expand")
1083
+ },
1084
+ onClick: (e) => e.stopPropagation(),
1085
+ children: /* @__PURE__ */ jsx3(
1086
+ "button",
1087
+ {
1088
+ type: "button",
1089
+ className: isExpanded ? "tbx-expand-btn tbx-expand-btn--open" : "tbx-expand-btn",
1090
+ "aria-label": isExpanded ? "Collapse row" : "Expand row",
1091
+ onClick: (e) => {
1092
+ e.stopPropagation();
1093
+ toggleExpandRow(id);
1094
+ },
1095
+ children: /* @__PURE__ */ jsx3(ChevronRightIcon, { className: "tbx-icon" })
1096
+ }
1097
+ )
1098
+ }
1099
+ ) : null,
1100
+ enableSelection ? /* @__PURE__ */ jsx3(
1101
+ "td",
1102
+ {
1103
+ className: [
1104
+ "tbx-td tbx-td--select",
1105
+ leftOffsets.has("__select") ? "tbx-td--pinned-left" : void 0,
1106
+ lastLeftPinnedId === "__select" ? "tbx-pinned-border-left" : void 0
1107
+ ].filter(Boolean).join(" "),
1108
+ style: {
1109
+ left: leftOffsets.get("__select")
1110
+ },
1111
+ onClick: (event) => event.stopPropagation(),
1112
+ children: /* @__PURE__ */ jsx3(
1113
+ "input",
1114
+ {
1115
+ type: isSingleSelect ? "radio" : "checkbox",
1116
+ name: isSingleSelect ? `${instanceId}-select` : void 0,
1117
+ className: "tbx-checkbox",
1118
+ checked: isSelected,
1119
+ onChange: () => toggleSelectRow(id),
1120
+ onClick: (event) => event.stopPropagation(),
1121
+ "aria-label": formatMessage(locale.selectRowLabel, { id })
1122
+ }
1123
+ )
1124
+ }
1125
+ ) : null,
1126
+ showSerialNumber ? /* @__PURE__ */ jsx3(
1127
+ "td",
1128
+ {
1129
+ className: [
1130
+ "tbx-td tbx-td--serial",
1131
+ leftOffsets.has("__serial") ? "tbx-td--pinned-left" : void 0,
1132
+ lastLeftPinnedId === "__serial" ? "tbx-pinned-border-left" : void 0
1133
+ ].filter(Boolean).join(" "),
1134
+ style: {
1135
+ left: leftOffsets.get("__serial")
1136
+ },
1137
+ children: serialNumber(currentPage, pageSize, index)
1138
+ }
1139
+ ) : null,
1140
+ visible.map((col, colIndex) => {
1141
+ const colId = getColumnId2(col);
1142
+ const isPinnedLeft = leftOffsets.has(colId);
1143
+ const isPinnedRight = rightOffsets.has(colId);
1144
+ const isLastLeft = lastLeftPinnedId === colId;
1145
+ const isFirstRight = firstRightPinnedId === colId;
1146
+ const isCellEditable = isEditable(col);
1147
+ const isCurrentlyEditing = editingCell?.rowId === id && editingCell?.columnId === colId;
1148
+ const tdStyle = {
1149
+ ...bodyCellStyle(col),
1150
+ ...isPinnedLeft ? { left: leftOffsets.get(colId) } : {},
1151
+ ...isPinnedRight ? { right: rightOffsets.get(colId) } : {}
1152
+ };
1153
+ return /* @__PURE__ */ jsx3(
1154
+ "td",
696
1155
  {
697
- type: "checkbox",
698
- className: "nxg-checkbox",
699
- checked: isSelected,
700
- onChange: () => toggleSelectRow(id),
701
- onClick: (event) => event.stopPropagation(),
702
- "aria-label": formatMessage(locale.selectRowLabel, { id })
703
- }
704
- )
705
- }
706
- ) : null,
707
- visible.map((col, colIndex) => /* @__PURE__ */ jsx3(
708
- "td",
709
- {
710
- className: "nxg-td",
711
- style: bodyCellStyle(col),
712
- children: renderCellContent(col, row, boolLabels)
713
- },
714
- getColumnId2(col) || `col-${colIndex}`
715
- ))
716
- ]
717
- },
718
- id || index
719
- );
1156
+ className: [
1157
+ "tbx-td",
1158
+ isCellEditable ? "tbx-cell--editable" : void 0,
1159
+ isPinnedLeft ? "tbx-td--pinned-left" : void 0,
1160
+ isPinnedRight ? "tbx-td--pinned-right" : void 0,
1161
+ isLastLeft ? "tbx-pinned-border-left" : void 0,
1162
+ isFirstRight ? "tbx-pinned-border-right" : void 0
1163
+ ].filter(Boolean).join(" "),
1164
+ style: tdStyle,
1165
+ onDoubleClick: isCellEditable ? (e) => {
1166
+ e.stopPropagation();
1167
+ setEditingCell({ rowId: id, columnId: colId });
1168
+ } : void 0,
1169
+ children: isCurrentlyEditing ? /* @__PURE__ */ jsxs2(
1170
+ "div",
1171
+ {
1172
+ className: "tbx-cell-edit-wrap",
1173
+ onClick: (e) => e.stopPropagation(),
1174
+ children: [
1175
+ col.meta?.editType === "select" && col.meta.editOptions ? /* @__PURE__ */ jsx3(
1176
+ "select",
1177
+ {
1178
+ autoFocus: true,
1179
+ className: "tbx-cell-edit-select tbx-cell-edit-input",
1180
+ defaultValue: String(row[colId] ?? ""),
1181
+ id: `${instanceId}-edit-${id}-${colId}`,
1182
+ children: col.meta.editOptions.map((opt) => /* @__PURE__ */ jsx3("option", { value: opt, children: opt }, opt))
1183
+ }
1184
+ ) : /* @__PURE__ */ jsx3(
1185
+ "input",
1186
+ {
1187
+ autoFocus: true,
1188
+ type: col.meta?.editType === "number" ? "number" : "text",
1189
+ className: "tbx-cell-edit-input",
1190
+ defaultValue: String(row[colId] ?? ""),
1191
+ id: `${instanceId}-edit-${id}-${colId}`,
1192
+ onKeyDown: (e) => {
1193
+ if (e.key === "Enter") {
1194
+ e.preventDefault();
1195
+ const el = e.currentTarget;
1196
+ const val = col.meta?.editType === "number" ? Number(el.value) : el.value;
1197
+ const oldVal = row[colId];
1198
+ row[colId] = val;
1199
+ onCellEdit?.({ row, columnId: colId, oldValue: oldVal, newValue: val });
1200
+ setEditingCell(null);
1201
+ } else if (e.key === "Escape") {
1202
+ e.preventDefault();
1203
+ setEditingCell(null);
1204
+ }
1205
+ }
1206
+ }
1207
+ ),
1208
+ /* @__PURE__ */ jsxs2("div", { className: "tbx-cell-edit-actions", children: [
1209
+ /* @__PURE__ */ jsx3(
1210
+ "button",
1211
+ {
1212
+ type: "button",
1213
+ className: "tbx-cell-edit-btn tbx-cell-edit-btn--save",
1214
+ onClick: (e) => {
1215
+ e.stopPropagation();
1216
+ const el = document.getElementById(`${instanceId}-edit-${id}-${colId}`);
1217
+ if (el) {
1218
+ const val = col.meta?.editType === "number" ? Number(el.value) : el.value;
1219
+ const oldVal = row[colId];
1220
+ row[colId] = val;
1221
+ onCellEdit?.({ row, columnId: colId, oldValue: oldVal, newValue: val });
1222
+ }
1223
+ setEditingCell(null);
1224
+ },
1225
+ children: /* @__PURE__ */ jsx3(CheckIcon, { className: "tbx-icon" })
1226
+ }
1227
+ ),
1228
+ /* @__PURE__ */ jsx3(
1229
+ "button",
1230
+ {
1231
+ type: "button",
1232
+ className: "tbx-cell-edit-btn tbx-cell-edit-btn--cancel",
1233
+ onClick: (e) => {
1234
+ e.stopPropagation();
1235
+ setEditingCell(null);
1236
+ },
1237
+ children: /* @__PURE__ */ jsx3(XIcon, { className: "tbx-icon" })
1238
+ }
1239
+ )
1240
+ ] })
1241
+ ]
1242
+ }
1243
+ ) : renderCellContent(col, row, boolLabels)
1244
+ },
1245
+ colId || `col-${colIndex}`
1246
+ );
1247
+ })
1248
+ ]
1249
+ }
1250
+ ),
1251
+ isExpanded && renderExpandedRow ? /* @__PURE__ */ jsx3("tr", { className: "tbx-expanded-row", children: /* @__PURE__ */ jsx3("td", { className: "tbx-expanded-cell", colSpan: columnCount, children: /* @__PURE__ */ jsx3("div", { className: "tbx-detail-panel", children: renderExpandedRow(row) }) }) }) : null
1252
+ ] }, id || index);
720
1253
  }) })
721
1254
  ] }) }),
722
- /* @__PURE__ */ jsx3("div", { className: "nxg-cards", children: isLoading ? /* @__PURE__ */ jsx3("div", { className: "nxg-card", children: /* @__PURE__ */ jsxs2("div", { className: "nxg-state", children: [
723
- /* @__PURE__ */ jsx3("span", { className: "nxg-spinner", "aria-hidden": "true" }),
724
- /* @__PURE__ */ jsx3("div", { "aria-live": "polite", children: locale.loadingText })
725
- ] }) }) : data.length === 0 ? /* @__PURE__ */ jsx3("div", { className: "nxg-card", children: /* @__PURE__ */ jsx3("div", { className: "nxg-state", children: locale.emptyText }) }) : data.map((row, index) => {
1255
+ /* @__PURE__ */ jsx3("div", { className: "tbx-cards", children: isLoading ? /* @__PURE__ */ jsx3("div", { className: "tbx-card", children: /* @__PURE__ */ jsxs2("div", { className: "tbx-state", children: [
1256
+ /* @__PURE__ */ jsxs2("div", { className: "tbx-dotted-loader", "aria-hidden": "true", children: [
1257
+ /* @__PURE__ */ jsx3("span", { className: "tbx-dot" }),
1258
+ /* @__PURE__ */ jsx3("span", { className: "tbx-dot" }),
1259
+ /* @__PURE__ */ jsx3("span", { className: "tbx-dot" }),
1260
+ /* @__PURE__ */ jsx3("span", { className: "tbx-dot" })
1261
+ ] }),
1262
+ /* @__PURE__ */ jsx3("div", { className: "tbx-loading-text", "aria-live": "polite", children: locale.loadingText })
1263
+ ] }) }) : data.length === 0 ? /* @__PURE__ */ jsx3("div", { className: "tbx-card", children: /* @__PURE__ */ jsx3("div", { className: "tbx-state", children: locale.emptyText }) }) : data.map((row, index) => {
726
1264
  const id = pageRowIds[index] ?? String(index);
727
1265
  const isSelected = selectedIds.has(id);
728
1266
  return /* @__PURE__ */ jsxs2(
729
1267
  "div",
730
1268
  {
731
1269
  className: [
732
- "nxg-card",
733
- isSelected ? "nxg-card--selected" : void 0,
734
- rowIsClickable ? "nxg-card--clickable" : void 0
1270
+ "tbx-card",
1271
+ isSelected ? "tbx-card--selected" : void 0,
1272
+ rowIsClickable ? "tbx-card--clickable" : void 0
735
1273
  ].filter(Boolean).join(" "),
736
1274
  onClick: rowIsClickable ? activateRow(row) : void 0,
737
1275
  onKeyDown: rowIsClickable ? rowKeyDown(row) : void 0,
738
1276
  tabIndex: rowIsClickable ? 0 : void 0,
739
1277
  children: [
740
- showSerialNumber || enableSelection ? /* @__PURE__ */ jsxs2("div", { className: "nxg-card-head", children: [
741
- showSerialNumber ? /* @__PURE__ */ jsxs2("span", { className: "nxg-card-serial", children: [
1278
+ showSerialNumber || enableSelection ? /* @__PURE__ */ jsxs2("div", { className: "tbx-card-head", children: [
1279
+ showSerialNumber ? /* @__PURE__ */ jsxs2("span", { className: "tbx-card-serial", children: [
742
1280
  "#",
743
1281
  serialNumber(currentPage, pageSize, index)
744
1282
  ] }) : null,
745
1283
  enableSelection ? /* @__PURE__ */ jsx3(
746
1284
  "span",
747
1285
  {
748
- className: "nxg-card-select",
1286
+ className: "tbx-card-select",
749
1287
  onClick: (event) => event.stopPropagation(),
750
1288
  children: /* @__PURE__ */ jsx3(
751
1289
  "input",
752
1290
  {
753
1291
  type: "checkbox",
754
- className: "nxg-checkbox",
1292
+ className: "tbx-checkbox",
755
1293
  checked: isSelected,
756
1294
  onChange: () => toggleSelectRow(id),
757
1295
  onClick: (event) => event.stopPropagation(),
@@ -761,9 +1299,9 @@ function NexGrid({
761
1299
  }
762
1300
  ) : null
763
1301
  ] }) : null,
764
- /* @__PURE__ */ jsx3("dl", { className: "nxg-card-rows", children: visible.map((col, colIndex) => {
1302
+ /* @__PURE__ */ jsx3("dl", { className: "tbx-card-rows", children: visible.map((col, colIndex) => {
765
1303
  const colId = getColumnId2(col);
766
- return /* @__PURE__ */ jsxs2("div", { className: "nxg-card-row", children: [
1304
+ return /* @__PURE__ */ jsxs2("div", { className: "tbx-card-row", children: [
767
1305
  /* @__PURE__ */ jsx3("dt", { children: getColumnTitle(col) || colId }),
768
1306
  /* @__PURE__ */ jsx3("dd", { children: renderCellContent(col, row, boolLabels) })
769
1307
  ] }, colId || `col-${colIndex}`);
@@ -773,52 +1311,55 @@ function NexGrid({
773
1311
  id || index
774
1312
  );
775
1313
  }) }),
776
- /* @__PURE__ */ jsxs2("div", { className: "nxg-footer", children: [
777
- /* @__PURE__ */ jsxs2("div", { className: "nxg-range", children: [
1314
+ showFooter ? /* @__PURE__ */ jsxs2("div", { className: "tbx-footer", children: [
1315
+ /* @__PURE__ */ jsxs2("div", { className: "tbx-range", children: [
778
1316
  /* @__PURE__ */ jsx3("span", { children: renderTemplate(locale.showingRange, {
779
1317
  start: /* @__PURE__ */ jsx3("strong", { children: range.start }),
780
1318
  end: /* @__PURE__ */ jsx3("strong", { children: range.end }),
781
- total: /* @__PURE__ */ jsx3("strong", { className: "nxg-range-total", children: total.toLocaleString() })
1319
+ total: /* @__PURE__ */ jsx3("strong", { className: "tbx-range-total", children: total.toLocaleString() })
782
1320
  }) }),
783
- selectedIds.size > 0 ? /* @__PURE__ */ jsx3("span", { className: "nxg-selected-badge", children: formatMessage(locale.selectedBadge, { count: selectedIds.size }) }) : null
1321
+ selectedIds.size > 0 ? /* @__PURE__ */ jsx3("span", { className: "tbx-selected-badge", children: formatMessage(locale.selectedBadge, { count: selectedIds.size }) }) : null
784
1322
  ] }),
785
- /* @__PURE__ */ jsxs2("div", { className: "nxg-pagination", children: [
786
- /* @__PURE__ */ jsxs2("div", { className: "nxg-rows-per-page", children: [
1323
+ /* @__PURE__ */ jsxs2("div", { className: "tbx-pagination", children: [
1324
+ isRowsPerPageVisible ? /* @__PURE__ */ jsxs2("div", { className: "tbx-rows-per-page", children: [
787
1325
  /* @__PURE__ */ jsx3("span", { children: locale.rowsPerPage }),
788
1326
  /* @__PURE__ */ jsx3(
789
1327
  "select",
790
1328
  {
791
- className: "nxg-rows-select",
1329
+ className: "tbx-rows-select",
792
1330
  value: String(pageSize),
793
1331
  onChange: (event) => {
794
1332
  onQueryChange(withPageSize(query, Number.parseInt(event.target.value, 10)));
795
1333
  },
796
1334
  "aria-label": locale.rowsPerPage,
797
- children: PAGE_SIZES.map((size) => /* @__PURE__ */ jsx3("option", { value: size, children: size }, size))
1335
+ children: PAGE_SIZES.map((size) => /* @__PURE__ */ jsxs2("option", { value: size, children: [
1336
+ size,
1337
+ " rows"
1338
+ ] }, size))
798
1339
  }
799
1340
  )
800
- ] }),
801
- /* @__PURE__ */ jsxs2("div", { className: "nxg-pager", children: [
1341
+ ] }) : null,
1342
+ isPaginationVisible ? /* @__PURE__ */ jsxs2("div", { className: "tbx-pager", children: [
802
1343
  /* @__PURE__ */ jsxs2(
803
1344
  "button",
804
1345
  {
805
1346
  type: "button",
806
- className: "nxg-page-nav",
1347
+ className: "tbx-page-nav",
807
1348
  disabled: currentPage <= 1,
808
1349
  onClick: () => onQueryChange(withPage(query, currentPage - 1, totalPages)),
809
1350
  "aria-label": locale.previousPage,
810
1351
  children: [
811
1352
  /* @__PURE__ */ jsx3(ChevronLeftIcon, { size: 16 }),
812
- /* @__PURE__ */ jsx3("span", { className: "nxg-sr-only", children: locale.previousPage })
1353
+ /* @__PURE__ */ jsx3("span", { className: "tbx-sr-only", children: locale.previousPage })
813
1354
  ]
814
1355
  }
815
1356
  ),
816
1357
  pageItems.map(
817
- (item, index) => item === "..." ? /* @__PURE__ */ jsx3("span", { className: "nxg-page-ellipsis", children: "\u2026" }, `gap-${index}`) : /* @__PURE__ */ jsx3(
1358
+ (item, index) => item === "..." ? /* @__PURE__ */ jsx3("span", { className: "tbx-page-ellipsis", children: "\u2026" }, `gap-${index}`) : /* @__PURE__ */ jsx3(
818
1359
  "button",
819
1360
  {
820
1361
  type: "button",
821
- className: item === currentPage ? "nxg-page-btn nxg-page-btn--current" : "nxg-page-btn",
1362
+ className: item === currentPage ? "tbx-page-btn tbx-page-btn--current" : "tbx-page-btn",
822
1363
  onClick: () => onQueryChange(withPage(query, item, totalPages)),
823
1364
  "aria-label": formatMessage(locale.pageLabel, { page: item }),
824
1365
  "aria-current": item === currentPage ? "page" : void 0,
@@ -831,46 +1372,57 @@ function NexGrid({
831
1372
  "button",
832
1373
  {
833
1374
  type: "button",
834
- className: "nxg-page-nav",
1375
+ className: "tbx-page-nav",
835
1376
  disabled: currentPage >= totalPages,
836
1377
  onClick: () => onQueryChange(withPage(query, currentPage + 1, totalPages)),
837
1378
  "aria-label": locale.nextPage,
838
1379
  children: [
839
1380
  /* @__PURE__ */ jsx3(ChevronRightIcon, { size: 16 }),
840
- /* @__PURE__ */ jsx3("span", { className: "nxg-sr-only", children: locale.nextPage })
1381
+ /* @__PURE__ */ jsx3("span", { className: "tbx-sr-only", children: locale.nextPage })
841
1382
  ]
842
1383
  }
843
1384
  )
844
- ] }),
845
- /* @__PURE__ */ jsxs2("form", { className: "nxg-jump", onSubmit: submitJump, children: [
846
- /* @__PURE__ */ jsx3("label", { className: "nxg-jump-label", htmlFor: jumpInputId, children: locale.goToPage }),
847
- /* @__PURE__ */ jsx3(
848
- "input",
849
- {
850
- id: jumpInputId,
851
- type: "number",
852
- className: "nxg-jump-input",
853
- min: 1,
854
- max: totalPages,
855
- value: jumpText,
856
- onChange: (event) => setJumpText(event.target.value),
857
- onBlur: () => submitJump(),
858
- "aria-label": locale.goToPageOf
859
- }
860
- )
861
- ] })
1385
+ ] }) : null,
1386
+ isJumpToPageVisible ? /* @__PURE__ */ jsxs2(
1387
+ "form",
1388
+ {
1389
+ className: "tbx-jump",
1390
+ onSubmit: (event) => {
1391
+ event.preventDefault();
1392
+ submitJump(jumpText);
1393
+ },
1394
+ children: [
1395
+ /* @__PURE__ */ jsx3("label", { className: "tbx-jump-label", htmlFor: jumpInputId, children: locale.goToPage }),
1396
+ /* @__PURE__ */ jsx3(
1397
+ "input",
1398
+ {
1399
+ id: jumpInputId,
1400
+ type: "number",
1401
+ className: "tbx-jump-input",
1402
+ min: 1,
1403
+ max: totalPages,
1404
+ value: jumpText,
1405
+ onChange: (event) => setJumpText(event.target.value),
1406
+ onBlur: () => submitJump(jumpText),
1407
+ "aria-label": locale.goToPageOf
1408
+ }
1409
+ )
1410
+ ]
1411
+ }
1412
+ ) : null
862
1413
  ] })
863
- ] })
1414
+ ] }) : null
864
1415
  ] });
865
1416
  }
1417
+ var NexGrid = TableX;
866
1418
 
867
- // src/use-client-nex-grid.ts
1419
+ // src/use-client-table-x.ts
868
1420
  import { useMemo as useMemo2, useState as useState4 } from "react";
869
1421
  import {
870
1422
  defaultQuery,
871
1423
  queryClientData
872
1424
  } from "@nexgrid/core";
873
- function useClientNexGrid(allData, options) {
1425
+ function useClientTableX(allData, options) {
874
1426
  const [query, setQuery] = useState4(() => ({
875
1427
  ...defaultQuery(),
876
1428
  ...options?.initialQuery
@@ -890,6 +1442,7 @@ function useClientNexGrid(allData, options) {
890
1442
  setQuery
891
1443
  };
892
1444
  }
1445
+ var useClientNexGrid = useClientTableX;
893
1446
 
894
1447
  // src/index.ts
895
1448
  import {
@@ -903,11 +1456,12 @@ import {
903
1456
  fromODataResponse,
904
1457
  primarySort as primarySort2,
905
1458
  withToggledSort as withToggledSort2,
1459
+ withToggledMultiSort as withToggledMultiSort2,
906
1460
  withSort,
907
1461
  withSearch as withSearch2,
908
1462
  withPage as withPage2,
909
1463
  withPageSize as withPageSize2,
910
- withFilter,
1464
+ withFilter as withFilter2,
911
1465
  totalPagesFor as totalPagesFor2,
912
1466
  isPageSize as isPageSize2,
913
1467
  PAGE_SIZES as PAGE_SIZES2,
@@ -920,6 +1474,7 @@ export {
920
1474
  DEFAULT_PAGE_SIZE,
921
1475
  NexGrid,
922
1476
  PAGE_SIZES2 as PAGE_SIZES,
1477
+ TableX,
923
1478
  buildODataUrl,
924
1479
  buildQueryUrl2 as buildQueryUrl,
925
1480
  defaultQuery2 as defaultQuery,
@@ -933,11 +1488,13 @@ export {
933
1488
  toODataParams,
934
1489
  totalPagesFor2 as totalPagesFor,
935
1490
  useClientNexGrid,
936
- withFilter,
1491
+ useClientTableX,
1492
+ withFilter2 as withFilter,
937
1493
  withPage2 as withPage,
938
1494
  withPageSize2 as withPageSize,
939
1495
  withSearch2 as withSearch,
940
1496
  withSort,
1497
+ withToggledMultiSort2 as withToggledMultiSort,
941
1498
  withToggledSort2 as withToggledSort
942
1499
  };
943
1500
  //# sourceMappingURL=index.js.map