react-kd-grid 2.2.0 → 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 +1 -1
  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,2 +0,0 @@
1
- import{jsx as e,Fragment as t,jsxs as l}from"react/jsx-runtime";import{useState as r,useEffect as n}from"react";import{ArrowUp as a,ArrowDown as o,Menu as s,Filter as i,ArrowUpDown as d,Pin as c,PinOff as u,Ungroup as m,Group as h,FilterX as b}from"lucide-react";import{SELECT_COL_WIDTH as g}from"../constants.js";import{FilterContent as y}from"./filters/FilterContent.js";const p=({pinnedColumns:p,unpinnedColumns:x,hvPadLeft:f=0,hvPadRight:k=0,headerHeight:v,sortConfig:w,columnFilters:N,selectable:C,selectedRows:D,totalRows:z,data:$,onSort:A,onColumnFilter:j,onSelectAll:R,onColumnResize:T,pinnedKeySet:P=new Set,onColumnPin:E,groupable:S=!1,groupedByColumn:M,onGroupBy:O,groupedByColumns:B=[],onGroupToggle:F,onAutosizeColumn:L,onAutosizeAllColumns:G,onResetColumns:H,columnOrder:U,onColumnOrderChange:X,paginationMode:Y="client"})=>{const K=[...p,...x],[W,q]=r(null),[I,J]=r(null),[Q,V]=r(null),[Z,_]=r(0),[ee,te]=r(0),[le,re]=r("menu"),[ne,ae]=r(null),[oe,se]=r(!1);n(()=>{se("ontouchstart"in window||navigator.maxTouchPoints>0||window.matchMedia("(pointer: coarse)").matches)},[]);const[ie,de]=r(null),[ce,ue]=r(null),me=D.size===z&&z>0,he=D.size>0&&D.size<z,be=(e,t)=>{if(t.stopPropagation(),W===e)q(null);else{q(e),re("menu"),ae(N[e]||null);const l=t.currentTarget.getBoundingClientRect(),r=t.currentTarget.closest("[data-grid-container]"),n=r?r.getBoundingClientRect():new DOMRect(0,0,window.innerWidth,window.innerHeight),a=320,o=10,s=n.left+o,i=n.right-a-o,d=Math.max(s,Math.min(l.left,i));J({top:l.bottom+4,left:d,containerRect:n})}},ge=e=>{j(e,ne||null),q(null)},ye=e=>null!=N[e],pe=(e,t)=>{t.preventDefault(),V(e),_(t.clientX);const l=[...p,...x].find(t=>t.key===e);te(l?.width||100)},xe=e=>{if(!Q||!T)return;const t=e.clientX-Z,l=Math.max(50,ee+t);T(Q,l)},fe=()=>{V(null),_(0),te(0)},[ke,ve]=r(null),[we,Ne]=r(null),Ce=(e,t)=>{ve(e),t.dataTransfer.effectAllowed="move",t.dataTransfer.setData("text/plain",e)},De=(e,t)=>{t.preventDefault(),t.dataTransfer.dropEffect="move";const l=t.currentTarget.getBoundingClientRect(),r=l.left+l.width/2,n=t.clientX<r?"before":"after";Ne({key:e,position:n})},ze=e=>{const t=ke;if(!t||t===e)return;if(P.has(t)!==P.has(e))return ve(null),void Ne(null);const l=we?.key!==e||"before"===we?.position,r=U.filter(e=>e!==t);let n=r.indexOf(e);if(-1===n)return X(r),ve(null),void Ne(null);l||(n+=1),r.splice(n,0,t);X(r),ve(null),Ne(null)},$e=()=>{ve(null),Ne(null)},Ae=(e,t)=>{de(e),t.dataTransfer.effectAllowed="move",t.dataTransfer.setData("text/plain",e)},je=(e,t)=>{t.preventDefault(),t.dataTransfer.dropEffect="move";const l=t.currentTarget.getBoundingClientRect(),r=l.top+l.height/2,n=t.clientY<r?"before":"after";ue({key:e,position:n})},Re=e=>{const t=ie;if(!t||t===e)return;if(P.has(t)!==P.has(e))return de(null),void ue(null);const l=ce?.key!==e||"before"===ce?.position,r=U.filter(e=>e!==t);let n=r.indexOf(e);if(-1===n)return X(r),de(null),void ue(null);l||(n+=1),r.splice(n,0,t),X(r),de(null),ue(null)},Te=()=>{de(null),ue(null)};return n(()=>{if(Q)return document.addEventListener("mousemove",xe),document.addEventListener("mouseup",fe),document.body.style.cursor="col-resize",document.body.style.userSelect="none",()=>{document.removeEventListener("mousemove",xe),document.removeEventListener("mouseup",fe),document.body.style.cursor="",document.body.style.userSelect=""}},[Q,Z,ee,T]),n(()=>{const e=e=>{const t=e.target;W&&!t.closest("[data-column-menu]")&&q(null)};if(W)return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[W]),e(t,{children:e("div",{className:"bg-blue-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700",style:{height:v},role:"row","aria-label":"Column headers",children:l("div",{className:"flex h-full",children:[C&&e("div",{className:"px-3 border-r border-gray-200 dark:border-gray-700 flex items-center justify-center bg-blue-50 dark:bg-gray-800 sticky left-0 z-3 h-full",style:{width:g,height:v},role:"columnheader","aria-label":"Select all rows",children:e("input",{type:"checkbox",checked:me,ref:e=>{e&&(e.indeterminate=he)},onChange:R,onKeyDown:e=>{" "!==e.key&&"Enter"!==e.key||(e.preventDefault(),R())},className:"rounded border-gray-300 dark:border-gray-600 text-blue-600 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 h-4 w-4 transition-all duration-150","aria-label":me?"Deselect all rows":he?`${D.size} rows selected. Click to select all`:"Select all rows",title:me?`Deselect all ${z} rows`:he?`${D.size} of ${z} rows selected`:`Select all ${z} rows`})}),p.map((r,n)=>{const x=P.has(r.key),f=p.filter(e=>P.has(e.key)).map(e=>e.key),k=f.indexOf(r.key),N=x?f.slice(0,k).reduce((e,t)=>{const l=p.find(e=>e.key===t);return e+(l?.width||100)},C?g:0):0,D="center"===r.headerAlign?"justify-center":"right"===r.headerAlign?"justify-end":"justify-start",z=!1!==r.sortable;return l("div",{className:`flex-none border-r border-gray-200 dark:border-gray-700 last:border-r-0 relative ${x?"bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-700 sticky z-2":""} `,style:{width:r.width||100,left:x?`${N}px`:"auto",height:v},"data-column-key":r.key,draggable:!0,onDragStart:e=>Ce(r.key,e),onDragOver:e=>De(r.key,e),onDrop:()=>ze(r.key),onDragEnd:$e,children:[we?.key===r.key&&e("div",{className:"absolute top-0 bottom-0 w-0.5 bg-blue-600 z-4",style:{left:"before"===we?.position?0:void 0,right:"after"===we?.position?0:void 0}}),e("div",{className:"px-3 h-full",children:l("div",{className:"flex items-center justify-between gap-1 group h-full",children:[l("div",{className:`flex items-center min-w-0 flex-1 ${D} ${z?"cursor-pointer hover:text-blue-600":""}`,onClick:()=>z&&A(r.key),children:[l("div",{className:"flex items-center gap-2 min-w-0",children:[ye(r.key)&&e("div",{className:"w-2 h-2 bg-red-500 rounded-full shrink-0",title:"Filter applied"}),e("span",{className:"font-medium text-gray-900 dark:text-gray-100 text-sm truncate min-w-0",children:r.header})]}),z&&w.key===r.key&&e("div",{className:"ml-1 shrink-0 pointer-events-none select-none",children:"asc"===w.direction?e(a,{className:"w-3 h-3 text-blue-600 dark:text-blue-400"}):e(o,{className:"w-3 h-3 text-blue-600 dark:text-blue-400"})})]}),(r.filterable||E||S)&&l("div",{className:"relative "+(W===r.key||oe?"block":"hidden group-hover:block"),"data-column-menu":!0,children:[e("button",{className:"p-1 hover:bg-gray-200 dark:hover:bg-gray-700 rounded shrink-0",onClick:e=>be(r.key,e),"data-menu-trigger":!0,children:e(s,{className:"w-4 h-4 text-gray-500 dark:text-gray-400"})}),W===r.key&&I&&l("div",{className:"fixed bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-md shadow-lg z-1000 w-[320px] overflow-auto",style:{top:`${I.top}px`,left:`${I.left}px`,maxHeight:`${Math.max(160,I.containerRect.bottom-12-I.top)}px`},"data-column-menu":!0,children:[l("div",{className:"flex items-center border-b border-gray-200 dark:border-gray-700",children:[e("button",{className:"px-3 py-2 text-sm flex items-center gap-2 "+("menu"===le?"border-b-2 border-blue-600 text-blue-600":"text-gray-600"),onClick:()=>re("menu"),children:e(s,{className:"w-4 h-4"})}),r.filterable&&e("button",{className:"px-3 py-2 text-sm flex items-center gap-2 "+("filter"===le?"border-b-2 border-blue-600 text-blue-600":"text-gray-600"),onClick:()=>re("filter"),children:e(i,{className:"w-4 h-4"})}),e("button",{className:"px-3 py-2 text-sm flex items-center gap-2 "+("reorder"===le?"border-b-2 border-blue-600 text-blue-600":"text-gray-600"),onClick:()=>re("reorder"),children:e(d,{className:"w-4 h-4"})})]}),"menu"===le&&l("div",{className:"py-1",children:[E&&(M===r.key?l("div",{className:"w-full px-3 py-2 text-left text-sm flex items-center gap-2 text-blue-600",children:[e(c,{className:"w-4 h-4"}),"Pinned by grouping"]}):e("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 flex items-center gap-2",onClick:e=>{e.stopPropagation(),q(null),E?.(r.key,!P.has(r.key))},children:P.has(r.key)?l(t,{children:[e(u,{className:"w-4 h-4"}),"Unpin Column"]}):l(t,{children:[e(c,{className:"w-4 h-4"}),"Pin Column"]})})),L&&e("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50",onClick:()=>{L?.(r.key),q(null)},children:"Autosize This Column"}),G&&e("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50",onClick:()=>{G?.(),q(null)},children:"Autosize All Columns"}),S&&e("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 flex items-center gap-2",onClick:e=>{e.stopPropagation(),q(null);const t=B?.includes(r.key)||M===r.key;F?F(r.key,!t):O?.(t?null:r.key)},children:M===r.key||B?.includes(r.key)?l(t,{children:[e(m,{className:"w-4 h-4"}),"Ungroup"]}):l(t,{children:[e(h,{className:"w-4 h-4"}),"Group by ",r.header]})}),H&&e("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50",onClick:()=>{H?.(),q(null)},children:"Reset Columns"})]}),"filter"===le&&l("div",{className:"p-3 w-full",children:[ye(r.key)&&l("button",{className:"mb-2 text-xs text-red-600 hover:underline flex items-center gap-1",onClick:()=>{ae(null),j(r.key,null),q(null)},children:[e(b,{className:"w-3 h-3"})," Clear Filter"]}),e("div",{className:"max-h-75 overflow-auto pr-1",children:e(y,{column:r,data:$,value:ne,onChange:e=>{ae(e),"server"!==Y&&j(r.key,e)}})}),"server"===Y?l("div",{className:"flex justify-end gap-2 mt-3",children:[e("button",{className:"px-3 py-1.5 text-sm bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200",onClick:()=>q(null),children:"Cancel"}),e("button",{className:"px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700",onClick:()=>ge(r.key),children:"Apply"})]}):e("div",{className:"flex justify-end mt-3",children:e("button",{className:"px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700",onClick:()=>q(null),children:"Close"})})]}),"reorder"===le&&l("div",{className:"px-3 py-2",children:[e("div",{className:"text-xs font-medium text-gray-500 mb-1",children:"Reorder Columns"}),e("div",{className:"max-h-60 overflow-auto border border-gray-200 rounded-md",children:[...U.map(e=>K.find(t=>t.key===e)).filter(Boolean),...K.filter(e=>!U.includes(e.key))].map(t=>{const r=P.has(t.key);return l("div",{className:`flex items-center justify-between px-2 py-1 text-sm bg-white hover:bg-gray-50 border-b last:border-b-0 relative ${ie===t.key?"opacity-60":""} ${r?"bg-blue-50/40":""}`,draggable:!0,onDragStart:e=>Ae(t.key,e),onDragOver:e=>je(t.key,e),onDrop:()=>Re(t.key),onDragEnd:Te,children:[ce?.key===t.key&&e("div",{className:"absolute left-0 right-0 h-0.5 bg-blue-600",style:{top:"before"===ce?.position?0:void 0,bottom:"after"===ce?.position?0:void 0}}),l("div",{className:"flex items-center gap-2",children:[e("span",{className:"text-gray-400 select-none",children:"⋮⋮"}),l("span",{className:"text-gray-800 truncate max-w-45",children:[t.header,r&&e("span",{className:"ml-1 text-[10px] text-blue-600",children:"(pinned)"})]})]})]},t.key)})}),e("div",{className:"text-[10px] text-gray-400 mt-1",children:"Tip: You can only reorder within pinned or unpinned groups."})]})]})]})]})}),n<p.length-1&&T&&e("div",{className:"absolute top-0 right-0 w-1 h-full cursor-col-resize hover:bg-blue-300 transition-colors group",onMouseDown:e=>pe(r.key,e),onDoubleClick:e=>{e.preventDefault(),e.stopPropagation(),L?.(r.key)},title:"Drag to resize • Double‑click to autosize",children:e("div",{className:"w-full h-full group-hover:bg-blue-400"})})]},r.key+n)}),f>0&&e("div",{style:{width:f,height:v},className:"flex-none"}),x.map((r,n)=>{const g="center"===r.headerAlign?"justify-center":"right"===r.headerAlign?"justify-end":"justify-start",p=!1!==r.sortable;return l("div",{className:"flex-none border-r border-gray-200 dark:border-gray-700 last:border-r-0 relative",style:{width:r.width||100,height:v},"data-column-key":r.key,draggable:!0,onDragStart:e=>Ce(r.key,e),onDragOver:e=>De(r.key,e),onDrop:()=>ze(r.key),onDragEnd:$e,children:[we?.key===r.key&&e("div",{className:"absolute top-0 bottom-0 w-0.5 bg-blue-600 z-4",style:{left:"before"===we?.position?0:void 0,right:"after"===we?.position?0:void 0}}),e("div",{className:"px-3 h-full",children:l("div",{className:"flex items-center justify-between gap-1 group h-full",children:[l("div",{className:`flex items-center min-w-0 flex-1 ${g} ${p?"cursor-pointer hover:text-blue-600":""}`,onClick:()=>p&&A(r.key),children:[l("div",{className:"flex items-center gap-2 min-w-0",children:[ye(r.key)&&e("div",{className:"w-2 h-2 bg-red-500 rounded-full shrink-0",title:"Filter applied"}),e("span",{className:"font-medium text-gray-900 dark:text-gray-100 text-sm truncate min-w-0",children:r.header})]}),p&&w.key===r.key&&e("div",{className:"ml-1 shrink-0 pointer-events-none select-none",children:"asc"===w.direction?e(a,{className:"w-3 h-3 text-blue-600 dark:text-blue-400"}):e(o,{className:"w-3 h-3 text-blue-600 dark:text-blue-400"})})]}),(r.filterable||E||S)&&l("div",{className:"relative "+(W===r.key||oe?"block":"hidden group-hover:block"),"data-column-menu":!0,children:[e("button",{className:"p-1 hover:bg-gray-200 dark:hover:bg-gray-700 rounded shrink-0",onClick:e=>be(r.key,e),"data-menu-trigger":!0,children:e(s,{className:"w-4 h-4 text-gray-500 dark:text-gray-400"})}),W===r.key&&I&&l("div",{className:"fixed bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-md shadow-lg z-10 w-[320px] overflow-auto",style:{top:`${I.top}px`,left:`${I.left}px`,maxHeight:`${Math.max(160,I.containerRect.bottom-12-I.top)}px`},"data-column-menu":!0,children:[l("div",{className:"flex items-center border-b border-gray-200 dark:border-gray-700",children:[e("button",{className:"px-3 py-2 text-sm flex items-center gap-2 "+("menu"===le?"border-b-2 border-blue-600 text-blue-600":"text-gray-600"),onClick:()=>re("menu"),children:e(s,{className:"w-4 h-4"})}),r.filterable&&e("button",{className:"px-3 py-2 text-sm flex items-center gap-2 "+("filter"===le?"border-b-2 border-blue-600 text-blue-600":"text-gray-600"),onClick:()=>re("filter"),children:e(i,{className:"w-4 h-4"})}),e("button",{className:"px-3 py-2 text-sm flex items-center gap-2 "+("reorder"===le?"border-b-2 border-blue-600 text-blue-600":"text-gray-600"),onClick:()=>re("reorder"),children:e(d,{className:"w-4 h-4"})})]}),"menu"===le&&l("div",{className:"py-1",children:[E&&e("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 flex items-center gap-2",onClick:e=>{e.stopPropagation(),q(null);const t=!P.has(r.key);E?.(r.key,t)},children:P.has(r.key)?l(t,{children:[e(u,{className:"w-4 h-4"}),"Unpin Column"]}):l(t,{children:[e(c,{className:"w-4 h-4"}),"Pin Column"]})}),L&&e("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50",onClick:()=>{L?.(r.key),q(null)},children:"Autosize This Column"}),G&&e("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50",onClick:()=>{G?.(),q(null)},children:"Autosize All Columns"}),S&&e("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 flex items-center gap-2",onClick:e=>{e.stopPropagation(),q(null);const t=B?.includes(r.key)||M===r.key;F?F(r.key,!t):O?.(t?null:r.key)},children:M===r.key||B?.includes(r.key)?l(t,{children:[e(m,{className:"w-4 h-4"}),"Ungroup"]}):l(t,{children:[e(h,{className:"w-4 h-4"}),"Group by ",r.header]})}),H&&e("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50",onClick:()=>{H?.(),q(null)},children:"Reset Columns"})]}),"filter"===le&&l("div",{className:"p-3 w-full",children:[e("div",{className:"max-h-75 overflow-auto pr-1",children:e(y,{column:r,data:$,value:ne,onChange:e=>{ae(e),"server"!==Y&&j(r.key,e)}})}),l("div",{className:"flex justify-end gap-2 mt-3",children:[ye(r.key)&&l("button",{className:"px-3 py-1.5 text-sm bg-red-500 text-white rounded-md hover:bg-red-600 flex items-center gap-2 cursor-pointer",onClick:()=>{ae(null),j(r.key,null),q(null)},children:[e(b,{className:"w-3 h-3"})," Clear Filter"]}),e("button",{className:"px-3 py-1.5 text-sm bg-green-100 text-green-700 rounded-md hover:bg-green-200 cursor-pointer",onClick:()=>q(null),children:"Apply"}),"server"===Y&&e("button",{className:"px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700",onClick:()=>ge(r.key),children:"Apply"})]})]}),"reorder"===le&&l("div",{className:"px-3 py-2",children:[e("div",{className:"text-xs font-medium text-gray-500 mb-1",children:"Reorder Columns"}),e("div",{className:"max-h-60 overflow-auto border border-gray-200 rounded-md",children:[...U.map(e=>K.find(t=>t.key===e)).filter(Boolean),...K.filter(e=>!U.includes(e.key))].map(t=>{const r=P.has(t.key);return l("div",{className:`flex items-center justify-between px-2 py-1 text-sm bg-white hover:bg-gray-50 border-b last:border-b-0 relative ${ie===t.key?"opacity-60":""} ${r?"bg-blue-50/40":""}`,draggable:!0,onDragStart:e=>Ae(t.key,e),onDragOver:e=>je(t.key,e),onDrop:()=>Re(t.key),onDragEnd:Te,children:[ce?.key===t.key&&e("div",{className:"absolute left-0 right-0 h-0.5 bg-blue-600",style:{top:"before"===ce?.position?0:void 0,bottom:"after"===ce?.position?0:void 0}}),l("div",{className:"flex items-center gap-2",children:[e("span",{className:"text-gray-400 select-none",children:"⋮⋮"}),l("span",{className:"text-gray-800 truncate max-w-45",children:[t.header,r&&e("span",{className:"ml-1 text-[10px] text-blue-600",children:"(pinned)"})]})]})]},t.key)})}),e("div",{className:"text-[10px] text-gray-400 mt-1",children:"Tip: You can only reorder within pinned or unpinned groups."})]})]})]})]})}),n<x.length-1&&T&&e("div",{className:"absolute top-0 right-0 w-1 h-full cursor-col-resize hover:bg-blue-300 transition-colors group",onMouseDown:e=>pe(r.key,e),onDoubleClick:e=>{e.preventDefault(),e.stopPropagation(),L?.(r.key)},title:"Drag to resize • Double‑click to autosize",children:e("div",{className:"w-full h-full group-hover:bg-blue-400"})})]},r.key+n)}),k>0&&e("div",{style:{width:k,height:v},className:"flex-none"})]})})})};export{p as GridHeader};
2
- //# sourceMappingURL=GridHeader.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"GridHeader.js","sources":["../../../../../components/GridHeader.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport type { MouseEvent as ReactMouseEvent } from \"react\";\nimport {\n Filter,\n FilterX,\n Menu,\n Pin,\n PinOff,\n Group,\n Ungroup,\n ArrowUp,\n ArrowDown,\n ArrowUpDown,\n} from \"lucide-react\";\nimport {\n GridColumn,\n SortConfig,\n ActiveFilters,\n ColumnFilterValue,\n GridRow,\n} from \"../types\";\nimport { SELECT_COL_WIDTH } from \"../constants\";\nimport { FilterContent } from \"./filters/FilterContent\";\n\ninterface GridHeaderProps {\n pinnedColumns: GridColumn[];\n unpinnedColumns: GridColumn[];\n hvPadLeft?: number;\n hvPadRight?: number;\n // Fixed header height in px (use density-controlled row height)\n headerHeight: number;\n sortConfig: SortConfig;\n columnFilters: ActiveFilters;\n selectable: boolean;\n selectedRows: Set<string | number>;\n totalRows: number;\n data: GridRow[];\n onSort: (key: string) => void;\n onColumnFilter: (key: string, filter: ColumnFilterValue | null) => void;\n onSelectAll: () => void;\n onColumnResize?: (columnKey: string, width: number) => void;\n pinnedKeySet?: Set<string>;\n onColumnPin?: (columnKey: string, pinned: boolean) => void;\n groupable?: boolean;\n // Back-compat single grouped column\n groupedByColumn?: string | null;\n onGroupBy?: (columnKey: string | null) => void;\n // New multi-group API\n groupedByColumns?: string[];\n onGroupToggle?: (columnKey: string, nextGrouped: boolean) => void;\n onAutosizeColumn?: (columnKey: string) => void;\n onAutosizeAllColumns?: () => void;\n onResetColumns?: () => void;\n // Reorder props\n columnOrder: string[];\n onColumnOrderChange: (order: string[]) => void;\n // Pagination mode for auto-apply filtering\n paginationMode?: \"client\" | \"server\" | null;\n}\n\nexport const GridHeader = ({\n pinnedColumns,\n unpinnedColumns,\n hvPadLeft = 0,\n hvPadRight = 0,\n headerHeight,\n sortConfig,\n columnFilters,\n selectable,\n selectedRows,\n totalRows,\n data,\n onSort,\n onColumnFilter,\n onSelectAll,\n onColumnResize,\n pinnedKeySet = new Set<string>(),\n onColumnPin,\n groupable = false,\n groupedByColumn,\n onGroupBy,\n groupedByColumns = [],\n onGroupToggle,\n onAutosizeColumn,\n onAutosizeAllColumns,\n onResetColumns,\n columnOrder,\n onColumnOrderChange,\n paginationMode = \"client\",\n}: GridHeaderProps) => {\n const allColumns = [...pinnedColumns, ...unpinnedColumns];\n const [activeColumnMenu, setActiveColumnMenu] = useState<string | null>(null);\n const [menuPosition, setMenuPosition] = useState<{\n top: number;\n left: number;\n containerRect: DOMRect;\n } | null>(null);\n const [isResizing, setIsResizing] = useState<string | null>(null);\n const [startX, setStartX] = useState<number>(0);\n const [startWidth, setStartWidth] = useState<number>(0);\n const [activeTab, setActiveTab] = useState<\"menu\" | \"filter\" | \"reorder\">(\n \"menu\"\n );\n const [tempFilter, setTempFilter] = useState<ColumnFilterValue | null>(null);\n const [isTouchDevice, setIsTouchDevice] = useState(false);\n\n useEffect(() => {\n setIsTouchDevice(\n \"ontouchstart\" in window ||\n navigator.maxTouchPoints > 0 ||\n window.matchMedia(\"(pointer: coarse)\").matches\n );\n }, []);\n\n // Reorder-in-menu state\n const [menuReorderDraggingKey, setMenuReorderDraggingKey] = useState<\n string | null\n >(null);\n const [menuReorderDragOver, setMenuReorderDragOver] = useState<{\n key: string;\n position: \"before\" | \"after\";\n } | null>(null);\n\n const isAllSelected = selectedRows.size === totalRows && totalRows > 0;\n const isIndeterminate =\n selectedRows.size > 0 && selectedRows.size < totalRows;\n\n const handleColumnMenuClick = (\n columnKey: string,\n event: ReactMouseEvent<HTMLButtonElement>\n ) => {\n event.stopPropagation();\n if (activeColumnMenu === columnKey) {\n setActiveColumnMenu(null);\n } else {\n setActiveColumnMenu(columnKey);\n setActiveTab(\"menu\");\n setTempFilter(columnFilters[columnKey] || null);\n\n // Store button position and clamp to grid container bounds\n const rect = event.currentTarget.getBoundingClientRect();\n // Find the nearest grid container for boundary clamping\n const containerEl = event.currentTarget.closest(\n \"[data-grid-container]\"\n ) as HTMLElement | null;\n const containerRect = containerEl\n ? containerEl.getBoundingClientRect()\n : new DOMRect(0, 0, window.innerWidth, window.innerHeight);\n\n const MENU_WIDTH = 320; // matches dropdown width below\n const PADDING = 10;\n\n // Clamp left so the menu stays inside the grid container horizontally\n const minLeft = containerRect.left + PADDING;\n const maxLeft = containerRect.right - MENU_WIDTH - PADDING;\n const clampedLeft = Math.max(minLeft, Math.min(rect.left, maxLeft));\n\n setMenuPosition({\n top: rect.bottom + 4,\n left: clampedLeft,\n containerRect,\n });\n }\n };\n\n const handleApplyFilter = (columnKey: string) => {\n onColumnFilter(columnKey, tempFilter || null);\n setActiveColumnMenu(null);\n };\n\n const hasActiveFilter = (columnKey: string) => {\n return columnFilters[columnKey] != null;\n };\n\n const handleResizeStart = (columnKey: string, event: ReactMouseEvent) => {\n event.preventDefault();\n setIsResizing(columnKey);\n setStartX(event.clientX);\n const column = [...pinnedColumns, ...unpinnedColumns].find(\n (col) => col.key === columnKey\n );\n setStartWidth(column?.width || 100);\n };\n\n const handleResizeMove = (event: globalThis.MouseEvent) => {\n if (!isResizing || !onColumnResize) return;\n\n const deltaX = event.clientX - startX;\n const newWidth = Math.max(50, startWidth + deltaX); // Minimum width of 50px\n onColumnResize(isResizing, newWidth);\n };\n\n const handleResizeEnd = () => {\n setIsResizing(null);\n setStartX(0);\n setStartWidth(0);\n };\n\n // Drag & Drop state for 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 // (no-op helper removed; ordering is computed inline in handleDrop)\n\n const handleDragStart = (\n columnKey: string,\n e: React.DragEvent<HTMLDivElement>\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<HTMLDivElement>\n ) => {\n // Allow drop\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const midpoint = rect.left + rect.width / 2;\n const position = e.clientX < 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 // Prevent cross pinned/unpinned moves for clearer UX\n const sourcePinned = pinnedKeySet.has(sourceKey);\n const targetPinned = pinnedKeySet.has(targetKey);\n if (sourcePinned !== targetPinned) {\n setDraggingKey(null);\n setDragOver(null);\n return;\n }\n\n const before =\n dragOver?.key === targetKey ? dragOver?.position === \"before\" : true;\n const base = columnOrder.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 const next = base;\n onColumnOrderChange(next);\n setDraggingKey(null);\n setDragOver(null);\n };\n\n const handleDragEnd = () => {\n setDraggingKey(null);\n setDragOver(null);\n };\n\n // --- Reorder handlers for the popup list ---\n const handleMenuReorderDragStart = (\n columnKey: string,\n e: React.DragEvent<HTMLDivElement>\n ) => {\n setMenuReorderDraggingKey(columnKey);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", columnKey);\n };\n\n const handleMenuReorderDragOver = (\n targetKey: string,\n e: React.DragEvent<HTMLDivElement>\n ) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const midpoint = rect.top + rect.height / 2;\n const position = e.clientY < midpoint ? \"before\" : \"after\";\n setMenuReorderDragOver({ key: targetKey, position });\n };\n\n const handleMenuReorderDrop = (targetKey: string) => {\n const sourceKey = menuReorderDraggingKey;\n if (!sourceKey || sourceKey === targetKey) return;\n\n // Prevent cross pinned/unpinned moves\n const sourcePinned = pinnedKeySet.has(sourceKey);\n const targetPinned = pinnedKeySet.has(targetKey);\n if (sourcePinned !== targetPinned) {\n setMenuReorderDraggingKey(null);\n setMenuReorderDragOver(null);\n return;\n }\n\n const before =\n menuReorderDragOver?.key === targetKey\n ? menuReorderDragOver?.position === \"before\"\n : true;\n const base = columnOrder.filter((k) => k !== sourceKey);\n let idx = base.indexOf(targetKey);\n if (idx === -1) {\n onColumnOrderChange(base);\n setMenuReorderDraggingKey(null);\n setMenuReorderDragOver(null);\n return;\n }\n if (!before) idx += 1;\n base.splice(idx, 0, sourceKey);\n onColumnOrderChange(base);\n setMenuReorderDraggingKey(null);\n setMenuReorderDragOver(null);\n };\n\n const handleMenuReorderDragEnd = () => {\n setMenuReorderDraggingKey(null);\n setMenuReorderDragOver(null);\n };\n\n // Add global mouse event listeners for resizing\n useEffect(() => {\n if (isResizing) {\n document.addEventListener(\"mousemove\", handleResizeMove);\n document.addEventListener(\"mouseup\", handleResizeEnd);\n document.body.style.cursor = \"col-resize\";\n document.body.style.userSelect = \"none\";\n\n return () => {\n document.removeEventListener(\"mousemove\", handleResizeMove);\n document.removeEventListener(\"mouseup\", handleResizeEnd);\n document.body.style.cursor = \"\";\n document.body.style.userSelect = \"\";\n };\n }\n }, [isResizing, startX, startWidth, onColumnResize]);\n\n // Close menu on outside click\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n const target = event.target as Element;\n if (activeColumnMenu && !target.closest(\"[data-column-menu]\")) {\n setActiveColumnMenu(null);\n }\n };\n\n if (activeColumnMenu) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () =>\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }\n }, [activeColumnMenu]);\n\n return (\n <>\n <div\n className=\"bg-blue-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700\"\n style={{ height: headerHeight }}\n role=\"row\"\n aria-label=\"Column headers\"\n >\n <div className=\"flex h-full\">\n {selectable && (\n <div\n className=\"px-3 border-r border-gray-200 dark:border-gray-700 flex items-center justify-center bg-blue-50 dark:bg-gray-800 sticky left-0 z-3 h-full\"\n style={{ width: SELECT_COL_WIDTH, height: headerHeight }}\n role=\"columnheader\"\n aria-label=\"Select all rows\"\n >\n <input\n type=\"checkbox\"\n checked={isAllSelected}\n ref={(el) => {\n if (el) el.indeterminate = isIndeterminate;\n }}\n onChange={onSelectAll}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n onSelectAll();\n }\n }}\n className=\"rounded border-gray-300 dark:border-gray-600 text-blue-600 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 h-4 w-4 transition-all duration-150\"\n aria-label={\n isAllSelected\n ? \"Deselect all rows\"\n : isIndeterminate\n ? `${selectedRows.size} rows selected. Click to select all`\n : \"Select all rows\"\n }\n title={\n isAllSelected\n ? `Deselect all ${totalRows} rows`\n : isIndeterminate\n ? `${selectedRows.size} of ${totalRows} rows selected`\n : `Select all ${totalRows} rows`\n }\n />\n </div>\n )}\n\n {/* Pinned columns */}\n {pinnedColumns.map((column, index) => {\n const isPinned = pinnedKeySet.has(column.key);\n const pinnedKeysInOrder = pinnedColumns\n .filter((c) => pinnedKeySet.has(c.key))\n .map((c) => c.key);\n const pinnedIndex = pinnedKeysInOrder.indexOf(column.key);\n const leftOffset = isPinned\n ? pinnedKeysInOrder.slice(0, pinnedIndex).reduce(\n (sum, key) => {\n const col = pinnedColumns.find((c) => c.key === key);\n return sum + (col?.width || 100);\n },\n selectable ? SELECT_COL_WIDTH : 0\n )\n : 0;\n\n const headerJustify =\n column.headerAlign === \"center\"\n ? \"justify-center\"\n : column.headerAlign === \"right\"\n ? \"justify-end\"\n : \"justify-start\";\n\n // Determine effective sortable (default true unless explicitly false)\n const colSortable = column.sortable !== false;\n return (\n <div\n key={column.key + index}\n className={`flex-none border-r border-gray-200 dark:border-gray-700 last:border-r-0 relative ${\n isPinned\n ? \"bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-700 sticky z-2\"\n : \"\"\n } `}\n style={{\n width: column.width || 100,\n left: isPinned ? `${leftOffset}px` : \"auto\",\n height: headerHeight,\n }}\n data-column-key={column.key}\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 {/* Drop indicator */}\n {dragOver?.key === column.key && (\n <div\n className=\"absolute top-0 bottom-0 w-0.5 bg-blue-600 z-4\"\n style={{\n left: dragOver?.position === \"before\" ? 0 : undefined,\n right: dragOver?.position === \"after\" ? 0 : undefined,\n }}\n />\n )}\n <div className=\"px-3 h-full\">\n {/* Header with sort */}\n <div className=\"flex items-center justify-between gap-1 group h-full\">\n <div\n className={`flex items-center min-w-0 flex-1 ${headerJustify} ${\n colSortable ? \"cursor-pointer hover:text-blue-600\" : \"\"\n }`}\n onClick={() => colSortable && onSort(column.key)}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n {/* Filter indicator */}\n {hasActiveFilter(column.key) && (\n <div\n className=\"w-2 h-2 bg-red-500 rounded-full shrink-0\"\n title=\"Filter applied\"\n />\n )}\n <span className=\"font-medium text-gray-900 dark:text-gray-100 text-sm truncate min-w-0\">\n {column.header}\n </span>\n </div>\n {colSortable && sortConfig.key === column.key && (\n <div className=\"ml-1 shrink-0 pointer-events-none select-none\">\n {sortConfig.direction === \"asc\" ? (\n <ArrowUp className=\"w-3 h-3 text-blue-600 dark:text-blue-400\" />\n ) : (\n <ArrowDown className=\"w-3 h-3 text-blue-600 dark:text-blue-400\" />\n )}\n </div>\n )}\n </div>\n\n {/* Three-dot menu */}\n {(column.filterable || onColumnPin || groupable) && (\n <div\n className={`relative ${\n activeColumnMenu === column.key || isTouchDevice\n ? \"block\"\n : \"hidden group-hover:block\"\n }`}\n data-column-menu\n >\n <button\n className=\"p-1 hover:bg-gray-200 dark:hover:bg-gray-700 rounded shrink-0\"\n onClick={(e) => handleColumnMenuClick(column.key, e)}\n data-menu-trigger\n >\n <Menu className=\"w-4 h-4 text-gray-500 dark:text-gray-400\" />\n </button>\n\n {/* Dropdown Menu with Tabs */}\n {activeColumnMenu === column.key && menuPosition && (\n <div\n className=\"fixed bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-md shadow-lg z-1000 w-[320px] overflow-auto\"\n style={{\n top: `${menuPosition.top}px`,\n left: `${menuPosition.left}px`,\n // Ensure the menu height never exceeds available space within the grid container\n maxHeight: `${Math.max(\n 160,\n menuPosition.containerRect.bottom -\n 12 -\n menuPosition.top\n )}px`,\n }}\n data-column-menu\n >\n {/* Tabs */}\n <div className=\"flex items-center border-b border-gray-200 dark:border-gray-700\">\n <button\n className={`px-3 py-2 text-sm flex items-center gap-2 ${\n activeTab === \"menu\"\n ? \"border-b-2 border-blue-600 text-blue-600\"\n : \"text-gray-600\"\n }`}\n onClick={() => setActiveTab(\"menu\")}\n >\n <Menu className=\"w-4 h-4\" />\n </button>\n {column.filterable && (\n <button\n className={`px-3 py-2 text-sm flex items-center gap-2 ${\n activeTab === \"filter\"\n ? \"border-b-2 border-blue-600 text-blue-600\"\n : \"text-gray-600\"\n }`}\n onClick={() => setActiveTab(\"filter\")}\n >\n <Filter className=\"w-4 h-4\" />\n </button>\n )}\n <button\n className={`px-3 py-2 text-sm flex items-center gap-2 ${\n activeTab === \"reorder\"\n ? \"border-b-2 border-blue-600 text-blue-600\"\n : \"text-gray-600\"\n }`}\n onClick={() => setActiveTab(\"reorder\")}\n >\n <ArrowUpDown className=\"w-4 h-4\" />\n </button>\n </div>\n {/* Tab Content */}\n {activeTab === \"menu\" && (\n <div className=\"py-1\">\n {onColumnPin &&\n (groupedByColumn === column.key ? (\n <div className=\"w-full px-3 py-2 text-left text-sm flex items-center gap-2 text-blue-600\">\n <Pin className=\"w-4 h-4\" />\n Pinned by grouping\n </div>\n ) : (\n <button\n className=\"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 flex items-center gap-2\"\n onClick={(e) => {\n e.stopPropagation();\n setActiveColumnMenu(null);\n onColumnPin?.(\n column.key,\n !pinnedKeySet.has(column.key)\n );\n }}\n >\n {pinnedKeySet.has(column.key) ? (\n <>\n <PinOff className=\"w-4 h-4\" />\n Unpin Column\n </>\n ) : (\n <>\n <Pin className=\"w-4 h-4\" />\n Pin Column\n </>\n )}\n </button>\n ))}\n\n {onAutosizeColumn && (\n <button\n className=\"w-full px-3 py-2 text-left text-sm hover:bg-gray-50\"\n onClick={() => {\n onAutosizeColumn?.(column.key);\n setActiveColumnMenu(null);\n }}\n >\n Autosize This Column\n </button>\n )}\n {onAutosizeAllColumns && (\n <button\n className=\"w-full px-3 py-2 text-left text-sm hover:bg-gray-50\"\n onClick={() => {\n onAutosizeAllColumns?.();\n setActiveColumnMenu(null);\n }}\n >\n Autosize All Columns\n </button>\n )}\n\n {groupable && (\n <button\n className=\"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 flex items-center gap-2\"\n onClick={(e) => {\n e.stopPropagation();\n setActiveColumnMenu(null);\n const isGrouped =\n groupedByColumns?.includes(\n column.key\n ) || groupedByColumn === column.key;\n if (onGroupToggle)\n onGroupToggle(column.key, !isGrouped);\n else\n onGroupBy?.(\n isGrouped ? null : column.key\n );\n }}\n >\n {groupedByColumn === column.key ||\n groupedByColumns?.includes(column.key) ? (\n <>\n <Ungroup className=\"w-4 h-4\" />\n Ungroup\n </>\n ) : (\n <>\n <Group className=\"w-4 h-4\" />\n Group by {column.header}\n </>\n )}\n </button>\n )}\n\n {onResetColumns && (\n <button\n className=\"w-full px-3 py-2 text-left text-sm hover:bg-gray-50\"\n onClick={() => {\n onResetColumns?.();\n setActiveColumnMenu(null);\n }}\n >\n Reset Columns\n </button>\n )}\n </div>\n )}\n {activeTab === \"filter\" && (\n <div className=\"p-3 w-full\">\n {/* Filter Tab */}\n {hasActiveFilter(column.key) && (\n <button\n className=\"mb-2 text-xs text-red-600 hover:underline flex items-center gap-1\"\n onClick={() => {\n setTempFilter(null);\n onColumnFilter(column.key, null);\n setActiveColumnMenu(null);\n }}\n >\n <FilterX className=\"w-3 h-3\" /> Clear Filter\n </button>\n )}\n <div className=\"max-h-75 overflow-auto pr-1\">\n <FilterContent\n column={column}\n data={data}\n value={tempFilter}\n onChange={(val) => {\n setTempFilter(val);\n // Auto-apply for client-side or no pagination\n if (paginationMode !== \"server\") {\n onColumnFilter(column.key, val);\n }\n }}\n />\n </div>\n {paginationMode === \"server\" ? (\n <div className=\"flex justify-end gap-2 mt-3\">\n <button\n className=\"px-3 py-1.5 text-sm bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200\"\n onClick={() => setActiveColumnMenu(null)}\n >\n Cancel\n </button>\n <button\n className=\"px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700\"\n onClick={() =>\n handleApplyFilter(column.key)\n }\n >\n Apply\n </button>\n </div>\n ) : (\n <div className=\"flex justify-end mt-3\">\n <button\n className=\"px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700\"\n onClick={() => setActiveColumnMenu(null)}\n >\n Close\n </button>\n </div>\n )}\n </div>\n )}\n {activeTab === \"reorder\" && (\n <div className=\"px-3 py-2\">\n <div className=\"text-xs font-medium text-gray-500 mb-1\">\n Reorder Columns\n </div>\n <div className=\"max-h-60 overflow-auto border border-gray-200 rounded-md\">\n {(() => {\n // Build ordered array by columnOrder using allColumns\n const ordered = [\n ...columnOrder\n .map((k) =>\n allColumns.find((c) => c.key === k)\n )\n .filter(Boolean),\n // add any missing\n ...allColumns.filter(\n (c) => !columnOrder.includes(c.key)\n ),\n ] as GridColumn[];\n\n return ordered.map((c) => {\n const isPinnedItem = pinnedKeySet.has(\n c.key\n );\n return (\n <div\n key={c.key}\n className={`flex items-center justify-between px-2 py-1 text-sm bg-white hover:bg-gray-50 border-b last:border-b-0 relative ${\n menuReorderDraggingKey === c.key\n ? \"opacity-60\"\n : \"\"\n } ${\n isPinnedItem ? \"bg-blue-50/40\" : \"\"\n }`}\n draggable\n onDragStart={(e) =>\n handleMenuReorderDragStart(c.key, e)\n }\n onDragOver={(e) =>\n handleMenuReorderDragOver(c.key, e)\n }\n onDrop={() =>\n handleMenuReorderDrop(c.key)\n }\n onDragEnd={handleMenuReorderDragEnd}\n >\n {/* drop indicator */}\n {menuReorderDragOver?.key ===\n c.key && (\n <div\n className=\"absolute left-0 right-0 h-0.5 bg-blue-600\"\n style={{\n top:\n menuReorderDragOver?.position ===\n \"before\"\n ? 0\n : undefined,\n bottom:\n menuReorderDragOver?.position ===\n \"after\"\n ? 0\n : undefined,\n }}\n />\n )}\n <div className=\"flex items-center gap-2\">\n <span className=\"text-gray-400 select-none\">\n ⋮⋮\n </span>\n <span className=\"text-gray-800 truncate max-w-45\">\n {c.header}\n {isPinnedItem && (\n <span className=\"ml-1 text-[10px] text-blue-600\">\n (pinned)\n </span>\n )}\n </span>\n </div>\n </div>\n );\n });\n })()}\n </div>\n <div className=\"text-[10px] text-gray-400 mt-1\">\n Tip: You can only reorder within pinned or\n unpinned groups.\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n\n {/* Resize handle */}\n {index < pinnedColumns.length - 1 && onColumnResize && (\n <div\n className=\"absolute top-0 right-0 w-1 h-full cursor-col-resize hover:bg-blue-300 transition-colors group\"\n onMouseDown={(e) => handleResizeStart(column.key, e)}\n onDoubleClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n onAutosizeColumn?.(column.key);\n }}\n title=\"Drag to resize • Double‑click to autosize\"\n >\n <div className=\"w-full h-full group-hover:bg-blue-400\" />\n </div>\n )}\n </div>\n );\n })}\n\n {/* Spacer before first visible unpinned col */}\n {hvPadLeft > 0 && (\n <div\n style={{ width: hvPadLeft, height: headerHeight }}\n className=\"flex-none\"\n />\n )}\n\n {/* Unpinned visible columns */}\n {unpinnedColumns.map((column, index) => {\n // unpinned visible segment\n const headerJustify =\n column.headerAlign === \"center\"\n ? \"justify-center\"\n : column.headerAlign === \"right\"\n ? \"justify-end\"\n : \"justify-start\";\n\n const colSortable = column.sortable !== false;\n return (\n <div\n key={column.key + index}\n className={`flex-none border-r border-gray-200 dark:border-gray-700 last:border-r-0 relative`}\n style={{ width: column.width || 100, height: headerHeight }}\n data-column-key={column.key}\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 {/* Drop indicator */}\n {dragOver?.key === column.key && (\n <div\n className=\"absolute top-0 bottom-0 w-0.5 bg-blue-600 z-4\"\n style={{\n left: dragOver?.position === \"before\" ? 0 : undefined,\n right: dragOver?.position === \"after\" ? 0 : undefined,\n }}\n />\n )}\n <div className=\"px-3 h-full\">\n {/* Header with sort */}\n <div className=\"flex items-center justify-between gap-1 group h-full\">\n <div\n className={`flex items-center min-w-0 flex-1 ${headerJustify} ${\n colSortable ? \"cursor-pointer hover:text-blue-600\" : \"\"\n }`}\n onClick={() => colSortable && onSort(column.key)}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n {/* Filter indicator */}\n {hasActiveFilter(column.key) && (\n <div\n className=\"w-2 h-2 bg-red-500 rounded-full shrink-0\"\n title=\"Filter applied\"\n />\n )}\n <span className=\"font-medium text-gray-900 dark:text-gray-100 text-sm truncate min-w-0\">\n {column.header}\n </span>\n </div>\n {colSortable && sortConfig.key === column.key && (\n <div className=\"ml-1 shrink-0 pointer-events-none select-none\">\n {sortConfig.direction === \"asc\" ? (\n <ArrowUp className=\"w-3 h-3 text-blue-600 dark:text-blue-400\" />\n ) : (\n <ArrowDown className=\"w-3 h-3 text-blue-600 dark:text-blue-400\" />\n )}\n </div>\n )}\n </div>\n\n {/* Three-dot menu */}\n {(column.filterable || onColumnPin || groupable) && (\n <div\n className={`relative ${\n activeColumnMenu === column.key || isTouchDevice\n ? \"block\"\n : \"hidden group-hover:block\"\n }`}\n data-column-menu\n >\n <button\n className=\"p-1 hover:bg-gray-200 dark:hover:bg-gray-700 rounded shrink-0\"\n onClick={(e) => handleColumnMenuClick(column.key, e)}\n data-menu-trigger\n >\n <Menu className=\"w-4 h-4 text-gray-500 dark:text-gray-400\" />\n </button>\n\n {/* Dropdown Menu with Tabs */}\n {activeColumnMenu === column.key && menuPosition && (\n <div\n className=\"fixed bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-md shadow-lg z-10 w-[320px] overflow-auto\"\n style={{\n top: `${menuPosition.top}px`,\n left: `${menuPosition.left}px`,\n // Ensure the menu height never exceeds available space within the grid container\n maxHeight: `${Math.max(\n 160,\n menuPosition.containerRect.bottom -\n 12 -\n menuPosition.top\n )}px`,\n }}\n data-column-menu\n >\n {/* Tabs */}\n <div className=\"flex items-center border-b border-gray-200 dark:border-gray-700\">\n <button\n className={`px-3 py-2 text-sm flex items-center gap-2 ${\n activeTab === \"menu\"\n ? \"border-b-2 border-blue-600 text-blue-600\"\n : \"text-gray-600\"\n }`}\n onClick={() => setActiveTab(\"menu\")}\n >\n <Menu className=\"w-4 h-4\" />\n </button>\n {column.filterable && (\n <button\n className={`px-3 py-2 text-sm flex items-center gap-2 ${\n activeTab === \"filter\"\n ? \"border-b-2 border-blue-600 text-blue-600\"\n : \"text-gray-600\"\n }`}\n onClick={() => setActiveTab(\"filter\")}\n >\n <Filter className=\"w-4 h-4\" />\n </button>\n )}\n <button\n className={`px-3 py-2 text-sm flex items-center gap-2 ${\n activeTab === \"reorder\"\n ? \"border-b-2 border-blue-600 text-blue-600\"\n : \"text-gray-600\"\n }`}\n onClick={() => setActiveTab(\"reorder\")}\n >\n <ArrowUpDown className=\"w-4 h-4\" />\n </button>\n </div>\n {/* Tab Content (reusing existing code paths) */}\n {activeTab === \"menu\" && (\n <div className=\"py-1\">\n {onColumnPin && (\n <button\n className=\"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 flex items-center gap-2\"\n onClick={(e) => {\n e.stopPropagation();\n setActiveColumnMenu(null);\n const nextPinned = !pinnedKeySet.has(\n column.key\n );\n onColumnPin?.(column.key, nextPinned);\n }}\n >\n {pinnedKeySet.has(column.key) ? (\n <>\n <PinOff className=\"w-4 h-4\" />\n Unpin Column\n </>\n ) : (\n <>\n <Pin className=\"w-4 h-4\" />\n Pin Column\n </>\n )}\n </button>\n )}\n {onAutosizeColumn && (\n <button\n className=\"w-full px-3 py-2 text-left text-sm hover:bg-gray-50\"\n onClick={() => {\n onAutosizeColumn?.(column.key);\n setActiveColumnMenu(null);\n }}\n >\n Autosize This Column\n </button>\n )}\n {onAutosizeAllColumns && (\n <button\n className=\"w-full px-3 py-2 text-left text-sm hover:bg-gray-50\"\n onClick={() => {\n onAutosizeAllColumns?.();\n setActiveColumnMenu(null);\n }}\n >\n Autosize All Columns\n </button>\n )}\n\n {groupable && (\n <button\n className=\"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 flex items-center gap-2\"\n onClick={(e) => {\n e.stopPropagation();\n setActiveColumnMenu(null);\n const isGrouped =\n groupedByColumns?.includes(\n column.key\n ) || groupedByColumn === column.key;\n if (onGroupToggle)\n onGroupToggle(column.key, !isGrouped);\n else\n onGroupBy?.(\n isGrouped ? null : column.key\n );\n }}\n >\n {groupedByColumn === column.key ||\n groupedByColumns?.includes(column.key) ? (\n <>\n <Ungroup className=\"w-4 h-4\" />\n Ungroup\n </>\n ) : (\n <>\n <Group className=\"w-4 h-4\" />\n Group by {column.header}\n </>\n )}\n </button>\n )}\n\n {onResetColumns && (\n <button\n className=\"w-full px-3 py-2 text-left text-sm hover:bg-gray-50\"\n onClick={() => {\n onResetColumns?.();\n setActiveColumnMenu(null);\n }}\n >\n Reset Columns\n </button>\n )}\n </div>\n )}\n {activeTab === \"filter\" && (\n <div className=\"p-3 w-full\">\n <div className=\"max-h-75 overflow-auto pr-1\">\n <FilterContent\n column={column}\n data={data}\n value={tempFilter}\n onChange={(val) => {\n setTempFilter(val);\n // Auto-apply for client-side or no pagination\n if (paginationMode !== \"server\") {\n onColumnFilter(column.key, val);\n }\n }}\n />\n </div>\n <div className=\"flex justify-end gap-2 mt-3\">\n {hasActiveFilter(column.key) && (\n <button\n className=\"px-3 py-1.5 text-sm bg-red-500 text-white rounded-md hover:bg-red-600 flex items-center gap-2 cursor-pointer\"\n onClick={() => {\n setTempFilter(null);\n onColumnFilter(column.key, null);\n setActiveColumnMenu(null);\n }}\n >\n <FilterX className=\"w-3 h-3\" /> Clear\n Filter\n </button>\n )}\n <button\n className=\"px-3 py-1.5 text-sm bg-green-100 text-green-700 rounded-md hover:bg-green-200 cursor-pointer\"\n onClick={() => setActiveColumnMenu(null)}\n >\n Apply\n </button>\n {paginationMode === \"server\" && (\n <button\n className=\"px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700\"\n onClick={() =>\n handleApplyFilter(column.key)\n }\n >\n Apply\n </button>\n )}\n </div>\n </div>\n )}\n {activeTab === \"reorder\" && (\n <div className=\"px-3 py-2\">\n <div className=\"text-xs font-medium text-gray-500 mb-1\">\n Reorder Columns\n </div>\n <div className=\"max-h-60 overflow-auto border border-gray-200 rounded-md\">\n {(() => {\n const ordered = [\n ...columnOrder\n .map((k) =>\n allColumns.find((c) => c.key === k)\n )\n .filter(Boolean),\n ...allColumns.filter(\n (c) => !columnOrder.includes(c.key)\n ),\n ] as GridColumn[];\n\n return ordered.map((c) => {\n const isPinnedItem = pinnedKeySet.has(\n c.key\n );\n return (\n <div\n key={c.key}\n className={`flex items-center justify-between px-2 py-1 text-sm bg-white hover:bg-gray-50 border-b last:border-b-0 relative ${\n menuReorderDraggingKey === c.key\n ? \"opacity-60\"\n : \"\"\n } ${\n isPinnedItem ? \"bg-blue-50/40\" : \"\"\n }`}\n draggable\n onDragStart={(e) =>\n handleMenuReorderDragStart(c.key, e)\n }\n onDragOver={(e) =>\n handleMenuReorderDragOver(c.key, e)\n }\n onDrop={() =>\n handleMenuReorderDrop(c.key)\n }\n onDragEnd={handleMenuReorderDragEnd}\n >\n {menuReorderDragOver?.key ===\n c.key && (\n <div\n className=\"absolute left-0 right-0 h-0.5 bg-blue-600\"\n style={{\n top:\n menuReorderDragOver?.position ===\n \"before\"\n ? 0\n : undefined,\n bottom:\n menuReorderDragOver?.position ===\n \"after\"\n ? 0\n : undefined,\n }}\n />\n )}\n <div className=\"flex items-center gap-2\">\n <span className=\"text-gray-400 select-none\">\n ⋮⋮\n </span>\n <span className=\"text-gray-800 truncate max-w-45\">\n {c.header}\n {isPinnedItem && (\n <span className=\"ml-1 text-[10px] text-blue-600\">\n (pinned)\n </span>\n )}\n </span>\n </div>\n </div>\n );\n });\n })()}\n </div>\n <div className=\"text-[10px] text-gray-400 mt-1\">\n Tip: You can only reorder within pinned or\n unpinned groups.\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n\n {/* Resize handle */}\n {index < unpinnedColumns.length - 1 && onColumnResize && (\n <div\n className=\"absolute top-0 right-0 w-1 h-full cursor-col-resize hover:bg-blue-300 transition-colors group\"\n onMouseDown={(e) => handleResizeStart(column.key, e)}\n onDoubleClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n onAutosizeColumn?.(column.key);\n }}\n title=\"Drag to resize • Double‑click to autosize\"\n >\n <div className=\"w-full h-full group-hover:bg-blue-400\" />\n </div>\n )}\n </div>\n );\n })}\n\n {/* Spacer after last visible unpinned col */}\n {hvPadRight > 0 && (\n <div\n style={{ width: hvPadRight, height: headerHeight }}\n className=\"flex-none\"\n />\n )}\n </div>\n </div>\n\n {/* Inline filter handled in dropdown tabs */}\n </>\n );\n};\n"],"names":["GridHeader","pinnedColumns","unpinnedColumns","hvPadLeft","hvPadRight","headerHeight","sortConfig","columnFilters","selectable","selectedRows","totalRows","data","onSort","onColumnFilter","onSelectAll","onColumnResize","pinnedKeySet","Set","onColumnPin","groupable","groupedByColumn","onGroupBy","groupedByColumns","onGroupToggle","onAutosizeColumn","onAutosizeAllColumns","onResetColumns","columnOrder","onColumnOrderChange","paginationMode","allColumns","activeColumnMenu","setActiveColumnMenu","useState","menuPosition","setMenuPosition","isResizing","setIsResizing","startX","setStartX","startWidth","setStartWidth","activeTab","setActiveTab","tempFilter","setTempFilter","isTouchDevice","setIsTouchDevice","useEffect","window","navigator","maxTouchPoints","matchMedia","matches","menuReorderDraggingKey","setMenuReorderDraggingKey","menuReorderDragOver","setMenuReorderDragOver","isAllSelected","size","isIndeterminate","handleColumnMenuClick","columnKey","event","stopPropagation","rect","currentTarget","getBoundingClientRect","containerEl","closest","containerRect","DOMRect","innerWidth","innerHeight","MENU_WIDTH","PADDING","minLeft","left","maxLeft","right","clampedLeft","Math","max","min","top","bottom","handleApplyFilter","hasActiveFilter","handleResizeStart","preventDefault","clientX","column","find","col","key","width","handleResizeMove","deltaX","newWidth","handleResizeEnd","draggingKey","setDraggingKey","dragOver","setDragOver","handleDragStart","e","dataTransfer","effectAllowed","setData","handleDragOver","targetKey","dropEffect","midpoint","position","handleDrop","sourceKey","has","before","base","filter","k","idx","indexOf","splice","handleDragEnd","handleMenuReorderDragStart","handleMenuReorderDragOver","height","clientY","handleMenuReorderDrop","handleMenuReorderDragEnd","document","addEventListener","body","style","cursor","userSelect","removeEventListener","handleClickOutside","target","_jsx","_Fragment","children","className","role","_jsxs","SELECT_COL_WIDTH","type","checked","ref","el","indeterminate","onChange","onKeyDown","title","map","index","isPinned","pinnedKeysInOrder","c","pinnedIndex","leftOffset","slice","reduce","sum","headerJustify","headerAlign","colSortable","sortable","draggable","onDragStart","onDragOver","onDrop","onDragEnd","undefined","onClick","header","direction","ArrowUp","ArrowDown","filterable","Menu","maxHeight","Filter","ArrowUpDown","Pin","PinOff","isGrouped","includes","Ungroup","Group","FilterX","FilterContent","value","val","Boolean","isPinnedItem","length","onMouseDown","onDoubleClick","nextPinned"],"mappings":"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"}
@@ -1,49 +0,0 @@
1
- import { CSSProperties, MouseEvent } from "react";
2
- import { GridRow, GridColumn, VirtualizedRange } from "../types";
3
- interface GridRowsProps {
4
- data: GridRow[];
5
- columns: GridColumn[];
6
- selectedRows: Set<string | number>;
7
- virtualized: boolean;
8
- virtualizedRange: VirtualizedRange;
9
- rowHeight: number;
10
- selectable: boolean;
11
- isRowSelectable?: (row: GridRow) => boolean;
12
- onRowSelect: (rowId: string | number, isSelected: boolean) => void;
13
- pinnedColumns?: Set<string>;
14
- hvPadLeft?: number;
15
- hvPadRight?: number;
16
- rowStyle?: (row: GridRow) => CSSProperties | undefined;
17
- globalFilter?: string;
18
- onContextMenu?: (row: GridRow, event: MouseEvent) => void;
19
- onRowDoubleClick?: (row: GridRow, event: MouseEvent) => void;
20
- onRowClick?: (row: GridRow, event: MouseEvent) => void;
21
- onCellClick?: (args: {
22
- row: GridRow;
23
- column: GridColumn;
24
- value: any;
25
- event: MouseEvent;
26
- }) => void;
27
- isCellFocused?: (rowId: string | number, columnKey: string) => boolean;
28
- isCellSelected?: (rowId: string | number, columnKey: string) => boolean;
29
- onCellContextMenu?: (args: {
30
- row: GridRow;
31
- column: GridColumn;
32
- value: any;
33
- displayValue: string;
34
- event: MouseEvent;
35
- }) => void;
36
- onCellMouseDown?: (args: {
37
- row: GridRow;
38
- column: GridColumn;
39
- event: MouseEvent;
40
- }) => void;
41
- onCellMouseEnter?: (args: {
42
- row: GridRow;
43
- column: GridColumn;
44
- event: MouseEvent;
45
- }) => void;
46
- getRowId?: (row: GridRow) => string | number;
47
- }
48
- export declare const GridRows: import("react").MemoExoticComponent<({ data, columns, selectedRows, virtualized, virtualizedRange, rowHeight, selectable, isRowSelectable, onRowSelect, pinnedColumns, hvPadLeft, hvPadRight, rowStyle, globalFilter, onContextMenu, onRowDoubleClick, onRowClick, onCellClick, isCellFocused, isCellSelected, onCellContextMenu, onCellMouseDown, onCellMouseEnter, getRowId, }: GridRowsProps) => import("react/jsx-runtime").JSX.Element>;
49
- export {};
@@ -1,2 +0,0 @@
1
- import{jsx as e,jsxs as t,Fragment as r}from"react/jsx-runtime";import{memo as n,useMemo as o}from"react";import{SELECT_COL_WIDTH as l}from"../constants.js";import{containsSearchQuery as i,highlightText as a}from"../utils/highlightText.js";const d=n(({data:n,columns:d,selectedRows:s,virtualized:u,virtualizedRange:c,rowHeight:g,selectable:f,isRowSelectable:y,onRowSelect:h,pinnedColumns:b=new Set,hvPadLeft:p=0,hvPadRight:w=0,rowStyle:m,globalFilter:v,onContextMenu:k,onRowDoubleClick:x,onRowClick:C,onCellClick:R,isCellFocused:z,isCellSelected:$,onCellContextMenu:I,onCellMouseDown:M,onCellMouseEnter:S,getRowId:D})=>{const N=o(()=>n.length*g,[n.length,g]),{leftOffsetByPinnedKey:j}=o(()=>{if(0===b.size)return{leftOffsetByPinnedKey:new Map};const e=d.filter(e=>b.has(e.key)).map(e=>e.key),t=new Map;for(const e of d)t.set(e.key,e.width||100);const r=new Map;let n=f?l:0;for(const o of e)r.set(o,n),n+=t.get(o)||100;return{leftOffsetByPinnedKey:r}},[d,b,f]),E=o(()=>d.reduce((e,t)=>e+(b.has(t.key)?1:0),0),[d,b]);return e("div",{style:{height:u?`${N}px`:"auto",position:"relative"},children:e("div",{style:{transform:u?`translate3d(0, ${c.offsetY}px, 0)`:"none",position:u?"absolute":"static",top:0,left:0,right:0},children:n.map((n,o)=>{const N=u?c.startIndex+o:o,P=m?.(n),F=((e,t)=>D?D(e):void 0!==e.id?e.id:("development"===process.env.NODE_ENV&&0===t&&console.warn("[CustomDataGrid] No row IDs found. Either:\n 1. Add 'id' property to each row object, or\n 2. Provide 'getRowId' prop to extract a unique identifier.\n Using row index as fallback ID, but this may cause issues with pagination/filtering."),t??0))(n,N),H=N%2==0?"bg-white dark:bg-gray-900":"bg-gray-25 dark:bg-gray-800",K=s.has(F)?"bg-blue-50 dark:bg-blue-900/20":"";return t("div",{className:`flex border-b border-gray-100 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 ${K||(P?"":H)}`,style:{height:`${g}px`,...P},onContextMenu:e=>((e,t)=>{e.preventDefault(),k?.(t,e)})(e,n),onDoubleClick:e=>((e,t)=>{x?.(t,e)})(e,n),onClick:e=>((e,t)=>{C?.(t,e)})(e,n),children:[f&&e("div",{className:"flex items-center justify-center sticky left-0 bg-white dark:bg-gray-900 z-2 border-r border-gray-200 dark:border-gray-700",style:{width:l},children:e("input",{type:"checkbox",checked:s.has(F),disabled:!!y&&!y(n),onChange:e=>h(F,e.target.checked),onKeyDown:e=>{" "!==e.key&&"Enter"!==e.key||(e.preventDefault(),h(F,!s.has(F)))},className:"rounded border-gray-300 dark:border-gray-600 text-blue-600 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 h-4 w-4 transition-all duration-150","aria-label":`Select row ${F}`,tabIndex:0})}),d.map((o,l)=>{const d=b.has(o.key),s=d&&j.get(o.key)||0,u=n[o.key];let c,g;if(o.cellRenderer?(c=o.cellRenderer(u,n),"string"!=typeof u&&"number"!=typeof u&&"boolean"!=typeof u||(g=String(u))):o.formatter?(c=o.formatter(u),g=String(c)):(c=u??"",g=c?String(c):void 0),v&&v.trim()&&!o.cellRenderer&&c){const e=String(c);i(e,v)&&(c=a(e,v))}g&&0===g.trim().length&&(g=void 0);const f="center"===o.align?"text-center":"right"===o.align?"text-right":"text-left",y="center"===o.align?"justify-center":"right"===o.align?"justify-end":"justify-start",h=o.noPadding?"p-0":"p-3",w="function"==typeof o.className?o.className(u,n):o.className||"",m="function"==typeof o.cellStyle?o.cellStyle(u,n):o.cellStyle||void 0,k=t("div",{className:`border-r border-gray-200 last:border-r-0 ${h} text-sm flex items-center ${$?.(F,o.key)?"bg-blue-100/60 dark:bg-blue-900/30":""} ${d?z?.(F,o.key)?"sticky z-2 bg-inherit":"sticky z-1 bg-inherit":""} ${z?.(F,o.key)?"relative":""} ${f} ${y} ${w}`,style:{width:`${o.width||100}px`,left:d?`${s}px`:"auto",...m},title:g,onClick:e=>((e,t,r,n)=>{R?.({row:t,column:r,value:n,event:e})})(e,n,o,n[o.key]),onContextMenu:e=>{n._isGroupHeader||n._isGroupFooter||I&&(e.preventDefault(),e.stopPropagation(),I({row:n,column:o,value:n[o.key],displayValue:g??"",event:e}))},onMouseDown:e=>M?.({row:n,column:o,event:e}),onMouseEnter:e=>S?.({row:n,column:o,event:e}),children:[z?.(F,o.key)&&e("div",{className:"pointer-events-none absolute inset-0 border border-blue-400"}),!1===o.wrapCellContent?e(r,{children:c}):e("div",{className:"truncate w-full",children:c})]},`${o.key}-${l}`);return p>0&&l===E?t(r,{children:[e("div",{style:{width:p},className:"flex-none"}),k]}):k}),w>0&&e("div",{style:{width:w},className:"flex-none"})]},`${F}-${N}`)})})})},(e,t)=>{if(e.rowHeight!==t.rowHeight)return!1;if(e.selectable!==t.selectable)return!1;if(e.virtualized!==t.virtualized)return!1;if(e.globalFilter!==t.globalFilter)return!1;if(e.virtualizedRange.startIndex!==t.virtualizedRange.startIndex)return!1;if(e.virtualizedRange.endIndex!==t.virtualizedRange.endIndex)return!1;if(e.virtualizedRange.offsetY!==t.virtualizedRange.offsetY)return!1;if(e.isCellSelected!==t.isCellSelected)return!1;if(e.isCellFocused!==t.isCellFocused)return!1;if(e.onCellMouseDown!==t.onCellMouseDown)return!1;if(e.onCellMouseEnter!==t.onCellMouseEnter)return!1;if(e.getRowId!==t.getRowId)return!1;if(e.selectedRows.size!==t.selectedRows.size)return!1;if(e.pinnedColumns?.size!==t.pinnedColumns?.size)return!1;if(e.columns.map(e=>e.key).join("|")!==t.columns.map(e=>e.key).join("|"))return!1;if(e.data.length!==t.data.length)return!1;const r=(e,t,r)=>r?r(e):void 0!==e.id?e.id:t,n=e.data.length>0?r(e.data[0],0,e.getRowId):void 0,o=t.data.length>0?r(t.data[0],0,t.getRowId):void 0,l=e.data.length-1,i=t.data.length-1,a=e.data.length>0?r(e.data[l],l,e.getRowId):void 0,d=t.data.length>0?r(t.data[i],i,t.getRowId):void 0;return n===o&&a===d});export{d as GridRows};
2
- //# sourceMappingURL=GridRows.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"GridRows.js","sources":["../../../../../components/GridRows.tsx"],"sourcesContent":["import { CSSProperties, MouseEvent, memo, useMemo } from \"react\";\nimport { GridRow, GridColumn, VirtualizedRange } from \"../types\";\nimport { SELECT_COL_WIDTH } from \"../constants\";\nimport { highlightText, containsSearchQuery } from \"../utils/highlightText\";\n\ninterface GridRowsProps {\n data: GridRow[];\n columns: GridColumn[];\n selectedRows: Set<string | number>;\n virtualized: boolean;\n virtualizedRange: VirtualizedRange;\n rowHeight: number;\n selectable: boolean;\n isRowSelectable?: (row: GridRow) => boolean;\n onRowSelect: (rowId: string | number, isSelected: boolean) => void;\n pinnedColumns?: Set<string>;\n hvPadLeft?: number;\n hvPadRight?: number;\n rowStyle?: (row: GridRow) => CSSProperties | undefined;\n globalFilter?: string;\n onContextMenu?: (row: GridRow, event: MouseEvent) => void;\n onRowDoubleClick?: (row: GridRow, event: MouseEvent) => void;\n onRowClick?: (row: GridRow, event: MouseEvent) => void;\n onCellClick?: (args: {\n row: GridRow;\n column: GridColumn;\n value: any;\n event: MouseEvent;\n }) => void;\n // Cell focus & selection\n isCellFocused?: (rowId: string | number, columnKey: string) => boolean;\n isCellSelected?: (rowId: string | number, columnKey: string) => boolean;\n // Cell-level context menu (right-click)\n onCellContextMenu?: (args: {\n row: GridRow;\n column: GridColumn;\n value: any;\n displayValue: string;\n event: MouseEvent;\n }) => void;\n onCellMouseDown?: (args: {\n row: GridRow;\n column: GridColumn;\n event: MouseEvent;\n }) => void;\n onCellMouseEnter?: (args: {\n row: GridRow;\n column: GridColumn;\n event: MouseEvent;\n }) => void;\n getRowId?: (row: GridRow) => string | number;\n}\n\nconst GridRowsComponent = ({\n data,\n columns,\n selectedRows,\n virtualized,\n virtualizedRange,\n rowHeight,\n selectable,\n isRowSelectable,\n onRowSelect,\n pinnedColumns = new Set(),\n hvPadLeft = 0,\n hvPadRight = 0,\n rowStyle,\n globalFilter,\n onContextMenu,\n onRowDoubleClick,\n onRowClick,\n onCellClick,\n isCellFocused,\n isCellSelected,\n onCellContextMenu,\n onCellMouseDown,\n onCellMouseEnter,\n getRowId,\n}: GridRowsProps) => {\n // Helper to extract row ID\n const extractRowId = (row: GridRow, rowIndex?: number): string | number => {\n if (getRowId) {\n return getRowId(row);\n }\n if (row.id !== undefined) {\n return row.id;\n }\n // Fallback: use row index\n if (process.env.NODE_ENV === \"development\" && rowIndex === 0) {\n console.warn(\n \"[CustomDataGrid] No row IDs found. Either:\\n\" +\n \" 1. Add 'id' property to each row object, or\\n\" +\n \" 2. Provide 'getRowId' prop to extract a unique identifier.\\n\" +\n \" Using row index as fallback ID, but this may cause issues with pagination/filtering.\",\n );\n }\n return rowIndex ?? 0;\n };\n const totalHeight = useMemo(\n () => data.length * rowHeight,\n [data.length, rowHeight],\n );\n\n // Precompute pinned metadata for left offsets efficiently - OPTIMIZED\n const { leftOffsetByPinnedKey } = useMemo(() => {\n // Early return if no pinned columns\n if (pinnedColumns.size === 0) {\n return { leftOffsetByPinnedKey: new Map<string, number>() };\n }\n\n const pinnedKeysInOrder = columns\n .filter((c) => pinnedColumns.has(c.key))\n .map((c) => c.key);\n\n // Use direct property access instead of Map for better performance\n const widthByKey = new Map<string, number>();\n for (const col of columns) {\n widthByKey.set(col.key, col.width || 100);\n }\n\n const leftOffsetByPinnedKey = new Map<string, number>();\n let acc = selectable ? SELECT_COL_WIDTH : 0;\n\n for (const key of pinnedKeysInOrder) {\n leftOffsetByPinnedKey.set(key, acc);\n acc += widthByKey.get(key) || 100;\n }\n\n return { leftOffsetByPinnedKey };\n }, [columns, pinnedColumns, selectable]);\n\n // Count how many columns are pinned in the provided visible columns list\n const pinnedCount = useMemo(\n () => columns.reduce((n, c) => n + (pinnedColumns.has(c.key) ? 1 : 0), 0),\n [columns, pinnedColumns],\n );\n\n const handleContextMenu = (e: MouseEvent, row: GridRow) => {\n e.preventDefault();\n onContextMenu?.(row, e);\n };\n\n const handleDoubleClick = (e: MouseEvent, row: GridRow) => {\n onRowDoubleClick?.(row, e);\n };\n\n const handleRowClick = (e: MouseEvent, row: GridRow) => {\n onRowClick?.(row, e);\n };\n\n const handleCellClick = (\n e: MouseEvent,\n row: GridRow,\n column: GridColumn,\n value: any,\n ) => {\n onCellClick?.({ row, column, value, event: e });\n };\n\n return (\n <div\n style={{\n height: virtualized ? `${totalHeight}px` : \"auto\",\n position: \"relative\",\n }}\n >\n <div\n style={{\n transform: virtualized\n ? `translate3d(0, ${virtualizedRange.offsetY}px, 0)`\n : \"none\",\n position: virtualized ? \"absolute\" : \"static\",\n top: 0,\n left: 0,\n right: 0,\n }}\n >\n {data.map((row, index) => {\n const actualIndex = virtualized\n ? virtualizedRange.startIndex + index\n : index;\n const customRowStyles = rowStyle?.(row);\n const rowId = extractRowId(row, actualIndex);\n const defaultRowColor =\n actualIndex % 2 === 0\n ? \"bg-white dark:bg-gray-900\"\n : \"bg-gray-25 dark:bg-gray-800\";\n const selectedRowColor = selectedRows.has(rowId)\n ? \"bg-blue-50 dark:bg-blue-900/20\"\n : \"\";\n\n return (\n <div\n key={`${rowId}-${actualIndex}`}\n className={`flex border-b border-gray-100 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 ${\n selectedRowColor || (customRowStyles ? \"\" : defaultRowColor)\n }`}\n style={{\n height: `${rowHeight}px`,\n ...customRowStyles,\n }}\n onContextMenu={(e) => handleContextMenu(e, row)}\n onDoubleClick={(e) => handleDoubleClick(e, row)}\n onClick={(e) => handleRowClick(e, row)}\n >\n {selectable && (\n <div\n className=\"flex items-center justify-center sticky left-0 bg-white dark:bg-gray-900 z-2 border-r border-gray-200 dark:border-gray-700\"\n style={{ width: SELECT_COL_WIDTH }}\n >\n <input\n type=\"checkbox\"\n checked={selectedRows.has(rowId)}\n disabled={isRowSelectable ? !isRowSelectable(row) : false}\n onChange={(e) => onRowSelect(rowId, e.target.checked)}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n onRowSelect(rowId, !selectedRows.has(rowId));\n }\n }}\n className=\"rounded border-gray-300 dark:border-gray-600 text-blue-600 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 h-4 w-4 transition-all duration-150\"\n aria-label={`Select row ${rowId}`}\n tabIndex={0}\n />\n </div>\n )}\n\n {columns.map((column, colIndex) => {\n const isPinned = pinnedColumns.has(column.key);\n const leftOffset = isPinned\n ? leftOffsetByPinnedKey.get(column.key) || 0\n : 0;\n\n // Optimized cell value processing\n const rawCell = row[column.key];\n let renderedValue: React.ReactNode;\n let displayValue: string | undefined;\n\n // Optimize cell renderer calls\n if (column.cellRenderer) {\n renderedValue = column.cellRenderer(rawCell, row);\n // Only compute display value if needed for tooltip\n if (\n typeof rawCell === \"string\" ||\n typeof rawCell === \"number\" ||\n typeof rawCell === \"boolean\"\n ) {\n displayValue = String(rawCell);\n }\n } else if (column.formatter) {\n renderedValue = column.formatter(rawCell);\n displayValue = String(renderedValue);\n } else {\n renderedValue = rawCell ?? \"\";\n displayValue = renderedValue\n ? String(renderedValue)\n : undefined;\n }\n\n // Apply highlighting for global filter if present and no custom renderer\n if (\n globalFilter &&\n globalFilter.trim() &&\n !column.cellRenderer &&\n renderedValue\n ) {\n const textValue = String(renderedValue);\n if (containsSearchQuery(textValue, globalFilter)) {\n renderedValue = highlightText(textValue, globalFilter);\n }\n }\n\n // Clean up empty display values\n if (displayValue && displayValue.trim().length === 0) {\n displayValue = undefined;\n }\n\n // Pre-compute CSS classes for better performance\n const alignClass =\n column.align === \"center\"\n ? \"text-center\"\n : column.align === \"right\"\n ? \"text-right\"\n : \"text-left\";\n const justifyClass =\n column.align === \"center\"\n ? \"justify-center\"\n : column.align === \"right\"\n ? \"justify-end\"\n : \"justify-start\";\n const paddingClass = column.noPadding ? \"p-0\" : \"p-3\";\n\n // Optimize dynamic class/style computation\n const extraCellClass =\n typeof column.className === \"function\"\n ? column.className(rawCell, row)\n : column.className || \"\";\n const extraCellStyle =\n typeof column.cellStyle === \"function\"\n ? column.cellStyle(rawCell, row)\n : column.cellStyle || undefined;\n\n const cell = (\n <div\n key={`${column.key}-${colIndex}`}\n className={`border-r border-gray-200 last:border-r-0 ${paddingClass} text-sm flex items-center ${\n isCellSelected?.(rowId, column.key)\n ? \"bg-blue-100/60 dark:bg-blue-900/30\"\n : \"\"\n } ${\n isPinned\n ? isCellFocused?.(rowId, column.key)\n ? \"sticky z-2 bg-inherit\"\n : \"sticky z-1 bg-inherit\"\n : \"\"\n } ${\n isCellFocused?.(rowId, column.key) ? \"relative\" : \"\"\n } ${alignClass} ${justifyClass} ${extraCellClass}`}\n style={{\n width: `${column.width || 100}px`,\n left: isPinned ? `${leftOffset}px` : \"auto\",\n ...extraCellStyle,\n }}\n // Show native tooltip only when a meaningful value exists (non-empty string after trimming)\n title={displayValue}\n onClick={(e) =>\n handleCellClick(e, row, column, row[column.key])\n }\n onContextMenu={(e) => {\n // Only handle for real data rows\n if (\n (row as any)._isGroupHeader ||\n (row as any)._isGroupFooter\n )\n return;\n if (onCellContextMenu) {\n e.preventDefault();\n e.stopPropagation();\n onCellContextMenu({\n row,\n column,\n value: (row as any)[column.key],\n displayValue: displayValue ?? \"\",\n event: e as any,\n });\n }\n // If no onCellContextMenu prop, fall back to row-level handler (do not stop propagation)\n }}\n onMouseDown={(e) =>\n onCellMouseDown?.({ row, column, event: e })\n }\n onMouseEnter={(e) =>\n onCellMouseEnter?.({ row, column, event: e })\n }\n >\n {isCellFocused?.(rowId, column.key) && (\n <div className=\"pointer-events-none absolute inset-0 border border-blue-400\" />\n )}\n {column.wrapCellContent === false ? (\n <>{renderedValue}</>\n ) : (\n <div className=\"truncate w-full\">{renderedValue}</div>\n )}\n </div>\n );\n // Insert left spacer once before the first unpinned visible column\n if (hvPadLeft > 0 && colIndex === pinnedCount) {\n return (\n <>\n <div style={{ width: hvPadLeft }} className=\"flex-none\" />\n {cell}\n </>\n );\n }\n\n return cell;\n })}\n {/* Spacer after last visible unpinned col */}\n {hvPadRight > 0 && (\n <div style={{ width: hvPadRight }} className=\"flex-none\" />\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n};\n\nconst areEqual = (prev: GridRowsProps, next: GridRowsProps) => {\n if (prev.rowHeight !== next.rowHeight) return false;\n if (prev.selectable !== next.selectable) return false;\n if (prev.virtualized !== next.virtualized) return false;\n if (prev.globalFilter !== next.globalFilter) return false;\n if (prev.virtualizedRange.startIndex !== next.virtualizedRange.startIndex)\n return false;\n if (prev.virtualizedRange.endIndex !== next.virtualizedRange.endIndex)\n return false;\n if (prev.virtualizedRange.offsetY !== next.virtualizedRange.offsetY)\n return false;\n // Re-render when focus/selection functions change identity (they depend on selection & focus states)\n if (prev.isCellSelected !== next.isCellSelected) return false;\n if (prev.isCellFocused !== next.isCellFocused) return false;\n // Re-render when drag-selection handlers change identity (closure depends on selectionAnchor/end)\n if (prev.onCellMouseDown !== next.onCellMouseDown) return false;\n if (prev.onCellMouseEnter !== next.onCellMouseEnter) return false;\n if (prev.getRowId !== next.getRowId) return false;\n if (prev.selectedRows.size !== next.selectedRows.size) return false;\n if (prev.pinnedColumns?.size !== next.pinnedColumns?.size) return false;\n const prevCols = prev.columns.map((c) => c.key).join(\"|\");\n const nextCols = next.columns.map((c) => c.key).join(\"|\");\n if (prevCols !== nextCols) return false;\n if (prev.data.length !== next.data.length) return false;\n\n // Helper to extract IDs for comparison\n const extractId = (\n row: GridRow,\n idx: number,\n getRowId?: (r: GridRow) => string | number,\n ) => {\n if (getRowId) {\n return getRowId(row);\n }\n if (row.id !== undefined) {\n return row.id;\n }\n return idx;\n };\n\n const prevFirst =\n prev.data.length > 0\n ? extractId(prev.data[0], 0, prev.getRowId)\n : undefined;\n const nextFirst =\n next.data.length > 0\n ? extractId(next.data[0], 0, next.getRowId)\n : undefined;\n const prevLastIdx = prev.data.length - 1;\n const nextLastIdx = next.data.length - 1;\n const prevLast =\n prev.data.length > 0\n ? extractId(prev.data[prevLastIdx], prevLastIdx, prev.getRowId)\n : undefined;\n const nextLast =\n next.data.length > 0\n ? extractId(next.data[nextLastIdx], nextLastIdx, next.getRowId)\n : undefined;\n if (prevFirst !== nextFirst || prevLast !== nextLast) return false;\n return true;\n};\n\nexport const GridRows = memo(GridRowsComponent, areEqual);\n"],"names":["GridRows","memo","data","columns","selectedRows","virtualized","virtualizedRange","rowHeight","selectable","isRowSelectable","onRowSelect","pinnedColumns","Set","hvPadLeft","hvPadRight","rowStyle","globalFilter","onContextMenu","onRowDoubleClick","onRowClick","onCellClick","isCellFocused","isCellSelected","onCellContextMenu","onCellMouseDown","onCellMouseEnter","getRowId","totalHeight","useMemo","length","leftOffsetByPinnedKey","size","Map","pinnedKeysInOrder","filter","c","has","key","map","widthByKey","col","set","width","acc","SELECT_COL_WIDTH","get","pinnedCount","reduce","n","_jsx","style","height","position","children","transform","offsetY","top","left","right","row","index","actualIndex","startIndex","customRowStyles","rowId","rowIndex","undefined","id","process","env","NODE_ENV","console","warn","extractRowId","defaultRowColor","selectedRowColor","_jsxs","className","e","preventDefault","handleContextMenu","onDoubleClick","handleDoubleClick","onClick","handleRowClick","type","checked","disabled","onChange","target","onKeyDown","tabIndex","column","colIndex","isPinned","leftOffset","rawCell","renderedValue","displayValue","cellRenderer","String","formatter","trim","textValue","containsSearchQuery","highlightText","alignClass","align","justifyClass","paddingClass","noPadding","extraCellClass","extraCellStyle","cellStyle","cell","title","value","event","handleCellClick","_isGroupHeader","_isGroupFooter","stopPropagation","onMouseDown","onMouseEnter","wrapCellContent","_Fragment","prev","next","endIndex","join","extractId","idx","prevFirst","nextFirst","prevLastIdx","nextLastIdx","prevLast","nextLast"],"mappings":"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"}
@@ -1,12 +0,0 @@
1
- import type { GridColumn } from "../types";
2
- interface GroupBarProps {
3
- columns: GridColumn[];
4
- groupedKeys: string[];
5
- onRemove: (columnKey: string) => void;
6
- onReorder: (newOrder: string[]) => void;
7
- onDropColumnKey: (columnKey: string) => void;
8
- onToggleExpandAll?: () => void;
9
- isAnyExpanded?: boolean;
10
- }
11
- export declare const GroupBar: ({ columns, groupedKeys, onRemove, onReorder, onDropColumnKey, onToggleExpandAll, isAnyExpanded, }: GroupBarProps) => import("react/jsx-runtime").JSX.Element;
12
- export {};
@@ -1,2 +0,0 @@
1
- import{jsxs as e,jsx as r}from"react/jsx-runtime";import{useState as t}from"react";const l=({columns:l,groupedKeys:a,onRemove:n,onReorder:o,onDropColumnKey:s,onToggleExpandAll:i,isAnyExpanded:p=!1})=>{const[d,u]=t(null),[c,g]=t(null),[m,x]=t(!0),b=e=>l.find(r=>r.key===e)?.header||e,f=e=>r=>{u(e),r.dataTransfer.effectAllowed="move",r.dataTransfer.setData("application/x-group-key",e)},v=e=>r=>{r.preventDefault();const t=r.currentTarget.getBoundingClientRect(),l=r.clientX<t.left+t.width/2;g(e),x(l)};return e("div",{className:"flex items-center gap-2 px-3 py-2 bg-gray-50 border-b border-gray-200 text-sm",onDrop:e=>{e.preventDefault();const r=e.dataTransfer.getData("text/plain");r&&(a.includes(r)||s(r))},onDragOver:e=>{e.preventDefault()},onDragEnd:()=>{u(null),g(null)},children:[r("span",{className:"text-gray-600 whitespace-nowrap",children:"Group by:"}),a.length>0&&r("button",{type:"button",className:"ml-1 px-2 py-1 text-xs border border-gray-300 rounded hover:bg-gray-100",title:p?"Collapse all groups":"Expand all groups",onClick:e=>{e.preventDefault(),e.stopPropagation(),i?.()},children:p?"Collapse All":"Expand All"}),0===a.length&&r("span",{className:"text-gray-400",children:"Drag a column here"}),r("div",{className:"flex items-center gap-2 flex-wrap",children:a.map(t=>{return e("div",{className:"inline-flex items-center gap-2 bg-blue-100 text-blue-800 px-2 py-1 rounded-md border border-blue-200 cursor-move relative",draggable:!0,onDragStart:f(t),onDragOver:v(t),onDrop:(l=t,()=>{if(!d||d===l)return u(null),void g(null);const e=a.filter(e=>e!==d),r=e.indexOf(l);-1!==r&&(m?e.splice(r,0,d):e.splice(r+1,0,d),o(e),u(null),g(null))}),title:b(t),children:[r("span",{className:"text-xs font-medium truncate max-w-[160px]",children:b(t)}),r("button",{className:"text-blue-700 hover:text-blue-900",onClick:()=>n(t),"aria-label":`Remove grouping ${b(t)}`,children:"×"}),c===t&&r("span",{className:"absolute top-0 bottom-0 w-0.5 bg-blue-600 dark:bg-blue-400 animate-pulse",style:{left:m?0:void 0,right:m?void 0:0},"aria-hidden":"true"})]},t);var l})})]})};export{l as GroupBar};
2
- //# sourceMappingURL=GroupBar.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"GroupBar.js","sources":["../../../../../components/GroupBar.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport type { GridColumn } from \"../types\";\n\ninterface GroupBarProps {\n columns: GridColumn[];\n groupedKeys: string[];\n onRemove: (columnKey: string) => void;\n onReorder: (newOrder: string[]) => void;\n onDropColumnKey: (columnKey: string) => void;\n onToggleExpandAll?: () => void;\n isAnyExpanded?: boolean;\n}\n\nexport const GroupBar = ({\n columns,\n groupedKeys,\n onRemove,\n onReorder,\n onDropColumnKey,\n onToggleExpandAll,\n isAnyExpanded = false,\n}: GroupBarProps) => {\n const [dragKey, setDragKey] = useState<string | null>(null);\n const [dragOverKey, setDragOverKey] = useState<string | null>(null);\n const [dragOverBefore, setDragOverBefore] = useState<boolean>(true);\n\n const labelFor = (key: string) => columns.find((c) => c.key === key)?.header || key;\n\n const handleDropFromHeader: React.DragEventHandler<HTMLDivElement> = (e) => {\n e.preventDefault();\n const key = e.dataTransfer.getData(\"text/plain\");\n if (!key) return;\n if (!groupedKeys.includes(key)) onDropColumnKey(key);\n };\n\n const onDragOverBar: React.DragEventHandler<HTMLDivElement> = (e) => {\n e.preventDefault();\n };\n\n const handleChipDragStart = (key: string): React.DragEventHandler<HTMLDivElement> => (e) => {\n setDragKey(key);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"application/x-group-key\", key);\n };\n\n const handleChipDragOver = (key: string): React.DragEventHandler<HTMLDivElement> => (e) => {\n e.preventDefault();\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const before = e.clientX < rect.left + rect.width / 2;\n setDragOverKey(key);\n setDragOverBefore(before);\n };\n\n const handleChipDrop = (targetKey: string): React.DragEventHandler<HTMLDivElement> => () => {\n if (!dragKey || dragKey === targetKey) {\n setDragKey(null);\n setDragOverKey(null);\n return;\n }\n const order = groupedKeys.filter((k) => k !== dragKey);\n const idx = order.indexOf(targetKey);\n if (idx === -1) return;\n if (!dragOverBefore) {\n order.splice(idx + 1, 0, dragKey);\n } else {\n order.splice(idx, 0, dragKey);\n }\n onReorder(order);\n setDragKey(null);\n setDragOverKey(null);\n };\n\n const clearDnD = () => {\n setDragKey(null);\n setDragOverKey(null);\n };\n\n return (\n <div\n className=\"flex items-center gap-2 px-3 py-2 bg-gray-50 border-b border-gray-200 text-sm\"\n onDrop={handleDropFromHeader}\n onDragOver={onDragOverBar}\n onDragEnd={clearDnD}\n >\n <span className=\"text-gray-600 whitespace-nowrap\">Group by:</span>\n {groupedKeys.length > 0 && (\n <button\n type=\"button\"\n className=\"ml-1 px-2 py-1 text-xs border border-gray-300 rounded hover:bg-gray-100\"\n title={isAnyExpanded ? \"Collapse all groups\" : \"Expand all groups\"}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n onToggleExpandAll?.();\n }}\n >\n {isAnyExpanded ? \"Collapse All\" : \"Expand All\"}\n </button>\n )}\n {groupedKeys.length === 0 && (\n <span className=\"text-gray-400\">Drag a column here</span>\n )}\n <div className=\"flex items-center gap-2 flex-wrap\">\n {groupedKeys.map((key) => (\n <div\n key={key}\n className=\"inline-flex items-center gap-2 bg-blue-100 text-blue-800 px-2 py-1 rounded-md border border-blue-200 cursor-move relative\"\n draggable\n onDragStart={handleChipDragStart(key)}\n onDragOver={handleChipDragOver(key)}\n onDrop={handleChipDrop(key)}\n title={labelFor(key)}\n >\n <span className=\"text-xs font-medium truncate max-w-[160px]\">{labelFor(key)}</span>\n <button\n className=\"text-blue-700 hover:text-blue-900\"\n onClick={() => onRemove(key)}\n aria-label={`Remove grouping ${labelFor(key)}`}\n >\n ×\n </button>\n {dragOverKey === key && (\n <span\n className=\"absolute top-0 bottom-0 w-0.5 bg-blue-600 dark:bg-blue-400 animate-pulse\"\n style={{ left: dragOverBefore ? 0 : undefined, right: dragOverBefore ? undefined : 0 }}\n aria-hidden=\"true\"\n />\n )}\n </div>\n ))}\n </div>\n </div>\n );\n};\n"],"names":["GroupBar","columns","groupedKeys","onRemove","onReorder","onDropColumnKey","onToggleExpandAll","isAnyExpanded","dragKey","setDragKey","useState","dragOverKey","setDragOverKey","dragOverBefore","setDragOverBefore","labelFor","key","find","c","header","handleChipDragStart","e","dataTransfer","effectAllowed","setData","handleChipDragOver","preventDefault","rect","currentTarget","getBoundingClientRect","before","clientX","left","width","_jsxs","className","onDrop","getData","includes","onDragOver","onDragEnd","children","_jsx","length","type","title","onClick","stopPropagation","map","draggable","onDragStart","targetKey","order","filter","k","idx","indexOf","splice","style","undefined","right"],"mappings":"yFAaaA,EAAW,EACtBC,UACAC,cACAC,WACAC,YACAC,kBACAC,oBACAC,iBAAgB,MAEhB,MAAOC,EAASC,GAAcC,EAAwB,OAC/CC,EAAaC,GAAkBF,EAAwB,OACvDG,EAAgBC,GAAqBJ,GAAkB,GAExDK,EAAYC,GAAgBf,EAAQgB,KAAMC,GAAMA,EAAEF,MAAQA,IAAMG,QAAUH,EAa1EI,EAAuBJ,GAAyDK,IACpFZ,EAAWO,GACXK,EAAEC,aAAaC,cAAgB,OAC/BF,EAAEC,aAAaE,QAAQ,0BAA2BR,IAG9CS,EAAsBT,GAAyDK,IACnFA,EAAEK,iBACF,MAAMC,EAAQN,EAAEO,cAAiCC,wBAC3CC,EAAST,EAAEU,QAAUJ,EAAKK,KAAOL,EAAKM,MAAQ,EACpDrB,EAAeI,GACfF,EAAkBgB,IA2BpB,OACEI,EACE,MAAA,CAAAC,UAAU,gFACVC,OApDkEf,IACpEA,EAAEK,iBACF,MAAMV,EAAMK,EAAEC,aAAae,QAAQ,cAC9BrB,IACAd,EAAYoC,SAAStB,IAAMX,EAAgBW,KAiD9CuB,WA9C2DlB,IAC7DA,EAAEK,kBA8CAc,UAVa,KACf/B,EAAW,MACXG,EAAe,OAQM6B,SAAA,CAEnBC,EAAM,OAAA,CAAAP,UAAU,kCAAkDM,SAAA,cACjEvC,EAAYyC,OAAS,GACpBD,EACE,SAAA,CAAAE,KAAK,SACLT,UAAU,0EACVU,MAAOtC,EAAgB,sBAAwB,oBAC/CuC,QAAUzB,IACRA,EAAEK,iBACFL,EAAE0B,kBACFzC,gBAGDC,EAAgB,eAAiB,eAGd,IAAvBL,EAAYyC,QACXD,UAAMP,UAAU,gBAAeM,SAAA,uBAEjCC,EAAA,MAAA,CAAKP,UAAU,oCACZM,SAAAvC,EAAY8C,IAAKhC,IAAG,OACnBkB,EAEE,MAAA,CAAAC,UAAU,4HACVc,WAAS,EACTC,YAAa9B,EAAoBJ,GACjCuB,WAAYd,EAAmBT,GAC/BoB,QAzDce,EAyDSnC,EAzDqD,KACpF,IAAKR,GAAWA,IAAY2C,EAG1B,OAFA1C,EAAW,WACXG,EAAe,MAGjB,MAAMwC,EAAQlD,EAAYmD,OAAQC,GAAMA,IAAM9C,GACxC+C,EAAMH,EAAMI,QAAQL,IACb,IAATI,IACC1C,EAGHuC,EAAMK,OAAOF,EAAK,EAAG/C,GAFrB4C,EAAMK,OAAOF,EAAM,EAAG,EAAG/C,GAI3BJ,EAAUgD,GACV3C,EAAW,MACXG,EAAe,SA0CPiC,MAAO9B,EAASC,GAAIyB,SAAA,CAEpBC,UAAMP,UAAU,6CAA4CM,SAAE1B,EAASC,KACvE0B,EACE,SAAA,CAAAP,UAAU,oCACVW,QAAS,IAAM3C,EAASa,gBACZ,mBAAmBD,EAASC,KAAMyB,SAAA,MAI/C9B,IAAgBK,GACf0B,EACE,OAAA,CAAAP,UAAU,2EACVuB,MAAO,CAAE1B,KAAMnB,EAAiB,OAAI8C,EAAWC,MAAO/C,OAAiB8C,EAAY,iBACvE,WApBX3C,GApDQ,IAACmC"}
@@ -1,29 +0,0 @@
1
- import { GridRow, CustomDataGridProps } from "../types";
2
- interface GroupHeaderProps {
3
- row: GridRow & {
4
- _isGroupHeader?: boolean;
5
- _groupKey?: string;
6
- _groupCount?: number;
7
- };
8
- isExpanded: boolean;
9
- onToggle: (groupKey: string) => void;
10
- viewportWidth: number;
11
- selectable: boolean;
12
- rowHeight?: number;
13
- /**
14
- * Optional function to map a column key to its display label (header).
15
- * If not provided, the raw column key will be used as a fallback.
16
- */
17
- getHeaderLabel?: (columnKey: string) => string;
18
- /**
19
- * Optional function to map a column key and raw group value to a display label.
20
- * Useful to apply the column's formatter for group headers.
21
- */
22
- getValueLabel?: (columnKey: string, rawValue: any) => string;
23
- /**
24
- * Optional custom renderer for actions on grouped rows.
25
- */
26
- renderGroupActions?: CustomDataGridProps["renderGroupActions"];
27
- }
28
- export declare const GroupHeader: import("react").MemoExoticComponent<({ row, isExpanded, onToggle, viewportWidth, selectable, rowHeight, getHeaderLabel, getValueLabel, renderGroupActions, }: GroupHeaderProps) => import("react/jsx-runtime").JSX.Element>;
29
- export {};
@@ -1,2 +0,0 @@
1
- import{jsxs as e,jsx as r}from"react/jsx-runtime";import{memo as o}from"react";import{ChevronDown as t,ChevronRight as l}from"lucide-react";import{SELECT_COL_WIDTH as n}from"../constants.js";const u=o(({row:o,isExpanded:u,onToggle:a,viewportWidth:p,selectable:i,rowHeight:s=40,getHeaderLabel:g,getValueLabel:c,renderGroupActions:m})=>{const d=()=>{o._groupKey&&a(o._groupKey)};return e("div",{className:"flex items-center bg-blue-50 dark:bg-blue-900/20 border-b border-gray-200 dark:border-gray-800 hover:bg-blue-100/70 cursor-pointer sticky left-0 z-20 overflow-hidden",style:{minWidth:`${p+(i?n:0)}px`,height:`${s}px`},onClick:d,role:"button",tabIndex:0,"aria-expanded":u,onKeyDown:e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),d())},children:[i&&r("div",{className:"w-12 flex items-center justify-center"}),e("div",{className:"flex items-center px-4 py-2 flex-1",children:[r("div",{className:"flex items-center mr-3",style:{paddingLeft:(o._groupLevel?16*o._groupLevel:0)+"px"},children:r(u?t:l,{className:"w-4 h-4 text-gray-600"})}),e("div",{className:"flex items-center gap-2",children:[e("span",{className:"font-medium text-gray-900",children:[o._groupColumnKey?`${g?g(o._groupColumnKey):o._groupColumnKey}: `:"",c&&o._groupColumnKey?c(o._groupColumnKey,o._groupValue):o._groupValue??(o._groupKey||"Unknown")]}),e("span",{className:"text-sm text-gray-600 bg-gray-200/70 px-2 py-1 rounded-full",children:[o._groupCount," ",1===o._groupCount?"item":"items"]})]}),m&&r("div",{className:"flex items-center px-4",onClick:e=>e.stopPropagation(),children:m({groupKey:o._groupKey||"",columnKey:o._groupColumnKey||"",groupValue:o._groupValue,rows:o._groupRows||[],count:o._groupCount||0,level:o._groupLevel||0})})]})]})});export{u as GroupHeader};
2
- //# sourceMappingURL=GroupHeader.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"GroupHeader.js","sources":["../../../../../components/GroupHeader.tsx"],"sourcesContent":["import { memo } from \"react\";\nimport { ChevronDown, ChevronRight } from \"lucide-react\";\nimport { GridRow, CustomDataGridProps } from \"../types\";\nimport { SELECT_COL_WIDTH } from \"../constants\";\n\ninterface GroupHeaderProps {\n row: GridRow & {\n _isGroupHeader?: boolean;\n _groupKey?: string;\n _groupCount?: number;\n };\n isExpanded: boolean;\n onToggle: (groupKey: string) => void;\n viewportWidth: number;\n selectable: boolean;\n rowHeight?: number;\n /**\n * Optional function to map a column key to its display label (header).\n * If not provided, the raw column key will be used as a fallback.\n */\n getHeaderLabel?: (columnKey: string) => string;\n /**\n * Optional function to map a column key and raw group value to a display label.\n * Useful to apply the column's formatter for group headers.\n */\n getValueLabel?: (columnKey: string, rawValue: any) => string;\n /**\n * Optional custom renderer for actions on grouped rows.\n */\n renderGroupActions?: CustomDataGridProps[\"renderGroupActions\"];\n}\n\nexport const GroupHeader = memo(\n ({\n row,\n isExpanded,\n onToggle,\n viewportWidth,\n selectable,\n rowHeight = 40,\n getHeaderLabel,\n getValueLabel,\n renderGroupActions,\n }: GroupHeaderProps) => {\n const handleToggle = () => {\n if (row._groupKey) {\n onToggle(row._groupKey);\n }\n };\n\n return (\n <div\n className=\"flex items-center bg-blue-50 dark:bg-blue-900/20 border-b border-gray-200 dark:border-gray-800 hover:bg-blue-100/70 cursor-pointer sticky left-0 z-20 overflow-hidden\"\n style={{\n minWidth: `${viewportWidth + (selectable ? SELECT_COL_WIDTH : 0)}px`,\n height: `${rowHeight}px`,\n }}\n onClick={handleToggle}\n role=\"button\"\n tabIndex={0}\n aria-expanded={isExpanded}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleToggle();\n }\n }}\n >\n {selectable && (\n <div className=\"w-12 flex items-center justify-center\">\n {/* Empty space for checkbox column */}\n </div>\n )}\n\n <div className=\"flex items-center px-4 py-2 flex-1\">\n <div\n className=\"flex items-center mr-3\"\n style={{\n paddingLeft: `${(row as any)._groupLevel ? ((row as any)._groupLevel as number) * 16 : 0}px`,\n }}\n >\n {isExpanded ? (\n <ChevronDown className=\"w-4 h-4 text-gray-600\" />\n ) : (\n <ChevronRight className=\"w-4 h-4 text-gray-600\" />\n )}\n </div>\n\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-gray-900\">\n {(row as any)._groupColumnKey\n ? `${getHeaderLabel ? getHeaderLabel((row as any)._groupColumnKey) : (row as any)._groupColumnKey}: `\n : \"\"}\n {getValueLabel && (row as any)._groupColumnKey\n ? getValueLabel(\n (row as any)._groupColumnKey,\n (row as any)._groupValue,\n )\n : ((row as any)._groupValue ?? (row._groupKey || \"Unknown\"))}\n </span>\n <span className=\"text-sm text-gray-600 bg-gray-200/70 px-2 py-1 rounded-full\">\n {row._groupCount} {row._groupCount === 1 ? \"item\" : \"items\"}\n </span>\n </div>\n\n {renderGroupActions && (\n <div\n className=\"flex items-center px-4\"\n onClick={(e) => e.stopPropagation()}\n >\n {renderGroupActions({\n groupKey: row._groupKey || \"\",\n columnKey: (row as any)._groupColumnKey || \"\",\n groupValue: (row as any)._groupValue,\n rows: (row as any)._groupRows || [],\n count: row._groupCount || 0,\n level: (row as any)._groupLevel || 0,\n })}\n </div>\n )}\n </div>\n </div>\n );\n },\n);\n"],"names":["GroupHeader","memo","row","isExpanded","onToggle","viewportWidth","selectable","rowHeight","getHeaderLabel","getValueLabel","renderGroupActions","handleToggle","_groupKey","_jsxs","className","style","minWidth","SELECT_COL_WIDTH","height","onClick","role","tabIndex","onKeyDown","e","key","preventDefault","children","_jsx","paddingLeft","_groupLevel","ChevronDown","ChevronRight","_groupColumnKey","_groupValue","_groupCount","stopPropagation","groupKey","columnKey","groupValue","rows","_groupRows","count","level"],"mappings":"+LAgCO,MAAMA,EAAcC,EACzB,EACEC,MACAC,aACAC,WACAC,gBACAC,aACAC,YAAY,GACZC,iBACAC,gBACAC,yBAEA,MAAMC,EAAe,KACfT,EAAIU,WACNR,EAASF,EAAIU,YAIjB,OACEC,EACE,MAAA,CAAAC,UAAU,wKACVC,MAAO,CACLC,SAAU,GAAGX,GAAiBC,EAAaW,EAAmB,OAC9DC,OAAQ,GAAGX,OAEbY,QAASR,EACTS,KAAK,SACLC,SAAU,EAAC,gBACIlB,EACfmB,UAAYC,IACI,UAAVA,EAAEC,KAA6B,MAAVD,EAAEC,MACzBD,EAAEE,iBACFd,MAEHe,SAAA,CAEApB,GACCqB,SAAKb,UAAU,0CAKjBD,SAAKC,UAAU,qCACbY,SAAA,CAAAC,EAAA,MAAA,CACEb,UAAU,yBACVC,MAAO,CACLa,aAAiB1B,EAAY2B,YAAqD,GAArC3B,EAAY2B,YAA8B,GAA1E,MACdH,SAGCC,EADDxB,EACE2B,EAEAC,EAFW,CAACjB,UAAU,4BAM3BD,SAAKC,UAAU,0BAAyBY,SAAA,CACtCb,UAAMC,UAAU,4BACZY,SAAA,CAAAxB,EAAY8B,gBACV,GAAGxB,EAAiBA,EAAgBN,EAAY8B,iBAAoB9B,EAAY8B,oBAChF,GACHvB,GAAkBP,EAAY8B,gBAC3BvB,EACGP,EAAY8B,gBACZ9B,EAAY+B,aAEb/B,EAAY+B,cAAgB/B,EAAIU,WAAa,cAErDC,EAAM,OAAA,CAAAC,UAAU,8DACbY,SAAA,CAAAxB,EAAIgC,YAAc,IAAoB,IAApBhC,EAAIgC,YAAoB,OAAS,cAIvDxB,GACCiB,EAAA,MAAA,CACEb,UAAU,0BACVK,QAAUI,GAAMA,EAAEY,kBAAiBT,SAElChB,EAAmB,CAClB0B,SAAUlC,EAAIU,WAAa,GAC3ByB,UAAYnC,EAAY8B,iBAAmB,GAC3CM,WAAapC,EAAY+B,YACzBM,KAAOrC,EAAYsC,YAAc,GACjCC,MAAOvC,EAAIgC,aAAe,EAC1BQ,MAAQxC,EAAY2B,aAAe"}
@@ -1,7 +0,0 @@
1
- interface NoDataMessageProps {
2
- hasFilters?: boolean;
3
- hasData?: boolean;
4
- message?: string;
5
- }
6
- export declare const NoDataMessage: ({ hasFilters, hasData, message, }: NoDataMessageProps) => import("react/jsx-runtime").JSX.Element;
7
- export {};
@@ -1,2 +0,0 @@
1
- import{jsxs as t,jsx as e}from"react/jsx-runtime";import{Database as r,Search as a}from"lucide-react";const i=({hasFilters:i=!1,hasData:s=!0,message:c})=>{const{title:o,description:n,icon:l}=c?{title:c,description:"",icon:r}:s?i?{title:"No Results Found",description:"No data matches your current search criteria. Try adjusting your filters.",icon:a}:{title:"No Data to Display",description:"There are no items to show at the moment.",icon:r}:{title:"No Data Available",description:"There is no data to display in this table.",icon:r};return t("div",{className:"flex flex-col items-center justify-center pt-16 pb-10 px-4 text-center",children:[e("div",{className:"w-16 h-16 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center mb-4",children:e(l,{className:"w-8 h-8 text-gray-400 dark:text-gray-500"})}),e("h3",{className:"text-lg font-medium text-gray-900 dark:text-gray-100 mb-2",children:o}),e("p",{className:"text-sm text-gray-500 dark:text-gray-400 max-w-md",children:n})]})};export{i as NoDataMessage};
2
- //# sourceMappingURL=NoDataMessage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"NoDataMessage.js","sources":["../../../../../components/NoDataMessage.tsx"],"sourcesContent":["import { Search, Database } from \"lucide-react\";\n\ninterface NoDataMessageProps {\n hasFilters?: boolean;\n hasData?: boolean;\n message?: string;\n}\n\nexport const NoDataMessage = ({\n hasFilters = false,\n hasData = true,\n message,\n}: NoDataMessageProps) => {\n const getMessage = () => {\n if (message) {\n return {\n title: message,\n description: \"\",\n icon: Database,\n };\n }\n\n if (!hasData) {\n return {\n title: \"No Data Available\",\n description: \"There is no data to display in this table.\",\n icon: Database,\n };\n }\n\n if (hasFilters) {\n return {\n title: \"No Results Found\",\n description:\n \"No data matches your current search criteria. Try adjusting your filters.\",\n icon: Search,\n };\n }\n\n return {\n title: \"No Data to Display\",\n description: \"There are no items to show at the moment.\",\n icon: Database,\n };\n };\n\n const { title, description, icon: Icon } = getMessage();\n\n return (\n <div className=\"flex flex-col items-center justify-center pt-16 pb-10 px-4 text-center\">\n <div className=\"w-16 h-16 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center mb-4\">\n <Icon className=\"w-8 h-8 text-gray-400 dark:text-gray-500\" />\n </div>\n <h3 className=\"text-lg font-medium text-gray-900 dark:text-gray-100 mb-2\">\n {title}\n </h3>\n <p className=\"text-sm text-gray-500 dark:text-gray-400 max-w-md\">\n {description}\n </p>\n </div>\n );\n};\n"],"names":["NoDataMessage","hasFilters","hasData","message","title","description","icon","Icon","Database","Search","_jsxs","className","_jsx","children"],"mappings":"sGAQa,MAAAA,EAAgB,EAC3BC,cAAa,EACbC,WAAU,EACVC,cAEA,MAiCMC,MAAEA,EAAKC,YAAEA,EAAaC,KAAMC,GAhC5BJ,EACK,CACLC,MAAOD,EACPE,YAAa,GACbC,KAAME,GAILN,EAQDD,EACK,CACLG,MAAO,mBACPC,YACE,4EACFC,KAAMG,GAIH,CACLL,MAAO,qBACPC,YAAa,4CACbC,KAAME,GAnBC,CACLJ,MAAO,oBACPC,YAAa,6CACbC,KAAME,GAsBZ,OACEE,EAAK,MAAA,CAAAC,UAAU,mFACbC,EAAK,MAAA,CAAAD,UAAU,qGACbC,EAACL,EAAK,CAAAI,UAAU,+CAElBC,QAAID,UAAU,4DAA2DE,SACtET,IAEHQ,EAAG,IAAA,CAAAD,UAAU,oDAAmDE,SAC7DR"}
@@ -1,15 +0,0 @@
1
- import { PaginationConfig } from "../types";
2
- interface PaginationControlsProps {
3
- paginationConfig: PaginationConfig;
4
- currentPage: number;
5
- isServerLoading: boolean;
6
- selectedRowsCount: number;
7
- totalDataLength: number;
8
- filteredDataLength?: number;
9
- paginationMode?: "client" | "server";
10
- onPageChange: (page: number, pageSize: number) => void;
11
- onPageSizeChange: (pageSize: number) => void;
12
- showNoDataMessage?: boolean;
13
- }
14
- export declare const PaginationControls: ({ paginationConfig, currentPage, isServerLoading, selectedRowsCount, totalDataLength, filteredDataLength, paginationMode, onPageChange, onPageSizeChange, }: PaginationControlsProps) => import("react/jsx-runtime").JSX.Element;
15
- export {};
@@ -1,2 +0,0 @@
1
- import{jsx as e,jsxs as r}from"react/jsx-runtime";import{Database as a,Users as t,Eye as o,Loader2 as i,ChevronsLeft as d,ChevronLeft as l,ChevronRight as n,ChevronsRight as s}from"lucide-react";const g=({paginationConfig:g,currentPage:c,isServerLoading:m,selectedRowsCount:p,totalDataLength:h,filteredDataLength:y,paginationMode:b="client",onPageChange:u,onPageSizeChange:x})=>{const{start:f,end:v,total:w}=(()=>{const e=g.enabled||"server"===b?g.totalRows||h:y||h;return{start:g.enabled?Math.min((c-1)*g.pageSize+1,e):1,end:g.enabled?Math.min(c*g.pageSize,e):e,total:e}})(),k="client"===b&&y&&y!==h;return e("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",children:r("div",{className:"flex flex-col xl:flex-row gap-4 xl:gap-6 xl:justify-between xl:items-center",children:[r("div",{className:"flex flex-col sm:flex-row gap-3 sm:gap-4 items-start sm:items-center",children:[r("div",{className:"flex flex-wrap items-center gap-2 sm:gap-3",children:[!g.enabled&&r("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",children:[e(a,{className:"w-3 h-3"}),r("span",{className:"font-bold",children:[w.toLocaleString()," ",1===w?"Record":"Records"]}),k&&r("span",{className:"text-blue-100 font-normal",children:["(of ",h.toLocaleString(),")"]})]}),p>0&&r("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",children:[e(t,{className:"w-3 h-3"}),r("span",{children:[p.toLocaleString()," selected"]})]}),k&&r("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",children:[e(o,{className:"w-3 h-3"}),e("span",{children:"Filtered"})]}),g.enabled&&e("div",{className:"hidden sm:block text-sm text-gray-600 dark:text-gray-400 font-medium",children:r("span",{className:"inline-flex items-center gap-1",children:[e("span",{children:"Showing"}),e("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",children:f.toLocaleString()}),e("span",{children:"-"}),e("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",children:v.toLocaleString()}),r("span",{children:["of ",w.toLocaleString()]})]})})]}),g.enabled&&g.showPageSizeSelector&&r("div",{className:"flex items-center gap-2",children:[e("span",{className:"text-sm font-medium text-gray-700 dark:text-gray-300 whitespace-nowrap",children:"Rows per page:"}),e("select",{value:g.pageSize,onChange:e=>x(Number(e.target.value)),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",disabled:m,children:g.pageSizeOptions?.map(r=>e("option",{value:r,children:r},r))})]})]}),g.enabled&&r("div",{className:"flex flex-col sm:flex-row items-start sm:items-center gap-3 sm:gap-4",children:[m&&r("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",children:[e(i,{className:"w-4 h-4 animate-spin text-primary"}),e("span",{className:"text-sm font-medium text-primary",children:"Loading..."})]}),e("div",{className:"sm:hidden text-sm text-gray-600 dark:text-gray-400 font-medium",children:r("div",{className:"flex flex-col gap-1",children:[r("span",{className:"inline-flex items-center gap-1",children:[e("span",{children:"Page"}),e("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",children:c.toLocaleString()}),e("span",{children:"of"}),e("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",children:g.totalPages.toLocaleString()})]}),r("span",{className:"text-xs text-gray-500 dark:text-gray-500",children:[f.toLocaleString()," - ",v.toLocaleString()," of"," ",w.toLocaleString()]})]})}),r("div",{className:"flex items-center gap-1 sm:gap-2",children:[e("button",{onClick:()=>u(1,g.pageSize),disabled:1===c||m,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",title:"First page","aria-label":"Go to first page",children:e(d,{className:"w-3.5 h-3.5"})}),e("button",{onClick:()=>u(c-1,g.pageSize),disabled:1===c||m,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",title:"Previous page","aria-label":"Go to previous page",children:e(l,{className:"w-3.5 h-3.5"})}),e("div",{className:"sm:hidden",children:e("select",{value:c,onChange:e=>u(Number(e.target.value),g.pageSize),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]",disabled:m,"aria-label":"Select page",children:Array.from({length:g.totalPages},(e,r)=>r+1).map(r=>e("option",{value:r,children:r},r))})}),e("div",{className:"hidden sm:flex items-center gap-1 mx-2",children:(()=>{const r=[],a=g.totalPages,t=c,o="undefined"!=typeof window&&window.innerWidth>=768?7:5;if(a<=o)for(let e=1;e<=a;e++)r.push(e);else{const e=Math.floor(o/2)-1;if(t<=e+1){for(let e=1;e<=o-2;e++)r.push(e);r.push("ellipsis1"),r.push(a)}else if(t>=a-e){r.push(1),r.push("ellipsis1");for(let e=a-(o-3);e<=a;e++)r.push(e)}else{r.push(1),r.push("ellipsis1");for(let a=t-e;a<=t+e;a++)r.push(a);r.push("ellipsis2"),r.push(a)}}return r.map(r=>{if("string"==typeof r)return e("div",{className:"flex items-center justify-center w-8 h-8 text-gray-400 dark:text-gray-500 select-none","aria-hidden":"true",children:e("span",{className:"text-lg leading-none",children:"⋯"})},r);const a=r===t;return e("button",{onClick:()=>u(r,g.pageSize),disabled:m,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 "+(a?"bg-linear-to-r from-primary to-primary text-white shadow-lg ring-2 ring-primary/20 transform scale-105 z-10 relative":"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"),"aria-label":`Go to page ${r}`,"aria-current":a?"page":void 0,children:r},r)})})()}),e("button",{onClick:()=>u(c+1,g.pageSize),disabled:c===g.totalPages||m,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",title:"Next page","aria-label":"Go to next page",children:e(n,{className:"w-3.5 h-3.5"})}),e("button",{onClick:()=>u(g.totalPages,g.pageSize),disabled:c===g.totalPages||m,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",title:"Last page","aria-label":"Go to last page",children:e(s,{className:"w-3.5 h-3.5"})})]})]})]})})};export{g as PaginationControls};
2
- //# sourceMappingURL=PaginationControls.js.map