@payglocal_ui/flux-ui 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +44 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -3
- package/dist/index.d.ts +24 -3
- package/dist/index.js +45 -28
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/data-table.tsx +92 -34
package/dist/index.d.cts
CHANGED
|
@@ -777,10 +777,31 @@ interface DataTableProps<T> {
|
|
|
777
777
|
label: string;
|
|
778
778
|
onClick?: (row: T) => void;
|
|
779
779
|
};
|
|
780
|
+
/**
|
|
781
|
+
* Custom action revealed on row hover — typically a `<Button>` or
|
|
782
|
+
* `<ButtonGroup>`, but any `ReactNode` is accepted. Pass a **function** to
|
|
783
|
+
* render per-row: it receives `(row, index)`, so the action always has the
|
|
784
|
+
* record for its row (e.g. to navigate or open a drawer for that row).
|
|
785
|
+
*
|
|
786
|
+
* It is not a real column: it floats as an overlay **pinned to the right edge
|
|
787
|
+
* of the viewport**, so it stays in view as the table scrolls horizontally
|
|
788
|
+
* (no scrolling to the end to reach it) while the last data column stays
|
|
789
|
+
* flush with nothing trailing it. Takes precedence over `rowCta`.
|
|
790
|
+
*/
|
|
791
|
+
rowAction?: ReactNode | ((row: T, index: number) => ReactNode);
|
|
780
792
|
/** Row / cell vertical rhythm and horizontal gutters */
|
|
781
793
|
density?: DataTableDensity;
|
|
782
|
-
/**
|
|
783
|
-
|
|
794
|
+
/**
|
|
795
|
+
* Column-sizing strategy:
|
|
796
|
+
* - `fixed` — widths come only from `colgroup` hints (`width`/`minWidth`/
|
|
797
|
+
* `maxWidth`); content is ignored and overflow is clipped. Table fills 100%.
|
|
798
|
+
* - `auto` — columns size to content but the table still fills 100%, so any
|
|
799
|
+
* leftover space is distributed into the columns (they stretch).
|
|
800
|
+
* - `content` — columns size to their content's intrinsic width and the table
|
|
801
|
+
* shrinks to fit. Leftover space stays empty to the right of the last
|
|
802
|
+
* column; it scrolls horizontally only once content exceeds the container.
|
|
803
|
+
*/
|
|
804
|
+
tableLayout?: "auto" | "fixed" | "content";
|
|
784
805
|
theadClassName?: string;
|
|
785
806
|
headerStyle?: DataTableHeaderStyle;
|
|
786
807
|
/** Footer: paginated range vs simple `n items` */
|
|
@@ -793,7 +814,7 @@ interface DataTableProps<T> {
|
|
|
793
814
|
/** With `density="compact"`, use tighter cell gutters (`pl-1.5 pr-2.5` vs `px-3`). Footer keeps normal horizontal padding. */
|
|
794
815
|
snug?: boolean;
|
|
795
816
|
}
|
|
796
|
-
declare function DataTable<T>({ columns, data, isLoading, skeletonRows, emptyTitle, emptyDescription, pageSize, page: controlledPage, onPageChange, totalRows, className, rowKey, rowCta, density, tableLayout, theadClassName, headerStyle, footerSummary, footerCountLabels, snug, }: DataTableProps<T>): React$1.JSX.Element;
|
|
817
|
+
declare function DataTable<T>({ columns, data, isLoading, skeletonRows, emptyTitle, emptyDescription, pageSize, page: controlledPage, onPageChange, totalRows, className, rowKey, rowCta, rowAction, density, tableLayout, theadClassName, headerStyle, footerSummary, footerCountLabels, snug, }: DataTableProps<T>): React$1.JSX.Element;
|
|
797
818
|
|
|
798
819
|
interface EmptyStateProps {
|
|
799
820
|
icon?: LucideIcon;
|
package/dist/index.d.ts
CHANGED
|
@@ -777,10 +777,31 @@ interface DataTableProps<T> {
|
|
|
777
777
|
label: string;
|
|
778
778
|
onClick?: (row: T) => void;
|
|
779
779
|
};
|
|
780
|
+
/**
|
|
781
|
+
* Custom action revealed on row hover — typically a `<Button>` or
|
|
782
|
+
* `<ButtonGroup>`, but any `ReactNode` is accepted. Pass a **function** to
|
|
783
|
+
* render per-row: it receives `(row, index)`, so the action always has the
|
|
784
|
+
* record for its row (e.g. to navigate or open a drawer for that row).
|
|
785
|
+
*
|
|
786
|
+
* It is not a real column: it floats as an overlay **pinned to the right edge
|
|
787
|
+
* of the viewport**, so it stays in view as the table scrolls horizontally
|
|
788
|
+
* (no scrolling to the end to reach it) while the last data column stays
|
|
789
|
+
* flush with nothing trailing it. Takes precedence over `rowCta`.
|
|
790
|
+
*/
|
|
791
|
+
rowAction?: ReactNode | ((row: T, index: number) => ReactNode);
|
|
780
792
|
/** Row / cell vertical rhythm and horizontal gutters */
|
|
781
793
|
density?: DataTableDensity;
|
|
782
|
-
/**
|
|
783
|
-
|
|
794
|
+
/**
|
|
795
|
+
* Column-sizing strategy:
|
|
796
|
+
* - `fixed` — widths come only from `colgroup` hints (`width`/`minWidth`/
|
|
797
|
+
* `maxWidth`); content is ignored and overflow is clipped. Table fills 100%.
|
|
798
|
+
* - `auto` — columns size to content but the table still fills 100%, so any
|
|
799
|
+
* leftover space is distributed into the columns (they stretch).
|
|
800
|
+
* - `content` — columns size to their content's intrinsic width and the table
|
|
801
|
+
* shrinks to fit. Leftover space stays empty to the right of the last
|
|
802
|
+
* column; it scrolls horizontally only once content exceeds the container.
|
|
803
|
+
*/
|
|
804
|
+
tableLayout?: "auto" | "fixed" | "content";
|
|
784
805
|
theadClassName?: string;
|
|
785
806
|
headerStyle?: DataTableHeaderStyle;
|
|
786
807
|
/** Footer: paginated range vs simple `n items` */
|
|
@@ -793,7 +814,7 @@ interface DataTableProps<T> {
|
|
|
793
814
|
/** With `density="compact"`, use tighter cell gutters (`pl-1.5 pr-2.5` vs `px-3`). Footer keeps normal horizontal padding. */
|
|
794
815
|
snug?: boolean;
|
|
795
816
|
}
|
|
796
|
-
declare function DataTable<T>({ columns, data, isLoading, skeletonRows, emptyTitle, emptyDescription, pageSize, page: controlledPage, onPageChange, totalRows, className, rowKey, rowCta, density, tableLayout, theadClassName, headerStyle, footerSummary, footerCountLabels, snug, }: DataTableProps<T>): React$1.JSX.Element;
|
|
817
|
+
declare function DataTable<T>({ columns, data, isLoading, skeletonRows, emptyTitle, emptyDescription, pageSize, page: controlledPage, onPageChange, totalRows, className, rowKey, rowCta, rowAction, density, tableLayout, theadClassName, headerStyle, footerSummary, footerCountLabels, snug, }: DataTableProps<T>): React$1.JSX.Element;
|
|
797
818
|
|
|
798
819
|
interface EmptyStateProps {
|
|
799
820
|
icon?: LucideIcon;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
// src/utils.ts
|
|
2
4
|
import { clsx } from "clsx";
|
|
3
5
|
import { twMerge } from "tailwind-merge";
|
|
@@ -3605,6 +3607,7 @@ function DataTable({
|
|
|
3605
3607
|
className,
|
|
3606
3608
|
rowKey,
|
|
3607
3609
|
rowCta,
|
|
3610
|
+
rowAction,
|
|
3608
3611
|
density = "default",
|
|
3609
3612
|
tableLayout = "fixed",
|
|
3610
3613
|
theadClassName,
|
|
@@ -3617,6 +3620,8 @@ function DataTable({
|
|
|
3617
3620
|
const [internalPage, setInternalPage] = useState6(1);
|
|
3618
3621
|
const page = isControlled ? controlledPage : internalPage;
|
|
3619
3622
|
const setPage = isControlled ? (p) => onPageChange?.(p) : (p) => setInternalPage(p);
|
|
3623
|
+
const hasAction = rowAction != null || rowCta != null;
|
|
3624
|
+
const hasSpacer = tableLayout === "content";
|
|
3620
3625
|
const total = totalRows ?? data.length;
|
|
3621
3626
|
const totalPages = Math.ceil(total / pageSize);
|
|
3622
3627
|
const paginated = isControlled ? data : data.slice((page - 1) * pageSize, page * pageSize);
|
|
@@ -3634,7 +3639,7 @@ function DataTable({
|
|
|
3634
3639
|
const headPad = comfortable ? "px-5 py-4" : compactCellPad;
|
|
3635
3640
|
const footerPad = comfortable ? "px-5 py-4" : compact ? "px-4 py-2.5" : "px-4 py-3.5";
|
|
3636
3641
|
const headText = comfortable ? "text-[12px] font-medium text-muted-foreground tracking-normal" : compact ? "text-[11px] font-semibold text-muted-foreground" : "text-[11px] font-semibold text-foreground/75 dark:text-foreground/85";
|
|
3637
|
-
const
|
|
3642
|
+
const actionGutter = comfortable ? 20 : compact ? 12 : 16;
|
|
3638
3643
|
return /* @__PURE__ */ jsxs30(
|
|
3639
3644
|
"div",
|
|
3640
3645
|
{
|
|
@@ -3657,7 +3662,13 @@ function DataTable({
|
|
|
3657
3662
|
"table",
|
|
3658
3663
|
{
|
|
3659
3664
|
className: cn(tableLayout === "auto" && "min-w-[920px]"),
|
|
3660
|
-
style: {
|
|
3665
|
+
style: {
|
|
3666
|
+
// `content` uses the automatic algorithm but stays 100% wide; a
|
|
3667
|
+
// greedy spacer column (below) soaks up the slack so the data
|
|
3668
|
+
// columns collapse to their content width while the table fills.
|
|
3669
|
+
tableLayout: tableLayout === "fixed" ? "fixed" : "auto",
|
|
3670
|
+
width: "100%"
|
|
3671
|
+
},
|
|
3661
3672
|
children: [
|
|
3662
3673
|
tableLayout === "fixed" && /* @__PURE__ */ jsxs30("colgroup", { children: [
|
|
3663
3674
|
columns.map((col) => /* @__PURE__ */ jsx49(
|
|
@@ -3671,7 +3682,7 @@ function DataTable({
|
|
|
3671
3682
|
},
|
|
3672
3683
|
col.key
|
|
3673
3684
|
)),
|
|
3674
|
-
|
|
3685
|
+
hasAction ? /* @__PURE__ */ jsx49("col", { style: { width: 0 } }) : null
|
|
3675
3686
|
] }),
|
|
3676
3687
|
/* @__PURE__ */ jsx49(
|
|
3677
3688
|
"thead",
|
|
@@ -3703,7 +3714,8 @@ function DataTable({
|
|
|
3703
3714
|
},
|
|
3704
3715
|
col.key
|
|
3705
3716
|
)),
|
|
3706
|
-
|
|
3717
|
+
hasSpacer ? /* @__PURE__ */ jsx49("th", { className: "w-full p-0", "aria-hidden": true }) : null,
|
|
3718
|
+
hasAction ? /* @__PURE__ */ jsx49("th", { className: "sticky right-0 z-[1] w-0 p-0", "aria-hidden": true }) : null
|
|
3707
3719
|
]
|
|
3708
3720
|
}
|
|
3709
3721
|
)
|
|
@@ -3712,12 +3724,12 @@ function DataTable({
|
|
|
3712
3724
|
/* @__PURE__ */ jsx49("tbody", { children: isLoading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ jsx49(
|
|
3713
3725
|
TableRowSkeleton,
|
|
3714
3726
|
{
|
|
3715
|
-
cols: columns.length
|
|
3727
|
+
cols: columns.length,
|
|
3716
3728
|
density,
|
|
3717
3729
|
snug
|
|
3718
3730
|
},
|
|
3719
3731
|
i
|
|
3720
|
-
)) : paginated.length === 0 ? /* @__PURE__ */ jsx49("tr", { children: /* @__PURE__ */ jsx49("td", { colSpan: columns.length + (
|
|
3732
|
+
)) : paginated.length === 0 ? /* @__PURE__ */ jsx49("tr", { children: /* @__PURE__ */ jsx49("td", { colSpan: columns.length + (hasSpacer ? 1 : 0) + (hasAction ? 1 : 0), children: /* @__PURE__ */ jsx49(EmptyState, { title: emptyTitle, description: emptyDescription }) }) }) : paginated.map((row, i) => /* @__PURE__ */ jsxs30(
|
|
3721
3733
|
"tr",
|
|
3722
3734
|
{
|
|
3723
3735
|
className: cn(
|
|
@@ -3725,7 +3737,7 @@ function DataTable({
|
|
|
3725
3737
|
comfortable && "min-h-[56px]",
|
|
3726
3738
|
compact && "min-h-[44px]",
|
|
3727
3739
|
"hover:bg-muted/40 dark:hover:bg-muted/25",
|
|
3728
|
-
|
|
3740
|
+
hasAction && "hover:shadow-[0_1px_0_rgba(0,0,0,0.04)] dark:hover:shadow-none"
|
|
3729
3741
|
),
|
|
3730
3742
|
children: [
|
|
3731
3743
|
columns.map((col) => /* @__PURE__ */ jsx49(
|
|
@@ -3749,27 +3761,32 @@ function DataTable({
|
|
|
3749
3761
|
},
|
|
3750
3762
|
col.key
|
|
3751
3763
|
)),
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3764
|
+
hasSpacer ? /* @__PURE__ */ jsx49("td", { className: "p-0", "aria-hidden": true }) : null,
|
|
3765
|
+
hasAction ? (
|
|
3766
|
+
// Zero-width sticky cell pinned to the right edge of the
|
|
3767
|
+
// viewport. Its children are positioned absolutely so they
|
|
3768
|
+
// float over the row (out of the 0-width cell) — the action
|
|
3769
|
+
// stays in view while scrolling and nothing trails the last
|
|
3770
|
+
// data column. Everything is revealed on hover only.
|
|
3771
|
+
/* @__PURE__ */ jsx49("td", { className: "sticky right-0 z-[1] w-0 p-0 align-middle", children: /* @__PURE__ */ jsx49(
|
|
3772
|
+
"span",
|
|
3773
|
+
{
|
|
3774
|
+
className: "absolute top-1/2 -translate-y-1/2 z-[1] inline-flex items-center opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100",
|
|
3775
|
+
style: { right: actionGutter },
|
|
3776
|
+
children: rowAction != null ? typeof rowAction === "function" ? rowAction(row, i) : rowAction : /* @__PURE__ */ jsx49(
|
|
3777
|
+
"button",
|
|
3778
|
+
{
|
|
3779
|
+
type: "button",
|
|
3780
|
+
onClick: () => rowCta?.onClick?.(row),
|
|
3781
|
+
className: cn(
|
|
3782
|
+
"inline-flex items-center font-medium text-foreground bg-card rounded-lg border border-border hover:border-muted-foreground/50 whitespace-nowrap shadow-sm",
|
|
3783
|
+
compact ? "px-2.5 py-1 text-[11px]" : "px-3 py-1.5 text-[12px]"
|
|
3784
|
+
),
|
|
3785
|
+
children: rowCta?.label
|
|
3786
|
+
}
|
|
3787
|
+
)
|
|
3788
|
+
}
|
|
3789
|
+
) })
|
|
3773
3790
|
) : null
|
|
3774
3791
|
]
|
|
3775
3792
|
},
|