react-kd-grid 2.1.2 → 2.2.1

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.
Files changed (141) hide show
  1. package/dist/hooks/useAdvancedFiltering.d.ts +3 -1
  2. package/dist/index.esm.js +1 -1
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/package.json +2 -4
  7. package/dist/cjs/CustomGrid.d.ts +0 -3
  8. package/dist/cjs/components/ColumnFilterSelector.d.ts +0 -18
  9. package/dist/cjs/components/CustomSelect.d.ts +0 -14
  10. package/dist/cjs/components/FooterAggregate.d.ts +0 -16
  11. package/dist/cjs/components/GridHeader.d.ts +0 -33
  12. package/dist/cjs/components/GridRows.d.ts +0 -49
  13. package/dist/cjs/components/GroupBar.d.ts +0 -12
  14. package/dist/cjs/components/GroupHeader.d.ts +0 -29
  15. package/dist/cjs/components/NoDataMessage.d.ts +0 -7
  16. package/dist/cjs/components/PaginationControls.d.ts +0 -15
  17. package/dist/cjs/components/Popover.d.ts +0 -17
  18. package/dist/cjs/components/RowContextMenu.d.ts +0 -22
  19. package/dist/cjs/components/SearchToolbar.d.ts +0 -79
  20. package/dist/cjs/components/filters/BooleanFilter.d.ts +0 -7
  21. package/dist/cjs/components/filters/DateFilter.d.ts +0 -9
  22. package/dist/cjs/components/filters/FilterContent.d.ts +0 -9
  23. package/dist/cjs/components/filters/FilterPopup.d.ts +0 -2
  24. package/dist/cjs/components/filters/MultiselectFilter.d.ts +0 -10
  25. package/dist/cjs/components/filters/NumberFilter.d.ts +0 -9
  26. package/dist/cjs/components/filters/TextFilter.d.ts +0 -8
  27. package/dist/cjs/components/filters/index.d.ts +0 -6
  28. package/dist/cjs/components/ui/DatePicker.d.ts +0 -10
  29. package/dist/cjs/constants.d.ts +0 -1
  30. package/dist/cjs/hooks/useAdvancedFiltering.d.ts +0 -16
  31. package/dist/cjs/hooks/useDataWorker.d.ts +0 -10
  32. package/dist/cjs/hooks/useExport.d.ts +0 -15
  33. package/dist/cjs/hooks/useFilteringAndSorting.d.ts +0 -16
  34. package/dist/cjs/hooks/useGrouping.d.ts +0 -28
  35. package/dist/cjs/hooks/usePagination.d.ts +0 -28
  36. package/dist/cjs/hooks/useSelection.d.ts +0 -13
  37. package/dist/cjs/hooks/useVirtualization.d.ts +0 -17
  38. package/dist/cjs/index.d.ts +0 -11
  39. package/dist/cjs/index.js +0 -2
  40. package/dist/cjs/index.js.map +0 -1
  41. package/dist/cjs/types.d.ts +0 -421
  42. package/dist/cjs/utils/highlightText.d.ts +0 -15
  43. package/dist/cjs/workers/dataWorker.d.ts +0 -16
  44. package/dist/core/DataGrid/DataGrid.d.ts +0 -3
  45. package/dist/esm/CustomGrid.d.ts +0 -3
  46. package/dist/esm/CustomGrid.js +0 -2
  47. package/dist/esm/CustomGrid.js.map +0 -1
  48. package/dist/esm/components/ColumnFilterSelector.d.ts +0 -18
  49. package/dist/esm/components/ColumnFilterSelector.js +0 -2
  50. package/dist/esm/components/ColumnFilterSelector.js.map +0 -1
  51. package/dist/esm/components/CustomSelect.d.ts +0 -14
  52. package/dist/esm/components/CustomSelect.js +0 -2
  53. package/dist/esm/components/CustomSelect.js.map +0 -1
  54. package/dist/esm/components/FooterAggregate.d.ts +0 -16
  55. package/dist/esm/components/FooterAggregate.js +0 -2
  56. package/dist/esm/components/FooterAggregate.js.map +0 -1
  57. package/dist/esm/components/GridHeader.d.ts +0 -33
  58. package/dist/esm/components/GridHeader.js +0 -2
  59. package/dist/esm/components/GridHeader.js.map +0 -1
  60. package/dist/esm/components/GridRows.d.ts +0 -49
  61. package/dist/esm/components/GridRows.js +0 -2
  62. package/dist/esm/components/GridRows.js.map +0 -1
  63. package/dist/esm/components/GroupBar.d.ts +0 -12
  64. package/dist/esm/components/GroupBar.js +0 -2
  65. package/dist/esm/components/GroupBar.js.map +0 -1
  66. package/dist/esm/components/GroupHeader.d.ts +0 -29
  67. package/dist/esm/components/GroupHeader.js +0 -2
  68. package/dist/esm/components/GroupHeader.js.map +0 -1
  69. package/dist/esm/components/NoDataMessage.d.ts +0 -7
  70. package/dist/esm/components/NoDataMessage.js +0 -2
  71. package/dist/esm/components/NoDataMessage.js.map +0 -1
  72. package/dist/esm/components/PaginationControls.d.ts +0 -15
  73. package/dist/esm/components/PaginationControls.js +0 -2
  74. package/dist/esm/components/PaginationControls.js.map +0 -1
  75. package/dist/esm/components/Popover.d.ts +0 -17
  76. package/dist/esm/components/Popover.js +0 -2
  77. package/dist/esm/components/Popover.js.map +0 -1
  78. package/dist/esm/components/RowContextMenu.d.ts +0 -22
  79. package/dist/esm/components/SearchToolbar.d.ts +0 -79
  80. package/dist/esm/components/SearchToolbar.js +0 -2
  81. package/dist/esm/components/SearchToolbar.js.map +0 -1
  82. package/dist/esm/components/filters/BooleanFilter.d.ts +0 -7
  83. package/dist/esm/components/filters/BooleanFilter.js +0 -2
  84. package/dist/esm/components/filters/BooleanFilter.js.map +0 -1
  85. package/dist/esm/components/filters/DateFilter.d.ts +0 -9
  86. package/dist/esm/components/filters/DateFilter.js +0 -2
  87. package/dist/esm/components/filters/DateFilter.js.map +0 -1
  88. package/dist/esm/components/filters/FilterContent.d.ts +0 -9
  89. package/dist/esm/components/filters/FilterContent.js +0 -2
  90. package/dist/esm/components/filters/FilterContent.js.map +0 -1
  91. package/dist/esm/components/filters/FilterPopup.d.ts +0 -2
  92. package/dist/esm/components/filters/MultiselectFilter.d.ts +0 -10
  93. package/dist/esm/components/filters/MultiselectFilter.js +0 -2
  94. package/dist/esm/components/filters/MultiselectFilter.js.map +0 -1
  95. package/dist/esm/components/filters/NumberFilter.d.ts +0 -9
  96. package/dist/esm/components/filters/NumberFilter.js +0 -2
  97. package/dist/esm/components/filters/NumberFilter.js.map +0 -1
  98. package/dist/esm/components/filters/TextFilter.d.ts +0 -8
  99. package/dist/esm/components/filters/TextFilter.js +0 -2
  100. package/dist/esm/components/filters/TextFilter.js.map +0 -1
  101. package/dist/esm/components/filters/index.d.ts +0 -6
  102. package/dist/esm/components/ui/DatePicker.d.ts +0 -10
  103. package/dist/esm/components/ui/DatePicker.js +0 -2
  104. package/dist/esm/components/ui/DatePicker.js.map +0 -1
  105. package/dist/esm/constants.d.ts +0 -1
  106. package/dist/esm/constants.js +0 -2
  107. package/dist/esm/constants.js.map +0 -1
  108. package/dist/esm/hooks/useAdvancedFiltering.d.ts +0 -16
  109. package/dist/esm/hooks/useAdvancedFiltering.js +0 -2
  110. package/dist/esm/hooks/useAdvancedFiltering.js.map +0 -1
  111. package/dist/esm/hooks/useDataWorker.d.ts +0 -10
  112. package/dist/esm/hooks/useDataWorker.js +0 -2
  113. package/dist/esm/hooks/useDataWorker.js.map +0 -1
  114. package/dist/esm/hooks/useExport.d.ts +0 -15
  115. package/dist/esm/hooks/useExport.js +0 -2
  116. package/dist/esm/hooks/useExport.js.map +0 -1
  117. package/dist/esm/hooks/useFilteringAndSorting.d.ts +0 -16
  118. package/dist/esm/hooks/useFilteringAndSorting.js +0 -2
  119. package/dist/esm/hooks/useFilteringAndSorting.js.map +0 -1
  120. package/dist/esm/hooks/useGrouping.d.ts +0 -28
  121. package/dist/esm/hooks/useGrouping.js +0 -2
  122. package/dist/esm/hooks/useGrouping.js.map +0 -1
  123. package/dist/esm/hooks/usePagination.d.ts +0 -28
  124. package/dist/esm/hooks/usePagination.js +0 -2
  125. package/dist/esm/hooks/usePagination.js.map +0 -1
  126. package/dist/esm/hooks/useSelection.d.ts +0 -13
  127. package/dist/esm/hooks/useSelection.js +0 -2
  128. package/dist/esm/hooks/useSelection.js.map +0 -1
  129. package/dist/esm/hooks/useVirtualization.d.ts +0 -17
  130. package/dist/esm/hooks/useVirtualization.js +0 -2
  131. package/dist/esm/hooks/useVirtualization.js.map +0 -1
  132. package/dist/esm/index.d.ts +0 -11
  133. package/dist/esm/index.js +0 -2
  134. package/dist/esm/index.js.map +0 -1
  135. package/dist/esm/types.d.ts +0 -421
  136. package/dist/esm/utils/highlightText.d.ts +0 -15
  137. package/dist/esm/utils/highlightText.js +0 -2
  138. package/dist/esm/utils/highlightText.js.map +0 -1
  139. package/dist/esm/workers/dataWorker.d.ts +0 -16
  140. package/dist/hooks/useFilteringAndSorting.d.ts +0 -16
  141. package/dist/workers/dataWorker.d.ts +0 -16
