boneless-table 0.1.1 → 0.1.2

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
@@ -271,7 +271,7 @@ function resolveColumnSettings(settings, column) {
271
271
  const configured = (_a = column.columnDef.meta) == null ? void 0 : _a.bonelessTable;
272
272
  const configuredSizing = configured == null ? void 0 : configured.sizing;
273
273
  return {
274
- sizing: configuredSizing && "widthPx" in configuredSizing ? { widthPx: configuredSizing.widthPx } : __spreadValues(__spreadValues({}, settings.columnDefaults.sizing), configuredSizing),
274
+ sizing: (configuredSizing == null ? void 0 : configuredSizing.widthPx) != null && configuredSizing.minPx == null && configuredSizing.maxPx == null && configuredSizing.flex == null && configuredSizing.resizable == null ? { widthPx: configuredSizing.widthPx } : __spreadValues(__spreadValues({}, settings.columnDefaults.sizing), configuredSizing),
275
275
  align: (_b = configured == null ? void 0 : configured.align) != null ? _b : settings.columnDefaults.align,
276
276
  borders: (_c = configured == null ? void 0 : configured.borders) != null ? _c : settings.columnDefaults.borders,
277
277
  sorting: __spreadValues(__spreadValues({}, settings.columnDefaults.sorting), configured == null ? void 0 : configured.sorting),
@@ -455,11 +455,13 @@ function BonelessTable(_a) {
455
455
  const defaultOrder = (0, import_react3.useMemo)(() => getColumnIds(resolvedColumns), [resolvedColumns]);
456
456
  const scrollerRef = (0, import_react3.useRef)(null);
457
457
  const headerScrollerRef = (0, import_react3.useRef)(null);
458
+ const rootRef = (0, import_react3.useRef)(null);
458
459
  const lastScrollLeftRef = (0, import_react3.useRef)(0);
459
460
  const columnsButtonRef = (0, import_react3.useRef)(null);
460
461
  const nearEndTriggeredRef = (0, import_react3.useRef)(false);
461
462
  const columnMenuId = (0, import_react3.useId)();
462
463
  const [showColumns, setShowColumns] = (0, import_react3.useState)(false);
464
+ const [headerScrollbarInset, setHeaderScrollbarInset] = (0, import_react3.useState)(0);
463
465
  const [sorting, setSorting] = (0, import_react3.useState)((_b2 = (_a2 = tableOptions.initialState) == null ? void 0 : _a2.sorting) != null ? _b2 : []);
464
466
  const [columnFilters, setColumnFilters] = (0, import_react3.useState)(
465
467
  (_d = (_c = tableOptions.initialState) == null ? void 0 : _c.columnFilters) != null ? _d : []
@@ -471,6 +473,7 @@ function BonelessTable(_a) {
471
473
  (_h = (_g = tableOptions.initialState) == null ? void 0 : _g.columnOrder) != null ? _h : defaultOrder
472
474
  );
473
475
  const [expanded, setExpanded] = (0, import_react3.useState)((_j = (_i = tableOptions.initialState) == null ? void 0 : _i.expanded) != null ? _j : {});
476
+ const [columnSizing, setColumnSizing] = (0, import_react3.useState)({});
474
477
  const _k = tableOptions, {
475
478
  state: controlledState,
476
479
  onSortingChange,
@@ -502,8 +505,28 @@ function BonelessTable(_a) {
502
505
  ]);
503
506
  (0, import_react3.useEffect)(() => {
504
507
  var _a3;
505
- if (scrollToTopOn !== void 0) (_a3 = scrollerRef.current) == null ? void 0 : _a3.scrollTo({ top: 0 });
508
+ if (scrollToTopOn !== void 0) {
509
+ nearEndTriggeredRef.current = false;
510
+ (_a3 = scrollerRef.current) == null ? void 0 : _a3.scrollTo({ top: 0 });
511
+ }
506
512
  }, [scrollToTopOn]);
513
+ (0, import_react3.useEffect)(() => {
514
+ const scrollerElement = scrollerRef.current;
515
+ if (!scrollerElement) return;
516
+ const syncHeaderScrollbarInset = () => {
517
+ setHeaderScrollbarInset(
518
+ Math.max(0, scrollerElement.offsetWidth - scrollerElement.clientWidth)
519
+ );
520
+ };
521
+ syncHeaderScrollbarInset();
522
+ const resizeObserver = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(syncHeaderScrollbarInset);
523
+ resizeObserver == null ? void 0 : resizeObserver.observe(scrollerElement);
524
+ window.addEventListener("resize", syncHeaderScrollbarInset);
525
+ return () => {
526
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
527
+ window.removeEventListener("resize", syncHeaderScrollbarInset);
528
+ };
529
+ }, []);
507
530
  const table = (0, import_react_table.useReactTable)(__spreadProps(__spreadValues({}, restTableOptions), {
508
531
  data,
509
532
  columns: resolvedColumns,
@@ -538,18 +561,33 @@ function BonelessTable(_a) {
538
561
  var _a3;
539
562
  return (_a3 = columnSettingsById.get(column.id)) != null ? _a3 : resolveColumnSettings(settings, column);
540
563
  };
564
+ const columnResizeVariables = (0, import_react3.useMemo)(
565
+ () => new Map(
566
+ allColumns.map((column, index) => [column.id, `--boneless-table-column-${index}-width`])
567
+ ),
568
+ [allColumns]
569
+ );
570
+ const getColumnResizeVariable = (columnId) => {
571
+ var _a3;
572
+ return (_a3 = columnResizeVariables.get(columnId)) != null ? _a3 : `--boneless-table-column-${columnId}-width`;
573
+ };
541
574
  const grid = visibleColumns.map((column) => {
575
+ var _a3, _b3, _c2;
542
576
  const columnSettings = getColumnSettings(column);
543
- if ("widthPx" in columnSettings.sizing) return `${columnSettings.sizing.widthPx}px`;
544
- return `minmax(${columnSettings.sizing.minPx}px, ${columnSettings.sizing.flex}fr)`;
577
+ const { sizing } = columnSettings;
578
+ const width = (_a3 = columnSizing[column.id]) != null ? _a3 : sizing.widthPx;
579
+ const track = width != null ? `${width}px` : `minmax(${(_b3 = sizing.minPx) != null ? _b3 : settings.columnDefaults.sizing.minPx}px, ${(_c2 = sizing.flex) != null ? _c2 : settings.columnDefaults.sizing.flex}fr)`;
580
+ return `var(${getColumnResizeVariable(column.id)}, ${track})`;
545
581
  }).join(" ");
546
582
  const minWidth = visibleColumns.reduce((width, column) => {
583
+ var _a3, _b3;
547
584
  const { sizing } = getColumnSettings(column);
548
- return width + ("widthPx" in sizing ? sizing.widthPx : sizing.minPx);
585
+ const configuredWidth = (_a3 = columnSizing[column.id]) != null ? _a3 : sizing.widthPx;
586
+ return width + ((_b3 = configuredWidth != null ? configuredWidth : sizing.minPx) != null ? _b3 : settings.columnDefaults.sizing.minPx);
549
587
  }, 0);
550
588
  const gridStyle = {
551
589
  "--boneless-table-grid": grid,
552
- minWidth: `${minWidth}px`
590
+ minWidth: `var(--boneless-table-min-width, ${minWidth}px)`
553
591
  };
554
592
  const tree = treeOption === true ? {} : treeOption === false ? void 0 : treeOption;
555
593
  const treeColumnId = (_m = tree == null ? void 0 : tree.columnId) != null ? _m : (_l = visibleColumns[0]) == null ? void 0 : _l.id;
@@ -567,8 +605,8 @@ function BonelessTable(_a) {
567
605
  [expandableRows, expanded]
568
606
  );
569
607
  (0, import_react3.useEffect)(() => {
570
- if (!isFetchingMore || !canLoadMore) nearEndTriggeredRef.current = false;
571
- }, [canLoadMore, isFetchingMore]);
608
+ if (!canLoadMore) nearEndTriggeredRef.current = false;
609
+ }, [canLoadMore]);
572
610
  function handleScroll() {
573
611
  const element = scrollerRef.current;
574
612
  if (!element) return;
@@ -587,12 +625,74 @@ function BonelessTable(_a) {
587
625
  onNearEnd();
588
626
  }
589
627
  function resetTable() {
628
+ var _a3;
590
629
  if (onReset) return onReset();
591
630
  table.resetSorting();
592
631
  table.resetColumnFilters();
593
632
  table.resetColumnVisibility();
594
633
  table.setColumnOrder(defaultOrder);
595
634
  table.resetExpanded();
635
+ columnResizeVariables.forEach((property) => {
636
+ var _a4;
637
+ return (_a4 = rootRef.current) == null ? void 0 : _a4.style.removeProperty(property);
638
+ });
639
+ (_a3 = rootRef.current) == null ? void 0 : _a3.style.removeProperty("--boneless-table-min-width");
640
+ setColumnSizing({});
641
+ }
642
+ function resizeColumn(columnId, startWidth, startX, minPx, maxPx) {
643
+ const property = getColumnResizeVariable(columnId);
644
+ const startMinWidth = minWidth;
645
+ let nextWidth = startWidth;
646
+ let hasMoved = false;
647
+ const onMove = (event) => {
648
+ var _a3, _b3;
649
+ nextWidth = constrainColumnWidth(startWidth + event.clientX - startX, minPx, maxPx);
650
+ hasMoved || (hasMoved = nextWidth !== startWidth);
651
+ (_a3 = rootRef.current) == null ? void 0 : _a3.style.setProperty(property, `${nextWidth}px`);
652
+ (_b3 = rootRef.current) == null ? void 0 : _b3.style.setProperty(
653
+ "--boneless-table-min-width",
654
+ `${startMinWidth - startWidth + nextWidth}px`
655
+ );
656
+ };
657
+ const onEnd = () => {
658
+ window.removeEventListener("pointermove", onMove);
659
+ window.removeEventListener("pointerup", onEnd);
660
+ window.removeEventListener("pointercancel", onEnd);
661
+ if (hasMoved) {
662
+ setColumnSizing((current) => __spreadProps(__spreadValues({}, current), { [columnId]: nextWidth }));
663
+ }
664
+ };
665
+ window.addEventListener("pointermove", onMove);
666
+ window.addEventListener("pointerup", onEnd);
667
+ window.addEventListener("pointercancel", onEnd);
668
+ }
669
+ function constrainColumnWidth(width, minPx, maxPx) {
670
+ return Math.min(maxPx != null ? maxPx : Number.POSITIVE_INFINITY, Math.max(minPx, Math.round(width)));
671
+ }
672
+ function getCurrentColumnWidth(columnId, fallback, element) {
673
+ var _a3, _b3, _c2, _d2;
674
+ const column = allColumns.find((item) => item.id === columnId);
675
+ const configuredWidth = column ? getColumnSettings(column).sizing.widthPx : void 0;
676
+ return (_d2 = (_c2 = (_a3 = columnSizing[columnId]) != null ? _a3 : configuredWidth) != null ? _c2 : (_b3 = element == null ? void 0 : element.parentElement) == null ? void 0 : _b3.getBoundingClientRect().width) != null ? _d2 : fallback;
677
+ }
678
+ function handleResizeStart(event, columnId, minPx, maxPx) {
679
+ var _a3, _b3;
680
+ event.preventDefault();
681
+ event.stopPropagation();
682
+ const currentWidth = getCurrentColumnWidth(columnId, minPx, event.currentTarget);
683
+ (_b3 = (_a3 = event.currentTarget).setPointerCapture) == null ? void 0 : _b3.call(_a3, event.pointerId);
684
+ resizeColumn(columnId, currentWidth, event.clientX, minPx, maxPx);
685
+ }
686
+ function handleResizeKeyDown(event, columnId, minPx, maxPx) {
687
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
688
+ event.preventDefault();
689
+ event.stopPropagation();
690
+ const step = event.shiftKey ? 32 : 8;
691
+ const currentWidth = getCurrentColumnWidth(columnId, minPx, event.currentTarget);
692
+ const direction = event.key === "ArrowLeft" ? -1 : 1;
693
+ setColumnSizing((current) => __spreadProps(__spreadValues({}, current), {
694
+ [columnId]: constrainColumnWidth(currentWidth + direction * step, minPx, maxPx)
695
+ }));
596
696
  }
597
697
  function moveColumn(id, direction) {
598
698
  const current = table.getState().columnOrder;
@@ -614,6 +714,11 @@ function BonelessTable(_a) {
614
714
  initialRect: { width: 0, height: 600 }
615
715
  });
616
716
  const estimatedRowSize = virtualization === false ? 58 : (_p = virtualization.estimateSize) != null ? _p : 58;
717
+ const measuredVirtualHeight = rowVirtualizer.getTotalSize();
718
+ const virtualHeight = isVirtualized ? Math.max(
719
+ Number.isFinite(measuredVirtualHeight) ? measuredVirtualHeight : 0,
720
+ rows.length * estimatedRowSize
721
+ ) : void 0;
617
722
  const virtualRows = !isVirtualized ? rows.map((row, index) => ({ index, start: index * 58, key: row.id })) : rowVirtualizer.getVirtualItems().length > 0 ? rowVirtualizer.getVirtualItems() : rows.slice(0, Math.ceil(600 / estimatedRowSize) + ((_q = virtualization.overscan) != null ? _q : 5)).map((row, index) => ({
618
723
  index,
619
724
  start: index * estimatedRowSize,
@@ -737,246 +842,315 @@ function BonelessTable(_a) {
737
842
  flex: "0 0 auto",
738
843
  minWidth: 0,
739
844
  overflow: "hidden",
740
- scrollbarGutter: "stable"
845
+ // The body loses this space to a classic vertical scrollbar on Windows. Reserving the
846
+ // same width here keeps both horizontal scroll ranges identical at their far edge.
847
+ marginInlineEnd: `${headerScrollbarInset}px`
741
848
  };
742
849
  const tableStyle = __spreadValues({
743
850
  "--boneless-table-grid": grid
744
851
  }, scroller === "fill" ? { display: "flex", flexDirection: "column", flex: "1 1 auto", minHeight: 0 } : {});
745
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: cn(className, classNames.root), "data-slot": "root", style: rootStyle, children: [
746
- renderSlot(toolbar, table, defaultToolbar),
747
- filterPlacement === "above" ? renderedFilters : null,
748
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
749
- "div",
750
- {
751
- className: classNames.table,
752
- "data-slot": "table",
753
- style: tableStyle,
754
- "aria-busy": isLoading || isFetchingMore,
755
- role: "table",
756
- children: [
757
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
758
- "div",
759
- {
760
- className: classNames.headerScroller,
761
- "data-slot": "header-scroller",
762
- ref: headerScrollerRef,
763
- style: headerScrollerStyle,
764
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
852
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
853
+ "div",
854
+ {
855
+ className: cn(className, classNames.root),
856
+ "data-slot": "root",
857
+ ref: rootRef,
858
+ style: rootStyle,
859
+ children: [
860
+ renderSlot(toolbar, table, defaultToolbar),
861
+ filterPlacement === "above" ? renderedFilters : null,
862
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
863
+ "div",
864
+ {
865
+ className: classNames.table,
866
+ "data-slot": "table",
867
+ style: tableStyle,
868
+ "aria-busy": isLoading || isFetchingMore,
869
+ role: "table",
870
+ children: [
871
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
765
872
  "div",
766
873
  {
767
- className: classNames.headerGroup,
768
- "data-slot": "header-group",
769
- role: "rowgroup",
770
- style: gridStyle,
771
- children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
874
+ className: classNames.headerScroller,
875
+ "data-slot": "header-scroller",
876
+ ref: headerScrollerRef,
877
+ style: headerScrollerStyle,
878
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
772
879
  "div",
773
880
  {
774
- className: classNames.headerRow,
775
- "data-slot": "header-row",
776
- role: "row",
777
- style: { display: "grid", gridTemplateColumns: "var(--boneless-table-grid)" },
778
- children: headerGroup.headers.map((header) => {
779
- const columnSettings = getColumnSettings(header.column);
780
- const direction = header.column.getIsSorted();
781
- const isSortable = !header.isPlaceholder && header.column.getCanSort() && columnSettings.sorting.enabled;
782
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
783
- "div",
784
- {
785
- className: classNames.header,
786
- "data-slot": "header",
787
- "data-align": columnSettings.align,
788
- "data-borders": columnSettings.borders,
789
- role: "columnheader",
790
- "aria-colspan": header.colSpan > 1 ? header.colSpan : void 0,
791
- "aria-sort": direction === "asc" ? "ascending" : direction === "desc" ? "descending" : isSortable ? "none" : void 0,
792
- style: { gridColumn: `span ${header.colSpan}` },
793
- children: header.isPlaceholder ? null : isSortable ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
794
- "button",
795
- {
796
- className: classNames.headerButton,
797
- "data-align": columnSettings.align,
798
- "data-slot": "header-button",
799
- onClick: header.column.getToggleSortingHandler(),
800
- children: [
801
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: classNames.headerLabel, "data-slot": "header-label", children: (0, import_react_table.flexRender)(header.column.columnDef.header, header.getContext()) }),
802
- (icons == null ? void 0 : icons.sort) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
803
- "span",
804
- {
805
- className: classNames.sortIndicator,
806
- "data-align": columnSettings.align,
807
- "data-slot": "sort-indicator",
808
- "data-reveal": columnSettings.sorting.reveal,
809
- children: icons.sort(direction)
810
- }
811
- ) : null
812
- ]
813
- }
814
- ) : (0, import_react_table.flexRender)(header.column.columnDef.header, header.getContext())
815
- },
816
- header.id
817
- );
818
- })
819
- },
820
- headerGroup.id
821
- ))
822
- }
823
- )
824
- }
825
- ),
826
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
827
- "div",
828
- {
829
- "aria-label": "Table rows",
830
- className: classNames.scroller,
831
- "data-slot": "scroller",
832
- ref: scrollerRef,
833
- onScroll: handleScroll,
834
- style: scrollerStyle,
835
- tabIndex: 0,
836
- children: [
837
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
838
- TableSkeleton,
839
- {
840
- columnCount: visibleColumns.length,
841
- rows: skeletonRows,
842
- label: skeletonLabel,
843
- classNames
844
- }
845
- ) : rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: classNames.emptyState, "data-slot": "empty-state", role: "status", children: emptyState ? typeof emptyState === "function" ? emptyState(table) : emptyState : table.getState().columnFilters.length > 0 ? "No rows match the current filters." : "No rows to display." }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
846
- "div",
847
- {
848
- className: classNames.rowGroup,
849
- "data-slot": "row-group",
850
- style: __spreadProps(__spreadValues({}, gridStyle), {
851
- height: `${isVirtualized ? rowVirtualizer.getTotalSize() : "auto"}`,
852
- position: "relative"
853
- }),
854
- role: "rowgroup",
855
- children: virtualRows.map((virtualRow) => {
856
- var _a3;
857
- const row = rows[virtualRow.index];
858
- const href = rowLink ? resolveRowHref(rowLink, row.original) : void 0;
859
- const RowLink = rowLink == null ? void 0 : rowLink.component;
860
- const rowContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
881
+ className: classNames.headerGroup,
882
+ "data-slot": "header-group",
883
+ role: "rowgroup",
884
+ style: gridStyle,
885
+ children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
861
886
  "div",
862
887
  {
863
- className: classNames.row,
864
- "data-slot": "row",
888
+ className: classNames.headerRow,
889
+ "data-slot": "header-row",
865
890
  role: "row",
866
891
  style: { display: "grid", gridTemplateColumns: "var(--boneless-table-grid)" },
867
- tabIndex: onRowClick && !href ? 0 : void 0,
868
- onClick: (event) => onRowClick == null ? void 0 : onRowClick(row.original, event),
869
- onKeyDown: (event) => {
870
- if (!onRowClick || href || event.key !== "Enter" && event.key !== " ")
871
- return;
872
- event.preventDefault();
873
- onRowClick(row.original, event);
874
- },
875
- children: row.getVisibleCells().map((cell) => {
876
- var _a4, _b3, _c2;
877
- const columnSettings = getColumnSettings(cell.column);
878
- const title = columnSettings.valueDisplay != null ? String((_a4 = cell.getValue()) != null ? _a4 : "") : void 0;
879
- const isTreeCell = Boolean(tree && cell.column.id === treeColumnId);
880
- const canExpand = row.getCanExpand();
881
- const cellContent = (0, import_react_table.flexRender)(cell.column.columnDef.cell, cell.getContext());
892
+ children: headerGroup.headers.map((header) => {
893
+ const columnSettings = getColumnSettings(header.column);
894
+ const direction = header.column.getIsSorted();
895
+ const isSortable = !header.isPlaceholder && header.column.getCanSort() && columnSettings.sorting.enabled;
882
896
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
883
897
  "div",
884
898
  {
885
- className: classNames.cell,
886
- "data-slot": "cell",
899
+ className: classNames.header,
900
+ "data-slot": "header",
887
901
  "data-align": columnSettings.align,
888
902
  "data-borders": columnSettings.borders,
889
- role: "cell",
890
- title,
891
- children: isTreeCell ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
892
- "div",
893
- {
894
- "data-slot": "tree-content",
895
- style: { paddingInlineStart: `${row.depth * treeIndentPx}px` },
896
- children: [
897
- canExpand ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
898
- "button",
899
- {
900
- "data-slot": "tree-row-toggle",
901
- type: "button",
902
- "aria-expanded": row.getIsExpanded(),
903
- "aria-label": `${row.getIsExpanded() ? "Collapse" : "Expand"} row`,
904
- onClick: (event) => {
905
- event.stopPropagation();
906
- row.toggleExpanded();
907
- },
908
- children: row.getIsExpanded() ? (_b3 = icons == null ? void 0 : icons.collapse) != null ? _b3 : "\u2212" : (_c2 = icons == null ? void 0 : icons.expand) != null ? _c2 : "+"
909
- }
910
- ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "data-slot": "tree-row-toggle-spacer", "aria-hidden": "true" }),
911
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "data-slot": "tree-value", children: cellContent })
912
- ]
913
- }
914
- ) : cellContent
903
+ role: "columnheader",
904
+ "aria-colspan": header.colSpan > 1 ? header.colSpan : void 0,
905
+ "aria-sort": direction === "asc" ? "ascending" : direction === "desc" ? "descending" : isSortable ? "none" : void 0,
906
+ style: { gridColumn: `span ${header.colSpan}` },
907
+ children: header.isPlaceholder ? null : isSortable ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
908
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
909
+ "button",
910
+ {
911
+ className: classNames.headerButton,
912
+ "data-align": columnSettings.align,
913
+ "data-slot": "header-button",
914
+ onClick: header.column.getToggleSortingHandler(),
915
+ children: [
916
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: classNames.headerLabel, "data-slot": "header-label", children: (0, import_react_table.flexRender)(header.column.columnDef.header, header.getContext()) }),
917
+ (icons == null ? void 0 : icons.sort) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
918
+ "span",
919
+ {
920
+ className: classNames.sortIndicator,
921
+ "data-align": columnSettings.align,
922
+ "data-slot": "sort-indicator",
923
+ "data-reveal": columnSettings.sorting.reveal,
924
+ children: icons.sort(direction)
925
+ }
926
+ ) : null
927
+ ]
928
+ }
929
+ ),
930
+ header.colSpan === 1 && columnSettings.sizing.resizable ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
931
+ "button",
932
+ {
933
+ "aria-label": `Resize ${header.column.id} column`,
934
+ className: classNames.resizeHandle,
935
+ "data-slot": "resize-handle",
936
+ onKeyDown: (event) => {
937
+ var _a3;
938
+ return handleResizeKeyDown(
939
+ event,
940
+ header.column.id,
941
+ (_a3 = columnSettings.sizing.minPx) != null ? _a3 : settings.columnDefaults.sizing.minPx,
942
+ columnSettings.sizing.maxPx
943
+ );
944
+ },
945
+ onPointerDown: (event) => {
946
+ var _a3;
947
+ return handleResizeStart(
948
+ event,
949
+ header.column.id,
950
+ (_a3 = columnSettings.sizing.minPx) != null ? _a3 : settings.columnDefaults.sizing.minPx,
951
+ columnSettings.sizing.maxPx
952
+ );
953
+ },
954
+ type: "button"
955
+ }
956
+ ) : null
957
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
958
+ (0, import_react_table.flexRender)(header.column.columnDef.header, header.getContext()),
959
+ header.colSpan === 1 && columnSettings.sizing.resizable ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
960
+ "button",
961
+ {
962
+ "aria-label": `Resize ${header.column.id} column`,
963
+ className: classNames.resizeHandle,
964
+ "data-slot": "resize-handle",
965
+ onKeyDown: (event) => {
966
+ var _a3;
967
+ return handleResizeKeyDown(
968
+ event,
969
+ header.column.id,
970
+ (_a3 = columnSettings.sizing.minPx) != null ? _a3 : settings.columnDefaults.sizing.minPx,
971
+ columnSettings.sizing.maxPx
972
+ );
973
+ },
974
+ onPointerDown: (event) => {
975
+ var _a3;
976
+ return handleResizeStart(
977
+ event,
978
+ header.column.id,
979
+ (_a3 = columnSettings.sizing.minPx) != null ? _a3 : settings.columnDefaults.sizing.minPx,
980
+ columnSettings.sizing.maxPx
981
+ );
982
+ },
983
+ type: "button"
984
+ }
985
+ ) : null
986
+ ] })
915
987
  },
916
- cell.id
988
+ header.id
917
989
  );
