diff --git a/.env b/.env index d8dbf36b8aa..f20131068a4 100644 --- a/.env +++ b/.env @@ -1,6 +1,6 @@ # Production Build -BUILD_GRID_VERSION=35.3.0-beta.20260609.1239 -BUILD_CHARTS_VERSION=13.3.0-beta.20260609 +BUILD_GRID_VERSION=35.3.0-beta.20260610.1146 +BUILD_CHARTS_VERSION=13.3.0-beta.20260610 ENV=local NX_BATCH_MODE=true NX_ADD_PLUGINS=false diff --git a/.vscode/settings.json b/.vscode/settings.json index a0b1d090bb9..4f0e0a8e8d2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -129,7 +129,7 @@ "alasql", "flatpickr", "fontawesome", - "xlsx-style", + "xlsx", "materialdesignicons", "seedrandom" ] diff --git a/community-modules/locale/package.json b/community-modules/locale/package.json index 0ee3110f396..c76c08e297d 100644 --- a/community-modules/locale/package.json +++ b/community-modules/locale/package.json @@ -1,6 +1,6 @@ { "name": "@ag-grid-community/locale", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "Localisation Module for AG Grid, providing translations in 31 languages.", "main": "./dist/package/main.cjs.js", "types": "./dist/types/src/main.d.ts", diff --git a/community-modules/locale/src/en-US.ts b/community-modules/locale/src/en-US.ts index 13ad46fdd17..b0fa5183983 100644 --- a/community-modules/locale/src/en-US.ts +++ b/community-modules/locale/src/en-US.ts @@ -281,6 +281,10 @@ export const AG_GRID_LOCALE_EN = { noRowsToShow: 'No Rows To Show', noMatchingRows: 'No Matching Rows', exportingOoo: 'Exporting...', + fileInputOverlay: 'Drag & Drop file to import data', + fileInputOverlayBrowse: 'Browse files', + fileInputProcessing: 'Processing ${variable}', + fileInputProcessingFailed: 'Error processing ${variable}', enabled: 'Enabled', // Menu diff --git a/community-modules/styles/_icon-font-codes.scss b/community-modules/styles/_icon-font-codes.scss index f0f2ac9686c..5de922da004 100644 --- a/community-modules/styles/_icon-font-codes.scss +++ b/community-modules/styles/_icon-font-codes.scss @@ -72,4 +72,5 @@ $icon-font-codes: ( filter-add: string.unquote("\"\\") + string.unquote("f144\""), edit: string.unquote("\"\\") + string.unquote("f145\""), search: string.unquote("\"\\") + string.unquote("f146\""), + document: string.unquote("\"\\") + string.unquote("f147\""), ) diff --git a/community-modules/styles/icon-fonts/build.js b/community-modules/styles/icon-fonts/build.js index 1d3d4fc2ad7..2b72e71954b 100644 --- a/community-modules/styles/icon-fonts/build.js +++ b/community-modules/styles/icon-fonts/build.js @@ -81,6 +81,7 @@ const nameToCodepoint = { 'filter-add': 0xf144, edit: 0xf145, search: 0xf146, + document: 0xf147, }; function generateFontFile(fontName) { diff --git a/community-modules/styles/icon-fonts/fonts/agGridAlpine/document.svg b/community-modules/styles/icon-fonts/fonts/agGridAlpine/document.svg new file mode 100644 index 00000000000..8db30d84c2f --- /dev/null +++ b/community-modules/styles/icon-fonts/fonts/agGridAlpine/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/community-modules/styles/icon-fonts/fonts/agGridBalham/document.svg b/community-modules/styles/icon-fonts/fonts/agGridBalham/document.svg new file mode 100644 index 00000000000..b496e2ef7a5 --- /dev/null +++ b/community-modules/styles/icon-fonts/fonts/agGridBalham/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/community-modules/styles/icon-fonts/fonts/agGridClassic/document.svg b/community-modules/styles/icon-fonts/fonts/agGridClassic/document.svg new file mode 100644 index 00000000000..8db30d84c2f --- /dev/null +++ b/community-modules/styles/icon-fonts/fonts/agGridClassic/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/community-modules/styles/icon-fonts/fonts/agGridMaterial/document.svg b/community-modules/styles/icon-fonts/fonts/agGridMaterial/document.svg new file mode 100644 index 00000000000..6552f7fd567 --- /dev/null +++ b/community-modules/styles/icon-fonts/fonts/agGridMaterial/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/community-modules/styles/icon-fonts/fonts/agGridQuartz/document.svg b/community-modules/styles/icon-fonts/fonts/agGridQuartz/document.svg new file mode 100644 index 00000000000..0b8080293c3 --- /dev/null +++ b/community-modules/styles/icon-fonts/fonts/agGridQuartz/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/community-modules/styles/package.json b/community-modules/styles/package.json index 573065f69a8..f1cb677fdb3 100644 --- a/community-modules/styles/package.json +++ b/community-modules/styles/package.json @@ -1,6 +1,6 @@ { "name": "@ag-grid-community/styles", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "AG Grid Styles and Themes", "main": "_index.scss", "files": [ diff --git a/community-modules/styles/src/internal/ag/generated/_agGridAlpine.scss b/community-modules/styles/src/internal/ag/generated/_agGridAlpine.scss index ef62d139294..49cbb8aa275 100644 --- a/community-modules/styles/src/internal/ag/generated/_agGridAlpine.scss +++ b/community-modules/styles/src/internal/ag/generated/_agGridAlpine.scss @@ -1,3 +1,3 @@ // THIS FILE IS GENERATED, DO NOT EDIT IT! -$data: "data:font/woff2;charset=utf-8;base64,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"; +$data: "data:font/woff2;charset=utf-8;base64,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"; diff --git a/community-modules/styles/src/internal/ag/generated/_agGridBalham.scss b/community-modules/styles/src/internal/ag/generated/_agGridBalham.scss index 77b38240db8..7fdae2d9db9 100644 --- a/community-modules/styles/src/internal/ag/generated/_agGridBalham.scss +++ b/community-modules/styles/src/internal/ag/generated/_agGridBalham.scss @@ -1,3 +1,3 @@ // THIS FILE IS GENERATED, DO NOT EDIT IT! -$data: "data:font/woff2;charset=utf-8;base64,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"; +$data: "data:font/woff2;charset=utf-8;base64,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"; diff --git a/community-modules/styles/src/internal/ag/generated/_agGridClassic.scss b/community-modules/styles/src/internal/ag/generated/_agGridClassic.scss index d272de025cc..3ae7326fba6 100644 --- a/community-modules/styles/src/internal/ag/generated/_agGridClassic.scss +++ b/community-modules/styles/src/internal/ag/generated/_agGridClassic.scss @@ -1,3 +1,3 @@ // THIS FILE IS GENERATED, DO NOT EDIT IT! -$data: "data:font/woff2;charset=utf-8;base64,d09GMgABAAAAABiAAAsAAAAANQQAABgvAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHIt0BmAAjTQKvXCybgE2AiQDgnALgToABCAFhFIHhlEbAi51xcHGAYyt+XGOqOCUy/7/j8mNMaRFW+2DQiaRCEiJnfzFNoXatItOd6/1K3ezHoUkc9bDjcZ8cr01puWoVCIt80OmEKxPsLnB4sbTH8+FU5c1b0+HyIzToZQE1FjbuxeNDNEqHrqKZdIPido8MZ1QL6T3+db+d5+Y//8Rldmd2Z1VQ8wTicgh/9MJkaQhUgIeEomBdXmiHmCaQllcXQBQAGPuJoaJtbyeyURq/b/afHeBtDNvgVpC1WylJvmh6lzgCleiFY2RmgiQ27HD0zb/wX2mjcdR6gpETteItSbGgQoYR1iBuCgDa1Xo5irACatTcZWwLFep62R/XxY/AwDCQPX025yEMNgtuU68XEcDAlAIXJxmK0nnwAEk6YClk//iOltx3DqSX5JzAz+DT3AJfoI+Avz/3+9X1m6hctANXjIx3P+QI5he8PQtXcyTrI6HIh6atZewNm3SxAnNUp8S+8z/nGnTEYKQ/Pyc+j8p/N+ftkv5Fy/jO864d0NgRclxrwfLAMnNsQI2ekKDVhvksKFB/fdSoNY5H8Zc31NvbFyfrDjjkJCEiMhP3hrfIoCynfagvgWqi/rZ9if3MIYgJwMsF4ez3dcvonjRLysoDIo/IFdTt+Lf2+/2htXwOzwn/1OkrK68z/5NbJRTtdbY3lNKhZC/TUQJCEYi49LyxFllmUKVC3WUShtESeMzMtTJpdssqOxTvsAIQiSlcRlFm71tIrjQNa912XwMGyTpksX5eTfjhS9zW6AkAhOzvmDp5R5SiHKpDKteNnURHAGC2xyv60A5NJThlOwQaaYPVtOs38OnM3aT/JClXJJiyFAij1VyPrUDLRFqDDJ1gKltSF68LEBxuyAkGssPvHTxcoImY1yEoZinvLwCQTmYNRB346mCpsLej2teeDNop6eirn8jbxzfhuKpru8kt/32Vw1UjNmJmIW+wAGEi8rc+4hAdVoeRYg0pq3hfmuEakl8eWH1w7f+yoam8fUxjmN8Az/Br0MtvCvp+0Ddvb5N5vjx9LK2ZI7frXEeT+mKmhK7CEtOYDUagfu5Z9IVVbKXsyJXEIosJTrI9T5PvpuMeD6GXXS1efTg49w2r/qacqseIyI0j6N0R1Gy9/sCVYVBR1X5XInLaylDQY5pyQTTiKoKKlUdy+c+1Iy8dKQFjpMwLa9JGj9epTWRrS9llY0VxrzhoghLcoIZXBN5r3MS1Z6ZauiMoyx+bnCmWyAQDil0yQS1fHtcwls5+3Nopz+yPbMvZl3iVUs63dJnFO25f4LAGRbwIXTyAIVcRloQAUWN89oL7njmMFagXFrd0RBNFBc9R1B8x0kHNiKiUqOpZaFPtQ7qqKc22KeRBr8XEpCsaj14+LBornHU2mmMX3V96HUD/7VxdKhFRZ3ZlDoyrSoLb6jRGbzQfyaWjT+Dd3IQX6SP4I3+/fBv1yANUS6DfGnqQLyCr22LQr/BSvY0Kr8IbMPnGgFyIAM6ALIQe8RzoQ3cpDvAyrzvg/g/VBWlZW3z54FXCfv/f51+3fYokZg2MhpU83AqMwd4Qm3XPBVHnJdYbir3feQN9vFRhSOUSEnLyCsoKinH589TU9fQJJLIFCqNzmCy2Bwujy8QisQSqUyuUKrUGq1ObzCq/zmOtSZgbVMzcwtLK4icwza2dvYOjk45DSGPtPCc//m9M5pOY8GUYE16XA4gjjE/UpwwwaxZFci+ym6CzpLmwDb1gh2aAbs0DvZoAuzTADigFXBIfeCIpsAxDYFTmgZnNAnOaR5c0Ai4pGFwRYvghvrBLY2BOxoE97QAHmgZPNIoeKJZ8ExL4KV0FRKCWkHABAEzQB5SQAHSBEVIDUqQFigD+kiwGgXWosF6DNiIBZtxYCsebCeAnUSwmwT2ksF+CjhIBYdp4CgdHGeAk0xwmgXOssF5DrjIBZd54CofXBeAm0JwWwTuisF9CXgoBY9l4KkcPFeAl0rwWgXeqsF7DfioBZ914KsefDckxDYC+SmhzyYQ1KYAo2aJsNkcQmQLCNgSAraCgK0hYBsI2BZg3A5M2gsVO0DAjhCwEwTsDAG7QMCuELAbBOwOhjks65h/f5wWfWs1MjBsoP0GeU575CNI9DLiGoamDWYcN1mOJMrS8dSqju+gnLt6L3mnkLawUhvXMYcr5LWVVnxHgyXEGDrNnBr0ECSGCbAV9Ax3FZahATDdk9N/3nGM8AKfxS2WRF0UYE4wELIkEoA/v4T08LA/WQhEVhIh7gT8c4PsieZY4J50BId1VWzA0RFb16Smb5hE60s6ad0Dt08uTlW7Q0LXUoqlMqohfeOGNhamXDDKJe1fZaFKlZmsVqDa3ufYbKFcAcv78qY7lJ6Ce61gZ7PlVP/yk/p55PVnN37bgxTrZa961ilVBkx4+BM7776lgQOFjYQSDju9LzeQWq0fKj+5YV//DCCvJ14DdxUBMNnoOmInANiSL6dY9nztvsGp7wZOR3E079XtJE36FYPnLjQepdheEzrbubvd6Kbr7qOUwwiGqaendffnW5xw3v0ibbwfb5Biv/5+Rndrc1xv4cZ6heAQkWAnQbCBmq0OU8BG09ovK9C03oXeyLpt9DoVa5fneTSziqVbNgjG/GSt03Xkj/cPOyNKQ3YiFbcrp7WBTnSPSdMEAQIMQ7I5SSQVg6wxVdI24BQJ3msOpoZm0tzMCCvHY2Ob+xu1sv8o3ot/eAvgU601VkgVCdm8wy7UauBWglLpAnau3npGvCc3EN/NGaUA3NvI+bqUu+bzXpbZ1x+DOyAnAxl/sZg9NEmNSnDTudWQt1wvbhSdK7k1FHqYpZLK1ouCiXxHrCzN2ujU98XROYMbRh+hxb2Z3MXGg9TuIXONIjsM3TjGzlxO63cQc4JOs0m88dvdx9ftG0+8Z7ecm0/3ub/99+k5f022MX8huJ80E0QRLO2mILhhoU6VePXOTHTcIWivBBlEWdZozzW3clyDtfPgBtg5+GyYkqyc/o1EjPN4HS5jdETHzCMxEYM77v04vv5jHPcJaSSQF6tDHvOfa97ypmhx8i7BkGDKpXCStZEQ0tSQ4ibDclyR6MJ6QG2fnTmMIZwXLmLPFj5aaLVLSxxjFOTMJZAPc7GGMkEQlDOTWUbUABOLYA2pGBAgrTGrtEQC4ncDInKq2SF3EGRySPC1jJrGGaTSBp38w6JwFf1tOYrjRormWpH3yqnLo7OF5KBaGP2JmkNFoxkPyQUYXxg6M19NlQebf3lMFU4qZNHqen+SrXac2ejhGDhnBLEsvLvAcNAgv5C60ztb9jqKf6LJ45OCUYKAUY5gQqSAyfl7jMkmIjAHik4DcseoWC5WU1PQ1SQIC7XF5cQrKgg6g64RJhVzPE3M/aCbeok07noxy2NhpjYNDyZx/UEd0byTbj/2g0XEy1JtYoffncN/8hjcQ54Tslk02yKKniCYMDgUH1LSToLEgHIQMmDNLP8JDGeUJMBwo2Keug3JNYKtMhCkVnGxOkm26qgNPvFw48JmuQYR2zjigTjwUY+Zy2VcBpiwnSDMYJhxPXAZwLI+Rk/Di6KTXLSkudCxJekySBEoyNt8DvdWWJlsbZM2TcVqSW80W6xje+wNmWxrG6QfzNrJo8iaYm39LWT7bch6HY8NSn1bpL/l4+MJtlM5PTPvGGdybnLayhJZzzpBDoYspGNzygi4v+V5McVsnVAInWzCRL2J5tXtGqhwKQTXLIdFjqvNaQquU+ijuoHTIJZXDwWtuUGQhEb6EWmjhg8g3MY2ir5V0RLb+UxGZ5gHjWlQr4GxE+w9cYmn/ELxZTK2mu8oNF74txN4roRx9du7q13WIfvN5FNTRBTbCtceP79+6caLJ/2ReBnktkuJyNU6OwX3qL+o7xobi87ZfDUSRSY7DcMGncg/qFtZMQlkfYecjh72Fe3CtEck44eWqf8w2OgmrxZ4G1vqn+2dU1ZpNdpe5OETZBLDykTva11P1xwq85SAQWXaxNI/IZRvMYnnGUmKltpt4xJz7KDyhBFs0xFCcgSRso+mZWZkF4Usjb5Ep12zZtbqQX4Cq+tX0lO0U+pv3Zp5+/bCu3dn3Rm5MiZdilZYeLq48ioNipvn3q5Umgu6h/X2Uasx2TkygkyWrIag5GSmJIYh8rTLMIhqNZkspYWiTJ1MBlfLtm41FBUQUPe4rY25AQiXfY68BIwwvEIRyw3G4i757n9Npfe/sThB7zJEIaO8ksjo+4iL30OuOaNrHiRHcnq/31KaFpI21y8WPm18UV5nTr96SJsWKW/tzqCeDoMGyYzx7TWRjROU/UdyzjOorxoRcfQQ6sLnVORgyFDfsPNfndecHczGgo7t663WTrSN3+5yAXNIk6zT6TKc/3rxqqhE6odkSS2RLpiaSDcr7evMBg+2+2dF6QUyiztrKOuWRIqo5Q6+5upxBIfD1KWCR+gdoQxwKuyfWbHLmnOF1zeofxFIP6AEPopk2J49u/dgWAXuErLdJXbL1OwBsXbyR84yNvcrl72M85G7zLsJ672MjKz+ElQJf4argr7AJVTGqFfiYbhyC04wik1j14DYTW87TsndeFqaTT4jow/BP/49IxS1LHjalIBmu+TJNzWhTuXBuxN2u6WwkEwePuwc53Pu7Lkdw7dubXinDeYCGeAGa943AHtXs7pZUra0RUmoCYlji6pFQeyebVA291PPhLvz5NPW3JovsPDHEggbabwxOqmZyMGQAouFcLuJ0p3WpZKbsOP5JnEP+D4Ghk0mGD5TBWJvvC4pNk2aNWoXCS1BBagRjU3/rTLznmuhzyur60i3vCNEQQ9Ik+x3/Bf3uEEPKhF4bKMY3NMmCGEN5dN8mgJqhlUIqaw9Ub2dxb31+uDpget3BgazGcwegRfdNL+GwNrRk9/7wzpaoJ31I3YjGEB/xqRN/aeKYQsYM0T9tCctwCezRcJkbj5Laxza0McZ6WL3AYwav0qlL4UdfZM9cQ31YA47qn2At6+NVgq2+cdMPxp7F79yUyyKFGoFUVqjK2ijjFkLtMIRooLqnHI0q7ewjYw6D61AyO9hTwq50BhjvRBzyBrTeAgioVXJVepUQikZmuiJ1pZN0VGwuTrQ7t/WZjAU5ANq0vjl18iNc+nViWMbxicyR1Jh7s+hGSMzmq5rTntTB/rDStV4vProSloDm86O0U/X1cQsoHhTe1NpR9BL1aAk3ASgIYFxeU8l86Ha1MmJ+tmLxpfcjpaKon4+6D/9fiIpH/cdsdnUPj3kJVebFTdUv1IqEMoHSRcWqhhprBTfXtmhGT753lrhrYangoSMeRVJd43Jg2Q5N5i6Rz4bh+BO0OsUYz65Nq3fC5w1RJcqwaW5nKKwAsoYSk7c7UVPBYnpc8oSZ2omtV4+SyP1ObEFcSWUSZS8WK0goegGU/vY+4Ass0RYNToGy1mXQPbv3sdXDfSYbwYvsVyv2wUownESlXLDFsIDNIQGjPjoxt1U18kTCFVdpAYgrhLOri3VIvhuW8X2LBSEIOMIXO1R9+ppJlRNDK7yqDTUbZdrKsT2kcCJDYSmFHHie1q1F/CrC3fjQ0uKbS0tBsMBRwWlorV1SDOYNs2MqJBEdG3VnDnmuRRJQpRIaWmFk1Zuu8osl68N7hVAJ7EE2joHIocVMgWioDlmz3HCcprcYZ4cBOAF5qrUVXkwjWZWGBgxz5lTha5d5GyG1aTVqVVrq+Cg8+C3zkHD8LPnOBQ0BSKDZwS5o04rYJHoAb2C18rldrDbTwqww2vXmkyxgveIe/P4NfL6goJi0kygx0U78QjDOqkWa5XV2jEVe/wYA40/ECIYnOKZiJJEc1SEhCisTieNvopzKZ3y/1utJRarcDn26BH2RajSS4BMgd9rWHaOHoP5BAjsqWqvsgW9pO+MWWhGeF1deAaafdmgQ+vqM8Kz+Jey+RymnuEX4jN1x5uNbnMrFBkippgpL82Pz42NzYkvKJV/U0xapVAkiJiSmwo5sXHHk1+qYImZolWAV872WC1WD04MN06op6zbDT5+zI3fOdqT1gXyrA2Jz8XdO1t32WdihsIMeTMeDXBM3tPp6J9DLzkmkziH69gxV/PKh8dfxXoS2HTYCBa5DV0rW5ytdwKCyS6apXdYUxdAizUuReU/iy9o8IIv/2x3BsQVPIvLP3FOa5J6zG/QlKoz+UUKzM9853sWnz/EcGbbKElZmcRs0BZzkwBmY47WqKnQ0hKnKJjl5il4OI8LuIpSylOGjhtnuUqQZR3HCg0gLBalCii/q5QWQL8pvgAUEMo6OxUYUnh9wIDoaFPF0aMHDx4fEBCYhbCA1CtGxKjT/QcKOt16UaXU0T/JYaOHKrSKGjveO4j0Ys62Cmzs4FCalnZBHXpdJ7tKqcmEnAEZ4pKDAmeOn6uT3xnzPLcGuzTaMTSIkvANf/8W3GqKfANY9R01qnOzYF7s7qAgaNMw1KiC7WnOc9FJCMWG5A/dCMSJOhGi20eDWvzc5V8i5cvs4WH/3wa16OXseIQig/rPNLoDbaMDxpxxAXDAzklCavh1H4UDHjHXgBbQCdY5AaBT1Keo4TtK95fCD0wm18YNGze6wPd4xIVcP4389BydfbU7il/KjqLIOL2Aa3sXRuuSzz7QTnfQE8InUnWd5tr91nyZwU8+cj0cDZ8IEngrN/iGZDkn/575TDiC3JN3a9aYnHm03pT6UEf1lFGd4N7rzp0g7l0BJYk+jbR3de0xkGkWlyL57UyEpWtt1WwZaZ5DsyPFAgZ9B9LiPW07Kq7QgXYkbac4+A/v3ht77UDBoG8r1pZN6bAtu6/L2HndRkfKOkr7PR+jiJqwlQFKnXyQFBdUy6uFt9qThgvx/U/XhNfA44wTjm3cLxFrZpDqefWkGWORNrSNPLbCsDQqaujON82SweIFCtcCXJMzFtYzM9JNpue+wiT/JKFCIdzrv1d4uroadN+0yrDNYOZChW1FF1DRZorkDQY8RcoX88PFqNQm0APE4VLUJiC4hkptfD6k6fEDtuzb69i7D+T9T8o86Z2Jhcahsg5aVPUs9KBQRM/4icMI1P/qDfQWrZGphgxolTiY3vKQJDigaUoBQP23JkIf4LdBD4ecwowxdfnPQXHUxNJZaLw1/raFg+kYr9NjA+yQ7v//rKHv/bd0zHRcrCM2qEhDoZtA/X+e6Z3uKcbZPk5ZvcyYqGyDdOZxKjayFbzVdT3V8/pmCEjOTq2wFfHQ0lJkfu+YBjlSZAkusTTZpA2RqQfP1wsKZOcib6B1ox3qSXok3nvQHVRmQ0x/HbTqb2Nnhj7awzPzqMN+ePtBb4CQ6fP86EyMaZ+/CKQfXoxIhq2hgPkxrj8d6H68YcV/UAmt/Nvo/P0JCR7nm36+50KE4UDeD6H/xN/WV+LHNOlohCStGe05lhtTEhqlaO+mCcSIpq1oJjcFQ73lTXTw2y6cJQGsiz+zphLdBSzziv7FCop+NU0w/MOtUPR/U8AH59+eGDAYDu8S/XMC1ei+YSgJpD32yuv+QtHI1D7098njeEdCAUPfLtatzuHRbGgH4al9YzJMidss/IHO+tEsP93dDTNVveNpCwTvROQ9Sw9Y87Qi5xsUlPaMiswEcukveM4u31VGWg9697Kad0LyFFiCPejCuqZqvqOPLKeDtowWbGrIm15WEqcc8y3J/OgPyKXe3qgQnT25y6c1yHp7Tot2GtgAhACJLGKZRpgwaRb7s88ah8v/+vFFSVZUTTdMy3Zczw/CKE7SLC/Kqm7arh9G48l0Nl8sV+vNdrc/HJ1yGiEQUYxExilUGp3BZLE5XB5fIBSJJc44m4bkEAQDWGRqQISXugvqKqiOqwaP6hoH5DDVbgSx83tQdJ8LXnXzIPrbRwVE8mgoUyQwvFznKCQVeuw4sXQ5rpSUvRtRJtJDx2QCztBXjvO6dsKqu07nXVesGprWuMrQfgkZtCv6A1xjpwl03G3EZohpi6jucKJWBYm5DsIlV08qWJVwsCZFGljtXmLwkcL+BKs4xQ1WE1LZt1TLqCVcWUVMeERsHaTES/R11qASd3OkOseZbT8LzpGLnktPb4a7RTFj6ngYzh6Fo1piGK1SmPFQp7v4zvOSFqxJ/BG4Lvz+DbQY257ZxqUJoid9+4UckFQ5Fa3XeIru2w6NhIoUzZyy67E/SRdA2hTazwKdlBkR+m7BZjwdMqHG+dCNOIudgZKPF6x5hjv2znwC7o4/9PML0YH3FfpojSKIG2u2QSCQiRhZUo6XjD4trHSTIlubDTZtAQA="; +$data: "data:font/woff2;charset=utf-8;base64,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"; diff --git a/community-modules/styles/src/internal/ag/generated/_agGridMaterial.scss b/community-modules/styles/src/internal/ag/generated/_agGridMaterial.scss index 37bbf131d2e..e5f58894a76 100644 --- a/community-modules/styles/src/internal/ag/generated/_agGridMaterial.scss +++ b/community-modules/styles/src/internal/ag/generated/_agGridMaterial.scss @@ -1,3 +1,3 @@ // THIS FILE IS GENERATED, DO NOT EDIT IT! -$data: "data:font/woff2;charset=utf-8;base64,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"; +$data: "data:font/woff2;charset=utf-8;base64,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"; diff --git a/community-modules/styles/src/internal/ag/generated/_agGridQuartz.scss b/community-modules/styles/src/internal/ag/generated/_agGridQuartz.scss index bdb4f103396..a3f7b88dcbf 100644 --- a/community-modules/styles/src/internal/ag/generated/_agGridQuartz.scss +++ b/community-modules/styles/src/internal/ag/generated/_agGridQuartz.scss @@ -1,3 +1,3 @@ // THIS FILE IS GENERATED, DO NOT EDIT IT! -$data: "data:font/woff2;charset=utf-8;base64,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"; +$data: "data:font/woff2;charset=utf-8;base64,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"; diff --git a/community-modules/styles/src/internal/base/parts/_calculated-columns.scss b/community-modules/styles/src/internal/base/parts/_calculated-columns.scss index 0559846160f..944fa14de57 100644 --- a/community-modules/styles/src/internal/base/parts/_calculated-columns.scss +++ b/community-modules/styles/src/internal/base/parts/_calculated-columns.scss @@ -29,11 +29,9 @@ } } - .ag-calculated-column-expression-error { - color: var(--ag-invalid-color); - font-size: 11px; - line-height: normal; - margin-top: calc(var(--ag-grid-size) / 2); + .ag-rtl .ag-calculated-column-expression-wrap .ag-text-area-input { + padding-left: var(--ag-input-padding-start); + direction: ltr; } .ag-calculated-column-expression-tools { @@ -83,12 +81,6 @@ flex: none; } - .ag-calculated-column-properties { - display: flex; - flex-direction: column; - gap: calc(var(--ag-grid-size) / 2); - } - .ag-calculated-column-actions { display: flex; justify-content: flex-end; diff --git a/community-modules/styles/src/internal/base/parts/_common-structural.scss b/community-modules/styles/src/internal/base/parts/_common-structural.scss index 38287dffd55..9739040e820 100644 --- a/community-modules/styles/src/internal/base/parts/_common-structural.scss +++ b/community-modules/styles/src/internal/base/parts/_common-structural.scss @@ -1090,11 +1090,86 @@ .ag-overlay-loading-wrapper, .ag-overlay-exporting-wrapper, - .ag-overlay-modal-wrapper { + .ag-overlay-modal-wrapper, + .ag-overlay-file-input-wrapper { // prevent interaction with grid while it's loading pointer-events: all; } + .ag-overlay-file-input-center { + border: solid 1px var(--ag-border-color); + background: var(--ag-background-color); + border-radius: var(--ag-card-radius); + box-shadow: var(--ag-card-shadow); + display: flex; + flex-direction: column; + align-items: center; + gap: calc(var(--ag-grid-size) * 2); + max-width: 420px; + padding: calc(var(--ag-grid-size) * 2); + } + + .ag-file-input-error-banner { + background: color-mix(in srgb, var(--ag-invalid-color) 10%, var(--ag-background-color)); + color: var(--ag-invalid-color); + border-radius: var(--ag-border-radius); + padding: calc(var(--ag-grid-size) * 0.75) calc(var(--ag-grid-size) * 2); + width: 100%; + text-align: center; + font-size: 0.9em; + } + + .ag-file-input-drop-zone { + border: dashed 2px var(--ag-border-color); + border-radius: var(--ag-border-radius); + padding: calc(var(--ag-grid-size) * 4); + display: flex; + flex-direction: column; + align-items: center; + gap: var(--ag-grid-size); + width: 100%; + } + + .ag-file-input-drop-zone-active { + border-color: var(--ag-input-focus-border-color); + background: color-mix(in srgb, var(--ag-input-focus-border-color) 10%, var(--ag-background-color)); + } + + .ag-file-input-processing { + display: flex; + align-items: center; + gap: calc(var(--ag-grid-size) * 0.75); + padding: calc(var(--ag-grid-size) * 4); + + .ag-loading-icon { + @include ag.unthemed-rtl( + ( + padding-right: 0, + ) + ); + } + } + + .ag-file-input-text-row { + display: flex; + align-items: center; + gap: calc(var(--ag-grid-size) * 0.75); + } + + .ag-file-input-text { + font-weight: 600; + } + + .ag-file-input-browse { + cursor: pointer; + border: solid 1px var(--ag-border-color); + background: transparent; + color: var(--ag-text-color); + border-radius: var(--ag-border-radius); + padding: calc(var(--ag-grid-size) * 0.5) calc(var(--ag-grid-size) * 2); + font: inherit; + } + // /** // **************************** // * Popup diff --git a/community-modules/styles/src/internal/base/parts/_footer.scss b/community-modules/styles/src/internal/base/parts/_footer.scss index f75f8507bd6..9384dd5e71d 100644 --- a/community-modules/styles/src/internal/base/parts/_footer.scss +++ b/community-modules/styles/src/internal/base/parts/_footer.scss @@ -38,6 +38,23 @@ line-height: 0; } + .ag-paging-row-summary-panel { + display: inline-grid; + + &::before { + content: var(--ag-internal-pagination-width-string); + grid-area: 1/1; + visibility: hidden; + font-weight: 500; + font-variant-numeric: tabular-nums; + } + } + + .ag-paging-row-summary-content { + grid-area: 1/1; + justify-self: center; + } + .ag-status-bar { border-top: var(--ag-borders) var(--ag-border-color); color: var(--ag-disabled-foreground-color); diff --git a/community-modules/styles/src/internal/base/parts/_toolbar.scss b/community-modules/styles/src/internal/base/parts/_toolbar.scss index fc2769e50b8..24e2e82929b 100644 --- a/community-modules/styles/src/internal/base/parts/_toolbar.scss +++ b/community-modules/styles/src/internal/base/parts/_toolbar.scss @@ -56,18 +56,15 @@ color: var(--ag-icon-button-hover-color, var(--ag-foreground-color)); } - // stylelint-disable-next-line selector-max-specificity .ag-toolbar-button-wrapper:hover .ag-toolbar-button, .ag-toolbar-button-wrapper:hover .ag-toolbar-button .ag-icon { color: var(--ag-icon-button-hover-color, var(--ag-foreground-color)); } - // stylelint-disable-next-line selector-max-specificity .ag-toolbar > .ag-toolbar-button-wrapper:first-child > .ag-toolbar-button { border-start-start-radius: calc(var(--ag-border-radius) + 1px); } - // stylelint-disable-next-line selector-max-specificity .ag-toolbar > .ag-toolbar-button-wrapper:last-child > .ag-toolbar-button { border-start-end-radius: calc(var(--ag-border-radius) + 1px); } @@ -103,18 +100,15 @@ margin: 0 calc(var(--ag-grid-size) * 2); } - // stylelint-disable-next-line selector-max-specificity .ag-toolbar-input + .ag-toolbar-input { margin-inline-start: 0; } - // stylelint-disable-next-line selector-max-specificity .ag-toolbar > .ag-toolbar-input:first-child, .ag-toolbar-right-start + .ag-toolbar-input { margin-inline-start: var(--ag-grid-size); } - // stylelint-disable-next-line selector-max-specificity .ag-toolbar > .ag-toolbar-input:last-child { margin-inline-end: var(--ag-grid-size); } @@ -146,7 +140,6 @@ // High-specificity padding override — beats theme text-input padding-left rules // (which reach .ag-theme-X .ag-ltr input[class^='ag-'][type='text'] = 0-4-1) .ag-toolbar-input { - // stylelint-disable-next-line selector-max-specificity input[class^='ag-'][type='text'].ag-toolbar-input-field { @include ag.unthemed-rtl( ( @@ -218,8 +211,7 @@ min-width: 0; } - // High-specificity overrides to prevent theme text-input rules reinstating border/shadow - // stylelint-disable-next-line selector-max-specificity + // high-specificity overrides to prevent theme text-input rules reinstating border/shadow .ag-toolbar .ag-toolbar-find input[class^='ag-'][type='text'].ag-toolbar-input-field { border: none; box-shadow: none; diff --git a/documentation/ag-grid-docs/package.json b/documentation/ag-grid-docs/package.json index e95ff06a69b..9ecc88c7eda 100644 --- a/documentation/ag-grid-docs/package.json +++ b/documentation/ag-grid-docs/package.json @@ -2,7 +2,7 @@ "name": "ag-grid-docs", "description": "Documentation for AG Grid", "type": "module", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "repository": { "type": "git", "url": "https://github.com/ag-grid/ag-grid.git" @@ -53,17 +53,17 @@ "@tweenjs/tween.js": "^18.6.4", "@types/react": "^18.2.47", "@types/react-dom": "^18.2.18", - "ag-charts-angular": "13.3.0-beta.20260609", - "ag-charts-community": "13.3.0-beta.20260609", - "ag-charts-enterprise": "13.3.0-beta.20260609", - "ag-charts-types": "13.3.0-beta.20260609", - "ag-charts-react": "13.3.0-beta.20260609", - "ag-charts-vue3": "13.3.0-beta.20260609", - "ag-grid-angular": "35.3.0-beta.20260609.1239", - "ag-grid-community": "35.3.0-beta.20260609.1239", - "ag-grid-enterprise": "35.3.0-beta.20260609.1239", - "ag-grid-react": "35.3.0-beta.20260609.1239", - "ag-grid-vue3": "35.3.0-beta.20260609.1239", + "ag-charts-angular": "13.3.0-beta.20260610", + "ag-charts-community": "13.3.0-beta.20260610", + "ag-charts-enterprise": "13.3.0-beta.20260610", + "ag-charts-types": "13.3.0-beta.20260610", + "ag-charts-react": "13.3.0-beta.20260610", + "ag-charts-vue3": "13.3.0-beta.20260610", + "ag-grid-angular": "35.3.0-beta.20260610.1146", + "ag-grid-community": "35.3.0-beta.20260610.1146", + "ag-grid-enterprise": "35.3.0-beta.20260610.1146", + "ag-grid-react": "35.3.0-beta.20260610.1146", + "ag-grid-vue3": "35.3.0-beta.20260610.1146", "algoliasearch": "^5.51.0", "astro": "6.1.9", "cheerio": "^1.0.0", diff --git a/documentation/ag-grid-docs/public/theme-icons/alpine/alpine-icons.zip b/documentation/ag-grid-docs/public/theme-icons/alpine/alpine-icons.zip index d9b7747e090..d1a462d6c41 100644 Binary files a/documentation/ag-grid-docs/public/theme-icons/alpine/alpine-icons.zip and b/documentation/ag-grid-docs/public/theme-icons/alpine/alpine-icons.zip differ diff --git a/documentation/ag-grid-docs/public/theme-icons/alpine/document.svg b/documentation/ag-grid-docs/public/theme-icons/alpine/document.svg new file mode 100644 index 00000000000..8db30d84c2f --- /dev/null +++ b/documentation/ag-grid-docs/public/theme-icons/alpine/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/documentation/ag-grid-docs/public/theme-icons/balham/balham-icons.zip b/documentation/ag-grid-docs/public/theme-icons/balham/balham-icons.zip index ac382218d1e..77dbc125f7f 100644 Binary files a/documentation/ag-grid-docs/public/theme-icons/balham/balham-icons.zip and b/documentation/ag-grid-docs/public/theme-icons/balham/balham-icons.zip differ diff --git a/documentation/ag-grid-docs/public/theme-icons/balham/document.svg b/documentation/ag-grid-docs/public/theme-icons/balham/document.svg new file mode 100644 index 00000000000..b496e2ef7a5 --- /dev/null +++ b/documentation/ag-grid-docs/public/theme-icons/balham/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/documentation/ag-grid-docs/public/theme-icons/base/base-icons.zip b/documentation/ag-grid-docs/public/theme-icons/base/base-icons.zip index 26fcc7a0e54..dcc5e8cecaf 100644 Binary files a/documentation/ag-grid-docs/public/theme-icons/base/base-icons.zip and b/documentation/ag-grid-docs/public/theme-icons/base/base-icons.zip differ diff --git a/documentation/ag-grid-docs/public/theme-icons/base/document.svg b/documentation/ag-grid-docs/public/theme-icons/base/document.svg new file mode 100644 index 00000000000..8db30d84c2f --- /dev/null +++ b/documentation/ag-grid-docs/public/theme-icons/base/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/documentation/ag-grid-docs/public/theme-icons/material/document.svg b/documentation/ag-grid-docs/public/theme-icons/material/document.svg new file mode 100644 index 00000000000..6552f7fd567 --- /dev/null +++ b/documentation/ag-grid-docs/public/theme-icons/material/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/documentation/ag-grid-docs/public/theme-icons/material/material-icons.zip b/documentation/ag-grid-docs/public/theme-icons/material/material-icons.zip index 185f85987eb..59c924b2be7 100644 Binary files a/documentation/ag-grid-docs/public/theme-icons/material/material-icons.zip and b/documentation/ag-grid-docs/public/theme-icons/material/material-icons.zip differ diff --git a/documentation/ag-grid-docs/public/theme-icons/quartz/document.svg b/documentation/ag-grid-docs/public/theme-icons/quartz/document.svg new file mode 100644 index 00000000000..0b8080293c3 --- /dev/null +++ b/documentation/ag-grid-docs/public/theme-icons/quartz/document.svg @@ -0,0 +1,3 @@ + + + diff --git a/documentation/ag-grid-docs/public/theme-icons/quartz/quartz-icons.zip b/documentation/ag-grid-docs/public/theme-icons/quartz/quartz-icons.zip index 97bfb4da525..9578e7d441b 100644 Binary files a/documentation/ag-grid-docs/public/theme-icons/quartz/quartz-icons.zip and b/documentation/ag-grid-docs/public/theme-icons/quartz/quartz-icons.zip differ diff --git a/documentation/ag-grid-docs/src/components/example-runner/framework-templates/lib/Extras.astro b/documentation/ag-grid-docs/src/components/example-runner/framework-templates/lib/Extras.astro index e59ce9c282e..a5d57c8fb10 100644 --- a/documentation/ag-grid-docs/src/components/example-runner/framework-templates/lib/Extras.astro +++ b/documentation/ag-grid-docs/src/components/example-runner/framework-templates/lib/Extras.astro @@ -23,8 +23,8 @@ const extrasMap: Record = { fontawesome: { styles: ['https://use.fontawesome.com/releases/v5.6.3/css/all.css'], }, - 'xlsx-style': { - scripts: ['https://cdn.jsdelivr.net/npm/xlsx-style@0.8.13/dist/xlsx.full.min.js'], + xlsx: { + scripts: ['https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js'], }, materialdesignicons: { styles: ['https://cdn.jsdelivr.net/npm/@mdi/font/css/materialdesignicons.css'], diff --git a/documentation/ag-grid-docs/src/components/icon/IconsPanel.tsx b/documentation/ag-grid-docs/src/components/icon/IconsPanel.tsx index 76de2dc1ed7..d483185043f 100644 --- a/documentation/ag-grid-docs/src/components/icon/IconsPanel.tsx +++ b/documentation/ag-grid-docs/src/components/icon/IconsPanel.tsx @@ -27,6 +27,7 @@ const ICONS = [ 'cross', 'csv', 'desc', + 'document', 'down', 'edit', 'excel', diff --git a/documentation/ag-grid-docs/src/content/api-documentation/grid-options/properties.json b/documentation/ag-grid-docs/src/content/api-documentation/grid-options/properties.json index 2dd460c7da7..82907331419 100644 --- a/documentation/ag-grid-docs/src/content/api-documentation/grid-options/properties.json +++ b/documentation/ag-grid-docs/src/content/api-documentation/grid-options/properties.json @@ -1018,6 +1018,12 @@ "name": "Overlay Component", "url": "./overlays/" } + }, + "processFileInput": { + "more": { + "name": "File Input Overlay", + "url": "./overlays-overview/#file-input-overlay" + } } }, "nav": { diff --git a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/customising-columns/example.spec.ts b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/customising-columns/example.spec.ts index ed79767b830..57b8aa2f0fb 100644 --- a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/customising-columns/example.spec.ts +++ b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/customising-columns/example.spec.ts @@ -1,11 +1,19 @@ -import { clickAllButtons, ensureGridReady, test, waitForGridContent } from '@utils/grid/test-utils'; +import { expect, test } from '@utils/grid/test-utils'; test.agExample(import.meta, () => { - test.eachFramework('Example', async ({ page }) => { - // PLACEHOLDER - MINIMAL TEST TO ENSURE GRID LOADS WITHOUT ERRORS - await ensureGridReady(page); - await waitForGridContent(page); - await clickAllButtons(page); - // END PLACEHOLDER + test.eachFramework('Example', async ({ agIdFor }) => { + // Auto-generated headers + await expect(agIdFor.headerCell('product')).toBeVisible(); + await expect(agIdFor.headerCell('region')).toBeVisible(); + await expect(agIdFor.headerCell('profit')).toBeVisible(); + await expect(agIdFor.headerCell('profitMargin')).toBeVisible(); + + // Profit columns display with £ currency formatting via currencyColumn type + await expect(agIdFor.cell('0', 'profit')).toContainText('£12,500'); + await expect(agIdFor.cell('0', 'profitMargin')).toContainText('£0.15'); + + // Non-profit columns display without formatting + await expect(agIdFor.cell('0', 'product')).toContainText('Widget A'); + await expect(agIdFor.cell('0', 'region')).toContainText('North'); }); }); diff --git a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/example.spec.ts b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/example.spec.ts new file mode 100644 index 00000000000..b9674ff7647 --- /dev/null +++ b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/example.spec.ts @@ -0,0 +1,35 @@ +import { ensureGridReady, expect, test } from '@utils/grid/test-utils'; + +test.agExample(import.meta, () => { + test.eachFramework('loads sample data via select', async ({ agIdFor, page }) => { + await ensureGridReady(page); + await page.locator('#sampleData').selectOption('small-row-data.json'); + + await expect(agIdFor.headerCell('make')).toBeVisible(); + await expect(agIdFor.headerCell('model')).toBeVisible(); + await expect(agIdFor.headerCell('price')).toBeVisible(); + + await expect(agIdFor.cell('0', 'make')).toContainText('Toyota'); + }); + + test.eachFramework('switches to different dataset', async ({ agIdFor, page }) => { + await ensureGridReady(page); + await page.locator('#sampleData').selectOption('small-row-data.json'); + await expect(agIdFor.headerCell('make')).toBeVisible(); + + await page.locator('#sampleData').selectOption('small-olympic-winners.json'); + await expect(agIdFor.headerCell('athlete')).toBeVisible({ timeout: 10000 }); + await expect(agIdFor.headerCell('sport')).toBeVisible(); + }); + + test.eachFramework('upload file toolbar button shows file input overlay', async ({ agIdFor, page }) => { + await ensureGridReady(page); + await page.locator('#sampleData').selectOption('small-row-data.json'); + await expect(agIdFor.headerCell('make')).toBeVisible(); + + await page.locator('.ag-toolbar-button-wrapper').getByText('Upload File').click(); + + await expect(page.locator('.ag-overlay-file-input-center')).toBeVisible(); + await expect(page.locator('.ag-file-input-drop-zone')).toBeVisible(); + }); +}); diff --git a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/exampleConfig.json b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/exampleConfig.json new file mode 100644 index 00000000000..ffbeed4eefa --- /dev/null +++ b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/exampleConfig.json @@ -0,0 +1,3 @@ +{ + "extras": ["xlsx"] +} diff --git a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/index.html b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/index.html new file mode 100644 index 00000000000..d94787a4b17 --- /dev/null +++ b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/index.html @@ -0,0 +1,16 @@ +
+
+ +
+
+
diff --git a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/main.ts b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/main.ts new file mode 100644 index 00000000000..6ecd58e4fac --- /dev/null +++ b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/main.ts @@ -0,0 +1,101 @@ +import type { GridApi, GridOptions, ProcessFileInputParams, ToolbarItemActionParams } from 'ag-grid-community'; +import { + AutoGenerateColumnsModule, + ClientSideRowModelModule, + ModuleRegistry, + NumberFilterModule, + TextFilterModule, + ValidationModule, + createGrid, +} from 'ag-grid-community'; +import { ToolbarModule } from 'ag-grid-enterprise'; + +declare let XLSX: any; + +ModuleRegistry.registerModules([ + ClientSideRowModelModule, + AutoGenerateColumnsModule, + TextFilterModule, + NumberFilterModule, + ToolbarModule, + ...(process.env.NODE_ENV !== 'production' ? [ValidationModule] : []), +]); + +let gridApi: GridApi; + +function parseWorkbook(workbook: any): Record[] { + const firstSheetName = workbook.SheetNames[0]; + const worksheet = workbook.Sheets[firstSheetName]; + return XLSX.utils.sheet_to_json(worksheet); +} + +function processFileInput(params: ProcessFileInputParams): void { + const file = params.files[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onerror = () => { + params.fail('Failed to read file'); + }; + reader.onload = (e) => { + try { + const workbook = XLSX.read(new Uint8Array(e.target?.result as ArrayBuffer)); + params.success(parseWorkbook(workbook)); + } catch (error) { + console.error(error); + params.fail('Failed to parse file'); + } + }; + reader.readAsArrayBuffer(file); +} + +const gridOptions: GridOptions = { + autoGenerateColumnDefs: true, + processFileInput: processFileInput, + defaultColDef: { + minWidth: 80, + flex: 1, + }, + toolbar: { + items: [ + { + label: 'Upload File', + icon: 'document', + alignment: 'right', + action: (params: ToolbarItemActionParams) => { + const curr = params.api.getGridOption('activeOverlay'); + params.api.setGridOption( + 'activeOverlay', + curr === 'agFileInputOverlay' ? undefined : 'agFileInputOverlay' + ); + }, + }, + ], + }, +}; + +function onLoadSampleData(): void { + const select = document.getElementById('sampleData') as HTMLSelectElement; + const value = select.value; + if (!value) return; + + if (value.endsWith('.xlsx')) { + fetch(`https://www.ag-grid.com/example-assets/${value}`) + .then((response) => response.arrayBuffer()) + .then((data: ArrayBuffer) => { + const workbook = XLSX.read(new Uint8Array(data)); + gridApi.updateGridOptions({ activeOverlay: undefined, rowData: parseWorkbook(workbook) }); + }); + } else { + fetch(`https://www.ag-grid.com/example-assets/${value}`) + .then((response) => response.json()) + .then((rows) => { + gridApi.updateGridOptions({ activeOverlay: undefined, rowData: rows }); + }); + } +} + +document.addEventListener('DOMContentLoaded', () => { + const gridDiv = document.querySelector('#myGrid')!; + gridApi = createGrid(gridDiv, gridOptions); +}); diff --git a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/styles.css b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/styles.css new file mode 100644 index 00000000000..7a08451a02b --- /dev/null +++ b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/file-drop-overlay/styles.css @@ -0,0 +1,19 @@ +.example-wrapper { + display: flex; + flex-direction: column; + height: 100%; +} + +#myGrid { + flex: 1 1 0px; + width: 100%; +} + +.example-header { + font-family: Verdana, Geneva, Tahoma, sans-serif; + font-size: 13px; + margin-bottom: 5px; + display: flex; + gap: 16px; + align-items: center; +} diff --git a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/nested-objects/example.spec.ts b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/nested-objects/example.spec.ts index ed79767b830..d9024ff55ae 100644 --- a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/nested-objects/example.spec.ts +++ b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/_examples/nested-objects/example.spec.ts @@ -1,11 +1,21 @@ -import { clickAllButtons, ensureGridReady, test, waitForGridContent } from '@utils/grid/test-utils'; +import { expect, test } from '@utils/grid/test-utils'; test.agExample(import.meta, () => { - test.eachFramework('Example', async ({ page }) => { - // PLACEHOLDER - MINIMAL TEST TO ENSURE GRID LOADS WITHOUT ERRORS - await ensureGridReady(page); - await waitForGridContent(page); - await clickAllButtons(page); - // END PLACEHOLDER + test.eachFramework('Example', async ({ agIdFor, page }) => { + // Column group headers for nested objects + await expect(page.locator('.ag-header-group-cell').filter({ hasText: 'Address' })).toBeVisible(); + await expect(page.locator('.ag-header-group-cell').filter({ hasText: 'Scores' })).toBeVisible(); + + // Leaf column headers + await expect(agIdFor.headerCell('name')).toBeVisible(); + await expect(agIdFor.headerCell('address.city')).toBeVisible(); + await expect(agIdFor.headerCell('address.country')).toBeVisible(); + await expect(agIdFor.headerCell('scores.maths')).toBeVisible(); + await expect(agIdFor.headerCell('scores.science')).toBeVisible(); + + // Cell data + await expect(agIdFor.cell('0', 'name')).toContainText('Alice'); + await expect(agIdFor.cell('0', 'address.city')).toContainText('London'); + await expect(agIdFor.cell('0', 'scores.maths')).toContainText('92'); }); }); diff --git a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/index.mdoc b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/index.mdoc index d310268d949..47eb7a7f56b 100644 --- a/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/index.mdoc +++ b/documentation/ag-grid-docs/src/content/docs/auto-generate-columns/index.mdoc @@ -143,3 +143,32 @@ const gridOptions = { The example below uses [Column Types](./column-definitions/#column-types) to apply a `currencyColumn` type to any column whose field contains `"profit"`: {% gridExampleRunner title="Customising Columns" name="customising-columns" exampleHeight=300 /%} + +## File Drop Overlay + +When `autoGenerateColumnDefs` is enabled and no `rowData` is present, a file drop overlay is shown automatically when `processFileInput` is provided. Files can be dragged onto the overlay or selected via a browse button. See [Overlays](./overlays-overview/) for more on grid overlays. + +Provide a `processFileInput` callback. The `params` object contains the selected `files` array along with `success` and `fail` callbacks. Call `success(rowData)` to load the parsed data into the grid, or `fail(message)` to display an error in the overlay using the `fileInputProcessingFailed` locale. + +```js +const gridOptions = { + autoGenerateColumnDefs: true, + processFileInput: (params) => { + const file = params.files[0]; + const reader = new FileReader(); + reader.onload = (e) => { + try { + const rowData = parseCsv(e.target.result); + params.success(rowData); + } catch { + params.fail('Failed to parse file'); + } + }; + reader.readAsText(file); + }, +}; +``` + +The example below auto-generates columns from various data sources. Files can be dragged onto the overlay, selected via the browse button, or loaded from the sample data dropdown. The toolbar **Upload File** button re-shows the overlay by setting `activeOverlay` to `'agFileInputOverlay'`. + +{% gridExampleRunner title="Auto-Generate Columns" name="file-drop-overlay" exampleHeight=500 /%} diff --git a/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/exampleConfig.json b/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/exampleConfig.json index f521b8bbf84..ffbeed4eefa 100644 --- a/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/exampleConfig.json +++ b/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/exampleConfig.json @@ -1,3 +1,3 @@ { - "extras": ["xlsx-style"] + "extras": ["xlsx"] } diff --git a/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/index.html b/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/index.html index ef1fce268cb..514751a14c0 100644 --- a/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/index.html +++ b/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/index.html @@ -1,4 +1,7 @@
- +
+ + +
diff --git a/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/main.ts b/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/main.ts index 7de9b8acebd..f687d7a910c 100644 --- a/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/main.ts +++ b/documentation/ag-grid-docs/src/content/docs/excel-import/_examples/excel-import/main.ts @@ -1,11 +1,18 @@ -import type { GridApi, GridOptions } from 'ag-grid-community'; -import { ClientSideRowModelModule, ModuleRegistry, ValidationModule, createGrid } from 'ag-grid-community'; +import type { GridApi, GridOptions, ProcessFileInputParams } from 'ag-grid-community'; +import { + AutoGenerateColumnsModule, + ClientSideRowModelModule, + ModuleRegistry, + ValidationModule, + createGrid, +} from 'ag-grid-community'; import { ColumnMenuModule, ContextMenuModule, ExcelExportModule } from 'ag-grid-enterprise'; declare let XLSX: any; ModuleRegistry.registerModules([ ClientSideRowModelModule, + AutoGenerateColumnsModule, ExcelExportModule, ColumnMenuModule, ContextMenuModule, @@ -15,99 +22,51 @@ ModuleRegistry.registerModules([ let gridApi: GridApi; const gridOptions: GridOptions = { - columnDefs: [ - { field: 'athlete', minWidth: 180 }, - { field: 'age' }, - { field: 'country', minWidth: 150 }, - { field: 'year' }, - { field: 'date', minWidth: 130 }, - { field: 'sport', minWidth: 100 }, - { field: 'gold' }, - { field: 'silver' }, - { field: 'bronze' }, - { field: 'total' }, - ], + autoGenerateColumnDefs: true, defaultColDef: { minWidth: 80, flex: 1, }, - rowData: [], + processFileInput: (params: ProcessFileInputParams) => { + const file = params.files[0]; + if (!file) return; + const reader = new FileReader(); + reader.onerror = () => params.fail('Failed to read file'); + reader.onload = (e) => { + try { + const workbook = XLSX.read(new Uint8Array(e.target?.result as ArrayBuffer)); + params.success(parseWorkbook(workbook)); + } catch { + params.fail('Failed to parse file'); + } + }; + reader.readAsArrayBuffer(file); + }, }; -// read the raw data and convert it to a XLSX workbook -function convertDataToWorkbook(dataRows: ArrayBuffer) { - /* convert data to binary string */ - const data = new Uint8Array(dataRows); - const arr = []; - - for (let i = 0; i !== data.length; ++i) { - arr[i] = String.fromCharCode(data[i]); - } - - const bstr = arr.join(''); - - return XLSX.read(bstr, { type: 'binary' }); -} - -// pull out the values we're after, converting it into an array of rowData - -function populateGrid(api: GridApi, workbook: any) { - // our data is in the first sheet +function parseWorkbook(workbook: any): Record[] { const firstSheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[firstSheetName]; + return XLSX.utils.sheet_to_json(worksheet); +} - // we expect the following columns to be present - const columns: Record = { - A: 'athlete', - B: 'age', - C: 'country', - D: 'year', - E: 'date', - F: 'sport', - G: 'gold', - H: 'silver', - I: 'bronze', - J: 'total', - }; - - const rowData = []; - - // start at the 2nd row - the first row are the headers - let rowIndex = 2; - - // iterate over the worksheet pulling out the columns we're expecting - while (worksheet['A' + rowIndex]) { - var row: any = {}; - Object.keys(columns).forEach((column) => { - row[columns[column]] = worksheet[column + rowIndex].w; - }); - - rowData.push(row); - - rowIndex++; - } - - // finally, set the imported rowData into the grid - api.setGridOption('rowData', rowData); +function uploadFile() { + const curr = gridApi.getGridOption('activeOverlay'); + gridApi.setGridOption('activeOverlay', curr === 'agFileInputOverlay' ? undefined : 'agFileInputOverlay'); } function importExcel() { fetch('https://www.ag-grid.com/example-assets/olympic-data.xlsx') .then((response) => response.arrayBuffer()) .then((data: ArrayBuffer) => { - const workbook = convertDataToWorkbook(data); - populateGrid(gridApi, workbook); + const workbook = XLSX.read(new Uint8Array(data)); + gridApi.updateGridOptions({ rowData: parseWorkbook(workbook), activeOverlay: undefined }); }); } -// wait for the document to be loaded, otherwise -// AG Grid will not find the div in the document. document.addEventListener('DOMContentLoaded', function () { - // lookup the container we want the Grid to use const eGridDiv = document.querySelector('#myGrid')!; - - // create the grid passing in the div to use together with the columns & data we want to use gridApi = createGrid(eGridDiv, gridOptions); }); diff --git a/documentation/ag-grid-docs/src/content/docs/excel-import/index.mdoc b/documentation/ag-grid-docs/src/content/docs/excel-import/index.mdoc index 4939a4726f8..9d169b5b162 100644 --- a/documentation/ag-grid-docs/src/content/docs/excel-import/index.mdoc +++ b/documentation/ag-grid-docs/src/content/docs/excel-import/index.mdoc @@ -2,13 +2,11 @@ title: "Excel Import" --- -Below we illustrate how you might import an Excel spreadsheet into AG Grid using a third-party library - in this example we're using [xlsx-style](https://github.com/protobi/js-xlsx). +Below we illustrate how you might import an Excel spreadsheet into AG Grid using a third-party library - in this example we're using [xlsx](https://www.jsdelivr.com/package/npm/xlsx). -In this example we're providing a simple Excel file for importing but in your application you could allow uploading of Excel files by end users. +[Auto-Generate Columns](./auto-generate-columns/) is used so no column definitions need to be provided upfront — columns are created from the imported data. The `processFileInput` callback parses dropped Excel files using the same library. -The spreadsheet contains a few rows of simple data, which the example parses and sets as row data. - -The spreadsheet can be downloaded [here](https://www.ag-grid.com/example-assets/olympic-data.xlsx). +Click **Load Sample Excel** to fetch a sample spreadsheet, or drag your own `.xlsx` file onto the grid. Click **Upload File** to re-show the file input overlay. The spreadsheet can also be downloaded [here](https://www.ag-grid.com/example-assets/olympic-data.xlsx). ## Example Import diff --git a/documentation/ag-grid-docs/src/content/docs/overlays-overview/index.mdoc b/documentation/ag-grid-docs/src/content/docs/overlays-overview/index.mdoc index 505dd8fe044..94d2dbb2117 100644 --- a/documentation/ag-grid-docs/src/content/docs/overlays-overview/index.mdoc +++ b/documentation/ag-grid-docs/src/content/docs/overlays-overview/index.mdoc @@ -17,6 +17,7 @@ The grid provides the following overlays that will be shown automatically based - [No Rows](./overlays-provided/#no-rows) - shown when there are no rows to display - [No Matching Rows](./overlays-provided/#no-matching-rows) - shown when no rows match the current filter - [Exporting](./overlays-provided/#exporting) - shown when data is exporting to CSV / Excel +- [File Input](./overlays-provided/#file-input) - shown when `processFileInput` is provided and no row data is present For details about the provided overlays and how to customise them see: [Provided Overlays](./overlays-provided). diff --git a/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/example.spec.ts b/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/example.spec.ts new file mode 100644 index 00000000000..b50305e3bbb --- /dev/null +++ b/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/example.spec.ts @@ -0,0 +1,10 @@ +import { expect } from '@playwright/test'; +import { ensureGridReady, test } from '@utils/grid/test-utils'; + +test.agExample(import.meta, () => { + test.eachFramework('shows file input overlay when no row data', async ({ page }) => { + await ensureGridReady(page); + await expect(page.locator('.ag-overlay-file-input-center')).toBeVisible(); + await expect(page.locator('.ag-file-input-drop-zone')).toBeVisible(); + }); +}); diff --git a/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/exampleConfig.json b/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/exampleConfig.json new file mode 100644 index 00000000000..ffbeed4eefa --- /dev/null +++ b/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/exampleConfig.json @@ -0,0 +1,3 @@ +{ + "extras": ["xlsx"] +} diff --git a/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/index.html b/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/index.html new file mode 100644 index 00000000000..411a9161bbd --- /dev/null +++ b/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/index.html @@ -0,0 +1 @@ +
diff --git a/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/main.ts b/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/main.ts new file mode 100644 index 00000000000..46ed4740fb5 --- /dev/null +++ b/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/main.ts @@ -0,0 +1,53 @@ +import type { GridOptions, ProcessFileInputParams } from 'ag-grid-community'; +import { + AutoGenerateColumnsModule, + ClientSideRowModelModule, + ModuleRegistry, + ValidationModule, + createGrid, +} from 'ag-grid-community'; + +declare let XLSX: any; + +ModuleRegistry.registerModules([ + ClientSideRowModelModule, + AutoGenerateColumnsModule, + ...(process.env.NODE_ENV !== 'production' ? [ValidationModule] : []), +]); + +function parseWorkbook(workbook: any): Record[] { + const firstSheetName = workbook.SheetNames[0]; + const worksheet = workbook.Sheets[firstSheetName]; + return XLSX.utils.sheet_to_json(worksheet); +} + +function processFileInput(params: ProcessFileInputParams): void { + const file = params.files[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onerror = () => params.fail('Failed to read file'); + reader.onload = (e) => { + try { + const workbook = XLSX.read(new Uint8Array(e.target?.result as ArrayBuffer)); + params.success(parseWorkbook(workbook)); + } catch { + params.fail('Failed to parse file'); + } + }; + reader.readAsArrayBuffer(file); +} + +const gridOptions: GridOptions = { + autoGenerateColumnDefs: true, + processFileInput, + defaultColDef: { + flex: 1, + minWidth: 100, + }, +}; + +document.addEventListener('DOMContentLoaded', () => { + const gridDiv = document.querySelector('#myGrid')!; + createGrid(gridDiv, gridOptions); +}); diff --git a/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/styles.css b/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/styles.css new file mode 100644 index 00000000000..97daf67ef66 --- /dev/null +++ b/documentation/ag-grid-docs/src/content/docs/overlays-provided/_examples/file-input-overlay/styles.css @@ -0,0 +1,4 @@ +#myGrid { + height: 100%; + width: 100%; +} diff --git a/documentation/ag-grid-docs/src/content/docs/overlays-provided/index.mdoc b/documentation/ag-grid-docs/src/content/docs/overlays-provided/index.mdoc index 7a3483218ed..ba347f0ee61 100644 --- a/documentation/ag-grid-docs/src/content/docs/overlays-provided/index.mdoc +++ b/documentation/ag-grid-docs/src/content/docs/overlays-provided/index.mdoc @@ -4,7 +4,7 @@ title: "Provided Overlays" The grid shows built-in overlays when data is loading or being exported and when there is no data or no rows match the current filter. -The following example demonstrates all the provided overlays. +The following example demonstrates most of the provided overlays. - Toggle the loading state to show/hide the loading overlay. - Note that the loading overlay takes precedence over the other provided overlays if they are shown at the same time. @@ -32,6 +32,34 @@ The no-matching-rows overlay is displayed when the grid has rows but none of the The exporting overlay is displayed when data is being exported from the grid to CSV or Excel. +## File Input + +When `processFileInput` is provided and `rowData` is not set, the grid shows a built-in file input overlay. Users can drag a file onto the overlay or click the browse button to select one. + +Provide a `processFileInput` callback. The `params` object contains the selected `files` array along with `success` and `fail` callbacks. Call `success(rowData)` to load the parsed data, or `fail(message)` to display an error in the overlay. + +```{% frameworkTransform=true %} +const gridOptions = { + processFileInput: ({ files, success, fail }) => { + const file = files[0]; + const reader = new FileReader(); + reader.onload = (e) => { + try { + const rowData = parseFile(e) + success(rowData); + } catch { + fail('Failed to parse file'); + } + }; + reader.readAsArrayBuffer(file); + }, +}; +``` + +The example below shows the file input overlay, using [Auto-Generate Columns](./auto-generate-columns) to create the column definitions from the loaded file. Drag a file onto the overlay or use the browse button to load it. + +{% gridExampleRunner title="File Input Overlay" name="file-input-overlay" exampleHeight=400 /%} + ## Customisation The provided overlays can be customised to change their content or completely replaced with custom components. The grid still manages the timing of when the overlays are displayed based on grid state. @@ -49,6 +77,7 @@ const gridOptions = { noRows: { overlayText: 'This grid has no data!' }, noMatchingRows: { overlayText: 'Current Filter Matches No Rows' }, exporting: { overlayText: 'Exporting your data...' }, + fileInput: { overlayText: 'Provide a file...' }, } }; ``` diff --git a/documentation/ag-grid-docs/src/content/module-mappings/modules.json b/documentation/ag-grid-docs/src/content/module-mappings/modules.json index 1879fc4d21e..f11788320df 100644 --- a/documentation/ag-grid-docs/src/content/module-mappings/modules.json +++ b/documentation/ag-grid-docs/src/content/module-mappings/modules.json @@ -28,6 +28,11 @@ "name": "Auto-Generate Columns", "path": "auto-generate-columns" }, + { + "moduleName": "FileInputOverlayModule", + "name": "File Input Overlay", + "path": "auto-generate-columns/#file-drop-overlay" + }, { "moduleName": "CalculatedColumnsModule", "name": "Calculated Columns", diff --git a/documentation/ag-grid-docs/src/utils/htaccess/htaccessRules.test.ts b/documentation/ag-grid-docs/src/utils/htaccess/htaccessRules.test.ts new file mode 100644 index 00000000000..45dc4aff2dd --- /dev/null +++ b/documentation/ag-grid-docs/src/utils/htaccess/htaccessRules.test.ts @@ -0,0 +1,209 @@ +import { getHtaccessContent } from './htaccessRules'; +import { SITE_301_REDIRECTS } from './redirects'; + +describe('htaccessRules', () => { + let productionContent: string; + let stagingContent: string; + + beforeAll(() => { + productionContent = getHtaccessContent({ env: 'production' }); + stagingContent = getHtaccessContent({ env: 'staging' }); + }); + + describe('AG-17159 / AG-17158: non-www to www redirect', () => { + it('should redirect ag-grid.com to www.ag-grid.com', () => { + expect(productionContent).toContain('RewriteCond %{HTTP_HOST} ^ag-grid\\.com$ [NC]'); + expect(productionContent).toContain('RewriteRule ^(.*)$ https://www.ag-grid.com/$1 [R=301,L]'); + }); + + it('should preserve the full path in the redirect', () => { + const match = productionContent.match( + /RewriteCond %\{HTTP_HOST\} \^ag-grid\\\.com\$ \[NC\]\s*\n\s*RewriteRule \^\(\.\*\)\$ https:\/\/www\.ag-grid\.com\/\$1/ + ); + expect(match).not.toBeNull(); + }); + + it('should not redirect www.ag-grid.com (only bare domain)', () => { + const nonWwwCond = productionContent.match(/RewriteCond %\{HTTP_HOST\} \^ag-grid\\\.com\$/); + expect(nonWwwCond).not.toBeNull(); + }); + }); + + describe('AG-17136 / SE-26: Phase 1 subdomain 301 redirects', () => { + const phase1Subdomains = [ + 'angulargrid.ag-grid.com', + 'angular-grid.ag-grid.com', + 'javascript-grid.ag-grid.com', + 'react-grid.ag-grid.com', + ]; + + for (const subdomain of phase1Subdomains) { + it(`should redirect ${subdomain} to www.ag-grid.com`, () => { + const escapedInHtaccess = subdomain.replace(/\./g, '\\.'); + expect(productionContent).toContain(escapedInHtaccess); + expect(productionContent).toContain('https://www.ag-grid.com/$1 [R=301,L]'); + }); + + it(`should redirect all paths for ${subdomain} (not just root)`, () => { + const lines = productionContent.split('\n'); + const escapedInHtaccess = subdomain.replace(/\./g, '\\.'); + const condIndex = lines.findIndex((l) => l.includes(escapedInHtaccess)); + expect(condIndex).toBeGreaterThan(-1); + const ruleLineIndex = condIndex + 1; + expect(lines[ruleLineIndex]).toContain('^(.*)$'); + }); + } + }); + + describe('AG-17133: Security headers', () => { + it('should include Referrer-Policy header', () => { + expect(productionContent).toContain('Referrer-Policy'); + expect(productionContent).toContain('strict-origin-when-cross-origin'); + }); + + it('should include Permissions-Policy header', () => { + expect(productionContent).toContain('Permissions-Policy'); + expect(productionContent).toContain('geolocation=(), microphone=(), camera=()'); + }); + + it('should NOT include X-Frame-Options header directive (replaced by CSP frame-ancestors)', () => { + expect(productionContent).not.toMatch(/Header\s+.*set\s+X-Frame-Options/); + }); + }); + + describe('AG-17152: /charts/ framework overview redirects', () => { + const chartsFrameworkRedirects = [ + { from: '^/javascript-charts', to: 'charts/javascript/quick-start/' }, + { from: '^/angular-charts', to: 'charts/angular/quick-start/' }, + { from: '^/react-charts', to: 'charts/react/quick-start/' }, + { from: '^/vue-charts', to: 'charts/vue/quick-start/' }, + ]; + + for (const { from, to } of chartsFrameworkRedirects) { + it(`should have a server-side 301 for ${from} -> ${to}`, () => { + const matchingRedirect = SITE_301_REDIRECTS.find( + (r) => 'fromPattern' in r && (r as any).fromPattern.includes(from.replace('^', '')) + ); + expect(matchingRedirect).toBeDefined(); + expect((matchingRedirect as any).to).toContain(to); + }); + } + + const docChartsRedirects = [ + { from: '^/documentation/javascript/charts', to: 'charts/javascript/quick-start/' }, + { from: '^/documentation/angular/charts', to: 'charts/angular/quick-start/' }, + { from: '^/documentation/react/charts', to: 'charts/react/quick-start/' }, + { from: '^/documentation/vue/charts', to: 'charts/vue/quick-start/' }, + ]; + + for (const { from, to } of docChartsRedirects) { + it(`should have a server-side 301 for ${from} -> ${to}`, () => { + const matchingRedirect = SITE_301_REDIRECTS.find( + (r) => 'fromPattern' in r && (r as any).fromPattern.includes(from.replace('^', '')) + ); + expect(matchingRedirect).toBeDefined(); + expect((matchingRedirect as any).to).toContain(to); + }); + } + + it('should render charts redirects as RedirectMatch 301 in the generated htaccess', () => { + expect(productionContent).toContain('RedirectMatch 301'); + expect(productionContent).toContain('javascript-charts'); + }); + }); + + describe('AG-17157: noindex for archive paths', () => { + it('should have redirect rules for /archive paths', () => { + const archiveRedirects = SITE_301_REDIRECTS.filter( + (r) => 'fromPattern' in r && (r as any).fromPattern.includes('archive') + ); + expect(archiveRedirects.length).toBeGreaterThan(0); + }); + }); + + describe('htaccess quality: redundant directives', () => { + it('should have only one RewriteEngine On directive', () => { + const matches = productionContent.match(/RewriteEngine On/g); + expect(matches).not.toBeNull(); + expect(matches!.length).toBe(1); + }); + }); + + describe('htaccess quality: HTTPS redirect scoping', () => { + it('should scope the HTTPS redirect to www/bare domain only', () => { + const lines = productionContent.split('\n'); + const httpsRuleIndex = lines.findIndex((l) => l.includes('RewriteCond %{SERVER_PORT} 80')); + expect(httpsRuleIndex).toBeGreaterThan(-1); + const hostCondIndex = lines.findIndex( + (l, i) => + i >= httpsRuleIndex - 3 && + i <= httpsRuleIndex + 3 && + l.includes('HTTP_HOST') && + (l.includes('ag-grid') || l.includes('www')) + ); + expect(hostCondIndex).toBeGreaterThan(-1); + }); + }); + + describe('htaccess quality: angulargrid.com redirect', () => { + it('should use HTTPS for angulargrid.com redirect', () => { + const lines = productionContent.split('\n'); + const angulargridCondIndex = lines.findIndex( + (l) => l.includes('angulargrid\\.com') && !l.includes('.ag-grid.com') + ); + expect(angulargridCondIndex).toBeGreaterThan(-1); + const nextRuleLine = lines.slice(angulargridCondIndex).find((l) => l.includes('RewriteRule')); + expect(nextRuleLine).toBeDefined(); + expect(nextRuleLine).toContain('https://www.ag-grid.com'); + expect(nextRuleLine).not.toContain('http\\:'); + }); + + it('should redirect all paths for angulargrid.com (not just root)', () => { + const lines = productionContent.split('\n'); + const angulargridCondIndex = lines.findIndex( + (l) => l.includes('angulargrid\\.com') && !l.includes('.ag-grid.com') + ); + expect(angulargridCondIndex).toBeGreaterThan(-1); + const nextRuleLine = lines.slice(angulargridCondIndex).find((l) => l.includes('RewriteRule')); + expect(nextRuleLine).toBeDefined(); + expect(nextRuleLine).toContain('^(.*)$'); + }); + }); + + describe('production vs staging', () => { + it('should include mod_rewrite rules in production only', () => { + expect(productionContent).toContain('mod_rewrite.c'); + expect(stagingContent).not.toContain('mod_rewrite.c'); + }); + + it('should include mod_expires rules in production only', () => { + expect(productionContent).toContain('mod_expires.c'); + expect(stagingContent).not.toContain('mod_expires.c'); + }); + + it('should include CORS headers in production only', () => { + expect(productionContent).toContain('Access-Control-Allow-Origin'); + expect(stagingContent).not.toContain('Access-Control-Allow-Origin'); + }); + + it('should include CSP in both environments', () => { + expect(productionContent).toContain('Content-Security-Policy'); + expect(stagingContent).toContain('Content-Security-Policy'); + }); + }); + + describe('basic structure', () => { + it('should include the autogenerated header', () => { + expect(productionContent).toContain('### AUTOGENERATED DO NOT EDIT'); + }); + + it('should include a 404 error document', () => { + expect(productionContent).toContain('ErrorDocument 404 /404.html'); + }); + + it('should include MIME types for example files', () => { + expect(productionContent).toContain('AddType text/javascript jsx'); + expect(productionContent).toContain('AddType application/typescript ts tsx'); + }); + }); +}); diff --git a/documentation/ag-grid-docs/src/utils/htaccess/htaccessRules.ts b/documentation/ag-grid-docs/src/utils/htaccess/htaccessRules.ts index d14da9ba640..e46c3e04e47 100644 --- a/documentation/ag-grid-docs/src/utils/htaccess/htaccessRules.ts +++ b/documentation/ag-grid-docs/src/utils/htaccess/htaccessRules.ts @@ -1,6 +1,6 @@ import { urlWithBaseUrl } from '../urlWithBaseUrl'; import type { CspEnv } from './cspRules'; -import { getCspHtaccessBlock, getCspHtaccessLine } from './cspRules'; +import { getCspHtaccessBlock } from './cspRules'; import { SITE_301_REDIRECTS } from './redirects'; export type HtaccessEnv = Extract; @@ -67,8 +67,9 @@ const getModRewriteRules = (): string => ` RewriteEngine On - # Always use https for secure connections - # (as it appears on your SSL certificate) + # Always use https for secure connections (scoped to www/bare domain only + # so that charts.ag-grid.com and studio.ag-grid.com are not affected) + RewriteCond %{HTTP_HOST} ^(www\\.)?ag-grid\\.com$ [NC] RewriteCond %{SERVER_PORT} 80 RewriteCond %{REQUEST_URI} !^/\\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ RewriteCond %{REQUEST_URI} !^/\\.well-known/cpanel-dcv/[0-9a-zA-Z_-]+$ @@ -79,24 +80,21 @@ const getModRewriteRules = (): string => ` # Redirect non-www to www RewriteCond %{HTTP_HOST} ^ag-grid\\.com$ [NC] RewriteRule ^(.*)$ https://www.ag-grid.com/$1 [R=301,L] - - RewriteEngine On + + # Redirect legacy Phase 1 subdomains to www RewriteCond %{HTTP_HOST} ^angulargrid\\.ag-grid\\.com$ [NC] RewriteRule ^(.*)$ https://www.ag-grid.com/$1 [R=301,L] - RewriteEngine On RewriteCond %{HTTP_HOST} ^angular-grid\\.ag-grid\\.com$ [NC] RewriteRule ^(.*)$ https://www.ag-grid.com/$1 [R=301,L] - RewriteEngine On RewriteCond %{HTTP_HOST} ^javascript-grid\\.ag-grid\\.com$ [NC] RewriteRule ^(.*)$ https://www.ag-grid.com/$1 [R=301,L] - RewriteEngine On RewriteCond %{HTTP_HOST} ^react-grid\\.ag-grid\\.com$ [NC] RewriteRule ^(.*)$ https://www.ag-grid.com/$1 [R=301,L] - - # Redirect angulargrid.com to ag-grid.com + + # Redirect angulargrid.com to www.ag-grid.com RewriteCond %{HTTP_HOST} ^angulargrid\\.com$ [OR] RewriteCond %{HTTP_HOST} ^www\\.angulargrid\\.com$ - RewriteRule ^/?$ "http\\:\\/\\/www\\.ag\\-grid\\.com" [R=301,L] + RewriteRule ^(.*)$ https://www.ag-grid.com/$1 [R=301,L] # Remove "index.php" from URLs RewriteCond %{REQUEST_URI} !^/\\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ @@ -156,8 +154,7 @@ function getStagingHtaccessContent(): string { return `${baseRules} # Content-Security-Policy — enforced. Unsets the legacy wildcard CSP on the staging -# vhost so this tightened policy is the only one in effect. Production stays -# report-only on latest until the release enforce rollout is verified. +# vhost so this tightened policy is the only one in effect. ${getCspHtaccessBlock({ env: 'staging' }, 'enforce')} Options -Indexes @@ -176,11 +173,12 @@ ${getModRewriteRules()} Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()" -# Content-Security-Policy — report-only while validating the tightened policy on production. -# Ships alongside the existing loose enforcing CSP on the vhost: that one still allows -# everything (nothing breaks), this one reports what the tightened policy would block. -# Flip to enforce + remove the vhost wildcard once the report-only window is clean. -${getCspHtaccessLine({ env: 'production' }, 'report-only')} +# Content-Security-Policy — enforced (the report-only validation window is complete). +# The block unsets the inherited headers (incl. the legacy wildcard CSP on the vhost) +# and sets this tightened policy as the enforced CSP. If the vhost wildcard lingers as a +# separate header, browsers enforce the intersection, so the tightened policy still wins; +# removing the vhost wildcard line is a follow-up infra cleanup. +${getCspHtaccessBlock({ env: 'production' }, 'enforce')} # CORS settings Header add Access-Control-Allow-Origin "*" diff --git a/documentation/update-algolia-indices/package.json b/documentation/update-algolia-indices/package.json index 343f883f268..298369af14e 100644 --- a/documentation/update-algolia-indices/package.json +++ b/documentation/update-algolia-indices/package.json @@ -1,6 +1,6 @@ { "name": "update-algolia-indices", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "Update algolia indices", "main": "src/index.ts", "type": "module", diff --git a/package.json b/package.json index bba6eacbeef..7be8ac36448 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "license": "MIT", "scripts": { "compressVideo": "tsx external/ag-website-shared/scripts/compress-video", diff --git a/packages/ag-grid-angular/package.json b/packages/ag-grid-angular/package.json index a56666229d3..9f8fb53f88b 100644 --- a/packages/ag-grid-angular/package.json +++ b/packages/ag-grid-angular/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-angular", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "AG Grid Angular Component", "scripts": { "clean": "rimraf dist", @@ -15,7 +15,7 @@ "module": "./dist/ag-grid-angular/fesm2022/ag-grid-angular.mjs", "typings": "./dist/ag-grid-angular/index.d.ts", "dependencies": { - "ag-grid-community": "35.3.0-beta.20260609.1239", + "ag-grid-community": "35.3.0-beta.20260610.1146", "@angular/animations": "^20.0.0", "@angular/common": "^20.0.0", "@angular/compiler": "^20.0.0", @@ -27,7 +27,7 @@ "zone.js": "~0.15.1" }, "devDependencies": { - "ag-grid-community": "35.3.0-beta.20260609.1239", + "ag-grid-community": "35.3.0-beta.20260610.1146", "@angular/build": "^20.0.0", "@angular/cli": "^20.0.0", "@angular/forms": "^20.0.0", diff --git a/packages/ag-grid-angular/projects/ag-grid-angular/package.json b/packages/ag-grid-angular/projects/ag-grid-angular/package.json index 6c6cb41baa8..0d8e69c8d48 100644 --- a/packages/ag-grid-angular/projects/ag-grid-angular/package.json +++ b/packages/ag-grid-angular/projects/ag-grid-angular/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-angular", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "AG Grid Angular Component", "license": "MIT", "peerDependencies": { @@ -8,7 +8,7 @@ "@angular/core": ">= 20.0.0" }, "dependencies": { - "ag-grid-community": "35.3.0-beta.20260609.1239", + "ag-grid-community": "35.3.0-beta.20260610.1146", "tslib": "^2.8.1" }, "repository": { diff --git a/packages/ag-grid-angular/projects/ag-grid-angular/src/lib/ag-grid-angular.component.ts b/packages/ag-grid-angular/projects/ag-grid-angular/src/lib/ag-grid-angular.component.ts index 09ffe72b364..868a0fceba6 100644 --- a/packages/ag-grid-angular/projects/ag-grid-angular/src/lib/ag-grid-angular.component.ts +++ b/packages/ag-grid-angular/projects/ag-grid-angular/src/lib/ag-grid-angular.component.ts @@ -183,6 +183,7 @@ import type { ProcessCellForClipboard, ProcessCellFromClipboard, ProcessDataFromClipboard, + ProcessFileInputParams, ProcessGroupHeaderForClipboard, ProcessHeaderForClipboard, ProcessPivotResultColDef, @@ -1076,7 +1077,7 @@ export class AgGridAngular = ColDef = ColDef) => void) | undefined = undefined; /** Set whether pagination is enabled. * @default false * @agModule `PaginationModule` diff --git a/packages/ag-grid-community/package.json b/packages/ag-grid-community/package.json index e6ef3b8b2f8..56a14888768 100644 --- a/packages/ag-grid-community/package.json +++ b/packages/ag-grid-community/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-community", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue", "main": "./dist/package/main.cjs.js", "types": "./dist/types/src/main.d.ts", @@ -119,8 +119,8 @@ ], "homepage": "https://www.ag-grid.com/", "dependencies": { - "ag-stack": "35.3.0-beta.20260609.1239", - "ag-charts-types": "13.3.0-beta.20260609" + "ag-stack": "35.3.0-beta.20260610.1146", + "ag-charts-types": "13.3.0-beta.20260610" }, "devDependencies": { "web-streams-polyfill": "^4.2.0", diff --git a/packages/ag-grid-community/src/autoGenerateColumns/autoGenerateColumnsModule.ts b/packages/ag-grid-community/src/autoGenerateColumns/autoGenerateColumnsModule.ts index b4342882766..0212bfa0394 100644 --- a/packages/ag-grid-community/src/autoGenerateColumns/autoGenerateColumnsModule.ts +++ b/packages/ag-grid-community/src/autoGenerateColumns/autoGenerateColumnsModule.ts @@ -1,4 +1,5 @@ import type { _ModuleWithoutApi } from '../interfaces/iModule'; +import { FileInputOverlayModule } from '../rendering/overlays/fileInputOverlayModule'; import { VERSION } from '../version'; import { AutoGenerateColumnsService } from './autoGenerateColumnsService'; @@ -10,4 +11,5 @@ export const AutoGenerateColumnsModule: _ModuleWithoutApi = { moduleName: 'AutoGenerateColumns', version: VERSION, beans: [AutoGenerateColumnsService], + dependsOn: [FileInputOverlayModule], }; diff --git a/packages/ag-grid-community/src/context/context.ts b/packages/ag-grid-community/src/context/context.ts index 5e480bf3a18..3ee1f0c7ed1 100644 --- a/packages/ag-grid-community/src/context/context.ts +++ b/packages/ag-grid-community/src/context/context.ts @@ -206,6 +206,7 @@ export type UserComponentName = | 'agExportingOverlay' | 'agNoRowsOverlay' | 'agNoMatchingRowsOverlay' + | 'agFileInputOverlay' | 'agTooltipComponent' | 'agReadOnlyFloatingFilter' | 'agTextColumnFilter' diff --git a/packages/ag-grid-community/src/edit/editService.ts b/packages/ag-grid-community/src/edit/editService.ts index 029f0f5525c..b2c19ab37af 100644 --- a/packages/ag-grid-community/src/edit/editService.ts +++ b/packages/ag-grid-community/src/edit/editService.ts @@ -925,6 +925,11 @@ export class EditService extends BeanStub implements NamedBean { return 'continue'; } + /** Calls through to standalone method for treeshaking via the editService */ + public populateModelValidationErrors() { + _populateModelValidationErrors(this.beans); + } + public revertSingleCellEdit(cellPosition: Required, focus = false): void { const cellCtrl = _getCellCtrl(this.beans, cellPosition); if (!cellCtrl?.comp?.getCellEditor()) { diff --git a/packages/ag-grid-community/src/edit/strategy/fullRowEditStrategy.ts b/packages/ag-grid-community/src/edit/strategy/fullRowEditStrategy.ts index d1c64ff591c..9c5081c035d 100644 --- a/packages/ag-grid-community/src/edit/strategy/fullRowEditStrategy.ts +++ b/packages/ag-grid-community/src/edit/strategy/fullRowEditStrategy.ts @@ -6,12 +6,7 @@ import type { EditPosition, EditRowPosition, StartEditWithPositionParams } from import type { IRowNode } from '../../interfaces/iRowNode'; import type { CellCtrl } from '../../rendering/cell/cellCtrl'; import { _getCellCtrl, _getRowCtrl } from '../utils/controllers'; -import { - _destroyEditor, - _populateModelValidationErrors, - _setupEditor, - _sourceAndPendingDiffer, -} from '../utils/editors'; +import { _destroyEditor, _setupEditor, _sourceAndPendingDiffer } from '../utils/editors'; import type { EditValidationAction, EditValidationResult } from './baseEditStrategy'; import { BaseEditStrategy } from './baseEditStrategy'; @@ -140,7 +135,7 @@ export class FullRowEditStrategy extends BaseEditStrategy { } public override stopCommitted(event: Event | null, commit: boolean): boolean { - const { rowNode, beans, model, editSvc } = this; + const { rowNode, model, editSvc } = this; if (rowNode && !model.hasEdits()) { return false; } @@ -159,7 +154,7 @@ export class FullRowEditStrategy extends BaseEditStrategy { } }); - _populateModelValidationErrors(beans); + editSvc.populateModelValidationErrors(); if (editSvc.checkNavWithValidation({ rowNode }) === 'block-stop') { return false; } diff --git a/packages/ag-grid-community/src/edit/strategy/strategyUtils.ts b/packages/ag-grid-community/src/edit/strategy/strategyUtils.ts index 33b15114a37..553de18f949 100644 --- a/packages/ag-grid-community/src/edit/strategy/strategyUtils.ts +++ b/packages/ag-grid-community/src/edit/strategy/strategyUtils.ts @@ -1,6 +1,5 @@ import { KeyCode } from 'ag-stack'; -import { _hasCalculatedExpression } from '../../columns/calculatedColumnUtils'; import type { BeanCollection } from '../../context/context'; import type { AgColumn } from '../../entities/agColumn'; import type { ColDef } from '../../entities/colDef'; @@ -77,7 +76,7 @@ export function isCellEditable(beans: BeanCollection, editPosition: Required { suppressNoRowsOverlay?: boolean; /** - * List of provided overlay names to suppress. One of `loading`, `noRows`, `noMatchingRows`, `exporting`. + * List of provided overlay names to suppress. One of `loading`, `noRows`, `noMatchingRows`, `exporting`, `fileInput`. */ suppressOverlays?: OverlayType[]; @@ -1085,6 +1086,15 @@ export interface GridOptions { */ activeOverlayParams?: any; + // *** File Input *** // + /** + * Callback to handle files received via the file input overlay (drag-and-drop or file browser). + * When provided, the file input overlay is shown when there is no row data. + * Call `params.success(rowData)` to load parsed data into the grid, or `params.fail(message)` to show an error. + * @agModule `FileInputOverlayModule` + */ + processFileInput?: (params: ProcessFileInputParams) => void; + // *** Pagination *** // /** * Set whether pagination is enabled. diff --git a/packages/ag-grid-community/src/interfaces/iFileProcessor.ts b/packages/ag-grid-community/src/interfaces/iFileProcessor.ts new file mode 100644 index 00000000000..86aeb28aba4 --- /dev/null +++ b/packages/ag-grid-community/src/interfaces/iFileProcessor.ts @@ -0,0 +1,10 @@ +import type { AgGridCommon } from './iCommon'; + +export interface ProcessFileInputParams extends AgGridCommon { + /** The files received via drag-and-drop or file browser on the File Input Overlay. */ + files: File[]; + /** Call with parsed row data to load it into the grid. */ + success(rowData: TData[]): void; + /** Call to show the error state in the overlay. Optionally provide a custom `errorMessage` to be displayed in the File Input Overlay. */ + fail(errorMessage?: string): void; +} diff --git a/packages/ag-grid-community/src/interfaces/iModule.ts b/packages/ag-grid-community/src/interfaces/iModule.ts index 6fbe57972f3..b53210afe05 100644 --- a/packages/ag-grid-community/src/interfaces/iModule.ts +++ b/packages/ag-grid-community/src/interfaces/iModule.ts @@ -155,6 +155,7 @@ export type CommunityModuleName = | 'DragAndDrop' | 'EventApi' | 'ExternalFilter' + | 'FileInputOverlay' | 'GridState' | 'HighlightChanges' | 'InfiniteRowModel' @@ -244,6 +245,7 @@ export type AgModuleName = | 'DragAndDropModule' | 'EventApiModule' | 'ExternalFilterModule' + | 'FileInputOverlayModule' | 'GridStateModule' | 'RowGroupingEditModule' | 'HighlightChangesModule' diff --git a/packages/ag-grid-community/src/main-internal.ts b/packages/ag-grid-community/src/main-internal.ts index 394c45e5796..cce64fbce03 100644 --- a/packages/ag-grid-community/src/main-internal.ts +++ b/packages/ag-grid-community/src/main-internal.ts @@ -38,7 +38,7 @@ export { _csrmFirstLeaf, _csrmReorderAllLeafs } from './clientSideRowModel/clien export { _dispatchColumnChangedEvent, dispatchColumnVisibleEvent } from './columns/columnEventUtils'; export { _buildColumnTree } from './columns/buildColumnTree'; export { _addColumnDefaultAndTypes, _createUserColumn } from './columns/colDefUtils'; -export { _hasCalculatedExpression, _normaliseCalculatedExpression } from './columns/calculatedColumnUtils'; +export { _normaliseCalculatedExpression } from './columns/calculatedColumnUtils'; export { BaseSingleColService as _BaseSingleColService } from './columns/baseSingleColService'; export type { ColumnModel } from './columns/columnModel'; export type { ColumnNameService } from './columns/columnNameService'; diff --git a/packages/ag-grid-community/src/main.ts b/packages/ag-grid-community/src/main.ts index e8b76a1d06b..ec39e0e1c6f 100644 --- a/packages/ag-grid-community/src/main.ts +++ b/packages/ag-grid-community/src/main.ts @@ -461,8 +461,12 @@ export type { IToolPanelParams, } from './interfaces/iToolPanel'; +// File Processor +export type { ProcessFileInputParams } from './interfaces/iFileProcessor'; + // Overlays export type { IExportingOverlay, IExportingOverlayComp } from './rendering/overlays/exportingOverlayComponent'; +export type { IFileInputOverlay, IFileInputOverlayComp } from './rendering/overlays/fileInputOverlayComponent'; export type { ILoadingOverlay, ILoadingOverlayComp } from './rendering/overlays/loadingOverlayComponent'; export type { INoMatchingRowsOverlay, @@ -471,7 +475,9 @@ export type { export type { INoRowsOverlay, INoRowsOverlayComp } from './rendering/overlays/noRowsOverlayComponent'; export type { ExportingOverlayUserParams, + FileInputOverlayUserParams, IExportingOverlayParams, + IFileInputOverlayParams, ILoadingOverlayParams, INoMatchingRowsOverlayParams, INoRowsOverlayParams, @@ -992,6 +998,7 @@ export type { export { AlignedGridsModule } from './alignedGrids/alignedGridsModule'; export { AllCommunityModule } from './allCommunityModule'; export { AutoGenerateColumnsModule } from './autoGenerateColumns/autoGenerateColumnsModule'; +export { FileInputOverlayModule } from './rendering/overlays/fileInputOverlayModule'; export { forEachColDef } from './columns/columnUtils'; export { RowApiModule, ScrollApiModule } from './api/apiModule'; export { ClientSideRowModelApiModule, ClientSideRowModelModule } from './clientSideRowModel/clientSideRowModelModule'; diff --git a/packages/ag-grid-community/src/pagination/paginationComp.css b/packages/ag-grid-community/src/pagination/paginationComp.css index 684e108b538..ec96ec59d51 100644 --- a/packages/ag-grid-community/src/pagination/paginationComp.css +++ b/packages/ag-grid-community/src/pagination/paginationComp.css @@ -54,3 +54,20 @@ /* avoids misalignment of buttons and text */ line-height: 0; } + +.ag-paging-row-summary-panel { + display: inline-grid; +} + +.ag-paging-row-summary-panel::before { + content: var(--ag-internal-pagination-width-string); + grid-area: 1/1; + visibility: hidden; + font-weight: 500; + font-variant-numeric: tabular-nums; +} + +.ag-paging-row-summary-content { + grid-area: 1/1; + justify-self: center; +} diff --git a/packages/ag-grid-community/src/pagination/rowSummaryComp.ts b/packages/ag-grid-community/src/pagination/rowSummaryComp.ts index b213d590e64..41d82ef1d23 100644 --- a/packages/ag-grid-community/src/pagination/rowSummaryComp.ts +++ b/packages/ag-grid-community/src/pagination/rowSummaryComp.ts @@ -35,23 +35,29 @@ export class RowSummaryComp extends Component { children: [ { tag: 'span', - ref: 'lbFirstRowOnPage', - cls: 'ag-paging-row-summary-panel-number', - attrs: { id: `${idPrefix}-first-row` }, - }, - { tag: 'span', attrs: { id: `${idPrefix}-to` }, children: localeTextFunc('to', 'to') }, - { - tag: 'span', - ref: 'lbLastRowOnPage', - cls: 'ag-paging-row-summary-panel-number', - attrs: { id: `${idPrefix}-last-row` }, - }, - { tag: 'span', attrs: { id: `${idPrefix}-of` }, children: localeTextFunc('of', 'of') }, - { - tag: 'span', - ref: 'lbRecordCount', - cls: 'ag-paging-row-summary-panel-number', - attrs: { id: `${idPrefix}-row-count` }, + cls: 'ag-paging-row-summary-content', + children: [ + { + tag: 'span', + ref: 'lbFirstRowOnPage', + cls: 'ag-paging-row-summary-panel-number', + attrs: { id: `${idPrefix}-first-row` }, + }, + { tag: 'span', attrs: { id: `${idPrefix}-to` }, children: localeTextFunc('to', 'to') }, + { + tag: 'span', + ref: 'lbLastRowOnPage', + cls: 'ag-paging-row-summary-panel-number', + attrs: { id: `${idPrefix}-last-row` }, + }, + { tag: 'span', attrs: { id: `${idPrefix}-of` }, children: localeTextFunc('of', 'of') }, + { + tag: 'span', + ref: 'lbRecordCount', + cls: 'ag-paging-row-summary-panel-number', + attrs: { id: `${idPrefix}-row-count` }, + }, + ], }, ], }); @@ -116,5 +122,11 @@ export class RowSummaryComp extends Component { const strTo = localeTextFunc('to', 'to'); const strOf = localeTextFunc('of', 'of'); this.ariaStatus = `${lbFirstRowOnPage} ${strTo} ${lbLastRowOnPage} ${strOf} ${lbRecordCount}`; + + const esc = (s: string) => s.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\s+/g, ' '); + this.getGui().style.setProperty( + '--ag-internal-pagination-width-string', + `'${lbRecordCount} ${esc(strTo)} ${lbRecordCount} ${esc(strOf)} ${lbRecordCount}'`.replaceAll(/\d/g, '0') + ); } } diff --git a/packages/ag-grid-community/src/propertyKeys.ts b/packages/ag-grid-community/src/propertyKeys.ts index edb21fe1766..921f5a961cd 100644 --- a/packages/ag-grid-community/src/propertyKeys.ts +++ b/packages/ag-grid-community/src/propertyKeys.ts @@ -350,6 +350,7 @@ export const _FUNCTION_GRID_OPTIONS: (CallbackKeys | FunctionKeys)[] = [ 'doesExternalFilterPass', 'processPivotResultColDef', 'processPivotResultColGroupDef', + 'processFileInput', 'getBusinessKeyForNode', 'isRowSelectable', 'rowDragText', diff --git a/packages/ag-grid-community/src/rendering/cell/cellCtrl.ts b/packages/ag-grid-community/src/rendering/cell/cellCtrl.ts index a80f8966089..e7c136754dd 100644 --- a/packages/ag-grid-community/src/rendering/cell/cellCtrl.ts +++ b/packages/ag-grid-community/src/rendering/cell/cellCtrl.ts @@ -16,7 +16,6 @@ import { BeanStub } from '../../context/beanStub'; import type { BeanCollection } from '../../context/context'; import type { RowDragComp } from '../../dragAndDrop/rowDragComp'; import type { EditService } from '../../edit/editService'; -import { _populateModelValidationErrors } from '../../edit/utils/editors'; import type { AgColumn } from '../../entities/agColumn'; import type { CellStyle, CheckboxSelectionCallback, ColDef } from '../../entities/colDef'; import type { RowNode } from '../../entities/rowNode'; @@ -229,7 +228,7 @@ export class CellCtrl extends BeanStub { } this.editorTooltipFeature = this.beans.tooltipSvc?.setupCellEditorTooltip(this, editor); - _populateModelValidationErrors(this.beans); + this.editSvc?.populateModelValidationErrors(); } public disableEditorTooltipFeature(): void { diff --git a/packages/ag-grid-community/src/rendering/cell/cellKeyboardListenerFeature.ts b/packages/ag-grid-community/src/rendering/cell/cellKeyboardListenerFeature.ts index 021411c1605..70b1a6c3172 100644 --- a/packages/ag-grid-community/src/rendering/cell/cellKeyboardListenerFeature.ts +++ b/packages/ag-grid-community/src/rendering/cell/cellKeyboardListenerFeature.ts @@ -3,7 +3,6 @@ import { KeyCode, _isMacOsUserAgent } from 'ag-stack'; import { isRowNumberCol } from '../../columns/columnUtils'; import { BeanStub } from '../../context/beanStub'; import type { BeanCollection } from '../../context/context'; -import { _populateModelValidationErrors } from '../../edit/utils/editors'; import type { AgColumn } from '../../entities/agColumn'; import type { RowNode } from '../../entities/rowNode'; import { _isCellSelectionEnabled, _isRowSelection } from '../../gridOptionsUtils'; @@ -173,7 +172,7 @@ export class CellKeyboardListenerFeature extends BeanStub { } // re-run ALL validations, Enter key is used to commit the edit, so we want to ensure it's valid - _populateModelValidationErrors(beans); + editSvc?.populateModelValidationErrors(); if (editSvc?.checkNavWithValidation(undefined, event) === 'block-stop') { return; @@ -232,7 +231,7 @@ export class CellKeyboardListenerFeature extends BeanStub { if (editing) { // re-run ALL validations, F2 is used to initiate a new edit. If we have one already in progress, // we want to ensure it's valid before initiating a new edit cycle - _populateModelValidationErrors(this.beans); + editSvc?.populateModelValidationErrors(); if (editSvc?.checkNavWithValidation(undefined, event) === 'block-stop') { return; diff --git a/packages/ag-grid-community/src/rendering/overlays/fileInputOverlayComponent.ts b/packages/ag-grid-community/src/rendering/overlays/fileInputOverlayComponent.ts new file mode 100644 index 00000000000..6fb3d54a7da --- /dev/null +++ b/packages/ag-grid-community/src/rendering/overlays/fileInputOverlayComponent.ts @@ -0,0 +1,262 @@ +import { RefPlaceholder, _clearElement } from 'ag-stack'; + +import type { GridOptions } from '../../entities/gridOptions'; +import { _addGridCommonParams } from '../../gridOptionsUtils'; +import type { ProcessFileInputParams } from '../../interfaces/iFileProcessor'; +import type { ElementParams } from '../../utils/element'; +import { _createElement } from '../../utils/element'; +import { _createIconNoSpan } from '../../utils/icon'; +import { _warn } from '../../validation/logging'; +import type { + IFileInputOverlayParams, + IOverlay, + IOverlayComp, + IOverlayParams, + OverlayComponentUserParams, +} from './overlayComponent'; +import { OverlayComponent } from './overlayComponent'; + +export interface IFileInputOverlay extends IOverlay< + TData, + TContext, + IFileInputOverlayParams +> {} + +export interface IFileInputOverlayComp extends IOverlayComp< + TData, + TContext, + IFileInputOverlayParams +> {} + +type FileInputState = 'ready' | 'processing' | 'error'; + +const FileInputOverlayElement: ElementParams = { + tag: 'div', + cls: 'ag-overlay-file-input-center', + children: [ + { tag: 'div', ref: 'eErrorBanner', cls: 'ag-file-input-error-banner' }, + { tag: 'div', ref: 'eDropZone', cls: 'ag-file-input-drop-zone' }, + { tag: 'div', ref: 'eProcessingState', cls: 'ag-file-input-processing' }, + ], +}; + +export class FileInputOverlayComponent + extends OverlayComponent + implements IFileInputOverlayComp +{ + private readonly eErrorBanner: HTMLElement = RefPlaceholder; + private readonly eDropZone: HTMLElement = RefPlaceholder; + private readonly eProcessingState: HTMLElement = RefPlaceholder; + + private state: FileInputState = 'ready'; + private dragCounter: number = 0; + private processingToken: number = 0; + + public init(params: IFileInputOverlayParams & OverlayComponentUserParams): void { + this.setTemplate(FileInputOverlayElement); + this.buildDropZone(params); + this.showState('ready'); + this.setupDragListeners(); + if (!this.gos.get('processFileInput')) { + _warn(305); + this.showError('gridOptions.processFileInput is missing'); + } + } + + private buildDropZone(params: IFileInputOverlayParams & OverlayComponentUserParams): void { + const { beans } = this; + const localeTextFunc = this.getLocaleTextFunc(); + + const text = + params.fileInput?.overlayText ?? localeTextFunc('fileInputOverlay', 'Drag & Drop file to import data'); + + const icon = _createIconNoSpan('document', beans, null); + const textSpan = { tag: 'span', cls: 'ag-file-input-text', children: text } as const; + const eTextRow = _createElement({ + tag: 'div', + cls: 'ag-file-input-text-row', + children: icon ? [() => icon, textSpan] : [textSpan], + }); + + this.eDropZone.appendChild(eTextRow); + this.appendBrowseButton(this.eDropZone); + + beans.ariaAnnounce.announceValue(text, 'overlay'); + } + + private updateProcessingState(fileName: string): void { + const { beans } = this; + const localeTextFunc = this.getLocaleTextFunc(); + + _clearElement(this.eProcessingState); + + const eIcon = _createIconNoSpan('overlayLoading', beans, null); + if (eIcon) { + eIcon.classList.add('ag-loading-icon'); + this.eProcessingState.appendChild(eIcon); + } + + const text = localeTextFunc('fileInputProcessing', `Processing ${fileName}`, [fileName]); + const eText = _createElement({ + tag: 'span', + cls: 'ag-file-input-text', + children: text, + }); + this.eProcessingState.appendChild(eText); + + beans.ariaAnnounce.announceValue(text, 'overlay'); + } + + private showError(message: string): void { + this.eErrorBanner.textContent = message; + this.showState('error'); + this.beans.ariaAnnounce.announceValue(message, 'overlay'); + } + + private appendBrowseButton(parent: HTMLElement): void { + const localeTextFunc = this.getLocaleTextFunc(); + + const eFileInput = _createElement({ + tag: 'input', + cls: 'ag-file-input-input', + attrs: { type: 'file', style: 'display:none' }, + }); + this.addManagedElementListeners(eFileInput, { change: () => this.onFileInputChange(eFileInput) }); + parent.appendChild(eFileInput); + + const eButton = _createElement({ + tag: 'button', + cls: 'ag-file-input-browse', + attrs: { type: 'button' }, + children: localeTextFunc('fileInputOverlayBrowse', 'Browse files'), + }); + this.addManagedElementListeners(eButton, { click: () => eFileInput.click() }); + parent.appendChild(eButton); + } + + private showState(state: FileInputState): void { + this.state = state; + const eGui = this.getGui(); + _clearElement(eGui); + switch (state) { + case 'error': + eGui.appendChild(this.eErrorBanner); + eGui.appendChild(this.eDropZone); + break; + case 'processing': + eGui.appendChild(this.eProcessingState); + break; + default: + eGui.appendChild(this.eDropZone); + break; + } + } + + private setupDragListeners(): void { + const eGui = this.getGui(); + + this.addManagedElementListeners(eGui, { + dragenter: (e: DragEvent) => { + if (!this.isFileDrag(e)) { + return; + } + e.preventDefault(); + this.dragCounter++; + if (this.dragCounter === 1) { + this.eDropZone.classList.add('ag-file-input-drop-zone-active'); + } + }, + dragover: (e: DragEvent) => { + if (!this.isFileDrag(e)) { + return; + } + e.preventDefault(); + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'copy'; + } + }, + dragleave: (e: DragEvent) => { + if (!this.isFileDrag(e)) { + return; + } + e.preventDefault(); + this.dragCounter--; + if (this.dragCounter <= 0) { + this.dragCounter = 0; + this.eDropZone.classList.remove('ag-file-input-drop-zone-active'); + } + }, + drop: (e: DragEvent) => { + if (!this.isFileDrag(e)) { + return; + } + e.preventDefault(); + this.dragCounter = 0; + this.eDropZone.classList.remove('ag-file-input-drop-zone-active'); + + this.handleFileList(e.dataTransfer?.files); + }, + }); + } + + private isFileDrag(e: DragEvent): boolean { + return e.dataTransfer?.types?.includes('Files') ?? false; + } + + private onFileInputChange(eFileInput: HTMLInputElement): void { + this.handleFileList(eFileInput.files); + eFileInput.value = ''; + } + + private handleFileList(files: FileList | null | undefined): void { + if (files && files.length > 0) { + this.handleFiles(Array.from(files)); + } + } + + private handleFiles(files: File[]): void { + if (this.state === 'processing') { + return; + } + + const { gos } = this; + const processFileInput = gos.get('processFileInput'); + + const fileName = files[0].name; + this.updateProcessingState(fileName); + this.showState('processing'); + + const token = ++this.processingToken; + + const success = (rowData: any[]) => { + if (!this.isAlive() || token !== this.processingToken) { + return; + } + const options: GridOptions = { rowData }; + if (gos.get('activeOverlay') === 'agFileInputOverlay') { + options.activeOverlay = undefined; + } + gos.updateGridOptions({ options, source: 'api' }); + }; + + const fail = (errorMessage?: string) => { + if (!this.isAlive() || token !== this.processingToken) { + return; + } + const localeTextFunc = this.getLocaleTextFunc(); + const message = + errorMessage ?? localeTextFunc('fileInputProcessingFailed', `Error processing ${fileName}`, [fileName]); + this.showError(message); + }; + + if (!processFileInput) { + fail(); + } else { + try { + processFileInput(_addGridCommonParams(gos, { files, success, fail })); + } catch (error) { + fail(error instanceof Error ? error.message : undefined); + } + } + } +} diff --git a/packages/ag-grid-community/src/rendering/overlays/fileInputOverlayModule.ts b/packages/ag-grid-community/src/rendering/overlays/fileInputOverlayModule.ts new file mode 100644 index 00000000000..705d6b58e3f --- /dev/null +++ b/packages/ag-grid-community/src/rendering/overlays/fileInputOverlayModule.ts @@ -0,0 +1,20 @@ +import type { _ModuleWithoutApi } from '../../interfaces/iModule'; +import { VERSION } from '../../version'; +import { FileInputOverlayComponent } from './fileInputOverlayComponent'; +import { OverlayModule } from './overlayModule'; + +/** + * @feature Accessories -> File Input Overlay + * @gridOption processFileInput + */ +export const FileInputOverlayModule: _ModuleWithoutApi = { + moduleName: 'FileInputOverlay', + version: VERSION, + userComponents: { + agFileInputOverlay: FileInputOverlayComponent, + }, + icons: { + document: 'document', + }, + dependsOn: [OverlayModule], +}; diff --git a/packages/ag-grid-community/src/rendering/overlays/overlayComponent.ts b/packages/ag-grid-community/src/rendering/overlays/overlayComponent.ts index 7c5aa6f0e5e..10be5e6cdbd 100644 --- a/packages/ag-grid-community/src/rendering/overlays/overlayComponent.ts +++ b/packages/ag-grid-community/src/rendering/overlays/overlayComponent.ts @@ -3,7 +3,7 @@ import type { IComponent } from 'ag-stack'; import type { AgGridCommon } from '../../interfaces/iCommon'; import { Component } from '../../widgets/component'; -export type OverlayType = 'loading' | 'noRows' | 'noMatchingRows' | 'exporting'; +export type OverlayType = 'loading' | 'noRows' | 'noMatchingRows' | 'exporting' | 'fileInput'; interface ProvidedOverlayUserParams { /** @@ -16,6 +16,7 @@ export interface LoadingOverlayUserParams extends ProvidedOverlayUserParams {} export interface ExportingOverlayUserParams extends ProvidedOverlayUserParams {} export interface NoRowsOverlayUserParams extends ProvidedOverlayUserParams {} export interface NoMatchingRowsOverlayUserParams extends ProvidedOverlayUserParams {} +export interface FileInputOverlayUserParams extends ProvidedOverlayUserParams {} export interface ILoadingOverlayParams extends AgGridCommon { /** @@ -43,6 +44,13 @@ export interface INoMatchingRowsOverlayParams exten overlayType: 'noMatchingRows'; } +export interface IFileInputOverlayParams extends AgGridCommon { + /** + * The default overlay the grid would show in the given state. + */ + overlayType: 'fileInput'; +} + /** * Parameters available to configure the provided overlays. */ @@ -55,13 +63,16 @@ export interface OverlayComponentUserParams { noMatchingRows?: NoMatchingRowsOverlayUserParams; /** Parameters to customise the provided exporting overlay. */ exporting?: ExportingOverlayUserParams; + /** Parameters to customise the provided file drop overlay. */ + fileInput?: FileInputOverlayUserParams; } export type IOverlayParams = | ILoadingOverlayParams | IExportingOverlayParams | INoRowsOverlayParams - | INoMatchingRowsOverlayParams; + | INoMatchingRowsOverlayParams + | IFileInputOverlayParams; export interface IOverlay< TData = any, diff --git a/packages/ag-grid-community/src/rendering/overlays/overlayService.ts b/packages/ag-grid-community/src/rendering/overlays/overlayService.ts index c5db94ebc50..bdc528af970 100644 --- a/packages/ag-grid-community/src/rendering/overlays/overlayService.ts +++ b/packages/ag-grid-community/src/rendering/overlays/overlayService.ts @@ -21,6 +21,7 @@ type OverlayCompType = | 'agNoRowsOverlay' | 'agNoMatchingRowsOverlay' | 'agExportingOverlay' + | 'agFileInputOverlay' | 'activeOverlay'; type OverlayDef = Readonly<{ @@ -74,6 +75,14 @@ const ExportingOverlayDef: OverlayDef = { exclusive: true, }; +const FileInputOverlayDef: OverlayDef = { + id: 'agFileInputOverlay', + overlayType: 'fileInput', + comp: overlayCompType('fileInputOverlayComponent'), + wrapperCls: 'ag-overlay-file-input-wrapper', + exclusive: true, +}; + const CustomOverlayDef: Readonly = { id: 'activeOverlay', comp: overlayCompType('activeOverlay'), @@ -92,6 +101,7 @@ const getActiveOverlayDef = (activeOverlay: any): OverlayDef | null => { agNoRowsOverlay: NoRowsOverlayDef, agNoMatchingRowsOverlay: NoMatchingRowsOverlayDef, agExportingOverlay: ExportingOverlayDef, + agFileInputOverlay: FileInputOverlayDef, } as Record )[activeOverlay] ?? CustomOverlayDef ); @@ -106,6 +116,7 @@ const getOverlayDefForType = (overlayType: OverlayType | null): OverlayDef | nul noRows: NoRowsOverlayDef, noMatchingRows: NoMatchingRowsOverlayDef, exporting: ExportingOverlayDef, + fileInput: FileInputOverlayDef, } as Record )[overlayType]; }; @@ -157,6 +168,8 @@ export class OverlayService extends BeanStub implements NamedBean { 'overlayComponentParams', 'loadingOverlayComponentParams', 'noRowsOverlayComponentParams', + 'autoGenerateColumnDefs', + 'processFileInput', ], (params) => this.onPropChange(new Set(params.changeSet?.properties)) ); @@ -388,9 +401,15 @@ export class OverlayService extends BeanStub implements NamedBean { return LoadingOverlayDef; } } else if (this.showInitialOverlay) { - if (!this.isDisabled(LoadingOverlayDef) && (!gos.get('columnDefs') || !gos.get('rowData'))) { - // if no columns or no row data, we show the initial loading overlay - return LoadingOverlayDef; + const noColumnDefs = !gos.get('columnDefs') && !gos.get('autoGenerateColumnDefs'); + const noRowData = !gos.get('rowData'); + if (noColumnDefs || noRowData) { + if (noRowData && gos.get('processFileInput') && !this.isDisabled(FileInputOverlayDef)) { + return FileInputOverlayDef; + } + if (!this.isDisabled(LoadingOverlayDef)) { + return LoadingOverlayDef; + } } this.disableInitialOverlay(); } else { diff --git a/packages/ag-grid-community/src/rendering/overlays/overlayWrapperComponent.css b/packages/ag-grid-community/src/rendering/overlays/overlayWrapperComponent.css index 52274309c67..2ef8c0b4a70 100644 --- a/packages/ag-grid-community/src/rendering/overlays/overlayWrapperComponent.css +++ b/packages/ag-grid-community/src/rendering/overlays/overlayWrapperComponent.css @@ -25,7 +25,8 @@ .ag-overlay-loading-wrapper, .ag-overlay-exporting-wrapper, -.ag-overlay-modal-wrapper { +.ag-overlay-modal-wrapper, +.ag-overlay-file-input-wrapper { /* prevent interaction with grid while it's loading */ pointer-events: all; } @@ -39,3 +40,69 @@ padding: var(--ag-spacing); display: flex; } + +.ag-overlay-file-input-center { + background: var(--ag-background-color); + border: solid var(--ag-border-width) var(--ag-border-color); + border-radius: var(--ag-border-radius); + box-shadow: var(--ag-popup-shadow); + display: flex; + flex-direction: column; + align-items: center; + gap: calc(var(--ag-spacing) * 2); + max-width: 420px; + padding: calc(var(--ag-spacing) * 2); +} + +.ag-file-input-error-banner { + background: color-mix(in srgb, var(--ag-invalid-color) 10%, var(--ag-background-color)); + color: var(--ag-invalid-color); + border-radius: var(--ag-border-radius); + padding: calc(var(--ag-spacing) * 0.75) calc(var(--ag-spacing) * 2); + width: 100%; + text-align: center; + font-size: 0.9em; +} + +.ag-file-input-drop-zone { + border: dashed calc(var(--ag-border-width) * 2) var(--ag-border-color); + border-radius: var(--ag-border-radius); + padding: calc(var(--ag-spacing) * 4); + display: flex; + flex-direction: column; + align-items: center; + gap: var(--ag-spacing); + width: 100%; +} + +.ag-file-input-drop-zone-active { + border-color: var(--ag-accent-color); + background: var(--ag-row-hover-color); +} + +.ag-file-input-processing { + display: flex; + align-items: center; + gap: calc(var(--ag-spacing) * 0.75); + padding: calc(var(--ag-spacing) * 4); +} + +.ag-file-input-text-row { + display: flex; + align-items: center; + gap: calc(var(--ag-spacing) * 0.75); +} + +.ag-file-input-text { + font-weight: 600; +} + +.ag-file-input-browse { + cursor: pointer; + border: solid var(--ag-border-width) var(--ag-border-color); + background: transparent; + color: var(--ag-text-color); + border-radius: var(--ag-border-radius); + padding: calc(var(--ag-spacing) * 0.5) calc(var(--ag-spacing) * 2); + font: inherit; +} diff --git a/packages/ag-grid-community/src/styling/calculatedColumnCss.ts b/packages/ag-grid-community/src/styling/calculatedColumnCss.ts index e3f38300820..693d3471018 100644 --- a/packages/ag-grid-community/src/styling/calculatedColumnCss.ts +++ b/packages/ag-grid-community/src/styling/calculatedColumnCss.ts @@ -1,4 +1,3 @@ -import { _hasCalculatedExpression } from '../columns/calculatedColumnUtils'; import type { AgColumn } from '../entities/agColumn'; import type { ICalculatedColumnsService } from '../interfaces/iCalculatedColumns'; @@ -16,11 +15,11 @@ export function _getCalculatedColumnCssClasses( column: AgColumn | null | undefined, calculatedColsSvc: ICalculatedColumnsService | undefined ): readonly string[] { - if (calculatedColsSvc == null || !_hasCalculatedExpression(column?.colDef)) { + if (calculatedColsSvc == null || !column?.isCalculatedCol) { return EMPTY_CALCULATED_COLUMN_CSS_CLASSES; } - return calculatedColsSvc.isHighlightedColumn(column ?? null) + return calculatedColsSvc.isHighlightedColumn(column) ? HIGHLIGHTED_CALCULATED_COLUMN_CSS_CLASSES : CALCULATED_COLUMN_CSS_CLASSES; } diff --git a/packages/ag-grid-community/src/theming/parts/icon-set/alpine/alpine-svg-icons/document.svg b/packages/ag-grid-community/src/theming/parts/icon-set/alpine/alpine-svg-icons/document.svg new file mode 100644 index 00000000000..c53b44bda30 --- /dev/null +++ b/packages/ag-grid-community/src/theming/parts/icon-set/alpine/alpine-svg-icons/document.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ag-grid-community/src/theming/parts/icon-set/alpine/icon-set-alpine.css b/packages/ag-grid-community/src/theming/parts/icon-set/alpine/icon-set-alpine.css index 841fe8c758d..666a70b21cd 100644 --- a/packages/ag-grid-community/src/theming/parts/icon-set/alpine/icon-set-alpine.css +++ b/packages/ag-grid-community/src/theming/parts/icon-set/alpine/icon-set-alpine.css @@ -62,6 +62,10 @@ mask-image: url('./alpine-svg-icons/adesc.svg'); } +.ag-icon-document::before { + mask-image: url('./alpine-svg-icons/document.svg'); +} + .ag-icon-down::before { mask-image: url('./alpine-svg-icons/down.svg'); } diff --git a/packages/ag-grid-community/src/theming/parts/icon-set/balham/balham-svg-icons/document.svg b/packages/ag-grid-community/src/theming/parts/icon-set/balham/balham-svg-icons/document.svg new file mode 100644 index 00000000000..3f84039bd05 --- /dev/null +++ b/packages/ag-grid-community/src/theming/parts/icon-set/balham/balham-svg-icons/document.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ag-grid-community/src/theming/parts/icon-set/balham/icon-set-balham.css b/packages/ag-grid-community/src/theming/parts/icon-set/balham/icon-set-balham.css index b91cbb24528..1a117570924 100644 --- a/packages/ag-grid-community/src/theming/parts/icon-set/balham/icon-set-balham.css +++ b/packages/ag-grid-community/src/theming/parts/icon-set/balham/icon-set-balham.css @@ -61,6 +61,10 @@ mask-image: url('./balham-svg-icons/adesc.svg'); } +.ag-icon-document::before { + mask-image: url('./balham-svg-icons/document.svg'); +} + .ag-icon-down::before { mask-image: url('./balham-svg-icons/down.svg'); } diff --git a/packages/ag-grid-community/src/theming/parts/icon-set/material/icon-set-material.css b/packages/ag-grid-community/src/theming/parts/icon-set/material/icon-set-material.css index f2ad8de25a8..0c09742c8fd 100644 --- a/packages/ag-grid-community/src/theming/parts/icon-set/material/icon-set-material.css +++ b/packages/ag-grid-community/src/theming/parts/icon-set/material/icon-set-material.css @@ -62,6 +62,10 @@ mask-image: url('./material-svg-icons/adesc.svg'); } +.ag-icon-document::before { + mask-image: url('./material-svg-icons/document.svg'); +} + .ag-icon-down::before { mask-image: url('./material-svg-icons/down.svg'); } diff --git a/packages/ag-grid-community/src/theming/parts/icon-set/material/material-svg-icons/document.svg b/packages/ag-grid-community/src/theming/parts/icon-set/material/material-svg-icons/document.svg new file mode 100644 index 00000000000..99db7860a04 --- /dev/null +++ b/packages/ag-grid-community/src/theming/parts/icon-set/material/material-svg-icons/document.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ag-grid-community/src/theming/parts/icon-set/quartz/quartz-icon-data.ts b/packages/ag-grid-community/src/theming/parts/icon-set/quartz/quartz-icon-data.ts index 996e149d7fa..30dee74ff98 100644 --- a/packages/ag-grid-community/src/theming/parts/icon-set/quartz/quartz-icon-data.ts +++ b/packages/ag-grid-community/src/theming/parts/icon-set/quartz/quartz-icon-data.ts @@ -75,6 +75,8 @@ const iconNameToFullSvg: Record = { '', 'column-arrow': '', + document: + '', edit: '', 'filter-add': '', diff --git a/packages/ag-grid-community/src/tooltip/tooltipService.ts b/packages/ag-grid-community/src/tooltip/tooltipService.ts index 963f6c3dcb0..d01cf78c66a 100644 --- a/packages/ag-grid-community/src/tooltip/tooltipService.ts +++ b/packages/ag-grid-community/src/tooltip/tooltipService.ts @@ -1,7 +1,6 @@ import type { LocaleTextFunc } from 'ag-stack'; import { _exists, _getValueUsingDotField, _isElementOverflowingCallback } from 'ag-stack'; -import { _hasCalculatedExpression } from '../columns/calculatedColumnUtils'; import type { NamedBean } from '../context/bean'; import { BeanStub } from '../context/beanStub'; import type { BeanCollection } from '../context/context'; @@ -134,7 +133,7 @@ const resolveCellTooltip = ({ const colDef = column.colDef; // 1) formula error tooltip has highest priority. - const isCalculatedColumn = _hasCalculatedExpression(colDef) && beans.calculatedColsSvc != null; + const isCalculatedColumn = column.isCalculatedCol; if ((colDef.allowFormula && formula?.active) || (isCalculatedColumn && formula)) { const error = formula.getFormulaError(column, rowNode); if (error) { diff --git a/packages/ag-grid-community/src/utils/icon.ts b/packages/ag-grid-community/src/utils/icon.ts index 2f7feab7694..18b0d56a7bd 100644 --- a/packages/ag-grid-community/src/utils/icon.ts +++ b/packages/ag-grid-community/src/utils/icon.ts @@ -125,7 +125,8 @@ export type IconName = | 'checkboxUnchecked' // deprecated v33 | 'radioButtonOn' // deprecated v33 | 'radioButtonOff' // deprecated v33 - | 'search'; + | 'search' + | 'document'; export type Icons = { [key: string]: ((...args: any[]) => any) | string }; diff --git a/packages/ag-grid-community/src/validation/errorMessages/errorText.ts b/packages/ag-grid-community/src/validation/errorMessages/errorText.ts index e4fbf5fd9a0..68aa6dcd95f 100644 --- a/packages/ag-grid-community/src/validation/errorMessages/errorText.ts +++ b/packages/ag-grid-community/src/validation/errorMessages/errorText.ts @@ -802,6 +802,8 @@ export const AG_GRID_ERRORS = { `Multiple toolbar items share the explicit key '${key}'. Only the first item is rendered.` as const, 304: ({ dataType }: { dataType: string }) => `Invalid calculatedColumns.dataTypes entry "${dataType}" - it must be a built-in data type or registered via dataTypeDefinitions. It has been ignored.` as const, + 305: () => + `The file input overlay is shown but no 'processFileInput' is configured. The overlay will not work without a 'processFileInput'.` as const, }; export type ErrorMap = typeof AG_GRID_ERRORS; diff --git a/packages/ag-grid-community/src/validation/rules/gridOptionsValidations.ts b/packages/ag-grid-community/src/validation/rules/gridOptionsValidations.ts index 79a6efa8036..2b5c0994d43 100644 --- a/packages/ag-grid-community/src/validation/rules/gridOptionsValidations.ts +++ b/packages/ag-grid-community/src/validation/rules/gridOptionsValidations.ts @@ -107,6 +107,7 @@ function toConstrainedNum(key: keyof GridOptions, value: any, min: number): stri export const GRID_OPTIONS_MODULES: Partial>> = { autoGenerateColumnDefs: 'AutoGenerateColumns', + processFileInput: 'FileInputOverlay', alignedGrids: 'AlignedGrids', allowContextMenuWithControlKey: 'ContextMenu', autoSizeStrategy: 'ColumnAutoSize', diff --git a/packages/ag-grid-community/src/validation/rules/iconValidations.ts b/packages/ag-grid-community/src/validation/rules/iconValidations.ts index 4c1ce7a2dca..146e438b74d 100644 --- a/packages/ag-grid-community/src/validation/rules/iconValidations.ts +++ b/packages/ag-grid-community/src/validation/rules/iconValidations.ts @@ -44,6 +44,7 @@ export const ICON_VALUES: Record = { save: 1, csv: 1, excel: 1, + document: 1, 'small-down': 1, 'small-left': 1, 'small-right': 1, @@ -192,6 +193,7 @@ export const ICON_MODULES: Record = new Set([ diff --git a/packages/ag-grid-community/src/validation/rules/userCompValidations.ts b/packages/ag-grid-community/src/validation/rules/userCompValidations.ts index 6fc9153ead5..6f7c1ee9243 100644 --- a/packages/ag-grid-community/src/validation/rules/userCompValidations.ts +++ b/packages/ag-grid-community/src/validation/rules/userCompValidations.ts @@ -27,6 +27,7 @@ export const USER_COMP_MODULES: Record agExportingOverlay: 'Overlay', agNoRowsOverlay: 'Overlay', agNoMatchingRowsOverlay: 'Overlay', + agFileInputOverlay: 'FileInputOverlay', agTooltipComponent: 'Tooltip', agReadOnlyFloatingFilter: 'CustomFilter', agTextColumnFilter: 'TextFilter', diff --git a/packages/ag-grid-community/src/version.ts b/packages/ag-grid-community/src/version.ts index fe252f610fe..033f6034e0c 100644 --- a/packages/ag-grid-community/src/version.ts +++ b/packages/ag-grid-community/src/version.ts @@ -1,2 +1,2 @@ // DO NOT UPDATE MANUALLY: Generated from script during build time -export const VERSION = '35.3.0-beta.20260609.1239'; +export const VERSION = '35.3.0-beta.20260610.1146'; diff --git a/packages/ag-grid-enterprise/package.json b/packages/ag-grid-enterprise/package.json index 36a5949cddd..b05969b80c4 100644 --- a/packages/ag-grid-enterprise/package.json +++ b/packages/ag-grid-enterprise/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-enterprise", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue", "main": "./dist/package/main.cjs.js", "types": "./dist/types/src/main.d.ts", @@ -113,16 +113,16 @@ ], "homepage": "https://www.ag-grid.com/", "dependencies": { - "ag-stack": "35.3.0-beta.20260609.1239", - "ag-grid-community": "35.3.0-beta.20260609.1239" + "ag-stack": "35.3.0-beta.20260610.1146", + "ag-grid-community": "35.3.0-beta.20260610.1146" }, "optionalDependencies": { - "ag-charts-community": "13.3.0-beta.20260609", - "ag-charts-enterprise": "13.3.0-beta.20260609" + "ag-charts-community": "13.3.0-beta.20260610", + "ag-charts-enterprise": "13.3.0-beta.20260610" }, "devDependencies": { - "ag-charts-community": "13.3.0-beta.20260609", - "ag-charts-enterprise": "13.3.0-beta.20260609", + "ag-charts-community": "13.3.0-beta.20260610", + "ag-charts-enterprise": "13.3.0-beta.20260610", "canvas": "^3.2.3" } } diff --git a/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnForm.ts b/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnForm.ts index b81df92cc1d..3938e395d09 100644 --- a/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnForm.ts +++ b/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnForm.ts @@ -25,7 +25,7 @@ import type { CalculatedColumnDraft, ColumnSuggestion, } from './calculatedColumnFormTypes'; -import { getOperatorReplacementRange } from './calculatedColumnUtils'; +import { getOperatorReplacementRange, isInsideStringLiteral } from './calculatedColumnUtils'; export const DEFAULT_DRAFT: Omit = { cellDataType: 'text', @@ -221,23 +221,20 @@ export class CalculatedColumnForm extends Component { } private addActionListeners(): void { - if (this.expressionPickers.has('columns')) { - this.addManagedElementListeners(this.eColumns, { - mousedown: () => this.rememberExpressionSelection(), - click: () => this.openPicker('column', this.eColumns), - }); - } - if (this.expressionPickers.has('functions')) { - this.addManagedElementListeners(this.eFunctions, { - mousedown: () => this.rememberExpressionSelection(), - click: () => this.openPicker('function', this.eFunctions), - }); - } - if (this.expressionPickers.has('operators')) { - this.addManagedElementListeners(this.eOperators, { - mousedown: () => this.rememberExpressionSelection(), - click: () => this.openPicker('operator', this.eOperators), - }); + const expressionPickers = this.expressionPickers; + const pickerButtons: [CalculatedColumnExpressionPicker, ColumnSuggestion['type'], HTMLButtonElement][] = [ + ['columns', 'column', this.eColumns], + ['functions', 'function', this.eFunctions], + ['operators', 'operator', this.eOperators], + ]; + for (const pickerButton of pickerButtons) { + const [pickerKey, suggestionType, button] = pickerButton; + if (expressionPickers.has(pickerKey)) { + this.addManagedElementListeners(button, { + mousedown: () => this.rememberExpressionSelection(), + click: () => this.openPicker(suggestionType, button), + }); + } } if (!this.livePreview) { this.addManagedElementListeners(this.eApply, { @@ -557,7 +554,7 @@ export class CalculatedColumnForm extends Component { } private getFunctionToken(value: string, caret: number): { start: number; end: number; prefix: string } | null { - if (this.isInsideStringLiteral(value, caret)) { + if (isInsideStringLiteral(value, caret)) { return null; } @@ -591,19 +588,4 @@ export class CalculatedColumnForm extends Component { } return null; } - - private isInsideStringLiteral(value: string, offset: number): boolean { - let inString = false; - for (let i = 0; i < offset && i < value.length; i++) { - if (value[i] !== '"') { - continue; - } - if (value[i + 1] === '"') { - i++; - continue; - } - inString = !inString; - } - return inString; - } } diff --git a/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnReferenceMapper.ts b/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnReferenceMapper.ts index 312ddca0083..6ec6b90378d 100644 --- a/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnReferenceMapper.ts +++ b/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnReferenceMapper.ts @@ -10,7 +10,7 @@ interface CalculatedColumnReferenceError { reference: string; } -interface CalculatedColumnReferenceMapper { +export interface CalculatedColumnReferenceMapper { suggestions: ColumnSuggestion[]; toInternalExpression(expression: string): { expression: string } | { error: CalculatedColumnReferenceError }; toInternalExpressionBestEffort(expression: string): string; diff --git a/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnUtils.ts b/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnUtils.ts index ec2a4388e25..19476064ca4 100644 --- a/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnUtils.ts +++ b/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnUtils.ts @@ -187,7 +187,7 @@ function isInsideBracketReference(expression: string, offset: number): boolean { return bracketStart > bracketEnd; } -function isInsideStringLiteral(expression: string, offset: number): boolean { +export function isInsideStringLiteral(expression: string, offset: number): boolean { let inString = false; for (let i = 0; i < offset && i < expression.length; ++i) { if (expression[i] !== '"') { diff --git a/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumns.css b/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumns.css index 084a2225f2c..c97d8a5c678 100644 --- a/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumns.css +++ b/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumns.css @@ -29,6 +29,14 @@ resize: none; } +/* stylelint-disable-next-line selector-max-specificity */ +.ag-rtl .ag-calculated-column-expression-wrap .ag-text-area-input { + /* rtl:ignore */ + padding-left: var(--ag-input-padding-start); + /* rtl:ignore */ + direction: ltr; +} + .ag-calculated-column-expression-tools { display: flex; gap: calc(var(--ag-spacing) / 2); diff --git a/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnsService.ts b/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnsService.ts index 1b395c8164a..400ae248c51 100644 --- a/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnsService.ts +++ b/packages/ag-grid-enterprise/src/calculatedColumns/calculatedColumnsService.ts @@ -18,7 +18,6 @@ import { BeanStub, _addColumnDefaultAndTypes, _createUserColumn, - _hasCalculatedExpression, _mergedEqual, _normaliseCalculatedExpression, _warn, @@ -39,6 +38,7 @@ import type { CalculatedColumnDraft, ColumnSuggestion, } from './calculatedColumnFormTypes'; +import type { CalculatedColumnReferenceMapper } from './calculatedColumnReferenceMapper'; import { createCalculatedColumnReferenceMapper, translateCalculatedColumnReferenceError, @@ -47,6 +47,9 @@ import { clearStaleDataTypeProperties, replaceBracketReferences } from './calcul type ValidationState = 'valid' | CalculatedColumnValidationReason; +// bounds the parse-error memo; dialog keystrokes feed it one entry per expression variant. +const FORMULA_ERROR_CACHE_LIMIT = 256; + const BASE_DATA_TYPE_LOCALE_KEYS: Record = { text: 'dataTypeText', number: 'dataTypeNumber', @@ -82,7 +85,7 @@ type OpenCalculatedColumnDialog = { type PendingLivePreviewUpdate = { draft: CalculatedColumnDraft; - mapper: ReturnType; + mapper: CalculatedColumnReferenceMapper; }; type KnownCalculatedColumn = { @@ -111,6 +114,8 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa private readonly openDialogsByColId = new Map(); private readonly scheduledLivePreviewColIds = new Set(); private readonly pendingLivePreviewUpdatesByColId = new Map(); + // Memoised parse results keyed by expression; see getFormulaError. + private readonly formulaErrorsByExpression = new Map(); public postConstruct(): void { this.addManagedEventListeners({ @@ -155,7 +160,7 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa const source: ColumnEventType = 'calculatedColumn'; const { colModel } = this.beans; const targetColumn = colModel.getCol(column); - if (targetColumn == null || !_hasCalculatedExpression(targetColumn.colDef)) { + if (!targetColumn?.isCalculatedCol) { return; } const oldExpression = targetColumn.colDef.calculatedExpression; @@ -207,9 +212,22 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa this.refreshCalculatedColumn(targetColId); } + private getFormulaError(expression: string): FormulaError | null { + const cache = this.formulaErrorsByExpression; + const cached = cache.get(expression); + if (cached !== undefined) { + return cached; + } + if (cache.size >= FORMULA_ERROR_CACHE_LIMIT) { + cache.clear(); + } + const error = (this.beans.formula?.validateExpression(`=${expression}`) ?? null) as FormulaError | null; + cache.set(expression, error); + return error; + } + private getFormulaExpressionError(expression: string): string | null { - const error = this.beans.formula?.validateExpression(`=${expression}`); - return error ? (error as FormulaError).getTranslatedMessage(this.getLocaleTextFunc()) : null; + return this.getFormulaError(expression)?.getTranslatedMessage(this.getLocaleTextFunc()) ?? null; } private validateFormulaExpression(expression: string): boolean { @@ -278,10 +296,12 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa return; } - if (column == null || !_hasCalculatedExpression(column.colDef)) { + if (!column?.isCalculatedCol) { return; } - const draft = this.toDraft(column); + // Built once and shared by toDraft + showDialog — both need the same column snapshot. + const mapper = createCalculatedColumnReferenceMapper(this.beans, this.beans.colModel.colsList, column.colId); + const draft = this.toDraft(column, mapper); this.showDialog( draft, (nextDraft) => { @@ -290,7 +310,8 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa }, column, focus, - livePreview + livePreview, + mapper ); } @@ -324,7 +345,7 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa } public removeCalculatedColumn(column: AgColumn | null | undefined): void { - if (column == null || !_hasCalculatedExpression(column.colDef)) { + if (!column?.isCalculatedCol) { return; } const source: ColumnEventType = 'calculatedColumn'; @@ -496,7 +517,8 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa onApply: (draft: CalculatedColumnDraft) => void, columnToHighlight?: AgColumn | null, focusDialog = true, - livePreview = false + livePreview = false, + existingMapper?: CalculatedColumnReferenceMapper ): void { const openDialogState = this.openDialogsByColId.get(draft.colId); if (openDialogState) { @@ -508,7 +530,8 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa const state: { close?: () => void; resolved: boolean } = { resolved: false }; const beans = this.beans; - const mapper = createCalculatedColumnReferenceMapper(beans, beans.colModel.colsList, draft.colId); + const mapper = + existingMapper ?? createCalculatedColumnReferenceMapper(beans, beans.colModel.colsList, draft.colId); const getValidatedExpression = ( nextDraft: CalculatedColumnDraft @@ -620,10 +643,7 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa dialog.addEventListener('destroyed', () => this.destroyBean(form)); } - private scheduleLivePreviewUpdate( - draft: CalculatedColumnDraft, - mapper: ReturnType - ): void { + private scheduleLivePreviewUpdate(draft: CalculatedColumnDraft, mapper: CalculatedColumnReferenceMapper): void { const colId = draft.colId; this.pendingLivePreviewUpdatesByColId.set(colId, { draft, mapper }); if (this.scheduledLivePreviewColIds.has(colId)) { @@ -719,22 +739,17 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa : (expressionPickers ?? []); } - private toDraft(column: AgColumn): CalculatedColumnDraft { - const beans = this.beans; + private toDraft(column: AgColumn, mapper: CalculatedColumnReferenceMapper): CalculatedColumnDraft { const colDef = column.colDef; const colId = column.colId; const cellDataType = colDef.cellDataType; - const displayName = beans.colNames.getDisplayNameForColumn(column, 'header'); + const displayName = this.beans.colNames.getDisplayNameForColumn(column, 'header'); return { colId, headerName: colDef.headerName ?? displayName ?? colId, cellDataType: typeof cellDataType === 'string' ? cellDataType : DEFAULT_DRAFT.cellDataType, - calculatedExpression: createCalculatedColumnReferenceMapper( - beans, - beans.colModel.colsList, - colId - ).toDisplayExpression(colDef.calculatedExpression ?? ''), + calculatedExpression: mapper.toDisplayExpression(colDef.calculatedExpression ?? ''), }; } @@ -797,7 +812,7 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa const cols = this.beans.colModel.colsList; for (let i = 0, len = cols.length; i < len; ++i) { const column = cols[i]; - if (!_hasCalculatedExpression(column.colDef)) { + if (!column.isCalculatedCol) { continue; } const expression = column.colDef.calculatedExpression ?? ''; @@ -849,7 +864,7 @@ export class CalculatedColumnsService extends BeanStub implements NamedBean, ICa const cols = this.beans.colModel.colsList; for (let i = 0, len = cols.length; i < len; ++i) { const column = cols[i]; - if (!_hasCalculatedExpression(column.colDef)) { + if (!column.isCalculatedCol) { continue; } const expression = column.colDef.calculatedExpression ?? ''; diff --git a/packages/ag-grid-enterprise/src/formula/formulaService.ts b/packages/ag-grid-enterprise/src/formula/formulaService.ts index cb05810ac06..3bcd30bfeb9 100644 --- a/packages/ag-grid-enterprise/src/formula/formulaService.ts +++ b/packages/ag-grid-enterprise/src/formula/formulaService.ts @@ -11,7 +11,7 @@ import type { RowNodeDataChangedEvent, _ChangedRowNodes, } from 'ag-grid-community'; -import { BeanStub, _convertColumnEventSourceType, _hasCalculatedExpression, _warn } from 'ag-grid-community'; +import { BeanStub, _convertColumnEventSourceType, _warn } from 'ag-grid-community'; import { parseFormula } from './ast/parsers'; import { serializeFormula } from './ast/serializer'; @@ -116,7 +116,7 @@ export class FormulaService extends BeanStub implements IFormulaService, NamedBe if (col.isAllowFormula()) { editableFormulaColumnsPresent = true; } - if (calculatedColumnsEnabled && _hasCalculatedExpression(col.colDef)) { + if (col.isCalculatedCol) { calculatedColumnsPresent = true; } if (editableFormulaColumnsPresent && (calculatedColumnsPresent || !calculatedColumnsEnabled)) { diff --git a/packages/ag-grid-enterprise/src/menu/columnMenuFactory.ts b/packages/ag-grid-enterprise/src/menu/columnMenuFactory.ts index 6966fb2d03c..e0c7bfcfbff 100644 --- a/packages/ag-grid-enterprise/src/menu/columnMenuFactory.ts +++ b/packages/ag-grid-enterprise/src/menu/columnMenuFactory.ts @@ -4,7 +4,6 @@ import { _addGridCommonParams, _getDisplaySortForColumn, _getGrandTotalRow, - _hasCalculatedExpression, _isClientSideRowModel, _isLegacyMenuEnabled, } from 'ag-grid-community'; @@ -174,7 +173,7 @@ export class ColumnMenuFactory extends BeanStub implements NamedBean { if (!colModel.pivotMode) { result.push('calculatedColumn'); } - if (_hasCalculatedExpression(column?.colDef)) { + if (column?.isCalculatedCol) { result.push('editCalculatedColumn'); result.push('removeCalculatedColumn'); } diff --git a/packages/ag-grid-enterprise/src/menu/contextMenu.ts b/packages/ag-grid-enterprise/src/menu/contextMenu.ts index 1b33eb79f97..c57e5c7dd6a 100644 --- a/packages/ag-grid-enterprise/src/menu/contextMenu.ts +++ b/packages/ag-grid-enterprise/src/menu/contextMenu.ts @@ -23,13 +23,7 @@ import type { TouchShowContextMenuParam, WithoutGridCommon, } from 'ag-grid-community'; -import { - BeanStub, - _addGridCommonParams, - _attemptToRestoreCellFocus, - _getGrandTotalRow, - _hasCalculatedExpression, -} from 'ag-grid-community'; +import { BeanStub, _addGridCommonParams, _attemptToRestoreCellFocus, _getGrandTotalRow } from 'ag-grid-community'; import { AgContextMenuService } from '../agStack/agContextMenuService'; import { MENU_ITEM_CALLBACKS } from '../widgets/menuItemComponent'; @@ -92,19 +86,9 @@ export class ContextMenuService extends BeanStub implements NamedBean, IContextM const defaultMenuOptions: DefaultMenuItem[] = []; - const { - clipboardSvc, - chartSvc, - csvCreator, - excelCreator, - colModel, - rangeSvc, - gos, - notesSvc, - calculatedColsSvc, - } = this.beans; - - const isCalculatedColumn = _hasCalculatedExpression(column?.getColDef()) && calculatedColsSvc != null; + const { clipboardSvc, chartSvc, csvCreator, excelCreator, colModel, rangeSvc, gos, notesSvc } = this.beans; + + const isCalculatedColumn = !!(column as AgColumn | null)?.isCalculatedCol; if (_exists(node) && clipboardSvc) { if (column) { diff --git a/packages/ag-grid-enterprise/src/menu/menuItemMapper.ts b/packages/ag-grid-enterprise/src/menu/menuItemMapper.ts index c3558fff456..cf6fd81c5b6 100644 --- a/packages/ag-grid-enterprise/src/menu/menuItemMapper.ts +++ b/packages/ag-grid-enterprise/src/menu/menuItemMapper.ts @@ -20,7 +20,6 @@ import { BeanStub, _createIconNoSpan, _getRowNode, - _hasCalculatedExpression, _normalizeSortType, _resetColumnState, _warn, @@ -489,7 +488,7 @@ export class MenuItemMapper extends BeanStub implements NamedBean { } : null; case 'editCalculatedColumn': - return calculatedColsSvc && _hasCalculatedExpression(column?.colDef) + return calculatedColsSvc && column?.isCalculatedCol ? { name: localeTextFunc('calculatedColumnEdit', 'Edit Calculated Column'), icon: _createIconNoSpan('calculatedColumnEdit', beans, null), @@ -497,7 +496,7 @@ export class MenuItemMapper extends BeanStub implements NamedBean { } : null; case 'removeCalculatedColumn': - return calculatedColsSvc && _hasCalculatedExpression(column?.colDef) + return calculatedColsSvc && column?.isCalculatedCol ? { name: localeTextFunc('calculatedColumnRemove', 'Remove Calculated Column'), icon: _createIconNoSpan('calculatedColumnRemove', beans, null), diff --git a/packages/ag-grid-enterprise/src/rangeSelection/agFillHandle.ts b/packages/ag-grid-enterprise/src/rangeSelection/agFillHandle.ts index b82ab4e1731..4054ec0d9bc 100644 --- a/packages/ag-grid-enterprise/src/rangeSelection/agFillHandle.ts +++ b/packages/ag-grid-enterprise/src/rangeSelection/agFillHandle.ts @@ -348,6 +348,10 @@ export class AgFillHandle extends AbstractSelectionHandle { ) => { let currentValue: any; let skipValue: boolean = false; + // ValueContext entries feed the cyclic source lookup in processValues, so a filled + // cell must record the cell its value originated from, not the cell being written. + let valueSourceCol: AgColumn = col; + let valueSourceRowNode: RowNode = rowNode; if (withinInitialRange) { currentValue = valueSvc.getValue(col, rowNode, 'edit'); @@ -369,6 +373,9 @@ export class AgFillHandle extends AbstractSelectionHandle { idx: idx++, }); + valueSourceCol = sourceCol ?? col; + valueSourceRowNode = sourceRowNode ?? rowNode; + currentValue = value; if (col.isCellEditable(rowNode)) { const cellValue = valueSvc.getValue(col, rowNode, 'edit'); @@ -410,8 +417,8 @@ export class AgFillHandle extends AbstractSelectionHandle { if (!skipValue) { currentValues.push({ value: currentValue, - column: col, - rowNode, + column: valueSourceCol, + rowNode: valueSourceRowNode, }); } }; diff --git a/packages/ag-grid-enterprise/src/version.ts b/packages/ag-grid-enterprise/src/version.ts index fe252f610fe..033f6034e0c 100644 --- a/packages/ag-grid-enterprise/src/version.ts +++ b/packages/ag-grid-enterprise/src/version.ts @@ -1,2 +1,2 @@ // DO NOT UPDATE MANUALLY: Generated from script during build time -export const VERSION = '35.3.0-beta.20260609.1239'; +export const VERSION = '35.3.0-beta.20260610.1146'; diff --git a/packages/ag-grid-react/package.json b/packages/ag-grid-react/package.json index 5179776c8b4..73f72d488b3 100644 --- a/packages/ag-grid-react/package.json +++ b/packages/ag-grid-react/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-react", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "AG Grid React Component", "main": "./dist/package/index.cjs.js", "types": "./dist/types/src/index.d.ts", @@ -31,7 +31,7 @@ "devDependencies": { "@babel/runtime": "^7.29.2", "prop-types": "^15.6.2", - "ag-grid-community": "35.3.0-beta.20260609.1239", + "ag-grid-community": "35.3.0-beta.20260610.1146", "@babel/plugin-proposal-throw-expressions": "^7.27.1", "@babel/preset-typescript": "^7.28.5", "@types/react": "~18.3.26", @@ -44,7 +44,7 @@ }, "dependencies": { "prop-types": "^15.8.1", - "ag-grid-community": "35.3.0-beta.20260609.1239" + "ag-grid-community": "35.3.0-beta.20260610.1146" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", diff --git a/packages/ag-grid-vue3/package.json b/packages/ag-grid-vue3/package.json index a482953f094..9ea819a474d 100644 --- a/packages/ag-grid-vue3/package.json +++ b/packages/ag-grid-vue3/package.json @@ -1,7 +1,7 @@ { "name": "ag-grid-vue3", "description": "AG Grid Vue 3 Component", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "author": "Sean Landsman ", "license": "MIT", "files": [ @@ -44,7 +44,7 @@ "build-only:watch": "vite build --watch" }, "dependencies": { - "ag-grid-community": "35.3.0-beta.20260609.1239" + "ag-grid-community": "35.3.0-beta.20260610.1146" }, "devDependencies": { "vue": "^3.5.32", diff --git a/packages/ag-grid-vue3/src/components/utils.ts b/packages/ag-grid-vue3/src/components/utils.ts index 7b9575ee096..3f8adc684fa 100644 --- a/packages/ag-grid-vue3/src/components/utils.ts +++ b/packages/ag-grid-vue3/src/components/utils.ts @@ -88,6 +88,7 @@ import type { ProcessCellForClipboard, ProcessCellFromClipboard, ProcessDataFromClipboard, + ProcessFileInputParams, ProcessGroupHeaderForClipboard, ProcessHeaderForClipboard, ProcessPivotResultColDef, @@ -901,7 +902,7 @@ export interface Props { * @initial */ suppressNoRowsOverlay?: boolean, - /** List of provided overlay names to suppress. One of `loading`, `noRows`, `noMatchingRows`, `exporting`. + /** List of provided overlay names to suppress. One of `loading`, `noRows`, `noMatchingRows`, `exporting`, `fileInput`. */ suppressOverlays?: OverlayType[], /** Provide a custom overlay component to be used for all grid provided overlays (loading, no rows, no matching rows, exporting etc). @@ -927,6 +928,12 @@ export interface Props { /** Custom parameters to be supplied to the `activeOverlay` component in addition to `IOverlayParams`. Updating the params will trigger a refresh of the active overlay. */ activeOverlayParams?: any, + /** Callback to handle files received via the file input overlay (drag-and-drop or file browser). + * When provided, the file input overlay is shown when there is no row data. + * Call `params.success(rowData)` to load parsed data into the grid, or `params.fail(message)` to show an error. + * @agModule `FileInputOverlayModule` + */ + processFileInput?: (params: ProcessFileInputParams) => void, /** Set whether pagination is enabled. * @default false * @agModule `PaginationModule` @@ -2249,6 +2256,7 @@ export function getProps() { overlayComponentSelector: undefined, activeOverlay: undefined, activeOverlayParams: undefined, + processFileInput: undefined, pagination: undefined, paginationPageSize: undefined, paginationPageSizeSelector: undefined, diff --git a/packages/ag-stack/package.json b/packages/ag-stack/package.json index 6f357b76b43..0bd04fb1218 100644 --- a/packages/ag-stack/package.json +++ b/packages/ag-stack/package.json @@ -1,6 +1,6 @@ { "name": "ag-stack", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue", "main": "./dist/package/main.cjs.js", "types": "./dist/types/src/main.d.ts", diff --git a/packages/ag-stack/src/core/baseEnvironment.ts b/packages/ag-stack/src/core/baseEnvironment.ts index 389b5118ea3..fbbbedc6ee2 100644 --- a/packages/ag-stack/src/core/baseEnvironment.ts +++ b/packages/ag-stack/src/core/baseEnvironment.ts @@ -89,7 +89,7 @@ export abstract class BaseEnvironment< }); this.addDestroyFunc(() => this.mutationObserver.disconnect()); - this.addDestroyFunc(_initStyledRootFromInnerOfThreeElements(this, eRootDiv)); + this.initStyledRoot(); this.getSizeEl(LIST_ITEM_HEIGHT); this.initVariables(); @@ -307,6 +307,11 @@ export abstract class BaseEnvironment< [`${change}Changed`]: true, }); } + + // overridden by studio + protected initStyledRoot(): void { + this.addDestroyFunc(_initStyledRootFromInnerOfThreeElements(this, this.eRootDiv)); + } } /** @internal AG_GRID_INTERNAL - Not for public use. Can change / be removed at any time. */ diff --git a/packages/ag-stack/src/interfaces/iIcon.ts b/packages/ag-stack/src/interfaces/iIcon.ts index 1e00c077c89..48f17393264 100644 --- a/packages/ag-stack/src/interfaces/iIcon.ts +++ b/packages/ag-stack/src/interfaces/iIcon.ts @@ -40,6 +40,7 @@ export type IconValue = | 'save' | 'csv' | 'excel' + | 'document' | 'small-down' | 'small-left' | 'small-right' diff --git a/packages/ag-stack/src/main-internal.ts b/packages/ag-stack/src/main-internal.ts index 1c6d3587f2e..984079ab6a9 100644 --- a/packages/ag-stack/src/main-internal.ts +++ b/packages/ag-stack/src/main-internal.ts @@ -75,7 +75,12 @@ export { AutoScrollService } from './rendering/autoScrollService'; export { CssClassManager } from './rendering/cssClassManager'; export { defaultFontFamily, defaultLightColorSchemeParams, sharedDefaults } from './theming/shared/shared-css'; export type { SharedThemeParams } from './theming/shared/shared-css'; -export { _createStyledRootElements, _initDetachedStyledRoot, _initStyledRoot } from './theming/styledRoot'; +export { + _createStyledRootElements, + _initDetachedStyledRoot, + _initStyledRoot, + _initStyledRootFromInnerOfThreeElements, +} from './theming/styledRoot'; export { _asThemeImpl, createSharedTheme, ThemeImpl } from './theming/themeImpl'; export type { ThemeLogger } from './theming/themeLogger'; export { diff --git a/packages/ag-stack/src/theming/styledRoot.ts b/packages/ag-stack/src/theming/styledRoot.ts index 6faf4df0665..c8e572ef860 100644 --- a/packages/ag-stack/src/theming/styledRoot.ts +++ b/packages/ag-stack/src/theming/styledRoot.ts @@ -30,7 +30,11 @@ export function _createStyledRootElements(): [outer: HTMLElement, inner: HTMLEle } /** @internal AG_GRID_INTERNAL - Not for public use. Can change / be removed at any time. */ -export function _initStyledRootFromInnerOfThreeElements(env: IEnvironment, inner: HTMLElement): () => void { +export function _initStyledRootFromInnerOfThreeElements( + env: IEnvironment, + inner: HTMLElement, + postApplyClasses?: () => void +): () => void { const middle = inner.parentElement!; const outer = middle.parentElement!; const applyClasses = () => { @@ -38,6 +42,7 @@ export function _initStyledRootFromInnerOfThreeElements(env: IEnvironment, inner outer.className = ['ag-styled-root', inheritClass].join(' '); middle.className = ['ag-styled-root', applyClass].join(' '); inner.className = ['ag-styled-root', directionClass].join(' '); + postApplyClasses?.(); }; applyClasses(); return env.onThemeChanged(applyClasses); diff --git a/packages/ag-stack/src/version.ts b/packages/ag-stack/src/version.ts index fe252f610fe..033f6034e0c 100644 --- a/packages/ag-stack/src/version.ts +++ b/packages/ag-stack/src/version.ts @@ -1,2 +1,2 @@ // DO NOT UPDATE MANUALLY: Generated from script during build time -export const VERSION = '35.3.0-beta.20260609.1239'; +export const VERSION = '35.3.0-beta.20260610.1146'; diff --git a/plugins/ag-grid-generate-code-reference-files/package.json b/plugins/ag-grid-generate-code-reference-files/package.json index 6467165e8c3..cc5afefaa77 100644 --- a/plugins/ag-grid-generate-code-reference-files/package.json +++ b/plugins/ag-grid-generate-code-reference-files/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-generate-code-reference-files", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "private": true, "dependencies": { "ag-shared": "0.0.1", diff --git a/plugins/ag-grid-generate-example-files/package.json b/plugins/ag-grid-generate-example-files/package.json index 27c6e14a594..99250239bc6 100644 --- a/plugins/ag-grid-generate-example-files/package.json +++ b/plugins/ag-grid-generate-example-files/package.json @@ -1,10 +1,10 @@ { "name": "ag-grid-generate-example-files", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "private": true, "dependencies": { "ag-shared": "0.0.1", - "ag-grid-community": "35.3.0-beta.20260609.1239", + "ag-grid-community": "35.3.0-beta.20260610.1146", "glob": "^11.1.0", "typescript": "~5.8.3", "cheerio": "^1.2.0", diff --git a/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/grid-vanilla-to-angular.ts b/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/grid-vanilla-to-angular.ts index 8c5e39ee769..5df6d210507 100644 --- a/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/grid-vanilla-to-angular.ts +++ b/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/grid-vanilla-to-angular.ts @@ -189,7 +189,9 @@ export function vanillaToAngular( propertyAttributes.push('[rowData]="rowData"'); } - if (!propertyAssignments.find((item) => item.indexOf('rowData') >= 0)) { + if ( + !propertyAssignments.find((item) => item.replace(/setGridOption\('rowData'/g, '').indexOf('rowData') >= 0) + ) { propertyAssignments.push(`rowData!: ${rowDataType}[];`); } diff --git a/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/grid-vanilla-to-vue3.ts b/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/grid-vanilla-to-vue3.ts index b1214f21efb..44bce7bc7d9 100644 --- a/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/grid-vanilla-to-vue3.ts +++ b/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/grid-vanilla-to-vue3.ts @@ -117,7 +117,7 @@ function getPropertyBindings( propertyNames.push('rowData'); } - if (!propertyAssignments.find((item) => item.indexOf('rowData') >= 0)) { + if (!propertyAssignments.find((item) => item.replace(/setGridOption\('rowData'/g, '').indexOf('rowData') >= 0)) { propertyAssignments.push(`const rowData = ref<${rowDataType}[]>(null);`); } diff --git a/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/parser-utils.ts b/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/parser-utils.ts index 11c77417620..71d7ec605b0 100644 --- a/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/parser-utils.ts +++ b/plugins/ag-grid-generate-example-files/src/executors/generate/generator/transformation-scripts/parser-utils.ts @@ -409,6 +409,8 @@ export function findAllAccessedProperties(node) { // Do nothing for Class declarations as this is likely a cell renderer setup } else if (ts.isTypeReferenceNode(node)) { // Do nothing for Type references + } else if (ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) { + // Do nothing for literals — they are values, not property accesses } else if (node instanceof Array) { node.forEach((element) => { properties = [...properties, ...findAllAccessedProperties(element)]; diff --git a/plugins/ag-grid-task-autogen/package.json b/plugins/ag-grid-task-autogen/package.json index 7f85a0c7080..8ee0c62e3cf 100644 --- a/plugins/ag-grid-task-autogen/package.json +++ b/plugins/ag-grid-task-autogen/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-task-autogen", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "private": true, "dependencies": { "@nx/devkit": "20.8.4", diff --git a/scripts/removeLocalDeps.sh b/scripts/removeLocalDeps.sh index cdf447bd466..cf3c763160a 100755 --- a/scripts/removeLocalDeps.sh +++ b/scripts/removeLocalDeps.sh @@ -7,6 +7,3 @@ find ./node_modules ./packages/*/node_modules -name ag-charts-\* -type l -depth echo "Reinstalling latest ag-charts-* versions." npm run bootstrap --force - -echo "Reverting configuration patch..." -git apply -R ./scripts/setupLocalDeps.patch diff --git a/scripts/setupLocalDeps.patch b/scripts/setupLocalDeps.patch deleted file mode 100644 index 49e902b8b5c..00000000000 --- a/scripts/setupLocalDeps.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/packages/ag-grid-enterprise/tsconfig.lib.json b/packages/ag-grid-enterprise/tsconfig.lib.json -index 1a566f32fc..096f4e6dbc 100644 ---- a/packages/ag-grid-enterprise/tsconfig.lib.json -+++ b/packages/ag-grid-enterprise/tsconfig.lib.json -@@ -3,8 +3,8 @@ - "compilerOptions": { - "types": [], - "baseUrl": "src", -- "module": "node16", -- "moduleResolution": "node16" -+ "module": "es2020", -+ "moduleResolution": "bundler" - }, - "include": ["src/**/*.ts"], - "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts", "src/**/test/**", "src/**/test-utils/**"] diff --git a/scripts/setupLocalDeps.sh b/scripts/setupLocalDeps.sh index 523fe3ea4c0..7857155cb16 100755 --- a/scripts/setupLocalDeps.sh +++ b/scripts/setupLocalDeps.sh @@ -25,6 +25,3 @@ packages=( for name in ${packages[@]} ; do ln -s $(readlink -f $(pwd)/..)/ag-charts/packages/${name}/ ./node_modules/${name} done - -echo "Applying configuration patch..." -git apply ./scripts/setupLocalDeps.patch diff --git a/testing/accessibility/package.json b/testing/accessibility/package.json index c2b58c59143..c65f8d33615 100644 --- a/testing/accessibility/package.json +++ b/testing/accessibility/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-accessibility", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "scripts": { "download-examples": "curl --retry 5 -retry-all-errors https://grid-staging.ag-grid.com/debug/all-examples.json > ./all-examples.json", "download-examples-local": "curl https://localhost:4610/debug/all-examples.json > ./all-examples.json", @@ -18,11 +18,11 @@ "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", - "ag-grid-angular": "35.3.0-beta.20260609.1239", - "ag-grid-community": "35.3.0-beta.20260609.1239", - "ag-grid-enterprise": "35.3.0-beta.20260609.1239", - "ag-charts-community": "13.3.0-beta.20260609", - "ag-charts-enterprise": "13.3.0-beta.20260609", + "ag-grid-angular": "35.3.0-beta.20260610.1146", + "ag-grid-community": "35.3.0-beta.20260610.1146", + "ag-grid-enterprise": "35.3.0-beta.20260610.1146", + "ag-charts-community": "13.3.0-beta.20260610", + "ag-charts-enterprise": "13.3.0-beta.20260610", "rxjs": "~7.8.2", "tslib": "^2.8.1", "zone.js": "~0.15.0" diff --git a/testing/angular-tests/package.json b/testing/angular-tests/package.json index bad21fb4b9a..3b776cca68a 100644 --- a/testing/angular-tests/package.json +++ b/testing/angular-tests/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-angular-tests", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "private": true, "scripts": { "test:e2e": "jest --no-cache" @@ -11,8 +11,8 @@ "@angular/core": "^21.0.0", "@angular/platform-browser": "^21.0.0", "@angular/platform-browser-dynamic": "^21.0.0", - "ag-grid-angular": "35.3.0-beta.20260609.1239", - "ag-grid-community": "35.3.0-beta.20260609.1239", + "ag-grid-angular": "35.3.0-beta.20260610.1146", + "ag-grid-community": "35.3.0-beta.20260610.1146", "rxjs": "~7.8.2", "tslib": "^2.8.1", "zone.js": "~0.15.0" diff --git a/testing/behavioural/package.json b/testing/behavioural/package.json index edc9903e41c..7776256f6d1 100644 --- a/testing/behavioural/package.json +++ b/testing/behavioural/package.json @@ -1,6 +1,6 @@ { "name": "ag-behavioural-testing", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "private": true, "description": "Behavioural unit testing for ag-Grid", "dependencies": { @@ -8,9 +8,9 @@ }, "type": "module", "devDependencies": { - "ag-grid-community": "35.3.0-beta.20260609.1239", - "ag-grid-enterprise": "35.3.0-beta.20260609.1239", - "ag-grid-react": "35.3.0-beta.20260609.1239", + "ag-grid-community": "35.3.0-beta.20260610.1146", + "ag-grid-enterprise": "35.3.0-beta.20260610.1146", + "ag-grid-react": "35.3.0-beta.20260610.1146", "@types/react": "^18.3.23", "@types/react-dom": "^18.3.7", "@testing-library/dom": "^10.4.1", diff --git a/testing/behavioural/src/cell-editing/clipboard/clipboard-fill-handle.test.ts b/testing/behavioural/src/cell-editing/clipboard/clipboard-fill-handle.test.ts index 505519953ce..e8fbaa2083f 100644 --- a/testing/behavioural/src/cell-editing/clipboard/clipboard-fill-handle.test.ts +++ b/testing/behavioural/src/cell-editing/clipboard/clipboard-fill-handle.test.ts @@ -316,4 +316,112 @@ describe('Clipboard Paste Behaviour: fill handle', () => { expect(editRequests).toEqual(['ROW_1:field:Top Value', 'ROW_2:field:Top Value']); }); + + test('readOnlyEdit fill handle uses source cell value for all column types', async () => { + const editRequests: string[] = []; + + const api = await gridMgr.createGridAndWait('clipboardGridReadOnlyFillTypes', { + readOnlyEdit: true, + cellSelection: { + handle: { + mode: 'fill', + }, + }, + columnDefs: [ + { field: 'text', editable: true }, + { field: 'bool', editable: true }, + { field: 'date', editable: true, cellDataType: 'dateString' }, + ], + rowData: [ + { id: 'ROW_0', text: 'Source', bool: true, date: '2024-01-15' }, + { id: 'ROW_1', text: 'Other1', bool: false, date: '2024-06-20' }, + { id: 'ROW_2', text: 'Other2', bool: false, date: '2024-12-25' }, + ], + getRowId: (params) => params.data.id, + onCellEditRequest: (event) => { + editRequests.push(`${event.node?.id ?? 'unknown'}:${event.colDef.field}:${event.newValue}`); + }, + }); + + const gridDiv = getGridElement(api)! as HTMLElement; + + for (const field of ['text', 'bool', 'date']) { + editRequests.length = 0; + + await asyncSetTimeout(1); + const cell = getByTestId(gridDiv, agTestIdFor.cell('ROW_0', field)); + const cellSelectionChanged = waitForEvent('cellSelectionChanged', api); + cell.dispatchEvent(new MouseEvent('touchstart', { bubbles: true })); + await cellSelectionChanged; + await asyncSetTimeout(1); + + const fillHandle = getByTestId(gridDiv, agTestIdFor.fillHandle()); + const fillEnd = waitForEvent('fillEnd', api); + await userEvent.dblClick(fillHandle); + await fillEnd; + + const sourceValues: Record = { text: 'Source', bool: 'true', date: '2024-01-15' }; + const sourceValue = sourceValues[field]; + expect(editRequests, `fill for ${field} column`).toEqual([ + `ROW_1:${field}:${sourceValue}`, + `ROW_2:${field}:${sourceValue}`, + ]); + } + }); + + test('readOnlyEdit fill handle cycles multi-row selection pattern for all column types', async () => { + const editRequests: string[] = []; + + const api = await gridMgr.createGridAndWait('clipboardGridReadOnlyFillCyclic', { + readOnlyEdit: true, + cellSelection: { + handle: { + mode: 'fill', + }, + }, + columnDefs: [ + { field: 'text', editable: true }, + { field: 'bool', editable: true }, + { field: 'date', editable: true, cellDataType: 'dateString' }, + ], + rowData: [ + { id: 'ROW_0', text: 'A', bool: true, date: '2024-01-15' }, + { id: 'ROW_1', text: 'B', bool: false, date: '2024-06-20' }, + { id: 'ROW_2', text: 'X', bool: false, date: '2024-12-25' }, + { id: 'ROW_3', text: 'Y', bool: false, date: '2024-12-31' }, + { id: 'ROW_4', text: 'Z', bool: true, date: '2024-03-01' }, + ], + getRowId: (params) => params.data.id, + onCellEditRequest: (event) => { + editRequests.push(`${event.node?.id ?? 'unknown'}:${event.colDef.field}:${event.newValue}`); + }, + }); + + const gridDiv = getGridElement(api)! as HTMLElement; + + for (const field of ['text', 'bool', 'date']) { + editRequests.length = 0; + api.clearCellSelection(); + + const cellSelectionChanged = waitForEvent('cellSelectionChanged', api); + api.addCellRange({ rowStartIndex: 0, rowEndIndex: 1, columns: [field] }); + await cellSelectionChanged; + await asyncSetTimeout(1); + + const fillHandle = getByTestId(gridDiv, agTestIdFor.fillHandle()); + const fillEnd = waitForEvent('fillEnd', api); + await userEvent.dblClick(fillHandle); + await fillEnd; + + const expectedRow0: Record = { text: 'A', bool: 'true', date: '2024-01-15' }; + const expectedRow1: Record = { text: 'B', bool: 'false', date: '2024-06-20' }; + const val0 = expectedRow0[field]; + const val1 = expectedRow1[field]; + expect(editRequests, `cyclic fill for ${field} column`).toEqual([ + `ROW_2:${field}:${val0}`, + `ROW_3:${field}:${val1}`, + `ROW_4:${field}:${val0}`, + ]); + } + }); }); diff --git a/testing/behavioural/src/overlays/overlays-file-input.test.ts b/testing/behavioural/src/overlays/overlays-file-input.test.ts new file mode 100644 index 00000000000..082501f50d8 --- /dev/null +++ b/testing/behavioural/src/overlays/overlays-file-input.test.ts @@ -0,0 +1,601 @@ +import type { MockInstance } from 'vitest'; + +import type { ProcessFileInputParams } from 'ag-grid-community'; +import { AutoGenerateColumnsModule, ClientSideRowModelModule } from 'ag-grid-community'; + +import { GridRows, TestGridsManager, initPointerEventPolyfill, isAgHtmlElementVisible } from '../test-utils'; + +describe('ag-grid file input overlay', () => { + const gridsManager = new TestGridsManager({ + modules: [ClientSideRowModelModule, AutoGenerateColumnsModule], + }); + let consoleWarnSpy: MockInstance; + + function hasFileInputOverlay() { + return isAgHtmlElementVisible(document.querySelector('.ag-overlay-file-input-center')); + } + + function hasFileInputOverlayWrapper() { + return isAgHtmlElementVisible('.ag-overlay-file-input-wrapper'); + } + + function hasLoadingOverlay() { + return isAgHtmlElementVisible(document.querySelector('.ag-overlay-loading-center')); + } + + function hasLoadingOverlayWrapper() { + return isAgHtmlElementVisible('.ag-overlay-loading-wrapper'); + } + + function hasNoRowsOverlay() { + return isAgHtmlElementVisible(document.querySelector('.ag-overlay-no-rows-center')); + } + + function hasNoRowsOverlayWrapper() { + return isAgHtmlElementVisible('.ag-overlay-no-rows-wrapper'); + } + + function hasDropZone() { + return isAgHtmlElementVisible(document.querySelector('.ag-file-input-drop-zone')); + } + + function hasProcessingState() { + return isAgHtmlElementVisible(document.querySelector('.ag-file-input-processing')); + } + + function hasErrorBanner() { + return isAgHtmlElementVisible(document.querySelector('.ag-file-input-error-banner')); + } + + function getErrorBannerText(): string { + return document.querySelector('.ag-file-input-error-banner')?.textContent ?? ''; + } + + function getProcessingText(): string { + return document.querySelector('.ag-file-input-processing .ag-file-input-text')?.textContent ?? ''; + } + + function getDropZoneText(): string { + return document.querySelector('.ag-file-input-drop-zone .ag-file-input-text')?.textContent ?? ''; + } + + function hasBrowseButton() { + return !!document.querySelector('.ag-file-input-browse'); + } + + function hasActiveDropZone() { + return document.querySelector('.ag-file-input-drop-zone')?.classList.contains('ag-file-input-drop-zone-active'); + } + + function makeProcessFileInput( + handler?: (params: ProcessFileInputParams) => void + ): (params: ProcessFileInputParams) => void { + return handler ?? (() => {}); + } + + function createFileDragEvent(type: string, files?: File[]): DragEvent { + const dt = new DataTransfer(); + dt.types.push('Files'); + if (files) { + for (const file of files) { + dt.items.add(file); + (dt.files as unknown as File[]).push(file); + } + } + return new DragEvent(type, { dataTransfer: dt, bubbles: true, cancelable: true }); + } + + function createNonFileDragEvent(type: string): DragEvent { + const dt = new DataTransfer(); + dt.setData('text/plain', 'some text'); + return new DragEvent(type, { dataTransfer: dt, bubbles: true, cancelable: true }); + } + + function getOverlayGui(): HTMLElement { + const wrapper = document.querySelector('.ag-overlay-file-input-wrapper'); + const center = wrapper?.querySelector('.ag-overlay-file-input-center'); + return center as HTMLElement; + } + + beforeEach(() => { + initPointerEventPolyfill(); + consoleWarnSpy = vitest.spyOn(console, 'warn').mockImplementation(() => {}); + gridsManager.reset(); + }); + + afterEach(() => { + gridsManager.reset(); + consoleWarnSpy.mockRestore(); + expect(hasFileInputOverlayWrapper()).toBeFalsy(); + expect(hasLoadingOverlayWrapper()).toBeFalsy(); + expect(hasNoRowsOverlayWrapper()).toBeFalsy(); + }); + + describe('visibility', () => { + test('shows file input overlay with explicit columnDefs, null rowData, and processFileInput', () => { + gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + rowData: null as any, + processFileInput: makeProcessFileInput(), + }); + expect(hasFileInputOverlay()).toBeTruthy(); + expect(hasLoadingOverlay()).toBeFalsy(); + }); + + test('shows no-rows overlay when processFileInput set with empty rowData', () => { + gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + rowData: [], + processFileInput: makeProcessFileInput(), + }); + expect(hasNoRowsOverlay()).toBeTruthy(); + expect(hasFileInputOverlay()).toBeFalsy(); + }); + + test('shows no-rows overlay when processFileInput set and rowData cleared to empty', () => { + const api = gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + rowData: [{ a: 1 }], + processFileInput: makeProcessFileInput(), + }); + expect(hasFileInputOverlay()).toBeFalsy(); + + api.setGridOption('rowData', []); + expect(hasNoRowsOverlay()).toBeTruthy(); + expect(hasFileInputOverlay()).toBeFalsy(); + }); + + test('shows file input overlay when processFileInput set with undefined rowData and autoGenerateColumnDefs', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + expect(hasFileInputOverlay()).toBeTruthy(); + expect(hasLoadingOverlay()).toBeFalsy(); + }); + + test('does not show file input overlay when autoGenerateColumnDefs with rowData provided', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + rowData: [{ a: 1 }], + processFileInput: makeProcessFileInput(), + }); + expect(hasFileInputOverlay()).toBeFalsy(); + expect(hasLoadingOverlay()).toBeFalsy(); + expect(hasNoRowsOverlay()).toBeFalsy(); + }); + + test('shows no-rows overlay when autoGenerateColumnDefs with empty rowData and processFileInput', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + rowData: [], + processFileInput: makeProcessFileInput(), + }); + expect(hasNoRowsOverlay()).toBeTruthy(); + expect(hasFileInputOverlay()).toBeFalsy(); + expect(hasLoadingOverlay()).toBeFalsy(); + }); + + test('shows loading overlay when autoGenerateColumnDefs without processFileInput', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + }); + expect(hasLoadingOverlay()).toBeTruthy(); + expect(hasFileInputOverlay()).toBeFalsy(); + }); + + test('shows loading overlay without processFileInput when rowData undefined', () => { + gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + }); + expect(hasLoadingOverlay()).toBeTruthy(); + expect(hasFileInputOverlay()).toBeFalsy(); + }); + + test('does not show file input overlay when rowData has rows', () => { + gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + rowData: [{ a: 1 }], + processFileInput: makeProcessFileInput(), + }); + expect(hasFileInputOverlay()).toBeFalsy(); + expect(hasLoadingOverlay()).toBeFalsy(); + expect(hasNoRowsOverlay()).toBeFalsy(); + }); + + test('hides file input overlay when rowData is set with rows', async () => { + const api = gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + expect(hasFileInputOverlay()).toBeTruthy(); + + api.setGridOption('rowData', [{ a: 1 }]); + expect(hasFileInputOverlay()).toBeFalsy(); + + await new GridRows(api, 'after rowData set').check(` + ROOT id:ROOT_NODE_ID + └── LEAF id:0 a:1 + `); + }); + + test('shows file input overlay on demand via activeOverlay over existing data', () => { + const api = gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + rowData: [{ a: 1 }], + processFileInput: makeProcessFileInput(), + }); + expect(hasFileInputOverlay()).toBeFalsy(); + + api.setGridOption('activeOverlay', 'agFileInputOverlay'); + expect(hasFileInputOverlay()).toBeTruthy(); + }); + + test('shows file input overlay via activeOverlay without autoGenerateColumnDefs', () => { + gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + rowData: [{ a: 1 }], + processFileInput: makeProcessFileInput(), + activeOverlay: 'agFileInputOverlay', + }); + expect(hasFileInputOverlay()).toBeTruthy(); + expect(hasFileInputOverlayWrapper()).toBeTruthy(); + expect(hasLoadingOverlay()).toBeFalsy(); + expect(hasNoRowsOverlay()).toBeFalsy(); + }); + + test('activeOverlay shows file input even without processFileInput', () => { + gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + rowData: [{ a: 1 }], + activeOverlay: 'agFileInputOverlay', + }); + expect(hasFileInputOverlay()).toBeTruthy(); + expect(hasErrorBanner()).toBeTruthy(); + expect(getErrorBannerText()).toBe('gridOptions.processFileInput is missing'); + }); + + test('shows no-rows overlay with explicit columnDefs and empty rowData even with processFileInput', () => { + gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + rowData: [], + processFileInput: makeProcessFileInput(), + }); + expect(hasNoRowsOverlay()).toBeTruthy(); + expect(hasFileInputOverlay()).toBeFalsy(); + }); + + test('loading=true takes precedence over processFileInput', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + loading: true, + }); + expect(hasLoadingOverlay()).toBeTruthy(); + expect(hasFileInputOverlay()).toBeFalsy(); + }); + }); + + describe('drop zone content', () => { + test('shows default overlay text', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + expect(getDropZoneText()).toBe('Drag & Drop file to import data'); + }); + + test('shows custom overlay text from overlayComponentParams', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + overlayComponentParams: { + fileInput: { overlayText: 'Drop CSV here' }, + }, + }); + expect(getDropZoneText()).toBe('Drop CSV here'); + }); + + test('shows browse button', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + expect(hasBrowseButton()).toBeTruthy(); + }); + }); + + describe('error state', () => { + test('shows error when processFileInput is missing', () => { + gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + rowData: [], + processFileInput: undefined, + }); + + // Without processFileInput, the overlay is not shown via the service + expect(hasFileInputOverlay()).toBeFalsy(); + }); + + test('shows error banner when processFileInput calls fail', () => { + let capturedParams: ProcessFileInputParams | undefined; + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput((params) => { + capturedParams = params; + }), + }); + expect(hasFileInputOverlay()).toBeTruthy(); + + const file = new File(['data'], 'test.csv', { type: 'text/csv' }); + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('drop', [file])); + + expect(capturedParams).toBeDefined(); + capturedParams!.fail('Custom error message'); + + expect(hasErrorBanner()).toBeTruthy(); + expect(getErrorBannerText()).toBe('Custom error message'); + expect(hasDropZone()).toBeTruthy(); + expect(hasProcessingState()).toBeFalsy(); + }); + + test('shows default error message when fail called without argument', () => { + let capturedParams: ProcessFileInputParams | undefined; + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput((params) => { + capturedParams = params; + }), + }); + + const file = new File(['data'], 'report.xlsx', { type: 'application/vnd.ms-excel' }); + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('drop', [file])); + + capturedParams!.fail(); + + expect(hasErrorBanner()).toBeTruthy(); + expect(getErrorBannerText()).toBe('Error processing report.xlsx'); + }); + + test('shows error when processFileInput throws synchronously', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(() => { + throw new Error('sync error'); + }), + }); + + const file = new File(['data'], 'bad.csv', { type: 'text/csv' }); + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('drop', [file])); + + expect(hasErrorBanner()).toBeTruthy(); + expect(hasDropZone()).toBeTruthy(); + expect(hasProcessingState()).toBeFalsy(); + }); + }); + + describe('processing state', () => { + test('shows processing state when file is dropped', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + + const file = new File(['data'], 'test.csv', { type: 'text/csv' }); + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('drop', [file])); + + expect(hasProcessingState()).toBeTruthy(); + expect(hasDropZone()).toBeFalsy(); + expect(getProcessingText()).toBe('Processing test.csv'); + }); + + test('ignores additional drops while processing', () => { + let callCount = 0; + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(() => { + callCount++; + }), + }); + + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('drop', [new File(['a'], 'first.csv')])); + eGui.dispatchEvent(createFileDragEvent('drop', [new File(['b'], 'second.csv')])); + + expect(callCount).toBe(1); + expect(getProcessingText()).toBe('Processing first.csv'); + }); + }); + + describe('successful file processing', () => { + test('updates grid rowData on success', async () => { + let capturedParams: ProcessFileInputParams | undefined; + const api = gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput((params) => { + capturedParams = params; + }), + }); + + const file = new File(['data'], 'test.csv', { type: 'text/csv' }); + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('drop', [file])); + + expect(capturedParams).toBeDefined(); + expect(capturedParams!.files).toHaveLength(1); + expect(capturedParams!.files[0].name).toBe('test.csv'); + + capturedParams!.success([{ a: 10 }, { a: 20 }]); + + expect(hasFileInputOverlay()).toBeFalsy(); + await new GridRows(api, 'after success').check(` + ROOT id:ROOT_NODE_ID + ├── LEAF id:0 a:10 + └── LEAF id:1 a:20 + `); + }); + + test('clears activeOverlay when file input overlay success is called via activeOverlay', async () => { + let capturedParams: ProcessFileInputParams | undefined; + const api = gridsManager.createGrid('myGrid', { + columnDefs: [{ field: 'a' }], + rowData: [{ a: 1 }], + processFileInput: makeProcessFileInput((params) => { + capturedParams = params; + }), + }); + expect(hasFileInputOverlay()).toBeFalsy(); + + api.setGridOption('activeOverlay', 'agFileInputOverlay'); + expect(hasFileInputOverlay()).toBeTruthy(); + + const file = new File(['data'], 'test.csv', { type: 'text/csv' }); + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('drop', [file])); + + capturedParams!.success([{ a: 10 }, { a: 20 }]); + + expect(hasFileInputOverlay()).toBeFalsy(); + expect(api.getGridOption('activeOverlay')).toBeUndefined(); + await new GridRows(api, 'after success via activeOverlay').check(` + ROOT id:ROOT_NODE_ID + ├── LEAF id:0 a:10 + └── LEAF id:1 a:20 + `); + }); + + test('shows no-rows overlay when success is called with empty array', () => { + let capturedParams: ProcessFileInputParams | undefined; + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput((params) => { + capturedParams = params; + }), + }); + + const file = new File([''], 'empty.csv', { type: 'text/csv' }); + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('drop', [file])); + + capturedParams!.success([]); + + expect(hasNoRowsOverlay()).toBeTruthy(); + expect(hasFileInputOverlay()).toBeFalsy(); + }); + }); + + describe('drag and drop interactions', () => { + test('adds active class on dragenter with file', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('dragenter')); + + expect(hasActiveDropZone()).toBeTruthy(); + }); + + test('removes active class on dragleave', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('dragenter')); + expect(hasActiveDropZone()).toBeTruthy(); + + eGui.dispatchEvent(createFileDragEvent('dragleave')); + expect(hasActiveDropZone()).toBeFalsy(); + }); + + test('handles nested dragenter/dragleave via counter', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + + const eGui = getOverlayGui(); + + // Enter outer, then enter inner child + eGui.dispatchEvent(createFileDragEvent('dragenter')); + eGui.dispatchEvent(createFileDragEvent('dragenter')); + expect(hasActiveDropZone()).toBeTruthy(); + + // Leave inner child — should stay active + eGui.dispatchEvent(createFileDragEvent('dragleave')); + expect(hasActiveDropZone()).toBeTruthy(); + + // Leave outer — now inactive + eGui.dispatchEvent(createFileDragEvent('dragleave')); + expect(hasActiveDropZone()).toBeFalsy(); + }); + + test('resets drag state on drop', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('dragenter')); + expect(hasActiveDropZone()).toBeTruthy(); + + const file = new File(['data'], 'test.csv', { type: 'text/csv' }); + eGui.dispatchEvent(createFileDragEvent('drop', [file])); + expect(hasActiveDropZone()).toBeFalsy(); + }); + + test('ignores non-file drag events', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + + const eGui = getOverlayGui(); + eGui.dispatchEvent(createNonFileDragEvent('dragenter')); + + expect(hasActiveDropZone()).toBeFalsy(); + }); + + test('does not process drop without files', () => { + let called = false; + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(() => { + called = true; + }), + }); + + const eGui = getOverlayGui(); + eGui.dispatchEvent(createFileDragEvent('drop')); + + expect(called).toBeFalsy(); + expect(hasDropZone()).toBeTruthy(); + }); + }); + + describe('file input (browse button)', () => { + test('browse button and hidden file input are rendered', () => { + gridsManager.createGrid('myGrid', { + autoGenerateColumnDefs: true, + processFileInput: makeProcessFileInput(), + }); + + const eFileInput = document.querySelector('.ag-file-input-input'); + expect(eFileInput).toBeTruthy(); + expect(eFileInput!.type).toBe('file'); + expect(eFileInput!.style.display).toBe('none'); + + const eBrowse = document.querySelector('.ag-file-input-browse'); + expect(eBrowse).toBeTruthy(); + expect(eBrowse!.textContent).toBe('Browse files'); + }); + }); +}); diff --git a/testing/behavioural/src/version.ts b/testing/behavioural/src/version.ts index fe252f610fe..033f6034e0c 100644 --- a/testing/behavioural/src/version.ts +++ b/testing/behavioural/src/version.ts @@ -1,2 +1,2 @@ // DO NOT UPDATE MANUALLY: Generated from script during build time -export const VERSION = '35.3.0-beta.20260609.1239'; +export const VERSION = '35.3.0-beta.20260610.1146'; diff --git a/testing/csp/package.json b/testing/csp/package.json index 14a0eab2ac8..aa78a0c0305 100644 --- a/testing/csp/package.json +++ b/testing/csp/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-csp", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "CSP testing for AG Grid", "main": "index.js", "scripts": {}, diff --git a/testing/module-size-angular/package.json b/testing/module-size-angular/package.json index a33ac8e6e69..5ee15860083 100644 --- a/testing/module-size-angular/package.json +++ b/testing/module-size-angular/package.json @@ -1,6 +1,6 @@ { "name": "ag-grid-module-size-angular", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "scripts": { "ng": "ng", "start": "ng serve", @@ -20,11 +20,11 @@ "@angular/platform-browser": "^20.0.0", "@angular/platform-browser-dynamic": "^20.0.0", "@angular/router": "^20.0.0", - "ag-grid-angular": "35.3.0-beta.20260609.1239", - "ag-grid-community": "35.3.0-beta.20260609.1239", - "ag-grid-enterprise": "35.3.0-beta.20260609.1239", - "ag-charts-community": "13.3.0-beta.20260609", - "ag-charts-enterprise": "13.3.0-beta.20260609", + "ag-grid-angular": "35.3.0-beta.20260610.1146", + "ag-grid-community": "35.3.0-beta.20260610.1146", + "ag-grid-enterprise": "35.3.0-beta.20260610.1146", + "ag-charts-community": "13.3.0-beta.20260610", + "ag-charts-enterprise": "13.3.0-beta.20260610", "rxjs": "~7.8.2", "tslib": "^2.8.1", "zone.js": "~0.15.0" diff --git a/testing/module-size/package.json b/testing/module-size/package.json index f68a3debb5b..a5660915c7b 100644 --- a/testing/module-size/package.json +++ b/testing/module-size/package.json @@ -1,7 +1,7 @@ { "name": "ag-grid-module-size", "private": true, - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "scripts": { "dev": "vite", "cp-app": "cp ./src/App_Src.tsx ./src/App_AUTO.tsx", @@ -14,11 +14,11 @@ "test:e2e": "run-s \"module-combinations -- {1}\" module-validate --" }, "dependencies": { - "ag-grid-react": "35.3.0-beta.20260609.1239", - "ag-grid-community": "35.3.0-beta.20260609.1239", - "ag-grid-enterprise": "35.3.0-beta.20260609.1239", - "ag-charts-community": "13.3.0-beta.20260609", - "ag-charts-enterprise": "13.3.0-beta.20260609", + "ag-grid-react": "35.3.0-beta.20260610.1146", + "ag-grid-community": "35.3.0-beta.20260610.1146", + "ag-grid-enterprise": "35.3.0-beta.20260610.1146", + "ag-charts-community": "13.3.0-beta.20260610", + "ag-charts-enterprise": "13.3.0-beta.20260610", "ag-shared": "0.0.1", "react": "^18.3.1", "react-dom": "^18.3.1" diff --git a/testing/public-recipes/e2e/package.json b/testing/public-recipes/e2e/package.json index 9f78a8a09d6..c98c08340b9 100644 --- a/testing/public-recipes/e2e/package.json +++ b/testing/public-recipes/e2e/package.json @@ -1,12 +1,12 @@ { "name": "ag-grid-public-e2e-testing-recipes", - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "description": "Public E2E testing recipes for AG Grid", "main": "index.js", "scripts": {}, "license": "MIT", "devDependencies": { - "ag-grid-community": "35.3.0-beta.20260609.1239", + "ag-grid-community": "35.3.0-beta.20260610.1146", "playwright": "^1.59.1", "@playwright/test": "^1.59.1", "@types/node": "^22.15.3" diff --git a/testing/shared/moduleDefinitions.ts b/testing/shared/moduleDefinitions.ts index b79ab4a06cb..237cf635de3 100644 --- a/testing/shared/moduleDefinitions.ts +++ b/testing/shared/moduleDefinitions.ts @@ -5,7 +5,7 @@ import type { } from '../../packages/ag-grid-community/src/interfaces/iModule'; // Use satisfies for type safety (catches typos) while allowing extra modules not in release types -export const AllGridCommunityModules: Record<`${CommunityModuleName}Module` | 'BigIntFilterModule', number> = { +export const AllGridCommunityModules: Record<`${CommunityModuleName}Module` | 'FileInputOverlayModule', number> = { AlignedGridsModule: 6.88, AllCommunityModule: 511.54, AutoGenerateColumnsModule: 5, @@ -51,6 +51,7 @@ export const AllGridCommunityModules: Record<`${CommunityModuleName}Module` | 'B UndoRedoEditModule: 74.12, ValidationModule: 74.37, ValueCacheModule: 0.65, + FileInputOverlayModule: 5, }; export const AllEnterpriseModules: Record<`${EnterpriseModuleName}Module`, number> = { AdvancedFilterModule: 223.75, diff --git a/testing/vue3-tests/package.json b/testing/vue3-tests/package.json index 69837e4754b..08b69d13730 100644 --- a/testing/vue3-tests/package.json +++ b/testing/vue3-tests/package.json @@ -1,7 +1,7 @@ { "name": "ag-grid-vue3-tests", "private": true, - "version": "35.3.0-beta.20260609.1239", + "version": "35.3.0-beta.20260610.1146", "type": "module", "scripts": { "dev": "vite", @@ -15,9 +15,9 @@ "dependencies": { "vue": "^3.5.32", "vue-router": "^5.0.6", - "ag-grid-community": "35.3.0-beta.20260609.1239", - "ag-grid-enterprise": "35.3.0-beta.20260609.1239", - "ag-grid-vue3": "35.3.0-beta.20260609.1239", + "ag-grid-community": "35.3.0-beta.20260610.1146", + "ag-grid-enterprise": "35.3.0-beta.20260610.1146", + "ag-grid-vue3": "35.3.0-beta.20260610.1146", "decimal.js": "^10.6.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 31b0989dc38..ac332ffd557 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8557,61 +8557,61 @@ adm-zip@^0.5.10: resolved "https://registry.ag-grid.com/adm-zip/-/adm-zip-0.5.16.tgz#0b5e4c779f07dedea5805cdccb1147071d94a909" integrity sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ== -ag-charts-angular@13.3.0-beta.20260609: - version "13.3.0-beta.20260609" - resolved "https://registry.ag-grid.com/ag-charts-angular/-/ag-charts-angular-13.3.0-beta.20260609.tgz#cb577d6ac4ec7c03935cd163e0a817c5b0fad337" - integrity sha512-sa+8R0BxpO1vIHJZFgpkiRXpV0eTHorNgx6V9smVILic5JAk/Ff/JNn7sytbLhKS7/2G3lJYxFdqsc0NRlfPtw== +ag-charts-angular@13.3.0-beta.20260610: + version "13.3.0-beta.20260610" + resolved "https://registry.ag-grid.com/ag-charts-angular/-/ag-charts-angular-13.3.0-beta.20260610.tgz#25e9e7e5f2bc0745442bb7eab660f22cb38146cd" + integrity sha512-pPtCsQzyqUepUn1mNZFolfLeFF3JmpXP1BNjYEjit/N1Qu+A8Jt2aTq8odD809O5lfWJUKwkD46DhUVBDAqU1g== dependencies: - ag-charts-community "13.3.0-beta.20260609" + ag-charts-community "13.3.0-beta.20260610" tslib "^2.8.1" -ag-charts-community@13.3.0-beta.20260609: - version "13.3.0-beta.20260609" - resolved "https://registry.ag-grid.com/ag-charts-community/-/ag-charts-community-13.3.0-beta.20260609.tgz#6604801d95bac335b9651f5766dff0731f0cd9e1" - integrity sha512-uY2XpENXYwr+51qkYtJugqdeXE1JVLB+zYbMGikpmP6mxMWqQTdky6ks1daM4rnJsEsyLCOCItp5Fp3ZTGx2MQ== +ag-charts-community@13.3.0-beta.20260610: + version "13.3.0-beta.20260610" + resolved "https://registry.ag-grid.com/ag-charts-community/-/ag-charts-community-13.3.0-beta.20260610.tgz#56cca7d8990b1a4d8a14d76c6d8d30bb54007f04" + integrity sha512-x2PVBhZvlIMi+56M9WfT/VPse4hdd6xcMnJ0sFXUq6YBvjSnj2EI+wUuBCod/YCe2wAyKNtu38ERUMBGWHHYiw== dependencies: - ag-charts-core "13.3.0-beta.20260609" - ag-charts-locale "13.3.0-beta.20260609" - ag-charts-types "13.3.0-beta.20260609" + ag-charts-core "13.3.0-beta.20260610" + ag-charts-locale "13.3.0-beta.20260610" + ag-charts-types "13.3.0-beta.20260610" -ag-charts-core@13.3.0-beta.20260609: - version "13.3.0-beta.20260609" - resolved "https://registry.ag-grid.com/ag-charts-core/-/ag-charts-core-13.3.0-beta.20260609.tgz#566ad07294069a5c5ff19abe34576d641cbbcba6" - integrity sha512-3mXSbPCo9xamOvPXpOTlsWyQKT7WacRVPQ8qJRQ0wdvcQ1Dxs57FPIGaxZKSsV5QsWxi1vm4lXaoHmMusfwgzg== +ag-charts-core@13.3.0-beta.20260610: + version "13.3.0-beta.20260610" + resolved "https://registry.ag-grid.com/ag-charts-core/-/ag-charts-core-13.3.0-beta.20260610.tgz#9978c5016652617be6f77d1f5db9e8c5ea626ef6" + integrity sha512-CH9kdgoDQRXioObXS3iKyOdnxezPUxDdTgAF1FMtAcYHG1W+uQD4Rn0Jfh3g4hGfSlYJFsjZ28OzTYdDxkOorw== dependencies: - ag-charts-types "13.3.0-beta.20260609" + ag-charts-types "13.3.0-beta.20260610" -ag-charts-enterprise@13.3.0-beta.20260609: - version "13.3.0-beta.20260609" - resolved "https://registry.ag-grid.com/ag-charts-enterprise/-/ag-charts-enterprise-13.3.0-beta.20260609.tgz#2d70e97b251548e53d62bd9b28b914f3dc818cd2" - integrity sha512-wnW35lSk+B27me2O/RaG0P/DCcO8Dlfx7hGu5duOeZzWGp/VlySOvmds5lBampu1rq3fZDmwN76TYIOCQQP/oA== +ag-charts-enterprise@13.3.0-beta.20260610: + version "13.3.0-beta.20260610" + resolved "https://registry.ag-grid.com/ag-charts-enterprise/-/ag-charts-enterprise-13.3.0-beta.20260610.tgz#4dacd5cdfdef9aea7300a80bc0fe415b57613df8" + integrity sha512-9yBPaZpGfmuLA24yuOGhCc0l14awbTYhJ5Qz4f7EeVsbs1R+ZkLThnCgwqbdpifnwF7gvFusf/HJsVmE+0f8yA== dependencies: - ag-charts-community "13.3.0-beta.20260609" - ag-charts-core "13.3.0-beta.20260609" + ag-charts-community "13.3.0-beta.20260610" + ag-charts-core "13.3.0-beta.20260610" -ag-charts-locale@13.3.0-beta.20260609: - version "13.3.0-beta.20260609" - resolved "https://registry.ag-grid.com/ag-charts-locale/-/ag-charts-locale-13.3.0-beta.20260609.tgz#79d9556979cf10a916e8709061931f3606f2ee5f" - integrity sha512-UQ2B2mEkmCB6ceMj4UPRE3Upo1fYvdIz2UkmV59o3dZPIRtyH/b1tFcVpbf5wkhJvbrbp+PuKzKdye8j6Fc3NA== +ag-charts-locale@13.3.0-beta.20260610: + version "13.3.0-beta.20260610" + resolved "https://registry.ag-grid.com/ag-charts-locale/-/ag-charts-locale-13.3.0-beta.20260610.tgz#00674618ce88343f38456954dedaf335bf111f2b" + integrity sha512-DGobzPDUPmSjryK+iMSJQTiGkL6ptSUShsUzLJWzi9/6ddMEfwJ2sYh2ifUtwpSuORvvWmB9fncWIbbCijmGxA== -ag-charts-react@13.3.0-beta.20260609: - version "13.3.0-beta.20260609" - resolved "https://registry.ag-grid.com/ag-charts-react/-/ag-charts-react-13.3.0-beta.20260609.tgz#8e56744ad58f4d9fb0b778c842b5591fc0073e17" - integrity sha512-XB58yp6QrBKaqpPnO0V5q+lRyOiKVAyHxuFRwSiDqW8IjzX2TFN4Q0T37Fs8hd4FH3/G8Kueti4RD5FduhIiyQ== +ag-charts-react@13.3.0-beta.20260610: + version "13.3.0-beta.20260610" + resolved "https://registry.ag-grid.com/ag-charts-react/-/ag-charts-react-13.3.0-beta.20260610.tgz#ad13c9fb89e2d2d27c0e0a37dd980e6e08db5568" + integrity sha512-WrmRGgQVHhITXG5uRi78rRlxgV/fLcxk/0/8ZMbiQqvLInmHEhHsLPbKU5rvNVVjU4W7FTqL+VjAqZ4tRODh+w== dependencies: - ag-charts-community "13.3.0-beta.20260609" + ag-charts-community "13.3.0-beta.20260610" -ag-charts-types@13.3.0-beta.20260609: - version "13.3.0-beta.20260609" - resolved "https://registry.ag-grid.com/ag-charts-types/-/ag-charts-types-13.3.0-beta.20260609.tgz#38df75e9bbd391507afa6bc4a01106da715d9a2e" - integrity sha512-wAdwxoYWrd6r0GCw3Yb+exSQCKYYiOssFsVaCVGV3llCe9kZ+DHOuS/FFJ5b0Un4uKBpXnFATwNIp8K6HjR7eA== +ag-charts-types@13.3.0-beta.20260610: + version "13.3.0-beta.20260610" + resolved "https://registry.ag-grid.com/ag-charts-types/-/ag-charts-types-13.3.0-beta.20260610.tgz#0404c8ad2b4fe1e88cf2a756e1dc51d85ce390e5" + integrity sha512-EVaKGlnTpfl64ATrdl/Ji/V33MPFAmPr1tAEHzwK5UNKICvX7gznnB+80V8NVtq54y5/pqn5PEJuY4WRSecXnQ== -ag-charts-vue3@13.3.0-beta.20260609: - version "13.3.0-beta.20260609" - resolved "https://registry.ag-grid.com/ag-charts-vue3/-/ag-charts-vue3-13.3.0-beta.20260609.tgz#f7351f1d279555a8aa13e07b49ce807a7e79a5ab" - integrity sha512-QzYZ7dzASGJkMISTNXCmX8caUy+sglajTq0mGGlLtWU8gW1Jfng0Ke85jIIL/wnkrW3e7ot4zWlzgkHmAcfHOg== +ag-charts-vue3@13.3.0-beta.20260610: + version "13.3.0-beta.20260610" + resolved "https://registry.ag-grid.com/ag-charts-vue3/-/ag-charts-vue3-13.3.0-beta.20260610.tgz#646ce087fee017b43cd9f2cca6abd9275cab7709" + integrity sha512-tF67BIHZXwf92tMqvW/kxmkeWl/W7rzM3Ixs8Fgc2CyeSBU2NqILas3Z2FBBc10DBNOor7JVvBIW7yqSxqU0OA== dependencies: - ag-charts-community "13.3.0-beta.20260609" + ag-charts-community "13.3.0-beta.20260610" agent-base@6, agent-base@^6.0.2: version "6.0.2"