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 +0,0 @@
1
- {"version":3,"file":"TextFilter.js","sources":["../../../../../../components/filters/TextFilter.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { ColumnFilterValue } from \"../../types\";\n\ninterface TextFilterProps {\n value: ColumnFilterValue | null;\n onChange: (value: ColumnFilterValue | null) => void;\n placeholder?: string;\n}\n\nexport const TextFilter = ({\n value,\n onChange,\n placeholder = \"Enter text to filter...\",\n}: TextFilterProps) => {\n const [textValue, setTextValue] = useState(value?.value || \"\");\n const [operator, setOperator] = useState<\n \"contains\" | \"equals\" | \"startsWith\" | \"endsWith\"\n >((value?.operator as any) || \"contains\");\n\n const handleTextChange = (newText: string) => {\n setTextValue(newText);\n if (newText.trim()) {\n onChange({\n type: \"text\",\n value: newText,\n operator: operator as any,\n });\n } else {\n onChange(null);\n }\n };\n\n const handleOperatorChange = (newOperator: string) => {\n const op = newOperator as \"contains\" | \"equals\" | \"startsWith\" | \"endsWith\";\n setOperator(op);\n if (textValue.trim()) {\n onChange({\n type: \"text\",\n value: textValue,\n operator: op,\n });\n }\n };\n\n return (\n <div className=\"space-y-3\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n Filter Type\n </label>\n <select\n value={operator}\n onChange={(e) => handleOperatorChange(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\n >\n <option value=\"contains\">Contains</option>\n <option value=\"equals\">Equals</option>\n <option value=\"startsWith\">Starts with</option>\n <option value=\"endsWith\">Ends with</option>\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n Text Value\n </label>\n <input\n type=\"text\"\n value={textValue}\n onChange={(e) => handleTextChange(e.target.value)}\n placeholder={placeholder}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\n />\n </div>\n </div>\n );\n};\n"],"names":["TextFilter","value","onChange","placeholder","textValue","setTextValue","useState","operator","setOperator","_jsxs","className","children","_jsx","e","newOperator","op","trim","type","handleOperatorChange","target","handleTextChange","newText"],"mappings":"mFASO,MAAMA,EAAa,EACxBC,QACAC,WACAC,cAAc,8BAEd,MAAOC,EAAWC,GAAgBC,EAASL,GAAOA,OAAS,KACpDM,EAAUC,GAAeF,EAE7BL,GAAOM,UAAoB,YA2B9B,OACEE,SAAKC,UAAU,YACbC,SAAA,CAAAF,EAAA,MAAA,CAAAE,SAAA,CACEC,EAAO,QAAA,CAAAF,UAAU,wEAGjBD,EAAA,SAAA,CACER,MAAOM,EACPL,SAAWW,GApBU,CAACC,IAC5B,MAAMC,EAAKD,EACXN,EAAYO,GACRX,EAAUY,QACZd,EAAS,CACPe,KAAM,OACNhB,MAAOG,EACPG,SAAUQ,KAaSG,CAAqBL,EAAEM,OAAOlB,OAC/CS,UAAU,4GAEVC,SAAA,CAAAC,EAAA,SAAA,CAAQX,MAAM,WAA4BU,SAAA,aAC1CC,EAAQ,SAAA,CAAAX,MAAM,SAAQU,SAAA,WACtBC,EAAA,SAAA,CAAQX,MAAM,aAAiCU,SAAA,gBAC/CC,EAAQ,SAAA,CAAAX,MAAM,wCAIlBQ,EAAA,MAAA,CAAAE,SAAA,CACEC,EAAO,QAAA,CAAAF,UAAU,+CAA8CC,SAAA,eAG/DC,EAAA,QAAA,CACEK,KAAK,OACLhB,MAAOG,EACPF,SAAWW,IAAMO,OAlDCC,EAkDgBR,EAAEM,OAAOlB,MAjDjDI,EAAagB,QACTA,EAAQL,OACVd,EAAS,CACPe,KAAM,OACNhB,MAAOoB,EACPd,SAAUA,IAGZL,EAAS,OATY,IAACmB,GAmDlBlB,YAAaA,EACbO,UAAU"}
@@ -1,6 +0,0 @@
1
- export { TextFilter } from './TextFilter';
2
- export { NumberFilter } from './NumberFilter';
3
- export { DateFilter } from './DateFilter';
4
- export { MultiselectFilter } from './MultiselectFilter';
5
- export { BooleanFilter } from './BooleanFilter';
6
- export { FilterPopup } from './FilterPopup';
@@ -1,10 +0,0 @@
1
- import React from 'react';
2
- interface DatePickerProps {
3
- name?: string;
4
- label?: string;
5
- value: string | null;
6
- onChange: (value: string | null) => void;
7
- className?: string;
8
- }
9
- export declare const DatePicker: React.FC<DatePickerProps>;
10
- export {};
@@ -1,2 +0,0 @@
1
- import{jsxs as e,jsx as a}from"react/jsx-runtime";const l=({name:l,label:r,value:t,onChange:n,className:s=""})=>e("div",{className:`space-y-1 ${s}`,children:[r&&a("label",{className:"text-sm font-medium text-gray-700",children:r}),a("input",{type:"date",name:l,value:t||"",onChange:e=>n(e.target.value||null),className:"w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500"})]});export{l as DatePicker};
2
- //# sourceMappingURL=DatePicker.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DatePicker.js","sources":["../../../../../../components/ui/DatePicker.tsx"],"sourcesContent":["import React from 'react';\n\ninterface DatePickerProps {\n name?: string;\n label?: string;\n value: string | null;\n onChange: (value: string | null) => void;\n className?: string;\n}\n\nexport const DatePicker: React.FC<DatePickerProps> = ({\n name,\n label,\n value,\n onChange,\n className = '',\n}) => {\n return (\n <div className={`space-y-1 ${className}`}>\n {label && (\n <label className=\"text-sm font-medium text-gray-700\">\n {label}\n </label>\n )}\n <input\n type=\"date\"\n name={name}\n value={value || ''}\n onChange={(e) => onChange(e.target.value || null)}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\n />\n </div>\n );\n};"],"names":["DatePicker","name","label","value","onChange","className","_jsxs","children","_jsx","type","e","target"],"mappings":"kDAUa,MAAAA,EAAwC,EACnDC,OACAC,QACAC,QACAC,WACAC,YAAY,MAGVC,EAAK,MAAA,CAAAD,UAAW,aAAaA,IAC1BE,SAAA,CAAAL,GACCM,EAAO,QAAA,CAAAH,UAAU,oCACdE,SAAAL,IAGLM,EAAA,QAAA,CACEC,KAAK,OACLR,KAAMA,EACNE,MAAOA,GAAS,GAChBC,SAAWM,GAAMN,EAASM,EAAEC,OAAOR,OAAS,MAC5CE,UAAU"}
@@ -1 +0,0 @@
1
- export declare const SELECT_COL_WIDTH = 48;
@@ -1,2 +0,0 @@
1
- const o=48;export{o as SELECT_COL_WIDTH};
2
- //# sourceMappingURL=constants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.js","sources":["../../../../constants.ts"],"sourcesContent":["export const SELECT_COL_WIDTH = 48; // px\n"],"names":["SELECT_COL_WIDTH"],"mappings":"AAAa,MAAAA,EAAmB"}
@@ -1,16 +0,0 @@
1
- import { GridRow, GridColumn, ActiveFilters, ColumnFilterValue } from "../types";
2
- interface UseAdvancedFilteringProps {
3
- data: GridRow[];
4
- columns: GridColumn[];
5
- }
6
- export declare const useAdvancedFiltering: ({ data, columns, }: UseAdvancedFilteringProps) => {
7
- globalFilter: string;
8
- setGlobalFilter: import("react").Dispatch<import("react").SetStateAction<string>>;
9
- columnFilters: ActiveFilters;
10
- filteredData: GridRow[];
11
- setColumnFilter: (columnKey: string, filter: ColumnFilterValue | null) => void;
12
- clearColumnFilter: (columnKey: string) => void;
13
- clearAllFilters: () => void;
14
- getActiveFilterCount: () => number;
15
- };
16
- export {};
@@ -1,2 +0,0 @@
1
- import{useState as e,useDeferredValue as t,useCallback as r,useRef as n,useMemo as a}from"react";const s=({data:s,columns:l})=>{const[u,i]=e(""),[c,o]=e({}),g=t(u),m=t(c),f=r((e,t,r)=>{const n=e[t];switch(r.type){case"text":const e=String(n||"").toLowerCase(),t=String(r.value||"").toLowerCase();switch(r.operator){case"contains":default:return e.includes(t);case"equals":return e===t;case"startsWith":return e.startsWith(t);case"endsWith":return e.endsWith(t)}case"number":const a=parseFloat(n),s=parseFloat(r.value);if(isNaN(a)||isNaN(s))return!1;switch(r.operator){case"equals":default:return a===s;case"gt":return a>s;case"gte":return a>=s;case"lt":return a<s;case"lte":return a<=s;case"between":const e=parseFloat(r.secondValue);return!isNaN(e)&&a>=s&&a<=e}case"date":const l=new Date(n),u=new Date(r.value);if(isNaN(l.getTime())||isNaN(u.getTime()))return!1;const i=new Date(l.getFullYear(),l.getMonth(),l.getDate()),c=new Date(u.getFullYear(),u.getMonth(),u.getDate());switch(r.operator){case"equals":default:return i.getTime()===c.getTime();case"gt":return i.getTime()>c.getTime();case"gte":return i.getTime()>=c.getTime();case"lt":return i.getTime()<c.getTime();case"lte":return i.getTime()<=c.getTime();case"between":const e=new Date(r.secondValue);if(isNaN(e.getTime()))return!1;const t=new Date(e.getFullYear(),e.getMonth(),e.getDate());return i.getTime()>=c.getTime()&&i.getTime()<=t.getTime()}case"boolean":return Boolean(n)===Boolean(r.value);case"multiselect":const o=Array.isArray(r.value)?r.value:[r.value],g=e=>null==e||""===e||"string"==typeof e&&""===e.trim()?null:e,m=g(n);return o.map(g).includes(m);default:return!0}},[]),w=n(new WeakMap),p=n(0),T=r(()=>{p.current>5e3&&(w.current=new WeakMap,p.current=0)},[]),h=a(()=>{T();const e=Object.keys(m).length>0,t=!!g;if(!e&&!t)return s;const r=g.toLowerCase(),n=w.current;let a=s;if(e)for(const[e,t]of Object.entries(m))if(t&&(a=a.filter(r=>f(r,e,t)),0===a.length))break;if(t&&a.length>0){const e=l.filter(e=>!1!==e.visible);a=a.filter(t=>{let a=n.get(t);return null==a&&(a=e.map(e=>{const r=t[e.key];if(null==r)return"";if("string"==typeof r)return r.toLowerCase();if("number"==typeof r||"boolean"==typeof r)return String(r).toLowerCase();const n=String(r);return n.length>100?n.slice(0,100):n}).join("|"),p.current<5e3&&(n.set(t,a),p.current++)),a.includes(r)})}return a},[s,m,g,l,f,T]),d=r((e,t)=>{o(r=>{const n={...r};return t?n[e]=t:delete n[e],n})},[]),b=r(e=>{d(e,null)},[d]),F=r(()=>{o({}),i(""),w.current=new WeakMap,p.current=0},[]),N=r(()=>{let e=0;return g&&e++,e+=Object.keys(m).length,e},[g,m]);return{globalFilter:u,setGlobalFilter:i,columnFilters:m,filteredData:h,setColumnFilter:d,clearColumnFilter:b,clearAllFilters:F,getActiveFilterCount:N}};export{s as useAdvancedFiltering};
2
- //# sourceMappingURL=useAdvancedFiltering.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useAdvancedFiltering.js","sources":["../../../../../hooks/useAdvancedFiltering.ts"],"sourcesContent":["import {\n useState,\n useMemo,\n useCallback,\n useDeferredValue,\n useRef,\n} from \"react\";\nimport {\n GridRow,\n GridColumn,\n ActiveFilters,\n ColumnFilterValue,\n} from \"../types\";\n\ninterface UseAdvancedFilteringProps {\n data: GridRow[];\n columns: GridColumn[];\n}\n\nexport const useAdvancedFiltering = ({\n data,\n columns,\n}: UseAdvancedFilteringProps) => {\n const [globalFilter, setGlobalFilter] = useState<string>(\"\");\n const [columnFilters, setColumnFilters] = useState<ActiveFilters>({});\n\n // Use deferred values for better performance with large datasets\n const deferredGlobalFilter = useDeferredValue(globalFilter);\n const deferredColumnFilters = useDeferredValue(columnFilters);\n\n const applyColumnFilter = useCallback(\n (row: GridRow, columnKey: string, filter: ColumnFilterValue): boolean => {\n const value = row[columnKey];\n\n switch (filter.type) {\n case \"text\":\n const textValue = String(value || \"\").toLowerCase();\n const filterText = String(filter.value || \"\").toLowerCase();\n\n switch (filter.operator) {\n case \"contains\":\n return textValue.includes(filterText);\n case \"equals\":\n return textValue === filterText;\n case \"startsWith\":\n return textValue.startsWith(filterText);\n case \"endsWith\":\n return textValue.endsWith(filterText);\n default:\n return textValue.includes(filterText);\n }\n\n case \"number\":\n const numValue = parseFloat(value);\n const filterNum = parseFloat(filter.value);\n\n if (isNaN(numValue) || isNaN(filterNum)) return false;\n\n switch (filter.operator) {\n case \"equals\":\n return numValue === filterNum;\n case \"gt\":\n return numValue > filterNum;\n case \"gte\":\n return numValue >= filterNum;\n case \"lt\":\n return numValue < filterNum;\n case \"lte\":\n return numValue <= filterNum;\n case \"between\":\n const secondNum = parseFloat(filter.secondValue);\n return (\n !isNaN(secondNum) &&\n numValue >= filterNum &&\n numValue <= secondNum\n );\n default:\n return numValue === filterNum;\n }\n\n case \"date\":\n const dateValue = new Date(value);\n const filterDate = new Date(filter.value);\n\n if (isNaN(dateValue.getTime()) || isNaN(filterDate.getTime()))\n return false;\n\n // Compare dates without time\n const dateOnly = new Date(\n dateValue.getFullYear(),\n dateValue.getMonth(),\n dateValue.getDate()\n );\n const filterDateOnly = new Date(\n filterDate.getFullYear(),\n filterDate.getMonth(),\n filterDate.getDate()\n );\n\n switch (filter.operator) {\n case \"equals\":\n return dateOnly.getTime() === filterDateOnly.getTime();\n case \"gt\":\n return dateOnly.getTime() > filterDateOnly.getTime();\n case \"gte\":\n return dateOnly.getTime() >= filterDateOnly.getTime();\n case \"lt\":\n return dateOnly.getTime() < filterDateOnly.getTime();\n case \"lte\":\n return dateOnly.getTime() <= filterDateOnly.getTime();\n case \"between\":\n const secondDate = new Date(filter.secondValue);\n if (isNaN(secondDate.getTime())) return false;\n const secondDateOnly = new Date(\n secondDate.getFullYear(),\n secondDate.getMonth(),\n secondDate.getDate()\n );\n return (\n dateOnly.getTime() >= filterDateOnly.getTime() &&\n dateOnly.getTime() <= secondDateOnly.getTime()\n );\n default:\n return dateOnly.getTime() === filterDateOnly.getTime();\n }\n\n case \"boolean\":\n return Boolean(value) === Boolean(filter.value);\n\n case \"multiselect\":\n const filterValues = Array.isArray(filter.value)\n ? filter.value\n : [filter.value];\n\n // Normalize blank values for comparison\n const normalizeBlank = (val: any) => {\n if (\n val === null ||\n val === undefined ||\n val === \"\" ||\n (typeof val === \"string\" && val.trim() === \"\")\n ) {\n return null;\n }\n return val;\n };\n\n const normalizedValue = normalizeBlank(value);\n const normalizedFilterValues = filterValues.map(normalizeBlank);\n\n return normalizedFilterValues.includes(normalizedValue);\n\n default:\n return true;\n }\n },\n []\n );\n\n // Optimized search cache with size limits for large datasets\n const rowSearchCacheRef = useRef<WeakMap<GridRow, string>>(new WeakMap());\n const cacheSizeRef = useRef(0);\n const maxCacheSize = 5000; // Limit cache size for memory management\n\n // Clear cache when it gets too large\n const clearCacheIfNeeded = useCallback(() => {\n if (cacheSizeRef.current > maxCacheSize) {\n rowSearchCacheRef.current = new WeakMap();\n cacheSizeRef.current = 0;\n }\n }, []);\n\n const filteredData = useMemo(() => {\n clearCacheIfNeeded();\n\n // Short-circuit quickly when nothing active\n const hasColumnFilters = Object.keys(deferredColumnFilters).length > 0;\n const hasGlobal = !!deferredGlobalFilter;\n if (!hasColumnFilters && !hasGlobal) return data;\n\n const lowerGlobal = deferredGlobalFilter.toLowerCase();\n const cache = rowSearchCacheRef.current!;\n let working = data;\n\n // Apply column filters first (usually more selective)\n if (hasColumnFilters) {\n for (const [columnKey, filter] of Object.entries(deferredColumnFilters)) {\n if (!filter) continue;\n working = working.filter((row) =>\n applyColumnFilter(row, columnKey, filter)\n );\n // Early exit if no results\n if (working.length === 0) break;\n }\n }\n\n // Apply global filter with optimized search\n if (hasGlobal && working.length > 0) {\n // Only search visible columns for better performance\n const visibleColumns = columns.filter((col) => col.visible !== false);\n\n working = working.filter((row) => {\n let packed = cache.get(row);\n if (packed == null) {\n packed = visibleColumns\n .map((c) => {\n const v = row[c.key];\n if (v == null) return \"\";\n if (typeof v === \"string\") return v.toLowerCase();\n if (typeof v === \"number\" || typeof v === \"boolean\")\n return String(v).toLowerCase();\n // Limit object stringification to prevent performance issues\n const s = String(v);\n return s.length > 100 ? s.slice(0, 100) : s;\n })\n .join(\"|\");\n\n // Cache with size limit\n if (cacheSizeRef.current < maxCacheSize) {\n cache.set(row, packed);\n cacheSizeRef.current++;\n }\n }\n return packed.includes(lowerGlobal);\n });\n }\n\n return working;\n }, [\n data,\n deferredColumnFilters,\n deferredGlobalFilter,\n columns,\n applyColumnFilter,\n clearCacheIfNeeded,\n ]);\n\n const setColumnFilter = useCallback(\n (columnKey: string, filter: ColumnFilterValue | null) => {\n setColumnFilters((prev) => {\n const newFilters = { ...prev };\n if (filter) {\n newFilters[columnKey] = filter;\n } else {\n delete newFilters[columnKey];\n }\n return newFilters;\n });\n },\n []\n );\n\n const clearColumnFilter = useCallback(\n (columnKey: string) => {\n setColumnFilter(columnKey, null);\n },\n [setColumnFilter]\n );\n\n const clearAllFilters = useCallback(() => {\n setColumnFilters({});\n setGlobalFilter(\"\");\n // Clear cache when filters are cleared\n rowSearchCacheRef.current = new WeakMap();\n cacheSizeRef.current = 0;\n }, []);\n\n const getActiveFilterCount = useCallback(() => {\n let count = 0;\n if (deferredGlobalFilter) count++;\n count += Object.keys(deferredColumnFilters).length;\n return count;\n }, [deferredGlobalFilter, deferredColumnFilters]);\n\n return {\n globalFilter,\n setGlobalFilter,\n columnFilters: deferredColumnFilters,\n filteredData,\n setColumnFilter,\n clearColumnFilter,\n clearAllFilters,\n getActiveFilterCount,\n };\n};\n"],"names":["useAdvancedFiltering","data","columns","globalFilter","setGlobalFilter","useState","columnFilters","setColumnFilters","deferredGlobalFilter","useDeferredValue","deferredColumnFilters","applyColumnFilter","useCallback","row","columnKey","filter","value","type","textValue","String","toLowerCase","filterText","operator","includes","startsWith","endsWith","numValue","parseFloat","filterNum","isNaN","secondNum","secondValue","dateValue","Date","filterDate","getTime","dateOnly","getFullYear","getMonth","getDate","filterDateOnly","secondDate","secondDateOnly","Boolean","filterValues","Array","isArray","normalizeBlank","val","trim","normalizedValue","map","rowSearchCacheRef","useRef","WeakMap","cacheSizeRef","clearCacheIfNeeded","current","filteredData","useMemo","hasColumnFilters","Object","keys","length","hasGlobal","lowerGlobal","cache","working","entries","visibleColumns","col","visible","packed","get","c","v","key","s","slice","join","set","setColumnFilter","prev","newFilters","clearColumnFilter","clearAllFilters","getActiveFilterCount","count"],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- type SortCfg = {
2
- key: string;
3
- direction: "asc" | "desc";
4
- } | null;
5
- export declare function useDataWorker(options?: {
6
- enabled?: boolean;
7
- }): {
8
- process: (rows: any[], sort: SortCfg) => Promise<any[]>;
9
- };
10
- export {};
@@ -1,2 +0,0 @@
1
- import{useRef as r,useEffect as e,useMemo as t}from"react";function n(n){const l=n?.enabled??!0,s=r(null),u=r(null);e(()=>{if(!l)return;try{const r=`(${o.toString()})()`,e=new Blob([r],{type:"application/javascript"});s.current=new Worker(URL.createObjectURL(e))}catch(r){console.warn("Failed to initialize data worker, grid will run in main thread mode.",r),s.current=null}const r=s.current;return r.onmessage=r=>{const e=r.data;e&&"result"===e.type&&(u.current?.(e.payload.rows),u.current=null)},()=>{r?.terminate(),s.current=null,u.current=null}},[l]);return{process:t(()=>(r,e)=>{if(!l||!s.current){if(!r||0===r.length||!e?.key)return Promise.resolve(r);const t="asc"===e.direction?1:-1,n=[...r].sort((r,n)=>{const o=r?.[e.key],l=n?.[e.key];return null==o&&null==l?0:null==o?-1*t:null==l?1*t:"number"==typeof o&&"number"==typeof l?(o-l)*t:String(o).localeCompare(String(l))*t});return Promise.resolve(n)}return new Promise(t=>{u.current=t,s.current.postMessage({type:"process",payload:{rows:r,sort:e}})})},[l])}}function o(){const r=self;r.onmessage=e=>{const t=e.data;if(t&&"process"===t.type)try{const{rows:e,sort:n}=t.payload,o=((r,e)=>{if(!r||0===r.length)return r;let t=r;if(e&&e.key){const{key:n,direction:o}=e,l="asc"===o?1:-1;t=[...r].sort((r,e)=>{const t=r?.[n],o=e?.[n];if(null==t&&null==o)return 0;if(null==t)return-1*l;if(null==o)return 1*l;if("number"==typeof t&&"number"==typeof o)return(t-o)*l;const s=String(t),u=String(o);return s.localeCompare(u)*l})}return t})(e,n??null);r.postMessage({type:"result",payload:{rows:o}})}catch(t){r.postMessage({type:"result",payload:{rows:e.data?.payload?.rows||[]}})}}}export{n as useDataWorker};
2
- //# sourceMappingURL=useDataWorker.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useDataWorker.js","sources":["../../../../../hooks/useDataWorker.ts"],"sourcesContent":["import { useEffect, useMemo, useRef } from \"react\";\n\ntype SortCfg = { key: string; direction: \"asc\" | \"desc\" } | null;\n\nexport function useDataWorker(options?: { enabled?: boolean }) {\n const enabled = options?.enabled ?? true;\n const workerRef = useRef<Worker | null>(null);\n const resolverRef = useRef<((rows: any[]) => void) | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n // Use Blob-based worker to avoid path resolution issues in consuming projects\n try {\n const code = `(${workerFactory.toString()})()`;\n const blob = new Blob([code], { type: \"application/javascript\" });\n workerRef.current = new Worker(URL.createObjectURL(blob));\n } catch (err) {\n console.warn(\n \"Failed to initialize data worker, grid will run in main thread mode.\",\n err,\n );\n workerRef.current = null;\n }\n const w = workerRef.current;\n w!.onmessage = (e: MessageEvent) => {\n const data = e.data;\n if (data && data.type === \"result\") {\n resolverRef.current?.(data.payload.rows);\n resolverRef.current = null;\n }\n };\n return () => {\n w?.terminate();\n workerRef.current = null;\n resolverRef.current = null;\n };\n }, [enabled]);\n\n const process = useMemo(() => {\n return (rows: any[], sort: SortCfg) => {\n if (!enabled || !workerRef.current) {\n // Inline fallback\n if (!rows || rows.length === 0 || !sort?.key)\n return Promise.resolve(rows);\n const dir = sort.direction === \"asc\" ? 1 : -1;\n const out = [...rows].sort((a, b) => {\n const av = a?.[sort.key!];\n const bv = b?.[sort.key!];\n if (av == null && bv == null) return 0;\n if (av == null) return -1 * dir;\n if (bv == null) return 1 * dir;\n if (typeof av === \"number\" && typeof bv === \"number\")\n return (av - bv) * dir;\n return String(av).localeCompare(String(bv)) * dir;\n });\n return Promise.resolve(out);\n }\n return new Promise<any[]>((resolve) => {\n resolverRef.current = resolve;\n workerRef.current!.postMessage({\n type: \"process\",\n payload: { rows, sort },\n });\n });\n };\n }, [enabled]);\n\n return { process };\n}\n\n// Inlined worker code for Blob fallback\nfunction workerFactory() {\n const ctx = self as any;\n const processData = (\n rows: any[],\n sort?: { key: string; direction: \"asc\" | \"desc\" } | null,\n ) => {\n if (!rows || rows.length === 0) return rows;\n let out = rows;\n if (sort && sort.key) {\n const { key, direction } = sort;\n const dir = direction === \"asc\" ? 1 : -1;\n out = [...rows].sort((a, b) => {\n const av = a?.[key];\n const bv = b?.[key];\n if (av == null && bv == null) return 0;\n if (av == null) return -1 * dir;\n if (bv == null) return 1 * dir;\n if (typeof av === \"number\" && typeof bv === \"number\")\n return (av - bv) * dir;\n const as = String(av);\n const bs = String(bv);\n return as.localeCompare(bs) * dir;\n });\n }\n return out;\n };\n (ctx as any).onmessage = (e: MessageEvent) => {\n const msg = e.data;\n if (!msg || msg.type !== \"process\") return;\n try {\n const { rows, sort } = msg.payload;\n const result = processData(rows, sort ?? null);\n (ctx as any).postMessage({ type: \"result\", payload: { rows: result } });\n } catch (err) {\n (ctx as any).postMessage({\n type: \"result\",\n payload: { rows: e.data?.payload?.rows || [] },\n });\n }\n };\n}\n"],"names":["useDataWorker","options","enabled","workerRef","useRef","resolverRef","useEffect","code","workerFactory","toString","blob","Blob","type","current","Worker","URL","createObjectURL","err","console","warn","w","onmessage","e","data","payload","rows","terminate","process","useMemo","sort","length","key","Promise","resolve","dir","direction","out","a","b","av","bv","String","localeCompare","postMessage","ctx","self","msg","result","as","bs","processData"],"mappings":"2DAIM,SAAUA,EAAcC,GAC5B,MAAMC,EAAUD,GAASC,UAAW,EAC9BC,EAAYC,EAAsB,MAClCC,EAAcD,EAAuC,MAE3DE,EAAU,KACR,IAAKJ,EAAS,OAEd,IACE,MAAMK,EAAO,IAAIC,EAAcC,gBACzBC,EAAO,IAAIC,KAAK,CAACJ,GAAO,CAAEK,KAAM,2BACtCT,EAAUU,QAAU,IAAIC,OAAOC,IAAIC,gBAAgBN,GACpD,CAAC,MAAOO,GACPC,QAAQC,KACN,uEACAF,GAEFd,EAAUU,QAAU,IACrB,CACD,MAAMO,EAAIjB,EAAUU,QAQpB,OAPAO,EAAGC,UAAaC,IACd,MAAMC,EAAOD,EAAEC,KACXA,GAAsB,WAAdA,EAAKX,OACfP,EAAYQ,UAAUU,EAAKC,QAAQC,MACnCpB,EAAYQ,QAAU,OAGnB,KACLO,GAAGM,YACHvB,EAAUU,QAAU,KACpBR,EAAYQ,QAAU,OAEvB,CAACX,IA+BJ,MAAO,CAAEyB,QA7BOC,EAAQ,IACf,CAACH,EAAaI,KACnB,IAAK3B,IAAYC,EAAUU,QAAS,CAElC,IAAKY,GAAwB,IAAhBA,EAAKK,SAAiBD,GAAME,IACvC,OAAOC,QAAQC,QAAQR,GACzB,MAAMS,EAAyB,QAAnBL,EAAKM,UAAsB,GAAK,EACtCC,EAAM,IAAIX,GAAMI,KAAK,CAACQ,EAAGC,KAC7B,MAAMC,EAAKF,IAAIR,EAAKE,KACdS,EAAKF,IAAIT,EAAKE,KACpB,OAAU,MAANQ,GAAoB,MAANC,EAAmB,EAC3B,MAAND,GAAoB,EAAIL,EAClB,MAANM,EAAmB,EAAIN,EACT,iBAAPK,GAAiC,iBAAPC,GAC3BD,EAAKC,GAAMN,EACdO,OAAOF,GAAIG,cAAcD,OAAOD,IAAON,IAEhD,OAAOF,QAAQC,QAAQG,EACxB,CACD,OAAO,IAAIJ,QAAgBC,IACzB5B,EAAYQ,QAAUoB,EACtB9B,EAAUU,QAAS8B,YAAY,CAC7B/B,KAAM,UACNY,QAAS,CAAEC,OAAMI,aAItB,CAAC3B,IAGN,CAGA,SAASM,IACP,MAAMoC,EAAMC,KAyBXD,EAAYvB,UAAaC,IACxB,MAAMwB,EAAMxB,EAAEC,KACd,GAAKuB,GAAoB,YAAbA,EAAIlC,KAChB,IACE,MAAMa,KAAEA,EAAII,KAAEA,GAASiB,EAAItB,QACrBuB,EA7BU,EAClBtB,EACAI,KAEA,IAAKJ,GAAwB,IAAhBA,EAAKK,OAAc,OAAOL,EACvC,IAAIW,EAAMX,EACV,GAAII,GAAQA,EAAKE,IAAK,CACpB,MAAMA,IAAEA,EAAGI,UAAEA,GAAcN,EACrBK,EAAoB,QAAdC,EAAsB,GAAK,EACvCC,EAAM,IAAIX,GAAMI,KAAK,CAACQ,EAAGC,KACvB,MAAMC,EAAKF,IAAIN,GACTS,EAAKF,IAAIP,GACf,GAAU,MAANQ,GAAoB,MAANC,EAAY,OAAO,EACrC,GAAU,MAAND,EAAY,OAAQ,EAAIL,EAC5B,GAAU,MAANM,EAAY,OAAO,EAAIN,EAC3B,GAAkB,iBAAPK,GAAiC,iBAAPC,EACnC,OAAQD,EAAKC,GAAMN,EACrB,MAAMc,EAAKP,OAAOF,GACZU,EAAKR,OAAOD,GAClB,OAAOQ,EAAGN,cAAcO,GAAMf,GAEjC,CACD,OAAOE,GAOUc,CAAYzB,EAAMI,GAAQ,MACxCe,EAAYD,YAAY,CAAE/B,KAAM,SAAUY,QAAS,CAAEC,KAAMsB,IAC7D,CAAC,MAAO9B,GACN2B,EAAYD,YAAY,CACvB/B,KAAM,SACNY,QAAS,CAAEC,KAAMH,EAAEC,MAAMC,SAASC,MAAQ,KAE7C,EAEL"}
@@ -1,15 +0,0 @@
1
- import { GridRow, GridColumn } from "../types";
2
- export type ExportFormat = "csv" | "json" | "xlsx";
3
- interface UseExportProps {
4
- data: GridRow[];
5
- columns: GridColumn[];
6
- selectedRows?: Set<string | number>;
7
- filename?: string;
8
- columnVisibility?: Record<string, boolean>;
9
- }
10
- export declare const useExport: ({ data, columns, selectedRows, filename, columnVisibility, }: UseExportProps) => {
11
- exportData: (format: ExportFormat, exportSelected?: boolean) => void;
12
- canExportSelected: boolean;
13
- selectedCount: number;
14
- };
15
- export {};
@@ -1,2 +0,0 @@
1
- import{useCallback as e}from"react";const t=({data:t,columns:o,selectedRows:n,filename:r="data",columnVisibility:s})=>{const a=s?o.filter(e=>!1!==s[e.key]):o,c=e((e,t,o)=>{const n=new Blob([e],{type:o}),r=URL.createObjectURL(n),s=document.createElement("a");s.href=r,s.download=t,document.body.appendChild(s),s.click(),document.body.removeChild(s),URL.revokeObjectURL(r)},[]),i=e((e,t)=>{const o=[a.map(e=>e.header).join(","),...e.map(e=>a.map(t=>{const o=e[t.key],n=String(o||"");return n.includes(",")||n.includes('"')?`"${n.replace(/"/g,'""')}"`:n}).join(","))].join("\n");c(o,`${t}.csv`,"text/csv")},[a,c]),l=e((e,t)=>{const o=e.map(e=>{const t={};return a.forEach(o=>{t[o.header]=e[o.key]}),t}),n=JSON.stringify(o,null,2);c(n,`${t}.json`,"application/json")},[a,c]),d=e(async(e,t)=>{const[o,{saveAs:n}]=await Promise.all([import("exceljs"),import("file-saver")]),r=new(o.default||o).Workbook,s=r.addWorksheet("Data"),c=e.slice(0,50),i=e=>{if(null==e)return"";if("number"==typeof e)return e;if("boolean"==typeof e)return e;if(e instanceof Date)return e;const t=String(e);if(/[a-zA-Z]/.test(t))return t;if(/^-?[\d,]+\.?\d*$/.test(t.trim())){const e=Number(t.replace(/,/g,""));if(Number.isFinite(e))return e}return t},l=a.map(e=>{const t=e.header||e.key;let o=t?.length||10;for(const t of c){const n=t[e.key],r=null==n?"":String(n);r.length>o&&(o=r.length)}const n=Math.max(8,Math.min(50,Math.ceil(1.1*o)));return{header:t,key:e.key,width:n}});s.columns=l;for(const t of e){const e={};for(const o of a)e[o.key]=i(t[o.key]);s.addRow(e)}s.getRow(1).font={bold:!0},s.autoFilter={from:{row:1,column:1},to:{row:Math.max(1,s.rowCount),column:a.length}};const d=await r.xlsx.writeBuffer();n(new Blob([d],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}),`${t}.xlsx`)},[a]);return{exportData:e((e,o=!1)=>{const s=o&&n&&n.size>0?t.filter(e=>n.has(e.id)):t,a=o&&n&&n.size>0?`${r}_selected_${n.size}_rows`:r;switch(e){case"csv":i(s,a);break;case"json":l(s,a);break;case"xlsx":d(s,a);break;default:console.warn(`Unsupported export format: ${e}`)}},[t,n,r,i,l,d]),canExportSelected:n&&n.size>0,selectedCount:n?.size||0}};export{t as useExport};
2
- //# sourceMappingURL=useExport.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useExport.js","sources":["../../../../../hooks/useExport.ts"],"sourcesContent":["import { useCallback } from \"react\";\nimport { GridRow, GridColumn } from \"../types\";\n\nexport type ExportFormat = \"csv\" | \"json\" | \"xlsx\";\n\ninterface UseExportProps {\n data: GridRow[];\n columns: GridColumn[];\n selectedRows?: Set<string | number>;\n filename?: string;\n columnVisibility?: Record<string, boolean>;\n}\n\nexport const useExport = ({\n data,\n columns,\n selectedRows,\n filename = \"data\",\n columnVisibility,\n}: UseExportProps) => {\n // Filter only visible columns\n const visibleColumns = columnVisibility\n ? columns.filter((col) => columnVisibility[col.key] !== false)\n : columns;\n const downloadFile = useCallback(\n (content: string, fileName: string, mimeType: string) => {\n const blob = new Blob([content], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = fileName;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n },\n [],\n );\n\n const exportToCSV = useCallback(\n (exportData: GridRow[], exportFilename: string) => {\n const headers = visibleColumns.map((col) => col.header).join(\",\");\n const rows = exportData.map((row) =>\n visibleColumns\n .map((col) => {\n const value = row[col.key];\n // Escape commas and quotes in CSV\n const stringValue = String(value || \"\");\n return stringValue.includes(\",\") || stringValue.includes('\"')\n ? `\"${stringValue.replace(/\"/g, '\"\"')}\"`\n : stringValue;\n })\n .join(\",\"),\n );\n\n const csvContent = [headers, ...rows].join(\"\\n\");\n downloadFile(csvContent, `${exportFilename}.csv`, \"text/csv\");\n },\n [visibleColumns, downloadFile],\n );\n\n const exportToJSON = useCallback(\n (exportData: GridRow[], exportFilename: string) => {\n const jsonData = exportData.map((row) => {\n const cleanRow: Record<string, any> = {};\n visibleColumns.forEach((col) => {\n cleanRow[col.header] = row[col.key];\n });\n return cleanRow;\n });\n\n const jsonContent = JSON.stringify(jsonData, null, 2);\n downloadFile(jsonContent, `${exportFilename}.json`, \"application/json\");\n },\n [visibleColumns, downloadFile],\n );\n\n const exportToXLSX = useCallback(\n async (exportData: GridRow[], exportFilename: string) => {\n // Dynamic import to keep main bundle light\n const [ExcelJS, { saveAs }] = await Promise.all([\n import(\"exceljs\"),\n import(\"file-saver\"),\n ]);\n\n const workbook = new (ExcelJS.default || ExcelJS).Workbook();\n const sheet = workbook.addWorksheet(\"Data\");\n\n // Define columns with headers and keys; approximate widths by sampling\n const SAMPLE_COUNT = 50; // limit for width estimation\n const sampled = exportData.slice(0, SAMPLE_COUNT);\n\n const coerceValue = (v: any) => {\n if (v == null) return \"\";\n if (typeof v === \"number\") return v;\n if (typeof v === \"boolean\") return v;\n if (v instanceof Date) return v;\n const s = String(v);\n\n // If contains letters, keep as text (prevents CR-154, INV-123 conversion)\n if (/[a-zA-Z]/.test(s)) return s;\n\n // Only convert to number if purely numeric\n if (/^-?[\\d,]+\\.?\\d*$/.test(s.trim())) {\n const n = Number(s.replace(/,/g, \"\"));\n if (Number.isFinite(n)) return n;\n }\n\n return s;\n };\n\n // Compute widths in \"characters\" based on header and sample values\n const columnDefs = visibleColumns.map((col) => {\n const header = col.header || col.key;\n let maxLen = header?.length || 10;\n for (const row of sampled) {\n const raw = row[col.key];\n const s = raw == null ? \"\" : String(raw);\n if (s.length > maxLen) maxLen = s.length;\n }\n // ExcelJS width is approx in characters; clamp for readability\n const width = Math.max(8, Math.min(50, Math.ceil(maxLen * 1.1)));\n return { header, key: col.key, width };\n });\n\n sheet.columns = columnDefs as any;\n\n // Add rows\n for (const row of exportData) {\n const obj: Record<string, any> = {};\n for (const col of visibleColumns) {\n obj[col.key] = coerceValue(row[col.key]);\n }\n sheet.addRow(obj);\n }\n\n // Format header row bold\n const headerRow = sheet.getRow(1);\n headerRow.font = { bold: true };\n\n // Auto-filter\n sheet.autoFilter = {\n from: { row: 1, column: 1 },\n to: { row: Math.max(1, sheet.rowCount), column: visibleColumns.length },\n };\n\n const buffer = await workbook.xlsx.writeBuffer();\n const blob = new Blob([buffer], {\n type: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n });\n saveAs(blob, `${exportFilename}.xlsx`);\n },\n [visibleColumns],\n );\n\n const exportData = useCallback(\n (format: ExportFormat, exportSelected: boolean = false) => {\n const exportData =\n exportSelected && selectedRows && selectedRows.size > 0\n ? data.filter((row) => selectedRows.has(row.id))\n : data;\n\n const exportFilename =\n exportSelected && selectedRows && selectedRows.size > 0\n ? `${filename}_selected_${selectedRows.size}_rows`\n : filename;\n\n switch (format) {\n case \"csv\":\n exportToCSV(exportData, exportFilename);\n break;\n case \"json\":\n exportToJSON(exportData, exportFilename);\n break;\n case \"xlsx\":\n // Fire and forget\n void exportToXLSX(exportData, exportFilename);\n break;\n default:\n console.warn(`Unsupported export format: ${format}`);\n }\n },\n [data, selectedRows, filename, exportToCSV, exportToJSON, exportToXLSX],\n );\n\n const canExportSelected = selectedRows && selectedRows.size > 0;\n\n return {\n exportData,\n canExportSelected,\n selectedCount: selectedRows?.size || 0,\n };\n};\n"],"names":["useExport","data","columns","selectedRows","filename","columnVisibility","visibleColumns","filter","col","key","downloadFile","useCallback","content","fileName","mimeType","blob","Blob","type","url","URL","createObjectURL","link","document","createElement","href","download","body","appendChild","click","removeChild","revokeObjectURL","exportToCSV","exportData","exportFilename","csvContent","map","header","join","row","value","stringValue","String","includes","replace","exportToJSON","jsonData","cleanRow","forEach","jsonContent","JSON","stringify","exportToXLSX","async","ExcelJS","saveAs","Promise","all","import","workbook","default","Workbook","sheet","addWorksheet","sampled","slice","coerceValue","v","Date","s","test","trim","n","Number","isFinite","columnDefs","maxLen","length","raw","width","Math","max","min","ceil","obj","addRow","getRow","font","bold","autoFilter","from","column","to","rowCount","buffer","xlsx","writeBuffer","format","exportSelected","size","has","id","console","warn","canExportSelected","selectedCount"],"mappings":"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"}
@@ -1,16 +0,0 @@
1
- import { ChangeEvent } from "react";
2
- import { SortConfig, GridRow, GridColumn } from "../types";
3
- interface UseFilteringAndSortingProps {
4
- data: GridRow[];
5
- columns: GridColumn[];
6
- }
7
- export declare const useFilteringAndSorting: ({ data, columns, }: UseFilteringAndSortingProps) => {
8
- sortConfig: SortConfig;
9
- filters: Record<string, string>;
10
- globalFilter: string;
11
- filteredData: GridRow[];
12
- handleSort: (key: string) => void;
13
- handleFilter: (key: string, value: string) => void;
14
- handleGlobalFilterChange: (e: ChangeEvent<HTMLInputElement>) => void;
15
- };
16
- export {};
@@ -1,2 +0,0 @@
1
- import{useState as e,useDeferredValue as t,useMemo as r,useCallback as n}from"react";const o=({data:o,columns:l})=>{const[i,c]=e({key:null,direction:null}),[a,s]=e({}),[u,f]=e(""),d=t(u),m=t(a),y=r(()=>i.key?[...o].sort((e,t)=>{const r=e[i.key||""],n=t[i.key||""];if(null==r&&null==n)return 0;if(null==r)return"asc"===i.direction?-1:1;if(null==n)return"asc"===i.direction?1:-1;if("string"==typeof r&&"string"==typeof n)return"asc"===i.direction?r.localeCompare(n):n.localeCompare(r);if("number"==typeof r&&"number"==typeof n)return"asc"===i.direction?r-n:n-r;const o=String(r),l=String(n);return"asc"===i.direction?o.localeCompare(l):l.localeCompare(o)}):o,[o,i]),g=r(()=>{let e=y;if(Object.entries(m).forEach(([t,r])=>{if(r){const n=r.toLowerCase();e=e.filter(e=>{const r=e[t];return null!=r&&String(r).toLowerCase().includes(n)})}}),d){const t=d.toLowerCase();e=e.filter(e=>l.some(r=>{const n=e[r.key];return null!=n&&String(n).toLowerCase().includes(t)}))}return e},[y,m,d,l]),p=n(e=>{c(t=>({key:e,direction:t.key===e&&"asc"===t.direction?"desc":"asc"}))},[]),C=n((e,t)=>{s(r=>({...r,[e]:t}))},[]),k=r(()=>function(e,t){let r;return(...n)=>{clearTimeout(r),r=setTimeout(()=>e(...n),t)}}(e=>f(e),300),[]),b=n(e=>{k(e.target.value)},[k]);return{sortConfig:i,filters:a,globalFilter:u,filteredData:g,handleSort:p,handleFilter:C,handleGlobalFilterChange:b}};export{o as useFilteringAndSorting};
2
- //# sourceMappingURL=useFilteringAndSorting.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useFilteringAndSorting.js","sources":["../../../../../hooks/useFilteringAndSorting.ts"],"sourcesContent":["import {\n useState,\n useMemo,\n useCallback,\n useDeferredValue,\n ChangeEvent,\n} from \"react\";\nimport { SortConfig, GridRow, GridColumn } from \"../types\";\n\n// Debounce utility for performance optimization\nfunction debounce<T extends (...args: any[]) => any>(func: T, wait: number): T {\n let timeout: NodeJS.Timeout;\n return ((...args: any[]) => {\n clearTimeout(timeout);\n timeout = setTimeout(() => func(...args), wait);\n }) as T;\n}\n\ninterface UseFilteringAndSortingProps {\n data: GridRow[];\n columns: GridColumn[];\n}\n\nexport const useFilteringAndSorting = ({\n data,\n columns,\n}: UseFilteringAndSortingProps) => {\n const [sortConfig, setSortConfig] = useState<SortConfig>({\n key: null,\n direction: null,\n });\n const [filters, setFilters] = useState<Record<string, string>>({});\n const [globalFilter, setGlobalFilter] = useState<string>(\"\");\n\n // Use deferred values for better performance with large datasets\n const deferredGlobalFilter = useDeferredValue(globalFilter);\n const deferredFilters = useDeferredValue(filters);\n\n // Sorting logic\n const sortedData = useMemo(() => {\n if (!sortConfig.key) return data;\n\n return [...data].sort((a, b) => {\n const aValue = a[sortConfig.key || \"\"];\n const bValue = b[sortConfig.key || \"\"];\n\n if (aValue == null && bValue == null) return 0;\n if (aValue == null) return sortConfig.direction === \"asc\" ? -1 : 1;\n if (bValue == null) return sortConfig.direction === \"asc\" ? 1 : -1;\n\n if (typeof aValue === \"string\" && typeof bValue === \"string\") {\n return sortConfig.direction === \"asc\"\n ? aValue.localeCompare(bValue)\n : bValue.localeCompare(aValue);\n }\n\n if (typeof aValue === \"number\" && typeof bValue === \"number\") {\n return sortConfig.direction === \"asc\"\n ? aValue - bValue\n : bValue - aValue;\n }\n\n // Convert to strings for comparison if types don't match\n const aStr = String(aValue);\n const bStr = String(bValue);\n return sortConfig.direction === \"asc\"\n ? aStr.localeCompare(bStr)\n : bStr.localeCompare(aStr);\n });\n }, [data, sortConfig]);\n\n // Optimized filtering logic with deferred values\n const filteredData = useMemo(() => {\n let result = sortedData;\n\n // Column-specific filters\n Object.entries(deferredFilters).forEach(([key, value]) => {\n if (value) {\n const lowerValue = value.toLowerCase();\n result = result.filter((row) => {\n const cellValue = row[key];\n return (\n cellValue != null &&\n String(cellValue).toLowerCase().includes(lowerValue)\n );\n });\n }\n });\n\n // Global filter with optimized search\n if (deferredGlobalFilter) {\n const lowerGlobalFilter = deferredGlobalFilter.toLowerCase();\n result = result.filter((row) => {\n // Only search in visible columns for better performance\n return columns.some((column) => {\n const value = row[column.key];\n return (\n value != null &&\n String(value).toLowerCase().includes(lowerGlobalFilter)\n );\n });\n });\n }\n\n return result;\n }, [sortedData, deferredFilters, deferredGlobalFilter, columns]);\n\n // Handlers\n const handleSort = useCallback((key: string) => {\n setSortConfig((prev) => ({\n key,\n direction: prev.key === key && prev.direction === \"asc\" ? \"desc\" : \"asc\",\n }));\n }, []);\n\n const handleFilter = useCallback((key: string, value: string) => {\n setFilters((prev) => ({ ...prev, [key]: value }));\n }, []);\n\n // Debounced filter handler for better performance\n const debouncedSetGlobalFilter = useMemo(\n () => debounce((value: string) => setGlobalFilter(value), 300),\n []\n );\n\n const handleGlobalFilterChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n debouncedSetGlobalFilter(e.target.value);\n },\n [debouncedSetGlobalFilter]\n );\n\n return {\n sortConfig,\n filters,\n globalFilter,\n filteredData,\n handleSort,\n handleFilter,\n handleGlobalFilterChange,\n };\n};\n"],"names":["useFilteringAndSorting","data","columns","sortConfig","setSortConfig","useState","key","direction","filters","setFilters","globalFilter","setGlobalFilter","deferredGlobalFilter","useDeferredValue","deferredFilters","sortedData","useMemo","sort","a","b","aValue","bValue","localeCompare","aStr","String","bStr","filteredData","result","Object","entries","forEach","value","lowerValue","toLowerCase","filter","row","cellValue","includes","lowerGlobalFilter","some","column","handleSort","useCallback","prev","handleFilter","debouncedSetGlobalFilter","func","wait","timeout","args","clearTimeout","setTimeout","debounce","handleGlobalFilterChange","e","target"],"mappings":"qFAuBa,MAAAA,EAAyB,EACpCC,OACAC,cAEA,MAAOC,EAAYC,GAAiBC,EAAqB,CACvDC,IAAK,KACLC,UAAW,QAENC,EAASC,GAAcJ,EAAiC,CAAE,IAC1DK,EAAcC,GAAmBN,EAAiB,IAGnDO,EAAuBC,EAAiBH,GACxCI,EAAkBD,EAAiBL,GAGnCO,EAAaC,EAAQ,IACpBb,EAAWG,IAET,IAAIL,GAAMgB,KAAK,CAACC,EAAGC,KACxB,MAAMC,EAASF,EAAEf,EAAWG,KAAO,IAC7Be,EAASF,EAAEhB,EAAWG,KAAO,IAEnC,GAAc,MAAVc,GAA4B,MAAVC,EAAgB,OAAO,EAC7C,GAAc,MAAVD,EAAgB,MAAgC,QAAzBjB,EAAWI,WAAuB,EAAI,EACjE,GAAc,MAAVc,EAAgB,MAAgC,QAAzBlB,EAAWI,UAAsB,GAAK,EAEjE,GAAsB,iBAAXa,GAAyC,iBAAXC,EACvC,MAAgC,QAAzBlB,EAAWI,UACda,EAAOE,cAAcD,GACrBA,EAAOC,cAAcF,GAG3B,GAAsB,iBAAXA,GAAyC,iBAAXC,EACvC,MAAgC,QAAzBlB,EAAWI,UACda,EAASC,EACTA,EAASD,EAIf,MAAMG,EAAOC,OAAOJ,GACdK,EAAOD,OAAOH,GACpB,MAAgC,QAAzBlB,EAAWI,UACdgB,EAAKD,cAAcG,GACnBA,EAAKH,cAAcC,KA3BGtB,EA6B3B,CAACA,EAAME,IAGJuB,EAAeV,EAAQ,KAC3B,IAAIW,EAASZ,EAiBb,GAdAa,OAAOC,QAAQf,GAAiBgB,QAAQ,EAAExB,EAAKyB,MAC7C,GAAIA,EAAO,CACT,MAAMC,EAAaD,EAAME,cACzBN,EAASA,EAAOO,OAAQC,IACtB,MAAMC,EAAYD,EAAI7B,GACtB,OACe,MAAb8B,GACAZ,OAAOY,GAAWH,cAAcI,SAASL,IAG9C,IAICpB,EAAsB,CACxB,MAAM0B,EAAoB1B,EAAqBqB,cAC/CN,EAASA,EAAOO,OAAQC,GAEfjC,EAAQqC,KAAMC,IACnB,MAAMT,EAAQI,EAAIK,EAAOlC,KACzB,OACW,MAATyB,GACAP,OAAOO,GAAOE,cAAcI,SAASC,KAI5C,CAED,OAAOX,GACN,CAACZ,EAAYD,EAAiBF,EAAsBV,IAGjDuC,EAAaC,EAAapC,IAC9BF,EAAeuC,IAAU,CACvBrC,MACAC,UAAWoC,EAAKrC,MAAQA,GAA0B,QAAnBqC,EAAKpC,UAAsB,OAAS,UAEpE,IAEGqC,EAAeF,EAAY,CAACpC,EAAayB,KAC7CtB,EAAYkC,IAAI,IAAWA,EAAMrC,CAACA,GAAMyB,MACvC,IAGGc,EAA2B7B,EAC/B,IA/GJ,SAAqD8B,EAASC,GAC5D,IAAIC,EACJ,MAAQ,IAAIC,KACVC,aAAaF,GACbA,EAAUG,WAAW,IAAML,KAAQG,GAAOF,EAC3C,CACH,CAyGUK,CAAUrB,GAAkBpB,EAAgBoB,GAAQ,KAC1D,IAGIsB,EAA2BX,EAC9BY,IACCT,EAAyBS,EAAEC,OAAOxB,QAEpC,CAACc,IAGH,MAAO,CACL1C,aACAK,UACAE,eACAgB,eACAe,aACAG,eACAS"}
@@ -1,28 +0,0 @@
1
- import { GridRow, GroupConfig, GridColumn } from "../types";
2
- interface UseGroupingProps {
3
- data: GridRow[];
4
- columns: GridColumn[];
5
- }
6
- export declare const useGrouping: ({ data, columns }: UseGroupingProps) => {
7
- groupConfig: GroupConfig;
8
- displayData: (GridRow & {
9
- _isGroupHeader?: boolean;
10
- _groupKey?: string;
11
- _groupCount?: number;
12
- _groupLevel?: number;
13
- _groupColumnKey?: string;
14
- _groupValue?: string;
15
- _groupRows?: GridRow[];
16
- _isGroupFooter?: boolean;
17
- _groupAgg?: Record<string, any>;
18
- })[];
19
- handleGroupBy: (columnKey: string | null) => void;
20
- addGroupKey: (columnKey: string) => void;
21
- removeGroupKey: (columnKey: string) => void;
22
- setGroupKeys: (columnKeys: string[]) => void;
23
- toggleGroupExpansion: (groupPath: string) => void;
24
- expandAllGroups: () => void;
25
- collapseAllGroups: () => void;
26
- isGrouped: boolean;
27
- };
28
- export {};
@@ -1,2 +0,0 @@
1
- import{useState as e,useMemo as n,useEffect as t}from"react";const o=({data:o,columns:r})=>{const[s,a]=e({columnKeys:[],expanded:new Set}),u="Unknown",l=e=>e.join("|"),i=n(()=>{const e=s.columnKeys;if(!e.length)return o;const n=[],t=e=>{const n={};for(const t of r){if(!t.aggregate)continue;const o=e.map(e=>e[t.key]);let r=null;if("function"==typeof t.aggregate)try{r=t.aggregate(o)}catch(e){r=null}else{const e=e=>!!/^\d{4}-\d{2}-\d{2}$/.test(e)||(!!/^\d{2}-\d{2}-\d{4}$/.test(e)||(!!/^\d{4}\/\d{2}\/\d{2}$/.test(e)||(!!/^\d{2}\/\d{2}\/\d{4}$/.test(e)||!(!e.includes("-")&&!e.includes("/")||!Number.isFinite(Date.parse(e)))))),n=o.map(n=>{if("number"==typeof n)return n;if(null==n)return NaN;const t=String(n);if(e(t))return NaN;const o=parseFloat(t.replace(/,/g,""));return Number.isFinite(o)?o:NaN}).filter(e=>Number.isFinite(e)),s=()=>o.map(e=>{if(e instanceof Date)return e.getTime();if("string"==typeof e||"number"==typeof e){const n=Date.parse(String(e));return Number.isFinite(n)?n:NaN}return NaN}).filter(e=>Number.isFinite(e));if("sum"===t.aggregate||"avg"===t.aggregate)if(n.length)if("sum"===t.aggregate)r=n.reduce((e,n)=>e+n,0);else{r=n.reduce((e,n)=>e+n,0)/n.length}else r=null;else if("min"===t.aggregate||"max"===t.aggregate)if(n.length)r="min"===t.aggregate?Math.min(...n):Math.max(...n);else{const e=s();if(e.length){const n="min"===t.aggregate?Math.min(...e):Math.max(...e);r=new Date(n)}else r=null}}null!=r&&(n[t.key]=r)}return n},a=(o,r,i)=>{const g=e[r],c=new Map;for(const e of o){const n=String(e[g]??u),t=c.get(n);t?t.push(e):c.set(n,[e])}const d=Array.from(c.entries()).sort(([e],[n])=>e.localeCompare(n));for(const[o,u]of d){const c=[...i,`${g}=${o}`],d=l(c);n.push({id:`group-${d}`,_isGroupHeader:!0,_groupKey:d,_groupCount:u.length,_groupLevel:r,_groupColumnKey:g,_groupValue:o,_groupRows:u});if(!s.expanded.has(d))continue;if(r<e.length-1)a(u,r+1,c);else for(const e of u)n.push(e);const p=t(u);n.push({id:`group-footer-${d}`,_isGroupFooter:!0,_groupKey:d,_groupLevel:r,_groupAgg:p})}};return a(o,0,[]),n},[o,s.columnKeys,s.expanded]);t(()=>{if(!s.columnKeys.length)return;const e=s.columnKeys,n=new Set,t=(o,r,s)=>{const a=e[r],i=new Map;for(const e of o){const n=String(e[a]??u),t=i.get(n);t?t.push(e):i.set(n,[e])}for(const[o,u]of i.entries()){const i=[...s,`${a}=${o}`],g=l(i);n.add(g),r<e.length-1&&t(u,r+1,i)}};t(o,0,[]);let r=!1;if(n.size!==s.expanded.size)r=!0;else for(const e of n)if(!s.expanded.has(e)){r=!0;break}r&&a(e=>({...e,expanded:n}))},[s.columnKeys,o]);return{groupConfig:s,displayData:i,handleGroupBy:e=>{a({columnKeys:e?[e]:[],expanded:new Set})},addGroupKey:e=>{a(n=>n.columnKeys.includes(e)?n:{...n,columnKeys:[...n.columnKeys,e]})},removeGroupKey:e=>{a(n=>{const t=n.columnKeys.filter(n=>n!==e),o=new Set;for(const t of n.expanded)t.includes(`${e}=`)||o.add(t);return{columnKeys:t,expanded:o}})},setGroupKeys:e=>{a({columnKeys:[...e],expanded:new Set})},toggleGroupExpansion:e=>{a(n=>{const t=new Set(n.expanded);return t.has(e)?t.delete(e):t.add(e),{...n,expanded:t}})},expandAllGroups:()=>{const e=s.columnKeys;if(!e.length)return;const n=(t,o,r,s)=>{const a=e[o],i=new Map;for(const e of t){const n=String(e[a]??u),t=i.get(n);t?t.push(e):i.set(n,[e])}for(const[t,u]of i.entries()){const i=[...r,`${a}=${t}`],g=l(i);s.add(g),o<e.length-1&&n(u,o+1,i,s)}},t=new Set;n(o,0,[],t),a(e=>({...e,expanded:t}))},collapseAllGroups:()=>{a(e=>({...e,expanded:new Set}))},isGrouped:s.columnKeys.length>0}};export{o as useGrouping};
2
- //# sourceMappingURL=useGrouping.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useGrouping.js","sources":["../../../../../hooks/useGrouping.ts"],"sourcesContent":["import { useState, useMemo, useEffect } from \"react\";\nimport { GridRow, GroupConfig, GridColumn } from \"../types\";\n\ninterface UseGroupingProps {\n data: GridRow[];\n columns: GridColumn[];\n}\n\nexport const useGrouping = ({ data, columns }: UseGroupingProps) => {\n const [groupConfig, setGroupConfig] = useState<GroupConfig>({\n columnKeys: [],\n expanded: new Set<string>(),\n });\n\n type FlatRow = GridRow & {\n _isGroupHeader?: boolean;\n _groupKey?: string; // path string e.g. City=SF|Status=Open\n _groupCount?: number;\n _groupLevel?: number; // 0-based\n _groupColumnKey?: string;\n _groupValue?: string;\n _groupRows?: GridRow[];\n _isGroupFooter?: boolean;\n _groupAgg?: Record<string, any>;\n };\n\n const UNKNOWN = \"Unknown\";\n const buildPath = (parts: string[]) => parts.join(\"|\");\n\n // Build flattened rows with nested group headers based on columnKeys\n const displayData = useMemo<FlatRow[]>(() => {\n const keys = groupConfig.columnKeys;\n if (!keys.length) return data as FlatRow[];\n\n const flat: FlatRow[] = [];\n\n const computeAggregates = (rows: GridRow[]) => {\n const result: Record<string, any> = {};\n for (const col of columns) {\n if (!col.aggregate) continue;\n const values = rows.map((r) => (r as any)[col.key]);\n let aggVal: any = null;\n if (typeof col.aggregate === \"function\") {\n try {\n aggVal = col.aggregate(values);\n } catch (_) {\n aggVal = null;\n }\n } else {\n // Try numeric aggregation first\n const isDateLike = (s: string) => {\n // Common date formats: YYYY-MM-DD, DD-MM-YYYY, with '/' too\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(s)) return true;\n if (/^\\d{2}-\\d{2}-\\d{4}$/.test(s)) return true;\n if (/^\\d{4}\\/\\d{2}\\/\\d{2}$/.test(s)) return true;\n if (/^\\d{2}\\/\\d{2}\\/\\d{4}$/.test(s)) return true;\n // Fallback: if Date.parse works and the string contains '-' or '/'\n if (\n (s.includes(\"-\") || s.includes(\"/\")) &&\n Number.isFinite(Date.parse(s))\n )\n return true;\n return false;\n };\n\n const nums = values\n .map((v) => {\n if (typeof v === \"number\") return v;\n if (v == null) return NaN;\n const sv = String(v);\n // Prevent treating date-like strings as numbers (e.g., \"2025-01-01\" -> 2025)\n if (isDateLike(sv)) return NaN;\n const n = parseFloat(sv.replace(/,/g, \"\"));\n return Number.isFinite(n) ? n : NaN;\n })\n .filter((n) => Number.isFinite(n)) as number[];\n\n const tryDateNumbers = () => {\n // Convert date-like values to timestamps for min/max\n const dateNums = values\n .map((v) => {\n if (v instanceof Date) return v.getTime();\n if (typeof v === \"string\" || typeof v === \"number\") {\n const t = Date.parse(String(v));\n return Number.isFinite(t) ? t : NaN;\n }\n return NaN;\n })\n .filter((t) => Number.isFinite(t)) as number[];\n return dateNums;\n };\n\n if (col.aggregate === \"sum\" || col.aggregate === \"avg\") {\n if (nums.length) {\n if (col.aggregate === \"sum\")\n aggVal = nums.reduce((a, b) => a + b, 0);\n else {\n const s = nums.reduce((a, b) => a + b, 0);\n aggVal = s / nums.length;\n }\n } else {\n // Non-numeric data: skip sum/avg\n aggVal = null;\n }\n } else if (col.aggregate === \"min\" || col.aggregate === \"max\") {\n if (nums.length) {\n aggVal =\n col.aggregate === \"min\" ? Math.min(...nums) : Math.max(...nums);\n } else {\n const dateNums = tryDateNumbers();\n if (dateNums.length) {\n const picked =\n col.aggregate === \"min\"\n ? Math.min(...dateNums)\n : Math.max(...dateNums);\n aggVal = new Date(picked);\n } else {\n aggVal = null;\n }\n }\n }\n }\n if (aggVal !== null && aggVal !== undefined) {\n result[col.key] = aggVal;\n }\n }\n return result;\n };\n\n const recurse = (rows: GridRow[], level: number, pathParts: string[]) => {\n const colKey = keys[level];\n const map = new Map<string, GridRow[]>();\n for (const r of rows) {\n const str = String((r as any)[colKey] ?? UNKNOWN);\n const arr = map.get(str);\n if (arr) arr.push(r);\n else map.set(str, [r]);\n }\n const entries = Array.from(map.entries()).sort(([a], [b]) =>\n a.localeCompare(b),\n );\n for (const [value, groupRows] of entries) {\n const seg = `${colKey}=${value}`;\n const nextPath = [...pathParts, seg];\n const pathStr = buildPath(nextPath);\n flat.push({\n id: `group-${pathStr}`,\n _isGroupHeader: true,\n _groupKey: pathStr,\n _groupCount: groupRows.length,\n _groupLevel: level,\n _groupColumnKey: colKey,\n _groupValue: value,\n _groupRows: groupRows,\n } as FlatRow);\n\n const isExpanded = groupConfig.expanded.has(pathStr);\n if (!isExpanded) continue;\n if (level < keys.length - 1) {\n recurse(groupRows, level + 1, nextPath);\n } else {\n for (const r of groupRows) flat.push(r);\n }\n\n // Append footer with aggregates for this group\n const agg = computeAggregates(groupRows);\n flat.push({\n id: `group-footer-${pathStr}`,\n _isGroupFooter: true,\n _groupKey: pathStr,\n _groupLevel: level,\n _groupAgg: agg,\n } as FlatRow);\n }\n };\n\n recurse(data, 0, []);\n return flat;\n }, [data, groupConfig.columnKeys, groupConfig.expanded]);\n\n // Always keep groups expanded by default when grouping is active.\n useEffect(() => {\n if (!groupConfig.columnKeys.length) return;\n // Build full set of all possible group paths for current data + keys\n const keys = groupConfig.columnKeys;\n const allPaths = new Set<string>();\n const gather = (rows: GridRow[], level: number, parts: string[]) => {\n const colKey = keys[level];\n const map = new Map<string, GridRow[]>();\n for (const r of rows) {\n const str = String((r as any)[colKey] ?? UNKNOWN);\n const arr = map.get(str);\n if (arr) arr.push(r);\n else map.set(str, [r]);\n }\n for (const [value, groupRows] of map.entries()) {\n const seg = `${colKey}=${value}`;\n const next = [...parts, seg];\n const pathStr = buildPath(next);\n allPaths.add(pathStr);\n if (level < keys.length - 1) gather(groupRows, level + 1, next);\n }\n };\n gather(data, 0, []);\n // If expanded differs from allPaths, update\n let differs = false;\n if (allPaths.size !== groupConfig.expanded.size) differs = true;\n else {\n for (const p of allPaths)\n if (!groupConfig.expanded.has(p)) {\n differs = true;\n break;\n }\n }\n if (differs) {\n setGroupConfig((prev) => ({ ...prev, expanded: allPaths }));\n }\n }, [groupConfig.columnKeys, data]);\n\n // Single-key convenience API (back-compat)\n const handleGroupBy = (columnKey: string | null) => {\n setGroupConfig({\n columnKeys: columnKey ? [columnKey] : [],\n expanded: new Set(),\n });\n };\n\n // Multi-key operations\n const addGroupKey = (columnKey: string) => {\n setGroupConfig((prev) =>\n prev.columnKeys.includes(columnKey)\n ? prev\n : { ...prev, columnKeys: [...prev.columnKeys, columnKey] },\n );\n };\n\n const removeGroupKey = (columnKey: string) => {\n setGroupConfig((prev) => {\n const nextKeys = prev.columnKeys.filter((k) => k !== columnKey);\n const nextExpanded = new Set<string>();\n for (const p of prev.expanded)\n if (!p.includes(`${columnKey}=`)) nextExpanded.add(p);\n return { columnKeys: nextKeys, expanded: nextExpanded };\n });\n };\n\n const setGroupKeys = (columnKeys: string[]) => {\n setGroupConfig({ columnKeys: [...columnKeys], expanded: new Set() });\n };\n\n const toggleGroupExpansion = (groupPath: string) => {\n setGroupConfig((prev) => {\n const next = new Set(prev.expanded);\n if (next.has(groupPath)) next.delete(groupPath);\n else next.add(groupPath);\n return { ...prev, expanded: next };\n });\n };\n\n // Expand/collapse helpers\n const expandAllGroups = () => {\n const keys = groupConfig.columnKeys;\n if (!keys.length) return;\n // gather all group paths\n const gatherAllPaths = (\n rows: GridRow[],\n level: number,\n parts: string[],\n acc: Set<string>,\n ) => {\n const colKey = keys[level];\n const map = new Map<string, GridRow[]>();\n for (const r of rows) {\n const str = String((r as any)[colKey] ?? UNKNOWN);\n const arr = map.get(str);\n if (arr) arr.push(r);\n else map.set(str, [r]);\n }\n for (const [value, groupRows] of map.entries()) {\n const seg = `${colKey}=${value}`;\n const next = [...parts, seg];\n const pathStr = buildPath(next);\n acc.add(pathStr);\n if (level < keys.length - 1)\n gatherAllPaths(groupRows, level + 1, next, acc);\n }\n };\n const acc = new Set<string>();\n gatherAllPaths(data, 0, [], acc);\n setGroupConfig((prev) => ({ ...prev, expanded: acc }));\n };\n\n const collapseAllGroups = () => {\n setGroupConfig((prev) => ({ ...prev, expanded: new Set<string>() }));\n };\n\n return {\n groupConfig,\n displayData,\n handleGroupBy,\n addGroupKey,\n removeGroupKey,\n setGroupKeys,\n toggleGroupExpansion,\n expandAllGroups,\n collapseAllGroups,\n isGrouped: groupConfig.columnKeys.length > 0,\n };\n};\n"],"names":["useGrouping","data","columns","groupConfig","setGroupConfig","useState","columnKeys","expanded","Set","UNKNOWN","buildPath","parts","join","displayData","useMemo","keys","length","flat","computeAggregates","rows","result","col","aggregate","values","map","r","key","aggVal","_","isDateLike","s","test","includes","Number","isFinite","Date","parse","nums","v","NaN","sv","String","n","parseFloat","replace","filter","tryDateNumbers","getTime","t","reduce","a","b","Math","min","max","dateNums","picked","recurse","level","pathParts","colKey","Map","str","arr","get","push","set","entries","Array","from","sort","localeCompare","value","groupRows","nextPath","pathStr","id","_isGroupHeader","_groupKey","_groupCount","_groupLevel","_groupColumnKey","_groupValue","_groupRows","has","agg","_isGroupFooter","_groupAgg","useEffect","allPaths","gather","next","add","differs","size","p","prev","handleGroupBy","columnKey","addGroupKey","removeGroupKey","nextKeys","k","nextExpanded","setGroupKeys","toggleGroupExpansion","groupPath","delete","expandAllGroups","gatherAllPaths","acc","collapseAllGroups","isGrouped"],"mappings":"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"}
@@ -1,28 +0,0 @@
1
- import { PaginationConfig, GridRow } from "../types";
2
- interface UsePaginationProps {
3
- data: GridRow[];
4
- pagination?: {
5
- enabled?: boolean;
6
- mode?: "client" | "server";
7
- pageSize?: number;
8
- showPageSizeSelector?: boolean;
9
- pageSizeOptions?: number[];
10
- serverConfig?: {
11
- enabled: boolean;
12
- onPageChange: (page: number, pageSize: number) => Promise<void> | void;
13
- onPageSizeChange?: (pageSize: number) => Promise<void> | void;
14
- loading?: boolean;
15
- totalRows: number;
16
- };
17
- };
18
- }
19
- export declare const usePagination: ({ data, pagination }: UsePaginationProps) => {
20
- currentPage: number;
21
- resetPage: () => void;
22
- paginationConfig: PaginationConfig;
23
- paginatedData: GridRow[];
24
- isServerLoading: boolean;
25
- handlePageChange: (page: number) => Promise<void>;
26
- handlePageSizeChange: (newPageSize: number) => Promise<void>;
27
- };
28
- export {};
@@ -1,2 +0,0 @@
1
- import{useState as e,useCallback as a,useMemo as n}from"react";const r=({data:r,pagination:t})=>{const[o,i]=e(1),[g,s]=e(t?.pageSize||50),[l,c]=e(!1),d=a(()=>{i(1)},[]),h=n(()=>{const e=!1!==t?.enabled,a="server"===(t?.mode||"client")?t?.serverConfig?.totalRows||0:r.length,n=Math.ceil(a/g);return{enabled:e,pageSize:g,currentPage:o,totalPages:n,totalRows:a,showPageSizeSelector:!1!==t?.showPageSizeSelector,pageSizeOptions:t?.pageSizeOptions||[25,50,100,200,500]}},[t,g,o,r.length]),f=n(()=>{if(!h.enabled||"server"===t?.mode)return r;const e=(o-1)*g,a=e+g;return r.slice(e,a)},[r,o,g,h.enabled,t?.mode]),C=a(async e=>{if("server"===t?.mode&&t?.serverConfig?.onPageChange){c(!0);try{await t.serverConfig.onPageChange(e,g)}finally{c(!1)}}i(e)},[t,g]),P=a(async e=>{if("server"===t?.mode&&t?.serverConfig?.onPageSizeChange){c(!0);try{await t.serverConfig.onPageSizeChange(e)}finally{c(!1)}}s(e),i(1)},[t]);return{currentPage:o,resetPage:d,paginationConfig:h,paginatedData:f,isServerLoading:l,handlePageChange:C,handlePageSizeChange:P}};export{r as usePagination};
2
- //# sourceMappingURL=usePagination.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"usePagination.js","sources":["../../../../../hooks/usePagination.ts"],"sourcesContent":["import { useState, useMemo, useCallback } from \"react\";\nimport { PaginationConfig, GridRow } from \"../types\";\n\ninterface UsePaginationProps {\n data: GridRow[];\n pagination?: {\n enabled?: boolean;\n mode?: \"client\" | \"server\";\n pageSize?: number;\n showPageSizeSelector?: boolean;\n pageSizeOptions?: number[];\n serverConfig?: {\n enabled: boolean;\n onPageChange: (page: number, pageSize: number) => Promise<void> | void;\n onPageSizeChange?: (pageSize: number) => Promise<void> | void;\n loading?: boolean;\n totalRows: number;\n };\n };\n}\n\nexport const usePagination = ({ data, pagination }: UsePaginationProps) => {\n const [currentPage, setCurrentPage] = useState(1);\n const [pageSize, setPageSize] = useState(pagination?.pageSize || 50);\n const [isServerLoading, setIsServerLoading] = useState(false);\n\n const resetPage = useCallback(() => {\n setCurrentPage(1);\n }, []);\n\n const paginationConfig: PaginationConfig = useMemo(() => {\n const isEnabled = pagination?.enabled !== false;\n const mode = pagination?.mode || \"client\";\n const totalRows =\n mode === \"server\"\n ? pagination?.serverConfig?.totalRows || 0\n : data.length;\n const totalPages = Math.ceil(totalRows / pageSize);\n\n return {\n enabled: isEnabled,\n pageSize,\n currentPage,\n totalPages,\n totalRows,\n showPageSizeSelector: pagination?.showPageSizeSelector !== false,\n pageSizeOptions: pagination?.pageSizeOptions || [25, 50, 100, 200, 500],\n };\n }, [pagination, pageSize, currentPage, data.length]);\n\n const paginatedData = useMemo(() => {\n if (!paginationConfig.enabled || pagination?.mode === \"server\") {\n return data;\n }\n\n const startIndex = (currentPage - 1) * pageSize;\n const endIndex = startIndex + pageSize;\n return data.slice(startIndex, endIndex);\n }, [data, currentPage, pageSize, paginationConfig.enabled, pagination?.mode]);\n\n const handlePageChange = useCallback(\n async (page: number) => {\n if (\n pagination?.mode === \"server\" &&\n pagination?.serverConfig?.onPageChange\n ) {\n setIsServerLoading(true);\n try {\n await pagination.serverConfig.onPageChange(page, pageSize);\n } finally {\n setIsServerLoading(false);\n }\n }\n setCurrentPage(page);\n },\n [pagination, pageSize]\n );\n\n const handlePageSizeChange = useCallback(\n async (newPageSize: number) => {\n if (\n pagination?.mode === \"server\" &&\n pagination?.serverConfig?.onPageSizeChange\n ) {\n setIsServerLoading(true);\n try {\n await pagination.serverConfig.onPageSizeChange(newPageSize);\n } finally {\n setIsServerLoading(false);\n }\n }\n setPageSize(newPageSize);\n setCurrentPage(1);\n },\n [pagination]\n );\n\n return {\n currentPage,\n resetPage,\n paginationConfig,\n paginatedData,\n isServerLoading,\n handlePageChange,\n handlePageSizeChange,\n };\n};\n"],"names":["usePagination","data","pagination","currentPage","setCurrentPage","useState","pageSize","setPageSize","isServerLoading","setIsServerLoading","resetPage","useCallback","paginationConfig","useMemo","isEnabled","enabled","totalRows","mode","serverConfig","length","totalPages","Math","ceil","showPageSizeSelector","pageSizeOptions","paginatedData","startIndex","endIndex","slice","handlePageChange","async","page","onPageChange","handlePageSizeChange","newPageSize","onPageSizeChange"],"mappings":"+DAqBa,MAAAA,EAAgB,EAAGC,OAAMC,iBACpC,MAAOC,EAAaC,GAAkBC,EAAS,IACxCC,EAAUC,GAAeF,EAASH,GAAYI,UAAY,KAC1DE,EAAiBC,GAAsBJ,GAAS,GAEjDK,EAAYC,EAAY,KAC5BP,EAAe,IACd,IAEGQ,EAAqCC,EAAQ,KACjD,MAAMC,GAAoC,IAAxBZ,GAAYa,QAExBC,EACK,YAFEd,GAAYe,MAAQ,UAG3Bf,GAAYgB,cAAcF,WAAa,EACvCf,EAAKkB,OACLC,EAAaC,KAAKC,KAAKN,EAAYV,GAEzC,MAAO,CACLS,QAASD,EACTR,WACAH,cACAiB,aACAJ,YACAO,sBAA2D,IAArCrB,GAAYqB,qBAClCC,gBAAiBtB,GAAYsB,iBAAmB,CAAC,GAAI,GAAI,IAAK,IAAK,OAEpE,CAACtB,EAAYI,EAAUH,EAAaF,EAAKkB,SAEtCM,EAAgBZ,EAAQ,KAC5B,IAAKD,EAAiBG,SAAgC,WAArBb,GAAYe,KAC3C,OAAOhB,EAGT,MAAMyB,GAAcvB,EAAc,GAAKG,EACjCqB,EAAWD,EAAapB,EAC9B,OAAOL,EAAK2B,MAAMF,EAAYC,IAC7B,CAAC1B,EAAME,EAAaG,EAAUM,EAAiBG,QAASb,GAAYe,OAEjEY,EAAmBlB,EACvBmB,MAAOC,IACL,GACuB,WAArB7B,GAAYe,MACZf,GAAYgB,cAAcc,aAC1B,CACAvB,GAAmB,GACnB,UACQP,EAAWgB,aAAac,aAAaD,EAAMzB,EAClD,CAAS,QACRG,GAAmB,EACpB,CACF,CACDL,EAAe2B,IAEjB,CAAC7B,EAAYI,IAGT2B,EAAuBtB,EAC3BmB,MAAOI,IACL,GACuB,WAArBhC,GAAYe,MACZf,GAAYgB,cAAciB,iBAC1B,CACA1B,GAAmB,GACnB,UACQP,EAAWgB,aAAaiB,iBAAiBD,EAChD,CAAS,QACRzB,GAAmB,EACpB,CACF,CACDF,EAAY2B,GACZ9B,EAAe,IAEjB,CAACF,IAGH,MAAO,CACLC,cACAO,YACAE,mBACAa,gBACAjB,kBACAqB,mBACAI"}
@@ -1,13 +0,0 @@
1
- import { GridRow } from "../types";
2
- interface UseSelectionProps {
3
- data: GridRow[];
4
- selectedRowIds?: Iterable<string | number> | null;
5
- onRowSelect?: (row: GridRow) => void;
6
- getRowId?: (row: GridRow) => string | number;
7
- }
8
- export declare const useSelection: ({ data, selectedRowIds, onRowSelect, getRowId, }: UseSelectionProps) => {
9
- selectedRows: Set<string | number>;
10
- handleRowSelect: (rowId: string | number, isSelected: boolean) => void;
11
- handleSelectAll: (isSelected: boolean) => void;
12
- };
13
- export {};
@@ -1,2 +0,0 @@
1
- import{useCallback as e,useState as t,useEffect as o}from"react";const n=(e,t)=>{if(e.size!==t.size)return!1;for(const o of e)if(!t.has(o))return!1;return!0},r=({data:r,selectedRowIds:s,onRowSelect:a,getRowId:i})=>{const d=e((e,t)=>i?i(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),[i]),[c,w]=t(()=>new Set(s?Array.from(s):[]));o(()=>{s&&w(e=>{const t=new Set(Array.from(s));return n(e,t)?e:t})},[s]),o(()=>{const e=new Set(r.map((e,t)=>d(e,t)));w(t=>{const o=new Set;return t.forEach(t=>{e.has(t)&&o.add(t)}),n(t,o)?t:o})},[r,d]);return{selectedRows:c,handleRowSelect:e((e,t)=>{if(w(o=>{const n=new Set(o);return t?n.add(e):n.delete(e),n}),a){const t=r.find((t,o)=>d(t,o)===e);t&&a(t)}},[r,a,d]),handleSelectAll:e(e=>{w(e?new Set(r.map((e,t)=>d(e,t))):new Set)},[r,d])}};export{r as useSelection};
2
- //# sourceMappingURL=useSelection.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useSelection.js","sources":["../../../../../hooks/useSelection.ts"],"sourcesContent":["import { useState, useCallback, useEffect } from \"react\";\nimport { GridRow } from \"../types\";\n\ninterface UseSelectionProps {\n data: GridRow[];\n selectedRowIds?: Iterable<string | number> | null;\n onRowSelect?: (row: GridRow) => void;\n getRowId?: (row: GridRow) => string | number;\n}\n\nconst areSetsEqual = (a: Set<string | number>, b: Set<string | number>) => {\n if (a.size !== b.size) return false;\n for (const value of a) {\n if (!b.has(value)) return false;\n }\n return true;\n};\n\nexport const useSelection = ({\n data,\n selectedRowIds,\n onRowSelect,\n getRowId,\n}: UseSelectionProps) => {\n // Extract row IDs based on getRowId or fallback to row.id\n const extractRowId = useCallback(\n (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 [getRowId]\n );\n\n const [selectedRows, setSelectedRows] = useState<Set<string | number>>(\n () => new Set(selectedRowIds ? Array.from(selectedRowIds) : [])\n );\n\n useEffect(() => {\n if (!selectedRowIds) return;\n setSelectedRows((prev) => {\n const next = new Set(Array.from(selectedRowIds));\n if (areSetsEqual(prev, next)) return prev;\n return next;\n });\n }, [selectedRowIds]);\n\n useEffect(() => {\n const validIds = new Set(data.map((row, idx) => extractRowId(row, idx)));\n setSelectedRows((prev) => {\n const next = new Set<string | number>();\n prev.forEach((id) => {\n if (validIds.has(id)) next.add(id);\n });\n if (areSetsEqual(prev, next)) return prev;\n return next;\n });\n }, [data, extractRowId]);\n\n const handleRowSelect = useCallback(\n (rowId: string | number, isSelected: boolean) => {\n setSelectedRows((prev) => {\n const newSet = new Set(prev);\n if (isSelected) {\n newSet.add(rowId);\n } else {\n newSet.delete(rowId);\n }\n return newSet;\n });\n\n if (onRowSelect) {\n const row = data.find((item, idx) => extractRowId(item, idx) === rowId);\n if (row) onRowSelect(row);\n }\n },\n [data, onRowSelect, extractRowId]\n );\n\n const handleSelectAll = useCallback(\n (isSelected: boolean) => {\n if (isSelected) {\n setSelectedRows(new Set(data.map((row, idx) => extractRowId(row, idx))));\n } else {\n setSelectedRows(new Set());\n }\n },\n [data, extractRowId]\n );\n\n return {\n selectedRows,\n handleRowSelect,\n handleSelectAll,\n };\n};\n"],"names":["areSetsEqual","a","b","size","value","has","useSelection","data","selectedRowIds","onRowSelect","getRowId","extractRowId","useCallback","row","rowIndex","undefined","id","process","env","NODE_ENV","console","warn","selectedRows","setSelectedRows","useState","Set","Array","from","useEffect","prev","next","validIds","map","idx","forEach","add","handleRowSelect","rowId","isSelected","newSet","delete","find","item","handleSelectAll"],"mappings":"iEAUA,MAAMA,EAAe,CAACC,EAAyBC,KAC7C,GAAID,EAAEE,OAASD,EAAEC,KAAM,OAAO,EAC9B,IAAK,MAAMC,KAASH,EAClB,IAAKC,EAAEG,IAAID,GAAQ,OAAO,EAE5B,OAAO,GAGIE,EAAe,EAC1BC,OACAC,iBACAC,cACAC,eAGA,MAAMC,EAAeC,EACnB,CAACC,EAAcC,IACTJ,EACKA,EAASG,QAEHE,IAAXF,EAAIG,GACCH,EAAIG,IAGgB,gBAAzBC,QAAQC,IAAIC,UAA2C,IAAbL,GAC5CM,QAAQC,KACN,mPAMGP,GAAY,GAErB,CAACJ,KAGIY,EAAcC,GAAmBC,EACtC,IAAM,IAAIC,IAAIjB,EAAiBkB,MAAMC,KAAKnB,GAAkB,KAG9DoB,EAAU,KACHpB,GACLe,EAAiBM,IACf,MAAMC,EAAO,IAAIL,IAAIC,MAAMC,KAAKnB,IAChC,OAAIR,EAAa6B,EAAMC,GAAcD,EAC9BC,KAER,CAACtB,IAEJoB,EAAU,KACR,MAAMG,EAAW,IAAIN,IAAIlB,EAAKyB,IAAI,CAACnB,EAAKoB,IAAQtB,EAAaE,EAAKoB,KAClEV,EAAiBM,IACf,MAAMC,EAAO,IAAIL,IAIjB,OAHAI,EAAKK,QAASlB,IACRe,EAAS1B,IAAIW,IAAKc,EAAKK,IAAInB,KAE7BhB,EAAa6B,EAAMC,GAAcD,EAC9BC,KAER,CAACvB,EAAMI,IAiCV,MAAO,CACLW,eACAc,gBAjCsBxB,EACtB,CAACyB,EAAwBC,KAWvB,GAVAf,EAAiBM,IACf,MAAMU,EAAS,IAAId,IAAII,GAMvB,OALIS,EACFC,EAAOJ,IAAIE,GAEXE,EAAOC,OAAOH,GAETE,IAGL9B,EAAa,CACf,MAAMI,EAAMN,EAAKkC,KAAK,CAACC,EAAMT,IAAQtB,EAAa+B,EAAMT,KAASI,GAC7DxB,GAAKJ,EAAYI,EACtB,GAEH,CAACN,EAAME,EAAaE,IAiBpBgC,gBAdsB/B,EACrB0B,IAEGf,EADEe,EACc,IAAIb,IAAIlB,EAAKyB,IAAI,CAACnB,EAAKoB,IAAQtB,EAAaE,EAAKoB,KAEjD,IAAIR,MAGxB,CAAClB,EAAMI"}
@@ -1,17 +0,0 @@
1
- import { UIEvent } from "react";
2
- import { VirtualizedRange, GridRow } from "../types";
3
- interface UseVirtualizationProps {
4
- data: GridRow[];
5
- virtualized?: boolean;
6
- rowHeight?: number;
7
- overscan?: number;
8
- height: number;
9
- }
10
- export declare const useVirtualization: ({ data, virtualized, rowHeight, overscan, height, }: UseVirtualizationProps) => {
11
- scrollRef: import("react").MutableRefObject<HTMLDivElement>;
12
- virtualizedRange: VirtualizedRange;
13
- visibleData: GridRow[];
14
- totalHeight: number;
15
- handleScroll: (e: UIEvent<HTMLDivElement>) => void;
16
- };
17
- export {};
@@ -1,2 +0,0 @@
1
- import{useRef as t,useState as e,useMemo as n,useCallback as r,useEffect as a}from"react";const l=({data:l,virtualized:c=!0,rowHeight:i=40,overscan:o=10,height:h})=>{const u=t(null),[s,d]=e(0),m=t(null),x=t(0),[g,M]=e(h),f=n(()=>{if(!c)return{startIndex:0,endIndex:l.length-1,offsetY:0};const t=Math.max(1,Math.ceil(g/i)),e=Math.max(o,Math.max(8,Math.min(2*t,50))),n=Math.max(0,Math.floor(s/i)-e),r=Math.ceil(g/i);return{startIndex:n,endIndex:Math.min(l.length-1,n+r+2*e),offsetY:n*i}},[s,g,l.length,i,o,c]),I=n(()=>c?l.slice(f.startIndex,f.endIndex+1):l,[l,f,c]),v=l.length*i,p=r(t=>{const e=t.target.scrollTop;x.current=e,null==m.current&&(m.current=requestAnimationFrame(()=>{m.current=null,d(x.current)}))},[]);return a(()=>()=>{null!=m.current&&cancelAnimationFrame(m.current)},[]),a(()=>{M(h)},[h]),{scrollRef:u,virtualizedRange:f,visibleData:I,totalHeight:v,handleScroll:p}};export{l as useVirtualization};
2
- //# sourceMappingURL=useVirtualization.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useVirtualization.js","sources":["../../../../../hooks/useVirtualization.ts"],"sourcesContent":["import {\n useState,\n useMemo,\n useCallback,\n useEffect,\n useRef,\n UIEvent,\n} from \"react\";\nimport { VirtualizedRange, GridRow } from \"../types\";\n\ninterface UseVirtualizationProps {\n data: GridRow[];\n virtualized?: boolean;\n rowHeight?: number;\n overscan?: number;\n height: number;\n}\n\nexport const useVirtualization = ({\n data,\n virtualized = true,\n rowHeight = 40,\n overscan = 10,\n height,\n}: UseVirtualizationProps) => {\n const scrollRef = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState(0);\n const rafIdRef = useRef<number | null>(null);\n const pendingScrollTopRef = useRef<number>(0);\n const [containerHeight, setContainerHeight] = useState(height);\n\n const virtualizedRange = useMemo((): VirtualizedRange => {\n if (!virtualized) {\n return {\n startIndex: 0,\n endIndex: data.length - 1,\n offsetY: 0,\n };\n }\n\n // Dynamic overscan scaled by viewport height (rows in view)\n const rowsInView = Math.max(1, Math.ceil(containerHeight / rowHeight));\n const dynamicOverscan = Math.max(\n overscan,\n Math.max(8, Math.min(rowsInView * 2, 50))\n );\n\n const startIndex = Math.max(\n 0,\n Math.floor(scrollTop / rowHeight) - dynamicOverscan\n );\n const visibleCount = Math.ceil(containerHeight / rowHeight);\n const endIndex = Math.min(\n data.length - 1,\n startIndex + visibleCount + dynamicOverscan * 2\n );\n\n const offsetY = startIndex * rowHeight;\n return { startIndex, endIndex, offsetY };\n }, [\n scrollTop,\n containerHeight,\n data.length,\n rowHeight,\n overscan,\n virtualized,\n ]);\n\n const visibleData = useMemo(() => {\n if (!virtualized) return data;\n return data.slice(\n virtualizedRange.startIndex,\n virtualizedRange.endIndex + 1\n );\n }, [data, virtualizedRange, virtualized]);\n\n const totalHeight = data.length * rowHeight;\n\n const handleScroll = useCallback((e: UIEvent<HTMLDivElement>) => {\n const target = e.target as HTMLDivElement;\n const nextTop = target.scrollTop;\n pendingScrollTopRef.current = nextTop;\n if (rafIdRef.current == null) {\n rafIdRef.current = requestAnimationFrame(() => {\n rafIdRef.current = null;\n setScrollTop(pendingScrollTopRef.current);\n });\n }\n }, []);\n\n useEffect(() => {\n return () => {\n if (rafIdRef.current != null) cancelAnimationFrame(rafIdRef.current);\n };\n }, []);\n\n useEffect(() => {\n setContainerHeight(height);\n }, [height]);\n\n return {\n scrollRef,\n virtualizedRange,\n visibleData,\n totalHeight,\n handleScroll,\n };\n};\n"],"names":["useVirtualization","data","virtualized","rowHeight","overscan","height","scrollRef","useRef","scrollTop","setScrollTop","useState","rafIdRef","pendingScrollTopRef","containerHeight","setContainerHeight","virtualizedRange","useMemo","startIndex","endIndex","length","offsetY","rowsInView","Math","max","ceil","dynamicOverscan","min","floor","visibleCount","visibleData","slice","totalHeight","handleScroll","useCallback","e","nextTop","target","current","requestAnimationFrame","useEffect","cancelAnimationFrame"],"mappings":"gGAkBaA,EAAoB,EAC/BC,OACAC,eAAc,EACdC,YAAY,GACZC,WAAW,GACXC,aAEA,MAAMC,EAAYC,EAAuB,OAClCC,EAAWC,GAAgBC,EAAS,GACrCC,EAAWJ,EAAsB,MACjCK,EAAsBL,EAAe,IACpCM,EAAiBC,GAAsBJ,EAASL,GAEjDU,EAAmBC,EAAQ,KAC/B,IAAKd,EACH,MAAO,CACLe,WAAY,EACZC,SAAUjB,EAAKkB,OAAS,EACxBC,QAAS,GAKb,MAAMC,EAAaC,KAAKC,IAAI,EAAGD,KAAKE,KAAKX,EAAkBV,IACrDsB,EAAkBH,KAAKC,IAC3BnB,EACAkB,KAAKC,IAAI,EAAGD,KAAKI,IAAiB,EAAbL,EAAgB,MAGjCJ,EAAaK,KAAKC,IACtB,EACAD,KAAKK,MAAMnB,EAAYL,GAAasB,GAEhCG,EAAeN,KAAKE,KAAKX,EAAkBV,GAOjD,MAAO,CAAEc,aAAYC,SANJI,KAAKI,IACpBzB,EAAKkB,OAAS,EACdF,EAAaW,EAAiC,EAAlBH,GAICL,QADfH,EAAad,IAE5B,CACDK,EACAK,EACAZ,EAAKkB,OACLhB,EACAC,EACAF,IAGI2B,EAAcb,EAAQ,IACrBd,EACED,EAAK6B,MACVf,EAAiBE,WACjBF,EAAiBG,SAAW,GAHLjB,EAKxB,CAACA,EAAMc,EAAkBb,IAEtB6B,EAAc9B,EAAKkB,OAAShB,EAE5B6B,EAAeC,EAAaC,IAChC,MACMC,EADSD,EAAEE,OACM5B,UACvBI,EAAoByB,QAAUF,EACN,MAApBxB,EAAS0B,UACX1B,EAAS0B,QAAUC,sBAAsB,KACvC3B,EAAS0B,QAAU,KACnB5B,EAAaG,EAAoByB,aAGpC,IAYH,OAVAE,EAAU,IACD,KACmB,MAApB5B,EAAS0B,SAAiBG,qBAAqB7B,EAAS0B,UAE7D,IAEHE,EAAU,KACRzB,EAAmBT,IAClB,CAACA,IAEG,CACLC,YACAS,mBACAc,cACAE,cACAC"}
@@ -1,11 +0,0 @@
1
- export { default as CustomDataGrid } from "./CustomGrid";
2
- export * from "./types";
3
- export { usePagination } from "./hooks/usePagination";
4
- export { useVirtualization } from "./hooks/useVirtualization";
5
- export { useFilteringAndSorting } from "./hooks/useFilteringAndSorting";
6
- export { useSelection } from "./hooks/useSelection";
7
- export { PaginationControls } from "./components/PaginationControls";
8
- export { GridHeader } from "./components/GridHeader";
9
- export { GridRows } from "./components/GridRows";
10
- export { SearchToolbar } from "./components/SearchToolbar";
11
- export { FooterAggregate } from "./components/FooterAggregate";
package/dist/esm/index.js DELETED
@@ -1,2 +0,0 @@
1
- export{CustomDataGrid}from"./CustomGrid.js";export{usePagination}from"./hooks/usePagination.js";export{useVirtualization}from"./hooks/useVirtualization.js";export{useFilteringAndSorting}from"./hooks/useFilteringAndSorting.js";export{useSelection}from"./hooks/useSelection.js";export{PaginationControls}from"./components/PaginationControls.js";export{GridHeader}from"./components/GridHeader.js";export{GridRows}from"./components/GridRows.js";export{SearchToolbar}from"./components/SearchToolbar.js";export{FooterAggregate}from"./components/FooterAggregate.js";
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}