@facter/ds-core 1.23.0 → 1.24.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.d.mts CHANGED
@@ -398,11 +398,15 @@ interface DataTableContentProps {
398
398
  /**
399
399
  * Habilita scroll vertical com altura calculada automaticamente.
400
400
  * O header das colunas fica sticky e apenas as rows fazem scroll.
401
- * O bottomOffset controla a margem inferior (default: 16px).
402
401
  */
403
402
  scrollable?: boolean;
404
- /** Margem inferior em px para o cálculo de altura automática (default: 16) */
403
+ /** Margem inferior em px para o cálculo de altura automática (default: 68) */
405
404
  scrollBottomOffset?: number;
405
+ /**
406
+ * Calcula automaticamente o número de rows por página baseado na altura disponível.
407
+ * Mede do início do tbody até o final do viewport, descontando pagination e margem.
408
+ */
409
+ autoPageSize?: boolean;
406
410
  /** Custom className */
407
411
  className?: string;
408
412
  }
@@ -2718,15 +2722,11 @@ declare function useAvailableHeight<T extends HTMLElement = HTMLDivElement>(opti
2718
2722
  };
2719
2723
 
2720
2724
  interface UseAutoPageSizeOptions {
2721
- /** Height of each row in pixels (default: 49 — default density + border) */
2725
+ /** Height of each row in pixels (default: 49) */
2722
2726
  rowHeight?: number;
2723
- /** Height of the column header in pixels (default: 41) */
2724
- headerHeight?: number;
2725
- /** Height of the pagination bar in pixels (default: 52) */
2726
- paginationHeight?: number;
2727
- /** Extra bottom offset in pixels (default: 16) */
2727
+ /** Extra offset below the table in pixels — pagination, margins, etc (default: 64) */
2728
2728
  bottomOffset?: number;
2729
- /** Minimum rows per page (default: 5) */
2729
+ /** Minimum rows per page (default: 3) */
2730
2730
  minRows?: number;
2731
2731
  /** Maximum rows per page (default: 50) */
2732
2732
  maxRows?: number;
@@ -2737,22 +2737,11 @@ interface UseAutoPageSizeOptions {
2737
2737
  * Hook that calculates the optimal number of rows per page
2738
2738
  * based on the available viewport height.
2739
2739
  *
2740
- * Returns the calculated perPage as default. If the user manually
2741
- * changes the page size, respects their choice.
2740
+ * The ref should point to the element where rows START (e.g. tbody container).
2741
+ * The hook measures from ref.top to viewport bottom, subtracts bottomOffset,
2742
+ * and divides by rowHeight.
2742
2743
  *
2743
- * @example
2744
- * ```tsx
2745
- * function MyTable() {
2746
- * const { ref, perPage, setPerPage } = useAutoPageSize()
2747
- * return (
2748
- * <div ref={ref}>
2749
- * <DataTable data={data} columns={columns}>
2750
- * <DataTable.Pagination onPageSizeChange={setPerPage} />
2751
- * </DataTable>
2752
- * </div>
2753
- * )
2754
- * }
2755
- * ```
2744
+ * If the user manually changes page size, their choice is respected.
2756
2745
  */
2757
2746
  declare function useAutoPageSize<T extends HTMLElement = HTMLDivElement>(options?: UseAutoPageSizeOptions): {
2758
2747
  ref: React$1.RefObject<T | null>;
@@ -2760,7 +2749,6 @@ declare function useAutoPageSize<T extends HTMLElement = HTMLDivElement>(options
2760
2749
  setPerPage: (size: number) => void;
2761
2750
  autoPerPage: number;
2762
2751
  isAutoSized: boolean;
2763
- isReady: boolean;
2764
2752
  };
2765
2753
 
2766
2754
  type Theme = 'dark' | 'light' | 'system';
package/dist/index.d.ts CHANGED
@@ -398,11 +398,15 @@ interface DataTableContentProps {
398
398
  /**
399
399
  * Habilita scroll vertical com altura calculada automaticamente.
400
400
  * O header das colunas fica sticky e apenas as rows fazem scroll.
401
- * O bottomOffset controla a margem inferior (default: 16px).
402
401
  */
403
402
  scrollable?: boolean;
404
- /** Margem inferior em px para o cálculo de altura automática (default: 16) */
403
+ /** Margem inferior em px para o cálculo de altura automática (default: 68) */
405
404
  scrollBottomOffset?: number;
405
+ /**
406
+ * Calcula automaticamente o número de rows por página baseado na altura disponível.
407
+ * Mede do início do tbody até o final do viewport, descontando pagination e margem.
408
+ */
409
+ autoPageSize?: boolean;
406
410
  /** Custom className */
407
411
  className?: string;
408
412
  }
@@ -2718,15 +2722,11 @@ declare function useAvailableHeight<T extends HTMLElement = HTMLDivElement>(opti
2718
2722
  };
2719
2723
 
2720
2724
  interface UseAutoPageSizeOptions {
2721
- /** Height of each row in pixels (default: 49 — default density + border) */
2725
+ /** Height of each row in pixels (default: 49) */
2722
2726
  rowHeight?: number;
2723
- /** Height of the column header in pixels (default: 41) */
2724
- headerHeight?: number;
2725
- /** Height of the pagination bar in pixels (default: 52) */
2726
- paginationHeight?: number;
2727
- /** Extra bottom offset in pixels (default: 16) */
2727
+ /** Extra offset below the table in pixels — pagination, margins, etc (default: 64) */
2728
2728
  bottomOffset?: number;
2729
- /** Minimum rows per page (default: 5) */
2729
+ /** Minimum rows per page (default: 3) */
2730
2730
  minRows?: number;
2731
2731
  /** Maximum rows per page (default: 50) */
2732
2732
  maxRows?: number;
@@ -2737,22 +2737,11 @@ interface UseAutoPageSizeOptions {
2737
2737
  * Hook that calculates the optimal number of rows per page
2738
2738
  * based on the available viewport height.
2739
2739
  *
2740
- * Returns the calculated perPage as default. If the user manually
2741
- * changes the page size, respects their choice.
2740
+ * The ref should point to the element where rows START (e.g. tbody container).
2741
+ * The hook measures from ref.top to viewport bottom, subtracts bottomOffset,
2742
+ * and divides by rowHeight.
2742
2743
  *
2743
- * @example
2744
- * ```tsx
2745
- * function MyTable() {
2746
- * const { ref, perPage, setPerPage } = useAutoPageSize()
2747
- * return (
2748
- * <div ref={ref}>
2749
- * <DataTable data={data} columns={columns}>
2750
- * <DataTable.Pagination onPageSizeChange={setPerPage} />
2751
- * </DataTable>
2752
- * </div>
2753
- * )
2754
- * }
2755
- * ```
2744
+ * If the user manually changes page size, their choice is respected.
2756
2745
  */
2757
2746
  declare function useAutoPageSize<T extends HTMLElement = HTMLDivElement>(options?: UseAutoPageSizeOptions): {
2758
2747
  ref: React$1.RefObject<T | null>;
@@ -2760,7 +2749,6 @@ declare function useAutoPageSize<T extends HTMLElement = HTMLDivElement>(options
2760
2749
  setPerPage: (size: number) => void;
2761
2750
  autoPerPage: number;
2762
2751
  isAutoSized: boolean;
2763
- isReady: boolean;
2764
2752
  };
2765
2753
 
2766
2754
  type Theme = 'dark' | 'light' | 'system';
package/dist/index.js CHANGED
@@ -1455,27 +1455,23 @@ function useAvailableHeight(options = {}) {
1455
1455
  function useAutoPageSize(options = {}) {
1456
1456
  const {
1457
1457
  rowHeight = 49,
1458
- headerHeight = 41,
1459
- paginationHeight = 52,
1460
- bottomOffset = 16,
1461
- minRows = 5,
1458
+ bottomOffset = 64,
1459
+ minRows = 3,
1462
1460
  maxRows = 50,
1463
1461
  enabled = true
1464
1462
  } = options;
1465
1463
  const ref = React10.useRef(null);
1466
1464
  const [autoPerPage, setAutoPerPage] = React10.useState(minRows);
1467
1465
  const [userOverride, setUserOverride] = React10.useState(null);
1468
- const hasCalculated = React10.useRef(false);
1469
1466
  const calculate = React10.useCallback(() => {
1470
1467
  const el = ref.current;
1471
1468
  if (!el || !enabled) return;
1472
1469
  const rect = el.getBoundingClientRect();
1473
- const availableHeight = window.innerHeight - rect.top - headerHeight - paginationHeight - bottomOffset;
1470
+ const availableHeight = window.innerHeight - rect.top - bottomOffset;
1474
1471
  const rows = Math.floor(availableHeight / rowHeight);
1475
1472
  const clamped = Math.max(minRows, Math.min(maxRows, rows));
1476
1473
  setAutoPerPage(clamped);
1477
- hasCalculated.current = true;
1478
- }, [rowHeight, headerHeight, paginationHeight, bottomOffset, minRows, maxRows, enabled]);
1474
+ }, [rowHeight, bottomOffset, minRows, maxRows, enabled]);
1479
1475
  React10.useEffect(() => {
1480
1476
  if (!enabled) return;
1481
1477
  const frame = requestAnimationFrame(calculate);
@@ -1488,14 +1484,12 @@ function useAutoPageSize(options = {}) {
1488
1484
  const setPerPage = React10.useCallback((size) => {
1489
1485
  setUserOverride(size);
1490
1486
  }, []);
1491
- const perPage = userOverride ?? autoPerPage;
1492
1487
  return {
1493
1488
  ref,
1494
- perPage,
1489
+ perPage: userOverride ?? autoPerPage,
1495
1490
  setPerPage,
1496
1491
  autoPerPage,
1497
- isAutoSized: userOverride === null,
1498
- isReady: hasCalculated.current
1492
+ isAutoSized: userOverride === null
1499
1493
  };
1500
1494
  }
1501
1495
  var Table = React10__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -1583,6 +1577,7 @@ var DataTableContent = React10__namespace.memo(function DataTableContent2({
1583
1577
  onRowClick,
1584
1578
  scrollable = false,
1585
1579
  scrollBottomOffset = 68,
1580
+ autoPageSize = false,
1586
1581
  className
1587
1582
  }) {
1588
1583
  const table = useDataTable();
@@ -1590,15 +1585,36 @@ var DataTableContent = React10__namespace.memo(function DataTableContent2({
1590
1585
  const { density } = useDataTableDensity();
1591
1586
  const { config: emptyStateConfig } = useDataTableEmptyStateConfig();
1592
1587
  const { isLoading, skeletonRows } = useDataTableLoadingState();
1593
- const { ref, style: scrollStyle } = useAvailableHeight({
1588
+ const { setPageSize } = useDataTablePagination();
1589
+ const tbodyRef = React10__namespace.useRef(null);
1590
+ const { ref: scrollRef, style: scrollStyle } = useAvailableHeight({
1594
1591
  bottomOffset: scrollBottomOffset,
1595
1592
  enabled: scrollable
1596
1593
  });
1597
1594
  const densityStyles = DENSITY_CONFIG[density];
1595
+ const rowHeight = densityStyles.rowHeight + 1;
1598
1596
  const cellClasses = cn(densityStyles.padding, densityStyles.fontSize);
1599
1597
  const columnCount = table.getVisibleLeafColumns().length;
1600
1598
  const hasRows = table.getRowModel().rows?.length > 0;
1601
1599
  const effectiveStickyHeader = stickyHeader || scrollable;
1600
+ React10__namespace.useEffect(() => {
1601
+ if (!autoPageSize) return;
1602
+ const calculate = () => {
1603
+ const tbody = tbodyRef.current;
1604
+ if (!tbody) return;
1605
+ const rect = tbody.getBoundingClientRect();
1606
+ const available = window.innerHeight - rect.top - 68;
1607
+ const rows = Math.floor(available / rowHeight);
1608
+ const clamped = Math.max(3, Math.min(50, rows));
1609
+ setPageSize(clamped);
1610
+ };
1611
+ const frame = requestAnimationFrame(calculate);
1612
+ window.addEventListener("resize", calculate);
1613
+ return () => {
1614
+ cancelAnimationFrame(frame);
1615
+ window.removeEventListener("resize", calculate);
1616
+ };
1617
+ }, [autoPageSize, rowHeight, setPageSize]);
1602
1618
  if (!hasRows && isEmpty && !isLoading) {
1603
1619
  return /* @__PURE__ */ jsxRuntime.jsx(
1604
1620
  EmptyState,
@@ -1613,7 +1629,7 @@ var DataTableContent = React10__namespace.memo(function DataTableContent2({
1613
1629
  return /* @__PURE__ */ jsxRuntime.jsx(
1614
1630
  "div",
1615
1631
  {
1616
- ref,
1632
+ ref: scrollRef,
1617
1633
  className: cn("rounded-md overflow-auto bg-card", className),
1618
1634
  style: scrollStyle,
1619
1635
  children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
@@ -1637,7 +1653,7 @@ var DataTableContent = React10__namespace.memo(function DataTableContent2({
1637
1653
  )) }, headerGroup.id))
1638
1654
  }
1639
1655
  ),
1640
- /* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: isLoading ? Array.from({ length: skeletonRows }).map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(TableRow, { className: "animate-pulse", children: Array.from({ length: columnCount || 4 }).map((_2, colIndex) => /* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: cellClasses, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded w-3/4" }) }, colIndex)) }, `skeleton-${index}`)) : table.getRowModel().rows.map((row, index) => /* @__PURE__ */ jsxRuntime.jsx(
1656
+ /* @__PURE__ */ jsxRuntime.jsx(TableBody, { ref: tbodyRef, children: isLoading ? Array.from({ length: skeletonRows }).map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(TableRow, { className: "animate-pulse", children: Array.from({ length: columnCount || 4 }).map((_2, colIndex) => /* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: cellClasses, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded w-3/4" }) }, colIndex)) }, `skeleton-${index}`)) : table.getRowModel().rows.map((row, index) => /* @__PURE__ */ jsxRuntime.jsx(
1641
1657
  TableRow,
1642
1658
  {
1643
1659
  "data-state": row.getIsSelected() && "selected",