Browse Source

Display selector as list of radio buttons or check boxes (#696)

* Display selector as list of radio buttons or check boxes
resolves #689

* fix test

* fix linter for custom

---------

Co-authored-by: Fred Lefévère-Laoide <Fred.Lefevere-Laoide@Taipy.io>
Fred Lefévère-Laoide 1 year ago
parent
commit
970fb3bb8e

+ 240 - 198
frontend/taipy-gui/package-lock.json

@@ -56,7 +56,7 @@
         "@typescript-eslint/parser": "^6.7.0",
         "add-asset-html-webpack-plugin": "^6.0.0",
         "autoprefixer": "^10.4.0",
-        "copy-webpack-plugin": "^11.0.0",
+        "copy-webpack-plugin": "^12.0.1",
         "cross-env": "^7.0.3",
         "css-loader": "^6.5.0",
         "css-mediaquery": "^0.1.2",
@@ -1030,13 +1030,13 @@
       "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
     },
     "node_modules/@humanwhocodes/config-array": {
-      "version": "0.11.13",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
-      "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
+      "version": "0.11.14",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+      "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
       "dev": true,
       "dependencies": {
-        "@humanwhocodes/object-schema": "^2.0.1",
-        "debug": "^4.1.1",
+        "@humanwhocodes/object-schema": "^2.0.2",
+        "debug": "^4.3.1",
         "minimatch": "^3.0.5"
       },
       "engines": {
@@ -1079,9 +1079,9 @@
       }
     },
     "node_modules/@humanwhocodes/object-schema": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
