diff --git a/build.washingtonpost.com/docs/components/input-search.mdx b/build.washingtonpost.com/docs/components/input-search.mdx index 6eee56e49..59ce89e3c 100644 --- a/build.washingtonpost.com/docs/components/input-search.mdx +++ b/build.washingtonpost.com/docs/components/input-search.mdx @@ -236,15 +236,14 @@ export default function Example() { /> ))} {results2.length > 3 && ( - <> - Group + {results2.slice(3).map((city) => ( ))} - + )} ) : ( diff --git a/build.washingtonpost.com/public/sitemap.xml b/build.washingtonpost.com/public/sitemap.xml index f91c14650..cbeafc323 100644 --- a/build.washingtonpost.com/public/sitemap.xml +++ b/build.washingtonpost.com/public/sitemap.xml @@ -128,6 +128,10 @@ https://build.washingtonpost.com/components/visually-hidden + + https://build.washingtonpost.com/font-faces + + https://build.washingtonpost.com/foundations/base diff --git a/package-lock.json b/package-lock.json index e996cd713..5d87c28f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3340,6 +3340,50 @@ "version": "0.2.1", "license": "MIT" }, + "node_modules/@formatjs/ecma402-abstract": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.0.0.tgz", + "integrity": "sha512-rRqXOqdFmk7RYvj4khklyqzcfQl9vEL/usogncBHRZfZBDOwMGuSRNFl02fu5KGHXdbinju+YXyuR+Nk8xlr/g==", + "dependencies": { + "@formatjs/intl-localematcher": "0.5.4", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/fast-memoize": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.0.tgz", + "integrity": "sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.7.8", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.8.tgz", + "integrity": "sha512-nBZJYmhpcSX0WeJ5SDYUkZ42AgR3xiyhNCsQweFx3cz/ULJjym8bHAzWKvG5e2+1XO98dBYC0fWeeAECAVSwLA==", + "dependencies": { + "@formatjs/ecma402-abstract": "2.0.0", + "@formatjs/icu-skeleton-parser": "1.8.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.2.tgz", + "integrity": "sha512-k4ERKgw7aKGWJZgTarIcNEmvyTVD9FYh0mTrrBMHZ1b8hUu6iOJ4SzsZlo3UNAvHYa+PnvntIwRPt1/vy4nA9Q==", + "dependencies": { + "@formatjs/ecma402-abstract": "2.0.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.4.tgz", + "integrity": "sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@gar/promisify": { "version": "1.1.3", "dev": true, @@ -3426,6 +3470,39 @@ "node": ">=6.9.0" } }, + "node_modules/@internationalized/date": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.4.tgz", + "integrity": "sha512-qoVJVro+O0rBaw+8HPjUB1iH8Ihf8oziEnqMnvhJUSuVIrHOuZ6eNLHNvzXJKUvAtaDiqMnRlg8Z2mgh09BlUw==", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/message": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.4.tgz", + "integrity": "sha512-Dygi9hH1s7V9nha07pggCkvmRfDd3q2lWnMGvrJyrOwYMe1yj4D2T9BoH9I6MGR7xz0biQrtLPsqUkqXzIrBOw==", + "dependencies": { + "@swc/helpers": "^0.5.0", + "intl-messageformat": "^10.1.0" + } + }, + "node_modules/@internationalized/number": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.5.3.tgz", + "integrity": "sha512-rd1wA3ebzlp0Mehj5YTuTI50AQEx80gWFyHcQu+u91/5NgdwBecO8BH6ipPfE+lmQ9d63vpB3H9SHoIUiupllw==", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/string": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.3.tgz", + "integrity": "sha512-9kpfLoA8HegiWTeCbR2livhdVeKobCnVv8tlJ6M2jF+4tcMqDo94ezwlnrUANBWPgd8U7OXIHCk2Ov2qhk4KXw==", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "dev": true, @@ -8819,6 +8896,760 @@ "react-dom": "^16.8.0 || 17.x" } }, + "node_modules/@react-aria/breadcrumbs": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@react-aria/breadcrumbs/-/breadcrumbs-3.5.13.tgz", + "integrity": "sha512-G1Gqf/P6kVdfs94ovwP18fTWuIxadIQgHsXS08JEVcFVYMjb9YjqnEBaohUxD1tq2WldMbYw53ahQblT4NTG+g==", + "dependencies": { + "@react-aria/i18n": "^3.11.1", + "@react-aria/link": "^3.7.1", + "@react-aria/utils": "^3.24.1", + "@react-types/breadcrumbs": "^3.7.5", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/button": { + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-aria/button/-/button-3.9.5.tgz", + "integrity": "sha512-dgcYR6j8WDOMLKuVrtxzx4jIC05cVKDzc+HnPO8lNkBAOfjcuN5tkGRtIjLtqjMvpZHhQT5aDbgFpIaZzxgFIg==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/utils": "^3.24.1", + "@react-stately/toggle": "^3.7.4", + "@react-types/button": "^3.9.4", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/calendar": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@react-aria/calendar/-/calendar-3.5.8.tgz", + "integrity": "sha512-Whlp4CeAA5/ZkzrAHUv73kgIRYjw088eYGSc+cvSOCxfrc/2XkBm9rNrnSBv0DvhJ8AG0Fjz3vYakTmF3BgZBw==", + "dependencies": { + "@internationalized/date": "^3.5.4", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/live-announcer": "^3.3.4", + "@react-aria/utils": "^3.24.1", + "@react-stately/calendar": "^3.5.1", + "@react-types/button": "^3.9.4", + "@react-types/calendar": "^3.4.6", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/checkbox": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/@react-aria/checkbox/-/checkbox-3.14.3.tgz", + "integrity": "sha512-EtBJL6iu0gvrw3A4R7UeVLR6diaVk/mh4kFBc7c8hQjpEJweRr4hmJT3hrNg3MBcTWLxFiMEXPGgWEwXDBygtA==", + "dependencies": { + "@react-aria/form": "^3.0.5", + "@react-aria/interactions": "^3.21.3", + "@react-aria/label": "^3.7.8", + "@react-aria/toggle": "^3.10.4", + "@react-aria/utils": "^3.24.1", + "@react-stately/checkbox": "^3.6.5", + "@react-stately/form": "^3.0.3", + "@react-stately/toggle": "^3.7.4", + "@react-types/checkbox": "^3.8.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/combobox": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-aria/combobox/-/combobox-3.9.1.tgz", + "integrity": "sha512-SpK92dCmT8qn8aEcUAihRQrBb5LZUhwIbDExFII8PvUvEFy/PoQHXIo3j1V29WkutDBDpMvBv/6XRCHGXPqrhQ==", + "dependencies": { + "@react-aria/i18n": "^3.11.1", + "@react-aria/listbox": "^3.12.1", + "@react-aria/live-announcer": "^3.3.4", + "@react-aria/menu": "^3.14.1", + "@react-aria/overlays": "^3.22.1", + "@react-aria/selection": "^3.18.1", + "@react-aria/textfield": "^3.14.5", + "@react-aria/utils": "^3.24.1", + "@react-stately/collections": "^3.10.7", + "@react-stately/combobox": "^3.8.4", + "@react-stately/form": "^3.0.3", + "@react-types/button": "^3.9.4", + "@react-types/combobox": "^3.11.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/datepicker": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@react-aria/datepicker/-/datepicker-3.10.1.tgz", + "integrity": "sha512-4HZL593nrNMa1GjBmWEN/OTvNS6d3/16G1YJWlqiUlv11ADulSbqBIjMmkgwrJVFcjrgqtXFy+yyrTA/oq94Zw==", + "dependencies": { + "@internationalized/date": "^3.5.4", + "@internationalized/number": "^3.5.3", + "@internationalized/string": "^3.2.3", + "@react-aria/focus": "^3.17.1", + "@react-aria/form": "^3.0.5", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/label": "^3.7.8", + "@react-aria/spinbutton": "^3.6.5", + "@react-aria/utils": "^3.24.1", + "@react-stately/datepicker": "^3.9.4", + "@react-stately/form": "^3.0.3", + "@react-types/button": "^3.9.4", + "@react-types/calendar": "^3.4.6", + "@react-types/datepicker": "^3.7.4", + "@react-types/dialog": "^3.5.10", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/dialog": { + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@react-aria/dialog/-/dialog-3.5.14.tgz", + "integrity": "sha512-oqDCjQ8hxe3GStf48XWBf2CliEnxlR9GgSYPHJPUc69WBj68D9rVcCW3kogJnLAnwIyf3FnzbX4wSjvUa88sAQ==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/overlays": "^3.22.1", + "@react-aria/utils": "^3.24.1", + "@react-types/dialog": "^3.5.10", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/dnd": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@react-aria/dnd/-/dnd-3.6.1.tgz", + "integrity": "sha512-6WnujUTD+cIYZVF/B+uXdHyJ+WSpbYa8jH282epvY4FUAq1qLmen12/HHcoj/5dswKQe8X6EM3OhkQM89d9vFw==", + "dependencies": { + "@internationalized/string": "^3.2.3", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/live-announcer": "^3.3.4", + "@react-aria/overlays": "^3.22.1", + "@react-aria/utils": "^3.24.1", + "@react-stately/dnd": "^3.3.1", + "@react-types/button": "^3.9.4", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/focus": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.17.1.tgz", + "integrity": "sha512-FLTySoSNqX++u0nWZJPPN5etXY0WBxaIe/YuL/GTEeuqUIuC/2bJSaw5hlsM6T2yjy6Y/VAxBcKSdAFUlU6njQ==", + "dependencies": { + "@react-aria/interactions": "^3.21.3", + "@react-aria/utils": "^3.24.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/focus/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-aria/form": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@react-aria/form/-/form-3.0.5.tgz", + "integrity": "sha512-n290jRwrrRXO3fS82MyWR+OKN7yznVesy5Q10IclSTVYHHI3VI53xtAPr/WzNjJR1um8aLhOcDNFKwnNIUUCsQ==", + "dependencies": { + "@react-aria/interactions": "^3.21.3", + "@react-aria/utils": "^3.24.1", + "@react-stately/form": "^3.0.3", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/grid": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.9.1.tgz", + "integrity": "sha512-fGEZqAEaS8mqzV/II3N4ndoNWegIcbh+L3PmKbXdpKKUP8VgMs/WY5rYl5WAF0f5RoFwXqx3ibDLeR9tKj/bOg==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/live-announcer": "^3.3.4", + "@react-aria/selection": "^3.18.1", + "@react-aria/utils": "^3.24.1", + "@react-stately/collections": "^3.10.7", + "@react-stately/grid": "^3.8.7", + "@react-stately/selection": "^3.15.1", + "@react-stately/virtualizer": "^3.7.1", + "@react-types/checkbox": "^3.8.1", + "@react-types/grid": "^3.2.6", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/gridlist": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@react-aria/gridlist/-/gridlist-3.8.1.tgz", + "integrity": "sha512-vVPkkA+Ct0NDcpnNm/tnYaBumg0fP9pXxsPLqL1rxvsTyj1PaIpFTZ4corabPTbTDExZwUSTS3LG1n+o1OvBtQ==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/grid": "^3.9.1", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/selection": "^3.18.1", + "@react-aria/utils": "^3.24.1", + "@react-stately/collections": "^3.10.7", + "@react-stately/list": "^3.10.5", + "@react-stately/tree": "^3.8.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/i18n": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.11.1.tgz", + "integrity": "sha512-vuiBHw1kZruNMYeKkTGGnmPyMnM5T+gT8bz97H1FqIq1hQ6OPzmtBZ6W6l6OIMjeHI5oJo4utTwfZl495GALFQ==", + "dependencies": { + "@internationalized/date": "^3.5.4", + "@internationalized/message": "^3.1.4", + "@internationalized/number": "^3.5.3", + "@internationalized/string": "^3.2.3", + "@react-aria/ssr": "^3.9.4", + "@react-aria/utils": "^3.24.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.21.3.tgz", + "integrity": "sha512-BWIuf4qCs5FreDJ9AguawLVS0lV9UU+sK4CCnbCNNmYqOWY+1+gRXCsnOM32K+oMESBxilAjdHW5n1hsMqYMpA==", + "dependencies": { + "@react-aria/ssr": "^3.9.4", + "@react-aria/utils": "^3.24.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/label": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.8.tgz", + "integrity": "sha512-MzgTm5+suPA3KX7Ug6ZBK2NX9cin/RFLsv1BdafJ6CZpmUSpWnGE/yQfYUB7csN7j31OsZrD3/P56eShYWAQfg==", + "dependencies": { + "@react-aria/utils": "^3.24.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/link": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-aria/link/-/link-3.7.1.tgz", + "integrity": "sha512-a4IaV50P3fXc7DQvEIPYkJJv26JknFbRzFT5MJOMgtzuhyJoQdILEUK6XHYjcSSNCA7uLgzpojArVk5Hz3lCpw==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/utils": "^3.24.1", + "@react-types/link": "^3.5.5", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/listbox": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.12.1.tgz", + "integrity": "sha512-7JiUp0NGykbv/HgSpmTY1wqhuf/RmjFxs1HZcNaTv8A+DlzgJYc7yQqFjP3ZA/z5RvJFuuIxggIYmgIFjaRYdA==", + "dependencies": { + "@react-aria/interactions": "^3.21.3", + "@react-aria/label": "^3.7.8", + "@react-aria/selection": "^3.18.1", + "@react-aria/utils": "^3.24.1", + "@react-stately/collections": "^3.10.7", + "@react-stately/list": "^3.10.5", + "@react-types/listbox": "^3.4.9", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/live-announcer": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@react-aria/live-announcer/-/live-announcer-3.3.4.tgz", + "integrity": "sha512-w8lxs35QrRrn6pBNzVfyGOeqWdxeVKf9U6bXIVwhq7rrTqRULL8jqy8RJIMfIs1s8G5FpwWYjyBOjl2g5Cu1iA==", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@react-aria/menu": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/@react-aria/menu/-/menu-3.14.1.tgz", + "integrity": "sha512-BYliRb38uAzq05UOFcD5XkjA5foQoXRbcH3ZufBsc4kvh79BcP1PMW6KsXKGJ7dC/PJWUwCui6QL1kUg8PqMHA==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/overlays": "^3.22.1", + "@react-aria/selection": "^3.18.1", + "@react-aria/utils": "^3.24.1", + "@react-stately/collections": "^3.10.7", + "@react-stately/menu": "^3.7.1", + "@react-stately/tree": "^3.8.1", + "@react-types/button": "^3.9.4", + "@react-types/menu": "^3.9.9", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/meter": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/@react-aria/meter/-/meter-3.4.13.tgz", + "integrity": "sha512-oG6KvHQM3ri93XkYQkgEaMKSMO9KNDVpcW1MUqFfqyUXHFBRZRrJB4BTXMZ4nyjheFVQjVboU51fRwoLjOzThg==", + "dependencies": { + "@react-aria/progress": "^3.4.13", + "@react-types/meter": "^3.4.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/numberfield": { + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/@react-aria/numberfield/-/numberfield-3.11.3.tgz", + "integrity": "sha512-QQ9ZTzBbRI8d9ksaBWm6YVXbgv+5zzUsdxVxwzJVXLznvivoORB8rpdFJzUEWVCo25lzoBxluCEPYtLOxP1B0w==", + "dependencies": { + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/spinbutton": "^3.6.5", + "@react-aria/textfield": "^3.14.5", + "@react-aria/utils": "^3.24.1", + "@react-stately/form": "^3.0.3", + "@react-stately/numberfield": "^3.9.3", + "@react-types/button": "^3.9.4", + "@react-types/numberfield": "^3.8.3", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/overlays": { + "version": "3.22.1", + "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.22.1.tgz", + "integrity": "sha512-GHiFMWO4EQ6+j6b5QCnNoOYiyx1Gk8ZiwLzzglCI4q1NY5AG2EAmfU4Z1+Gtrf2S5Y0zHbumC7rs9GnPoGLUYg==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/ssr": "^3.9.4", + "@react-aria/utils": "^3.24.1", + "@react-aria/visually-hidden": "^3.8.12", + "@react-stately/overlays": "^3.6.7", + "@react-types/button": "^3.9.4", + "@react-types/overlays": "^3.8.7", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/progress": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/@react-aria/progress/-/progress-3.4.13.tgz", + "integrity": "sha512-YBV9bOO5JzKvG8QCI0IAA00o6FczMgIDiK8Q9p5gKorFMatFUdRayxlbIPoYHMi+PguLil0jHgC7eOyaUcrZ0g==", + "dependencies": { + "@react-aria/i18n": "^3.11.1", + "@react-aria/label": "^3.7.8", + "@react-aria/utils": "^3.24.1", + "@react-types/progress": "^3.5.4", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/radio": { + "version": "3.10.4", + "resolved": "https://registry.npmjs.org/@react-aria/radio/-/radio-3.10.4.tgz", + "integrity": "sha512-3fmoMcQtCpgjTwJReFjnvIE/C7zOZeCeWUn4JKDqz9s1ILYsC3Rk5zZ4q66tFn6v+IQnecrKT52wH6+hlVLwTA==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/form": "^3.0.5", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/label": "^3.7.8", + "@react-aria/utils": "^3.24.1", + "@react-stately/radio": "^3.10.4", + "@react-types/radio": "^3.8.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/searchfield": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/@react-aria/searchfield/-/searchfield-3.7.5.tgz", + "integrity": "sha512-h1sMUOWjhevaKKUHab/luHbM6yiyeN57L4RxZU0IIc9Ww0h5Rp2GUuKZA3pcdPiExHje0aijcImL3wBHEbKAzw==", + "dependencies": { + "@react-aria/i18n": "^3.11.1", + "@react-aria/textfield": "^3.14.5", + "@react-aria/utils": "^3.24.1", + "@react-stately/searchfield": "^3.5.3", + "@react-types/button": "^3.9.4", + "@react-types/searchfield": "^3.5.5", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/select": { + "version": "3.14.5", + "resolved": "https://registry.npmjs.org/@react-aria/select/-/select-3.14.5.tgz", + "integrity": "sha512-s8jixBuTUNdKWRHe2tIJqp55ORHeUObGMw1s7PQRRVrrHPdNSYseAOI9B2W7qpl3hKhvjJg40UW+45mcb1WKbw==", + "dependencies": { + "@react-aria/form": "^3.0.5", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/label": "^3.7.8", + "@react-aria/listbox": "^3.12.1", + "@react-aria/menu": "^3.14.1", + "@react-aria/selection": "^3.18.1", + "@react-aria/utils": "^3.24.1", + "@react-aria/visually-hidden": "^3.8.12", + "@react-stately/select": "^3.6.4", + "@react-types/button": "^3.9.4", + "@react-types/select": "^3.9.4", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/selection": { + "version": "3.18.1", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.18.1.tgz", + "integrity": "sha512-GSqN2jX6lh7v+ldqhVjAXDcrWS3N4IsKXxO6L6Ygsye86Q9q9Mq9twWDWWu5IjHD6LoVZLUBCMO+ENGbOkyqeQ==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/utils": "^3.24.1", + "@react-stately/selection": "^3.15.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/separator": { + "version": "3.3.13", + "resolved": "https://registry.npmjs.org/@react-aria/separator/-/separator-3.3.13.tgz", + "integrity": "sha512-hofA6JCPnAOqSE9vxnq7Dkazr7Kb2A0I5sR16fOG7ddjYRc/YEY5Nv7MWfKUGU0kNFHkgNjsDAILERtLechzeA==", + "dependencies": { + "@react-aria/utils": "^3.24.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/slider": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/@react-aria/slider/-/slider-3.7.8.tgz", + "integrity": "sha512-MYvPcM0K8jxEJJicUK2+WxUkBIM/mquBxOTOSSIL3CszA80nXIGVnLlCUnQV3LOUzpWtabbWaZokSPtGgOgQOw==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/label": "^3.7.8", + "@react-aria/utils": "^3.24.1", + "@react-stately/slider": "^3.5.4", + "@react-types/shared": "^3.23.1", + "@react-types/slider": "^3.7.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/spinbutton": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.5.tgz", + "integrity": "sha512-0aACBarF/Xr/7ixzjVBTQ0NBwwwsoGkf5v6AVFVMTC0uYMXHTALvRs+ULHjHMa5e/cX/aPlEvaVT7jfSs+Xy9Q==", + "dependencies": { + "@react-aria/i18n": "^3.11.1", + "@react-aria/live-announcer": "^3.3.4", + "@react-aria/utils": "^3.24.1", + "@react-types/button": "^3.9.4", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.4.tgz", + "integrity": "sha512-4jmAigVq409qcJvQyuorsmBR4+9r3+JEC60wC+Y0MZV0HCtTmm8D9guYXlJMdx0SSkgj0hHAyFm/HvPNFofCoQ==", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/switch": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@react-aria/switch/-/switch-3.6.4.tgz", + "integrity": "sha512-2nVqz4ZuJyof47IpGSt3oZRmp+EdS8wzeDYgf42WHQXrx4uEOk1mdLJ20+NnsYhj/2NHZsvXVrjBeKMjlMs+0w==", + "dependencies": { + "@react-aria/toggle": "^3.10.4", + "@react-stately/toggle": "^3.7.4", + "@react-types/switch": "^3.5.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/table": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/@react-aria/table/-/table-3.14.1.tgz", + "integrity": "sha512-WaPgQe4zQF5OaluO5rm+Y2nEoFR63vsLd4BT4yjK1uaFhKhDY2Zk+1SCVQvBLLKS4WK9dhP05nrNzT0vp/ZPOw==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/grid": "^3.9.1", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/live-announcer": "^3.3.4", + "@react-aria/utils": "^3.24.1", + "@react-aria/visually-hidden": "^3.8.12", + "@react-stately/collections": "^3.10.7", + "@react-stately/flags": "^3.0.3", + "@react-stately/table": "^3.11.8", + "@react-stately/virtualizer": "^3.7.1", + "@react-types/checkbox": "^3.8.1", + "@react-types/grid": "^3.2.6", + "@react-types/shared": "^3.23.1", + "@react-types/table": "^3.9.5", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/tabs": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-aria/tabs/-/tabs-3.9.1.tgz", + "integrity": "sha512-S5v/0sRcOaSXaJYZuuy1ZVzYc7JD4sDyseG1133GjyuNjJOFHgoWMb+b4uxNIJbZxnLgynn/ZDBZSO+qU+fIxw==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/i18n": "^3.11.1", + "@react-aria/selection": "^3.18.1", + "@react-aria/utils": "^3.24.1", + "@react-stately/tabs": "^3.6.6", + "@react-types/shared": "^3.23.1", + "@react-types/tabs": "^3.3.7", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/tag": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@react-aria/tag/-/tag-3.4.1.tgz", + "integrity": "sha512-gcIGPYZ2OBwMT4IHnlczEezKlxr0KRPL/mSfm2Q91GE027ZGOJnqusH9az6DX1qxrQx8x3vRdqYT2KmuefkrBQ==", + "dependencies": { + "@react-aria/gridlist": "^3.8.1", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/label": "^3.7.8", + "@react-aria/selection": "^3.18.1", + "@react-aria/utils": "^3.24.1", + "@react-stately/list": "^3.10.5", + "@react-types/button": "^3.9.4", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/textfield": { + "version": "3.14.5", + "resolved": "https://registry.npmjs.org/@react-aria/textfield/-/textfield-3.14.5.tgz", + "integrity": "sha512-hj7H+66BjB1iTKKaFXwSZBZg88YT+wZboEXZ0DNdQB2ytzoz/g045wBItUuNi4ZjXI3P+0AOZznVMYadWBAmiA==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/form": "^3.0.5", + "@react-aria/label": "^3.7.8", + "@react-aria/utils": "^3.24.1", + "@react-stately/form": "^3.0.3", + "@react-stately/utils": "^3.10.1", + "@react-types/shared": "^3.23.1", + "@react-types/textfield": "^3.9.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/toggle": { + "version": "3.10.4", + "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.10.4.tgz", + "integrity": "sha512-bRk+CdB8QzrSyGNjENXiTWxfzYKRw753iwQXsEAU7agPCUdB8cZJyrhbaUoD0rwczzTp2zDbZ9rRbUPdsBE2YQ==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/utils": "^3.24.1", + "@react-stately/toggle": "^3.7.4", + "@react-types/checkbox": "^3.8.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/tooltip": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@react-aria/tooltip/-/tooltip-3.7.4.tgz", + "integrity": "sha512-+XRx4HlLYqWY3fB8Z60bQi/rbWDIGlFUtXYbtoa1J+EyRWfhpvsYImP8qeeNO/vgjUtDy1j9oKa8p6App9mBMQ==", + "dependencies": { + "@react-aria/focus": "^3.17.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/utils": "^3.24.1", + "@react-stately/tooltip": "^3.4.9", + "@react-types/shared": "^3.23.1", + "@react-types/tooltip": "^3.4.9", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/utils": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.24.1.tgz", + "integrity": "sha512-O3s9qhPMd6n42x9sKeJ3lhu5V1Tlnzhu6Yk8QOvDuXf7UGuUjXf9mzfHJt1dYzID4l9Fwm8toczBzPM9t0jc8Q==", + "dependencies": { + "@react-aria/ssr": "^3.9.4", + "@react-stately/utils": "^3.10.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/utils/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-aria/visually-hidden": { + "version": "3.8.12", + "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.12.tgz", + "integrity": "sha512-Bawm+2Cmw3Xrlr7ARzl2RLtKh0lNUdJ0eNqzWcyx4c0VHUAWtThmH5l+HRqFUGzzutFZVo89SAy40BAbd0gjVw==", + "dependencies": { + "@react-aria/interactions": "^3.21.3", + "@react-aria/utils": "^3.24.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, "node_modules/@react-hook/intersection-observer": { "version": "3.1.1", "license": "MIT", @@ -8837,6 +9668,654 @@ "react": ">=16.8" } }, + "node_modules/@react-stately/calendar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.5.1.tgz", + "integrity": "sha512-7l7QhqGUJ5AzWHfvZzbTe3J4t72Ht5BmhW4hlVI7flQXtfrmYkVtl3ZdytEZkkHmWGYZRW9b4IQTQGZxhtlElA==", + "dependencies": { + "@internationalized/date": "^3.5.4", + "@react-stately/utils": "^3.10.1", + "@react-types/calendar": "^3.4.6", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/checkbox": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@react-stately/checkbox/-/checkbox-3.6.5.tgz", + "integrity": "sha512-IXV3f9k+LtmfQLE+DKIN41Q5QB/YBLDCB1YVx5PEdRp52S9+EACD5683rjVm8NVRDwjMi2SP6RnFRk7fVb5Azg==", + "dependencies": { + "@react-stately/form": "^3.0.3", + "@react-stately/utils": "^3.10.1", + "@react-types/checkbox": "^3.8.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/collections": { + "version": "3.10.7", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.10.7.tgz", + "integrity": "sha512-KRo5O2MWVL8n3aiqb+XR3vP6akmHLhLWYZEmPKjIv0ghQaEebBTrN3wiEjtd6dzllv0QqcWvDLM1LntNfJ2TsA==", + "dependencies": { + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/combobox": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/@react-stately/combobox/-/combobox-3.8.4.tgz", + "integrity": "sha512-iLVGvKRRz0TeJXZhZyK783hveHpYA6xovOSdzSD+WGYpiPXo1QrcrNoH3AE0Z2sHtorU+8nc0j58vh5PB+m2AA==", + "dependencies": { + "@react-stately/collections": "^3.10.7", + "@react-stately/form": "^3.0.3", + "@react-stately/list": "^3.10.5", + "@react-stately/overlays": "^3.6.7", + "@react-stately/select": "^3.6.4", + "@react-stately/utils": "^3.10.1", + "@react-types/combobox": "^3.11.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/data": { + "version": "3.11.4", + "resolved": "https://registry.npmjs.org/@react-stately/data/-/data-3.11.4.tgz", + "integrity": "sha512-PbnUQxeE6AznSuEWYnRmrYQ9t5z1Asx98Jtrl96EeA6Iapt9kOjTN9ySqCxtPxMKleb1NIqG3+uHU3veIqmLsg==", + "dependencies": { + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/datepicker": { + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-stately/datepicker/-/datepicker-3.9.4.tgz", + "integrity": "sha512-yBdX01jn6gq4NIVvHIqdjBUPo+WN8Bujc4OnPw+ZnfA4jI0eIgq04pfZ84cp1LVXW0IB0VaCu1AlQ/kvtZjfGA==", + "dependencies": { + "@internationalized/date": "^3.5.4", + "@internationalized/string": "^3.2.3", + "@react-stately/form": "^3.0.3", + "@react-stately/overlays": "^3.6.7", + "@react-stately/utils": "^3.10.1", + "@react-types/datepicker": "^3.7.4", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/dnd": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@react-stately/dnd/-/dnd-3.3.1.tgz", + "integrity": "sha512-I/Ci5xB8hSgAXzoWYWScfMM9UK1MX/eTlARBhiSlfudewweOtNJAI+cXJgU7uiUnGjh4B4v3qDBtlAH1dWDCsw==", + "dependencies": { + "@react-stately/selection": "^3.15.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/flags": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.0.3.tgz", + "integrity": "sha512-/ha7XFA0RZTQsbzSPwu3KkbNMgbvuM0GuMTYLTBWpgBrovBNTM+QqI/PfZTdHg8PwCYF4H5Y8gjdSpdulCvJFw==", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@react-stately/form": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.0.3.tgz", + "integrity": "sha512-92YYBvlHEWUGUpXgIaQ48J50jU9XrxfjYIN8BTvvhBHdD63oWgm8DzQnyT/NIAMzdLnhkg7vP+fjG8LjHeyIAg==", + "dependencies": { + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/grid": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.8.7.tgz", + "integrity": "sha512-he3TXCLAhF5C5z1/G4ySzcwyt7PEiWcVIupxebJQqRyFrNWemSuv+7tolnStmG8maMVIyV3P/3j4eRBbdSlOIg==", + "dependencies": { + "@react-stately/collections": "^3.10.7", + "@react-stately/selection": "^3.15.1", + "@react-types/grid": "^3.2.6", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/list": { + "version": "3.10.5", + "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.10.5.tgz", + "integrity": "sha512-fV9plO+6QDHiewsYIhboxcDhF17GO95xepC5ki0bKXo44gr14g/LSo/BMmsaMnV+1BuGdBunB05bO4QOIaigXA==", + "dependencies": { + "@react-stately/collections": "^3.10.7", + "@react-stately/selection": "^3.15.1", + "@react-stately/utils": "^3.10.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/menu": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-stately/menu/-/menu-3.7.1.tgz", + "integrity": "sha512-mX1w9HHzt+xal1WIT2xGrTQsoLvDwuB2R1Er1MBABs//MsJzccycatcgV/J/28m6tO5M9iuFQQvLV+i1dCtodg==", + "dependencies": { + "@react-stately/overlays": "^3.6.7", + "@react-types/menu": "^3.9.9", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/numberfield": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-stately/numberfield/-/numberfield-3.9.3.tgz", + "integrity": "sha512-UlPTLSabhLEuHtgzM0PgfhtEaHy3yttbzcRb8yHNvGo4KbCHeHpTHd3QghKfTFm024Mug7+mVlWCmMtW0f5ttg==", + "dependencies": { + "@internationalized/number": "^3.5.3", + "@react-stately/form": "^3.0.3", + "@react-stately/utils": "^3.10.1", + "@react-types/numberfield": "^3.8.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/overlays": { + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.7.tgz", + "integrity": "sha512-6zp8v/iNUm6YQap0loaFx6PlvN8C0DgWHNlrlzMtMmNuvjhjR0wYXVaTfNoUZBWj25tlDM81ukXOjpRXg9rLrw==", + "dependencies": { + "@react-stately/utils": "^3.10.1", + "@react-types/overlays": "^3.8.7", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/radio": { + "version": "3.10.4", + "resolved": "https://registry.npmjs.org/@react-stately/radio/-/radio-3.10.4.tgz", + "integrity": "sha512-kCIc7tAl4L7Hu4Wt9l2jaa+MzYmAJm0qmC8G8yPMbExpWbLRu6J8Un80GZu+JxvzgDlqDyrVvyv9zFifwH/NkQ==", + "dependencies": { + "@react-stately/form": "^3.0.3", + "@react-stately/utils": "^3.10.1", + "@react-types/radio": "^3.8.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/searchfield": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@react-stately/searchfield/-/searchfield-3.5.3.tgz", + "integrity": "sha512-H0OvlgwPIFdc471ypw79MDjz3WXaVq9+THaY6JM4DIohEJNN5Dwei7O9g6r6m/GqPXJIn5TT3b74kJ2Osc00YQ==", + "dependencies": { + "@react-stately/utils": "^3.10.1", + "@react-types/searchfield": "^3.5.5", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/select": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.6.4.tgz", + "integrity": "sha512-whZgF1N53D0/dS8tOFdrswB0alsk5Q5620HC3z+5f2Hpi8gwgAZ8TYa+2IcmMYRiT+bxVuvEc/NirU9yPmqGbA==", + "dependencies": { + "@react-stately/form": "^3.0.3", + "@react-stately/list": "^3.10.5", + "@react-stately/overlays": "^3.6.7", + "@react-types/select": "^3.9.4", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/selection": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.15.1.tgz", + "integrity": "sha512-6TQnN9L0UY9w19B7xzb1P6mbUVBtW840Cw1SjgNXCB3NPaCf59SwqClYzoj8O2ZFzMe8F/nUJtfU1NS65/OLlw==", + "dependencies": { + "@react-stately/collections": "^3.10.7", + "@react-stately/utils": "^3.10.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/slider": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@react-stately/slider/-/slider-3.5.4.tgz", + "integrity": "sha512-Jsf7K17dr93lkNKL9ij8HUcoM1sPbq8TvmibD6DhrK9If2lje+OOL8y4n4qreUnfMT56HCAeS9wCO3fg3eMyrw==", + "dependencies": { + "@react-stately/utils": "^3.10.1", + "@react-types/shared": "^3.23.1", + "@react-types/slider": "^3.7.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/table": { + "version": "3.11.8", + "resolved": "https://registry.npmjs.org/@react-stately/table/-/table-3.11.8.tgz", + "integrity": "sha512-EdyRW3lT1/kAVDp5FkEIi1BQ7tvmD2YgniGdLuW/l9LADo0T+oxZqruv60qpUS6sQap+59Riaxl91ClDxrJnpg==", + "dependencies": { + "@react-stately/collections": "^3.10.7", + "@react-stately/flags": "^3.0.3", + "@react-stately/grid": "^3.8.7", + "@react-stately/selection": "^3.15.1", + "@react-stately/utils": "^3.10.1", + "@react-types/grid": "^3.2.6", + "@react-types/shared": "^3.23.1", + "@react-types/table": "^3.9.5", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/tabs": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/@react-stately/tabs/-/tabs-3.6.6.tgz", + "integrity": "sha512-sOLxorH2uqjAA+v1ppkMCc2YyjgqvSGeBDgtR/lyPSDd4CVMoTExszROX2dqG0c8il9RQvzFuufUtQWMY6PgSA==", + "dependencies": { + "@react-stately/list": "^3.10.5", + "@react-types/shared": "^3.23.1", + "@react-types/tabs": "^3.3.7", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/toggle": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.7.4.tgz", + "integrity": "sha512-CoYFe9WrhLkDP4HGDpJYQKwfiYCRBAeoBQHv+JWl5eyK61S8xSwoHsveYuEZ3bowx71zyCnNAqWRrmNOxJ4CKA==", + "dependencies": { + "@react-stately/utils": "^3.10.1", + "@react-types/checkbox": "^3.8.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/tooltip": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/@react-stately/tooltip/-/tooltip-3.4.9.tgz", + "integrity": "sha512-P7CDJsdoKarz32qFwf3VNS01lyC+63gXpDZG31pUu+EO5BeQd4WKN/AH1Beuswpr4GWzxzFc1aXQgERFGVzraA==", + "dependencies": { + "@react-stately/overlays": "^3.6.7", + "@react-types/tooltip": "^3.4.9", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/tree": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@react-stately/tree/-/tree-3.8.1.tgz", + "integrity": "sha512-LOdkkruJWch3W89h4B/bXhfr0t0t1aRfEp+IMrrwdRAl23NaPqwl5ILHs4Xu5XDHqqhg8co73pHrJwUyiTWEjw==", + "dependencies": { + "@react-stately/collections": "^3.10.7", + "@react-stately/selection": "^3.15.1", + "@react-stately/utils": "^3.10.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-VS/EHRyicef25zDZcM/ClpzYMC5i2YGN6uegOeQawmgfGjb02yaCX0F0zR69Pod9m2Hr3wunTbtpgVXvYbZItg==", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/virtualizer": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-stately/virtualizer/-/virtualizer-3.7.1.tgz", + "integrity": "sha512-voHgE6EQ+oZaLv6u2umKxakvIKNkCQuUihqKACTjdslp7SJh4Mvs3oLBI0hf0JOh+rCcFIKDvQtFwy1fXFRYBA==", + "dependencies": { + "@react-aria/utils": "^3.24.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/breadcrumbs": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/@react-types/breadcrumbs/-/breadcrumbs-3.7.5.tgz", + "integrity": "sha512-lV9IDYsMiu2TgdMIjEmsOE0YWwjb3jhUNK1DCZZfq6uWuiHLgyx2EncazJBUWSjHJ4ta32j7xTuXch+8Ai6u/A==", + "dependencies": { + "@react-types/link": "^3.5.5", + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/button": { + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.9.4.tgz", + "integrity": "sha512-raeQBJUxBp0axNF74TXB8/H50GY8Q3eV6cEKMbZFP1+Dzr09Ngv0tJBeW0ewAxAguNH5DRoMUAUGIXtSXskVdA==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/calendar": { + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/@react-types/calendar/-/calendar-3.4.6.tgz", + "integrity": "sha512-WSntZPwtvsIYWvBQRAPvuCn55UTJBZroTvX0vQvWykJRQnPAI20G1hMQ3dNsnAL+gLZUYxBXn66vphmjUuSYew==", + "dependencies": { + "@internationalized/date": "^3.5.4", + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/checkbox": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.8.1.tgz", + "integrity": "sha512-5/oVByPw4MbR/8QSdHCaalmyWC71H/QGgd4aduTJSaNi825o+v/hsN2/CH7Fq9atkLKsC8fvKD00Bj2VGaKriQ==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/combobox": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@react-types/combobox/-/combobox-3.11.1.tgz", + "integrity": "sha512-UNc3OHt5cUt5gCTHqhQIqhaWwKCpaNciD8R7eQazmHiA9fq8ROlV+7l3gdNgdhJbTf5Bu/V5ISnN7Y1xwL3zqQ==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/datepicker": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@react-types/datepicker/-/datepicker-3.7.4.tgz", + "integrity": "sha512-ZfvgscvNzBJpYyVWg3nstJtA/VlWLwErwSkd1ivZYam859N30w8yH+4qoYLa6FzWLCFlrsRHyvtxlEM7lUAt5A==", + "dependencies": { + "@internationalized/date": "^3.5.4", + "@react-types/calendar": "^3.4.6", + "@react-types/overlays": "^3.8.7", + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/dialog": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.10.tgz", + "integrity": "sha512-S9ga+edOLNLZw7/zVOnZdT5T40etpzUYBXEKdFPbxyPYnERvRxJAsC1/ASuBU9fQAXMRgLZzADWV+wJoGS/X9g==", + "dependencies": { + "@react-types/overlays": "^3.8.7", + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/grid": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.2.6.tgz", + "integrity": "sha512-XfHenL2jEBUYrhKiPdeM24mbLRXUn79wVzzMhrNYh24nBwhsPPpxF+gjFddT3Cy8dt6tRInfT6pMEu9nsXwaHw==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/link": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@react-types/link/-/link-3.5.5.tgz", + "integrity": "sha512-G6P5WagHDR87npN7sEuC5IIgL1GsoY4WFWKO4734i2CXRYx24G9P0Su3AX4GA3qpspz8sK1AWkaCzBMmvnunfw==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/listbox": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.4.9.tgz", + "integrity": "sha512-S5G+WmNKUIOPZxZ4svWwWQupP3C6LmVfnf8QQmPDvwYXGzVc0WovkqUWyhhjJirFDswTXRCO9p0yaTHHIlkdwQ==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/menu": { + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/@react-types/menu/-/menu-3.9.9.tgz", + "integrity": "sha512-FamUaPVs1Fxr4KOMI0YcR2rYZHoN7ypGtgiEiJ11v/tEPjPPGgeKDxii0McCrdOkjheatLN1yd2jmMwYj6hTDg==", + "dependencies": { + "@react-types/overlays": "^3.8.7", + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/meter": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@react-types/meter/-/meter-3.4.1.tgz", + "integrity": "sha512-AIJV4NDFAqKH94s02c5Da4TH2qgJjfrw978zuFM0KUBFD85WRPKh7MvgWpomvUgmzqE6lMCzIdi1KPKqrRabdw==", + "dependencies": { + "@react-types/progress": "^3.5.4" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/numberfield": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/@react-types/numberfield/-/numberfield-3.8.3.tgz", + "integrity": "sha512-z5fGfVj3oh5bmkw9zDvClA1nDBSFL9affOuyk2qZ/M2SRUmykDAPCksbfcMndft0XULWKbF4s2CYbVI+E/yrUA==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/overlays": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.7.tgz", + "integrity": "sha512-zCOYvI4at2DkhVpviIClJ7bRrLXYhSg3Z3v9xymuPH3mkiuuP/dm8mUCtkyY4UhVeUTHmrQh1bzaOP00A+SSQA==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/progress": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@react-types/progress/-/progress-3.5.4.tgz", + "integrity": "sha512-JNc246sTjasPyx5Dp7/s0rp3Bz4qlu4LrZTulZlxWyb53WgBNL7axc26CCi+I20rWL9+c7JjhrRxnLl/1cLN5g==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/radio": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@react-types/radio/-/radio-3.8.1.tgz", + "integrity": "sha512-bK0gio/qj1+0Ldu/3k/s9BaOZvnnRgvFtL3u5ky479+aLG5qf1CmYed3SKz8ErZ70JkpuCSrSwSCFf0t1IHovw==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/searchfield": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@react-types/searchfield/-/searchfield-3.5.5.tgz", + "integrity": "sha512-T/NHg12+w23TxlXMdetogLDUldk1z5dDavzbnjKrLkajLb221bp8brlR/+O6C1CtFpuJGALqYHgTasU1qkQFSA==", + "dependencies": { + "@react-types/shared": "^3.23.1", + "@react-types/textfield": "^3.9.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/select": { + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.9.4.tgz", + "integrity": "sha512-xI7dnOW2st91fPPcv6hdtrTdcfetYiqZuuVPZ5TRobY7Q10/Zqqe/KqtOw1zFKUj9xqNJe4Ov3xP5GSdcO60Eg==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/shared": { + "version": "3.23.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.23.1.tgz", + "integrity": "sha512-5d+3HbFDxGZjhbMBeFHRQhexMFt4pUce3okyRtUVKbbedQFUrtXSBg9VszgF2RTeQDKDkMCIQDtz5ccP/Lk1gw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/slider": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.7.3.tgz", + "integrity": "sha512-F8qFQaD2mqug2D0XeWMmjGBikiwbdERFlhFzdvNGbypPLz3AZICBKp1ZLPWdl0DMuy03G/jy6Gl4mDobl7RT2g==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/switch": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.3.tgz", + "integrity": "sha512-Nb6+J5MrPaFa8ZNFKGMzAsen/NNzl5UG/BbC65SLGPy7O0VDa/sUpn7dcu8V2xRpRwwIN/Oso4v63bt2sgdkgA==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/table": { + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-types/table/-/table-3.9.5.tgz", + "integrity": "sha512-fgM2j9F/UR4Anmd28CueghCgBwOZoCVyN8fjaIFPd2MN4gCwUUfANwxLav65gZk4BpwUXGoQdsW+X50L3555mg==", + "dependencies": { + "@react-types/grid": "^3.2.6", + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/tabs": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.7.tgz", + "integrity": "sha512-ZdLe5xOcFX6+/ni45Dl2jO0jFATpTnoSqj6kLIS/BYv8oh0n817OjJkLf+DS3CLfNjApJWrHqAk34xNh6nRnEg==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/textfield": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-types/textfield/-/textfield-3.9.3.tgz", + "integrity": "sha512-DoAY6cYOL0pJhgNGI1Rosni7g72GAt4OVr2ltEx2S9ARmFZ0DBvdhA9lL2nywcnKMf27PEJcKMXzXc10qaHsJw==", + "dependencies": { + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/tooltip": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/@react-types/tooltip/-/tooltip-3.4.9.tgz", + "integrity": "sha512-wZ+uF1+Zc43qG+cOJzioBmLUNjRa7ApdcT0LI1VvaYvH5GdfjzUJOorLX9V/vAci0XMJ50UZ+qsh79aUlw2yqg==", + "dependencies": { + "@react-types/overlays": "^3.8.7", + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.17.2", "cpu": [ @@ -11444,8 +12923,9 @@ }, "node_modules/@types/jest": { "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", "dev": true, - "license": "MIT", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -21866,6 +23346,17 @@ "version": "0.10.0", "license": "W3C-20150513" }, + "node_modules/intl-messageformat": { + "version": "10.5.14", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz", + "integrity": "sha512-IjC6sI0X7YRjjyVH9aUgdftcmZK7WXdHeil4KwbjDnRWjnVitKpAx3rr6t6di1joFp5188VqKcobOPA6mCLG/w==", + "dependencies": { + "@formatjs/ecma402-abstract": "2.0.0", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.8", + "tslib": "^2.4.0" + } + }, "node_modules/invariant": { "version": "2.2.4", "license": "MIT", @@ -30925,6 +32416,54 @@ "node": ">=0.10.0" } }, + "node_modules/react-aria": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/react-aria/-/react-aria-3.33.1.tgz", + "integrity": "sha512-hFC3K/UA+90Krlx2IgRTgzFbC6FSPi4pUwHT+STperPLK+cTEHkI+3Lu0YYwQSBatkgxnIv9+GtFuVbps2kROw==", + "dependencies": { + "@internationalized/string": "^3.2.3", + "@react-aria/breadcrumbs": "^3.5.13", + "@react-aria/button": "^3.9.5", + "@react-aria/calendar": "^3.5.8", + "@react-aria/checkbox": "^3.14.3", + "@react-aria/combobox": "^3.9.1", + "@react-aria/datepicker": "^3.10.1", + "@react-aria/dialog": "^3.5.14", + "@react-aria/dnd": "^3.6.1", + "@react-aria/focus": "^3.17.1", + "@react-aria/gridlist": "^3.8.1", + "@react-aria/i18n": "^3.11.1", + "@react-aria/interactions": "^3.21.3", + "@react-aria/label": "^3.7.8", + "@react-aria/link": "^3.7.1", + "@react-aria/listbox": "^3.12.1", + "@react-aria/menu": "^3.14.1", + "@react-aria/meter": "^3.4.13", + "@react-aria/numberfield": "^3.11.3", + "@react-aria/overlays": "^3.22.1", + "@react-aria/progress": "^3.4.13", + "@react-aria/radio": "^3.10.4", + "@react-aria/searchfield": "^3.7.5", + "@react-aria/select": "^3.14.5", + "@react-aria/selection": "^3.18.1", + "@react-aria/separator": "^3.3.13", + "@react-aria/slider": "^3.7.8", + "@react-aria/ssr": "^3.9.4", + "@react-aria/switch": "^3.6.4", + "@react-aria/table": "^3.14.1", + "@react-aria/tabs": "^3.9.1", + "@react-aria/tag": "^3.4.1", + "@react-aria/textfield": "^3.14.5", + "@react-aria/tooltip": "^3.7.4", + "@react-aria/utils": "^3.24.1", + "@react-aria/visually-hidden": "^3.8.12", + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, "node_modules/react-colorful": { "version": "5.6.1", "dev": true, @@ -31132,6 +32671,39 @@ } } }, + "node_modules/react-stately": { + "version": "3.31.1", + "resolved": "https://registry.npmjs.org/react-stately/-/react-stately-3.31.1.tgz", + "integrity": "sha512-wuq673NHkYSdoceGryjtMJJvB9iQgyDkQDsnTN0t2v91pXjGDsN/EcOvnUrxXSBtY9eLdIw74R54z9GX5cJNEg==", + "dependencies": { + "@react-stately/calendar": "^3.5.1", + "@react-stately/checkbox": "^3.6.5", + "@react-stately/collections": "^3.10.7", + "@react-stately/combobox": "^3.8.4", + "@react-stately/data": "^3.11.4", + "@react-stately/datepicker": "^3.9.4", + "@react-stately/dnd": "^3.3.1", + "@react-stately/form": "^3.0.3", + "@react-stately/list": "^3.10.5", + "@react-stately/menu": "^3.7.1", + "@react-stately/numberfield": "^3.9.3", + "@react-stately/overlays": "^3.6.7", + "@react-stately/radio": "^3.10.4", + "@react-stately/searchfield": "^3.5.3", + "@react-stately/select": "^3.6.4", + "@react-stately/selection": "^3.15.1", + "@react-stately/slider": "^3.5.4", + "@react-stately/table": "^3.11.8", + "@react-stately/tabs": "^3.6.6", + "@react-stately/toggle": "^3.7.4", + "@react-stately/tooltip": "^3.4.9", + "@react-stately/tree": "^3.8.1", + "@react-types/shared": "^3.23.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "license": "MIT", @@ -38386,18 +39958,21 @@ "@radix-ui/react-tabs": "latest", "@radix-ui/react-tooltip": "^1.0.0", "@radix-ui/react-use-controllable-state": "^1.0.1", - "@reach/combobox": "^0.18.0", - "@reach/popover": "^0.18.0", + "@react-types/combobox": "^3.11.1", + "@react-types/shared": "^3.23.1", "@stitches/react": "1.3.1-1", "@washingtonpost/wpds-assets": "2.0.0", "match-sorter": "6.3.1", "nanoid": "^3.3.4", "popper-max-size-modifier": "^0.2.0", + "react-aria": "^3.33.1", "react-popper": "^2.2.5", + "react-stately": "^3.31.1", "react-swipeable": "^7.0.0", "react-transition-group": "^4.4.5" }, "devDependencies": { + "@types/jest": "^29.5.12", "tsup": "8.0.2", "typescript": "4.5.5" }, diff --git a/packages/kit/package.json b/packages/kit/package.json index ba0dc575e..9621668d8 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -55,18 +55,21 @@ "@radix-ui/react-tabs": "latest", "@radix-ui/react-tooltip": "^1.0.0", "@radix-ui/react-use-controllable-state": "^1.0.1", - "@reach/combobox": "^0.18.0", - "@reach/popover": "^0.18.0", + "@react-types/combobox": "^3.11.1", + "@react-types/shared": "^3.23.1", "@stitches/react": "1.3.1-1", "@washingtonpost/wpds-assets": "2.0.0", "match-sorter": "6.3.1", "nanoid": "^3.3.4", "popper-max-size-modifier": "^0.2.0", "react-popper": "^2.2.5", + "react-aria": "^3.33.1", + "react-stately": "^3.31.1", "react-swipeable": "^7.0.0", "react-transition-group": "^4.4.5" }, "devDependencies": { + "@types/jest": "^29.5.12", "tsup": "8.0.2", "typescript": "4.5.5" }, diff --git a/packages/kit/src/input-search/InputSearchInput.test.tsx b/packages/kit/src/input-search/InputSearchInput.test.tsx index 33197530e..66fd1f7c8 100644 --- a/packages/kit/src/input-search/InputSearchInput.test.tsx +++ b/packages/kit/src/input-search/InputSearchInput.test.tsx @@ -1,27 +1,210 @@ import { render, screen } from "@testing-library/react"; +// eslint-disable-next-line import/no-named-as-default +import userEvent from "@testing-library/user-event"; import { InputSearchInput } from "./InputSearchInput"; import { InputSearchRoot } from "./InputSearchRoot"; import { InputSearchPopover } from "./InputSearchPopover"; +import { InputSearchList } from "./InputSearchList"; +import { InputSearchListItem } from "./InputSearchListItem"; +import { theme } from "../theme"; describe("InputSearchInput", () => { const customRender = (ui, contextProps) => { return render( - + {ui} - + + + + + ); }; + test("renders visibly into the document", () => { - customRender(, {}); - expect(screen.getByLabelText("Test")).toBeInTheDocument(); + customRender(, {}); + expect(screen.getByRole("combobox")).toBeInTheDocument(); + }); + + test("renders with custom CSS class", () => { + customRender( + , + {} + ); + expect(screen.getByRole("combobox")).toHaveClass(/wpds-.*-css/); + }); + + test("uses the error prop", () => { + customRender(, {}); + expect(screen.getByTestId("input-text-container")).toHaveClass( + /wpds-.*-isInvalid-true/ + ); + }); + + test("uses the success prop", () => { + customRender(, {}); + expect(screen.getByTestId("input-text-container")).toHaveClass( + /wpds-.*-isSuccessful-true/ + ); + }); + + test("uses the disabled prop", () => { + customRender(, {}); + expect(screen.getByRole("combobox")).toBeDisabled(); + }); + + test("uses the label", () => { + const labelText = "Test"; + customRender( + , + {} + ); + expect(screen.getByLabelText(labelText)).toBeInTheDocument(); + }); + + /** must be managed by react-stately / react-aria */ + test.skip("uses id", () => { + customRender(, {}); + expect(screen.getByRole("combobox")).toHaveAttribute("id", "test"); + }); + + test("uses name", () => { + customRender(, {}); + expect(screen.getByRole("combobox")).toHaveAttribute("name", "test"); + }); + + test("uses name", () => { + customRender(, {}); + expect(screen.getByRole("combobox")).toHaveAttribute("name", "test"); + }); + + test("uses placeholder", () => { + customRender( + , + {} + ); + expect(screen.getByRole("combobox")).toHaveAttribute("placeholder", "Test"); + }); + + test("renders with custom CSS class", () => { + customRender( + , + {} + ); + expect(screen.getByRole("combobox")).toHaveClass(/wpds-.*-css/); + }); + + test("shows as required", () => { + customRender(, {}); + expect(screen.getByText("*")).toBeInTheDocument(); }); - test("uses contexts portal prop", () => { - customRender(, { - portal: false, - }); - expect(screen.getByTestId("border-style-override")).toHaveStyle( - "--wpds-colors-signal: var(--wpds-colors-subtle)" + + test("uses the value prop", () => { + customRender(, {}); + expect(screen.getByRole("combobox")).toHaveValue("Test"); + }); + + test("uses the buttonIconText prop", () => { + const buttonIconText = "Click to search"; + customRender( + , + {} + ); + expect(screen.getByText(buttonIconText)).toBeInTheDocument(); + }); + + test("uses the buttonIconType prop", () => { + customRender( + , + {} + ); + expect(screen.getByRole("button")).toHaveAttribute("type", "submit"); + }); + + test("uses the errorMessage prop", () => { + customRender( + , + {} + ); + expect(screen.getByText("Error")).toBeInTheDocument(); + }); + + test("uses the helperText prop", () => { + customRender( + , + {} + ); + expect(screen.getByText("Help")).toBeInTheDocument(); + }); + + test("uses the onFocus event handler", () => { + const onFocus = jest.fn(); + customRender( + , + {} ); + screen.getByRole("combobox").focus(); + expect(onFocus).toHaveBeenCalled(); + }); + + test("uses the onBlur event handler", () => { + const onBlur = jest.fn(); + customRender( + , + {} + ); + const input = screen.getByRole("combobox"); + input.focus(); + input.blur(); + + expect(onBlur).toHaveBeenCalled(); + }); + + test("uses the onChange event handler", async () => { + const user = userEvent.setup(); + const onChange = jest.fn(); + customRender( + , + {} + ); + + await user.keyboard("Test"); + + expect(onChange).toHaveBeenCalled; + }); + + test("uses the onButtonIconClick event handler", async () => { + const user = userEvent.setup(); + const onButtonIconClick = jest.fn(); + customRender( + , + {} + ); + await user.click(screen.getByRole("button")); + expect(onButtonIconClick).toHaveBeenCalled(); + }); + + test("updates the value when an item is highlighted", async () => { + const user = userEvent.setup(); + customRender(, {}); + const inputElement = screen.getByRole("combobox"); + await user.click(inputElement); + await user.keyboard("T"); + await user.keyboard("[ArrowDown]"); + expect(inputElement).toHaveValue("Test item"); }); }); diff --git a/packages/kit/src/input-search/InputSearchInput.tsx b/packages/kit/src/input-search/InputSearchInput.tsx index 6d5a07988..93f04a545 100644 --- a/packages/kit/src/input-search/InputSearchInput.tsx +++ b/packages/kit/src/input-search/InputSearchInput.tsx @@ -1,57 +1,105 @@ import React from "react"; - -import { ComboboxInput } from "@reach/combobox"; - import { InputText } from "../input-text"; -import { InputLabel } from "../input-label"; import type * as WPDS from "../theme"; - import { InputSearchContext } from "./InputSearchRoot"; -type InputSearchLabelVariants = WPDS.VariantProps; - -export type InputSearchInputProps = InputSearchLabelVariants & { +export type InputSearchInputProps = { /** Override CSS */ css?: WPDS.CSS; /**The input's label text, required for accessibility * @default Search */ label?: string; -} & React.ComponentPropsWithRef & - Omit, "label">; - -//TODO: when you press the search button things should search + /** Determines if the value in the input changes or not as the user navigates with the keyboard. If true, the value changes, if false the value doesn't change. Set this to false when you don't really need the value from the input but want to populate some other state (like the recipient selector in Gmail). But if your input is more like a normal ``, then leave the `true` default. + * @default true + */ + autocomplete?: boolean; +} & Omit, "label">; export const InputSearchInput = React.forwardRef< HTMLInputElement, InputSearchInputProps ->(({ label = "Search", name, id, ...rest }: InputSearchInputProps, ref) => { - const { disabled, usePortal } = React.useContext(InputSearchContext); - // console.log("usePortal", usePortal); - return ( -
( + ( + { + label = "Search", + autocomplete = true, + id, + ...rest + }: InputSearchInputProps, + ref + ) => { + const { inputProps, inputRef, state, isDisabled } = + React.useContext(InputSearchContext); + // make use of both external and internal ref + React.useEffect(() => { + if (!ref) return; + typeof ref === "function" + ? ref(inputRef.current) + : (ref.current = inputRef.current); + }, [ref, inputRef]); + + // handle internal and external onChange + const handleChange = (event: React.ChangeEvent) => { + if (rest.onChange) rest.onChange(event); + if (inputProps.onChange) inputProps.onChange(event); + }; + + const [tempText, setTempText] = React.useState(); + const withKeyboard = React.useRef(false); + React.useEffect(() => { + if (state.selectionManager.isFocused) { + const focusedItem = state.collection.getItem( + state.selectionManager.focusedKey + ); + + if (focusedItem && withKeyboard.current) { + setTempText(focusedItem.textValue); + } + } else { + setTempText(undefined); } - data-testid="border-style-override" - > - ) => { + if (event.key === "ArrowDown" || event.key === "ArrowUp") { + withKeyboard.current = true; + } + if (rest.onKeyDown) rest.onKeyDown(event); + if (inputProps.onKeyDown) inputProps.onKeyDown(event); + }; + const handleKeyUp = (event: React.KeyboardEvent) => { + if (event.key === "ArrowDown" || event.key === "ArrowUp") { + withKeyboard.current = false; + } + if (rest.onKeyUp) rest.onKeyUp(event); + if (inputProps.onKeyUp) inputProps.onKeyUp(event); + }; + + return ( + -
- ); -}); + ); + } +); InputSearchInput.displayName = "InputSearchInput"; diff --git a/packages/kit/src/input-search/InputSearchItemText.test.tsx b/packages/kit/src/input-search/InputSearchItemText.test.tsx index 4e0982e19..d21df8ef9 100644 --- a/packages/kit/src/input-search/InputSearchItemText.test.tsx +++ b/packages/kit/src/input-search/InputSearchItemText.test.tsx @@ -1,23 +1,31 @@ import { render, screen } from "@testing-library/react"; +// eslint-disable-next-line import/no-named-as-default +import userEvent from "@testing-library/user-event"; import { InputSearchItemText } from "./InputSearchItemText"; import { InputSearchRoot } from "./InputSearchRoot"; import { InputSearchListItem } from "./InputSearchListItem"; import { InputSearchList } from "./InputSearchList"; +import { InputSearchPopover } from "./InputSearchPopover"; +import { InputSearchInput } from "./InputSearchInput"; describe("InputSearchItemText", () => { const customRender = (ui, contextProps) => { return render( - - - {ui} - + + + + + {ui} + + ); }; - test("renders visibly into the document", () => { - customRender(, { - value: "test", - }); + test("renders visibly into the document", async () => { + const user = userEvent.setup(); + customRender(test, {}); + + await user.click(screen.getByRole("combobox")); expect(screen.getByText("test")).toBeInTheDocument(); }); }); diff --git a/packages/kit/src/input-search/InputSearchItemText.tsx b/packages/kit/src/input-search/InputSearchItemText.tsx index 2b4179f9c..66395fc3d 100644 --- a/packages/kit/src/input-search/InputSearchItemText.tsx +++ b/packages/kit/src/input-search/InputSearchItemText.tsx @@ -1,8 +1,8 @@ import React from "react"; -import { ComboboxOptionText } from "@reach/combobox"; import { styled } from "../theme"; +import { InputSearchContext } from "./InputSearchRoot"; -const StyledItemText = styled(ComboboxOptionText, {}); +const StyledItemText = styled("span", {}); export type InputSearchItemTextProps = { children: React.ReactNode; @@ -12,7 +12,19 @@ export const InputSearchItemText = ({ children, ...rest }: InputSearchItemTextProps) => { - return {children}; + const { state } = React.useContext(InputSearchContext); + + const highlighted = (children as string).replace( + new RegExp(state.inputValue, "gi"), + (match) => (match ? `${match}` : "") + ); + + return ( + + ); }; InputSearchItemText.displayName = "InputSearchItemText"; diff --git a/packages/kit/src/input-search/InputSearchList.test.tsx b/packages/kit/src/input-search/InputSearchList.test.tsx index 47945a9b4..b37683a3b 100644 --- a/packages/kit/src/input-search/InputSearchList.test.tsx +++ b/packages/kit/src/input-search/InputSearchList.test.tsx @@ -1,6 +1,12 @@ import { render, screen } from "@testing-library/react"; +// eslint-disable-next-line import/no-named-as-default +import userEvent from "@testing-library/user-event"; + import { InputSearchList } from "./InputSearchList"; import { InputSearchRoot } from "./InputSearchRoot"; +import { InputSearchInput } from "./InputSearchInput"; +import { InputSearchPopover } from "./InputSearchPopover"; +import { InputSearchListItem } from "./InputSearchListItem"; describe("InputSearchList", () => { const customRender = (ui, contextProps) => { @@ -8,7 +14,46 @@ describe("InputSearchList", () => { }; test("renders visibly into the document", () => { - customRender(, {}); + customRender(test, {}); expect(screen.getByRole("listbox")).toBeInTheDocument(); }); + + test("renders with custom CSS class", () => { + customRender( + test, + {} + ); + expect(screen.getByRole("listbox")).toHaveClass(/wpds-.*-css/); + }); + + /** test persistSelection prop */ + test("uses persistSelection prop", async () => { + const user = userEvent.setup(); + customRender( + <> + + + + + + + + + , + { openOnFocus: true } + ); + const input = screen.getByRole("combobox"); + await user.click(input); + + await user.keyboard("[ArrowDown]"); + await user.keyboard("[ArrowDown]"); + await user.keyboard("[Enter]"); + + await user.click(document.body); + await user.click(input); + + const item = screen.getAllByRole("option")[1]; + expect(item).toHaveAttribute("aria-selected", "true"); + expect(item).toHaveClass(/wpds-.*-focused-true/); + }); }); diff --git a/packages/kit/src/input-search/InputSearchList.tsx b/packages/kit/src/input-search/InputSearchList.tsx index e3347a7cf..aac7ef189 100644 --- a/packages/kit/src/input-search/InputSearchList.tsx +++ b/packages/kit/src/input-search/InputSearchList.tsx @@ -1,8 +1,12 @@ import React from "react"; -import { ComboboxList, useComboboxContext } from "@reach/combobox"; +import { useListBox } from "react-aria"; import { styled } from "../theme"; +import { InputSearchContext } from "./InputSearchRoot"; +import { ListItem } from "./InputSearchListItem"; +import { ListHeading } from "./InputSearchListHeading"; +import type { CollectionChildren } from "@react-types/shared"; -const StyledList = styled(ComboboxList, { +const StyledList = styled("ul", { marginBlock: 0, maxHeight: "300px", overflowY: "auto", @@ -11,46 +15,54 @@ const StyledList = styled(ComboboxList, { listStyleType: "none", }); -export type InputSearchListProps = React.ComponentPropsWithRef< - typeof StyledList ->; +export type InputSearchListProps = { + persistSelection?: boolean; +} & React.ComponentPropsWithRef; export const InputSearchList = ({ children, - css, + persistSelection = false, ...rest }: InputSearchListProps) => { - const { navigationValue, state } = useComboboxContext(); - - const listRef = React.useRef(null); + const { + listBoxProps: contextProps, + listBoxRef, + state, + setCollectionChildren, + } = React.useContext(InputSearchContext); React.useEffect(() => { - if (state === "NAVIGATING") { - const listEl = listRef.current; - if (!listEl) return; - - const selectedEl = listEl.querySelector( - '[aria-selected = "true"]' - ) as HTMLElement; - if (!selectedEl) return; - - const listTop = listEl.scrollTop; - const listBottom = listTop + listEl.clientHeight; - - const selectedTop = selectedEl.offsetTop; - const selectedBottom = selectedTop + selectedEl.clientHeight; + if (children) { + setCollectionChildren(children as CollectionChildren); + } + }, [children]); - if (selectedTop < listTop) { - listEl.scrollTop -= listTop - selectedTop; - } else if (selectedBottom > listBottom) { - listEl.scrollTop += selectedBottom - listBottom; + React.useEffect(() => { + if (state.isOpen) { + // Focus on the first item when the list opens + if (persistSelection) { + const selectedKey = state.selectionManager.selectedKeys + .values() + .next().value; + if (selectedKey) { + state.selectionManager.setFocusedKey(selectedKey); + } + //state.selectionManager.setFocusedKey(state.collection.getFirstKey()); } } - }, [navigationValue, state]); + }, [state.isOpen]); + + const { listBoxProps } = useListBox(contextProps, state, listBoxRef); return ( - - {children} + + {Array.from(state.collection).map((item) => + item.type === "section" ? ( + + ) : ( + + ) + )} ); }; diff --git a/packages/kit/src/input-search/InputSearchListHeading.test.tsx b/packages/kit/src/input-search/InputSearchListHeading.test.tsx index a33a94481..84a5da841 100644 --- a/packages/kit/src/input-search/InputSearchListHeading.test.tsx +++ b/packages/kit/src/input-search/InputSearchListHeading.test.tsx @@ -1,9 +1,27 @@ import { render, screen } from "@testing-library/react"; +// eslint-disable-next-line import/no-named-as-default +import userEvent from "@testing-library/user-event"; import { InputSearchListHeading } from "./InputSearchListHeading"; +import { InputSearchRoot } from "./InputSearchRoot"; +import { InputSearchInput } from "./InputSearchInput"; +import { InputSearchPopover } from "./InputSearchPopover"; +import { InputSearchList } from "./InputSearchList"; describe("InputSearchListHeading", () => { - test("renders visibly into the document", () => { - render(test); - expect(screen.getByText("test")).toBeInTheDocument(); + const customRender = (ui) => { + return render( + + + + {ui} + + + ); + }; + test("renders visibly into the document", async () => { + const user = userEvent.setup(); + customRender(heading); + await user.click(screen.getByRole("combobox")); + expect(screen.getByText("heading")).toBeInTheDocument(); }); }); diff --git a/packages/kit/src/input-search/InputSearchListHeading.tsx b/packages/kit/src/input-search/InputSearchListHeading.tsx index 46fedcf4f..fe2d45d8f 100644 --- a/packages/kit/src/input-search/InputSearchListHeading.tsx +++ b/packages/kit/src/input-search/InputSearchListHeading.tsx @@ -1,14 +1,12 @@ import React from "react"; - -import type * as WPDS from "../theme"; +import { Section } from "react-stately"; +import { useListBoxSection } from "react-aria"; import { styled, theme } from "../theme"; +import { ListItem } from "./InputSearchListItem"; -export type InputSearchListHeadingProps = { - /** Any React node may be used as a child */ - children?: React.ReactNode; - /** Override CSS */ - css?: WPDS.CSS; -}; +import type { ListState } from "react-stately"; +import type { Node } from "@react-types/shared"; +import type * as WPDS from "../theme"; const StyledListItem = styled("li", { borderBlockStart: `1px solid ${theme.colors.faint}`, @@ -19,11 +17,72 @@ const StyledListItem = styled("li", { paddingBlock: "$050", }); -export const InputSearchListHeading = ({ - children, - ...rest -}: InputSearchListHeadingProps) => { - return {children}; +const UnstyledList = styled("ul", { + listStyleType: "none", + marginBlock: 0, + marginInline: `calc(-1*${theme.space["075"]})`, + paddingInlineStart: 0, +}); + +export type InputSearchListHeadingProps = { + /** Any React node may be used as a child */ + children?: React.ReactNode; + /** Override CSS */ + css?: WPDS.CSS; + //** Title when used to wrap items*/ + title?: string; +}; + +/* + To extend react-stately's Section component without errors we return an empty function and attach its getCollectionNode static method to it. https://github.com/nextui-org/nextui/issues/1761#issuecomment-1790586620 +*/ + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export const InputSearchListHeading = (props: InputSearchListHeadingProps) => { + return null; +}; + +InputSearchListHeading.getCollectionNode = (props) => { + const alteredProps = { ...props }; + // handle the previously used child text as title + if (props.children && !props.title) { + alteredProps.title = props.children; + alteredProps.children = undefined; + } + // @ts-expect-error - static method is excluded from the type definition https://github.com/adobe/react-spectrum/blob/main/packages/%40react-stately/collections/src/Section.ts#L57 + return Section.getCollectionNode(alteredProps); +}; + +/* + ListHeading component rendered by InputSearchList from a Collection in state. + Any props assigned will get passed through from InputSearchListItem +*/ + +interface SectionProps { + section: Node; + state: ListState; +} + +export const ListHeading = ({ section, state }: SectionProps) => { + const { itemProps, headingProps, groupProps } = useListBoxSection({ + heading: section.rendered, + "aria-label": section["aria-label"], + }); + + const childNodesArr = Array.from(section.childNodes); + const childNodeLength = childNodesArr.length; + return ( + + {section.rendered && {section.rendered}} + {childNodeLength > 0 && ( + + {childNodesArr.map((node) => ( + + ))} + + )} + + ); }; -InputSearchListHeading.displayName = "InputSearchListHeading"; +ListHeading.displayName = "InputSearchListHeading"; diff --git a/packages/kit/src/input-search/InputSearchListItem.test.tsx b/packages/kit/src/input-search/InputSearchListItem.test.tsx index 0ffbec33c..3cf66f227 100644 --- a/packages/kit/src/input-search/InputSearchListItem.test.tsx +++ b/packages/kit/src/input-search/InputSearchListItem.test.tsx @@ -1,18 +1,27 @@ import { render, screen } from "@testing-library/react"; +// eslint-disable-next-line import/no-named-as-default +import userEvent from "@testing-library/user-event"; import { InputSearchListItem } from "./InputSearchListItem"; import { InputSearchRoot } from "./InputSearchRoot"; +import { InputSearchInput } from "./InputSearchInput"; +import { InputSearchPopover } from "./InputSearchPopover"; import { InputSearchList } from "./InputSearchList"; -describe("InputSearchItemText", () => { - const customRender = (ui, contextProps) => { +describe("InputSearchListItem", () => { + const customRender = (ui) => { return render( - - {ui} + + + + {ui} + ); }; - test("renders visibly into the document", () => { - customRender(, {}); + test("renders visibly into the document", async () => { + const user = userEvent.setup(); + customRender(); + await user.click(screen.getByRole("combobox")); expect(screen.getByRole("option")).toBeInTheDocument(); }); }); diff --git a/packages/kit/src/input-search/InputSearchListItem.tsx b/packages/kit/src/input-search/InputSearchListItem.tsx index 4ac95fb47..841a28139 100644 --- a/packages/kit/src/input-search/InputSearchListItem.tsx +++ b/packages/kit/src/input-search/InputSearchListItem.tsx @@ -1,40 +1,112 @@ import React from "react"; -import { ComboboxOption } from "@reach/combobox"; +import { Item } from "react-stately"; +import { useOption } from "react-aria"; import { styled, theme } from "../theme"; -const StyledListItem = styled(ComboboxOption, { +import type { Node, ListState, ComboBoxState } from "react-stately"; + +const StyledListItem = styled("li", { color: theme.colors.primary, fontFamily: theme.fonts.meta, fontSize: theme.fontSizes["100"], fontWeight: theme.fontWeights.light, paddingBlock: "$050", paddingInline: "$075", - "&:hover": { - backgroundColor: theme.colors.gray400, - }, - "&[aria-selected='true']": { - backgroundColor: theme.colors.gray400, - }, - "[data-user-value='true']": { + "& > span > mark": { + backgroundColor: "transparent", fontWeight: theme.fontWeights.bold, }, + variants: { + selected: { + true: { + backgroundColor: theme.colors.gray400, + }, + }, + focused: { + true: { + backgroundColor: theme.colors.gray400, + }, + }, + disabled: { + true: { + color: theme.colors.onDisabled, + }, + }, + }, }); -export type InputSearchListItemProps = Omit< +export type InputSearchListItemProps = { value?: string } & Omit< React.ComponentPropsWithRef, "index" >; -export const InputSearchListItem = ({ - children, - value, - ...rest -}: InputSearchListItemProps) => { +/* + To extend react-stately's Item component without errors we return an empty function and attach its getCollectionNode static method to it. https://github.com/nextui-org/nextui/issues/1761#issuecomment-1790586620 +*/ + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export const InputSearchListItem = (props: InputSearchListItemProps) => { + return null; +}; + +InputSearchListItem.getCollectionNode = (props, context) => { + const alteredProps = { ...props }; + // handle the previously used value prop from @reach/combobox + + if (props.value) { + alteredProps.textValue = props.value; + if (!props.children) { + alteredProps.children = props.value; + } + delete alteredProps.value; + } + // @ts-expect-error - static method is excluded from the type definition https://github.com/adobe/react-spectrum/blob/main/packages/%40react-stately/collections/src/Item.ts#L78 + return Item.getCollectionNode(alteredProps, context); +}; + +/* + ListItem component rendered by InputSearchList from a Collection in state. + Any props assigned will get passed through from InputSearchListItem +*/ + +interface ListItemProps { + item: Node; + state: ListState; +} + +export const ListItem = ({ item, state }: ListItemProps) => { + const ref = React.useRef(null); + const { optionProps, isDisabled, isSelected, isFocused } = useOption( + { + key: item.key, + }, + state, + ref + ); + + let highlighted; + if (typeof item.rendered === "string") { + highlighted = item.rendered.replace( + new RegExp((state as ComboBoxState).inputValue, "gi"), + (match) => (match ? `${match}` : "") + ); + } + return ( - - {children} + + {highlighted ? ( + + ) : ( + item.rendered + )} ); }; -InputSearchListItem.displayName = "InputSearchListItem"; +ListItem.displayName = "InputSearchListItem"; diff --git a/packages/kit/src/input-search/InputSearchPopover.test.tsx b/packages/kit/src/input-search/InputSearchPopover.test.tsx index c2b907caf..4eebe9f2e 100644 --- a/packages/kit/src/input-search/InputSearchPopover.test.tsx +++ b/packages/kit/src/input-search/InputSearchPopover.test.tsx @@ -1,15 +1,43 @@ import { render, screen } from "@testing-library/react"; +// eslint-disable-next-line import/no-named-as-default +import userEvent from "@testing-library/user-event"; import { InputSearchPopover } from "./InputSearchPopover"; import { InputSearchRoot } from "./InputSearchRoot"; +import { InputSearchInput } from "./InputSearchInput"; describe("InputSearchPopover", () => { const customRender = (ui, contextProps) => { - return render({ui}); + return render( + + + {ui} + + ); }; - test("renders invisibly into the document", () => { - customRender(test, {}); - const popover = screen.getByText("test"); - expect(popover).toBeInTheDocument(); - expect(popover).not.toBeVisible(); + + test("renders into the document", async () => { + const user = userEvent.setup(); + customRender(, {}); + const inputElement = screen.getByRole("combobox"); + await user.click(inputElement); + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); + + test("renders with custom CSS class", async () => { + const user = userEvent.setup(); + customRender(, {}); + const inputElement = screen.getByRole("combobox"); + await user.click(inputElement); + expect(screen.getByRole("dialog")).toHaveClass(/wpds-.*-css/); + }); + + test("renders portal false variant", async () => { + const user = userEvent.setup(); + customRender(, {}); + const inputElement = screen.getByRole("combobox"); + await user.click(inputElement); + expect(screen.getByRole("dialog")).not.toHaveClass( + /wpds-.*-density-default/ + ); }); }); diff --git a/packages/kit/src/input-search/InputSearchPopover.tsx b/packages/kit/src/input-search/InputSearchPopover.tsx index 70b020898..61dc56ee3 100644 --- a/packages/kit/src/input-search/InputSearchPopover.tsx +++ b/packages/kit/src/input-search/InputSearchPopover.tsx @@ -1,53 +1,77 @@ import React from "react"; -import { ComboboxPopover } from "@reach/combobox"; -import { positionMatchWidth } from "@reach/popover"; +import { createPortal } from "react-dom"; +import { Popover } from "../popover"; import { styled, theme } from "../theme"; import { InputSearchContext } from "./InputSearchRoot"; -const Background = styled("div", { - backgroundColor: theme.colors.secondary, - variants: { - floating: { - true: { - border: `1px solid ${theme.colors.subtle}`, - boxShadow: theme.shadows["200"], - marginBlock: theme.space["025"], - }, - }, - }, +const StyledContent = styled("div", { + backgroundColor: theme.colors.background, + borderTop: `1px solid ${theme.colors.gray300}`, + color: theme.colors.primary, + marginTop: "-1px", + overflow: "hidden", }); -export type InputSearchPopoverProps = Omit< - React.ComponentPropsWithRef, - "unstable_observableRefs" | "unstable_skipInitialPortalRender" -> & - React.ComponentProps; +export type InputSearchPopoverProps = React.ComponentPropsWithRef< + typeof Popover.Content +> & { portal?: boolean; portalDomNode?: HTMLElement }; export const InputSearchPopover = ({ css, children, portal = true, + portalDomNode, ...rest }: InputSearchPopoverProps) => { - const { setUsePortal, rootRect } = React.useContext(InputSearchContext); + const { popoverRef, state, containerRef, setUsePortal, setPortalDomNode } = + React.useContext(InputSearchContext); + + const [key, setKey] = React.useState(0); + React.useEffect(() => { + setPortalDomNode(portalDomNode || document.body); + // There is a race condition where the portalDomNode is not yet mounted + // Force a re-render to ensure content is rendered + setTimeout(() => { + setKey((prev) => prev + 1); + }, 30); + }, [portalDomNode, setPortalDomNode, setKey]); React.useEffect(() => { setUsePortal(portal); - }, []); - - return ( - { - return positionMatchWidth(rootRect, popoverRect); - }} - {...rest} - > - + }, [portal, setUsePortal]); + + if (!state.isOpen) return null; + + if (portal) { + return ( + + + + { + event.preventDefault(); + }} + css={{ + width: "var(--radix-popper-anchor-width)", + padding: 0, + ...css, + }} + {...rest} + > + {children} + + + + ); + } else { + return createPortal( + {children} - - - ); + , + popoverRef.current as unknown as HTMLElement + ); + } }; InputSearchPopover.displayName = "InputSearchPopover"; diff --git a/packages/kit/src/input-search/InputSearchRoot.test.tsx b/packages/kit/src/input-search/InputSearchRoot.test.tsx index 3454ed671..0a2ba70ec 100644 --- a/packages/kit/src/input-search/InputSearchRoot.test.tsx +++ b/packages/kit/src/input-search/InputSearchRoot.test.tsx @@ -1,24 +1,119 @@ -import { useContext } from "react"; import { render, screen } from "@testing-library/react"; -import { InputSearchRoot, InputSearchContext } from "./InputSearchRoot"; +// eslint-disable-next-line import/no-named-as-default +import userEvent from "@testing-library/user-event"; +import { InputSearchRoot } from "./InputSearchRoot"; +import { InputSearchInput } from "./InputSearchInput"; +import { InputSearchPopover } from "./InputSearchPopover"; +import { InputSearchList } from "./InputSearchList"; +import { InputSearchListItem } from "./InputSearchListItem"; describe("InputSearchRoot", () => { - const TestComponent = () => { - const { rootRect } = useContext(InputSearchContext); - return
{rootRect && rootRect.top}
; - }; - test("renders visibly into the document", () => { render(Test); expect(screen.getByText("Test")).toBeInTheDocument(); }); - test("provides root rect in context", () => { + test("accepts children", () => { + const testText = "Test child component"; render( - +
{testText}
+
+ ); + expect(screen.getByText(testText)).toBeInTheDocument(); + }); + + test("disables input with disabled prop", () => { + render( + + + + ); + expect(screen.getByRole("combobox")).toBeDisabled(); + }); + + test("renders with custom CSS class", () => { + render( + + Test + + ); + expect(screen.getByTestId("root")).toHaveClass(/wpds-.*-css/); + }); + + test("renders with aria-label attribute", () => { + const ariaLabel = "Search"; + render( + + + + ); + + expect(screen.getByRole("combobox")).toHaveAttribute( + "aria-label", + ariaLabel + ); + }); + + test("renders with aria-labelledby attribute", () => { + const labelId = "search-label"; + render( + + ); - expect(screen.getByText("0")).toBeInTheDocument(); + + expect(screen.getByRole("combobox")).toHaveAttribute( + "aria-labelledby", + expect.stringContaining(labelId) + ); + }); + + test("renders portal false variant", () => { + render( + + + + ); + + expect(screen.getByTestId("root")).toHaveClass(/wpds-.*-portal-false/); + }); + + test("opens the dropdown on focus", async () => { + const user = userEvent.setup(); + + render( + + + popover + + ); + + const inputElement = screen.getByRole("combobox"); + await user.click(inputElement); + + expect(await screen.findByText("popover")).toBeInTheDocument(); + }); + + test("calls onSelect callback when an option is selected", async () => { + const user = userEvent.setup(); + const onSelect = jest.fn(); + render( + + + + + + + + + ); + + const inputElement = screen.getByRole("combobox"); + await user.click(inputElement); + const item = screen.getByRole("option"); + expect(item).toBeInTheDocument(); + await user.click(item); + expect(onSelect).toHaveBeenCalledWith("Option 1"); }); }); diff --git a/packages/kit/src/input-search/InputSearchRoot.tsx b/packages/kit/src/input-search/InputSearchRoot.tsx index fb2e9248e..95370d67d 100644 --- a/packages/kit/src/input-search/InputSearchRoot.tsx +++ b/packages/kit/src/input-search/InputSearchRoot.tsx @@ -1,21 +1,35 @@ import React from "react"; -import { Combobox } from "@reach/combobox"; +import { createPortal } from "react-dom"; +import { useComboBoxState } from "react-stately"; +import { useComboBox } from "react-aria"; import { styled, theme } from "../theme"; +import type * as WPDS from "../theme"; +import type { ComboBoxState } from "react-stately"; +import type { AriaListBoxOptions } from "react-aria"; +import type { CollectionChildren } from "@react-types/shared"; + type InputSearchContextProps = { - term: string; - setTerm: (string: string) => void; - disabled: boolean; - usePortal: boolean; - setUsePortal: (bool: boolean) => void; - rootRect: DOMRect | undefined; + state: ComboBoxState; + inputRef: React.MutableRefObject; + listBoxRef: React.MutableRefObject; + popoverRef: React.MutableRefObject; + containerRef: React.MutableRefObject; + inputProps: React.InputHTMLAttributes; + listBoxProps: AriaListBoxOptions; + setCollectionChildren: React.Dispatch< + React.SetStateAction | undefined> + >; + isDisabled?: boolean; + setUsePortal: React.Dispatch>; + setPortalDomNode: React.Dispatch>; }; export const InputSearchContext = React.createContext( {} as InputSearchContextProps ); -const StyledComboBox = styled(Combobox, { +const StyledRoot = styled("div", { width: "100%", position: "relative", variants: { @@ -36,53 +50,102 @@ const StyledComboBox = styled(Combobox, { }); export type InputSearchRootProps = { + /** Defines a string value that labels the current element. */ + "aria-label"?: string; + /** Identifies the element (or elements) that labels the current element. */ + "aria-labelledby"?: string; + /** InputSearch.Root expects to receive InputSearch.Input and InputSearch.Popover as children.*/ + children?: React.ReactNode; + /** Override CSS */ + css?: WPDS.CSS; /** Whether the input field should be disabled or not */ disabled?: boolean; -} & React.ComponentPropsWithRef; + /** If true, the popover opens when focus is on the text box. */ + openOnFocus?: boolean; + /** Called with the selection value when the user makes a selection from the list. */ + onSelect?: (value: string) => void; +} & React.ComponentPropsWithoutRef<"div">; export const InputSearchRoot = ({ children, css, - disabled = false, + disabled, + openOnFocus, + onSelect, ...props }: InputSearchRootProps) => { - const comboboxRef = React.useRef(null); - const [rootRect, setRootRect] = React.useState(); - const [term, setTerm] = React.useState(""); - const [usePortal, setUsePortal] = React.useState(true); + const [collectionChildren, setCollectionChildren] = + React.useState>(); - React.useEffect(() => { - if (comboboxRef.current) { - const positionChangeHandler = () => { - setRootRect(comboboxRef.current?.getBoundingClientRect()); - }; + const state = useComboBoxState({ + children: collectionChildren, + allowsCustomValue: true, + allowsEmptyCollection: true, + menuTrigger: openOnFocus ? "focus" : "input", + ...props, + }); - window.addEventListener("resize", positionChangeHandler); - document.addEventListener("scroll", positionChangeHandler); + const inputRef = React.useRef(null); + const listBoxRef = React.useRef(null); + const popoverRef = React.useRef(null); - positionChangeHandler(); + const { inputProps, listBoxProps } = useComboBox( + { + label: "Search", + ...props, + inputRef, + listBoxRef, + popoverRef, + }, + state + ); - return () => { - window.removeEventListener("resize", positionChangeHandler); - document.removeEventListener("scroll", positionChangeHandler); - }; + React.useEffect(() => { + if (state.selectedItem && onSelect) { + onSelect( + state.selectedItem.textValue || (state.selectedItem.rendered as string) + ); } - }, [setRootRect]); + }, [state.selectedItem, onSelect]); + + const containerRef = React.useRef(null); + + const [usePortal, setUsePortal] = React.useState(); + const [portalDomNode, setPortalDomNode] = React.useState( + null + ); return ( - + {children} - + {/* + react-aria's ariaHideOutside utility assumes popover is visible when the global state.isOpen is true. This isn't always the case for conditional rendering, especially when async data is involved. Use root level containers to avoid errors and respond correctly to clicks + */} + {usePortal ? ( + portalDomNode !== null && + createPortal( +
, + portalDomNode + ) + ) : ( +
+ )} + ); }; diff --git a/packages/kit/src/input-search/index.ts b/packages/kit/src/input-search/index.ts index 8585a8660..8a422e180 100644 --- a/packages/kit/src/input-search/index.ts +++ b/packages/kit/src/input-search/index.ts @@ -3,8 +3,8 @@ export * from "./InputSearchRoot"; export * from "./InputSearchInput"; export * from "./InputSearchPopover"; export * from "./InputSearchList"; -export * from "./InputSearchListItem"; +export { InputSearchListItem } from "./InputSearchListItem"; export * from "./InputSearchItemText"; -export * from "./InputSearchListHeading"; +export { InputSearchListHeading } from "./InputSearchListHeading"; export * from "./InputSearchEmptyState"; export * from "./InputSearchLoadingState"; diff --git a/packages/kit/src/input-search/play.stories.tsx b/packages/kit/src/input-search/play.stories.tsx index 2aa3edf82..dccf0591b 100644 --- a/packages/kit/src/input-search/play.stories.tsx +++ b/packages/kit/src/input-search/play.stories.tsx @@ -165,15 +165,17 @@ const GroupingTemplate: StoryFn = (args) => { + Fruits - Vegetables - - - + + + + + diff --git a/packages/kit/src/input-text/StyledContainer.tsx b/packages/kit/src/input-text/StyledContainer.tsx index 7f4c90ff4..21eebd065 100644 --- a/packages/kit/src/input-text/StyledContainer.tsx +++ b/packages/kit/src/input-text/StyledContainer.tsx @@ -60,7 +60,7 @@ export const StyledContainer = React.forwardRef< HTMLDivElement, StyledContainerProps >(({ children, ...props }, ref) => ( - + {children} ));