@toolbox-web/grid 2.1.1 → 2.3.0

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 (90) hide show
  1. package/all.js +2 -2
  2. package/all.js.map +1 -1
  3. package/custom-elements.json +21 -2
  4. package/index.js +1 -1
  5. package/index.js.map +1 -1
  6. package/lib/core/adapter-conformance.d.ts +23 -0
  7. package/lib/core/constants.d.ts +18 -0
  8. package/lib/core/grid.d.ts +13 -15
  9. package/lib/core/internal/value-accessor.d.ts +33 -0
  10. package/lib/core/types.d.ts +186 -12
  11. package/lib/plugins/clipboard/index.js +1 -1
  12. package/lib/plugins/clipboard/index.js.map +1 -1
  13. package/lib/plugins/column-virtualization/index.js.map +1 -1
  14. package/lib/plugins/context-menu/index.js.map +1 -1
  15. package/lib/plugins/editing/index.js +1 -1
  16. package/lib/plugins/editing/index.js.map +1 -1
  17. package/lib/plugins/export/index.js +1 -1
  18. package/lib/plugins/export/index.js.map +1 -1
  19. package/lib/plugins/filtering/FilteringPlugin.d.ts +19 -1
  20. package/lib/plugins/filtering/index.js +1 -1
  21. package/lib/plugins/filtering/index.js.map +1 -1
  22. package/lib/plugins/grouping-columns/index.js.map +1 -1
  23. package/lib/plugins/grouping-rows/index.js +2 -2
  24. package/lib/plugins/grouping-rows/index.js.map +1 -1
  25. package/lib/plugins/master-detail/index.js +1 -1
  26. package/lib/plugins/master-detail/index.js.map +1 -1
  27. package/lib/plugins/multi-sort/index.js +1 -1
  28. package/lib/plugins/multi-sort/index.js.map +1 -1
  29. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +1 -1
  30. package/lib/plugins/pinned-columns/index.js +1 -1
  31. package/lib/plugins/pinned-columns/index.js.map +1 -1
  32. package/lib/plugins/pinned-columns/types.d.ts +7 -0
  33. package/lib/plugins/pinned-rows/index.js +1 -1
  34. package/lib/plugins/pinned-rows/index.js.map +1 -1
  35. package/lib/plugins/pivot/index.js.map +1 -1
  36. package/lib/plugins/print/index.js +1 -1
  37. package/lib/plugins/print/index.js.map +1 -1
  38. package/lib/plugins/reorder-columns/ReorderPlugin.d.ts +13 -1
  39. package/lib/plugins/reorder-columns/column-drag.d.ts +7 -1
  40. package/lib/plugins/reorder-columns/index.js +1 -1
  41. package/lib/plugins/reorder-columns/index.js.map +1 -1
  42. package/lib/plugins/reorder-columns/types.d.ts +12 -0
  43. package/lib/plugins/reorder-rows/index.js +1 -1
  44. package/lib/plugins/reorder-rows/index.js.map +1 -1
  45. package/lib/plugins/responsive/index.js.map +1 -1
  46. package/lib/plugins/selection/index.js +1 -1
  47. package/lib/plugins/selection/index.js.map +1 -1
  48. package/lib/plugins/selection/types.d.ts +8 -0
  49. package/lib/plugins/server-side/ServerSidePlugin.d.ts +4 -0
  50. package/lib/plugins/server-side/index.js +1 -1
  51. package/lib/plugins/server-side/index.js.map +1 -1
  52. package/lib/plugins/server-side/types.d.ts +48 -0
  53. package/lib/plugins/tooltip/index.js.map +1 -1
  54. package/lib/plugins/tree/index.js.map +1 -1
  55. package/lib/plugins/undo-redo/index.js.map +1 -1
  56. package/lib/plugins/visibility/VisibilityPlugin.d.ts +11 -1
  57. package/lib/plugins/visibility/index.js +1 -1
  58. package/lib/plugins/visibility/index.js.map +1 -1
  59. package/package.json +1 -1
  60. package/public.d.ts +5 -1
  61. package/umd/grid.all.umd.js +1 -1
  62. package/umd/grid.all.umd.js.map +1 -1
  63. package/umd/grid.umd.js +1 -1
  64. package/umd/grid.umd.js.map +1 -1
  65. package/umd/plugins/clipboard.umd.js +1 -1
  66. package/umd/plugins/clipboard.umd.js.map +1 -1
  67. package/umd/plugins/editing.umd.js +1 -1
  68. package/umd/plugins/editing.umd.js.map +1 -1
  69. package/umd/plugins/export.umd.js +1 -1
  70. package/umd/plugins/export.umd.js.map +1 -1
  71. package/umd/plugins/filtering.umd.js +1 -1
  72. package/umd/plugins/filtering.umd.js.map +1 -1
  73. package/umd/plugins/multi-sort.umd.js +1 -1
  74. package/umd/plugins/multi-sort.umd.js.map +1 -1
  75. package/umd/plugins/pinned-columns.umd.js +1 -1
  76. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  77. package/umd/plugins/pinned-rows.umd.js +1 -1
  78. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  79. package/umd/plugins/print.umd.js +1 -1
  80. package/umd/plugins/print.umd.js.map +1 -1
  81. package/umd/plugins/reorder-columns.umd.js +1 -1
  82. package/umd/plugins/reorder-columns.umd.js.map +1 -1
  83. package/umd/plugins/reorder-rows.umd.js +1 -1
  84. package/umd/plugins/reorder-rows.umd.js.map +1 -1
  85. package/umd/plugins/selection.umd.js +1 -1
  86. package/umd/plugins/selection.umd.js.map +1 -1
  87. package/umd/plugins/server-side.umd.js +1 -1
  88. package/umd/plugins/server-side.umd.js.map +1 -1
  89. package/umd/plugins/visibility.umd.js +1 -1
  90. package/umd/plugins/visibility.umd.js.map +1 -1
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("../../core/plugin/base-plugin")):"function"==typeof define&&define.amd?define(["exports","../../core/plugin/base-plugin"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TbwGridPlugin_export={},e.TbwGrid)}(this,function(e,t){"use strict";function n(e,t){return t?.length?[...t].sort((e,t)=>e-t).map(t=>e[t]).filter(e=>null!=e):e}function o(e,t=!0){if(null==e)return"";if(e instanceof Date)return e.toISOString();if("object"==typeof e)return JSON.stringify(e);const n=String(e);return t&&(n.includes(",")||n.includes('"')||n.includes("\n")||n.includes("\r"))?`"${n.replace(/"/g,'""')}"`:n}function r(e,t){const n=URL.createObjectURL(e),o=document.createElement("a");o.href=n,o.download=t,o.style.display="none",document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(n)}function s(e){return JSON.stringify(l(e))}function l(e){if(null==e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(l);const t={};for(const n of Object.keys(e).sort())t[n]=l(e[n]);return t}class i{#e=new Map;#t=0;register(e){const t=s(e),n=this.#e.get(t);if(n)return n.id;this.#t++;const o=`s${this.#t}`;return this.#e.set(t,{id:o,style:e}),o}getStyleId(e){return this.#e.get(s(e))?.id}get size(){return this.#e.size}toXml(){if(0===this.#e.size)return"";let e="\n<Styles>";for(const{id:t,style:n}of this.#e.values())e+=c(t,n);return e+="\n</Styles>",e}}function c(e,t){let n=`\n<Style ss:ID="${e}">`;if(t.font&&(n+="<Font",t.font.name&&(n+=` ss:FontName="${t.font.name}"`),t.font.size&&(n+=` ss:Size="${t.font.size}"`),t.font.bold&&(n+=' ss:Bold="1"'),t.font.italic&&(n+=' ss:Italic="1"'),t.font.color&&(n+=` ss:Color="${t.font.color}"`),n+="/>"),t.fill){const e=t.fill.pattern??"Solid";n+=`<Interior ss:Color="${t.fill.color}" ss:Pattern="${e}"/>`}return t.numberFormat&&(n+=`<NumberFormat ss:Format="${t.numberFormat}"/>`),t.alignment&&(n+="<Alignment",t.alignment.horizontal&&(n+=` ss:Horizontal="${t.alignment.horizontal}"`),t.alignment.vertical&&(n+=` ss:Vertical="${t.alignment.vertical}"`),t.alignment.wrapText&&(n+=' ss:WrapText="1"'),n+="/>"),t.borders&&(n+="<Borders>",t.borders.top&&(n+=f("Top",t.borders.top)),t.borders.bottom&&(n+=f("Bottom",t.borders.bottom)),t.borders.left&&(n+=f("Left",t.borders.left)),t.borders.right&&(n+=f("Right",t.borders.right)),n+="</Borders>"),n+="</Style>",n}function f(e,t){let n=`<Border ss:Position="${e}" ss:LineStyle="Continuous" ss:Weight="${function(e){switch(e){case"Thin":return 1;case"Medium":return 2;case"Thick":return 3}}(t.style)}"`;return t.color&&(n+=` ss:Color="${t.color}"`),n+="/>",n}function a(e,t,n,o,r){if(t.cellStyle){const s=t.cellStyle(n,o,r);if(s)return e.register(s)}const s=t.columnStyles?.[o];return s?e.getStyleId(s):t.defaultStyle?e.getStyleId(t.defaultStyle):void 0}function u(e,t){const n=Math.min(t.length,50);let o=(e.header??e.field).length;for(let r=0;r<n;r++){const n=t[r][e.field],s=null==n?0:String(n).length;s>o&&(o=s)}return o+2}function d(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function p(e,t,n){const o=n.excelStyles,r=o?function(e){const t=new i;if(e.headerStyle&&t.register(e.headerStyle),e.defaultStyle&&t.register(e.defaultStyle),e.columnStyles)for(const n of Object.values(e.columnStyles))t.register(n);return t}(o):void 0;let s='<?xml version="1.0" encoding="UTF-8"?>\n<?mso-application progid="Excel.Sheet"?>\n<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"\n xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">';if(r){if(o.cellStyle)for(const n of e)for(const e of t){const t=n[e.field],s=o.cellStyle(t,e.field,n);s&&r.register(s)}s+=r.toXml()}s+='\n<Worksheet ss:Name="Sheet1">\n<Table>',o&&(s+=function(e,t,n){const o=n.columnWidths,r=n.autoFitColumns;if(!o&&!r)return"";let s="";for(const l of e){let e=o?.[l.field];null==e&&r&&(e=u(l,t)),s+=null!=e?`\n<Column ss:Width="${7*e}"/>`:"\n<Column/>"}return s}(t,e,o));const l=o?.headerStyle&&r?r.getStyleId(o.headerStyle):void 0;if(!1!==n.includeHeaders){s+="\n<Row>";for(const e of t){const t=e.header||e.field;s+=`<Cell${l?` ss:StyleID="${l}"`:""}><Data ss:Type="String">${d(n.processHeader?n.processHeader(t,e.field):t)}</Data></Cell>`}s+="</Row>"}for(const i of e){s+="\n<Row>";for(const e of t){let t=i[e.field];n.processCell&&(t=n.processCell(t,e.field,i));let l="String",c="";null==t?c="":"number"!=typeof t||isNaN(t)?t instanceof Date?(l="DateTime",c=t.toISOString()):c=d(String(t)):(l="Number",c=String(t));const f=r&&o?a(r,o,t,e.field,i):void 0;s+=`<Cell${f?` ss:StyleID="${f}"`:""}><Data ss:Type="${l}">${c}</Data></Cell>`}s+="</Row>"}return s+="\n</Table>\n</Worksheet>\n</Workbook>",s}class m extends t.BaseGridPlugin{static manifest={queries:[{type:"export:csv",description:"Triggers a CSV export"}]};name="export";get defaultConfig(){return{fileName:"export",includeHeaders:!0,onlyVisible:!0,onlySelected:!1}}isExportingFlag=!1;lastExportInfo=null;handleQuery(e){if("export:csv"===e.type)return this.exportCsv(),!0}performExport(e,t){const s=this.config,l={format:e,fileName:t?.fileName??s.fileName??"export",includeHeaders:t?.includeHeaders??s.includeHeaders,processCell:t?.processCell,processHeader:t?.processHeader,columns:t?.columns,rowIndices:t?.rowIndices,excelStyles:t?.excelStyles,fileExtension:t?.fileExtension},i=function(e,t,n=!0){let o=e;if(n&&(o=o.filter(e=>!e.hidden&&!e.field.startsWith("__")&&!0!==e.meta?.utility)),t?.length){const e=new Set(t);o=o.filter(t=>e.has(t.field))}return o}(this.columns,t?.columns,s.onlyVisible);let c;if(t?.rowIndices)c=n(this.rows,t.rowIndices);else if(s.onlySelected){const e=this.getSelectionState();c=e?.selected?.size?n(this.rows,[...e.selected]):[...this.rows]}else c=[...this.rows];this.isExportingFlag=!0;let f=l.fileName;try{switch(e){case"csv":{const e=function(e,t,n,r={}){const s=r.delimiter??",",l=r.newline??"\n",i=[],c=r.bom?"\ufeff":"";if(!1!==n.includeHeaders){const e=t.map(e=>{const t=e.header||e.field;return o(n.processHeader?n.processHeader(t,e.field):t)});i.push(e.join(s))}for(const f of e){const e=t.map(e=>{let t=f[e.field];return n.processCell&&(t=n.processCell(t,e.field,f)),o(t)});i.push(e.join(s))}return c+i.join(l)}(c,i,l,{bom:!0});f=f.endsWith(".csv")?f:`${f}.csv`,function(e,t){r(new Blob([e],{type:"text/csv;charset=utf-8;"}),t)}(e,f);break}case"excel":{const e=p(c,i,l),t=l.fileExtension??".xls",n=t.startsWith(".")?t:`.${t}`;f=f.endsWith(n)?f:`${f}${n}`,function(e,t){r(new Blob([e],{type:"application/vnd.ms-excel;charset=utf-8;"}),t)}(e,f);break}case"json":{const e=c.map(e=>{const t={};for(const n of i){let o=e[n.field];l.processCell&&(o=l.processCell(o,n.field,e)),t[n.field]=o}return t}),t=JSON.stringify(e,null,2);f=f.endsWith(".json")?f:`${f}.json`;r(new Blob([t],{type:"application/json"}),f);break}}this.lastExportInfo={format:e,timestamp:new Date},this.emit("export-complete",{format:e,fileName:f,rowCount:c.length,columnCount:i.length})}finally{this.isExportingFlag=!1}}getSelectionState(){try{return this.grid?.getPluginState?.("selection")??null}catch{return null}}exportCsv(e){this.performExport("csv",e)}exportExcel(e){this.performExport("excel",e)}exportJson(e){this.performExport("json",e)}isExporting(){return this.isExportingFlag}getLastExport(){return this.lastExportInfo}}e.ExportPlugin=m,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("../../core/internal/value-accessor"),require("../../core/plugin/base-plugin")):"function"==typeof define&&define.amd?define(["exports","../../core/internal/value-accessor","../../core/plugin/base-plugin"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TbwGridPlugin_export={},e.TbwGrid,e.TbwGrid)}(this,function(e,t,n){"use strict";function o(e,t){return t?.length?[...t].sort((e,t)=>e-t).map(t=>e[t]).filter(e=>null!=e):e}function r(e,t=!0){if(null==e)return"";if(e instanceof Date)return e.toISOString();if("object"==typeof e)return JSON.stringify(e);const n=String(e);return t&&(n.includes(",")||n.includes('"')||n.includes("\n")||n.includes("\r"))?`"${n.replace(/"/g,'""')}"`:n}function s(e,t){const n=URL.createObjectURL(e),o=document.createElement("a");o.href=n,o.download=t,o.style.display="none",document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(n)}function l(e){return JSON.stringify(i(e))}function i(e){if(null==e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(i);const t={};for(const n of Object.keys(e).sort())t[n]=i(e[n]);return t}class c{#e=new Map;#t=0;register(e){const t=l(e),n=this.#e.get(t);if(n)return n.id;this.#t++;const o=`s${this.#t}`;return this.#e.set(t,{id:o,style:e}),o}getStyleId(e){return this.#e.get(l(e))?.id}get size(){return this.#e.size}toXml(){if(0===this.#e.size)return"";let e="\n<Styles>";for(const{id:t,style:n}of this.#e.values())e+=a(t,n);return e+="\n</Styles>",e}}function a(e,t){let n=`\n<Style ss:ID="${e}">`;if(t.font&&(n+="<Font",t.font.name&&(n+=` ss:FontName="${t.font.name}"`),t.font.size&&(n+=` ss:Size="${t.font.size}"`),t.font.bold&&(n+=' ss:Bold="1"'),t.font.italic&&(n+=' ss:Italic="1"'),t.font.color&&(n+=` ss:Color="${t.font.color}"`),n+="/>"),t.fill){const e=t.fill.pattern??"Solid";n+=`<Interior ss:Color="${t.fill.color}" ss:Pattern="${e}"/>`}return t.numberFormat&&(n+=`<NumberFormat ss:Format="${t.numberFormat}"/>`),t.alignment&&(n+="<Alignment",t.alignment.horizontal&&(n+=` ss:Horizontal="${t.alignment.horizontal}"`),t.alignment.vertical&&(n+=` ss:Vertical="${t.alignment.vertical}"`),t.alignment.wrapText&&(n+=' ss:WrapText="1"'),n+="/>"),t.borders&&(n+="<Borders>",t.borders.top&&(n+=f("Top",t.borders.top)),t.borders.bottom&&(n+=f("Bottom",t.borders.bottom)),t.borders.left&&(n+=f("Left",t.borders.left)),t.borders.right&&(n+=f("Right",t.borders.right)),n+="</Borders>"),n+="</Style>",n}function f(e,t){let n=`<Border ss:Position="${e}" ss:LineStyle="Continuous" ss:Weight="${function(e){switch(e){case"Thin":return 1;case"Medium":return 2;case"Thick":return 3}}(t.style)}"`;return t.color&&(n+=` ss:Color="${t.color}"`),n+="/>",n}function u(e,t,n,o,r){if(t.cellStyle){const s=t.cellStyle(n,o,r);if(s)return e.register(s)}const s=t.columnStyles?.[o];return s?e.getStyleId(s):t.defaultStyle?e.getStyleId(t.defaultStyle):void 0}function d(e,t){const n=Math.min(t.length,50);let o=(e.header??e.field).length;for(let r=0;r<n;r++){const n=t[r][e.field],s=null==n?0:String(n).length;s>o&&(o=s)}return o+2}function p(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function m(e,n,o){const r=o.excelStyles,s=r?function(e){const t=new c;if(e.headerStyle&&t.register(e.headerStyle),e.defaultStyle&&t.register(e.defaultStyle),e.columnStyles)for(const n of Object.values(e.columnStyles))t.register(n);return t}(r):void 0;let l='<?xml version="1.0" encoding="UTF-8"?>\n<?mso-application progid="Excel.Sheet"?>\n<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"\n xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">';if(s){if(r.cellStyle)for(const o of e)for(const e of n){const n=t.resolveCellValue(o,e),l=r.cellStyle(n,e.field,o);l&&s.register(l)}l+=s.toXml()}l+='\n<Worksheet ss:Name="Sheet1">\n<Table>',r&&(l+=function(e,t,n){const o=n.columnWidths,r=n.autoFitColumns;if(!o&&!r)return"";let s="";for(const l of e){let e=o?.[l.field];null==e&&r&&(e=d(l,t)),s+=null!=e?`\n<Column ss:Width="${7*e}"/>`:"\n<Column/>"}return s}(n,e,r));const i=r?.headerStyle&&s?s.getStyleId(r.headerStyle):void 0;if(!1!==o.includeHeaders){l+="\n<Row>";for(const e of n){const t=e.header||e.field;l+=`<Cell${i?` ss:StyleID="${i}"`:""}><Data ss:Type="String">${p(o.processHeader?o.processHeader(t,e.field):t)}</Data></Cell>`}l+="</Row>"}for(const c of e){l+="\n<Row>";for(const e of n){let n=t.resolveCellValue(c,e);o.processCell&&(n=o.processCell(n,e.field,c));let i="String",a="";null==n?a="":"number"!=typeof n||isNaN(n)?n instanceof Date?(i="DateTime",a=n.toISOString()):a=p(String(n)):(i="Number",a=String(n));const f=s&&r?u(s,r,n,e.field,c):void 0;l+=`<Cell${f?` ss:StyleID="${f}"`:""}><Data ss:Type="${i}">${a}</Data></Cell>`}l+="</Row>"}return l+="\n</Table>\n</Worksheet>\n</Workbook>",l}class g extends n.BaseGridPlugin{static manifest={queries:[{type:"export:csv",description:"Triggers a CSV export"}]};name="export";get defaultConfig(){return{fileName:"export",includeHeaders:!0,onlyVisible:!0,onlySelected:!1}}isExportingFlag=!1;lastExportInfo=null;handleQuery(e){if("export:csv"===e.type)return this.exportCsv(),!0}performExport(e,n){const l=this.config,i={format:e,fileName:n?.fileName??l.fileName??"export",includeHeaders:n?.includeHeaders??l.includeHeaders,processCell:n?.processCell,processHeader:n?.processHeader,columns:n?.columns,rowIndices:n?.rowIndices,excelStyles:n?.excelStyles,fileExtension:n?.fileExtension},c=function(e,t,n=!0){let o=e;if(n&&(o=o.filter(e=>!e.hidden&&!e.field.startsWith("__")&&!0!==e.utility)),t?.length){const e=new Set(t);o=o.filter(t=>e.has(t.field))}return o}(this.columns,n?.columns,l.onlyVisible);let a;if(n?.rowIndices)a=o(this.rows,n.rowIndices);else if(l.onlySelected){const e=this.getSelectionState();a=e?.selected?.size?o(this.rows,[...e.selected]):[...this.rows]}else a=[...this.rows];this.isExportingFlag=!0;let f=i.fileName;try{switch(e){case"csv":{const e=function(e,n,o,s={}){const l=s.delimiter??",",i=s.newline??"\n",c=[],a=s.bom?"\ufeff":"";if(!1!==o.includeHeaders){const e=n.map(e=>{const t=e.header||e.field;return r(o.processHeader?o.processHeader(t,e.field):t)});c.push(e.join(l))}for(const f of e){const e=n.map(e=>{let n=t.resolveCellValue(f,e);return o.processCell&&(n=o.processCell(n,e.field,f)),r(n)});c.push(e.join(l))}return a+c.join(i)}(a,c,i,{bom:!0});f=f.endsWith(".csv")?f:`${f}.csv`,function(e,t){s(new Blob([e],{type:"text/csv;charset=utf-8;"}),t)}(e,f);break}case"excel":{const e=m(a,c,i),t=i.fileExtension??".xls",n=t.startsWith(".")?t:`.${t}`;f=f.endsWith(n)?f:`${f}${n}`,function(e,t){s(new Blob([e],{type:"application/vnd.ms-excel;charset=utf-8;"}),t)}(e,f);break}case"json":{const e=a.map(e=>{const n={};for(const o of c){let r=t.resolveCellValue(e,o);i.processCell&&(r=i.processCell(r,o.field,e)),n[o.field]=r}return n}),n=JSON.stringify(e,null,2);f=f.endsWith(".json")?f:`${f}.json`;s(new Blob([n],{type:"application/json"}),f);break}}this.lastExportInfo={format:e,timestamp:new Date},this.emit("export-complete",{format:e,fileName:f,rowCount:a.length,columnCount:c.length})}finally{this.isExportingFlag=!1}}getSelectionState(){try{return this.grid?.getPluginState?.("selection")??null}catch{return null}}exportCsv(e){this.performExport("csv",e)}exportExcel(e){this.performExport("excel",e)}exportJson(e){this.performExport("json",e)}isExporting(){return this.isExportingFlag}getLastExport(){return this.lastExportInfo}}e.ExportPlugin=g,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
2
2
  //# sourceMappingURL=export.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"export.umd.js","sources":["../../../../../libs/grid/src/lib/plugins/shared/data-collection.ts","../../../../../libs/grid/src/lib/plugins/export/csv.ts","../../../../../libs/grid/src/lib/plugins/export/excel-styles.ts","../../../../../libs/grid/src/lib/plugins/export/excel.ts","../../../../../libs/grid/src/lib/plugins/export/ExportPlugin.ts"],"sourcesContent":["/**\n * Shared Data Collection Utilities\n *\n * Pure functions for resolving columns and formatting values, shared between\n * the Clipboard and Export plugins. Each plugin bundles its own copy of this\n * module (no chunk splitting) since plugin builds inline sibling imports.\n *\n * @internal\n */\n\nimport type { ColumnConfig } from '../../core/types';\n\n/**\n * Resolve which columns to include in a data export or copy operation.\n *\n * Filters out hidden columns, utility columns (`meta.utility`), and\n * internal columns (`__`-prefixed fields). Optionally restricts to an\n * explicit set of field names.\n *\n * @param columns - All column configurations\n * @param fields - If provided, only include columns whose field is in this list\n * @param onlyVisible - When `true` (default), exclude hidden and internal columns\n * @returns Filtered column array preserving original order\n */\nexport function resolveColumns(\n columns: readonly ColumnConfig[],\n fields?: string[],\n onlyVisible = true,\n): ColumnConfig[] {\n let result = columns as ColumnConfig[];\n\n if (onlyVisible) {\n result = result.filter((c) => !c.hidden && !c.field.startsWith('__') && c.meta?.utility !== true);\n }\n\n if (fields?.length) {\n const fieldSet = new Set(fields);\n result = result.filter((c) => fieldSet.has(c.field));\n }\n\n return result;\n}\n\n/**\n * Resolve which rows to include, optionally filtered to specific indices.\n *\n * @param rows - All row data\n * @param indices - If provided, only include rows at these indices (sorted ascending)\n * @returns Filtered row array\n */\nexport function resolveRows<T>(rows: readonly T[], indices?: number[]): T[] {\n if (!indices?.length) return rows as T[];\n\n return [...indices]\n .sort((a, b) => a - b)\n .map((i) => rows[i])\n .filter((r): r is T => r != null);\n}\n\n/**\n * Format a raw cell value as a text string.\n *\n * Provides the common null / Date / object → string conversion shared by\n * both clipboard and export output builders.\n *\n * @param value - The cell value to format\n * @returns A plain-text representation of the value\n */\nexport function formatValueAsText(value: unknown): string {\n if (value == null) return '';\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'object') return JSON.stringify(value);\n return String(value);\n}\n","/**\n * CSV Export Utilities\n *\n * Functions for building and downloading CSV content.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ExportParams } from './types';\n\n/** CSV export options */\nexport interface CsvOptions {\n /** Field delimiter (default: ',') */\n delimiter?: string;\n /** Line separator (default: '\\n') */\n newline?: string;\n /** Whether to quote strings containing special characters (default: true) */\n quoteStrings?: boolean;\n /** Add UTF-8 BOM for Excel compatibility (default: false) */\n bom?: boolean;\n}\n\n/**\n * Format a value for CSV output.\n * Handles null, Date, objects, and strings with special characters.\n */\nexport function formatCsvValue(value: any, quote = true): string {\n if (value == null) return '';\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'object') return JSON.stringify(value);\n\n const str = String(value);\n\n // Quote if contains special characters (comma, quote, newline)\n if (quote && (str.includes(',') || str.includes('\"') || str.includes('\\n') || str.includes('\\r'))) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n\n return str;\n}\n\n/**\n * Build CSV content from rows and columns.\n */\nexport function buildCsv(rows: any[], columns: ColumnConfig[], params: ExportParams, options: CsvOptions = {}): string {\n const delimiter = options.delimiter ?? ',';\n const newline = options.newline ?? '\\n';\n const lines: string[] = [];\n\n // UTF-8 BOM for Excel compatibility\n const bom = options.bom ? '\\uFEFF' : '';\n\n // Build header row\n if (params.includeHeaders !== false) {\n const headerRow = columns.map((col) => {\n const header = col.header || col.field;\n const processed = params.processHeader ? params.processHeader(header, col.field) : header;\n return formatCsvValue(processed);\n });\n lines.push(headerRow.join(delimiter));\n }\n\n // Build data rows\n for (const row of rows) {\n const cells = columns.map((col) => {\n let value = row[col.field];\n if (params.processCell) {\n value = params.processCell(value, col.field, row);\n }\n return formatCsvValue(value);\n });\n lines.push(cells.join(delimiter));\n }\n\n return bom + lines.join(newline);\n}\n\n/**\n * Download a Blob as a file.\n */\nexport function downloadBlob(blob: Blob, fileName: string): void {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = fileName;\n link.style.display = 'none';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n\n/**\n * Download CSV content as a file.\n */\nexport function downloadCsv(content: string, fileName: string): void {\n const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });\n downloadBlob(blob, fileName);\n}\n","/**\n * Excel Style Engine\n *\n * Builds a deduplicated `<Styles>` block for XML Spreadsheet 2003.\n * Collects unique ExcelCellStyle objects, assigns ss:StyleID values,\n * and generates the corresponding XML.\n */\n\nimport type { ExcelBorder, ExcelCellStyle, ExcelStyleConfig } from './types';\n\n// #region Style Hashing\n\n/**\n * Produce a deterministic string key for a style object.\n * Two structurally identical styles produce the same hash.\n * Recursively sorts object keys for order-independent comparison.\n */\nfunction hashStyle(style: ExcelCellStyle): string {\n return JSON.stringify(sortKeys(style));\n}\n\n/** Recursively sort object keys for deterministic serialization. */\nfunction sortKeys(obj: unknown): unknown {\n if (obj == null || typeof obj !== 'object') return obj;\n if (Array.isArray(obj)) return obj.map(sortKeys);\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = sortKeys((obj as Record<string, unknown>)[key]);\n }\n return sorted;\n}\n\n// #endregion\n\n// #region Style Registry\n\n/** Maps a hash → style ID and the original style. */\nexport interface StyleEntry {\n id: string;\n style: ExcelCellStyle;\n}\n\n/**\n * Collects unique styles and assigns each an `ss:StyleID`.\n * Register styles via `register()`, then call `getStyleId()` to look up\n * the ID for a given style, and `toXml()` to emit the `<Styles>` block.\n */\nexport class StyleRegistry {\n /** hash → StyleEntry */\n #entries = new Map<string, StyleEntry>();\n #counter = 0;\n\n /**\n * Register a style and return its assigned ID.\n * If an identical style was already registered, returns the existing ID.\n */\n register(style: ExcelCellStyle): string {\n const hash = hashStyle(style);\n const existing = this.#entries.get(hash);\n if (existing) return existing.id;\n\n this.#counter++;\n const id = `s${this.#counter}`;\n this.#entries.set(hash, { id, style });\n return id;\n }\n\n /** Look up the ID previously assigned to a style (or undefined). */\n getStyleId(style: ExcelCellStyle): string | undefined {\n return this.#entries.get(hashStyle(style))?.id;\n }\n\n /** Number of unique styles registered so far. */\n get size(): number {\n return this.#entries.size;\n }\n\n /** Emit the full `<Styles>…</Styles>` XML fragment, or empty string if no styles. */\n toXml(): string {\n if (this.#entries.size === 0) return '';\n\n let xml = '\\n<Styles>';\n for (const { id, style } of this.#entries.values()) {\n xml += buildStyleElement(id, style);\n }\n xml += '\\n</Styles>';\n return xml;\n }\n}\n\n// #endregion\n\n// #region XML Builders\n\nfunction buildStyleElement(id: string, style: ExcelCellStyle): string {\n let xml = `\\n<Style ss:ID=\"${id}\">`;\n\n if (style.font) {\n xml += '<Font';\n if (style.font.name) xml += ` ss:FontName=\"${style.font.name}\"`;\n if (style.font.size) xml += ` ss:Size=\"${style.font.size}\"`;\n if (style.font.bold) xml += ' ss:Bold=\"1\"';\n if (style.font.italic) xml += ' ss:Italic=\"1\"';\n if (style.font.color) xml += ` ss:Color=\"${style.font.color}\"`;\n xml += '/>';\n }\n\n if (style.fill) {\n const pattern = style.fill.pattern ?? 'Solid';\n xml += `<Interior ss:Color=\"${style.fill.color}\" ss:Pattern=\"${pattern}\"/>`;\n }\n\n if (style.numberFormat) {\n xml += `<NumberFormat ss:Format=\"${style.numberFormat}\"/>`;\n }\n\n if (style.alignment) {\n xml += '<Alignment';\n if (style.alignment.horizontal) xml += ` ss:Horizontal=\"${style.alignment.horizontal}\"`;\n if (style.alignment.vertical) xml += ` ss:Vertical=\"${style.alignment.vertical}\"`;\n if (style.alignment.wrapText) xml += ' ss:WrapText=\"1\"';\n xml += '/>';\n }\n\n if (style.borders) {\n xml += '<Borders>';\n if (style.borders.top) xml += buildBorderElement('Top', style.borders.top);\n if (style.borders.bottom) xml += buildBorderElement('Bottom', style.borders.bottom);\n if (style.borders.left) xml += buildBorderElement('Left', style.borders.left);\n if (style.borders.right) xml += buildBorderElement('Right', style.borders.right);\n xml += '</Borders>';\n }\n\n xml += '</Style>';\n return xml;\n}\n\nfunction buildBorderElement(position: string, border: ExcelBorder): string {\n let xml = `<Border ss:Position=\"${position}\" ss:LineStyle=\"Continuous\" ss:Weight=\"${borderWeight(border.style)}\"`;\n if (border.color) xml += ` ss:Color=\"${border.color}\"`;\n xml += '/>';\n return xml;\n}\n\nfunction borderWeight(style: ExcelBorder['style']): number {\n switch (style) {\n case 'Thin':\n return 1;\n case 'Medium':\n return 2;\n case 'Thick':\n return 3;\n }\n}\n\n// #endregion\n\n// #region Style Resolution\n\n/**\n * Build a StyleRegistry pre-populated with all styles declared in the config.\n * This covers headerStyle, defaultStyle, and columnStyles.\n * (cellStyle callbacks are resolved per-cell at render time.)\n */\nexport function buildStyleRegistry(config: ExcelStyleConfig): StyleRegistry {\n const registry = new StyleRegistry();\n\n if (config.headerStyle) registry.register(config.headerStyle);\n\n if (config.defaultStyle) registry.register(config.defaultStyle);\n\n if (config.columnStyles) {\n for (const style of Object.values(config.columnStyles)) {\n registry.register(style);\n }\n }\n\n return registry;\n}\n\n/**\n * Resolve the style ID for a data cell. Precedence (highest → lowest):\n * 1. cellStyle callback return value\n * 2. columnStyles[field]\n * 3. defaultStyle\n */\nexport function resolveDataStyleId(\n registry: StyleRegistry,\n config: ExcelStyleConfig,\n value: unknown,\n field: string,\n row: unknown,\n): string | undefined {\n // 1. Dynamic cell callback\n if (config.cellStyle) {\n const dynamic = config.cellStyle(value, field, row);\n if (dynamic) {\n // Register on-the-fly (dedup handles repeats)\n return registry.register(dynamic);\n }\n }\n\n // 2. Per-column override\n const colStyle = config.columnStyles?.[field];\n if (colStyle) return registry.getStyleId(colStyle);\n\n // 3. Default\n if (config.defaultStyle) return registry.getStyleId(config.defaultStyle);\n\n return undefined;\n}\n\n// #endregion\n\n// #region Column Widths\n\n/** Character width → Excel column width approximation (px ≈ chars × 7) */\nconst CHAR_WIDTH = 7;\n\n/**\n * Build `<Column>` elements for explicit or auto-fit widths.\n */\nexport function buildColumnWidthsXml(\n columns: { field: string; header?: string }[],\n rows: Record<string, unknown>[],\n config: ExcelStyleConfig,\n): string {\n const widths = config.columnWidths;\n const autoFit = config.autoFitColumns;\n\n if (!widths && !autoFit) return '';\n\n let xml = '';\n for (const col of columns) {\n let width: number | undefined = widths?.[col.field];\n\n if (width == null && autoFit) {\n width = autoFitWidth(col, rows);\n }\n\n if (width != null) {\n xml += `\\n<Column ss:Width=\"${width * CHAR_WIDTH}\"/>`;\n } else {\n // Emit an empty column entry to keep ordinal alignment\n xml += '\\n<Column/>';\n }\n }\n\n return xml;\n}\n\n/** Estimate width from header + first N data rows (capped at 50). */\nfunction autoFitWidth(col: { field: string; header?: string }, rows: Record<string, unknown>[]): number {\n const sampleSize = Math.min(rows.length, 50);\n let maxLen = (col.header ?? col.field).length;\n\n for (let i = 0; i < sampleSize; i++) {\n const val = rows[i][col.field];\n const len = val == null ? 0 : String(val).length;\n if (len > maxLen) maxLen = len;\n }\n\n // Add a small padding\n return maxLen + 2;\n}\n\n// #endregion\n","/**\n * Excel Export Utilities\n *\n * Simple Excel XML format export (no external dependencies).\n * Produces XML Spreadsheet 2003 format which opens in Excel.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport { downloadBlob } from './csv';\nimport { buildColumnWidthsXml, buildStyleRegistry, resolveDataStyleId } from './excel-styles';\nimport type { ExportParams } from './types';\n\n/**\n * Escape XML special characters.\n */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * Build Excel XML content from rows and columns.\n * Uses XML Spreadsheet 2003 format for broad compatibility.\n */\nexport function buildExcelXml(rows: any[], columns: ColumnConfig[], params: ExportParams): string {\n const styles = params.excelStyles;\n const registry = styles ? buildStyleRegistry(styles) : undefined;\n\n let xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?mso-application progid=\"Excel.Sheet\"?>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\n xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">`;\n\n // Emit <Styles> block (only when styles are configured)\n if (registry) {\n // Pre-register dynamic cellStyle entries so they appear in <Styles>\n if (styles!.cellStyle) {\n for (const row of rows) {\n for (const col of columns) {\n const value = row[col.field];\n const dynamic = styles!.cellStyle(value, col.field, row);\n if (dynamic) registry.register(dynamic);\n }\n }\n }\n xml += registry.toXml();\n }\n\n xml += '\\n<Worksheet ss:Name=\"Sheet1\">\\n<Table>';\n\n // Column widths\n if (styles) {\n xml += buildColumnWidthsXml(columns, rows as Record<string, unknown>[], styles);\n }\n\n // Header style ID\n const headerStyleId = styles?.headerStyle && registry ? registry.getStyleId(styles.headerStyle) : undefined;\n\n // Build header row\n if (params.includeHeaders !== false) {\n xml += '\\n<Row>';\n for (const col of columns) {\n const header = col.header || col.field;\n const processed = params.processHeader ? params.processHeader(header, col.field) : header;\n const styleAttr = headerStyleId ? ` ss:StyleID=\"${headerStyleId}\"` : '';\n xml += `<Cell${styleAttr}><Data ss:Type=\"String\">${escapeXml(processed)}</Data></Cell>`;\n }\n xml += '</Row>';\n }\n\n // Build data rows\n for (const row of rows) {\n xml += '\\n<Row>';\n for (const col of columns) {\n let value = row[col.field];\n if (params.processCell) {\n value = params.processCell(value, col.field, row);\n }\n\n // Determine cell type based on value\n let type: 'Number' | 'String' | 'DateTime' = 'String';\n let displayValue = '';\n\n if (value == null) {\n displayValue = '';\n } else if (typeof value === 'number' && !isNaN(value)) {\n type = 'Number';\n displayValue = String(value);\n } else if (value instanceof Date) {\n type = 'DateTime';\n displayValue = value.toISOString();\n } else {\n displayValue = escapeXml(String(value));\n }\n\n // Resolve data cell style\n const dataStyleId = registry && styles ? resolveDataStyleId(registry, styles, value, col.field, row) : undefined;\n const styleAttr = dataStyleId ? ` ss:StyleID=\"${dataStyleId}\"` : '';\n\n xml += `<Cell${styleAttr}><Data ss:Type=\"${type}\">${displayValue}</Data></Cell>`;\n }\n xml += '</Row>';\n }\n\n xml += '\\n</Table>\\n</Worksheet>\\n</Workbook>';\n return xml;\n}\n\n/**\n * Download Excel XML content as a file.\n */\nexport function downloadExcel(content: string, fileName: string): void {\n const blob = new Blob([content], {\n type: 'application/vnd.ms-excel;charset=utf-8;',\n });\n downloadBlob(blob, fileName);\n}\n","/**\n * Export Plugin (Class-based)\n *\n * Provides data export functionality for tbw-grid.\n * Supports CSV, Excel (XML), and JSON formats.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BaseGridPlugin, type PluginManifest, type PluginQuery } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport { resolveColumns, resolveRows } from '../shared/data-collection';\nimport { buildCsv, downloadBlob, downloadCsv } from './csv';\nimport { buildExcelXml, downloadExcel } from './excel';\nimport type { ExportCompleteDetail, ExportConfig, ExportFormat, ExportParams } from './types';\n\n/** Selection plugin state interface for type safety */\ninterface SelectionPluginState {\n selected: Set<number>;\n}\n\n/**\n * Export Plugin for tbw-grid\n *\n * Lets users download grid data as CSV, Excel (XML), or JSON with a single click\n * or API call. Great for reporting, data backup, or letting users work with data\n * in Excel. Integrates with SelectionPlugin to export only selected rows.\n *\n * ## Installation\n *\n * ```ts\n * import { ExportPlugin } from '@toolbox-web/grid/plugins/export';\n * ```\n *\n * ## Supported Formats\n *\n * | Format | Method | Description |\n * |--------|--------|-------------|\n * | CSV | `exportToCSV()` | Comma-separated values |\n * | Excel | `exportToExcel()` | Excel XML format (.xlsx) |\n * | JSON | `exportToJSON()` | JSON array of objects |\n *\n * @example Basic Export with Button\n * ```ts\n * import { queryGrid } from '@toolbox-web/grid';\n * import { ExportPlugin } from '@toolbox-web/grid/plugins/export';\n *\n * const grid = queryGrid('tbw-grid');\n * grid.gridConfig = {\n * columns: [\n * { field: 'name', header: 'Name' },\n * { field: 'email', header: 'Email' },\n * ],\n * plugins: [new ExportPlugin({ fileName: 'employees', includeHeaders: true })],\n * };\n *\n * // Trigger export via button\n * document.getElementById('export-btn').addEventListener('click', () => {\n * grid.getPluginByName('export').exportToCSV();\n * });\n * ```\n *\n * @example Export Selected Rows Only\n * ```ts\n * import { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';\n *\n * grid.gridConfig = {\n * plugins: [\n * new SelectionPlugin({ mode: 'row' }),\n * new ExportPlugin({ onlySelected: true }),\n * ],\n * };\n * ```\n *\n * @see {@link ExportConfig} for all configuration options\n * @see {@link ExportParams} for method parameters\n * @see SelectionPlugin for exporting selected rows\n *\n * @internal Extends BaseGridPlugin\n */\nexport class ExportPlugin extends BaseGridPlugin<ExportConfig> {\n /**\n * Plugin manifest — declares queries for inter-plugin communication.\n * @internal\n */\n static override readonly manifest: PluginManifest = {\n queries: [{ type: 'export:csv', description: 'Triggers a CSV export' }],\n };\n\n /** @internal */\n readonly name = 'export';\n\n /** @internal */\n protected override get defaultConfig(): Partial<ExportConfig> {\n return {\n fileName: 'export',\n includeHeaders: true,\n onlyVisible: true,\n onlySelected: false,\n };\n }\n\n // #region Internal State\n private isExportingFlag = false;\n private lastExportInfo: { format: ExportFormat; timestamp: Date } | null = null;\n // #endregion\n\n // #region Query System\n\n /** @internal */\n override handleQuery(query: PluginQuery): unknown {\n if (query.type === 'export:csv') {\n this.exportCsv();\n return true;\n }\n return undefined;\n }\n // #endregion\n\n // #region Private Methods\n\n private performExport(format: ExportFormat, params?: Partial<ExportParams>): void {\n const config = this.config;\n\n // Build full params with defaults\n const fullParams: ExportParams = {\n format,\n fileName: params?.fileName ?? config.fileName ?? 'export',\n includeHeaders: params?.includeHeaders ?? config.includeHeaders,\n processCell: params?.processCell,\n processHeader: params?.processHeader,\n columns: params?.columns,\n rowIndices: params?.rowIndices,\n excelStyles: params?.excelStyles,\n fileExtension: params?.fileExtension,\n };\n\n // Get columns to export (shared utility handles hidden/utility filtering)\n const columns = resolveColumns(this.columns, params?.columns, config.onlyVisible) as ColumnConfig[];\n\n // Get rows to export\n let rows: Record<string, unknown>[];\n if (params?.rowIndices) {\n rows = resolveRows(this.rows as Record<string, unknown>[], params.rowIndices);\n } else if (config.onlySelected) {\n const selectionState = this.getSelectionState();\n if (selectionState?.selected?.size) {\n rows = resolveRows(this.rows as Record<string, unknown>[], [...selectionState.selected]);\n } else {\n rows = [...this.rows] as Record<string, unknown>[];\n }\n } else {\n rows = [...this.rows] as Record<string, unknown>[];\n }\n\n this.isExportingFlag = true;\n let fileName = fullParams.fileName!;\n\n try {\n switch (format) {\n case 'csv': {\n const content = buildCsv(rows, columns, fullParams, { bom: true });\n fileName = fileName.endsWith('.csv') ? fileName : `${fileName}.csv`;\n downloadCsv(content, fileName);\n break;\n }\n\n case 'excel': {\n const content = buildExcelXml(rows, columns, fullParams);\n const ext = fullParams.fileExtension ?? '.xls';\n const normalizedExt = ext.startsWith('.') ? ext : `.${ext}`;\n fileName = fileName.endsWith(normalizedExt) ? fileName : `${fileName}${normalizedExt}`;\n downloadExcel(content, fileName);\n break;\n }\n\n case 'json': {\n const jsonData = rows.map((row) => {\n const obj: Record<string, any> = {};\n for (const col of columns) {\n let value = row[col.field];\n if (fullParams.processCell) {\n value = fullParams.processCell(value, col.field, row);\n }\n obj[col.field] = value;\n }\n return obj;\n });\n const content = JSON.stringify(jsonData, null, 2);\n fileName = fileName.endsWith('.json') ? fileName : `${fileName}.json`;\n const blob = new Blob([content], { type: 'application/json' });\n downloadBlob(blob, fileName);\n break;\n }\n }\n\n this.lastExportInfo = { format, timestamp: new Date() };\n\n this.emit<ExportCompleteDetail>('export-complete', {\n format,\n fileName,\n rowCount: rows.length,\n columnCount: columns.length,\n });\n } finally {\n this.isExportingFlag = false;\n }\n }\n\n private getSelectionState(): SelectionPluginState | null {\n try {\n return (this.grid?.getPluginState?.('selection') as SelectionPluginState | null) ?? null;\n } catch {\n return null;\n }\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Export data to CSV format.\n * @param params - Optional export parameters\n */\n exportCsv(params?: Partial<ExportParams>): void {\n this.performExport('csv', params);\n }\n\n /**\n * Export data to Excel format (XML Spreadsheet).\n * @param params - Optional export parameters\n */\n exportExcel(params?: Partial<ExportParams>): void {\n this.performExport('excel', params);\n }\n\n /**\n * Export data to JSON format.\n * @param params - Optional export parameters\n */\n exportJson(params?: Partial<ExportParams>): void {\n this.performExport('json', params);\n }\n\n /**\n * Check if an export is currently in progress.\n * @returns Whether export is in progress\n */\n isExporting(): boolean {\n return this.isExportingFlag;\n }\n\n /**\n * Get information about the last export.\n * @returns Export info or null if no export has occurred\n */\n getLastExport(): { format: ExportFormat; timestamp: Date } | null {\n return this.lastExportInfo;\n }\n // #endregion\n}\n"],"names":["resolveRows","rows","indices","length","sort","a","b","map","i","filter","r","formatCsvValue","value","quote","Date","toISOString","JSON","stringify","str","String","includes","replace","downloadBlob","blob","fileName","url","URL","createObjectURL","link","document","createElement","href","download","style","display","body","appendChild","click","removeChild","revokeObjectURL","hashStyle","sortKeys","obj","Array","isArray","sorted","key","Object","keys","StyleRegistry","entries","Map","counter","register","hash","existing","this","get","id","set","getStyleId","size","toXml","xml","values","buildStyleElement","font","name","bold","italic","color","fill","pattern","numberFormat","alignment","horizontal","vertical","wrapText","borders","top","buildBorderElement","bottom","left","right","position","border","borderWeight","resolveDataStyleId","registry","config","field","row","cellStyle","dynamic","colStyle","columnStyles","defaultStyle","autoFitWidth","col","sampleSize","Math","min","maxLen","header","val","len","escapeXml","buildExcelXml","columns","params","styles","excelStyles","headerStyle","buildStyleRegistry","widths","columnWidths","autoFit","autoFitColumns","width","buildColumnWidthsXml","headerStyleId","includeHeaders","processHeader","processCell","type","displayValue","isNaN","dataStyleId","ExportPlugin","BaseGridPlugin","static","queries","description","defaultConfig","onlyVisible","onlySelected","isExportingFlag","lastExportInfo","handleQuery","query","exportCsv","performExport","format","fullParams","rowIndices","fileExtension","fields","result","c","hidden","startsWith","meta","utility","fieldSet","Set","has","resolveColumns","selectionState","getSelectionState","selected","content","options","delimiter","newline","lines","bom","headerRow","push","join","cells","buildCsv","endsWith","Blob","downloadCsv","ext","normalizedExt","downloadExcel","jsonData","timestamp","emit","rowCount","columnCount","grid","getPluginState","exportExcel","exportJson","isExporting","getLastExport"],"mappings":"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"}
1
+ {"version":3,"file":"export.umd.js","sources":["../../../../../libs/grid/src/lib/plugins/shared/data-collection.ts","../../../../../libs/grid/src/lib/plugins/export/csv.ts","../../../../../libs/grid/src/lib/plugins/export/excel-styles.ts","../../../../../libs/grid/src/lib/plugins/export/excel.ts","../../../../../libs/grid/src/lib/plugins/export/ExportPlugin.ts"],"sourcesContent":["/**\n * Shared Data Collection Utilities\n *\n * Pure functions for resolving columns and formatting values, shared between\n * the Clipboard and Export plugins. Each plugin bundles its own copy of this\n * module (no chunk splitting) since plugin builds inline sibling imports.\n *\n * @internal\n */\n\nimport type { ColumnConfig } from '../../core/types';\n\n/**\n * Resolve which columns to include in a data export or copy operation.\n *\n * Filters out hidden columns, utility columns (`meta.utility`), and\n * internal columns (`__`-prefixed fields). Optionally restricts to an\n * explicit set of field names.\n *\n * @param columns - All column configurations\n * @param fields - If provided, only include columns whose field is in this list\n * @param onlyVisible - When `true` (default), exclude hidden and internal columns\n * @returns Filtered column array preserving original order\n */\nexport function resolveColumns(\n columns: readonly ColumnConfig[],\n fields?: string[],\n onlyVisible = true,\n): ColumnConfig[] {\n let result = columns as ColumnConfig[];\n\n if (onlyVisible) {\n result = result.filter((c) => !c.hidden && !c.field.startsWith('__') && c.utility !== true);\n }\n\n if (fields?.length) {\n const fieldSet = new Set(fields);\n result = result.filter((c) => fieldSet.has(c.field));\n }\n\n return result;\n}\n\n/**\n * Resolve which rows to include, optionally filtered to specific indices.\n *\n * @param rows - All row data\n * @param indices - If provided, only include rows at these indices (sorted ascending)\n * @returns Filtered row array\n */\nexport function resolveRows<T>(rows: readonly T[], indices?: number[]): T[] {\n if (!indices?.length) return rows as T[];\n\n return [...indices]\n .sort((a, b) => a - b)\n .map((i) => rows[i])\n .filter((r): r is T => r != null);\n}\n\n/**\n * Format a raw cell value as a text string.\n *\n * Provides the common null / Date / object → string conversion shared by\n * both clipboard and export output builders.\n *\n * @param value - The cell value to format\n * @returns A plain-text representation of the value\n */\nexport function formatValueAsText(value: unknown): string {\n if (value == null) return '';\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'object') return JSON.stringify(value);\n return String(value);\n}\n","/**\n * CSV Export Utilities\n *\n * Functions for building and downloading CSV content.\n */\n\nimport { resolveCellValue } from '../../core/internal/value-accessor';\nimport type { ColumnConfig } from '../../core/types';\nimport type { ExportParams } from './types';\n\n/** CSV export options */\nexport interface CsvOptions {\n /** Field delimiter (default: ',') */\n delimiter?: string;\n /** Line separator (default: '\\n') */\n newline?: string;\n /** Whether to quote strings containing special characters (default: true) */\n quoteStrings?: boolean;\n /** Add UTF-8 BOM for Excel compatibility (default: false) */\n bom?: boolean;\n}\n\n/**\n * Format a value for CSV output.\n * Handles null, Date, objects, and strings with special characters.\n */\nexport function formatCsvValue(value: any, quote = true): string {\n if (value == null) return '';\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'object') return JSON.stringify(value);\n\n const str = String(value);\n\n // Quote if contains special characters (comma, quote, newline)\n if (quote && (str.includes(',') || str.includes('\"') || str.includes('\\n') || str.includes('\\r'))) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n\n return str;\n}\n\n/**\n * Build CSV content from rows and columns.\n */\nexport function buildCsv(rows: any[], columns: ColumnConfig[], params: ExportParams, options: CsvOptions = {}): string {\n const delimiter = options.delimiter ?? ',';\n const newline = options.newline ?? '\\n';\n const lines: string[] = [];\n\n // UTF-8 BOM for Excel compatibility\n const bom = options.bom ? '\\uFEFF' : '';\n\n // Build header row\n if (params.includeHeaders !== false) {\n const headerRow = columns.map((col) => {\n const header = col.header || col.field;\n const processed = params.processHeader ? params.processHeader(header, col.field) : header;\n return formatCsvValue(processed);\n });\n lines.push(headerRow.join(delimiter));\n }\n\n // Build data rows\n for (const row of rows) {\n const cells = columns.map((col) => {\n let value = resolveCellValue(row, col);\n if (params.processCell) {\n value = params.processCell(value, col.field, row);\n }\n return formatCsvValue(value);\n });\n lines.push(cells.join(delimiter));\n }\n\n return bom + lines.join(newline);\n}\n\n/**\n * Download a Blob as a file.\n */\nexport function downloadBlob(blob: Blob, fileName: string): void {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = fileName;\n link.style.display = 'none';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n\n/**\n * Download CSV content as a file.\n */\nexport function downloadCsv(content: string, fileName: string): void {\n const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });\n downloadBlob(blob, fileName);\n}\n","/**\n * Excel Style Engine\n *\n * Builds a deduplicated `<Styles>` block for XML Spreadsheet 2003.\n * Collects unique ExcelCellStyle objects, assigns ss:StyleID values,\n * and generates the corresponding XML.\n */\n\nimport type { ExcelBorder, ExcelCellStyle, ExcelStyleConfig } from './types';\n\n// #region Style Hashing\n\n/**\n * Produce a deterministic string key for a style object.\n * Two structurally identical styles produce the same hash.\n * Recursively sorts object keys for order-independent comparison.\n */\nfunction hashStyle(style: ExcelCellStyle): string {\n return JSON.stringify(sortKeys(style));\n}\n\n/** Recursively sort object keys for deterministic serialization. */\nfunction sortKeys(obj: unknown): unknown {\n if (obj == null || typeof obj !== 'object') return obj;\n if (Array.isArray(obj)) return obj.map(sortKeys);\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = sortKeys((obj as Record<string, unknown>)[key]);\n }\n return sorted;\n}\n\n// #endregion\n\n// #region Style Registry\n\n/** Maps a hash → style ID and the original style. */\nexport interface StyleEntry {\n id: string;\n style: ExcelCellStyle;\n}\n\n/**\n * Collects unique styles and assigns each an `ss:StyleID`.\n * Register styles via `register()`, then call `getStyleId()` to look up\n * the ID for a given style, and `toXml()` to emit the `<Styles>` block.\n */\nexport class StyleRegistry {\n /** hash → StyleEntry */\n #entries = new Map<string, StyleEntry>();\n #counter = 0;\n\n /**\n * Register a style and return its assigned ID.\n * If an identical style was already registered, returns the existing ID.\n */\n register(style: ExcelCellStyle): string {\n const hash = hashStyle(style);\n const existing = this.#entries.get(hash);\n if (existing) return existing.id;\n\n this.#counter++;\n const id = `s${this.#counter}`;\n this.#entries.set(hash, { id, style });\n return id;\n }\n\n /** Look up the ID previously assigned to a style (or undefined). */\n getStyleId(style: ExcelCellStyle): string | undefined {\n return this.#entries.get(hashStyle(style))?.id;\n }\n\n /** Number of unique styles registered so far. */\n get size(): number {\n return this.#entries.size;\n }\n\n /** Emit the full `<Styles>…</Styles>` XML fragment, or empty string if no styles. */\n toXml(): string {\n if (this.#entries.size === 0) return '';\n\n let xml = '\\n<Styles>';\n for (const { id, style } of this.#entries.values()) {\n xml += buildStyleElement(id, style);\n }\n xml += '\\n</Styles>';\n return xml;\n }\n}\n\n// #endregion\n\n// #region XML Builders\n\nfunction buildStyleElement(id: string, style: ExcelCellStyle): string {\n let xml = `\\n<Style ss:ID=\"${id}\">`;\n\n if (style.font) {\n xml += '<Font';\n if (style.font.name) xml += ` ss:FontName=\"${style.font.name}\"`;\n if (style.font.size) xml += ` ss:Size=\"${style.font.size}\"`;\n if (style.font.bold) xml += ' ss:Bold=\"1\"';\n if (style.font.italic) xml += ' ss:Italic=\"1\"';\n if (style.font.color) xml += ` ss:Color=\"${style.font.color}\"`;\n xml += '/>';\n }\n\n if (style.fill) {\n const pattern = style.fill.pattern ?? 'Solid';\n xml += `<Interior ss:Color=\"${style.fill.color}\" ss:Pattern=\"${pattern}\"/>`;\n }\n\n if (style.numberFormat) {\n xml += `<NumberFormat ss:Format=\"${style.numberFormat}\"/>`;\n }\n\n if (style.alignment) {\n xml += '<Alignment';\n if (style.alignment.horizontal) xml += ` ss:Horizontal=\"${style.alignment.horizontal}\"`;\n if (style.alignment.vertical) xml += ` ss:Vertical=\"${style.alignment.vertical}\"`;\n if (style.alignment.wrapText) xml += ' ss:WrapText=\"1\"';\n xml += '/>';\n }\n\n if (style.borders) {\n xml += '<Borders>';\n if (style.borders.top) xml += buildBorderElement('Top', style.borders.top);\n if (style.borders.bottom) xml += buildBorderElement('Bottom', style.borders.bottom);\n if (style.borders.left) xml += buildBorderElement('Left', style.borders.left);\n if (style.borders.right) xml += buildBorderElement('Right', style.borders.right);\n xml += '</Borders>';\n }\n\n xml += '</Style>';\n return xml;\n}\n\nfunction buildBorderElement(position: string, border: ExcelBorder): string {\n let xml = `<Border ss:Position=\"${position}\" ss:LineStyle=\"Continuous\" ss:Weight=\"${borderWeight(border.style)}\"`;\n if (border.color) xml += ` ss:Color=\"${border.color}\"`;\n xml += '/>';\n return xml;\n}\n\nfunction borderWeight(style: ExcelBorder['style']): number {\n switch (style) {\n case 'Thin':\n return 1;\n case 'Medium':\n return 2;\n case 'Thick':\n return 3;\n }\n}\n\n// #endregion\n\n// #region Style Resolution\n\n/**\n * Build a StyleRegistry pre-populated with all styles declared in the config.\n * This covers headerStyle, defaultStyle, and columnStyles.\n * (cellStyle callbacks are resolved per-cell at render time.)\n */\nexport function buildStyleRegistry(config: ExcelStyleConfig): StyleRegistry {\n const registry = new StyleRegistry();\n\n if (config.headerStyle) registry.register(config.headerStyle);\n\n if (config.defaultStyle) registry.register(config.defaultStyle);\n\n if (config.columnStyles) {\n for (const style of Object.values(config.columnStyles)) {\n registry.register(style);\n }\n }\n\n return registry;\n}\n\n/**\n * Resolve the style ID for a data cell. Precedence (highest → lowest):\n * 1. cellStyle callback return value\n * 2. columnStyles[field]\n * 3. defaultStyle\n */\nexport function resolveDataStyleId(\n registry: StyleRegistry,\n config: ExcelStyleConfig,\n value: unknown,\n field: string,\n row: unknown,\n): string | undefined {\n // 1. Dynamic cell callback\n if (config.cellStyle) {\n const dynamic = config.cellStyle(value, field, row);\n if (dynamic) {\n // Register on-the-fly (dedup handles repeats)\n return registry.register(dynamic);\n }\n }\n\n // 2. Per-column override\n const colStyle = config.columnStyles?.[field];\n if (colStyle) return registry.getStyleId(colStyle);\n\n // 3. Default\n if (config.defaultStyle) return registry.getStyleId(config.defaultStyle);\n\n return undefined;\n}\n\n// #endregion\n\n// #region Column Widths\n\n/** Character width → Excel column width approximation (px ≈ chars × 7) */\nconst CHAR_WIDTH = 7;\n\n/**\n * Build `<Column>` elements for explicit or auto-fit widths.\n */\nexport function buildColumnWidthsXml(\n columns: { field: string; header?: string }[],\n rows: Record<string, unknown>[],\n config: ExcelStyleConfig,\n): string {\n const widths = config.columnWidths;\n const autoFit = config.autoFitColumns;\n\n if (!widths && !autoFit) return '';\n\n let xml = '';\n for (const col of columns) {\n let width: number | undefined = widths?.[col.field];\n\n if (width == null && autoFit) {\n width = autoFitWidth(col, rows);\n }\n\n if (width != null) {\n xml += `\\n<Column ss:Width=\"${width * CHAR_WIDTH}\"/>`;\n } else {\n // Emit an empty column entry to keep ordinal alignment\n xml += '\\n<Column/>';\n }\n }\n\n return xml;\n}\n\n/** Estimate width from header + first N data rows (capped at 50). */\nfunction autoFitWidth(col: { field: string; header?: string }, rows: Record<string, unknown>[]): number {\n const sampleSize = Math.min(rows.length, 50);\n let maxLen = (col.header ?? col.field).length;\n\n for (let i = 0; i < sampleSize; i++) {\n const val = rows[i][col.field];\n const len = val == null ? 0 : String(val).length;\n if (len > maxLen) maxLen = len;\n }\n\n // Add a small padding\n return maxLen + 2;\n}\n\n// #endregion\n","/**\n * Excel Export Utilities\n *\n * Simple Excel XML format export (no external dependencies).\n * Produces XML Spreadsheet 2003 format which opens in Excel.\n */\n\nimport { resolveCellValue } from '../../core/internal/value-accessor';\nimport type { ColumnConfig } from '../../core/types';\nimport { downloadBlob } from './csv';\nimport { buildColumnWidthsXml, buildStyleRegistry, resolveDataStyleId } from './excel-styles';\nimport type { ExportParams } from './types';\n\n/**\n * Escape XML special characters.\n */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * Build Excel XML content from rows and columns.\n * Uses XML Spreadsheet 2003 format for broad compatibility.\n */\nexport function buildExcelXml(rows: any[], columns: ColumnConfig[], params: ExportParams): string {\n const styles = params.excelStyles;\n const registry = styles ? buildStyleRegistry(styles) : undefined;\n\n let xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?mso-application progid=\"Excel.Sheet\"?>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\n xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">`;\n\n // Emit <Styles> block (only when styles are configured)\n if (registry) {\n // Pre-register dynamic cellStyle entries so they appear in <Styles>\n if (styles!.cellStyle) {\n for (const row of rows) {\n for (const col of columns) {\n const value = resolveCellValue(row, col);\n const dynamic = styles!.cellStyle(value, col.field, row);\n if (dynamic) registry.register(dynamic);\n }\n }\n }\n xml += registry.toXml();\n }\n\n xml += '\\n<Worksheet ss:Name=\"Sheet1\">\\n<Table>';\n\n // Column widths\n if (styles) {\n xml += buildColumnWidthsXml(columns, rows as Record<string, unknown>[], styles);\n }\n\n // Header style ID\n const headerStyleId = styles?.headerStyle && registry ? registry.getStyleId(styles.headerStyle) : undefined;\n\n // Build header row\n if (params.includeHeaders !== false) {\n xml += '\\n<Row>';\n for (const col of columns) {\n const header = col.header || col.field;\n const processed = params.processHeader ? params.processHeader(header, col.field) : header;\n const styleAttr = headerStyleId ? ` ss:StyleID=\"${headerStyleId}\"` : '';\n xml += `<Cell${styleAttr}><Data ss:Type=\"String\">${escapeXml(processed)}</Data></Cell>`;\n }\n xml += '</Row>';\n }\n\n // Build data rows\n for (const row of rows) {\n xml += '\\n<Row>';\n for (const col of columns) {\n let value = resolveCellValue(row, col);\n if (params.processCell) {\n value = params.processCell(value, col.field, row);\n }\n\n // Determine cell type based on value\n let type: 'Number' | 'String' | 'DateTime' = 'String';\n let displayValue = '';\n\n if (value == null) {\n displayValue = '';\n } else if (typeof value === 'number' && !isNaN(value)) {\n type = 'Number';\n displayValue = String(value);\n } else if (value instanceof Date) {\n type = 'DateTime';\n displayValue = value.toISOString();\n } else {\n displayValue = escapeXml(String(value));\n }\n\n // Resolve data cell style\n const dataStyleId = registry && styles ? resolveDataStyleId(registry, styles, value, col.field, row) : undefined;\n const styleAttr = dataStyleId ? ` ss:StyleID=\"${dataStyleId}\"` : '';\n\n xml += `<Cell${styleAttr}><Data ss:Type=\"${type}\">${displayValue}</Data></Cell>`;\n }\n xml += '</Row>';\n }\n\n xml += '\\n</Table>\\n</Worksheet>\\n</Workbook>';\n return xml;\n}\n\n/**\n * Download Excel XML content as a file.\n */\nexport function downloadExcel(content: string, fileName: string): void {\n const blob = new Blob([content], {\n type: 'application/vnd.ms-excel;charset=utf-8;',\n });\n downloadBlob(blob, fileName);\n}\n","/**\n * Export Plugin (Class-based)\n *\n * Provides data export functionality for tbw-grid.\n * Supports CSV, Excel (XML), and JSON formats.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { resolveCellValue } from '../../core/internal/value-accessor';\nimport { BaseGridPlugin, type PluginManifest, type PluginQuery } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport { resolveColumns, resolveRows } from '../shared/data-collection';\nimport { buildCsv, downloadBlob, downloadCsv } from './csv';\nimport { buildExcelXml, downloadExcel } from './excel';\nimport type { ExportCompleteDetail, ExportConfig, ExportFormat, ExportParams } from './types';\n\n/** Selection plugin state interface for type safety */\ninterface SelectionPluginState {\n selected: Set<number>;\n}\n\n/**\n * Export Plugin for tbw-grid\n *\n * Lets users download grid data as CSV, Excel (XML), or JSON with a single click\n * or API call. Great for reporting, data backup, or letting users work with data\n * in Excel. Integrates with SelectionPlugin to export only selected rows.\n *\n * ## Installation\n *\n * ```ts\n * import { ExportPlugin } from '@toolbox-web/grid/plugins/export';\n * ```\n *\n * ## Supported Formats\n *\n * | Format | Method | Description |\n * |--------|--------|-------------|\n * | CSV | `exportToCSV()` | Comma-separated values |\n * | Excel | `exportToExcel()` | Excel XML format (.xlsx) |\n * | JSON | `exportToJSON()` | JSON array of objects |\n *\n * @example Basic Export with Button\n * ```ts\n * import { queryGrid } from '@toolbox-web/grid';\n * import { ExportPlugin } from '@toolbox-web/grid/plugins/export';\n *\n * const grid = queryGrid('tbw-grid');\n * grid.gridConfig = {\n * columns: [\n * { field: 'name', header: 'Name' },\n * { field: 'email', header: 'Email' },\n * ],\n * plugins: [new ExportPlugin({ fileName: 'employees', includeHeaders: true })],\n * };\n *\n * // Trigger export via button\n * document.getElementById('export-btn').addEventListener('click', () => {\n * grid.getPluginByName('export').exportToCSV();\n * });\n * ```\n *\n * @example Export Selected Rows Only\n * ```ts\n * import { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';\n *\n * grid.gridConfig = {\n * plugins: [\n * new SelectionPlugin({ mode: 'row' }),\n * new ExportPlugin({ onlySelected: true }),\n * ],\n * };\n * ```\n *\n * @see {@link ExportConfig} for all configuration options\n * @see {@link ExportParams} for method parameters\n * @see SelectionPlugin for exporting selected rows\n *\n * @internal Extends BaseGridPlugin\n */\nexport class ExportPlugin extends BaseGridPlugin<ExportConfig> {\n /**\n * Plugin manifest — declares queries for inter-plugin communication.\n * @internal\n */\n static override readonly manifest: PluginManifest = {\n queries: [{ type: 'export:csv', description: 'Triggers a CSV export' }],\n };\n\n /** @internal */\n readonly name = 'export';\n\n /** @internal */\n protected override get defaultConfig(): Partial<ExportConfig> {\n return {\n fileName: 'export',\n includeHeaders: true,\n onlyVisible: true,\n onlySelected: false,\n };\n }\n\n // #region Internal State\n private isExportingFlag = false;\n private lastExportInfo: { format: ExportFormat; timestamp: Date } | null = null;\n // #endregion\n\n // #region Query System\n\n /** @internal */\n override handleQuery(query: PluginQuery): unknown {\n if (query.type === 'export:csv') {\n this.exportCsv();\n return true;\n }\n return undefined;\n }\n // #endregion\n\n // #region Private Methods\n\n private performExport(format: ExportFormat, params?: Partial<ExportParams>): void {\n const config = this.config;\n\n // Build full params with defaults\n const fullParams: ExportParams = {\n format,\n fileName: params?.fileName ?? config.fileName ?? 'export',\n includeHeaders: params?.includeHeaders ?? config.includeHeaders,\n processCell: params?.processCell,\n processHeader: params?.processHeader,\n columns: params?.columns,\n rowIndices: params?.rowIndices,\n excelStyles: params?.excelStyles,\n fileExtension: params?.fileExtension,\n };\n\n // Get columns to export (shared utility handles hidden/utility filtering)\n const columns = resolveColumns(this.columns, params?.columns, config.onlyVisible) as ColumnConfig[];\n\n // Get rows to export\n let rows: Record<string, unknown>[];\n if (params?.rowIndices) {\n rows = resolveRows(this.rows as Record<string, unknown>[], params.rowIndices);\n } else if (config.onlySelected) {\n const selectionState = this.getSelectionState();\n if (selectionState?.selected?.size) {\n rows = resolveRows(this.rows as Record<string, unknown>[], [...selectionState.selected]);\n } else {\n rows = [...this.rows] as Record<string, unknown>[];\n }\n } else {\n rows = [...this.rows] as Record<string, unknown>[];\n }\n\n this.isExportingFlag = true;\n let fileName = fullParams.fileName!;\n\n try {\n switch (format) {\n case 'csv': {\n const content = buildCsv(rows, columns, fullParams, { bom: true });\n fileName = fileName.endsWith('.csv') ? fileName : `${fileName}.csv`;\n downloadCsv(content, fileName);\n break;\n }\n\n case 'excel': {\n const content = buildExcelXml(rows, columns, fullParams);\n const ext = fullParams.fileExtension ?? '.xls';\n const normalizedExt = ext.startsWith('.') ? ext : `.${ext}`;\n fileName = fileName.endsWith(normalizedExt) ? fileName : `${fileName}${normalizedExt}`;\n downloadExcel(content, fileName);\n break;\n }\n\n case 'json': {\n const jsonData = rows.map((row) => {\n const obj: Record<string, any> = {};\n for (const col of columns) {\n let value = resolveCellValue(row, col);\n if (fullParams.processCell) {\n value = fullParams.processCell(value, col.field, row);\n }\n obj[col.field] = value;\n }\n return obj;\n });\n const content = JSON.stringify(jsonData, null, 2);\n fileName = fileName.endsWith('.json') ? fileName : `${fileName}.json`;\n const blob = new Blob([content], { type: 'application/json' });\n downloadBlob(blob, fileName);\n break;\n }\n }\n\n this.lastExportInfo = { format, timestamp: new Date() };\n\n this.emit<ExportCompleteDetail>('export-complete', {\n format,\n fileName,\n rowCount: rows.length,\n columnCount: columns.length,\n });\n } finally {\n this.isExportingFlag = false;\n }\n }\n\n private getSelectionState(): SelectionPluginState | null {\n try {\n return (this.grid?.getPluginState?.('selection') as SelectionPluginState | null) ?? null;\n } catch {\n return null;\n }\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Export data to CSV format.\n * @param params - Optional export parameters\n */\n exportCsv(params?: Partial<ExportParams>): void {\n this.performExport('csv', params);\n }\n\n /**\n * Export data to Excel format (XML Spreadsheet).\n * @param params - Optional export parameters\n */\n exportExcel(params?: Partial<ExportParams>): void {\n this.performExport('excel', params);\n }\n\n /**\n * Export data to JSON format.\n * @param params - Optional export parameters\n */\n exportJson(params?: Partial<ExportParams>): void {\n this.performExport('json', params);\n }\n\n /**\n * Check if an export is currently in progress.\n * @returns Whether export is in progress\n */\n isExporting(): boolean {\n return this.isExportingFlag;\n }\n\n /**\n * Get information about the last export.\n * @returns Export info or null if no export has occurred\n */\n getLastExport(): { format: ExportFormat; timestamp: Date } | null {\n return this.lastExportInfo;\n }\n // #endregion\n}\n"],"names":["resolveRows","rows","indices","length","sort","a","b","map","i","filter","r","formatCsvValue","value","quote","Date","toISOString","JSON","stringify","str","String","includes","replace","downloadBlob","blob","fileName","url","URL","createObjectURL","link","document","createElement","href","download","style","display","body","appendChild","click","removeChild","revokeObjectURL","hashStyle","sortKeys","obj","Array","isArray","sorted","key","Object","keys","StyleRegistry","entries","Map","counter","register","hash","existing","this","get","id","set","getStyleId","size","toXml","xml","values","buildStyleElement","font","name","bold","italic","color","fill","pattern","numberFormat","alignment","horizontal","vertical","wrapText","borders","top","buildBorderElement","bottom","left","right","position","border","borderWeight","resolveDataStyleId","registry","config","field","row","cellStyle","dynamic","colStyle","columnStyles","defaultStyle","autoFitWidth","col","sampleSize","Math","min","maxLen","header","val","len","escapeXml","buildExcelXml","columns","params","styles","excelStyles","headerStyle","buildStyleRegistry","resolveCellValue","widths","columnWidths","autoFit","autoFitColumns","width","buildColumnWidthsXml","headerStyleId","includeHeaders","processHeader","processCell","type","displayValue","isNaN","dataStyleId","ExportPlugin","BaseGridPlugin","static","queries","description","defaultConfig","onlyVisible","onlySelected","isExportingFlag","lastExportInfo","handleQuery","query","exportCsv","performExport","format","fullParams","rowIndices","fileExtension","fields","result","c","hidden","startsWith","utility","fieldSet","Set","has","resolveColumns","selectionState","getSelectionState","selected","content","options","delimiter","newline","lines","bom","headerRow","push","join","cells","buildCsv","endsWith","Blob","downloadCsv","ext","normalizedExt","downloadExcel","jsonData","timestamp","emit","rowCount","columnCount","grid","getPluginState","exportExcel","exportJson","isExporting","getLastExport"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("../../core/internal/aria"),require("../../core/plugin/base-plugin"),require("../../core/plugin/expander-column"),require("../../core/internal/virtualization")):"function"==typeof define&&define.amd?define(["exports","../../core/internal/aria","../../core/plugin/base-plugin","../../core/plugin/expander-column","../../core/internal/virtualization"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TbwGridPlugin_filtering={},e.TbwGrid,e.TbwGrid,e.TbwGrid,e.TbwGrid)}(this,function(e,t,r,n,i){"use strict";const l="(Blank)";function a(e){if("number"==typeof e)return e;if(e instanceof Date)return e.getTime();const t=Number(e);if(!isNaN(t))return t;return new Date(e).getTime()}function s(e,t,r=!1,n){if(!t.length)return e;const i=t.map(e=>function(e,t,r){const n=e.field,i=e.operator,s=r?e=>r(e[n],e):e=>e[n];if("blank"===i)return e=>{const t=s(e);return null==t||""===t||"number"==typeof t&&isNaN(t)};if("notBlank"===i)return e=>{const t=s(e);return null!=t&&""!==t&&!("number"==typeof t&&isNaN(t))};if(r&&("notIn"===i||"in"===i)){const t=e.value;if("notIn"===i){if(!Array.isArray(t))return()=>!0;const e=new Set(t);return t=>{const i=r(t[n],t),a=Array.isArray(i)?i:null!=i?[i]:[];return 0===a.length?!e.has(l):!a.some(t=>e.has(t))}}if(!Array.isArray(t))return()=>!1;const a=new Set(t);return e=>{const t=r(e[n],e),i=Array.isArray(t)?t:null!=t?[t]:[];return 0===i.length?a.has(l):i.some(e=>a.has(e))}}if("notIn"===i){if(!Array.isArray(e.value))return()=>!0;const t=new Set(e.value);return e=>{const r=e[n];return null==r||""===r?!t.has(l):!t.has(r)}}if("in"===i){if(!Array.isArray(e.value))return()=>!1;const t=new Set(e.value);return e=>{const r=e[n];return null==r||""===r?t.has(l):t.has(r)}}const o="number"===e.type&&!r,c=e=>null==e||""===e||"number"==typeof e&&isNaN(e);if("greaterThan"===i){const t=a(e.value);return o?e=>{const r=e[n];return!c(r)&&r>t}:e=>{const r=s(e);if(c(r))return!1;const n=a(r);return!isNaN(n)&&n>t}}if("greaterThanOrEqual"===i){const t=a(e.value);return o?e=>{const r=e[n];return!c(r)&&r>=t}:e=>{const r=s(e);if(c(r))return!1;const n=a(r);return!isNaN(n)&&n>=t}}if("lessThan"===i){const t=a(e.value);return o?e=>{const r=e[n];return!c(r)&&r<t}:e=>{const r=s(e);if(c(r))return!1;const n=a(r);return!isNaN(n)&&n<t}}if("lessThanOrEqual"===i){const t=a(e.value);return o?e=>{const r=e[n];return!c(r)&&r<=t}:e=>{const r=s(e);if(c(r))return!1;const n=a(r);return!isNaN(n)&&n<=t}}if("between"===i){const t=a(e.value),r=a(e.valueTo);return o?e=>{const i=e[n];return!c(i)&&(i>=t&&i<=r)}:e=>{const n=s(e);if(c(n))return!1;const i=a(n);return!isNaN(i)&&i>=t&&i<=r}}const d=t?String(e.value):String(e.value).toLowerCase();return"contains"===i?t?e=>{const t=s(e);return null!=t&&String(t).includes(d)}:e=>{const t=s(e);return null!=t&&String(t).toLowerCase().includes(d)}:"notContains"===i?t?e=>{const t=s(e);return null!=t&&!String(t).includes(d)}:e=>{const t=s(e);return null!=t&&!String(t).toLowerCase().includes(d)}:"equals"===i?t?e=>{const t=s(e);return null!=t&&String(t)===d}:e=>{const t=s(e);return null!=t&&String(t).toLowerCase()===d}:"notEquals"===i?t?e=>{const t=s(e);return null!=t&&String(t)!==d}:e=>{const t=s(e);return null!=t&&String(t).toLowerCase()!==d}:"startsWith"===i?t?e=>{const t=s(e);return null!=t&&String(t).startsWith(d)}:e=>{const t=s(e);return null!=t&&String(t).toLowerCase().startsWith(d)}:"endsWith"===i?t?e=>{const t=s(e);return null!=t&&String(t).endsWith(d)}:e=>{const t=s(e);return null!=t&&String(t).toLowerCase().endsWith(d)}:()=>!0}(e,r,n?.get(e.field)));return 1===i.length?e.filter(i[0]):e.filter(e=>{for(let t=0;t<i.length;t++)if(!i[t](e))return!1;return!0})}function o(e,t,r){const n=new Set;let i=!1;for(const l of e){const e=l[t];if(r){const t=r(e,l);if(Array.isArray(t)){0===t.length&&(i=!0);for(const e of t)null!=e&&n.add(e)}else null!=t?n.add(t):i=!0}else null!=e&&""!==e?n.add(e):i=!0}return i&&n.add(l),[...n].sort((e,t)=>"number"==typeof e&&"number"==typeof t?e-t:String(e).localeCompare(String(t)))}function c(e){return e?e.toISOString().split("T")[0]:""}function d(e){return e?"string"==typeof e?e:"number"==typeof e?c(new Date(e)):"":""}function u(e,t,r,n,l,a){const{field:s,column:o}=t,c=function(e){if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-filter-item-height");if(t&&t.trim()){const e=parseFloat(t);if(!isNaN(e)&&e>0)return e}}return 28}(e),d=e=>{if(null==e)return"(Blank)";if(o.format&&!o.filterValue){const t=o.format(e,void 0);if(t)return t}return String(e)};r=r.slice().sort((e,t)=>"number"==typeof e&&"number"==typeof t?e-t:d(e).localeCompare(d(t)));const u=document.createElement("div");u.className="tbw-filter-search";const p=document.createElement("input");p.type="text",p.placeholder="Search...",p.className="tbw-filter-search-input",p.value=a.get(s)??"",u.appendChild(p),e.appendChild(u);const f=document.createElement("div");f.className="tbw-filter-actions";const h=document.createElement("label");h.className="tbw-filter-value-item",h.style.padding="0",h.style.margin="0";const b=document.createElement("input");b.type="checkbox",b.className="tbw-filter-checkbox";const g=document.createElement("span");g.textContent="Select All",h.appendChild(b),h.appendChild(g),f.appendChild(h);const m=new Map;r.forEach(e=>{const t=null==e?"__null__":String(e);m.set(t,!n.has(e))});const v=()=>{const e=[...m.values()],t=e.every(e=>e),r=e.every(e=>!e);b.checked=t,b.indeterminate=!t&&!r};b.addEventListener("change",()=>{const e=b.checked;for(const t of m.keys())m.set(t,e);v(),S()}),v(),e.appendChild(f);const w=document.createElement("div");w.className="tbw-filter-values";const y=document.createElement("div");y.className="tbw-filter-values-spacer",w.appendChild(y);const x=document.createElement("div");x.className="tbw-filter-values-content",w.appendChild(x);let C=[];const E=(e,t)=>{const r=d(e),n=null==e?"__null__":String(e),i=document.createElement("label");i.className="tbw-filter-value-item",i.style.position="absolute",i.style.top=`calc(var(--tbw-filter-item-height, 28px) * ${t})`,i.style.left="0",i.style.right="0",i.style.boxSizing="border-box";const l=document.createElement("input");l.type="checkbox",l.className="tbw-filter-checkbox",l.checked=m.get(n)??!0,l.dataset.value=n,l.addEventListener("change",()=>{m.set(n,l.checked),v()});const a=document.createElement("span");return a.textContent=r,i.appendChild(l),i.appendChild(a),i},S=()=>{const e=C.length,t=w.clientHeight,r=w.scrollTop;if(y.style.height=e*c+"px",i.shouldBypassVirtualization(e,50/3))return x.innerHTML="",x.style.transform="translateY(0px)",void C.forEach((e,t)=>{x.appendChild(E(e,t))});const n=i.computeVirtualWindow({totalRows:e,viewportHeight:t,scrollTop:r,rowHeight:c,overscan:3});x.style.transform=`translateY(${n.offsetY}px)`,x.innerHTML="";for(let i=n.start;i<n.end;i++)x.appendChild(E(C[i],i-n.start))},k=e=>{const t=l.caseSensitive??!1,n=t?e:e.toLowerCase();if(C=r.filter(r=>{const i=d(r),l=t?i:i.toLowerCase();return!e||l.includes(n)}),C.sort((e,t)=>{const r=null==e?"__null__":String(e),n=null==t?"__null__":String(t),i=m.get(r)??!0;return i!==(m.get(n)??!0)?i?-1:1:"number"==typeof e&&"number"==typeof t?e-t:d(e).localeCompare(d(t))}),0===C.length){y.style.height="0px",x.innerHTML="";const e=document.createElement("div");return e.className="tbw-filter-no-match",e.textContent="No matching values",void x.appendChild(e)}S()};let F;w.addEventListener("scroll",()=>{C.length>0&&S()},{passive:!0}),k(p.value),e.appendChild(w),p.addEventListener("input",()=>{clearTimeout(F),F=setTimeout(()=>{a.set(s,p.value),k(p.value)},l.debounceMs??150)});const N=document.createElement("div");N.className="tbw-filter-buttons";const T=document.createElement("button");T.className="tbw-filter-apply-btn",T.textContent="Apply",T.addEventListener("click",()=>{const e=[];for(const[t,n]of m)if(!n)if("__null__"===t)e.push(null);else{const n=r.find(e=>String(e)===t);e.push(void 0!==n?n:t)}t.applySetFilter(e)}),N.appendChild(T);const A=document.createElement("button");A.className="tbw-filter-clear-btn",A.textContent="Clear Filter",A.addEventListener("click",()=>{t.clearFilter()}),N.appendChild(A),e.appendChild(N)}function p(e,t){if("number"==typeof e)return e;if("string"==typeof e){const r=parseFloat(e);return isNaN(r)?t:r}return t}class f extends r.BaseGridPlugin{static manifest={events:[{type:"filter-change",description:"Emitted when filter criteria change. Broadcast to both DOM consumers and plugin bus."}],queries:[{type:"getContextMenuItems",description:"Contributes filter-related items to the header context menu"}]};name="filtering";styles='@layer tbw-plugins{tbw-grid .tbw-quick-filter-input{flex:1;max-width:300px;height:var(--tbw-input-height, 1.75rem);padding:var(--tbw-input-padding, 0 .5rem);border:1px solid var(--tbw-color-border);border-radius:var(--tbw-border-radius);background:var(--tbw-color-bg);color:var(--tbw-color-fg);font-size:var(--tbw-font-size-sm, .8125rem)}tbw-grid .tbw-quick-filter-input:focus{outline:none;border-color:var(--tbw-color-accent)}tbw-grid .header-cell.filtered:before{content:"";position:absolute;top:var(--tbw-spacing-xs, .25rem);right:var(--tbw-spacing-xs, .25rem);width:var(--tbw-indicator-size, .375rem);height:var(--tbw-indicator-size, .375rem);background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border-radius:50%}tbw-grid .tbw-filter-btn{display:var(--tbw-filter-btn-display, inline-flex);visibility:var(--tbw-filter-btn-visibility, visible);align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;padding:2px;margin-left:var(--tbw-spacing-xs, .25rem);opacity:.4;transition:opacity .15s,visibility 0s,display 0s allow-discrete;color:inherit;vertical-align:middle;transition-behavior:allow-discrete}tbw-grid .tbw-filter-btn:hover,tbw-grid .tbw-filter-btn.active{opacity:1;visibility:visible;display:inline-flex}tbw-grid .tbw-filter-btn.active{color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}tbw-grid .header-row .cell:hover .tbw-filter-btn,tbw-grid .header-row .cell.filtered .tbw-filter-btn{display:inline-flex;visibility:visible}}';get defaultConfig(){return{debounceMs:300,caseSensitive:!1,trimInput:!0,useWorker:!0}}isFilteringEnabled(){return!1!==this.grid.effectiveConfig?.filterable}isColumnFilterable(e){return!!this.isFilteringEnabled()&&!1!==e.filterable}getFilterValues(){const e=this.grid.effectiveConfig?.columns;if(!e)return;let t;for(const r of e)r.field&&r.filterValue&&(t||(t=new Map),t.set(r.field,r.filterValue));return t}filters=new Map;cachedResult=null;cacheKey=null;cachedInputSpot=null;openPanelField=null;panelElement=null;panelAnchorElement=null;panelButtonElement=null;searchText=new Map;excludedValues=new Map;panelAbortController=null;globalStylesInjected=!1;computeSelected(){const e={},t=[];for(const[r,n]of this.filters)if("set"===n.type)if("in"===n.operator&&Array.isArray(n.value))e[r]=n.value;else if("notIn"===n.operator){const e=this.grid.effectiveConfig?.columns?.find(e=>e.field===r);t.push({field:r,filterValue:e?.filterValue})}if(t.length>0){const r=function(e,t){const r=new Map;for(const{field:i,filterValue:l}of t)r.set(i,{values:new Set,hasBlank:!1,hasExtractor:!!l});for(const i of e)for(const{field:e,filterValue:n}of t){const t=r.get(e),l=i[e];if(n){const e=n(l,i);if(Array.isArray(e)){0===e.length&&(t.hasBlank=!0);for(const r of e)null!=r&&t.values.add(r)}else null!=e?t.values.add(e):t.hasBlank=!0}else null!=l&&""!==l?t.values.add(l):t.hasBlank=!0}const n=new Map;for(const[i,{values:a,hasBlank:s}]of r)s&&a.add(l),n.set(i,[...a].sort((e,t)=>"number"==typeof e&&"number"==typeof t?e-t:String(e).localeCompare(String(t))));return n}(this.sourceRows,t);for(const{field:n}of t){const t=this.excludedValues.get(n),i=r.get(n)??[];e[n]=t?i.filter(e=>!t.has(e)):i}}return e}syncExcludedValues(e,t){if(t)if("set"===t.type&&"notIn"===t.operator&&Array.isArray(t.value))this.excludedValues.set(e,new Set(t.value));else if("set"===t.type&&"in"===t.operator&&Array.isArray(t.value)){const r=this.sourceRows;if(!r||0===r.length)return void this.excludedValues.delete(e);const n=t.value,i=new Set(n.map(e=>null==e?l:e)),a=this.getUniqueValues(e),s=new Set(a.filter(e=>!i.has(e)));this.excludedValues.set(e,s)}else"set"===t.type&&this.excludedValues.delete(e);else this.excludedValues.delete(e)}attach(e){super.attach(e),this.injectGlobalStyles()}detach(){this.filters.clear(),this.cachedResult=null,this.cacheKey=null,this.cachedInputSpot=null,this.openPanelField=null,this.panelElement&&(this.panelElement.remove(),this.panelElement=null),this.searchText.clear(),this.excludedValues.clear(),this.panelAbortController?.abort(),this.panelAbortController=null}handleQuery(e){if("getContextMenuItems"===e.type){const t=e.context;if(!t.isHeader)return;const r=t.column;if(!r?.field)return;if(!this.isFilteringEnabled())return;if(!this.isColumnFilterable(r))return;const n=[],i=this.isFieldFiltered(r.field),l=this.filters.size>0;return i&&n.push({id:"filtering/clear-column-filter",label:"Clear Filter",icon:"✕",order:20,action:()=>this.clearFieldFilter(r.field)}),l&&n.push({id:"filtering/clear-all-filters",label:"Clear All Filters",icon:"✕",order:21,disabled:!l,action:()=>this.clearAllFilters()}),n.length>0?n:void 0}}processRows(e){if(!this.filters.size)return e;const t=[...this.filters.values()];if(this.config.filterHandler)return this.cachedResult?this.cachedResult:e;const r=(n=t,JSON.stringify(n.map(e=>({field:e.field,operator:e.operator,value:e.value,valueTo:e.valueTo}))));var n;const i={len:e.length,first:e[0],mid:e[Math.floor(e.length/2)],last:e[e.length-1]},l=null!=this.cachedInputSpot&&i.len===this.cachedInputSpot.len&&i.first===this.cachedInputSpot.first&&i.mid===this.cachedInputSpot.mid&&i.last===this.cachedInputSpot.last;if(this.cacheKey===r&&this.cachedResult&&l)return this.cachedResult;if(!l)for(const[s,o]of this.filters)"set"===o.type&&"in"===o.operator&&this.syncExcludedValues(s,o);const a=s(e,t,this.config.caseSensitive,this.getFilterValues());return this.cachedResult=a,this.cacheKey=r,this.cachedInputSpot=i,a}afterRender(){const e=this.gridElement;if(!e)return;e.querySelectorAll('[part~="header-cell"]').forEach(e=>{const t=e.getAttribute("data-col");if(null===t)return;const r=this.visibleColumns[parseInt(t,10)];if(!r||!this.isColumnFilterable(r))return;if(n.isUtilityColumn(r))return;const i=r.field;if(!i)return;const l=this.filters.has(i);let a=e.querySelector(".tbw-filter-btn");if(a){const t=a.classList.contains("active");return a.classList.toggle("active",l),e.classList.toggle("filtered",l),l?e.setAttribute("aria-description","Filtered"):e.removeAttribute("aria-description"),void(t!==l&&this.setIcon(a,l?"filterActive":"filter"))}a=document.createElement("button"),a.className="tbw-filter-btn",a.setAttribute("aria-label",`Filter ${r.header??i}`),this.setIcon(a,l?"filterActive":"filter"),l&&(a.classList.add("active"),e.classList.add("filtered"),e.setAttribute("aria-description","Filtered")),a.addEventListener("click",e=>{e.stopPropagation(),this.toggleFilterPanel(i,r,a)});const s=e.querySelector(".resize-handle");s?e.insertBefore(a,s):e.appendChild(a)})}setFilter(e,r,n){if(null===r)this.filters.delete(e),this.syncExcludedValues(e,null);else{const t={...r,field:e};this.filters.set(e,t),this.syncExcludedValues(e,t)}if(this.cachedResult=null,this.cacheKey=null,this.cachedInputSpot=null,n?.silent)this.emitPluginEvent("filter-change",{filters:[...this.filters.values()]});else{this.broadcast("filter-change",{filters:[...this.filters.values()],filteredRowCount:0,selected:this.computeSelected()}),this.config.trackColumnState&&this.grid.requestStateChange?.();const n=this.grid.effectiveConfig?.columns?.find(t=>t.field===e)?.header??e;t.announce(this.gridElement,null===r?t.getA11yMessage(this.gridElement,"filterCleared",n):t.getA11yMessage(this.gridElement,"filterApplied",n))}this.requestRender()}getFilter(e){return this.filters.get(e)}getFilters(){return[...this.filters.values()]}getFilterModel(){return this.getFilters()}setFilterModel(e,t){this.filters.clear(),this.excludedValues.clear();for(const r of e)this.filters.set(r.field,r),this.syncExcludedValues(r.field,r);this.cachedResult=null,this.cacheKey=null,this.cachedInputSpot=null,t?.silent?this.emitPluginEvent("filter-change",{filters:[...this.filters.values()]}):(this.broadcast("filter-change",{filters:[...this.filters.values()],filteredRowCount:0,selected:this.computeSelected()}),this.config.trackColumnState&&this.grid.requestStateChange?.()),this.requestRender()}clearAllFilters(e){this.filters.clear(),this.excludedValues.clear(),this.searchText.clear(),this.applyFiltersInternal(e?.silent),e?.silent||t.announce(this.gridElement,t.getA11yMessage(this.gridElement,"allFiltersCleared"))}clearFieldFilter(e,r){if(this.filters.delete(e),this.excludedValues.delete(e),this.searchText.delete(e),this.applyFiltersInternal(r?.silent),!r?.silent){const r=this.grid.effectiveConfig?.columns?.find(t=>t.field===e)?.header??e;t.announce(this.gridElement,t.getA11yMessage(this.gridElement,"filterCleared",r))}}isFieldFiltered(e){return this.filters.has(e)}getFilteredRowCount(){return this.cachedResult?.length??this.rows.length}getActiveFilters(){return this.getFilters()}getUniqueValues(e){const t=this.grid.effectiveConfig?.columns?.find(t=>t.field===e),r=t?.filterValue;return o(this.sourceRows,e,r)}getStaleFilters(){const e=[];for(const[t,r]of this.filters){if("set"!==r.type)continue;const n=this.getUniqueValues(t);if("notIn"===r.operator&&Array.isArray(r.value)){const t=new Set(r.value);0===n.filter(e=>!t.has(e)).length&&e.push(r)}else if("in"===r.operator&&Array.isArray(r.value)){const t=new Set(r.value);0===n.filter(e=>t.has(e)).length&&e.push(r)}}return e}getBlankMode(e){const t=this.filters.get(e);return"blank"===t?.operator?"blanksOnly":"notBlank"===t?.operator?"nonBlanksOnly":"all"}toggleBlankFilter(e,t){if("all"===t){const t=this.filters.get(e);if(t?.valueTo&&"object"==typeof t.valueTo){const r=t.valueTo;this.setFilter(e,r)}else this.setFilter(e,null);return}const r=this.filters.get(e),n=r&&"blank"!==r.operator&&"notBlank"!==r.operator?{type:r.type,operator:r.operator,value:r.value,valueTo:r.valueTo}:r?.valueTo;this.setFilter(e,{type:r?.type??"text",operator:"blanksOnly"===t?"blank":"notBlank",value:"",valueTo:n})}copyGridThemeContext(e){const t=this.gridElement;if(!t)return;for(const n of t.classList)n.startsWith("tbw-")||"selecting"===n||e.classList.add(n);const r=t.dataset.theme;r&&(e.dataset.theme=r)}injectGlobalStyles(){if(this.globalStylesInjected)return;if(document.getElementById("tbw-filter-panel-styles"))return void(this.globalStylesInjected=!0);const e=document.createElement("style");e.id="tbw-filter-panel-styles",e.textContent="@layer tbw-plugins{.tbw-filter-panel{position:fixed;background:var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));color:var(--tbw-filter-panel-fg, var(--tbw-color-fg, light-dark(#222222, #eeeeee)));border:1px solid var(--tbw-filter-panel-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-panel-radius, var(--tbw-border-radius, .25rem));box-shadow:0 4px 16px var(--tbw-filter-panel-shadow, var(--tbw-color-shadow, light-dark(rgba(0, 0, 0, .1), rgba(0, 0, 0, .3))));padding:var(--tbw-panel-padding, var(--tbw-spacing-lg, .75rem));z-index:10000;min-width:200px;max-width:280px;max-height:350px;display:flex;flex-direction:column;font-family:var(--tbw-font-family, system-ui, sans-serif);font-size:var(--tbw-font-size, .8125rem);transform-origin:top center}.tbw-filter-panel.tbw-filter-panel-above{transform-origin:bottom center}.tbw-filter-panel.tbw-filter-panel-animated{animation:tbw-filter-panel-enter var(--tbw-animation-duration, .15s) var(--tbw-animation-easing, ease-out)}.tbw-filter-panel.tbw-filter-panel-above.tbw-filter-panel-animated{animation:tbw-filter-panel-enter-above var(--tbw-animation-duration, .15s) var(--tbw-animation-easing, ease-out)}@keyframes tbw-filter-panel-enter{0%{opacity:0;transform:scaleY(.3) translateY(-10px)}to{opacity:1;transform:scaleY(1) translateY(0)}}@keyframes tbw-filter-panel-enter-above{0%{opacity:0;transform:scaleY(.3) translateY(10px)}to{opacity:1;transform:scaleY(1) translateY(0)}}@supports (anchor-name: --test){.tbw-filter-panel{position-anchor:--tbw-filter-anchor;top:anchor(bottom);right:anchor(right);margin-top:4px;position-try-fallbacks:flip-inline,flip-block,flip-block flip-inline}}.tbw-filter-search{margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));min-height:var(--tbw-filter-item-height, 28px)}.tbw-filter-search-input{height:var(--tbw-filter-item-height, 28px);width:100%;padding:var(--tbw-filter-search-padding, var(--tbw-spacing-sm, .375rem) var(--tbw-spacing-md, .5rem));background:var(--tbw-filter-input-bg, var(--tbw-color-bg, transparent));color:inherit;border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-input-radius, var(--tbw-border-radius, .25rem));font-size:inherit;box-sizing:border-box}.tbw-filter-search-input:focus{outline:none;border-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));box-shadow:0 0 0 2px rgba(from var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6)) r g b / 15%)}.tbw-filter-actions{display:flex;padding:var(--tbw-button-padding-sm, .25rem .125rem);margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));border-bottom:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));min-height:var(--tbw-filter-item-height, 28px)}.tbw-filter-actions .tbw-filter-value-item{flex:1}.tbw-filter-values{flex:1;overflow-y:auto;margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));max-height:180px;position:relative}.tbw-filter-values-spacer{width:1px}.tbw-filter-values-content{position:absolute;top:0;left:0;right:0}.tbw-filter-value-item{display:flex;align-items:center;gap:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));padding:var(--tbw-button-padding-sm, .25rem .125rem);cursor:pointer;border-radius:3px;height:var(--tbw-filter-item-height, 28px)}.tbw-filter-value-item:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}.tbw-filter-checkbox{margin:0;cursor:pointer;accent-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}.tbw-filter-no-match{color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));padding:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem)) 0;text-align:center;font-style:italic}.tbw-filter-buttons{display:flex;gap:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));padding-top:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));border-top:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-apply-btn{flex:1;padding:var(--tbw-filter-btn-padding, var(--tbw-button-padding, .375rem .75rem));background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));color:var(--tbw-filter-accent-fg, var(--tbw-color-accent-fg, light-dark(#ffffff, #000000)));border:none;border-radius:var(--tbw-border-radius, .25rem);cursor:pointer;font-size:var(--tbw-font-size-sm, .8125rem);font-weight:var(--tbw-filter-btn-font-weight, 500);min-height:var(--tbw-filter-btn-min-height, auto)}.tbw-filter-apply-btn:hover{filter:brightness(.9)}.tbw-filter-clear-btn{flex:1;padding:var(--tbw-filter-btn-padding, var(--tbw-button-padding, .375rem .75rem));background:transparent;color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-border-radius, .25rem);cursor:pointer;font-size:var(--tbw-font-size-sm, .8125rem);font-weight:var(--tbw-filter-btn-font-weight, 500);min-height:var(--tbw-filter-btn-min-height, auto)}.tbw-filter-clear-btn:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}.tbw-filter-range-inputs,.tbw-filter-date-range{display:flex;align-items:flex-end;gap:var(--tbw-spacing-sm, .375rem);margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem))}.tbw-filter-range-group,.tbw-filter-date-group{display:flex;flex-direction:column;gap:var(--tbw-spacing-xs, .25rem);flex:1}.tbw-filter-range-label{font-size:var(--tbw-font-size-xs, .75rem);color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)))}.tbw-filter-range-input,.tbw-filter-date-input{width:100%;height:var(--tbw-filter-item-height, 28px);padding:var(--tbw-spacing-xs, .25rem) var(--tbw-spacing-sm, .375rem);background:var(--tbw-filter-input-bg, var(--tbw-color-bg, transparent));color:inherit;border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-input-radius, var(--tbw-border-radius, .25rem));font-size:inherit;box-sizing:border-box}.tbw-filter-range-input:focus,.tbw-filter-date-input:focus{outline:none;border-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));box-shadow:0 0 0 2px rgba(from var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6)) r g b / 15%)}.tbw-filter-range-separator{color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));padding-bottom:var(--tbw-spacing-xs, .25rem)}.tbw-filter-blank-option{display:flex;align-items:center;gap:var(--tbw-spacing-sm, .375rem);padding:var(--tbw-spacing-xs, .25rem) 0;margin-bottom:var(--tbw-spacing-xs, .25rem);font-size:var(--tbw-font-size-sm, .8125rem);cursor:pointer;-webkit-user-select:none;user-select:none}.tbw-filter-blank-checkbox{accent-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));margin:0;cursor:pointer}.tbw-filter-date-range.tbw-filter-disabled,.tbw-filter-range-inputs.tbw-filter-disabled,.tbw-filter-range-slider.tbw-filter-disabled{opacity:.4;pointer-events:none}.tbw-filter-range-slider{position:relative;height:24px;margin:var(--tbw-spacing-md, .5rem) 0 var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem))}.tbw-filter-range-track{position:absolute;top:50%;left:0;right:0;height:4px;background:var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:2px;transform:translateY(-50%)}.tbw-filter-range-fill{position:absolute;top:50%;height:4px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border-radius:2px;transform:translateY(-50%)}.tbw-filter-range-thumb{position:absolute;top:0;width:100%;height:100%;background:none;pointer-events:none;-webkit-appearance:none;appearance:none}.tbw-filter-range-thumb::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border:2px solid var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));border-radius:50%;cursor:pointer;pointer-events:all;box-shadow:0 1px 3px #0003}.tbw-filter-range-thumb::-moz-range-thumb{width:16px;height:16px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border:2px solid var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));border-radius:50%;cursor:pointer;pointer-events:all;box-shadow:0 1px 3px #0003}.tbw-filter-range-thumb::-webkit-slider-thumb:hover{transform:scale(1.1)}.tbw-filter-range-thumb::-moz-range-thumb:hover{transform:scale(1.1)}}",document.head.appendChild(e),this.globalStylesInjected=!0}toggleFilterPanel(e,t,r){if(this.openPanelField===e)return void this.closeFilterPanel();this.closeFilterPanel();const n=document.createElement("div");if(n.className="tbw-filter-panel",this.copyGridThemeContext(n),this.isAnimationEnabled&&n.classList.add("tbw-filter-panel-animated"),this.panelElement=n,this.openPanelField=e,r.classList.add("active"),this.panelButtonElement=r,this.config.valuesHandler)return n.innerHTML='<div class="tbw-filter-loading">Loading...</div>',document.body.appendChild(n),this.positionPanel(n,r),this.setupPanelCloseHandler(n,r),void this.config.valuesHandler(e,t).then(r=>{this.openPanelField===e&&this.panelElement&&(n.innerHTML="",this.renderPanelContent(e,t,n,r))});const i=o(this.sourceRows,e,t.filterValue);document.body.appendChild(n),this.positionPanel(n,r),this.renderPanelContent(e,t,n,i),this.setupPanelCloseHandler(n,r)}renderPanelContent(e,t,r,n){const i=this.filters.get(e);if("in"===i?.operator&&"set"===i.type&&Array.isArray(i.value)&&!this.excludedValues.has(e)){const t=i.value,r=new Set(t.map(e=>null==e?l:e)),a=new Set(n.filter(e=>!r.has(e)));this.excludedValues.set(e,a)}let a=this.excludedValues.get(e);a||(a=new Set,this.excludedValues.set(e,a));const s=this.searchText.get(e)??"",o={field:e,column:t,uniqueValues:n,excludedValues:a,searchText:s,currentFilter:this.filters.get(e),applySetFilter:(t,r)=>{this.applySetFilter(e,t,r),this.closeFilterPanel()},applyTextFilter:(t,r,n)=>{this.applyTextFilter(e,t,r,n),this.closeFilterPanel()},clearFilter:()=>{this.clearFieldFilter(e),this.closeFilterPanel()},closePanel:()=>this.closeFilterPanel()};let f=!1;if(this.config.filterPanelRenderer&&(this.config.filterPanelRenderer(r,o),f=r.children.length>0),!f&&t.type){const e=this.grid.effectiveConfig.typeDefaults?.[t.type];e?.filterPanelRenderer&&(e.filterPanelRenderer(r,o),f=r.children.length>0)}if(!f){const e=t.filterType??t.type;"number"===e?function(e,t,r,n){const{field:i,column:l}=t,a=l.filterParams,s=l.editorParams,o=r.filter(e=>"number"==typeof e&&!isNaN(e)),c=o.length>0?Math.min(...o):0,d=o.length>0?Math.max(...o):100,u=p(a?.min??s?.min,c),f=p(a?.max??s?.max,d),h=a?.step??s?.step??1,b=n.get(i);let g=u,m=f;const v="blank"===b?.operator;"between"===b?.operator?(g=p(b.value,u),m=p(b.valueTo,f)):"greaterThanOrEqual"===b?.operator?g=p(b.value,u):"lessThanOrEqual"===b?.operator&&(m=p(b.value,f));const w=document.createElement("div");w.className="tbw-filter-range-inputs";const y=document.createElement("div");y.className="tbw-filter-range-group";const x=document.createElement("label");x.textContent="Min",x.className="tbw-filter-range-label";const C=document.createElement("input");C.type="number",C.className="tbw-filter-range-input",C.min=String(u),C.max=String(f),C.step=String(h),C.value=String(g),y.appendChild(x),y.appendChild(C),w.appendChild(y);const E=document.createElement("span");E.className="tbw-filter-range-separator",E.textContent="–",w.appendChild(E);const S=document.createElement("div");S.className="tbw-filter-range-group";const k=document.createElement("label");k.textContent="Max",k.className="tbw-filter-range-label";const F=document.createElement("input");F.type="number",F.className="tbw-filter-range-input",F.min=String(u),F.max=String(f),F.step=String(h),F.value=String(m),S.appendChild(k),S.appendChild(F),w.appendChild(S),e.appendChild(w);const N=document.createElement("div");N.className="tbw-filter-range-slider";const T=document.createElement("div");T.className="tbw-filter-range-track";const A=document.createElement("div");A.className="tbw-filter-range-fill";const L=document.createElement("input");L.type="range",L.className="tbw-filter-range-thumb tbw-filter-range-thumb-min",L.min=String(u),L.max=String(f),L.step=String(h),L.value=String(g);const P=document.createElement("input");P.type="range",P.className="tbw-filter-range-thumb tbw-filter-range-thumb-max",P.min=String(u),P.max=String(f),P.step=String(h),P.value=String(m),N.appendChild(T),N.appendChild(A),N.appendChild(L),N.appendChild(P),e.appendChild(N);const R=document.createElement("label");R.className="tbw-filter-blank-option";const V=document.createElement("input");V.type="checkbox",V.className="tbw-filter-blank-checkbox",V.checked=v;const M=document.createTextNode("Blank");R.appendChild(V),R.appendChild(M);const I=e=>{C.disabled=e,F.disabled=e,L.disabled=e,P.disabled=e,w.classList.toggle("tbw-filter-disabled",e),N.classList.toggle("tbw-filter-disabled",e)};I(v),V.addEventListener("change",()=>{I(V.checked)}),e.appendChild(R);const q=()=>{const e=parseFloat(L.value),t=parseFloat(P.value),r=f-u,n=(e-u)/r*100,i=(t-u)/r*100;A.style.left=`${n}%`,A.style.width=i-n+"%"};L.addEventListener("input",()=>{const e=Math.min(parseFloat(L.value),parseFloat(P.value));L.value=String(e),C.value=String(e),q()}),P.addEventListener("input",()=>{const e=Math.max(parseFloat(P.value),parseFloat(L.value));P.value=String(e),F.value=String(e),q()}),C.addEventListener("input",()=>{const e=parseFloat(C.value);let t=Number.isFinite(e)?e:u;t=Math.max(u,Math.min(t,parseFloat(F.value))),L.value=String(t),q()}),F.addEventListener("input",()=>{const e=parseFloat(F.value);let t=Number.isFinite(e)?e:f;t=Math.min(f,Math.max(t,parseFloat(C.value))),P.value=String(t),q()}),q();const B=document.createElement("div");B.className="tbw-filter-buttons";const z=document.createElement("button");z.className="tbw-filter-apply-btn",z.textContent="Apply",z.addEventListener("click",()=>{if(V.checked)return void t.applyTextFilter("blank","");const e=parseFloat(C.value),r=parseFloat(F.value),n=Number.isFinite(e)?e:u,i=Number.isFinite(r)?r:f;n!==u||i!==f?t.applyTextFilter("between",n,i):t.clearFilter()}),B.appendChild(z);const _=document.createElement("button");_.className="tbw-filter-clear-btn",_.textContent="Clear Filter",_.addEventListener("click",()=>{t.clearFilter()}),B.appendChild(_),e.appendChild(B)}(r,o,n,this.filters):"date"===e?function(e,t,r,n){const{field:i,column:l}=t,a=l.filterParams,s=l.editorParams,o=r.filter(e=>e instanceof Date||"string"==typeof e&&!isNaN(Date.parse(e))).map(e=>e instanceof Date?e:new Date(e)).filter(e=>!isNaN(e.getTime())),u=o.length>0?new Date(Math.min(...o.map(e=>e.getTime()))):null,p=o.length>0?new Date(Math.max(...o.map(e=>e.getTime()))):null,f=d(a?.min)||d(s?.min)||c(u),h=d(a?.max)||d(s?.max)||c(p),b=n.get(i);let g="",m="";const v="blank"===b?.operator;"between"===b?.operator?(g=d(b.value)||"",m=d(b.valueTo)||""):"greaterThanOrEqual"===b?.operator?g=d(b.value)||"":"lessThanOrEqual"===b?.operator&&(m=d(b.value)||"");const w=document.createElement("div");w.className="tbw-filter-date-range";const y=document.createElement("div");y.className="tbw-filter-date-group";const x=document.createElement("label");x.textContent="From",x.className="tbw-filter-range-label";const C=document.createElement("input");C.type="date",C.className="tbw-filter-date-input",f&&(C.min=f),h&&(C.max=h),C.value=g,y.appendChild(x),y.appendChild(C),w.appendChild(y);const E=document.createElement("span");E.className="tbw-filter-range-separator",E.textContent="–",w.appendChild(E);const S=document.createElement("div");S.className="tbw-filter-date-group";const k=document.createElement("label");k.textContent="To",k.className="tbw-filter-range-label";const F=document.createElement("input");F.type="date",F.className="tbw-filter-date-input",f&&(F.min=f),h&&(F.max=h),F.value=m,S.appendChild(k),S.appendChild(F),w.appendChild(S),e.appendChild(w);const N=document.createElement("label");N.className="tbw-filter-blank-option";const T=document.createElement("input");T.type="checkbox",T.className="tbw-filter-blank-checkbox",T.checked=v;const A=document.createTextNode("Show only blank");N.appendChild(T),N.appendChild(A);const L=e=>{C.disabled=e,F.disabled=e,w.classList.toggle("tbw-filter-disabled",e)};L(v),T.addEventListener("change",()=>{L(T.checked)}),e.appendChild(N);const P=document.createElement("div");P.className="tbw-filter-buttons";const R=document.createElement("button");R.className="tbw-filter-apply-btn",R.textContent="Apply",R.addEventListener("click",()=>{if(T.checked)return void t.applyTextFilter("blank","");const e=C.value,r=F.value;e&&r?t.applyTextFilter("between",e,r):e?t.applyTextFilter("greaterThanOrEqual",e):r?t.applyTextFilter("lessThanOrEqual",r):t.clearFilter()}),P.appendChild(R);const V=document.createElement("button");V.className="tbw-filter-clear-btn",V.textContent="Clear Filter",V.addEventListener("click",()=>{t.clearFilter()}),P.appendChild(V),e.appendChild(P)}(r,o,n,this.filters):u(r,o,n,a,{caseSensitive:this.config.caseSensitive,debounceMs:this.config.debounceMs},this.searchText)}}setupPanelCloseHandler(e,t){this.panelAbortController=new AbortController;const{signal:r}=this.panelAbortController;setTimeout(()=>{r.aborted||document.addEventListener("click",r=>{e.contains(r.target)||r.target===t||this.closeFilterPanel()},{signal:r})},0)}closeFilterPanel(){const e=this.panelElement;if(e&&(e.remove(),this.panelElement=null),this.panelAnchorElement&&(this.panelAnchorElement.style.anchorName="",this.panelAnchorElement=null),this.panelButtonElement){const e=this.openPanelField;e&&this.filters.has(e)||this.panelButtonElement.classList.remove("active"),this.panelButtonElement=null}this.openPanelField=null,this.panelAbortController?.abort(),this.panelAbortController=null}static supportsAnchorPositioning=null;static checkAnchorPositioningSupport(){return null===f.supportsAnchorPositioning&&(f.supportsAnchorPositioning=CSS.supports("anchor-name","--test")),f.supportsAnchorPositioning}positionPanel(e,t){const r=t.closest(".header-row")??t;if(r.style.anchorName="--tbw-filter-anchor",this.panelAnchorElement=r,f.checkAnchorPositioningSupport()){r.style.anchorName="",t.style.anchorName="--tbw-filter-anchor",this.panelAnchorElement=t;const n=r.getBoundingClientRect().bottom-t.getBoundingClientRect().bottom;return e.style.marginTop=`${n+4}px`,void requestAnimationFrame(()=>{const r=e.getBoundingClientRect(),n=t.getBoundingClientRect();r.top<n.top&&e.classList.add("tbw-filter-panel-above")})}const n=r.getBoundingClientRect(),i=t.getBoundingClientRect();e.style.position="fixed",e.style.top=`${n.bottom+4}px`,e.style.left=`${i.right}px`,requestAnimationFrame(()=>{const t=e.getBoundingClientRect();e.style.left=i.right-t.width+"px";i.right-t.width<8&&(e.style.left=`${i.left}px`),t.bottom>window.innerHeight-8&&(e.style.top=n.top-t.height-4+"px",e.classList.add("tbw-filter-panel-above"))})}applySetFilter(e,t,r){if(this.excludedValues.set(e,new Set(t)),0===t.length)this.filters.delete(e);else{const n=this.filters.get(e);if("in"===n?.operator){const n=this.getUniqueValues(e),i=new Set(t),l=n.filter(e=>!i.has(e));this.filters.set(e,{field:e,type:"set",operator:"in",value:l,...void 0!==r&&{valueTo:r}})}else this.filters.set(e,{field:e,type:"set",operator:"notIn",value:t,...void 0!==r&&{valueTo:r}})}this.applyFiltersInternal()}applyTextFilter(e,t,r,n){const i=this.grid.effectiveConfig?.columns?.find(t=>t.field===e),l=i?.filterType??i?.type??"text";this.filters.set(e,{field:e,type:l,operator:t,value:r,valueTo:n}),this.applyFiltersInternal()}applyFiltersInternal(e){this.cachedResult=null,this.cacheKey=null,this.cachedInputSpot=null;const t=[...this.filters.values()];if(this.config.filterHandler){this.gridElement.setAttribute("aria-busy","true");const r=this.config.filterHandler(t,this.sourceRows),n=r=>{this.gridElement.removeAttribute("aria-busy"),this.cachedResult=r,this.grid.rows=r,e?this.emitPluginEvent("filter-change",{filters:t}):(this.broadcast("filter-change",{filters:t,filteredRowCount:r.length,selected:this.computeSelected()}),this.config.trackColumnState&&this.grid.requestStateChange?.()),this.requestRender()};return void(r&&"function"==typeof r.then?r.then(n):n(r))}e?this.emitPluginEvent("filter-change",{filters:t}):(this.broadcast("filter-change",{filters:t,filteredRowCount:0,selected:this.computeSelected()}),this.config.trackColumnState&&this.grid.requestStateChange?.()),this.requestRender()}getColumnState(e){if(!this.config.trackColumnState)return;const t=this.filters.get(e);return t?{filter:{type:t.type,operator:t.operator,value:t.value,valueTo:t.valueTo}}:void 0}applyColumnState(e,t){if(!this.config.trackColumnState)return;if(!t.filter)return void this.filters.delete(e);const r={field:e,type:t.filter.type,operator:t.filter.operator,value:t.filter.value,valueTo:t.filter.valueTo};this.filters.set(e,r),this.cachedResult=null,this.cacheKey=null,this.cachedInputSpot=null}}e.BLANK_FILTER_VALUE=l,e.FilteringPlugin=f,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("../../core/internal/aria"),require("../../core/internal/value-accessor"),require("../../core/plugin/base-plugin"),require("../../core/plugin/expander-column"),require("../../core/internal/virtualization")):"function"==typeof define&&define.amd?define(["exports","../../core/internal/aria","../../core/internal/value-accessor","../../core/plugin/base-plugin","../../core/plugin/expander-column","../../core/internal/virtualization"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TbwGridPlugin_filtering={},e.TbwGrid,e.TbwGrid,e.TbwGrid,e.TbwGrid,e.TbwGrid)}(this,function(e,t,r,n,i,l){"use strict";const a="(Blank)";function s(e){if("number"==typeof e)return e;if(e instanceof Date)return e.getTime();const t=Number(e);if(!isNaN(t))return t;return new Date(e).getTime()}function o(e,t,r=!1,n){if(!t.length)return e;const i=t.map(e=>function(e,t,r){const n=e.field,i=e.operator,l=r?e=>r(e[n],e):e=>e[n];if("blank"===i)return e=>{const t=l(e);return null==t||""===t||"number"==typeof t&&isNaN(t)};if("notBlank"===i)return e=>{const t=l(e);return null!=t&&""!==t&&!("number"==typeof t&&isNaN(t))};if(r&&("notIn"===i||"in"===i)){const t=e.value;if("notIn"===i){if(!Array.isArray(t))return()=>!0;const e=new Set(t);return t=>{const i=r(t[n],t),l=Array.isArray(i)?i:null!=i?[i]:[];return 0===l.length?!e.has(a):!l.some(t=>e.has(t))}}if(!Array.isArray(t))return()=>!1;const l=new Set(t);return e=>{const t=r(e[n],e),i=Array.isArray(t)?t:null!=t?[t]:[];return 0===i.length?l.has(a):i.some(e=>l.has(e))}}if("notIn"===i){if(!Array.isArray(e.value))return()=>!0;const t=new Set(e.value);return e=>{const r=e[n];return null==r||""===r?!t.has(a):!t.has(r)}}if("in"===i){if(!Array.isArray(e.value))return()=>!1;const t=new Set(e.value);return e=>{const r=e[n];return null==r||""===r?t.has(a):t.has(r)}}const o="number"===e.type&&!r,c=e=>null==e||""===e||"number"==typeof e&&isNaN(e);if("greaterThan"===i){const t=s(e.value);return o?e=>{const r=e[n];return!c(r)&&r>t}:e=>{const r=l(e);if(c(r))return!1;const n=s(r);return!isNaN(n)&&n>t}}if("greaterThanOrEqual"===i){const t=s(e.value);return o?e=>{const r=e[n];return!c(r)&&r>=t}:e=>{const r=l(e);if(c(r))return!1;const n=s(r);return!isNaN(n)&&n>=t}}if("lessThan"===i){const t=s(e.value);return o?e=>{const r=e[n];return!c(r)&&r<t}:e=>{const r=l(e);if(c(r))return!1;const n=s(r);return!isNaN(n)&&n<t}}if("lessThanOrEqual"===i){const t=s(e.value);return o?e=>{const r=e[n];return!c(r)&&r<=t}:e=>{const r=l(e);if(c(r))return!1;const n=s(r);return!isNaN(n)&&n<=t}}if("between"===i){const t=s(e.value),r=s(e.valueTo);return o?e=>{const i=e[n];return!c(i)&&(i>=t&&i<=r)}:e=>{const n=l(e);if(c(n))return!1;const i=s(n);return!isNaN(i)&&i>=t&&i<=r}}const d=t?String(e.value):String(e.value).toLowerCase();return"contains"===i?t?e=>{const t=l(e);return null!=t&&String(t).includes(d)}:e=>{const t=l(e);return null!=t&&String(t).toLowerCase().includes(d)}:"notContains"===i?t?e=>{const t=l(e);return null!=t&&!String(t).includes(d)}:e=>{const t=l(e);return null!=t&&!String(t).toLowerCase().includes(d)}:"equals"===i?t?e=>{const t=l(e);return null!=t&&String(t)===d}:e=>{const t=l(e);return null!=t&&String(t).toLowerCase()===d}:"notEquals"===i?t?e=>{const t=l(e);return null!=t&&String(t)!==d}:e=>{const t=l(e);return null!=t&&String(t).toLowerCase()!==d}:"startsWith"===i?t?e=>{const t=l(e);return null!=t&&String(t).startsWith(d)}:e=>{const t=l(e);return null!=t&&String(t).toLowerCase().startsWith(d)}:"endsWith"===i?t?e=>{const t=l(e);return null!=t&&String(t).endsWith(d)}:e=>{const t=l(e);return null!=t&&String(t).toLowerCase().endsWith(d)}:()=>!0}(e,r,n?.get(e.field)));return 1===i.length?e.filter(i[0]):e.filter(e=>{for(let t=0;t<i.length;t++)if(!i[t](e))return!1;return!0})}function c(e,t,r){const n=new Set;let i=!1;for(const l of e){const e=l[t];if(r){const t=r(e,l);if(Array.isArray(t)){0===t.length&&(i=!0);for(const e of t)null!=e&&n.add(e)}else null!=t?n.add(t):i=!0}else null!=e&&""!==e?n.add(e):i=!0}return i&&n.add(a),[...n].sort((e,t)=>"number"==typeof e&&"number"==typeof t?e-t:String(e).localeCompare(String(t)))}function d(e){return e?e.toISOString().split("T")[0]:""}function u(e){return e?"string"==typeof e?e:"number"==typeof e?d(new Date(e)):"":""}function p(e,t,r,n,i,a){const{field:s,column:o}=t,c=function(e){if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-filter-item-height");if(t&&t.trim()){const e=parseFloat(t);if(!isNaN(e)&&e>0)return e}}return 28}(e),d=e=>{if(null==e)return"(Blank)";if(o.format&&!o.filterValue){const t=o.format(e,void 0);if(t)return t}return String(e)};r=r.slice().sort((e,t)=>"number"==typeof e&&"number"==typeof t?e-t:d(e).localeCompare(d(t)));const u=document.createElement("div");u.className="tbw-filter-search";const p=document.createElement("input");p.type="text",p.placeholder="Search...",p.className="tbw-filter-search-input",p.value=a.get(s)??"",u.appendChild(p),e.appendChild(u);const f=document.createElement("div");f.className="tbw-filter-actions";const h=document.createElement("label");h.className="tbw-filter-value-item",h.style.padding="0",h.style.margin="0";const b=document.createElement("input");b.type="checkbox",b.className="tbw-filter-checkbox";const g=document.createElement("span");g.textContent="Select All",h.appendChild(b),h.appendChild(g),f.appendChild(h);const m=new Map;r.forEach(e=>{const t=null==e?"__null__":String(e);m.set(t,!n.has(e))});const v=()=>{const e=[...m.values()],t=e.every(e=>e),r=e.every(e=>!e);b.checked=t,b.indeterminate=!t&&!r};b.addEventListener("change",()=>{const e=b.checked;for(const t of m.keys())m.set(t,e);v(),S()}),v(),e.appendChild(f);const w=document.createElement("div");w.className="tbw-filter-values";const y=document.createElement("div");y.className="tbw-filter-values-spacer",w.appendChild(y);const x=document.createElement("div");x.className="tbw-filter-values-content",w.appendChild(x);let C=[];const E=(e,t)=>{const r=d(e),n=null==e?"__null__":String(e),i=document.createElement("label");i.className="tbw-filter-value-item",i.style.position="absolute",i.style.top=`calc(var(--tbw-filter-item-height, 28px) * ${t})`,i.style.left="0",i.style.right="0",i.style.boxSizing="border-box";const l=document.createElement("input");l.type="checkbox",l.className="tbw-filter-checkbox",l.checked=m.get(n)??!0,l.dataset.value=n,l.addEventListener("change",()=>{m.set(n,l.checked),v()});const a=document.createElement("span");return a.textContent=r,i.appendChild(l),i.appendChild(a),i},S=()=>{const e=C.length,t=w.clientHeight,r=w.scrollTop;if(y.style.height=e*c+"px",l.shouldBypassVirtualization(e,50/3))return x.innerHTML="",x.style.transform="translateY(0px)",void C.forEach((e,t)=>{x.appendChild(E(e,t))});const n=l.computeVirtualWindow({totalRows:e,viewportHeight:t,scrollTop:r,rowHeight:c,overscan:3});x.style.transform=`translateY(${n.offsetY}px)`,x.innerHTML="";for(let i=n.start;i<n.end;i++)x.appendChild(E(C[i],i-n.start))},k=e=>{const t=i.caseSensitive??!1,n=t?e:e.toLowerCase();if(C=r.filter(r=>{const i=d(r),l=t?i:i.toLowerCase();return!e||l.includes(n)}),C.sort((e,t)=>{const r=null==e?"__null__":String(e),n=null==t?"__null__":String(t),i=m.get(r)??!0;return i!==(m.get(n)??!0)?i?-1:1:"number"==typeof e&&"number"==typeof t?e-t:d(e).localeCompare(d(t))}),0===C.length){y.style.height="0px",x.innerHTML="";const e=document.createElement("div");return e.className="tbw-filter-no-match",e.textContent="No matching values",void x.appendChild(e)}S()};let F;w.addEventListener("scroll",()=>{C.length>0&&S()},{passive:!0}),k(p.value),e.appendChild(w),p.addEventListener("input",()=>{clearTimeout(F),F=setTimeout(()=>{a.set(s,p.value),k(p.value)},i.debounceMs??150)});const N=document.createElement("div");N.className="tbw-filter-buttons";const A=document.createElement("button");A.className="tbw-filter-apply-btn",A.textContent="Apply",A.addEventListener("click",()=>{const e=[];for(const[t,n]of m)if(!n)if("__null__"===t)e.push(null);else{const n=r.find(e=>String(e)===t);e.push(void 0!==n?n:t)}t.applySetFilter(e)}),N.appendChild(A);const T=document.createElement("button");T.className="tbw-filter-clear-btn",T.textContent="Clear Filter",T.addEventListener("click",()=>{t.clearFilter()}),N.appendChild(T),e.appendChild(N)}function f(e,t){if("number"==typeof e)return e;if("string"==typeof e){const r=parseFloat(e);return isNaN(r)?t:r}return t}class h extends n.BaseGridPlugin{static manifest={events:[{type:"filter-change",description:"Emitted when filter criteria change. Broadcast to both DOM consumers and plugin bus."}],queries:[{type:"getContextMenuItems",description:"Contributes filter-related items to the header context menu"}]};name="filtering";styles='@layer tbw-plugins{tbw-grid .tbw-quick-filter-input{flex:1;max-width:300px;height:var(--tbw-input-height, 1.75rem);padding:var(--tbw-input-padding, 0 .5rem);border:1px solid var(--tbw-color-border);border-radius:var(--tbw-border-radius);background:var(--tbw-color-bg);color:var(--tbw-color-fg);font-size:var(--tbw-font-size-sm, .8125rem)}tbw-grid .tbw-quick-filter-input:focus{outline:none;border-color:var(--tbw-color-accent)}tbw-grid .header-cell.filtered:before{content:"";position:absolute;top:var(--tbw-spacing-xs, .25rem);right:var(--tbw-spacing-xs, .25rem);width:var(--tbw-indicator-size, .375rem);height:var(--tbw-indicator-size, .375rem);background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border-radius:50%}tbw-grid .tbw-filter-btn{display:var(--tbw-filter-btn-display, inline-flex);visibility:var(--tbw-filter-btn-visibility, visible);align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;padding:2px;margin-left:var(--tbw-spacing-xs, .25rem);opacity:.4;transition:opacity .15s,visibility 0s,display 0s allow-discrete;color:inherit;vertical-align:middle;transition-behavior:allow-discrete}tbw-grid .tbw-filter-btn:hover,tbw-grid .tbw-filter-btn.active{opacity:1;visibility:visible;display:inline-flex}tbw-grid .tbw-filter-btn.active{color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}tbw-grid .header-row .cell:hover .tbw-filter-btn,tbw-grid .header-row .cell.filtered .tbw-filter-btn{display:inline-flex;visibility:visible}}';get defaultConfig(){return{debounceMs:300,caseSensitive:!1,trimInput:!0,useWorker:!0}}isFilteringEnabled(){return!1!==this.grid.effectiveConfig?.filterable}isColumnFilterable(e){return!!this.isFilteringEnabled()&&!1!==e.filterable}getDataRows(){const e=this.sourceRows;if(e.length>0)return e;const t=this.rows;return 0===t.length?t:t.filter(e=>null!=e&&!0!==e.__loading)}getFilterValues(){const e=this.grid.effectiveConfig?.columns;if(!e)return;let t;for(const n of e)if(n.field)if(n.filterValue)t||(t=new Map),t.set(n.field,n.filterValue);else if(n.valueAccessor){t||(t=new Map);const e=n;t.set(n.field,(t,n)=>r.resolveCellValue(n,e))}return t}filters=new Map;cachedResult=null;cacheKey=null;cachedInputSpot=null;openPanelField=null;panelElement=null;panelAnchorElement=null;panelButtonElement=null;searchText=new Map;excludedValues=new Map;panelAbortController=null;globalStylesInjected=!1;computeSelected(){const e={},t=[];for(const[n,i]of this.filters)if("set"===i.type)if("in"===i.operator&&Array.isArray(i.value))e[n]=i.value;else if("notIn"===i.operator){const e=this.grid.effectiveConfig?.columns?.find(e=>e.field===n),i=e?.filterValue??(e?.valueAccessor?(t,n)=>r.resolveCellValue(n,e):void 0);t.push({field:n,filterValue:i})}if(t.length>0){const r=function(e,t){const r=new Map;for(const{field:i,filterValue:l}of t)r.set(i,{values:new Set,hasBlank:!1,hasExtractor:!!l});for(const i of e)for(const{field:e,filterValue:n}of t){const t=r.get(e),l=i[e];if(n){const e=n(l,i);if(Array.isArray(e)){0===e.length&&(t.hasBlank=!0);for(const r of e)null!=r&&t.values.add(r)}else null!=e?t.values.add(e):t.hasBlank=!0}else null!=l&&""!==l?t.values.add(l):t.hasBlank=!0}const n=new Map;for(const[i,{values:l,hasBlank:s}]of r)s&&l.add(a),n.set(i,[...l].sort((e,t)=>"number"==typeof e&&"number"==typeof t?e-t:String(e).localeCompare(String(t))));return n}(this.getDataRows(),t);for(const{field:n}of t){const t=this.excludedValues.get(n),i=r.get(n)??[];e[n]=t?i.filter(e=>!t.has(e)):i}}return e}syncExcludedValues(e,t){if(t)if("set"===t.type&&"notIn"===t.operator&&Array.isArray(t.value))this.excludedValues.set(e,new Set(t.value));else if("set"===t.type&&"in"===t.operator&&Array.isArray(t.value)){const r=this.getDataRows();if(!r||0===r.length)return void this.excludedValues.delete(e);const n=t.value,i=new Set(n.map(e=>null==e?a:e)),l=this.getUniqueValues(e),s=new Set(l.filter(e=>!i.has(e)));this.excludedValues.set(e,s)}else"set"===t.type&&this.excludedValues.delete(e);else this.excludedValues.delete(e)}attach(e){super.attach(e),this.injectGlobalStyles()}detach(){this.filters.clear(),this.cachedResult=null,this.cacheKey=null,this.cachedInputSpot=null,this.openPanelField=null,this.panelElement&&(this.panelElement.remove(),this.panelElement=null),this.searchText.clear(),this.excludedValues.clear(),this.panelAbortController?.abort(),this.panelAbortController=null}handleQuery(e){if("filter:get-model"===e.type){if(!this.filters.size)return;return Object.fromEntries(this.filters)}if("getContextMenuItems"===e.type){const t=e.context;if(!t.isHeader)return;const r=t.column;if(!r?.field)return;if(!this.isFilteringEnabled())return;if(!this.isColumnFilterable(r))return;const n=[],i=this.isFieldFiltered(r.field),l=this.filters.size>0;return i&&n.push({id:"filtering/clear-column-filter",label:"Clear Filter",icon:"✕",order:20,action:()=>this.clearFieldFilter(r.field)}),l&&n.push({id:"filtering/clear-all-filters",label:"Clear All Filters",icon:"✕",order:21,disabled:!l,action:()=>this.clearAllFilters()}),n.length>0?n:void 0}}processRows(e){if(!this.filters.size)return e;const t=[...this.filters.values()];if(this.config.filterHandler)return this.cachedResult?this.cachedResult:e;const r=(n=t,JSON.stringify(n.map(e=>({field:e.field,operator:e.operator,value:e.value,valueTo:e.valueTo}))));var n;const i={len:e.length,first:e[0],mid:e[Math.floor(e.length/2)],last:e[e.length-1]},l=null!=this.cachedInputSpot&&i.len===this.cachedInputSpot.len&&i.first===this.cachedInputSpot.first&&i.mid===this.cachedInputSpot.mid&&i.last===this.cachedInputSpot.last;if(this.cacheKey===r&&this.cachedResult&&l)return this.cachedResult;if(!l)for(const[s,o]of this.filters)"set"===o.type&&"in"===o.operator&&this.syncExcludedValues(s,o);const a=o(e,t,this.config.caseSensitive,this.getFilterValues());return this.cachedResult=a,this.cacheKey=r,this.cachedInputSpot=i,a}afterRender(){const e=this.gridElement;if(!e)return;e.querySelectorAll('[part~="header-cell"]').forEach(e=>{const t=e.getAttribute("data-col");if(null===t)return;const r=this.visibleColumns[parseInt(t,10)];if(!r||!this.isColumnFilterable(r))return;if(i.isUtilityColumn(r))return;const n=r.field;if(!n)return;const l=this.filters.has(n);let a=e.querySelector(".tbw-filter-btn");if(a){const t=a.classList.contains("active");return a.classList.toggle("active",l),e.classList.toggle("filtered",l),l?e.setAttribute("aria-description","Filtered"):e.removeAttribute("aria-description"),void(t!==l&&this.setIcon(a,l?"filterActive":"filter"))}a=document.createElement("button"),a.className="tbw-filter-btn",a.setAttribute("aria-label",`Filter ${r.header??n}`),this.setIcon(a,l?"filterActive":"filter"),l&&(a.classList.add("active"),e.classList.add("filtered"),e.setAttribute("aria-description","Filtered")),a.addEventListener("click",e=>{e.stopPropagation(),this.toggleFilterPanel(n,r,a)});const s=e.querySelector(".resize-handle");s?e.insertBefore(a,s):e.appendChild(a)})}setFilter(e,r,n){if(null===r)this.filters.delete(e),this.syncExcludedValues(e,null);else{const t={...r,field:e};this.filters.set(e,t),this.syncExcludedValues(e,t)}if(this.cachedResult=null,this.cacheKey=null,this.cachedInputSpot=null,n?.silent)this.emitPluginEvent("filter-change",{filters:[...this.filters.values()]});else{this.broadcast("filter-change",{filters:[...this.filters.values()],filteredRowCount:0,selected:this.computeSelected()}),this.config.trackColumnState&&this.grid.requestStateChange?.();const n=this.grid.effectiveConfig?.columns?.find(t=>t.field===e)?.header??e;t.announce(this.gridElement,null===r?t.getA11yMessage(this.gridElement,"filterCleared",n):t.getA11yMessage(this.gridElement,"filterApplied",n))}this.requestRender()}getFilter(e){return this.filters.get(e)}getFilters(){return[...this.filters.values()]}getFilterModel(){return this.getFilters()}setFilterModel(e,t){this.filters.clear(),this.excludedValues.clear();for(const r of e)this.filters.set(r.field,r),this.syncExcludedValues(r.field,r);this.cachedResult=null,this.cacheKey=null,this.cachedInputSpot=null,t?.silent?this.emitPluginEvent("filter-change",{filters:[...this.filters.values()]}):(this.broadcast("filter-change",{filters:[...this.filters.values()],filteredRowCount:0,selected:this.computeSelected()}),this.config.trackColumnState&&this.grid.requestStateChange?.()),this.requestRender()}clearAllFilters(e){this.filters.clear(),this.excludedValues.clear(),this.searchText.clear(),this.applyFiltersInternal(e?.silent),e?.silent||t.announce(this.gridElement,t.getA11yMessage(this.gridElement,"allFiltersCleared"))}clearFieldFilter(e,r){if(this.filters.delete(e),this.excludedValues.delete(e),this.searchText.delete(e),this.applyFiltersInternal(r?.silent),!r?.silent){const r=this.grid.effectiveConfig?.columns?.find(t=>t.field===e)?.header??e;t.announce(this.gridElement,t.getA11yMessage(this.gridElement,"filterCleared",r))}}isFieldFiltered(e){return this.filters.has(e)}getFilteredRowCount(){return this.cachedResult?.length??this.rows.length}getActiveFilters(){return this.getFilters()}getUniqueValues(e){const t=this.grid.effectiveConfig?.columns?.find(t=>t.field===e),r=t?.filterValue;return c(this.getDataRows(),e,r)}getStaleFilters(){const e=[];for(const[t,r]of this.filters){if("set"!==r.type)continue;const n=this.getUniqueValues(t);if("notIn"===r.operator&&Array.isArray(r.value)){const t=new Set(r.value);0===n.filter(e=>!t.has(e)).length&&e.push(r)}else if("in"===r.operator&&Array.isArray(r.value)){const t=new Set(r.value);0===n.filter(e=>t.has(e)).length&&e.push(r)}}return e}getBlankMode(e){const t=this.filters.get(e);return"blank"===t?.operator?"blanksOnly":"notBlank"===t?.operator?"nonBlanksOnly":"all"}toggleBlankFilter(e,t){if("all"===t){const t=this.filters.get(e);if(t?.valueTo&&"object"==typeof t.valueTo){const r=t.valueTo;this.setFilter(e,r)}else this.setFilter(e,null);return}const r=this.filters.get(e),n=r&&"blank"!==r.operator&&"notBlank"!==r.operator?{type:r.type,operator:r.operator,value:r.value,valueTo:r.valueTo}:r?.valueTo;this.setFilter(e,{type:r?.type??"text",operator:"blanksOnly"===t?"blank":"notBlank",value:"",valueTo:n})}copyGridThemeContext(e){const t=this.gridElement;if(!t)return;for(const n of t.classList)n.startsWith("tbw-")||"selecting"===n||e.classList.add(n);const r=t.dataset.theme;r&&(e.dataset.theme=r)}injectGlobalStyles(){if(this.globalStylesInjected)return;if(document.getElementById("tbw-filter-panel-styles"))return void(this.globalStylesInjected=!0);const e=document.createElement("style");e.id="tbw-filter-panel-styles",e.textContent="@layer tbw-plugins{.tbw-filter-panel{position:fixed;background:var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));color:var(--tbw-filter-panel-fg, var(--tbw-color-fg, light-dark(#222222, #eeeeee)));border:1px solid var(--tbw-filter-panel-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-panel-radius, var(--tbw-border-radius, .25rem));box-shadow:0 4px 16px var(--tbw-filter-panel-shadow, var(--tbw-color-shadow, light-dark(rgba(0, 0, 0, .1), rgba(0, 0, 0, .3))));padding:var(--tbw-panel-padding, var(--tbw-spacing-lg, .75rem));z-index:10000;min-width:200px;max-width:280px;max-height:350px;display:flex;flex-direction:column;font-family:var(--tbw-font-family, system-ui, sans-serif);font-size:var(--tbw-font-size, .8125rem);transform-origin:top center}.tbw-filter-panel.tbw-filter-panel-above{transform-origin:bottom center}.tbw-filter-panel.tbw-filter-panel-animated{animation:tbw-filter-panel-enter var(--tbw-animation-duration, .15s) var(--tbw-animation-easing, ease-out)}.tbw-filter-panel.tbw-filter-panel-above.tbw-filter-panel-animated{animation:tbw-filter-panel-enter-above var(--tbw-animation-duration, .15s) var(--tbw-animation-easing, ease-out)}@keyframes tbw-filter-panel-enter{0%{opacity:0;transform:scaleY(.3) translateY(-10px)}to{opacity:1;transform:scaleY(1) translateY(0)}}@keyframes tbw-filter-panel-enter-above{0%{opacity:0;transform:scaleY(.3) translateY(10px)}to{opacity:1;transform:scaleY(1) translateY(0)}}@supports (anchor-name: --test){.tbw-filter-panel{position-anchor:--tbw-filter-anchor;top:anchor(bottom);right:anchor(right);margin-top:4px;position-try-fallbacks:flip-inline,flip-block,flip-block flip-inline}}.tbw-filter-search{margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));min-height:var(--tbw-filter-item-height, 28px)}.tbw-filter-search-input{height:var(--tbw-filter-item-height, 28px);width:100%;padding:var(--tbw-filter-search-padding, var(--tbw-spacing-sm, .375rem) var(--tbw-spacing-md, .5rem));background:var(--tbw-filter-input-bg, var(--tbw-color-bg, transparent));color:inherit;border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-input-radius, var(--tbw-border-radius, .25rem));font-size:inherit;box-sizing:border-box}.tbw-filter-search-input:focus{outline:none;border-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));box-shadow:0 0 0 2px rgba(from var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6)) r g b / 15%)}.tbw-filter-actions{display:flex;padding:var(--tbw-button-padding-sm, .25rem .125rem);margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));border-bottom:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));min-height:var(--tbw-filter-item-height, 28px)}.tbw-filter-actions .tbw-filter-value-item{flex:1}.tbw-filter-values{flex:1;overflow-y:auto;margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));max-height:180px;position:relative}.tbw-filter-values-spacer{width:1px}.tbw-filter-values-content{position:absolute;top:0;left:0;right:0}.tbw-filter-value-item{display:flex;align-items:center;gap:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));padding:var(--tbw-button-padding-sm, .25rem .125rem);cursor:pointer;border-radius:3px;height:var(--tbw-filter-item-height, 28px)}.tbw-filter-value-item:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}.tbw-filter-checkbox{margin:0;cursor:pointer;accent-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}.tbw-filter-no-match{color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));padding:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem)) 0;text-align:center;font-style:italic}.tbw-filter-buttons{display:flex;gap:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));padding-top:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));border-top:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-apply-btn{flex:1;padding:var(--tbw-filter-btn-padding, var(--tbw-button-padding, .375rem .75rem));background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));color:var(--tbw-filter-accent-fg, var(--tbw-color-accent-fg, light-dark(#ffffff, #000000)));border:none;border-radius:var(--tbw-border-radius, .25rem);cursor:pointer;font-size:var(--tbw-font-size-sm, .8125rem);font-weight:var(--tbw-filter-btn-font-weight, 500);min-height:var(--tbw-filter-btn-min-height, auto)}.tbw-filter-apply-btn:hover{filter:brightness(.9)}.tbw-filter-clear-btn{flex:1;padding:var(--tbw-filter-btn-padding, var(--tbw-button-padding, .375rem .75rem));background:transparent;color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-border-radius, .25rem);cursor:pointer;font-size:var(--tbw-font-size-sm, .8125rem);font-weight:var(--tbw-filter-btn-font-weight, 500);min-height:var(--tbw-filter-btn-min-height, auto)}.tbw-filter-clear-btn:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}.tbw-filter-range-inputs,.tbw-filter-date-range{display:flex;align-items:flex-end;gap:var(--tbw-spacing-sm, .375rem);margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem))}.tbw-filter-range-group,.tbw-filter-date-group{display:flex;flex-direction:column;gap:var(--tbw-spacing-xs, .25rem);flex:1}.tbw-filter-range-label{font-size:var(--tbw-font-size-xs, .75rem);color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)))}.tbw-filter-range-input,.tbw-filter-date-input{width:100%;height:var(--tbw-filter-item-height, 28px);padding:var(--tbw-spacing-xs, .25rem) var(--tbw-spacing-sm, .375rem);background:var(--tbw-filter-input-bg, var(--tbw-color-bg, transparent));color:inherit;border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-input-radius, var(--tbw-border-radius, .25rem));font-size:inherit;box-sizing:border-box}.tbw-filter-range-input:focus,.tbw-filter-date-input:focus{outline:none;border-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));box-shadow:0 0 0 2px rgba(from var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6)) r g b / 15%)}.tbw-filter-range-separator{color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));padding-bottom:var(--tbw-spacing-xs, .25rem)}.tbw-filter-blank-option{display:flex;align-items:center;gap:var(--tbw-spacing-sm, .375rem);padding:var(--tbw-spacing-xs, .25rem) 0;margin-bottom:var(--tbw-spacing-xs, .25rem);font-size:var(--tbw-font-size-sm, .8125rem);cursor:pointer;-webkit-user-select:none;user-select:none}.tbw-filter-blank-checkbox{accent-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));margin:0;cursor:pointer}.tbw-filter-date-range.tbw-filter-disabled,.tbw-filter-range-inputs.tbw-filter-disabled,.tbw-filter-range-slider.tbw-filter-disabled{opacity:.4;pointer-events:none}.tbw-filter-range-slider{position:relative;height:24px;margin:var(--tbw-spacing-md, .5rem) 0 var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem))}.tbw-filter-range-track{position:absolute;top:50%;left:0;right:0;height:4px;background:var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:2px;transform:translateY(-50%)}.tbw-filter-range-fill{position:absolute;top:50%;height:4px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border-radius:2px;transform:translateY(-50%)}.tbw-filter-range-thumb{position:absolute;top:0;width:100%;height:100%;background:none;pointer-events:none;-webkit-appearance:none;appearance:none}.tbw-filter-range-thumb::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border:2px solid var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));border-radius:50%;cursor:pointer;pointer-events:all;box-shadow:0 1px 3px #0003}.tbw-filter-range-thumb::-moz-range-thumb{width:16px;height:16px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border:2px solid var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));border-radius:50%;cursor:pointer;pointer-events:all;box-shadow:0 1px 3px #0003}.tbw-filter-range-thumb::-webkit-slider-thumb:hover{transform:scale(1.1)}.tbw-filter-range-thumb::-moz-range-thumb:hover{transform:scale(1.1)}}",document.head.appendChild(e),this.globalStylesInjected=!0}toggleFilterPanel(e,t,n){if(this.openPanelField===e)return void this.closeFilterPanel();this.closeFilterPanel();const i=document.createElement("div");if(i.className="tbw-filter-panel",this.copyGridThemeContext(i),this.isAnimationEnabled&&i.classList.add("tbw-filter-panel-animated"),this.panelElement=i,this.openPanelField=e,n.classList.add("active"),this.panelButtonElement=n,this.config.valuesHandler)return i.innerHTML='<div class="tbw-filter-loading">Loading...</div>',document.body.appendChild(i),this.positionPanel(i,n),this.setupPanelCloseHandler(i,n),void this.config.valuesHandler(e,t).then(r=>{this.openPanelField===e&&this.panelElement&&(i.innerHTML="",this.renderPanelContent(e,t,i,r))});const l=t.filterValue??(t.valueAccessor?(e,n)=>r.resolveCellValue(n,t):void 0),a=c(this.getDataRows(),e,l);document.body.appendChild(i),this.positionPanel(i,n),this.renderPanelContent(e,t,i,a),this.setupPanelCloseHandler(i,n)}renderPanelContent(e,t,r,n){const i=this.filters.get(e);if("in"===i?.operator&&"set"===i.type&&Array.isArray(i.value)&&!this.excludedValues.has(e)){const t=i.value,r=new Set(t.map(e=>null==e?a:e)),l=new Set(n.filter(e=>!r.has(e)));this.excludedValues.set(e,l)}let l=this.excludedValues.get(e);l||(l=new Set,this.excludedValues.set(e,l));const s=this.searchText.get(e)??"",o={field:e,column:t,uniqueValues:n,excludedValues:l,searchText:s,currentFilter:this.filters.get(e),applySetFilter:(t,r)=>{this.applySetFilter(e,t,r),this.closeFilterPanel()},applyTextFilter:(t,r,n)=>{this.applyTextFilter(e,t,r,n),this.closeFilterPanel()},clearFilter:()=>{this.clearFieldFilter(e),this.closeFilterPanel()},closePanel:()=>this.closeFilterPanel()};let c=!1;if(this.config.filterPanelRenderer&&(this.config.filterPanelRenderer(r,o),c=r.children.length>0),!c&&t.type){const e=this.grid.effectiveConfig.typeDefaults?.[t.type];e?.filterPanelRenderer&&(e.filterPanelRenderer(r,o),c=r.children.length>0)}if(!c){const e=t.filterType??t.type;"number"===e?function(e,t,r,n){const{field:i,column:l}=t,a=l.filterParams,s=l.editorParams,o=r.filter(e=>"number"==typeof e&&!isNaN(e)),c=o.length>0?Math.min(...o):0,d=o.length>0?Math.max(...o):100,u=f(a?.min??s?.min,c),p=f(a?.max??s?.max,d),h=a?.step??s?.step??1,b=n.get(i);let g=u,m=p;const v="blank"===b?.operator;"between"===b?.operator?(g=f(b.value,u),m=f(b.valueTo,p)):"greaterThanOrEqual"===b?.operator?g=f(b.value,u):"lessThanOrEqual"===b?.operator&&(m=f(b.value,p));const w=document.createElement("div");w.className="tbw-filter-range-inputs";const y=document.createElement("div");y.className="tbw-filter-range-group";const x=document.createElement("label");x.textContent="Min",x.className="tbw-filter-range-label";const C=document.createElement("input");C.type="number",C.className="tbw-filter-range-input",C.min=String(u),C.max=String(p),C.step=String(h),C.value=String(g),y.appendChild(x),y.appendChild(C),w.appendChild(y);const E=document.createElement("span");E.className="tbw-filter-range-separator",E.textContent="–",w.appendChild(E);const S=document.createElement("div");S.className="tbw-filter-range-group";const k=document.createElement("label");k.textContent="Max",k.className="tbw-filter-range-label";const F=document.createElement("input");F.type="number",F.className="tbw-filter-range-input",F.min=String(u),F.max=String(p),F.step=String(h),F.value=String(m),S.appendChild(k),S.appendChild(F),w.appendChild(S),e.appendChild(w);const N=document.createElement("div");N.className="tbw-filter-range-slider";const A=document.createElement("div");A.className="tbw-filter-range-track";const T=document.createElement("div");T.className="tbw-filter-range-fill";const L=document.createElement("input");L.type="range",L.className="tbw-filter-range-thumb tbw-filter-range-thumb-min",L.min=String(u),L.max=String(p),L.step=String(h),L.value=String(g);const P=document.createElement("input");P.type="range",P.className="tbw-filter-range-thumb tbw-filter-range-thumb-max",P.min=String(u),P.max=String(p),P.step=String(h),P.value=String(m),N.appendChild(A),N.appendChild(T),N.appendChild(L),N.appendChild(P),e.appendChild(N);const V=document.createElement("label");V.className="tbw-filter-blank-option";const R=document.createElement("input");R.type="checkbox",R.className="tbw-filter-blank-checkbox",R.checked=v;const M=document.createTextNode("Blank");V.appendChild(R),V.appendChild(M);const I=e=>{C.disabled=e,F.disabled=e,L.disabled=e,P.disabled=e,w.classList.toggle("tbw-filter-disabled",e),N.classList.toggle("tbw-filter-disabled",e)};I(v),R.addEventListener("change",()=>{I(R.checked)}),e.appendChild(V);const q=()=>{const e=parseFloat(L.value),t=parseFloat(P.value),r=p-u,n=(e-u)/r*100,i=(t-u)/r*100;T.style.left=`${n}%`,T.style.width=i-n+"%"};L.addEventListener("input",()=>{const e=Math.min(parseFloat(L.value),parseFloat(P.value));L.value=String(e),C.value=String(e),q()}),P.addEventListener("input",()=>{const e=Math.max(parseFloat(P.value),parseFloat(L.value));P.value=String(e),F.value=String(e),q()}),C.addEventListener("input",()=>{const e=parseFloat(C.value);let t=Number.isFinite(e)?e:u;t=Math.max(u,Math.min(t,parseFloat(F.value))),L.value=String(t),q()}),F.addEventListener("input",()=>{const e=parseFloat(F.value);let t=Number.isFinite(e)?e:p;t=Math.min(p,Math.max(t,parseFloat(C.value))),P.value=String(t),q()}),q();const B=document.createElement("div");B.className="tbw-filter-buttons";const z=document.createElement("button");z.className="tbw-filter-apply-btn",z.textContent="Apply",z.addEventListener("click",()=>{if(R.checked)return void t.applyTextFilter("blank","");const e=parseFloat(C.value),r=parseFloat(F.value),n=Number.isFinite(e)?e:u,i=Number.isFinite(r)?r:p;n!==u||i!==p?t.applyTextFilter("between",n,i):t.clearFilter()}),B.appendChild(z);const _=document.createElement("button");_.className="tbw-filter-clear-btn",_.textContent="Clear Filter",_.addEventListener("click",()=>{t.clearFilter()}),B.appendChild(_),e.appendChild(B)}(r,o,n,this.filters):"date"===e?function(e,t,r,n){const{field:i,column:l}=t,a=l.filterParams,s=l.editorParams,o=r.filter(e=>e instanceof Date||"string"==typeof e&&!isNaN(Date.parse(e))).map(e=>e instanceof Date?e:new Date(e)).filter(e=>!isNaN(e.getTime())),c=o.length>0?new Date(Math.min(...o.map(e=>e.getTime()))):null,p=o.length>0?new Date(Math.max(...o.map(e=>e.getTime()))):null,f=u(a?.min)||u(s?.min)||d(c),h=u(a?.max)||u(s?.max)||d(p),b=n.get(i);let g="",m="";const v="blank"===b?.operator;"between"===b?.operator?(g=u(b.value)||"",m=u(b.valueTo)||""):"greaterThanOrEqual"===b?.operator?g=u(b.value)||"":"lessThanOrEqual"===b?.operator&&(m=u(b.value)||"");const w=document.createElement("div");w.className="tbw-filter-date-range";const y=document.createElement("div");y.className="tbw-filter-date-group";const x=document.createElement("label");x.textContent="From",x.className="tbw-filter-range-label";const C=document.createElement("input");C.type="date",C.className="tbw-filter-date-input",f&&(C.min=f),h&&(C.max=h),C.value=g,y.appendChild(x),y.appendChild(C),w.appendChild(y);const E=document.createElement("span");E.className="tbw-filter-range-separator",E.textContent="–",w.appendChild(E);const S=document.createElement("div");S.className="tbw-filter-date-group";const k=document.createElement("label");k.textContent="To",k.className="tbw-filter-range-label";const F=document.createElement("input");F.type="date",F.className="tbw-filter-date-input",f&&(F.min=f),h&&(F.max=h),F.value=m,S.appendChild(k),S.appendChild(F),w.appendChild(S),e.appendChild(w);const N=document.createElement("label");N.className="tbw-filter-blank-option";const A=document.createElement("input");A.type="checkbox",A.className="tbw-filter-blank-checkbox",A.checked=v;const T=document.createTextNode("Show only blank");N.appendChild(A),N.appendChild(T);const L=e=>{C.disabled=e,F.disabled=e,w.classList.toggle("tbw-filter-disabled",e)};L(v),A.addEventListener("change",()=>{L(A.checked)}),e.appendChild(N);const P=document.createElement("div");P.className="tbw-filter-buttons";const V=document.createElement("button");V.className="tbw-filter-apply-btn",V.textContent="Apply",V.addEventListener("click",()=>{if(A.checked)return void t.applyTextFilter("blank","");const e=C.value,r=F.value;e&&r?t.applyTextFilter("between",e,r):e?t.applyTextFilter("greaterThanOrEqual",e):r?t.applyTextFilter("lessThanOrEqual",r):t.clearFilter()}),P.appendChild(V);const R=document.createElement("button");R.className="tbw-filter-clear-btn",R.textContent="Clear Filter",R.addEventListener("click",()=>{t.clearFilter()}),P.appendChild(R),e.appendChild(P)}(r,o,n,this.filters):p(r,o,n,l,{caseSensitive:this.config.caseSensitive,debounceMs:this.config.debounceMs},this.searchText)}}setupPanelCloseHandler(e,t){this.panelAbortController=new AbortController;const{signal:r}=this.panelAbortController;setTimeout(()=>{r.aborted||document.addEventListener("click",r=>{e.contains(r.target)||r.target===t||this.closeFilterPanel()},{signal:r})},0)}closeFilterPanel(){const e=this.panelElement;if(e&&(e.remove(),this.panelElement=null),this.panelAnchorElement&&(this.panelAnchorElement.style.anchorName="",this.panelAnchorElement=null),this.panelButtonElement){const e=this.openPanelField;e&&this.filters.has(e)||this.panelButtonElement.classList.remove("active"),this.panelButtonElement=null}this.openPanelField=null,this.panelAbortController?.abort(),this.panelAbortController=null}static supportsAnchorPositioning=null;static checkAnchorPositioningSupport(){return null===h.supportsAnchorPositioning&&(h.supportsAnchorPositioning=CSS.supports("anchor-name","--test")),h.supportsAnchorPositioning}positionPanel(e,t){const r=t.closest(".header-row")??t;if(r.style.anchorName="--tbw-filter-anchor",this.panelAnchorElement=r,h.checkAnchorPositioningSupport()){r.style.anchorName="",t.style.anchorName="--tbw-filter-anchor",this.panelAnchorElement=t;const n=r.getBoundingClientRect().bottom-t.getBoundingClientRect().bottom;return e.style.marginTop=`${n+4}px`,void requestAnimationFrame(()=>{const r=e.getBoundingClientRect(),n=t.getBoundingClientRect();r.top<n.top&&e.classList.add("tbw-filter-panel-above")})}const n=r.getBoundingClientRect(),i=t.getBoundingClientRect();e.style.position="fixed",e.style.top=`${n.bottom+4}px`,e.style.left=`${i.right}px`,requestAnimationFrame(()=>{const t=e.getBoundingClientRect();e.style.left=i.right-t.width+"px";i.right-t.width<8&&(e.style.left=`${i.left}px`),t.bottom>window.innerHeight-8&&(e.style.top=n.top-t.height-4+"px",e.classList.add("tbw-filter-panel-above"))})}applySetFilter(e,t,r){if(this.excludedValues.set(e,new Set(t)),0===t.length)this.filters.delete(e);else{const n=this.filters.get(e);if("in"===n?.operator){const n=this.getUniqueValues(e),i=new Set(t),l=n.filter(e=>!i.has(e));this.filters.set(e,{field:e,type:"set",operator:"in",value:l,...void 0!==r&&{valueTo:r}})}else this.filters.set(e,{field:e,type:"set",operator:"notIn",value:t,...void 0!==r&&{valueTo:r}})}this.applyFiltersInternal()}applyTextFilter(e,t,r,n){const i=this.grid.effectiveConfig?.columns?.find(t=>t.field===e),l=i?.filterType??i?.type??"text";this.filters.set(e,{field:e,type:l,operator:t,value:r,valueTo:n}),this.applyFiltersInternal()}applyFiltersInternal(e){this.cachedResult=null,this.cacheKey=null,this.cachedInputSpot=null;const t=[...this.filters.values()];if(this.config.filterHandler){this.gridElement.setAttribute("aria-busy","true");const r=this.config.filterHandler(t,this.sourceRows),n=r=>{this.gridElement.removeAttribute("aria-busy"),this.cachedResult=r,this.grid.rows=r,e?this.emitPluginEvent("filter-change",{filters:t}):(this.broadcast("filter-change",{filters:t,filteredRowCount:r.length,selected:this.computeSelected()}),this.config.trackColumnState&&this.grid.requestStateChange?.()),this.requestRender()};return void(r&&"function"==typeof r.then?r.then(n):n(r))}e?this.emitPluginEvent("filter-change",{filters:t}):(this.broadcast("filter-change",{filters:t,filteredRowCount:0,selected:this.computeSelected()}),this.config.trackColumnState&&this.grid.requestStateChange?.()),this.requestRender()}getColumnState(e){if(!this.config.trackColumnState)return;const t=this.filters.get(e);return t?{filter:{type:t.type,operator:t.operator,value:t.value,valueTo:t.valueTo}}:void 0}applyColumnState(e,t){if(!this.config.trackColumnState)return;if(!t.filter)return void this.filters.delete(e);const r={field:e,type:t.filter.type,operator:t.filter.operator,value:t.filter.value,valueTo:t.filter.valueTo};this.filters.set(e,r),this.cachedResult=null,this.cacheKey=null,this.cachedInputSpot=null}}e.BLANK_FILTER_VALUE=a,e.FilteringPlugin=h,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
2
2
  //# sourceMappingURL=filtering.umd.js.map