-      "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
+      "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
       "dev": true
     },
     "node_modules/@istanbuljs/load-nyc-config": {
@@ -1557,9 +1557,9 @@
       "dev": true
     },
     "node_modules/@jridgewell/trace-mapping": {
-      "version": "0.3.20",
-      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
-      "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
+      "version": "0.3.21",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz",
+      "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==",
       "dev": true,
       "dependencies": {
         "@jridgewell/resolve-uri": "^3.1.0",
@@ -1662,16 +1662,16 @@
       }
     },
     "node_modules/@mui/base": {
-      "version": "5.0.0-beta.30",
-      "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.30.tgz",
-      "integrity": "sha512-dc38W4W3K42atE9nSaOeoJ7/x9wGIfawdwC/UmMxMLlZ1iSsITQ8dQJaTATCbn98YvYPINK/EH541YA5enQIPQ==",
-      "dependencies": {
-        "@babel/runtime": "^7.23.6",
-        "@floating-ui/react-dom": "^2.0.4",
-        "@mui/types": "^7.2.12",
-        "@mui/utils": "^5.15.3",
+      "version": "5.0.0-beta.31",
+      "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.31.tgz",
+      "integrity": "sha512-+uNbP3OHJuZVI00WyMg7xfLZotaEY7LgvYXDfONVJbrS+K9wyjCIPNfjy8r9XJn4fbHo/5ibiZqjWnU9LMNv+A==",
+      "dependencies": {
+        "@babel/runtime": "^7.23.7",
+        "@floating-ui/react-dom": "^2.0.5",
+        "@mui/types": "^7.2.13",
+        "@mui/utils": "^5.15.4",
         "@popperjs/core": "^2.11.8",
-        "clsx": "^2.0.0",
+        "clsx": "^2.1.0",
         "prop-types": "^15.8.1"
       },
       "engines": {
@@ -1693,20 +1693,20 @@
       }
     },
     "node_modules/@mui/core-downloads-tracker": {
-      "version": "5.15.3",
-      "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.3.tgz",
-      "integrity": "sha512-sWeihiVyxdJjpLkp8SHkTy9kt2M/o11M60G1MzwljGL2BXdM3Ktzqv5QaQHdi00y7Y1ulvtI3GOSxP2xU8mQJw==",
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.4.tgz",
+      "integrity": "sha512-0OZN9O6hAtBpx70mMNFOPaAIol/ytwZYPY+z7Rf9dK3+1Xlzwvj5/IeShJKvtp76S1qJyhPuvZg0+BGqQaUnUw==",
       "funding": {
         "type": "opencollective",
         "url": "https://opencollective.com/mui-org"
       }
     },
     "node_modules/@mui/icons-material": {
-      "version": "5.15.3",
-      "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.3.tgz",
-      "integrity": "sha512-7LEs8AnO2Se/XYH+CcJndRsGAE+M8KAExiiQHf0V11poqmPVGcbbY82Ry2IUYf9+rOilCVnWI18ErghZ625BPQ==",
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.4.tgz",
+      "integrity": "sha512-q/Yk7aokN8qGMpR7bwoDpBSeaNe6Bv7vaY9yHYodP37c64TM6ime05ueb/wgksOVszrKkNXC67E/XYbRWOoUFA==",
       "dependencies": {
-        "@babel/runtime": "^7.23.6"
+        "@babel/runtime": "^7.23.7"
       },
       "engines": {
         "node": ">=12.0.0"
@@ -1727,18 +1727,18 @@
       }
     },
     "node_modules/@mui/material": {
-      "version": "5.15.3",
-      "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.3.tgz",
-      "integrity": "sha512-DODBBMouyq1B5f3YkEWL9vO8pGCxuEGqtfpltF6peMJzz/78tJFyLQsDas9MNLC/8AdFu2BQdkK7wox5UBPTAA==",
-      "dependencies": {
-        "@babel/runtime": "^7.23.6",
-        "@mui/base": "5.0.0-beta.30",
-        "@mui/core-downloads-tracker": "^5.15.3",
-        "@mui/system": "^5.15.3",
-        "@mui/types": "^7.2.12",
-        "@mui/utils": "^5.15.3",
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.4.tgz",
+      "integrity": "sha512-T/LGRAC+M0c+D3+y67eHwIN5bSje0TxbcJCWR0esNvU11T0QwrX3jedXItPNBwMupF2F5VWCDHBVLlFnN3+ABA==",
+      "dependencies": {
+        "@babel/runtime": "^7.23.7",
+        "@mui/base": "5.0.0-beta.31",
+        "@mui/core-downloads-tracker": "^5.15.4",
+        "@mui/system": "^5.15.4",
+        "@mui/types": "^7.2.13",
+        "@mui/utils": "^5.15.4",
         "@types/react-transition-group": "^4.4.10",
-        "clsx": "^2.0.0",
+        "clsx": "^2.1.0",
         "csstype": "^3.1.2",
         "prop-types": "^15.8.1",
         "react-is": "^18.2.0",
@@ -1771,12 +1771,12 @@
       }
     },
     "node_modules/@mui/private-theming": {
-      "version": "5.15.3",
-      "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.3.tgz",
-      "integrity": "sha512-Q79MhVMmywC1l5bMsMZq5PsIudr1MNPJnx9/EqdMP0vpz5iNvFpnLmxsD7d8/hqTWgFAljI+LH3jX8MxlZH9Gw==",
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.4.tgz",
+      "integrity": "sha512-9N5myIMEEQTM5WYWPGvvYADzjFo12LgJ7S+2iTZkBNOcJpUxQYM1tvYjkHCDV+t1ocMOEgjR2EfJ9Dus30dBlg==",
       "dependencies": {
-        "@babel/runtime": "^7.23.6",
-        "@mui/utils": "^5.15.3",
+        "@babel/runtime": "^7.23.7",
+        "@mui/utils": "^5.15.4",
         "prop-types": "^15.8.1"
       },
       "engines": {
@@ -1797,11 +1797,11 @@
       }
     },
     "node_modules/@mui/styled-engine": {
-      "version": "5.15.3",
-      "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.3.tgz",
-      "integrity": "sha512-+d5XZCTeemOO/vBfWGEeHgTm8fjU1Psdgm+xAw+uegycO2EnoA/EfGSaG5UwZ6g3b66y48Mkxi35AggShMr88w==",
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.4.tgz",
+      "integrity": "sha512-vtrZUXG5XI8CNiNLcxjIirW4dEbOloR+ikfm6ePBo7jXpJdpXjVzBWetrfE+5eI0cHkKWlTptnJ2voKV8pBRfw==",
       "dependencies": {
-        "@babel/runtime": "^7.23.6",
+        "@babel/runtime": "^7.23.7",
         "@emotion/cache": "^11.11.0",
         "csstype": "^3.1.2",
         "prop-types": "^15.8.1"
@@ -1828,16 +1828,16 @@
       }
     },
     "node_modules/@mui/system": {
-      "version": "5.15.3",
-      "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.3.tgz",
-      "integrity": "sha512-ewVU4eRgo4VfNMGpO61cKlfWmH7l9s6rA8EknRzuMX3DbSLfmtW2WJJg6qPwragvpPIir0Pp/AdWVSDhyNy5Tw==",
-      "dependencies": {
-        "@babel/runtime": "^7.23.6",
-        "@mui/private-theming": "^5.15.3",
-        "@mui/styled-engine": "^5.15.3",
-        "@mui/types": "^7.2.12",
-        "@mui/utils": "^5.15.3",
-        "clsx": "^2.0.0",
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.4.tgz",
+      "integrity": "sha512-KCwkHajGBXPs2TK1HJjIyab4NDk0cZoBDYN/TTlXVo1qBAmCjY0vjqrlsjeoG+wrwwcezXMLs/e6OGP66fPCog==",
+      "dependencies": {
+        "@babel/runtime": "^7.23.7",
+        "@mui/private-theming": "^5.15.4",
+        "@mui/styled-engine": "^5.15.4",
+        "@mui/types": "^7.2.13",
+        "@mui/utils": "^5.15.4",
+        "clsx": "^2.1.0",
         "csstype": "^3.1.2",
         "prop-types": "^15.8.1"
       },
@@ -1867,9 +1867,9 @@
       }
     },
     "node_modules/@mui/types": {
-      "version": "7.2.12",
-      "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.12.tgz",
-      "integrity": "sha512-3kaHiNm9khCAo0pVe0RenketDSFoZGAlVZ4zDjB/QNZV0XiCj+sh1zkX0VVhQPgYJDlBEzAag+MHJ1tU3vf0Zw==",
+      "version": "7.2.13",
+      "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.13.tgz",
+      "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==",
       "peerDependencies": {
         "@types/react": "^17.0.0 || ^18.0.0"
       },
@@ -1880,11 +1880,11 @@
       }
     },
     "node_modules/@mui/utils": {
-      "version": "5.15.3",
-      "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.3.tgz",
-      "integrity": "sha512-mT3LiSt9tZWCdx1pl7q4Q5tNo6gdZbvJel286ZHGuj6LQQXjWNAh8qiF9d+LogvNUI+D7eLkTnj605d1zoazfg==",
+      "version": "5.15.4",
+      "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.4.tgz",
+      "integrity": "sha512-E2wLQGBcs3VR52CpMRjk46cGscC4cbf3Q2uyHNaAeL36yTTm+aVNbtsTCazXtjOP4BDd8lu6VtlTpVC8Rtl4mg==",
       "dependencies": {
-        "@babel/runtime": "^7.23.6",
+        "@babel/runtime": "^7.23.7",
         "@types/prop-types": "^15.7.11",
         "prop-types": "^15.8.1",
         "react-is": "^18.2.0"
@@ -1907,9 +1907,9 @@
       }
     },
     "node_modules/@mui/x-date-pickers": {
-      "version": "6.18.7",
-      "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.18.7.tgz",
-      "integrity": "sha512-4NoapaCT3jvEk2cuAUjG0ReZvTEk1i4dGDz94Gt1Oc08GuC1AuzYRwCR1/1tdmbDynwkR8ilkKL6AyS3NL1H4A==",
+      "version": "6.19.0",
+      "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.19.0.tgz",
+      "integrity": "sha512-/GccT+iFJTKjI6b9b0MWojyRKnizL/VYYAfPnR1q0wSVVXjYv7a1NK0uQlan4JbnovqoQCNVeTOCy/0bUJyD2Q==",
       "dependencies": {
         "@babel/runtime": "^7.23.2",
         "@mui/base": "^5.0.0-beta.22",
@@ -1931,7 +1931,7 @@
         "@emotion/styled": "^11.8.1",
         "@mui/material": "^5.8.6",
         "@mui/system": "^5.8.0",
-        "date-fns": "^2.25.0",
+        "date-fns": "^2.25.0 || ^3.2.0",
         "date-fns-jalali": "^2.13.0-0",
         "dayjs": "^1.10.7",
         "luxon": "^3.0.2",
@@ -2120,9 +2120,9 @@
       }
     },
     "node_modules/@remix-run/router": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.1.tgz",
-      "integrity": "sha512-Qg4DMQsfPNAs88rb2xkdk03N3bjK4jgX5fR24eHCTR9q6PrhZQZ4UJBPzCHJkIpTRN1UKxx2DzjZmnC+7Lj0Ow==",
+      "version": "1.14.2",
+      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.2.tgz",
+      "integrity": "sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==",
       "engines": {
         "node": ">=14.0.0"
       }
@@ -2133,6 +2133,18 @@
       "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
       "dev": true
     },
