@payglocal_ui/flux-ui 0.2.0 → 0.2.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.cjs +51 -29
- 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 +51 -29
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/data-table.tsx +105 -35
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
|
@@ -3605,6 +3605,7 @@ function DataTable({
|
|
|
3605
3605
|
className,
|
|
3606
3606
|
rowKey,
|
|
3607
3607
|
rowCta,
|
|
3608
|
+
rowAction,
|
|
3608
3609
|
density = "default",
|
|
3609
3610
|
tableLayout = "fixed",
|
|
3610
3611
|
theadClassName,
|
|
@@ -3617,9 +3618,18 @@ function DataTable({
|
|
|
3617
3618
|
const [internalPage, setInternalPage] = useState6(1);
|
|
3618
3619
|
const page = isControlled ? controlledPage : internalPage;
|
|
3619
3620
|
const setPage = isControlled ? (p) => onPageChange?.(p) : (p) => setInternalPage(p);
|
|
3621
|
+
const hasAction = rowAction != null || rowCta != null;
|
|
3622
|
+
const hasSpacer = tableLayout === "content";
|
|
3620
3623
|
const total = totalRows ?? data.length;
|
|
3621
3624
|
const totalPages = Math.ceil(total / pageSize);
|
|
3622
3625
|
const paginated = isControlled ? data : data.slice((page - 1) * pageSize, page * pageSize);
|
|
3626
|
+
const seenKeys = /* @__PURE__ */ new Map();
|
|
3627
|
+
const rowKeys = paginated.map((row) => {
|
|
3628
|
+
const base = rowKey(row);
|
|
3629
|
+
const seen = seenKeys.get(base) ?? 0;
|
|
3630
|
+
seenKeys.set(base, seen + 1);
|
|
3631
|
+
return seen === 0 ? base : `${base}__${seen}`;
|
|
3632
|
+
});
|
|
3623
3633
|
const comfortable = density === "comfortable";
|
|
3624
3634
|
const compact = density === "compact";
|
|
3625
3635
|
const compactCellPad = compact ? snug ? "pl-1.5 pr-2.5 py-2.5" : "px-3 py-2.5" : "px-4 py-3.5";
|
|
@@ -3627,7 +3637,7 @@ function DataTable({
|
|
|
3627
3637
|
const headPad = comfortable ? "px-5 py-4" : compactCellPad;
|
|
3628
3638
|
const footerPad = comfortable ? "px-5 py-4" : compact ? "px-4 py-2.5" : "px-4 py-3.5";
|
|
3629
3639
|
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";
|
|
3630
|
-
const
|
|
3640
|
+
const actionGutter = comfortable ? 20 : compact ? 12 : 16;
|
|
3631
3641
|
return /* @__PURE__ */ jsxs30(
|
|
3632
3642
|
"div",
|
|
3633
3643
|
{
|
|
@@ -3650,7 +3660,13 @@ function DataTable({
|
|
|
3650
3660
|
"table",
|
|
3651
3661
|
{
|
|
3652
3662
|
className: cn(tableLayout === "auto" && "min-w-[920px]"),
|
|
3653
|
-
style: {
|
|
3663
|
+
style: {
|
|
3664
|
+
// `content` uses the automatic algorithm but stays 100% wide; a
|
|
3665
|
+
// greedy spacer column (below) soaks up the slack so the data
|
|
3666
|
+
// columns collapse to their content width while the table fills.
|
|
3667
|
+
tableLayout: tableLayout === "fixed" ? "fixed" : "auto",
|
|
3668
|
+
width: "100%"
|
|
3669
|
+
},
|
|
3654
3670
|
children: [
|
|
3655
3671
|
tableLayout === "fixed" && /* @__PURE__ */ jsxs30("colgroup", { children: [
|
|
3656
3672
|
columns.map((col) => /* @__PURE__ */ jsx49(
|
|
@@ -3664,7 +3680,7 @@ function DataTable({
|
|
|
3664
3680
|
},
|
|
3665
3681
|
col.key
|
|
3666
3682
|
)),
|
|
3667
|
-
|
|
3683
|
+
hasAction ? /* @__PURE__ */ jsx49("col", { style: { width: 0 } }) : null
|
|
3668
3684
|
] }),
|
|
3669
3685
|
/* @__PURE__ */ jsx49(
|
|
3670
3686
|
"thead",
|
|
@@ -3696,7 +3712,8 @@ function DataTable({
|
|
|
3696
3712
|
},
|
|
3697
3713
|
col.key
|
|
3698
3714
|
)),
|
|
3699
|
-
|
|
3715
|
+
hasSpacer ? /* @__PURE__ */ jsx49("th", { className: "w-full p-0", "aria-hidden": true }) : null,
|
|
3716
|
+
hasAction ? /* @__PURE__ */ jsx49("th", { className: "sticky right-0 z-[1] w-0 p-0", "aria-hidden": true }) : null
|
|
3700
3717
|
]
|
|
3701
3718
|
}
|
|
3702
3719
|
)
|
|
@@ -3705,12 +3722,12 @@ function DataTable({
|
|
|
3705
3722
|
/* @__PURE__ */ jsx49("tbody", { children: isLoading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ jsx49(
|
|
3706
3723
|
TableRowSkeleton,
|
|
3707
3724
|
{
|
|
3708
|
-
cols: columns.length
|
|
3725
|
+
cols: columns.length,
|
|
3709
3726
|
density,
|
|
3710
3727
|
snug
|
|
3711
3728
|
},
|
|
3712
3729
|
i
|
|
3713
|
-
)) : paginated.length === 0 ? /* @__PURE__ */ jsx49("tr", { children: /* @__PURE__ */ jsx49("td", { colSpan: columns.length + (
|
|
3730
|
+
)) : 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(
|
|
3714
3731
|
"tr",
|
|
3715
3732
|
{
|
|
3716
3733
|
className: cn(
|
|
@@ -3718,7 +3735,7 @@ function DataTable({
|
|
|
3718
3735
|
comfortable && "min-h-[56px]",
|
|
3719
3736
|
compact && "min-h-[44px]",
|
|
3720
3737
|
"hover:bg-muted/40 dark:hover:bg-muted/25",
|
|
3721
|
-
|
|
3738
|
+
hasAction && "hover:shadow-[0_1px_0_rgba(0,0,0,0.04)] dark:hover:shadow-none"
|
|
3722
3739
|
),
|
|
3723
3740
|
children: [
|
|
3724
3741
|
columns.map((col) => /* @__PURE__ */ jsx49(
|
|
@@ -3742,31 +3759,36 @@ function DataTable({
|
|
|
3742
3759
|
},
|
|
3743
3760
|
col.key
|
|
3744
3761
|
)),
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3762
|
+
hasSpacer ? /* @__PURE__ */ jsx49("td", { className: "p-0", "aria-hidden": true }) : null,
|
|
3763
|
+
hasAction ? (
|
|
3764
|
+
// Zero-width sticky cell pinned to the right edge of the
|
|
3765
|
+
// viewport. Its children are positioned absolutely so they
|
|
3766
|
+
// float over the row (out of the 0-width cell) — the action
|
|
3767
|
+
// stays in view while scrolling and nothing trails the last
|
|
3768
|
+
// data column. Everything is revealed on hover only.
|
|
3769
|
+
/* @__PURE__ */ jsx49("td", { className: "sticky right-0 z-[1] w-0 p-0 align-middle", children: /* @__PURE__ */ jsx49(
|
|
3770
|
+
"span",
|
|
3771
|
+
{
|
|
3772
|
+
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",
|
|
3773
|
+
style: { right: actionGutter },
|
|
3774
|
+
children: rowAction != null ? typeof rowAction === "function" ? rowAction(row, i) : rowAction : /* @__PURE__ */ jsx49(
|
|
3775
|
+
"button",
|
|
3776
|
+
{
|
|
3777
|
+
type: "button",
|
|
3778
|
+
onClick: () => rowCta?.onClick?.(row),
|
|
3779
|
+
className: cn(
|
|
3780
|
+
"inline-flex items-center font-medium text-foreground bg-card rounded-lg border border-border hover:border-muted-foreground/50 whitespace-nowrap shadow-sm",
|
|
3781
|
+
compact ? "px-2.5 py-1 text-[11px]" : "px-3 py-1.5 text-[12px]"
|
|
3782
|
+
),
|
|
3783
|
+
children: rowCta?.label
|
|
3784
|
+
}
|
|
3785
|
+
)
|
|
3786
|
+
}
|
|
3787
|
+
) })
|
|
3766
3788
|
) : null
|
|
3767
3789
|
]
|
|
3768
3790
|
},
|
|
3769
|
-
|
|
3791
|
+
rowKeys[i]
|
|
3770
3792
|
)) })
|
|
3771
3793
|
]
|
|
3772
3794
|
}
|