UNPKG

@bilalsino/react-tanstack-data-table

Version:

Reusable React data table component with sorting, filtering, and pagination

1 lines 101 kB
{"version":3,"sources":["../src/components/CustomTable/index.tsx","../src/lib/utils.ts","../src/components/ui/table.tsx","../src/components/Loading/Loading.tsx","../src/components/CustomTable/THead.tsx","../src/components/CustomTable/Filter.tsx","../src/components/ui/popover.tsx","../src/components/FormComponents/FormInput/FormInput.tsx","../src/components/ui/input.tsx","../src/components/ui/select.tsx","../src/components/FormComponents/FormSelect/FormSelect.tsx","../src/components/ui/button.tsx","../src/components/FormComponents/FormCalendar/FormCalendar.tsx","../src/components/ui/calendar.tsx","../src/components/CustomTable/TCell.tsx","../src/components/CustomTable/BulkActions.tsx","../src/components/CustomTable/Pagination.tsx","../src/lib/stores/tableStore/index.ts","../src/components/ui/checkbox.tsx","../src/components/CustomTable/DefaultColumns.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n ColumnFiltersState,\n ColumnPinningState,\n FilterFn,\n getCoreRowModel,\n getFacetedMinMaxValues,\n getFacetedRowModel,\n getFacetedUniqueValues,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n Header,\n PaginationState,\n Row,\n RowSelectionState,\n SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { useEffect, useRef, useState, useMemo } from \"react\";\nimport { useVirtualizer } from \"@tanstack/react-virtual\";\nimport { AlertTriangle } from \"lucide-react\";\nimport { Table, TableBody, TableHeader, TableRow } from \"@/components/ui/table\";\nimport { Loading } from \"@/components/Loading\";\nimport THead from \"./THead\";\nimport TCell from \"./TCell\";\nimport BulkActions from \"./BulkActions\";\nimport { Pagination } from \"./Pagination\";\nimport { CustomTableProps } from \"@/lib/types/table.types\";\nimport useTableStore from \"@/lib/stores/tableStore\";\nimport \"@/styles/globals.css\";\n\nconst CustomTable = <T extends Record<string, any>>({\n tableId,\n columns,\n rows,\n defaultPageSize = 10,\n manualPagination = false,\n customPagination = false,\n defaultPinnedColumns,\n cardComponent,\n bulkActions,\n manualSearch,\n rightTop,\n leftTop,\n viewMode = \"table\",\n pageOffset = 15.5,\n scrollable = true,\n isLoading = false,\n defaultSorting,\n maxHeight,\n minHeight,\n emptyContent,\n}: CustomTableProps<T>) => {\n const { setTableData, tableData } = useTableStore();\n\n const initialPagination = useMemo(() => {\n return (\n tableData.find((t) => t.tableId === tableId)?.pagination || {\n pageIndex: 0,\n pageSize: defaultPageSize,\n }\n );\n }, [tableId, tableData, defaultPageSize]);\n\n const [pagination, setPagination] =\n useState<PaginationState>(initialPagination);\n\n const initialRowsData = useMemo(\n () => ({\n ...rows,\n data: rows.data || [],\n rowCount: rows.rowCount || rows.data?.length || 0,\n pageCount:\n rows.pageCount ||\n Math.ceil((rows.data?.length || 0) / initialPagination.pageSize),\n }),\n [rows, initialPagination.pageSize]\n );\n\n const [rowsData, setRowsData] =\n useState<CustomTableProps<T>[\"rows\"]>(initialRowsData);\n\n const [columnPinning, setColumnPinning] = useState<ColumnPinningState>(\n defaultPinnedColumns\n ? {\n left: [\"select\", ...(defaultPinnedColumns?.left || [])],\n right: [...(defaultPinnedColumns?.right || [])],\n }\n : {\n left: [],\n right: [],\n }\n );\n const [sorting, setSorting] = useState<SortingState>(\n tableData.find((t) => t.tableId === tableId)?.sorting ||\n defaultSorting ||\n []\n );\n const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>(\n tableData.find((t) => t.tableId === tableId)?.columnFilters || []\n );\n const [globalFilter, setGlobalFilter] = useState<any>(\n tableData.find((t) => t.tableId === tableId)?.globalFilter || \"\"\n );\n const [rowSelection, setRowSelection] = useState<RowSelectionState>(\n tableData.find((t) => t.tableId === tableId)?.rowSelection || {}\n );\n const weakIncludesStringFn: FilterFn<T> = (\n srows: Row<T>,\n columnId: string,\n filterValue: any\n ) => {\n const rowValue = srows.getValue(columnId);\n\n // Eğer rowValue null veya undefined ise eşleşme yok\n if (rowValue == null) return false;\n\n // String olarak karşılaştırma yap\n const rowValueString = String(rowValue).toLowerCase();\n const filterValueString = String(filterValue).toLowerCase();\n\n // Case-insensitive içerik eşleşmesi veya zayıf eşitlik\n return (\n rowValueString.includes(filterValueString) || rowValue === filterValue\n );\n };\n useEffect(() => {\n if (!rows.data) return;\n\n const newRowCount = rows.rowCount || rows.data.length;\n const newPageCount =\n rows.pageCount || Math.ceil(newRowCount / pagination.pageSize);\n\n setRowsData({\n ...rows,\n data: rows.data,\n rowCount: newRowCount,\n pageCount: newPageCount,\n });\n }, [rows, pagination.pageSize]);\n\n useEffect(() => {\n setTableData({\n tableId,\n columnFilters,\n columnPinning,\n sorting,\n pagination,\n globalFilter,\n rowSelection,\n });\n }, [\n tableId,\n columnFilters,\n columnPinning,\n sorting,\n pagination,\n globalFilter,\n rowSelection,\n setTableData,\n ]);\n console.log(columnFilters);\n const table = useReactTable<T>({\n columns,\n data: rowsData.data,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getFacetedRowModel: getFacetedRowModel(),\n getFacetedUniqueValues: getFacetedUniqueValues(),\n getFacetedMinMaxValues: getFacetedMinMaxValues(),\n state: {\n columnFilters,\n columnPinning,\n sorting,\n pagination,\n globalFilter,\n rowSelection,\n },\n rowCount: rowsData.rowCount,\n onColumnPinningChange: setColumnPinning,\n onSortingChange: setSorting,\n onPaginationChange: setPagination,\n onColumnFiltersChange: setColumnFilters,\n onGlobalFilterChange: setGlobalFilter,\n onRowSelectionChange: setRowSelection,\n globalFilterFn: weakIncludesStringFn,\n manualPagination,\n enableColumnResizing: true,\n columnResizeMode: \"onChange\",\n defaultColumn: {\n minSize: 100,\n size: 100,\n },\n pageCount: rowsData.pageCount,\n manualFiltering: false,\n });\n\n const tableContainerRef = useRef<any>(null);\n const rowVirtualizer = useVirtualizer({\n count: Math.max(\n pagination.pageSize < table.getFilteredRowModel().rows.length\n ? pagination.pageSize\n : table.getFilteredRowModel().rows.length,\n 0\n ),\n estimateSize: () => 300,\n getScrollElement: () => tableContainerRef.current,\n measureElement:\n typeof window !== \"undefined\" &&\n navigator.userAgent.indexOf(\"Firefox\") === -1\n ? (element) => element?.getBoundingClientRect().height\n : undefined,\n overscan: 5,\n });\n const selectedRows = rowsData.data.filter((_, index) => rowSelection[index]);\n const actions = {\n selectedRows,\n pagination,\n setRowSelection,\n setGlobalFilter,\n setPagination,\n table,\n };\n const renderBulkActions = () => {\n if (typeof bulkActions === \"function\") {\n return bulkActions(actions);\n }\n return bulkActions;\n };\n\n const renderCardComponent = (row: Row<T>) => {\n if (typeof cardComponent === \"function\") {\n return cardComponent({ row });\n }\n return cardComponent;\n };\n\n const renderRightTop = () => {\n if (typeof rightTop === \"function\") {\n return rightTop(actions);\n }\n return rightTop;\n };\n\n const renderLeftTop = () => {\n if (typeof leftTop === \"function\") {\n return leftTop(actions);\n }\n return leftTop;\n };\n\n const renderCustomPagination = () => {\n if (typeof customPagination === \"function\") {\n return customPagination(actions);\n }\n return customPagination;\n };\n const { rows: rowsModel } = table.getPaginationRowModel();\n useEffect(() => {\n if (!manualPagination) {\n const filteredRowCount =\n table.getState().columnFilters.length === 0\n ? rows.data.length\n : table.getFilteredRowModel().rows.length;\n const newPageCount = Math.ceil(filteredRowCount / pagination.pageSize);\n setRowsData((prev) => {\n return {\n ...prev,\n rowCount: filteredRowCount,\n pageCount: newPageCount,\n };\n });\n if (pagination.pageIndex >= newPageCount) {\n setPagination((prev) => ({\n ...prev,\n pageIndex: 0,\n }));\n }\n } else {\n setRowsData(rows);\n }\n }, [\n columnFilters,\n globalFilter,\n pagination.pageSize,\n table,\n pagination.pageIndex,\n manualPagination,\n rows,\n ]);\n\n return (\n <div className=\"w-full\">\n <div className=\"rounded-2.5xl max-w-full grid relative h-full\">\n {bulkActions && <BulkActions>{renderBulkActions()}</BulkActions>}\n <div className=\"md:p-3 flex flex-col gap-3 transition-none overflow-auto relative\">\n {isLoading && <Loading />}\n <div\n className={`flex justify-between items-center ${\n !bulkActions && !manualSearch && !manualPagination ? \"p-3\" : \"\"\n }`}\n >\n <div className=\"flex items-center h-full flex-1\">\n {!manualSearch && (\n <input\n className=\"h-10 w-full max-w-72 rounded-lg px-3 border border-gray-300\"\n value={globalFilter}\n onChange={(e) =>\n table.setGlobalFilter(String(e.target.value))\n }\n placeholder=\"Ara\"\n />\n )}\n {leftTop && (\n <div className=\"flex-1 flex justify-start items-center gap-2\">\n {renderLeftTop()}\n </div>\n )}\n </div>\n {rightTop && (\n <div className=\"flex-1 flex justify-end items-center gap-2\">\n {renderRightTop()}\n </div>\n )}\n </div>\n <div\n ref={tableContainerRef}\n style={{\n minHeight: scrollable ? \"70%\" : minHeight || \"auto\",\n maxHeight: scrollable\n ? `calc(100svh - ${pageOffset}rem)`\n : maxHeight &&\n Number(maxHeight) > rowVirtualizer.getTotalSize() + 48\n ? maxHeight\n : `calc(${rowVirtualizer.getTotalSize()}px + 64px)`,\n }}\n className=\"overflow-auto max-sm:flex h-screen\"\n >\n {viewMode === \"table\" && (\n <Table style={{ height: `${rowVirtualizer.getTotalSize()}px` }}>\n <TableHeader>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow isSticky key={headerGroup.id}>\n {headerGroup.headers.map((header) => (\n <THead key={header.id} table={table} header={header} />\n ))}\n </TableRow>\n ))}\n </TableHeader>\n {!isLoading &&\n table.getFilteredRowModel().rows.length === 0 && (\n <>\n {emptyContent ? (\n emptyContent\n ) : (\n <div className=\"w-full bg-yellow-100 text-yellow-800 flex items-center p-2 gap-2\">\n <span className=\"flex items-center gap-2 sticky left-2\">\n <AlertTriangle />\n Sonuç bulunamadı\n </span>\n </div>\n )}\n </>\n )}\n\n {!isLoading && table.getFilteredRowModel().rows.length > 0 && (\n <TableBody className=\"grid relative mb-auto\">\n {rowVirtualizer.getVirtualItems().map((virtualRow) => {\n const row = rowsModel[virtualRow.index] as Row<T>;\n if (!row) return null;\n return (\n <TableRow\n data-index={virtualRow.index}\n ref={(node) => rowVirtualizer.measureElement(node)}\n key={row.id}\n className=\"flex absolute w-full\"\n style={{\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n {row.getVisibleCells().map((cell) => {\n const header = table\n .getHeaderGroups()\n .flatMap((headerGroup) => headerGroup.headers)\n .find((h) => h.id === cell.column.id);\n return (\n <TCell\n key={cell.id}\n table={table}\n cell={cell}\n header={header as Header<T, unknown>}\n />\n );\n })}\n </TableRow>\n );\n })}\n </TableBody>\n )}\n </Table>\n )}\n </div>\n {viewMode === \"card\" && (\n <div className=\"h-full absolute top-[90px] left-0 p-3 w-full\">\n <div className=\"grid grid-cols-2 gap-5\">\n {table\n .getPaginationRowModel()\n .rows.map((row) => renderCardComponent(row))}\n </div>\n </div>\n )}\n </div>\n {!manualPagination && !customPagination && table && (\n <Pagination\n rows={rowsData}\n table={table}\n pagination={pagination}\n setPagination={setPagination}\n />\n )}\n {manualPagination && customPagination && renderCustomPagination()}\n </div>\n </div>\n );\n};\n\nexport { CustomTable };\n","import { type ClassValue, clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n} ","import { cn } from \"@/lib/utils\";\nimport {\n forwardRef,\n HTMLAttributes,\n TdHTMLAttributes,\n ThHTMLAttributes,\n} from \"react\";\n\nconst Table = forwardRef<HTMLTableElement, HTMLAttributes<HTMLTableElement>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"caption-bottom text-sm flex-1 inline-table w-full relative\",\n className\n )}\n {...props}\n />\n )\n);\nTable.displayName = \"Table\";\n\nconst TableHeader = forwardRef<\n HTMLTableSectionElement,\n HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"sticky top-0 h-12 z-20 w-full bg-zinc-100 rounded-xl\",\n className\n )}\n {...props}\n />\n));\nTableHeader.displayName = \"TableHeader\";\n\nconst TableBody = forwardRef<\n HTMLTableSectionElement,\n HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"relative\", className)} {...props} />\n));\nTableBody.displayName = \"TableBody\";\n\nconst TableFooter = forwardRef<\n HTMLTableSectionElement,\n HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n className\n )}\n {...props}\n />\n));\nTableFooter.displayName = \"TableFooter\";\n\nconst TableRow = forwardRef<\n HTMLTableRowElement,\n HTMLAttributes<HTMLTableRowElement> & { isSticky?: boolean }\n>(({ className, isSticky, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"transition-colors relative hover:text-zinc-800 data-[state=selected]:bg-white flex group\",\n isSticky && \"sticky top-0\",\n className\n )}\n {...props}\n />\n));\nTableRow.displayName = \"TableRow\";\n\nconst TableHead = forwardRef<\n HTMLTableCellElement,\n ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"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\",\n className\n )}\n {...props}\n />\n));\nTableHead.displayName = \"TableHead\";\n\nconst TableCell = forwardRef<\n HTMLTableCellElement,\n TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"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\",\n className\n )}\n {...props}\n />\n));\nTableCell.displayName = \"TableCell\";\n\nconst TableCaption = forwardRef<\n HTMLTableCaptionElement,\n HTMLAttributes<HTMLTableCaptionElement>\n>(({ className, ...props }, ref) => (\n <caption\n ref={ref}\n className={cn(\"mt-4 text-sm text-zinc-600 break-all\", className)}\n {...props}\n />\n));\nTableCaption.displayName = \"TableCaption\";\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n};\n","'use client'\r\n\r\nimport { cn } from '@/lib/utils'\r\nimport { HTMLAttributes } from 'react'\r\n\r\ninterface LoadingProps extends HTMLAttributes<HTMLDivElement> {}\r\n\r\nexport const Loading = ({ ...props }: LoadingProps) => {\r\n return (\r\n <div\r\n className={cn(\r\n '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',\r\n props.className,\r\n )}\r\n {...props}\r\n >\r\n <div className='h-4 w-4 bg-zinc-800 rounded-full animate-bounce [animation-delay:-0.3s]' />\r\n <div className='h-4 w-4 bg-zinc-800 rounded-full animate-bounce [animation-delay:-0.15s]' />\r\n <div className='h-4 w-4 bg-zinc-800 rounded-full animate-bounce' />\r\n </div>\r\n )\r\n}\r\n","import { CSSProperties } from \"react\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { Column, flexRender, Header, Table } from \"@tanstack/react-table\";\r\nimport { ChevronDown, ChevronUp } from \"lucide-react\";\r\nimport { TableHead } from \"@/components/ui/table\";\r\nimport Filter from \"./Filter\";\r\n\r\ninterface HeaderProps<T extends Record<string, any>> {\r\n table: Table<T>;\r\n header: Header<T, unknown>;\r\n}\r\n\r\nconst THead = <T extends Record<string, any>>({\r\n table,\r\n header,\r\n}: HeaderProps<T>) => {\r\n const getCommonPinningStyles = (column: Column<T>): CSSProperties => {\r\n const isPinned = column.getIsPinned();\r\n const isLastLeftPinnedColumn =\r\n isPinned === \"left\" && column.getIsLastColumn(\"left\");\r\n const isFirstRightPinnedColumn =\r\n isPinned === \"right\" && column.getIsFirstColumn(\"right\");\r\n\r\n return {\r\n boxShadow: isLastLeftPinnedColumn\r\n ? \"-4px 0 4px -4px lightgray inset\"\r\n : isFirstRightPinnedColumn\r\n ? \"4px 0 4px -4px lightgray inset\"\r\n : undefined,\r\n left: isPinned === \"left\" ? `${column.getStart(\"left\")}px` : undefined,\r\n right: isPinned === \"right\" ? `${column.getAfter(\"right\")}px` : undefined,\r\n position: isPinned ? \"sticky\" : \"relative\",\r\n zIndex: isPinned ? 1 : 0,\r\n };\r\n };\r\n return (\r\n <TableHead\r\n className={cn(\r\n \"relative text-left select-none min-h-12 text-sm group/head\",\r\n {\r\n \"cursor-pointer\": header.column.getCanSort(),\r\n \"flex-1\": table.getAllColumns().length - 1 === header.index,\r\n }\r\n )}\r\n style={{\r\n width: header.getSize(),\r\n ...getCommonPinningStyles(header.column),\r\n }}\r\n >\r\n <div\r\n className=\"flex max-sm:flex-col md:gap-3 sm:items-center sm:justify-between whitespace-nowrap relative w-full px-1\"\r\n onClick={\r\n header.column.getCanSort()\r\n ? header.column.getToggleSortingHandler()\r\n : undefined\r\n }\r\n role=\"button\"\r\n tabIndex={0}\r\n >\r\n {header.isPlaceholder\r\n ? null\r\n : flexRender(header.column.columnDef.header, header.getContext())}\r\n {(header.column.getCanFilter() || header.column.getCanSort()) && (\r\n <div className=\"flex items-center gap-1 md:pr-5 last:pr-0\">\r\n {header.column.getCanFilter() ? (\r\n <Filter column={header.column} table={table} />\r\n ) : null}\r\n {header.column.getCanSort() && (\r\n <div className=\"flex flex-col text-zinc-800\">\r\n <ChevronDown\r\n className={cn(\r\n \"translate-y-2 translate-x-1 size-5 text-gray-800\",\r\n {\r\n \"text-green-600\": header.column.getIsSorted() === \"asc\",\r\n }\r\n )}\r\n />\r\n <ChevronUp\r\n className={cn(\r\n \"-translate-y-2 -translate-x-1 size-5 text-gray-800\",\r\n {\r\n \"text-green-600\": header.column.getIsSorted() === \"desc\",\r\n }\r\n )}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {header.column.getCanResize() &&\r\n header.index !== table.getAllColumns().length - 1 && (\r\n <div\r\n aria-hidden=\"true\"\r\n onMouseDown={header.getResizeHandler()}\r\n onTouchStart={header.getResizeHandler()}\r\n className={cn(\r\n \"absolute right-0 top-0 flex justify-end h-full w-2 cursor-col-resize select-none touch-none \"\r\n )}\r\n >\r\n <div\r\n className={cn(\r\n \"w-[1px] h-full bg-transparent peer-hover:bg-gray-200 group-hover/head:bg-gray-200 transition-all\",\r\n {\r\n \"bg-gray-200 hover:bg-gray-200\":\r\n header.column.getIsResizing(),\r\n }\r\n )}\r\n />\r\n </div>\r\n )}\r\n </TableHead>\r\n );\r\n};\r\n\r\nexport default THead;\r\n","import { cn } from \"@/lib/utils\";\r\nimport { Column, Table } from \"@tanstack/react-table\";\r\nimport { useState } from \"react\";\r\nimport { formatISO, isValid, parseISO } from \"date-fns\";\r\nimport {\r\n Popover,\r\n PopoverContent,\r\n PopoverTrigger,\r\n} from \"@/components/ui/popover\";\r\nimport { FormInput } from \"@/components/FormComponents/FormInput\";\r\nimport { FormSelect } from \"@/components/FormComponents/FormSelect\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Filter as FilterIcon } from \"lucide-react\";\r\nimport { FormCalendar } from \"@/components/FormComponents/FormCalendar\";\r\nimport { motion, AnimatePresence } from \"motion/react\";\r\n\r\nconst parseDateString = (dateString: unknown): Date | undefined => {\r\n if (!dateString) return undefined;\r\n try {\r\n if (typeof dateString === \"string\") {\r\n const parsedDate = parseISO(dateString);\r\n return isValid(parsedDate) ? parsedDate : undefined;\r\n }\r\n return undefined;\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n } catch (error) {\r\n return undefined;\r\n }\r\n};\r\n\r\nconst Filter = ({\r\n column,\r\n table,\r\n}: {\r\n column: Column<any, any>;\r\n table: Table<any>;\r\n}) => {\r\n const [open, setOpen] = useState(false);\r\n const uniqueValues = Array.from(\r\n new Set(\r\n table\r\n .getPreFilteredRowModel()\r\n .flatRows.map((row) => row.getValue(column.id))\r\n )\r\n );\r\n\r\n const columnFilterValue = column.getFilterValue();\r\n const [filteredValue, setFilteredValue] = useState<any>(columnFilterValue);\r\n const filterType = column.columnDef.meta?.filterType;\r\n\r\n const renderFilterInput = () => {\r\n if (filterType === \"date\") {\r\n return (\r\n <motion.div\r\n key=\"date-filter\"\r\n initial={{ opacity: 0, y: -10 }}\r\n animate={{ opacity: 1, y: 0 }}\r\n exit={{ opacity: 0, y: -10 }}\r\n >\r\n <FormCalendar\r\n className=\"w-full\"\r\n value={\r\n filteredValue !== undefined\r\n ? parseISO(filteredValue as string)\r\n : columnFilterValue !== undefined\r\n ? parseISO(columnFilterValue as string)\r\n : undefined\r\n }\r\n onSelect={(e) => {\r\n setFilteredValue(formatISO(e).split(\"T\")[0]);\r\n }}\r\n disabled={(date) => {\r\n const availableDates = table\r\n .getPreFilteredRowModel()\r\n .flatRows.map((row) => {\r\n return parseDateString(row.getValue(column.id));\r\n })\r\n .filter((d): d is Date => d !== undefined)\r\n .map((d) => formatISO(d).split(\"T\")[0]);\r\n\r\n return !availableDates.includes(formatISO(date).split(\"T\")[0]);\r\n }}\r\n />\r\n </motion.div>\r\n );\r\n }\r\n\r\n if (filterType === \"number\") {\r\n return (\r\n <motion.div\r\n key=\"number-filter\"\r\n initial={{ opacity: 0, y: -10 }}\r\n animate={{ opacity: 1, y: 0 }}\r\n exit={{ opacity: 0, y: -10 }}\r\n className=\"flex gap-3\"\r\n >\r\n <FormInput\r\n type=\"number\"\r\n value={(columnFilterValue as [number, number])?.[0] ?? \"\"}\r\n onChange={(e) =>\r\n setFilteredValue((old: [number, number]) => [\r\n e.target.value,\r\n old?.[1] ?? (columnFilterValue as [number, number])?.[1],\r\n ])\r\n }\r\n placeholder=\"Min\"\r\n className=\"w-full rounded-lg border border-gray-200 dark:border-gray-800\"\r\n numeric\r\n />\r\n <FormInput\r\n type=\"number\"\r\n value={(columnFilterValue as [number, number])?.[1] ?? \"\"}\r\n onChange={(e) =>\r\n setFilteredValue((old: [number, number]) => [\r\n old?.[0] ?? (columnFilterValue as [number, number])?.[0],\r\n e.target.value,\r\n ])\r\n }\r\n placeholder=\"Maks\"\r\n className=\"w-full rounded-lg border border-gray-200 dark:border-gray-800\"\r\n numeric\r\n />\r\n </motion.div>\r\n );\r\n }\r\n\r\n if (filterType === \"select\") {\r\n return (\r\n <FormSelect\r\n options={uniqueValues.map((value) => ({\r\n label: value as string,\r\n value: value as string,\r\n }))}\r\n onChange={(evt) => setFilteredValue(evt.target.value)}\r\n onClick={(evt) => evt.stopPropagation()}\r\n placeholder=\"Seçiniz\"\r\n value={\r\n (filteredValue !== undefined\r\n ? filteredValue\r\n : columnFilterValue ?? \"\") as string\r\n }\r\n />\r\n );\r\n }\r\n\r\n if (filterType === \"boolean\") {\r\n return (\r\n <motion.div\r\n key=\"boolean-filter\"\r\n initial={{ opacity: 0, y: -10 }}\r\n animate={{ opacity: 1, y: 0 }}\r\n exit={{ opacity: 0, y: -10 }}\r\n >\r\n <FormSelect\r\n options={[\r\n { label: \"Evet\", value: \"true\" },\r\n { label: \"Hayır\", value: \"false\" },\r\n ]}\r\n placeholder=\"Seçiniz\"\r\n onChange={(evt) => {\r\n setFilteredValue(evt.target.value);\r\n }}\r\n value={\r\n (filteredValue !== undefined\r\n ? filteredValue\r\n : columnFilterValue?.toString() ?? \"\") as string\r\n }\r\n className=\"rounded-lg border border-gray-200 dark:border-gray-800\"\r\n />\r\n </motion.div>\r\n );\r\n }\r\n\r\n // Default text input\r\n return (\r\n <motion.div\r\n key=\"string-filter\"\r\n initial={{ opacity: 0, y: -10 }}\r\n animate={{ opacity: 1, y: 0 }}\r\n exit={{ opacity: 0, y: -10 }}\r\n >\r\n <FormInput\r\n className=\"w-full rounded-lg border border-gray-200 dark:border-gray-800\"\r\n onChange={(evt) => setFilteredValue(evt.target.value)}\r\n onClick={(evt) => evt.stopPropagation()}\r\n placeholder=\"Ara\"\r\n type=\"text\"\r\n value={filteredValue ?? \"\"}\r\n />\r\n </motion.div>\r\n );\r\n };\r\n\r\n return (\r\n <Popover open={open} onOpenChange={setOpen}>\r\n <PopoverTrigger\r\n onClick={(e) => e.stopPropagation()}\r\n className={cn(\r\n \"p-1.5 rounded-full transition-colors hover:bg-green-100 group/filter\",\r\n {\r\n \"bg-green-100\": columnFilterValue !== undefined,\r\n }\r\n )}\r\n >\r\n <motion.div whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.95 }}>\r\n <FilterIcon\r\n className={cn(\"size-4 group-hover/filter:text-green-600\", {\r\n \"text-green-600\": columnFilterValue !== undefined,\r\n \"text-gray-800\": columnFilterValue === undefined,\r\n })}\r\n />\r\n </motion.div>\r\n </PopoverTrigger>\r\n <PopoverContent\r\n onClick={(e) => e.stopPropagation()}\r\n 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\"\r\n >\r\n <AnimatePresence>\r\n <>\r\n {renderFilterInput()}\r\n <div className=\"flex gap-2 mt-2\">\r\n <Button\r\n variant=\"outline\"\r\n className=\"flex-1 flex justify-center items-center hover:bg-gray-100 dark:hover:bg-gray-800\"\r\n disabled={\r\n columnFilterValue === undefined && filteredValue === undefined\r\n }\r\n onClick={() => {\r\n column.setFilterValue(\"\");\r\n setFilteredValue(undefined);\r\n setOpen(false);\r\n }}\r\n >\r\n Temizle\r\n </Button>\r\n <Button\r\n className=\"flex-1 flex justify-center items-center bg-green-600 hover:bg-green-700 text-white\"\r\n disabled={!filteredValue}\r\n onClick={() => {\r\n if (filteredValue === \"true\" || filteredValue === \"false\") {\r\n column.setFilterValue(filteredValue === \"true\");\r\n } else {\r\n column.setFilterValue(filteredValue);\r\n }\r\n setFilteredValue(undefined);\r\n setOpen(false);\r\n }}\r\n >\r\n Uygula\r\n </Button>\r\n </div>\r\n </>\r\n </AnimatePresence>\r\n </PopoverContent>\r\n </Popover>\r\n );\r\n};\r\n\r\nexport default Filter;\r\n","import * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Popover({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\nfunction PopoverTrigger({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"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\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n )\n}\n\nfunction PopoverAnchor({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />\n}\n\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }\n","\"use client\";\r\n\r\nimport { InputHTMLAttributes } from \"react\";\r\nimport { cva, VariantProps } from \"class-variance-authority\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { Input } from \"@/components/ui/input\";\r\n\r\nexport interface InputProps\r\n extends InputHTMLAttributes<HTMLInputElement>,\r\n VariantProps<typeof inputVariants> {\r\n label?: string;\r\n numeric?: boolean;\r\n decimalScale?: number;\r\n allowNegative?: boolean;\r\n showMessage?: boolean;\r\n}\r\n\r\nconst inputVariants = cva(\"\", {\r\n variants: {\r\n variant: {\r\n default:\r\n \"block w-full rounded-lg h-10 py-2 text-sm border-zinc-200 border focus:border-zinc-400 placeholder:text-zinc-600\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n});\r\n\r\nconst FormInput = ({\r\n label,\r\n variant,\r\n className,\r\n type,\r\n numeric,\r\n showMessage = true,\r\n decimalScale = 2,\r\n allowNegative = true,\r\n ...props\r\n}: InputProps) => {\r\n return (\r\n <div>\r\n {label && (\r\n <div className=\"text-sm font-medium text-zinc-800 mb-1 block\">\r\n {label}\r\n </div>\r\n )}\r\n <div className=\"relative flex items-center\">\r\n <Input\r\n className={cn(\r\n inputVariants({\r\n variant,\r\n }),\r\n className\r\n )}\r\n numeric={numeric}\r\n id={props.id}\r\n type={type}\r\n placeholder={props.placeholder}\r\n {...props}\r\n decimalScale={decimalScale}\r\n allowNegative={allowNegative}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nFormInput.displayName = \"FormInput\";\r\n\r\nexport { FormInput };\r\n","import { InputHTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { NumericFormat, NumericFormatProps } from \"react-number-format\";\n\ninterface InputProps extends InputHTMLAttributes<HTMLInputElement> {\n numeric?: boolean;\n decimalScale?: number;\n allowNegative?: boolean;\n}\n\nconst Input = ({\n className,\n type,\n numeric,\n decimalScale = 2,\n allowNegative = true,\n ...props\n}: InputProps) => {\n if (numeric) {\n const { value, ...numericProps } = props;\n return (\n <NumericFormat\n decimalScale={decimalScale}\n value={value?.toString() ?? \"\"}\n {...(numericProps as NumericFormatProps)}\n className={cn(\n \"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\",\n className\n )}\n allowNegative={allowNegative}\n allowedDecimalSeparators={[\",\"]}\n />\n );\n }\n return (\n <input\n type={type}\n className={cn(\n \"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\",\n className\n )}\n {...props}\n />\n );\n};\n\nInput.displayName = \"Input\";\n\nexport { Input };\n","import * as React from \"react\";\nimport * as SelectPrimitive from \"@radix-ui/react-select\";\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Select({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nfunction SelectGroup({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />;\n}\n\nfunction SelectValue({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nfunction SelectTrigger({\n className,\n size = \"default\",\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {\n size?: \"sm\" | \"default\";\n}) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n \"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\",\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\n\nfunction SelectContent({\n className,\n children,\n position = \"popper\",\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n \"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\",\n position === \"popper\" &&\n \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n className\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n \"p-1\",\n position === \"popper\" &&\n \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1\"\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"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\",\n className\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\"bg-border pointer-events-none -mx-1 my-1 h-px\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n return (\n <SelectPrimitive.ScrollUpButton\n data-slot=\"select-scroll-up-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronUpIcon className=\"size-4\" />\n </SelectPrimitive.ScrollUpButton>\n );\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n return (\n <SelectPrimitive.ScrollDownButton\n data-slot=\"select-scroll-down-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronDownIcon className=\"size-4\" />\n </SelectPrimitive.ScrollDownButton>\n );\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n","\"use client\";\r\n\r\nimport { ChangeEvent, ReactNode, SelectHTMLAttributes } from \"react\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectGroup,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from \"@/components/ui/select\";\r\n\r\nexport interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {\r\n label?: ReactNode;\r\n leftIcon?: ReactNode;\r\n rightIcon?: ReactNode;\r\n placeholder?: string;\r\n options: { value: string; label: string }[];\r\n}\r\n\r\nconst FormSelect = ({\r\n label,\r\n className,\r\n options,\r\n placeholder,\r\n ...props\r\n}: SelectProps) => {\r\n return (\r\n <div>\r\n {label && (\r\n <div className=\"text-sm font-medium text-zinc-800 mb-1 block\">\r\n {label}\r\n </div>\r\n )}\r\n <div className={cn(\"relative flex items-center\", className)}>\r\n <Select\r\n onValueChange={(value) =>\r\n props.onChange?.({\r\n target: { value },\r\n } as ChangeEvent<HTMLSelectElement>)\r\n }\r\n value={String(props.value ?? \"\")}\r\n >\r\n <SelectTrigger>\r\n <SelectValue placeholder={placeholder} />\r\n </SelectTrigger>\r\n <SelectContent>\r\n <SelectGroup>\r\n {options?.map((item) => (\r\n <SelectItem key={item.value} value={item.value}>\r\n {item.label}\r\n </SelectItem>\r\n ))}\r\n </SelectGroup>\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nFormSelect.displayName = \"FormSelect\";\r\n\r\nexport { FormSelect };\r\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"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\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"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\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","\"use client\";\r\n\r\nimport { cva } from \"class-variance-authority\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport { tr } from \"date-fns/locale\";\r\nimport { CalendarIcon } from \"lucide-react\";\r\nimport { format } from \"date-fns\";\r\nimport { Calendar } from \"@/components/ui/calendar\";\r\nimport {\r\n Popover,\r\n PopoverContent,\r\n PopoverTrigger,\r\n} from \"@/components/ui/popover\";\r\nimport { useState } from \"react\";\r\nimport { CalendarProps } from \"@/lib/types/calendar.types\";\r\n\r\nconst calendarVariants = cva(\"\", {\r\n variants: {\r\n intent: {\r\n primary: [\r\n \"bg-opacityGray\",\r\n \"text-zinc-800\",\r\n \"border-zinc-600 border rounded-[10px]\",\r\n \"focus:outline-none focus:ring-2 focus:ring-zinc-800 focus:border-transparent\",\r\n \"h-[40px]\",\r\n ],\r\n secondary: [\"bg-gray-200\", \"text-gray-800\", \"border-gray-400\"],\r\n success: [\"bg-green-500\", \"text-white\", \"border-transparent\"],\r\n white: [\r\n \"bg-white\",\r\n \"text-zinc-800\",\r\n \"border-none\",\r\n \"focus:outline-none focus:ring-2 focus:ring-zinc-800 focus:border-transparent\",\r\n ],\r\n transparent: [\r\n \"bg-transparent\",\r\n \"border-none\",\r\n \"hover:bg-gray-200\",\r\n \"text-zinc-800\",\r\n \"disabled:text-text-exp\",\r\n ],\r\n refresh: [\r\n \"bg-green-500/15\",\r\n \"text-green-500\",\r\n \"border-none\",\r\n \"hover:bg-green-500/25\",\r\n ],\r\n },\r\n hasLeftIcon: {\r\n true: \"pl-10\",\r\n false: \"pl-3\",\r\n },\r\n hasRightIcon: {\r\n true: \"pr-10 !text-left\",\r\n false: \"pr-3\",\r\n },\r\n hasError: {\r\n true: \"border-red-500 border\",\r\n false: \"border-zinc-600 border\",\r\n },\r\n variant: {\r\n default:\r\n \"block w-full rounded-lg h-10 py-2 text-sm outline-2 placeholder:text-zinc-600\",\r\n waitlist:\r\n \"block w-full rounded-lg h-14 py-2 text-sm outline-2 placeholder:text-zinc-600 bg-white\",\r\n filter:\r\n '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',\r\n },\r\n },\r\n