918
990
  })
919
- }
920
- );
921
- const rowStyle = !isVirtualized ? void 0 : {
922
- position: "absolute",
923
- top: 0,
924
- left: 0,
925
- width: "100%",
926
- transform: `translateY(${virtualRow.start}px)`
927
- };
928
- if (!href || !rowLink || !RowLink || tree && row.getCanExpand())
929
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
930
- "div",
931
- {
932
- "data-index": isVirtualized ? virtualRow.index : void 0,
933
- ref: isVirtualized ? rowVirtualizer.measureElement : void 0,
934
- style: rowStyle,
935
- children: rowContent
936
- },
937
- row.id
938
- );
939
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
940
- "div",
941
- {
942
- "data-index": isVirtualized ? virtualRow.index : void 0,
943
- ref: isVirtualized ? rowVirtualizer.measureElement : void 0,
944
- style: rowStyle,
945
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
946
- RowLink,
991
+ },
992
+ headerGroup.id
993
+ ))
994
+ }
995
+ )
996
+ }
997
+ ),
998
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
999
+ "div",
1000
+ {
1001
+ "aria-label": "Table rows",
1002
+ className: classNames.scroller,
1003
+ "data-slot": "scroller",
1004
+ ref: scrollerRef,
1005
+ onScroll: handleScroll,
1006
+ style: scrollerStyle,
1007
+ tabIndex: 0,
1008
+ children: [
1009
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1010
+ TableSkeleton,
1011
+ {
1012
+ columnCount: visibleColumns.length,
1013
+ rows: skeletonRows,
1014
+ label: skeletonLabel,
1015
+ classNames
1016
+ }
1017
+ ) : rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: classNames.emptyState, "data-slot": "empty-state", role: "status", children: emptyState ? typeof emptyState === "function" ? emptyState(table) : emptyState : table.getState().columnFilters.length > 0 ? "No rows match the current filters." : "No rows to display." }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1018
+ "div",
1019
+ {
1020
+ className: classNames.rowGroup,
1021
+ "data-slot": "row-group",
1022
+ style: __spreadProps(__spreadValues({}, gridStyle), {
1023
+ height: isVirtualized ? `${virtualHeight}px` : "auto",
1024
+ position: "relative"
1025
+ }),
1026
+ role: "rowgroup",
1027
+ children: virtualRows.map((virtualRow) => {
1028
+ var _a3;
1029
+ const row = rows[virtualRow.index];
1030
+ const href = rowLink ? resolveRowHref(rowLink, row.original) : void 0;
1031
+ const RowLink = rowLink == null ? void 0 : rowLink.component;
1032
+ const rowContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1033
+ "div",
947
1034
  {
948
- className: (_a3 = classNames.rowLink) != null ? _a3 : "",
949
- href,
950
- "aria-label": resolveRowLinkLabel(rowLink, row.original),
951
- target: rowLink.target,
952
- rel: rowLink.rel,
953
- children: rowContent
1035
+ className: classNames.row,
1036
+ "data-slot": "row",
1037
+ role: "row",
1038
+ style: { display: "grid", gridTemplateColumns: "var(--boneless-table-grid)" },
1039
+ tabIndex: onRowClick && !href ? 0 : void 0,
1040
+ onClick: (event) => onRowClick == null ? void 0 : onRowClick(row.original, event),
1041
+ onKeyDown: (event) => {
1042
+ if (!onRowClick || href || event.key !== "Enter" && event.key !== " ")
1043
+ return;
1044
+ event.preventDefault();
1045
+ onRowClick(row.original, event);
1046
+ },
1047
+ children: row.getVisibleCells().map((cell) => {
1048
+ var _a4, _b3, _c2;
1049
+ const columnSettings = getColumnSettings(cell.column);
1050
+ const title = columnSettings.valueDisplay != null ? String((_a4 = cell.getValue()) != null ? _a4 : "") : void 0;
1051
+ const isTreeCell = Boolean(tree && cell.column.id === treeColumnId);
1052
+ const canExpand = row.getCanExpand();
1053
+ const cellContent = (0, import_react_table.flexRender)(cell.column.columnDef.cell, cell.getContext());
1054
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1055
+ "div",
1056
+ {
1057
+ className: classNames.cell,
1058
+ "data-slot": "cell",
1059
+ "data-align": columnSettings.align,
1060
+ "data-borders": columnSettings.borders,
1061
+ role: "cell",
1062
+ title,
1063
+ children: isTreeCell ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1064
+ "div",
1065
+ {
1066
+ "data-slot": "tree-content",
1067
+ style: { paddingInlineStart: `${row.depth * treeIndentPx}px` },
1068
+ children: [
1069
+ canExpand ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1070
+ "button",
1071
+ {
1072
+ "data-slot": "tree-row-toggle",
1073
+ type: "button",
1074
+ "aria-expanded": row.getIsExpanded(),
1075
+ "aria-label": `${row.getIsExpanded() ? "Collapse" : "Expand"} row`,
1076
+ onClick: (event) => {
1077
+ event.stopPropagation();
1078
+ row.toggleExpanded();
1079
+ },
1080
+ children: row.getIsExpanded() ? (_b3 = icons == null ? void 0 : icons.collapse) != null ? _b3 : "\u2212" : (_c2 = icons == null ? void 0 : icons.expand) != null ? _c2 : "+"
1081
+ }
1082
+ ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "data-slot": "tree-row-toggle-spacer", "aria-hidden": "true" }),
1083
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "data-slot": "tree-value", children: cellContent })
1084
+ ]
1085
+ }
1086
+ ) : cellContent
1087
+ },
1088
+ cell.id
1089
+ );
1090
+ })
954
1091
  }
