@bilalsino/react-tanstack-data-table
Version:
Reusable React data table component with sorting, filtering, and pagination
1,392 lines (1,368 loc) • 63.1 kB
JavaScript
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
// src/components/CustomTable/index.tsx
import {
getCoreRowModel,
getFacetedMinMaxValues,
getFacetedRowModel,
getFacetedUniqueValues,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable
} from "@tanstack/react-table";
import { useEffect as useEffect2, useRef, useState as useState3, useMemo } from "react";
import { useVirtualizer } from "@tanstack/react-virtual";
import { AlertTriangle } from "lucide-react";
// src/lib/utils.ts
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
function cn(...inputs) {
return twMerge(clsx(inputs));
}
// src/components/ui/table.tsx
import {
forwardRef
} from "react";
import { jsx } from "react/jsx-runtime";
var Table = forwardRef(
(_a, ref) => {
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
return /* @__PURE__ */ jsx(
"div",
__spreadValues({
ref,
className: cn(
"caption-bottom text-sm flex-1 inline-table w-full relative",
className
)
}, props)
);
}
);
Table.displayName = "Table";
var TableHeader = forwardRef((_a, ref) => {
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
return /* @__PURE__ */ jsx(
"div",
__spreadValues({
ref,
className: cn(
"sticky top-0 h-12 z-20 w-full bg-zinc-100 rounded-xl",
className
)
}, props)
);
});
TableHeader.displayName = "TableHeader";
var TableBody = forwardRef((_a, ref) => {
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
return /* @__PURE__ */ jsx("div", __spreadValues({ ref, className: cn("relative", className) }, props));
});
TableBody.displayName = "TableBody";
var TableFooter = forwardRef((_a, ref) => {
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
return /* @__PURE__ */ jsx(
"tfoot",
__spreadValues({
ref,
className: cn(
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
className
)
}, props)
);
});
TableFooter.displayName = "TableFooter";
var TableRow = forwardRef((_a, ref) => {
var _b = _a, { className, isSticky } = _b, props = __objRest(_b, ["className", "isSticky"]);
return /* @__PURE__ */ jsx(
"div",
__spreadValues({
ref,
className: cn(
"transition-colors relative hover:text-zinc-800 data-[state=selected]:bg-white flex group",
isSticky && "sticky top-0",
className
)
}, props)
);
});
TableRow.displayName = "TableRow";
var TableHead = forwardRef((_a, ref) => {
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
return /* @__PURE__ */ jsx(
"div",
__spreadValues({
ref,
className: cn(
"bg-gray-200 text-left align-middle font-medium text-base text-gray-800 flex items-center flex-shrink-0 last:rounded-r-lg first:rounded-l-lg md:first:pl-6 md:last:pr-6 last:flex-1 justify-end",
className
)
}, props)
);
});
TableHead.displayName = "TableHead";
var TableCell = forwardRef((_a, ref) => {
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
return /* @__PURE__ */ jsx(
"div",
__spreadValues({
ref,
className: cn(
"align-middle text-gray-800 flex flex-shrink-0 bg-white group-hover:bg-gray-100 group-hover:text-zinc-800 last:rounded-r-lg first:rounded-l-lg md:first:pl-6 md:last:pr-6 last:flex-1 justify-end",
className
)
}, props)
);
});
TableCell.displayName = "TableCell";
var TableCaption = forwardRef((_a, ref) => {
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
return /* @__PURE__ */ jsx(
"caption",
__spreadValues({
ref,
className: cn("mt-4 text-sm text-zinc-600 break-all", className)
}, props)
);
});
TableCaption.displayName = "TableCaption";
// src/components/Loading/Loading.tsx
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
var Loading = (_a) => {
var props = __objRest(_a, []);
return /* @__PURE__ */ jsxs(
"div",
__spreadProps(__spreadValues({
className: cn(
"absolute top-0 left-0 w-full h-full flex items-center justify-center space-x-2 bg-white/50 backdrop-blur-sm z-30",
props.className
)
}, props), {
children: [
/* @__PURE__ */ jsx2("div", { className: "h-4 w-4 bg-zinc-800 rounded-full animate-bounce [animation-delay:-0.3s]" }),
/* @__PURE__ */ jsx2("div", { className: "h-4 w-4 bg-zinc-800 rounded-full animate-bounce [animation-delay:-0.15s]" }),
/* @__PURE__ */ jsx2("div", { className: "h-4 w-4 bg-zinc-800 rounded-full animate-bounce" })
]
})
);
};
// src/components/CustomTable/THead.tsx
import { flexRender } from "@tanstack/react-table";
import { ChevronDown, ChevronUp } from "lucide-react";
// src/components/CustomTable/Filter.tsx
import { useState as useState2 } from "react";
import { formatISO, isValid, parseISO } from "date-fns";
// src/components/ui/popover.tsx
import * as PopoverPrimitive from "@radix-ui/react-popover";
import { jsx as jsx3 } from "react/jsx-runtime";
function Popover(_a) {
var props = __objRest(_a, []);
return /* @__PURE__ */ jsx3(PopoverPrimitive.Root, __spreadValues({ "data-slot": "popover" }, props));
}
function PopoverTrigger(_a) {
var props = __objRest(_a, []);
return /* @__PURE__ */ jsx3(PopoverPrimitive.Trigger, __spreadValues({ "data-slot": "popover-trigger" }, props));
}
function PopoverContent(_a) {
var _b = _a, {
className,
align = "center",
sideOffset = 4
} = _b, props = __objRest(_b, [
"className",
"align",
"sideOffset"
]);
return /* @__PURE__ */ jsx3(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx3(
PopoverPrimitive.Content,
__spreadValues({
"data-slot": "popover-content",
align,
sideOffset,
className: cn(
"z-[99999] w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)
}, props)
) });
}
// src/components/FormComponents/FormInput/FormInput.tsx
import { cva } from "class-variance-authority";
// src/components/ui/input.tsx
import { NumericFormat } from "react-number-format";
import { jsx as jsx4 } from "react/jsx-runtime";
var Input = (_a) => {
var _b = _a, {
className,
type,
numeric,
decimalScale = 2,
allowNegative = true
} = _b, props = __objRest(_b, [
"className",
"type",
"numeric",
"decimalScale",
"allowNegative"
]);
var _b2;
if (numeric) {
const _a2 = props, { value } = _a2, numericProps = __objRest(_a2, ["value"]);
return /* @__PURE__ */ jsx4(
NumericFormat,
__spreadProps(__spreadValues({
decimalScale,
value: (_b2 = value == null ? void 0 : value.toString()) != null ? _b2 : ""
}, numericProps), {
className: cn(
"flex h-10 w-full rounded-md border border-input bg-transparent placeholder:text-zinc-600 px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
),
allowNegative,
allowedDecimalSeparators: [","]
})
);
}
return /* @__PURE__ */ jsx4(
"input",
__spreadValues({
type,
className: cn(
"flex h-10 w-full rounded-md border border-input bg-transparent placeholder:text-zinc-600 px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)
}, props)
);
};
Input.displayName = "Input";
// src/components/FormComponents/FormInput/FormInput.tsx
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
var inputVariants = cva("", {
variants: {
variant: {
default: "block w-full rounded-lg h-10 py-2 text-sm border-zinc-200 border focus:border-zinc-400 placeholder:text-zinc-600"
}
},
defaultVariants: {
variant: "default"
}
});
var FormInput = (_a) => {
var _b = _a, {
label,
variant,
className,
type,
numeric,
showMessage = true,
decimalScale = 2,
allowNegative = true
} = _b, props = __objRest(_b, [
"label",
"variant",
"className",
"type",
"numeric",
"showMessage",
"decimalScale",
"allowNegative"
]);
return /* @__PURE__ */ jsxs2("div", { children: [
label && /* @__PURE__ */ jsx5("div", { className: "text-sm font-medium text-zinc-800 mb-1 block", children: label }),
/* @__PURE__ */ jsx5("div", { className: "relative flex items-center", children: /* @__PURE__ */ jsx5(
Input,
__spreadProps(__spreadValues({
className: cn(
inputVariants({
variant
}),
className
),
numeric,
id: props.id,
type,
placeholder: props.placeholder
}, props), {
decimalScale,
allowNegative
})
) })
] });
};
FormInput.displayName = "FormInput";
// src/components/ui/select.tsx
import * as SelectPrimitive from "@radix-ui/react-select";
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
function Select(_a) {
var props = __objRest(_a, []);
return /* @__PURE__ */ jsx6(SelectPrimitive.Root, __spreadValues({ "data-slot": "select" }, props));
}
function SelectGroup(_a) {
var props = __objRest(_a, []);
return /* @__PURE__ */ jsx6(SelectPrimitive.Group, __spreadValues({ "data-slot": "select-group" }, props));
}
function SelectValue(_a) {
var props = __objRest(_a, []);
return /* @__PURE__ */ jsx6(SelectPrimitive.Value, __spreadValues({ "data-slot": "select-value" }, props));
}
function SelectTrigger(_a) {
var _b = _a, {
className,
size = "default",
children
} = _b, props = __objRest(_b, [
"className",
"size",
"children"
]);
return /* @__PURE__ */ jsxs3(
SelectPrimitive.Trigger,
__spreadProps(__spreadValues({
"data-slot": "select-trigger",
"data-size": size,
className: cn(
"flex h-10 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-zinc-600 focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className
)
}, props), {
children: [
children,
/* @__PURE__ */ jsx6(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx6(ChevronDownIcon, { className: "size-4 opacity-50" }) })
]
})
);
}
function SelectContent(_a) {
var _b = _a, {
className,
children,
position = "popper"
} = _b, props = __objRest(_b, [
"className",
"children",
"position"
]);
return /* @__PURE__ */ jsx6(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs3(
SelectPrimitive.Content,
__spreadProps(__spreadValues({
"data-slot": "select-content",
className: cn(
"relative z-[999999] max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-white text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
),
position
}, props), {
children: [
/* @__PURE__ */ jsx6(SelectScrollUpButton, {}),
/* @__PURE__ */ jsx6(
SelectPrimitive.Viewport,
{
className: cn(
"p-1",
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
),
children
}
),
/* @__PURE__ */ jsx6(SelectScrollDownButton, {})
]
})
) });
}
function SelectItem(_a) {
var _b = _a, {
className,
children
} = _b, props = __objRest(_b, [
"className",
"children"
]);
return /* @__PURE__ */ jsxs3(
SelectPrimitive.Item,
__spreadProps(__spreadValues({
"data-slot": "select-item",
className: cn(
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
className
)
}, props), {
children: [
/* @__PURE__ */ jsx6("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx6(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx6(CheckIcon, { className: "size-4" }) }) }),
/* @__PURE__ */ jsx6(SelectPrimitive.ItemText, { children })
]
})
);
}
function SelectScrollUpButton(_a) {
var _b = _a, {
className
} = _b, props = __objRest(_b, [
"className"
]);
return /* @__PURE__ */ jsx6(
SelectPrimitive.ScrollUpButton,
__spreadProps(__spreadValues({
"data-slot": "select-scroll-up-button",
className: cn(
"flex cursor-default items-center justify-center py-1",
className
)
}, props), {
children: /* @__PURE__ */ jsx6(ChevronUpIcon, { className: "size-4" })
})
);
}
function SelectScrollDownButton(_a) {
var _b = _a, {
className
} = _b, props = __objRest(_b, [
"className"
]);
return /* @__PURE__ */ jsx6(
SelectPrimitive.ScrollDownButton,
__spreadProps(__spreadValues({
"data-slot": "select-scroll-down-button",
className: cn(
"flex cursor-default items-center justify-center py-1",
className
)
}, props), {
children: /* @__PURE__ */ jsx6(ChevronDownIcon, { className: "size-4" })
})
);
}
// src/components/FormComponents/FormSelect/FormSelect.tsx
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
var FormSelect = (_a) => {
var _b = _a, {
label,
className,
options,
placeholder
} = _b, props = __objRest(_b, [
"label",
"className",
"options",
"placeholder"
]);
var _a2;
return /* @__PURE__ */ jsxs4("div", { children: [
label && /* @__PURE__ */ jsx7("div", { className: "text-sm font-medium text-zinc-800 mb-1 block", children: label }),
/* @__PURE__ */ jsx7("div", { className: cn("relative flex items-center", className), children: /* @__PURE__ */ jsxs4(
Select,
{
onValueChange: (value) => {
var _a3;
return (_a3 = props.onChange) == null ? void 0 : _a3.call(props, {
target: { value }
});
},
value: String((_a2 = props.value) != null ? _a2 : ""),
children: [
/* @__PURE__ */ jsx7(SelectTrigger, { children: /* @__PURE__ */ jsx7(SelectValue, { placeholder }) }),
/* @__PURE__ */ jsx7(SelectContent, { children: /* @__PURE__ */ jsx7(SelectGroup, { children: options == null ? void 0 : options.map((item) => /* @__PURE__ */ jsx7(SelectItem, { value: item.value, children: item.label }, item.value)) }) })
]
}
) })
] });
};
FormSelect.displayName = "FormSelect";
// src/components/ui/button.tsx
import { Slot } from "@radix-ui/react-slot";
import { cva as cva2 } from "class-variance-authority";
import { jsx as jsx8 } from "react/jsx-runtime";
var buttonVariants = cva2(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
link: "text-primary underline-offset-4 hover:underline"
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9"
}
},
defaultVariants: {
variant: "default",
size: "default"
}
}
);
function Button(_a) {
var _b = _a, {
className,
variant,
size,
asChild = false
} = _b, props = __objRest(_b, [
"className",
"variant",
"size",
"asChild"
]);
const Comp = asChild ? Slot : "button";
return /* @__PURE__ */ jsx8(
Comp,
__spreadValues({
"data-slot": "button",
className: cn(buttonVariants({ variant, size, className }))
}, props)
);
}
// src/components/CustomTable/Filter.tsx
import { Filter as FilterIcon } from "lucide-react";
// src/components/FormComponents/FormCalendar/FormCalendar.tsx
import { cva as cva3 } from "class-variance-authority";
import { tr } from "date-fns/locale";
import { CalendarIcon } from "lucide-react";
import { format } from "date-fns";
// src/components/ui/calendar.tsx
import { ChevronLeft, ChevronRight } from "lucide-react";
import { DayPicker } from "react-day-picker";
import { jsx as jsx9 } from "react/jsx-runtime";
function Calendar(_a) {
var _b = _a, {
className,
classNames,
showOutsideDays = true
} = _b, props = __objRest(_b, [
"className",
"classNames",
"showOutsideDays"
]);
return /* @__PURE__ */ jsx9(
DayPicker,
__spreadValues({
showOutsideDays,
className: cn("p-3", className),
classNames: __spreadValues({
months: "flex flex-col sm:flex-row gap-2",
month: "flex flex-col gap-4",
caption: "flex justify-center pt-1 relative items-center w-full",
caption_label: "text-sm font-medium",
nav: "flex items-center gap-1",
nav_button: cn(
buttonVariants({ variant: "outline" }),
"size-7 bg-transparent p-0 opacity-50 hover:opacity-100"
),
nav_button_previous: "absolute left-1",
nav_button_next: "absolute right-1",
table: "w-full border-collapse space-x-1",
head_row: "flex",
head_cell: "text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
row: "flex w-full mt-2",
cell: cn(
"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-range-end)]:rounded-r-md",
props.mode === "range" ? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md" : "[&:has([aria-selected])]:rounded-md"
),
day: cn(
buttonVariants({ variant: "ghost" }),
"size-8 p-0 font-normal aria-selected:opacity-100"
),
day_range_start: "day-range-start aria-selected:bg-primary aria-selected:text-primary-foreground",
day_range_end: "day-range-end aria-selected:bg-primary aria-selected:text-primary-foreground",
day_selected: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
day_today: "bg-accent text-accent-foreground",
day_outside: "day-outside text-muted-foreground aria-selected:text-muted-foreground",
day_disabled: "text-muted-foreground opacity-50",
day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground",
day_hidden: "invisible"
}, classNames),
components: {
IconLeft: (_a2) => {
var _b2 = _a2, { className: className2 } = _b2, props2 = __objRest(_b2, ["className"]);
return /* @__PURE__ */ jsx9(ChevronLeft, __spreadValues({ className: cn("size-4", className2) }, props2));
},
IconRight: (_c) => {
var _d = _c, { className: className2 } = _d, props2 = __objRest(_d, ["className"]);
return /* @__PURE__ */ jsx9(ChevronRight, __spreadValues({ className: cn("size-4", className2) }, props2));
}
}
}, props)
);
}
// src/components/FormComponents/FormCalendar/FormCalendar.tsx
import { useState } from "react";
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
var calendarVariants = cva3("", {
variants: {
intent: {
primary: [
"bg-opacityGray",
"text-zinc-800",
"border-zinc-600 border rounded-[10px]",
"focus:outline-none focus:ring-2 focus:ring-zinc-800 focus:border-transparent",
"h-[40px]"
],
secondary: ["bg-gray-200", "text-gray-800", "border-gray-400"],
success: ["bg-green-500", "text-white", "border-transparent"],
white: [
"bg-white",
"text-zinc-800",
"border-none",
"focus:outline-none focus:ring-2 focus:ring-zinc-800 focus:border-transparent"
],
transparent: [
"bg-transparent",
"border-none",
"hover:bg-gray-200",
"text-zinc-800",
"disabled:text-text-exp"
],
refresh: [
"bg-green-500/15",
"text-green-500",
"border-none",
"hover:bg-green-500/25"
]
},
hasLeftIcon: {
true: "pl-10",
false: "pl-3"
},
hasRightIcon: {
true: "pr-10 !text-left",
false: "pr-3"
},
hasError: {
true: "border-red-500 border",
false: "border-zinc-600 border"
},
variant: {
default: "block w-full rounded-lg h-10 py-2 text-sm outline-2 placeholder:text-zinc-600",
waitlist: "block w-full rounded-lg h-14 py-2 text-sm outline-2 placeholder:text-zinc-600 bg-white",
filter: 'h-8 placeholder:text-xs text-center w-full rounded-md focus:border-zinc-800 outline-none [&:not(:placeholder-shown)]:border-zinc-800 placeholder:text-zinc-600 [&[type="date"]]:border-input'
}
},
defaultVariants: {
hasLeftIcon: false,
hasRightIcon: false,
hasError: false,
variant: "default"
}
});
var FormCalendar = (_a) => {
var _b = _a, {
label,
className,
value,
disabled
} = _b, props = __objRest(_b, [
"label",
"className",
"value",
"disabled"
]);
const [openCalendar, setOpenCalendar] = useState(false);
return /* @__PURE__ */ jsxs5(Popover, { open: openCalendar, onOpenChange: setOpenCalendar, children: [
/* @__PURE__ */ jsx10(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs5(
"button",
{
type: "button",
className: cn(
"h-10 w-60 flex items-center justify-between bg-transparent border px-3 rounded-lg border-zinc-600/15 text-zinc-800 hover:bg-zinc-600/15",
{ "text-zinc-800": value },
className
),
children: [
value ? format(value, "dd.MM.yyyy") : /* @__PURE__ */ jsx10("span", { children: "Tarih se\xE7" }),
/* @__PURE__ */ jsx10(CalendarIcon, { className: "h-4 w-4" })
]
}
) }),
/* @__PURE__ */ jsx10(PopoverContent, { className: "w-auto p-0", children: /* @__PURE__ */ jsx10(
Calendar,
{
locale: tr,
mode: "single",
disabled,
selected: value,
onSelect: (e) => {
var _a2;
if (typeof e === "undefined") {
return;
}
(_a2 = props.onSelect) == null ? void 0 : _a2.call(props, e);
setOpenCalendar(false);
},
initialFocus: true
}
) })
] });
};
FormCalendar.displayName = "FormCalendar";
// src/components/CustomTable/Filter.tsx
import { motion, AnimatePresence } from "motion/react";
import { Fragment, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
var parseDateString = (dateString) => {
if (!dateString) return void 0;
try {
if (typeof dateString === "string") {
const parsedDate = parseISO(dateString);
return isValid(parsedDate) ? parsedDate : void 0;
}
return void 0;
} catch (error) {
return void 0;
}
};
var Filter = ({
column,
table
}) => {
var _a;
const [open, setOpen] = useState2(false);
const uniqueValues = Array.from(
new Set(
table.getPreFilteredRowModel().flatRows.map((row) => row.getValue(column.id))
)
);
const columnFilterValue = column.getFilterValue();
const [filteredValue, setFilteredValue] = useState2(columnFilterValue);
const filterType = (_a = column.columnDef.meta) == null ? void 0 : _a.filterType;
const renderFilterInput = () => {
var _a2, _b, _c;
if (filterType === "date") {
return /* @__PURE__ */ jsx11(
motion.div,
{
initial: { opacity: 0, y: -10 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -10 },
children: /* @__PURE__ */ jsx11(
FormCalendar,
{
className: "w-full",
value: filteredValue !== void 0 ? parseISO(filteredValue) : columnFilterValue !== void 0 ? parseISO(columnFilterValue) : void 0,
onSelect: (e) => {
setFilteredValue(formatISO(e).split("T")[0]);
},
disabled: (date) => {
const availableDates = table.getPreFilteredRowModel().flatRows.map((row) => {
return parseDateString(row.getValue(column.id));
}).filter((d) => d !== void 0).map((d) => formatISO(d).split("T")[0]);
return !availableDates.includes(formatISO(date).split("T")[0]);
}
}
)
},
"date-filter"
);
}
if (filterType === "number") {
return /* @__PURE__ */ jsxs6(
motion.div,
{
initial: { opacity: 0, y: -10 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -10 },
className: "flex gap-3",
children: [
/* @__PURE__ */ jsx11(
FormInput,
{
type: "number",
value: (_a2 = columnFilterValue == null ? void 0 : columnFilterValue[0]) != null ? _a2 : "",
onChange: (e) => setFilteredValue((old) => {
var _a3;
return [
e.target.value,
(_a3 = old == null ? void 0 : old[1]) != null ? _a3 : columnFilterValue == null ? void 0 : columnFilterValue[1]
];
}),
placeholder: "Min",
className: "w-full rounded-lg border border-gray-200 dark:border-gray-800",
numeric: true
}
),
/* @__PURE__ */ jsx11(
FormInput,
{
type: "number",
value: (_b = columnFilterValue == null ? void 0 : columnFilterValue[1]) != null ? _b : "",
onChange: (e) => setFilteredValue((old) => {
var _a3;
return [
(_a3 = old == null ? void 0 : old[0]) != null ? _a3 : columnFilterValue == null ? void 0 : columnFilterValue[0],
e.target.value
];
}),
placeholder: "Maks",
className: "w-full rounded-lg border border-gray-200 dark:border-gray-800",
numeric: true
}
)
]
},
"number-filter"
);
}
if (filterType === "select") {
return /* @__PURE__ */ jsx11(
FormSelect,
{
options: uniqueValues.map((value) => ({
label: value,
value
})),
onChange: (evt) => setFilteredValue(evt.target.value),
onClick: (evt) => evt.stopPropagation(),
placeholder: "Se\xE7iniz",
value: filteredValue !== void 0 ? filteredValue : columnFilterValue != null ? columnFilterValue : ""
}
);
}
if (filterType === "boolean") {
return /* @__PURE__ */ jsx11(
motion.div,
{
initial: { opacity: 0, y: -10 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -10 },
children: /* @__PURE__ */ jsx11(
FormSelect,
{
options: [
{ label: "Evet", value: "true" },
{ label: "Hay\u0131r", value: "false" }
],
placeholder: "Se\xE7iniz",
onChange: (evt) => {
setFilteredValue(evt.target.value);
},
value: filteredValue !== void 0 ? filteredValue : (_c = columnFilterValue == null ? void 0 : columnFilterValue.toString()) != null ? _c : "",
className: "rounded-lg border border-gray-200 dark:border-gray-800"
}
)
},
"boolean-filter"
);
}
return /* @__PURE__ */ jsx11(
motion.div,
{
initial: { opacity: 0, y: -10 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -10 },
children: /* @__PURE__ */ jsx11(
FormInput,
{
className: "w-full rounded-lg border border-gray-200 dark:border-gray-800",
onChange: (evt) => setFilteredValue(evt.target.value),
onClick: (evt) => evt.stopPropagation(),
placeholder: "Ara",
type: "text",
value: filteredValue != null ? filteredValue : ""
}
)
},
"string-filter"
);
};
return /* @__PURE__ */ jsxs6(Popover, { open, onOpenChange: setOpen, children: [
/* @__PURE__ */ jsx11(
PopoverTrigger,
{
onClick: (e) => e.stopPropagation(),
className: cn(
"p-1.5 rounded-full transition-colors hover:bg-green-100 group/filter",
{
"bg-green-100": columnFilterValue !== void 0
}
),
children: /* @__PURE__ */ jsx11(motion.div, { whileHover: { scale: 1.1 }, whileTap: { scale: 0.95 }, children: /* @__PURE__ */ jsx11(
FilterIcon,
{
className: cn("size-4 group-hover/filter:text-green-600", {
"text-green-600": columnFilterValue !== void 0,
"text-gray-800": columnFilterValue === void 0
})
}
) })
}
),
/* @__PURE__ */ jsx11(
PopoverContent,
{
onClick: (e) => e.stopPropagation(),
className: "flex flex-col gap-3 p-4 shadow-lg border border-gray-200 dark:border-gray-800 rounded-lg bg-white dark:bg-gray-900",
children: /* @__PURE__ */ jsx11(AnimatePresence, { children: /* @__PURE__ */ jsxs6(Fragment, { children: [
renderFilterInput(),
/* @__PURE__ */ jsxs6("div", { className: "flex gap-2 mt-2", children: [
/* @__PURE__ */ jsx11(
Button,
{
variant: "outline",
className: "flex-1 flex justify-center items-center hover:bg-gray-100 dark:hover:bg-gray-800",
disabled: columnFilterValue === void 0 && filteredValue === void 0,
onClick: () => {
column.setFilterValue("");
setFilteredValue(void 0);
setOpen(false);
},
children: "Temizle"
}
),
/* @__PURE__ */ jsx11(
Button,
{
className: "flex-1 flex justify-center items-center bg-green-600 hover:bg-green-700 text-white",
disabled: !filteredValue,
onClick: () => {
if (filteredValue === "true" || filteredValue === "false") {
column.setFilterValue(filteredValue === "true");
} else {
column.setFilterValue(filteredValue);
}
setFilteredValue(void 0);
setOpen(false);
},
children: "Uygula"
}
)
] })
] }) })
}
)
] });
};
var Filter_default = Filter;
// src/components/CustomTable/THead.tsx
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
var THead = ({
table,
header
}) => {
const getCommonPinningStyles = (column) => {
const isPinned = column.getIsPinned();
const isLastLeftPinnedColumn = isPinned === "left" && column.getIsLastColumn("left");
const isFirstRightPinnedColumn = isPinned === "right" && column.getIsFirstColumn("right");
return {
boxShadow: isLastLeftPinnedColumn ? "-4px 0 4px -4px lightgray inset" : isFirstRightPinnedColumn ? "4px 0 4px -4px lightgray inset" : void 0,
left: isPinned === "left" ? `${column.getStart("left")}px` : void 0,
right: isPinned === "right" ? `${column.getAfter("right")}px` : void 0,
position: isPinned ? "sticky" : "relative",
zIndex: isPinned ? 1 : 0
};
};
return /* @__PURE__ */ jsxs7(
TableHead,
{
className: cn(
"relative text-left select-none min-h-12 text-sm group/head",
{
"cursor-pointer": header.column.getCanSort(),
"flex-1": table.getAllColumns().length - 1 === header.index
}
),
style: __spreadValues({
width: header.getSize()
}, getCommonPinningStyles(header.column)),
children: [
/* @__PURE__ */ jsxs7(
"div",
{
className: "flex max-sm:flex-col md:gap-3 sm:items-center sm:justify-between whitespace-nowrap relative w-full px-1",
onClick: header.column.getCanSort() ? header.column.getToggleSortingHandler() : void 0,
role: "button",
tabIndex: 0,
children: [
header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()),
(header.column.getCanFilter() || header.column.getCanSort()) && /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1 md:pr-5 last:pr-0", children: [
header.column.getCanFilter() ? /* @__PURE__ */ jsx12(Filter_default, { column: header.column, table }) : null,
header.column.getCanSort() && /* @__PURE__ */ jsxs7("div", { className: "flex flex-col text-zinc-800", children: [
/* @__PURE__ */ jsx12(
ChevronDown,
{
className: cn(
"translate-y-2 translate-x-1 size-5 text-gray-800",
{
"text-green-600": header.column.getIsSorted() === "asc"
}
)
}
),
/* @__PURE__ */ jsx12(
ChevronUp,
{
className: cn(
"-translate-y-2 -translate-x-1 size-5 text-gray-800",
{
"text-green-600": header.column.getIsSorted() === "desc"
}
)
}
)
] })
] })
]
}
),
header.column.getCanResize() && header.index !== table.getAllColumns().length - 1 && /* @__PURE__ */ jsx12(
"div",
{
"aria-hidden": "true",
onMouseDown: header.getResizeHandler(),
onTouchStart: header.getResizeHandler(),
className: cn(
"absolute right-0 top-0 flex justify-end h-full w-2 cursor-col-resize select-none touch-none "
),
children: /* @__PURE__ */ jsx12(
"div",
{
className: cn(
"w-[1px] h-full bg-transparent peer-hover:bg-gray-200 group-hover/head:bg-gray-200 transition-all",
{
"bg-gray-200 hover:bg-gray-200": header.column.getIsResizing()
}
)
}
)
}
)
]
}
);
};
var THead_default = THead;
// src/components/CustomTable/TCell.tsx
import { flexRender as flexRender2 } from "@tanstack/react-table";
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
var TCell = ({
table,
cell,
header
}) => {
const getCommonPinningStyles = (column) => {
const isPinned = column.getIsPinned();
const isLastLeftPinnedColumn = isPinned === "left" && column.getIsLastColumn("left");
const isFirstRightPinnedColumn = isPinned === "right" && column.getIsFirstColumn("right");
return {
boxShadow: isLastLeftPinnedColumn ? "-4px 0 4px -4px lightgray inset" : isFirstRightPinnedColumn ? "4px 0 4px -4px lightgray inset" : void 0,
left: isPinned === "left" ? `${column.getStart("left")}px` : void 0,
right: isPinned === "right" ? `${column.getAfter("right")}px` : void 0,
position: isPinned ? "sticky" : "relative",
zIndex: isPinned ? 1 : 0
};
};
return /* @__PURE__ */ jsxs8(
TableCell,
{
style: __spreadValues({
width: cell.column.getSize()
}, getCommonPinningStyles(cell.column)),
className: cn("text-left group/cell", {
"flex-1": table.getAllColumns().length - 1 === cell.column.getIndex()
}),
children: [
/* @__PURE__ */ jsx13("div", { className: "min-h-12 text-sm flex items-center break-all px-1 w-full", children: flexRender2(cell.column.columnDef.cell, cell.getContext()) }),
cell.column.getCanResize() && cell.column.getIndex() !== table.getAllColumns().length - 1 && /* @__PURE__ */ jsx13(
"div",
{
"aria-hidden": "true",
onMouseDown: header.getResizeHandler(),
onTouchStart: header.getResizeHandler(),
className: cn(
"absolute right-0 top-0 flex justify-end h-full w-2 cursor-col-resize select-none touch-none "
),
children: /* @__PURE__ */ jsx13(
"div",
{
className: cn(
"w-[1px] h-full bg-transparent peer-hover:bg-gray-800 group-hover/cell:bg-gray-800 transition-all",
{
"bg-gray-800 hover:bg-gray-800": cell.column.getIsResizing()
}
)
}
)
}
)
]
}
);
};
var TCell_default = TCell;
// src/components/CustomTable/BulkActions.tsx
import { jsx as jsx14 } from "react/jsx-runtime";
var BulkActions = ({ children }) => {
return /* @__PURE__ */ jsx14("div", { className: "sticky flex items-center justify-center top-16 -translate-y-1/2 z-30", children: /* @__PURE__ */ jsx14("div", { className: "bg-white px-2 py-2 rounded-xl shadow-md flex items-center justify-center gap-2", children }) });
};
var BulkActions_default = BulkActions;
// src/components/CustomTable/Pagination.tsx
import React, { useEffect } from "react";
import { ChevronLeft as ChevronLeft2, ChevronRight as ChevronRight2 } from "lucide-react";
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
var Pagination = ({
table,
setPagination,
pagination,
rows,
manualPagination,
loading
}) => {
var _a, _b, _c, _d, _e;
const pageSize = table ? table.getState().pagination.pageSize : pagination.pageSize;
const currentPage = table ? table.getState().pagination.pageIndex + 1 : pagination.pageIndex + 1;
const totalPages = table ? table.getPageCount() : Math.ceil(((_a = rows == null ? void 0 : rows.rowCount) != null ? _a : 0) / pageSize);
const renderPageNumbers = () => {
const pageNumbers = [];
if (totalPages <= 7) {
for (let i = 1; i <= totalPages; i += 1) {
pageNumbers.push(i);
}
} else {
pageNumbers.push(1);
if (currentPage <= 4) {
for (let i = 2; i <= 5; i += 1) {
pageNumbers.push(i);
}
pageNumbers.push("...");
pageNumbers.push(totalPages);
} else if (currentPage >= totalPages - 3) {
pageNumbers.push("...");
for (let i = totalPages - 4; i <= totalPages; i += 1) {
pageNumbers.push(i);
}
} else {
pageNumbers.push("...");
for (let i = currentPage - 1; i <= currentPage + 1; i += 1) {
pageNumbers.push(i);
}
pageNumbers.push("...");
pageNumbers.push(totalPages);
}
}
return pageNumbers;
};
const generatePageSizes = (maxSize) => {
const sizes = [];
let current = 10;
while (current <= maxSize) {
if (current !== maxSize) {
sizes.push(current);
}
if (current < 100) {
current += 10;
} else if (current < 1e3) {
current += 100;
} else {
current += 1e3;
}
}
return sizes;
};
const pageSizeOptions = generatePageSizes((_b = rows.rowCount) != null ? _b : 0).map((size) => ({
value: size.toString(),
label: size.toString()
}));
if (!manualPagination || ((_c = rows.rowCount) != null ? _c : 0) <= 1e3) {
pageSizeOptions.push({
value: (_e = (_d = rows.rowCount) == null ? void 0 : _d.toString()) != null ? _e : "0",
label: `Hepsini G\xF6ster (${rows.rowCount})`
});
}
useEffect(() => {
var _a2;
if (manualPagination && ((_a2 = rows.rowCount) != null ? _a2 : 0) > 1e3) {
setPagination(__spreadProps(__spreadValues({}, pagination), { pageSize: 1e3 }));
}
}, [manualPagination, rows.rowCount, pagination, setPagination]);
useEffect(() => {
if (manualPagination && !loading && pagination && (pagination == null ? void 0 : pagination.pageIndex) > totalPages - 1) {
setPagination(__spreadProps(__spreadValues({}, pagination), { pageIndex: 0 }));
}
}, [manualPagination, rows.pageCount, setPagination, totalPages, loading]);
const getPageNumber = () => {
var _a2;
if (manualPagination) {
if (totalPages === 1) {
return pageSizeOptions[pageSizeOptions.length - 1].value.toString();
}
const pageSizeOption = pageSizeOptions.find(
(option) => option.value === pagination.pageSize.toString()
);
if (!pageSizeOption) {
return pageSizeOptions[0].value.toString();
}
if (pagination.pageSize >= ((_a2 = rows == null ? void 0 : rows.rowCount) != null ? _a2 : 0)) {
return pagination.pageSize.toString();
}
return pagination.pageSize.toString();
}
if (pageSize >= rows.data.length) {
return rows.data.length.toString();
}
return pageSize.toString();
};
return /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 select-none mt-auto sticky z-20 bottom-2 shadow border-t bg-gray-200 p-5 rounded-2xl", children: [
/* @__PURE__ */ jsx15(
Button,
{
size: "icon",
className: "text-gray-800",
variant: "ghost",
onClick: () => table ? table.previousPage() : setPagination((currentValue) => __spreadProps(__spreadValues({}, currentValue), {
pageIndex: currentValue.pageIndex - 1
})),
disabled: table ? !table.getCanPreviousPage() : pagination.pageIndex === 0,
children: /* @__PURE__ */ jsx15(ChevronLeft2, {})
}
),
/* @__PURE__ */ jsx15("div", { className: "flex items-center gap-1", children: renderPageNumbers().map((pageNum) => /* @__PURE__ */ jsx15(React.Fragment, { children: pageNum === "..." ? /* @__PURE__ */ jsx15("span", { className: "px-2 h-8 w-8 flex items-center justify-center text-gray-800", children: "..." }) : /* @__PURE__ */ jsx15("div", { children: /* @__PURE__ */ jsx15(
Button,
{
variant: currentPage === pageNum ? "default" : "ghost",
className: "min-w-[32px] h-8 flex items-center justify-center px-1",
onClick: () => {
const newPage = pageNum - 1;
if (table) {
table.setPageIndex(newPage);
} else {
setPagination((prev) => __spreadProps(__spreadValues({}, prev), {
pageIndex: newPage
}));
}
},
children: pageNum
}
) }) }, pageNum)) }),
/* @__PURE__ */ jsx15(
Button,
{
size: "icon",
className: "text-gray-800",
variant: "ghost",
onClick: () => table ? table.nextPage() : setPagination((currentValue) => __spreadProps(__spreadValues({}, currentValue), {
pageIndex: currentValue.pageIndex + 1
})),
disabled: table ? !table.getCanNextPage() : pagination.pageIndex === totalPages - 1,
children: /* @__PURE__ */ jsx15(ChevronRight2, {})
}
),
/* @__PURE__ */ jsx15(
FormSelect,
{
onChange: (e) => {
if (table) {
table.setPageSize(Number(e.target.value));
} else {
setPagination(__spreadProps(__spreadValues({}, pagination), {
pageSize: Number(e.target.value)
}));
}
},
value: getPageNumber(),
options: pageSizeOptions
}
)
] });
};
// src/lib/stores/tableStore/index.ts
import { create } from "zustand";
import { devtools } from "zustand/middleware";
var useTableStore = create()(
devtools(
(set) => ({
tableData: [],
setTableData: (tableData) => set((state) => {
const existingTableIndex = state.tableData.findIndex(
(t) => t.tableId === tableData.tableId
);
if (existingTableIndex >= 0) {
const newTableData = [...state.tableData];
newTableData[existingTableIndex] = tableData;
return { tableData: newTableData };
}
return { tableData: [...state.tableData, tableData] };
}),
removeTableData: (tableId) => set((state) => ({
tableData: state.tableData.filter((t) => t.tableId !== tableId)
}))
}),
{ name: "table-storage" }
)
);
var tableStore_default = useTableStore;
// src/components/CustomTable/index.tsx
import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
var CustomTable = ({
tableId,
columns,
rows,
defaultPageSize = 10,
manualPagination = false,
customPagination = false,
defaultPinnedColumns,
cardComponent,
bulkActions,
manualSearch,
rightTop,
leftTop,
viewMode = "table",
pageOffset = 15.5,
scrollable = true,
isLoading = false,
defaultSorting,
maxHeight,
minHeight,
emptyContent
}) => {
var _a, _b, _c, _d;
const { setTableData, tableData } = tableStore_default();
const initialPagination = useMemo(() => {
var _a2;
return ((_a2 = tableData.find((t) => t.tableId === tableId)) == null ? void 0 : _a2.pagination) || {
pageIndex: 0,
pageSize: defaultPageSize
};
}, [tableId, tableData, defaultPageSize]);
const [pagination, setPagination] = useState3(initialPagination);
const initialRowsData = useMemo(
() => {
var _a2, _b2;
return __spreadProps(__spreadValues({}, rows), {
data: rows.data || [],
rowCount: rows.rowCount || ((_a2 = rows.data) == null ? void 0 : _a2.length) || 0,
pageCount: rows.pageCount || Ma