+    "node_modules/@sindresorhus/merge-streams": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz",
+      "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/@sinonjs/commons": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz",
@@ -2402,9 +2414,9 @@
       }
     },
     "node_modules/@types/eslint": {
-      "version": "8.56.1",
-      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.1.tgz",
-      "integrity": "sha512-18PLWRzhy9glDQp3+wOgfLYRWlhgX0azxgJ63rdpoUHyrC9z0f5CkFburjQx4uD7ZCruw85ZtMt6K+L+R8fLJQ==",
+      "version": "8.56.2",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz",
+      "integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==",
       "dev": true,
       "dependencies": {
         "@types/estree": "*",
@@ -2596,9 +2608,9 @@
       "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
     },
     "node_modules/@types/react": {
-      "version": "18.2.47",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.47.tgz",
-      "integrity": "sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ==",
+      "version": "18.2.48",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz",
+      "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==",
       "dependencies": {
         "@types/prop-types": "*",
         "@types/scheduler": "*",
@@ -2736,16 +2748,16 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "6.18.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz",
-      "integrity": "sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==",
+      "version": "6.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.0.tgz",
+      "integrity": "sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==",
       "dev": true,
       "dependencies": {
         "@eslint-community/regexpp": "^4.5.1",
-        "@typescript-eslint/scope-manager": "6.18.1",
-        "@typescript-eslint/type-utils": "6.18.1",
-        "@typescript-eslint/utils": "6.18.1",
-        "@typescript-eslint/visitor-keys": "6.18.1",
+        "@typescript-eslint/scope-manager": "6.19.0",
+        "@typescript-eslint/type-utils": "6.19.0",
+        "@typescript-eslint/utils": "6.19.0",
+        "@typescript-eslint/visitor-keys": "6.19.0",
         "debug": "^4.3.4",
         "graphemer": "^1.4.0",
         "ignore": "^5.2.4",
@@ -2771,15 +2783,15 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "6.18.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.1.tgz",
-      "integrity": "sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==",
+      "version": "6.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.0.tgz",
+      "integrity": "sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "6.18.1",
-        "@typescript-eslint/types": "6.18.1",
-        "@typescript-eslint/typescript-estree": "6.18.1",
-        "@typescript-eslint/visitor-keys": "6.18.1",
+        "@typescript-eslint/scope-manager": "6.19.0",
+        "@typescript-eslint/types": "6.19.0",
+        "@typescript-eslint/typescript-estree": "6.19.0",
+        "@typescript-eslint/visitor-keys": "6.19.0",
         "debug": "^4.3.4"
       },
       "engines": {
@@ -2799,13 +2811,13 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "6.18.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz",
-      "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==",
+      "version": "6.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz",
+      "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "6.18.1",
-        "@typescript-eslint/visitor-keys": "6.18.1"
+        "@typescript-eslint/types": "6.19.0",
+        "@typescript-eslint/visitor-keys": "6.19.0"
       },
       "engines": {
         "node": "^16.0.0 || >=18.0.0"
@@ -2816,13 +2828,13 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "6.18.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz",
-      "integrity": "sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==",
+      "version": "6.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.0.tgz",
+      "integrity": "sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/typescript-estree": "6.18.1",
-        "@typescript-eslint/utils": "6.18.1",
+        "@typescript-eslint/typescript-estree": "6.19.0",
+        "@typescript-eslint/utils": "6.19.0",
         "debug": "^4.3.4",
         "ts-api-utils": "^1.0.1"
       },
@@ -2843,9 +2855,9 @@
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "6.18.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz",
-      "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==",
+      "version": "6.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz",
+      "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==",
       "dev": true,
       "engines": {
         "node": "^16.0.0 || >=18.0.0"
@@ -2856,13 +2868,13 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "6.18.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz",
-      "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==",
+      "version": "6.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz",
+      "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "6.18.1",
-        "@typescript-eslint/visitor-keys": "6.18.1",
+        "@typescript-eslint/types": "6.19.0",
+        "@typescript-eslint/visitor-keys": "6.19.0",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -2884,17 +2896,17 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "6.18.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz",
-      "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==",
+      "version": "6.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz",
+      "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.4.0",
         "@types/json-schema": "^7.0.12",
         "@types/semver": "^7.5.0",
-        "@typescript-eslint/scope-manager": "6.18.1",
-        "@typescript-eslint/types": "6.18.1",
-        "@typescript-eslint/typescript-estree": "6.18.1",
+        "@typescript-eslint/scope-manager": "6.19.0",
+        "@typescript-eslint/types": "6.19.0",
+        "@typescript-eslint/typescript-estree": "6.19.0",
         "semver": "^7.5.4"
       },
       "engines": {
@@ -2909,12 +2921,12 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "6.18.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz",
-      "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==",
+      "version": "6.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz",
+      "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "6.18.1",
+        "@typescript-eslint/types": "6.19.0",
         "eslint-visitor-keys": "^3.4.1"
       },
       "engines": {
@@ -3183,9 +3195,9 @@
       }
     },
     "node_modules/acorn-walk": {
-      "version": "8.3.1",
-      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz",
-      "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==",
+      "version": "8.3.2",
+      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz",
+      "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==",
       "dev": true,
       "engines": {
         "node": ">=0.4.0"
@@ -3922,9 +3934,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001576",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz",
-      "integrity": "sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==",
+      "version": "1.0.30001577",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001577.tgz",
+      "integrity": "sha512-rs2ZygrG1PNXMfmncM0B5H1hndY5ZCC9b5TkFaVNfZ+AUlyqcMyVIQtc3fsezi0NUCk5XZfDf9WS6WxMxnfdrg==",
       "funding": [
         {
           "type": "opencollective",
@@ -4444,20 +4456,20 @@
       "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
     },
     "node_modules/copy-webpack-plugin": {
-      "version": "11.0.0",
-      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz",
-      "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==",
+      "version": "12.0.1",
+      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.1.tgz",
+      "integrity": "sha512-dhMfjJMYKDmmbG6Yn2pRSs1g8FgeQRtbE/JM6VAM9Xouk3KO1UVrwlLHLXxaI5F+o9WgnRfhFZzY9eV34O2gZQ==",
       "dev": true,
       "dependencies": {
-        "fast-glob": "^3.2.11",
+        "fast-glob": "^3.3.2",
         "glob-parent": "^6.0.1",
-        "globby": "^13.1.1",
+        "globby": "^14.0.0",
         "normalize-path": "^3.0.0",
-        "schema-utils": "^4.0.0",
-        "serialize-javascript": "^6.0.0"
+        "schema-utils": "^4.2.0",
+        "serialize-javascript": "^6.0.2"
       },
       "engines": {
-        "node": ">= 14.15.0"
+        "node": ">= 18.12.0"
       },
       "funding": {
         "type": "opencollective",
@@ -4468,28 +4480,29 @@
       }
     },
     "node_modules/copy-webpack-plugin/node_modules/globby": {
-      "version": "13.2.2",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz",
-      "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==",
+      "version": "14.0.0",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz",
+      "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==",
       "dev": true,
       "dependencies": {
-        "dir-glob": "^3.0.1",
-        "fast-glob": "^3.3.0",
+        "@sindresorhus/merge-streams": "^1.0.0",
+        "fast-glob": "^3.3.2",
         "ignore": "^5.2.4",
-        "merge2": "^1.4.1",
-        "slash": "^4.0.0"
+        "path-type": "^5.0.0",
+        "slash": "^5.1.0",
+        "unicorn-magic": "^0.1.0"
       },
       "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+        "node": ">=18"
       },
       "funding": {
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/copy-webpack-plugin/node_modules/slash": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
-      "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
+    "node_modules/copy-webpack-plugin/node_modules/path-type": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz",
+      "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==",
       "dev": true,
       "engines": {
         "node": ">=12"
@@ -4498,6 +4511,18 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/copy-webpack-plugin/node_modules/slash": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
+      "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==",
+      "dev": true,
+      "engines": {
+        "node": ">=14.16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/core-js": {
       "version": "3.35.0",
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.35.0.tgz",
@@ -5283,9 +5308,9 @@
       }
     },
     "node_modules/dts-bundle-generator": {
-      "version": "9.2.1",
-      "resolved": "https://registry.npmjs.org/dts-bundle-generator/-/dts-bundle-generator-9.2.1.tgz",
-      "integrity": "sha512-sMyIGJcn+FSc4f4VzRgX4muZS2uG91c/DjC++HkpZJyudGedSpGNR5bY9HEkSyyYFay0ERzjoDM7uKgUycaRvw==",
+      "version": "9.2.4",
+      "resolved": "https://registry.npmjs.org/dts-bundle-generator/-/dts-bundle-generator-9.2.4.tgz",
+      "integrity": "sha512-DUwg9NqwB4Gu+dNXUGW9v/Rc+sxTYrIHsvByKCfu0KinAT6dvmAjM0W+CtecdFGhuT753z9aNm1JpVeIPGIZjw==",
       "dev": true,
       "dependencies": {
         "typescript": ">=5.0.2",
@@ -5328,9 +5353,9 @@
       "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.625",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.625.tgz",
-      "integrity": "sha512-DENMhh3MFgaPDoXWrVIqSPInQoLImywfCwrSmVl3cf9QHzoZSiutHwGaB/Ql3VkqcQV30rzgdM+BjKqBAJxo5Q=="
+      "version": "1.4.632",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.632.tgz",
+      "integrity": "sha512-JGmudTwg7yxMYvR/gWbalqqQiyu7WTFv2Xu3vw4cJHXPFxNgAk0oy8UHaer8nLF4lZJa+rNoj6GsrKIVJTV6Tw=="
     },
     "node_modules/element-size": {
       "version": "1.1.1",
@@ -6291,9 +6316,9 @@
       }
     },
     "node_modules/follow-redirects": {
-      "version": "1.15.4",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
-      "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
+      "version": "1.15.5",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
+      "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
       "funding": [
         {
           "type": "individual",
@@ -6861,9 +6886,9 @@
       }
     },
     "node_modules/goober": {
-      "version": "2.1.13",
-      "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.13.tgz",
-      "integrity": "sha512-jFj3BQeleOoy7t93E9rZ2de+ScC4lQICLwiAQmKMg9F6roKGaLSHoCDYKkWlSafg138jejvq/mTdvmnwDQgqoQ==",
+      "version": "2.1.14",
+      "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz",
+      "integrity": "sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==",
       "peerDependencies": {
         "csstype": "^3.0.10"
       }
@@ -9650,9 +9675,9 @@
       }
     },
     "node_modules/mdast-util-to-hast": {
-      "version": "13.0.2",
-      "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.0.2.tgz",
-      "integrity": "sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==",
+      "version": "13.1.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz",
+      "integrity": "sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==",
       "dependencies": {
         "@types/hast": "^3.0.0",
         "@types/mdast": "^4.0.0",
@@ -9661,7 +9686,8 @@
         "micromark-util-sanitize-uri": "^2.0.0",
         "trim-lines": "^3.0.0",
         "unist-util-position": "^5.0.0",
-        "unist-util-visit": "^5.0.0"
+        "unist-util-visit": "^5.0.0",
+        "vfile": "^6.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -11398,9 +11424,9 @@
       }
     },
     "node_modules/react-jsx-parser/node_modules/@types/react": {
-      "version": "17.0.74",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.74.tgz",
-      "integrity": "sha512-nBtFGaeTMzpiL/p73xbmCi00SiCQZDTJUk9ZuHOLtil3nI+y7l269LHkHIAYpav99ZwGnPJzuJsJpfLXjiQ52g==",
+      "version": "17.0.75",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.75.tgz",
+      "integrity": "sha512-MSA+NzEzXnQKrqpO63CYqNstFjsESgvJAdAyyJ1n6ZQq/GLgf6nOfIKwk+Twuz0L1N6xPe+qz5xRCJrbhMaLsw==",
       "optional": true,
       "dependencies": {
         "@types/prop-types": "*",
@@ -11455,11 +11481,11 @@
       }
     },
     "node_modules/react-router": {
-      "version": "6.21.1",
-      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.1.tgz",
-      "integrity": "sha512-W0l13YlMTm1YrpVIOpjCADJqEUpz1vm+CMo47RuFX4Ftegwm6KOYsL5G3eiE52jnJpKvzm6uB/vTKTPKM8dmkA==",
+      "version": "6.21.2",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.2.tgz",
+      "integrity": "sha512-jJcgiwDsnaHIeC+IN7atO0XiSRCrOsQAHHbChtJxmgqG2IaYQXSnhqGb5vk2CU/wBQA12Zt+TkbuJjIn65gzbA==",
       "dependencies": {
-        "@remix-run/router": "1.14.1"
+        "@remix-run/router": "1.14.2"
       },
       "engines": {
         "node": ">=14.0.0"
@@ -11469,12 +11495,12 @@
       }
     },
     "node_modules/react-router-dom": {
-      "version": "6.21.1",
-      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.1.tgz",
-      "integrity": "sha512-QCNrtjtDPwHDO+AO21MJd7yIcr41UetYt5jzaB9Y1UYaPTCnVuJq6S748g1dE11OQlCFIQg+RtAA1SEZIyiBeA==",
+      "version": "6.21.2",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.2.tgz",
+      "integrity": "sha512-tE13UukgUOh2/sqYr6jPzZTzmzc70aGRP4pAjG2if0IP3aUT+sBtAKUJh0qMh0zylJHGLmzS+XWVaON4UklHeg==",
       "dependencies": {
-        "@remix-run/router": "1.14.1",
-        "react-router": "6.21.1"
+        "@remix-run/router": "1.14.2",
+        "react-router": "6.21.2"
       },
       "engines": {
         "node": ">=14.0.0"
@@ -11736,9 +11762,9 @@
       }
     },
     "node_modules/remark-rehype": {
-      "version": "11.0.0",
-      "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.0.0.tgz",
-      "integrity": "sha512-vx8x2MDMcxuE4lBmQ46zYUDfcFMmvg80WYX+UNLeG6ixjdCCLcw1lrgAukwBTuOFsS78eoAedHGn9sNM0w7TPw==",
+      "version": "11.1.0",
+      "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz",
+      "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==",
       "dependencies": {
         "@types/hast": "^3.0.0",
         "@types/mdast": "^4.0.0",
@@ -11939,13 +11965,13 @@
       "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
     },
     "node_modules/safe-array-concat": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
-      "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz",
+      "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "get-intrinsic": "^1.2.1",
+        "call-bind": "^1.0.5",
+        "get-intrinsic": "^1.2.2",
         "has-symbols": "^1.0.3",
         "isarray": "^2.0.5"
       },
@@ -11976,15 +12002,18 @@
       ]
     },
     "node_modules/safe-regex-test": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
-      "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz",
+      "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "get-intrinsic": "^1.1.3",
+        "call-bind": "^1.0.5",
+        "get-intrinsic": "^1.2.2",
         "is-regex": "^1.1.4"
       },
+      "engines": {
+        "node": ">= 0.4"
+      },
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
       }
@@ -12115,15 +12144,16 @@
       }
     },
     "node_modules/set-function-length": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
-      "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz",
+      "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==",
       "dev": true,
       "dependencies": {
         "define-data-property": "^1.1.1",
-        "get-intrinsic": "^1.2.1",
+        "function-bind": "^1.1.2",
+        "get-intrinsic": "^1.2.2",
         "gopd": "^1.0.1",
-        "has-property-descriptors": "^1.0.0"
+        "has-property-descriptors": "^1.0.1"
       },
       "engines": {
         "node": ">= 0.4"
@@ -12267,9 +12297,9 @@
       }
     },
     "node_modules/socket.io-client": {
-      "version": "4.7.3",
-      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.3.tgz",
-      "integrity": "sha512-nU+ywttCyBitXIl9Xe0RSEfek4LneYkJxCeNnKCuhwoH4jGXO1ipIUw/VA/+Vvv2G1MTym11fzFC0SxkrcfXDw==",
+      "version": "4.7.4",
+      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz",
+      "integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==",
       "dependencies": {
         "@socket.io/component-emitter": "~3.1.0",
         "debug": "~4.3.2",
@@ -12413,9 +12443,9 @@
       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
     },
     "node_modules/stream-shift": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
-      "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.2.tgz",
+      "integrity": "sha512-rV4Bovi9xx0BFzOb/X0B2GqoIjvqPCttZdu0Wgtx2Dxkj7ETyWl9gmqJ4EutWRLvtZWm8dxE+InQZX1IryZn/w=="
     },
     "node_modules/string_decoder": {
       "version": "1.1.1",
@@ -13346,6 +13376,18 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/unicorn-magic": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz",
+      "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/unified": {
       "version": "11.0.4",
       "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz",

+ 1 - 1
frontend/taipy-gui/package.json

@@ -92,7 +92,7 @@
     "@typescript-eslint/parser": "^6.7.0",
     "add-asset-html-webpack-plugin": "^6.0.0",
     "autoprefixer": "^10.4.0",
-    "copy-webpack-plugin": "^11.0.0",
+    "copy-webpack-plugin": "^12.0.1",
     "cross-env": "^7.0.3",
     "css-loader": "^6.5.0",
     "css-mediaquery": "^0.1.2",

+ 4 - 0
frontend/taipy-gui/public/stylekit/controls/selector.css

@@ -35,3 +35,7 @@
   display: flex;
   max-width: initial;
 }
+
+.taipy-selector-radio-group.row-radio-group, .taipy-selector-check-group.row-check-group{
+    flex-direction: row;
+}

+ 57 - 0
frontend/taipy-gui/src/components/Taipy/Selector.spec.tsx

@@ -198,4 +198,61 @@ describe("Selector Component", () => {
             expect(queryAllByRole("listbox")).toHaveLength(0);
         });
     });