@@ -1 +0,0 @@
1
- {"version":3,"file":"PaginationControls.js","sources":["../../../../../components/PaginationControls.tsx"],"sourcesContent":["import {\n ChevronLeft,\n ChevronRight,\n ChevronsLeft,\n ChevronsRight,\n Loader2,\n Users,\n Eye,\n Database,\n} from \"lucide-react\";\nimport { PaginationConfig } from \"../types\";\n\ninterface PaginationControlsProps {\n paginationConfig: PaginationConfig;\n currentPage: number;\n isServerLoading: boolean;\n selectedRowsCount: number;\n totalDataLength: number;\n filteredDataLength?: number;\n paginationMode?: \"client\" | \"server\";\n onPageChange: (page: number, pageSize: number) => void;\n onPageSizeChange: (pageSize: number) => void;\n showNoDataMessage?: boolean;\n}\n\nexport const PaginationControls = ({\n paginationConfig,\n currentPage,\n isServerLoading,\n selectedRowsCount,\n totalDataLength,\n filteredDataLength,\n paginationMode = \"client\",\n onPageChange,\n onPageSizeChange,\n}: PaginationControlsProps) => {\n // Helper function to get the effective total count\n const getEffectiveTotalCount = () => {\n if (paginationMode === \"server\") {\n return paginationConfig.totalRows || totalDataLength;\n }\n return filteredDataLength || totalDataLength;\n };\n\n // Helper function to get the current page range\n const getCurrentPageRange = () => {\n const effectiveTotal = paginationConfig.enabled\n ? paginationConfig.totalRows || totalDataLength\n : getEffectiveTotalCount();\n\n const start = paginationConfig.enabled\n ? Math.min(\n (currentPage - 1) * paginationConfig.pageSize + 1,\n effectiveTotal\n )\n : 1;\n\n const end = paginationConfig.enabled\n ? Math.min(currentPage * paginationConfig.pageSize, effectiveTotal)\n : effectiveTotal;\n\n return { start, end, total: effectiveTotal };\n };\n\n const { start, end, total } = getCurrentPageRange();\n const isFiltered =\n paginationMode === \"client\" &&\n filteredDataLength &&\n filteredDataLength !== totalDataLength;\n\n return (\n <div className=\"px-3 sm:px-6 py-2 border-t border-gray-200 dark:border-gray-700 bg-linear-to-r from-white via-gray-50 to-white dark:from-gray-900 dark:via-gray-800 dark:to-gray-900\">\n <div className=\"flex flex-col xl:flex-row gap-4 xl:gap-6 xl:justify-between xl:items-center\">\n {/* Left Section: Stats and Page Size */}\n <div className=\"flex flex-col sm:flex-row gap-3 sm:gap-4 items-start sm:items-center\">\n {/* Stats Section */}\n <div className=\"flex flex-wrap items-center gap-2 sm:gap-3\">\n {/* Total Count Badge - Only when pagination is disabled */}\n {!paginationConfig.enabled && (\n <div className=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-semibold bg-linear-to-r from-blue-500 to-blue-600 text-white shadow-lg ring-2 ring-blue-500/20\">\n <Database className=\"w-3 h-3\" />\n <span className=\"font-bold\">\n {total.toLocaleString()} {total === 1 ? \"Record\" : \"Records\"}\n </span>\n {isFiltered && (\n <span className=\"text-blue-100 font-normal\">\n (of {totalDataLength.toLocaleString()})\n </span>\n )}\n </div>\n )}\n\n {/* Selected Count Badge */}\n {selectedRowsCount > 0 && (\n <div className=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-semibold bg-linear-to-r from-primary to-primary text-white shadow-lg ring-2 ring-primary/20\">\n <Users className=\"w-3 h-3\" />\n <span>{selectedRowsCount.toLocaleString()} selected</span>\n </div>\n )}\n\n {/* Filtered Indicator */}\n {isFiltered && (\n <div className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-linear-to-r from-warning/10 to-warning/5 text-warning border border-warning/20\">\n <Eye className=\"w-3 h-3\" />\n <span>Filtered</span>\n </div>\n )}\n\n {/* Page Range Info (Desktop) */}\n {paginationConfig.enabled && (\n <div className=\"hidden sm:block text-sm text-gray-600 dark:text-gray-400 font-medium\">\n <span className=\"inline-flex items-center gap-1\">\n <span>Showing</span>\n <span className=\"px-2 py-0.5 bg-gray-100 dark:bg-gray-700 rounded-md font-bold text-gray-900 dark:text-gray-100\">\n {start.toLocaleString()}\n </span>\n <span>-</span>\n <span className=\"px-2 py-0.5 bg-gray-100 dark:bg-gray-700 rounded-md font-bold text-gray-900 dark:text-gray-100\">\n {end.toLocaleString()}\n </span>\n <span>of {total.toLocaleString()}</span>\n </span>\n </div>\n )}\n </div>\n\n {/* Page Size Selector */}\n {paginationConfig.enabled &&\n paginationConfig.showPageSizeSelector && (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-gray-700 dark:text-gray-300 whitespace-nowrap\">\n Rows per page:\n </span>\n <select\n value={paginationConfig.pageSize}\n onChange={(e) => onPageSizeChange(Number(e.target.value))}\n className=\"border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 rounded-xl px-3 py-1 text-sm font-medium focus:ring-2 focus:ring-primary focus:border-primary disabled:opacity-50 disabled:cursor-not-allowed shadow-sm transition-all duration-200 hover:border-gray-400 dark:hover:border-gray-500\"\n disabled={isServerLoading}\n >\n {paginationConfig.pageSizeOptions?.map((size) => (\n <option key={size} value={size}>\n {size}\n </option>\n ))}\n </select>\n </div>\n )}\n </div>\n\n {/* Right Section: Pagination Controls */}\n {paginationConfig.enabled && (\n <div className=\"flex flex-col sm:flex-row items-start sm:items-center gap-3 sm:gap-4\">\n {/* Loading Indicator */}\n {isServerLoading && (\n <div className=\"flex items-center gap-2 px-3 py-1.5 bg-blue-50 dark:bg-blue-900/20 rounded-full border border-blue-200 dark:border-blue-800\">\n <Loader2 className=\"w-4 h-4 animate-spin text-primary\" />\n <span className=\"text-sm font-medium text-primary\">\n Loading...\n </span>\n </div>\n )}\n\n {/* Mobile Page Info */}\n <div className=\"sm:hidden text-sm text-gray-600 dark:text-gray-400 font-medium\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"inline-flex items-center gap-1\">\n <span>Page</span>\n <span className=\"px-2 py-0.5 bg-gray-100 dark:bg-gray-700 rounded-md font-bold text-gray-900 dark:text-gray-100\">\n {currentPage.toLocaleString()}\n </span>\n <span>of</span>\n <span className=\"px-2 py-0.5 bg-gray-100 dark:bg-gray-700 rounded-md font-bold text-gray-900 dark:text-gray-100\">\n {paginationConfig.totalPages.toLocaleString()}\n </span>\n </span>\n <span className=\"text-xs text-gray-500 dark:text-gray-500\">\n {start.toLocaleString()} - {end.toLocaleString()} of{\" \"}\n {total.toLocaleString()}\n </span>\n </div>\n </div>\n\n {/* Pagination Navigation */}\n <div className=\"flex items-center gap-1 sm:gap-2\">\n {/* First Page Button */}\n <button\n onClick={() => onPageChange(1, paginationConfig.pageSize)}\n disabled={currentPage === 1 || isServerLoading}\n className=\"inline-flex items-center justify-center w-8 h-8 rounded-full border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 transition-all duration-200 hover:border-gray-400 dark:hover:border-gray-500 hover:shadow-md focus:ring-2 focus:ring-primary/20 focus:border-primary\"\n title=\"First page\"\n aria-label=\"Go to first page\"\n >\n <ChevronsLeft className=\"w-3.5 h-3.5\" />\n </button>\n\n {/* Previous Page Button */}\n <button\n onClick={() =>\n onPageChange(currentPage - 1, paginationConfig.pageSize)\n }\n disabled={currentPage === 1 || isServerLoading}\n className=\"inline-flex items-center justify-center w-8 h-8 rounded-full border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 transition-all duration-200 hover:border-gray-400 dark:hover:border-gray-500 hover:shadow-md focus:ring-2 focus:ring-primary/20 focus:border-primary\"\n title=\"Previous page\"\n aria-label=\"Go to previous page\"\n >\n <ChevronLeft className=\"w-3.5 h-3.5\" />\n </button>\n\n {/* Mobile Page Selector */}\n <div className=\"sm:hidden\">\n <select\n value={currentPage}\n onChange={(e) =>\n onPageChange(\n Number(e.target.value),\n paginationConfig.pageSize\n )\n }\n className=\"border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 rounded-xl px-3 py-2 text-sm font-medium focus:ring-2 focus:ring-primary focus:border-primary disabled:opacity-50 disabled:cursor-not-allowed shadow-sm min-w-[80px]\"\n disabled={isServerLoading}\n aria-label=\"Select page\"\n >\n {Array.from(\n { length: paginationConfig.totalPages },\n (_, i) => i + 1\n ).map((page) => (\n <option key={page} value={page}>\n {page}\n </option>\n ))}\n </select>\n </div>\n\n {/* Desktop Page Numbers */}\n <div className=\"hidden sm:flex items-center gap-1 mx-2\">\n {(() => {\n const pages = [];\n const totalPages = paginationConfig.totalPages;\n const current = currentPage;\n const maxVisible =\n typeof window !== \"undefined\" && window.innerWidth >= 768\n ? 7\n : 5;\n\n if (totalPages <= maxVisible) {\n for (let i = 1; i <= totalPages; i++) {\n pages.push(i);\n }\n } else {\n const delta = Math.floor(maxVisible / 2) - 1;\n if (current <= delta + 1) {\n for (let i = 1; i <= maxVisible - 2; i++) pages.push(i);\n pages.push(\"ellipsis1\");\n pages.push(totalPages);\n } else if (current >= totalPages - delta) {\n pages.push(1);\n pages.push(\"ellipsis1\");\n for (\n let i = totalPages - (maxVisible - 3);\n i <= totalPages;\n i++\n )\n pages.push(i);\n } else {\n pages.push(1);\n pages.push(\"ellipsis1\");\n for (let i = current - delta; i <= current + delta; i++)\n pages.push(i);\n pages.push(\"ellipsis2\");\n pages.push(totalPages);\n }\n }\n\n return pages.map((page) => {\n if (typeof page === \"string\") {\n return (\n <div\n key={page}\n className=\"flex items-center justify-center w-8 h-8 text-gray-400 dark:text-gray-500 select-none\"\n aria-hidden=\"true\"\n >\n <span className=\"text-lg leading-none\">⋯</span>\n </div>\n );\n }\n\n const isActive = page === current;\n return (\n <button\n key={page}\n onClick={() =>\n onPageChange(page, paginationConfig.pageSize)\n }\n disabled={isServerLoading}\n className={`inline-flex items-center justify-center w-8 h-8 rounded-full text-sm font-semibold transition-all duration-200 focus:ring-2 focus:ring-primary/20 focus:outline-none cursor-pointer ${\n isActive\n ? \"bg-linear-to-r from-primary to-primary text-white shadow-lg ring-2 ring-primary/20 transform scale-105 z-10 relative\"\n : \"border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-400 dark:hover:border-gray-500 hover:shadow-md disabled:opacity-40 disabled:cursor-not-allowed\"\n }`}\n aria-label={`Go to page ${page}`}\n aria-current={isActive ? \"page\" : undefined}\n >\n {page}\n </button>\n );\n });\n })()}\n </div>\n\n {/* Next Page Button */}\n <button\n onClick={() =>\n onPageChange(currentPage + 1, paginationConfig.pageSize)\n }\n disabled={\n currentPage === paginationConfig.totalPages || isServerLoading\n }\n className=\"inline-flex items-center justify-center w-8 h-8 rounded-full border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 transition-all duration-200 hover:border-gray-400 dark:hover:border-gray-500 hover:shadow-md focus:ring-2 focus:ring-primary/20 focus:border-primary\"\n title=\"Next page\"\n aria-label=\"Go to next page\"\n >\n <ChevronRight className=\"w-3.5 h-3.5\" />\n </button>\n\n {/* Last Page Button */}\n <button\n onClick={() =>\n onPageChange(\n paginationConfig.totalPages,\n paginationConfig.pageSize\n )\n }\n disabled={\n currentPage === paginationConfig.totalPages || isServerLoading\n }\n className=\"inline-flex items-center justify-center w-8 h-8 rounded-full border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 transition-all duration-200 hover:border-gray-400 dark:hover:border-gray-500 hover:shadow-md focus:ring-2 focus:ring-primary/20 focus:border-primary\"\n title=\"Last page\"\n aria-label=\"Go to last page\"\n >\n <ChevronsRight className=\"w-3.5 h-3.5\" />\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n"],"names":["PaginationControls","paginationConfig","currentPage","isServerLoading","selectedRowsCount","totalDataLength","filteredDataLength","paginationMode","onPageChange","onPageSizeChange","start","end","total","effectiveTotal","enabled","totalRows","Math","min","pageSize","getCurrentPageRange","isFiltered","_jsx","className","children","_jsxs","Database","toLocaleString","Users","Eye","showPageSizeSelector","value","onChange","e","Number","target","disabled","pageSizeOptions","map","size","Loader2","totalPages","onClick","title","ChevronsLeft","ChevronLeft","Array","from","length","_","i","page","pages","current","maxVisible","window","innerWidth","push","delta","floor","isActive","undefined","ChevronRight","ChevronsRight"],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- import React from "react";
2
- import { type Placement } from "@floating-ui/react";
3
- interface PopoverProps {
4
- open: boolean;
5
- anchorEl: HTMLElement | null;
6
- onClose: () => void;
7
- placement?: Placement;
8
- offset?: number;
9
- sameWidth?: boolean;
10
- maxHeight?: number | string;
11
- zIndex?: number;
12
- className?: string;
13
- children: React.ReactNode;
14
- shouldIgnoreClose?: (target: Node) => boolean;
15
- }
16
- export declare const Popover: React.FC<PopoverProps>;
17
- export default Popover;
@@ -1,2 +0,0 @@
1
- import{jsx as e}from"react/jsx-runtime";import{useEffect as t}from"react";import{createPortal as n}from"react-dom";import{useFloating as o,autoUpdate as r,offset as a,flip as i,shift as s,size as d}from"@floating-ui/react";const l=({open:l,anchorEl:m,onClose:c,placement:p="bottom-start",offset:u=8,sameWidth:f=!1,maxHeight:g,zIndex:h=1e3,className:v,children:x,shouldIgnoreClose:y})=>{const{refs:w,floatingStyles:E,update:b}=o({placement:p,whileElementsMounted:r,middleware:[a(u),i({padding:8}),s({padding:8}),d({apply({rects:e,elements:t,availableHeight:n,availableWidth:o}){const r=t.floating;r&&(f&&(r.style.width=`${e.reference.width}px`),r.style.maxHeight=null!=g?"number"==typeof g?`${g}px`:String(g):`${n}px`,null!=o&&(r.style.maxWidth=`${o}px`))}})]});return t(()=>{m&&w.setReference(m),l&&b&&b()},[m,l,w,b]),t(()=>{if(!l)return;const e=e=>{const t=e.target;if(y&&y(t))return;const n=w.floating.current;n&&(m&&m.contains(t)||n&&n.contains(t)||c())},t=e=>{"Escape"===e.key&&c()};return document.addEventListener("mousedown",e),document.addEventListener("keydown",t),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("keydown",t)}},[l,c,w.floating,m]),l&&m?n(e("div",{ref:w.setFloating,"data-popover-root":"true",style:{...E,zIndex:h,position:E.position,overflowX:"hidden"},className:v,children:x}),document.body):null};export{l as Popover,l as default};
2
- //# sourceMappingURL=Popover.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Popover.js","sources":["../../../../../components/Popover.tsx"],"sourcesContent":["import React, { useEffect } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n autoUpdate,\n flip,\n offset as fOffset,\n shift,\n size,\n useFloating,\n type Placement,\n} from \"@floating-ui/react\";\n\ninterface PopoverProps {\n open: boolean;\n anchorEl: HTMLElement | null;\n onClose: () => void;\n placement?: Placement;\n offset?: number;\n sameWidth?: boolean;\n maxHeight?: number | string;\n zIndex?: number;\n className?: string;\n children: React.ReactNode;\n shouldIgnoreClose?: (target: Node) => boolean;\n}\n\nexport const Popover: React.FC<PopoverProps> = ({\n open,\n anchorEl,\n onClose,\n placement = \"bottom-start\",\n offset = 8,\n sameWidth = false,\n maxHeight,\n zIndex = 1000,\n className,\n children,\n shouldIgnoreClose,\n}) => {\n const { refs, floatingStyles, update } = useFloating({\n placement,\n whileElementsMounted: autoUpdate,\n middleware: [\n fOffset(offset),\n flip({ padding: 8 }),\n shift({ padding: 8 }),\n size({\n apply({ rects, elements, availableHeight, availableWidth }) {\n const el = elements.floating as HTMLElement;\n if (!el) return;\n if (sameWidth) {\n el.style.width = `${rects.reference.width}px`;\n }\n if (maxHeight != null) {\n el.style.maxHeight =\n typeof maxHeight === \"number\"\n ? `${maxHeight}px`\n : String(maxHeight);\n } else {\n el.style.maxHeight = `${availableHeight}px`;\n }\n if (availableWidth != null) {\n el.style.maxWidth = `${availableWidth}px`;\n }\n },\n }),\n ],\n });\n\n // Attach the reference programmatically\n useEffect(() => {\n if (anchorEl) refs.setReference(anchorEl);\n // Force an update when anchor changes\n if (open && update) update();\n }, [anchorEl, open, refs, update]);\n\n // Close on outside click and Escape\n useEffect(() => {\n if (!open) return;\n const onMouseDown = (e: MouseEvent) => {\n const t = e.target as Node;\n if (shouldIgnoreClose && shouldIgnoreClose(t)) return;\n const floating = refs.floating.current;\n if (!floating) return;\n if (\n (anchorEl && anchorEl.contains(t)) ||\n (floating && floating.contains(t))\n ) {\n return; // inside\n }\n onClose();\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"mousedown\", onMouseDown);\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"mousedown\", onMouseDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [open, onClose, refs.floating, anchorEl]);\n\n if (!open || !anchorEl) return null;\n\n return createPortal(\n <div\n ref={refs.setFloating}\n data-popover-root=\"true\"\n style={{\n ...floatingStyles,\n zIndex,\n position: floatingStyles.position as any,\n overflowX: \"hidden\",\n }}\n className={className}\n >\n {children}\n </div>,\n document.body\n );\n};\n\nexport default Popover;\n"],"names":["Popover","open","anchorEl","onClose","placement","offset","sameWidth","maxHeight","zIndex","className","children","shouldIgnoreClose","refs","floatingStyles","update","useFloating","whileElementsMounted","autoUpdate","middleware","fOffset","flip","padding","shift","size","apply","rects","elements","availableHeight","availableWidth","el","floating","style","width","reference","String","maxWidth","useEffect","setReference","onMouseDown","e","t","target","current","contains","onKeyDown","key","document","addEventListener","removeEventListener","createPortal","_jsx","ref","setFloating","position","overflowX","body"],"mappings":"+NA0Ba,MAAAA,EAAkC,EAC7CC,OACAC,WACAC,UACAC,YAAY,eAAcC,OAC1BA,EAAS,EACTC,aAAY,EACZC,YACAC,SAAS,IACTC,YACAC,WACAC,wBAEA,MAAMC,KAAEA,EAAIC,eAAEA,EAAcC,OAAEA,GAAWC,EAAY,CACnDX,YACAY,qBAAsBC,EACtBC,WAAY,CACVC,EAAQd,GACRe,EAAK,CAAEC,QAAS,IAChBC,EAAM,CAAED,QAAS,IACjBE,EAAK,CACH,KAAAC,EAAMC,MAAEA,EAAKC,SAAEA,EAAQC,gBAAEA,EAAeC,eAAEA,IACxC,MAAMC,EAAKH,EAASI,SACfD,IACDvB,IACFuB,EAAGE,MAAMC,MAAQ,GAAGP,EAAMQ,UAAUD,WAGpCH,EAAGE,MAAMxB,UADM,MAAbA,EAEqB,iBAAdA,EACH,GAAGA,MACH2B,OAAO3B,GAEQ,GAAGoB,MAEJ,MAAlBC,IACFC,EAAGE,MAAMI,SAAW,GAAGP,OAE1B,OAuCP,OAjCAQ,EAAU,KACJlC,GAAUU,EAAKyB,aAAanC,GAE5BD,GAAQa,GAAQA,KACnB,CAACZ,EAAUD,EAAMW,EAAME,IAG1BsB,EAAU,KACR,IAAKnC,EAAM,OACX,MAAMqC,EAAeC,IACnB,MAAMC,EAAID,EAAEE,OACZ,GAAI9B,GAAqBA,EAAkB6B,GAAI,OAC/C,MAAMV,EAAWlB,EAAKkB,SAASY,QAC1BZ,IAEF5B,GAAYA,EAASyC,SAASH,IAC9BV,GAAYA,EAASa,SAASH,IAIjCrC,MAEIyC,EAAaL,IACH,WAAVA,EAAEM,KAAkB1C,KAI1B,OAFA2C,SAASC,iBAAiB,YAAaT,GACvCQ,SAASC,iBAAiB,UAAWH,GAC9B,KACLE,SAASE,oBAAoB,YAAaV,GAC1CQ,SAASE,oBAAoB,UAAWJ,KAEzC,CAAC3C,EAAME,EAASS,EAAKkB,SAAU5B,IAE7BD,GAASC,EAEP+C,EACLC,EACE,MAAA,CAAAC,IAAKvC,EAAKwC,YACQ,oBAAA,OAClBrB,MAAO,IACFlB,EACHL,SACA6C,SAAUxC,EAAewC,SACzBC,UAAW,UAEb7C,UAAWA,EAEVC,SAAAA,IAEHoC,SAASS,MAhBoB"}
@@ -1,22 +0,0 @@
1
- import { ReactNode } from "react";
2
- import { GridRow } from "../types";
3
- export interface ContextMenuItem {
4
- id: string;
5
- label: string;
6
- icon?: ReactNode;
7
- onClick: (row: GridRow) => void;
8
- disabled?: boolean;
9
- separator?: boolean;
10
- }
11
- interface RowContextMenuProps {
12
- row: GridRow;
13
- position: {
14
- x: number;
15
- y: number;
16
- };
17
- isVisible: boolean;
18
- onClose: () => void;
19
- menuItems?: ContextMenuItem[];
20
- }
21
- export declare const RowContextMenu: ({ row, position, isVisible, onClose, menuItems, }: RowContextMenuProps) => import("react/jsx-runtime").JSX.Element;
22
- export {};
@@ -1,79 +0,0 @@
1
- import { ReactNode, ChangeEvent } from "react";
2
- import type { Density } from "../types";
3
- export type ExportFormat = "csv" | "json" | "xlsx";
4
- export type BulkAction = "delete" | "archive" | "copy" | "edit" | "export";
5
- export interface BulkActionOption {
6
- id: BulkAction;
7
- label: string;
8
- icon: ReactNode;
9
- onClick: (selectedRows: Set<string | number>) => void;
10
- disabled?: boolean;
11
- destructive?: boolean;
12
- }
13
- interface ColumnVisibility {
14
- [columnKey: string]: boolean;
15
- }
16
- interface SavedFilter {
17
- id: string;
18
- name: string;
19
- globalFilter: string;
20
- columnFilters: Record<string, any>;
21
- }
22
- interface SearchToolbarProps {
23
- globalFilter: string;
24
- filteredDataLength: number;
25
- totalDataLength: number;
26
- paginationMode?: "client" | "server";
27
- totalRows?: number;
28
- selectedRowsCount?: number;
29
- selectedRows?: Set<string | number>;
30
- showExport?: boolean;
31
- showRefresh?: boolean;
32
- showColumnToggle?: boolean;
33
- showBulkActions?: boolean;
34
- showSavedFilters?: boolean;
35
- columns?: Array<{
36
- key: string;
37
- header: string;
38
- visible?: boolean;
39
- filterOptions?: Array<{
40
- label: string;
41
- value: string | number;
42
- }>;
43
- filterType?: "text" | "select" | "multiselect";
44
- filterable?: any;
45
- }>;
46
- columnVisibility?: ColumnVisibility;
47
- columnFilters?: Record<string, any>;
48
- savedFilters?: SavedFilter[];
49
- bulkActions?: BulkActionOption[];
50
- isLoading?: boolean;
51
- exportOptions?: {
52
- enabled: boolean;
53
- formats?: ExportFormat[];
54
- filename?: string;
55
- onExport?: (format: ExportFormat, exportSelected: boolean) => void;
56
- };
57
- onGlobalFilterChange: (e: ChangeEvent<HTMLInputElement>) => void;
58
- onClearFilters?: () => void;
59
- onRefresh?: () => void;
60
- onColumnVisibilityChange?: (columnKey: string, visible: boolean) => void;
61
- onColumnFilter?: (columnKey: string, filter: any) => void;
62
- onSaveFilter?: (filter: Omit<SavedFilter, "id">) => void;
63
- onLoadFilter?: (filter: SavedFilter) => void;
64
- onDeleteFilter?: (filterId: string) => void;
65
- onRowSelect?: (selectedRows: number[]) => void;
66
- onToggleFilters?: (show: boolean) => void;
67
- onResetColumns?: () => void;
68
- columnOrder?: string[];
69
- onColumnOrderChange?: (order: string[]) => void;
70
- pinnedColumns?: Set<string>;
71
- onScrollToColumn?: (columnKey: string) => void;
72
- density?: Density;
73
- onDensityChange?: (density: Density) => void;
74
- showDensityControl?: boolean;
75
- customLeftContent?: ReactNode;
76
- customRightContent?: ReactNode;
77
- }
78
- export declare const SearchToolbar: ({ globalFilter, filteredDataLength, selectedRowsCount, selectedRows, showExport, showColumnToggle, showBulkActions, columns, columnVisibility, columnFilters, bulkActions, exportOptions, onGlobalFilterChange, onClearFilters, onColumnVisibilityChange, onColumnFilter, onResetColumns, columnOrder, onColumnOrderChange, pinnedColumns, onScrollToColumn, density, onDensityChange, showDensityControl, customLeftContent, customRightContent, }: SearchToolbarProps) => import("react/jsx-runtime").JSX.Element;
79
- export {};
@@ -1,2 +0,0 @@
1
- import{jsxs as e,jsx as r}from"react/jsx-runtime";import{useState as t,useRef as a,useEffect as l,useMemo as s}from"react";import{Filter as o,X as n,MoreHorizontal as i,Settings as c,Search as d,Eye as u,EyeOff as m,LocateFixed as g,Download as h,FileText as p,Database as b,Table as x,Edit as y,Copy as f,Archive as v,Trash2 as N}from"lucide-react";import{ColumnFilterSelector as w}from"./ColumnFilterSelector.js";import{Popover as k}from"./Popover.js";const C=({globalFilter:C,filteredDataLength:E,selectedRowsCount:S=0,selectedRows:j=new Set,showExport:A=!0,showColumnToggle:D=!0,showBulkActions:P=!0,columns:z=[],columnVisibility:F={},columnFilters:O={},bulkActions:$=[],exportOptions:L,onGlobalFilterChange:M,onClearFilters:R,onColumnVisibilityChange:T,onColumnFilter:B,onResetColumns:I,columnOrder:V=[],onColumnOrderChange:H,pinnedColumns:K,onScrollToColumn:q,density:G="md",onDensityChange:J,showDensityControl:U=!1,customLeftContent:Y,customRightContent:Q})=>{const[W,X]=t(!1),[Z,_]=t(!1),[ee,re]=t(!1),[te,ae]=t(!1),[le,se]=t(""),[oe,ne]=t(null),[ie,ce]=t(null),de=a(null),ue=a(null),me=a(null),ge=a(null),he=a(null),pe=a(null),be=a(null),xe=a(null),ye=a(null);l(()=>{const e=e=>{if((e=>{let r=e;for(;r;){if(r.getAttribute&&"true"===r.getAttribute("data-popover-root")||r.dataset&&"true"===r.dataset.popoverRoot)return!0;r=r.parentNode}return!1})(e.target))return;ue.current&&!ue.current.contains(e.target)&&X(!1),me.current&&!me.current.contains(e.target)&&re(!1),ge.current&&!ge.current.contains(e.target)&&ae(!1),!he.current||he.current.contains(e.target)||(e=>{let r=e;for(;r;){if(r.classList){const e=Array.from(r.classList).join(" ");if(/MuiPickers|MuiDatePicker|MuiPickersPopper/.test(e))return!0}if(r.getAttribute&&"dialog"===r.getAttribute("role")){const e=r.className?.toString()||"";if(/MuiPickers|MuiDatePicker/.test(e))return!0}r=r.parentNode}return!1})(e.target)||_(!1)};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[]);const fe=L?.formats||["xlsx"],ve=(C?.length??0)>0||Object.keys(O||{}).length>0,Ne=S>0,we=z.filter(e=>!1!==F[e.key]).length,ke=[...V.map(e=>z.find(r=>r.key===e)).filter(Boolean),...z.filter(e=>!V.includes(e.key))].filter(e=>e.header?.toLowerCase()?.includes(le?.toLowerCase())),Ce=e=>{switch(e){case"csv":return r(x,{size:18});case"json":return r(b,{size:18});case"xlsx":return r(p,{size:18});default:return r(h,{size:18})}},Ee=e=>{switch(e){case"delete":return r(N,{size:18});case"archive":return r(v,{size:18});case"copy":return r(f,{size:18});case"edit":return r(y,{size:18});case"export":return r(h,{size:18});default:return r(i,{size:18})}},Se=e=>{switch(e){case"csv":return"CSV";case"json":return"JSON";case"xlsx":return"Excel";default:return e}},je=(e,r=!1)=>{L?.onExport?.(e,r),X(!1)},Ae=()=>{ne(null),ce(null)},De=s(()=>z.some(e=>e.filterable),[z]);return e("div",{className:"bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700",role:"toolbar","aria-label":"Data grid toolbar",children:[e("div",{id:"search-results-status",className:"sr-only",role:"status","aria-live":"polite","aria-atomic":"true",children:[ve?`Showing ${E} of ${E} rows`:`${E} total rows`,Ne&&`, ${S} row${1!==S?"s":""} selected`]}),r("div",{className:"px-3 py-2",children:e("div",{className:"flex flex-wrap items-center justify-between gap-2 sm:gap-4",children:[e("div",{className:"order-1 flex items-center flex-wrap gap-2 sm:gap-3",children:[e("div",{className:"relative",ref:he,children:[De&&e("button",{ref:e=>{pe.current=e},onClick:()=>_(!Z),className:"flex cursor-pointer items-center gap-2 px-3 py-2 border rounded-lg transition-colors "+(Z?"bg-blue-50 dark:bg-blue-900/40 border-blue-200 dark:border-blue-600 text-blue-700 dark:text-blue-300":"border-gray-300 dark:border-gray-600 text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800"),title:"Toggle column filters (Ctrl+K)","aria-label":"Toggle column filters","aria-haspopup":"menu","aria-expanded":Z,"aria-controls":"filters-menu","aria-keyshortcuts":"Control+K",children:[r(o,{className:"w-4 h-4"}),r("span",{className:"hidden sm:inline",children:"Filters"}),Object.keys(O).length>0&&e("button",{type:"button",onClick:e=>{e.stopPropagation(),R?.()},className:"bg-red-500 cursor-pointer hover:bg-red-600 text-white text-xs px-1.5 py-0.5 rounded-full min-w-5 h-5 flex items-center justify-center transition-all group relative",title:"Clear all filters",children:[r("span",{className:"group-hover:hidden",children:Object.keys(O).length}),r(n,{className:"w-3 h-3 hidden group-hover:block absolute"})]})]}),e(k,{open:Z,anchorEl:pe.current,onClose:()=>_(!1),placement:"bottom-start",offset:8,zIndex:1e3,maxHeight:520,className:"w-88 sm:w-88 max-w-[90vw] bg-white border border-gray-200 rounded-lg shadow-xl overflow-y-auto min-h-100",shouldIgnoreClose:e=>{let r=e;for(;r;){if(r.classList){const e=Array.from(r.classList).join(" ");if(/MuiPickers|MuiDatePicker|MuiPickersPopper/.test(e))return!0}if(r.getAttribute&&"dialog"===r.getAttribute("role")){const e=r.className?.toString()||"";if(/MuiPickers|MuiDatePicker/.test(e))return!0}r=r.parentNode}return!1},children:[e("div",{className:"flex items-center justify-between px-2",children:[e("div",{className:"p-3 border-b border-gray-100",children:[r("h3",{className:"font-medium text-gray-900",children:"Column Filters"}),r("p",{className:"text-xs text-gray-500 mt-1",children:"Filter data by column values"})]}),r("button",{onClick:R,className:"px-3 py-1.5 text-sm text-gray-600 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors",children:"Clear All"})]}),r("div",{className:"p-3 space-y-3",children:r(w,{columns:z,columnFilters:O,onColumnFilter:B})}),r("div",{className:"flex items-center justify-between p-3 border-t border-gray-200",children:r("div",{className:"text-sm text-gray-600",children:Object.keys(O).length>0&&e("span",{children:[Object.keys(O).length," filter",1!==Object.keys(O).length?"s":""," ","applied"]})})})]})]}),Y]}),e("div",{className:"order-2 flex items-center gap-2 sm:gap-3 flex-wrap sm:flex-nowrap",children:[Q,P&&Ne&&$.length>0&&e("div",{className:"relative",ref:me,children:[e("button",{ref:e=>{xe.current=e},onClick:()=>re(!ee),className:"flex items-center gap-2 px-3 py-2.5 bg-orange-600 text-white rounded-lg hover:bg-orange-700 transition-colors",title:"Bulk actions",children:[r(i,{className:"w-4 h-4"}),e("span",{className:"hidden sm:inline text-sm font-medium",children:["Actions (",S,")"]})]}),e(k,{open:ee,anchorEl:xe.current,onClose:()=>re(!1),placement:"bottom-end",offset:8,zIndex:1e3,className:"w-56 bg-white border border-gray-200 rounded-lg shadow-xl",children:[e("div",{className:"p-3 border-b border-gray-100",children:[r("h3",{className:"font-medium text-gray-900",children:"Bulk Actions"}),e("p",{className:"text-xs text-gray-500 mt-1",children:[S," row",1!==S?"s":""," selected"]})]}),r("div",{className:"p-2",children:$.map(r=>e("button",{onClick:()=>(e=>{e.disabled||(e.onClick(j),re(!1))})(r),disabled:r.disabled,className:"w-full flex items-center gap-3 px-3 py-2 text-sm rounded-md transition-colors "+(r.disabled?"text-gray-400 cursor-not-allowed":r.destructive?"text-red-700 hover:bg-red-50":"text-gray-700 hover:bg-gray-50"),children:[Ee(r.id),r.label]},r.id))})]})]}),D&&z.length>0&&e("div",{className:"relative",ref:ge,children:[e("button",{ref:e=>{ye.current=e},onClick:()=>ae(!te),className:"flex items-center gap-2 px-3 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors",title:"Column visibility","aria-label":`Column visibility. ${we} of ${z.length} columns visible`,"aria-haspopup":"menu","aria-expanded":te,"aria-controls":"column-visibility-menu",children:[r(c,{className:"w-4 h-4"}),r("span",{className:"hidden sm:inline text-sm font-medium",children:"Columns"}),e("span",{className:"hidden sm:inline text-xs text-gray-500",children:["(",we,"/",z.length,")"]})]}),e(k,{open:te,anchorEl:ye.current,onClose:()=>ae(!1),placement:"bottom-end",offset:8,zIndex:1e3,className:"w-[90vw] sm:w-72 max-w-[90vw] bg-white border border-gray-200 rounded-lg shadow-xl",children:[e("div",{className:"p-3 border-b border-gray-100",children:[r("h3",{className:"font-medium text-gray-900",children:"Show/Hide Columns"}),e("div",{className:"relative mt-2",children:[r(d,{className:"absolute left-2 top-1/2 -translate-y-1/2 text-gray-400 w-4 h-4"}),r("input",{type:"text",placeholder:"Search columns...",className:"w-full pl-8 pr-2 py-1.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm",value:le,onChange:e=>se(e.target.value)})]})]}),r("div",{className:"max-h-60 overflow-y-auto p-2",children:ke.map(t=>{const a=!1!==F[t.key];return e("label",{className:"flex items-center gap-3 p-2 hover:bg-gray-50 rounded-md cursor-grab relative "+(oe===t.key?"opacity-60":""),draggable:!0,onDragStart:e=>((e,r)=>{ne(e),r.dataTransfer.effectAllowed="move",r.dataTransfer.setData("text/plain",e)})(t.key,e),onDragOver:e=>((e,r)=>{r.preventDefault(),r.dataTransfer.dropEffect="move";const t=r.currentTarget.getBoundingClientRect(),a=t.top+t.height/2,l=r.clientY<a?"before":"after";ce({key:e,position:l})})(t.key,e),onDrop:()=>(e=>{const r=oe;if(!r||r===e)return;if(K&&K.has(r)!==K.has(e))return ne(null),void ce(null);const t=ie?.key!==e||"before"===ie.position,a=(V&&V.length?V:z.map(e=>e.key)).filter(e=>e!==r);let l=a.indexOf(e);if(-1===l)return H?.(a),ne(null),void ce(null);t||(l+=1),a.splice(l,0,r),H?.(a),ne(null),ce(null)})(t.key),onDragEnd:Ae,children:[ie?.key===t.key&&r("span",{className:"absolute left-2 right-2 h-0.5 bg-blue-600",style:{top:"before"===ie.position?0:void 0,bottom:"after"===ie.position?0:void 0}}),r("input",{type:"checkbox",checked:a,onChange:()=>(e=>{const r=!1!==F[e];T?.(e,!r)})(t.key),className:"rounded border-gray-300 text-blue-600 focus:ring-blue-500"}),a?r(u,{className:"w-4 h-4 text-green-600"}):r(m,{className:"w-4 h-4 text-gray-400"}),r("span",{className:"text-sm text-gray-700",children:t.header}),r("button",{type:"button",onClick:e=>{e.preventDefault(),e.stopPropagation(),a?q?.(t.key):(T?.(t.key,!0),requestAnimationFrame(()=>q?.(t.key)))},className:"ml-auto p-1 text-gray-400 hover:text-blue-600",title:"Scroll to this column","aria-label":`Scroll to column ${t.header}`,children:r(g,{className:"w-4 h-4"})})]},t.key)})}),e("div",{className:"p-2 border-t border-gray-100",children:[e("div",{className:"flex items-center justify-between",children:[e("label",{className:"flex items-center gap-2 text-sm text-gray-600 hover:text-gray-900 cursor-pointer hover:bg-gray-50 px-3 py-1.5 rounded transition-colors min-h-9",children:[r("input",{type:"checkbox",checked:ke.every(e=>!1!==F[e.key]),onChange:e=>{ke.forEach(r=>{T?.(r.key,e.target.checked)})},className:"rounded border-gray-300 text-blue-600 focus:ring-blue-500"}),r("span",{children:"Select All"})]}),r("button",{className:"text-sm text-gray-600 hover:text-gray-900 hover:bg-gray-50 px-3 py-1.5 rounded transition-colors min-h-9",onClick:()=>{z.forEach(e=>{T?.(e.key,!1!==e.visible)}),H?.(z.map(e=>e.key)),I?.(),ae(!1)},children:"Reset Columns"})]}),le&&r("button",{className:"text-xs text-blue-600 hover:underline mt-2",onClick:()=>se(""),children:"Clear Search"})]})]})]}),U&&r("div",{className:"flex items-center",children:r("div",{className:"flex items-center gap-1 border border-gray-300 rounded-lg p-1",title:"Row density",children:["sm","md","lg"].map(e=>r("button",{className:"px-2 py-1 text-xs rounded-md "+(G===e?"bg-blue-600 text-white":"text-gray-700 hover:bg-gray-100"),onClick:()=>J?.(e),children:e.toUpperCase()},e))})}),r("div",{className:"flex items-center gap-2 order-3 w-full sm:order-0 sm:w-auto flex-1 min-w-0",children:e("div",{className:"relative",children:[r(d,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4","aria-hidden":"true"}),r("input",{ref:de,type:"text",placeholder:"Search...",className:"w-full sm:w-64 pl-10 pr-10 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:text-gray-200 transition-colors",value:C,onChange:M,"aria-label":"Search all columns","aria-keyshortcuts":"Control+F","aria-describedby":"search-results-status"}),C&&r("button",{onClick:()=>M({target:{value:""}}),className:"absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors",title:"Clear search",children:r(n,{className:"w-4 h-4"})})]})}),A&&L?.enabled&&e("div",{className:"relative",ref:ue,children:[r("button",{ref:e=>{be.current=e},onClick:()=>X(!W),className:"p-2.5 cursor-pointer border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-300 transition-colors","aria-label":"Export data"+(Ne?` (${S} rows selected)`:` (${E} rows)`),"aria-haspopup":"menu","aria-expanded":W,"aria-controls":"export-menu","aria-keyshortcuts":"Control+E",title:"Export data (Ctrl+E)",children:r(h,{className:"w-4 h-4"})}),e(k,{open:W,anchorEl:be.current,onClose:()=>X(!1),placement:"bottom-end",offset:8,zIndex:1e3,className:"w-[90vw] sm:w-64 max-w-[90vw] bg-white border border-gray-200 rounded-lg shadow-xl",children:[e("div",{className:"p-3 border-b border-gray-100",children:[r("h3",{className:"font-medium text-gray-900",children:"Export Data"}),r("p",{className:"text-xs text-gray-500 mt-1",children:"Choose format and data scope"})]}),e("div",{className:"p-2",children:[e("div",{className:"mb-3",children:[r("p",{className:"text-xs font-medium text-gray-700 mb-2 px-2",children:"Export All Data"}),r("div",{className:"space-y-1",children:fe.map(r=>e("button",{onClick:()=>je(r,!1),className:" cursor-pointer w-full flex items-center gap-3 px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 rounded-md transition-colors",children:[Ce(r),e("span",{children:["Export as ",Se(r)]}),e("span",{className:"ml-auto text-xs text-gray-500",children:[E.toLocaleString()," rows"]})]},`all-${r}`))})]}),Ne&&e("div",{children:[r("p",{className:"text-xs font-medium text-gray-700 mb-2 px-2",children:"Export Selected"}),r("div",{className:"space-y-1",children:fe.map(r=>e("button",{onClick:()=>je(r,!0),className:"w-full flex items-center gap-3 px-3 py-2 text-sm text-blue-700 hover:bg-blue-50 rounded-md transition-colors",children:[Ce(r),e("span",{children:["Export as ",Se(r)]}),e("span",{className:"ml-auto text-xs text-blue-500",children:[S," rows"]})]},`selected-${r}`))})]})]})]})]})]})]})})]})};export{C as SearchToolbar};
2
- //# sourceMappingURL=SearchToolbar.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SearchToolbar.js","sources":["../../../../../components/SearchToolbar.tsx"],"sourcesContent":["import {\n useState,\n useRef,\n useEffect,\n ReactNode,\n ChangeEvent,\n useMemo,\n} from \"react\";\nimport {\n Search,\n Download,\n Filter,\n X,\n FileText,\n Database,\n Table,\n Settings,\n Eye,\n EyeOff,\n MoreHorizontal,\n Trash2,\n Copy,\n Edit,\n Archive,\n LocateFixed,\n} from \"lucide-react\";\nimport { ColumnFilterSelector } from \"./ColumnFilterSelector\";\nimport Popover from \"./Popover\";\nimport type { Density } from \"../types\";\n\nexport type ExportFormat = \"csv\" | \"json\" | \"xlsx\";\n// SearchMode removed along with UI\nexport type BulkAction = \"delete\" | \"archive\" | \"copy\" | \"edit\" | \"export\";\n\nexport interface BulkActionOption {\n id: BulkAction;\n label: string;\n icon: ReactNode;\n onClick: (selectedRows: Set<string | number>) => void;\n disabled?: boolean;\n destructive?: boolean;\n}\n\ninterface ColumnVisibility {\n [columnKey: string]: boolean;\n}\n\ninterface SavedFilter {\n id: string;\n name: string;\n globalFilter: string;\n columnFilters: Record<string, any>;\n}\n\ninterface SearchToolbarProps {\n globalFilter: string;\n filteredDataLength: number;\n totalDataLength: number;\n paginationMode?: \"client\" | \"server\";\n totalRows?: number;\n selectedRowsCount?: number;\n selectedRows?: Set<string | number>;\n showExport?: boolean;\n showRefresh?: boolean;\n showColumnToggle?: boolean;\n showBulkActions?: boolean;\n showSavedFilters?: boolean;\n columns?: Array<{\n key: string;\n header: string;\n visible?: boolean;\n filterOptions?: Array<{ label: string; value: string | number }>;\n filterType?: \"text\" | \"select\" | \"multiselect\";\n filterable?: any;\n }>;\n columnVisibility?: ColumnVisibility;\n columnFilters?: Record<string, any>;\n savedFilters?: SavedFilter[];\n bulkActions?: BulkActionOption[];\n isLoading?: boolean;\n exportOptions?: {\n enabled: boolean;\n formats?: ExportFormat[];\n filename?: string;\n onExport?: (format: ExportFormat, exportSelected: boolean) => void;\n };\n onGlobalFilterChange: (e: ChangeEvent<HTMLInputElement>) => void;\n onClearFilters?: () => void;\n onRefresh?: () => void;\n onColumnVisibilityChange?: (columnKey: string, visible: boolean) => void;\n onColumnFilter?: (columnKey: string, filter: any) => void;\n onSaveFilter?: (filter: Omit<SavedFilter, \"id\">) => void;\n onLoadFilter?: (filter: SavedFilter) => void;\n onDeleteFilter?: (filterId: string) => void;\n onRowSelect?: (selectedRows: number[]) => void;\n onToggleFilters?: (show: boolean) => void;\n onResetColumns?: () => void;\n // New: reorder support\n columnOrder?: string[];\n onColumnOrderChange?: (order: string[]) => void;\n pinnedColumns?: Set<string>;\n // Scroll to a specific column in the grid\n onScrollToColumn?: (columnKey: string) => void;\n // Density controls\n density?: Density;\n onDensityChange?: (density: Density) => void;\n showDensityControl?: boolean;\n // Custom content slots\n customLeftContent?: ReactNode;\n customRightContent?: ReactNode;\n}\n\nexport const SearchToolbar = ({\n globalFilter,\n filteredDataLength,\n selectedRowsCount = 0,\n selectedRows = new Set(),\n showExport = true,\n showColumnToggle = true,\n showBulkActions = true,\n columns = [],\n columnVisibility = {},\n columnFilters = {},\n bulkActions = [],\n exportOptions,\n onGlobalFilterChange,\n onClearFilters,\n onColumnVisibilityChange,\n onColumnFilter,\n onResetColumns,\n columnOrder = [],\n onColumnOrderChange,\n pinnedColumns,\n onScrollToColumn,\n density = \"md\",\n onDensityChange,\n showDensityControl = false,\n customLeftContent,\n customRightContent,\n}: SearchToolbarProps) => {\n const [showExportMenu, setShowExportMenu] = useState(false);\n const [showFilters, setShowFilters] = useState(false);\n const [showBulkActionsMenu, setShowBulkActionsMenu] = useState(false);\n const [showColumnMenu, setShowColumnMenu] = useState(false);\n const [columnSearch, setColumnSearch] = useState(\"\");\n // DnD state for in-menu reordering\n const [draggingKey, setDraggingKey] = useState<string | null>(null);\n const [dragOver, setDragOver] = useState<{\n key: string;\n position: \"before\" | \"after\";\n } | null>(null);\n\n const searchInputRef = useRef<HTMLInputElement>(null);\n const exportMenuRef = useRef<HTMLDivElement>(null);\n const bulkActionsRef = useRef<HTMLDivElement>(null);\n const columnMenuRef = useRef<HTMLDivElement>(null);\n const filtersMenuRef = useRef<HTMLDivElement>(null);\n const filtersAnchorRef = useRef<HTMLButtonElement | null>(null);\n const exportAnchorRef = useRef<HTMLButtonElement | null>(null);\n const bulkActionsAnchorRef = useRef<HTMLButtonElement | null>(null);\n const columnAnchorRef = useRef<HTMLButtonElement | null>(null);\n\n // Close menus when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n // If clicking inside any portal popover root, do nothing here.\n const isInAnyPopover = (target: any): boolean => {\n let node: any = target;\n while (node) {\n if (\n (node.getAttribute &&\n node.getAttribute(\"data-popover-root\") === \"true\") ||\n (node.dataset && (node.dataset as any).popoverRoot === \"true\")\n )\n return true;\n node = node.parentNode;\n }\n return false;\n };\n\n if (isInAnyPopover(event.target)) return;\n // Helper: detect if click occurred inside a MUI Date Picker popup so we don't treat it as outside\n const isInMuiDatePicker = (target: any): boolean => {\n let node: any = target;\n while (node) {\n if (node.classList) {\n const cls = Array.from(node.classList).join(\" \");\n if (/MuiPickers|MuiDatePicker|MuiPickersPopper/.test(cls))\n return true;\n }\n // Some pickers add role=\"dialog\"\n if (node.getAttribute && node.getAttribute(\"role\") === \"dialog\") {\n const cls = node.className?.toString() || \"\";\n if (/MuiPickers|MuiDatePicker/.test(cls)) return true;\n }\n node = node.parentNode;\n }\n return false;\n };\n\n if (\n exportMenuRef.current &&\n !exportMenuRef.current.contains(event.target as Node)\n ) {\n setShowExportMenu(false);\n }\n if (\n bulkActionsRef.current &&\n !bulkActionsRef.current.contains(event.target as Node)\n ) {\n setShowBulkActionsMenu(false);\n }\n if (\n columnMenuRef.current &&\n !columnMenuRef.current.contains(event.target as Node)\n ) {\n setShowColumnMenu(false);\n }\n if (\n filtersMenuRef.current &&\n !filtersMenuRef.current.contains(event.target as Node) &&\n !isInMuiDatePicker(event.target)\n ) {\n setShowFilters(false);\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n }, []);\n\n const exportFormats = exportOptions?.formats || [\"xlsx\"];\n const hasActiveFilters =\n (globalFilter?.length ?? 0) > 0 ||\n Object.keys(columnFilters || {}).length > 0;\n const hasSelectedRows = selectedRowsCount > 0;\n const visibleColumnsCount = columns.filter(\n (col) => columnVisibility[col.key] !== false\n ).length;\n\n // Build ordered list based on columnOrder, append any missing, then filter by search\n const orderedAll = (() => {\n const fromOrder = columnOrder\n .map((k) => columns.find((c) => c.key === k))\n .filter(Boolean) as typeof columns;\n const missing = columns.filter((c) => !columnOrder.includes(c.key));\n return [...fromOrder, ...missing];\n })();\n\n const filteredColumns = orderedAll.filter((c) =>\n c.header?.toLowerCase()?.includes(columnSearch?.toLowerCase())\n );\n\n // Search mode UI removed per request; default behavior remains in parent handlers.\n\n const getExportIcon = (format: ExportFormat) => {\n switch (format) {\n case \"csv\":\n return <Table size={18} />;\n case \"json\":\n return <Database size={18} />;\n case \"xlsx\":\n return <FileText size={18} />;\n default:\n return <Download size={18} />;\n }\n };\n\n const getBulkActionIcon = (action: BulkAction) => {\n switch (action) {\n case \"delete\":\n return <Trash2 size={18} />;\n case \"archive\":\n return <Archive size={18} />;\n case \"copy\":\n return <Copy size={18} />;\n case \"edit\":\n return <Edit size={18} />;\n case \"export\":\n return <Download size={18} />;\n default:\n return <MoreHorizontal size={18} />;\n }\n };\n\n const getFormatLabel = (format: ExportFormat) => {\n switch (format) {\n case \"csv\":\n return \"CSV\";\n case \"json\":\n return \"JSON\";\n case \"xlsx\":\n return \"Excel\";\n default:\n return format;\n }\n };\n\n const handleExport = (\n format: ExportFormat,\n exportSelected: boolean = false\n ) => {\n exportOptions?.onExport?.(format, exportSelected);\n setShowExportMenu(false);\n };\n\n const handleBulkAction = (action: BulkActionOption) => {\n if (!action.disabled) {\n action.onClick(selectedRows);\n setShowBulkActionsMenu(false);\n }\n };\n\n const handleColumnToggle = (columnKey: string) => {\n const isVisible = columnVisibility[columnKey] !== false;\n onColumnVisibilityChange?.(columnKey, !isVisible);\n };\n\n // DnD handlers for reordering within menu\n const handleDragStart = (\n columnKey: string,\n e: React.DragEvent<HTMLLabelElement>\n ) => {\n setDraggingKey(columnKey);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", columnKey);\n };\n\n const handleDragOver = (\n targetKey: string,\n e: React.DragEvent<HTMLLabelElement>\n ) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n const rect = (e.currentTarget as HTMLLabelElement).getBoundingClientRect();\n const midpoint = rect.top + rect.height / 2;\n const position = e.clientY < midpoint ? \"before\" : \"after\";\n setDragOver({ key: targetKey, position });\n };\n\n const handleDrop = (targetKey: string) => {\n const sourceKey = draggingKey;\n if (!sourceKey || sourceKey === targetKey) return;\n\n // respect pinned vs unpinned if provided\n if (pinnedColumns) {\n const sPinned = pinnedColumns.has(sourceKey);\n const tPinned = pinnedColumns.has(targetKey);\n if (sPinned !== tPinned) {\n setDraggingKey(null);\n setDragOver(null);\n return;\n }\n }\n\n const before =\n dragOver?.key === targetKey ? dragOver.position === \"before\" : true;\n const base = (\n columnOrder && columnOrder.length\n ? columnOrder\n : columns.map((c) => c.key)\n ).filter((k) => k !== sourceKey);\n let idx = base.indexOf(targetKey);\n if (idx === -1) {\n onColumnOrderChange?.(base);\n setDraggingKey(null);\n setDragOver(null);\n return;\n }\n if (!before) idx += 1;\n base.splice(idx, 0, sourceKey);\n onColumnOrderChange?.(base);\n setDraggingKey(null);\n setDragOver(null);\n };\n\n const handleDragEnd = () => {\n setDraggingKey(null);\n setDragOver(null);\n };\n\n // Search mode handler removed with UI\n\n const handleResetColumns = () => {\n columns.forEach((column) => {\n onColumnVisibilityChange?.(column.key, column.visible !== false);\n });\n onColumnOrderChange?.(columns.map((column) => column.key));\n onResetColumns?.();\n };\n\n const hasFilterableColumns = useMemo(\n () => columns.some((col) => col.filterable),\n [columns]\n );\n\n return (\n <div\n className=\"bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700\"\n role=\"toolbar\"\n aria-label=\"Data grid toolbar\"\n >\n {/* Screen reader status region */}\n <div\n id=\"search-results-status\"\n className=\"sr-only\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >\n {hasActiveFilters\n ? `Showing ${filteredDataLength} of ${filteredDataLength} rows`\n : `${filteredDataLength} total rows`}\n {hasSelectedRows &&\n `, ${selectedRowsCount} row${\n selectedRowsCount !== 1 ? \"s\" : \"\"\n } selected`}\n </div>\n\n {/* Main Toolbar */}\n <div className=\"px-3 py-2\">\n <div className=\"flex flex-wrap items-center justify-between gap-2 sm:gap-4\">\n {/* Left Section - Actions */}\n <div className=\"order-1 flex items-center flex-wrap gap-2 sm:gap-3\">\n {/* Filter Toggle */}\n <div className=\"relative\" ref={filtersMenuRef}>\n {hasFilterableColumns && (\n <button\n ref={(el) => {\n filtersAnchorRef.current = el;\n }}\n onClick={() => setShowFilters(!showFilters)}\n className={`flex cursor-pointer items-center gap-2 px-3 py-2 border rounded-lg transition-colors ${\n showFilters\n ? \"bg-blue-50 dark:bg-blue-900/40 border-blue-200 dark:border-blue-600 text-blue-700 dark:text-blue-300\"\n : \"border-gray-300 dark:border-gray-600 text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800\"\n }`}\n title=\"Toggle column filters (Ctrl+K)\"\n aria-label=\"Toggle column filters\"\n aria-haspopup=\"menu\"\n aria-expanded={showFilters}\n aria-controls=\"filters-menu\"\n aria-keyshortcuts=\"Control+K\"\n >\n <Filter className=\"w-4 h-4\" />\n <span className=\"hidden sm:inline\">Filters</span>\n {Object.keys(columnFilters).length > 0 && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onClearFilters?.();\n }}\n className=\"bg-red-500 cursor-pointer hover:bg-red-600 text-white text-xs px-1.5 py-0.5 rounded-full min-w-5 h-5 flex items-center justify-center transition-all group relative\"\n title=\"Clear all filters\"\n >\n <span className=\"group-hover:hidden\">\n {Object.keys(columnFilters).length}\n </span>\n <X className=\"w-3 h-3 hidden group-hover:block absolute\" />\n </button>\n )}\n </button>\n )}\n <Popover\n open={showFilters}\n anchorEl={filtersAnchorRef.current}\n onClose={() => setShowFilters(false)}\n placement=\"bottom-start\"\n offset={8}\n zIndex={1000}\n maxHeight={520}\n className=\"w-88 sm:w-88 max-w-[90vw] bg-white border border-gray-200 rounded-lg shadow-xl overflow-y-auto min-h-100\"\n shouldIgnoreClose={(target) => {\n // Ignore clicks inside MUI pickers (often portal-rooted)\n let node: any = target;\n while (node) {\n if (node.classList) {\n const cls = Array.from(node.classList).join(\" \");\n if (/MuiPickers|MuiDatePicker|MuiPickersPopper/.test(cls))\n return true;\n }\n if (\n node.getAttribute &&\n node.getAttribute(\"role\") === \"dialog\"\n ) {\n const cls = node.className?.toString() || \"\";\n if (/MuiPickers|MuiDatePicker/.test(cls)) return true;\n }\n node = node.parentNode;\n }\n return false;\n }}\n >\n <div className=\"flex items-center justify-between px-2\">\n <div className=\"p-3 border-b border-gray-100\">\n <h3 className=\"font-medium text-gray-900\">\n Column Filters\n </h3>\n <p className=\"text-xs text-gray-500 mt-1\">\n Filter data by column values\n </p>\n </div>\n <button\n onClick={onClearFilters}\n className=\"px-3 py-1.5 text-sm text-gray-600 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors\"\n >\n Clear All\n </button>\n </div>\n <div className=\"p-3 space-y-3\">\n <ColumnFilterSelector\n columns={columns}\n columnFilters={columnFilters}\n onColumnFilter={onColumnFilter}\n />\n </div>\n <div className=\"flex items-center justify-between p-3 border-t border-gray-200\">\n <div className=\"text-sm text-gray-600\">\n {Object.keys(columnFilters).length > 0 && (\n <span>\n {Object.keys(columnFilters).length} filter\n {Object.keys(columnFilters).length !== 1\n ? \"s\"\n : \"\"}{\" \"}\n applied\n </span>\n )}\n </div>\n </div>\n </Popover>\n </div>\n\n {/* Custom Left Content Slot */}\n {customLeftContent}\n </div>\n\n {/* Right Section - Actions */}\n <div className=\"order-2 flex items-center gap-2 sm:gap-3 flex-wrap sm:flex-nowrap\">\n {/* Custom Right Content Slot */}\n {customRightContent}\n {/* Search mode option removed */}\n\n {/* Bulk Actions */}\n {showBulkActions && hasSelectedRows && bulkActions.length > 0 && (\n <div className=\"relative\" ref={bulkActionsRef}>\n <button\n ref={(el) => {\n bulkActionsAnchorRef.current = el;\n }}\n onClick={() => setShowBulkActionsMenu(!showBulkActionsMenu)}\n className=\"flex items-center gap-2 px-3 py-2.5 bg-orange-600 text-white rounded-lg hover:bg-orange-700 transition-colors\"\n title=\"Bulk actions\"\n >\n <MoreHorizontal className=\"w-4 h-4\" />\n <span className=\"hidden sm:inline text-sm font-medium\">\n Actions ({selectedRowsCount})\n </span>\n </button>\n <Popover\n open={showBulkActionsMenu}\n anchorEl={bulkActionsAnchorRef.current}\n onClose={() => setShowBulkActionsMenu(false)}\n placement=\"bottom-end\"\n offset={8}\n zIndex={1000}\n className=\"w-56 bg-white border border-gray-200 rounded-lg shadow-xl\"\n >\n <div className=\"p-3 border-b border-gray-100\">\n <h3 className=\"font-medium text-gray-900\">Bulk Actions</h3>\n <p className=\"text-xs text-gray-500 mt-1\">\n {selectedRowsCount} row\n {selectedRowsCount !== 1 ? \"s\" : \"\"} selected\n </p>\n </div>\n <div className=\"p-2\">\n {bulkActions.map((action) => (\n <button\n key={action.id}\n onClick={() => handleBulkAction(action)}\n disabled={action.disabled}\n className={`w-full flex items-center gap-3 px-3 py-2 text-sm rounded-md transition-colors ${\n action.disabled\n ? \"text-gray-400 cursor-not-allowed\"\n : action.destructive\n ? \"text-red-700 hover:bg-red-50\"\n : \"text-gray-700 hover:bg-gray-50\"\n }`}\n >\n {getBulkActionIcon(action.id)}\n {action.label}\n </button>\n ))}\n </div>\n </Popover>\n </div>\n )}\n\n {/* Column Visibility Toggle */}\n {showColumnToggle && columns.length > 0 && (\n <div className=\"relative\" ref={columnMenuRef}>\n <button\n ref={(el) => {\n columnAnchorRef.current = el;\n }}\n onClick={() => setShowColumnMenu(!showColumnMenu)}\n className=\"flex items-center gap-2 px-3 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors\"\n title=\"Column visibility\"\n aria-label={`Column visibility. ${visibleColumnsCount} of ${columns.length} columns visible`}\n aria-haspopup=\"menu\"\n aria-expanded={showColumnMenu}\n aria-controls=\"column-visibility-menu\"\n >\n <Settings className=\"w-4 h-4\" />\n <span className=\"hidden sm:inline text-sm font-medium\">\n Columns\n </span>\n <span className=\"hidden sm:inline text-xs text-gray-500\">\n ({visibleColumnsCount}/{columns.length})\n </span>\n </button>\n\n {/* Column Visibility Dropdown */}\n <Popover\n open={showColumnMenu}\n anchorEl={columnAnchorRef.current}\n onClose={() => setShowColumnMenu(false)}\n placement=\"bottom-end\"\n offset={8}\n zIndex={1000}\n className=\"w-[90vw] sm:w-72 max-w-[90vw] bg-white border border-gray-200 rounded-lg shadow-xl\"\n >\n <div className=\"p-3 border-b border-gray-100\">\n <h3 className=\"font-medium text-gray-900\">\n Show/Hide Columns\n </h3>\n <div className=\"relative mt-2\">\n <Search className=\"absolute left-2 top-1/2 -translate-y-1/2 text-gray-400 w-4 h-4\" />\n <input\n type=\"text\"\n placeholder=\"Search columns...\"\n className=\"w-full pl-8 pr-2 py-1.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm\"\n value={columnSearch}\n onChange={(e) => setColumnSearch(e.target.value)}\n />\n </div>\n </div>\n <div className=\"max-h-60 overflow-y-auto p-2\">\n {filteredColumns.map((column) => {\n const isVisible = columnVisibility[column.key] !== false;\n return (\n <label\n key={column.key}\n className={`flex items-center gap-3 p-2 hover:bg-gray-50 rounded-md cursor-grab relative ${\n draggingKey === column.key ? \"opacity-60\" : \"\"\n }`}\n draggable\n onDragStart={(e) => handleDragStart(column.key, e)}\n onDragOver={(e) => handleDragOver(column.key, e)}\n onDrop={() => handleDrop(column.key)}\n onDragEnd={handleDragEnd}\n >\n {dragOver?.key === column.key && (\n <span\n className=\"absolute left-2 right-2 h-0.5 bg-blue-600\"\n style={{\n top:\n dragOver.position === \"before\"\n ? 0\n : undefined,\n bottom:\n dragOver.position === \"after\" ? 0 : undefined,\n }}\n />\n )}\n <input\n type=\"checkbox\"\n checked={isVisible}\n onChange={() => handleColumnToggle(column.key)}\n className=\"rounded border-gray-300 text-blue-600 focus:ring-blue-500\"\n />\n {isVisible ? (\n <Eye className=\"w-4 h-4 text-green-600\" />\n ) : (\n <EyeOff className=\"w-4 h-4 text-gray-400\" />\n )}\n <span className=\"text-sm text-gray-700\">\n {column.header}\n </span>\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n // Ensure column is visible before scrolling\n if (!isVisible) {\n onColumnVisibilityChange?.(column.key, true);\n // Wait for visibility update to render before scrolling\n requestAnimationFrame(() =>\n onScrollToColumn?.(column.key)\n );\n } else {\n onScrollToColumn?.(column.key);\n }\n }}\n className=\"ml-auto p-1 text-gray-400 hover:text-blue-600\"\n title=\"Scroll to this column\"\n aria-label={`Scroll to column ${column.header}`}\n >\n <LocateFixed className=\"w-4 h-4\" />\n </button>\n </label>\n );\n })}\n </div>\n <div className=\"p-2 border-t border-gray-100\">\n <div className=\"flex items-center justify-between\">\n <label className=\"flex items-center gap-2 text-sm text-gray-600 hover:text-gray-900 cursor-pointer hover:bg-gray-50 px-3 py-1.5 rounded transition-colors min-h-9\">\n <input\n type=\"checkbox\"\n checked={filteredColumns.every(\n (col) => columnVisibility[col.key] !== false\n )}\n onChange={(e) => {\n filteredColumns.forEach((column) => {\n onColumnVisibilityChange?.(\n column.key,\n e.target.checked\n );\n });\n }}\n className=\"rounded border-gray-300 text-blue-600 focus:ring-blue-500\"\n />\n <span>Select All</span>\n </label>\n <button\n className=\"text-sm text-gray-600 hover:text-gray-900 hover:bg-gray-50 px-3 py-1.5 rounded transition-colors min-h-9\"\n onClick={() => {\n handleResetColumns();\n setShowColumnMenu(false);\n }}\n >\n Reset Columns\n </button>\n </div>\n {columnSearch && (\n <button\n className=\"text-xs text-blue-600 hover:underline mt-2\"\n onClick={() => setColumnSearch(\"\")}\n >\n Clear Search\n </button>\n )}\n </div>\n </Popover>\n </div>\n )}\n\n {/* Density Selector */}\n {showDensityControl && (\n <div className=\"flex items-center\">\n <div\n className=\"flex items-center gap-1 border border-gray-300 rounded-lg p-1\"\n title=\"Row density\"\n >\n {([\"sm\", \"md\", \"lg\"] as Density[]).map((d) => (\n <button\n key={d}\n className={`px-2 py-1 text-xs rounded-md ${\n density === d\n ? \"bg-blue-600 text-white\"\n : \"text-gray-700 hover:bg-gray-100\"\n }`}\n onClick={() => onDensityChange?.(d)}\n >\n {d.toUpperCase()}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Enhanced Search Panel - Right aligned */}\n <div className=\"flex items-center gap-2 order-3 w-full sm:order-0 sm:w-auto flex-1 min-w-0\">\n {/* Search Input with integrated match type */}\n <div className=\"relative\">\n <Search\n className=\"absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4\"\n aria-hidden=\"true\"\n />\n <input\n ref={searchInputRef}\n type=\"text\"\n placeholder={`Search...`}\n className=\"w-full sm:w-64 pl-10 pr-10 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:text-gray-200 transition-colors\"\n value={globalFilter}\n onChange={onGlobalFilterChange}\n aria-label=\"Search all columns\"\n aria-keyshortcuts=\"Control+F\"\n aria-describedby=\"search-results-status\"\n />\n {globalFilter && (\n <button\n onClick={() =>\n onGlobalFilterChange({\n target: { value: \"\" },\n } as ChangeEvent<HTMLInputElement>)\n }\n className=\"absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors\"\n title=\"Clear search\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Export Icon Button */}\n {showExport && exportOptions?.enabled && (\n <div className=\"relative\" ref={exportMenuRef}>\n <button\n ref={(el) => {\n exportAnchorRef.current = el;\n }}\n onClick={() => setShowExportMenu(!showExportMenu)}\n className=\"p-2.5 cursor-pointer border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-300 transition-colors\"\n aria-label={`Export data${\n hasSelectedRows\n ? ` (${selectedRowsCount} rows selected)`\n : ` (${filteredDataLength} rows)`\n }`}\n aria-haspopup=\"menu\"\n aria-expanded={showExportMenu}\n aria-controls=\"export-menu\"\n aria-keyshortcuts=\"Control+E\"\n title=\"Export data (Ctrl+E)\"\n >\n <Download className=\"w-4 h-4\" />\n </button>\n <Popover\n open={showExportMenu}\n anchorEl={exportAnchorRef.current}\n onClose={() => setShowExportMenu(false)}\n placement=\"bottom-end\"\n offset={8}\n zIndex={1000}\n className=\"w-[90vw] sm:w-64 max-w-[90vw] bg-white border border-gray-200 rounded-lg shadow-xl\"\n >\n <div className=\"p-3 border-b border-gray-100\">\n <h3 className=\"font-medium text-gray-900\">Export Data</h3>\n <p className=\"text-xs text-gray-500 mt-1\">\n Choose format and data scope\n </p>\n </div>\n\n <div className=\"p-2\">\n {/* Export All */}\n <div className=\"mb-3\">\n <p className=\"text-xs font-medium text-gray-700 mb-2 px-2\">\n Export All Data\n </p>\n <div className=\"space-y-1\">\n {exportFormats.map((format) => (\n <button\n key={`all-${format}`}\n onClick={() => handleExport(format, false)}\n className=\" cursor-pointer w-full flex items-center gap-3 px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 rounded-md transition-colors\"\n >\n {getExportIcon(format)}\n <span>Export as {getFormatLabel(format)}</span>\n <span className=\"ml-auto text-xs text-gray-500\">\n {filteredDataLength.toLocaleString()} rows\n </span>\n </button>\n ))}\n </div>\n </div>\n\n {/* Export Selected */}\n {hasSelectedRows && (\n <div>\n <p className=\"text-xs font-medium text-gray-700 mb-2 px-2\">\n Export Selected\n </p>\n <div className=\"space-y-1\">\n {exportFormats.map((format) => (\n <button\n key={`selected-${format}`}\n onClick={() => handleExport(format, true)}\n className=\"w-full flex items-center gap-3 px-3 py-2 text-sm text-blue-700 hover:bg-blue-50 rounded-md transition-colors\"\n >\n {getExportIcon(format)}\n <span>Export as {getFormatLabel(format)}</span>\n <span className=\"ml-auto text-xs text-blue-500\">\n {selectedRowsCount} rows\n </span>\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n </Popover>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};\n"],"names":["SearchToolbar","globalFilter","filteredDataLength","selectedRowsCount","selectedRows","Set","showExport","showColumnToggle","showBulkActions","columns","columnVisibility","columnFilters","bulkActions","exportOptions","onGlobalFilterChange","onClearFilters","onColumnVisibilityChange","onColumnFilter","onResetColumns","columnOrder","onColumnOrderChange","pinnedColumns","onScrollToColumn","density","onDensityChange","showDensityControl","customLeftContent","customRightContent","showExportMenu","setShowExportMenu","useState","showFilters","setShowFilters","showBulkActionsMenu","setShowBulkActionsMenu","showColumnMenu","setShowColumnMenu","columnSearch","setColumnSearch","draggingKey","setDraggingKey","dragOver","setDragOver","searchInputRef","useRef","exportMenuRef","bulkActionsRef","columnMenuRef","filtersMenuRef","filtersAnchorRef","exportAnchorRef","bulkActionsAnchorRef","columnAnchorRef","useEffect","handleClickOutside","event","target","node","getAttribute","dataset","popoverRoot","parentNode","isInAnyPopover","current","contains","classList","cls","Array","from","join","test","className","toString","isInMuiDatePicker","document","addEventListener","removeEventListener","exportFormats","formats","hasActiveFilters","length","Object","keys","hasSelectedRows","visibleColumnsCount","filter","col","key","filteredColumns","map","k","find","c","Boolean","includes","header","toLowerCase","getExportIcon","format","_jsx","Table","size","Database","FileText","Download","getBulkActionIcon","action","Trash2","Archive","Copy","Edit","MoreHorizontal","getFormatLabel","handleExport","exportSelected","onExport","handleDragEnd","hasFilterableColumns","useMemo","some","filterable","_jsxs","role","children","id","ref","el","onClick","title","Filter","type","e","stopPropagation","X","Popover","open","anchorEl","onClose","placement","offset","zIndex","maxHeight","shouldIgnoreClose","ColumnFilterSelector","disabled","handleBulkAction","destructive","label","Settings","Search","placeholder","value","onChange","column","isVisible","draggable","onDragStart","columnKey","dataTransfer","effectAllowed","setData","handleDragStart","onDragOver","targetKey","preventDefault","dropEffect","rect","currentTarget","getBoundingClientRect","midpoint","top","height","position","clientY","handleDragOver","onDrop","sourceKey","has","before","base","idx","indexOf","splice","handleDrop","onDragEnd","style","undefined","bottom","checked","handleColumnToggle","Eye","EyeOff","requestAnimationFrame","LocateFixed","every","forEach","visible","d","toUpperCase","enabled","toLocaleString"],"mappings":"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"}
@@ -1,7 +0,0 @@
1
- import { ColumnFilterValue } from "../../types";
2
- interface BooleanFilterProps {
3
- value: ColumnFilterValue | null;
4
- onChange: (value: ColumnFilterValue | null) => void;
5
- }
6
- export declare const BooleanFilter: ({ value, onChange }: BooleanFilterProps) => import("react/jsx-runtime").JSX.Element;
7
- export {};
@@ -1,2 +0,0 @@
1
- import{jsx as e,jsxs as l}from"react/jsx-runtime";import{useState as r}from"react";const a=({value:a,onChange:o})=>{const[n,u]=r(void 0!==a?.value?String(a.value):"");return e("div",{className:"space-y-3",children:l("div",{children:[e("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Boolean Value"}),l("select",{value:n,onChange:e=>{return l=e.target.value,u(l),void o(""===l?null:{type:"boolean",value:"true"===l,operator:"equals"});var l},className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500",children:[e("option",{value:"",children:"All values"}),e("option",{value:"true",children:"True"}),e("option",{value:"false",children:"False"})]})]})})};export{a as BooleanFilter};
2
- //# sourceMappingURL=BooleanFilter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BooleanFilter.js","sources":["../../../../../../components/filters/BooleanFilter.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { ColumnFilterValue } from \"../../types\";\n\ninterface BooleanFilterProps {\n value: ColumnFilterValue | null;\n onChange: (value: ColumnFilterValue | null) => void;\n}\n\nexport const BooleanFilter = ({ value, onChange }: BooleanFilterProps) => {\n const [booleanValue, setBooleanValue] = useState<string>(\n value?.value !== undefined ? String(value.value) : \"\"\n );\n\n const handleValueChange = (newValue: string) => {\n setBooleanValue(newValue);\n\n if (newValue === \"\") {\n onChange(null);\n } else {\n onChange({\n type: \"boolean\",\n value: newValue === \"true\",\n operator: \"equals\",\n });\n }\n };\n\n return (\n <div className=\"space-y-3\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n Boolean Value\n </label>\n <select\n value={booleanValue}\n onChange={(e) => handleValueChange(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\n >\n <option value=\"\">All values</option>\n <option value=\"true\">True</option>\n <option value=\"false\">False</option>\n </select>\n </div>\n </div>\n );\n};\n"],"names":["BooleanFilter","value","onChange","booleanValue","setBooleanValue","useState","undefined","String","_jsx","className","children","_jsxs","e","handleValueChange","newValue","target","type","operator"],"mappings":"mFAQa,MAAAA,EAAgB,EAAGC,QAAOC,eACrC,MAAOC,EAAcC,GAAmBC,OACrBC,IAAjBL,GAAOA,MAAsBM,OAAON,EAAMA,OAAS,IAiBrD,OACEO,EAAK,MAAA,CAAAC,UAAU,YACbC,SAAAC,EAAA,MAAA,CAAAD,SAAA,CACEF,EAAO,QAAA,CAAAC,UAAU,+CAETC,SAAA,kBACRC,EACE,SAAA,CAAAV,MAAOE,EACPD,SAAWU,IAAMC,OAtBEC,EAsBgBF,EAAEG,OAAOd,MArBlDG,EAAgBU,QAGdZ,EADe,KAAbY,EACO,KAEA,CACPE,KAAM,UACNf,MAAoB,SAAba,EACPG,SAAU,WATU,IAACH,GAuBnBL,UAAU,4GAEVC,SAAA,CAAAF,EAAA,SAAA,CAAQP,MAAM,GAAES,SAAA,eAChBF,EAAA,SAAA,CAAQP,MAAM,OAAMS,SAAA,SACpBF,EAAA,SAAA,CAAQP,MAAM,QAAOS,SAAA"}
@@ -1,9 +0,0 @@
1
- import { ColumnFilterValue } from "../../types";
2
- interface DateFilterProps {
3
- value: ColumnFilterValue | null;
4
- onChange: (value: ColumnFilterValue | null) => void;
5
- min?: number;
6
- max?: number;
7
- }
8
- export declare const DateFilter: ({ value, onChange, min, max }: DateFilterProps) => import("react/jsx-runtime").JSX.Element;
9
- export {};
@@ -1,2 +0,0 @@
1
- import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useState as l,useEffect as n,useMemo as a}from"react";import{DatePicker as r}from"../ui/DatePicker.js";import{format as o,parse as u}from"date-fns";const d=({value:d,onChange:i,min:c,max:s})=>{const m=e=>{if(!e)return null;if(e instanceof Date)return isNaN(e.getTime())?null:e;try{const t=u(String(e),"yyyy-MM-dd",new Date);return isNaN(t.getTime())?null:t}catch(t){const l=new Date(e);return isNaN(l.getTime())?null:l}},y=e=>e?o(e,"yyyy-MM-dd"):"",[p,b]=l(m(d?.value)),[v,f]=l("between"===d?.operator?m(d?.secondValue??d?.value):null),[w,h]=l(d?.operator||"between");n(()=>{h(d?.operator||"between"),b(m(d?.value)),f("between"===d?.operator?m(d?.secondValue??d?.value):null)},[d?.value,d?.secondValue,d?.operator]),n(()=>{"between"===w&&!v&&p&&f(p)},[w,p,v]);const g=(e,t,l)=>e?t&&e<t||l&&e>l?null:e:null,D=(e,t=!1)=>{const l=t?p:e,n=t?e:v,a="between"===w&&v?v:M,r=t?g(e,p??N??void 0,M):g(e,N,a);if(t?f(r):b(r),"between"===w)if(l&&n){const e=l>=n?l:n;i({type:"date",value:y(l<=n?l:n),secondValue:y(e),operator:"between"})}else i(null);else i(r?{type:"date",value:y(r),operator:w}:null)},N=a(()=>c?new Date(c):void 0,[c]),M=a(()=>s?new Date(s):void 0,[s]);return e("div",{className:"space-y-3",children:[e("div",{children:[t("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Filter Type"}),e("select",{value:w,onChange:e=>(e=>{const t=e;h(t),"between"===t?p&&v&&i({type:"date",value:p<=v?p:v,secondValue:p>=v?p:v,operator:"between"}):p&&i({type:"date",value:p,operator:t})})(e.target.value),className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500",children:[t("option",{value:"equals",children:"On Date"}),t("option",{value:"gt",children:"After"}),t("option",{value:"gte",children:"On or After"}),t("option",{value:"lt",children:"Before"}),t("option",{value:"lte",children:"On or Before"}),t("option",{value:"between",children:"Between Dates"})]})]}),e("div",{children:[t("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"between"===w?"From Date":"Date"}),t(r,{name:"date_filter_start",value:p?o(p,"yyyy-MM-dd"):null,onChange:e=>D(e?u(e,"yyyy-MM-dd",new Date):null,!1),className:"w-full"})]}),"between"===w&&e("div",{children:[t("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"To Date"}),t(r,{name:"date_filter_end",value:v?o(v,"yyyy-MM-dd"):null,onChange:e=>D(e?u(e,"yyyy-MM-dd",new Date):null,!0),className:"w-full"})]})]})};export{d as DateFilter};
2
- //# sourceMappingURL=DateFilter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DateFilter.js","sources":["../../../../../../components/filters/DateFilter.tsx"],"sourcesContent":["import { useState, useEffect, useMemo } from \"react\";\nimport { ColumnFilterValue } from \"../../types\";\nimport { DatePicker } from \"../ui/DatePicker\";\nimport { format, parse } from \"date-fns\";\n\ninterface DateFilterProps {\n value: ColumnFilterValue | null;\n onChange: (value: ColumnFilterValue | null) => void;\n min?: number;\n max?: number;\n}\n\nexport const DateFilter = ({ value, onChange, min, max }: DateFilterProps) => {\n // Local UI state uses Date objects; stored values use \"yyyy-MM-dd\"\n const toDateObj = (v?: string | Date | null): Date | null => {\n if (!v) return null;\n if (v instanceof Date) return isNaN(v.getTime()) ? null : v;\n // Try parse yyyy-MM-dd first\n try {\n const d = parse(String(v), \"yyyy-MM-dd\", new Date());\n return isNaN(d.getTime()) ? null : d;\n } catch (e) {\n const d = new Date(v);\n return isNaN(d.getTime()) ? null : d;\n }\n };\n const toStored = (d: Date | null): string =>\n d ? format(d, \"yyyy-MM-dd\") : \"\";\n\n const [dateValue, setDateValue] = useState<Date | null>(\n toDateObj(value?.value as any),\n );\n const [secondDateValue, setSecondDateValue] = useState<Date | null>(\n value?.operator === \"between\"\n ? toDateObj((value?.secondValue as any) ?? (value?.value as any))\n : null,\n );\n const [operator, setOperator] = useState<\n \"equals\" | \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"between\"\n >((value?.operator as any) || \"between\");\n\n // Sync local state when parent value changes (e.g., clear/apply from outside)\n useEffect(() => {\n setOperator((value?.operator as any) || \"between\");\n setDateValue(toDateObj(value?.value as any));\n setSecondDateValue(\n value?.operator === \"between\"\n ? toDateObj((value?.secondValue as any) ?? (value?.value as any))\n : null,\n );\n }, [value?.value, value?.secondValue, value?.operator]);\n\n // Handle operator changes\n useEffect(() => {\n if (operator === \"between\" && !secondDateValue && dateValue) {\n // If switching to between mode and second date is not set, initialize it with first date\n setSecondDateValue(dateValue);\n }\n }, [operator, dateValue, secondDateValue]);\n\n const clampDate = (date: Date | null, minDate?: Date, maxDate?: Date) => {\n if (!date) return null;\n if (minDate && date < minDate) return null;\n if (maxDate && date > maxDate) return null;\n return date;\n };\n\n const handleDateChange = (newDate: Date | null, isSecond = false) => {\n const nextFirst = isSecond ? dateValue : newDate;\n const nextSecond = isSecond ? newDate : secondDateValue;\n\n const maxForFirst =\n operator === \"between\" && secondDateValue ? secondDateValue : maxDateObj;\n const minForSecond = dateValue ?? minDateObj ?? undefined;\n\n const clampedDate = isSecond\n ? clampDate(newDate, minForSecond, maxDateObj)\n : clampDate(newDate, minDateObj, maxForFirst);\n\n if (isSecond) setSecondDateValue(clampedDate);\n else setDateValue(clampedDate);\n\n if (operator === \"between\") {\n if (nextFirst && nextSecond) {\n const start = nextFirst <= nextSecond ? nextFirst : nextSecond;\n const end = nextFirst >= nextSecond ? nextFirst : nextSecond;\n onChange({\n type: \"date\",\n value: toStored(start),\n secondValue: toStored(end),\n operator: \"between\",\n });\n } else {\n onChange(null);\n }\n } else {\n if (clampedDate) {\n onChange({\n type: \"date\",\n value: toStored(clampedDate),\n operator: operator as any,\n });\n } else {\n onChange(null);\n }\n }\n };\n\n const handleOperatorChange = (newOperator: string) => {\n const op = newOperator as\n | \"equals\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"between\";\n setOperator(op);\n\n if (op === \"between\") {\n if (dateValue && secondDateValue) {\n const start =\n dateValue <= secondDateValue ? dateValue : secondDateValue;\n const end = dateValue >= secondDateValue ? dateValue : secondDateValue;\n onChange({\n type: \"date\",\n value: start,\n secondValue: end,\n operator: \"between\",\n });\n }\n } else {\n if (dateValue) {\n onChange({\n type: \"date\",\n value: dateValue,\n operator: op,\n });\n }\n }\n };\n\n const minDateObj = useMemo(() => (min ? new Date(min) : undefined), [min]);\n const maxDateObj = useMemo(() => (max ? new Date(max) : undefined), [max]);\n\n return (\n <div className=\"space-y-3\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n Filter Type\n </label>\n <select\n value={operator}\n onChange={(e) => handleOperatorChange(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\n >\n <option value=\"equals\">On Date</option>\n <option value=\"gt\">After</option>\n <option value=\"gte\">On or After</option>\n <option value=\"lt\">Before</option>\n <option value=\"lte\">On or Before</option>\n <option value=\"between\">Between Dates</option>\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {operator === \"between\" ? \"From Date\" : \"Date\"}\n </label>\n <DatePicker\n name=\"date_filter_start\"\n value={dateValue ? format(dateValue, \"yyyy-MM-dd\") : null}\n onChange={(d) =>\n handleDateChange(\n d ? parse(d, \"yyyy-MM-dd\", new Date()) : null,\n false,\n )\n }\n className=\"w-full\"\n />\n </div>\n\n {operator === \"between\" && (\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n To Date\n </label>\n <DatePicker\n name=\"date_filter_end\"\n value={\n secondDateValue ? format(secondDateValue, \"yyyy-MM-dd\") : null\n }\n onChange={(d) =>\n handleDateChange(\n d ? parse(d, \"yyyy-MM-dd\", new Date()) : null,\n true,\n )\n }\n className=\"w-full\"\n />\n </div>\n )}\n </div>\n );\n};\n"],"names":["DateFilter","value","onChange","min","max","toDateObj","v","Date","isNaN","getTime","d","parse","String","e","toStored","format","dateValue","setDateValue","useState","secondDateValue","setSecondDateValue","operator","secondValue","setOperator","useEffect","clampDate","date","minDate","maxDate","handleDateChange","newDate","isSecond","nextFirst","nextSecond","maxForFirst","maxDateObj","clampedDate","minDateObj","undefined","end","type","useMemo","_jsxs","className","children","_jsx","newOperator","op","handleOperatorChange","target","DatePicker","name"],"mappings":"6MAYO,MAAMA,EAAa,EAAGC,QAAOC,WAAUC,MAAKC,UAEjD,MAAMC,EAAaC,IACjB,IAAKA,EAAG,OAAO,KACf,GAAIA,aAAaC,KAAM,OAAOC,MAAMF,EAAEG,WAAa,KAAOH,EAE1D,IACE,MAAMI,EAAIC,EAAMC,OAAON,GAAI,aAAc,IAAIC,MAC7C,OAAOC,MAAME,EAAED,WAAa,KAAOC,CACpC,CAAC,MAAOG,GACP,MAAMH,EAAI,IAAIH,KAAKD,GACnB,OAAOE,MAAME,EAAED,WAAa,KAAOC,CACpC,GAEGI,EAAYJ,GAChBA,EAAIK,EAAOL,EAAG,cAAgB,IAEzBM,EAAWC,GAAgBC,EAChCb,EAAUJ,GAAOA,SAEZkB,EAAiBC,GAAsBF,EACxB,YAApBjB,GAAOoB,SACHhB,EAAWJ,GAAOqB,aAAwBrB,GAAOA,OACjD,OAECoB,EAAUE,GAAeL,EAE7BjB,GAAOoB,UAAoB,WAG9BG,EAAU,KACRD,EAAatB,GAAOoB,UAAoB,WACxCJ,EAAaZ,EAAUJ,GAAOA,QAC9BmB,EACsB,YAApBnB,GAAOoB,SACHhB,EAAWJ,GAAOqB,aAAwBrB,GAAOA,OACjD,OAEL,CAACA,GAAOA,MAAOA,GAAOqB,YAAarB,GAAOoB,WAG7CG,EAAU,KACS,YAAbH,IAA2BF,GAAmBH,GAEhDI,EAAmBJ,IAEpB,CAACK,EAAUL,EAAWG,IAEzB,MAAMM,EAAY,CAACC,EAAmBC,EAAgBC,IAC/CF,EACDC,GAAWD,EAAOC,GAClBC,GAAWF,EAAOE,EADgB,KAE/BF,EAHW,KAMdG,EAAmB,CAACC,EAAsBC,GAAW,KACzD,MAAMC,EAAYD,EAAWf,EAAYc,EACnCG,EAAaF,EAAWD,EAAUX,EAElCe,EACS,YAAbb,GAA0BF,EAAkBA,EAAkBgB,EAG1DC,EAAcL,EAChBN,EAAUK,EAHOd,GAAaqB,QAAcC,EAGXH,GACjCV,EAAUK,EAASO,EAAYH,GAKnC,GAHIH,EAAUX,EAAmBgB,GAC5BnB,EAAamB,GAED,YAAbf,EACF,GAAIW,GAAaC,EAAY,CAC3B,MACMM,EAAMP,GAAaC,EAAaD,EAAYC,EAClD/B,EAAS,CACPsC,KAAM,OACNvC,MAAOa,EAJKkB,GAAaC,EAAaD,EAAYC,GAKlDX,YAAaR,EAASyB,GACtBlB,SAAU,WAEb,MACCnB,EAAS,WAITA,EADEkC,EACO,CACPI,KAAM,OACNvC,MAAOa,EAASsB,GAChBf,SAAUA,GAGH,OAsCTgB,EAAaI,EAAQ,IAAOtC,EAAM,IAAII,KAAKJ,QAAOmC,EAAY,CAACnC,IAC/DgC,EAAaM,EAAQ,IAAOrC,EAAM,IAAIG,KAAKH,QAAOkC,EAAY,CAAClC,IAErE,OACEsC,EAAK,MAAA,CAAAC,UAAU,sBACbD,EACE,MAAA,CAAAE,SAAA,CAAAC,EAAA,QAAA,CAAOF,UAAU,+CAA8CC,SAAA,gBAG/DF,EACE,SAAA,CAAAzC,MAAOoB,EACPnB,SAAWW,GA5CU,CAACiC,IAC5B,MAAMC,EAAKD,EAOXvB,EAAYwB,GAED,YAAPA,EACE/B,GAAaG,GAIfjB,EAAS,CACPsC,KAAM,OACNvC,MAJAe,GAAaG,EAAkBH,EAAYG,EAK3CG,YAJUN,GAAaG,EAAkBH,EAAYG,EAKrDE,SAAU,YAIVL,GACFd,EAAS,CACPsC,KAAM,OACNvC,MAAOe,EACPK,SAAU0B,KAiBOC,CAAqBnC,EAAEoC,OAAOhD,OAC/C0C,UAAU,4GAEVC,SAAA,CAAAC,EAAA,SAAA,CAAQ5C,MAAM,SAAyB2C,SAAA,YACvCC,EAAQ,SAAA,CAAA5C,MAAM,KAAmB2C,SAAA,UACjCC,EAAQ,SAAA,CAAA5C,MAAM,MAA0B2C,SAAA,gBACxCC,YAAQ5C,MAAM,KAAI2C,SAAA,WAClBC,EAAA,SAAA,CAAQ5C,MAAM,MAA2B2C,SAAA,iBACzCC,EAAQ,SAAA,CAAA5C,MAAM,UAAS2C,SAAA,wBAI3BF,EAAA,MAAA,CAAAE,SAAA,CACEC,EAAO,QAAA,CAAAF,UAAU,+CACdC,SAAa,YAAbvB,EAAyB,YAAc,SAE1CwB,EAACK,EAAU,CACTC,KAAK,oBACLlD,MAAOe,EAAYD,EAAOC,EAAW,cAAgB,KACrDd,SAAWQ,GACTmB,EACEnB,EAAIC,EAAMD,EAAG,aAAc,IAAIH,MAAU,MACzC,GAGJoC,UAAU,cAIA,YAAbtB,GACCqB,EAAA,MAAA,CAAAE,SAAA,CACEC,EAAO,QAAA,CAAAF,UAAU,+CAETC,SAAA,YACRC,EAACK,EACC,CAAAC,KAAK,kBACLlD,MACEkB,EAAkBJ,EAAOI,EAAiB,cAAgB,KAE5DjB,SAAWQ,GACTmB,EACEnB,EAAIC,EAAMD,EAAG,aAAc,IAAIH,MAAU,MACzC,GAGJoC,UAAU"}
@@ -1,9 +0,0 @@
1
- import { ColumnFilterValue, GridColumn, GridRow } from "../../types";
2
- interface FilterContentProps {
3
- column: GridColumn;
4
- data: GridRow[];
5
- value: ColumnFilterValue | null;
6
- onChange: (val: ColumnFilterValue | null) => void;
7
- }
8
- export declare const FilterContent: ({ column, data, value, onChange }: FilterContentProps) => import("react/jsx-runtime").JSX.Element;
9
- export {};
@@ -1,2 +0,0 @@
1
- import{jsx as e}from"react/jsx-runtime";import{useMemo as t}from"react";import{TextFilter as r}from"./TextFilter.js";import{NumberFilter as n}from"./NumberFilter.js";import{DateFilter as o}from"./DateFilter.js";import{MultiselectFilter as a}from"./MultiselectFilter.js";import{BooleanFilter as l}from"./BooleanFilter.js";const i=({column:i,data:m,value:u,onChange:s})=>{const p=t(()=>{if("object"==typeof i.filterable)return i.filterable;const e=m.slice(0,100).map(e=>e[i.key]).filter(e=>null!=e);if(0===e.length)return{type:"text"};const t=e[0];if("boolean"==typeof t)return{type:"boolean"};if("number"==typeof t)return{type:"number"};if(t instanceof Date||"string"==typeof t&&!isNaN(Date.parse(t)))return{type:"date"};const r=[...new Set(e)];return r.length<=20?{type:"multiselect",options:r.map(e=>({label:String(e),value:e}))}:{type:"text"}},[i.filterable,i.key,m]);switch(p.type){case"text":return e(r,{value:u,onChange:s,placeholder:p.placeholder});case"number":return e(n,{value:u,onChange:s,min:p.min,max:p.max});case"date":return e(o,{value:u,onChange:s,min:p.min,max:p.max});case"multiselect":return e(a,{value:u,onChange:s,options:p.options||[],data:m,columnKey:i.key});case"boolean":return e(l,{value:u,onChange:s});default:return null}};export{i as FilterContent};
2
- //# sourceMappingURL=FilterContent.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FilterContent.js","sources":["../../../../../../components/filters/FilterContent.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport { ColumnFilterValue, ColumnFilter, GridColumn, GridRow } from \"../../types\";\nimport { TextFilter } from \"./TextFilter\";\nimport { NumberFilter } from \"./NumberFilter\";\nimport { DateFilter } from \"./DateFilter\";\nimport { MultiselectFilter } from \"./MultiselectFilter\";\nimport { BooleanFilter } from \"./BooleanFilter\";\n\ninterface FilterContentProps {\n column: GridColumn;\n data: GridRow[];\n value: ColumnFilterValue | null;\n onChange: (val: ColumnFilterValue | null) => void;\n}\n\nexport const FilterContent = ({ column, data, value, onChange }: FilterContentProps) => {\n const filterConfig: ColumnFilter = useMemo(() => {\n if (typeof column.filterable === \"object\") return column.filterable;\n\n // Auto-detect filter type based on data\n const sampleValues = data\n .slice(0, 100)\n .map((row) => row[column.key])\n .filter((val) => val != null);\n\n if (sampleValues.length === 0) return { type: \"text\" };\n\n const firstValue = sampleValues[0];\n if (typeof firstValue === \"boolean\") return { type: \"boolean\" };\n if (typeof firstValue === \"number\") return { type: \"number\" };\n if (\n firstValue instanceof Date ||\n (typeof firstValue === \"string\" && !isNaN(Date.parse(firstValue)))\n ) {\n return { type: \"date\" };\n }\n\n const uniqueValues = [...new Set(sampleValues)];\n if (uniqueValues.length <= 20) {\n return {\n type: \"multiselect\",\n options: uniqueValues.map((val) => ({ label: String(val), value: val })),\n };\n }\n\n return { type: \"text\" };\n }, [column.filterable, column.key, data]);\n\n switch (filterConfig.type) {\n case \"text\":\n return (\n <TextFilter value={value} onChange={onChange} placeholder={filterConfig.placeholder} />\n );\n case \"number\":\n return (\n <NumberFilter value={value} onChange={onChange} min={filterConfig.min} max={filterConfig.max} />\n );\n case \"date\":\n return (\n <DateFilter value={value} onChange={onChange} min={filterConfig.min} max={filterConfig.max} />\n );\n case \"multiselect\":\n return (\n <MultiselectFilter\n value={value}\n onChange={onChange}\n options={filterConfig.options || []}\n data={data}\n columnKey={column.key}\n />\n );\n case \"boolean\":\n return <BooleanFilter value={value} onChange={onChange} />;\n default:\n return null;\n }\n};\n"],"names":["FilterContent","column","data","value","onChange","filterConfig","useMemo","filterable","sampleValues","slice","map","row","key","filter","val","length","type","firstValue","Date","isNaN","parse","uniqueValues","Set","options","label","String","_jsx","TextFilter","placeholder","NumberFilter","min","max","DateFilter","MultiselectFilter","columnKey","BooleanFilter"],"mappings":"iUAeO,MAAMA,EAAgB,EAAGC,SAAQC,OAAMC,QAAOC,eACnD,MAAMC,EAA6BC,EAAQ,KACzC,GAAiC,iBAAtBL,EAAOM,WAAyB,OAAON,EAAOM,WAGzD,MAAMC,EAAeN,EAClBO,MAAM,EAAG,KACTC,IAAKC,GAAQA,EAAIV,EAAOW,MACxBC,OAAQC,GAAe,MAAPA,GAEnB,GAA4B,IAAxBN,EAAaO,OAAc,MAAO,CAAEC,KAAM,QAE9C,MAAMC,EAAaT,EAAa,GAChC,GAA0B,kBAAfS,EAA0B,MAAO,CAAED,KAAM,WACpD,GAA0B,iBAAfC,EAAyB,MAAO,CAAED,KAAM,UACnD,GACEC,aAAsBC,MACC,iBAAfD,IAA4BE,MAAMD,KAAKE,MAAMH,IAErD,MAAO,CAAED,KAAM,QAGjB,MAAMK,EAAe,IAAI,IAAIC,IAAId,IACjC,OAAIa,EAAaN,QAAU,GAClB,CACLC,KAAM,cACNO,QAASF,EAAaX,IAAKI,IAAG,CAAQU,MAAOC,OAAOX,GAAMX,MAAOW,MAI9D,CAAEE,KAAM,SACd,CAACf,EAAOM,WAAYN,EAAOW,IAAKV,IAEnC,OAAQG,EAAaW,MACnB,IAAK,OACH,OACEU,EAACC,GAAWxB,MAAOA,EAAOC,SAAUA,EAAUwB,YAAavB,EAAauB,cAE5E,IAAK,SACH,OACEF,EAACG,EAAa,CAAA1B,MAAOA,EAAOC,SAAUA,EAAU0B,IAAKzB,EAAayB,IAAKC,IAAK1B,EAAa0B,MAE7F,IAAK,OACH,OACEL,EAACM,EAAW,CAAA7B,MAAOA,EAAOC,SAAUA,EAAU0B,IAAKzB,EAAayB,IAAKC,IAAK1B,EAAa0B,MAE3F,IAAK,cACH,OACEL,EAACO,EAAiB,CAChB9B,MAAOA,EACPC,SAAUA,EACVmB,QAASlB,EAAakB,SAAW,GACjCrB,KAAMA,EACNgC,UAAWjC,EAAOW,MAGxB,IAAK,UACH,OAAOc,EAACS,EAAa,CAAChC,MAAOA,EAAOC,SAAUA,IAChD,QACE,OAAO"}
@@ -1,2 +0,0 @@
1
- import { FilterPopupProps } from "../../types";
2
- export declare const FilterPopup: ({ column, data, currentFilter, onApplyFilter, onClose, position, autoApply, }: FilterPopupProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,10 +0,0 @@
1
- import { ColumnFilterValue, FilterOption, GridRow } from "../../types";
2
- interface MultiselectFilterProps {
3
- value: ColumnFilterValue | null;
4
- onChange: (value: ColumnFilterValue | null) => void;
5
- options?: FilterOption[];
6
- data: GridRow[];
7
- columnKey: string;
8
- }
9
- export declare const MultiselectFilter: ({ value, onChange, options, data, columnKey, }: MultiselectFilterProps) => import("react/jsx-runtime").JSX.Element;
10
- export {};
@@ -1,2 +0,0 @@
1
- import{jsxs as e,jsx as l}from"react/jsx-runtime";import{useState as t,useEffect as a,useMemo as r}from"react";import{Search as n,Check as s}from"lucide-react";const o=({value:o,onChange:i,options:c,data:u,columnKey:m})=>{const[d,p]=t(""),[b,v]=t(new Set(o?.value||[]));a(()=>{v(new Set(o?.value||[]))},[o]);const g=r(()=>{let e=[];const l=e=>null==e||""===e||"string"==typeof e&&""===e.trim();if(c&&c.length>0)e=c;else{const t=u.map(e=>{const t=e[m];return l(t)?null:t});e=[...new Set(t)].map(e=>({label:null===e?"Blank":String(e),value:e}))}const t=e.map(e=>{const t=l(e.value);return{...e,label:t?"Blank":e.label,value:t?null:e.value,isBlank:t}});return Array.from(new Map(t.map(e=>[e.isBlank?"__blank__":e.value,e])).values()).sort((e,l)=>e.isBlank&&!l.isBlank?1:!e.isBlank&&l.isBlank?-1:String(e.label).localeCompare(String(l.label)))},[c,u,m]),h=r(()=>{if(!d)return g;const e=d.toLowerCase();return g.filter(l=>l.label.toLowerCase().includes(e)||String(l.value).toLowerCase().includes(e)||"blank"===e&&l.isBlank)},[g,d]);return e("div",{className:"space-y-3",children:[e("div",{className:"relative",children:[l(n,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4"}),l("input",{type:"text",value:d,onChange:e=>p(e.target.value),placeholder:"Search options...",className:"w-full pl-10 pr-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"})]}),e("div",{className:"flex justify-between items-center text-sm",children:[e("span",{className:"text-gray-600",children:[b.size," of ",g.length," selected"]}),e("div",{className:"flex gap-2",children:[l("button",{onClick:()=>{const e=new Set(h.map(e=>e.value));v(e),i({type:"multiselect",value:Array.from(e),operator:"equals"})},className:"text-blue-600 hover:text-blue-800 transition-colors",children:"Select All"}),l("button",{onClick:()=>{v(new Set),i(null)},className:"text-gray-600 hover:text-gray-800 transition-colors",children:"Clear All"})]})]}),l("div",{className:"max-h-48 overflow-y-auto border border-gray-200 rounded-md",children:0===h.length?l("div",{className:"p-3 text-sm text-gray-500 text-center",children:"No options found"}):h.map((t,a)=>{const r=b.has(t.value);return e("div",{onClick:()=>(e=>{const l=new Set(b);l.has(e)?l.delete(e):l.add(e),v(l),l.size>0?i({type:"multiselect",value:Array.from(l),operator:"equals"}):i(null)})(t.value),className:"flex items-center gap-3 p-2 cursor-pointer hover:bg-gray-50 transition-colors "+(r?"bg-blue-50":""),children:[l("div",{className:"w-4 h-4 border-2 rounded flex items-center justify-center "+(r?"bg-blue-600 border-blue-600 text-white":"border-gray-300"),children:r&&l(s,{className:"w-3 h-3"})}),l("span",{className:`text-sm ${r?"text-blue-900 font-medium":"text-gray-700"} ${t.isBlank?"italic text-gray-500":""}`,children:t.label})]},a)})})]})};export{o as MultiselectFilter};
2
- //# sourceMappingURL=MultiselectFilter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MultiselectFilter.js","sources":["../../../../../../components/filters/MultiselectFilter.tsx"],"sourcesContent":["import { useState, useMemo, useEffect } from \"react\";\nimport { Search, Check } from \"lucide-react\";\nimport { ColumnFilterValue, FilterOption, GridRow } from \"../../types\";\n\ninterface MultiselectFilterProps {\n value: ColumnFilterValue | null;\n onChange: (value: ColumnFilterValue | null) => void;\n options?: FilterOption[];\n data: GridRow[];\n columnKey: string;\n}\n\nexport const MultiselectFilter = ({\n value,\n onChange,\n options,\n data,\n columnKey,\n}: MultiselectFilterProps) => {\n const [searchText, setSearchText] = useState(\"\");\n const [selectedValues, setSelectedValues] = useState<Set<any>>(\n new Set(value?.value || [])\n );\n\n // Sync selectedValues when value prop changes\n useEffect(() => {\n setSelectedValues(new Set(value?.value || []));\n }, [value]);\n\n // Generate options from data if not provided\n const availableOptions = useMemo(() => {\n let opts: FilterOption[] = [];\n\n // Helper to check if a value is blank\n const isBlankValue = (val: any): boolean => {\n return (\n val === null ||\n val === undefined ||\n val === \"\" ||\n (typeof val === \"string\" && val.trim() === \"\")\n );\n };\n\n if (options && options.length > 0) {\n opts = options;\n } else {\n // Normalize blank values to null and collect unique values\n const normalizedValues = data.map((row) => {\n const val = row[columnKey];\n return isBlankValue(val) ? null : val;\n });\n\n const uniqueValues = [...new Set(normalizedValues)];\n\n opts = uniqueValues.map((val) => ({\n label: val === null ? \"Blank\" : String(val),\n value: val,\n }));\n }\n\n // Transform blank/null/empty values to display as \"Blank\"\n // and sort them to the end of the list\n const processedOptions = opts.map((opt) => {\n const isBlank = isBlankValue(opt.value);\n\n return {\n ...opt,\n label: isBlank ? \"Blank\" : opt.label,\n value: isBlank ? null : opt.value, // Normalize all blank values to null\n isBlank,\n };\n });\n\n // Remove duplicates after normalization (in case options had multiple blank types)\n const uniqueProcessed = Array.from(\n new Map(\n processedOptions.map((opt) => [\n opt.isBlank ? \"__blank__\" : opt.value,\n opt,\n ])\n ).values()\n );\n\n // Sort: non-blank items first (alphabetically), then blank items at the end\n return uniqueProcessed.sort((a, b) => {\n if (a.isBlank && !b.isBlank) return 1;\n if (!a.isBlank && b.isBlank) return -1;\n return String(a.label).localeCompare(String(b.label));\n });\n }, [options, data, columnKey]);\n\n // Filter options based on search\n const filteredOptions = useMemo(() => {\n if (!searchText) return availableOptions;\n const searchLower = searchText.toLowerCase();\n return availableOptions.filter(\n (option) =>\n option.label.toLowerCase().includes(searchLower) ||\n String(option.value).toLowerCase().includes(searchLower) ||\n (searchLower === \"blank\" && (option as any).isBlank)\n );\n }, [availableOptions, searchText]);\n\n const handleToggleValue = (optionValue: any) => {\n const newSelected = new Set(selectedValues);\n\n if (newSelected.has(optionValue)) {\n newSelected.delete(optionValue);\n } else {\n newSelected.add(optionValue);\n }\n\n setSelectedValues(newSelected);\n\n // Update the temp filter state but don't apply immediately\n if (newSelected.size > 0) {\n onChange({\n type: \"multiselect\",\n value: Array.from(newSelected),\n operator: \"equals\",\n });\n } else {\n onChange(null);\n }\n };\n\n const handleSelectAll = () => {\n const allValues = new Set(filteredOptions.map((opt) => opt.value));\n setSelectedValues(allValues);\n onChange({\n type: \"multiselect\",\n value: Array.from(allValues),\n operator: \"equals\",\n });\n };\n\n const handleClearAll = () => {\n setSelectedValues(new Set());\n onChange(null);\n };\n\n return (\n <div className=\"space-y-3\">\n {/* Search */}\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4\" />\n <input\n type=\"text\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n placeholder=\"Search options...\"\n className=\"w-full pl-10 pr-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\n />\n </div>\n\n {/* Actions */}\n <div className=\"flex justify-between items-center text-sm\">\n <span className=\"text-gray-600\">\n {selectedValues.size} of {availableOptions.length} selected\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={handleSelectAll}\n className=\"text-blue-600 hover:text-blue-800 transition-colors\"\n >\n Select All\n </button>\n <button\n onClick={handleClearAll}\n className=\"text-gray-600 hover:text-gray-800 transition-colors\"\n >\n Clear All\n </button>\n </div>\n </div>\n\n {/* Options List */}\n <div className=\"max-h-48 overflow-y-auto border border-gray-200 rounded-md\">\n {filteredOptions.length === 0 ? (\n <div className=\"p-3 text-sm text-gray-500 text-center\">\n No options found\n </div>\n ) : (\n filteredOptions.map((option, index) => {\n const isSelected = selectedValues.has(option.value);\n return (\n <div\n key={index}\n onClick={() => handleToggleValue(option.value)}\n className={`flex items-center gap-3 p-2 cursor-pointer hover:bg-gray-50 transition-colors ${\n isSelected ? \"bg-blue-50\" : \"\"\n }`}\n >\n <div\n className={`w-4 h-4 border-2 rounded flex items-center justify-center ${\n isSelected\n ? \"bg-blue-600 border-blue-600 text-white\"\n : \"border-gray-300\"\n }`}\n >\n {isSelected && <Check className=\"w-3 h-3\" />}\n </div>\n <span\n className={`text-sm ${\n isSelected ? \"text-blue-900 font-medium\" : \"text-gray-700\"\n } ${(option as any).isBlank ? \"italic text-gray-500\" : \"\"}`}\n >\n {option.label}\n </span>\n </div>\n );\n })\n )}\n </div>\n </div>\n );\n};\n"],"names":["MultiselectFilter","value","onChange","options","data","columnKey","searchText","setSearchText","useState","selectedValues","setSelectedValues","Set","useEffect","availableOptions","useMemo","opts","isBlankValue","val","trim","length","normalizedValues","map","row","label","String","processedOptions","opt","isBlank","Array","from","Map","values","sort","a","b","localeCompare","filteredOptions","searchLower","toLowerCase","filter","option","includes","_jsxs","className","children","_jsx","Search","type","e","target","placeholder","size","onClick","allValues","operator","index","isSelected","has","optionValue","newSelected","delete","add","handleToggleValue","Check"],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- import { ColumnFilterValue } from "../../types";
2
- interface NumberFilterProps {
3
- value: ColumnFilterValue | null;
4
- onChange: (value: ColumnFilterValue | null) => void;
5
- min?: number;
6
- max?: number;
7
- }
8
- export declare const NumberFilter: ({ value, onChange, min, max, }: NumberFilterProps) => import("react/jsx-runtime").JSX.Element;
9
- export {};
@@ -1,2 +0,0 @@
1
- import{jsxs as e,jsx as a}from"react/jsx-runtime";import{useState as r}from"react";const l=({value:l,onChange:t,min:n,max:o})=>{const[u,s]=r(l?.value||""),[i,c]=r(l?.secondValue||""),[m,d]=r(l?.operator||"equals"),b=(e,a=!1)=>{a?c(e):s(e);const r=parseFloat(e),l=parseFloat(i);"between"===m?isNaN(r)||isNaN(l)?t(null):t({type:"number",value:Math.min(r,l),secondValue:Math.max(r,l),operator:"between"}):isNaN(r)?t(null):t({type:"number",value:r,operator:m})};return e("div",{className:"space-y-3",children:[e("div",{children:[a("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Filter Type"}),e("select",{value:m,onChange:e=>(e=>{const a=e;if(d(a),"between"===a){const e=parseFloat(u),a=parseFloat(i);isNaN(e)||isNaN(a)||t({type:"number",value:Math.min(e,a),secondValue:Math.max(e,a),operator:"between"})}else{const e=parseFloat(u);isNaN(e)||t({type:"number",value:e,operator:a})}})(e.target.value),className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500",children:[a("option",{value:"equals",children:"Equals"}),a("option",{value:"gt",children:"Greater than"}),a("option",{value:"gte",children:"Greater than or equal"}),a("option",{value:"lt",children:"Less than"}),a("option",{value:"lte",children:"Less than or equal"}),a("option",{value:"between",children:"Between"})]})]}),e("div",{children:[a("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"between"===m?"From Value":"Number Value"}),a("input",{type:"number",value:u,onChange:e=>b(e.target.value),min:n,max:o,className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"})]}),"between"===m&&e("div",{children:[a("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"To Value"}),a("input",{type:"number",value:i,onChange:e=>b(e.target.value,!0),min:n,max:o,className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"})]})]})};export{l as NumberFilter};
2
- //# sourceMappingURL=NumberFilter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"NumberFilter.js","sources":["../../../../../../components/filters/NumberFilter.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { ColumnFilterValue } from \"../../types\";\n\ninterface NumberFilterProps {\n value: ColumnFilterValue | null;\n onChange: (value: ColumnFilterValue | null) => void;\n min?: number;\n max?: number;\n}\n\nexport const NumberFilter = ({\n value,\n onChange,\n min,\n max,\n}: NumberFilterProps) => {\n const [numberValue, setNumberValue] = useState(value?.value || \"\");\n const [secondValue, setSecondValue] = useState(value?.secondValue || \"\");\n const [operator, setOperator] = useState<\n \"equals\" | \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"between\"\n >((value?.operator as any) || \"equals\");\n\n const handleValueChange = (newValue: string, isSecond = false) => {\n if (isSecond) {\n setSecondValue(newValue);\n } else {\n setNumberValue(newValue);\n }\n\n const numValue = parseFloat(newValue);\n const numSecondValue = parseFloat(secondValue);\n\n if (operator === \"between\") {\n if (!isNaN(numValue) && !isNaN(numSecondValue)) {\n onChange({\n type: \"number\",\n value: Math.min(numValue, numSecondValue),\n secondValue: Math.max(numValue, numSecondValue),\n operator: \"between\",\n });\n } else {\n onChange(null);\n }\n } else {\n if (!isNaN(numValue)) {\n onChange({\n type: \"number\",\n value: numValue,\n operator: operator as any,\n });\n } else {\n onChange(null);\n }\n }\n };\n\n const handleOperatorChange = (newOperator: string) => {\n const op = newOperator as\n | \"equals\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"between\";\n setOperator(op);\n\n if (op === \"between\") {\n const numValue = parseFloat(numberValue);\n const numSecondValue = parseFloat(secondValue);\n if (!isNaN(numValue) && !isNaN(numSecondValue)) {\n onChange({\n type: \"number\",\n value: Math.min(numValue, numSecondValue),\n secondValue: Math.max(numValue, numSecondValue),\n operator: \"between\",\n });\n }\n } else {\n const numValue = parseFloat(numberValue);\n if (!isNaN(numValue)) {\n onChange({\n type: \"number\",\n value: numValue,\n operator: op,\n });\n }\n }\n };\n\n return (\n <div className=\"space-y-3\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n Filter Type\n </label>\n <select\n value={operator}\n onChange={(e) => handleOperatorChange(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\n >\n <option value=\"equals\">Equals</option>\n <option value=\"gt\">Greater than</option>\n <option value=\"gte\">Greater than or equal</option>\n <option value=\"lt\">Less than</option>\n <option value=\"lte\">Less than or equal</option>\n <option value=\"between\">Between</option>\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {operator === \"between\" ? \"From Value\" : \"Number Value\"}\n </label>\n <input\n type=\"number\"\n value={numberValue}\n onChange={(e) => handleValueChange(e.target.value)}\n min={min}\n max={max}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\n />\n </div>\n\n {operator === \"between\" && (\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n To Value\n </label>\n <input\n type=\"number\"\n value={secondValue}\n onChange={(e) => handleValueChange(e.target.value, true)}\n min={min}\n max={max}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\n />\n </div>\n )}\n </div>\n );\n};\n"],"names":["NumberFilter","value","onChange","min","max","numberValue","setNumberValue","useState","secondValue","setSecondValue","operator","setOperator","handleValueChange","newValue","isSecond","numValue","parseFloat","numSecondValue","isNaN","type","Math","_jsxs","className","children","_jsx","e","newOperator","op","handleOperatorChange","target"],"mappings":"mFAUO,MAAMA,EAAe,EAC1BC,QACAC,WACAC,MACAC,UAEA,MAAOC,EAAaC,GAAkBC,EAASN,GAAOA,OAAS,KACxDO,EAAaC,GAAkBF,EAASN,GAAOO,aAAe,KAC9DE,EAAUC,GAAeJ,EAE7BN,GAAOS,UAAoB,UAExBE,EAAoB,CAACC,EAAkBC,GAAW,KAClDA,EACFL,EAAeI,GAEfP,EAAeO,GAGjB,MAAME,EAAWC,WAAWH,GACtBI,EAAiBD,WAAWR,GAEjB,YAAbE,EACGQ,MAAMH,IAAcG,MAAMD,GAQ7Bf,EAAS,MAPTA,EAAS,CACPiB,KAAM,SACNlB,MAAOmB,KAAKjB,IAAIY,EAAUE,GAC1BT,YAAaY,KAAKhB,IAAIW,EAAUE,GAChCP,SAAU,YAMTQ,MAAMH,GAOTb,EAAS,MANTA,EAAS,CACPiB,KAAM,SACNlB,MAAOc,EACPL,SAAUA,KAyClB,OACEW,SAAKC,UAAU,YACbC,SAAA,CAAAF,EAAA,MAAA,CAAAE,SAAA,CACEC,WAAOF,UAAU,+CAETC,SAAA,gBACRF,YACEpB,MAAOS,EACPR,SAAWuB,GAzCU,CAACC,IAC5B,MAAMC,EAAKD,EASX,GAFAf,EAAYgB,GAED,YAAPA,EAAkB,CACpB,MAAMZ,EAAWC,WAAWX,GACtBY,EAAiBD,WAAWR,GAC7BU,MAAMH,IAAcG,MAAMD,IAC7Bf,EAAS,CACPiB,KAAM,SACNlB,MAAOmB,KAAKjB,IAAIY,EAAUE,GAC1BT,YAAaY,KAAKhB,IAAIW,EAAUE,GAChCP,SAAU,WAGf,KAAM,CACL,MAAMK,EAAWC,WAAWX,GACvBa,MAAMH,IACTb,EAAS,CACPiB,KAAM,SACNlB,MAAOc,EACPL,SAAUiB,GAGf,GAWsBC,CAAqBH,EAAEI,OAAO5B,OAC/CqB,UAAU,sHAEVE,EAAQ,SAAA,CAAAvB,MAAM,SAAQsB,SAAA,WACtBC,EAAQ,SAAA,CAAAvB,MAAM,KAAIsB,SAAA,iBAClBC,EAAQ,SAAA,CAAAvB,MAAM,MAAKsB,SAAA,0BACnBC,EAAQ,SAAA,CAAAvB,MAAM,KAAIsB,SAAA,cAClBC,EAAQ,SAAA,CAAAvB,MAAM,MAAKsB,SAAA,uBACnBC,EAAQ,SAAA,CAAAvB,MAAM,UAASsB,SAAA,kBAI3BF,mBACEG,EAAO,QAAA,CAAAF,UAAU,+CAA8CC,SAC/C,YAAbb,EAAyB,aAAe,iBAE3Cc,EACE,QAAA,CAAAL,KAAK,SACLlB,MAAOI,EACPH,SAAWuB,GAAMb,EAAkBa,EAAEI,OAAO5B,OAC5CE,IAAKA,EACLC,IAAKA,EACLkB,UAAU,iHAIA,YAAbZ,GACCW,mBACEG,EAAO,QAAA,CAAAF,UAAU,+CAA8CC,SAAA,aAG/DC,EACE,QAAA,CAAAL,KAAK,SACLlB,MAAOO,EACPN,SAAWuB,GAAMb,EAAkBa,EAAEI,OAAO5B,OAAO,GACnDE,IAAKA,EACLC,IAAKA,EACLkB,UAAU"}
@@ -1,8 +0,0 @@
1
- import { ColumnFilterValue } from "../../types";
2
- interface TextFilterProps {
3
- value: ColumnFilterValue | null;
4
- onChange: (value: ColumnFilterValue | null) => void;
5
- placeholder?: string;
6
- }
7
- export declare const TextFilter: ({ value, onChange, placeholder, }: TextFilterProps) => import("react/jsx-runtime").JSX.Element;
8
- export {};
@@ -1,2 +0,0 @@
1
- import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useState as r}from"react";const l=({value:l,onChange:a,placeholder:o="Enter text to filter..."})=>{const[n,i]=r(l?.value||""),[u,c]=r(l?.operator||"contains");return e("div",{className:"space-y-3",children:[e("div",{children:[t("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Filter Type"}),e("select",{value:u,onChange:e=>(e=>{const t=e;c(t),n.trim()&&a({type:"text",value:n,operator:t})})(e.target.value),className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500",children:[t("option",{value:"contains",children:"Contains"}),t("option",{value:"equals",children:"Equals"}),t("option",{value:"startsWith",children:"Starts with"}),t("option",{value:"endsWith",children:"Ends with"})]})]}),e("div",{children:[t("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Text Value"}),t("input",{type:"text",value:n,onChange:e=>{return t=e.target.value,i(t),void(t.trim()?a({type:"text",value:t,operator:u}):a(null));var t},placeholder:o,className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"})]})]})};export{l as TextFilter};
2
- //# sourceMappingURL=TextFilter.js.map