diff --git a/.gitignore b/.gitignore index e415eddaa..5dc5d9b28 100644 --- a/.gitignore +++ b/.gitignore @@ -32,5 +32,6 @@ custom-elements.json i18nRepo # Development environment +.env .envrc .direnv diff --git a/CHANGELOG.md b/CHANGELOG.md index b2646906f..6ef965393 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] +### Added +- Chat component + ## [6.2.2] - 2025-09-16 ### Fixed - Minor bug fixes around styles diff --git a/package-lock.json b/package-lock.json index c4d1e7404..2a895d289 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,13 +16,13 @@ }, "devDependencies": { "@biomejs/biome": "~2.2.4", - "@custom-elements-manifest/analyzer": "^0.10.5", + "@custom-elements-manifest/analyzer": "^0.10.6", "@igniteui/material-icons-extended": "^3.1.0", "@open-wc/testing": "^4.0.0", - "@storybook/addon-a11y": "^9.1.5", - "@storybook/addon-docs": "^9.1.5", - "@storybook/addon-links": "^9.1.5", - "@storybook/web-components-vite": "^9.1.5", + "@storybook/addon-a11y": "^9.1.6", + "@storybook/addon-docs": "^9.1.6", + "@storybook/addon-links": "^9.1.6", + "@storybook/web-components-vite": "^9.1.6", "@types/mocha": "^10.0.10", "@web/dev-server-esbuild": "^1.0.4", "@web/test-runner": "^0.20.2", @@ -36,8 +36,8 @@ "globby": "^14.1.0", "husky": "^9.1.7", "ig-typedoc-theme": "^6.2.3", - "igniteui-theming": "^19.3.1", - "keep-a-changelog": "^2.7.0", + "igniteui-theming": "^20.0.0", + "keep-a-changelog": "^2.7.1", "lint-staged": "^16.1.6", "lit-analyzer": "^2.0.3", "madge": "^8.0.0", @@ -48,7 +48,7 @@ "rimraf": "^6.0.1", "sass-embedded": "~1.92.1", "sinon": "^21.0.0", - "storybook": "^9.1.5", + "storybook": "^9.1.6", "stylelint": "^16.24.0", "stylelint-config-standard-scss": "^16.0.0", "stylelint-prettier": "^5.0.3", @@ -58,7 +58,13 @@ "typedoc": "~0.27.9", "typedoc-plugin-localization": "^3.0.6", "typescript": "^5.8.3", - "vite": "^7.1.5" + "vite": "^7.1.6" + }, + "peerDependencies": { + "dompurify": "^3.2.7", + "marked": "^16.3.0", + "marked-shiki": "^1.2.1", + "shiki": "^3.12.2" } }, "node_modules/@adobe/css-tools": { @@ -104,13 +110,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz", - "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.7" + "@babel/types": "^7.28.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -120,9 +126,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "dev": true, "license": "MIT", "engines": { @@ -130,9 +136,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz", - "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -313,6 +319,37 @@ "dev": true, "license": "(Apache-2.0 AND BSD-3-Clause)" }, + "node_modules/@cacheable/memoize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cacheable/memoize/-/memoize-2.0.1.tgz", + "integrity": "sha512-WBLH37SynkCa39S6IrTSMQF3Wdv4/51WxuU5TuCNEqZcLgLGHme8NUxRTcDIO8ZZFXlslWbh9BD3DllixgPg6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/utils": "^2.0.1" + } + }, + "node_modules/@cacheable/memory": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.1.tgz", + "integrity": "sha512-Ufc7iQnRKFC8gjZVGOTOsMwM/vZtmsw3LafvctVXPm835ElgK3DpMe1U5i9sd6OieSkyJhXbAT2Q2FosXBBbAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/memoize": "^2.0.1", + "@cacheable/utils": "^2.0.1", + "@keyv/bigmap": "^1.0.0", + "hookified": "^1.12.0", + "keyv": "^5.5.1" + } + }, + "node_modules/@cacheable/utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.0.1.tgz", + "integrity": "sha512-sxHjO6wKn4/0wHCFYbh6tljj+ciP9BKgyBi09NLsor3sN+nu/Rt3FwLw6bYp7bp8usHpmcwUozrB/u4RuSw/eg==", + "dev": true, + "license": "MIT" + }, "node_modules/@csstools/css-parser-algorithms": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", @@ -404,13 +441,13 @@ } }, "node_modules/@custom-elements-manifest/analyzer": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/@custom-elements-manifest/analyzer/-/analyzer-0.10.5.tgz", - "integrity": "sha512-Y9iUIhTDtcoaiH9XLwkK5POTxVJkcDuN9buCH4kQJmPmTMdm8Fhq7yk0l8Pu3TYC+RuXy6xA49+1IwvFJLF5mg==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@custom-elements-manifest/analyzer/-/analyzer-0.10.6.tgz", + "integrity": "sha512-zWz7BIjY1o7DUrHZPFpsSNtQjkEbLPbEkH1zxSJB3RX/SvyKnw8mvdkTl7nDYgVYEzokIDMZhdPrPzqpV0OXYg==", "dev": true, "license": "MIT", "dependencies": { - "@custom-elements-manifest/find-dependencies": "^0.0.5", + "@custom-elements-manifest/find-dependencies": "^0.0.6", "@github/catalyst": "^1.6.0", "@web/config-loader": "0.1.3", "chokidar": "3.5.2", @@ -482,13 +519,13 @@ } }, "node_modules/@custom-elements-manifest/find-dependencies": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@custom-elements-manifest/find-dependencies/-/find-dependencies-0.0.5.tgz", - "integrity": "sha512-fKIMMZCDFSoL2ySUoz8knWgpV4jpb0lUXgLOvdZQMQFHxgxz1PqOJpUIypwvEVyKk3nEHRY4f10gNol02HjeCg==", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@custom-elements-manifest/find-dependencies/-/find-dependencies-0.0.6.tgz", + "integrity": "sha512-2iVksJ156XuaeeC6jB6oMG6k9ROHS3W1delwJLL804yQMri9NnQW78JDCYMtFfW8b4locUG+3+hrtAHxk+fNGg==", "dev": true, "license": "ISC", "dependencies": { - "es-module-lexer": "^0.9.3" + "rs-module-lexer": "^2.5.1" } }, "node_modules/@deno/shim-deno": { @@ -550,20 +587,20 @@ } }, "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.2.1.tgz", + "integrity": "sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==", "dev": true, "license": "MIT", "funding": { "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/JounQin" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", "cpu": [ "ppc64" ], @@ -578,9 +615,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", "cpu": [ "arm" ], @@ -595,9 +632,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", "cpu": [ "arm64" ], @@ -612,9 +649,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", "cpu": [ "x64" ], @@ -629,9 +666,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", "cpu": [ "arm64" ], @@ -646,9 +683,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", "cpu": [ "x64" ], @@ -663,9 +700,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", "cpu": [ "arm64" ], @@ -680,9 +717,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", "cpu": [ "x64" ], @@ -697,9 +734,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", "cpu": [ "arm" ], @@ -714,9 +751,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", "cpu": [ "arm64" ], @@ -731,9 +768,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", "cpu": [ "ia32" ], @@ -748,9 +785,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", "cpu": [ "loong64" ], @@ -765,9 +802,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", "cpu": [ "mips64el" ], @@ -782,9 +819,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", "cpu": [ "ppc64" ], @@ -799,9 +836,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", "cpu": [ "riscv64" ], @@ -816,9 +853,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", "cpu": [ "s390x" ], @@ -833,9 +870,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", "cpu": [ "x64" ], @@ -850,9 +887,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", "cpu": [ "arm64" ], @@ -867,9 +904,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", "cpu": [ "x64" ], @@ -884,9 +921,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", "cpu": [ "arm64" ], @@ -901,9 +938,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", "cpu": [ "x64" ], @@ -917,10 +954,27 @@ "node": ">=18" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", "cpu": [ "x64" ], @@ -935,9 +989,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", "cpu": [ "arm64" ], @@ -952,9 +1006,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", "cpu": [ "ia32" ], @@ -969,9 +1023,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", "cpu": [ "x64" ], @@ -1032,6 +1086,28 @@ "@shikijs/vscode-textmate": "^10.0.1" } }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/engine-oniguruma": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.2.tgz", + "integrity": "sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1" + } + }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/types": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.29.2.tgz", + "integrity": "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.1", + "@types/hast": "^3.0.4" + } + }, "node_modules/@github/catalyst": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/@github/catalyst/-/catalyst-1.7.0.tgz", @@ -1190,16 +1266,16 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -1207,17 +1283,30 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@keyv/bigmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.0.1.tgz", + "integrity": "sha512-dZ7TMshK6brpuGPPRoq4pHNzNH4KTWaxVPB7KEnPErlgJpc+jG1Oyx3sw6nBFiZ0OCKwC1zU6skMEG7H421f9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "hookified": "^1.12.0" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/@keyv/serialize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.0.tgz", - "integrity": "sha512-RlDgexML7Z63Q8BSaqhXdCYNBy/JQnqYIwxofUrNLGCblOMHp+xux2Q8nLMLlPpgHQPoU0Do8Z6btCpRBEqZ8g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", "dev": true, "license": "MIT" }, "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.3.0.tgz", - "integrity": "sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz", + "integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==", "license": "BSD-3-Clause" }, "node_modules/@lit-labs/virtualizer": { @@ -1240,12 +1329,12 @@ } }, "node_modules/@lit/reactive-element": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.0.tgz", - "integrity": "sha512-L2qyoZSQClcBmq0qajBVbhYEcG6iK0XfLn66ifLe/RfC0/ihpc+pl0Wdn8bJ8o+hj38cG0fGXRgSS20MuXn7qA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.1.tgz", + "integrity": "sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==", "license": "BSD-3-Clause", "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0" + "@lit-labs/ssr-dom-shim": "^1.4.0" } }, "node_modules/@mdn/browser-compat-data": { @@ -1256,9 +1345,9 @@ "license": "CC0-1.0" }, "node_modules/@mdx-js/react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", - "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", + "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "dev": true, "license": "MIT", "dependencies": { @@ -1694,18 +1783,18 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "2.10.5", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.5.tgz", - "integrity": "sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==", + "version": "2.10.10", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.10.tgz", + "integrity": "sha512-3ZG500+ZeLql8rE0hjfhkycJjDj0pI/btEh3L9IkWUYcOrgP0xCNRq3HbtbqOPbvDhFaAWD88pDFtlLv8ns8gA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "debug": "^4.4.1", + "debug": "^4.4.3", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", "semver": "^7.7.2", - "tar-fs": "^3.0.8", + "tar-fs": "^3.1.0", "yargs": "^17.7.2" }, "bin": { @@ -1716,9 +1805,9 @@ } }, "node_modules/@puppeteer/browsers/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -1766,9 +1855,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", - "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1802,9 +1891,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz", - "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.2.tgz", + "integrity": "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==", "cpu": [ "arm" ], @@ -1816,9 +1905,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz", - "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.2.tgz", + "integrity": "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==", "cpu": [ "arm64" ], @@ -1830,9 +1919,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz", - "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.2.tgz", + "integrity": "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==", "cpu": [ "arm64" ], @@ -1844,9 +1933,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz", - "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.2.tgz", + "integrity": "sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A==", "cpu": [ "x64" ], @@ -1858,9 +1947,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz", - "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.2.tgz", + "integrity": "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==", "cpu": [ "arm64" ], @@ -1872,9 +1961,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz", - "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.2.tgz", + "integrity": "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==", "cpu": [ "x64" ], @@ -1886,9 +1975,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz", - "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.2.tgz", + "integrity": "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==", "cpu": [ "arm" ], @@ -1900,9 +1989,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz", - "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.2.tgz", + "integrity": "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==", "cpu": [ "arm" ], @@ -1914,9 +2003,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz", - "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.2.tgz", + "integrity": "sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg==", "cpu": [ "arm64" ], @@ -1928,9 +2017,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz", - "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.2.tgz", + "integrity": "sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ==", "cpu": [ "arm64" ], @@ -1941,10 +2030,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz", - "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.50.2.tgz", + "integrity": "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==", "cpu": [ "loong64" ], @@ -1955,10 +2044,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz", - "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.2.tgz", + "integrity": "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==", "cpu": [ "ppc64" ], @@ -1970,9 +2059,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz", - "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.2.tgz", + "integrity": "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==", "cpu": [ "riscv64" ], @@ -1984,9 +2073,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz", - "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.2.tgz", + "integrity": "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==", "cpu": [ "riscv64" ], @@ -1998,9 +2087,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz", - "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.2.tgz", + "integrity": "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==", "cpu": [ "s390x" ], @@ -2012,9 +2101,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz", - "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.2.tgz", + "integrity": "sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA==", "cpu": [ "x64" ], @@ -2026,9 +2115,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz", - "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.2.tgz", + "integrity": "sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw==", "cpu": [ "x64" ], @@ -2039,10 +2128,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.2.tgz", + "integrity": "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz", - "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.2.tgz", + "integrity": "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==", "cpu": [ "arm64" ], @@ -2054,9 +2157,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz", - "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.2.tgz", + "integrity": "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==", "cpu": [ "ia32" ], @@ -2068,9 +2171,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz", - "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.2.tgz", + "integrity": "sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA==", "cpu": [ "x64" ], @@ -2081,25 +2184,70 @@ "win32" ] }, + "node_modules/@shikijs/core": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.12.2.tgz", + "integrity": "sha512-L1Safnhra3tX/oJK5kYHaWmLEBJi1irASwewzY3taX5ibyXyMkkSDZlq01qigjryOBwrXSdFgTiZ3ryzSNeu7Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@shikijs/types": "3.12.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.12.2.tgz", + "integrity": "sha512-Nm3/azSsaVS7hk6EwtHEnTythjQfwvrO5tKqMlaH9TwG1P+PNaR8M0EAKZ+GaH2DFwvcr4iSfTveyxMIvXEHMw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@shikijs/types": "3.12.2", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.3" + } + }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.2.tgz", - "integrity": "sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==", - "dev": true, + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.12.2.tgz", + "integrity": "sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w==", "license": "MIT", + "peer": true, "dependencies": { - "@shikijs/types": "1.29.2", - "@shikijs/vscode-textmate": "^10.0.1" + "@shikijs/types": "3.12.2", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.12.2.tgz", + "integrity": "sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww==", + "license": "MIT", + "peer": true, + "dependencies": { + "@shikijs/types": "3.12.2" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.12.2.tgz", + "integrity": "sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@shikijs/types": "3.12.2" } }, "node_modules/@shikijs/types": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.29.2.tgz", - "integrity": "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==", - "dev": true, + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.12.2.tgz", + "integrity": "sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==", "license": "MIT", + "peer": true, "dependencies": { - "@shikijs/vscode-textmate": "^10.0.1", + "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, @@ -2107,7 +2255,6 @@ "version": "10.0.2", "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "dev": true, "license": "MIT" }, "node_modules/@sindresorhus/merge-streams": { @@ -2144,14 +2291,13 @@ } }, "node_modules/@sinonjs/samsam": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", - "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.3.tgz", + "integrity": "sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", - "lodash.get": "^4.4.2", "type-detect": "^4.1.0" } }, @@ -2173,9 +2319,9 @@ "license": "MIT" }, "node_modules/@storybook/addon-a11y": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-9.1.5.tgz", - "integrity": "sha512-IMS325fT/3sAOwSl285Wl7gBKd4NK58ebsIUZytyzLJ7Bv6BgxUdRBZ2E0822WP6zofYTkOk7/PDmBfzEWgY2g==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-9.1.6.tgz", + "integrity": "sha512-jpuzbZlT8G1hx4N6nhhmxy6Lu+Xnz1oeGb2/pm+rKx2fZ4oy7yGRliRNOvpTy8MbkpnfMoLLrcqc66s/kfdf3A==", "dev": true, "license": "MIT", "dependencies": { @@ -2187,20 +2333,20 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.5" + "storybook": "^9.1.6" } }, "node_modules/@storybook/addon-docs": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-9.1.5.tgz", - "integrity": "sha512-q1j5RRElxFSnHOh60eS3dS2TAyAHzcQeH/2B9UXo6MUHu7HmhNpw3qt2YibIw0zEogHCvZhLNx6TNzSy+7wRUw==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-9.1.6.tgz", + "integrity": "sha512-4ZE/T2Ayw77/v2ersAk/VM7vlvqV2zCNFwt0uvOzUR1VZ9VqZCHhsfy/IyBPeKt6Otax3EpfE1LkH4slfceB0g==", "dev": true, "license": "MIT", "dependencies": { "@mdx-js/react": "^3.0.0", - "@storybook/csf-plugin": "9.1.5", + "@storybook/csf-plugin": "9.1.6", "@storybook/icons": "^1.4.0", - "@storybook/react-dom-shim": "9.1.5", + "@storybook/react-dom-shim": "9.1.6", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "ts-dedent": "^2.0.0" @@ -2210,13 +2356,13 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.5" + "storybook": "^9.1.6" } }, "node_modules/@storybook/addon-links": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-9.1.5.tgz", - "integrity": "sha512-jJmUgORT9/CF7t8EgN6P8PhTpmKB9PzIKGpSAFm+pzLgvVvm956656BMRwK4MpfNz+AeduhPPdSGmZBOwiyMDA==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-9.1.6.tgz", + "integrity": "sha512-TY9d3MVylNHNQswlwsvXMaGNZXGaEr8RMvV9BES65BC4GAPnHM6W1I9mEf1ckg+uSFBf43ZMOsYulSMo86ddpQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2228,7 +2374,7 @@ }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^9.1.5" + "storybook": "^9.1.6" }, "peerDependenciesMeta": { "react": { @@ -2237,13 +2383,13 @@ } }, "node_modules/@storybook/builder-vite": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-9.1.5.tgz", - "integrity": "sha512-sgt/9+Yl/5O7Bj5hdbHfadN8e/e4CNiDZKDcbLOMpOjKKoqF8vm19I1QocWIAiKjTOhF+4E9v9LddjtAGnfqHQ==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-9.1.6.tgz", + "integrity": "sha512-AUoSjXr4MvtkFQkfFfZSXrqVM0z80DX0sebm80nODu/qFhsJIU5trNP+XDYY8ClODERXd5QSZJyOyH9nOz60SA==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/csf-plugin": "9.1.5", + "@storybook/csf-plugin": "9.1.6", "ts-dedent": "^2.0.0" }, "funding": { @@ -2251,14 +2397,14 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.5", + "storybook": "^9.1.6", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, "node_modules/@storybook/csf-plugin": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-9.1.5.tgz", - "integrity": "sha512-PmHuF+j11Z7BxAI2/4wQYn0gH1d67gNvycyR+EWgp4P/AWam9wFbuI/T1R45CRQTV2/VrfGdts/tFrvo5kXWig==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-9.1.6.tgz", + "integrity": "sha512-cz4Y+OYCtuovFNwoLkIKk0T62clrRTYf26Bbo1gdIGuX/W3JPP/LnN97sP2/0nfF6heZqCdEwb47k7RubkxXZg==", "dev": true, "license": "MIT", "dependencies": { @@ -2269,7 +2415,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.5" + "storybook": "^9.1.6" } }, "node_modules/@storybook/global": { @@ -2280,9 +2426,9 @@ "license": "MIT" }, "node_modules/@storybook/icons": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.4.0.tgz", - "integrity": "sha512-Td73IeJxOyalzvjQL+JXx72jlIYHgs+REaHiREOqfpo3A2AYYG71AUbcv+lg7mEDIweKVCxsMQ0UKo634c8XeA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.6.0.tgz", + "integrity": "sha512-hcFZIjW8yQz8O8//2WTIXylm5Xsgc+lW9ISLgUk1xGmptIJQRdlhVIXCpSyLrQaaRiyhQRaVg7l3BD9S216BHw==", "dev": true, "license": "MIT", "engines": { @@ -2294,9 +2440,9 @@ } }, "node_modules/@storybook/react-dom-shim": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-9.1.5.tgz", - "integrity": "sha512-blSq9uzSYnfgEYPHYKgM5O14n8hbXNiXx2GiVJyDSg8QPNicbsBg+lCb1TC7/USfV26pNZr/lGNNKGkcCEN6Gw==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-9.1.6.tgz", + "integrity": "sha512-Px4duzPMTPqI3kes6eUyYjWpEeJ0AOCCeSDCBDm9rzlf4a+eXlxfhkcVWft3viCDiIkc0vtYagb2Yu7bcSIypg==", "dev": true, "license": "MIT", "funding": { @@ -2306,13 +2452,13 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^9.1.5" + "storybook": "^9.1.6" } }, "node_modules/@storybook/web-components": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/@storybook/web-components/-/web-components-9.1.5.tgz", - "integrity": "sha512-m4JuawTUd7SfdGSEB1/zY3b62XktXi/jsymgZ+EUFMYnBdiouEl/9IMQ53FGm91Pp+5DAXLDPtTpWXiutu93Wg==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@storybook/web-components/-/web-components-9.1.6.tgz", + "integrity": "sha512-nbhm14etM1Mf+xz2NmBP7qKc7V1lvZMbRxtMFHc3LmxYHQGlUhvp+v0aH48OsSY+jdAauw8ZsrfkBede46MFWA==", "dev": true, "license": "MIT", "dependencies": { @@ -2329,18 +2475,18 @@ }, "peerDependencies": { "lit": "^2.0.0 || ^3.0.0", - "storybook": "^9.1.5" + "storybook": "^9.1.6" } }, "node_modules/@storybook/web-components-vite": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/@storybook/web-components-vite/-/web-components-vite-9.1.5.tgz", - "integrity": "sha512-7xLw/cD7+z2+u1Q/vEUV+AMaUGQMOporCJQ1hoJgUd4HkTrYdB6okfFUg/Gd/96WUdgZPZ9ZFDwDeI0SEKhxpw==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@storybook/web-components-vite/-/web-components-vite-9.1.6.tgz", + "integrity": "sha512-OlfNDu2N2hgi0NuiizmuzuUKiESfPJB+57+shGG48btSqzI9+W4jrQGVceLPPnUv9zXlConMlrFOe+HGi9fs9Q==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/builder-vite": "9.1.5", - "@storybook/web-components": "9.1.5" + "@storybook/builder-vite": "9.1.6", + "@storybook/web-components": "9.1.6" }, "engines": { "node": ">=20.0.0" @@ -2350,7 +2496,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.5" + "storybook": "^9.1.6" } }, "node_modules/@testing-library/dom": { @@ -2664,9 +2810,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", - "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", + "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2680,7 +2826,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "*" @@ -2761,6 +2906,16 @@ "@types/koa": "*" } }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/mdx": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", @@ -2783,13 +2938,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.0.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.4.tgz", - "integrity": "sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==", + "version": "24.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz", + "integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.8.0" + "undici-types": "~7.12.0" } }, "node_modules/@types/parse5": { @@ -2814,9 +2969,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.1.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", - "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", + "version": "19.1.13", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.13.tgz", + "integrity": "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==", "dev": true, "license": "MIT", "peer": true, @@ -2892,7 +3047,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, "license": "MIT" }, "node_modules/@types/ws": { @@ -2916,28 +3070,172 @@ "@types/node": "*" } }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.0.tgz", + "integrity": "sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.44.0", + "@typescript-eslint/types": "^8.44.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/project-service/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.0.tgz", + "integrity": "sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/@typescript-eslint/types": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", - "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.0.tgz", + "integrity": "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.0.tgz", + "integrity": "sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.44.0", + "@typescript-eslint/tsconfig-utils": "8.44.0", + "@typescript-eslint/types": "8.44.0", + "@typescript-eslint/visitor-keys": "8.44.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz", - "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.0.tgz", + "integrity": "sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/types": "8.44.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -2948,6 +3246,13 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC", + "peer": true + }, "node_modules/@vitest/expect": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", @@ -3061,63 +3366,63 @@ "license": "MIT" }, "node_modules/@vue/compiler-core": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.17.tgz", - "integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.21.tgz", + "integrity": "sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.5", - "@vue/shared": "3.5.17", + "@babel/parser": "^7.28.3", + "@vue/shared": "3.5.21", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz", - "integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.21.tgz", + "integrity": "sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.17", - "@vue/shared": "3.5.17" + "@vue/compiler-core": "3.5.21", + "@vue/shared": "3.5.21" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz", - "integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.21.tgz", + "integrity": "sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.5", - "@vue/compiler-core": "3.5.17", - "@vue/compiler-dom": "3.5.17", - "@vue/compiler-ssr": "3.5.17", - "@vue/shared": "3.5.17", + "@babel/parser": "^7.28.3", + "@vue/compiler-core": "3.5.21", + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-ssr": "3.5.21", + "@vue/shared": "3.5.21", "estree-walker": "^2.0.2", - "magic-string": "^0.30.17", + "magic-string": "^0.30.18", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz", - "integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.21.tgz", + "integrity": "sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.17", - "@vue/shared": "3.5.17" + "@vue/compiler-dom": "3.5.21", + "@vue/shared": "3.5.21" } }, "node_modules/@vue/shared": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.17.tgz", - "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.21.tgz", + "integrity": "sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==", "dev": true, "license": "MIT" }, @@ -3223,13 +3528,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@web/dev-server-core/node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, - "license": "MIT" - }, "node_modules/@web/dev-server-core/node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -3570,13 +3868,166 @@ "node": ">=8" } }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "license": "MIT", - "dependencies": { + "node_modules/@xn-sakina/rml-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@xn-sakina/rml-darwin-arm64/-/rml-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-opF0AyFOYXkVoibAFh6tLgYHETduN3/aubxGJXOYkAcW4b4YMmDKXqU7UDjsNse3D/5T+8XFxUIl4E0+lHPRxg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14" + } + }, + "node_modules/@xn-sakina/rml-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@xn-sakina/rml-darwin-x64/-/rml-darwin-x64-2.5.1.tgz", + "integrity": "sha512-kWcLQgAZ7aNP10URYxzsWFJH6rMZvGmX904644TEMzTrv1EaqZj0qQwQ34aFq5WX9ze0/MpzlvZ/w0hJIqQH8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14" + } + }, + "node_modules/@xn-sakina/rml-linux-arm-gnueabihf": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@xn-sakina/rml-linux-arm-gnueabihf/-/rml-linux-arm-gnueabihf-2.5.1.tgz", + "integrity": "sha512-HlQ85PvF+MyOeAScdarAkPpI+PS0u8qh9AAvsRRolhQ8kehHvTzMYFiLAerIZEaRHTHMpgVIhttcZ6ZWKdTUpQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14" + } + }, + "node_modules/@xn-sakina/rml-linux-arm64-gnu": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@xn-sakina/rml-linux-arm64-gnu/-/rml-linux-arm64-gnu-2.5.1.tgz", + "integrity": "sha512-9GQDgAUNqErwC/OftCCch0199zjALgVopTu+FSwQS2ECW4n+sumeyF18xtGQAj4NQUYNn9HseT+7cn3gk7f7HA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14" + } + }, + "node_modules/@xn-sakina/rml-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@xn-sakina/rml-linux-arm64-musl/-/rml-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-pN+F/V9H/HZvlovD9T/zeAvXE45qvzti8WD9m7T+fa9A6qdmBwSJTFZeEa0c+lP66r+1OSv9BIir1iMi99wvHw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14" + } + }, + "node_modules/@xn-sakina/rml-linux-x64-gnu": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@xn-sakina/rml-linux-x64-gnu/-/rml-linux-x64-gnu-2.5.1.tgz", + "integrity": "sha512-9y5LnhD0N9Hh36CwhlYwO/AiAz+LGAQvYLt9JfGuSTy/m5A4npqSOC4zaGx3hjAIu56FyxfHP3PJHW3opw0mzg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14" + } + }, + "node_modules/@xn-sakina/rml-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@xn-sakina/rml-linux-x64-musl/-/rml-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-x5TJC6KRG9ATZvVqL5TJBUGN3sVjbw00TCulrdVcxWAv352sxM+yYvxZsMq6yxbU8Y3jAOX36mbZSKcAkR4XYg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14" + } + }, + "node_modules/@xn-sakina/rml-win32-arm64-msvc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@xn-sakina/rml-win32-arm64-msvc/-/rml-win32-arm64-msvc-2.5.1.tgz", + "integrity": "sha512-KCe+wursdZFNM3yfQgwX+6Bgs40t4bg2LLz1DXslZ35dEM64bbAngi4anqr5tdllS4146+Gn5L71DGrxytR8Kw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14" + } + }, + "node_modules/@xn-sakina/rml-win32-x64-msvc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@xn-sakina/rml-win32-x64-msvc/-/rml-win32-x64-msvc-2.5.1.tgz", + "integrity": "sha512-v56lTBAmggAppgohjSVwxbhWniaN+KP5HK/zTQO2OaTdSBUHzufFp9Wt/M/bMRvuhjZzkAp2WNkiYWLJyB3sXg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" }, @@ -3598,9 +4049,9 @@ } }, "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", "engines": { @@ -3840,11 +4291,19 @@ } }, "node_modules/b4a": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", - "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.1.tgz", + "integrity": "sha512-ZovbrBV0g6JxK5cGUF1Suby1vLfKjv4RWi8IxoaO/Mon8BDD9I21RxjHFtgQ+kskJqLAVyQZly3uMBui+vhc8Q==", "dev": true, - "license": "Apache-2.0" + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } }, "node_modules/balanced-match": { "version": "1.0.2", @@ -3854,24 +4313,26 @@ "license": "MIT" }, "node_modules/bare-events": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", - "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.7.0.tgz", + "integrity": "sha512-b3N5eTW1g7vXkw+0CXh/HazGTcO5KYuu/RCNaJbDMPI6LHDi+7qe8EmxKUVe1sUbY2KZOVZFyj62x0OEz9qyAA==", "dev": true, "license": "Apache-2.0", "optional": true }, "node_modules/bare-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.5.tgz", - "integrity": "sha512-1zccWBMypln0jEE05LzZt+V/8y8AQsQQqxtklqaIyg5nu6OAYFhZxPXinJTSG+kU5qyNmeLgcn9AW7eHiCHVLA==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.4.4.tgz", + "integrity": "sha512-Q8yxM1eLhJfuM7KXVP3zjhBvtMJCYRByoTT+wHXjpdMELv0xICFJX+1w4c7csa+WZEOsq4ItJ4RGwvzid6m/dw==", "dev": true, "license": "Apache-2.0", "optional": true, "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", - "bare-stream": "^2.6.4" + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" }, "engines": { "bare": ">=1.16.0" @@ -3886,9 +4347,9 @@ } }, "node_modules/bare-os": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", - "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz", + "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==", "dev": true, "license": "Apache-2.0", "optional": true, @@ -3908,9 +4369,9 @@ } }, "node_modules/bare-stream": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz", - "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz", + "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==", "dev": true, "license": "Apache-2.0", "optional": true, @@ -3930,6 +4391,17 @@ } } }, + "node_modules/bare-url": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.2.2.tgz", + "integrity": "sha512-g+ueNGKkrjMazDG3elZO1pNs3HY5+mMmOet1jtKyhOaCnkLzitxf26z7hoAEkDNgdNmnc1KIlt/dw6Po6xZMpA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-path": "^3.0.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -3961,6 +4433,16 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.5.tgz", + "integrity": "sha512-TiU4qUT9jdCuh4aVOG7H1QozyeI2sZRqoRPdqBIaslfNt4WUSanRBueAwl2x5jt4rXBMim3lIN2x6yT8PDi24Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/basic-ftp": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", @@ -4115,9 +4597,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "version": "4.26.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", + "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", "dev": true, "funding": [ { @@ -4135,9 +4617,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", + "baseline-browser-mapping": "^2.8.3", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "node-releases": "^2.0.21", "update-browserslist-db": "^1.1.3" }, "bin": { @@ -4221,14 +4704,17 @@ } }, "node_modules/cacheable": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.10.4.tgz", - "integrity": "sha512-Gd7ccIUkZ9TE2odLQVS+PDjIvQCdJKUlLdJRVvZu0aipj07Qfx+XIej7hhDrKGGoIxV5m5fT/kOJNJPQhQneRg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.0.1.tgz", + "integrity": "sha512-MSKxcybpxB5kcWKpj+1tPBm2os4qKKGxDovsZmLhZmWIDYp8EgtC45C5zk1fLe1IC9PpI4ZE4eyryQH0N10PKA==", "dev": true, "license": "MIT", "dependencies": { - "hookified": "^1.11.0", - "keyv": "^5.5.0" + "@cacheable/memoize": "^2.0.1", + "@cacheable/memory": "^2.0.1", + "@cacheable/utils": "^2.0.1", + "hookified": "^1.12.0", + "keyv": "^5.5.1" } }, "node_modules/call-bind-apply-helpers": { @@ -4286,9 +4772,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001726", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", - "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", + "version": "1.0.30001743", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", + "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==", "dev": true, "funding": [ { @@ -4306,6 +4792,17 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/cem-plugin-expanded-types": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/cem-plugin-expanded-types/-/cem-plugin-expanded-types-1.4.0.tgz", @@ -4374,6 +4871,28 @@ "url": "https://github.com/chalk/chalk-template?sponsor=1" } }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/check-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", @@ -4426,9 +4945,9 @@ } }, "node_modules/chromium-bidi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-5.1.0.tgz", - "integrity": "sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-8.0.0.tgz", + "integrity": "sha512-d1VmE0FD7lxZQHzcDUCKZSNRtRwISXDsdg4HjdTR5+Ll5nQ/vzU12JeNmupD6VWffrPSlrnGhEWlLESKH3VO+g==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4473,17 +4992,17 @@ } }, "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.0.tgz", + "integrity": "sha512-7JDGG+4Zp0CsknDCedl0DYdaeOhc46QNpXi3NLQblkZpXXgA6LncLDUUyvrjSvZeF3VRQa+KiMGomazQrC1V8g==", "dev": true, "license": "MIT", "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" + "slice-ansi": "^7.1.0", + "string-width": "^8.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4504,13 +5023,6 @@ "node": ">=12" } }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, "node_modules/cliui/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -4633,6 +5145,17 @@ "dev": true, "license": "MIT" }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/command-line-args": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.2.tgz", @@ -4676,9 +5199,9 @@ } }, "node_modules/commander": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", - "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", "dev": true, "license": "MIT", "engines": { @@ -5150,7 +5673,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5300,125 +5822,6 @@ "typescript": "^5.4.4" } }, - "node_modules/detective-typescript/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz", - "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.38.0", - "@typescript-eslint/tsconfig-utils": "8.38.0", - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/detective-typescript/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz", - "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.38.0", - "@typescript-eslint/types": "^8.38.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/detective-typescript/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz", - "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/detective-typescript/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/detective-typescript/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/detective-typescript/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/detective-typescript/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/detective-vue2": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/detective-vue2/-/detective-vue2-2.2.0.tgz", @@ -5453,10 +5856,24 @@ "node": ">= 0.8.0" } }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "peer": true, + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/devtools-protocol": { - "version": "0.0.1464554", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1464554.tgz", - "integrity": "sha512-CAoP3lYfwAGQTaAXYvA6JZR0fjGUb7qec1qf4mToyoH2TZgUFeIqYcjh6f9jNuhHfuZiEdH+PONHYrLhRQX6aw==", + "version": "0.0.1495869", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1495869.tgz", + "integrity": "sha512-i+bkd9UYFis40RcnkW7XrOprCujXRAHg62IVh/Ah3G8MmNXpCGt1m0dTFhSdx/AVs8XEMbdOGRwdkR1Bcta8AA==", "dev": true, "license": "BSD-3-Clause" }, @@ -5516,6 +5933,16 @@ "license": "MIT", "peer": true }, + "node_modules/dompurify": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", + "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "peer": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -5570,16 +5997,16 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.177", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz", - "integrity": "sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g==", + "version": "1.5.221", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.221.tgz", + "integrity": "sha512-/1hFJ39wkW01ogqSyYoA4goOXOtMRy6B+yvA1u42nnsEGtHzIzmk93aPISumVQeblj47JUHLC9coCjUxb1EvtQ==", "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", - "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, @@ -5743,9 +6170,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", "dev": true, "license": "MIT", "dependencies": { @@ -5793,9 +6220,9 @@ } }, "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5830,9 +6257,9 @@ } }, "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, @@ -5850,9 +6277,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", - "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -5863,31 +6290,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.5", - "@esbuild/android-arm": "0.25.5", - "@esbuild/android-arm64": "0.25.5", - "@esbuild/android-x64": "0.25.5", - "@esbuild/darwin-arm64": "0.25.5", - "@esbuild/darwin-x64": "0.25.5", - "@esbuild/freebsd-arm64": "0.25.5", - "@esbuild/freebsd-x64": "0.25.5", - "@esbuild/linux-arm": "0.25.5", - "@esbuild/linux-arm64": "0.25.5", - "@esbuild/linux-ia32": "0.25.5", - "@esbuild/linux-loong64": "0.25.5", - "@esbuild/linux-mips64el": "0.25.5", - "@esbuild/linux-ppc64": "0.25.5", - "@esbuild/linux-riscv64": "0.25.5", - "@esbuild/linux-s390x": "0.25.5", - "@esbuild/linux-x64": "0.25.5", - "@esbuild/netbsd-arm64": "0.25.5", - "@esbuild/netbsd-x64": "0.25.5", - "@esbuild/openbsd-arm64": "0.25.5", - "@esbuild/openbsd-x64": "0.25.5", - "@esbuild/sunos-x64": "0.25.5", - "@esbuild/win32-arm64": "0.25.5", - "@esbuild/win32-ia32": "0.25.5", - "@esbuild/win32-x64": "0.25.5" + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" } }, "node_modules/esbuild-register": { @@ -5904,9 +6332,9 @@ } }, "node_modules/esbuild-register/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -6108,9 +6536,9 @@ } }, "node_modules/extract-zip/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -6187,9 +6615,9 @@ } }, "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "dev": true, "funding": [ { @@ -6335,15 +6763,15 @@ } }, "node_modules/flat-cache": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.13.tgz", - "integrity": "sha512-gmtS2PaUjSPa4zjObEIn4WWliKyZzYljgxODBfxugpK6q6HU9ClXzgCJ+nlcPKY9Bt090ypTOLIFWkV0jbKFjw==", + "version": "6.1.14", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.14.tgz", + "integrity": "sha512-ExZSCSV9e7v/Zt7RzCbX57lY2dnPdxzU/h3UE6WJ6NtEMfwBd8jmi1n4otDEUfz+T/R+zxrFDpICFdjhD3H/zw==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^1.10.4", + "cacheable": "^2.0.1", "flatted": "^3.3.3", - "hookified": "^1.11.0" + "hookified": "^1.12.0" } }, "node_modules/flatted": { @@ -6354,9 +6782,9 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "dev": true, "funding": [ { @@ -6497,9 +6925,9 @@ } }, "node_modules/get-east-asian-width": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.1.tgz", - "integrity": "sha512-R1QfovbPsKmosqTnPoRFiJ7CF9MLRgb53ChvMZm+r4p76/+8yKDy17qLL2PKInORy2RkZZekuK0efYgmzTkXyQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", "dev": true, "license": "MIT", "engines": { @@ -6569,9 +6997,9 @@ } }, "node_modules/get-uri": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", - "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", "dev": true, "license": "MIT", "dependencies": { @@ -6584,9 +7012,9 @@ } }, "node_modules/get-uri/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -6800,6 +7228,44 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hookified": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.12.0.tgz", @@ -6827,6 +7293,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/http-assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", @@ -6908,9 +7385,9 @@ } }, "node_modules/http-proxy-agent/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -6947,9 +7424,9 @@ } }, "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -7046,14 +7523,11 @@ } }, "node_modules/igniteui-theming": { - "version": "19.3.1", - "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-19.3.1.tgz", - "integrity": "sha512-8Q2hVpvUJbnwE8Sege+6jHOZSqK7d97muqdb4t1CkLG2onz8HDcMQooUXf7mI7gRQgWavvLQLSgMRWXnUUAsJw==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-20.0.0.tgz", + "integrity": "sha512-g+pxAskmX1g0wlwaO0MPcT8sMTbr3rzSEOJRWg26FBKcVE09cxPEbX2Vl9k7LdbBc5VdDoiAgsI9yvZhAUM0Xg==", "dev": true, - "license": "MIT", - "peerDependencies": { - "sass": "^1.69.5" - } + "license": "MIT" }, "node_modules/ignore": { "version": "7.0.5", @@ -7178,15 +7652,11 @@ } }, "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", "dev": true, "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, "engines": { "node": ">= 12" } @@ -7274,13 +7744,16 @@ } }, "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", "dev": true, "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7477,9 +7950,9 @@ } }, "node_modules/isbinaryfile": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.4.tgz", - "integrity": "sha512-YKBKVkKhty7s8rxddb40oOkuP0NbaeXrQvLin6QMHL7Ypiy2RW9LwOVrVgZRyOrhQlayMd9t+D8yDy8MKFTSDQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.6.tgz", + "integrity": "sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==", "dev": true, "license": "MIT", "engines": { @@ -7522,9 +7995,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -7571,13 +8044,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, - "license": "MIT" - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -7616,9 +8082,9 @@ } }, "node_modules/keep-a-changelog": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/keep-a-changelog/-/keep-a-changelog-2.7.0.tgz", - "integrity": "sha512-P6OK3tfFgCbkG8SU871qR7YdfiTEd+aS4YgEpJF3JfgiI0H0hbZ5c44Bn7EYM/RsO7Bgh6bIAjilKZw8gK4Usw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/keep-a-changelog/-/keep-a-changelog-2.7.1.tgz", + "integrity": "sha512-uwxVmpiSd2LOT+sffmd+7odV80WLFxe7jUyGLh4K6H3bjnPIlWJ4d/632+13K2WvtRz4NAwak8PPw416hS5NHA==", "dev": true, "license": "MIT", "dependencies": { @@ -7642,13 +8108,13 @@ } }, "node_modules/keyv": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.0.tgz", - "integrity": "sha512-QG7qR2tijh1ftOvClut4YKKg1iW6cx3GZsKoGyJPxHkGWK9oJhG9P3j5deP0QQOGDowBMVQFaP+Vm4NpGYvmIQ==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.2.tgz", + "integrity": "sha512-TXcFHbmm/z7MGd1u9ASiCSfTS+ei6Z8B3a5JHzx3oPa/o7QzWVtPRpc4KGER5RR469IC+/nfg4U5YLIuDUua2g==", "dev": true, "license": "MIT", "dependencies": { - "@keyv/serialize": "^1.1.0" + "@keyv/serialize": "^1.1.1" } }, "node_modules/kind-of": { @@ -7750,9 +8216,9 @@ } }, "node_modules/koa-send/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -7806,9 +8272,9 @@ "license": "MIT" }, "node_modules/koa/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -7939,9 +8405,9 @@ } }, "node_modules/lint-staged/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -7964,13 +8430,13 @@ "license": "MIT" }, "node_modules/listr2": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.3.tgz", - "integrity": "sha512-0aeh5HHHgmq1KRdMMDHfhMWQmIT/m7nRDTlxlFqni2Sp0had9baqsjJRvDGdlvgd6NmPE0nPloOipiQJGFtTHQ==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.4.tgz", + "integrity": "sha512-1wd/kpAdKRLwv7/3OKC8zZ5U8e/fajCfWMxacUvB79S5nLrYGPtUI/8chMQhn3LQjsRVErTb9i1ECAwW0ZIHnQ==", "dev": true, "license": "MIT", "dependencies": { - "cli-truncate": "^4.0.0", + "cli-truncate": "^5.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", @@ -8010,19 +8476,6 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/listr2/node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -8046,22 +8499,6 @@ "dev": true, "license": "MIT" }, - "node_modules/listr2/node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/listr2/node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", @@ -8128,23 +8565,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/listr2/node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/listr2/node_modules/strip-ansi": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", @@ -8279,20 +8699,20 @@ } }, "node_modules/lit-element": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.0.tgz", - "integrity": "sha512-MGrXJVAI5x+Bfth/pU9Kst1iWID6GHDLEzFEnyULB/sFiRLgkd8NPK/PeeXxktA3T6EIIaq8U3KcbTU5XFcP2Q==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.1.tgz", + "integrity": "sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==", "license": "BSD-3-Clause", "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0", + "@lit-labs/ssr-dom-shim": "^1.4.0", "@lit/reactive-element": "^2.1.0", "lit-html": "^3.3.0" } }, "node_modules/lit-html": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.0.tgz", - "integrity": "sha512-RHoswrFAxY2d8Cf2mm4OZ1DgzCoBKUKSPvA1fhtSELxUERq2aQQ2h05pO9j81gS1o7RIRJ+CePLogfyahwmynw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.1.tgz", + "integrity": "sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==", "license": "BSD-3-Clause", "dependencies": { "@types/trusted-types": "^2.0.2" @@ -8319,14 +8739,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.isfinite": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", @@ -8377,13 +8789,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, "node_modules/log-update/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -8527,9 +8932,9 @@ } }, "node_modules/madge/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -8552,13 +8957,13 @@ "license": "MIT" }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/make-dir": { @@ -8605,6 +9010,30 @@ "markdown-it": "bin/markdown-it.mjs" } }, + "node_modules/marked": { + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.3.0.tgz", + "integrity": "sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==", + "license": "MIT", + "peer": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/marked-shiki": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/marked-shiki/-/marked-shiki-1.2.1.tgz", + "integrity": "sha512-yHxYQhPY5oYaIRnROn98foKhuClark7M373/VpLxiy5TrDu9Jd/LsMwo8w+U91Up4oDb9IXFrP0N1MFRz8W/DQ==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "marked": ">=7.0.0", + "shiki": ">=1.0.0" + } + }, "node_modules/marky": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz", @@ -8633,6 +9062,28 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdn-data": { "version": "2.12.2", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", @@ -8683,9 +9134,103 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 8" - } + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "peer": true }, "node_modules/micromatch": { "version": "4.0.8", @@ -8877,9 +9422,9 @@ "license": "MIT" }, "node_modules/nano-spawn": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.2.tgz", - "integrity": "sha512-21t+ozMQDAL/UGgQVBbZ/xXvNO10++ZPuTmKRO8k9V3AClVRht49ahtDjfY8l1q6nSHOrE5ASfthzH3ol6R/hg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.3.tgz", + "integrity": "sha512-jtpsQDetTnvS2Ts1fiRdci5rx0VYws5jGyC+4IYOTnIQ/wwdf6JdomlHBwqC3bJYOvaKu0C2GSZ1A60anrYpaA==", "dev": true, "license": "MIT", "engines": { @@ -8944,9 +9489,9 @@ "optional": true }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", "dev": true, "license": "MIT" }, @@ -9068,6 +9613,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/oniguruma-parser": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", + "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", + "license": "MIT", + "peer": true + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz", + "integrity": "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==", + "license": "MIT", + "peer": true, + "dependencies": { + "oniguruma-parser": "^0.12.1", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, "node_modules/only": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", @@ -9199,9 +9763,9 @@ } }, "node_modules/pac-proxy-agent/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -9478,9 +10042,9 @@ } }, "node_modules/portfinder": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz", - "integrity": "sha512-yuGIEjDAYnnOex9ddMnKZEMFE0CcGo6zbfzDklkmT1m5z734ss6JMzN9rNB3+RR7iS+F10D4/BVIaXOyh8PQKw==", + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.38.tgz", + "integrity": "sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==", "dev": true, "license": "MIT", "dependencies": { @@ -9492,9 +10056,9 @@ } }, "node_modules/portfinder/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -9802,6 +10366,17 @@ "node": ">=0.4.0" } }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/proxy-agent": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", @@ -9823,9 +10398,9 @@ } }, "node_modules/proxy-agent/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -9896,27 +10471,28 @@ } }, "node_modules/puppeteer-core": { - "version": "24.11.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.11.0.tgz", - "integrity": "sha512-ncLty0wRjCX67UxzXemmD1mOxb6y1Xzrx1nym8SAQ6cYrcypOVf77CfcZru6P+EiMA9gNDeQNscowKSE9xvhMw==", + "version": "24.22.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.22.0.tgz", + "integrity": "sha512-oUeWlIg0pMz8YM5pu0uqakM+cCyYyXkHBxx9di9OUELu9X9+AYrNGGRLK9tNME3WfN3JGGqQIH3b4/E9LGek/w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.10.5", - "chromium-bidi": "5.1.0", - "debug": "^4.4.1", - "devtools-protocol": "0.0.1464554", + "@puppeteer/browsers": "2.10.10", + "chromium-bidi": "8.0.0", + "debug": "^4.4.3", + "devtools-protocol": "0.0.1495869", "typed-query-selector": "^2.12.0", - "ws": "^8.18.2" + "webdriver-bidi-protocol": "0.2.11", + "ws": "^8.18.3" }, "engines": { "node": ">=18" } }, "node_modules/puppeteer-core/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -10074,9 +10650,9 @@ } }, "node_modules/react": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", + "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", "dev": true, "license": "MIT", "engines": { @@ -10084,16 +10660,16 @@ } }, "node_modules/react-dom": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", - "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", + "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", "dev": true, "license": "MIT", "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { - "react": "^19.1.0" + "react": "^19.1.1" } }, "node_modules/react-is": { @@ -10186,6 +10762,33 @@ "node": ">=8" } }, + "node_modules/regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz", + "integrity": "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==", + "license": "MIT", + "peer": true, + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "license": "MIT", + "peer": true, + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT", + "peer": true + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -10452,9 +11055,9 @@ } }, "node_modules/rollup": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz", - "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.2.tgz", + "integrity": "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==", "dev": true, "license": "MIT", "dependencies": { @@ -10468,29 +11071,52 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.44.1", - "@rollup/rollup-android-arm64": "4.44.1", - "@rollup/rollup-darwin-arm64": "4.44.1", - "@rollup/rollup-darwin-x64": "4.44.1", - "@rollup/rollup-freebsd-arm64": "4.44.1", - "@rollup/rollup-freebsd-x64": "4.44.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", - "@rollup/rollup-linux-arm-musleabihf": "4.44.1", - "@rollup/rollup-linux-arm64-gnu": "4.44.1", - "@rollup/rollup-linux-arm64-musl": "4.44.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", - "@rollup/rollup-linux-riscv64-gnu": "4.44.1", - "@rollup/rollup-linux-riscv64-musl": "4.44.1", - "@rollup/rollup-linux-s390x-gnu": "4.44.1", - "@rollup/rollup-linux-x64-gnu": "4.44.1", - "@rollup/rollup-linux-x64-musl": "4.44.1", - "@rollup/rollup-win32-arm64-msvc": "4.44.1", - "@rollup/rollup-win32-ia32-msvc": "4.44.1", - "@rollup/rollup-win32-x64-msvc": "4.44.1", + "@rollup/rollup-android-arm-eabi": "4.50.2", + "@rollup/rollup-android-arm64": "4.50.2", + "@rollup/rollup-darwin-arm64": "4.50.2", + "@rollup/rollup-darwin-x64": "4.50.2", + "@rollup/rollup-freebsd-arm64": "4.50.2", + "@rollup/rollup-freebsd-x64": "4.50.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.50.2", + "@rollup/rollup-linux-arm-musleabihf": "4.50.2", + "@rollup/rollup-linux-arm64-gnu": "4.50.2", + "@rollup/rollup-linux-arm64-musl": "4.50.2", + "@rollup/rollup-linux-loong64-gnu": "4.50.2", + "@rollup/rollup-linux-ppc64-gnu": "4.50.2", + "@rollup/rollup-linux-riscv64-gnu": "4.50.2", + "@rollup/rollup-linux-riscv64-musl": "4.50.2", + "@rollup/rollup-linux-s390x-gnu": "4.50.2", + "@rollup/rollup-linux-x64-gnu": "4.50.2", + "@rollup/rollup-linux-x64-musl": "4.50.2", + "@rollup/rollup-openharmony-arm64": "4.50.2", + "@rollup/rollup-win32-arm64-msvc": "4.50.2", + "@rollup/rollup-win32-ia32-msvc": "4.50.2", + "@rollup/rollup-win32-x64-msvc": "4.50.2", "fsevents": "~2.3.2" } }, + "node_modules/rs-module-lexer": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/rs-module-lexer/-/rs-module-lexer-2.5.1.tgz", + "integrity": "sha512-Zud7if8vr+tCEf7LjGY7ReHyjCrSZrM4feQbWrUtrQ3c1ljDRSQ8zpdc89DCCgWyZyvMTIcInu9BxkrSUtFGyA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "@xn-sakina/rml-darwin-arm64": "2.5.1", + "@xn-sakina/rml-darwin-x64": "2.5.1", + "@xn-sakina/rml-linux-arm-gnueabihf": "2.5.1", + "@xn-sakina/rml-linux-arm64-gnu": "2.5.1", + "@xn-sakina/rml-linux-arm64-musl": "2.5.1", + "@xn-sakina/rml-linux-x64-gnu": "2.5.1", + "@xn-sakina/rml-linux-x64-musl": "2.5.1", + "@xn-sakina/rml-win32-arm64-msvc": "2.5.1", + "@xn-sakina/rml-win32-x64-msvc": "2.5.1" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -10584,6 +11210,7 @@ "integrity": "sha512-ffmsdbwqb3XeyR8jJR6KelIXARM9bFQe8A6Q3W4Klmwy5Ckd5gz7jgUNHo4UOqutU5Sk1DtKLbpDP0nLCg1xqQ==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -11004,6 +11631,7 @@ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -11019,7 +11647,8 @@ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/sass/node_modules/readdirp": { "version": "4.1.2", @@ -11027,6 +11656,7 @@ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, "license": "MIT", + "optional": true, "engines": { "node": ">= 14.18.0" }, @@ -11272,6 +11902,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/shiki": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.12.2.tgz", + "integrity": "sha512-uIrKI+f9IPz1zDT+GMz+0RjzKJiijVr6WDWm9Pe3NNY6QigKCfifCEv9v9R2mDASKKjzjQ2QpFLcxaR3iHSnMA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@shikijs/core": "3.12.2", + "@shikijs/engine-javascript": "3.12.2", + "@shikijs/engine-oniguruma": "3.12.2", + "@shikijs/langs": "3.12.2", + "@shikijs/themes": "3.12.2", + "@shikijs/types": "3.12.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -11397,17 +12044,17 @@ } }, "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" @@ -11620,13 +12267,13 @@ "license": "MIT" }, "node_modules/socks": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz", - "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==", + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "dev": true, "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", + "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -11650,9 +12297,9 @@ } }, "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -11694,12 +12341,16 @@ "node": ">=0.10.0" } }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause" + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, "node_modules/statuses": { "version": "1.3.1", @@ -11712,9 +12363,9 @@ } }, "node_modules/storybook": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-9.1.5.tgz", - "integrity": "sha512-cGwJ2AE6nxlwqQlOiI+HKX5qa7+FOV7Ha7Qa+GoASBIQSSnLfbY6UldgAxHCJGJOFtgW/wuqfDtNvni6sj1/OQ==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-9.1.6.tgz", + "integrity": "sha512-iIcMaDKkjR5nN+JYBy9hhoxZhjX4TXhyJgUBed+toJOlfrl+QvxpBjImAi7qKyLR3hng3uoigEP0P8+vYtXpOg==", "dev": true, "license": "MIT", "dependencies": { @@ -11838,18 +12489,17 @@ } }, "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", + "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", + "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11871,13 +12521,6 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -11917,6 +12560,21 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "peer": true, + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/stringify-object": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", @@ -12223,9 +12881,9 @@ "license": "MIT" }, "node_modules/stylelint/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -12240,13 +12898,6 @@ } } }, - "node_modules/stylelint/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, "node_modules/stylelint/node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -12449,13 +13100,6 @@ "node": ">=12.17" } }, - "node_modules/table/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -12500,19 +13144,23 @@ } }, "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", + "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/tar-fs": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.10.tgz", - "integrity": "sha512-C1SwlQGNLe/jPNqapK8epDsXME7CAJR5RL3GcE6KWx1d9OUByzoHVcbu1VPI8tevg9H8Alae0AApHHFGzrD5zA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", + "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", "dev": true, "license": "MIT", "dependencies": { @@ -12667,6 +13315,17 @@ "tree-kill": "cli.js" } }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -12843,9 +13502,9 @@ } }, "node_modules/typedoc-plugin-localization/node_modules/fs-extra": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", - "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", "dev": true, "license": "MIT", "dependencies": { @@ -12931,9 +13590,9 @@ } }, "node_modules/ua-parser-js": { - "version": "1.0.40", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz", - "integrity": "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==", + "version": "1.0.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", + "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", "dev": true, "funding": [ { @@ -12965,9 +13624,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", - "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", + "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", "dev": true, "license": "MIT" }, @@ -12984,6 +13643,79 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -13098,10 +13830,40 @@ "node": ">= 0.8" } }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vite": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", - "integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.6.tgz", + "integrity": "sha512-SRYIB8t/isTwNn8vMB3MR6E+EQZM/WG1aKmmIUCfDXfVvKfc20ZpamngWHKzAmmu9ppsgxsg4b2I7c90JZudIQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13309,6 +14071,13 @@ "node": ">=14.17" } }, + "node_modules/webdriver-bidi-protocol": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.2.11.tgz", + "integrity": "sha512-Y9E1/oi4XMxcR8AT0ZC4OvYntl34SPgwjmELH+owjBr0korAX4jKgZULBWILGCVGdVCQ0dodTToIETozhG8zvA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -13403,13 +14172,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -13461,6 +14223,31 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", @@ -13594,13 +14381,6 @@ "node": ">=12" } }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, "node_modules/yargs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -13648,14 +14428,25 @@ } }, "node_modules/zod": { - "version": "3.25.67", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", - "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/package.json b/package.json index 172a5cf32..53630baa5 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "license": "SEE LICENSE IN LICENSE", "exports": { ".": "./src/index.js", - "./types": "./src/types.js" + "./types": "./src/types.js", + "./extras": "./src/extras/index.js" }, "type": "module", "repository": { @@ -59,13 +60,13 @@ }, "devDependencies": { "@biomejs/biome": "~2.2.4", - "@custom-elements-manifest/analyzer": "^0.10.5", + "@custom-elements-manifest/analyzer": "^0.10.6", "@igniteui/material-icons-extended": "^3.1.0", "@open-wc/testing": "^4.0.0", - "@storybook/addon-a11y": "^9.1.5", - "@storybook/addon-docs": "^9.1.5", - "@storybook/addon-links": "^9.1.5", - "@storybook/web-components-vite": "^9.1.5", + "@storybook/addon-a11y": "^9.1.6", + "@storybook/addon-docs": "^9.1.6", + "@storybook/addon-links": "^9.1.6", + "@storybook/web-components-vite": "^9.1.6", "@types/mocha": "^10.0.10", "@web/dev-server-esbuild": "^1.0.4", "@web/test-runner": "^0.20.2", @@ -79,8 +80,8 @@ "globby": "^14.1.0", "husky": "^9.1.7", "ig-typedoc-theme": "^6.2.3", - "igniteui-theming": "^19.3.1", - "keep-a-changelog": "^2.7.0", + "igniteui-theming": "^20.0.0", + "keep-a-changelog": "^2.7.1", "lint-staged": "^16.1.6", "lit-analyzer": "^2.0.3", "madge": "^8.0.0", @@ -91,7 +92,7 @@ "rimraf": "^6.0.1", "sass-embedded": "~1.92.1", "sinon": "^21.0.0", - "storybook": "^9.1.5", + "storybook": "^9.1.6", "stylelint": "^16.24.0", "stylelint-config-standard-scss": "^16.0.0", "stylelint-prettier": "^5.0.3", @@ -101,7 +102,13 @@ "typedoc": "~0.27.9", "typedoc-plugin-localization": "^3.0.6", "typescript": "^5.8.3", - "vite": "^7.1.5" + "vite": "^7.1.6" + }, + "peerDependencies": { + "dompurify": "^3.2.7", + "marked": "^16.3.0", + "marked-shiki": "^1.2.1", + "shiki": "^3.12.2" }, "browserslist": [ "defaults" diff --git a/scripts/_package.json b/scripts/_package.json index 383d42c69..e0c6d9d9e 100644 --- a/scripts/_package.json +++ b/scripts/_package.json @@ -10,7 +10,11 @@ "types": "./index.d.ts", "default": "./index.js" }, - "./themes/*.css": "./themes/*.css" + "./themes/*.css": "./themes/*.css", + "./extras": { + "types": "./extras/index.d.ts", + "default": "./extras/index.js" + } }, "type": "module", "sideEffects": false, @@ -28,6 +32,7 @@ "webcomponents", "web components", "UI components", + "AI chat", "accordion", "avatar", "badge", @@ -38,6 +43,7 @@ "card", "carousel", "circular progress", + "chat", "checkbox", "chip", "combo", @@ -72,11 +78,31 @@ "tree" ], "customElements": "custom-elements.json", + "web-types": "./web-types.json", "dependencies": { "@floating-ui/dom": "^1.7.0", "@lit-labs/virtualizer": "^2.1.0", "@lit/context": "^1.1.0", "lit": "^3.3.0" }, - "web-types": "./web-types.json" + "peerDependencies": { + "dompurify": "^3.2.", + "marked": "^16.3.0", + "marked-shiki": "^1.2.0", + "shiki": "^3.12.0" + }, + "peerDependenciesMeta": { + "dompurify": { + "optional": true + }, + "marked": { + "optional": true + }, + "marked-shiki": { + "optional": true + }, + "shiki": { + "optional": true + } + } } diff --git a/scripts/build.mjs b/scripts/build.mjs index 2504b3e4a..326402a84 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -1,5 +1,5 @@ import { exec as _exec } from 'node:child_process'; -import { copyFile, writeFile } from 'node:fs/promises'; +import { copyFile, mkdir, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { promisify } from 'node:util'; @@ -11,6 +11,7 @@ import { import customElements from '../custom-elements.json' with { type: 'json' }; import report from './report.mjs'; import { buildComponents, buildThemes } from './sass.mjs'; +import { globby } from 'globby'; const exec = promisify(_exec); @@ -49,12 +50,23 @@ async function runTask(tag, cmd) { ) ); - await runTask('Copying release files', () => + await runTask('Copying release files', async () => { + const pngFiles = await globby('src/components/**/*.png'); + pngFiles.forEach( + async (dest) => + await mkdir(path.dirname(DEST_DIR(dest.replace('src', ''))), { + recursive: true, + }) + ); + Promise.all([ copyFile('scripts/_package.json', DEST_DIR('package.json')), ...RELEASE_FILES.map((file) => copyFile(file, DEST_DIR(file))), - ]) - ); + ...pngFiles.map((file) => + copyFile(file, DEST_DIR(file.replace('src', ''))) + ), + ]); + }); await runTask('VSCode custom data + Web types', () => Promise.all([ diff --git a/src/components/chat/chat-input.ts b/src/components/chat/chat-input.ts new file mode 100644 index 000000000..27d457e0f --- /dev/null +++ b/src/components/chat/chat-input.ts @@ -0,0 +1,392 @@ +import { consume } from '@lit/context'; +import { html, LitElement, nothing } from 'lit'; +import { query, state } from 'lit/decorators.js'; +import { cache } from 'lit/directives/cache.js'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { until } from 'lit/directives/until.js'; +import { addThemingController } from '../../theming/theming-controller.js'; +import IgcIconButtonComponent from '../button/icon-button.js'; +import IgcChipComponent from '../chip/chip.js'; +import { chatContext, chatUserInputContext } from '../common/context.js'; +import { enterKey } from '../common/controllers/key-bindings.js'; +import { registerComponent } from '../common/definitions/register.js'; +import { partMap } from '../common/part-map.js'; +import { bindIf, hasFiles, isEmpty, trimmedHtml } from '../common/util.js'; +import IgcIconComponent from '../icon/icon.js'; +import IgcTextareaComponent from '../textarea/textarea.js'; +import type { ChatState } from './chat-state.js'; +import { styles } from './themes/input.base.css.js'; +import { all } from './themes/input.js'; +import { styles as shared } from './themes/shared/input/input.common.css.js'; +import type { + ChatInputRenderContext, + ChatRenderContext, + ChatTemplateRenderer, + IgcChatMessageAttachment, +} from './types.js'; +import { getChatAcceptedFiles, getIconName } from './utils.js'; + +type DefaultInputRenderers = { + input: ChatTemplateRenderer; + inputActions: ChatTemplateRenderer; + inputActionsEnd: ChatTemplateRenderer; + inputActionsStart: ChatTemplateRenderer; + inputAttachments: ChatTemplateRenderer; + fileUploadButton: ChatTemplateRenderer; + sendButton: ChatTemplateRenderer; +}; + +/* blazorSuppress */ +/** + * A web component that provides the input area for the `igc-chat` interface. + * + * It supports: + * - Text input with automatic resizing + * - Sending messages on Enter key (with Shift+Enter for newlines) + * - File attachments via file picker or drag-and-drop + * - Customizable templates for send button, attachments, and text input + * - Emits various chat-related events (typing, input focus/blur, attachment drop, etc.) + * + * @element igc-chat-input + * + * @slot - Default unnamed slot for rendering inside the component + * @fires igcTypingChange - Fired when the user starts/stops typing + * @fires igcInputFocus - Fired when the input area receives focus + * @fires igcInputBlur - Fired when the input area loses focus + * @fires igcAttachmentDrag - Fired when dragging a file over the input + * @fires igcAttachmentDrop - Fired when a file is dropped into the input + * @fires igcChange - Fired when file input changes (delegated from ``) + * + * @csspart input-container - Container for the input section + * @csspart input-wrapper - Wrapper around the text input + * @csspart text-input - The `` component + * @csspart actions-container - Container for file upload/send buttons + * @csspart send-button - The send icon button + * @csspart attachments - Container for rendering attachments + * @csspart attachment-wrapper - Wrapper for individual attachment + * @csspart attachment-name - Display name of an attachment + */ +export default class IgcChatInputComponent extends LitElement { + public static readonly tagName = 'igc-chat-input'; + public static override styles = [styles, shared]; + + /* blazorSuppress */ + public static register(): void { + registerComponent( + IgcChatInputComponent, + IgcTextareaComponent, + IgcIconButtonComponent, + IgcChipComponent, + IgcIconComponent + ); + } + + private readonly _defaults: Readonly = Object.freeze({ + fileUploadButton: () => this._renderFileUploadButton(), + input: () => this._renderTextArea(), + inputActions: () => this._renderActionsArea(), + inputActionsEnd: () => nothing, + inputActionsStart: () => nothing, + inputAttachments: (ctx) => this._renderAttachmentsArea(ctx.attachments), + sendButton: () => this._renderSendButton(), + }); + + @consume({ context: chatContext, subscribe: true }) + private readonly _state!: ChatState; + + @consume({ context: chatUserInputContext, subscribe: true }) + private readonly _userInputState!: ChatState; + + @query(IgcTextareaComponent.tagName) + private readonly _textInputElement!: IgcTextareaComponent; + + @query('#input_attachments') + protected readonly _fileInput!: HTMLInputElement; + + @state() + private _parts = { 'input-container': true, dragging: false }; + + private get _acceptedTypes() { + return this._state.acceptedFileTypes; + } + + constructor() { + super(); + addThemingController(this, all); + } + + /** @internal */ + public focusInput(): void { + this._textInputElement.focus(); + } + + private _getRenderer( + name: U + ): DefaultInputRenderers[U] { + return this._state.options?.renderers + ? ((this._state.options.renderers[name] ?? + this._defaults[name]) as DefaultInputRenderers[U]) + : this._defaults[name]; + } + + private async _sendMessage(): Promise { + if ( + !this._userInputState.hasInputValue && + !this._userInputState.hasInputAttachments + ) { + return; + } + + this._userInputState.addMessageWithEvent({ + text: this._userInputState.inputValue, + attachments: this._userInputState.inputAttachments, + }); + + this.style.height = 'auto'; + + await this._userInputState.host.updateComplete; + this.focusInput(); + } + + private _handleAttachmentRemoved(attachment: IgcChatMessageAttachment): void { + const current = this._userInputState.inputAttachments; + + if (this._state.emitAttachmentRemoved(attachment)) { + this._state.inputAttachments = current.toSpliced( + current.indexOf(attachment), + 1 + ); + } + } + + private _handleKeydown(event: KeyboardEvent): void { + const isSendRequest = + event.key.toLowerCase() === enterKey.toLowerCase() && !event.shiftKey; + + if (isSendRequest) { + event.preventDefault(); + this._sendMessage(); + } else { + // TODO: + this._state.handleKeyDown(event); + } + } + + private _handleFileInputClick(): void { + this._fileInput.showPicker(); + } + + private _handleFocusState(event: FocusEvent): void { + this._state.emitEvent( + event.type === 'focus' ? 'igcInputFocus' : 'igcInputBlur' + ); + } + + private _handleDragEnter(event: DragEvent): void { + event.preventDefault(); + event.stopPropagation(); + + const validFiles = getChatAcceptedFiles(event, this._acceptedTypes); + this._parts = { 'input-container': true, dragging: !isEmpty(validFiles) }; + this._state.emitEvent('igcAttachmentDrag'); + } + + private _handleDragOver(event: DragEvent): void { + event.preventDefault(); + event.stopPropagation(); + } + + private _handleDragLeave(event: DragEvent): void { + event.preventDefault(); + event.stopPropagation(); + + // Check if we're actually leaving the container + const rect = (event.currentTarget as HTMLElement).getBoundingClientRect(); + const x = event.clientX; + const y = event.clientY; + + if ( + x <= rect.left || + x >= rect.right || + y <= rect.top || + y >= rect.bottom + ) { + this._parts = { 'input-container': true, dragging: false }; + } + } + + private _handleDrop(event: DragEvent): void { + event.preventDefault(); + event.stopPropagation(); + this._parts = { 'input-container': true, dragging: false }; + + const validFiles = getChatAcceptedFiles(event, this._acceptedTypes); + this._state.emitEvent('igcAttachmentDrop'); + this._state.attachFilesWithEvent(validFiles); + this.requestUpdate(); + } + + private _handleInput({ detail }: CustomEvent): void { + this._state.inputValue = detail; + this._state.emitEvent('igcInputChange', { detail: { value: detail } }); + } + + private _handleFileUpload(event: Event): void { + const input = event.target as HTMLInputElement; + + if (hasFiles(input)) { + this._state.attachFilesWithEvent(Array.from(input.files!)); + } + } + /** + * Default attachments area template used when no custom template is provided. + * Renders the list of input attachments as chips. + * @returns TemplateResult containing the attachments area + */ + private _renderAttachmentsArea(attachments: IgcChatMessageAttachment[]) { + return html`${attachments?.map( + (attachment) => html` +
+ this._handleAttachmentRemoved(attachment)} + > + + ${attachment.name} + +
+ ` + )} `; + } + + /** + * Default text area template used when no custom template is provided. + * Renders a text area for user input. + * @returns TemplateResult containing the text area + */ + private _renderTextArea() { + return html` + + `; + } + + private _renderFileUploadButton() { + const accepted = this._state.options?.acceptedFiles; + const attachmentsDisabled = this._state.options?.disableInputAttachments; + + return html`${cache( + attachmentsDisabled + ? nothing + : html` + + ` + )}`; + } + + private _renderSendButton() { + const enabled = + this._state.hasInputValue || this._state.hasInputAttachments; + + return html` + + `; + } + + private _renderActionsArea() { + const ctx: ChatRenderContext = { instance: this._state.host }; + + return trimmedHtml` +
+ ${this._getRenderer('fileUploadButton')(ctx)} +
+
+ ${this._getRenderer('inputActionsStart')(ctx)} +
+
${this._getRenderer('sendButton')(ctx)}
+
+ ${this._getRenderer('inputActionsEnd')(ctx)} +
+ `; + } + + protected override render() { + const ctx: ChatRenderContext = { instance: this._state.host }; + + const inputCtx: ChatInputRenderContext = { + ...ctx, + attachments: this._state.inputAttachments, + value: this._state.inputValue, + }; + + return html` +
+ ${this._state.hasInputAttachments + ? html` +
+ ${until(this._getRenderer('inputAttachments')(inputCtx))} +
+ ` + : nothing} + +
+ ${until(this._getRenderer('input')(inputCtx))} +
+ +
+ ${until(this._getRenderer('inputActions')(ctx))} +
+
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'igc-chat-input': IgcChatInputComponent; + } +} diff --git a/src/components/chat/chat-message.ts b/src/components/chat/chat-message.ts new file mode 100644 index 000000000..b723f689e --- /dev/null +++ b/src/components/chat/chat-message.ts @@ -0,0 +1,293 @@ +import { consume } from '@lit/context'; +import { html, LitElement, nothing } from 'lit'; +import { property } from 'lit/decorators.js'; +import { cache } from 'lit/directives/cache.js'; +import { until } from 'lit/directives/until.js'; +import { addThemingController } from '../../theming/theming-controller.js'; +import IgcIconButtonComponent from '../button/icon-button.js'; +import { chatContext } from '../common/context.js'; +import { registerComponent } from '../common/definitions/register.js'; +import { partMap } from '../common/part-map.js'; +import { isEmpty, trimmedHtml } from '../common/util.js'; +import type { ChatState } from './chat-state.js'; +import IgcMessageAttachmentsComponent from './message-attachments.js'; +import { styles } from './themes/message.base.css.js'; +import { all } from './themes/message.js'; +import { styles as shared } from './themes/shared/chat-message/chat-message.common.css.js'; +import type { + ChatMessageRenderContext, + ChatTemplateRenderer, + IgcChatMessage, +} from './types.js'; +import { chatMessageAdoptPageStyles } from './utils.js'; + +const LIKE_INACTIVE = 'thumb_up_inactive'; +const LIKE_ACTIVE = 'thumb_up_active'; +const DISLIKE_INACTIVE = 'thumb_down_inactive'; +const DISLIKE_ACTIVE = 'thumb_down_active'; +const COPY_CONTENT = 'copy_content'; +const REGENERATE = 'regenerate'; + +type DefaultMessageRenderers = { + messageHeader: ChatTemplateRenderer; + messageContent: ChatTemplateRenderer; + messageAttachments: ChatTemplateRenderer; + messageActions: ChatTemplateRenderer; +}; + +/* blazorSuppress */ +/** + * A chat message component for displaying individual messages in ``. + * + * @element igc-chat-message + * + * + * This component renders a single chat message including: + * - Message text (sanitized) + * - Attachments (if any) + * - Custom templates for message content and actions (if provided via chat options) + * + * It distinguishes sent messages from received messages by comparing + * the message sender with the current user ID from chat state. + * + * The message text is sanitized with DOMPurify before rendering, + * and can be rendered with a markdown renderer if provided. + */ +export default class IgcChatMessageComponent extends LitElement { + public static readonly tagName = 'igc-chat-message'; + public static override styles = [styles, shared]; + + /* blazorSuppress */ + public static register(): void { + registerComponent( + IgcChatMessageComponent, + IgcMessageAttachmentsComponent, + IgcIconButtonComponent + ); + } + + private readonly _defaults = Object.freeze({ + messageHeader: () => this._renderHeader(), + messageContent: () => this._renderContent(), + messageAttachments: () => this._renderAttachments(), + messageActions: () => this._renderActions(), + }); + + @consume({ context: chatContext, subscribe: true }) + private readonly _state!: ChatState; + + /** + * The chat message to render. + */ + @property({ attribute: false }) + public message!: IgcChatMessage; + + constructor() { + super(); + addThemingController(this, all); + } + + protected override firstUpdated(): void { + if (this._state.options?.adoptRootStyles) { + chatMessageAdoptPageStyles(this); + } + } + + private _getRenderer(name: keyof DefaultMessageRenderers) { + return this._state.options?.renderers + ? (this._state.options.renderers[name] ?? this._defaults[name]) + : this._defaults[name]; + } + + private async _handleCopy(): Promise { + const text = this.message.text; + const separator = text ? '\n\n' : ''; + const attachments = this.message.attachments ?? []; + const { attachmentLabel, attachmentsListLabel, messageCopied } = + this._state.resourceStrings!; + + const attachmentsText = isEmpty(attachments) + ? '' + : attachments + .map(({ name, url }) => `${name ?? attachmentLabel}: ${url ?? ''}`) + .join('\n'); + + const payload = attachmentsText + ? `${text}${separator}${attachmentsListLabel}:\n${attachmentsText}` + : text; + + try { + await navigator.clipboard.writeText(payload); + this._state.showActionToast(messageCopied); + } catch (err) { + throw new Error(`Failed to copy message: ${err}`); + } + } + + private _handleMessageActionClick(event: PointerEvent): void { + const targetButton = event.target as HTMLElement; + const button = targetButton.closest(IgcIconButtonComponent.tagName); + + if (!button) { + return; + } + + let reaction = button.name; + + switch (reaction) { + case LIKE_INACTIVE: + case LIKE_ACTIVE: + reaction = this.message.reactions?.includes(LIKE_ACTIVE) + ? LIKE_INACTIVE + : LIKE_ACTIVE; + break; + case DISLIKE_INACTIVE: + case DISLIKE_ACTIVE: + reaction = this.message.reactions?.includes(DISLIKE_ACTIVE) + ? DISLIKE_INACTIVE + : DISLIKE_ACTIVE; + break; + case COPY_CONTENT: + reaction = COPY_CONTENT; + this._handleCopy(); + break; + case REGENERATE: + reaction = REGENERATE; + break; + default: + reaction = ''; + } + + this.message.reactions = reaction ? [reaction] : []; + this._state.emitMessageReaction({ message: this.message, reaction }); + this.requestUpdate(); + } + + private _renderHeader() { + return nothing; + } + + private _renderContent() { + return html`${this.message.text}`; + } + + private _renderActions() { + const isSent = this.message.sender === this._state.currentUserId; + const hasText = this.message.text.trim(); + const hasAttachments = !isEmpty(this.message.attachments ?? []); + const isTyping = this._state._isTyping; + const isLastMessage = this.message === this._state.messages.at(-1); + const resourceStrings = this._state.resourceStrings!; + + if (isSent || !(hasText || hasAttachments) || (isLastMessage && isTyping)) { + return nothing; + } + + return html` + ${this._renderActionButton(COPY_CONTENT, resourceStrings.reactionCopy)} + ${this._renderActionButton( + this.message.reactions?.includes(LIKE_ACTIVE) + ? LIKE_ACTIVE + : LIKE_INACTIVE, + resourceStrings.reactionLike + )} + ${this._renderActionButton( + this.message.reactions?.includes(DISLIKE_ACTIVE) + ? DISLIKE_ACTIVE + : DISLIKE_INACTIVE, + resourceStrings.reactionDislike + )} + ${this._renderActionButton( + REGENERATE, + resourceStrings.reactionRegenerate + )} + `; + } + + private _renderActionButton(name: string, tooltipMessage: string) { + return html` + + this._state.showActionsTooltip(target as Element, tooltipMessage)} + @focus=${({ target }: FocusEvent) => + this._state.showActionsTooltip(target as Element, tooltipMessage)} + > + `; + } + + private _renderAttachments() { + return isEmpty(this.message.attachments ?? []) + ? nothing + : html` + + `; + } + + private _renderMessage() { + const ctx: ChatMessageRenderContext = { + message: this.message, + instance: this._state.host, + }; + + return trimmedHtml` +
+ ${until(this._getRenderer('messageHeader')(ctx))} +
+
+ ${until(this._getRenderer('messageContent')(ctx))} +
+
+ ${until(this._getRenderer('messageAttachments')(ctx))} +
+
+ ${until(this._getRenderer('messageActions')(ctx))} +
+ `; + } + + protected override render() { + const messageRenderer = this._state.options?.renderers?.message; + const ctx: ChatMessageRenderContext = { + message: this.message, + instance: this._state.host, + }; + + const parts = { + 'message-container': true, + sent: this._state.isCurrentUserMessage(this.message), + }; + + return html` + ${cache( + this.message + ? html` +
+ ${cache( + messageRenderer + ? until(messageRenderer(ctx)) + : this._renderMessage() + )} +
+ ` + : nothing + )} + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'igc-chat-message': IgcChatMessageComponent; + } +} diff --git a/src/components/chat/chat-state.ts b/src/components/chat/chat-state.ts new file mode 100644 index 000000000..4bf109bba --- /dev/null +++ b/src/components/chat/chat-state.ts @@ -0,0 +1,354 @@ +import { IgcChatResourceStringEN } from '../common/i18n/chat.resources.js'; +import { isEmpty, nanoid } from '../common/util.js'; +import IgcToastComponent from '../toast/toast.js'; +import IgcTooltipComponent from '../tooltip/tooltip.js'; +import type IgcChatComponent from './chat.js'; +import type { IgcChatComponentEventMap } from './chat.js'; +import type { + ChatSuggestionsPosition, + IgcChatMessage, + IgcChatMessageAttachment, + IgcChatMessageReaction, + IgcChatOptions, +} from './types.js'; +import { + type ChatAcceptedFileTypes, + isImageAttachment, + parseAcceptedFileTypes, +} from './utils.js'; + +/** + * Internal state manager for the `` component. + * + * Manages messages, input value, attachments, options, and event emissions. + */ +export class ChatState { + //#region Internal properties and state /** The host `` component instance */ + private readonly _host: IgcChatComponent; + + private readonly _contextUpdateFn: () => unknown; + private readonly _userInputContextUpdateFn: () => unknown; + + private _actionsTooltip?: IgcTooltipComponent; + private _actionToast?: IgcToastComponent; + + /** The current list of messages */ + private _messages: IgcChatMessage[] = []; + /** Chat options/configuration */ + private _options?: IgcChatOptions; + + /** List of current input attachments */ + private _inputAttachments: IgcChatMessageAttachment[] = []; + /** Current input text */ + private _inputValue = ''; + /** + * Cache of accepted file types, organized into extensions, mimeTypes, and wildcardTypes + */ + private _acceptedTypesCache: ChatAcceptedFileTypes | null = null; + + public _isTyping = false; + private _lastTyped = Date.now(); + + public resourceStrings = IgcChatResourceStringEN; + + //#endregion + + //#region Public properties + + public get host(): IgcChatComponent { + return this._host; + } + + public get acceptedFileTypes(): ChatAcceptedFileTypes | null { + return this._acceptedTypesCache; + } + + public get disableAutoScroll(): boolean { + return this._options?.disableAutoScroll ?? false; + } + + /** + * Gets the list of chat messages. + */ + public get messages(): IgcChatMessage[] { + return this._messages; + } + + /** + * Sets the list of chat messages. + */ + public set messages(value: IgcChatMessage[]) { + this._messages = value; + } + + /** + * Gets current chat options. + */ + public get options(): IgcChatOptions | undefined { + return this._options; + } + + /** + * Sets chat options and requests host update. + */ + public set options(value: IgcChatOptions) { + this._options = value; + this._setAcceptedTypesCache(); + this._contextUpdateFn.call(this._host); + } + + /** + * Gets the current user ID from options or returns 'user' as fallback. + */ + public get currentUserId(): string { + return this._options?.currentUserId ?? 'user'; + } + + /** + * Gets the current suggestionsPosition from options or returns the default value 'below-messages'. + */ + public get suggestionsPosition(): ChatSuggestionsPosition { + return this._options?.suggestionsPosition ?? 'below-messages'; + } + + /** + * Gets the current stopTypingDelay from options or returns the default value `3000`. + */ + public get stopTypingDelay(): number { + return this._options?.stopTypingDelay ?? 3000; + } + + /** + * Gets the list of attachments currently attached to input. + */ + public get inputAttachments(): IgcChatMessageAttachment[] { + return this._inputAttachments; + } + + /** + * Sets the input attachments and requests host update. + */ + public set inputAttachments(value: IgcChatMessageAttachment[]) { + this._inputAttachments = value; + this._userInputContextUpdateFn.call(this._host); + } + + /** + * Gets the current input value. + */ + public get inputValue(): string { + return this._inputValue; + } + + /** + * Sets the current input value and requests host update. + */ + public set inputValue(value: string) { + this._inputValue = value; + this._userInputContextUpdateFn.call(this._host); + } + + /** + * Returns whether the default chat input textarea has a trimmed value payload. + * @internal + */ + public get hasInputValue(): boolean { + return !!this._inputValue.trim(); + } + + /** + * Returns whether the default file input of the chat has any attached files. + * @internal + */ + public get hasInputAttachments(): boolean { + return !isEmpty(this._inputAttachments); + } + + //#endregion + + constructor( + chat: IgcChatComponent, + contextUpdateFn: () => unknown, + userInputContextUpdateFn: () => unknown + ) { + this._host = chat; + this._contextUpdateFn = contextUpdateFn; + this._userInputContextUpdateFn = userInputContextUpdateFn; + } + + public isCurrentUserMessage(message?: IgcChatMessage): boolean { + return this.currentUserId === message?.sender; + } + + //#region Event handlers + + public emitEvent(name: keyof IgcChatComponentEventMap, args?: any): boolean { + return this._host.emitEvent(name, args); + } + + /** @internal */ + public emitMessageCreated(message: IgcChatMessage): boolean { + return this._host.emitEvent('igcMessageCreated', { + detail: message, + cancelable: true, + }); + } + + /** @internal */ + public emitAttachmentsAdded( + attachments: IgcChatMessageAttachment[] + ): boolean { + return this._host.emitEvent('igcAttachmentAdded', { + detail: attachments, + cancelable: true, + }); + } + + /** @internal */ + public emitAttachmentRemoved(attachment: IgcChatMessageAttachment): boolean { + return this._host.emitEvent('igcAttachmentRemoved', { + detail: attachment, + cancelable: true, + }); + } + + /** @internal */ + public emitMessageReaction(reaction: IgcChatMessageReaction): boolean { + return this._host.emitEvent('igcMessageReact', { detail: reaction }); + } + + /** + * @internal + */ + public showActionsTooltip(target: Element, message: string): void { + if (!this._actionsTooltip) { + this._actionsTooltip = document.createElement( + IgcTooltipComponent.tagName + ); + this._actionsTooltip.hideTriggers = 'pointerleave,click,blur'; + this._actionsTooltip.hideDelay = 100; + this._host.renderRoot.appendChild(this._actionsTooltip); + } + this._actionsTooltip.message = message; + this._actionsTooltip.show(target); + } + + /** + * @internal + */ + public showActionToast(content: string): void { + if (!this._actionToast) { + this._actionToast = document.createElement(IgcToastComponent.tagName); + this._actionToast.displayTime = 3000; + this._host.renderRoot.appendChild(this._actionToast); + } + this._actionToast.textContent = content; + this._actionToast.show(); + } + + //#endregion + + /** + * Updates the internal cache for accepted file types. + * Parses the acceptedFiles string option into extensions, mimeTypes, and wildcard types. + */ + private _setAcceptedTypesCache(): void { + this._acceptedTypesCache = this.options?.acceptedFiles + ? parseAcceptedFileTypes(this.options.acceptedFiles) + : null; + } + + protected _createMessage(message: Partial): IgcChatMessage { + return { + id: message.id ?? nanoid(), + text: message.text ?? '', + sender: message.sender ?? this.currentUserId, + timestamp: message.timestamp ?? Date.now().toString(), + attachments: message.attachments || [], + }; + } + + public addMessage(message: Partial) { + this.messages.push(this._createMessage(message)); + this._host.requestUpdate('messages'); + } + + //#region Public API + + /** + * Adds a new chat message. + * Emits 'igcMessageCreated' event which can be canceled to prevent adding. + * Clears input value and attachments on success. + * @internal + */ + public addMessageWithEvent(message: Partial): void { + const newMessage = this._createMessage(message); + + if (this.emitMessageCreated(newMessage)) { + this.addMessage(newMessage); + this.inputValue = ''; + this.inputAttachments = []; + } + } + + /** + * Adds files as attachments to the input. + * Emits 'igcAttachmentChange' event which can be canceled to prevent adding. + * @internal + */ + public attachFilesWithEvent(files: File[]): void { + const newAttachments: IgcChatMessageAttachment[] = []; + const fileNames = new Set( + this.inputAttachments.map((attachment) => attachment.file?.name ?? '') + ); + + for (const file of files) { + if (fileNames.has(file.name)) { + continue; + } + + const url = URL.createObjectURL(file); + const attachment: IgcChatMessageAttachment = { + id: nanoid(), + url, + name: file.name, + file, + }; + + if (isImageAttachment(file)) { + attachment.thumbnail = url; + } + newAttachments.push(attachment); + } + + if (this.emitAttachmentsAdded(newAttachments)) { + this.inputAttachments = [...this.inputAttachments, ...newAttachments]; + } + } + + public handleKeyDown = (_: KeyboardEvent) => { + this._lastTyped = Date.now(); + if (!this._isTyping) { + this.emitEvent('igcTypingChange', { + detail: { isTyping: true }, + }); + this._isTyping = true; + + const stopTypingDelay = this.stopTypingDelay; + setTimeout(() => { + if ( + this._isTyping && + stopTypingDelay && + this._lastTyped + stopTypingDelay < Date.now() + ) { + this.emitEvent('igcTypingChange', { + detail: { isTyping: false }, + }); + this._isTyping = false; + } + }, stopTypingDelay); + } + }; + + //#endregion +} diff --git a/src/components/chat/chat.spec.ts b/src/components/chat/chat.spec.ts new file mode 100644 index 000000000..dc05997cc --- /dev/null +++ b/src/components/chat/chat.spec.ts @@ -0,0 +1,1157 @@ +import { elementUpdated, expect, fixture } from '@open-wc/testing'; +import { html, nothing } from 'lit'; +import { spy, stub, useFakeTimers } from 'sinon'; +import type IgcIconButtonComponent from '../button/icon-button.js'; +import IgcChipComponent from '../chip/chip.js'; +import { enterKey } from '../common/controllers/key-bindings.js'; +import { defineComponents } from '../common/definitions/defineComponents.js'; +import { first, last } from '../common/util.js'; +import { + isFocused, + simulateBlur, + simulateClick, + simulateFocus, + simulateKeyboard, +} from '../common/utils.spec.js'; +import { simulateFileUpload } from '../file-input/file-input.spec.js'; +import IgcInputComponent from '../input/input.js'; +import IgcListItemComponent from '../list/list-item.js'; +import IgcTextareaComponent from '../textarea/textarea.js'; +import IgcChatComponent from './chat.js'; +import IgcChatInputComponent from './chat-input.js'; +import IgcChatMessageComponent from './chat-message.js'; +import IgcMessageAttachmentsComponent from './message-attachments.js'; +import type { IgcChatMessage, IgcChatMessageAttachment } from './types.js'; + +describe('Chat', () => { + before(() => { + defineComponents(IgcChatComponent, IgcInputComponent); + }); + + const textInputTemplate = (text: string) => html` + + `; + + const textAreaActionsTemplate = () => html` +
+ Upload + Send +
+ `; + + const textAreaAttachmentsTemplate = ( + attachments: IgcChatMessageAttachment[] + ) => { + return html` +
+ ${attachments.map( + (attachment) => html` + + ${attachment.name} + + ` + )} +
+ `; + }; + + const messages: IgcChatMessage[] = [ + { + id: '1', + text: 'Hello! How can I help you today?', + sender: 'bot', + }, + { + id: '2', + text: 'Hello!', + sender: 'user', + attachments: [ + { + id: 'img1', + name: 'img1.png', + url: 'https://www.infragistics.com/angular-demos/assets/images/men/1.jpg', + type: 'image', + }, + ], + }, + { + id: '3', + text: 'Thank you!', + sender: 'bot', + attachments: [ + { + id: 'file1', + name: 'file1.other', + url: 'http://some-link-to/file1.other', + type: 'file', + }, + ], + }, + { + id: '4', + text: 'Thank you too!', + sender: 'user', + }, + ]; + + const draftMessage = { + text: 'Draft message', + attachments: [ + { + id: 'img1', + name: 'img1.png', + url: 'https://www.infragistics.com/angular-demos/assets/images/men/1.jpg', + type: 'image', + }, + ], + }; + + const files = [ + new File(['test content'], 'test.txt', { type: 'text/plain' }), + new File(['image data'], 'image.png', { type: 'image/png' }), + ]; + + let chat: IgcChatComponent; + + beforeEach(async () => { + chat = await fixture(html``); + }); + + describe('Initialization', () => { + it('is correctly initialized with its default component state', () => { + expect(chat.messages).to.be.empty; + expect(chat.options).to.be.undefined; + expect(chat.draftMessage).to.eql({ text: '', attachments: [] }); + }); + + it('empty chat is rendered correctly', () => { + const { emptyState, input } = getChatDOM(chat); + + expect(emptyState).not.to.be.null; + expect(input.fileInput).not.to.be.null; + expect(input.textarea).not.to.be.null; + expect(input.sendButton).not.to.be.null; + }); + + it('should render initially set messages correctly', async () => { + chat.messages = messages; + await elementUpdated(chat); + + const { messageList, messages: renderedMessages } = getChatDOM(chat); + + expect(chat.messages).lengthOf(messages.length); + expect(messageList).not.to.be.null; + expect(renderedMessages).lengthOf(messages.length); + + const [firstMessage, lastMessage] = [ + first(renderedMessages), + last(renderedMessages), + ]; + + // Response messages have the default reactions. + expect(getChatMessageDOM(firstMessage).defaultActionButtons).lengthOf(4); + + // Current user messages does not have default reactions + expect(getChatMessageDOM(lastMessage).defaultActionButtons).to.be.empty; + }); + + it('should render messages from the current user correctly', async () => { + chat.messages = [ + first(messages), + last(messages), + { id: '2', text: 'Hello!', sender: 'me' }, + ]; + chat.options = { currentUserId: 'me' }; + await elementUpdated(chat); + + const renderedMessages = getChatDOM(chat).messages; + const currentUserMessage = last(renderedMessages); + + for (const each of renderedMessages) { + expect( + getChatMessageDOM(each).container.part.contains('sent') + ).to.equal(each === currentUserMessage); + } + }); + + it('should render the message in `draftMessage` correctly', async () => { + chat.draftMessage = draftMessage; + await elementUpdated(chat); + + const { input } = getChatDOM(chat); + + expect(input.textarea.value).to.equal(draftMessage.text); + expect(input.chips).lengthOf(draftMessage.attachments.length); + }); + + it('should apply `headerText` correctly', async () => { + chat.options = { headerText: 'Chat' }; + await elementUpdated(chat); + + const { header } = getChatDOM(chat); + expect(header.innerText).to.equal(chat.options.headerText); + }); + + it('should apply `inputPlaceholder` correctly', async () => { + chat.options = { inputPlaceholder: 'Type message here...' }; + await elementUpdated(chat); + + const { input } = getChatDOM(chat); + + expect(input.textarea.placeholder).to.equal( + chat.options.inputPlaceholder + ); + }); + + it('should enable/disable the send button properly', async () => { + const { textarea, sendButton, fileInput } = getChatDOM(chat).input; + + expect(sendButton.disabled).to.be.true; + + // When there is a text in the text area, the send button should be enabled + let value = 'Hello!'; + textarea.value = value; + textarea.emitEvent('igcInput', { detail: value }); + await elementUpdated(chat); + + expect(sendButton.disabled).to.be.false; + + // When there is no text in the text area, the send button should be disabled + value = ''; + textarea.value = value; + textarea.emitEvent('igcInput', { detail: value }); + await elementUpdated(chat); + + expect(sendButton.disabled).to.be.true; + + // When there are attachments, the send button should be enabled regardless of the text area content + simulateFileUpload(fileInput, files); + await elementUpdated(chat); + + expect(sendButton.disabled).to.be.false; + }); + + it('should not render attachment button if `disableInputAttachments` is true', async () => { + chat.options = { disableInputAttachments: true }; + await elementUpdated(chat); + + const { input } = getChatDOM(chat); + expect(input.fileInput).to.be.null; + }); + + it('should update the file-input accepted prop based on the `acceptedFiles`', async () => { + chat.options = { acceptedFiles: 'image/*' }; + await elementUpdated(chat); + + const { input } = getChatDOM(chat); + + expect(input.fileInput.accept).to.equal(chat.options.acceptedFiles); + + chat.options = {}; + await elementUpdated(chat); + + expect(input.fileInput.accept).to.be.empty; + }); + + it('should render attachments chips correctly', async () => { + const { input } = getChatDOM(chat); + const fileNames = new Set(files.map((file) => file.name)); + + simulateFileUpload(input.fileInput, files); + await elementUpdated(chat); + + expect(input.chips).length(files.length); + expect(input.chips.every((chip) => fileNames.has(chip.innerText))).to.be + .true; + }); + + it('should not render container if suggestions are not provided', () => { + expect(getChatDOM(chat).suggestionsContainer).to.be.null; + }); + + it('should render suggestions if provided', async () => { + chat.options = { suggestions: ['Suggestion 1', 'Suggestion 2'] }; + await elementUpdated(chat); + + const { suggestionsContainer } = getChatDOM(chat); + + expect(suggestionsContainer).not.to.be.null; + expect(suggestionsContainer.querySelector('igc-list')).not.to.be.null; + }); + + it('should render suggestions below empty state by default', async () => { + chat.options = { suggestions: ['Suggestion 1', 'Suggestion 2'] }; + await elementUpdated(chat); + + const { emptyState, suggestionsContainer } = getChatDOM(chat); + expect(suggestionsContainer.previousElementSibling).to.eql(emptyState); + }); + + it('should render suggestions below messages by default', async () => { + chat.options = { suggestions: ['Suggestion 1', 'Suggestion 2'] }; + chat.messages.push({ id: '5', text: 'New message', sender: 'user' }); + await elementUpdated(chat); + + const { messageList, suggestionsContainer } = getChatDOM(chat); + + expect( + suggestionsContainer.getBoundingClientRect().top + ).to.be.greaterThanOrEqual(messageList.getBoundingClientRect().bottom); + }); + + it("should render suggestions below input area when position is 'below-input'", async () => { + chat.options = { + suggestions: ['Suggestion 1', 'Suggestion 2'], + suggestionsPosition: 'below-input', + }; + await elementUpdated(chat); + + const { input, suggestionsContainer } = getChatDOM(chat); + expect(suggestionsContainer.getBoundingClientRect().top).lessThanOrEqual( + input.self.getBoundingClientRect().bottom + ); + }); + + it('should render typing indicator if `isTyping` is true', async () => { + chat.options = { isTyping: true }; + await elementUpdated(chat); + + expect(getChatDOM(chat).typingIndicator).not.to.be.null; + + chat.options = { isTyping: false }; + await elementUpdated(chat); + + expect(getChatDOM(chat).typingIndicator).to.be.null; + }); + }); + + describe('Slots', () => { + const getSlottedElements = (slotName: string) => { + const prefixSlot = chat.shadowRoot?.querySelector( + `slot[name="${slotName}"` + ) as HTMLSlotElement; + return prefixSlot?.assignedElements(); + }; + const suggestions = ['Login screen', 'Registration Form']; + + beforeEach(async () => { + chat = await fixture(html` + +
+ ⋯ +
+

Title

+
+ ? +
+ What do you want to build? +

Get inspired

+
+ ${suggestions.map((suggestion, index) => { + return html` +
+ ${index}. ${suggestion} + +
+ `; + })} +
+

Add more ...

+
+ `); + + chat.options = { ...chat.options, suggestions }; + await elementUpdated(chat); + }); + + it('should slot header prefix', () => { + const slottedElements = getSlottedElements('prefix'); + expect(slottedElements.length).to.equal(1); + expect(slottedElements[0]).dom.to.equal( + `
+ ⋯ +
` + ); + }); + it('should slot header title', () => { + const slottedElements = getSlottedElements('title'); + expect(slottedElements.length).to.equal(1); + expect(slottedElements[0]).dom.to.equal(`

Title

`); + }); + it('should slot header action buttons area', () => { + const slottedElements = getSlottedElements('actions'); + expect(slottedElements.length).to.equal(1); + expect(slottedElements[0]).dom.to.equal( + `
+ ? +
` + ); + }); + it('should slot message list area when there are no messages', () => { + const slottedElements = getSlottedElements('empty-state'); + expect(slottedElements.length).to.equal(1); + expect(slottedElements[0]).dom.to.equal( + `What do you want to build?` + ); + }); + it('should slot suggestions header', async () => { + const slottedElements = getSlottedElements('suggestions-header'); + expect(slottedElements?.length).to.equal(1); + expect(slottedElements[0]).dom.to.equal( + `

Get inspired

` + ); + }); + it('should slot suggestions area', async () => { + const slottedElements = getSlottedElements('suggestions'); + expect(slottedElements?.length).to.equal(1); + expect(slottedElements[0]).dom.to.equal(`
+
+ + 0. Login screen + + + +
+
+ + 1. Registration Form + + + +
+
`); + }); + it('should slot suggestions actions area', async () => { + const slottedElements = getSlottedElements('suggestions-actions'); + expect(slottedElements?.length).to.equal(1); + expect(slottedElements[0]).dom.to.equal( + `

Add more ...

` + ); + }); + }); + + describe('Templates', () => { + beforeEach(async () => { + chat.messages = [messages[1], messages[2]]; + }); + + it('should render attachment template', async () => { + chat.options = { + renderers: { + attachment: ({ attachment }) => html` + + ${attachment.name} + + `, + }, + }; + await elementUpdated(chat); + + const { messages } = getChatDOM(chat); + const attachments = messages.flatMap( + (message) => getChatMessageDOM(message).attachments + ); + + for (const attachment of attachments) { + expect( + getChatAttachmentDOM(attachment).container.querySelector( + 'igc-chip.custom-attachment' + ) + ).not.to.be.null; + } + }); + + it('should render attachmentHeader template, attachmentContent template', async () => { + chat.options = { + renderers: { + attachmentHeader: ({ attachment }) => + html`
Custom ${attachment.name}
`, + attachmentContent: ({ attachment }) => html` +

This is a template rendered as content of ${attachment.name}

+ `, + }, + }; + await elementUpdated(chat); + + const { messages } = getChatDOM(chat); + const attachments = messages.flatMap( + (message) => getChatMessageDOM(message).attachments + ); + + for (const attachment of attachments) { + const { header, content } = getChatAttachmentDOM(attachment); + expect(header.querySelector('h5')?.innerText).matches(/^Custom/); + expect(content.querySelector('p')?.innerText).matches( + /^This is a template/ + ); + } + }); + + it('should render message template', async () => { + chat.options = { + renderers: { + message: ({ message }) => html` +
+
${message.sender === 'user' ? 'You' : 'Bot'}
+

${message.text}

+
+ `, + }, + }; + await elementUpdated(chat); + + for (const message of getChatDOM(chat).messages) { + expect( + getChatMessageDOM(message).container.querySelector('h5')?.innerText + ).to.equal(message.message.sender === 'user' ? 'You' : 'Bot'); + } + }); + + it('should render messageContent template', async () => { + chat.options = { + renderers: { + messageContent: ({ message }) => html`${message.text.toUpperCase()}`, + }, + }; + await elementUpdated(chat); + + for (const [index, message] of getChatDOM(chat).messages.entries()) { + expect(getChatMessageDOM(message).content.innerText).to.equal( + chat.messages[index].text.toUpperCase() + ); + } + }); + + it('should render messageActionsTemplate', async () => { + chat.options = { + renderers: { + messageActions: ({ message }) => + message.sender !== 'user' + ? html`` + : nothing, + }, + }; + await elementUpdated(chat); + + for (const message of getChatDOM(chat).messages) { + expect(getChatMessageDOM(message).actions.innerText).to.equal( + message.message.sender === 'user' ? '' : 'Custom action' + ); + } + }); + + it('should render custom typingIndicator', async () => { + chat.messages = [messages[0]]; + chat.options = { + isTyping: true, + renderers: { + typingIndicator: () => html`loading...`, + }, + }; + await elementUpdated(chat); + + expect(getChatDOM(chat).typingIndicator.innerText).to.equal('loading...'); + }); + + it('should render text area templates', async () => { + chat.draftMessage = draftMessage; + chat.options = { + renderers: { + input: (ctx) => textInputTemplate(ctx.value), + inputActions: () => textAreaActionsTemplate(), + inputAttachments: (ctx) => + textAreaAttachmentsTemplate(ctx.attachments), + }, + }; + await elementUpdated(chat); + + const { self: inputArea, sendButton, fileInput } = getChatDOM(chat).input; + + expect(inputArea.renderRoot.querySelector('igc-input')?.value).to.equal( + draftMessage.text + ); + expect(inputArea.renderRoot.querySelector('a')?.href).to.equal( + draftMessage.attachments[0].url + ); + + expect(sendButton).to.be.null; + expect(fileInput).to.be.null; + var customActions = + inputArea.renderRoot.querySelector('div.custom-actions'); + expect(customActions).not.to.be.null; + }); + + it('should render messageHeader template', async () => { + chat.options = { + renderers: { + messageHeader: ({ message }) => + html`${message.sender !== 'user' ? 'AI Assistant' : ''}`, + }, + }; + await elementUpdated(chat); + + for (const message of getChatDOM(chat).messages) { + expect(getChatMessageDOM(message).header.innerText).to.equal( + message.message.sender === 'user' ? '' : 'AI Assistant' + ); + } + }); + }); + + describe('Interactions', () => { + describe('Click', () => { + it('should update messages properly on send button click', async () => { + const eventSpy = spy(chat, 'emitEvent'); + const { textarea, sendButton } = getChatDOM(chat).input!; + textarea.setAttribute('value', 'Hello!'); + textarea.dispatchEvent( + new CustomEvent('igcInput', { detail: 'Hello!' }) + ); + await elementUpdated(chat); + + simulateClick(sendButton); + await elementUpdated(chat); + + expect(eventSpy).calledWith('igcMessageCreated'); + const eventArgs = eventSpy.getCall(1).args[1]?.detail as IgcChatMessage; + const args = { ...eventArgs, text: 'Hello!', sender: 'user' }; + expect(eventArgs).to.deep.equal(args); + expect(chat.messages.length).to.equal(1); + expect(chat.messages[0].text).to.equal('Hello!'); + expect(chat.messages[0].sender).to.equal('user'); + // The focus should be on the input area after send button is clicked + expect(isFocused(textarea)).to.be.true; + }); + + it('should update messages properly on suggestion chip click', async () => { + const eventSpy = spy(chat, 'emitEvent'); + chat.options = { + suggestions: ['Suggestion 1', 'Suggestion 2'], + }; + await elementUpdated(chat); + + const suggestionItems = getChatDOM( + chat + ).suggestionsContainer.querySelectorAll(IgcListItemComponent.tagName); + + expect(suggestionItems.length).to.equal(2); + simulateClick(suggestionItems[0]); + await elementUpdated(chat); + + expect(eventSpy).calledWith('igcMessageCreated'); + const eventArgs = eventSpy.getCall(0).args[1]?.detail; + const args = + eventArgs && typeof eventArgs === 'object' + ? { ...eventArgs, text: 'Suggestion 1', sender: 'user' } + : { text: 'Suggestion 1', sender: 'user' }; + expect(eventArgs).to.deep.equal(args); + expect(chat.messages.length).to.equal(1); + expect(chat.messages[0].text).to.equal('Suggestion 1'); + expect(chat.messages[0].sender).to.equal('user'); + + // The focus should be on the input area after suggestion click + expect(isFocused(getChatDOM(chat).input.textarea)).to.be.true; + }); + + it('should remove attachment on chip remove button click', async () => { + const eventSpy = spy(chat, 'emitEvent'); + const fileInput = getChatDOM(chat).input.fileInput; + simulateFileUpload(fileInput, files); + await elementUpdated(chat); + + expect(eventSpy).calledOnce; + expect(eventSpy.calledWith('igcAttachmentAdded')).to.be.true; + + const attachments = getChatDOM(chat).input.chips; + expect(attachments.length).to.equal(2); + const removeFileButton = attachments[1]?.renderRoot.querySelector( + 'igc-icon' + ) as HTMLElement; + simulateClick(removeFileButton); + await elementUpdated(chat); + + expect(eventSpy).calledTwice; + expect(eventSpy.calledWith('igcAttachmentRemoved')).to.be.true; + const detail = eventSpy.getCall(1).args[1]?.detail; + expect((detail as IgcChatMessageAttachment).name).to.equal( + files[1].name + ); + }); + + it('should disable send button on removing all attachments', async () => { + const inputArea = getChatDOM(chat).input!; + const { fileInput, sendButton } = inputArea; + + simulateFileUpload(fileInput, files); + await elementUpdated(chat); + + const attachments = inputArea.chips; + simulateClick(attachments[1].renderRoot.querySelector('igc-icon')!); + simulateClick(attachments[0].renderRoot.querySelector('igc-icon')!); + await elementUpdated(inputArea.self); + + expect(sendButton.disabled).to.be.true; + }); + + it('should update like button state on click', async () => { + chat.messages = [messages[0]]; + await elementUpdated(chat); + + const firstMessage = getChatDOM(chat).messages[0]; + // click on like (inactive) icon + const likeIcon = + getChatMessageDOM(firstMessage).defaultActionButtons[1]; + simulateClick(likeIcon); + await elementUpdated(chat); + + expect(likeIcon.name).to.equal('thumb_up_active'); + // click on like (active) icon + simulateClick(likeIcon); + await elementUpdated(chat); + + expect(likeIcon.name).to.equal('thumb_up_inactive'); + + // click on like (inactive) icon + simulateClick(likeIcon); + await elementUpdated(chat); + expect(likeIcon.name).to.equal('thumb_up_active'); + }); + + it('should toggle like/dislike state on click', async () => { + chat.messages = [messages[0]]; + await elementUpdated(chat); + + const firstMessage = getChatDOM(chat).messages[0]; + // click on like (inactive) icon + const likeIcon = + getChatMessageDOM(firstMessage).defaultActionButtons[1]; + simulateClick(likeIcon); + await elementUpdated(chat); + + const dislikeIcon = + getChatMessageDOM(firstMessage).defaultActionButtons[2]; + expect(dislikeIcon.name).to.equal('thumb_down_inactive'); + // click on dislike (active) icon + simulateClick(dislikeIcon); + await elementUpdated(chat); + + expect(likeIcon.name).to.equal('thumb_up_inactive'); + expect(dislikeIcon.name).to.equal('thumb_down_active'); + + // click on like (inactive) icon + simulateClick(likeIcon); + await elementUpdated(chat); + expect(likeIcon.name).to.equal('thumb_up_active'); + }); + + it('should handle the copy action properly', async () => { + const clipboardWriteText = stub( + navigator.clipboard, + 'writeText' + ).resolves(); + chat.messages = [messages[0]]; + await elementUpdated(chat); + + expect(clipboardWriteText.called).to.be.false; + const firstMessage = + chat.shadowRoot?.querySelectorAll('igc-chat-message')[0]; + // click on copy icon + const copyIcon = firstMessage?.shadowRoot?.querySelector( + 'igc-icon-button[name="copy_content"]' + ) as HTMLElement; + simulateClick(copyIcon); + await elementUpdated(chat); + expect(clipboardWriteText.called).to.be.true; + }); + }); + + describe('Drag & Drop', () => { + beforeEach(async () => { + const options = { + acceptedFiles: '.txt', + }; + chat = await fixture( + html` ` + ); + }); + + it('should be able to drag & drop files based on the types listed in `acceptedFiles`', async () => { + const eventSpy = spy(chat, 'emitEvent'); + const inputArea = getChatDOM(chat).input.self!; + const dropZone = inputArea?.renderRoot.querySelector( + `div[part='input-container']` + ); + + expect(dropZone).not.to.be.null; + if (dropZone) { + const mockDataTransfer = new DataTransfer(); + files.forEach((file) => { + mockDataTransfer.items.add(file); + }); + + const dragEnterEvent = new DragEvent('dragenter', { + bubbles: true, + cancelable: true, + }); + + Object.defineProperty(dragEnterEvent, 'dataTransfer', { + value: mockDataTransfer, + }); + + dropZone?.dispatchEvent(dragEnterEvent); + await elementUpdated(chat); + + expect(eventSpy).calledOnce; + expect(eventSpy).calledWith('igcAttachmentDrag'); + + const dropEvent = new DragEvent('drop', { + bubbles: true, + cancelable: true, + }); + Object.defineProperty(dropEvent, 'dataTransfer', { + value: mockDataTransfer, + }); + + dropZone.dispatchEvent(dropEvent); + await elementUpdated(chat); + + expect(eventSpy).calledWith('igcAttachmentDrop'); + const attachments = getChatDOM(chat).input.chips; + expect(attachments?.length).to.equal(1); + expect(attachments?.[0]?.textContent?.trim()).to.equal('test.txt'); + expect(eventSpy).calledWith('igcAttachmentDrop'); + expect(eventSpy).calledWith('igcAttachmentAdded'); + } + }); + }); + + describe('Keyboard', () => { + it('should update messages properly on `Enter` keypress when the textarea is focused', async () => { + const eventSpy = spy(chat, 'emitEvent'); + const textArea = getChatDOM(chat).input.textarea; + + textArea.setAttribute('value', 'Hello!'); + textArea.dispatchEvent( + new CustomEvent('igcInput', { detail: 'Hello!' }) + ); + await elementUpdated(chat); + simulateFocus(textArea); + simulateKeyboard(textArea, enterKey); + await elementUpdated(chat); + + expect(eventSpy).calledWith('igcMessageCreated'); + const eventArgs = eventSpy.getCall(2).args[1]?.detail; + const args = + eventArgs && typeof eventArgs === 'object' + ? { ...eventArgs, text: 'Hello!', sender: 'user' } + : { text: 'Hello!', sender: 'user' }; + expect(eventArgs).to.deep.equal(args); + expect(chat.messages.length).to.equal(1); + expect(chat.messages[0].text).to.equal('Hello!'); + expect(chat.messages[0].sender).to.equal('user'); + + // The focus should be on the input area after message is sent + expect(isFocused(textArea)).to.be.true; + }); + }); + }); + + describe('Events', () => { + it('emits igcAttachmentClick', async () => { + const eventSpy = spy(chat, 'emitEvent'); + chat.messages = [messages[1]]; + await elementUpdated(chat); + + const messageElement = getChatDOM(chat).messages[0]; + const attachment = getChatMessageDOM(messageElement).attachments[0]; + const attachmentHeader = getChatAttachmentDOM(attachment).header; + + simulateClick(attachmentHeader); + expect(eventSpy).calledWith('igcAttachmentClick', { + detail: { ...messages[1].attachments?.at(0) }, + }); + }); + + it('emits igcTypingChange', async () => { + const clock = useFakeTimers({ now: 0, toFake: ['Date', 'setTimeout'] }); + + const eventSpy = spy(chat, 'emitEvent'); + const textArea = getChatDOM(chat).input.textarea; + + chat.options = { stopTypingDelay: 2500 }; + simulateKeyboard(textArea, 'a'); + await elementUpdated(chat); + + expect(eventSpy).calledWith('igcTypingChange'); + expect(eventSpy.firstCall.args[1]?.detail).to.eql({ isTyping: true }); + + clock.setSystemTime(2501); + await clock.runAllAsync(); + + expect(eventSpy).calledWith('igcTypingChange'); + expect(eventSpy.lastCall.args[1]?.detail).to.eql({ isTyping: false }); + + clock.restore(); + }); + + it('emits igcInputFocus', async () => { + const eventSpy = spy(chat, 'emitEvent'); + + simulateFocus(getChatDOM(chat).input.textarea); + expect(eventSpy).calledWith('igcInputFocus'); + }); + + it('emits igcInputBlur', async () => { + const eventSpy = spy(chat, 'emitEvent'); + + simulateBlur(getChatDOM(chat).input.textarea); + expect(eventSpy).calledWith('igcInputBlur'); + }); + + it('emits igcInputChange', async () => { + const eventSpy = spy(chat, 'emitEvent'); + const textArea = getChatDOM(chat).input.textarea!; + + textArea.setAttribute('value', 'Hello!'); + textArea.dispatchEvent(new CustomEvent('igcInput', { detail: 'Hello!' })); + await elementUpdated(chat); + expect(eventSpy).calledWith('igcInputChange', { + detail: { value: 'Hello!' }, + }); + }); + + it('emits igcMessageReact', async () => { + const eventSpy = spy(chat, 'emitEvent'); + chat.messages = [messages[0]]; + await elementUpdated(chat); + + const messageElement = getChatDOM(chat).messages[0]; + const likeIcon = + getChatMessageDOM(messageElement).defaultActionButtons[1]; + + simulateClick(likeIcon); + expect(eventSpy).calledWith('igcMessageReact', { + detail: { message: messages[0], reaction: 'thumb_up_active' }, + }); + }); + + it('can cancel `igcMessageCreated` event', async () => { + const inputArea = getChatDOM(chat).input; + const { sendButton, textarea } = inputArea; + + chat.addEventListener('igcMessageCreated', (event) => { + event.preventDefault(); + }); + + textarea.setAttribute('value', 'Hello!'); + textarea.dispatchEvent(new CustomEvent('igcInput', { detail: 'Hello!' })); + await elementUpdated(chat); + simulateClick(sendButton); + await elementUpdated(chat); + + expect(chat.messages.length).to.equal(0); + }); + + it('can cancel `igcAttachmentChange` event', async () => { + const inputArea = getChatDOM(chat).input!; + const fileInput = inputArea.fileInput; + + chat.addEventListener('igcAttachmentAdded', (event) => { + event.preventDefault(); + }); + + simulateFileUpload(fileInput, files); + await elementUpdated(chat); + + expect(inputArea?.chips.length).to.equal(0); + }); + }); + + describe('adoptRootStyles behavior', () => { + const customStyles = 'custom-background'; + + beforeEach(async () => { + const styles = document.createElement('style'); + styles.setAttribute('id', 'adopt-styles-test'); + styles.innerHTML = ` + .custom-background { + background-color: rgb(255, 0, 0); + } + `; + document.head.append(styles); + }); + + it('correctly applies `adoptRootStyles` when set', async () => { + chat.options = { + adoptRootStyles: true, + renderers: { + messageContent: ({ message }) => + html`
${message.text}
`, + }, + }; + chat.messages = [{ id: 'id', sender: 'bot', text: 'Hello' }]; + + await elementUpdated(chat); + + const { messages } = getChatDOM(chat); + expect( + getComputedStyle( + getChatMessageDOM(first(messages)).content.querySelector( + `.${customStyles}` + )! + ).backgroundColor + ).equal('rgb(255, 0, 0)'); + }); + + it('skips `adoptRootStyles` when not set', async () => { + chat.options = { + renderers: { + messageContent: ({ message }) => + html`
${message.text}
`, + }, + }; + + chat.messages = [{ id: 'id', sender: 'bot', text: 'Hello' }]; + + await elementUpdated(chat); + + const { messages } = getChatDOM(chat); + expect( + getComputedStyle( + getChatMessageDOM(first(messages)).content.querySelector( + `.${customStyles}` + )! + ).backgroundColor + ).not.equal('rgb(255, 0, 0)'); + }); + }); +}); + +/** Returns an object containing the shadow DOM structure of a chat component. */ +function getChatDOM(chat: IgcChatComponent) { + const root = chat.renderRoot!; + const inputArea = root.querySelector(IgcChatInputComponent.tagName)!; + + return { + /** The igc-chat-input component */ + input: { + /** The igc-chat-input component itself */ + get self() { + return inputArea; + }, + /** The default textarea input of the chat. */ + get textarea() { + return inputArea.renderRoot.querySelector( + IgcTextareaComponent.tagName + )!; + }, + /** The default file input of the chat. */ + get fileInput() { + return inputArea.renderRoot.querySelector('input')!; + }, + /** The default send button of the chat. */ + get sendButton() { + return inputArea.renderRoot.querySelector( + '[name="send_message"]' + )!; + }, + /** The default igc-chip components representing attachments */ + get chips() { + return Array.from( + inputArea.renderRoot.querySelectorAll(IgcChipComponent.tagName) + ); + }, + }, + /** The chat header container */ + get header() { + return root.querySelector('[part="header"]')!; + }, + /** The chat message container */ + get messageList() { + return root.querySelector('[part="message-list"]')!; + }, + /** Rendered chat messages */ + get messages() { + return Array.from(root.querySelectorAll(IgcChatMessageComponent.tagName)); + }, + /** The typing indicator container of the chat */ + get typingIndicator() { + return root.querySelector('[part="typing-indicator"]')!; + }, + /** The chat container when no messages are present */ + get emptyState() { + return root.querySelector('[part="empty-state"]')!; + }, + /** The container of the chat suggestions */ + get suggestionsContainer() { + return root.querySelector('[part="suggestions-container"]')!; + }, + }; +} + +/** Returns an object containing the shadow DOM structure of a chat message component. */ +function getChatMessageDOM(message: IgcChatMessageComponent) { + const root = message.renderRoot; + + return { + /** The encompassing container of the chat message component */ + get container() { + return root.querySelector('[part~="message-container"]')!; + }, + /** Header container of the chat message holding the `messageHeader` renderer output. */ + get header() { + return root.querySelector('[part="message-header"]')!; + }, + /** Content container of the chat message holding the `messageContent` renderer output. */ + get content() { + return root.querySelector('[part="plain-text"]')!; + }, + /** Chat message attachments container */ + get attachmentsContainer() { + return root.querySelector('[part="message-attachments"]')!; + }, + /** The attachments components of the message */ + get attachments() { + return Array.from( + root.querySelectorAll(IgcMessageAttachmentsComponent.tagName) + ); + }, + /** Actions container of the chat message holding the `messageActions` renderer output. */ + get actions() { + return root.querySelector('[part="message-actions"]')!; + }, + /** The default reaction buttons of a chat message */ + get defaultActionButtons() { + return Array.from( + root.querySelectorAll( + '[part="message-actions"] igc-icon-button' + ) + )!; + }, + }; +} + +function getChatAttachmentDOM(attachment: IgcMessageAttachmentsComponent) { + const root = attachment.renderRoot; + + return { + get header() { + return root.querySelector('[part="details"]')!; + }, + get content() { + return root.querySelector('[part~="attachment-content"]')!; + }, + get container() { + return root.querySelector('[part="attachments-container"]')!; + }, + }; +} diff --git a/src/components/chat/chat.ts b/src/components/chat/chat.ts new file mode 100644 index 000000000..c298da872 --- /dev/null +++ b/src/components/chat/chat.ts @@ -0,0 +1,535 @@ +import { ContextProvider } from '@lit/context'; +import { html, LitElement, nothing, type PropertyValues } from 'lit'; +import { property, query } from 'lit/decorators.js'; +import { cache } from 'lit/directives/cache.js'; +import { repeat } from 'lit/directives/repeat.js'; +import { addThemingController } from '../../theming/theming-controller.js'; +import IgcButtonComponent from '../button/button.js'; +import { chatContext, chatUserInputContext } from '../common/context.js'; +import { addSlotController, setSlots } from '../common/controllers/slot.js'; +import { registerComponent } from '../common/definitions/register.js'; +import { IgcChatResourceStringEN } from '../common/i18n/chat.resources.js'; +import type { Constructor } from '../common/mixins/constructor.js'; +import { EventEmitterMixin } from '../common/mixins/event-emitter.js'; +import { isEmpty } from '../common/util.js'; +import IgcIconComponent from '../icon/icon.js'; +import IgcListComponent from '../list/list.js'; +import IgcToastComponent from '../toast/toast.js'; +import IgcTooltipComponent from '../tooltip/tooltip.js'; +import IgcChatInputComponent from './chat-input.js'; +import IgcChatMessageComponent from './chat-message.js'; +import { ChatState } from './chat-state.js'; +import { styles } from './themes/chat.base.css.js'; +import { styles as shared } from './themes/shared/chat.common.css.js'; +import { all } from './themes/themes.js'; +import type { + ChatRenderContext, + ChatTemplateRenderer, + IgcChatMessage, + IgcChatMessageAttachment, + IgcChatMessageReaction, + IgcChatOptions, +} from './types.js'; + +type DefaultChatRenderers = { + typingIndicator: ChatTemplateRenderer; + suggestionPrefix: ChatTemplateRenderer; +}; + +/** + * Defines the custom events dispatched by the `` component. + */ +export interface IgcChatComponentEventMap { + /** + * Dispatched when a new chat message is created (sent). + */ + igcMessageCreated: CustomEvent; + + /** + * Dispatched when a message is reacted to. + */ + igcMessageReact: CustomEvent; + + /** + * Dispatched when a chat message attachment is clicked. + */ + igcAttachmentClick: CustomEvent; + + /** + * Dispatched when attachment(s) are added either through drag & drop or through + * the default file input. + */ + igcAttachmentAdded: CustomEvent; + + /** + * Dispatched when an attachment is removed by the user. + */ + igcAttachmentRemoved: CustomEvent; + + /** + * Dispatched during an attachment drag operation. + */ + igcAttachmentDrag: CustomEvent; + + /** + * Dispatched when an attachment is dropped (e.g., in a drag-and-drop operation). + */ + igcAttachmentDrop: CustomEvent; + + /** + * Dispatched when the typing status changes (e.g., user starts or stops typing). + */ + igcTypingChange: CustomEvent; + + /** + * Dispatched when the chat input field gains focus. + */ + igcInputFocus: CustomEvent; + + /** + * Dispatched when the chat input field loses focus. + */ + igcInputBlur: CustomEvent; + + /** + * Dispatched when the content of the chat input changes. + */ + igcInputChange: CustomEvent; +} + +const Slots = setSlots( + 'prefix', + 'title', + 'actions', + 'suggestions-header', + 'suggestions', + 'suggestions-actions', + 'suggestion', + 'empty-state' +); + +/** + * A chat UI component for displaying messages, attachments, and input interaction. + * + * @element igc-chat + * + * @fires igcMessageCreated - Dispatched when a new chat message is created (sent). + * @fires igcMessageReact - Dispatched when a message is reacted to. + * @fires igcAttachmentClick - Dispatched when a chat message attachment is clicked. + * @fires igcAttachmentAdded - Dispatched when attachment(s) are added either through drag & drop or through the default file input. + * @fires igcAttachmentRemoved - Dispatched when an attachment is removed by the user. + * @fires igcAttachmentDrag - Dispatched during an attachment drag operation. + * @fires igcAttachmentDrop - Dispatched when an attachment is dropped (e.g., in a drag-and-drop operation). + * @fires igcTypingChange - Dispatched when the typing status changes (e.g., user starts or stops typing). + * @fires igcInputFocus - Dispatched when the chat input field gains focus. + * @fires igcInputBlur - Dispatched when the chat input field loses focus. + * @fires igcInputChange - Dispatched when the content of the chat input changes. + * + * @slot prefix - Slot for injecting content (e.g., avatar or icon) before the chat title. + * @slot title - Slot for overriding the chat title content. + * @slot actions - Slot for injecting header actions (e.g., buttons, menus). + * @slot suggestions-header - Slot for rendering a custom header for the suggestions list. + * @slot suggestions - Slot for rendering a custom list of quick reply suggestions. + * @slot suggestions-actions - Slot for rendering additional actions. + * @slot suggestion - Slot for rendering a single suggestion item. + * @slot empty-state - Slot shown when there are no messages. + * + * @csspart chat-container - Styles the main chat container. + * @csspart header - Styles the chat header container. + * @csspart prefix - Styles the element before the chat title (e.g., avatar). + * @csspart title - Styles the chat header title. + * + * @csspart message-area-container - Styles the container holding the messages and (optional) suggestions. + * @csspart message-list - Styles the message list container. + * @csspart message-item - Styles each message wrapper. + * @csspart typing-indicator - Styles the typing indicator container. + * @csspart typing-dot - Styles individual typing indicator dots. + * + * @csspart suggestions-container - Styles the container holding all suggestions. + * @csspart suggestions-header - Styles the suggestions header. + * @csspart suggestion - Styles each suggestion item. + * @csspart suggestion-prefix - Styles the icon or prefix in a suggestion. + * @csspart suggestion-title - Styles the text/title of a suggestion. + * + * @csspart empty-state - Styles the empty state container when there are no messages. + * + * @csspart input-area-container - Styles the wrapper around the chat input area. + * @csspart input-container - Styles the main input container. + * @csspart input-attachments-container - Styles the container for attachments in the input. + * @csspart input-attachment-container - Styles a single attachment in the input area. + * @csspart input-attachment-name - Styles the file name of an attachment. + * @csspart input-attachment-icon - Styles the icon of an attachment. + * @csspart text-input - Styles the text input field for typing messages. + * @csspart input-actions-container - Styles the container for input actions. + * @csspart input-actions-start - Styles the group of actions at the start of the input after the default file upload. + * @csspart input-actions-end - Styles the group of actions at the end of the input. + * @csspart file-upload-container - Styles the container for the file upload input. + * @csspart file-upload - Styles the file upload input itself. + * @csspart send-button-container - Styles the container around the send button. + * @csspart send-button - Styles the send button. + * + * @csspart message-container - Styles the container of a single message. + * @csspart message-list (forwarded) - Styles the internal list of messages. + * @csspart message-header - Styles the header of a message (e.g., sender, timestamp). + * @csspart message-content - Styles the text content of a message. + * @csspart message-attachments-container - Styles the container for message attachments. + * @csspart message-attachment - Styles a single message attachment. + * @csspart message-actions-container - Styles the container holding message actions. + * @csspart message-sent - Styles messages marked as sent by the current user. + * @csspart attachment-header - Styles the header of an attachment block. + * @csspart attachment-content - Styles the content of an attachment block. + * @csspart attachment-icon - Styles the icon of an attachment. + * @csspart file-name - Styles the file name shown in an attachment. + */ +export default class IgcChatComponent extends EventEmitterMixin< + IgcChatComponentEventMap, + Constructor +>(LitElement) { + public static readonly tagName = 'igc-chat'; + + public static styles = [styles, shared]; + + /* blazorSuppress */ + public static register(): void { + registerComponent( + IgcChatComponent, + IgcChatInputComponent, + IgcChatMessageComponent, + IgcButtonComponent, + IgcIconComponent, + IgcListComponent, + IgcTooltipComponent, + IgcToastComponent + ); + } + + private readonly _state = new ChatState( + this, + this._updateContext, + this._updateUserInputContext + ); + + private readonly _defaults = Object.freeze({ + typingIndicator: () => this._renderLoadingTemplate(), + suggestionPrefix: () => this._renderSuggestionPrefix(), + }); + + private readonly _slots = addSlotController(this, { + slots: Slots, + }); + + private readonly _context = new ContextProvider(this, { + context: chatContext, + initialValue: this._state, + }); + + private readonly _userInputContext = new ContextProvider(this, { + context: chatUserInputContext, + initialValue: this._state, + }); + + @query(IgcChatInputComponent.tagName) + private readonly _input?: IgcChatInputComponent; + + @query('[part="typing-indicator"]') + private readonly _typingIndicator?: HTMLElement; + + @query('[part="suggestions-container"]') + private readonly _suggestionsContainer?: HTMLElement; + + @query('[part="message-area-container"]', true) + private readonly _scrollContainer!: HTMLElement; + + private _updateContext(): void { + this._context.setValue(this._state, true); + } + + private _updateUserInputContext(): void { + this._userInputContext.setValue(this._state, true); + } + + /** + * The list of chat messages currently displayed. + * Use this property to set or update the message history. + */ + @property({ attribute: false }) + public set messages(value: IgcChatMessage[]) { + this._state.messages = value; + } + + public get messages(): IgcChatMessage[] { + return this._state.messages; + } + + /** + * The chat message currently being composed but not yet sent. + * Includes the draft text and any attachments. + */ + @property({ attribute: false }) + public set draftMessage(value: { + text: string; + attachments?: IgcChatMessageAttachment[]; + }) { + if (this._state && value) { + this._state.inputValue = value.text; + this._state.inputAttachments = value.attachments || []; + this.requestUpdate(); + } + } + + public get draftMessage(): { + text: string; + attachments?: IgcChatMessageAttachment[]; + } { + return { + text: this._state.inputValue, + attachments: this._state.inputAttachments, + }; + } + + /** + * Controls the chat behavior and appearance through a configuration object. + * Use this to toggle UI options, provide suggestions, templates, etc. + */ + @property({ attribute: false }) + public set options(value: IgcChatOptions) { + this._state.options = value; + } + + public get options(): IgcChatOptions | undefined { + return this._state.options; + } + + /** + * The resource strings of the chat. + */ + @property({ attribute: false }) + public resourceStrings = IgcChatResourceStringEN; + + constructor() { + super(); + addThemingController(this, all); + } + + private _getRenderer( + name: U + ): DefaultChatRenderers[U] { + return this._state.options?.renderers + ? (this._state.options.renderers[name] ?? this._defaults[name]) + : this._defaults[name]; + } + + private _handleSuggestionClick(text: string): void { + this._state.addMessageWithEvent({ text }); + this._input?.focusInput(); + } + + /** + * Scrolls the view to a specific message by id. + */ + public scrollToMessage(messageId: string): void { + if (!isEmpty(this.messages)) { + const message = this.renderRoot.querySelector(`#message-${messageId}`); + message?.scrollIntoView({ block: 'end', inline: 'end' }); + } + } + + protected override updated(properties: PropertyValues): void { + if ( + (properties.has('messages') || + this._typingIndicator || + this._suggestionsContainer) && + !this._state.disableAutoScroll + ) { + this._scrollToBottom(); + } + } + + private _scrollToBottom(): void { + const current = this._scrollContainer.scrollTop; + + requestAnimationFrame(() => { + const scrollHeight = this._scrollContainer.scrollHeight; + if (current < scrollHeight) { + this._scrollContainer.scrollBy({ + top: Math.abs(scrollHeight - current), + }); + } + }); + } + + private _renderHeader() { + const hasContent = + this._slots.hasAssignedElements('prefix') || + this._slots.hasAssignedElements('title') || + this._slots.hasAssignedElements('actions') || + this._state.options?.headerText; + + return html` +
+ + ${this._state.options?.headerText} + +
+ `; + } + + private _renderMessages() { + const ctx = { instance: this }; + + return html` +
+ ${repeat( + this._state.messages, + (message) => message.id, + (message) => { + return html` + + + `; + } + )} + ${this._state.options?.isTyping + ? html` +
+ ${this._getRenderer('typingIndicator')(ctx)} +
+ ` + : nothing} +
+ `; + } + + private _renderLoadingTemplate() { + return html` +
+
+
+
+ `; + } + + private _renderSuggestionPrefix() { + return html``; + } + + private _renderSuggestions() { + const hasContent = this._slots.hasAssignedElements('suggestions-header'); + const suggestions = this._state.options?.suggestions ?? []; + const ctx = { instance: this }; + + return html` +
+ + + + ${this.resourceStrings.suggestionsHeader} + + + + + ${suggestions.map( + (suggestion) => html` + + this._handleSuggestionClick(suggestion)} + > + + ${this._getRenderer('suggestionPrefix')(ctx)} + + ${suggestion} + + + ` + )} + + + +
+ `; + } + + private _renderEmptyState() { + return html` +
+ +
+ `; + } + + protected override render() { + const hasMessages = !isEmpty(this.messages); + const suggestions = isEmpty(this._state.options?.suggestions ?? []) + ? nothing + : this._renderSuggestions(); + + return html` +
+ ${this._renderHeader()} + +
+ ${cache( + hasMessages || this._state.options?.isTyping + ? this._renderMessages() + : this._renderEmptyState() + )} + ${this._state.suggestionsPosition === 'below-messages' + ? suggestions + : nothing} +
+ + + + ${this._state.suggestionsPosition === 'below-input' + ? suggestions + : nothing} +
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'igc-chat': IgcChatComponent; + } +} diff --git a/src/components/chat/extras/markdown-renderer.ts b/src/components/chat/extras/markdown-renderer.ts new file mode 100644 index 000000000..553ad5099 --- /dev/null +++ b/src/components/chat/extras/markdown-renderer.ts @@ -0,0 +1,87 @@ +import DOMPurify from 'dompurify'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import { Marked } from 'marked'; +import markedShiki from 'marked-shiki'; +import { bundledThemes, createHighlighter } from 'shiki/bundle/web'; +import type { IgcChatMessage } from '../types.js'; + +const DEFAULT_LANGUAGES = ['javascript', 'typescript', 'html', 'css']; +const DEFAULT_THEME = { + light: 'github-light', + dark: 'github-dark', +}; + +/** + * Options to configure the MarkdownMessageRenderer. + */ +export interface MarkdownRendererOptions { + /** + * If true, disables syntax highlighting entirely. + */ + noHighlighter?: boolean; + + /** + * List of programming languages to support in syntax highlighting. + */ + languages?: string[]; + + /** + * The theme used by the syntax highlighter (e.g., 'github-light'). + */ + theme?: { + light?: string; + dark?: string; + }; + + /** + * A custom HTML sanitization function. Defaults to DOMPurify.sanitize. + */ + sanitizer?: (html: string) => string; +} + +export async function createMarkdownRenderer( + options?: MarkdownRendererOptions +) { + const sanitizer = options?.sanitizer ?? DOMPurify.sanitize; + + const markdown = new Marked({ + breaks: true, + gfm: true, + extensions: [ + { + name: 'link', + renderer({ href, title, text }) { + return `${text}`; + }, + }, + ], + }); + + if (!options?.noHighlighter) { + const themes = options?.theme ?? DEFAULT_THEME; + const langs = options?.languages ?? DEFAULT_LANGUAGES; + + const highlighter = await createHighlighter({ + langs, + themes: Object.keys(bundledThemes), + }); + + markdown.use( + markedShiki({ + highlight(code, lang, _) { + try { + return highlighter.codeToHtml(code, { lang, themes }); + } catch { + return `
${sanitizer(code)}
`; + } + }, + }) + ); + } + + return async (message: IgcChatMessage): Promise => { + return message.text + ? unsafeHTML(sanitizer(await markdown.parse(message.text))) + : ''; + }; +} diff --git a/src/components/chat/message-attachments.ts b/src/components/chat/message-attachments.ts new file mode 100644 index 000000000..8b8fc39f2 --- /dev/null +++ b/src/components/chat/message-attachments.ts @@ -0,0 +1,218 @@ +import { consume } from '@lit/context'; +import { html, LitElement, nothing } from 'lit'; +import { property } from 'lit/decorators.js'; +import { cache } from 'lit/directives/cache.js'; +import { repeat } from 'lit/directives/repeat.js'; +import { until } from 'lit/directives/until.js'; +import { addThemingController } from '../../theming/theming-controller.js'; +import IgcIconButtonComponent from '../button/icon-button.js'; +import { chatContext } from '../common/context.js'; +import { registerComponent } from '../common/definitions/register.js'; +import { partMap } from '../common/part-map.js'; +import { trimmedHtml } from '../common/util.js'; +import IgcIconComponent from '../icon/icon.js'; +import type { ChatState } from './chat-state.js'; +import { all } from './themes/attachments.js'; +import { styles } from './themes/message-attachments.base.css.js'; +import { styles as shared } from './themes/shared/message-attachments/message-attachments.common.css.js'; +import type { + ChatAttachmentRenderContext, + ChatTemplateRenderer, + IgcChatMessage, + IgcChatMessageAttachment, +} from './types.js'; +import { + ChatFileTypeIcons, + createAttachmentURL, + getFileExtension, + isImageAttachment, +} from './utils.js'; + +type DefaultAttachmentRenderers = { + attachment: ChatTemplateRenderer; + attachmentHeader: ChatTemplateRenderer; + attachmentContent: ChatTemplateRenderer; +}; + +/** + * A component that renders message attachments within a chat. + * + * Displays attachments such as images or files, supporting custom templates + * and default rendering using expansion panels. + * + * @element igc-message-attachments + * + * @csspart attachments-container - Container wrapping all attachments. + * @csspart attachment - Wrapper for a single attachment. + * @csspart attachment-header - Wrapper for a single attachment header. + * @csspart attachments-content - Part representing the attachment preview. + * @csspart attachment-icon - Icon part representing the attachment type. + * @csspart file-name - Part representing the attachment's file name. + * @csspart actions - Container for header action buttons. + * @csspart image-attachment - Part for the image element inside an image attachment. + * + * @fires igcAttachmentClick - Fired when an attachment header is toggled (clicked). + */ +export default class IgcMessageAttachmentsComponent extends LitElement { + public static readonly tagName = 'igc-message-attachments'; + public static override styles = [styles, shared]; + + /* blazorSuppress */ + public static register(): void { + registerComponent( + IgcMessageAttachmentsComponent, + IgcIconComponent, + IgcIconButtonComponent + ); + } + + private readonly _defaults: Readonly = + Object.freeze({ + attachment: (ctx) => this._renderAttachment(ctx.attachment), + attachmentHeader: (ctx) => this.renderHeader(ctx.attachment), + attachmentContent: (ctx) => this._renderContent(ctx.attachment), + }); + + @consume({ context: chatContext, subscribe: true }) + private readonly _state!: ChatState; + + /** + * The array of attachments to render. + */ + @property({ attribute: false }) + public message?: IgcChatMessage; + + constructor() { + super(); + addThemingController(this, all); + } + + private _getRenderer(name: keyof DefaultAttachmentRenderers) { + return this._state.options?.renderers + ? (this._state.options.renderers[name] ?? this._defaults[name]) + : this._defaults[name]; + } + + private _handleHeaderClick = (attachment: IgcChatMessageAttachment) => { + this._state.emitEvent('igcAttachmentClick', { detail: attachment }); + }; + /** + * Default attachment header template used when no custom template is provided. + * Renders the attachment icon and name. + * @param attachment The message attachment to render + * @returns TemplateResult containing the rendered attachment header + */ + private renderHeader(attachment: IgcChatMessageAttachment) { + const isCurrentUser = this._state.isCurrentUserMessage(this.message); + const iconName = isImageAttachment(attachment) + ? 'attach_image' + : 'document_thumbnail'; + + return html` + ${!isCurrentUser + ? html`` + : nothing} + ${attachment.name} + `; + } + + /** + * Default attachment content template used when no custom template is provided. + * Renders the attachment content based on its type. + * @param attachment The message attachment to render + * @returns TemplateResult containing the rendered attachment content + */ + private _renderContent(attachment: IgcChatMessageAttachment) { + const iconName = + ChatFileTypeIcons.get(getFileExtension(attachment.name)) ?? + ChatFileTypeIcons.get('default')!; + + return isImageAttachment(attachment) + ? html` + ${attachment.name} + ` + : html``; + } + + private _renderAttachment(attachment: IgcChatMessageAttachment) { + const isCurrentUser = this._state.isCurrentUserMessage(this.message); + + const contentParts = { + 'attachment-content': true, + sent: isCurrentUser, + }; + const headerParts = { + 'attachment-header': true, + sent: isCurrentUser, + }; + + const ctx: ChatAttachmentRenderContext = { + attachment, + message: this.message!, + instance: this._state.host, + }; + + const content = html`
+ ${until(this._getRenderer('attachmentContent')(ctx))} +
`; + const header = html`
this._handleHeaderClick(attachment)} + > +
+ ${until(this._getRenderer('attachmentHeader')(ctx))} +
+
`; + + return html` + ${isCurrentUser ? content : nothing} ${header} + ${!isCurrentUser ? content : nothing} + `; + } + + protected override render() { + const attachments = this.message?.attachments ?? []; + const isCurrentUser = this._state.isCurrentUserMessage(this.message); + const attachmentParts = { + attachment: true, + sent: isCurrentUser, + }; + return html`${cache( + this.message + ? html` +
+ ${repeat( + attachments, + (attachment) => attachment.id, + (attachment) => trimmedHtml` +
+ ${until( + this._getRenderer('attachment')({ + attachment, + message: this.message!, + instance: this._state.host, + }) + )} +
+ ` + )} +
+ ` + : nothing + )}`; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'igc-message-attachments': IgcMessageAttachmentsComponent; + } +} diff --git a/src/components/chat/themes/attachments.ts b/src/components/chat/themes/attachments.ts new file mode 100644 index 000000000..75f7a773e --- /dev/null +++ b/src/components/chat/themes/attachments.ts @@ -0,0 +1,19 @@ +import { css } from 'lit'; + +import type { Themes } from '../../../theming/types.js'; +// Shared Styles +import { styles as indigo } from './shared/message-attachments/message-attachments.indigo.css.js'; + +const light = { + indigo: css` + ${indigo} + `, +}; + +const dark = { + indigo: css` + ${indigo} + `, +}; + +export const all: Themes = { light, dark }; diff --git a/src/components/chat/themes/chat.base.scss b/src/components/chat/themes/chat.base.scss new file mode 100644 index 000000000..f2c135c72 --- /dev/null +++ b/src/components/chat/themes/chat.base.scss @@ -0,0 +1,179 @@ +@use 'styles/common/component'; +@use 'styles/utilities' as *; + +$inline-inset: rem(24px); + +:host { + --igc-chat-height: 100%; + + width: 100%; + height: var(--igc-chat-height); + overflow: hidden; + display: flex; + flex-direction: column; + container-type: inline-size; + + ::part(text-input) { + --textarea-height: #{rem(48px)}; + } +} + +[part='chat-container'] { + display: grid; + grid-template-columns: 1fr minmax(rem(320px), #{calc(rem(760px) + $inline-inset * 2)}) 1fr; + grid-template-rows: auto 1fr auto; + height: 100%; +} + +[part='message-area-container'] { + display: grid; + grid-template-columns: subgrid; + overflow: hidden auto; + grid-column: 1 / -1; + grid-template-rows: auto 1fr; + align-items: start; + grid-row: 2; + + &:has([part='empty-state']) { + grid-template-rows: 1fr auto; + } +} + +[part='message-list'], +[part='empty-state'], +[part='suggestions-container'] { + grid-column: 2 / 3; + display: grid; + grid-template-columns: subgrid; + width: 100%; + padding-inline: $inline-inset; +} + +[part='message-list'] { + padding-block: rem(16px) rem(24px); + gap: rem(24px); +} + +[part='empty-state'] { + height: 100%; +} + +[part='header'] { + display: flex; + align-items: center; + min-height: rem(56px); + padding-inline: rem(16px); + box-shadow: var(--ig-elevation-4); + width: 100%; + z-index: 1; + grid-column: 1 / -1; + grid-row: 1 / 2; +} + +[part='typing-indicator'] { + display: flex; + align-items: center; + gap: rem(2px); +} + +[part='typing-dot'] { + display: flex; + align-items: center; + justify-content: center; + width: rem(8px); + aspect-ratio: 1; + + &::after { + content: ''; + display: block; + animation: blink 1.2s ease-in-out infinite; + animation-fill-mode: both; + width: rem(6px); + aspect-ratio: 1; + border-radius: 50%; + } + + &:nth-child(2)::after { + animation-delay: .2s; + width: rem(4px); + } + + &:nth-child(3)::after { + animation-delay: .4s; + } + + &:nth-child(4)::after { + animation-delay: .6s; + width: rem(2px); + } +} + +slot[name='title'] { + @include type-style('h6') { + margin: 0; + }; +} + +slot[name='actions'] { + display: flex; + margin-inline-start: auto; + gap: rem(16px); +} + +slot[name='prefix'] { + display: block; + margin-inline-end: rem(32px); +} + +igc-chat-input { + grid-row: 3; +} + +igc-list { + --ig-size: 3; + + padding-block-end: rem(24px); + min-height: fit-content; + width: fit-content; + max-width: rem(576px); +} + +igc-list-item { + cursor: pointer; +} + +igc-list, +igc-list-item:not(:hover), +igc-list-header { + background: initial; +} + +igc-list-item::part(title) { + @include line-clamp(2, true, true); +} + +@container (max-width: 400px) { + [part='message-list'], + [part='empty-state'], + [part='suggestions-container'] { + padding-inline: rem(16px); + } + + [part='message-list'] { + padding-block: rem(12px); + } +} + +@keyframes blink { + 0%, 100% { + transform: scale(0.9); + } + + 25%, 75% { + transform: scale(1.05); + } + + 50% { + transform: scale(1.1); + } +} diff --git a/src/components/chat/themes/dark/_themes.scss b/src/components/chat/themes/dark/_themes.scss new file mode 100644 index 000000000..ac7c2a0a1 --- /dev/null +++ b/src/components/chat/themes/dark/_themes.scss @@ -0,0 +1,7 @@ +@use 'styles/utilities' as *; +@use 'igniteui-theming/sass/themes/schemas/components/dark/chat' as *; + +$material: digest-schema($dark-material-chat); +$bootstrap: digest-schema($dark-bootstrap-chat); +$fluent: digest-schema($dark-fluent-chat); +$indigo: digest-schema($dark-indigo-chat); diff --git a/src/components/chat/themes/dark/chat.bootstrap.scss b/src/components/chat/themes/dark/chat.bootstrap.scss new file mode 100644 index 000000000..8ae2decc7 --- /dev/null +++ b/src/components/chat/themes/dark/chat.bootstrap.scss @@ -0,0 +1,9 @@ +@use 'styles/utilities' as *; +@use 'themes' as *; +@use '../light/themes' as light; + +$theme: $bootstrap; + +:host { + @include css-vars-from-theme(diff(light.$base, $theme), 'ig-chat'); +} diff --git a/src/components/chat/themes/dark/chat.fluent.scss b/src/components/chat/themes/dark/chat.fluent.scss new file mode 100644 index 000000000..de7767075 --- /dev/null +++ b/src/components/chat/themes/dark/chat.fluent.scss @@ -0,0 +1,9 @@ +@use 'styles/utilities' as *; +@use 'themes' as *; +@use '../light/themes' as light; + +$theme: $fluent; + +:host { + @include css-vars-from-theme(diff(light.$base, $theme), 'ig-chat'); +} diff --git a/src/components/chat/themes/dark/chat.indigo.scss b/src/components/chat/themes/dark/chat.indigo.scss new file mode 100644 index 000000000..20a6f366e --- /dev/null +++ b/src/components/chat/themes/dark/chat.indigo.scss @@ -0,0 +1,9 @@ +@use 'styles/utilities' as *; +@use 'themes' as *; +@use '../light/themes' as light; + +$theme: $indigo; + +:host { + @include css-vars-from-theme(diff(light.$base, $theme), 'ig-chat'); +} diff --git a/src/components/chat/themes/dark/chat.material.scss b/src/components/chat/themes/dark/chat.material.scss new file mode 100644 index 000000000..2f8acca66 --- /dev/null +++ b/src/components/chat/themes/dark/chat.material.scss @@ -0,0 +1,9 @@ +@use 'styles/utilities' as *; +@use 'themes' as *; +@use '../light/themes' as light; + +$theme: $material; + +:host { + @include css-vars-from-theme(diff(light.$base, $theme), 'ig-chat'); +} diff --git a/src/components/chat/themes/input.base.scss b/src/components/chat/themes/input.base.scss new file mode 100644 index 000000000..61630e630 --- /dev/null +++ b/src/components/chat/themes/input.base.scss @@ -0,0 +1,76 @@ +@use 'styles/common/component'; +@use 'styles/utilities' as *; + +:host { + display: flex; + align-items: center; + width: 100%; + padding-block: rem(16px); + justify-content: center; + grid-column: 2 / 3; +} + +[part~='input-container'] { + display: flex; + flex-direction: column; + width: 100%; + margin-inline: rem(24px); + border-radius: rem(4px); + padding: rem(16px); + gap: rem(12px); +} + +[part='actions-container'] { + display: flex; + align-items: center; +} + +[part='send-button-container'] { + margin-inline-start: auto; +} + +[part='file-upload-container'] { + position: relative; + display: inline-block; + + input { + position: absolute; + width: 0; + aspect-ratio: 1; + inset: 0; + opacity: 0; + } +} + +[part='attachments'] { + display: flex; + flex-wrap: wrap; + gap: rem(8px); +} + +[part='attachment-wrapper'] { + min-width: rem(90px); + max-width: fit-content; + flex: 1 1; + + igc-chip { + --ig-size: 2; + } +} + +igc-textarea::part(input) { + // maximum eight lines + max-height: rem(216px); + overflow-y: auto; +} + +igc-icon-button, +igc-textarea { + --ig-size: 2; +} + +@container (max-width: 400px) { + [part~='input-container'] { + margin-inline: rem(12px); + } +} diff --git a/src/components/chat/themes/input.ts b/src/components/chat/themes/input.ts new file mode 100644 index 000000000..33071c03f --- /dev/null +++ b/src/components/chat/themes/input.ts @@ -0,0 +1,40 @@ +import { css } from 'lit'; + +import type { Themes } from '../../../theming/types.js'; +// Shared Styles +import { styles as bootstrap } from './shared/input/input.bootstrap.css.js'; +import { styles as fluent } from './shared/input/input.fluent.css.js'; +import { styles as indigo } from './shared/input/input.indigo.css.js'; +import { styles as material } from './shared/input/input.material.css.js'; + +const light = { + bootstrap: css` + ${bootstrap} + `, + fluent: css` + ${fluent} + `, + indigo: css` + ${indigo} + `, + material: css` + ${material} + `, +}; + +const dark = { + bootstrap: css` + ${bootstrap} + `, + fluent: css` + ${fluent} + `, + indigo: css` + ${indigo} + `, + material: css` + ${material} + `, +}; + +export const all: Themes = { light, dark }; diff --git a/src/components/chat/themes/light/_themes.scss b/src/components/chat/themes/light/_themes.scss new file mode 100644 index 000000000..0930bb5bc --- /dev/null +++ b/src/components/chat/themes/light/_themes.scss @@ -0,0 +1,22 @@ +@use 'sass:map'; +@use 'styles/utilities' as *; +@use 'igniteui-theming/sass/themes/schemas/components/light/chat' as *; +@use 'components/input/themes/light/themes' as input-theme; + +$base: digest-schema($light-chat); +$material: map.merge(digest-schema($material-chat), ( + box-background-focus: map.get(input-theme.$material, 'box-background-focus'), + focused-bottom-line-color: map.get(input-theme.$material, 'focused-bottom-line-color') +)); +$bootstrap: map.merge(digest-schema($bootstrap-chat), ( + focused-border-color: map.get(input-theme.$bootstrap, 'focused-border-color'), + focused-secondary-color: map.get(input-theme.$bootstrap, 'focused-secondary-color') +)); +$fluent: map.merge(digest-schema($fluent-chat), ( + focused-border-color: map.get(input-theme.$fluent, 'focused-border-color'), +)); +$indigo: map.merge(digest-schema($indigo-chat), ( + box-background-hover: map.get(input-theme.$indigo, 'box-background-hover'), + focused-bottom-line-color: map.get(input-theme.$indigo, 'focused-bottom-line-color'), + focused-text-color: map.get(input-theme.$indigo, 'focused-text-color') +)); \ No newline at end of file diff --git a/src/components/chat/themes/light/chat.bootstrap.scss b/src/components/chat/themes/light/chat.bootstrap.scss new file mode 100644 index 000000000..d9580a4b5 --- /dev/null +++ b/src/components/chat/themes/light/chat.bootstrap.scss @@ -0,0 +1,8 @@ +@use 'styles/utilities' as *; +@use 'themes' as *; + +$theme: $bootstrap; + +:host { + @include css-vars-from-theme(diff($base, $theme), 'ig-chat'); +} diff --git a/src/components/chat/themes/light/chat.fluent.scss b/src/components/chat/themes/light/chat.fluent.scss new file mode 100644 index 000000000..d1c3e4abb --- /dev/null +++ b/src/components/chat/themes/light/chat.fluent.scss @@ -0,0 +1,8 @@ +@use 'styles/utilities' as *; +@use 'themes' as *; + +$theme: $fluent; + +:host { + @include css-vars-from-theme(diff($base, $theme), 'ig-chat'); +} diff --git a/src/components/chat/themes/light/chat.indigo.scss b/src/components/chat/themes/light/chat.indigo.scss new file mode 100644 index 000000000..c0a2f2917 --- /dev/null +++ b/src/components/chat/themes/light/chat.indigo.scss @@ -0,0 +1,8 @@ +@use 'styles/utilities' as *; +@use 'themes' as *; + +$theme: $indigo; + +:host { + @include css-vars-from-theme(diff($base, $theme), 'ig-chat'); +} diff --git a/src/components/chat/themes/light/chat.material.scss b/src/components/chat/themes/light/chat.material.scss new file mode 100644 index 000000000..6a388bd8d --- /dev/null +++ b/src/components/chat/themes/light/chat.material.scss @@ -0,0 +1,8 @@ +@use 'styles/utilities' as *; +@use 'themes' as *; + +$theme: $material; + +:host { + @include css-vars-from-theme(diff($base, $theme), 'ig-chat'); +} diff --git a/src/components/chat/themes/light/chat.shared.scss b/src/components/chat/themes/light/chat.shared.scss new file mode 100644 index 000000000..d2e557ef4 --- /dev/null +++ b/src/components/chat/themes/light/chat.shared.scss @@ -0,0 +1,8 @@ +@use 'styles/utilities' as *; +@use 'themes' as *; + +$theme: $base; + +:host { + @include css-vars-from-theme($theme, 'ig-chat'); +} diff --git a/src/components/chat/themes/message-attachments.base.scss b/src/components/chat/themes/message-attachments.base.scss new file mode 100644 index 000000000..460e042cd --- /dev/null +++ b/src/components/chat/themes/message-attachments.base.scss @@ -0,0 +1,81 @@ +@use 'styles/common/component'; +@use 'styles/utilities' as *; + +:host { + display: block; +} + +[part='attachments-container'] { + display: flex; + flex-wrap: wrap; + gap: rem(16px); +} + +[part='attachment'] { + flex: 1 1; + border-radius: rem(4px); + overflow: hidden; + min-width: rem(80px); + max-width: rem(400px); +} + +[part='attachment sent'] { + border-radius: rem(2px); + max-width: rem(80px); +} + +[part~='attachment-header'] { + padding: rem(8px) rem(12px) rem(8px) rem(16px); + border-top-left-radius: inherit; + border-top-right-radius: inherit; +} + +[part='attachment-header sent'] { + padding: rem(6px) 0 0; +} + +[part~='attachment-content'] { + display: flex; + justify-content: center; + align-items: center; + border-bottom-left-radius: inherit; + border-bottom-right-radius: inherit; + max-height: rem(240px); + overflow: hidden; +} + +[part='attachment-content sent'] { + border-top-left-radius: inherit; + border-top-right-radius: inherit; + width: rem(78px); + aspect-ratio: 1; +} + +[part='image-attachment-icon'] { + width: 100%; + height: 100%; + border-radius: inherit; + object-fit: cover; +} + +[part~='attachment-icon'] { + --ig-size: 1; +} + +[part='file-attachment-icon'] { + --size: #{rem(32px)}; +} + +[part='details'] { + display: flex; + align-items: center; + gap: rem(8px); +} + +[part='file-name'] { + @include type-style('body-2') { + margin: 0; + }; + + @include ellipsis(); +} diff --git a/src/components/chat/themes/message.base.scss b/src/components/chat/themes/message.base.scss new file mode 100644 index 000000000..ca4217968 --- /dev/null +++ b/src/components/chat/themes/message.base.scss @@ -0,0 +1,60 @@ +@use 'styles/common/component'; +@use 'styles/utilities' as *; + +:host { + --igc-chat-message-padding: #{rem(12px) rem(16px)}; + --igc-chat-sent-message-start-margin: auto; + --igc-chat-sent-message-end-margin: unset; + --igc-chat-message-container-end-margin: auto; + + display: flex; + flex-direction: column; + width: 100%; +} + +[part~='message-container'], +[part='plain-text'] { + @include type-style('body-1') { + margin: 0; + }; +} + +[part~='message-container'] { + display: flex; + margin-inline-end: var(--igc-chat-message-container-end-margin); + flex-direction: column; + gap: rem(16px); + + p { + margin: 0; + padding: 0; + } + + a { + overflow-wrap: anywhere; + color: color(primary, 500); + } + + pre, code { + white-space: pre-wrap; + overflow-wrap: break-word; + overflow-x: auto; + margin-block: unset; + } +} + +[part~='message-header'], +[part~='message-attachments'], +[part~='message-actions'] { + &:empty { + display: none; + } +} + +[part~='sent'] { + margin-inline: var(--igc-chat-sent-message-start-margin, 0) var(--igc-chat-sent-message-end-margin, 0); + padding: var(--igc-chat-message-padding); + border-radius: rem(24px) rem(24px) 0; + max-width: rem(576px); + width: fit-content; +} diff --git a/src/components/chat/themes/message.ts b/src/components/chat/themes/message.ts new file mode 100644 index 000000000..954406b5c --- /dev/null +++ b/src/components/chat/themes/message.ts @@ -0,0 +1,33 @@ +import { css } from 'lit'; + +import type { Themes } from '../../../theming/types.js'; +// Shared Styles +import { styles as bootstrap } from './shared/chat-message/chat-message.bootstrap.css.js'; +import { styles as fluent } from './shared/chat-message/chat-message.fluent.css.js'; +import { styles as indigo } from './shared/chat-message/chat-message.indigo.css.js'; + +const light = { + bootstrap: css` + ${bootstrap} + `, + indigo: css` + ${indigo} + `, + fluent: css` + ${fluent} + `, +}; + +const dark = { + bootstrap: css` + ${bootstrap} + `, + indigo: css` + ${indigo} + `, + fluent: css` + ${fluent} + `, +}; + +export const all: Themes = { light, dark }; diff --git a/src/components/chat/themes/shared/chat-message/chat-message.bootstrap.scss b/src/components/chat/themes/shared/chat-message/chat-message.bootstrap.scss new file mode 100644 index 000000000..e2b886e49 --- /dev/null +++ b/src/components/chat/themes/shared/chat-message/chat-message.bootstrap.scss @@ -0,0 +1,5 @@ +@use 'styles/utilities' as *; + +[part~='sent'] { + border-radius: rem(8px) rem(8px) 0; +} diff --git a/src/components/chat/themes/shared/chat-message/chat-message.common.scss b/src/components/chat/themes/shared/chat-message/chat-message.common.scss new file mode 100644 index 000000000..6523bc6d0 --- /dev/null +++ b/src/components/chat/themes/shared/chat-message/chat-message.common.scss @@ -0,0 +1,18 @@ +@use 'styles/utilities' as *; +@use '../../light/themes' as *; + +$theme: $material; + +[part~='sent'] { + background: var-get($theme, 'message-background'); +} + +[part~='message-container'] { + color: var-get($theme, 'message-color'); +} + +[part~='message-actions'] { + igc-icon-button::part(icon) { + color: var-get($theme, 'message-actions-color'); + } +} \ No newline at end of file diff --git a/src/components/chat/themes/shared/chat-message/chat-message.fluent.scss b/src/components/chat/themes/shared/chat-message/chat-message.fluent.scss new file mode 100644 index 000000000..ad9a0deec --- /dev/null +++ b/src/components/chat/themes/shared/chat-message/chat-message.fluent.scss @@ -0,0 +1,5 @@ +@use 'styles/utilities' as *; + +// [part~='sent'] { +// border-radius: rem(2px); +// } diff --git a/src/components/chat/themes/shared/chat-message/chat-message.indigo.scss b/src/components/chat/themes/shared/chat-message/chat-message.indigo.scss new file mode 100644 index 000000000..31b6929c4 --- /dev/null +++ b/src/components/chat/themes/shared/chat-message/chat-message.indigo.scss @@ -0,0 +1,5 @@ +@use 'styles/utilities' as *; + +[part~='sent'] { + border-radius: rem(8px); +} diff --git a/src/components/chat/themes/shared/chat.bootstrap.scss b/src/components/chat/themes/shared/chat.bootstrap.scss new file mode 100644 index 000000000..4e3ed2cfa --- /dev/null +++ b/src/components/chat/themes/shared/chat.bootstrap.scss @@ -0,0 +1,29 @@ +@use 'styles/utilities' as *; +@use '../light/themes' as *; + +$theme: $bootstrap; + +:host { + ::part(text-input) { + --textarea-height: #{rem(38px)}; + } +} + +[part='header'] { + box-shadow: none; + border-block-end: rem(1px) solid var-get($theme, 'header-border'); +} + +slot[name='title'] { + @include type-style('h5') { + margin: 0; + }; +} + +slot[name='prefix'] { + margin-inline-end: rem(16px); +} + +igc-list { + border: none; +} diff --git a/src/components/chat/themes/shared/chat.common.scss b/src/components/chat/themes/shared/chat.common.scss new file mode 100644 index 000000000..af8aed6ce --- /dev/null +++ b/src/components/chat/themes/shared/chat.common.scss @@ -0,0 +1,17 @@ +@use 'styles/utilities' as *; +@use '../light/themes' as *; + +$theme: $material; + +:host { + background: var-get($theme, 'background'); +} + +[part='header'] { + background: var-get($theme, 'header-background'); + color: var-get($theme, 'header-color'); +} + +[part='typing-dot']::after { + background: var-get($theme, 'progress-indicator-color'); +} diff --git a/src/components/chat/themes/shared/chat.fluent.scss b/src/components/chat/themes/shared/chat.fluent.scss new file mode 100644 index 000000000..5261e419f --- /dev/null +++ b/src/components/chat/themes/shared/chat.fluent.scss @@ -0,0 +1,17 @@ +@use 'styles/utilities' as *; + +:host { + ::part(text-input) { + --textarea-height: #{rem(40px)}; + } +} + +slot[name='title'] { + @include type-style('subtitle-2') { + margin: 0; + }; +} + +slot[name='prefix'] { + margin-inline-end: rem(16px); +} \ No newline at end of file diff --git a/src/components/chat/themes/shared/chat.indigo.scss b/src/components/chat/themes/shared/chat.indigo.scss new file mode 100644 index 000000000..f4f79e57e --- /dev/null +++ b/src/components/chat/themes/shared/chat.indigo.scss @@ -0,0 +1,33 @@ +@use 'styles/utilities' as *; +@use '../light/themes' as *; + +$theme: $indigo; + +:host { + ::part(text-input) { + --textarea-height: #{rem(28px)}; + } +} + +[part='header'] { + box-shadow: none; + border-block-end: rem(1px) solid var-get($theme, 'header-border'); +} + +slot[name='title'] { + @include type-style('h5') { + margin: 0; + }; +} + +slot[name='prefix'] { + margin-inline-end: rem(16px); +} + +slot[name='actions'] { + gap: rem(8px); +} + +igc-list { + --ig-size: 2; +} \ No newline at end of file diff --git a/src/components/chat/themes/shared/input/input.bootstrap.scss b/src/components/chat/themes/shared/input/input.bootstrap.scss new file mode 100644 index 000000000..e2953e6e9 --- /dev/null +++ b/src/components/chat/themes/shared/input/input.bootstrap.scss @@ -0,0 +1,16 @@ +@use 'styles/utilities' as *; +@use '../../light/themes' as *; + +$theme: $bootstrap; + +igc-textarea::part(input) { + max-height: rem(170px); + padding-block: rem(8px); +} + +[part~='dragging'] { + igc-textarea::part(input) { + border: rem(1px) solid var-get($theme, 'focused-border-color'); + box-shadow: 0 0 0 rem(4px) var-get($theme, 'focused-secondary-color'); + } +} \ No newline at end of file diff --git a/src/components/chat/themes/shared/input/input.common.scss b/src/components/chat/themes/shared/input/input.common.scss new file mode 100644 index 000000000..418dc655b --- /dev/null +++ b/src/components/chat/themes/shared/input/input.common.scss @@ -0,0 +1,8 @@ +@use 'styles/utilities' as *; +@use '../../light/themes' as *; + +$theme: $material; + +[part~='input-container'] { + border: rem(1px) solid var-get($theme, 'chat-input-border'); +} diff --git a/src/components/chat/themes/shared/input/input.fluent.scss b/src/components/chat/themes/shared/input/input.fluent.scss new file mode 100644 index 000000000..4632c8ddb --- /dev/null +++ b/src/components/chat/themes/shared/input/input.fluent.scss @@ -0,0 +1,15 @@ +@use 'styles/utilities' as *; +@use '../../light/themes' as *; + +$theme: $fluent; + +igc-textarea::part(input) { + max-height: rem(150px); + padding-block: rem(11px); +} + +[part~='dragging'] { + igc-textarea::part(container)::before { + box-shadow: inset 0 0 0 rem(2px) var-get($theme, 'focused-border-color'); + } +} diff --git a/src/components/chat/themes/shared/input/input.indigo.scss b/src/components/chat/themes/shared/input/input.indigo.scss new file mode 100644 index 000000000..a6604f048 --- /dev/null +++ b/src/components/chat/themes/shared/input/input.indigo.scss @@ -0,0 +1,32 @@ +@use 'styles/utilities' as *; +@use '../../light/themes' as *; + +$theme: $indigo; + +igc-textarea::part(input) { + max-height: rem(140px); +} + +[part~='input-container'] { + border-radius: rem(13px); +} + +[part~='dragging'] { + igc-textarea::part(container) { + background: var-get($theme, 'box-background-hover'); + + &::after { + border-block-end-color: var-get($theme, 'focused-bottom-line-color'); + } + } + + igc-textarea::part(input) { + color: var-get($theme, 'focused-text-color'); + } +} + +[part='attachment-wrapper'] { + igc-chip { + --ig-size: 1; + } +} diff --git a/src/components/chat/themes/shared/input/input.material.scss b/src/components/chat/themes/shared/input/input.material.scss new file mode 100644 index 000000000..80e55617f --- /dev/null +++ b/src/components/chat/themes/shared/input/input.material.scss @@ -0,0 +1,19 @@ +@use 'styles/utilities' as *; +@use '../../light/themes' as *; + +$theme: $material; + +[part~='dragging'] { + igc-textarea::part(container) { + background: var-get($theme, 'box-background-focus'); + + &::after { + border-block-end: rem(2px) solid var-get($theme, 'focused-bottom-line-color'); + } + } +} + +igc-textarea::part(input) { + margin-block-start: unset; + padding-block: rem(12px); +} diff --git a/src/components/chat/themes/shared/message-attachments/message-attachments.common.scss b/src/components/chat/themes/shared/message-attachments/message-attachments.common.scss new file mode 100644 index 000000000..a4a82d5e4 --- /dev/null +++ b/src/components/chat/themes/shared/message-attachments/message-attachments.common.scss @@ -0,0 +1,32 @@ +@use 'styles/utilities' as *; +@use '../../light/themes' as *; + +$theme: $material; + +[part='attachment-header'], +[part='attachment-content'], +[part='attachment-content sent'] { + border: rem(1px) solid var-get($theme, 'image-border'); +} + +[part='attachment-header'] { + background: var-get($theme, 'image-background'); + border-block-end: none; +} + +[part~='attachment-content'] { + background: var-get($theme, 'file-background'); +} + +[part='attachment-content'] { + border-block-start: none; +} + +[part~='attachment-icon'] { + color: var-get($theme, 'image-attachment-icon'); +} + +[part="file-attachment-icon"] { + --color: #{var-get($theme, 'file-icon-color')}; + --accent-color: #{var-get($theme, 'file-icon-accent-color')}; +} diff --git a/src/components/chat/themes/shared/message-attachments/message-attachments.indigo.scss b/src/components/chat/themes/shared/message-attachments/message-attachments.indigo.scss new file mode 100644 index 000000000..00db564a6 --- /dev/null +++ b/src/components/chat/themes/shared/message-attachments/message-attachments.indigo.scss @@ -0,0 +1,5 @@ +@use 'styles/utilities' as *; + +[part~='attachment-icon'] { + --ig-size: 2; +} diff --git a/src/components/chat/themes/themes.ts b/src/components/chat/themes/themes.ts new file mode 100644 index 000000000..02e2dd5f1 --- /dev/null +++ b/src/components/chat/themes/themes.ts @@ -0,0 +1,56 @@ +import { css } from 'lit'; + +import type { Themes } from '../../../theming/types.js'; +// Dark Overrides +import { styles as bootstrapDark } from './dark/chat.bootstrap.css.js'; +import { styles as fluentDark } from './dark/chat.fluent.css.js'; +import { styles as indigoDark } from './dark/chat.indigo.css.js'; +import { styles as materialDark } from './dark/chat.material.css.js'; +// Light Overrides +import { styles as bootstrapLight } from './light/chat.bootstrap.css.js'; +import { styles as fluentLight } from './light/chat.fluent.css.js'; +import { styles as indigoLight } from './light/chat.indigo.css.js'; +import { styles as materialLight } from './light/chat.material.css.js'; +// Shared Styles +import { styles as shared } from './light/chat.shared.css.js'; +import { styles as bootstrap } from './shared/chat.bootstrap.css.js'; +import { styles as fluent } from './shared/chat.fluent.css.js'; +import { styles as indigo } from './shared/chat.indigo.css.js'; + +const light = { + shared: css` + ${shared} + `, + bootstrap: css` + ${bootstrap} ${bootstrapLight} + `, + material: css` + ${materialLight} + `, + fluent: css` + ${fluent} ${fluentLight} + `, + indigo: css` + ${indigo} ${indigoLight} + `, +}; + +const dark = { + shared: css` + ${shared} + `, + bootstrap: css` + ${bootstrap} ${bootstrapDark} + `, + material: css` + ${materialDark} + `, + fluent: css` + ${fluent} ${fluentDark} + `, + indigo: css` + ${indigo} ${indigoDark} + `, +}; + +export const all: Themes = { light, dark }; diff --git a/src/components/chat/types.ts b/src/components/chat/types.ts new file mode 100644 index 000000000..e4921d255 --- /dev/null +++ b/src/components/chat/types.ts @@ -0,0 +1,305 @@ +import type IgcChatComponent from './chat.js'; + +/** + * Represents a single chat message in the conversation. + */ +export interface IgcChatMessage { + /** + * A unique identifier for the message. + */ + id: string; + + /** + * The textual content of the message. + */ + text: string; + + /** + * The identifier or name of the sender of the message. + */ + sender: string; + + /** + * The timestamp indicating when the message was sent. + */ + timestamp?: string; + + /** + * Optional list of attachments associated with the message, + * such as images, files, or links. + */ + attachments?: IgcChatMessageAttachment[]; + + /** + * Optional list of reactions associated with the message. + */ + reactions?: string[]; +} + +/** + * Represents an attachment associated with a chat message. + */ +export interface IgcChatMessageAttachment { + /** + * A unique identifier for the attachment. + */ + id: string; + + /** + * The display name of the attachment (e.g. file name). + */ + name: string; + + /** + * The URL from which the attachment can be downloaded or viewed. + * Typically used for attachments stored on a server or CDN. + */ + url?: string; + + /** + * The actual File object, if the attachment was provided locally (e.g. via upload). + */ + file?: File; + + /** + * The MIME type or a custom type identifier for the attachment (e.g. "image/png", "pdf", "audio"). + */ + type?: string; + + /** + * Optional URL to a thumbnail preview of the attachment (e.g. for images or videos). + */ + thumbnail?: string; +} + +/** + * Configuration options for customizing the behavior and appearance of the chat component. + */ +export type IgcChatOptions = { + /** + * The ID of the current user. Used to differentiate between incoming and outgoing messages. + */ + currentUserId?: string; + /** + * If `true`, prevents the chat from automatically scrolling to the latest message. + */ + disableAutoScroll?: boolean; + /** + * If `true`, disables the ability to upload and send attachments. + * Defaults to `false`. + */ + disableInputAttachments?: boolean; + /** + * Indicates whether the other user is currently typing a message. + */ + isTyping?: boolean; + /** + * The accepted files that could be attached. + * Defines the file types as a list of comma-separated values (e.g. "image/*,.pdf") that the file input should accept. + */ + acceptedFiles?: string; + /** + * Optional header text to display at the top of the chat component. + */ + headerText?: string; + /** + * Optional placeholder text for the chat input area. + * Provides a hint to the user about what they can type (e.g. "Type a message..."). + */ + inputPlaceholder?: string; + /** + * Suggested text snippets or quick replies that can be shown as user-selectable options. + */ + suggestions?: string[]; + /** + * Controls the position of the chat suggestions within the component layout. + * + * - `"below-input"`: Renders suggestions below the chat input area. + * - `"below-messages"`: Renders suggestions below the chat messages area. + * + * Default is `"below-messages"`. + */ + suggestionsPosition?: ChatSuggestionsPosition; + /** + * Time in milliseconds to wait before dispatching a stop typing event. + * Default is `3000`. + */ + stopTypingDelay?: number; + + /** + * A boolean flag that, when `true`, enables a **quick and dirty workaround** for styling + * components rendered within the Shadow DOM, from custom message renderers, by allowing them + * to inherit styles from the document's root. This can be useful for developers who prefer not to handle + * Shadow DOM encapsulation, but it is **not the recommended approach**. + * + * It is highly advised to use standard Web Component styling methods first, in this order: + * + * 1. **CSS Variables and Parts API**: Use the exposed `::part` API with custom CSS variables to style + * your content in your custom renderers. + * + * 2. **`link` elements**: For larger style sheets, link them directly within the Shadow DOM to maintain + * encapsulation. + * + * 3. **Inline `