+
+    describe("Selector Component radio mode", () => {
+        //dropdown
+        it("displays a list of unselected radios", async () => {
+            const { getByText, getByRole } = render(<Selector lov={lov} mode="radio" className="taipy-selector" />);
+            getByText("Item 1");
+            getByRole("radiogroup");
+            expect(document.querySelector("div.taipy-selector-radio-group")).not.toBeNull();
+        });
+        it("displays a list of radios with one selected", async () => {
+            const { getByText } = render(<Selector lov={lov} defaultValue="id1" mode="radio" />);
+            const elt = getByText("Item 1");
+            expect(elt.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+        });
+        it("selects on click", async () => {
+            const { getByText, getByRole, queryAllByRole } = render(<Selector lov={lov} defaultValue="id1"  mode="radio" />);
+            const elt = getByText("Item 2");
+            expect(elt.parentElement?.querySelector("span.Mui-checked")).toBeNull();
+            await userEvent.click(elt);
+            expect(elt.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+        });
+    });
+
+    describe("Selector Component check mode", () => {
+        //dropdown
+        it("displays a list of unselected checks", async () => {
+            const { getByText } = render(<Selector lov={lov} mode="check" className="taipy-selector" />);
+            const elt = getByText("Item 1");
+            expect(elt.parentElement?.parentElement).toHaveClass("taipy-selector-check-group");
+            expect(document.querySelector("span.MuiCheckbox-root")).not.toBeNull();
+        });
+        it("displays a list of checks with one selected", async () => {
+            const { getByText } = render(<Selector lov={lov} defaultValue="id1" mode="check" />);
+            const elt = getByText("Item 1");
+            expect(elt.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+        });
+        it("selects on click", async () => {
+            const { getByText, getByRole, queryAllByRole } = render(<Selector lov={lov} defaultValue="id1"  mode="check" />);
+            const elt1 = getByText("Item 1");
+            expect(elt1.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+            const elt2 = getByText("Item 2");
+            expect(elt2.parentElement?.querySelector("span.Mui-checked")).toBeNull();
+            await userEvent.click(elt2);
+            expect(elt1.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+            expect(elt2.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+            const elt3 = getByText("Item 3");
+            expect(elt3.parentElement?.querySelector("span.Mui-checked")).toBeNull();
+            await userEvent.click(elt3);
+            expect(elt1.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+            expect(elt2.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+            expect(elt3.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+            await userEvent.click(elt1);
+            expect(elt1.parentElement?.querySelector("span.Mui-checked")).toBeNull();
+            expect(elt2.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+            expect(elt3.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
+        });
+    });
 });

+ 120 - 51
frontend/taipy-gui/src/components/Taipy/Selector.tsx

@@ -11,26 +11,31 @@
  * specific language governing permissions and limitations under the License.
  */
 
-import React, { useState, useCallback, useEffect, useMemo, CSSProperties, MouseEvent } from "react";
+import React, { useState, useCallback, useEffect, useMemo, CSSProperties, MouseEvent, ChangeEvent } from "react";
+import Avatar from "@mui/material/Avatar";
 import Box from "@mui/material/Box";
 import Checkbox from "@mui/material/Checkbox";
+import Chip from "@mui/material/Chip";
+import FormControl from "@mui/material/FormControl";
+import FormControlLabel from "@mui/material/FormControlLabel";
+import FormGroup from "@mui/material/FormGroup";
+import FormLabel from "@mui/material/FormLabel";
 import InputLabel from "@mui/material/InputLabel";
 import List from "@mui/material/List";
 import ListItemButton from "@mui/material/ListItemButton";
 import ListItemIcon from "@mui/material/ListItemIcon";
 import ListItemText from "@mui/material/ListItemText";
 import ListItemAvatar from "@mui/material/ListItemAvatar";
-import Paper from "@mui/material/Paper";
-import OutlinedInput from "@mui/material/OutlinedInput";
-import Avatar from "@mui/material/Avatar";
 import MenuItem from "@mui/material/MenuItem";
-import FormControl from "@mui/material/FormControl";
+import OutlinedInput from "@mui/material/OutlinedInput";
+import Paper from "@mui/material/Paper";
 import Tooltip from "@mui/material/Tooltip";
+import Radio from "@mui/material/Radio";
+import RadioGroup from "@mui/material/RadioGroup";
 import Select, { SelectChangeEvent } from "@mui/material/Select";
-import Chip from "@mui/material/Chip";
 import { Theme, useTheme } from "@mui/material";
 
-import { doNotPropagateEvent, getUpdateVar } from "./utils";
+import { doNotPropagateEvent, getSuffixedClassNames, getUpdateVar } from "./utils";
 import { createSendUpdateAction } from "../../context/taipyReducers";
 import { ItemProps, LovImage, paperBaseSx, SelTreeProps, showItem, SingleItem, useLovListMemo } from "./lovUtils";
 import {
@@ -48,7 +53,7 @@ const MultipleItem = ({ value, clickHandler, selectedValue, item, disabled }: It
             <Checkbox
                 disabled={disabled}
                 edge="start"
-                checked={selectedValue.indexOf(value) !== -1}
+                checked={selectedValue.includes(value)}
                 tabIndex={-1}
                 disableRipple
             />
@@ -92,14 +97,13 @@ const Selector = (props: SelTreeProps) => {
         updateVarName = "",
         defaultLov = "",
         filter = false,
-        multiple = false,
-        dropdown = false,
         propagate = true,
         lov,
         updateVars = "",
         width = "100%",
         height,
         valueById,
+        mode = "",
     } = props;
     const [searchValue, setSearchValue] = useState("");
     const [selectedValue, setSelectedValue] = useState<string[]>([]);
@@ -113,6 +117,11 @@ const Selector = (props: SelTreeProps) => {
 
     useDispatchRequestUpdateOnFirstRender(dispatch, id, module, updateVars, updateVarName);
 
+    const isRadio = mode && mode.toLocaleLowerCase() == "radio";
+    const isCheck = mode && mode.toLocaleLowerCase() == "check";
+    const dropdown = isRadio || isCheck || props.dropdown === undefined ? false : props.dropdown;
+    const multiple = isCheck ? true : isRadio || props.multiple === undefined ? false : props.multiple;
+
     const lovList = useLovListMemo(lov, defaultLov);
     const listSx = useMemo(
         () => ({
@@ -149,47 +158,64 @@ const Selector = (props: SelTreeProps) => {
         }
     }, [defaultValue, value]);
 
+    const selectHandler = useCallback(
+        (key: string) => {
+            setSelectedValue((keys) => {
+                if (multiple) {
+                    const newKeys = [...keys];
+                    const p = newKeys.indexOf(key);
+                    if (p === -1) {
+                        newKeys.push(key);
+                    } else {
+                        newKeys.splice(p, 1);
+                    }
+                    dispatch(
+                        createSendUpdateAction(
+                            updateVarName,
+                            newKeys,
+                            module,
+                            props.onChange,
+                            propagate,
+                            valueById ? undefined : getUpdateVar(updateVars, "lov")
+                        )
+                    );
+                    return newKeys;
+                } else {
+                    dispatch(
+                        createSendUpdateAction(
+                            updateVarName,
+                            key,
+                            module,
+                            props.onChange,
+                            propagate,
+                            valueById ? undefined : getUpdateVar(updateVars, "lov")
+                        )
+                    );
+                    return [key];
+                }
+            });
+        },
+        [updateVarName, dispatch, multiple, propagate, updateVars, valueById, props.onChange, module]
+    );
+
     const clickHandler = useCallback(
         (evt: MouseEvent<HTMLElement>) => {
             if (active) {
                 const { id: key = "" } = evt.currentTarget.dataset;
-                setSelectedValue((keys) => {
-                    if (multiple) {
-                        const newKeys = [...keys];
-                        const p = newKeys.indexOf(key);
-                        if (p === -1) {
-                            newKeys.push(key);
-                        } else {
-                            newKeys.splice(p, 1);
-                        }
-                        dispatch(
-                            createSendUpdateAction(
-                                updateVarName,
-                                newKeys,
-                                module,
-                                props.onChange,
-                                propagate,
-                                valueById ? undefined : getUpdateVar(updateVars, "lov")
-                            )
-                        );
-                        return newKeys;
-                    } else {
-                        dispatch(
-                            createSendUpdateAction(
-                                updateVarName,
-                                key,
-                                module,
-                                props.onChange,
-                                propagate,
-                                valueById ? undefined : getUpdateVar(updateVars, "lov")
-                            )
-                        );
-                        return [key];
-                    }
-                });
+                selectHandler(key);
             }
         },
-        [active, updateVarName, dispatch, multiple, propagate, updateVars, valueById, props.onChange, module]
+        [active, selectHandler]
+    );
+
+    const changeHandler = useCallback(
+        (evt: ChangeEvent<HTMLInputElement>) => {
+            if (active) {
+                const { id: key = "" } = (evt.currentTarget as HTMLElement).parentElement?.dataset || {};
+                selectHandler(key);
+            }
+        },
+        [active, selectHandler]
     );
 
     const handleChange = useCallback(
@@ -236,18 +262,61 @@ const Selector = (props: SelTreeProps) => {
 
     const handleInput = useCallback((e: React.ChangeEvent<HTMLInputElement>) => setSearchValue(e.target.value), []);
 
-    const dropdownValue = (dropdown &&
+    const dropdownValue = ((dropdown || isRadio) &&
         (multiple ? selectedValue : selectedValue.length > 0 ? selectedValue[0] : "")) as string[];
 
     return (
         <FormControl sx={controlSx} className={className}>
             {props.label ? (
-                <InputLabel disableAnimation className={!dropdown ? "static-label" : undefined}>
-                    {props.label}
-                </InputLabel>
+                isRadio || isCheck ? (
+                    <FormLabel>{props.label}</FormLabel>
+                ) : (
+                    <InputLabel disableAnimation className={!dropdown ? "static-label" : undefined}>
+                        {props.label}
+                    </InputLabel>
+                )
             ) : null}
-            <Tooltip title={hover || ""} placement={dropdown ? "top": undefined} >
-                {dropdown ? (
+            <Tooltip title={hover || ""} placement={dropdown ? "top" : undefined}>
+                {isRadio ? (
+                    <RadioGroup
+                        value={dropdownValue}
+                        onChange={handleChange}
+                        className={getSuffixedClassNames(className, "-radio-group")}
+                    >
+                        {lovList.map((item) => (
+                            <FormControlLabel
+                                key={item.id}
+                                value={item.id}
+                                control={<Radio />}
+                                label={
+                                    typeof item.item === "string" ? item.item : <LovImage item={item.item as Icon} />
+                                }
+                                style={getStyles(item.id, selectedValue, theme)}
+                                disabled={!active}
+                            />
+                        ))}
+                    </RadioGroup>
+                ) : isCheck ? (
+                    <FormGroup className={getSuffixedClassNames(className, "-check-group")}>
+                        {lovList.map((item) => (
+                            <FormControlLabel
+                                key={item.id}
+                                control={
+                                    <Checkbox
+                                        data-id={item.id}
+                                        checked={selectedValue.includes(item.id)}
+                                        onChange={changeHandler}
+                                    />
+                                }
+                                label={
+                                    typeof item.item === "string" ? item.item : <LovImage item={item.item as Icon} />
+                                }
+                                style={getStyles(item.id, selectedValue, theme)}
+                                disabled={!active}
+                            ></FormControlLabel>
+                        ))}
+                    </FormGroup>
+                ) : dropdown ? (
                     <Select
                         id={id}
                         multiple={multiple}

+ 1 - 0
frontend/taipy-gui/src/components/Taipy/lovUtils.tsx

@@ -31,6 +31,7 @@ export interface SelTreeProps extends LovProps, TaipyLabelProps {
     multiple?: boolean;
     width?: string | number;
     dropdown?: boolean;
+    mode?: string;
 }
 
 export interface LovProps<T = string | string[], U = string> extends TaipyActiveProps, TaipyChangeProps {

+ 2 - 1
taipy/gui/_renderers/factory.py

@@ -408,6 +408,7 @@ class _Factory:
                 ("width", PropertyType.string_or_number),
                 ("on_change", PropertyType.function),
                 ("label",),
+                ("mode",),
             ]
         )
         ._set_propagate(),
@@ -499,7 +500,7 @@ class _Factory:
                 ("id",),
                 ("hover_text", PropertyType.dynamic_string),
                 ("raw", PropertyType.boolean, False),
-                ("mode", PropertyType.string),
+                ("mode",),
             ]
         ),
         "toggle": lambda gui, control_type, attrs: _Builder(

+ 3 - 4
taipy/gui/custom/_page.py

@@ -17,15 +17,14 @@ from abc import ABC, abstractmethod
 from ..page import Page as BasePage
 from ..utils.singleton import _Singleton
 
-if t.TYPE_CHECKING:
-    from ..gui import Gui
-
 
 class Page(BasePage):
     """NOT DOCUMENTED
     A custom page for external application that can be added to Taipy GUI"""
 
-    def __init__(self, resource_handler: ResourceHandler, binding_variables: t.Optional[t.List[str]] = None, **kwargs) -> None:
+    def __init__(
+        self, resource_handler: ResourceHandler, binding_variables: t.Optional[t.List[str]] = None, **kwargs
+    ) -> None:
         if binding_variables is None:
             binding_variables = []
         super().__init__(**kwargs)

+ 5 - 3
taipy/gui/server.py

@@ -158,9 +158,11 @@ class _Server:
                 if resource_handler is None:
                     return (f"Invalid value for query {_Server._RESOURCE_HANDLER_ARG}", 404)
                 try:
-                    return resource_handler.get_resources(path, f"{static_folder}{os.path.sep}{_Server.__BASE_FILE_NAME}")
-                except Exception:
-                    raise RuntimeError("Can't get resources from custom resource handler")
+                    return resource_handler.get_resources(
+                        path, f"{static_folder}{os.path.sep}{_Server.__BASE_FILE_NAME}"
+                    )
+                except Exception as e:
+                    raise RuntimeError("Can't get resources from custom resource handler") from e
             if path == "" or path == "index.html" or "." not in path:
                 try:
                     return render_template(

+ 5 - 0
taipy/gui/viselements.json

@@ -866,6 +866,11 @@
             "type": "str",
             "default_value": "None",
             "doc": "The label associated with the selector when in dropdown mode."
+          },
+          {
+            "name": "mode",
+            "type": "str",
+            "doc": "Define the way the selector is displayed:<ul><li>&quote;radio&quote;: list of radio buttons</li><li>&quote;check&quote;: list of check buttons</li><li>any other value: selector as usual."
           }
         ]
       }