955
- )
956
- },
957
- row.id
958
- );
959
- })
960
- }
961
- ),
962
- isFetchingMore ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
963
- TableSkeleton,
964
- {
965
- columnCount: visibleColumns.length,
966
- rows: 3,
967
- label: skeletonLabel,
968
- classNames
969
- }
970
- ) : null
971
- ]
972
- }
973
- )
974
- ]
975
- }
976
- ),
977
- filterPlacement === "below" ? renderedFilters : null,
978
- renderSlot(footer, table, defaultFooter)
979
- ] });
1092
+ );
1093
+ const rowStyle = !isVirtualized ? void 0 : {
1094
+ position: "absolute",
1095
+ top: 0,
1096
+ left: 0,
1097
+ width: "100%",
1098
+ transform: `translateY(${virtualRow.start}px)`
1099
+ };
1100
+ if (!href || !rowLink || !RowLink || tree && row.getCanExpand())
1101
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1102
+ "div",
1103
+ {
1104
+ "data-index": isVirtualized ? virtualRow.index : void 0,
1105
+ ref: isVirtualized ? rowVirtualizer.measureElement : void 0,
1106
+ style: rowStyle,
1107
+ children: rowContent
1108
+ },
1109
+ row.id
1110
+ );
1111
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1112
+ "div",
1113
+ {
1114
+ "data-index": isVirtualized ? virtualRow.index : void 0,
1115
+ ref: isVirtualized ? rowVirtualizer.measureElement : void 0,
1116
+ style: rowStyle,
1117
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1118
+ RowLink,
1119
+ {
1120
+ className: (_a3 = classNames.rowLink) != null ? _a3 : "",
1121
+ href,
1122
+ "aria-label": resolveRowLinkLabel(rowLink, row.original),
1123
+ target: rowLink.target,
1124
+ rel: rowLink.rel,
1125
+ children: rowContent
1126
+ }
1127
+ )
1128
+ },
1129
+ row.id
1130
+ );
1131
+ })
1132
+ }
1133
+ ),
1134
+ isFetchingMore ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1135
+ TableSkeleton,
1136
+ {
1137
+ columnCount: visibleColumns.length,
1138
+ rows: 3,
1139
+ label: skeletonLabel,
1140
+ classNames
1141
+ }
1142
+ ) : null
1143
+ ]
1144
+ }
1145
+ )
1146
+ ]
1147
+ }
1148
+ ),
1149
+ filterPlacement === "below" ? renderedFilters : null,
1150
+ renderSlot(footer, table, defaultFooter)
1151
+ ]
1152
+ }
1153
+ );
980
1154
  }
981
1155
 
982
1156
  // src/index.ts