boneless-table 0.1.0 → 0.1.1

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.d.mts CHANGED
@@ -24,7 +24,6 @@ type BonelessTableColumnSettings = {
24
24
  filtering?: {
25
25
  type: FilterType;
26
26
  options?: readonly string[];
27
- reveal?: RevealMode;
28
27
  };
29
28
  valueDisplay?: {
30
29
  truncateAt: number;
@@ -37,7 +36,6 @@ type BonelessTableSettings = {
37
36
  sorting: Required<NonNullable<BonelessTableColumnSettings['sorting']>>;
38
37
  };
39
38
  interactions: {
40
- filterReveal: RevealMode;
41
39
  horizontalOverflow: 'auto' | 'scroll';
42
40
  };
43
41
  };
@@ -67,7 +65,6 @@ declare function resolveColumnSettings(settings: BonelessTableSettings, column:
67
65
  filtering: {
68
66
  type: FilterType;
69
67
  options?: readonly string[];
70
- reveal?: RevealMode;
71
68
  } | undefined;
72
69
  valueDisplay: {
73
70
  truncateAt: number;
@@ -137,6 +134,7 @@ type BonelessTableToolbarLayout<TData extends RowData> = (context: {
137
134
  actions: ReactNode;
138
135
  }) => ReactNode;
139
136
  type BonelessTableSlot<TData extends RowData> = boolean | ReactNode | ((table: Table<TData>) => ReactNode);
137
+ type BonelessTableFilterPlacement = 'above' | 'below';
140
138
  type BonelessTableRowClickEvent = MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>;
141
139
  /**
142
140
  * Named hooks for your stylesheet. The renderer applies no default class names or visual styles.
@@ -145,15 +143,22 @@ type BonelessTableClassNames = Partial<{
145
143
  root: string;
146
144
  toolbar: string;
147
145
  toolbarSummary: string;
146
+ toolbarCount: string;
147
+ toolbarLabel: string;
148
148
  toolbarHint: string;
149
149
  toolbarActions: string;
150
150
  scroller: string;
151
+ headerScroller: string;
151
152
  table: string;
152
153
  headerGroup: string;
153
154
  headerRow: string;
154
155
  header: string;
155
156
  headerButton: string;
157
+ headerLabel: string;
156
158
  sortIndicator: string;
159
+ filters: string;
160
+ filterItem: string;
161
+ filterLabel: string;
157
162
  rowGroup: string;
158
163
  row: string;
159
164
  cell: string;
@@ -203,6 +208,10 @@ type BonelessTablePresentationOptions<TData extends RowData> = {
203
208
  toolbar?: BonelessTableSlot<TData>;
204
209
  /** Reposition the default summary and action controls without rebuilding their behavior. */
205
210
  toolbarLayout?: BonelessTableToolbarLayout<TData>;
211
+ /** Built-in filters, custom filter content, or a render function receiving the table instance. */
212
+ filters?: BonelessTableSlot<TData>;
213
+ /** Places the filter region outside the table scroll area. Defaults to "above". */
214
+ filterPlacement?: BonelessTableFilterPlacement;
206
215
  footer?: BonelessTableSlot<TData>;
207
216
  totalCount?: number;
208
217
  resultLabel?: string;
@@ -232,7 +241,7 @@ type BonelessTableProps<TData extends RowData> = BonelessTableOptions<TData> & B
232
241
  data: TData[];
233
242
  columns: BonelessTableColumn<TData>[];
234
243
  };
235
- declare function BonelessTable<TData extends RowData>({ data, columns, settings: settingsOverride, className, classNames, icons, tree: treeOption, isLoading, isFetchingMore, skeletonRows, skeletonLabel, onNearEnd, canLoadMore, nearEndOffset, filterDebounceMs, scroller, toolbar, toolbarLayout, footer, totalCount, resultLabel, resultHint, onReset, onRowClick, scrollToTopOn, rowLink, emptyState, virtualization, ...tableOptions }: BonelessTableProps<TData>): react.JSX.Element;
244
+ declare function BonelessTable<TData extends RowData>({ data, columns, settings: settingsOverride, className, classNames, icons, tree: treeOption, isLoading, isFetchingMore, skeletonRows, skeletonLabel, onNearEnd, canLoadMore, nearEndOffset, filterDebounceMs, scroller, toolbar, toolbarLayout, filters, filterPlacement, footer, totalCount, resultLabel, resultHint, onReset, onRowClick, scrollToTopOn, rowLink, emptyState, virtualization, ...tableOptions }: BonelessTableProps<TData>): react.JSX.Element;
236
245
 
237
246
  declare function defineColumns<TData extends RowData>(columns: BonelessTableColumn<TData>[]): BonelessTableColumn<TData>[];
238
247
  declare function resolveColumns<TData extends RowData>(columns: BonelessTableColumn<TData>[]): ResolvedBonelessTableColumn<TData>[];
@@ -255,4 +264,4 @@ declare function TableSkeleton({ columnCount, rows, label, classNames, }: {
255
264
  classNames?: Pick<BonelessTableClassNames, 'row' | 'cell' | 'skeleton'>;
256
265
  }): react.JSX.Element;
257
266
 
258
- export { BonelessTable, type BonelessTableClassNames, type BonelessTableColumn, type BonelessTableColumnSettings, type BonelessTableIcons, type BonelessTableOptions, type BonelessTablePresentationOptions, type BonelessTableProps, type BonelessTableRowClickEvent, type BonelessTableRowLink, type BonelessTableRowLinkComponentProps, type BonelessTableSettings, type BonelessTableSlot, type BonelessTableToolbarLayout, type BonelessTableTreeOptions, type ColumnAlignment, type ColumnBorders, ColumnFilter, ColumnMenu, type DeepPartial, type FilterType, type ResolvedBonelessTableColumn, type RevealMode, TableSkeleton, compactValue, defaultBonelessTableSettings, defineColumns, getColumnIds, mergeBonelessTableSettings, resolveColumnSettings, resolveColumns, resolveRowHref, resolveRowLinkLabel, withDefaultCells };
267
+ export { BonelessTable, type BonelessTableClassNames, type BonelessTableColumn, type BonelessTableColumnSettings, type BonelessTableFilterPlacement, type BonelessTableIcons, type BonelessTableOptions, type BonelessTablePresentationOptions, type BonelessTableProps, type BonelessTableRowClickEvent, type BonelessTableRowLink, type BonelessTableRowLinkComponentProps, type BonelessTableSettings, type BonelessTableSlot, type BonelessTableToolbarLayout, type BonelessTableTreeOptions, type ColumnAlignment, type ColumnBorders, ColumnFilter, ColumnMenu, type DeepPartial, type FilterType, type ResolvedBonelessTableColumn, type RevealMode, TableSkeleton, compactValue, defaultBonelessTableSettings, defineColumns, getColumnIds, mergeBonelessTableSettings, resolveColumnSettings, resolveColumns, resolveRowHref, resolveRowLinkLabel, withDefaultCells };
package/dist/index.d.ts CHANGED
@@ -24,7 +24,6 @@ type BonelessTableColumnSettings = {
24
24
  filtering?: {
25
25
  type: FilterType;
26
26
  options?: readonly string[];
27
- reveal?: RevealMode;
28
27
  };
29
28
  valueDisplay?: {
30
29
  truncateAt: number;
@@ -37,7 +36,6 @@ type BonelessTableSettings = {
37
36
  sorting: Required<NonNullable<BonelessTableColumnSettings['sorting']>>;
38
37
  };
39
38
  interactions: {
40
- filterReveal: RevealMode;
41
39
  horizontalOverflow: 'auto' | 'scroll';
42
40
  };
43
41
  };
@@ -67,7 +65,6 @@ declare function resolveColumnSettings(settings: BonelessTableSettings, column:
67
65
  filtering: {
68
66
  type: FilterType;
69
67
  options?: readonly string[];
70
- reveal?: RevealMode;
71
68
  } | undefined;
72
69
  valueDisplay: {
73
70
  truncateAt: number;
@@ -137,6 +134,7 @@ type BonelessTableToolbarLayout<TData extends RowData> = (context: {
137
134
  actions: ReactNode;
138
135
  }) => ReactNode;
139
136
  type BonelessTableSlot<TData extends RowData> = boolean | ReactNode | ((table: Table<TData>) => ReactNode);
137
+ type BonelessTableFilterPlacement = 'above' | 'below';
140
138
  type BonelessTableRowClickEvent = MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>;
141
139
  /**
142
140
  * Named hooks for your stylesheet. The renderer applies no default class names or visual styles.
@@ -145,15 +143,22 @@ type BonelessTableClassNames = Partial<{
145
143
  root: string;
146
144
  toolbar: string;
147
145
  toolbarSummary: string;
146
+ toolbarCount: string;
147
+ toolbarLabel: string;
148
148
  toolbarHint: string;
149
149
  toolbarActions: string;
150
150
  scroller: string;
151
+ headerScroller: string;
151
152
  table: string;
152
153
  headerGroup: string;
153
154
  headerRow: string;
154
155
  header: string;
155
156
  headerButton: string;
157
+ headerLabel: string;
156
158
  sortIndicator: string;
159
+ filters: string;
160
+ filterItem: string;
161
+ filterLabel: string;
157
162
  rowGroup: string;
158
163
  row: string;
159
164
  cell: string;
@@ -203,6 +208,10 @@ type BonelessTablePresentationOptions<TData extends RowData> = {
203
208
  toolbar?: BonelessTableSlot<TData>;
204
209
  /** Reposition the default summary and action controls without rebuilding their behavior. */
205
210
  toolbarLayout?: BonelessTableToolbarLayout<TData>;
211
+ /** Built-in filters, custom filter content, or a render function receiving the table instance. */
212
+ filters?: BonelessTableSlot<TData>;
213
+ /** Places the filter region outside the table scroll area. Defaults to "above". */
214
+ filterPlacement?: BonelessTableFilterPlacement;
206
215
  footer?: BonelessTableSlot<TData>;
207
216
  totalCount?: number;
208
217
  resultLabel?: string;
@@ -232,7 +241,7 @@ type BonelessTableProps<TData extends RowData> = BonelessTableOptions<TData> & B
232
241
  data: TData[];
233
242
  columns: BonelessTableColumn<TData>[];
234
243
  };
235
- declare function BonelessTable<TData extends RowData>({ data, columns, settings: settingsOverride, className, classNames, icons, tree: treeOption, isLoading, isFetchingMore, skeletonRows, skeletonLabel, onNearEnd, canLoadMore, nearEndOffset, filterDebounceMs, scroller, toolbar, toolbarLayout, footer, totalCount, resultLabel, resultHint, onReset, onRowClick, scrollToTopOn, rowLink, emptyState, virtualization, ...tableOptions }: BonelessTableProps<TData>): react.JSX.Element;
244
+ declare function BonelessTable<TData extends RowData>({ data, columns, settings: settingsOverride, className, classNames, icons, tree: treeOption, isLoading, isFetchingMore, skeletonRows, skeletonLabel, onNearEnd, canLoadMore, nearEndOffset, filterDebounceMs, scroller, toolbar, toolbarLayout, filters, filterPlacement, footer, totalCount, resultLabel, resultHint, onReset, onRowClick, scrollToTopOn, rowLink, emptyState, virtualization, ...tableOptions }: BonelessTableProps<TData>): react.JSX.Element;
236
245
 
237
246
  declare function defineColumns<TData extends RowData>(columns: BonelessTableColumn<TData>[]): BonelessTableColumn<TData>[];
238
247
  declare function resolveColumns<TData extends RowData>(columns: BonelessTableColumn<TData>[]): ResolvedBonelessTableColumn<TData>[];
@@ -255,4 +264,4 @@ declare function TableSkeleton({ columnCount, rows, label, classNames, }: {
255
264
  classNames?: Pick<BonelessTableClassNames, 'row' | 'cell' | 'skeleton'>;
256
265
  }): react.JSX.Element;
257
266
 
258
- export { BonelessTable, type BonelessTableClassNames, type BonelessTableColumn, type BonelessTableColumnSettings, type BonelessTableIcons, type BonelessTableOptions, type BonelessTablePresentationOptions, type BonelessTableProps, type BonelessTableRowClickEvent, type BonelessTableRowLink, type BonelessTableRowLinkComponentProps, type BonelessTableSettings, type BonelessTableSlot, type BonelessTableToolbarLayout, type BonelessTableTreeOptions, type ColumnAlignment, type ColumnBorders, ColumnFilter, ColumnMenu, type DeepPartial, type FilterType, type ResolvedBonelessTableColumn, type RevealMode, TableSkeleton, compactValue, defaultBonelessTableSettings, defineColumns, getColumnIds, mergeBonelessTableSettings, resolveColumnSettings, resolveColumns, resolveRowHref, resolveRowLinkLabel, withDefaultCells };
267
+ export { BonelessTable, type BonelessTableClassNames, type BonelessTableColumn, type BonelessTableColumnSettings, type BonelessTableFilterPlacement, type BonelessTableIcons, type BonelessTableOptions, type BonelessTablePresentationOptions, type BonelessTableProps, type BonelessTableRowClickEvent, type BonelessTableRowLink, type BonelessTableRowLinkComponentProps, type BonelessTableSettings, type BonelessTableSlot, type BonelessTableToolbarLayout, type BonelessTableTreeOptions, type ColumnAlignment, type ColumnBorders, ColumnFilter, ColumnMenu, type DeepPartial, type FilterType, type ResolvedBonelessTableColumn, type RevealMode, TableSkeleton, compactValue, defaultBonelessTableSettings, defineColumns, getColumnIds, mergeBonelessTableSettings, resolveColumnSettings, resolveColumns, resolveRowHref, resolveRowLinkLabel, withDefaultCells };
package/dist/index.js CHANGED
@@ -92,10 +92,13 @@ function ColumnFilter({
92
92
  var _a, _b;
93
93
  const value = String((_a = column.getFilterValue()) != null ? _a : "");
94
94
  const [inputValue, setInputValue] = (0, import_react.useState)(value);
95
+ const lastColumnValueRef = (0, import_react.useRef)(value);
95
96
  (0, import_react.useEffect)(() => {
96
- setInputValue(value);
97
- }, [value]);
98
- (0, import_react.useEffect)(() => {
97
+ if (value !== lastColumnValueRef.current) {
98
+ lastColumnValueRef.current = value;
99
+ setInputValue(value);
100
+ return;
101
+ }
99
102
  if (settings.type !== "text" || inputValue === value) return;
100
103
  if (debounceMs <= 0) {
101
104
  column.setFilterValue(inputValue || void 0);
@@ -248,7 +251,7 @@ var defaultBonelessTableSettings = {
248
251
  borders: "none",
249
252
  sorting: { enabled: true, reveal: "hover" }
250
253
  },
251
- interactions: { filterReveal: "hover", horizontalOverflow: "auto" }
254
+ interactions: { horizontalOverflow: "auto" }
252
255
  };
253
256
  function mergeBonelessTableSettings(override, base = defaultBonelessTableSettings) {
254
257
  var _a, _b, _c, _d, _e, _f;
@@ -402,6 +405,8 @@ function BonelessTable(_a) {
402
405
  scroller = "auto",
403
406
  toolbar = true,
404
407
  toolbarLayout,
408
+ filters = true,
409
+ filterPlacement = "above",
405
410
  footer = true,
406
411
  totalCount,
407
412
  resultLabel = "rows",
@@ -431,6 +436,8 @@ function BonelessTable(_a) {
431
436
  "scroller",
432
437
  "toolbar",
433
438
  "toolbarLayout",
439
+ "filters",
440
+ "filterPlacement",
434
441
  "footer",
435
442
  "totalCount",
436
443
  "resultLabel",
@@ -448,11 +455,11 @@ function BonelessTable(_a) {
448
455
  const defaultOrder = (0, import_react3.useMemo)(() => getColumnIds(resolvedColumns), [resolvedColumns]);
449
456
  const scrollerRef = (0, import_react3.useRef)(null);
450
457
  const headerScrollerRef = (0, import_react3.useRef)(null);
458
+ const lastScrollLeftRef = (0, import_react3.useRef)(0);
451
459
  const columnsButtonRef = (0, import_react3.useRef)(null);
452
460
  const nearEndTriggeredRef = (0, import_react3.useRef)(false);
453
461
  const columnMenuId = (0, import_react3.useId)();
454
462
  const [showColumns, setShowColumns] = (0, import_react3.useState)(false);
455
- const [headerScrollbarGutter, setHeaderScrollbarGutter] = (0, import_react3.useState)(0);
456
463
  const [sorting, setSorting] = (0, import_react3.useState)((_b2 = (_a2 = tableOptions.initialState) == null ? void 0 : _a2.sorting) != null ? _b2 : []);
457
464
  const [columnFilters, setColumnFilters] = (0, import_react3.useState)(
458
465
  (_d = (_c = tableOptions.initialState) == null ? void 0 : _c.columnFilters) != null ? _d : []
@@ -497,18 +504,6 @@ function BonelessTable(_a) {
497
504
  var _a3;
498
505
  if (scrollToTopOn !== void 0) (_a3 = scrollerRef.current) == null ? void 0 : _a3.scrollTo({ top: 0 });
499
506
  }, [scrollToTopOn]);
500
- (0, import_react3.useEffect)(() => {
501
- const scroller2 = scrollerRef.current;
502
- if (!scroller2) return;
503
- const syncHeaderScrollbarGutter = () => {
504
- setHeaderScrollbarGutter(Math.max(0, scroller2.offsetWidth - scroller2.clientWidth));
505
- };
506
- syncHeaderScrollbarGutter();
507
- if (typeof ResizeObserver === "undefined") return;
508
- const observer = new ResizeObserver(syncHeaderScrollbarGutter);
509
- observer.observe(scroller2);
510
- return () => observer.disconnect();
511
- }, []);
512
507
  const table = (0, import_react_table.useReactTable)(__spreadProps(__spreadValues({}, restTableOptions), {
513
508
  data,
514
509
  columns: resolvedColumns,
@@ -577,13 +572,17 @@ function BonelessTable(_a) {
577
572
  function handleScroll() {
578
573
  const element = scrollerRef.current;
579
574
  if (!element) return;
580
- if (headerScrollerRef.current) headerScrollerRef.current.scrollLeft = element.scrollLeft;
575
+ if (element.scrollLeft !== lastScrollLeftRef.current) {
576
+ lastScrollLeftRef.current = element.scrollLeft;
577
+ if (headerScrollerRef.current) headerScrollerRef.current.scrollLeft = element.scrollLeft;
578
+ }
579
+ if (!onNearEnd) return;
581
580
  const isNearEnd = element.scrollHeight - element.scrollTop - element.clientHeight < nearEndOffset;
582
581
  if (!isNearEnd) {
583
582
  nearEndTriggeredRef.current = false;
584
583
  return;
585
584
  }
586
- if (!onNearEnd || !canLoadMore || isFetchingMore || nearEndTriggeredRef.current) return;
585
+ if (!canLoadMore || isFetchingMore || nearEndTriggeredRef.current) return;
587
586
  nearEndTriggeredRef.current = true;
588
587
  onNearEnd();
589
588
  }
@@ -626,10 +625,13 @@ function BonelessTable(_a) {
626
625
  (_a3 = columnsButtonRef.current) == null ? void 0 : _a3.focus();
627
626
  }
628
627
  const toolbarSummary = /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: classNames.toolbarSummary, "data-slot": "toolbar-summary", children: [
629
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: total.toLocaleString() }),
628
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { className: classNames.toolbarCount, "data-slot": "toolbar-count", children: total.toLocaleString() }),
630
629
  " ",
631
- resultLabel,
632
- resultHint ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: classNames.toolbarHint, "data-slot": "toolbar-hint", children: resultHint }) : null
630
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: classNames.toolbarLabel, "data-slot": "toolbar-label", children: resultLabel }),
631
+ resultHint ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
632
+ " ",
633
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: classNames.toolbarHint, "data-slot": "toolbar-hint", children: resultHint })
634
+ ] }) : null
633
635
  ] });
634
636
  const toolbarActions = /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: classNames.toolbarActions, "data-slot": "toolbar-actions", children: [
635
637
  tree && expandableRows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
@@ -681,6 +683,43 @@ function BonelessTable(_a) {
681
683
  toolbarSummary,
682
684
  toolbarActions
683
685
  ] });
686
+ const filterHeaders = table.getLeafHeaders().filter((header) => !header.isPlaceholder && getColumnSettings(header.column).filtering);
687
+ const defaultFilters = filterHeaders.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
688
+ "div",
689
+ {
690
+ "aria-label": "Table filters",
691
+ className: classNames.filters,
692
+ "data-slot": "filters",
693
+ role: "group",
694
+ children: filterHeaders.map((header) => {
695
+ var _a3, _b3;
696
+ const filterSettings = getColumnSettings(header.column).filtering;
697
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
698
+ "div",
699
+ {
700
+ className: classNames.filterItem,
701
+ "data-column-id": header.column.id,
702
+ "data-slot": "filter-item",
703
+ children: [
704
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: classNames.filterLabel, "data-slot": "filter-label", children: (_b3 = (_a3 = header.column.columnDef.meta) == null ? void 0 : _a3.columnLabel) != null ? _b3 : typeof header.column.columnDef.header === "string" || typeof header.column.columnDef.header === "number" ? String(header.column.columnDef.header) : header.column.id }),
705
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
706
+ ColumnFilter,
707
+ {
708
+ className: classNames.filter,
709
+ column: header.column,
710
+ settings: filterSettings,
711
+ icon: filterSettings.type === "text" ? icons == null ? void 0 : icons.search : void 0,
712
+ debounceMs: filterDebounceMs
713
+ }
714
+ )
715
+ ]
716
+ },
717
+ header.id
718
+ );
719
+ })
720
+ }
721
+ ) : null;
722
+ const renderedFilters = renderSlot(filters, table, defaultFilters);
684
723
  const defaultFooter = /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("footer", { className: classNames.footer, "data-slot": "footer", children: [
685
724
  "Showing ",
686
725
  shown.toLocaleString(),
@@ -691,13 +730,21 @@ function BonelessTable(_a) {
691
730
  ] });
692
731
  const rootStyle = scroller === "fill" ? { display: "flex", flexDirection: "column", minHeight: 0 } : void 0;
693
732
  const scrollerStyle = __spreadValues({
694
- overflowX: settings.interactions.horizontalOverflow
733
+ overflowX: settings.interactions.horizontalOverflow,
734
+ scrollbarGutter: "stable"
695
735
  }, scroller === "fill" ? { flex: "1 1 auto", minHeight: 0, overflowY: "auto" } : {});
736
+ const headerScrollerStyle = {
737
+ flex: "0 0 auto",
738
+ minWidth: 0,
739
+ overflow: "hidden",
740
+ scrollbarGutter: "stable"
741
+ };
696
742
  const tableStyle = __spreadValues({
697
743
  "--boneless-table-grid": grid
698
744
  }, scroller === "fill" ? { display: "flex", flexDirection: "column", flex: "1 1 auto", minHeight: 0 } : {});
699
745
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: cn(className, classNames.root), "data-slot": "root", style: rootStyle, children: [
700
746
  renderSlot(toolbar, table, defaultToolbar),
747
+ filterPlacement === "above" ? renderedFilters : null,
701
748
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
702
749
  "div",
703
750
  {
@@ -710,14 +757,10 @@ function BonelessTable(_a) {
710
757
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
711
758
  "div",
712
759
  {
760
+ className: classNames.headerScroller,
713
761
  "data-slot": "header-scroller",
714
762
  ref: headerScrollerRef,
715
- style: {
716
- flex: "0 0 auto",
717
- minWidth: 0,
718
- overflow: "hidden",
719
- paddingInlineEnd: headerScrollbarGutter || void 0
720
- },
763
+ style: headerScrollerStyle,
721
764
  children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
722
765
  "div",
723
766
  {
@@ -733,11 +776,10 @@ function BonelessTable(_a) {
733
776
  role: "row",
734
777
  style: { display: "grid", gridTemplateColumns: "var(--boneless-table-grid)" },
735
778
  children: headerGroup.headers.map((header) => {
736
- var _a3;
737
779
  const columnSettings = getColumnSettings(header.column);
738
780
  const direction = header.column.getIsSorted();
739
781
  const isSortable = !header.isPlaceholder && header.column.getCanSort() && columnSettings.sorting.enabled;
740
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
782
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
741
783
  "div",
742
784
  {
743
785
  className: classNames.header,
@@ -748,47 +790,28 @@ function BonelessTable(_a) {
748
790
  "aria-colspan": header.colSpan > 1 ? header.colSpan : void 0,
749
791
  "aria-sort": direction === "asc" ? "ascending" : direction === "desc" ? "descending" : isSortable ? "none" : void 0,
750
792
  style: { gridColumn: `span ${header.colSpan}` },
751
- children: [
752
- header.isPlaceholder ? null : isSortable ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
753
- "button",
754
- {
755
- className: classNames.headerButton,
756
- "data-align": columnSettings.align,
757
- "data-slot": "header-button",
758
- onClick: header.column.getToggleSortingHandler(),
759
- children: [
760
- (0, import_react_table.flexRender)(header.column.columnDef.header, header.getContext()),
761
- (icons == null ? void 0 : icons.sort) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
762
- "span",
763
- {
764
- className: classNames.sortIndicator,
765
- "data-align": columnSettings.align,
766
- "data-slot": "sort-indicator",
767
- "data-reveal": columnSettings.sorting.reveal,
768
- children: icons.sort(direction)
769
- }
770
- ) : null
771
- ]
772
- }
773
- ) : (0, import_react_table.flexRender)(header.column.columnDef.header, header.getContext()),
774
- !header.isPlaceholder && columnSettings.filtering ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
775
- "div",
776
- {
777
- className: classNames.filter,
778
- "data-slot": "filter",
779
- "data-reveal": (_a3 = columnSettings.filtering.reveal) != null ? _a3 : settings.interactions.filterReveal,
780
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
781
- ColumnFilter,
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",
782
804
  {
783
- column: header.column,
784
- settings: columnSettings.filtering,
785
- icon: icons == null ? void 0 : icons.search,
786
- debounceMs: filterDebounceMs
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)
787
810
  }
788
- )
789
- }
790
- ) : null
791
- ]
811
+ ) : null
812
+ ]
813
+ }
814
+ ) : (0, import_react_table.flexRender)(header.column.columnDef.header, header.getContext())
792
815
  },
793
816
  header.id
794
817
  );
@@ -803,11 +826,13 @@ function BonelessTable(_a) {
803
826
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
804
827
  "div",
805
828
  {
829
+ "aria-label": "Table rows",
806
830
  className: classNames.scroller,
807
831
  "data-slot": "scroller",
808
832
  ref: scrollerRef,
809
833
  onScroll: handleScroll,
810
834
  style: scrollerStyle,
835
+ tabIndex: 0,
811
836
  children: [
812
837
  isLoading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
813
838
  TableSkeleton,
@@ -949,6 +974,7 @@ function BonelessTable(_a) {
949
974
  ]
950
975
  }
951
976
  ),
977
+ filterPlacement === "below" ? renderedFilters : null,
952
978
  renderSlot(footer, table, defaultFooter)
953
979
  ] });
954
980
  }