diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 84981a56..41e8c131 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -28,6 +28,7 @@ jobs: VITE_SENTRY_DSN: ${{ secrets.SENTRY_DSN }} VITE_SENTRY_CI_RELEASE_NAME: ${{ github.event.release.name }} VITE_STRIPE_PUBLISHABLE_KEY: ${{ secrets.STRIPE_TEST_PUBLISHABLE_KEY }} + VITE_GOOGLE_OAUTH_CLIENT_ID: ${{ secrets.GOOGLE_OAUTH_CLIENT_ID }} run: | if [ "${{ github.event.release.prerelease }}" == 'true' ]; then npm run build:staging diff --git a/.storybook/decorators/globalDecorators.tsx b/.storybook/decorators/globalDecorators.tsx index 9080e47d..4eb0a452 100644 --- a/.storybook/decorators/globalDecorators.tsx +++ b/.storybook/decorators/globalDecorators.tsx @@ -2,6 +2,7 @@ import { DecoratorHelpers } from "@storybook/addon-themes"; import CssBaseline from "@mui/material/CssBaseline"; import MuiThemeProvider from "@mui/material/styles/ThemeProvider"; import { GlobalStyles } from "@/app/GlobalStyles"; +import { GoogleOAuthContextProvider } from "@/app/GoogleOAuthContext"; import { PageLayoutContextProvider } from "@/app/PageLayoutContext"; import { THEMES, THEME_NAMES, type ThemeName } from "@/app/ThemeProvider/themes"; import { useAppThemeObject } from "@/app/ThemeProvider/useAppThemeObject"; @@ -30,8 +31,12 @@ const withCustomThemeProvider = (): DecoratorFunction => { const themeFromGlobals = globals?.theme; const themeOverrideFromParameters = parameters?.themes?.themeOverride; - const selectedTheme = themeOverrideFromParameters || themeFromGlobals || DEFAULT_THEME; + let selectedTheme = themeOverrideFromParameters || themeFromGlobals || DEFAULT_THEME; + // Ensure selectedTheme is either DARK or LIGHT: + if (selectedTheme !== THEME_NAMES.LIGHT) selectedTheme = THEME_NAMES.DARK; + + // Get the Mui theme object for the selected theme: const theme = useAppThemeObject(selectedTheme); return ( @@ -51,14 +56,23 @@ const withCustomThemeProvider = (): DecoratorFunction => { * but counter-intuitively, _higher_ index decorators wrap _lower_ index decorators. */ export const globalDecorators: Array> = [ + // ThemeProvider + withCustomThemeProvider(), + + // GoogleOAuthContextProvider + (Story) => ( + + + + ), + // DateTimeLocalizationProvider (Story) => ( ), - // ThemeProvider - withCustomThemeProvider(), + // PageLayoutContextProvider (Story) => ( diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html index d070af0a..d468a734 100644 --- a/.storybook/preview-head.html +++ b/.storybook/preview-head.html @@ -1,8 +1,10 @@ + + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b0e74e..7bd559ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,62 @@ All notable changes to this project will be documented in this file. --- +# [1.4.0-next.1](https://github.com/Nerdware-LLC/fixit-web/compare/v1.3.1...v1.4.0-next.1) (2024-03-24) + + +### Bug Fixes + +* add 'justifyContent:center' ([f8f8037](https://github.com/Nerdware-LLC/fixit-web/commit/f8f803773b68ad01f53a7e871cce655b444942cc)) +* add check ensuring afterTrialPriceStr is not null ([1f8c415](https://github.com/Nerdware-LLC/fixit-web/commit/1f8c4153a4aa43f318128e45a4319fbb7f3243a4)) +* add nullish fallback to 'value' ([9989c1b](https://github.com/Nerdware-LLC/fixit-web/commit/9989c1b2ac33f562cb353fe5c1dac9e5dc3e61fc)) +* correct accum typings for parsers+reducers ([3e744da](https://github.com/Nerdware-LLC/fixit-web/commit/3e744da4e682200c14918ed8223cab823775d378)) +* correct type-policy 'options.args' typings ([a9d1ebf](https://github.com/Nerdware-LLC/fixit-web/commit/a9d1ebf18da3d25325e97e3786aff536684a99f4)) +* impl logic checks for null phone values ([a499038](https://github.com/Nerdware-LLC/fixit-web/commit/a49903876434486ce95cbac405943ce2d2ad79f2)) +* mv all image imports into ProductImage for fast-refresh ([8947030](https://github.com/Nerdware-LLC/fixit-web/commit/894703099ed5d0b86e4a486c9d7958a1dc23abd3)) +* mv map key to Fragment ([7786f3d](https://github.com/Nerdware-LLC/fixit-web/commit/7786f3d2a62bee117c760425f6b658b6131f75e1)) +* rm clearing of checkoutValues ([212b3cf](https://github.com/Nerdware-LLC/fixit-web/commit/212b3cfb5979890f9a7437ddcdc73953a6271209)) +* rm extraneous 'as const' assertions ([2995812](https://github.com/Nerdware-LLC/fixit-web/commit/29958128d17002cf06e44d5cc5483c0261393169)) +* set axios.defaults.withCredentials only in deployed envs ([fed8071](https://github.com/Nerdware-LLC/fixit-web/commit/fed807156283860f78e7f04c689b54cf1e9b160f)) +* set redirect to /products if no active sub ([5c8319a](https://github.com/Nerdware-LLC/fixit-web/commit/5c8319a4491f17b7c7b096adffe9f3103bceb316)) +* update checks for null/falsey values ([5ce552b](https://github.com/Nerdware-LLC/fixit-web/commit/5ce552b4cd81299a44aaebba1a29901170d646c4)) +* update className to legalLinksRoot ([853bb7b](https://github.com/Nerdware-LLC/fixit-web/commit/853bb7b1732e0d2e5131c06b0885edaaaeafe2d0)) +* update DataDisplay exports ([69e94f5](https://github.com/Nerdware-LLC/fixit-web/commit/69e94f520ffcf9de07bbaccd73b11ec9aae628d1)) +* update global scrollbar className usage ([2202fec](https://github.com/Nerdware-LLC/fixit-web/commit/2202fec4e7d8aeac233ad18a23952e5bc4add1b4)) +* update import path to reflect Form/Inputs renaming ([eb2e5c8](https://github.com/Nerdware-LLC/fixit-web/commit/eb2e5c8594f2c54645d0de06a82bf04f48f40ff1)) +* update typing for Yup err msg fn ([fac9fc5](https://github.com/Nerdware-LLC/fixit-web/commit/fac9fc50f4f9290a1a33fc7ff28e7dd5dd25b439)) +* update usage of scrollbar.forceShowPaperBG ([fad8edf](https://github.com/Nerdware-LLC/fixit-web/commit/fad8edfda754c7baed4e4c5174e197d70a1a85e4)) + + +### Features + +* add 'long' labels and 'Cookies' ([b7ac57b](https://github.com/Nerdware-LLC/fixit-web/commit/b7ac57b39b303c6cba454c7b5a5c7003af8a32d1)) +* add APP_LINKS object w github repo url ([bd357be](https://github.com/Nerdware-LLC/fixit-web/commit/bd357bebeb942f1000adfc60252c8902a0e02551)) +* add authTokenUpdateAt storage feat ([328004e](https://github.com/Nerdware-LLC/fixit-web/commit/328004e90144297fd91326e53f5a9d292d5475b8)) +* add classNames for ClickToCopyText ([39fcc9c](https://github.com/Nerdware-LLC/fixit-web/commit/39fcc9c7ea3907e5d6c65bb5e9729745290b11a8)) +* add CloseIconButton comp ([8256d49](https://github.com/Nerdware-LLC/fixit-web/commit/8256d49c146345fb334062452ebde15f2bdfa909)) +* add CookiePolicyPage ([090c3ce](https://github.com/Nerdware-LLC/fixit-web/commit/090c3cee64c0017c0c503dcc7a3e9fea4d749a34)) +* add defaultSize, rename to reflect broader scope ([8f3ee71](https://github.com/Nerdware-LLC/fixit-web/commit/8f3ee7191ab58d75d824257615199cb97b6c8b92)) +* add DemoInfo component ([da09354](https://github.com/Nerdware-LLC/fixit-web/commit/da093546d74ffecec31bfefc5536d61cef17f333)) +* add DemoInfo components ([a3b068d](https://github.com/Nerdware-LLC/fixit-web/commit/a3b068d36342ba0c86c39e3dcce423697ead084b)) +* add DemoInfoDialog ([5cc138c](https://github.com/Nerdware-LLC/fixit-web/commit/5cc138ceb18a69d58577678a4cbf59e8d90898bb)) +* add DemoStripeCardInfoAccordion ([3de0011](https://github.com/Nerdware-LLC/fixit-web/commit/3de0011e276cd8ae6e2a24b4156bf50d8ae8d73d)) +* add DividerWithText comp ([6b0f531](https://github.com/Nerdware-LLC/fixit-web/commit/6b0f531b64d97d7114f46c994e4b35fb0698b28e)) +* add err-handling utils ([1b00dda](https://github.com/Nerdware-LLC/fixit-web/commit/1b00ddaffc2d66614f8caa0483276e0d60b6bbc3)) +* add footer to LandingPage ([8673ac4](https://github.com/Nerdware-LLC/fixit-web/commit/8673ac49151c57a57cc8418d9eea676dd5bb30d8)) +* add Google OAuth login feature ([fc028ff](https://github.com/Nerdware-LLC/fixit-web/commit/fc028ff2a9c90e2f37619f2f934a7bf17070837b)) +* add GoogleOAuth btns to Login+Register ([2422af1](https://github.com/Nerdware-LLC/fixit-web/commit/2422af196a9f4a83a4a337373cc3d971bd136c0b)) +* add GoogleOAuth types ([9515fd2](https://github.com/Nerdware-LLC/fixit-web/commit/9515fd224517583f39b2f05c905ef5980260928f)) +* add loginWithGoogleToken method ([fd68ac0](https://github.com/Nerdware-LLC/fixit-web/commit/fd68ac08d3dcd894d9b1ea38254498164ec9a54e)) +* add PolicyInfoTable comp ([5684609](https://github.com/Nerdware-LLC/fixit-web/commit/5684609a314c5181db92f1ccf2d870237d44ef11)) +* add root-app loading indicator to AppBarLogoButton ([9ad45cd](https://github.com/Nerdware-LLC/fixit-web/commit/9ad45cd40a56a5681aa50621b889aa2e783cff6d)) +* add type UseDialogHookProps ([43ea6a9](https://github.com/Nerdware-LLC/fixit-web/commit/43ea6a9a06529864346ea0c08a1d7d68bcd0f832)) +* centralize password and googleIDToken field schema ([83b079e](https://github.com/Nerdware-LLC/fixit-web/commit/83b079ef210c212aa6439841deffdf3cb19ee7b2)) +* impl new err-handling helpers ([2be61c8](https://github.com/Nerdware-LLC/fixit-web/commit/2be61c88806df6111265672f29b391532bfd3438)) +* replace old Title+Logo w the new one that has loading-spinner ([3e4f91b](https://github.com/Nerdware-LLC/fixit-web/commit/3e4f91bf54a65363faa2be09a256694885a3eed6)) +* rm 'to' prop, only do 'nav(-1)' ([14f0870](https://github.com/Nerdware-LLC/fixit-web/commit/14f0870ced4b722d841b51335913aa868099bff5)) +* rm unused userLogin makeFake util ([378e85b](https://github.com/Nerdware-LLC/fixit-web/commit/378e85b0bee914437a9576bf955845c09db010e0)) +* update gql schema doc ([c70ebc3](https://github.com/Nerdware-LLC/fixit-web/commit/c70ebc3dc577b89b32e27584bb07bafdc8b99d6e)) + ## [1.3.1](https://github.com/Nerdware-LLC/fixit-web/compare/v1.3.0...v1.3.1) (2024-03-10) ## [1.3.1-next.1](https://github.com/Nerdware-LLC/fixit-web/compare/v1.3.0...v1.3.1-next.1) (2024-03-10) diff --git a/eslint.config.js b/eslint.config.js index 09d1ebdf..3cdcf118 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -121,6 +121,16 @@ export default [ }, ], "@typescript-eslint/prefer-reduce-type-parameter": "off", + "@typescript-eslint/restrict-template-expressions": [ + "error", + { + allowAny: false, + allowBoolean: true, + allowNullish: false, + allowNumber: true, + allowRegExp: false, + }, + ], ...eslintConfigPrettier.rules, // <-- must be last, removes rules that conflict with prettier }, settings: { diff --git a/fixit@current.graphql b/fixit@current.graphql index 6e6ede07..bc970024 100644 --- a/fixit@current.graphql +++ b/fixit@current.graphql @@ -119,7 +119,7 @@ interface FixitUser { email: Email! """Phone number of either a User or Contact""" - phone: String! + phone: String """Profile object of either a User or Contact""" profile: Profile! @@ -161,7 +161,7 @@ type Contact implements FixitUser { email: Email! """Contact phone number""" - phone: String! + phone: String """Contact Profile object""" profile: Profile! @@ -298,8 +298,8 @@ type User implements FixitUser { """(Immutable) User's own email address""" email: Email! - """(Immutable) User's own phone number""" - phone: String! + """User's own phone number""" + phone: String """ (Mobile-Only) User's Expo push token, used to send push notifications to the User's mobile device @@ -482,11 +482,11 @@ type AuthTokenPayload { id: ID! handle: String! email: String! - phone: String! + phone: String profile: Profile! stripeCustomerID: String! subscription: AuthTokenPayloadSubscriptionInfo - stripeConnectAccount: AuthTokenPayloadStripeConnectAccountInfo! + stripeConnectAccount: AuthTokenPayloadStripeConnectAccountInfo createdAt: DateTime! updatedAt: DateTime! } diff --git a/index.html b/index.html index 85f7ad95..fff10ab9 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ + Fixit + + + + + + - Fixit + + - + + + diff --git a/package-lock.json b/package-lock.json index 23acf3d4..afe87de8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "fixit-web", - "version": "1.3.1", + "version": "1.4.0-next.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fixit-web", - "version": "1.3.1", + "version": "1.4.0-next.1", "license": "LicenseRef-LICENSE", "dependencies": { "@apollo/client": "^3.9.4", @@ -16,7 +16,7 @@ "@mui/material": "^5.13.6", "@mui/x-data-grid": "^6.9.1", "@mui/x-date-pickers": "^6.9.1", - "@nerdware/ts-string-helpers": "^1.1.2", + "@nerdware/ts-string-helpers": "^1.2.1", "@nerdware/ts-type-safety-utils": "^1.0.8", "@sentry/react": "^7.57.0", "@stripe/react-stripe-js": "^2.4.0", @@ -26,7 +26,7 @@ "chart.js": "^4.3.0", "chartjs-adapter-dayjs-4": "^1.0.4", "dayjs": "^1.11.8", - "formik": "^2.4.2", + "formik": "^2.4.5", "graphql": "^16.8.1", "jwt-decode": "^4.0.0", "lodash.merge": "^4.6.2", @@ -168,9 +168,9 @@ } }, "node_modules/@apollo/client": { - "version": "3.9.6", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.9.6.tgz", - "integrity": "sha512-+zpddcnZ4G2VZ0xIEnvIHFsLqeopNOnWuE2ZVbRuetLLpj/biLPNN719B/iofdd1/iHRclKfv0XaAmX6PBhYKA==", + "version": "3.9.8", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.9.8.tgz", + "integrity": "sha512-ausPftEb2xAUkZqz+VkSSIhNxKraShJXdV2/NJ7JbHAAciGsFlapGtZ++b7lF0/+3Jp/p34g/i6dvO8b4WjQig==", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@wry/caches": "^1.0.0", @@ -401,105 +401,41 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz", - "integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.0", - "@babel/parser": "^7.24.0", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.0", + "@babel/traverse": "^7.24.1", "@babel/types": "^7.24.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -522,14 +458,14 @@ "dev": true }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", "dev": true, "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -577,9 +513,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.0.tgz", - "integrity": "sha512-QAH+vfvts51BCsNZ2PhY6HAggnlS6omLLFTsIpeqZk/MmJ6cW7tgz5yRv0fMJThcr6FmbMrENh1RgrWPTYA76g==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz", + "integrity": "sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", @@ -587,7 +523,7 @@ "@babel/helper-function-name": "^7.23.0", "@babel/helper-member-expression-to-functions": "^7.23.0", "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", "semver": "^6.3.1" @@ -617,9 +553,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.0.tgz", - "integrity": "sha512-efwOM90nCG6YeT8o3PCyBVSxRfmILxCNL+TNI8CGQl7a62M0Wd9VkV+XHwIlkOz1r4b+lxu6gBjdWiOMdUCrCQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", + "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -679,11 +615,11 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -747,13 +683,13 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", + "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-member-expression-to-functions": "^7.23.0", "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { @@ -800,9 +736,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "engines": { "node": ">=6.9.0" } @@ -839,13 +775,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz", - "integrity": "sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", "dev": true, "dependencies": { "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.0", + "@babel/traverse": "^7.24.1", "@babel/types": "^7.24.0" }, "engines": { @@ -853,13 +789,14 @@ } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -930,9 +867,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", - "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -942,12 +879,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", - "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", + "integrity": "sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -957,14 +894,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", - "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz", + "integrity": "sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.23.3" + "@babel/plugin-transform-optional-chaining": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -974,13 +911,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", - "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz", + "integrity": "sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1114,12 +1051,12 @@ } }, "node_modules/@babel/plugin-syntax-flow": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.23.3.tgz", - "integrity": "sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz", + "integrity": "sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1129,12 +1066,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", - "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", + "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1144,12 +1081,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", - "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz", + "integrity": "sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1183,12 +1120,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1300,12 +1237,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1331,12 +1268,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", - "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", + "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1346,13 +1283,13 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", - "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz", + "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-remap-async-to-generator": "^7.22.20", "@babel/plugin-syntax-async-generators": "^7.8.4" }, @@ -1364,13 +1301,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", - "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", + "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-module-imports": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-remap-async-to-generator": "^7.22.20" }, "engines": { @@ -1381,12 +1318,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", - "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", + "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1396,12 +1333,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", - "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.1.tgz", + "integrity": "sha512-h71T2QQvDgM2SmT29UYU6ozjMlAt7s7CSs5Hvy8f8cf/GM/Z4a2zMfN+fjVGaieeCrXR3EdQl6C4gQG+OgmbKw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1411,13 +1348,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", - "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz", + "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1427,13 +1364,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", - "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.1.tgz", + "integrity": "sha512-FUHlKCn6J3ERiu8Dv+4eoz7w8+kFLSyeVG4vDAikwADGjUCoHw/JHokyGtr8OR4UjpwPVivyF+h8Q5iv/JmrtA==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -1444,17 +1381,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", - "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz", + "integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, @@ -1475,13 +1412,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", - "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", + "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.15" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/template": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1491,12 +1428,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", - "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", + "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1506,13 +1443,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", - "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz", + "integrity": "sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1522,12 +1459,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", - "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz", + "integrity": "sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1537,12 +1474,12 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", - "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz", + "integrity": "sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -1553,13 +1490,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", - "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", + "integrity": "sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==", "dev": true, "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1569,12 +1506,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", - "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz", + "integrity": "sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -1585,13 +1522,13 @@ } }, "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.23.3.tgz", - "integrity": "sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.1.tgz", + "integrity": "sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-flow": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-flow": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1601,12 +1538,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", - "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", + "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { @@ -1617,14 +1554,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", - "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", + "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1634,12 +1571,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", - "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz", + "integrity": "sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -1650,12 +1587,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", - "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", + "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1665,12 +1602,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", - "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz", + "integrity": "sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -1681,12 +1618,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", - "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", + "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1696,13 +1633,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", - "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz", + "integrity": "sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1712,13 +1649,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-simple-access": "^7.22.5" }, "engines": { @@ -1729,14 +1666,14 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", - "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz", + "integrity": "sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==", "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { @@ -1747,13 +1684,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", - "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz", + "integrity": "sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1779,12 +1716,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", - "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz", + "integrity": "sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1794,12 +1731,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", - "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz", + "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -1810,12 +1747,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", - "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz", + "integrity": "sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -1826,16 +1763,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.0.tgz", - "integrity": "sha512-y/yKMm7buHpFFXfxVFS4Vk1ToRJDilIa6fKRioB9Vjichv58TDGXTvqV0dN7plobAmTW5eSEGXDngE+Mm+uO+w==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz", + "integrity": "sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.5", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.23.3" + "@babel/plugin-transform-parameters": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1845,13 +1781,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", - "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", + "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-replace-supers": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1861,12 +1797,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", - "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz", + "integrity": "sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -1877,12 +1813,12 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", - "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz", + "integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, @@ -1894,12 +1830,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", - "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", + "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1909,13 +1845,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", - "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", + "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1925,14 +1861,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", + "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1943,12 +1879,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", - "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", + "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1958,12 +1894,12 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz", - "integrity": "sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz", + "integrity": "sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1992,12 +1928,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", - "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz", + "integrity": "sha512-kDJgnPujTmAZ/9q2CN4m2/lRsUUPDvsG3+tSHWUJIzMGTt5U/b/fwWd3RO3n+5mjLrsBrVa5eKFRVSQbi3dF1w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2007,12 +1943,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", - "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.1.tgz", + "integrity": "sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2022,12 +1958,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", - "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz", + "integrity": "sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "regenerator-transform": "^0.15.2" }, "engines": { @@ -2038,12 +1974,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", - "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz", + "integrity": "sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2053,12 +1989,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", - "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", + "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2068,12 +2004,12 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", - "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", + "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { @@ -2084,12 +2020,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", - "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz", + "integrity": "sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2099,12 +2035,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", - "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", + "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2114,12 +2050,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", - "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz", + "integrity": "sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2129,15 +2065,15 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", - "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.1.tgz", + "integrity": "sha512-liYSESjX2fZ7JyBFkYG78nfvHlMKE6IpNdTVnxmlYUR+j5ZLsitFbaAE+eJSK2zPPkNWNw4mXL51rQ8WrvdK0w==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.23.3" + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-typescript": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -2147,12 +2083,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", - "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz", + "integrity": "sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2162,13 +2098,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", - "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz", + "integrity": "sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2178,13 +2114,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", - "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz", + "integrity": "sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2194,13 +2130,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", - "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz", + "integrity": "sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2210,26 +2146,26 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.0.tgz", - "integrity": "sha512-ZxPEzV9IgvGn73iK0E6VB9/95Nd7aMFpbE0l8KQFDG70cOV9IxRP7Y2FUPmlK0v6ImlLqYX50iuZ3ZTVhOF2lA==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.3.tgz", + "integrity": "sha512-fSk430k5c2ff8536JcPvPWK4tZDwehWLGlBp0wrsBUjZVdeQV6lePbwKWZaZfK2vnh/1kQX1PzAJWsnBmVgGJA==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.5", + "@babel/compat-data": "^7.24.1", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.23.3", - "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-assertions": "^7.24.1", + "@babel/plugin-syntax-import-attributes": "^7.24.1", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -2241,58 +2177,58 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.23.3", - "@babel/plugin-transform-async-generator-functions": "^7.23.9", - "@babel/plugin-transform-async-to-generator": "^7.23.3", - "@babel/plugin-transform-block-scoped-functions": "^7.23.3", - "@babel/plugin-transform-block-scoping": "^7.23.4", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-class-static-block": "^7.23.4", - "@babel/plugin-transform-classes": "^7.23.8", - "@babel/plugin-transform-computed-properties": "^7.23.3", - "@babel/plugin-transform-destructuring": "^7.23.3", - "@babel/plugin-transform-dotall-regex": "^7.23.3", - "@babel/plugin-transform-duplicate-keys": "^7.23.3", - "@babel/plugin-transform-dynamic-import": "^7.23.4", - "@babel/plugin-transform-exponentiation-operator": "^7.23.3", - "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.6", - "@babel/plugin-transform-function-name": "^7.23.3", - "@babel/plugin-transform-json-strings": "^7.23.4", - "@babel/plugin-transform-literals": "^7.23.3", - "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", - "@babel/plugin-transform-member-expression-literals": "^7.23.3", - "@babel/plugin-transform-modules-amd": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-modules-systemjs": "^7.23.9", - "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-arrow-functions": "^7.24.1", + "@babel/plugin-transform-async-generator-functions": "^7.24.3", + "@babel/plugin-transform-async-to-generator": "^7.24.1", + "@babel/plugin-transform-block-scoped-functions": "^7.24.1", + "@babel/plugin-transform-block-scoping": "^7.24.1", + "@babel/plugin-transform-class-properties": "^7.24.1", + "@babel/plugin-transform-class-static-block": "^7.24.1", + "@babel/plugin-transform-classes": "^7.24.1", + "@babel/plugin-transform-computed-properties": "^7.24.1", + "@babel/plugin-transform-destructuring": "^7.24.1", + "@babel/plugin-transform-dotall-regex": "^7.24.1", + "@babel/plugin-transform-duplicate-keys": "^7.24.1", + "@babel/plugin-transform-dynamic-import": "^7.24.1", + "@babel/plugin-transform-exponentiation-operator": "^7.24.1", + "@babel/plugin-transform-export-namespace-from": "^7.24.1", + "@babel/plugin-transform-for-of": "^7.24.1", + "@babel/plugin-transform-function-name": "^7.24.1", + "@babel/plugin-transform-json-strings": "^7.24.1", + "@babel/plugin-transform-literals": "^7.24.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", + "@babel/plugin-transform-member-expression-literals": "^7.24.1", + "@babel/plugin-transform-modules-amd": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-modules-systemjs": "^7.24.1", + "@babel/plugin-transform-modules-umd": "^7.24.1", "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.23.3", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", - "@babel/plugin-transform-numeric-separator": "^7.23.4", - "@babel/plugin-transform-object-rest-spread": "^7.24.0", - "@babel/plugin-transform-object-super": "^7.23.3", - "@babel/plugin-transform-optional-catch-binding": "^7.23.4", - "@babel/plugin-transform-optional-chaining": "^7.23.4", - "@babel/plugin-transform-parameters": "^7.23.3", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-property-literals": "^7.23.3", - "@babel/plugin-transform-regenerator": "^7.23.3", - "@babel/plugin-transform-reserved-words": "^7.23.3", - "@babel/plugin-transform-shorthand-properties": "^7.23.3", - "@babel/plugin-transform-spread": "^7.23.3", - "@babel/plugin-transform-sticky-regex": "^7.23.3", - "@babel/plugin-transform-template-literals": "^7.23.3", - "@babel/plugin-transform-typeof-symbol": "^7.23.3", - "@babel/plugin-transform-unicode-escapes": "^7.23.3", - "@babel/plugin-transform-unicode-property-regex": "^7.23.3", - "@babel/plugin-transform-unicode-regex": "^7.23.3", - "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/plugin-transform-new-target": "^7.24.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", + "@babel/plugin-transform-numeric-separator": "^7.24.1", + "@babel/plugin-transform-object-rest-spread": "^7.24.1", + "@babel/plugin-transform-object-super": "^7.24.1", + "@babel/plugin-transform-optional-catch-binding": "^7.24.1", + "@babel/plugin-transform-optional-chaining": "^7.24.1", + "@babel/plugin-transform-parameters": "^7.24.1", + "@babel/plugin-transform-private-methods": "^7.24.1", + "@babel/plugin-transform-private-property-in-object": "^7.24.1", + "@babel/plugin-transform-property-literals": "^7.24.1", + "@babel/plugin-transform-regenerator": "^7.24.1", + "@babel/plugin-transform-reserved-words": "^7.24.1", + "@babel/plugin-transform-shorthand-properties": "^7.24.1", + "@babel/plugin-transform-spread": "^7.24.1", + "@babel/plugin-transform-sticky-regex": "^7.24.1", + "@babel/plugin-transform-template-literals": "^7.24.1", + "@babel/plugin-transform-typeof-symbol": "^7.24.1", + "@babel/plugin-transform-unicode-escapes": "^7.24.1", + "@babel/plugin-transform-unicode-property-regex": "^7.24.1", + "@babel/plugin-transform-unicode-regex": "^7.24.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.1", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.8", - "babel-plugin-polyfill-corejs3": "^0.9.0", - "babel-plugin-polyfill-regenerator": "^0.5.5", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", "core-js-compat": "^3.31.0", "semver": "^6.3.1" }, @@ -2304,14 +2240,14 @@ } }, "node_modules/@babel/preset-flow": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.0.tgz", - "integrity": "sha512-cum/nSi82cDaSJ21I4PgLTVlj0OXovFk6GRguJYe/IKg6y6JHLTbJhybtX4k35WT9wdeJfEVjycTixMhBHd0Dg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.1.tgz", + "integrity": "sha512-sWCV2G9pcqZf+JHyv/RyqEIpFypxdCSxWIxQjpdaQxenNog7cN1pr76hg8u0Fz8Qgg0H4ETkGcJnXL8d4j0PPA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-transform-flow-strip-types": "^7.23.3" + "@babel/plugin-transform-flow-strip-types": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -2335,16 +2271,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz", + "integrity": "sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-syntax-jsx": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-typescript": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -2507,9 +2443,9 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", - "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", + "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2532,18 +2468,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", - "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.0", + "@babel/parser": "^7.24.1", "@babel/types": "^7.24.0", "debug": "^4.3.1", "globals": "^11.1.0" @@ -2761,9 +2697,9 @@ "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", "cpu": [ "ppc64" ], @@ -3175,16 +3111,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -3200,18 +3126,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -3565,9 +3479,9 @@ } }, "node_modules/@graphql-tools/apollo-engine-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.7.tgz", - "integrity": "sha512-YZA+N3JcW1eh2QRi7o/ij+M07M0dqID73ltgsOEMRyEc2UYVDbyomaih+CWCEZqBIDHw4KMDveXvv4SBZ4TLIw==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.9.tgz", + "integrity": "sha512-LvPUGIF0PqO9JGkXq2J871YRU4Ivsf5inq6DH7Hq1omip3beDXNuNQGwLxi7/UTZvp6QFKvk2X4lM+J4FDk6xg==", "dev": true, "dependencies": { "@kamilkisiela/fast-url-parser": "^1.1.4", @@ -3660,12 +3574,12 @@ } }, "node_modules/@graphql-tools/executor": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-1.2.1.tgz", - "integrity": "sha512-BP5UI1etbNOXmTSt7q4NL1+zsURFgh2pG+Hyt9K/xO0LlsfbSx59L5dHLerqZP7Js0xI6GYqrUQ4m29rUwUHJg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-1.2.3.tgz", + "integrity": "sha512-aAS+TGjSq8BJuDq1RV/A/8E53Iu3KvaWpD8DPio0Qe/0YF26tdpK6EcmNSGrrjiZOwVIZ80wclZrFstHzCPm8A==", "dev": true, "dependencies": { - "@graphql-tools/utils": "^10.0.13", + "@graphql-tools/utils": "^10.1.1", "@graphql-typed-document-node/core": "3.2.0", "@repeaterjs/repeater": "^3.0.4", "tslib": "^2.4.0", @@ -3742,9 +3656,9 @@ } }, "node_modules/@graphql-tools/executor-http/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.7.tgz", - "integrity": "sha512-YZA+N3JcW1eh2QRi7o/ij+M07M0dqID73ltgsOEMRyEc2UYVDbyomaih+CWCEZqBIDHw4KMDveXvv4SBZ4TLIw==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.9.tgz", + "integrity": "sha512-LvPUGIF0PqO9JGkXq2J871YRU4Ivsf5inq6DH7Hq1omip3beDXNuNQGwLxi7/UTZvp6QFKvk2X4lM+J4FDk6xg==", "dev": true, "dependencies": { "@kamilkisiela/fast-url-parser": "^1.1.4", @@ -3846,9 +3760,9 @@ } }, "node_modules/@graphql-tools/github-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.7.tgz", - "integrity": "sha512-YZA+N3JcW1eh2QRi7o/ij+M07M0dqID73ltgsOEMRyEc2UYVDbyomaih+CWCEZqBIDHw4KMDveXvv4SBZ4TLIw==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.9.tgz", + "integrity": "sha512-LvPUGIF0PqO9JGkXq2J871YRU4Ivsf5inq6DH7Hq1omip3beDXNuNQGwLxi7/UTZvp6QFKvk2X4lM+J4FDk6xg==", "dev": true, "dependencies": { "@kamilkisiela/fast-url-parser": "^1.1.4", @@ -4046,9 +3960,9 @@ } }, "node_modules/@graphql-tools/prisma-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.7.tgz", - "integrity": "sha512-YZA+N3JcW1eh2QRi7o/ij+M07M0dqID73ltgsOEMRyEc2UYVDbyomaih+CWCEZqBIDHw4KMDveXvv4SBZ4TLIw==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.9.tgz", + "integrity": "sha512-LvPUGIF0PqO9JGkXq2J871YRU4Ivsf5inq6DH7Hq1omip3beDXNuNQGwLxi7/UTZvp6QFKvk2X4lM+J4FDk6xg==", "dev": true, "dependencies": { "@kamilkisiela/fast-url-parser": "^1.1.4", @@ -4152,9 +4066,9 @@ } }, "node_modules/@graphql-tools/url-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.7.tgz", - "integrity": "sha512-YZA+N3JcW1eh2QRi7o/ij+M07M0dqID73ltgsOEMRyEc2UYVDbyomaih+CWCEZqBIDHw4KMDveXvv4SBZ4TLIw==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.9.tgz", + "integrity": "sha512-LvPUGIF0PqO9JGkXq2J871YRU4Ivsf5inq6DH7Hq1omip3beDXNuNQGwLxi7/UTZvp6QFKvk2X4lM+J4FDk6xg==", "dev": true, "dependencies": { "@kamilkisiela/fast-url-parser": "^1.1.4", @@ -4174,9 +4088,9 @@ "dev": true }, "node_modules/@graphql-tools/utils": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.1.0.tgz", - "integrity": "sha512-wLPqhgeZ9BZJPRoaQbsDN/CtJDPd/L4qmmtPkjI3NuYJ39x+Eqz1Sh34EAGMuDh+xlOHqBwHczkZUpoK9tvzjw==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.1.2.tgz", + "integrity": "sha512-fX13CYsDnX4yifIyNdiN0cVygz/muvkreWWem6BBw130+ODbRRgfiVveL0NizCEnKXkpvdeTy9Bxvo9LIKlhrw==", "dev": true, "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", @@ -4192,14 +4106,14 @@ } }, "node_modules/@graphql-tools/wrap": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-10.0.2.tgz", - "integrity": "sha512-nb/YjBcyF02KBCy3hiyw0nBKIC+qkiDY/tGMCcIe4pM6BPEcnreaPhXA28Rdge7lKtySF4Mhbc86XafFH5bIkQ==", + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-10.0.5.tgz", + "integrity": "sha512-Cbr5aYjr3HkwdPvetZp1cpDWTGdD1Owgsb3z/ClzhmrboiK86EnQDxDvOJiQkDCPWE9lNBwj8Y4HfxroY0D9DQ==", "dev": true, "dependencies": { "@graphql-tools/delegate": "^10.0.4", "@graphql-tools/schema": "^10.0.3", - "@graphql-tools/utils": "^10.0.13", + "@graphql-tools/utils": "^10.1.1", "tslib": "^2.4.0", "value-or-promise": "^1.0.12" }, @@ -4247,28 +4161,6 @@ "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -4737,6 +4629,20 @@ "node": ">=10" } }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@jest/reporters/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4764,6 +4670,15 @@ "node": ">=10" } }, + "node_modules/@jest/reporters/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@jest/reporters/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4991,14 +4906,14 @@ } }, "node_modules/@mui/base": { - "version": "5.0.0-beta.38", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.38.tgz", - "integrity": "sha512-AsjD6Y1X5A1qndxz8xCcR8LDqv31aiwlgWMPxFAX/kCKiIGKlK65yMeVZ62iQr/6LBz+9hSKLiD1i4TZdAHKcQ==", + "version": "5.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", + "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", "dependencies": { "@babel/runtime": "^7.23.9", "@floating-ui/react-dom": "^2.0.8", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.12", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", "@popperjs/core": "^2.11.8", "clsx": "^2.1.0", "prop-types": "^15.8.1" @@ -5022,18 +4937,18 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.12", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.12.tgz", - "integrity": "sha512-brRO+tMFLpGyjEYHrX97bzqeF6jZmKpqqe1rY0LyIHAwP6xRVzh++zSecOQorDOCaZJg4XkGT9xfD+RWOWxZBA==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.14.tgz", + "integrity": "sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { - "version": "5.15.12", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.12.tgz", - "integrity": "sha512-3BXiDlOd3AexZoEXa/VqpIpVIvosCzjLHsdMWzKMXbZdnBiJjmb9ECdqfjn5SpTClO49qvkKLhkTqdBH3fSFGw==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.14.tgz", + "integrity": "sha512-vj/51k7MdFmt+XVw94sl30SCvGx6+wJLsNYjZRgxhS6y3UtnWnypMOsm3Kmg8TN+P0dqwsjy4/fX7B1HufJIhw==", "dependencies": { "@babel/runtime": "^7.23.9" }, @@ -5056,16 +4971,16 @@ } }, "node_modules/@mui/material": { - "version": "5.15.12", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.12.tgz", - "integrity": "sha512-vXJGg6KNKucsvbW6l7w9zafnpOp0CWc0Wx4mDykuABTpQ5QQBnZxP7+oB4yAS1hDZQ1WobbeIl0CjxK4EEahkA==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.14.tgz", + "integrity": "sha512-kEbRw6fASdQ1SQ7LVdWR5OlWV3y7Y54ZxkLzd6LV5tmz+NpO3MJKZXSfgR0LHMP7meKsPiMm4AuzV0pXDpk/BQ==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/base": "5.0.0-beta.38", - "@mui/core-downloads-tracker": "^5.15.12", - "@mui/system": "^5.15.12", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.12", + "@mui/base": "5.0.0-beta.40", + "@mui/core-downloads-tracker": "^5.15.14", + "@mui/system": "^5.15.14", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", "@types/react-transition-group": "^4.4.10", "clsx": "^2.1.0", "csstype": "^3.1.3", @@ -5100,12 +5015,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.15.12", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.12.tgz", - "integrity": "sha512-cqoSo9sgA5HE+8vZClbLrq9EkyOnYysooepi5eKaKvJ41lReT2c5wOZAeDDM1+xknrMDos+0mT2zr3sZmUiRRA==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz", + "integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.15.12", + "@mui/utils": "^5.15.14", "prop-types": "^15.8.1" }, "engines": { @@ -5126,9 +5041,9 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.15.11", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.11.tgz", - "integrity": "sha512-So21AhAngqo07ces4S/JpX5UaMU2RHXpEA6hNzI6IQjd/1usMPxpgK8wkGgTe3JKmC2KDmH8cvoycq5H3Ii7/w==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz", + "integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==", "dependencies": { "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.11.0", @@ -5157,15 +5072,15 @@ } }, "node_modules/@mui/system": { - "version": "5.15.12", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.12.tgz", - "integrity": "sha512-/pq+GO6yN3X7r3hAwFTrzkAh7K1bTF5r8IzS79B9eyKJg7v6B/t4/zZYMR6OT9qEPtwf6rYN2Utg1e6Z7F1OgQ==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.14.tgz", + "integrity": "sha512-auXLXzUaCSSOLqJXmsAaq7P96VPRXg2Rrz6OHNV7lr+kB8lobUF+/N84Vd9C4G/wvCXYPs5TYuuGBRhcGbiBGg==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.15.12", - "@mui/styled-engine": "^5.15.11", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.12", + "@mui/private-theming": "^5.15.14", + "@mui/styled-engine": "^5.15.14", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", "clsx": "^2.1.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -5196,9 +5111,9 @@ } }, "node_modules/@mui/types": { - "version": "7.2.13", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.13.tgz", - "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz", + "integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0" }, @@ -5209,9 +5124,9 @@ } }, "node_modules/@mui/utils": { - "version": "5.15.12", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.12.tgz", - "integrity": "sha512-8SDGCnO2DY9Yy+5bGzu00NZowSDtuyHP4H8gunhHGQoIlhlY2Z3w64wBzAOLpYw/ZhJNzksDTnS/i8qdJvxuow==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz", + "integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==", "dependencies": { "@babel/runtime": "^7.23.9", "@types/prop-types": "^15.7.11", @@ -5236,9 +5151,9 @@ } }, "node_modules/@mui/x-data-grid": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.19.6.tgz", - "integrity": "sha512-jpZkX1Gnlo87gKcD10mKMY8YoAzUD8Cv3/IvedH3FINDKO3hnraMeOciKDeUk0tYSj8RUDB02kpTHCM8ojLVBA==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.19.8.tgz", + "integrity": "sha512-QsOW9GhJdhvagJfUb5jpZE1MMaCLugxx0l89amxJAthMia95BlGS7jndiDEh8IQNthgzfxjAzrSv8GZpcgSEaA==", "dependencies": { "@babel/runtime": "^7.23.2", "@mui/utils": "^5.14.16", @@ -5261,9 +5176,9 @@ } }, "node_modules/@mui/x-date-pickers": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.19.6.tgz", - "integrity": "sha512-QW9AFcPi0vLpkUhmquhhyhLaBvB0AZJuu3NTrE173qNKx3Z3n51aCLY9bc7c6i4ltZMMsVRHlvzQjsve04TC8A==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.19.8.tgz", + "integrity": "sha512-6wgc2DoRTR9/mKesku4CVCKr9yYkY3FI2Oy/wshLTs2rFkw2Z10uxXFHBR9ugEtNPNCQv0qqwldElenYI97wsA==", "dependencies": { "@babel/runtime": "^7.23.2", "@mui/base": "^5.0.0-beta.22", @@ -5337,9 +5252,9 @@ } }, "node_modules/@nerdware/ts-string-helpers": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@nerdware/ts-string-helpers/-/ts-string-helpers-1.1.2.tgz", - "integrity": "sha512-wT8w3LxxdWT5OKgOeRrDzBFGAd6U7pD0Hva+dzqRoau8ehNBky0JPXZjdCA+BdBS+ccikRfs1xN+nabQcUg7nA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@nerdware/ts-string-helpers/-/ts-string-helpers-1.2.1.tgz", + "integrity": "sha512-0tBzMjXZbevJk7sWQd6gIUCuxCmfDQHuUXQWoXToRhKMYzx3mBPKFBmiOvkRr0mf5Ix5w3cIagPZIw7K2+vB1Q==", "engines": { "node": ">=16.0.0", "npm": ">=8.0.0" @@ -5480,6 +5395,15 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@npmcli/map-workspaces/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@npmcli/map-workspaces/node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -5518,6 +5442,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@npmcli/map-workspaces/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -5540,9 +5479,9 @@ } }, "node_modules/@oclif/core": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-3.23.0.tgz", - "integrity": "sha512-giQ/8Ft8yXWg4IyPVtynPb7ihoQsa3A/1Q53UIJIhh+8k+EedE3lJ01yn6sq6Ha35IGqsG1WhkeHzlJIuldEaw==", + "version": "3.25.3", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-3.25.3.tgz", + "integrity": "sha512-2TLZmqnDZos9h73KbrdKqvUQEXIPpUfEzgIfqdQRZwszfk1RtiHAb/7ihtnJICnRRVXlD4XLDmUlY4cFJ0ka4g==", "dev": true, "dependencies": { "@types/cli-progress": "^3.11.5", @@ -5587,6 +5526,15 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/@oclif/core/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@oclif/core/node_modules/clean-stack": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz", @@ -5615,6 +5563,21 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/@oclif/core/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@oclif/core/node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -5677,13 +5640,13 @@ } }, "node_modules/@oclif/plugin-help": { - "version": "6.0.17", - "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-6.0.17.tgz", - "integrity": "sha512-zHKRQf/SkaOyF8xwz9EJxQ4bsB9bK+ED+i0YF24dud/1DkTj5cEDvrNV6sj+YH34ONz7z4et230URdFM3SJKeQ==", + "version": "6.0.18", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-6.0.18.tgz", + "integrity": "sha512-Ly0gu/+eq7GfIMT76cirbHgElYGlu+PaZ5elrAKmDiegBh31AXqaPQAj8PH4+sG8RSv5srYtrkrygZaw8IF9CQ==", "dev": true, "hasShrinkwrap": true, "dependencies": { - "@oclif/core": "^3.21.0" + "@oclif/core": "^3.23.0" }, "engines": { "node": ">=18.0.0" @@ -9543,9 +9506,9 @@ } }, "node_modules/@oclif/plugin-help/node_modules/@oclif/core": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-3.21.0.tgz", - "integrity": "sha512-xR7qGPOWtOnYmdYocSn6oEh2oTQLsPOXoj3HYGpb26V3WulwF8Cm33WPnMsSISv4ben3Rtc5i59u9O5NnuG42g==", + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-3.23.0.tgz", + "integrity": "sha512-giQ/8Ft8yXWg4IyPVtynPb7ihoQsa3A/1Q53UIJIhh+8k+EedE3lJ01yn6sq6Ha35IGqsG1WhkeHzlJIuldEaw==", "dev": true, "license": "MIT", "dependencies": { @@ -9565,6 +9528,7 @@ "indent-string": "^4.0.0", "is-wsl": "^2.2.0", "js-yaml": "^3.14.1", + "minimatch": "^9.0.3", "natural-orderby": "^2.0.3", "object-treeify": "^1.1.33", "password-prompt": "^1.1.3", @@ -9605,6 +9569,22 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/@oclif/plugin-help/node_modules/@oclif/core/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@oclif/plugin-help/node_modules/@oclif/core/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -9634,85 +9614,6 @@ "node": ">=18.0.0" } }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-help/node_modules/@oclif/core": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-3.20.0.tgz", - "integrity": "sha512-8BajhglY8frYGAS1whAukeouFZUN9MgQoLfNXtScPVEAjPlaD2BbSIAYQH2yF2qb/iVvbj/1DwYS3gqicYOq1A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/cli-progress": "^3.11.5", - "ansi-escapes": "^4.3.2", - "ansi-styles": "^4.3.0", - "cardinal": "^2.1.1", - "chalk": "^4.1.2", - "clean-stack": "^3.0.1", - "cli-progress": "^3.12.0", - "color": "^4.2.3", - "debug": "^4.3.4", - "ejs": "^3.1.9", - "get-package-type": "^0.1.0", - "globby": "^11.1.0", - "hyperlinker": "^1.0.0", - "indent-string": "^4.0.0", - "is-wsl": "^2.2.0", - "js-yaml": "^3.14.1", - "natural-orderby": "^2.0.3", - "object-treeify": "^1.1.33", - "password-prompt": "^1.1.3", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "supports-color": "^8.1.1", - "supports-hyperlinks": "^2.2.0", - "widest-line": "^3.1.0", - "wordwrap": "^1.0.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-help/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-help/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-help/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-not-found": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-3.0.10.tgz", @@ -9728,85 +9629,6 @@ "node": ">=18.0.0" } }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-not-found/node_modules/@oclif/core": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-3.20.0.tgz", - "integrity": "sha512-8BajhglY8frYGAS1whAukeouFZUN9MgQoLfNXtScPVEAjPlaD2BbSIAYQH2yF2qb/iVvbj/1DwYS3gqicYOq1A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/cli-progress": "^3.11.5", - "ansi-escapes": "^4.3.2", - "ansi-styles": "^4.3.0", - "cardinal": "^2.1.1", - "chalk": "^4.1.2", - "clean-stack": "^3.0.1", - "cli-progress": "^3.12.0", - "color": "^4.2.3", - "debug": "^4.3.4", - "ejs": "^3.1.9", - "get-package-type": "^0.1.0", - "globby": "^11.1.0", - "hyperlinker": "^1.0.0", - "indent-string": "^4.0.0", - "is-wsl": "^2.2.0", - "js-yaml": "^3.14.1", - "natural-orderby": "^2.0.3", - "object-treeify": "^1.1.33", - "password-prompt": "^1.1.3", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "supports-color": "^8.1.1", - "supports-hyperlinks": "^2.2.0", - "widest-line": "^3.1.0", - "wordwrap": "^1.0.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-not-found/node_modules/@oclif/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-not-found/node_modules/@oclif/core/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-not-found/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-not-found/node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -9830,36 +9652,6 @@ "fastest-levenshtein": "^1.0.7" } }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-not-found/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-not-found/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-warn-if-update-available": { "version": "3.0.12", "resolved": "https://registry.npmjs.org/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-3.0.12.tgz", @@ -9877,85 +9669,6 @@ "node": ">=18.0.0" } }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-warn-if-update-available/node_modules/@oclif/core": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-3.20.0.tgz", - "integrity": "sha512-8BajhglY8frYGAS1whAukeouFZUN9MgQoLfNXtScPVEAjPlaD2BbSIAYQH2yF2qb/iVvbj/1DwYS3gqicYOq1A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/cli-progress": "^3.11.5", - "ansi-escapes": "^4.3.2", - "ansi-styles": "^4.3.0", - "cardinal": "^2.1.1", - "chalk": "^4.1.2", - "clean-stack": "^3.0.1", - "cli-progress": "^3.12.0", - "color": "^4.2.3", - "debug": "^4.3.4", - "ejs": "^3.1.9", - "get-package-type": "^0.1.0", - "globby": "^11.1.0", - "hyperlinker": "^1.0.0", - "indent-string": "^4.0.0", - "is-wsl": "^2.2.0", - "js-yaml": "^3.14.1", - "natural-orderby": "^2.0.3", - "object-treeify": "^1.1.33", - "password-prompt": "^1.1.3", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "supports-color": "^8.1.1", - "supports-hyperlinks": "^2.2.0", - "widest-line": "^3.1.0", - "wordwrap": "^1.0.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-warn-if-update-available/node_modules/@oclif/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-warn-if-update-available/node_modules/@oclif/core/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-warn-if-update-available/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-warn-if-update-available/node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -9969,36 +9682,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-warn-if-update-available/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/plugin-warn-if-update-available/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/@oclif/plugin-help/node_modules/@oclif/prettier-config": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@oclif/prettier-config/-/prettier-config-0.2.1.tgz", @@ -10021,85 +9704,6 @@ "node": ">=18.0.0" } }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/test/node_modules/@oclif/core": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-3.20.0.tgz", - "integrity": "sha512-8BajhglY8frYGAS1whAukeouFZUN9MgQoLfNXtScPVEAjPlaD2BbSIAYQH2yF2qb/iVvbj/1DwYS3gqicYOq1A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/cli-progress": "^3.11.5", - "ansi-escapes": "^4.3.2", - "ansi-styles": "^4.3.0", - "cardinal": "^2.1.1", - "chalk": "^4.1.2", - "clean-stack": "^3.0.1", - "cli-progress": "^3.12.0", - "color": "^4.2.3", - "debug": "^4.3.4", - "ejs": "^3.1.9", - "get-package-type": "^0.1.0", - "globby": "^11.1.0", - "hyperlinker": "^1.0.0", - "indent-string": "^4.0.0", - "is-wsl": "^2.2.0", - "js-yaml": "^3.14.1", - "natural-orderby": "^2.0.3", - "object-treeify": "^1.1.33", - "password-prompt": "^1.1.3", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "supports-color": "^8.1.1", - "supports-hyperlinks": "^2.2.0", - "widest-line": "^3.1.0", - "wordwrap": "^1.0.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/test/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/test/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@oclif/plugin-help/node_modules/@oclif/test/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/@oclif/plugin-help/node_modules/@octokit/auth-token": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", @@ -12064,9 +11668,9 @@ "license": "MIT" }, "node_modules/@oclif/plugin-help/node_modules/@types/node": { - "version": "18.19.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.21.tgz", - "integrity": "sha512-2Q2NeB6BmiTFQi4DHBzncSoq/cJMLDdhPaAoJFnFCyD9a8VPZRf7a1GAwp1Edb7ROaZc5Jz/tnZyL6EsWMRaqw==", + "version": "18.19.22", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.22.tgz", + "integrity": "sha512-p3pDIfuMg/aXBmhkyanPshdfJuX5c5+bQjYLIikPLXAUycEogij/c50n/C+8XOA5L93cU4ZRXtn+dNQGi0IZqQ==", "extraneous": true, "license": "MIT", "dependencies": { @@ -12992,11 +12596,14 @@ } }, "node_modules/@oclif/plugin-help/node_modules/builtins": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", "extraneous": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "semver": "^7.0.0" + } }, "node_modules/@oclif/plugin-help/node_modules/cacache": { "version": "15.3.0", @@ -14581,15 +14188,15 @@ } }, "node_modules/@oclif/plugin-help/node_modules/eslint-config-oclif": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/eslint-config-oclif/-/eslint-config-oclif-5.0.3.tgz", - "integrity": "sha512-H3pvoSCfni23l81agc7/r8jxQ7bVIKNqbLsN8eYG8w2wEpsACskplK3VEPzIrO8NSFDcxQJIxoVXxp94kXexTA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-oclif/-/eslint-config-oclif-5.1.0.tgz", + "integrity": "sha512-T4pFAFV9g1hy797f817bzkBeQB0R9j3AShrI0ohfVecHU54GrzzOTFufh0Ex8bwb89un/NlF8TE5RTiy8SKURQ==", "extraneous": true, "license": "MIT", "dependencies": { "eslint-config-xo-space": "^0.35.0", "eslint-plugin-mocha": "^10.3.0", - "eslint-plugin-node": "^11.1.0", + "eslint-plugin-n": "^15.1.0", "eslint-plugin-unicorn": "^48.0.1" }, "engines": { @@ -14922,6 +14529,125 @@ "node": ">=10" } }, + "node_modules/@oclif/plugin-help/node_modules/eslint-plugin-n": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", + "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", + "extraneous": true, + "license": "MIT", + "dependencies": { + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.11.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/@oclif/plugin-help/node_modules/eslint-plugin-n/node_modules/eslint-plugin-es": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", + "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", + "extraneous": true, + "license": "MIT", + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/@oclif/plugin-help/node_modules/eslint-plugin-n/node_modules/eslint-plugin-es/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "extraneous": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/@oclif/plugin-help/node_modules/eslint-plugin-n/node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "extraneous": true, + "license": "Apache-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/eslint-plugin-n/node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "extraneous": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/@oclif/plugin-help/node_modules/eslint-plugin-n/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "extraneous": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/@oclif/plugin-help/node_modules/eslint-plugin-n/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "extraneous": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/@oclif/plugin-help/node_modules/eslint-plugin-node": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", @@ -19108,85 +18834,6 @@ "node": ">=18.0.0" } }, - "node_modules/@oclif/plugin-help/node_modules/oclif/node_modules/@oclif/core": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-3.20.0.tgz", - "integrity": "sha512-8BajhglY8frYGAS1whAukeouFZUN9MgQoLfNXtScPVEAjPlaD2BbSIAYQH2yF2qb/iVvbj/1DwYS3gqicYOq1A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/cli-progress": "^3.11.5", - "ansi-escapes": "^4.3.2", - "ansi-styles": "^4.3.0", - "cardinal": "^2.1.1", - "chalk": "^4.1.2", - "clean-stack": "^3.0.1", - "cli-progress": "^3.12.0", - "color": "^4.2.3", - "debug": "^4.3.4", - "ejs": "^3.1.9", - "get-package-type": "^0.1.0", - "globby": "^11.1.0", - "hyperlinker": "^1.0.0", - "indent-string": "^4.0.0", - "is-wsl": "^2.2.0", - "js-yaml": "^3.14.1", - "natural-orderby": "^2.0.3", - "object-treeify": "^1.1.33", - "password-prompt": "^1.1.3", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "supports-color": "^8.1.1", - "supports-hyperlinks": "^2.2.0", - "widest-line": "^3.1.0", - "wordwrap": "^1.0.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@oclif/plugin-help/node_modules/oclif/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@oclif/plugin-help/node_modules/oclif/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@oclif/plugin-help/node_modules/oclif/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/@oclif/plugin-help/node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -21747,9 +21394,9 @@ "license": "MIT" }, "node_modules/@oclif/plugin-help/node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "extraneous": true, "license": "Apache-2.0", "bin": { @@ -21905,6 +21552,13 @@ "builtins": "^1.0.3" } }, + "node_modules/@oclif/plugin-help/node_modules/validate-npm-package-name/node_modules/builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "extraneous": true, + "license": "MIT" + }, "node_modules/@oclif/plugin-help/node_modules/vinyl": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", @@ -23328,13 +22982,20 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, + "node_modules/@redocly/config": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.1.4.tgz", + "integrity": "sha512-OEdCW1HRpFiZaZNrXQq8LoBxX3APijZaa/Xyoc6r44LnyAPWkjQqvPoBxE7IRqSvMihf8bl+ZRc1gtc1KuFLHw==", + "dev": true + }, "node_modules/@redocly/openapi-core": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.10.3.tgz", - "integrity": "sha512-4SnIWh8r3EM1ylcoHIJSnQnuvqRTpQMnf2RU3BfVdcCBa0A1uEyH6XSxgcO5ehxfQGuGGpUXJ+vPh32PUaQDkA==", + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.10.5.tgz", + "integrity": "sha512-RaVwWLbGuzQxK6ezbvPGnz4rtVMTo5DOrxyII/sKJiTexBHplZzUVqrpU6aeRckl3iY9xe9+w07c/kDiLEeWRQ==", "dev": true, "dependencies": { "@redocly/ajv": "^8.11.0", + "@redocly/config": "^0.1.4", "colorette": "^1.2.0", "js-levenshtein": "^1.1.6", "js-yaml": "^4.1.0", @@ -23349,6 +23010,15 @@ "npm": ">=7.0.0" } }, + "node_modules/@redocly/openapi-core/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@redocly/openapi-core/node_modules/colorette": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", @@ -23410,9 +23080,9 @@ "dev": true }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.1.tgz", - "integrity": "sha512-iU2Sya8hNn1LhsYyf0N+L4Gf9Qc+9eBTJJJsaOGUp+7x4n2M9dxTt8UvhJl3oeftSjblSlpCfvjA/IfP3g5VjQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz", + "integrity": "sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==", "cpu": [ "arm" ], @@ -23423,9 +23093,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.1.tgz", - "integrity": "sha512-wlzcWiH2Ir7rdMELxFE5vuM7D6TsOcJ2Yw0c3vaBR3VOsJFVTx9xvwnAvhgU5Ii8Gd6+I11qNHwndDscIm0HXg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz", + "integrity": "sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==", "cpu": [ "arm64" ], @@ -23436,9 +23106,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.1.tgz", - "integrity": "sha512-YRXa1+aZIFN5BaImK+84B3uNK8C6+ynKLPgvn29X9s0LTVCByp54TB7tdSMHDR7GTV39bz1lOmlLDuedgTwwHg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz", + "integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==", "cpu": [ "arm64" ], @@ -23449,9 +23119,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.1.tgz", - "integrity": "sha512-opjWJ4MevxeA8FhlngQWPBOvVWYNPFkq6/25rGgG+KOy0r8clYwL1CFd+PGwRqqMFVQ4/Qd3sQu5t7ucP7C/Uw==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz", + "integrity": "sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==", "cpu": [ "x64" ], @@ -23462,9 +23132,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.1.tgz", - "integrity": "sha512-uBkwaI+gBUlIe+EfbNnY5xNyXuhZbDSx2nzzW8tRMjUmpScd6lCQYKY2V9BATHtv5Ef2OBq6SChEP8h+/cxifQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz", + "integrity": "sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==", "cpu": [ "arm" ], @@ -23475,9 +23145,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.1.tgz", - "integrity": "sha512-0bK9aG1kIg0Su7OcFTlexkVeNZ5IzEsnz1ept87a0TUgZ6HplSgkJAnFpEVRW7GRcikT4GlPV0pbtVedOaXHQQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz", + "integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==", "cpu": [ "arm64" ], @@ -23488,9 +23158,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.1.tgz", - "integrity": "sha512-qB6AFRXuP8bdkBI4D7UPUbE7OQf7u5OL+R94JE42Z2Qjmyj74FtDdLGeriRyBDhm4rQSvqAGCGC01b8Fu2LthQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz", + "integrity": "sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==", "cpu": [ "arm64" ], @@ -23501,9 +23171,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.1.tgz", - "integrity": "sha512-sHig3LaGlpNgDj5o8uPEoGs98RII8HpNIqFtAI8/pYABO8i0nb1QzT0JDoXF/pxzqO+FkxvwkHZo9k0NJYDedg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz", + "integrity": "sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==", "cpu": [ "riscv64" ], @@ -23514,9 +23184,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.1.tgz", - "integrity": "sha512-nD3YcUv6jBJbBNFvSbp0IV66+ba/1teuBcu+fBBPZ33sidxitc6ErhON3JNavaH8HlswhWMC3s5rgZpM4MtPqQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz", + "integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==", "cpu": [ "x64" ], @@ -23527,9 +23197,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.1.tgz", - "integrity": "sha512-7/XVZqgBby2qp/cO0TQ8uJK+9xnSdJ9ct6gSDdEr4MfABrjTyrW6Bau7HQ73a2a5tPB7hno49A0y1jhWGDN9OQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz", + "integrity": "sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==", "cpu": [ "x64" ], @@ -23540,9 +23210,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.1.tgz", - "integrity": "sha512-CYc64bnICG42UPL7TrhIwsJW4QcKkIt9gGlj21gq3VV0LL6XNb1yAdHVp1pIi9gkts9gGcT3OfUYHjGP7ETAiw==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz", + "integrity": "sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==", "cpu": [ "arm64" ], @@ -23553,9 +23223,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.1.tgz", - "integrity": "sha512-LN+vnlZ9g0qlHGlS920GR4zFCqAwbv2lULrR29yGaWP9u7wF5L7GqWu9Ah6/kFZPXPUkpdZwd//TNR+9XC9hvA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz", + "integrity": "sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==", "cpu": [ "ia32" ], @@ -23566,9 +23236,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.1.tgz", - "integrity": "sha512-n+vkrSyphvmU0qkQ6QBNXCGr2mKjhP08mPRM/Xp5Ck2FV4NrHU+y6axzDeixUrCBHVUS51TZhjqrKBBsHLKb2Q==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz", + "integrity": "sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==", "cpu": [ "x64" ], @@ -23579,79 +23249,79 @@ ] }, "node_modules/@sentry-internal/feedback": { - "version": "7.106.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.106.0.tgz", - "integrity": "sha512-Uz6pv3SN8XORTMme5xPxP/kuho7CAA6E/pMlpMjsojjBbnwLIICu10JaEZNsF/AtEya1RcNVTyPCrtF1F3sBYA==", + "version": "7.107.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.107.0.tgz", + "integrity": "sha512-okF0B9AJHrpkwNMxNs/Lffw3N5ZNbGwz4uvCfyOfnMxc7E2VfDM18QzUvTBRvNr3bA9wl+InJ+EMG3aZhyPunA==", "dependencies": { - "@sentry/core": "7.106.0", - "@sentry/types": "7.106.0", - "@sentry/utils": "7.106.0" + "@sentry/core": "7.107.0", + "@sentry/types": "7.107.0", + "@sentry/utils": "7.107.0" }, "engines": { "node": ">=12" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "7.106.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.106.0.tgz", - "integrity": "sha512-59qmT6XqbwpQuK1nVmv+XFxgd80gpYNH3aqgF5BEKux23kRB02/ARR5MwYyIHgVO0JhwdGIuiTfiLVNDu+nwTQ==", + "version": "7.107.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.107.0.tgz", + "integrity": "sha512-dmDL9g3QDfo7axBOsVnpiKdJ/DXrdeuRv1AqsLgwzJKvItsv0ZizX0u+rj5b1UoxcwbXRMxJ0hit5a1yt3t/ow==", "dependencies": { - "@sentry/core": "7.106.0", - "@sentry/replay": "7.106.0", - "@sentry/types": "7.106.0", - "@sentry/utils": "7.106.0" + "@sentry/core": "7.107.0", + "@sentry/replay": "7.107.0", + "@sentry/types": "7.107.0", + "@sentry/utils": "7.107.0" }, "engines": { "node": ">=12" } }, "node_modules/@sentry-internal/tracing": { - "version": "7.106.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.106.0.tgz", - "integrity": "sha512-O8Es6Sa/tP80nfl+8soNfWzeRNFcT484SvjLR8BS3pHM9KDAlwNXyoQhFr2BKNYL1irbq6UF6eku4xCnUKVmqA==", + "version": "7.107.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.107.0.tgz", + "integrity": "sha512-le9wM8+OHBbq7m/8P7JUJ1UhSPIty+Z/HmRXc5Z64ODZcOwFV6TmDpYx729IXDdz36XUKmeI+BeM7yQdTTZPfQ==", "dependencies": { - "@sentry/core": "7.106.0", - "@sentry/types": "7.106.0", - "@sentry/utils": "7.106.0" + "@sentry/core": "7.107.0", + "@sentry/types": "7.107.0", + "@sentry/utils": "7.107.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/babel-plugin-component-annotate": { - "version": "2.14.3", - "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.14.3.tgz", - "integrity": "sha512-h0ONVTe8j3Ma2g5SMsl9ynmLZdCf+CupLF7PQ7n06K0L8dDtrHqo8yjsWaZSJf4InGrJ9HC4MaOSItbFjiTFLw==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.16.0.tgz", + "integrity": "sha512-+uy1qPkA5MSNgJ0L9ur/vNTydfdHwHnBX2RQ+0thsvkqf90fU788YjkkXwUiBBNuqNyI69JiOW6frixAWy7oUg==", "dev": true, "engines": { "node": ">= 14" } }, "node_modules/@sentry/browser": { - "version": "7.106.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.106.0.tgz", - "integrity": "sha512-OrHdw44giTtMa1DmlIUMBN4ypj1xTES9DLjq16ufK+bLqW3rWzwCuTy0sb9ZmSxc7fL2pdBlsL+sECiS+U2TEw==", + "version": "7.107.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.107.0.tgz", + "integrity": "sha512-KnqaQDhxv6w9dJ+mYLsNwPeGZfgbpM3vaismBNyJCKLgWn2V75kxkSq+bDX8LQT/13AyK7iFp317L6P8EuNa3g==", "dependencies": { - "@sentry-internal/feedback": "7.106.0", - "@sentry-internal/replay-canvas": "7.106.0", - "@sentry-internal/tracing": "7.106.0", - "@sentry/core": "7.106.0", - "@sentry/replay": "7.106.0", - "@sentry/types": "7.106.0", - "@sentry/utils": "7.106.0" + "@sentry-internal/feedback": "7.107.0", + "@sentry-internal/replay-canvas": "7.107.0", + "@sentry-internal/tracing": "7.107.0", + "@sentry/core": "7.107.0", + "@sentry/replay": "7.107.0", + "@sentry/types": "7.107.0", + "@sentry/utils": "7.107.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/bundler-plugin-core": { - "version": "2.14.3", - "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.14.3.tgz", - "integrity": "sha512-iEtMdAPFUAYngvYhkfbgY8m3zB439u+5tvovj9rBXHGMr3nEB5fzZLOcVuiL47GEuUvMjDdrubl9MDGZ0c1IuQ==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.16.0.tgz", + "integrity": "sha512-dhgIZsIR3L9KnE2OO5JJm6hPtStAjEPYKQsZzxRr69uVhd9xAvfXeXr0afKVNVEcIDksas6yMgHqwQ2wOXFIAg==", "dev": true, "dependencies": { "@babel/core": "^7.18.5", - "@sentry/babel-plugin-component-annotate": "2.14.3", + "@sentry/babel-plugin-component-annotate": "2.16.0", "@sentry/cli": "^2.22.3", "dotenv": "^16.3.1", "find-up": "^5.0.0", @@ -23663,6 +23333,15 @@ "node": ">= 14" } }, + "node_modules/@sentry/bundler-plugin-core/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { "version": "9.3.5", "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", @@ -23706,9 +23385,9 @@ } }, "node_modules/@sentry/cli": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.30.0.tgz", - "integrity": "sha512-GTO5e98vy2QwEYQvhE/ZtGUiVrUu4XungLioJbazm+ZOen8cyac8YOapZfozN5mtxjWOWMOwhOqoTeCU3Q8YKQ==", + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.30.2.tgz", + "integrity": "sha512-jQ/RBJ3bZ4PFbfOsGq8EykygHHmXXPw+i6jqsnQfAPIeZoX+DsqpAZbYubQEZKekmQ8EVGFxGHzUVkd6hLVMbA==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -23725,19 +23404,19 @@ "node": ">= 10" }, "optionalDependencies": { - "@sentry/cli-darwin": "2.30.0", - "@sentry/cli-linux-arm": "2.30.0", - "@sentry/cli-linux-arm64": "2.30.0", - "@sentry/cli-linux-i686": "2.30.0", - "@sentry/cli-linux-x64": "2.30.0", - "@sentry/cli-win32-i686": "2.30.0", - "@sentry/cli-win32-x64": "2.30.0" + "@sentry/cli-darwin": "2.30.2", + "@sentry/cli-linux-arm": "2.30.2", + "@sentry/cli-linux-arm64": "2.30.2", + "@sentry/cli-linux-i686": "2.30.2", + "@sentry/cli-linux-x64": "2.30.2", + "@sentry/cli-win32-i686": "2.30.2", + "@sentry/cli-win32-x64": "2.30.2" } }, "node_modules/@sentry/cli-darwin": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.30.0.tgz", - "integrity": "sha512-JVesQ9PznbHBOOOwuej2X8/onfXdmAEjBH6fTyWxBl6K8mB4KmBX/aHunXWMBX+VR9X32XZghIqj7acwaFUMPA==", + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.30.2.tgz", + "integrity": "sha512-lZkKXMt0HUAwLQuPpi/DM3CsdCCp+6B2cdur+8fAq7uARXTOsTKVDxv9pkuJHCgHUnguh8ittP5GMr0baTxmMg==", "dev": true, "optional": true, "os": [ @@ -23748,9 +23427,9 @@ } }, "node_modules/@sentry/cli-linux-arm": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.30.0.tgz", - "integrity": "sha512-MDB3iS31WKg4krCcLo520yxbUERPeA2DCtk9Qs9vSDbQl6Er64dteHllOdx1SDOyX/7GKcxrQEQ6SMmbnOo6wg==", + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.30.2.tgz", + "integrity": "sha512-H7hqiLpEL7w/EHdhuUGatwg9O080mdujq4/zS96buKIHXxZE6KqMXGtMVIAvTl1+z6BlBEnfvZGI19MPw3t/7w==", "cpu": [ "arm" ], @@ -23765,9 +23444,9 @@ } }, "node_modules/@sentry/cli-linux-arm64": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.30.0.tgz", - "integrity": "sha512-JNXPkkMubKoZVlcFIoClSmTb9C/I6Bz08DuAZm2jnjRaaOMiCBxI/l50H3dmfVZ6apjEguG9JkjFdb0kqKB90w==", + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.30.2.tgz", + "integrity": "sha512-IWassuXggNhHOPCNrORNmd5SrAx5rU4XDlgOWBJr/ez7DvlPrr9EhV1xsdht6K4mPXhCGJq3rtRdCoWGJQW6Uw==", "cpu": [ "arm64" ], @@ -23782,9 +23461,9 @@ } }, "node_modules/@sentry/cli-linux-i686": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.30.0.tgz", - "integrity": "sha512-WhVVziFQw/fO0Cc53pY8goPAzJtIs6ORTR89fVbKwa3ZDNkX++mEOECbP7RkmD87kuRxyKzN543RPV971PcAHw==", + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.30.2.tgz", + "integrity": "sha512-gZIq131M4TJTG1lX9uvpoaGWaEXCEfdDXrXu/z/YZmAKBcThpMYChodXmm8FB6X4xb0TPXzIFqdzlLdglFK46g==", "cpu": [ "x86", "ia32" @@ -23800,9 +23479,9 @@ } }, "node_modules/@sentry/cli-linux-x64": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.30.0.tgz", - "integrity": "sha512-QkiVDeSfspotZ0Au5Yauv2DAm/BC1fL9BwPek/WwddM18I2HqnDp6l4TA4bQeEY++o0KEuNF53cPahpepltPjw==", + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.30.2.tgz", + "integrity": "sha512-NmTAIl7aW9OHxwB4149sBfvCbTyK9T/CvBX38keaD2yIThet9gZ4koP49hBDxYF99aQX3E+LIAqWwnkV9W72Sw==", "cpu": [ "x64" ], @@ -23817,9 +23496,9 @@ } }, "node_modules/@sentry/cli-win32-i686": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.30.0.tgz", - "integrity": "sha512-xLY9B1EEGuNYPKpK6M9PMmcu2PzofdvRtbraTcU6Ck2zALS5oXB9kmWc4dDKucZ/uu9JB0m+Lo4ebaNlca45qQ==", + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.30.2.tgz", + "integrity": "sha512-SBR/Q3T6o+7uHwHNdjcG9GA3R++9w8oi778b95GuOC3dh0WOU6hXaKwQWe95ZcuSd2rKpouH7dhMjqqNM4HxOA==", "cpu": [ "x86", "ia32" @@ -23834,9 +23513,9 @@ } }, "node_modules/@sentry/cli-win32-x64": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.30.0.tgz", - "integrity": "sha512-CiXuxnpJI0zho0XE5PVqIS9CwjDEYoMnHQRIr4Jj9OzlGTJ2iSSU6Zp3Ykd7lgo2iK4P6MfxIBm30gFQPnSvVA==", + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.30.2.tgz", + "integrity": "sha512-gF9wSZxzXFgakkC+uKVLAAYlbYj13e1gTsNm3gm+ODfpV+rbHwvbKoLfNsbVCFVCEZxIV2rXEP5WmTr0kiMvWQ==", "cpu": [ "x64" ], @@ -23875,26 +23554,26 @@ } }, "node_modules/@sentry/core": { - "version": "7.106.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.106.0.tgz", - "integrity": "sha512-Dc13XtnyFaXup2E4vCbzuG0QKAVjrJBk4qfGwvSJaTuopEaEWBs2MpK6hRzFhsz9S3T0La7c1F/62NptvTUWsQ==", + "version": "7.107.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.107.0.tgz", + "integrity": "sha512-C7ogye6+KPyBi8NVL0P8Rxx3Ur7Td8ufnjxosVy678lqY+dcYPk/HONROrzUFYW5fMKWL4/KYnwP+x9uHnkDmw==", "dependencies": { - "@sentry/types": "7.106.0", - "@sentry/utils": "7.106.0" + "@sentry/types": "7.107.0", + "@sentry/utils": "7.107.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/react": { - "version": "7.106.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.106.0.tgz", - "integrity": "sha512-5KMfvkBYqK990o8Ju9vsRRRR0F8TnPpZynC9YqsJYpCViKjIt8W/ysDLrU1Dj5XZyeVElZjdRlXB0aQYrwEUWg==", - "dependencies": { - "@sentry/browser": "7.106.0", - "@sentry/core": "7.106.0", - "@sentry/types": "7.106.0", - "@sentry/utils": "7.106.0", + "version": "7.107.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.107.0.tgz", + "integrity": "sha512-3sXNKcDQjEimxwBPnRkewy3xNLt3KqStMAdDZ/dAF3rviOSVyk80DCQ3P6+HIqeB+IAXqWptg4eSWRA1qNZquA==", + "dependencies": { + "@sentry/browser": "7.107.0", + "@sentry/core": "7.107.0", + "@sentry/types": "7.107.0", + "@sentry/utils": "7.107.0", "hoist-non-react-statics": "^3.3.2" }, "engines": { @@ -23905,45 +23584,45 @@ } }, "node_modules/@sentry/replay": { - "version": "7.106.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.106.0.tgz", - "integrity": "sha512-buaAOvOI+3pFm+76vwtxSxciBATHyR78aDjStghJZcIpFDNF31K8ZV0uP9+EUPbXHohtkTwZ86cn/P9cyY6NgA==", + "version": "7.107.0", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.107.0.tgz", + "integrity": "sha512-BNJDEVaEwr/YnV22qnyVA1almx/3p615m3+KaF8lPo7YleYgJGSJv1auH64j1G8INkrJ0J0wFBujb1EFjMYkxA==", "dependencies": { - "@sentry-internal/tracing": "7.106.0", - "@sentry/core": "7.106.0", - "@sentry/types": "7.106.0", - "@sentry/utils": "7.106.0" + "@sentry-internal/tracing": "7.107.0", + "@sentry/core": "7.107.0", + "@sentry/types": "7.107.0", + "@sentry/utils": "7.107.0" }, "engines": { "node": ">=12" } }, "node_modules/@sentry/types": { - "version": "7.106.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.106.0.tgz", - "integrity": "sha512-oKTkDaL6P9xJC5/zHLRemHTWboUqRYjkJNaZCN63j4kJqGy56wee4vDtDese/NWWn4U4C1QV1h+Mifm2HmDcQg==", + "version": "7.107.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.107.0.tgz", + "integrity": "sha512-H7qcPjPSUWHE/Zf5bR1EE24G0pGVuJgrSx8Tvvl5nKEepswMYlbXHRVSDN0gTk/E5Z7cqf+hUBOpkQgZyps77w==", "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.106.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.106.0.tgz", - "integrity": "sha512-bVsePsXLpFu/1sH4rpJrPcnVxW2fXXfGfGxKs6Bm+dkOMbuVTlk/KAzIbdjCDIpVlrMDJmMNEv5xgTFjgWDkjw==", + "version": "7.107.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.107.0.tgz", + "integrity": "sha512-C6PbN5gHh73MRHohnReeQ60N8rrLYa9LciHue3Ru2290eSThg4CzsPnx4SzkGpkSeVlhhptKtKZ+hp/ha3iVuw==", "dependencies": { - "@sentry/types": "7.106.0" + "@sentry/types": "7.107.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/vite-plugin": { - "version": "2.14.3", - "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-2.14.3.tgz", - "integrity": "sha512-sSMbn6lND0N5eE0R/gmzlZKgegIgkSge/yrECf0xZi3tMHn4n6Ue1VO7m0+sJZFLP5C26htYFh0lI16EUweYEg==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-2.16.0.tgz", + "integrity": "sha512-/7rFTpasql9fJ1KbruF0yDESKV/ojvOP9pL/qqwUffvA9iy9Bvw3kYzzyzd1YsiCiVBgftoCsFTKPcvL3A4rwQ==", "dev": true, "dependencies": { - "@sentry/bundler-plugin-core": "2.14.3", + "@sentry/bundler-plugin-core": "2.16.0", "unplugin": "1.0.1" }, "engines": { @@ -24649,14 +24328,23 @@ } }, "node_modules/@storybook/core-common/node_modules/@types/node": { - "version": "18.19.22", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.22.tgz", - "integrity": "sha512-p3pDIfuMg/aXBmhkyanPshdfJuX5c5+bQjYLIikPLXAUycEogij/c50n/C+8XOA5L93cU4ZRXtn+dNQGi0IZqQ==", + "version": "18.19.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.26.tgz", + "integrity": "sha512-+wiMJsIwLOYCvUqSdKTrfkS8mpTp+MPINe6+Np4TAGFWWRWiBQ5kSq9nZGCSPkzx9mvT+uEukzpX4MOSCydcvw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, + "node_modules/@storybook/core-common/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@storybook/core-common/node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -24695,6 +24383,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@storybook/core-common/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@storybook/core-common/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -24774,9 +24477,9 @@ } }, "node_modules/@storybook/core-server/node_modules/@types/node": { - "version": "18.19.22", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.22.tgz", - "integrity": "sha512-p3pDIfuMg/aXBmhkyanPshdfJuX5c5+bQjYLIikPLXAUycEogij/c50n/C+8XOA5L93cU4ZRXtn+dNQGi0IZqQ==", + "version": "18.19.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.26.tgz", + "integrity": "sha512-+wiMJsIwLOYCvUqSdKTrfkS8mpTp+MPINe6+Np4TAGFWWRWiBQ5kSq9nZGCSPkzx9mvT+uEukzpX4MOSCydcvw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -24833,9 +24536,9 @@ "dev": true }, "node_modules/@storybook/csf": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.2.tgz", - "integrity": "sha512-ePrvE/pS1vsKR9Xr+o+YwdqNgHUyXvg+1Xjx0h9LrVx7Zq4zNe06pd63F5EvzTbCbJsHj7GHr9tkiaqm7U8WRA==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.3.tgz", + "integrity": "sha512-IPZvXXo4b3G+gpmgBSBqVM81jbp2ePOKsvhgJdhyZJtkYQCII7rg9KKLQhvBQM5sLaF1eU6r0iuwmyynC9d9SA==", "dev": true, "dependencies": { "type-fest": "^2.19.0" @@ -24868,9 +24571,9 @@ } }, "node_modules/@storybook/csf-plugin/node_modules/unplugin": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.9.0.tgz", - "integrity": "sha512-14PslvMY3gNbXnQtNIRB566Q057L5Fe7f5LDEamxVi0QQVxoz5hrveBwwZLcKyHtZ09ysmipxRRj5Lv+BGz2Iw==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.10.0.tgz", + "integrity": "sha512-CuZtvvO8ua2Wl+9q2jEaqH6m3DoQ38N7pvBYQbbaeNlWGvK2l6GHiKi29aIHDPoSxdUzQ7Unevf1/ugil5X6Pg==", "dev": true, "dependencies": { "acorn": "^8.11.3", @@ -25202,9 +24905,9 @@ } }, "node_modules/@storybook/react/node_modules/@types/node": { - "version": "18.19.22", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.22.tgz", - "integrity": "sha512-p3pDIfuMg/aXBmhkyanPshdfJuX5c5+bQjYLIikPLXAUycEogij/c50n/C+8XOA5L93cU4ZRXtn+dNQGi0IZqQ==", + "version": "18.19.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.26.tgz", + "integrity": "sha512-+wiMJsIwLOYCvUqSdKTrfkS8mpTp+MPINe6+Np4TAGFWWRWiBQ5kSq9nZGCSPkzx9mvT+uEukzpX4MOSCydcvw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -25258,9 +24961,9 @@ } }, "node_modules/@storybook/test-runner": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@storybook/test-runner/-/test-runner-0.16.0.tgz", - "integrity": "sha512-LDmNbKFoEDW/VS9o6KR8e1r5MnbCc5ZojUfi5yqLdq80gFD7BvilgKgV0lUh/xWHryzoy+Ids5LYgrPJZmU2dQ==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@storybook/test-runner/-/test-runner-0.17.0.tgz", + "integrity": "sha512-4mt822j0VF1H/c0//OWSST9eWV0wboncJUQ+hBm5N4wmyuObvwsiMh4pmgXw8Y82wF7g1RIofjEQqAGLa7NjgQ==", "dev": true, "dependencies": { "@babel/core": "^7.22.5", @@ -25268,16 +24971,13 @@ "@babel/template": "^7.22.5", "@babel/types": "^7.22.5", "@jest/types": "^29.6.3", - "@storybook/core-common": "^7.0.0-beta.0 || ^7.0.0-rc.0 || ^7.0.0", - "@storybook/csf": "^0.1.1", - "@storybook/csf-tools": "^7.0.0-beta.0 || ^7.0.0-rc.0 || ^7.0.0", - "@storybook/preview-api": "^7.0.0-beta.0 || ^7.0.0-rc.0 || ^7.0.0", + "@storybook/core-common": "^8.0.0", + "@storybook/csf": "^0.1.2", + "@storybook/csf-tools": "^8.0.0", + "@storybook/preview-api": "^8.0.0", "@swc/core": "^1.3.18", "@swc/jest": "^0.2.23", - "can-bind-to-host": "^1.1.1", - "commander": "^9.0.0", "expect-playwright": "^0.8.0", - "glob": "^10.2.2", "jest": "^29.6.4", "jest-circus": "^29.6.4", "jest-environment-node": "^29.6.4", @@ -25286,11 +24986,7 @@ "jest-runner": "^29.6.4", "jest-serializer-html": "^7.1.0", "jest-watch-typeahead": "^2.0.0", - "node-fetch": "^2", - "playwright": "^1.14.0", - "read-pkg-up": "^7.0.1", - "tempy": "^1.0.1", - "ts-dedent": "^2.0.0" + "playwright": "^1.14.0" }, "bin": { "test-storybook": "dist/test-storybook.js" @@ -25299,6 +24995,170 @@ "node": "^16.10.0 || ^18.0.0 || >=20.0.0" } }, + "node_modules/@storybook/test-runner/node_modules/@storybook/channels": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.0.2.tgz", + "integrity": "sha512-r7TMUlALWc8sTXzyRZ1wSngvDWGhRLfhU9VJ0ouMyk2oSNEgcKBGvq7FkMmHINKHr3gte9+Ab0iG7TAoQ7pPsg==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.0.2", + "@storybook/core-events": "8.0.2", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/test-runner/node_modules/@storybook/client-logger": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.0.2.tgz", + "integrity": "sha512-/GvjkCHk5LyiJ0EzoJ3kV+tqCGVarxYSnhD8ciszbWBUH4ZX104So+uZjwwGKCEZxh17HLppQa5bzOayGcdRDg==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/test-runner/node_modules/@storybook/core-common": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-8.0.2.tgz", + "integrity": "sha512-0LkQn2dCVzFepLqqlt82ouIuc11UCsDzPtRVHp4p18JA0xs2dmD6d8vJUfEAYAgoeEaH3bFjb57IhMbYT5adhw==", + "dev": true, + "dependencies": { + "@storybook/core-events": "8.0.2", + "@storybook/csf-tools": "8.0.2", + "@storybook/node-logger": "8.0.2", + "@storybook/types": "8.0.2", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", + "chalk": "^4.1.0", + "cross-spawn": "^7.0.3", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0", + "esbuild-register": "^3.5.0", + "execa": "^5.0.0", + "file-system-cache": "2.3.0", + "find-cache-dir": "^3.0.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "glob": "^10.0.0", + "handlebars": "^4.7.7", + "lazy-universal-dotenv": "^4.0.0", + "node-fetch": "^2.0.0", + "picomatch": "^2.3.0", + "pkg-dir": "^5.0.0", + "pretty-hrtime": "^1.0.3", + "resolve-from": "^5.0.0", + "semver": "^7.3.7", + "tempy": "^1.0.1", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/test-runner/node_modules/@storybook/core-events": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.0.2.tgz", + "integrity": "sha512-1rtecdU3eyWGMT3U27ldF6ApdakvmmcS8E+1PqLGd5K9v5T0W82n+QyXft3kb434N8KYSwNFf08NfrU0VZeC4w==", + "dev": true, + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/test-runner/node_modules/@storybook/csf-tools": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-8.0.2.tgz", + "integrity": "sha512-NZ7aYPslaCxciq2lKA5q4YsQYtIb7AeYdYqgjuVPdlwkqBuyeiym1OP7wF1X0iFwZVG3/UogqBCALnKQmROo2A==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/types": "8.0.2", + "fs-extra": "^11.1.0", + "recast": "^0.23.5", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/test-runner/node_modules/@storybook/node-logger": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-8.0.2.tgz", + "integrity": "sha512-UG6v5PCXYblNCZUlbC+D+NisvSn1caC+q3yNSVAW3Z2MDfWmrkThFVzI7LDj1c9DAkbMr2v9beMHdD+suSQe4g==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/test-runner/node_modules/@storybook/preview-api": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.0.2.tgz", + "integrity": "sha512-b321QTjSw6k50eKTPYeB1rlCso9frHADMeudpcQcRdf8ezYQzd/mUZx9DcJnmTS+WuW9LJ435GvJ7b5O1oA6kg==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.0.2", + "@storybook/client-logger": "8.0.2", + "@storybook/core-events": "8.0.2", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/types": "8.0.2", + "@types/qs": "^6.9.5", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/test-runner/node_modules/@storybook/types": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.0.2.tgz", + "integrity": "sha512-vVBNUZFf8v8qxm/FYtg06K5T6dEqHtGZjm4DH/fPc59XvqGpAIl6XEkOwgfTqv30QqXDV2PAaaPDO/21VtXjrQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.0.2", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/test-runner/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@storybook/test-runner/node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -25337,6 +25197,48 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@storybook/test-runner/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/test-runner/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@storybook/test-runner/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@storybook/test-runner/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -25349,6 +25251,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@storybook/test-runner/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@storybook/testing-library": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/@storybook/testing-library/-/testing-library-0.2.2.tgz", @@ -25397,9 +25305,9 @@ } }, "node_modules/@stripe/react-stripe-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-2.5.1.tgz", - "integrity": "sha512-95BwDhOkl1TwIn5sldWW35GYt6wx+uYuwGjebaMOpOdHGyBKcDnBhTjIww+bUdmA2oCmpUqKnoB4OZJuqK8tJA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-2.6.2.tgz", + "integrity": "sha512-FSjNg4v7BiCfojvx25PQ8DugOa09cGk1t816R/DLI/lT+1bgRAYpMvoPirLT4ZQ3ev/0VDtPdWNaabPsLDTOMA==", "dependencies": { "prop-types": "^15.7.2" }, @@ -25410,9 +25318,9 @@ } }, "node_modules/@stripe/stripe-js": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-3.0.7.tgz", - "integrity": "sha512-qmjTsxnst84iWDsGqPxk5Wlff/fG4nSFjy/r24t9WWFAlCuvwnuUAe4eGgbqZBng019AtgWvo8wuhM3Y5/olbw==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-3.0.10.tgz", + "integrity": "sha512-CFRNha+aPXR8GrqJss2TbK1j4aSGZXQY8gx0hvaYiSp+dU7EK/Zs5uwFTSAgV+t8H4+jcZ/iBGajAvoMYOwy+A==", "engines": { "node": ">=12.16" } @@ -25655,9 +25563,9 @@ } }, "node_modules/@swc/core": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.6.tgz", - "integrity": "sha512-A7iK9+1qzTCIuc3IYcS8gPHCm9bZVKUJrfNnwveZYyo6OFp3jLno4WOM2yBy5uqedgYATEiWgBYHKq37KrU6IA==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.8.tgz", + "integrity": "sha512-uY2RSJcFPgNOEg12RQZL197LZX+MunGiKxsbxmh22VfVxrOYGRvh4mPANFlrD1yb38CgmW1wI6YgIi8LkIwmWg==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -25672,16 +25580,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.4.6", - "@swc/core-darwin-x64": "1.4.6", - "@swc/core-linux-arm-gnueabihf": "1.4.6", - "@swc/core-linux-arm64-gnu": "1.4.6", - "@swc/core-linux-arm64-musl": "1.4.6", - "@swc/core-linux-x64-gnu": "1.4.6", - "@swc/core-linux-x64-musl": "1.4.6", - "@swc/core-win32-arm64-msvc": "1.4.6", - "@swc/core-win32-ia32-msvc": "1.4.6", - "@swc/core-win32-x64-msvc": "1.4.6" + "@swc/core-darwin-arm64": "1.4.8", + "@swc/core-darwin-x64": "1.4.8", + "@swc/core-linux-arm-gnueabihf": "1.4.8", + "@swc/core-linux-arm64-gnu": "1.4.8", + "@swc/core-linux-arm64-musl": "1.4.8", + "@swc/core-linux-x64-gnu": "1.4.8", + "@swc/core-linux-x64-musl": "1.4.8", + "@swc/core-win32-arm64-msvc": "1.4.8", + "@swc/core-win32-ia32-msvc": "1.4.8", + "@swc/core-win32-x64-msvc": "1.4.8" }, "peerDependencies": { "@swc/helpers": "^0.5.0" @@ -25693,9 +25601,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.6.tgz", - "integrity": "sha512-bpggpx/BfLFyy48aUKq1PsNUxb7J6CINlpAUk0V4yXfmGnpZH80Gp1pM3GkFDQyCfq7L7IpjPrIjWQwCrL4hYw==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.8.tgz", + "integrity": "sha512-hhQCffRTgzpTIbngSnC30vV6IJVTI9FFBF954WEsshsecVoCGFiMwazBbrkLG+RwXENTrMhgeREEFh6R3KRgKQ==", "cpu": [ "arm64" ], @@ -25709,9 +25617,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.6.tgz", - "integrity": "sha512-vJn+/ZuBTg+vtNkcmgZdH6FQpa0hFVdnB9bAeqYwKkyqP15zaPe6jfC+qL2y/cIeC7ASvHXEKrnCZgBLxfVQ9w==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.8.tgz", + "integrity": "sha512-P3ZBw8Jr8rKhY/J8d+6WqWriqngGTgHwtFeJ8MIakQJTbdYbFgXSZxcvDiERg3psbGeFXaUaPI0GO6BXv9k/OQ==", "cpu": [ "x64" ], @@ -25725,9 +25633,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.6.tgz", - "integrity": "sha512-hEmYcB/9XBAl02MtuVHszhNjQpjBzhk/NFulnU33tBMbNZpy2TN5yTsitezMq090QXdDz8sKIALApDyg07ZR8g==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.8.tgz", + "integrity": "sha512-PP9JIJt19bUWhAGcQW6qMwTjZOcMyzkvZa0/LWSlDm0ORYVLmDXUoeQbGD3e0Zju9UiZxyulnpjEN0ZihJgPTA==", "cpu": [ "arm" ], @@ -25741,9 +25649,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.6.tgz", - "integrity": "sha512-/UCYIVoGpm2YVvGHZM2QOA3dexa28BjcpLAIYnoCbgH5f7ulDhE8FAIO/9pasj+kixDBsdqewHfsNXFYlgGJjQ==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.8.tgz", + "integrity": "sha512-HvEWnwKHkoVUr5iftWirTApFJ13hGzhAY2CMw4lz9lur2m+zhPviRRED0FCI6T95Knpv7+8eUOr98Z7ctrG6DQ==", "cpu": [ "arm64" ], @@ -25757,9 +25665,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.6.tgz", - "integrity": "sha512-LGQsKJ8MA9zZ8xHCkbGkcPSmpkZL2O7drvwsGKynyCttHhpwVjj9lguhD4DWU3+FWIsjvho5Vu0Ggei8OYi/Lw==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.8.tgz", + "integrity": "sha512-kY8+qa7k/dEeBq9p0Hrta18QnJPpsiJvDQSLNaTIFpdM3aEM9zbkshWz8gaX5VVGUEALowCBUWqmzO4VaqM+2w==", "cpu": [ "arm64" ], @@ -25773,9 +25681,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.6.tgz", - "integrity": "sha512-10JL2nLIreMQDKvq2TECnQe5fCuoqBHu1yW8aChqgHUyg9d7gfZX/kppUsuimqcgRBnS0AjTDAA+JF6UsG/2Yg==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.8.tgz", + "integrity": "sha512-0WWyIw432wpO/zeGblwq4f2YWam4pn8Z/Ig4KzHMgthR/KmiLU3f0Z7eo45eVmq5vcU7Os1zi/Zb65OOt09q/w==", "cpu": [ "x64" ], @@ -25789,9 +25697,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.6.tgz", - "integrity": "sha512-EGyjFVzVY6Do89x8sfah7I3cuP4MwtwzmA6OlfD/KASqfCFf5eIaEBMbajgR41bVfMV7lK72lwAIea5xEyq1AQ==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.8.tgz", + "integrity": "sha512-p4yxvVS05rBNCrBaSTa20KK88vOwtg8ifTW7ec/yoab0bD5EwzzB8KbDmLLxE6uziFa0sdjF0dfRDwSZPex37Q==", "cpu": [ "x64" ], @@ -25805,9 +25713,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.6.tgz", - "integrity": "sha512-gfW9AuXvwSyK07Vb8Y8E9m2oJZk21WqcD+X4BZhkbKB0TCZK0zk1j/HpS2UFlr1JB2zPKPpSWLU3ll0GEHRG2A==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.8.tgz", + "integrity": "sha512-jKuXihxAaqUnbFfvPxtmxjdJfs87F1GdBf33il+VUmSyWCP4BE6vW+/ReDAe8sRNsKyrZ3UH1vI5q1n64csBUA==", "cpu": [ "arm64" ], @@ -25821,9 +25729,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.6.tgz", - "integrity": "sha512-ZuQm81FhhvNVYtVb9GfZ+Du6e7fZlkisWvuCeBeRiyseNt1tcrQ8J3V67jD2nxje8CVXrwG3oUIbPcybv2rxfQ==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.8.tgz", + "integrity": "sha512-O0wT4AGHrX8aBeH6c2ADMHgagAJc5Kf6W48U5moyYDAkkVnKvtSc4kGhjWhe1Yl0sI0cpYh2In2FxvYsb44eWw==", "cpu": [ "ia32" ], @@ -25837,9 +25745,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.6.tgz", - "integrity": "sha512-UagPb7w5V0uzWSjrXwOavGa7s9iv3wrVdEgWy+/inm0OwY4lj3zpK9qDnMWAwYLuFwkI3UG4Q3dH8wD+CUUcjw==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.8.tgz", + "integrity": "sha512-C2AYc3A2o+ECciqsJWRgIpp83Vk5EaRzHe7ed/xOWzVd0MsWR+fweEsyOjlmzHfpUxJSi46Ak3/BIZJlhZbXbg==", "cpu": [ "x64" ], @@ -25876,10 +25784,13 @@ } }, "node_modules/@swc/types": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", - "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", - "dev": true + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.6.tgz", + "integrity": "sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==", + "dev": true, + "dependencies": { + "@swc/counter": "^0.1.3" + } }, "node_modules/@testing-library/dom": { "version": "9.3.4", @@ -25965,9 +25876,9 @@ "dev": true }, "node_modules/@testing-library/react": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.2.1.tgz", - "integrity": "sha512-sGdjws32ai5TLerhvzThYFbpnF9XtL65Cjf+gB0Dhr29BGqK+mAeN7SURSdu+eqgET4ANcWoC7FQpkaiGvBr+A==", + "version": "14.2.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.2.2.tgz", + "integrity": "sha512-SOUuM2ysCvjUWBXTNfQ/ztmnKDmqaiPV3SvoIuyxMUca45rbSWWAT/qB8CUs/JQ/ux/8JFs9DNdFQ3f6jH3crA==", "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", @@ -26358,9 +26269,9 @@ "dev": true }, "node_modules/@types/lodash": { - "version": "4.14.202", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", - "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", "dev": true }, "node_modules/@types/lodash.merge": { @@ -26381,6 +26292,12 @@ "@types/unist": "^2" } }, + "node_modules/@types/mdast/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", + "dev": true + }, "node_modules/@types/mdx": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.11.tgz", @@ -26412,9 +26329,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", - "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -26453,9 +26370,9 @@ "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, "node_modules/@types/qs": { - "version": "6.9.12", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.12.tgz", - "integrity": "sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==", + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz", + "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==", "dev": true }, "node_modules/@types/range-parser": { @@ -26465,9 +26382,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.2.64", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.64.tgz", - "integrity": "sha512-MlmPvHgjj2p3vZaxbQgFUQFvD8QiZwACfGqEdDSWou5yISWxDQ4/74nCAwsUiX7UFLKZz3BbVSPj+YxeoGGCfg==", + "version": "18.2.67", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.67.tgz", + "integrity": "sha512-vkIE2vTIMHQ/xL0rgmuoECBCkZFZeHr49HeWSc24AptMbNRo7pwSBvj73rlJJs9fGKj0koS+V7kQB1jHS0uCgw==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -26475,9 +26392,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.21", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.21.tgz", - "integrity": "sha512-gnvBA/21SA4xxqNXEwNiVcP0xSGHh/gi1VhWv9Bl46a0ItbTT5nFY+G9VSQpaG/8N/qdJpJ+vftQ4zflTtnjLw==", + "version": "18.2.22", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.22.tgz", + "integrity": "sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ==", "dev": true, "dependencies": { "@types/react": "*" @@ -26560,9 +26477,9 @@ "dev": true }, "node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", "dev": true }, "node_modules/@types/uuid": { @@ -26604,20 +26521,212 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.3.1.tgz", + "integrity": "sha512-STEDMVQGww5lhCuNXVSQfbfuNII5E08QWkvAw5Qwf+bj2WT+JkG1uc+5/vXA3AOYMDHVOSpL+9rcbEUiHIm2dw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/type-utils": "7.3.1", + "@typescript-eslint/utils": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz", + "integrity": "sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.3.1.tgz", + "integrity": "sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz", + "integrity": "sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.3.1.tgz", + "integrity": "sha512-jIERm/6bYQ9HkynYlNZvXpzmXWZGhMbrOvq3jJzOSOlKXsVjrrolzWBjDW6/TvT5Q3WqaN4EkmcfdQwi9tDjBQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/typescript-estree": "7.3.1", + "semver": "^7.5.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz", + "integrity": "sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.3.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@typescript-eslint/parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", - "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.3.1.tgz", + "integrity": "sha512-Rq49+pq7viTRCH48XAbTA+wdLRrB/3sRq4Lpk0oGDm0VmnjBrAOVXH/Laalmwsv2VpekiEfVFwJYVk6/e8uvQw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/typescript-estree": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -26632,44 +26741,220 @@ } } }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz", + "integrity": "sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.3.1.tgz", + "integrity": "sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz", + "integrity": "sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz", + "integrity": "sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.3.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "node_modules/@typescript-eslint/type-utils": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.3.1.tgz", + "integrity": "sha512-iFhaysxFsMDQlzJn+vr3OrxN8NmdQkHks4WaqD4QBnt5hsq234wcYdyQ9uquzJJIDAj5W4wQne3yEsYA6OmXGw==", "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.3.1", + "@typescript-eslint/utils": "7.3.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz", + "integrity": "sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.3.1.tgz", + "integrity": "sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz", + "integrity": "sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -26678,7 +26963,146 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.3.1.tgz", + "integrity": "sha512-jIERm/6bYQ9HkynYlNZvXpzmXWZGhMbrOvq3jJzOSOlKXsVjrrolzWBjDW6/TvT5Q3WqaN4EkmcfdQwi9tDjBQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/typescript-estree": "7.3.1", + "semver": "^7.5.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz", + "integrity": "sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.3.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", @@ -26723,17 +27147,98 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", @@ -26766,9 +27271,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.3.1.tgz", - "integrity": "sha512-UuBnkSJUNE9rdHjDCPyJ4fYuMkoMtnghes1XohYa4At0MS3OQSAo97FrbwSLRshYsXThMZy1+ybD/byK5llyIg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.4.0.tgz", + "integrity": "sha512-4hDGyH1SvKpgZnIByr9LhGgCEuF9DKM34IBLCC/fVfy24Z3+PZ+Ii9hsVBsHvY1umM1aGPEjceRkzxCfcQ10wg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.1", @@ -26776,12 +27281,13 @@ "debug": "^4.3.4", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^4.0.1", + "istanbul-lib-source-maps": "^5.0.4", "istanbul-reports": "^3.1.6", "magic-string": "^0.30.5", "magicast": "^0.3.3", "picocolors": "^1.0.0", "std-env": "^3.5.0", + "strip-literal": "^2.0.0", "test-exclude": "^6.0.0", "v8-to-istanbul": "^9.2.0" }, @@ -26789,7 +27295,7 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "1.3.1" + "vitest": "1.4.0" } }, "node_modules/@vitest/coverage-v8/node_modules/magic-string": { @@ -26805,13 +27311,13 @@ } }, "node_modules/@vitest/expect": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.3.1.tgz", - "integrity": "sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.4.0.tgz", + "integrity": "sha512-Jths0sWCJZ8BxjKe+p+eKsoqev1/T8lYcrjavEaz8auEJ4jAVY0GwW3JKmdVU4mmNPLPHixh4GNXP7GFtAiDHA==", "dev": true, "dependencies": { - "@vitest/spy": "1.3.1", - "@vitest/utils": "1.3.1", + "@vitest/spy": "1.4.0", + "@vitest/utils": "1.4.0", "chai": "^4.3.10" }, "funding": { @@ -26819,12 +27325,12 @@ } }, "node_modules/@vitest/runner": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.3.1.tgz", - "integrity": "sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.4.0.tgz", + "integrity": "sha512-EDYVSmesqlQ4RD2VvWo3hQgTJ7ZrFQ2VSJdfiJiArkCerDAGeyF1i6dHkmySqk573jLp6d/cfqCN+7wUB5tLgg==", "dev": true, "dependencies": { - "@vitest/utils": "1.3.1", + "@vitest/utils": "1.4.0", "p-limit": "^5.0.0", "pathe": "^1.1.1" }, @@ -26860,9 +27366,9 @@ } }, "node_modules/@vitest/snapshot": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.3.1.tgz", - "integrity": "sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.4.0.tgz", + "integrity": "sha512-saAFnt5pPIA5qDGxOHxJ/XxhMFKkUSBJmVt5VgDsAqPTX6JP326r5C/c9UuCMPoXNzuudTPsYDZCoJ5ilpqG2A==", "dev": true, "dependencies": { "magic-string": "^0.30.5", @@ -26912,9 +27418,9 @@ } }, "node_modules/@vitest/spy": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.3.1.tgz", - "integrity": "sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.4.0.tgz", + "integrity": "sha512-Ywau/Qs1DzM/8Uc+yA77CwSegizMlcgTJuYGAi0jujOteJOUf1ujunHThYo243KG9nAyWT3L9ifPYZ5+As/+6Q==", "dev": true, "dependencies": { "tinyspy": "^2.2.0" @@ -26924,9 +27430,9 @@ } }, "node_modules/@vitest/utils": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.3.1.tgz", - "integrity": "sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-mx3Yd1/6e2Vt/PUC98DcqTirtfxUyAZ32uK82r8rZzbtBeBo+nqgnjx/LvqQdWsrvNtm14VmurNgcf4nqY5gJg==", "dev": true, "dependencies": { "diff-sequences": "^29.6.3", @@ -27343,9 +27849,9 @@ "dev": true }, "node_modules/aria-hidden": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", - "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", "dev": true, "dependencies": { "tslib": "^2.0.0" @@ -27386,15 +27892,16 @@ "dev": true }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -27413,35 +27920,17 @@ "node": ">=8" } }, - "node_modules/array.prototype.filter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", - "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.findlast": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.4.tgz", - "integrity": "sha512-BMtLxpV+8BD+6ZPFIWmnUBpQoy+A+ujcg4rhp2iwCRJYA7PEh2MS4NL3lz8EiDlLrJPp2hg9qWihr5pd//jcGw==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" }, "engines": { @@ -27452,15 +27941,16 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", - "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" }, "engines": { @@ -27634,15 +28124,6 @@ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "dev": true }, - "node_modules/asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -27685,11 +28166,11 @@ } }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -27811,13 +28292,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.9.tgz", - "integrity": "sha512-BXIWIaO3MewbXWdJdIGDWZurv5OGJlFNo7oy20DpB3kWDVJLcY2NRypRsRUbRe5KMqSNLuOGnWTFQQtY5MAsRw==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", + "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.0", + "@babel/helper-define-polyfill-provider": "^0.6.1", "semver": "^6.3.1" }, "peerDependencies": { @@ -27825,57 +28306,25 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", - "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.5.0", - "core-js-compat": "^3.34.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", - "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.5.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", + "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "@babel/helper-define-polyfill-provider": "^0.6.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -28039,12 +28488,15 @@ } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/binary-install": { @@ -28148,12 +28600,13 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -28420,19 +28873,10 @@ "node": ">=6" } }, - "node_modules/can-bind-to-host": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/can-bind-to-host/-/can-bind-to-host-1.1.2.tgz", - "integrity": "sha512-CqsgmaqiyFRNtP17Ihqa/uHbZxRirntNVNl/kJz31DLKuNRfzvzionkLoUSkElQ6Cz+cpXKA3mhHq4tjbieujA==", - "dev": true, - "bin": { - "can-bind-to-host": "dist/bin/can-bind-to-host.js" - } - }, "node_modules/caniuse-lite": { - "version": "1.0.30001596", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz", - "integrity": "sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==", + "version": "1.0.30001599", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz", + "integrity": "sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA==", "dev": true, "funding": [ { @@ -28691,9 +29135,9 @@ } }, "node_modules/chromatic": { - "version": "11.0.7", - "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.0.7.tgz", - "integrity": "sha512-Fa6LpfinKTgv31eo7rFTNcaSSCPgzuUtBjdkJVgeD3ZixxFEHPYv0lsJTs2kBaIltejqsIy2PpQ9zWQqEEQAEQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.2.0.tgz", + "integrity": "sha512-b7vzlMuy/68WnH0N6nXpo8FiFK5pEF0ClIyVVK9YfYYSbGLo5/6Lh/VEbjWMoRaShCUk59YSXA43Npa2NrXIsg==", "dev": true, "bin": { "chroma": "dist/bin.js", @@ -28701,8 +29145,8 @@ "chromatic-cli": "dist/bin.js" }, "peerDependencies": { - "@chromatic-com/cypress": "^0.5.2 || ^1.0.0", - "@chromatic-com/playwright": "^0.5.2 || ^1.0.0" + "@chromatic-com/cypress": "^0.*.* || ^1.0.0", + "@chromatic-com/playwright": "^0.*.* || ^1.0.0" }, "peerDependenciesMeta": { "@chromatic-com/cypress": { @@ -28989,12 +29433,12 @@ } }, "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true, "engines": { - "node": "^12.20.0 || >=14" + "node": ">= 6" } }, "node_modules/common-tags": { @@ -29188,9 +29632,9 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "dev": true, "engines": { "node": ">= 0.6" @@ -29203,12 +29647,12 @@ "dev": true }, "node_modules/core-js-compat": { - "version": "3.36.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", - "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==", + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", + "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", "dev": true, "dependencies": { - "browserslist": "^4.22.3" + "browserslist": "^4.23.0" }, "funding": { "type": "opencollective", @@ -29379,6 +29823,57 @@ "node": ">=18" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/dataloader": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", @@ -29701,9 +30196,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "dev": true, "engines": { "node": ">=8" @@ -30016,9 +30511,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.699", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.699.tgz", - "integrity": "sha512-I7q3BbQi6e4tJJN5CRcyvxhK0iJb34TV8eJQcgh+fR2fQ8miMgZcEInckCo1U9exDHbfz7DLDnFn8oqH/VcRKw==", + "version": "1.4.713", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.713.tgz", + "integrity": "sha512-vDarADhwntXiULEdmWd77g2dV6FrNGa8ecAC29MZ4TwPut2fvosD0/5sJd1qWNNe8HcJFAC+F5Lf9jW1NPtWmw==", "dev": true }, "node_modules/emittery": { @@ -30058,9 +30553,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz", - "integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", + "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -30097,17 +30592,21 @@ } }, "node_modules/es-abstract": { - "version": "1.22.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", - "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.0", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", @@ -30118,10 +30617,11 @@ "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.1", + "hasown": "^2.0.2", "internal-slot": "^1.0.7", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.3", @@ -30132,17 +30632,17 @@ "object-keys": "^1.1.1", "object.assign": "^4.1.5", "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", + "safe-array-concat": "^1.1.2", "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", "string.prototype.trimstart": "^1.0.7", "typed-array-buffer": "^1.0.2", "typed-array-byte-length": "^1.0.1", "typed-array-byte-offset": "^1.0.2", "typed-array-length": "^1.0.5", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -30151,12 +30651,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -30199,26 +30693,25 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz", - "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==", + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", + "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", "dev": true, "dependencies": { - "asynciterator.prototype": "^1.0.0", "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.4", + "es-abstract": "^1.23.0", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.0" + "safe-array-concat": "^1.1.2" }, "engines": { "node": ">= 0.4" @@ -30230,6 +30723,18 @@ "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", "dev": true }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", @@ -30601,16 +31106,6 @@ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -30632,18 +31127,6 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint-plugin-jsx-a11y": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", @@ -30692,28 +31175,6 @@ "node": ">=4" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint-plugin-markdown": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-3.0.1.tgz", @@ -30756,9 +31217,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.34.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.0.tgz", - "integrity": "sha512-MeVXdReleBTdkz/bvcQMSnCXGi+c9kvy51IpinjnJgutl3YTHWsDdke7Z1ufZpGfDG8xduBDKyjtB9JH1eBKIQ==", + "version": "7.34.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", + "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", "dev": true, "dependencies": { "array-includes": "^3.1.7", @@ -30799,16 +31260,6 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -30821,18 +31272,6 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", @@ -30877,223 +31316,93 @@ "lodash": "^4.17.15" } }, - "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "node_modules/eslint-plugin-testing-library": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.0.tgz", + "integrity": "sha512-+LCYJU81WF2yQ+Xu4A135CgK8IszcFcyMF4sWkbiu6Oj+Nel0TrkZq/HvDw0/1WuO3dhDQsZA/OpEMGd0NfcUw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "@typescript-eslint/utils": "^5.58.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "eslint": "^7.5.0 || ^8.0.0" } }, - "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "node_modules/eslint-plugin-vitest": { + "version": "0.3.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.26.tgz", + "integrity": "sha512-oxe5JSPgRjco8caVLTh7Ti8PxpwJdhSV0hTQAmkFcNcmy/9DnqLB/oNVRA11RmVRP//2+jIIT6JuBEcpW3obYg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@typescript-eslint/utils": "^7.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.0.0 || >= 20.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "eslint": ">=8.0.0", + "vitest": "*" }, "peerDependenciesMeta": { - "typescript": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "vitest": { "optional": true } } }, - "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-storybook/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-plugin-storybook/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-plugin-storybook/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-plugin-storybook/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-plugin-storybook/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/eslint-plugin-testing-library": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.0.tgz", - "integrity": "sha512-+LCYJU81WF2yQ+Xu4A135CgK8IszcFcyMF4sWkbiu6Oj+Nel0TrkZq/HvDw0/1WuO3dhDQsZA/OpEMGd0NfcUw==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^5.58.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0", - "npm": ">=6" - }, - "peerDependencies": { - "eslint": "^7.5.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/scope-manager": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz", + "integrity": "sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/types": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.3.1.tgz", + "integrity": "sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz", + "integrity": "sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -31105,72 +31414,58 @@ } } }, - "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/utils": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.3.1.tgz", + "integrity": "sha512-jIERm/6bYQ9HkynYlNZvXpzmXWZGhMbrOvq3jJzOSOlKXsVjrrolzWBjDW6/TvT5Q3WqaN4EkmcfdQwi9tDjBQ==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/typescript-estree": "7.3.1", + "semver": "^7.5.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, - "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz", + "integrity": "sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "7.3.1", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-testing-library/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/eslint-plugin-vitest/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-plugin-testing-library/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" + "balanced-match": "^1.0.0" } }, - "node_modules/eslint-plugin-testing-library/node_modules/lru-cache": { + "node_modules/eslint-plugin-vitest/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", @@ -31182,86 +31477,19 @@ "node": ">=10" } }, - "node_modules/eslint-plugin-testing-library/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-plugin-testing-library/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/eslint-plugin-vitest": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.24.tgz", - "integrity": "sha512-MjxQCfOzLVJwi5EBHZYtv6zKHVUMRDh269D3KHCxHW0skoJhNDgE5MKvuxQ0Rh6B1aa6KuGUcvffRCdtN4Bg7A==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^7.1.1" - }, - "engines": { - "node": "^18.0.0 || >= 20.0.0" - }, - "peerDependencies": { - "eslint": ">=8.0.0", - "vitest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "vitest": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "node_modules/eslint-plugin-vitest/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "semver": "^7.5.4" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/eslint-plugin-vitest/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/eslint-plugin-vitest/node_modules/semver": { @@ -31313,16 +31541,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint/node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -31338,18 +31556,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -31473,12 +31679,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/estree-util-visit/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -31635,9 +31835,9 @@ } }, "node_modules/express": { - "version": "4.18.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", - "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.1.tgz", + "integrity": "sha512-K4w1/Bp7y8iSiVObmCrtq8Cs79XjJc/RU2YYkZQ7wpUu5ZyZ7MtPHkqoMz4pf+mgXfNvo2qft8D9OnrH2ABk9w==", "dev": true, "dependencies": { "accepts": "~1.3.8", @@ -31645,7 +31845,7 @@ "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -31973,6 +32173,15 @@ "minimatch": "^5.0.1" } }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/filelist/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -32150,15 +32359,6 @@ "find-process": "bin/find-process.js" } }, - "node_modules/find-process/node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -32201,18 +32401,18 @@ "dev": true }, "node_modules/flow-parser": { - "version": "0.230.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.230.0.tgz", - "integrity": "sha512-ZAfKaarESYYcP/RoLdM91vX0u/1RR7jI5TJaFLnxwRlC2mp0o+Rw7ipIY7J6qpIpQYtAobWb/J6S0XPeu0gO8g==", + "version": "0.231.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.231.0.tgz", + "integrity": "sha512-WVzuqwq7ZnvBceCG0DGeTQebZE+iIU0mlk5PmJgYj9DDrt+0isGC2m1ezW9vxL4V+HERJJo9ExppOnwKH2op6Q==", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -32647,28 +32847,6 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/global-modules": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", @@ -32843,16 +33021,6 @@ } } }, - "node_modules/graphql-config/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/graphql-config/node_modules/minimatch": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.3.tgz", @@ -33064,9 +33232,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -33713,6 +33881,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -34366,28 +34549,19 @@ "dev": true }, "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.4.tgz", + "integrity": "sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==", "dev": true, "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "istanbul-lib-coverage": "^3.0.0" }, "engines": { "node": ">=10" } }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/istanbul-reports": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", @@ -34450,28 +34624,6 @@ "node": ">=10" } }, - "node_modules/jake/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/jake/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/javascript-natural-sort": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", @@ -36505,9 +36657,9 @@ } }, "node_modules/markdown-to-jsx": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.1.tgz", - "integrity": "sha512-GbrbkTnHp9u6+HqbPRFJbObi369AgJNXi/sGqq5HRsoZW063xR1XDCaConqq+whfEIAlzB1YPnOgsPc7B7bc/A==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.4.tgz", + "integrity": "sha512-R9SGyfV2zsQx25YIYImACpiQ8dQe617CNyoE1wLst4wFHtiBGG3SEtJDlI1bt9SeotIcbITbVy9+ieQFWfEoQw==", "dev": true, "engines": { "node": ">= 10" @@ -36529,6 +36681,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-definitions/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", + "dev": true + }, "node_modules/mdast-util-definitions/node_modules/unist-util-is": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", @@ -36693,12 +36851,6 @@ "@types/unist": "*" } }, - "node_modules/mdast-util-gfm-footnote/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-from-markdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", @@ -36808,12 +36960,6 @@ "@types/unist": "*" } }, - "node_modules/mdast-util-gfm-strikethrough/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/mdast-util-gfm-strikethrough/node_modules/mdast-util-from-markdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", @@ -36925,12 +37071,6 @@ "@types/unist": "*" } }, - "node_modules/mdast-util-gfm-table/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/mdast-util-gfm-table/node_modules/mdast-util-from-markdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", @@ -37041,12 +37181,6 @@ "@types/unist": "*" } }, - "node_modules/mdast-util-gfm-task-list-item/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/mdast-util-gfm-task-list-item/node_modules/mdast-util-from-markdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", @@ -37141,12 +37275,6 @@ "@types/unist": "*" } }, - "node_modules/mdast-util-gfm/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/mdast-util-gfm/node_modules/mdast-util-from-markdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", @@ -37276,12 +37404,6 @@ "@types/unist": "*" } }, - "node_modules/mdast-util-mdx-expression/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/mdast-util-mdx-expression/node_modules/mdast-util-from-markdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", @@ -37368,9 +37490,9 @@ } }, "node_modules/mdast-util-mdx-jsx": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.1.tgz", - "integrity": "sha512-Di63TQEHbiApe6CFp/qQXCORHMHnmW2JFdr5PYH57LuEIPjijRHicAmL5wQu+B0/Q4p0qJaEOE1EkhiwxiNmAQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz", + "integrity": "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA==", "dev": true, "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -37401,12 +37523,6 @@ "@types/unist": "*" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/mdast-util-mdx-jsx/node_modules/character-entities": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", @@ -37601,12 +37717,6 @@ "@types/unist": "*" } }, - "node_modules/mdast-util-mdx/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/mdast-util-mdx/node_modules/mdast-util-from-markdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", @@ -37719,12 +37829,6 @@ "@types/unist": "*" } }, - "node_modules/mdast-util-mdxjs-esm/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/mdast-util-mdxjs-esm/node_modules/mdast-util-from-markdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", @@ -37862,12 +37966,6 @@ "@types/unist": "*" } }, - "node_modules/mdast-util-to-markdown/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/mdast-util-to-markdown/node_modules/mdast-util-to-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", @@ -38571,12 +38669,6 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, - "node_modules/micromark-util-events-to-acorn/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", @@ -38769,18 +38861,15 @@ } }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "*" } }, "node_modules/minimist": { @@ -38974,28 +39063,6 @@ "node": ">= 0.10.5" } }, - "node_modules/node-dir/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/node-dir/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -39017,9 +39084,9 @@ } }, "node_modules/node-fetch-native": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.2.tgz", - "integrity": "sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.3.tgz", + "integrity": "sha512-5kvcZPQYJBlUPgHxG0L8RJ52wiu2Sn5RAXBJlU6xPv8X+4MbeOxJ8Do9NFzD1RaWDDc1OF2VtBTgo+OKzg01uA==", "dev": true }, "node_modules/node-fetch/node_modules/tr46": { @@ -42349,6 +42416,20 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/nyc/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -42400,6 +42481,15 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/nyc/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -42685,28 +42775,29 @@ } }, "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -42716,16 +42807,17 @@ } }, "node_modules/object.groupby": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", - "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "dependencies": { - "array.prototype.filter": "^1.0.3", - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0" + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/object.hasown": { @@ -42742,14 +42834,14 @@ } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -43291,8 +43383,7 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -43422,9 +43513,9 @@ } }, "node_modules/postcss": { - "version": "8.4.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", - "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "dev": true, "funding": [ { @@ -43443,7 +43534,7 @@ "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -43739,9 +43830,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { @@ -43957,9 +44048,9 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/react-number-format": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.3.3.tgz", - "integrity": "sha512-maGHWmOvwYzyeRIpL0YC6drWqYaX6iFqjisdJXpZ+HzEtSEJsL6nqw4azTpF5Sm6SAvwUeAr7JY924Ebqq8EdA==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.3.4.tgz", + "integrity": "sha512-2hHN5mbLuCDUx19bv0Q8wet67QqYK6xmtLQeY5xx+h7UXiMmRtaCwqko4mMPoKXLc6xAzwRrutg8XbTRlsfjRg==", "dependencies": { "prop-types": "^15.7.2" }, @@ -44003,9 +44094,9 @@ } }, "node_modules/react-remove-scroll-bar": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.5.tgz", - "integrity": "sha512-3cqjOqg6s0XbOjWvmasmqHch+RLxIEk2r/70rzGXuz3iIGQsQheEQyqYCBb5EECoD01Vo2SIbDqW4paLeLTASw==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", + "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", "dev": true, "dependencies": { "react-style-singleton": "^2.2.1", @@ -44170,15 +44261,15 @@ } }, "node_modules/react-toastify": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.4.tgz", - "integrity": "sha512-etR3RgueY8pe88SA67wLm8rJmL1h+CLqUGHuAoNsseW35oTGJEri6eBTyaXnFKNQ80v/eO10hBYLgz036XRGgA==", + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz", + "integrity": "sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==", "dependencies": { "clsx": "^2.1.0" }, "peerDependencies": { - "react": ">=16", - "react-dom": ">=16" + "react": ">=18", + "react-dom": ">=18" } }, "node_modules/react-transition-group": { @@ -44197,9 +44288,9 @@ } }, "node_modules/react-virtuoso": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.7.2.tgz", - "integrity": "sha512-xF4es1ajK36Hs9MciaiGA9l16tV2bpkpgxM9JVKh0rJSn6uhdAUrxSQ6FttQOOPAGt4GRG2A4gdjlo18JWhyRw==", + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.7.4.tgz", + "integrity": "sha512-aYD+ClOCtYxURuT/GK5GamcD7XFTtmagKakEDQ07EyCPBUFy7Oc6xC2I24zSGcY5rDj+QZf/R5Iiks9Ael8pCA==", "engines": { "node": ">=10" }, @@ -44430,16 +44521,16 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", - "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0", - "get-intrinsic": "^1.2.3", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", "which-builtin-type": "^1.1.3" }, @@ -44595,6 +44686,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-external-links/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", + "dev": true + }, "node_modules/remark-external-links/node_modules/unist-util-is": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", @@ -44661,12 +44758,6 @@ "@types/unist": "*" } }, - "node_modules/remark-gfm/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/remark-mdx": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", @@ -44706,12 +44797,6 @@ "@types/unist": "*" } }, - "node_modules/remark-parse/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/remark-parse/node_modules/mdast-util-from-markdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", @@ -44812,6 +44897,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-slug/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", + "dev": true + }, "node_modules/remark-slug/node_modules/mdast-util-to-string": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", @@ -45146,13 +45237,13 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -45319,17 +45410,17 @@ "dev": true }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -45628,9 +45719,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -45961,34 +46052,41 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -45998,14 +46096,14 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -46466,28 +46564,6 @@ "node": ">=8" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -46727,9 +46803,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { "node": ">=16" @@ -46959,9 +47035,9 @@ } }, "node_modules/type-fest": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.12.0.tgz", - "integrity": "sha512-5Y2/pp2wtJk8o08G0CMkuFPCO354FGwk/vbidxrdhRGZfd0tFnb4Qb8anp9XxXriwBgVPjdWbKpGl4J9lJY2jQ==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.13.1.tgz", + "integrity": "sha512-ASMgM+Vf2cLwDMt1KXSkMUDSYCxtckDJs8zsaVF/mYteIsiARKCVtyXtcK38mIKbLTctZP8v6GMqdNaeI3fo7g==", "dev": true, "engines": { "node": ">=16" @@ -47072,9 +47148,9 @@ } }, "node_modules/typescript": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", - "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -47085,78 +47161,16 @@ } }, "node_modules/typescript-eslint": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.1.1.tgz", - "integrity": "sha512-vScnjSkm0pjZqySB5o8ZbfywfGWamVOqIGtJeOnUuDDGFaGKwMqdZWVa7EYKBnLCUSuwD8MN2a2ur9OgaKu6Tg==", - "dev": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "7.1.1", - "@typescript-eslint/parser": "7.1.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", - "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/type-utils": "7.1.1", - "@typescript-eslint/utils": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", - "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.3.1.tgz", + "integrity": "sha512-psqcnHPRCdVIDbgj6RvfpwUKqMcNxIw7eizgxYi46X2BmXK6LxYqPD+SbDfPuA9JW+yPItY6aKJLRNbW7lZ4rA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/utils": "7.1.1", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "@typescript-eslint/eslint-plugin": "7.3.1", + "@typescript-eslint/parser": "7.3.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -47171,64 +47185,6 @@ } } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/typescript-eslint/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/typescript-eslint/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/typescript-eslint/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/ua-parser-js": { "version": "1.0.37", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", @@ -47253,9 +47209,9 @@ } }, "node_modules/ufo": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", - "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", "dev": true }, "node_modules/uglify-js": { @@ -47405,11 +47361,14 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unified-engine/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true + "node_modules/unified-engine/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } }, "node_modules/unified-engine/node_modules/concat-stream": { "version": "2.0.0", @@ -47482,6 +47441,21 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/unified-engine/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/unified-engine/node_modules/parse-json": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", @@ -47525,12 +47499,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/unified/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -47556,12 +47524,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-inspect/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/unist-util-is": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", @@ -47575,12 +47537,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-is/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/unist-util-position-from-estree": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", @@ -47594,12 +47550,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-position-from-estree/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/unist-util-remove-position": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", @@ -47614,12 +47564,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-remove-position/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/unist-util-stringify-position": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", @@ -47633,6 +47577,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-stringify-position/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", + "dev": true + }, "node_modules/unist-util-visit": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", @@ -47662,18 +47612,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-visit-parents/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, - "node_modules/unist-util-visit/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -47832,9 +47770,9 @@ "dev": true }, "node_modules/use-callback-ref": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.1.tgz", - "integrity": "sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", + "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", "dev": true, "dependencies": { "tslib": "^2.0.0" @@ -48050,12 +47988,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/vfile-message/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/vfile-message/node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", @@ -48089,12 +48021,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/vfile-reporter/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/vfile-reporter/node_modules/emoji-regex": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", @@ -48171,12 +48097,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/vfile/node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, "node_modules/vfile/node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", @@ -48191,14 +48111,14 @@ } }, "node_modules/vite": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.5.tgz", - "integrity": "sha512-BdN1xh0Of/oQafhU+FvopafUp6WaYenLU/NFoL5WyJL++GxkNfieKzBhM24H3HVsPQrlAqB7iJYTHabzaRed5Q==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.2.tgz", + "integrity": "sha512-FWZbz0oSdLq5snUI0b6sULbz58iXFXdvkZfZWR/F0ZJuKTSPO7v72QPXt6KqYeMFb0yytNp6kZosxJ96Nr/wDQ==", "dev": true, "dependencies": { - "esbuild": "^0.19.3", - "postcss": "^8.4.35", - "rollup": "^4.2.0" + "esbuild": "^0.20.1", + "postcss": "^8.4.36", + "rollup": "^4.13.0" }, "bin": { "vite": "bin/vite.js" @@ -48246,9 +48166,9 @@ } }, "node_modules/vite-node": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.3.1.tgz", - "integrity": "sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.4.0.tgz", + "integrity": "sha512-VZDAseqjrHgNd4Kh8icYHWzTKSCZMhia7GyHfhtzLW33fZlG9SwsB6CEhgyVOWkJfJ2pFLrp/Gj1FSfAiqH9Lw==", "dev": true, "dependencies": { "cac": "^6.7.14", @@ -48282,14 +48202,14 @@ } }, "node_modules/vite-tsconfig-paths": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.1.tgz", - "integrity": "sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz", + "integrity": "sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==", "dev": true, "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", - "tsconfck": "^3.0.1" + "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" @@ -48301,9 +48221,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], @@ -48317,9 +48237,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], @@ -48333,9 +48253,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], @@ -48349,9 +48269,9 @@ } }, "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -48365,9 +48285,9 @@ } }, "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], @@ -48381,9 +48301,9 @@ } }, "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], @@ -48397,9 +48317,9 @@ } }, "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], @@ -48413,9 +48333,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], @@ -48429,9 +48349,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], @@ -48445,9 +48365,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], @@ -48461,9 +48381,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], @@ -48477,9 +48397,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], @@ -48493,9 +48413,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], @@ -48509,9 +48429,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], @@ -48525,9 +48445,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], @@ -48541,9 +48461,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], @@ -48557,9 +48477,9 @@ } }, "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], @@ -48573,9 +48493,9 @@ } }, "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], @@ -48589,9 +48509,9 @@ } }, "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], @@ -48605,9 +48525,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], @@ -48621,9 +48541,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], @@ -48637,9 +48557,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], @@ -48659,9 +48579,9 @@ "dev": true }, "node_modules/vite/node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "dev": true, "hasInstallScript": true, "bin": { @@ -48671,35 +48591,35 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/vite/node_modules/rollup": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.1.tgz", - "integrity": "sha512-ggqQKvx/PsB0FaWXhIvVkSWh7a/PCLQAsMjBc+nA2M8Rv2/HG0X6zvixAB7KyZBRtifBUhy5k8voQX/mRnABPg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz", + "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -48712,33 +48632,33 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.12.1", - "@rollup/rollup-android-arm64": "4.12.1", - "@rollup/rollup-darwin-arm64": "4.12.1", - "@rollup/rollup-darwin-x64": "4.12.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.12.1", - "@rollup/rollup-linux-arm64-gnu": "4.12.1", - "@rollup/rollup-linux-arm64-musl": "4.12.1", - "@rollup/rollup-linux-riscv64-gnu": "4.12.1", - "@rollup/rollup-linux-x64-gnu": "4.12.1", - "@rollup/rollup-linux-x64-musl": "4.12.1", - "@rollup/rollup-win32-arm64-msvc": "4.12.1", - "@rollup/rollup-win32-ia32-msvc": "4.12.1", - "@rollup/rollup-win32-x64-msvc": "4.12.1", + "@rollup/rollup-android-arm-eabi": "4.13.0", + "@rollup/rollup-android-arm64": "4.13.0", + "@rollup/rollup-darwin-arm64": "4.13.0", + "@rollup/rollup-darwin-x64": "4.13.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.13.0", + "@rollup/rollup-linux-arm64-gnu": "4.13.0", + "@rollup/rollup-linux-arm64-musl": "4.13.0", + "@rollup/rollup-linux-riscv64-gnu": "4.13.0", + "@rollup/rollup-linux-x64-gnu": "4.13.0", + "@rollup/rollup-linux-x64-musl": "4.13.0", + "@rollup/rollup-win32-arm64-msvc": "4.13.0", + "@rollup/rollup-win32-ia32-msvc": "4.13.0", + "@rollup/rollup-win32-x64-msvc": "4.13.0", "fsevents": "~2.3.2" } }, "node_modules/vitest": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.3.1.tgz", - "integrity": "sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.4.0.tgz", + "integrity": "sha512-gujzn0g7fmwf83/WzrDTnncZt2UiXP41mHuFYFrdwaLRVQ6JYQEiME2IfEjU3vcFL3VKa75XhI3lFgn+hfVsQw==", "dev": true, "dependencies": { - "@vitest/expect": "1.3.1", - "@vitest/runner": "1.3.1", - "@vitest/snapshot": "1.3.1", - "@vitest/spy": "1.3.1", - "@vitest/utils": "1.3.1", + "@vitest/expect": "1.4.0", + "@vitest/runner": "1.4.0", + "@vitest/snapshot": "1.4.0", + "@vitest/spy": "1.4.0", + "@vitest/utils": "1.4.0", "acorn-walk": "^8.3.2", "chai": "^4.3.10", "debug": "^4.3.4", @@ -48752,7 +48672,7 @@ "tinybench": "^2.5.1", "tinypool": "^0.8.2", "vite": "^5.0.0", - "vite-node": "1.3.1", + "vite-node": "1.4.0", "why-is-node-running": "^2.2.2" }, "bin": { @@ -48767,8 +48687,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.3.1", - "@vitest/ui": "1.3.1", + "@vitest/browser": "1.4.0", + "@vitest/ui": "1.4.0", "happy-dom": "*", "jsdom": "*" }, @@ -49139,9 +49059,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", @@ -49334,16 +49254,16 @@ "dev": true }, "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -49573,9 +49493,9 @@ } }, "node_modules/yarn": { - "version": "1.22.21", - "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.21.tgz", - "integrity": "sha512-ynXaJsADJ9JiZ84zU25XkPGOvVMmZ5b7tmTSpKURYwgELdjucAOydqIOrOfTxVYcNXe91xvLZwcRh68SR3liCg==", + "version": "1.22.22", + "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz", + "integrity": "sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg==", "dev": true, "hasInstallScript": true, "bin": { diff --git a/package.json b/package.json index d470c5e0..9204a79b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fixit-web", - "version": "1.3.1", + "version": "1.4.0-next.1", "description": "React-based web app for managing work orders, invoices, and payments.", "author": { "name": "Trevor Anderson", @@ -41,6 +41,7 @@ "build:staging": "vite build --mode staging", "build:analyze-bundle": "source-map-explorer 'dist/assets/*.js*' --html bundleAnalysisResult.html", "preview": "vite preview", + "open-api:update-types": "scripts/codegen.open-api.sh", "gql:update-schema": "rover graph fetch fixit@current > fixit@current.graphql", "postgql:update-schema": "graphql-codegen-esm --config codegen.ts" }, @@ -52,7 +53,7 @@ "@mui/material": "^5.13.6", "@mui/x-data-grid": "^6.9.1", "@mui/x-date-pickers": "^6.9.1", - "@nerdware/ts-string-helpers": "^1.1.2", + "@nerdware/ts-string-helpers": "^1.2.1", "@nerdware/ts-type-safety-utils": "^1.0.8", "@sentry/react": "^7.57.0", "@stripe/react-stripe-js": "^2.4.0", @@ -62,7 +63,7 @@ "chart.js": "^4.3.0", "chartjs-adapter-dayjs-4": "^1.0.4", "dayjs": "^1.11.8", - "formik": "^2.4.2", + "formik": "^2.4.5", "graphql": "^16.8.1", "jwt-decode": "^4.0.0", "lodash.merge": "^4.6.2", diff --git a/src/app/ApolloProvider/apolloCache/typePolicies/Query.ts b/src/app/ApolloProvider/apolloCache/typePolicies/Query.ts index faeaa96a..fa0166e0 100644 --- a/src/app/ApolloProvider/apolloCache/typePolicies/Query.ts +++ b/src/app/ApolloProvider/apolloCache/typePolicies/Query.ts @@ -72,7 +72,7 @@ export const queryTypePolicies: TypePolicies = { merge: helpers.mergeArrays, read: ( existing: Array = [], - { args, readField }: FieldFunctionOptions + { args, readField }: FieldFunctionOptions<{ handle?: string }> ) => { // This query should never run without a "handle" arg if (existing.length > 0 && args?.handle) { diff --git a/src/app/ApolloProvider/apolloCache/typePolicies/helpers.ts b/src/app/ApolloProvider/apolloCache/typePolicies/helpers.ts index e21d51cd..859003d0 100644 --- a/src/app/ApolloProvider/apolloCache/typePolicies/helpers.ts +++ b/src/app/ApolloProvider/apolloCache/typePolicies/helpers.ts @@ -1,4 +1,8 @@ -import type { FieldMergeFunction, FieldReadFunction } from "@apollo/client/cache"; +import type { + FieldMergeFunction, + FieldReadFunction, + FieldFunctionOptions, +} from "@apollo/client/cache"; /** * **Type Policy Helpers** @@ -14,11 +18,7 @@ import type { FieldMergeFunction, FieldReadFunction } from "@apollo/client/cache export const helpers = { mergeArrays: (existing = [], incoming) => [...existing, ...incoming], - paginatedMerge: ( - existing = [], - incoming, - { args }: { args: { offset?: number; limit?: number } | null } - ) => { + paginatedMerge: (existing = [], incoming, { args }) => { // Make a copy of existing array since it can't be mutated directly const merged = existing.slice(0); // Determine start and end indices @@ -45,11 +45,40 @@ export const helpers = { } as const satisfies { mergeArrays: ArrayFieldMergeFunction; paginatedMerge: ArrayFieldMergeFunction; - paginatedRead: ArrayFieldReadFunction; + paginatedRead: ArrayFieldReadFn; }; -type ArrayFieldMergeFunction = - FieldMergeFunction; +/** + * Apollo's {@link FieldMergeFunction} with array-specific default type params. + */ +type ArrayFieldMergeFunction< + TypeExisting extends unknown[] = unknown[], + TypeReadResult = TypeExisting, + TypeOpts extends ArrayFieldFnBaseOpts = ArrayFieldFnBaseOpts, +> = FieldMergeFunction; + +/** + * Apollo's {@link FieldReadFunction} with array-specific default type params. + */ +type ArrayFieldReadFn< + TypeExisting extends unknown[] = unknown[], + TypeReadResult = TypeExisting, + TypeOpts extends ArrayFieldFnBaseOpts = ArrayFieldFnBaseOpts, +> = FieldReadFunction; -type ArrayFieldReadFunction = - FieldReadFunction; +/** + * Base type for array type-policy read-function param: `options` + */ +type ArrayFieldFnBaseOpts = FieldFunctionOptions< + ArrayTypePolicyPaginationArgs, // <-- read fn param "options.args" + Record // <-- read fn param "options.vars" +>; + +/** + * Base type for array type-policy read-function param: `options.args` + */ +type ArrayTypePolicyPaginationArgs = { + offset?: number; + limit?: number; + [key: string]: unknown; +}; diff --git a/src/app/App.tsx b/src/app/App.tsx index be113bec..f8325963 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -5,6 +5,7 @@ import { RootAppRouter } from "@/routes/RootAppRouter"; import { ApolloProvider } from "./ApolloProvider"; import { FetchStateContextProvider } from "./FetchStateContext"; import { GlobalStyles } from "./GlobalStyles"; +import { GoogleOAuthContextProvider } from "./GoogleOAuthContext"; import { PageLayoutContextProvider } from "./PageLayoutContext"; import { ThemeProvider } from "./ThemeProvider"; import { DateTimeLocalizationProvider } from "./localization"; @@ -24,14 +25,16 @@ export const App = () => ( - - - - - - - - + + + + + + + + + + diff --git a/src/app/GlobalStyles/GlobalStyles.tsx b/src/app/GlobalStyles/GlobalStyles.tsx index ff9051ae..b52caca3 100644 --- a/src/app/GlobalStyles/GlobalStyles.tsx +++ b/src/app/GlobalStyles/GlobalStyles.tsx @@ -3,6 +3,7 @@ import { Global as EmotionGlobalStyle, css } from "@emotion/react"; import { useTheme } from "@mui/material/styles"; import { filledInputClasses } from "@mui/material/FilledInput"; import { inputBaseClasses } from "@mui/material/InputBase"; +import { globalAnimations } from "./animations"; import { useScrollbarStyles } from "./useScrollbarStyles"; import type { RootElementIdArg } from "./types"; @@ -46,6 +47,14 @@ export const GlobalStyles = ({ rootElementID = "root" }: RootElementIdArg) => { }, }, scrollbarStyles, + [ + Object.fromEntries( + Object.values(globalAnimations).map((animationConfig) => [ + `.${animationConfig.className}`, + animationConfig.styles, + ]) + ), + ], { /* For multiline Mui TextField inputs with variant="filled", this style moves padding from the InputBase to the textarea to ensure the scrollbar sits next @@ -60,7 +69,7 @@ export const GlobalStyles = ({ rootElementID = "root" }: RootElementIdArg) => { }, } ), - [rootElementID, scrollbarStyles, palette.background.default] + [rootElementID, scrollbarStyles, palette] ); return ; diff --git a/src/app/GlobalStyles/animations.ts b/src/app/GlobalStyles/animations.ts new file mode 100644 index 00000000..6d6b1d59 --- /dev/null +++ b/src/app/GlobalStyles/animations.ts @@ -0,0 +1,53 @@ +import { globalClassNames } from "./classNames"; +import type { CSSObject } from "@emotion/react"; +import type { SetRequired } from "type-fest"; + +export interface AnimationConfigObject { + className: string; + durationMS: number; + styles: SetRequired; +} + +/** + * Internal helper for creating CSS animation config objects. + */ +// prettier-ignore +const makeAnimationCssObject = ({ + className, animationName, durationMS, keyframes, timingFn = "ease-in-out", +}: { + className: string; animationName: T; durationMS: number; keyframes: CSSObject; timingFn?: string; +}): AnimationConfigObject => { + return { + className, + durationMS, + styles: { + animation: `${animationName} ${durationMS}ms ${timingFn}`, + [`@keyframes ${animationName}`]: { + ...keyframes + }, + }, + } as const; +}; + +export const globalAnimations = { + /** + * ### **`Wiggle-X Animation`** + * + * This object contains fields for implementing the **`Wiggle-X Animation`**: + * + * - `duration`: The duration of the animation in milliseconds. + * - `styles`: The {@link CSSObject} styles which define the animation (provided to `GlobalStyles`). + * - `className`: The CSS class name for adding the animation to components. + */ + wiggleX: makeAnimationCssObject({ + className: globalClassNames.animations.wiggleX, + animationName: "global-wiggle-x", + durationMS: 350, + keyframes: { + "0%": { transform: "translateX(0)" }, + "25%": { transform: "translateX(-15px)" }, + "75%": { transform: "translateX(15px)" }, + "100%": { transform: "translateX(0)" }, + }, + }), +} as const satisfies Record; diff --git a/src/app/GlobalStyles/classNames.ts b/src/app/GlobalStyles/classNames.ts index d140115f..96cb3cdc 100644 --- a/src/app/GlobalStyles/classNames.ts +++ b/src/app/GlobalStyles/classNames.ts @@ -1,27 +1,42 @@ +/** + * Internal helper for creating global class names with a consistent format. + */ +const makeGlobalClassName = (name: T) => `global-class__${name}` as const; + /** * Global class names used in the app. */ export const globalClassNames = { /** - * A class name which when applied to an element, will ensure a scrollbar is - * never visible on that element where/when applicable. The relevant styles - * applied to this class are defined in `useScrollbarStyles`. - */ - scrollbarForceHidden: "scrollbar-force-hidden", - /** - * A class name which when applied to an element, will ensure a scrollbar is - * visible on that element where/when applicable. The relevant styles applied - * to this class are defined in `useScrollbarStyles`. - * - * > This class uses darker colors than `scrollbarForceShowPaperBG`. + * Class names related to global scrollbar-psuedo-element styles. + * - See `src/app/GlobalStyles/useScrollbarStyles.ts` for details. */ - scrollbarForceShow: "scrollbar-force-show", + scrollbar: { + /** + * Ensure a scrollbar is never visible on an element. + */ + forceHidden: makeGlobalClassName("scrollbar-force-hidden"), + /** + * Ensure a scrollbar is visible on an element where/when applicable. + * > This class uses darker colors than `"scrollbar-force-show-paper-bg"`. + */ + forceShow: makeGlobalClassName("scrollbar-force-show"), + /** + * Ensure a scrollbar is visible on an element where/when applicable. + * > This class uses lighter colors than `"scrollbar-force-show"`. + */ + forceShowPaperBG: makeGlobalClassName("scrollbar-force-show-paper-bg"), + }, /** - * A class name which when applied to an element, will ensure a scrollbar is - * visible on that element where/when applicable. The relevant styles applied - * to this class are defined in `useScrollbarStyles`. - * - * > This class uses lighter colors than `scrollbarForceShow`. + * Class names related to global animation styles. + * - See `src/app/GlobalStyles/animations.ts` for details. */ - scrollbarForceShowPaperBG: "scrollbar-force-show-paper-bg", + animations: { + /** + * Performs a 350ms-long wiggle animation on the x-axis to achieve a "head shake"/"nuh-uh" + * effect. This is meant to convey to the User that they've not yet provided a required input, + * and/or that one or more of their inputs are invalid. + */ + wiggleX: makeGlobalClassName("animation__wiggle-x"), + }, } as const; diff --git a/src/app/GlobalStyles/useScrollbarStyles.ts b/src/app/GlobalStyles/useScrollbarStyles.ts index 941c79bd..798cc6b9 100644 --- a/src/app/GlobalStyles/useScrollbarStyles.ts +++ b/src/app/GlobalStyles/useScrollbarStyles.ts @@ -1,14 +1,17 @@ -import { css, type CSSObject, type SerializedStyles } from "@emotion/react"; import { alpha, type Theme } from "@mui/material/styles"; import { paperClasses } from "@mui/material/Paper"; import { globalClassNames } from "./classNames"; +import type { CSSObject } from "@emotion/react"; import type { RootElementIdArg } from "./types"; +/** + * SCROLLBAR STYLES + */ export const useScrollbarStyles = ({ palette, variables: { isMobilePageLayout }, rootElementID = "root", -}: Pick & RootElementIdArg): SerializedStyles => { +}: Pick & RootElementIdArg): Array => { // Shared/dependent scrollbar style values: const trackDefaultBackgroundColor = @@ -103,13 +106,13 @@ export const useScrollbarStyles = ({ // scrollbar-force-show, scrollbar-force-show-paper-bg (ensure scrollbar is visible) const scrollbarForceShowClassStyles = { - [`.${globalClassNames.scrollbarForceShow},.${globalClassNames.scrollbarForceShowPaperBG}`]: { + [`.${globalClassNames.scrollbar.forceShow},.${globalClassNames.scrollbar.forceShowPaperBG}`]: { "&::-webkit-scrollbar": scrollbarStyles.VISIBLE.SCROLLBAR, "&::-webkit-scrollbar-thumb": scrollbarStyles.VISIBLE.THUMB, "&::-webkit-scrollbar-corner": scrollbarStyles.VISIBLE.CORNER, // Track color depends on whether or not the -paper-bg class is used - [`&.${globalClassNames.scrollbarForceShow}::-webkit-scrollbar-track`]: scrollbarStyles.VISIBLE.TRACK, // prettier-ignore - [`&.${globalClassNames.scrollbarForceShowPaperBG}::-webkit-scrollbar-track`]: scrollbarStyles.VISIBLE.TRACK_PAPER_BG, // prettier-ignore + [`&.${globalClassNames.scrollbar.forceShow}::-webkit-scrollbar-track`]: scrollbarStyles.VISIBLE.TRACK, // prettier-ignore + [`&.${globalClassNames.scrollbar.forceShowPaperBG}::-webkit-scrollbar-track`]: scrollbarStyles.VISIBLE.TRACK_PAPER_BG, // prettier-ignore }, }; @@ -117,7 +120,7 @@ export const useScrollbarStyles = ({ // scrollbar-force-show, scrollbar-force-show-paper-bg (ensure scrollbar is visible) const scrollbarForceHiddenClassStyles = { - [`.${globalClassNames.scrollbarForceHidden}`]: { + [`.${globalClassNames.scrollbar.forceHidden}`]: { "&::-webkit-scrollbar": scrollbarForceHidden, "&::-webkit-scrollbar-thumb": scrollbarForceHidden, "&::-webkit-scrollbar-corner": scrollbarForceHidden, @@ -125,12 +128,12 @@ export const useScrollbarStyles = ({ }, }; - return css( + return [ globalDefaultScrollbarStyles, scrollbarForceShowClassStyles, scrollbarForceHiddenClassStyles, - bodyElementScrollbarStyles - ); + bodyElementScrollbarStyles, + ]; }; /** Dict of scrollbar pseudo-elements. */ diff --git a/src/app/GoogleOAuthContext/GoogleAuthFormButton.tsx b/src/app/GoogleOAuthContext/GoogleAuthFormButton.tsx new file mode 100644 index 00000000..36076e61 --- /dev/null +++ b/src/app/GoogleOAuthContext/GoogleAuthFormButton.tsx @@ -0,0 +1,227 @@ +import { useState, useEffect } from "react"; +import { useFormikContext, type FormikState } from "formik"; +import { jwtDecode } from "jwt-decode"; +import DialogTitle from "@mui/material/DialogTitle"; +import Text from "@mui/material/Typography"; +import GoogleIcon from "@mui/icons-material/Google"; +import { useFetchStateContext } from "@/app/FetchStateContext/useFetchStateContext"; +import { globalAnimations } from "@/app/GlobalStyles/animations"; +import { CloseIconButton } from "@/components/Buttons/CloseIconButton"; +import { Dialog } from "@/components/Dialog"; +import { GoogleOAuthButton, type GoogleOAuthButtonProps } from "./GoogleOAuthButton"; +import type { CredentialResponse } from "@/types/googleOAuth"; +import type { Except, OverrideProperties } from "type-fest"; + +type BaseAuthFormValues = { + [key: PropertyKey]: unknown; + // Fields used in both registration and login forms: + email: string; + googleIDToken: string | null; + password: string | null; +}; + +type FormikValuesErrorsTouched = Pick< + FormikState, + "values" | "errors" | "touched" +>; + +export type GoogleAuthFormButtonProps = + OverrideProperties< + Except, + { + text: Extract; + } + > & { + /** + * Required-field input elements to be displayed in the "required-fields" Dialog if their + * respective values are not present in the Form context upon the User's completion of the + * Google OAuth prompt flow. + */ + requiredFieldInputs: React.ReactNode; + /** + * A hook for transforming the Formik state object. After the User completes the Google OAuth + * prompt flow, this component makes a best effort to ascertain desired values for Formik state + * objects — `values`, `errors`, and `touched` — using a combination of the Google OAuth2 ID + * token and current Form state. It then passes these values to `beforeSetFormikState` to allow + * the User to configure the Formik state as desired. + * > Use this function to handle state updates for form fields this component does not handle. + */ + beforeSetFormikState?: ( + formikState: FormikValuesErrorsTouched + ) => FormikValuesErrorsTouched; + }; + +/** + * A button that prompts the User to sign in or sign up with Google OAuth2. When the User + * completes the Google OAuth prompt flow, this component makes a best effort to ascertain + * desired values for Formik state objects — `values`, `errors`, and `touched` — for the + * following common auth-form fields: + * + * - `email` + * - `googleIDToken` + * - `password` + * + * Other form fields are supported via hook props like `beforeSetFormikState`. + */ +export const GoogleAuthFormButton = ({ + text, // "signin_with" or "signup_with" + requiredFieldInputs, + beforeSetFormikState, + ...googleOAuthButtonProps +}: GoogleAuthFormButtonProps) => { + const formikContext = useFormikContext(); + const { values, errors, touched } = formikContext; + const { setValues, setErrors, setTouched, validateForm, handleSubmit } = formikContext; + + const { setError: setFetchError } = useFetchStateContext(); + const { isDialogVisible, openDialog, closeDialog } = Dialog.use(); + const [shouldWiggle, setShouldWiggle] = useState(false); + + // See below remarks regarding the Formik stale-values bug and workaround. + // TODO Remove this state once Formik PR is merged + const [shouldSubmit, setShouldSubmit] = useState(false); + /** + * EFFECT: Run `handleSubmit` when `shouldSubmit` is `true`. + * + * This effect is a workaround for an existing Formik bug whereby validation runs on + * stale values if `touched` is manually updated, as is done in the `handleSuccess` + * function below. Links to the relevant issue and PR are below. Once the PR is merged, + * this effect can be removed, along with the `shouldSubmit` state (we'll be able to + * just call `handleSubmit`). + * + * ISSUE: https://github.com/jaredpalmer/formik/issues/2083 + * PR: https://github.com/jaredpalmer/formik/pull/3947 + * + * // TODO Remove this useEffect and `shouldSubmit` state once Formik PR is merged + */ + useEffect(() => { + if (shouldSubmit) { + handleSubmit(); + setShouldSubmit(false); + } + }, [shouldSubmit, handleSubmit]); + + const handleError = () => { + setFetchError( + new Error( + "Oops! We were unable to obtain valid login credentials from Google — please try again." + ) + ); + }; + + const handleSuccess = async (credentialResponse: CredentialResponse) => { + const googleIDToken = credentialResponse.credential; + + // If the User hasn't provided an email, try to extract it from the Google ID token: + let newEmailValue = values.email; + + if (!newEmailValue) { + try { + const payload = jwtDecode<{ email?: string }>(googleIDToken); + if (payload?.email) newEmailValue = payload.email; + } catch { + handleError(); + return; + } + } + + // Pass the Formik state to the `beforeSetFormikState` function to allow for any additional + // state updates that are not handled by the `GoogleAuthFormButton` component itself. + let newFormikState: FormikValuesErrorsTouched = { + values: { + ...values, + googleIDToken, + email: newEmailValue, + password: null, // Ensure `password` is null + }, + errors: { + ...errors, + googleIDToken: undefined, // Should already be undefined, but just in case + email: newEmailValue ? undefined : "Please provide an email", + password: undefined, // Is now null, so clear any errors + }, + touched: { + ...touched, + googleIDToken: true, + email: true, + password: true, + }, + }; + + // If `beforeSetFormikState` was provided, use it to update the Formik state object + if (beforeSetFormikState) newFormikState = beforeSetFormikState(newFormikState); + + // Perform all state updates at once via `setFormikState` + await setValues(newFormikState.values, true); + await setTouched(newFormikState.touched, false); + setErrors(newFormikState.errors); + + // If the new state lists any errors, open the "required-fields" Dialog, else submit the form + if (Object.values(newFormikState.errors).some(Boolean)) openDialog(); + else setShouldSubmit(true); // TODO <-- replace this with `handleSubmit` once Formik PR is merged + }; + + /** When the User clicks "OK", validate the form and close the dialog if there are no errors. */ + const handleAcceptDialog = async () => { + await validateForm(); + + if (Object.values(errors).some(Boolean)) { + setShouldWiggle(true); + setTimeout(() => setShouldWiggle(false), 1000); + } else { + handleCloseDialog(); + } + }; + + /** Close dialog, submit form. */ + const handleCloseDialog = () => { + closeDialog(); + handleSubmit(); + }; + + const { dialogTitle, promptMessage } = + text === "signup_with" + ? { + dialogTitle: "Sign Up with Google", + promptMessage: "Please provide these required fields to complete your registration:", + } + : { + dialogTitle: "Sign In with Google", + promptMessage: "Please provide these required fields to continue:", + }; + + return ( + <> + + + {dialogTitle} + + + } + isVisible={isDialogVisible} + handleAccept={handleAcceptDialog} + onClose={handleCloseDialog} + PaperProps={{ className: shouldWiggle ? globalAnimations.wiggleX.className : undefined }} + dialogContentProps={{ + sx: { + padding: "1.5rem 1.5rem 0.5rem 1.5rem", + gap: "0.5rem !important", + }, + }} + > + {promptMessage} + {requiredFieldInputs} + + + ); +}; diff --git a/src/app/GoogleOAuthContext/GoogleOAuthButton.stories.tsx b/src/app/GoogleOAuthContext/GoogleOAuthButton.stories.tsx new file mode 100644 index 00000000..598891d5 --- /dev/null +++ b/src/app/GoogleOAuthContext/GoogleOAuthButton.stories.tsx @@ -0,0 +1,35 @@ +import { GoogleOAuthButton } from "./GoogleOAuthButton"; +import type { Meta, StoryObj } from "@storybook/react"; + +const meta = { + title: "Components/Buttons/GoogleOAuthButton", + component: GoogleOAuthButton, + decorators: [ + (Story) => ( +
+ +
+ ), + ], + args: { + onSuccess: () => { + console.debug(`◐ — [GoogleLogin] — onSuccess callback called!`); + }, + type: "standard", + size: "large", + shape: "pill", + }, +} satisfies Meta; + +export default meta; + +/////////////////////////////////////////////////////////// +// STORIES + +type Story = StoryObj; + +export const BasicDemo = { + args: { + text: "signin_with", + }, +} satisfies Story; diff --git a/src/app/GoogleOAuthContext/GoogleOAuthButton.tsx b/src/app/GoogleOAuthContext/GoogleOAuthButton.tsx new file mode 100644 index 00000000..e1d228ac --- /dev/null +++ b/src/app/GoogleOAuthContext/GoogleOAuthButton.tsx @@ -0,0 +1,148 @@ +import { useEffect, useRef } from "react"; +import { useTheme } from "@mui/material/styles"; +import Box, { type BoxProps } from "@mui/material/Box"; +import { + IdConfiguration, + CredentialResponse, + GoogleCredentialResponse, + MomentListener, + GsiButtonConfiguration, +} from "@/types/googleOAuth"; +import { useGoogleOAuthContext } from "./GoogleOAuthContext"; +import { extractClientID } from "./helpers"; +import type { Except } from "type-fest"; + +export type GoogleOAuthButtonProps = { + onSuccess: (credentialResponse: CredentialResponse) => void; + onError?: () => void; + promptMomentNotification?: MomentListener; + useOneTap?: boolean; + containerProps?: Except; +} & Omit & + Omit; + +export const GoogleOAuthButton = ({ + onSuccess, + onError, + useOneTap, + promptMomentNotification, + type = "standard", + size = "large", + shape = "pill", + theme: buttonTheme, + text, + logo_alignment, + locale, + click_listener, + containerProps = {}, + use_fedcm_for_prompt = true, + ...props // <-- passed to `google.accounts.id.initialize` +}: GoogleOAuthButtonProps) => { + const btnContainerRef = useRef(null); + const { clientID, hasGoogleOAuthScriptLoadedSuccessfully } = useGoogleOAuthContext(); + + const onSuccessRef = useRef(onSuccess); + onSuccessRef.current = onSuccess; + + const onErrorRef = useRef(onError); + onErrorRef.current = onError; + + const promptMomentNotificationRef = useRef(promptMomentNotification); + promptMomentNotificationRef.current = promptMomentNotification; + + // Set default button "theme" if not provided + const { palette, variables } = useTheme(); + if (!buttonTheme) { + buttonTheme = palette.mode === "dark" ? "outline" : "filled_blue"; + } + + // Determine the `width` based on mobile/desktop: + const width = variables.isMobilePageLayout + ? GOOGLE_OAUTH_BTN_DIMENSIONS.WIDTH.MOBILE + : GOOGLE_OAUTH_BTN_DIMENSIONS.WIDTH.DESKTOP; + + useEffect(() => { + if (!hasGoogleOAuthScriptLoadedSuccessfully) return; + + // The context provider ensures that the google.accounts.id library is loaded + const googleAPI = window.google!; + + googleAPI.accounts.id.initialize({ + client_id: clientID, + callback: (credentialResponse: GoogleCredentialResponse) => { + if (!credentialResponse?.credential) { + return onErrorRef.current?.(); + } + + const { credential, select_by } = credentialResponse; + onSuccessRef.current({ + credential, + clientId: extractClientID(credentialResponse), + select_by, + }); + }, + use_fedcm_for_prompt, + ...props, + }); + + googleAPI.accounts.id.renderButton(btnContainerRef.current!, { + type, + theme: buttonTheme, + size, + text, + shape, + logo_alignment, + width, + locale, + click_listener, + }); + + if (useOneTap) googleAPI.accounts.id.prompt(promptMomentNotificationRef.current); + + return () => { + if (useOneTap) googleAPI.accounts.id.cancel(); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + clientID, + hasGoogleOAuthScriptLoadedSuccessfully, + useOneTap, + type, + buttonTheme, + size, + text, + shape, + logo_alignment, + locale, + ]); + + return ( + + ); +}; + +/** + * The width+height of the Google Login button, in pixels (not currently configurable). + */ +export const GOOGLE_OAUTH_BTN_DIMENSIONS = { + HEIGHT: 40, + WIDTH: { + MOBILE: 304, + DESKTOP: 320, + }, +} as const; + +/** + * Class names used by the `GoogleAuthButton` component. + */ +export const googleOAuthButtonClassNames = { + root: "google-open-auth-button__root", +} as const; diff --git a/src/app/GoogleOAuthContext/GoogleOAuthContext.tsx b/src/app/GoogleOAuthContext/GoogleOAuthContext.tsx new file mode 100644 index 00000000..09ffe54c --- /dev/null +++ b/src/app/GoogleOAuthContext/GoogleOAuthContext.tsx @@ -0,0 +1,69 @@ +import { createContext, useContext, useState, useEffect, useMemo } from "react"; +import { isFunction } from "@nerdware/ts-type-safety-utils"; +import { ENV } from "@/app/env"; + +export interface GoogleOAuthContextProps { + clientID: string; + hasGoogleOAuthScriptLoadedSuccessfully: boolean; +} + +export const GoogleOAuthContext = createContext({ + clientID: "", + hasGoogleOAuthScriptLoadedSuccessfully: false, +}); + +export const useGoogleOAuthContext = () => useContext(GoogleOAuthContext); + +export const GoogleOAuthContextProvider = ({ children }: { children: React.ReactNode }) => { + const [hasGoogleOAuthScriptLoadedSuccessfully, setHasGoogleOAuthScriptLoadedSuccessfully] = + useState(false); + + /** + * EFFECT: If GoogleOAuth SHOULD be enabled in the env, then ensure the Google OAuth + * client lib script loaded successfully, and update the associated state variable. + */ + useEffect(() => { + /** + * Only run hook logic if `GOOGLE_OAUTH_CLIENT_ID` is present and the necessary + * script has not yet been confirmed to have successfully loaded. + */ + if (ENV.GOOGLE_OAUTH_CLIENT_ID.length > 0 && !hasGoogleOAuthScriptLoadedSuccessfully) { + // Async IIFE to run the google-lib-checking logic with a 1s interval: + (async () => { + // Array to hold any setTimeout timerIDs used in the retry logic: + const timeoutTimerIDs: NodeJS.Timeout[] = []; + // Make 3 attempts to check if the google lib has loaded successfully: + for (let i = 0; i < 3; i++) { + if (hasGoogleOAuthScriptLoadedSuccessfully) break; + + if (isFunction(window.google?.accounts?.id?.initialize)) { + setHasGoogleOAuthScriptLoadedSuccessfully(true); + } else { + // Else wait 1s, add the timerID to the array, and try again + const timeoutTimerID = await new Promise((resolve) => + setTimeout(resolve, 1000) + ); + + timeoutTimerIDs.push(timeoutTimerID); + } + } + // Ensure any timers that had to be set are cleared: + if (timeoutTimerIDs.length > 0) { + timeoutTimerIDs.forEach((timerID) => clearTimeout(timerID)); + } + })(); + } + }, [hasGoogleOAuthScriptLoadedSuccessfully]); + + const contextValues = useMemo( + () => ({ + clientID: ENV.GOOGLE_OAUTH_CLIENT_ID, + hasGoogleOAuthScriptLoadedSuccessfully, + }), + [hasGoogleOAuthScriptLoadedSuccessfully] + ); + + return ( + {children} + ); +}; diff --git a/src/app/GoogleOAuthContext/helpers.ts b/src/app/GoogleOAuthContext/helpers.ts new file mode 100644 index 00000000..dcf9d294 --- /dev/null +++ b/src/app/GoogleOAuthContext/helpers.ts @@ -0,0 +1,57 @@ +import { GoogleCredentialResponse, TokenResponse } from "@/types/googleOAuth"; + +export const extractClientID = ( + credentialResponse: GoogleCredentialResponse +): string | undefined => { + return credentialResponse?.clientId ?? credentialResponse?.client_id; +}; + +/** + * When using one-tap login, when logging user out, consider [this issue][link] + * may happen. To prevent it, call this function when logging user out. + * + * [link]: https://developers.google.com/identity/gsi/web/guides/automatic-sign-in-sign-out#sign-out + */ +export const googleLogout = () => { + window?.google?.accounts?.id?.disableAutoSelect(); +}; + +/** + * Checks if the user granted all the specified scope or scopes + * @returns True if all the scopes are granted + */ +export const hasGrantedAllScopesGoogle = ( + tokenResponse: TokenResponse, + firstScope: string, + ...restScopes: string[] +): boolean => { + if (!window?.google) return false; + + return ( + window?.google?.accounts?.oauth2?.hasGrantedAllScopes( + tokenResponse, + firstScope, + ...restScopes + ) || false + ); +}; + +/** + * Checks if the user granted any of the specified scope or scopes. + * @returns True if any of the scopes are granted + */ +export const hasGrantedAnyScopeGoogle = ( + tokenResponse: TokenResponse, + firstScope: string, + ...restScopes: string[] +): boolean => { + if (!window?.google) return false; + + return ( + window?.google?.accounts?.oauth2?.hasGrantedAnyScope( + tokenResponse, + firstScope, + ...restScopes + ) || false + ); +}; diff --git a/src/app/GoogleOAuthContext/index.ts b/src/app/GoogleOAuthContext/index.ts new file mode 100644 index 00000000..a7dc141d --- /dev/null +++ b/src/app/GoogleOAuthContext/index.ts @@ -0,0 +1,9 @@ +export * from "./GoogleOAuthContext"; + +export * from "./GoogleOAuthButton"; +export * from "./GoogleAuthFormButton"; + +export * from "./useGoogleLogin"; +export * from "./useGoogleOneTapLogin"; + +export * from "./helpers"; diff --git a/src/app/GoogleOAuthContext/useGoogleLogin.ts b/src/app/GoogleOAuthContext/useGoogleLogin.ts new file mode 100644 index 00000000..0b348975 --- /dev/null +++ b/src/app/GoogleOAuthContext/useGoogleLogin.ts @@ -0,0 +1,122 @@ +import { useCallback, useEffect, useRef } from "react"; +import { + GoogleOAuthTokenClient, + GoogleOAuthCodeClient, + TokenClientConfig, + TokenResponse, + CodeClientConfig, + CodeResponse, + OverridableTokenClientConfig, + NonOAuthError, +} from "@/types/googleOAuth"; +import { useGoogleOAuthContext } from "./GoogleOAuthContext"; + +interface ImplicitFlowOptions extends Omit { + onSuccess?: ( + tokenResponse: Omit + ) => void; + onError?: ( + errorResponse: Pick + ) => void; + onNonOAuthError?: (nonOAuthError: NonOAuthError) => void; + scope?: TokenClientConfig["scope"]; + overrideScope?: boolean; +} + +interface AuthCodeFlowOptions extends Omit { + onSuccess?: ( + codeResponse: Omit + ) => void; + onError?: ( + errorResponse: Pick + ) => void; + onNonOAuthError?: (nonOAuthError: NonOAuthError) => void; + scope?: CodeResponse["scope"]; + overrideScope?: boolean; +} + +export type GoogleLoginFlow = "implicit" | "auth-code"; + +export type UseGoogleLoginOptionsImplicitFlow = { + flow?: "implicit"; +} & ImplicitFlowOptions; + +export type UseGoogleLoginOptionsAuthCodeFlow = { + flow?: "auth-code"; +} & AuthCodeFlowOptions; + +export type UseGoogleLoginOptions = + | UseGoogleLoginOptionsImplicitFlow + | UseGoogleLoginOptionsAuthCodeFlow; + +/** + * Interface defining two overloads for `useGoogleLogin` hook: + * 1. Hook used for the implicit flow + * 2. Hook used for the auth code flow + */ +export interface UseGoogleLoginHook { + (options: UseGoogleLoginOptionsImplicitFlow): (overrideConfig?: OverridableTokenClientConfig) => void; // prettier-ignore + (options: UseGoogleLoginOptionsAuthCodeFlow): () => void; +} + +export const useGoogleLogin: UseGoogleLoginHook = ({ + flow = "implicit", + scope = "", + onSuccess, + onError, + onNonOAuthError, + overrideScope, + state, + ...sharedClientInitOpts +}: UseGoogleLoginOptions) => { + const { clientID, hasGoogleOAuthScriptLoadedSuccessfully } = useGoogleOAuthContext(); + const clientRef = useRef(); + + const onSuccessRef = useRef(onSuccess); + onSuccessRef.current = onSuccess; + + const onErrorRef = useRef(onError); + onErrorRef.current = onError; + + const onNonOAuthErrorRef = useRef(onNonOAuthError); + onNonOAuthErrorRef.current = onNonOAuthError; + + useEffect(() => { + if (!hasGoogleOAuthScriptLoadedSuccessfully) return; + + // The context provider ensures that the google.accounts.id library is loaded + const googleAPI = window.google!; + + const clientMethod = flow === "implicit" ? "initTokenClient" : "initCodeClient"; + + const client = googleAPI.accounts.oauth2[clientMethod]({ + client_id: clientID, + scope: overrideScope ? scope : `openid profile email ${scope}`, + callback: (response) => { + if (response.error) return onErrorRef.current?.(response); + onSuccessRef.current?.(response as any); + }, + error_callback: (nonOAuthError: NonOAuthError) => { + onNonOAuthErrorRef.current?.(nonOAuthError); + }, + state, + ...sharedClientInitOpts, + }); + + clientRef.current = client; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [clientID, hasGoogleOAuthScriptLoadedSuccessfully, flow, scope, state]); + + const loginImplicitFlow = useCallback( + (overrideConfig?: OverridableTokenClientConfig) => + (clientRef.current as GoogleOAuthTokenClient)?.requestAccessToken(overrideConfig), + [] + ); + + const loginAuthCodeFlow = useCallback( + () => (clientRef.current as GoogleOAuthCodeClient)?.requestCode(), + [] + ); + + return flow === "implicit" ? loginImplicitFlow : loginAuthCodeFlow; +}; diff --git a/src/app/GoogleOAuthContext/useGoogleOneTapLogin.ts b/src/app/GoogleOAuthContext/useGoogleOneTapLogin.ts new file mode 100644 index 00000000..6dcf2020 --- /dev/null +++ b/src/app/GoogleOAuthContext/useGoogleOneTapLogin.ts @@ -0,0 +1,111 @@ +import { useEffect, useRef } from "react"; +import { useFetchStateContext } from "@/app/FetchStateContext/useFetchStateContext"; +import { useGoogleOAuthContext } from "./GoogleOAuthContext"; +import { extractClientID } from "./helpers"; +import type { + CredentialResponse, + GoogleCredentialResponse, + IdConfiguration, + MomentListener, + Context, +} from "@/types/googleOAuth"; + +interface UseGoogleOneTapLoginOptions { + onSuccess: (credentialResponse: CredentialResponse) => void; + onError?: () => void; + promptMomentNotification?: MomentListener; + context?: Context; + hosted_domain?: string; + prompt_parent_id?: string; + state_cookie_domain?: string; + use_fedcm_for_prompt?: IdConfiguration["use_fedcm_for_prompt"]; + cancel_on_tap_outside?: boolean; + auto_select?: boolean; + disabled?: boolean; +} + +export const useGoogleOneTapLogin = ({ + onSuccess, + onError, + promptMomentNotification, + context, + hosted_domain, + prompt_parent_id, + state_cookie_domain, + use_fedcm_for_prompt = true, + cancel_on_tap_outside = false, + auto_select = true, + disabled = false, +}: UseGoogleOneTapLoginOptions): void => { + const { clientID, hasGoogleOAuthScriptLoadedSuccessfully } = useGoogleOAuthContext(); + + const onSuccessRef = useRef(onSuccess); + onSuccessRef.current = onSuccess; + + const onErrorRef = useRef(onError); + onErrorRef.current = onError; + + const promptMomentNotificationRef = useRef(promptMomentNotification); + promptMomentNotificationRef.current = promptMomentNotification; + + const { setError: setFetchError } = useFetchStateContext(); + + useEffect(() => { + if (!hasGoogleOAuthScriptLoadedSuccessfully) return; + + // The context provider ensures that the google.accounts.id library is loaded + const googleAPI = window.google!; + + if (disabled) { + googleAPI.accounts.id.cancel(); + return; + } + + googleAPI.accounts.id.initialize({ + client_id: clientID, + callback: (credentialResponse: GoogleCredentialResponse) => { + if (!credentialResponse?.credential) { + setFetchError( + new Error( + "Oops! We were unable to obtain valid login credentials from Google — please try again." + ) + ); + return onErrorRef.current?.(); + } + + const { credential, select_by } = credentialResponse; + + onSuccessRef.current({ + credential, + clientId: extractClientID(credentialResponse), + select_by, + }); + }, + context, + hosted_domain, + prompt_parent_id, + state_cookie_domain, + use_fedcm_for_prompt, + cancel_on_tap_outside, + auto_select, + }); + + googleAPI.accounts.id.prompt(promptMomentNotificationRef.current); + + return () => { + googleAPI.accounts.id.cancel(); + }; + }, [ + clientID, + hasGoogleOAuthScriptLoadedSuccessfully, + context, + hosted_domain, + prompt_parent_id, + state_cookie_domain, + use_fedcm_for_prompt, + cancel_on_tap_outside, + auto_select, + disabled, + setFetchError, + ]); +}; diff --git a/src/app/ThemeProvider/components.ts b/src/app/ThemeProvider/components.ts index c08719d8..af0393f2 100644 --- a/src/app/ThemeProvider/components.ts +++ b/src/app/ThemeProvider/components.ts @@ -1,3 +1,4 @@ +import { tooltipClasses } from "@mui/material/Tooltip"; import type { Theme } from "@mui/material/styles"; /** @@ -124,6 +125,21 @@ export const COMPONENTS = { MuiTooltip: { defaultProps: { arrow: true, + PopperProps: { + sx: { + [`& > .${tooltipClasses.tooltip}`]: { + backgroundColor: "rgb(97,97,97)", // rm's the usual 0.92 alpha from tooltip bg + whiteSpace: "nowrap", + minWidth: "min-content", + maxWidth: "unset", + [`& > .${tooltipClasses.arrow}`]: { + "&::before": { + backgroundColor: "rgb(97,97,97)", + }, + }, + }, + }, + }, }, styleOverrides: { tooltip: { diff --git a/src/app/ThemeProvider/palettes.ts b/src/app/ThemeProvider/palettes.ts index 9747271e..cf19c080 100644 --- a/src/app/ThemeProvider/palettes.ts +++ b/src/app/ThemeProvider/palettes.ts @@ -11,8 +11,8 @@ import type { ConditionalKeys } from "type-fest"; */ export type PaletteColorKey = ConditionalKeys; -const DARK_PALETTE_NAME = "DARK" as const; -const LIGHT_PALETTE_NAME = "LIGHT" as const; +const DARK_PALETTE_NAME = "DARK"; +const LIGHT_PALETTE_NAME = "LIGHT"; export const PALETTE_NAMES = [DARK_PALETTE_NAME, LIGHT_PALETTE_NAME] as const; @@ -77,8 +77,8 @@ export const PALETTES = Object.fromEntries( paletteName === DARK_PALETTE_NAME ? { light: "#ffd900", - main: "#b69b00", - dark: "#a87b00", + main: "#c4bb00", + dark: "#b09f02", } : { light: "#ff9800", // MUI default diff --git a/src/app/env.ts b/src/app/env.ts index 0f2eccc3..f739d720 100644 --- a/src/app/env.ts +++ b/src/app/env.ts @@ -18,13 +18,14 @@ const API_HOSTS_BY_MODE: Partial>> = { const IS_DEV = import.meta.env.DEV; const IS_PROD = import.meta.env.PROD; -const IS_STORYBOOK = !!import.meta.env?.STORYBOOK; +const IS_STORYBOOK = !!import.meta.env.STORYBOOK; const PROJECT_VERSION = import.meta.env.VITE_PROJECT_VERSION; const SENTRY_DSN = import.meta.env.VITE_SENTRY_DSN; -const API_PROTOCOL = import.meta.env?.VITE_API_PROTOCOL || "https"; -const API_HOST = import.meta.env?.VITE_API_HOST || (API_HOSTS_BY_MODE?.[MODE] ?? "localhost"); -const API_BASE_PATH = import.meta.env?.VITE_API_BASE_PATH || "/api"; +const API_PROTOCOL = import.meta.env.VITE_API_PROTOCOL || "https"; +const API_HOST = import.meta.env.VITE_API_HOST || (API_HOSTS_BY_MODE?.[MODE] ?? "localhost"); +const API_BASE_PATH = import.meta.env.VITE_API_BASE_PATH || "/api"; const STRIPE_PUBLISHABLE_KEY = import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY; +const GOOGLE_OAUTH_CLIENT_ID = import.meta.env.VITE_GOOGLE_OAUTH_CLIENT_ID || ""; // Define the API's origin: const API_ORIGIN = `${API_PROTOCOL}://${API_HOST}`; @@ -49,4 +50,5 @@ export const ENV = { /** `"[API_PROTOCOL]://[API_HOST][API_BASE_PATH]"` */ API_URI: `${API_ORIGIN}${API_BASE_PATH}`, STRIPE_PUBLISHABLE_KEY, + GOOGLE_OAUTH_CLIENT_ID, } as const; diff --git a/src/app/localization/setupYup.ts b/src/app/localization/setupYup.ts index a74aabe2..c0d36882 100644 --- a/src/app/localization/setupYup.ts +++ b/src/app/localization/setupYup.ts @@ -1,4 +1,4 @@ -import { setLocale } from "yup"; +import { setLocale, type Message } from "yup"; setLocale({ mixed: { @@ -8,4 +8,10 @@ setLocale({ min: "Must be at least ${min} characters long", max: "Must be fewer than ${max} characters", }, -}); +} as const satisfies Record< + string, // "mixed" | "string" + Record< + string, // "required", "min", "max" + Message<{ [key: string]: unknown }> // <-- overrides Message default type param `any` + > +>); diff --git a/src/components/Alerts/PaymentRequiredToast.tsx b/src/components/Alerts/PaymentRequiredToast.tsx index 28e0942e..12aad1e6 100644 --- a/src/components/Alerts/PaymentRequiredToast.tsx +++ b/src/components/Alerts/PaymentRequiredToast.tsx @@ -28,7 +28,7 @@ export const PaymentRequiredToast = ({ closeToast }: PaymentRequiredToastProps) : "OK"} handleAccept={handleAccept} handleCancel={handleCancel} diff --git a/src/components/AppBar/AppBarLogoButton.tsx b/src/components/AppBar/AppBarLogoButton.tsx index 78735bfe..711f47e3 100644 --- a/src/components/AppBar/AppBarLogoButton.tsx +++ b/src/components/AppBar/AppBarLogoButton.tsx @@ -1,5 +1,7 @@ import { styled } from "@mui/material/styles"; +import CircularProgress, { circularProgressClasses } from "@mui/material/CircularProgress"; import Text, { typographyClasses } from "@mui/material/Typography"; +import { useFetchStateContext } from "@/app/FetchStateContext"; import { Logo, brandingClassNames } from "@/components/Branding"; import { Anchor } from "@/components/Navigation/Anchor"; import { APP_PATHS } from "@/routes/appPaths"; @@ -7,12 +9,16 @@ import { isAuthenticatedStore } from "@/stores"; export const AppBarLogoButton = () => { const isAuthenticated = isAuthenticatedStore.useSubToStore(); + const { isLoading } = useFetchStateContext(); return ( - + - - Fixit + {isLoading && } + + + Fixit + ); @@ -24,9 +30,35 @@ const StyledDiv = styled("div")(({ theme: { palette, variables } }) => ({ alignItems: "center", "& > a": { - // Increase the anchor's default hover-opacity (0.7) + position: "relative", + + // Increase the anchor's default hover-opacity from 0.7 to 0.75 "&:hover": { - opacity: 0.75, + // Why do the css selection like this? To avoid dimming the root app loading indicator. + [`& > .${brandingClassNames.fixitLogoImg},.${typographyClasses.root}`]: { + opacity: 0.75, + }, + }, + + // ROOT APP LOADING INDICATOR + // Note: This is only shown if `isLoading` prop is set true in the top-most FetchStateContext. + [`& > .${circularProgressClasses.root}`]: { + position: "absolute", + display: "flex", + alignItems: "center", + justifyContent: "center", + // These values ensure the spinner appears to go around the Logo img: + ...(variables.isMobilePageLayout + ? { height: "90% !important", left: "2px" } + : { height: "100% !important", left: "-2px" }), + [`& > svg.${circularProgressClasses.svg}`]: { + overflow: "visible", + // Like the parent el's height+left props, this height centers the spinner: + height: variables.isMobilePageLayout ? "130%" : "120%", + "& > circle": { + strokeWidth: variables.isMobilePageLayout ? "4px" : "5px", + }, + }, }, [`& > .${brandingClassNames.fixitLogoImg}`]: { diff --git a/src/components/AppBar/AppBarMenu/MobileAppBarMenu.tsx b/src/components/AppBar/AppBarMenu/MobileAppBarMenu.tsx index 7e7094c1..c4471df3 100644 --- a/src/components/AppBar/AppBarMenu/MobileAppBarMenu.tsx +++ b/src/components/AppBar/AppBarMenu/MobileAppBarMenu.tsx @@ -4,9 +4,9 @@ import IconButton from "@mui/material/IconButton"; import List, { listClasses } from "@mui/material/List"; import ListItemButton, { listItemButtonClasses } from "@mui/material/ListItemButton"; import { paperClasses } from "@mui/material/Paper"; -import CloseIcon from "@mui/icons-material/Close"; import MenuIcon from "@mui/icons-material/Menu"; import { AvatarMyProfile } from "@/components/Avatar/AvatarMyProfile"; +import { CloseIconButton } from "@/components/Buttons/CloseIconButton"; import { MobileModalContentBox } from "@/components/Modal/MobileModalContentBox"; import { DarkModeSwitch } from "./DarkModeSwitch"; import { MobileAppBarMenuAuthButton } from "./MobileAppBarMenuAuthButton"; @@ -23,17 +23,15 @@ export const MobileAppBarMenu = () => { return ( <> {isModalOpen ? ( - - - + /> ) : appState.isAccountActive === true ? ( ) : ( - - + + )} @@ -69,7 +67,7 @@ const StyledMobileModalContentBox = styled(MobileModalContentBox)({ height: "3.25rem", padding: "2rem", justifyContent: "space-between", - } + }, }, }, }); diff --git a/src/components/Branding/GitHubLogo.tsx b/src/components/Branding/GitHubLogo.tsx new file mode 100644 index 00000000..8258d360 --- /dev/null +++ b/src/components/Branding/GitHubLogo.tsx @@ -0,0 +1,23 @@ +import { getInlineSvgDataUrl } from "@/app/GlobalStyles/helpers"; +import GitHubLogoSVG from "@/images/github_logo.svg"; +import type { Except } from "type-fest"; + +export const GitHubLogo = ({ alt = "GitHub", style = {}, ...imgProps }: GitHubLogoProps) => ( + {alt} + + ` + ), + ...style, + }} + {...imgProps} + /> +); + +export type GitHubLogoProps = Except, "src">; diff --git a/src/components/Branding/StripeBadge.tsx b/src/components/Branding/StripeBadge.tsx index 96c52227..ce6b378f 100644 --- a/src/components/Branding/StripeBadge.tsx +++ b/src/components/Branding/StripeBadge.tsx @@ -1,3 +1,4 @@ +import { styled } from "@mui/material/styles"; import Tooltip, { type TooltipProps } from "@mui/material/Tooltip"; import { Anchor, type AnchorProps } from "@/components/Navigation/Anchor"; import StripeBadgeSVG from "@/images/powered_by_Stripe_purple.svg"; @@ -5,33 +6,52 @@ import { brandingClassNames } from "./classNames"; import type { Simplify, Except } from "type-fest"; export const StripeBadge = ({ - href = "https://stripe.com/", + href = STRIPE_LINKS.LANDING_PAGE, tabIndex = -1, tooltipProps: { title, ...tooltipProps } = {}, anchorProps = {}, ...imgProps }: StripeBadgeProps) => ( - Stripe Badge - + ); +/** + * A collection of links to Stripe's website. + */ +export const STRIPE_LINKS = { + LANDING_PAGE: "https://stripe.com/", + CONNECT_ACCOUNT_AGREEMENT: "https://stripe.com/connect-account/legal/full", +} as const satisfies Record; + +const StyledAnchor = styled(Anchor)({ + display: "contents", + + [`& > .${brandingClassNames.stripeBadgeImg}`]: { + height: "100%", + minHeight: "1.5rem !important", // smaller than this, and the text is too small on most screens + maxHeight: "3rem !important", // currently no reason the badge should ever be taller than this + objectFit: "contain", + }, +}); + export type StripeBadgeProps = { - href?: string; + href?: (typeof STRIPE_LINKS)[keyof typeof STRIPE_LINKS]; tooltipProps?: Simplify>>; anchorProps?: Simplify>; } & Except, "src" | "className" | "children">; diff --git a/src/components/Branding/TitleLogo.tsx b/src/components/Branding/TitleLogo.tsx index d9ce64c3..c74c9bc0 100644 --- a/src/components/Branding/TitleLogo.tsx +++ b/src/components/Branding/TitleLogo.tsx @@ -4,14 +4,25 @@ import { Logo } from "./Logo"; import { brandingClassNames } from "./classNames"; export const TitleLogo = ({ + size = "3rem", onClick, + style: containerStyle = {}, logoStyle = {}, textStyle = {}, ...divProps }: TitleLogoProps) => ( - - - + + + Fixit @@ -25,11 +36,14 @@ const StyledDiv = styled("div")(({ onClick }) => ({ alignItems: "center", justifyContent: "center", verticalAlign: "middle", - gap: "0.5rem", + + // gap uses 'ch' units in order to scale relative to fontSize in this div + gap: "0.5ch", + fontSize: "3rem", [`& > .${brandingClassNames.titleLogoText}`]: { + fontSize: "inherit !important", // For proper scaling, this must be set to 'inherit' margin: 0, - fontSize: "3rem", }, ...(onClick && { @@ -40,6 +54,7 @@ const StyledDiv = styled("div")(({ onClick }) => ({ })); export type TitleLogoProps = { + size?: string; onClick?: React.MouseEventHandler; logoStyle?: React.CSSProperties; textStyle?: React.CSSProperties; diff --git a/src/components/Branding/classNames.ts b/src/components/Branding/classNames.ts index e9a955dd..459437cc 100644 --- a/src/components/Branding/classNames.ts +++ b/src/components/Branding/classNames.ts @@ -4,8 +4,7 @@ export const brandingClassNames = { fixitLogoImg: "fixit-logo__img", - stripeBadgeRoot: "stripe-badge__root", - stripeBadgeAnchor: "stripe-badge__anchor", + stripeBadgeAnchor: "stripe-badge__anchor", // component root stripeBadgeImg: "stripe-badge__img", titleLogoRoot: "title-logo__root", diff --git a/src/components/Branding/index.ts b/src/components/Branding/index.ts index c08a7305..f33e6730 100644 --- a/src/components/Branding/index.ts +++ b/src/components/Branding/index.ts @@ -1,3 +1,4 @@ +export * from "./GitHubLogo"; export * from "./Logo"; export * from "./StripeBadge"; export * from "./TitleLogo"; diff --git a/src/components/Buttons/CloseIconButton.tsx b/src/components/Buttons/CloseIconButton.tsx new file mode 100644 index 00000000..9ec562ef --- /dev/null +++ b/src/components/Buttons/CloseIconButton.tsx @@ -0,0 +1,18 @@ +import IconButton, { type IconButtonProps } from "@mui/material/IconButton"; +import CloseIcon from "@mui/icons-material/Close"; +import type { SvgIconProps } from "@mui/material/SvgIcon"; +import type { Except } from "type-fest"; + +export const CloseIconButton = ({ + iconProps = {}, + "aria-label": ariaLabel = "close", + ...iconButtonProps +}: CloseIconButtonProps) => ( + + + +); + +export type CloseIconButtonProps = Except & { + iconProps?: SvgIconProps; +}; diff --git a/src/components/Checklist/Checklist.tsx b/src/components/Checklist/Checklist.tsx index da4812e0..068f95e5 100644 --- a/src/components/Checklist/Checklist.tsx +++ b/src/components/Checklist/Checklist.tsx @@ -56,7 +56,7 @@ export const Checklist = < role="list" // see jsdoc for details on why this is needed className={[ checklistClassNames.scrollableListContainer, - globalClassNames.scrollbarForceShowPaperBG, + globalClassNames.scrollbar.forceShowPaperBG, ].join(" ")} > {checklistItems.map((item, index) => diff --git a/src/components/DataDisplay/DividerWithText.tsx b/src/components/DataDisplay/DividerWithText.tsx new file mode 100644 index 00000000..449b08f1 --- /dev/null +++ b/src/components/DataDisplay/DividerWithText.tsx @@ -0,0 +1,17 @@ +import { styled } from "@mui/material/styles"; +import Divider, { dividerClasses, type DividerProps } from "@mui/material/Divider"; + +/** + * A Mui Divider styled to center text content (works best if `children` is a string). + */ +export const DividerWithText = styled(Divider)({ + margin: "0.5rem", + [`& > .${dividerClasses.wrapper}`]: { + display: "flex", + justifyContent: "center", + alignItems: "center", + minWidth: "4ch", + }, +}); + +export type DividerWithTextProps = DividerProps; diff --git a/src/components/DataDisplay/ItemDetails.tsx b/src/components/DataDisplay/ItemDetails.tsx index 636ce5cf..120b0687 100644 --- a/src/components/DataDisplay/ItemDetails.tsx +++ b/src/components/DataDisplay/ItemDetails.tsx @@ -1,3 +1,4 @@ +import { isString } from "@nerdware/ts-type-safety-utils"; import { styled } from "@mui/material/styles"; import Box, { type BoxProps } from "@mui/material/Box"; import Text from "@mui/material/Typography"; @@ -39,7 +40,7 @@ export const ItemDetails = ({ /> )}
- {typeof children === "string" ? {children || "--"} : children ?? emptyFallback} + {isString(children) ? {children || "--"} : children ?? emptyFallback}
); diff --git a/src/components/DataDisplay/LocationDetails.tsx b/src/components/DataDisplay/LocationDetails.tsx index f730001d..7a110a49 100644 --- a/src/components/DataDisplay/LocationDetails.tsx +++ b/src/components/DataDisplay/LocationDetails.tsx @@ -1,3 +1,4 @@ +import { isString } from "@nerdware/ts-type-safety-utils"; import { styled } from "@mui/material/styles"; import Tooltip from "@mui/material/Tooltip"; import Text, { type TypographyProps } from "@mui/material/Typography"; @@ -9,18 +10,40 @@ import { dataDisplayClassNames } from "./classNames"; import type { Location } from "@/graphql/types"; import type { SetOptional } from "type-fest"; +export type LocationDetailsProps = Partial & { + showLabel?: boolean; +} & ItemDetailsProps; + +type LocationDetailsContentProps = { + location: SetOptional; + locationTextProps: TypographyProps; +}; + export const LocationDetails = ({ location, locationTextProps = {}, showLabel = true, className = "", ...itemDetailsProps -}: LocationDetailsProps) => { - const { streetLine1, streetLine2, city, region, country } = location ?? {}; +}: LocationDetailsProps) => ( + + {location && ( + + )} + +); +const LocationDetailsContent = ({ + location: { streetLine1, streetLine2, city, region, country }, + locationTextProps, +}: LocationDetailsContentProps) => { // For display purposes, filter out falsey values (null/empty strings) const locationStringsArray = [streetLine1, streetLine2, city, region, country].filter( - (locationValue) => typeof locationValue === "string" && locationValue + (locationValue) => isString(locationValue) && locationValue ); const addressStr = locationStringsArray.join(", "); @@ -29,34 +52,26 @@ export const LocationDetails = ({ const mapLink = `https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent(addressStr)}`; return ( - - {location && ( - <> - - {streetLine1} - {streetLine2 && ( - <> - {`\n`} - {streetLine2} - - )} + <> + + {streetLine1} + {streetLine2 && ( + <> {`\n`} - {`${city}, `} - {region} - - - - - Map it - - - - )} - + {streetLine2} + + )} + {`\n`} + {`${city}, `} + {region} +
+ + + + Map it + + + ); }; @@ -111,9 +126,3 @@ const StyledItemDetails = styled(ItemDetails)(({ theme: { palette, variables } } }, }, })); - -export type LocationDetailsProps = { - location?: SetOptional; - locationTextProps?: TypographyProps; - showLabel?: boolean; -} & ItemDetailsProps; diff --git a/src/components/DataDisplay/index.ts b/src/components/DataDisplay/index.ts index 181b2c83..6b97492e 100644 --- a/src/components/DataDisplay/index.ts +++ b/src/components/DataDisplay/index.ts @@ -1,6 +1,7 @@ export * from "./ItemDetails"; export * from "./ItemDetailsGroup"; +export * from "./DividerWithText"; export * from "./HelpInfoIcon"; export * from "./InvoiceWorkOrderDetails"; export * from "./LocationDetails"; diff --git a/src/components/DataGrid/styles.printMedia.ts b/src/components/DataGrid/styles.printMedia.ts index 8ffdda1f..d234b8e4 100644 --- a/src/components/DataGrid/styles.printMedia.ts +++ b/src/components/DataGrid/styles.printMedia.ts @@ -1,7 +1,7 @@ import { alpha, darken } from "@mui/material/styles"; import { THEMES } from "@/app/ThemeProvider"; import { dataGridClassNames } from "./classNames"; -import type { SxPropsWithTheme } from "@/app/ThemeProvider/helpers"; +import type { CSSObject } from "@emotion/react"; /** * When the 'print' option is selected in the 'export' menu, all color-related @@ -48,4 +48,4 @@ export const dataGridStyledPrintMedia = { }, }, }, -} as const satisfies SxPropsWithTheme; +} as const satisfies CSSObject; diff --git a/src/components/DevTools/DemoInfo.tsx b/src/components/DevTools/DemoInfo.tsx new file mode 100644 index 00000000..f7c17ca2 --- /dev/null +++ b/src/components/DevTools/DemoInfo.tsx @@ -0,0 +1,82 @@ +import { Fragment } from "react"; +import Divider from "@mui/material/Divider"; +import List from "@mui/material/List"; +import Stack, { type StackProps } from "@mui/material/Stack"; +import Text from "@mui/material/Typography"; +import ConstructionIcon from "@mui/icons-material/Construction"; +import GppGoodIcon from "@mui/icons-material/GppGood"; +import MoneyOffIcon from "@mui/icons-material/MoneyOff"; +import { GitHubLogo } from "@/components/Branding/GitHubLogo"; +import { Anchor } from "@/components/Navigation/Anchor"; +import { APP_LINKS } from "@/routes/appLinks"; +import { DemoInfoListItem } from "./DemoInfoListItem"; +import { DemoModeStatement } from "./DemoModeStatement"; +import { StripeTestCardInfo } from "./StripeTestCardInfo"; + +export const DemoInfo = ({ + initShowStripeTestCardInfo = false, + spacing = "1rem", + alignItems = "center", + ...stackProps +}: DemoInfoProps = {}) => ( + + + Explore a feature-rich modern SaaS web application. + + + + {[ + { + Icon: MoneyOffIcon, + summary: "Transactions never involve real money.", + isInitiallyOpen: initShowStripeTestCardInfo, + details: , + }, + { + Icon: GppGoodIcon, + summary: + "Advanced encryption and cybersecurity best practices keep user data safe throughout the application.", + details: ( + + Security is always a top priority at every level of the application stack. Even though + this is a demo application, all user data is securely encrypted, transmitted, and + stored in accordance with industry standards and best practices. + + ), + }, + { + Icon: ConstructionIcon, + summary: "Dev tools give you the flexibility to explore.", + details: ( + + Feel free to explore the application and find inspiration for your own projects. + + ), + }, + ].map(({ Icon, summary, details, isInitiallyOpen = false }, index) => ( + + {index !== 0 && ( + + )} + + + ))} + + + + + View this project on GitHub + + + + +); + +export type DemoInfoProps = { + initShowStripeTestCardInfo?: boolean; +} & Omit; diff --git a/src/components/DevTools/DemoInfoDialog.stories.tsx b/src/components/DevTools/DemoInfoDialog.stories.tsx new file mode 100644 index 00000000..51f1be14 --- /dev/null +++ b/src/components/DevTools/DemoInfoDialog.stories.tsx @@ -0,0 +1,22 @@ +import { withNavDecorator } from "@/../.storybook/decorators"; +import { DemoInfoDialog } from "./DemoInfoDialog"; +import type { Meta, StoryObj } from "@storybook/react"; + +const meta = { + title: "Components/DevTools/DemoInfoDialog", + component: DemoInfoDialog, + decorators: [withNavDecorator], +} satisfies Meta; + +export default meta; + +/////////////////////////////////////////////////////////// +// STORIES + +type Story = StoryObj; + +export const BasicDemo = { + args: { + isVisible: true, + }, +} satisfies Story; diff --git a/src/components/DevTools/DemoInfoDialog.tsx b/src/components/DevTools/DemoInfoDialog.tsx new file mode 100644 index 00000000..0d68dd88 --- /dev/null +++ b/src/components/DevTools/DemoInfoDialog.tsx @@ -0,0 +1,50 @@ +import { useState, useEffect } from "react"; +import { ENV } from "@/app/env"; +import { DemoInfo, type DemoInfoProps } from "@/components/DevTools/DemoInfo"; +import { Dialog, type DialogProps, type UseDialogHookProps } from "@/components/Dialog"; +import type { SetOptional } from "type-fest"; + +export const DemoInfoDialog = ({ + title = `Welcome to Fixit — Demo Mode`, + isVisible, + closeDialog, + style = {}, + sx, + initShowStripeTestCardInfo = false, +}: DemoInfoDialogProps) => { + return ( + + + + ); +}; + +export const useDemoInfoDialog = () => { + const [hasInstanceBeenViewed, setHasInstanceBeenViewed] = useState(false); + const { isDialogVisible, openDialog, closeDialog } = Dialog.use(); + + // EFFECT: Open the demo-info dialog in staging/demo deployed envs when the component mounts + useEffect(() => { + if (ENV.IS_DEPLOYED_ENV && !ENV.IS_PROD && !hasInstanceBeenViewed) { + setHasInstanceBeenViewed(true); + openDialog(); + } + }, [hasInstanceBeenViewed, openDialog]); + + return { + isDialogVisible, + closeDialog, + }; +}; + +DemoInfoDialog.use = useDemoInfoDialog; + +export type DemoInfoDialogProps = DemoInfoProps & + Pick, "title" | "isVisible" | "style" | "sx"> & + Pick; diff --git a/src/components/DevTools/DemoInfoListItem.tsx b/src/components/DevTools/DemoInfoListItem.tsx new file mode 100644 index 00000000..d9c412ba --- /dev/null +++ b/src/components/DevTools/DemoInfoListItem.tsx @@ -0,0 +1,90 @@ +import React, { useState } from "react"; +import { styled } from "@mui/material/styles"; +import Avatar, { avatarClasses } from "@mui/material/Avatar"; +import Collapse, { collapseClasses } from "@mui/material/Collapse"; +import ListItemAvatar, { listItemAvatarClasses } from "@mui/material/ListItemAvatar"; +import ListItemButton from "@mui/material/ListItemButton"; +import ListItemIcon from "@mui/material/ListItemIcon"; +import ListItemText from "@mui/material/ListItemText"; +import SvgIcon, { svgIconClasses } from "@mui/material/SvgIcon"; +import { typographyClasses } from "@mui/material/Typography"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; + +export const DemoInfoListItem = ({ + isInitiallyOpen = false, + Icon, + summary, + details, +}: DemoInfoListItemProps) => { + const [isOpen, setIsOpen] = useState(isInitiallyOpen); + + const handleClick = () => setIsOpen(!isOpen); + + return ( + <> + + + + + + + {summary} + + + + + + + {details} + + + + ); +}; + +const StyledListItemButton = styled(ListItemButton)(({ theme: { palette } }) => ({ + gap: "1rem", + + [`& + .${collapseClasses.root}`]: { + // The text in the Collapse-div should appear horiz-inline with the above text: + paddingLeft: "5.5rem", + }, + + [`& > .${listItemAvatarClasses.root}`]: { + opacity: 0.85, + + [`& > .${avatarClasses.root}`]: { + ...(palette.mode === "light" && { + backgroundColor: palette.background.paper, + backgroundImage: "unset", + border: `0.25rem solid ${palette.success.main}`, + }), + }, + }, + + [`& .${svgIconClasses.root}`]: { + fontSize: "1.75rem", + }, +})); + +export type DemoInfoListItemProps = { + isInitiallyOpen?: boolean; + Icon: typeof SvgIcon; + summary: React.ReactNode; + details: React.ReactNode; +}; diff --git a/src/components/DevTools/DemoModeStatement.tsx b/src/components/DevTools/DemoModeStatement.tsx new file mode 100644 index 00000000..8542909b --- /dev/null +++ b/src/components/DevTools/DemoModeStatement.tsx @@ -0,0 +1,29 @@ +import { styled } from "@mui/material/styles"; +import Box, { type BoxProps } from "@mui/material/Box"; +import Text from "@mui/material/Typography"; +import AnnouncementIcon from "@mui/icons-material/Announcement"; +import type { Except } from "type-fest"; + +export const DemoModeStatement = ({ variant, ...boxProps }: DemoModeStatementProps) => ( + + + + You're viewing this application in "demo" mode + {variant === "long" ? `,\nwhich is for demonstration purposes only` : ""}. + + +); + +const StyledBox = styled(Box)(({ theme: { palette } }) => ({ + display: "flex", + alignItems: "flex-start", + justifyContent: "center", + gap: "0.5rem", + "& *": { + color: palette.warning.main, + }, +})); + +export type DemoModeStatementProps = { + variant: "short" | "long"; +} & Except; diff --git a/src/components/DevTools/DemoStripeCardInfoAccordion.tsx b/src/components/DevTools/DemoStripeCardInfoAccordion.tsx new file mode 100644 index 00000000..dce95b22 --- /dev/null +++ b/src/components/DevTools/DemoStripeCardInfoAccordion.tsx @@ -0,0 +1,59 @@ +import Accordion from "@mui/material/Accordion"; +import AccordionDetails from "@mui/material/AccordionDetails"; +import AccordionSummary from "@mui/material/AccordionSummary"; +import Box from "@mui/material/Box"; +import Text from "@mui/material/Typography"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import { Anchor } from "@/components/Navigation/Anchor"; +import { DemoModeStatement } from "./DemoModeStatement"; +import { StripeTestCardInfo } from "./StripeTestCardInfo"; + +export const DemoStripeCardInfoAccordion = () => { + return ( + ({ + border: `1px solid ${palette.warning.main}`, + borderRadius: "0.25rem", + })} + > + ({ + padding: "1rem", + justifyContent: "flex-start", + backgroundColor: palette.warning.main, + "& *": { + color: palette.getContrastText(palette.warning.main), + }, + })} + /> + + } + id="stripe-card-info-summary" + aria-controls="stripe-card-info-details" + sx={({ palette }) => ({ + gap: "1rem", + "&:hover": { + backgroundColor: palette.action.hover, + }, + })} + > + + Click here to learn how to use the{" "} + + {`Stripe-provided\ntest card number`} + {" "} + for testing this payment flow. + + + + + + + + ); +}; diff --git a/src/components/DevTools/StripeTestCardInfo.tsx b/src/components/DevTools/StripeTestCardInfo.tsx new file mode 100644 index 00000000..2d10e25c --- /dev/null +++ b/src/components/DevTools/StripeTestCardInfo.tsx @@ -0,0 +1,82 @@ +import { styled } from "@mui/material/styles"; +import List, { listClasses } from "@mui/material/List"; +import Stack, { type StackProps } from "@mui/material/Stack"; +import { Anchor } from "@/components/Navigation/Anchor"; +import { ClickToCopyText, textClassNames } from "@/components/Text"; +import type { Except } from "type-fest"; + +/** + * This component provides the user with information about using Stripe's test + * card numbers for testing payment flows. + */ +export const StripeTestCardInfo = ({ + spacing = "0.5rem", + ...stackProps +}: StripeTestCardInfoProps) => ( + + +
  • + All Stripe API calls are invoked with{" "} + test mode keys. +
  • +
  • + To test one of the payment flows, use the{" "} + + Stripe-provided test card number + {" "} + in any payment form:{" "} +
      +
    • + For the card number, enter{" "} + 4242 4242 4242 4242 +
    • +
    • For the exp date, use any valid future date.
    • +
    • For the CVC, use any 3 digits.
    • +
    • For the postal code, use any valid US zip code.
    • +
    +
  • +
    + Example: + Stripe test card details +
    +); + +const StyledStack = styled(Stack)(({ theme: { variables } }) => ({ + [`& > .${listClasses.root}`]: { + padding: "0 0 0 1.25rem", + + "& > li": { + listStyleType: "disc", + marginTop: "0.25rem", + + "& > ul > li": { + marginTop: "0.25rem", + ...(!variables.isMobilePageLayout && { + maxHeight: "1.5rem", + }), + + [`& > .${textClassNames.clickToCopyTextRoot}`]: { + transform: "translateY(-1px)", + }, + }, + }, + }, + "& img": { + boxShadow: "0 0 0.25rem rgba(0,0,0,0.5)", + borderRadius: "0.25rem", + marginBottom: "0.5rem", + }, +})); + +export type StripeTestCardInfoProps = Except; diff --git a/src/components/DevTools/index.ts b/src/components/DevTools/index.ts index aa61802b..c34e2327 100644 --- a/src/components/DevTools/index.ts +++ b/src/components/DevTools/index.ts @@ -1,4 +1,3 @@ export * from "./DevTools"; - -// re-exported as default for lazy loading (see AppBar): -export { DevTools as default } from "./DevTools"; +export * from "./DemoInfo"; +export * from "./DemoInfoDialog"; diff --git a/src/components/Dialog/Dialog.tsx b/src/components/Dialog/Dialog.tsx index c129ed04..8fe5b388 100644 --- a/src/components/Dialog/Dialog.tsx +++ b/src/components/Dialog/Dialog.tsx @@ -1,33 +1,41 @@ +import React from "react"; +import { isString } from "@nerdware/ts-type-safety-utils"; import { styled } from "@mui/material/styles"; import { backdropClasses } from "@mui/material/Backdrop"; import Button, { buttonClasses } from "@mui/material/Button"; import MuiDialog, { dialogClasses, type DialogProps as MuiDialogProps } from "@mui/material/Dialog"; import DialogActions, { dialogActionsClasses } from "@mui/material/DialogActions"; -import DialogContent, { dialogContentClasses } from "@mui/material/DialogContent"; +import DialogContent, { + dialogContentClasses, + type DialogContentProps, +} from "@mui/material/DialogContent"; import DialogContentText from "@mui/material/DialogContentText"; -import DialogTitle, { dialogTitleClasses } from "@mui/material/DialogTitle"; -import IconButton, { iconButtonClasses } from "@mui/material/IconButton"; +import DialogTitle, { dialogTitleClasses, type DialogTitleProps } from "@mui/material/DialogTitle"; +import { iconButtonClasses } from "@mui/material/IconButton"; import { typographyClasses } from "@mui/material/Typography"; -import CloseIcon from "@mui/icons-material/Close"; +import { CloseIconButton } from "@/components/Buttons/CloseIconButton"; import { SlideTransition } from "@/components/Transitions/SlideTransition"; import { dialogElementIDs } from "./elementIDs"; import { useDialog } from "./useDialog"; +import type { Except } from "type-fest"; /** * Docs: https://mui.com/components/dialogs/ */ -export const Dialog = ({ +export const Dialog = ({ isVisible = true, title, + dialogTitleProps, message, children, + dialogContentProps = {}, handleAccept, handleCancel, acceptLabel = "OK", cancelLabel = "CANCEL", showCancelButton = true, - ...containerProps -}: DialogProps) => ( + ...dialogProps +}: DialogProps) => ( - - {title} - {handleCancel && ( - - - - )} - - - {typeof message === "string" ? ( + {isString(title) ? ( + + {title} + {handleCancel && } + + ) : ( + title + )} + + {isString(message) ? ( {message} ) : ( message ?? children @@ -78,8 +86,9 @@ const StyledMuiDialog = styled(MuiDialog)(({ theme: { variables, breakpoints } } [`& .${iconButtonClasses.root}`]: { position: "absolute", - top: "0.5rem", right: "0.5rem", + top: "50%", + transform: "translateY(-50%)", color: "rgb(150,150,150)", }, }, @@ -118,15 +127,24 @@ const StyledMuiDialog = styled(MuiDialog)(({ theme: { variables, breakpoints } } }, })); -export type DialogProps = { +export type DialogProps = Except< + MuiDialogProps, + "title" | "open" +> & { /** Whether or not the Dialog is visible (default: `true`) */ isVisible?: boolean; - title: React.ReactNode; + title: DialogTitle; + /** Props for the DialogTitle component (ignored if `title` is not a string). */ + dialogTitleProps?: DialogTitle extends string + ? Except + : never; message?: React.ReactNode; children?: React.ReactNode; + /** Props for the DialogContent component. */ + dialogContentProps?: Except; handleAccept?: React.MouseEventHandler; handleCancel?: React.MouseEventHandler; acceptLabel?: React.ReactNode; cancelLabel?: React.ReactNode; showCancelButton?: boolean; -} & Omit; +}; diff --git a/src/components/Dialog/useDialog.ts b/src/components/Dialog/useDialog.ts index f27f9cab..61de344a 100644 --- a/src/components/Dialog/useDialog.ts +++ b/src/components/Dialog/useDialog.ts @@ -12,3 +12,5 @@ export const useDialog = (initIsVisible = false) => { closeDialog, }; }; + +export type UseDialogHookProps = ReturnType; diff --git a/src/components/Form/BaseFormSubmitButton.tsx b/src/components/Form/BaseFormSubmitButton.tsx index 649bac31..46ffd38f 100644 --- a/src/components/Form/BaseFormSubmitButton.tsx +++ b/src/components/Form/BaseFormSubmitButton.tsx @@ -23,7 +23,7 @@ export const BaseFormSubmitButton = ({ const StyledButton = styled(Button, { shouldForwardProp: (propName: string) => !propName.startsWith("grid"), })({ - height: "2.75rem", // default is 2.5rem + height: "2.5rem", position: "relative", ...muiGridSxProps, }); diff --git a/src/components/Form/inputs/AutoComplete.stories.tsx b/src/components/Form/Inputs/AutoComplete.stories.tsx similarity index 95% rename from src/components/Form/inputs/AutoComplete.stories.tsx rename to src/components/Form/Inputs/AutoComplete.stories.tsx index 596eaf87..435d975e 100644 --- a/src/components/Form/inputs/AutoComplete.stories.tsx +++ b/src/components/Form/Inputs/AutoComplete.stories.tsx @@ -57,4 +57,4 @@ export const BasicDemo = { }, } satisfies Story; -// TODO stories/controls for AutoComplete variations: FreeSolo, grouped opts +// TODO Add stories/controls for AutoComplete variations: FreeSolo, grouped opts diff --git a/src/components/Form/inputs/AutoComplete.tsx b/src/components/Form/Inputs/AutoComplete.tsx similarity index 100% rename from src/components/Form/inputs/AutoComplete.tsx rename to src/components/Form/Inputs/AutoComplete.tsx diff --git a/src/components/Form/inputs/AutoCompleteContact.stories.tsx b/src/components/Form/Inputs/AutoCompleteContact.stories.tsx similarity index 100% rename from src/components/Form/inputs/AutoCompleteContact.stories.tsx rename to src/components/Form/Inputs/AutoCompleteContact.stories.tsx diff --git a/src/components/Form/inputs/AutoCompleteContact.tsx b/src/components/Form/Inputs/AutoCompleteContact.tsx similarity index 100% rename from src/components/Form/inputs/AutoCompleteContact.tsx rename to src/components/Form/Inputs/AutoCompleteContact.tsx diff --git a/src/components/Form/inputs/AutoCompleteMyContacts.tsx b/src/components/Form/Inputs/AutoCompleteMyContacts.tsx similarity index 100% rename from src/components/Form/inputs/AutoCompleteMyContacts.tsx rename to src/components/Form/Inputs/AutoCompleteMyContacts.tsx diff --git a/src/components/Form/inputs/AutoCompleteStates.stories.tsx b/src/components/Form/Inputs/AutoCompleteStates.stories.tsx similarity index 100% rename from src/components/Form/inputs/AutoCompleteStates.stories.tsx rename to src/components/Form/Inputs/AutoCompleteStates.stories.tsx diff --git a/src/components/Form/inputs/AutoCompleteStates.tsx b/src/components/Form/Inputs/AutoCompleteStates.tsx similarity index 100% rename from src/components/Form/inputs/AutoCompleteStates.tsx rename to src/components/Form/Inputs/AutoCompleteStates.tsx diff --git a/src/components/Form/inputs/AutoCompleteWorkOrder.stories.tsx b/src/components/Form/Inputs/AutoCompleteWorkOrder.stories.tsx similarity index 100% rename from src/components/Form/inputs/AutoCompleteWorkOrder.stories.tsx rename to src/components/Form/Inputs/AutoCompleteWorkOrder.stories.tsx diff --git a/src/components/Form/inputs/AutoCompleteWorkOrder.tsx b/src/components/Form/Inputs/AutoCompleteWorkOrder.tsx similarity index 99% rename from src/components/Form/inputs/AutoCompleteWorkOrder.tsx rename to src/components/Form/Inputs/AutoCompleteWorkOrder.tsx index 3652dd56..13d080f5 100644 --- a/src/components/Form/inputs/AutoCompleteWorkOrder.tsx +++ b/src/components/Form/Inputs/AutoCompleteWorkOrder.tsx @@ -1,5 +1,5 @@ import dayjs from "dayjs"; -import { AutoComplete, type AutoCompleteProps } from "@/components/Form/inputs"; +import { AutoComplete, type AutoCompleteProps } from "@/components/Form/Inputs"; import { WorkOrderListItem, type WorkOrderListItemProps, diff --git a/src/components/Form/inputs/AutoCompleteWorkOrderCategory.stories.tsx b/src/components/Form/Inputs/AutoCompleteWorkOrderCategory.stories.tsx similarity index 100% rename from src/components/Form/inputs/AutoCompleteWorkOrderCategory.stories.tsx rename to src/components/Form/Inputs/AutoCompleteWorkOrderCategory.stories.tsx diff --git a/src/components/Form/inputs/AutoCompleteWorkOrderCategory.tsx b/src/components/Form/Inputs/AutoCompleteWorkOrderCategory.tsx similarity index 100% rename from src/components/Form/inputs/AutoCompleteWorkOrderCategory.tsx rename to src/components/Form/Inputs/AutoCompleteWorkOrderCategory.tsx diff --git a/src/components/Form/inputs/BaseTextField.stories.tsx b/src/components/Form/Inputs/BaseTextField.stories.tsx similarity index 100% rename from src/components/Form/inputs/BaseTextField.stories.tsx rename to src/components/Form/Inputs/BaseTextField.stories.tsx diff --git a/src/components/Form/inputs/BaseTextField.tsx b/src/components/Form/Inputs/BaseTextField.tsx similarity index 100% rename from src/components/Form/inputs/BaseTextField.tsx rename to src/components/Form/Inputs/BaseTextField.tsx diff --git a/src/components/Form/inputs/ChecklistInput/AddChecklistItemButton.tsx b/src/components/Form/Inputs/ChecklistInput/AddChecklistItemButton.tsx similarity index 100% rename from src/components/Form/inputs/ChecklistInput/AddChecklistItemButton.tsx rename to src/components/Form/Inputs/ChecklistInput/AddChecklistItemButton.tsx diff --git a/src/components/Form/inputs/ChecklistInput/ChecklistInput.stories.tsx b/src/components/Form/Inputs/ChecklistInput/ChecklistInput.stories.tsx similarity index 100% rename from src/components/Form/inputs/ChecklistInput/ChecklistInput.stories.tsx rename to src/components/Form/Inputs/ChecklistInput/ChecklistInput.stories.tsx diff --git a/src/components/Form/inputs/ChecklistInput/ChecklistInput.tsx b/src/components/Form/Inputs/ChecklistInput/ChecklistInput.tsx similarity index 100% rename from src/components/Form/inputs/ChecklistInput/ChecklistInput.tsx rename to src/components/Form/Inputs/ChecklistInput/ChecklistInput.tsx diff --git a/src/components/Form/inputs/ChecklistInput/ChecklistItemInput/ChecklistItemInput.stories.tsx b/src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/ChecklistItemInput.stories.tsx similarity index 100% rename from src/components/Form/inputs/ChecklistInput/ChecklistItemInput/ChecklistItemInput.stories.tsx rename to src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/ChecklistItemInput.stories.tsx diff --git a/src/components/Form/inputs/ChecklistInput/ChecklistItemInput/ChecklistItemInput.tsx b/src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/ChecklistItemInput.tsx similarity index 100% rename from src/components/Form/inputs/ChecklistInput/ChecklistItemInput/ChecklistItemInput.tsx rename to src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/ChecklistItemInput.tsx diff --git a/src/components/Form/inputs/ChecklistInput/ChecklistItemInput/DeleteChecklistItemButton.tsx b/src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/DeleteChecklistItemButton.tsx similarity index 81% rename from src/components/Form/inputs/ChecklistInput/ChecklistItemInput/DeleteChecklistItemButton.tsx rename to src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/DeleteChecklistItemButton.tsx index 10961141..3ef53e60 100644 --- a/src/components/Form/inputs/ChecklistInput/ChecklistItemInput/DeleteChecklistItemButton.tsx +++ b/src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/DeleteChecklistItemButton.tsx @@ -1,7 +1,7 @@ import { useField } from "formik"; import IconButton, { type IconButtonProps } from "@mui/material/IconButton"; import InputAdornment from "@mui/material/InputAdornment"; -import Tooltip, { tooltipClasses } from "@mui/material/Tooltip"; +import Tooltip from "@mui/material/Tooltip"; import XDeleteIcon from "@mui/icons-material/HighlightOff"; import { getTypeSafeError } from "@/utils/typeSafety/getTypeSafeError"; import type { BaseChecklistType } from "@/components/Checklist/types"; @@ -29,16 +29,7 @@ export const DeleteChecklistItemButton = ({ return ( - .${tooltipClasses.tooltip}`]: { - backgroundColor: "rgb(97,97,97)", // rm's the usual 0.92 alpha from tooltip bg - }, - }, - }} - > + - .${tooltipClasses.tooltip}`]: { - backgroundColor: "rgb(97,97,97)", // rm the usual 0.92 alpha from tooltip bg - }, - }, - }} - > + {!isCompleted ? : } diff --git a/src/components/Form/inputs/ChecklistInput/ChecklistItemInput/classNames.ts b/src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/classNames.ts similarity index 100% rename from src/components/Form/inputs/ChecklistInput/ChecklistItemInput/classNames.ts rename to src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/classNames.ts diff --git a/src/components/Form/inputs/ChecklistInput/ChecklistItemInput/index.ts b/src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/index.ts similarity index 100% rename from src/components/Form/inputs/ChecklistInput/ChecklistItemInput/index.ts rename to src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/index.ts diff --git a/src/components/Form/inputs/ChecklistInput/ChecklistItemInput/types.ts b/src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/types.ts similarity index 100% rename from src/components/Form/inputs/ChecklistInput/ChecklistItemInput/types.ts rename to src/components/Form/Inputs/ChecklistInput/ChecklistItemInput/types.ts diff --git a/src/components/Form/inputs/ChecklistInput/CreateChecklistButton.tsx b/src/components/Form/Inputs/ChecklistInput/CreateChecklistButton.tsx similarity index 100% rename from src/components/Form/inputs/ChecklistInput/CreateChecklistButton.tsx rename to src/components/Form/Inputs/ChecklistInput/CreateChecklistButton.tsx diff --git a/src/components/Form/inputs/ChecklistInput/RemoveChecklistButton.tsx b/src/components/Form/Inputs/ChecklistInput/RemoveChecklistButton.tsx similarity index 85% rename from src/components/Form/inputs/ChecklistInput/RemoveChecklistButton.tsx rename to src/components/Form/Inputs/ChecklistInput/RemoveChecklistButton.tsx index 751f3f47..f7da1e9b 100644 --- a/src/components/Form/inputs/ChecklistInput/RemoveChecklistButton.tsx +++ b/src/components/Form/Inputs/ChecklistInput/RemoveChecklistButton.tsx @@ -1,7 +1,7 @@ import { useField } from "formik"; import { dialogContentClasses } from "@mui/material/DialogContent"; import IconButton from "@mui/material/IconButton"; -import Tooltip, { tooltipClasses } from "@mui/material/Tooltip"; +import Tooltip from "@mui/material/Tooltip"; import Text from "@mui/material/Typography"; import DeleteIcon from "@mui/icons-material/DeleteOutlined"; import { Dialog } from "@/components/Dialog"; @@ -33,17 +33,7 @@ export const RemoveChecklistButton = ({ checklistFieldID }: ChecklistInputFormPr return ( <> - .${tooltipClasses.tooltip}`]: { - backgroundColor: "rgb(97,97,97)", // rm's the usual 0.92 alpha from tooltip bg - paddingBottom: "1px", // better spacing and text alignment - }, - }, - }} - > + ( + +); + +export type EmailInputProps = Except; diff --git a/src/components/Form/inputs/PasswordInput.stories.tsx b/src/components/Form/Inputs/PasswordInput.stories.tsx similarity index 100% rename from src/components/Form/inputs/PasswordInput.stories.tsx rename to src/components/Form/Inputs/PasswordInput.stories.tsx diff --git a/src/components/Form/inputs/PasswordInput.tsx b/src/components/Form/Inputs/PasswordInput.tsx similarity index 100% rename from src/components/Form/inputs/PasswordInput.tsx rename to src/components/Form/Inputs/PasswordInput.tsx diff --git a/src/components/Form/inputs/PhoneInput.stories.tsx b/src/components/Form/Inputs/PhoneInput.stories.tsx similarity index 100% rename from src/components/Form/inputs/PhoneInput.stories.tsx rename to src/components/Form/Inputs/PhoneInput.stories.tsx diff --git a/src/components/Form/inputs/PhoneInput.tsx b/src/components/Form/Inputs/PhoneInput.tsx similarity index 100% rename from src/components/Form/inputs/PhoneInput.tsx rename to src/components/Form/Inputs/PhoneInput.tsx diff --git a/src/components/Form/inputs/RegionInput.tsx b/src/components/Form/Inputs/RegionInput.tsx similarity index 100% rename from src/components/Form/inputs/RegionInput.tsx rename to src/components/Form/Inputs/RegionInput.tsx diff --git a/src/components/Form/inputs/Select.stories.tsx b/src/components/Form/Inputs/Select.stories.tsx similarity index 100% rename from src/components/Form/inputs/Select.stories.tsx rename to src/components/Form/Inputs/Select.stories.tsx diff --git a/src/components/Form/inputs/Select.tsx b/src/components/Form/Inputs/Select.tsx similarity index 92% rename from src/components/Form/inputs/Select.tsx rename to src/components/Form/Inputs/Select.tsx index 75143fc0..28f02a58 100644 --- a/src/components/Form/inputs/Select.tsx +++ b/src/components/Form/Inputs/Select.tsx @@ -3,7 +3,11 @@ import FormHelperText from "@mui/material/FormHelperText"; import InputLabel from "@mui/material/InputLabel"; import MenuItem from "@mui/material/MenuItem"; import MuiSelect from "@mui/material/Select"; -import { useFormikFieldProps, type FormikIntegratedInputProps } from "../helpers"; +import { + useFormikFieldProps, + getFormInputErrMsg, + type FormikIntegratedInputProps, +} from "../helpers"; import type { SelectProps as MuiSelectProps } from "@mui/material/Select"; export const Select = < @@ -27,7 +31,9 @@ export const Select = < }); const handleChange: SelectProps["onChange"] = async (event) => { - await setValue(event.target.value as ValueType).catch((error) => setError(error)); + await setValue(event.target.value as ValueType).catch((error: unknown) => + setError(getFormInputErrMsg(error)) + ); }; const selectLabelID = `Select:InputLabel:${id}`; diff --git a/src/components/Form/inputs/Slider.stories.tsx b/src/components/Form/Inputs/Slider.stories.tsx similarity index 100% rename from src/components/Form/inputs/Slider.stories.tsx rename to src/components/Form/Inputs/Slider.stories.tsx diff --git a/src/components/Form/inputs/Slider.tsx b/src/components/Form/Inputs/Slider.tsx similarity index 94% rename from src/components/Form/inputs/Slider.tsx rename to src/components/Form/Inputs/Slider.tsx index f0f86f8d..aaaf1da7 100644 --- a/src/components/Form/inputs/Slider.tsx +++ b/src/components/Form/Inputs/Slider.tsx @@ -6,8 +6,9 @@ import MuiSlider, { sliderClasses, type SliderProps as MuiSliderProps } from "@m import { formClassNames } from "../classNames"; import { useFormikFieldProps, + getFormInputErrMsg, type FormikIntegratedInputProps, -} from "../helpers/useFormikFieldProps"; +} from "../helpers"; /** * MUI Slider with Formik integration. @@ -32,7 +33,7 @@ export const Slider = ({ const handleChange = (_event: Event, value: number | Array, _activeThumb: number) => { const fieldValue = getFieldValue(value); - setValue(fieldValue as any).catch((error) => setError(error)); + setValue(fieldValue as any).catch((error: unknown) => setError(getFormInputErrMsg(error))); }; const labelID = `Slider:InputLabel:${id}`; @@ -86,7 +87,6 @@ const StyledMuiSlider = styled(MuiSlider, { }, [`& .${sliderClasses.valueLabel}`]: { - // lineHeight: 1.2, // TODO rm this line if text is fine after setting default line-height:1.5 fontSize: "12px", background: "unset", padding: 0, diff --git a/src/components/Form/inputs/SliderWorkOrderPriority.stories.tsx b/src/components/Form/Inputs/SliderWorkOrderPriority.stories.tsx similarity index 100% rename from src/components/Form/inputs/SliderWorkOrderPriority.stories.tsx rename to src/components/Form/Inputs/SliderWorkOrderPriority.stories.tsx diff --git a/src/components/Form/inputs/SliderWorkOrderPriority.tsx b/src/components/Form/Inputs/SliderWorkOrderPriority.tsx similarity index 95% rename from src/components/Form/inputs/SliderWorkOrderPriority.tsx rename to src/components/Form/Inputs/SliderWorkOrderPriority.tsx index a47d7920..9298ce85 100644 --- a/src/components/Form/inputs/SliderWorkOrderPriority.tsx +++ b/src/components/Form/Inputs/SliderWorkOrderPriority.tsx @@ -1,4 +1,4 @@ -import { Slider, type SliderProps } from "@/components/Form/inputs/Slider"; +import { Slider, type SliderProps } from "@/components/Form/Inputs/Slider"; import { capitalize } from "@/utils/formatters/strings"; import type { Mark } from "@mui/base/useSlider"; diff --git a/src/components/Form/inputs/TextInput.stories.tsx b/src/components/Form/Inputs/TextInput.stories.tsx similarity index 100% rename from src/components/Form/inputs/TextInput.stories.tsx rename to src/components/Form/Inputs/TextInput.stories.tsx diff --git a/src/components/Form/inputs/TextInput.tsx b/src/components/Form/Inputs/TextInput.tsx similarity index 100% rename from src/components/Form/inputs/TextInput.tsx rename to src/components/Form/Inputs/TextInput.tsx diff --git a/src/components/Form/Inputs/UserHandleInput.tsx b/src/components/Form/Inputs/UserHandleInput.tsx new file mode 100644 index 00000000..30f14326 --- /dev/null +++ b/src/components/Form/Inputs/UserHandleInput.tsx @@ -0,0 +1,14 @@ +import InputAdornment from "@mui/material/InputAdornment"; +import { TextInput, type TextInputProps } from "./TextInput"; + +export const UserHandleInput = ({ ...userHandleInputProps }: UserHandleInputProps) => ( + @, + }} + /> +); + +export type UserHandleInputProps = TextInputProps; diff --git a/src/components/Form/Inputs/classNames.ts b/src/components/Form/Inputs/classNames.ts new file mode 100644 index 00000000..763f311e --- /dev/null +++ b/src/components/Form/Inputs/classNames.ts @@ -0,0 +1,21 @@ +import { checklistInputClassNames } from "./ChecklistInput/classNames"; + +/** + * Class names for `Form/Inputs` components (src/components/Form/Inputs/). + */ +export const formInputsClassNames = { + autoCompleteInput: "form__auto-complete-input", + checklistInput: { + ...checklistInputClassNames, + }, + currencyInput: "form__currency-input", + dateInput: "form__date-input", + dateTimeInput: "form__date-time-input", + passwordInput: "form__password-input", + phoneInput: "form__phone-input", + sliderInput: "form__slider-input", + sliderInputContainer: "form__slider-input__container", + sliderInputLabel: "form__slider-input__label", + selectInput: "form__select-input", + textInput: "form__text-input", +} as const; diff --git a/src/components/Form/inputs/index.ts b/src/components/Form/Inputs/index.ts similarity index 86% rename from src/components/Form/inputs/index.ts rename to src/components/Form/Inputs/index.ts index 75d5eabc..2f1b9fbe 100644 --- a/src/components/Form/inputs/index.ts +++ b/src/components/Form/Inputs/index.ts @@ -9,6 +9,7 @@ export * from "./ChecklistInput"; export * from "./CurrencyInput"; export * from "./DatePicker"; export * from "./DateTimePicker"; +export * from "./EmailInput"; export * from "./PasswordInput"; export * from "./PhoneInput"; export * from "./RegionInput"; @@ -16,3 +17,6 @@ export * from "./Select"; export * from "./Slider"; export * from "./SliderWorkOrderPriority"; export * from "./TextInput"; +export * from "./UserHandleInput"; + +export * from "./classNames"; diff --git a/src/components/Form/classNames.ts b/src/components/Form/classNames.ts index a26f442a..1b6fae0d 100644 --- a/src/components/Form/classNames.ts +++ b/src/components/Form/classNames.ts @@ -1,31 +1,13 @@ -import { checklistInputClassNames } from "./inputs/ChecklistInput/classNames"; +import { formInputsClassNames } from "./Inputs/classNames"; /** * Class names for `Form` components (src/components/Form/). - * - * This object includes {@link checklistInputClassNames} exported from the `ChecklistInput` - * component under the key `checklistInput`. - * - * // TODO mv input-specific classNames to ./inputs/classNames.ts */ export const formClassNames = { root: "form__root", - // form inputs: - autoCompleteInput: "form__auto-complete-input", - checklistInput: { - ...checklistInputClassNames, - }, - currencyInput: "form__currency-input", - dateInput: "form__date-input", - dateTimeInput: "form__date-time-input", - passwordInput: "form__password-input", - phoneInput: "form__phone-input", - sliderInput: "form__slider-input", - sliderInputContainer: "form__slider-input__container", - sliderInputLabel: "form__slider-input__label", - selectInput: "form__select-input", - textInput: "form__text-input", // form buttons: submitButton: "form__submit-button", controlButtonsContainer: "form__control-buttons-container", + // form inputs: + ...formInputsClassNames, } as const; diff --git a/src/components/Form/helpers/errorHandling.ts b/src/components/Form/helpers/errorHandling.ts new file mode 100644 index 00000000..c0d2fd41 --- /dev/null +++ b/src/components/Form/helpers/errorHandling.ts @@ -0,0 +1,14 @@ +import { getErrorMessage } from "@nerdware/ts-type-safety-utils"; + +/** + * Default error message for Form input components. + */ +export const DEFAULT_FORM_INPUT_ERR_MSG = "Oops! Something went wrong — please try again."; + +/** + * Form input error-message handler. + * @returns the `error` arg if it is a `string`, else returns the {@link DEFAULT_FORM_INPUT_ERR_MSG}. + */ +export const getFormInputErrMsg = (error: unknown) => { + return getErrorMessage(error) ?? DEFAULT_FORM_INPUT_ERR_MSG; +}; diff --git a/src/components/Form/helpers/index.ts b/src/components/Form/helpers/index.ts index d2f9af5b..2aa8c70b 100644 --- a/src/components/Form/helpers/index.ts +++ b/src/components/Form/helpers/index.ts @@ -1,4 +1,5 @@ +export * from "./errorHandling"; export * from "./getInitialValuesFromSchema"; -export * from "./useDefaultTextFieldVariant"; export * from "./useFormikFieldProps"; +export * from "./useLayoutDependantTextFieldDefaults"; export * from "./yupCommonSchema"; diff --git a/src/components/Form/helpers/useDefaultTextFieldVariant.ts b/src/components/Form/helpers/useDefaultTextFieldVariant.ts deleted file mode 100644 index 2fcdeb0a..00000000 --- a/src/components/Form/helpers/useDefaultTextFieldVariant.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { usePageLayoutContext } from "@/app/PageLayoutContext/usePageLayoutContext"; -import type { TextFieldProps } from "@mui/material/TextField"; - -/** - * Default `variant` for all Mui inputs: - * - * - "filled" on desktop - * - "outlined" on mobile - */ -export const useDefaultTextFieldVariant = (): { - defaultVariant: TextFieldProps["variant"]; -} & ReturnType => { - const { isMobilePageLayout, isMobileUserAgent } = usePageLayoutContext(); - - return { - isMobilePageLayout, - isMobileUserAgent, - defaultVariant: isMobilePageLayout ? "outlined" : "filled", - }; -}; diff --git a/src/components/Form/helpers/useFormikFieldProps.ts b/src/components/Form/helpers/useFormikFieldProps.ts index 8d4bae38..7c3619d5 100644 --- a/src/components/Form/helpers/useFormikFieldProps.ts +++ b/src/components/Form/helpers/useFormikFieldProps.ts @@ -1,5 +1,6 @@ import { useField, type FieldInputProps, type FieldMetaProps, type FieldHelperProps } from "formik"; -import { useDefaultTextFieldVariant } from "./useDefaultTextFieldVariant"; +import { getFormInputErrMsg } from "./errorHandling"; +import { useLayoutDependantTextFieldDefaults } from "./useLayoutDependantTextFieldDefaults"; import type { TextFieldProps as MuiTextFieldProps } from "@mui/material/TextField"; import type { Simplify, SetReturnType } from "type-fest"; @@ -21,6 +22,7 @@ export const useFormikFieldProps = ({ fieldID, label: explicitLabel, variant: explicitVariant, + size: explicitSize, placeholder, shouldAlwaysRenderHelperText = true, }: UseFormikFieldPropsParams): UseFormikFieldPropsReturn => { @@ -28,7 +30,8 @@ export const useFormikFieldProps = ({ const { value: fieldValue, onChange, onBlur } = fieldInputProps; - const { defaultVariant, isMobilePageLayout, isMobileUserAgent } = useDefaultTextFieldVariant(); + const { defaultVariant, defaultSize, isMobilePageLayout, isMobileUserAgent } = + useLayoutDependantTextFieldDefaults(); const label = explicitLabel ?? fieldID; const showErrorState = fieldMetaProps.touched && !!fieldMetaProps?.error; @@ -40,12 +43,13 @@ export const useFormikFieldProps = ({ label, ...(!showErrorState && placeholder && { placeholder }), variant: explicitVariant ?? defaultVariant, + size: explicitSize ?? defaultSize, value: fieldValue, onChange, onBlur, error: showErrorState, helperText: showErrorState - ? `${fieldMetaProps.error}` + ? getFormInputErrMsg(fieldMetaProps.error) : shouldAlwaysRenderHelperText ? " " : "", @@ -58,6 +62,7 @@ export const useFormikFieldProps = ({ isMobilePageLayout, isMobileUserAgent, defaultVariant, + defaultSize, }, ]; }; @@ -74,6 +79,7 @@ export type UseFormikFieldPropsParams = { fieldID: string; label?: string; variant?: MuiTextFieldProps["variant"]; + size?: MuiTextFieldProps["size"]; placeholder?: string; shouldAlwaysRenderHelperText?: boolean; }; @@ -87,6 +93,7 @@ export type UseFormikFieldPropsReturn = [ label: string; placeholder?: string; variant: MuiTextFieldProps["variant"]; + size: MuiTextFieldProps["size"]; value: ValueType; onChange: FieldInputProps["onChange"]; onBlur: FieldInputProps["onBlur"]; @@ -96,7 +103,7 @@ export type UseFormikFieldPropsReturn = [ FieldInputProps & FieldMetaProps & FieldHelperProps & - ReturnType, + ReturnType, ]; /** diff --git a/src/components/Form/helpers/useLayoutDependantTextFieldDefaults.ts b/src/components/Form/helpers/useLayoutDependantTextFieldDefaults.ts new file mode 100644 index 00000000..5bb7afd9 --- /dev/null +++ b/src/components/Form/helpers/useLayoutDependantTextFieldDefaults.ts @@ -0,0 +1,24 @@ +import { usePageLayoutContext } from "@/app/PageLayoutContext/usePageLayoutContext"; +import type { TextFieldProps } from "@mui/material/TextField"; + +/** + * This hook reads the `PageLayoutContext` and returns default Mui TextField prop values: + * + * | TextField Prop   | Value on MOBILE   | Value on DESKTOP | + * | :-------------------- | :--------------------: | :--------------: | + * | `variant` | `"outlined"` | `"filled"` | + * | `size` | `"small"` | `"medium"` | + */ +export const useLayoutDependantTextFieldDefaults = (): { + defaultVariant: TextFieldProps["variant"]; + defaultSize: TextFieldProps["size"]; +} & ReturnType => { + const { isMobilePageLayout, isMobileUserAgent } = usePageLayoutContext(); + + return { + isMobilePageLayout, + isMobileUserAgent, + defaultVariant: isMobilePageLayout ? "outlined" : "filled", + defaultSize: isMobilePageLayout ? "small" : "medium", + }; +}; diff --git a/src/components/Form/helpers/yupCommonSchema.ts b/src/components/Form/helpers/yupCommonSchema.ts index 53fa8645..f6b8e291 100644 --- a/src/components/Form/helpers/yupCommonSchema.ts +++ b/src/components/Form/helpers/yupCommonSchema.ts @@ -2,13 +2,16 @@ import { isValidEmail, isValidPassword } from "@nerdware/ts-string-helpers"; import { string as yupString } from "yup"; /** - * Base string schema: `yup.string().trim().max(250)` + * Base string schema: `yup.string().defined().trim().max(250).default("")` + * - Prohibits `undefined` values. * - Trim whitespace from front and end of string values. * - Default max 250 per field ensures strings fit within API/DB limitations. * - Setting a default value of `''` ensures that calls to `Schema.getDefault()` and/or * `Schema.cast()` do not result in fields with `undefined` values. */ -const yupBaseStringSchema = yupString().trim().max(250).default(""); +const yupBaseStringSchema = yupString().defined().trim().max(250).default(""); + +const yupNullableStringSchema = yupBaseStringSchema.nullable().default(null); /** * @note Yup order of operations: @@ -17,10 +20,13 @@ const yupBaseStringSchema = yupString().trim().max(250).default(""); * 3. validations */ export const yupCommonSchema = { - /** Base string schema: `yup.string().trim().max(250).default('')` */ + /** ### Base string schema: `yup.string().defined().trim().max(250).default("")` */ string: yupBaseStringSchema, - /** Nullable string schema: `yup.string().trim().max(250).nullable().default(null)` */ - stringNullable: yupBaseStringSchema.nullable().default(null), + + /** ### Nullable string schema: `yup.string().defined().trim().max(250).nullable().default(null)` */ + stringNullable: yupNullableStringSchema, + + /** ### Email string schema */ email: yupBaseStringSchema /** * Yup's `email` validation uses the following pattern: @@ -34,13 +40,66 @@ export const yupCommonSchema = { message: "Please enter a valid email", test: (value) => isValidEmail(value), }), + + /** ### Phone string schema (for US phone numbers only) */ phone: yupBaseStringSchema.matches( /^\([1-9]\d{2}\)\s?\d{3}\s?-\s?\d{4}$/, "Must be a valid US phone number" ), - password: yupBaseStringSchema.test({ - name: "is-valid-password", - message: "Please enter a valid password", - test: (value) => isValidPassword(value), - }), + + /** + * ### Schema: Google OAuth2 ID Token (base64-encoded string) + * > **Note:** This cannot depend on the value of `password`, as that creates a circular dependency. + */ + googleIDToken: yupNullableStringSchema.max(Number.MAX_SAFE_INTEGER), + + /** + * ### Schema: Password + * + * A nullable-string schema which depends on the value of `googleIDToken`: + * - WHEN `googleIDToken` is present/truthy, `password` is nullable. + * - WHEN `googleIDToken` is not present/falsy, `password` must meet the following conditions: + * - Contains at least one lowercase letter. + * - Contains at least one uppercase letter. + * - Contains at least one number. + * - Contains at least one of !, \@, #, $, %, ^, &, and/or *. + * - Is at least 6 characters long, and no more than 250 characters long. + */ + // prettier-ignore + password: yupString().defined().nullable().default(null).when("googleIDToken", { + is: (googleIDToken: string | null) => !!googleIDToken, + then: (schema) => schema, + otherwise: (schema) => schema.nonNullable().default("").trim().max(250) + .test({ + name: "is-right-length", + message: "Passwords must be between 6-250 characters", + test: (value) => value?.length >= 6 && value?.length <= 250, + }) + .test({ + name: "contains-lowercase-char", + message: "Passwords must contain at least 1 lowercase letter", + test: (value) => /[a-z]/.test(value), + }) + .test({ + name: "contains-uppercase-char", + message: "Passwords must contain at least 1 uppercase letter", + test: (value) => /[A-Z]/.test(value), + }) + .test({ + name: "contains-number", + message: "Passwords must contain at least one number", + test: (value) => /\d/.test(value), + }) + .test({ + name: "contains-special-char", + message: "Must contain at least one special character: !, @, #, $, %, ^, &, or *", + test: (value) => /[!@#$%^&*]/.test(value), + }) + // This last one should be unnecessary, but it's here just in case. + .test({ + name: "fallback-is-valid-password", + message: "Your password does not meet platform requirements", + test: (value) => isValidPassword(value), + }), + }), } as const; diff --git a/src/components/Form/index.ts b/src/components/Form/index.ts index 1204069d..716b7429 100644 --- a/src/components/Form/index.ts +++ b/src/components/Form/index.ts @@ -1,6 +1,6 @@ export * from "./Form"; export * from "./FormControlButtons"; export * from "./FormSubmitButton"; -export * from "./inputs"; +export * from "./Inputs"; export * from "./classNames"; export * from "./helpers"; diff --git a/src/components/List/subComponents/EmptyListFallback.tsx b/src/components/List/subComponents/EmptyListFallback.tsx index 964bf319..6ba1d384 100644 --- a/src/components/List/subComponents/EmptyListFallback.tsx +++ b/src/components/List/subComponents/EmptyListFallback.tsx @@ -1,6 +1,5 @@ import { styled, alpha } from "@mui/material/styles"; import Box, { type BoxProps } from "@mui/material/Box"; -import { tooltipClasses } from "@mui/material/Tooltip"; import Text, { typographyClasses } from "@mui/material/Typography"; import AddToListIcon from "@mui/icons-material/PlaylistAddCircle"; import { HelpInfoIcon } from "@/components/DataDisplay/HelpInfoIcon"; @@ -29,20 +28,7 @@ export const EmptyListFallback = ({ {tooltip && ( <> - + )} diff --git a/src/components/Navigation/Anchor.tsx b/src/components/Navigation/Anchor.tsx index a1cd405e..ec8a19c1 100644 --- a/src/components/Navigation/Anchor.tsx +++ b/src/components/Navigation/Anchor.tsx @@ -1,6 +1,7 @@ import { forwardRef } from "react"; import { styled } from "@mui/material/styles"; import { useMaybeRef } from "@/hooks/useMaybeRef"; +import { isExternalUrl } from "@/routes/helpers"; import { getDefaultLinkStyles } from "./styles"; import type { Simplify } from "type-fest"; @@ -17,13 +18,11 @@ export const Anchor = forwardRef(function Anchor ) { const anchorRef = useMaybeRef(ref); - const isExternalUrl = href && href.startsWith("http") && !href.includes("gofixit.app"); - return ( = (event) => { event.preventDefault(); - nav(to); + nav(-1); }; return ( @@ -42,7 +38,6 @@ export const BackButton = ({ }; export type BackButtonProps = Omit & { - to?: To; label?: string; icon?: boolean; tooltip?: string; diff --git a/src/components/Navigation/LegalLinks.stories.tsx b/src/components/Navigation/LegalLinks.stories.tsx index 895852c2..4ef48f20 100644 --- a/src/components/Navigation/LegalLinks.stories.tsx +++ b/src/components/Navigation/LegalLinks.stories.tsx @@ -6,7 +6,14 @@ const meta = { title: "Components/Navigation/LegalLinks", component: LegalLinks, tags: ["autodocs"], - decorators: [withNavDecorator], + decorators: [ + withNavDecorator, + (Story) => ( +
    + +
    + ), + ], } satisfies Meta; export default meta; @@ -23,3 +30,16 @@ export const WithStripeBadge = { includeStripeBadge: true, }, } satisfies Story; + +export const WithLongLabels = { + args: { + useLongLabels: true, + }, +} satisfies Story; + +export const WithLongLabelsAndStripeBadge = { + args: { + useLongLabels: true, + includeStripeBadge: true, + }, +} satisfies Story; diff --git a/src/components/Navigation/LegalLinks.tsx b/src/components/Navigation/LegalLinks.tsx index da236ac5..ef0205d7 100644 --- a/src/components/Navigation/LegalLinks.tsx +++ b/src/components/Navigation/LegalLinks.tsx @@ -1,15 +1,18 @@ +import { Fragment } from "react"; import { styled, alpha } from "@mui/material/styles"; import Divider, { dividerClasses } from "@mui/material/Divider"; import Tooltip from "@mui/material/Tooltip"; -import { StripeBadge, brandingClassNames } from "@/components/Branding"; +import { StripeBadge, STRIPE_LINKS, brandingClassNames } from "@/components/Branding"; import { APP_PATHS } from "@/routes/appPaths"; import { Link } from "./Link"; import { navigationClassNames } from "./classNames"; +import type { Except } from "type-fest"; /** * Legal links: * - `Terms`: `"/ToS"` * - `Privacy`: `"/privacy"` + * - `Cookies`: `"/cookie-policy"` * * If `includeStripeBadge` is true, a vertical divider will be placed in between the * StripeBadge and the links; if it is false, the divider will be placed in between @@ -19,74 +22,83 @@ import { navigationClassNames } from "./classNames"; * the Stripe Connected Account Agreement page, rather than Stripe's landing page. */ export const LegalLinks = ({ + useLongLabels = false, includeStripeBadge = false, tabIndex = -1, - ...containerProps + ...divProps }: LegalLinksProps) => ( {includeStripeBadge && ( <> - + )} - - - Terms {/* <-- Don't rm the \s after Privacy, it elongates the underline */} - - - {!includeStripeBadge && } - - - Privacy {/* <-- Don't rm the \s after Privacy, it elongates the underline */} - - + {[ + { + label: useLongLabels ? "Terms of Service" : "Terms", + tooltip: "View Terms of Service", + link: APP_PATHS.ToS, + }, + { + label: useLongLabels ? "Privacy Policy" : "Privacy", + tooltip: "View our Privacy Policy", + link: APP_PATHS.PRIVACY, + }, + { + label: useLongLabels ? "Cookie Policy" : "Cookies", + tooltip: "View our Cookie Policy", + link: APP_PATHS.COOKIES, + }, + ].map(({ label, link, tooltip }, index) => ( + + {!includeStripeBadge && index !== 0 && } + + + {`${label} ` /* <-- Don't rm the \s after label, it elongates the underline */} + + + + ))} ); -const StyledDiv = styled("div")(({ theme: { palette } }) => ({ +const StyledDiv = styled("div")(({ includeStripeBadge, theme: { palette } }) => ({ + height: "2rem", display: "flex", flexDirection: "row", alignItems: "center", justifyContent: "center", - verticalAlign: "middle", - - [`& > .${brandingClassNames.stripeBadgeRoot}`]: { - height: "2rem", - margin: "0 0.5rem", - [`& .${brandingClassNames.stripeBadgeImg}`]: { - height: "100%", - }, - }, + gap: includeStripeBadge ? "1rem" : "0.75rem", [`& .${dividerClasses.root}`]: { - height: "1.5rem", - width: "0.1px", - marginTop: 0, - marginBottom: 0, + height: includeStripeBadge ? "2.25rem" : "1.75rem", + alignSelf: "center", backgroundColor: alpha(palette.mode === "dark" ? palette.grey[600] : palette.grey[800], 0.5), }, - [`& > a[href="${APP_PATHS.ToS}"],a[href="${APP_PATHS.PRIVACY}"]`]: { + [`& > a:not(.${brandingClassNames.stripeBadgeAnchor})`]: { color: palette.mode === "dark" ? palette.grey[500] : palette.grey[700], textDecoration: "underline dotted", textUnderlinePosition: "under", - margin: "0 0.5rem", whiteSpace: "pre", // preserve whitespace, text includes ending space to elongate underline + transform: "translateY(-1px)", // nudged up bc the underline makes the text appear to not be centered vertically }, })); export type LegalLinksProps = { includeStripeBadge?: boolean; -} & React.ComponentProps; + /** + * Whether to use the "long" names for the legal links, e.g. "Terms of Service" + * instead of "Terms" (default: `false`). + */ + useLongLabels?: boolean; +} & Except, "className" | "children">; diff --git a/src/components/Navigation/classNames.ts b/src/components/Navigation/classNames.ts index a9c0a63a..14428bed 100644 --- a/src/components/Navigation/classNames.ts +++ b/src/components/Navigation/classNames.ts @@ -2,7 +2,5 @@ * Class names for `Navigation` components (src/components/Navigation/). */ export const navigationClassNames = { - legalLinksContainer: "legal-links-container", - - navLinkPending: "rrd-nav-link-pending", + legalLinksRoot: "legal-links__root", } as const; diff --git a/src/components/Navigation/styles.ts b/src/components/Navigation/styles.ts index 8f2c8aaa..3b2e3409 100644 --- a/src/components/Navigation/styles.ts +++ b/src/components/Navigation/styles.ts @@ -1,4 +1,5 @@ -import type { Theme, SxProps } from "@mui/material/styles"; +import type { CSSObject } from "@emotion/react"; +import type { Theme } from "@mui/material/styles"; /** * Default styles for the `Link` and `Anchor` components. @@ -15,4 +16,4 @@ export const getDefaultLinkStyles = ({ theme: { palette } }: { theme: Theme }) = cursor: "pointer", opacity: 0.7, }, - }) satisfies SxProps; + }) satisfies CSSObject; diff --git a/src/components/Stepper/StepContentContainer.tsx b/src/components/Stepper/StepContentContainer.tsx index e8f71373..a46ed641 100644 --- a/src/components/Stepper/StepContentContainer.tsx +++ b/src/components/Stepper/StepContentContainer.tsx @@ -67,7 +67,6 @@ const StyledDiv = styled("div")({ [`& .${typographyClasses.root}`]: { fontSize: "1rem", - // lineHeight: "1.25rem", // TODO rm this line if text is fine after setting default line-height:1.5 }, }, diff --git a/src/components/StripeForm/StripePaymentInput/StripePaymentInput.tsx b/src/components/StripeForm/StripePaymentInput/StripePaymentInput.tsx index 3f04469a..b415d59a 100644 --- a/src/components/StripeForm/StripePaymentInput/StripePaymentInput.tsx +++ b/src/components/StripeForm/StripePaymentInput/StripePaymentInput.tsx @@ -38,7 +38,7 @@ export const StripePaymentInput = ({ billingDetails: { // Only `email` is required to enable Link, but more info = more streamlined checkout. email, - phone, + ...(phone && { phone }), ...(!!givenName && !!familyName && { // Stripe examples use the western `firstName lastName` convention for `name`: diff --git a/src/components/StripeForm/StripePaymentInput/useStripePaymentInput.ts b/src/components/StripeForm/StripePaymentInput/useStripePaymentInput.ts index 3bd42f3e..aedadbd9 100644 --- a/src/components/StripeForm/StripePaymentInput/useStripePaymentInput.ts +++ b/src/components/StripeForm/StripePaymentInput/useStripePaymentInput.ts @@ -25,7 +25,12 @@ export const useStripePaymentInput = () => { // Create the PaymentMethod using the details collected by the Payment Element const { error, paymentMethod } = await stripe.createPaymentMethod({ elements, - params: { billing_details: { email, phone } }, + params: { + billing_details: { + email, + ...(phone && { phone }), + }, + }, }); // Check for possible errors diff --git a/src/components/Text/ClickToCopyText.tsx b/src/components/Text/ClickToCopyText.tsx new file mode 100644 index 00000000..c3bdc65a --- /dev/null +++ b/src/components/Text/ClickToCopyText.tsx @@ -0,0 +1,64 @@ +import { styled, alpha } from "@mui/material/styles"; +import ButtonBase, { buttonBaseClasses } from "@mui/material/ButtonBase"; +import IconButton, { iconButtonClasses } from "@mui/material/IconButton"; +import { svgIconClasses } from "@mui/material/SvgIcon"; +import Tooltip from "@mui/material/Tooltip"; +import ContentCopyIcon from "@mui/icons-material/ContentCopy"; +import { THEMES } from "@/app/ThemeProvider/themes"; +import { textClassNames } from "./classNames"; + +export const ClickToCopyText = ({ + children: textToCopy, + stripeWhitespace = false, + tooltipTitle = "Click to copy", +}: ClickToCopyTextProps) => { + const handleClickCopyBtn = () => + window.navigator.clipboard.writeText( + stripeWhitespace ? textToCopy.replace(/\s/g, "") : textToCopy + ); + + return ( + + + {textToCopy} + + + + + + + + ); +}; + +const StyledSpan = styled("span")(({ theme: { palette } }) => ({ + display: "inline-flex", + alignItems: "center", + verticalAlign: "middle", + + [`& > .${buttonBaseClasses.root}:first-of-type`]: { + fontFamily: `source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace`, + cursor: "pointer", + display: "inline-block", + margin: "0 0.25ch", + padding: "0.1rem 0.5rem", + borderRadius: "0.25rem", + textAlign: "center", + verticalAlign: "middle", + color: THEMES.DARK.palette.text.primary, + backgroundColor: + palette.mode === "dark" + ? THEMES.DARK.palette.background.paper + : alpha(THEMES.DARK.palette.background.paper, 0.8), + }, + + [`& > .${iconButtonClasses.root} > .${svgIconClasses.root}`]: { + fontSize: "1rem", + }, +})); + +export type ClickToCopyTextProps = { + children: string; + stripeWhitespace?: boolean; + tooltipTitle?: string; +}; diff --git a/src/components/Text/classNames.ts b/src/components/Text/classNames.ts new file mode 100644 index 00000000..816b0469 --- /dev/null +++ b/src/components/Text/classNames.ts @@ -0,0 +1,6 @@ +/** + * Class names for `Text` components (src/components/Text/). + */ +export const textClassNames = { + clickToCopyTextRoot: "click-to-copy-text__root", +} as const; diff --git a/src/components/Text/index.ts b/src/components/Text/index.ts index c49534ed..cbc0ca6e 100644 --- a/src/components/Text/index.ts +++ b/src/components/Text/index.ts @@ -1 +1,4 @@ +export * from "./ClickToCopyText"; export * from "./NoWrapSpace"; + +export * from "./classNames"; diff --git a/src/components/Tooltips/NoMaxWidthTooltip.tsx b/src/components/Tooltips/NoMaxWidthTooltip.tsx deleted file mode 100644 index 6b3fc561..00000000 --- a/src/components/Tooltips/NoMaxWidthTooltip.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { styled } from "@mui/material/styles"; -import Tooltip, { tooltipClasses, type TooltipProps } from "@mui/material/Tooltip"; - -/** - * A Mui `Tooltip` with no max-width. - * - * Source: https://mui.com/material-ui/react-tooltip/#variable-width - */ -export const NoMaxWidthTooltip = styled(({ className, ...tooltipProps }: TooltipProps) => ( - -))({ - [`& .${tooltipClasses.tooltip}`]: { - maxWidth: "none", - }, -}); - -export type NoMaxWidthTooltipProps = Omit; diff --git a/src/components/Tooltips/index.ts b/src/components/Tooltips/index.ts deleted file mode 100644 index e7d3ce77..00000000 --- a/src/components/Tooltips/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./NoMaxWidthTooltip"; diff --git a/src/graphql/__codegen__/graphql.ts b/src/graphql/__codegen__/graphql.ts index 9ac1623e..c2bccd81 100644 --- a/src/graphql/__codegen__/graphql.ts +++ b/src/graphql/__codegen__/graphql.ts @@ -26,9 +26,9 @@ export type AuthTokenPayload = { email: Scalars['String']['output']; handle: Scalars['String']['output']; id: Scalars['ID']['output']; - phone: Scalars['String']['output']; + phone?: Maybe; profile: Profile; - stripeConnectAccount: AuthTokenPayloadStripeConnectAccountInfo; + stripeConnectAccount?: Maybe; stripeCustomerID: Scalars['String']['output']; subscription?: Maybe; updatedAt: Scalars['DateTime']['output']; @@ -75,7 +75,7 @@ export type Contact = FixitUser & { /** Contact ID internally identifies a user's contact */ id: Scalars['ID']['output']; /** Contact phone number */ - phone: Scalars['String']['output']; + phone?: Maybe; /** Contact Profile object */ profile: Profile; /** Timestamp of the most recent Contact object update */ @@ -129,7 +129,7 @@ export type FixitUser = { /** User ID internally identifies individual User accounts */ id: Scalars['ID']['output']; /** Phone number of either a User or Contact */ - phone: Scalars['String']['output']; + phone?: Maybe; /** Profile object of either a User or Contact */ profile: Profile; updatedAt: Scalars['DateTime']['output']; @@ -432,8 +432,8 @@ export type User = FixitUser & { handle: Scalars['String']['output']; /** (Immutable) User ID internally identifies individual User accounts */ id: Scalars['ID']['output']; - /** (Immutable) User's own phone number */ - phone: Scalars['String']['output']; + /** User's own phone number */ + phone?: Maybe; /** User's own Profile object */ profile: Profile; /** User Stripe Connect Account info */ @@ -534,7 +534,7 @@ export type WorkOrderStatus = | 'IN_PROGRESS' | 'UNASSIGNED'; -export type ContactFieldsFragment = { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }; +export type ContactFieldsFragment = { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }; export type ContactPublicFieldsFragment = { __typename?: 'Contact', id: string, handle: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }; @@ -543,7 +543,7 @@ export type CreateContactMutationVariables = Exact<{ }>; -export type CreateContactMutation = { __typename?: 'Mutation', createContact: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }; +export type CreateContactMutation = { __typename?: 'Mutation', createContact: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }; export type DeleteContactMutationVariables = Exact<{ contactID: Scalars['ID']['input']; @@ -557,16 +557,16 @@ export type ContactQueryVariables = Exact<{ }>; -export type ContactQuery = { __typename?: 'Query', contact: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }; +export type ContactQuery = { __typename?: 'Query', contact: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }; export type MyContactsQueryVariables = Exact<{ [key: string]: never; }>; -export type MyContactsQuery = { __typename?: 'Query', myContacts: Array<{ __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }> }; +export type MyContactsQuery = { __typename?: 'Query', myContacts: Array<{ __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }> }; -type FixitUserFields_Contact_Fragment = { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }; +type FixitUserFields_Contact_Fragment = { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }; -type FixitUserFields_User_Fragment = { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }; +type FixitUserFields_User_Fragment = { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }; export type FixitUserFieldsFragment = FixitUserFields_Contact_Fragment | FixitUserFields_User_Fragment; @@ -577,16 +577,16 @@ export type CreateInviteMutationVariables = Exact<{ export type CreateInviteMutation = { __typename?: 'Mutation', createInvite: { __typename?: 'GenericSuccessResponse', wasSuccessful: boolean } }; -export type InvoiceFieldsFragment = { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }; +export type InvoiceFieldsFragment = { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }; -export type InvoiceWithWorkOrderFieldsFragment = { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }; +export type InvoiceWithWorkOrderFieldsFragment = { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }; export type CreateInvoiceMutationVariables = Exact<{ invoice: InvoiceInput; }>; -export type CreateInvoiceMutation = { __typename?: 'Mutation', createInvoice: { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } } }; +export type CreateInvoiceMutation = { __typename?: 'Mutation', createInvoice: { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } } }; export type UpdateInvoiceAmountMutationVariables = Exact<{ invoiceID: Scalars['ID']['input']; @@ -594,14 +594,14 @@ export type UpdateInvoiceAmountMutationVariables = Exact<{ }>; -export type UpdateInvoiceAmountMutation = { __typename?: 'Mutation', updateInvoiceAmount: { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } } }; +export type UpdateInvoiceAmountMutation = { __typename?: 'Mutation', updateInvoiceAmount: { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } } }; export type PayInvoiceMutationVariables = Exact<{ invoiceID: Scalars['ID']['input']; }>; -export type PayInvoiceMutation = { __typename?: 'Mutation', payInvoice: { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } } }; +export type PayInvoiceMutation = { __typename?: 'Mutation', payInvoice: { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } } }; export type DeleteInvoiceMutationVariables = Exact<{ invoiceID: Scalars['ID']['input']; @@ -615,17 +615,17 @@ export type InvoiceQueryVariables = Exact<{ }>; -export type InvoiceQuery = { __typename?: 'Query', invoice: { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } } }; +export type InvoiceQuery = { __typename?: 'Query', invoice: { __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } } }; export type MyInvoicesQueryVariables = Exact<{ [key: string]: never; }>; -export type MyInvoicesQuery = { __typename?: 'Query', myInvoices: { __typename?: 'MyInvoicesQueryReturnType', createdByUser: Array<{ __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }>, assignedToUser: Array<{ __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }> } }; +export type MyInvoicesQuery = { __typename?: 'Query', myInvoices: { __typename?: 'MyInvoicesQueryReturnType', createdByUser: Array<{ __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }>, assignedToUser: Array<{ __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }> } }; export type MyInvoicesWithWorkOrderDataQueryVariables = Exact<{ [key: string]: never; }>; -export type MyInvoicesWithWorkOrderDataQuery = { __typename?: 'Query', myInvoices: { __typename?: 'MyInvoicesQueryReturnType', createdByUser: Array<{ __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }>, assignedToUser: Array<{ __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }> } }; +export type MyInvoicesWithWorkOrderDataQuery = { __typename?: 'Query', myInvoices: { __typename?: 'MyInvoicesQueryReturnType', createdByUser: Array<{ __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }>, assignedToUser: Array<{ __typename?: 'Invoice', id: string, amount: number, status: InvoiceStatus, stripePaymentIntentID?: string | null, createdAt: Date, updatedAt: Date, workOrder?: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } | null, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } }> } }; export type ProfileFieldsFragment = { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null }; @@ -643,32 +643,32 @@ export type MyProfileQuery = { __typename?: 'Query', myProfile: { __typename?: ' export type StripeConnectAccountFieldsFragment = { __typename?: 'UserStripeConnectAccount', id: string, detailsSubmitted: boolean, chargesEnabled: boolean, payoutsEnabled: boolean }; -export type UserPublicFieldsFragment = { __typename?: 'User', id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }; +export type UserPublicFieldsFragment = { __typename?: 'User', id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }; export type GetUserByHandleQueryVariables = Exact<{ handle: Scalars['String']['input']; }>; -export type GetUserByHandleQuery = { __typename?: 'Query', getUserByHandle?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null }; +export type GetUserByHandleQuery = { __typename?: 'Query', getUserByHandle?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null }; export type SearchForUsersByHandleQueryVariables = Exact<{ handle: Scalars['String']['input']; }>; -export type SearchForUsersByHandleQuery = { __typename?: 'Query', searchForUsersByHandle: Array<{ __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }> }; +export type SearchForUsersByHandleQuery = { __typename?: 'Query', searchForUsersByHandle: Array<{ __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }> }; export type UserSubscriptionFieldsFragment = { __typename?: 'UserSubscription', id: string, status: SubscriptionStatus, currentPeriodEnd: Date, productID: string, priceID: string, createdAt: Date }; -export type WorkOrderFieldsFragment = { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null }; +export type WorkOrderFieldsFragment = { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null }; export type CreateWorkOrderMutationVariables = Exact<{ workOrder: CreateWorkOrderInput; }>; -export type CreateWorkOrderMutation = { __typename?: 'Mutation', createWorkOrder: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } }; +export type CreateWorkOrderMutation = { __typename?: 'Mutation', createWorkOrder: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } }; export type UpdateWorkOrderMutationVariables = Exact<{ workOrderID: Scalars['ID']['input']; @@ -676,33 +676,33 @@ export type UpdateWorkOrderMutationVariables = Exact<{ }>; -export type UpdateWorkOrderMutation = { __typename?: 'Mutation', updateWorkOrder: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } }; +export type UpdateWorkOrderMutation = { __typename?: 'Mutation', updateWorkOrder: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } }; export type CancelWorkOrderMutationVariables = Exact<{ workOrderID: Scalars['ID']['input']; }>; -export type CancelWorkOrderMutation = { __typename?: 'Mutation', cancelWorkOrder: { __typename?: 'DeleteMutationResponse', id: string, wasDeleted: boolean } | { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } }; +export type CancelWorkOrderMutation = { __typename?: 'Mutation', cancelWorkOrder: { __typename?: 'DeleteMutationResponse', id: string, wasDeleted: boolean } | { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } }; export type SetWorkOrderStatusCompleteMutationVariables = Exact<{ workOrderID: Scalars['ID']['input']; }>; -export type SetWorkOrderStatusCompleteMutation = { __typename?: 'Mutation', setWorkOrderStatusComplete: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } }; +export type SetWorkOrderStatusCompleteMutation = { __typename?: 'Mutation', setWorkOrderStatusComplete: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } }; export type WorkOrderQueryVariables = Exact<{ workOrderID: Scalars['ID']['input']; }>; -export type WorkOrderQuery = { __typename?: 'Query', workOrder: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } }; +export type WorkOrderQuery = { __typename?: 'Query', workOrder: { __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null } }; export type MyWorkOrdersQueryVariables = Exact<{ [key: string]: never; }>; -export type MyWorkOrdersQuery = { __typename?: 'Query', myWorkOrders: { __typename?: 'MyWorkOrdersQueryReturnType', createdByUser: Array<{ __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null }>, assignedToUser: Array<{ __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone: string, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone: string, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null }> } }; +export type MyWorkOrdersQuery = { __typename?: 'Query', myWorkOrders: { __typename?: 'MyWorkOrdersQueryReturnType', createdByUser: Array<{ __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null }>, assignedToUser: Array<{ __typename?: 'WorkOrder', id: string, status: WorkOrderStatus, priority: WorkOrderPriority, category?: WorkOrderCategory | null, description?: string | null, dueDate?: Date | null, entryContact?: string | null, entryContactPhone?: string | null, scheduledDateTime?: Date | null, contractorNotes?: string | null, createdAt: Date, updatedAt: Date, createdBy: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } }, assignedTo?: { __typename?: 'Contact', id: string, handle: string, email: string, phone?: string | null, createdAt: Date, updatedAt: Date, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | { __typename?: 'User', createdAt: Date, updatedAt: Date, id: string, handle: string, email: string, phone?: string | null, profile: { __typename?: 'Profile', displayName: string, givenName?: string | null, familyName?: string | null, businessName?: string | null, photoUrl?: string | null } } | null, location: { __typename?: 'Location', country: string, region: string, city: string, streetLine1: string, streetLine2?: string | null }, checklist?: Array<{ __typename?: 'ChecklistItem', id: string, description: string, isCompleted: boolean } | null> | null }> } }; export const ProfileFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProfileFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Profile"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"givenName"}},{"kind":"Field","name":{"kind":"Name","value":"familyName"}},{"kind":"Field","name":{"kind":"Name","value":"businessName"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}}]}}]} as unknown as DocumentNode; export const ContactPublicFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ContactPublicFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Contact"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"handle"}},{"kind":"Field","name":{"kind":"Name","value":"profile"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProfileFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProfileFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Profile"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"givenName"}},{"kind":"Field","name":{"kind":"Name","value":"familyName"}},{"kind":"Field","name":{"kind":"Name","value":"businessName"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}}]}}]} as unknown as DocumentNode; diff --git a/src/hooks/useAuthInit.ts b/src/hooks/useAuthInit.ts new file mode 100644 index 00000000..a75ffcad --- /dev/null +++ b/src/hooks/useAuthInit.ts @@ -0,0 +1,114 @@ +import { useCallback } from "react"; +import { useNavigate } from "react-router-dom"; +import { toast } from "react-toastify"; +import { useFetchStateContext } from "@/app/FetchStateContext"; +import { useGoogleOneTapLogin } from "@/app/GoogleOAuthContext"; +import { APP_PATHS } from "@/routes/appPaths"; +import { authService, type GoogleTokenLoginParams } from "@/services/authService"; +import { isAuthenticatedStore, isActiveAccountStore, authenticatedUserStore } from "@/stores"; + +/** + * ### Auth Initialization Hook + * + * This hook is used to initialize the User's authentication state when the app is first loaded. + * The logic implemented here is as follows: + * + * - If an AuthToken is not present in LocalStorage, this hook does nothing. + * - If an AuthToken IS present, this hook will try two methods to "automatically" + * authenticate the User: + * + * 1. First, the hook will try to get the User signed in via Google OneTap. + * 2. If Google OneTap fails, or is dismissed/skipped/disabled, this hook will then attempt + * to refresh the User's AuthToken using the `authService.refreshAuthToken` method. Note + * that if Google OneTap is dismissed or skipped (not disabled), the refresh request will + * be made in the background (i.e. without showing loading/error indicators). + * + * - If any method results in successful User authentication, the User is informed via toast msg, + * and thereafter redirected to the appropriate page based on their account status: + * + * - If the User has an active subscription, they are redirected to the `/home` page. + * - If the User does not have an active subscription, they are redirected to the `/products` page. + */ +export const useAuthInit = () => { + const nav = useNavigate(); + const { setIsLoading } = useFetchStateContext(); + const isAuthenticated = isAuthenticatedStore.useSubToStore(); + + /** + * ### Auth Initialization Handler + * + * @param googleIDToken - Google ID Token. If provided, the `authService` method used + * by this fn will be `loginWithGoogleToken`, otherwise it will be `refreshAuthToken`. + * @param shouldRunInBackground - If true, loading/error indicators are not shown. + * @param authFailErrMsg - If provided, a toast will be shown on auth failure (ignored + * if `shouldRunInBackground` is true). + */ + const handleAuthInit = useCallback( + async ({ + googleIDToken, + authFailErrMsg, + }: Partial & { + authFailErrMsg?: string; + }) => { + // Determine the `authService` method to use based on the presence of `googleIDToken`: + const authInitFn = googleIDToken + ? () => authService.loginWithGoogleToken({ googleIDToken }) + : authService.refreshAuthToken; + + // Trigger loading and submit the auth request + setIsLoading(true); + const { token } = await authInitFn().catch(() => ({ token: null })); + setIsLoading(false); + + // If a `token` was returned, the request was successful. + + // If the req was successful, do toast+redirect based on account status + if (token) { + // If account is active, nav to /home, else nav to /products + const isActivePaidAccount = isActiveAccountStore.get(); + if (isActivePaidAccount) { + toast.success("Welcome back!", { toastId: "refreshed-token" }); + nav(APP_PATHS.HOME); + } else { + toast.info("Welcome back! Please select a subscription.", { toastId: "select-a-sub" }); + nav(APP_PATHS.PRODUCTS); + } + } else { + // If the req failed and a authFailErrMsg was provided, then toast+redirect + if (authFailErrMsg) { + toast.error(authFailErrMsg, { toastId: "auth-init-request-failed" }); + nav(APP_PATHS.LOGIN); + } + } + }, + [nav, setIsLoading] + ); + + /** + * Google OneTap login for automatic sign-in. + */ + useGoogleOneTapLogin({ + // Only enabled if User is not currently authenticated, BUT has an AuthToken already registered + disabled: isAuthenticated || !authenticatedUserStore.shouldAttemptAuthTokenRefresh(), + context: "signin", + onSuccess: (credentialResponse) => { + void handleAuthInit({ + googleIDToken: credentialResponse.credential, + authFailErrMsg: AUTH_FAIL_ERR_MSGS.GOOGLE_ONETAP_FAILED, + }); + }, + onError: () => { + void handleAuthInit({ + authFailErrMsg: AUTH_FAIL_ERR_MSGS.GOOGLE_ONETAP_FAILED, + }); + }, + }); +}; + +/** + * Error messages for failed auth requests. + */ +const AUTH_FAIL_ERR_MSGS = { + GOOGLE_ONETAP_FAILED: + "Oops! Automatic sign-in with Google One-Tap didn't work. Please sign in with a different method.", +} as const satisfies Record; diff --git a/src/hooks/useAuthRefresh.ts b/src/hooks/useAuthRefresh.ts deleted file mode 100644 index 41ac31f5..00000000 --- a/src/hooks/useAuthRefresh.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { useEffect, useCallback } from "react"; -import { useNavigate } from "react-router-dom"; -import { toast } from "react-toastify"; -import { APP_PATHS } from "@/routes/appPaths"; -import { authService } from "@/services/authService"; -import { authTokenLocalStorage, isActiveAccountStore } from "@/stores"; - -export const useAuthRefresh = () => { - const nav = useNavigate(); - - const handleAuthRefresh = useCallback(async () => { - // See if the user already has an auth token - if (authTokenLocalStorage.get()) { - const { token: refreshedAuthToken } = await authService - .refreshAuthToken() - .catch(() => ({ token: null })); - // Check if auth token was refreshed and user is auth'd - if (refreshedAuthToken) { - // If account is active, nav to /home, else nav to /products - const isActivePaidAccount = isActiveAccountStore.get(); - if (isActivePaidAccount) { - toast.success("Welcome back!", { toastId: "refreshed-token" }); - nav(APP_PATHS.HOME); - } else { - toast.info("Welcome back! Please select a subscription.", { toastId: "select-a-sub" }); - nav(APP_PATHS.PRODUCTS); - } - } - } - }, [nav]); - - // EFFECT: On initial load, nav to /home or /products if user is auth'd - useEffect(() => { - (async () => await handleAuthRefresh())(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return { - handleAuthRefresh, - }; -}; diff --git a/src/images/github_logo.svg b/src/images/github_logo.svg new file mode 100644 index 00000000..669be637 --- /dev/null +++ b/src/images/github_logo.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/layouts/AuthPageLayout/AuthPageLayout.tsx b/src/layouts/AuthPageLayout/AuthPageLayout.tsx index 51a890fb..4e8ab722 100644 --- a/src/layouts/AuthPageLayout/AuthPageLayout.tsx +++ b/src/layouts/AuthPageLayout/AuthPageLayout.tsx @@ -1,74 +1,87 @@ import { styled } from "@mui/material/styles"; -import Box, { type BoxProps } from "@mui/material/Box"; -import Text from "@mui/material/Typography"; +import Stack, { stackClasses, type StackProps } from "@mui/material/Stack"; +import Text, { typographyClasses } from "@mui/material/Typography"; import { FetchStateContextProvider } from "@/app/FetchStateContext"; +import { + GOOGLE_OAUTH_BTN_DIMENSIONS, + googleOAuthButtonClassNames, +} from "@/app/GoogleOAuthContext/GoogleOAuthButton"; import { usePageLayoutContext } from "@/app/PageLayoutContext/usePageLayoutContext"; -import { TitleLogo, brandingClassNames } from "@/components/Branding"; +import { TitleLogo } from "@/components/Branding/TitleLogo"; +import { formClassNames } from "@/components/Form/classNames"; import { authPageLayoutClassNames } from "./classNames"; +export type AuthPageLayoutProps = { pageTitle: string } & Pick; + /** * Layout used by `RegisterPage` and `LoginPage`. */ -export const AuthPageLayout = ({ pageTitle, children, ...boxProps }: AuthPageLayoutProps) => { +export const AuthPageLayout = ({ pageTitle, sx, children }: AuthPageLayoutProps) => { const { isMobilePageLayout } = usePageLayoutContext(); return ( - - + + {!isMobilePageLayout && } - - {pageTitle} - - - {children} - + {pageTitle} + + {children} + ); }; -const StyledBox = styled(Box)({ +/** The `variant` of the `AuthPageLayout` header text. */ +const HEADER_VARIANT = "h2"; + +const StyledStack = styled(Stack)(({ theme: { variables } }) => ({ height: "100%", - width: "100%", - overflow: "hidden", - display: "flex", - flexDirection: "column", - alignItems: "center", - justifyContent: "center", - gap: "3rem", - textAlign: "center", + padding: "0 1rem", + + "& button": { + borderRadius: "1.5rem", + }, - [`& > .${authPageLayoutClassNames.header}`]: { + // This MuiStack, and any MuiStack within it: + [`&.${stackClasses.root}, .${stackClasses.root}`]: { + width: "100%", display: "flex", - flexDirection: "column", alignItems: "center", - justifyContent: "center", - gap: "1.5rem", - - [`& > .${brandingClassNames.titleLogoRoot}`]: { - gap: "1rem", + justifyContent: "space-evenly", + textAlign: "center", + }, - [`& > .${brandingClassNames.titleLogoText}`]: { - fontSize: "3.5rem", - }, - }, + // The `headerContainer`: + [`& .${authPageLayoutClassNames.headerContainer}`]: { + gap: "1rem", - [`& > .${authPageLayoutClassNames.headerTitle}`]: { - fontSize: "2.25rem", + // The header text: + [`& .${typographyClasses[HEADER_VARIANT]}`]: { + fontSize: variables.isMobilePageLayout ? "2rem" : "2.25rem", }, }, - [`& > .${authPageLayoutClassNames.childrenContainer}`]: { - width: "clamp(18rem, 35vw, 26rem)", - minHeight: "25vh", - display: "flex", - flexDirection: "column", - justifyContent: "space-evenly", + // The `childrenContainer`: + [`& .${authPageLayoutClassNames.childrenContainer}`]: { + /* The `GoogleLogin` button's width must be set using an explicit pixel value + via it's `width` prop. This width is set and enforced here to ensure descendent + comps can just set `width: "100%"` and all have the same width. */ + width: variables.isMobilePageLayout + ? `${GOOGLE_OAUTH_BTN_DIMENSIONS.WIDTH.MOBILE}px !important` + : `${GOOGLE_OAUTH_BTN_DIMENSIONS.WIDTH.DESKTOP}px !important`, + + gap: "1rem", - "& button": { - borderRadius: "1.5rem", + [`& .${formClassNames.root}`]: { + width: "100%", + display: "flex", + flexDirection: "column", + gap: "0.5rem", }, - }, -}); -export type AuthPageLayoutProps = { pageTitle: string } & Omit; + [`& .${googleOAuthButtonClassNames.root}`]: { + alignSelf: "center", + }, + }, +})); diff --git a/src/layouts/AuthPageLayout/classNames.ts b/src/layouts/AuthPageLayout/classNames.ts index 319518d9..6454abcb 100644 --- a/src/layouts/AuthPageLayout/classNames.ts +++ b/src/layouts/AuthPageLayout/classNames.ts @@ -1,6 +1,8 @@ +/** + * Class names for `AuthPageLayout` components. + */ export const authPageLayoutClassNames = { - root: "auth-page-layout-root", // was "auth-page-layout-container" - header: "auth-page-layout-header", // was "auth-page-header" - headerTitle: "auth-page-layout-header-title", // was "auth-page-header-title" - childrenContainer: "auth-page-layout-content-container", // was "auth-page-content-container -}; + root: "auth-page-layout__root", + headerContainer: "auth-page-layout__header-container", + childrenContainer: "auth-page-layout__children-container", +} as const; diff --git a/src/layouts/HomePageLayout/DesktopNavDrawer.tsx b/src/layouts/HomePageLayout/DesktopNavDrawer.tsx index ced0f631..1a269a90 100644 --- a/src/layouts/HomePageLayout/DesktopNavDrawer.tsx +++ b/src/layouts/HomePageLayout/DesktopNavDrawer.tsx @@ -3,8 +3,9 @@ import Divider, { dividerClasses } from "@mui/material/Divider"; import Drawer, { drawerClasses } from "@mui/material/Drawer"; import List, { listClasses } from "@mui/material/List"; import { THEMES } from "@/app/ThemeProvider"; +import { AppBarLogoButton } from "@/components/AppBar/AppBarLogoButton"; import { useAppBarHeight } from "@/components/AppBar/helpers"; -import { TitleLogo, brandingClassNames } from "@/components/Branding"; +import { brandingClassNames } from "@/components/Branding"; import { useAppNavActions } from "@/routes/appNavActions"; import { isConnectOnboardingCompleteStore } from "@/stores"; import { DesktopNavDrawerButton } from "./DesktopNavDrawerButton"; @@ -27,7 +28,7 @@ export const DesktopNavDrawer = () => { return ( - + @@ -76,11 +77,7 @@ const StyledDrawer = styled(Drawer)(({ theme: { variables } }) => { padding: "0 0.5rem 0 1.2rem", justifyContent: "flex-start", width: "min-content", - [`& > .${brandingClassNames.titleLogoImg}`]: { - width: "2.25rem", - }, - [`& > .${brandingClassNames.titleLogoText}`]: { - fontSize: "1.5rem", + [`& .${brandingClassNames.titleLogoText}`]: { color: THEMES.DARK.palette.text.primary, }, }, diff --git a/src/layouts/LegalPolicyPageLayout/LegalPolicySection.tsx b/src/layouts/LegalPolicyPageLayout/LegalPolicySection.tsx index 86e7f29c..751a3f51 100644 --- a/src/layouts/LegalPolicyPageLayout/LegalPolicySection.tsx +++ b/src/layouts/LegalPolicyPageLayout/LegalPolicySection.tsx @@ -1,4 +1,5 @@ -import Text from "@mui/material/Typography"; +import Text, { type TypographyProps } from "@mui/material/Typography"; +import type { Except } from "type-fest"; /** * Legal policy section container with h2 header. @@ -6,20 +7,37 @@ import Text from "@mui/material/Typography"; export const LegalPolicySection = ({ sectionNumber, header, - headerID = header.replace(/[^A-Z0-9]/gi, "-"), // by default, just rm all non-alphanum chars from header str + headerProps = {}, children, -}: LegalPolicySectionProps) => ( -
    - - {sectionNumber}. {header} - - {children} -
    -); +}: LegalPolicySectionProps) => { + // Destructure `headerProps` and apply defaults + const { + id: headerID = header.replace(/[^A-Z0-9]/gi, "-"), // by default, just rm all non-alphanum chars from header str + variant: headerVariant = "h4", + component: headerComponent = "h3", + style: headerStyle = {}, + ...restHeaderProps + } = headerProps; + + return ( +
    + + {sectionNumber ? `${sectionNumber}. ${header}` : header} + + {children} +
    + ); +}; export type LegalPolicySectionProps = { - sectionNumber: number; header: string; - headerID?: string; + headerProps?: Except; + sectionNumber?: number; children: React.ReactNode; // section content }; diff --git a/src/layouts/LegalPolicyPageLayout/PolicyInfoTable.tsx b/src/layouts/LegalPolicyPageLayout/PolicyInfoTable.tsx new file mode 100644 index 00000000..f943e8f1 --- /dev/null +++ b/src/layouts/LegalPolicyPageLayout/PolicyInfoTable.tsx @@ -0,0 +1,40 @@ +import { isString } from "@nerdware/ts-type-safety-utils"; +import { styled } from "@mui/material/styles"; + +/** + * A simple table for displaying policy information. + */ +export const PolicyInfoTable = ({ headers, dataRows, ...tableProps }: PolicyInfoTableProps) => ( + + + + {headers.map((header, index) => ( + {header} + ))} + + + + {dataRows.map((row, index) => ( + + {row.map((cell, index) => ( + {cell} + ))} + + ))} + + +); + +export type PolicyInfoTableProps = { + headers: Array; + dataRows: Array>; +} & Omit, "children">; + +const StyledTable = styled("table")(({ theme: { palette } }) => ({ + borderCollapse: "collapse", + + "& th,td": { + padding: "0.75rem", + border: `1px solid ${palette.grey[700]}`, + }, +})); diff --git a/src/layouts/LegalPolicyPageLayout/PolicyToC.tsx b/src/layouts/LegalPolicyPageLayout/PolicyToC.tsx index de0014a0..aa441788 100644 --- a/src/layouts/LegalPolicyPageLayout/PolicyToC.tsx +++ b/src/layouts/LegalPolicyPageLayout/PolicyToC.tsx @@ -54,7 +54,6 @@ const StyledOL = styled("ol")(({ theme: { breakpoints } }) => ({ paddingInlineStart: "2rem", /* Note: `paddingInlineStart` is where the
  • 's CONTENT starts, which does not include the ::marker pseudo-el when `list-style-position` is "outside" (default).*/ - listStyleType: "square", "& > li > *": { verticalAlign: "top", // <-- ensures ::marker pseudo-els are aligned with
  • text diff --git a/src/layouts/ProfileViewLayout/ProfileViewHeader.tsx b/src/layouts/ProfileViewLayout/ProfileViewHeader.tsx index bf67054e..2dc56f66 100644 --- a/src/layouts/ProfileViewLayout/ProfileViewHeader.tsx +++ b/src/layouts/ProfileViewLayout/ProfileViewHeader.tsx @@ -9,10 +9,10 @@ export const ProfileViewHeader = ({ profile, handle }: ProfileViewHeaderProps) =
    - + {profile.displayName} - + {handle}
    diff --git a/src/layouts/ProfileViewLayout/UserProfileDetails.tsx b/src/layouts/ProfileViewLayout/UserProfileDetails.tsx index 5b175706..be220037 100644 --- a/src/layouts/ProfileViewLayout/UserProfileDetails.tsx +++ b/src/layouts/ProfileViewLayout/UserProfileDetails.tsx @@ -21,13 +21,13 @@ export const UserProfileDetails = ({ }: UserProfileDetailsProps) => ( }> - {givenName && `${givenName}${givenName && familyName && ` ${familyName}`}`} + {givenName && `${givenName}${givenName && familyName ? ` ${familyName}` : ""}`} }> {businessName} }> - {fmt.prettifyPhoneNum(phone)} + {phone ? fmt.prettifyPhoneNum(phone) : ""} }> {email} diff --git a/src/layouts/RootAppLayout/RootAppLayout.tsx b/src/layouts/RootAppLayout/RootAppLayout.tsx index 466059fe..918f7204 100644 --- a/src/layouts/RootAppLayout/RootAppLayout.tsx +++ b/src/layouts/RootAppLayout/RootAppLayout.tsx @@ -2,7 +2,7 @@ import { Outlet } from "react-router-dom"; import { styled } from "@mui/material/styles"; import { globalClassNames } from "@/app/GlobalStyles"; import { AppBar, useAppBarHeight } from "@/components/AppBar"; -import { useAuthRefresh } from "@/hooks/useAuthRefresh"; +import { useAuthInit } from "@/hooks/useAuthInit"; import { useHandlePageRefresh } from "@/hooks/useHandlePageRefresh"; import { rootAppLayoutElementIDs } from "./elementIDs"; @@ -15,11 +15,11 @@ import { rootAppLayoutElementIDs } from "./elementIDs"; * - Child components are rendered via ``. */ export const RootAppLayout = () => { - const { handleAuthRefresh } = useAuthRefresh(); - useHandlePageRefresh(handleAuthRefresh); + useHandlePageRefresh(); + useAuthInit(); return ( - +
    diff --git a/src/pages/CheckoutPage/CheckoutContent.tsx b/src/pages/CheckoutPage/CheckoutContent.tsx index fb4f55a3..2d014716 100644 --- a/src/pages/CheckoutPage/CheckoutContent.tsx +++ b/src/pages/CheckoutPage/CheckoutContent.tsx @@ -5,6 +5,7 @@ import Text from "@mui/material/Typography"; import { FetchStateContextProvider } from "@/app/FetchStateContext"; import { usePageLayoutContext } from "@/app/PageLayoutContext/usePageLayoutContext"; import { TitleLogo, brandingClassNames } from "@/components/Branding"; +import { DemoStripeCardInfoAccordion } from "@/components/DevTools/DemoStripeCardInfoAccordion"; import { CheckoutForm, type CheckoutFormProps } from "./CheckoutForm"; import { PaymentConfirmationInfo } from "./PaymentConfirmationInfo"; import { SubCostDetails } from "./SubCostDetails"; @@ -39,9 +40,10 @@ export const CheckoutContent = ({ ) : ( <> - - You'll receive a confirmation email with receipt upon completion. + + {`You'll receive a confirmation email\nwith receipt upon completion.`} + diff --git a/src/pages/CheckoutPage/CheckoutForm.tsx b/src/pages/CheckoutPage/CheckoutForm.tsx index 4072fce1..08366157 100644 --- a/src/pages/CheckoutPage/CheckoutForm.tsx +++ b/src/pages/CheckoutPage/CheckoutForm.tsx @@ -12,6 +12,7 @@ export const CheckoutForm = ({ }: CheckoutFormProps) => { // Route protection guarantees that selectedSubscription is defined, hence the as cast const { selectedSubscription, discountPercentage } = checkoutValuesStore.useSubToStore(); + const { error, clearError } = useFetchStateContext(); const amountDueToday = getPrice_FOR_DISPLAY_ONLY( @@ -20,7 +21,6 @@ export const CheckoutForm = ({ ); const handleSuccessfulSubmit: StripeFormProps["onSuccessfulSubmit"] = async () => { - checkoutValuesStore.clear(); if (parentOnSuccessfulSubmitHandler) { await parentOnSuccessfulSubmitHandler(); } diff --git a/src/pages/CheckoutPage/SubCostDetails.tsx b/src/pages/CheckoutPage/SubCostDetails.tsx index a6d69a46..c9be4dd9 100644 --- a/src/pages/CheckoutPage/SubCostDetails.tsx +++ b/src/pages/CheckoutPage/SubCostDetails.tsx @@ -56,7 +56,7 @@ export const SubCostDetails = () => { {billingPeriod ? `Billed ${billingPeriod}ly` - : afterTrial + : afterTrial && afterTrialPriceStr ? `Then ${afterTrialPriceStr} per ${afterTrial.billingPeriod} thereafter` : ""} diff --git a/src/pages/ContactsListView/ContactsListView.tsx b/src/pages/ContactsListView/ContactsListView.tsx index fd8407c1..2f56209c 100644 --- a/src/pages/ContactsListView/ContactsListView.tsx +++ b/src/pages/ContactsListView/ContactsListView.tsx @@ -1,4 +1,4 @@ -import { listItemButtonClasses } from "@mui/material/ListItemButton"; +import { styled } from "@mui/material/styles"; import GroupIcon from "@mui/icons-material/Group"; import { listClassNames } from "@/components/List"; import { ContactListItemButton } from "@/components/List/listItems/ContactListItem"; @@ -64,10 +64,10 @@ export const ContactsListView = () => ( */ increaseViewportBy: { top: 0, bottom: 1400 }, }} - sx={({ palette, variables, breakpoints }) => ({ + sx={({ variables, breakpoints }) => ({ /* On mobile, to accommodate the SearchUsers input, the CoreContentViewLayout - header flex-row is configured to wrap items and its height is increased. This - change makes it necessary to bump DataGrid down a bit as well. */ + header flex-row is configured to wrap items and its height is increased. This + change makes it necessary to bump DataGrid down a bit as well. */ ...(variables.isMobilePageLayout && { [`& .${coreContentViewLayoutClassNames.headerContainer}`]: { flexWrap: "wrap", @@ -76,7 +76,6 @@ export const ContactsListView = () => ( rowGap: "0.75rem", }, }), - // Contacts list root: [`& .${listClassNames.muiList.root}`]: { width: "100%", @@ -90,14 +89,6 @@ export const ContactsListView = () => ( [breakpoints.up(900)]: { gridTemplateColumns: "repeat( 3, minmax( 14rem, 1fr ))", }, - - // Contact ListItemButton: - [`& .${listItemButtonClasses.root}`]: { - borderRadius: "0.5rem", - ...(palette.mode === "dark" - ? { backgroundColor: palette.background.paper } - : { border: `2px solid ${palette.divider}` }), - }, }, })} /> @@ -107,5 +98,41 @@ export const ContactsListView = () => ( export const Component = ContactsListView; const renderContactsListItem: ListViewRenderItemFn = ({ item, onClick }) => ( - + ); + +const StyledContactListItemButton = styled(ContactListItemButton)(({ theme: { palette } }) => ({ + // Root class here is MuiListItemButton-root + position: "relative", + borderRadius: "0.5rem", + overflow: "hidden", + // LP base is 1rem, 5px added for left-stripe (ensures even spacing around the Avatar) + paddingLeft: "calc(1rem + 5px)", + // Stylish left-stripe (the color may eventually reflect the Contact's status or role) + "&::before": { + content: "''", + position: "absolute", + top: 0, + bottom: 0, + left: 0, + width: "5px", + height: "100%", + backgroundColor: palette.secondary.main, + }, + borderWidth: "2px", + borderStyle: "solid", + ...(palette.mode === "dark" + ? { + borderColor: "transparent", + backgroundColor: palette.background.paper, + "&:hover": { + backgroundColor: palette.action.hover, + }, + } + : { + borderColor: "rgba(150,150,150,0.4)", + "&:hover": { + borderColor: palette.secondary.main, + }, + }), +})); diff --git a/src/pages/ContactsListView/SearchUsers/SearchUsersForm.tsx b/src/pages/ContactsListView/SearchUsers/SearchUsersForm.tsx index 8ffc3a15..aa6eb659 100644 --- a/src/pages/ContactsListView/SearchUsers/SearchUsersForm.tsx +++ b/src/pages/ContactsListView/SearchUsers/SearchUsersForm.tsx @@ -47,7 +47,7 @@ const validateSearchUsersForm: FormValidationFunction<{ searchField: string }> = const inputType = helpers.getInputType(searchFieldValue); return !helpers.isValidFinalValue(searchFieldValue, inputType) - ? { searchField: `Invalid ${inputType}` } + ? { searchField: `Invalid ${inputType ?? "value"}` } : undefined; }; diff --git a/src/pages/ContactsListView/SearchUsers/SearchUsersPopperContent.tsx b/src/pages/ContactsListView/SearchUsers/SearchUsersPopperContent.tsx index 51aae16a..5342795a 100644 --- a/src/pages/ContactsListView/SearchUsers/SearchUsersPopperContent.tsx +++ b/src/pages/ContactsListView/SearchUsers/SearchUsersPopperContent.tsx @@ -3,13 +3,13 @@ import { ClickAwayListener } from "@mui/base/ClickAwayListener"; import { styled } from "@mui/material/styles"; import Box, { type BoxProps } from "@mui/material/Box"; import Button from "@mui/material/Button"; -import IconButton, { iconButtonClasses } from "@mui/material/IconButton"; +import { iconButtonClasses } from "@mui/material/IconButton"; import Text from "@mui/material/Typography"; import AddIcon from "@mui/icons-material/Add"; -import CloseIcon from "@mui/icons-material/Cancel"; import SendIcon from "@mui/icons-material/Send"; import SendToMobileIcon from "@mui/icons-material/SendToMobile"; import { ContactAvatar, avatarClassNames } from "@/components/Avatar"; +import { CloseIconButton } from "@/components/Buttons/CloseIconButton"; import { prettifyPhoneNum } from "@/utils/formatters/strings"; import { InputRequirementsInfo, INPUT_INFO_TEXT } from "./InputRequirementsInfo"; import { ariaElementIDs, searchUsersInputClassNames as classNames } from "./classNames"; @@ -94,9 +94,7 @@ export const SearchUsersPopperContent = forwardRef - - - + {titleText} diff --git a/src/pages/ContactsListView/tableProps.tsx b/src/pages/ContactsListView/tableProps.tsx index b2e70eb4..5493b123 100644 --- a/src/pages/ContactsListView/tableProps.tsx +++ b/src/pages/ContactsListView/tableProps.tsx @@ -34,7 +34,7 @@ const COLUMNS = getDataGridColDefs< }, phone: { headerName: "Phone", - valueFormatter: ({ value }) => fmt.prettifyPhoneNum(value), + valueFormatter: ({ value }) => (value ? fmt.prettifyPhoneNum(value) : ""), valueParser: (value) => (value ? fmt.prettifyPhoneNum(value) : ""), flex: 1, minWidth: 125, diff --git a/src/pages/CookiePolicyPage/CookiePolicyPage.stories.tsx b/src/pages/CookiePolicyPage/CookiePolicyPage.stories.tsx new file mode 100644 index 00000000..bc3e6578 --- /dev/null +++ b/src/pages/CookiePolicyPage/CookiePolicyPage.stories.tsx @@ -0,0 +1,21 @@ +import { withRootAppLayoutDecorator } from "@/../.storybook/decorators"; +import { CookiePolicyPage } from "./CookiePolicyPage"; +import type { Meta, StoryObj } from "@storybook/react"; + +const meta = { + title: "Pages/CookiePolicyPage", + component: CookiePolicyPage, + decorators: [withRootAppLayoutDecorator], + parameters: { + layout: "fullscreen", + }, +} satisfies Meta; + +export default meta; + +/////////////////////////////////////////////////////////// +// STORIES + +type Story = StoryObj; + +export const BasicDemo = {} satisfies Story; diff --git a/src/pages/CookiePolicyPage/CookiePolicyPage.tsx b/src/pages/CookiePolicyPage/CookiePolicyPage.tsx new file mode 100644 index 00000000..f02176f9 --- /dev/null +++ b/src/pages/CookiePolicyPage/CookiePolicyPage.tsx @@ -0,0 +1,246 @@ +import Text from "@mui/material/Typography"; +import { Anchor } from "@/components/Navigation/Anchor"; +import { Link } from "@/components/Navigation/Link"; +import { ClickToCopyText } from "@/components/Text/ClickToCopyText"; +import { LegalPolicyPageLayout } from "@/layouts/LegalPolicyPageLayout"; +import { LegalPolicySection } from "@/layouts/LegalPolicyPageLayout/LegalPolicySection"; +import { PolicyInfoTable } from "@/layouts/LegalPolicyPageLayout/PolicyInfoTable"; +import { APP_PATHS } from "@/routes/appPaths"; + +export const CookiePolicyPage = () => ( + + + This Cookie Policy explains how Nerdware, LLC ("Company," "we," "us," and "our") uses cookies + and similar technologies to enhance product security and aid in user and/or device recognition + when you visit our website at https://gofixit.app, + or any of its relevant subdomains ("Website", collectively). It explains what these + technologies are and why we use them, as well as your rights to control our use of them. + + + In some cases we may use cookies for security purposes, such as fraud prevention and + detection. We may also use cookies to collect personal information, or information that + becomes personal information if we combine it with other information. + + + + + Cookies are small text files that are stored in a computer's browser directory. They help + site providers with things like understanding how people use a site, remembering a User's + login details, and storing site preferences. We use "third-party" cookies as well as similar + technologies (e.g., URL tracking, local storage). + + + Cookies set by the website owner (in this case, Nerdware, LLC) are called "first-party + cookies". Cookies set by parties other than the website owner are called "third-party + cookies". Third-party cookies enable third-party features or functionality to be provided on + or through the website (e.g., advertising, interactive content, and analytics). The parties + that set these third-party cookies can recognize your computer both when it visits the + website in question and also when it visits certain other websites. + + + + + + We do not use any first-party cookies. However, we use similar technologies (e.g., local + storage), as well as third-party cookies. These technologies are used in accordance with our + Privacy Policy to: +
      +
    • ensure that our Services function properly,
    • +
    • + detect and prevent fraud and violations of our{" "} + terms of service, +
    • +
    • understand how visitors use and engage with our Site,
    • +
    • advertise products and services, where allowed and
    • +
    • analyze and improve our Services and your Site experience.
    • +
    + Some cookies and/or related technologies (e.g., URL tracking, local storage) are required + for technical reasons in order for our Website to operate, and we refer to these as + "essential" or "strictly necessary" cookies. Other cookies also enable us to track and + target the interests of our users to enhance the experience on our Online Properties. Third + parties serve cookies through our Website for advertising, analytics, and other purposes. + This is described in more detail below. +
    +
    + + + + You have the right to decide whether to accept or reject cookies. You can exercise your + cookie rights by setting your preferences in your web browser. + + + If you choose to reject cookies, you may still use our website, though your access to some + functionality and areas of our website may be restricted. You may also set or amend your web + browser controls to accept or refuse cookies. + + + The specific types of third-party cookies served through our Website and the purposes they + perform are described in the table below (please note that the specific cookies served may + vary depending on the specific Online Properties you visit): + + + + + + These cookies are strictly necessary to provide you with services available through our + Website and to use some of its features, such as access to secure areas. + + + View Stripe's Privacy Policy + , + "server_cookie", + "2 years", + ], + [ + "__stripe_mid", + "Fraud prevention and detection", + "stripe.com", + "Stripe", + + View Stripe's Privacy Policy + , + "http_cookie", + "1 year", + ], + [ + "__stripe_sid", + "Fraud prevention and detection", + "stripe.com", + "Stripe", + + View Stripe's Privacy Policy + , + "http_cookie", + "30 minutes", + ], + ]} + sx={{ "& td": { textAlign: "center", fontSize: "0.875rem" } }} + /> + + + + + As the means by which you can refuse cookies through your web browser controls vary from + browser to browser, you should visit your browser's help menu for more information. The + following is information about how to manage cookies on the most popular browsers: +
      + {[ + { + browserName: "Chrome", + link: "https://support.google.com/chrome/answer/95647#zippy=%2Callow-or-block-cookies", + }, + { + browserName: "Internet Explorer", + link: "https://support.microsoft.com/en-us/windows/delete-and-manage-cookies-168dab11-0753-043d-7c16-ede5947fc64d", + }, + { + browserName: "Firefox", + link: "https://support.mozilla.org/en-US/kb/enhanced-tracking-protection-firefox-desktop?redirectslug=enable-and-disable-cookies-website-preferences&redirectlocale=en-US", + }, + { + browserName: "Safari", + link: "https://support.apple.com/en-ie/guide/safari/sfri11471/mac", + }, + { + browserName: "Edge", + link: "https://support.microsoft.com/en-us/windows/microsoft-edge-browsing-data-and-privacy-bb8174ba-9d73-dcf2-9b4a-c582b4e640dd", + }, + { browserName: "Opera", link: "https://help.opera.com/en/latest/web-preferences/" }, + ].map(({ browserName, link }) => ( +
    • + {browserName} +
    • + ))} +
    + In addition, most advertising networks offer you a way to opt out of targeted advertising. + If you would like to find out more information, please visit: +
      + {[ + { + name: "Digital Advertising Alliance", + link: "https://www.aboutads.info/choices/", + }, + { + name: "Digital Advertising Alliance of Canada", + link: "https://youradchoices.ca/", + }, + { + name: "European Interactive Digital Advertising Alliance", + link: "https://www.youronlinechoices.com/", + }, + ].map(({ name, link }) => ( +
    • + {name} +
    • + ))} +
    +
    +
    + + + + Cookies are not the only way to recognize or track visitors to a website. We, and/or our + third-party service providers, may use other, similar technologies from time to time, like + web beacons (sometimes called "tracking pixels" or "clear gifs"). These are tiny graphics + files that contain a unique identifier that enables us to recognize when someone has visited + our Website oropened an email including them. This allows us, for example, to monitor the + traffic patterns of users from one page within a website to another, to deliver or + communicate with cookies, to understand whether you have come to the website from an online + advertisement displayed on a third-party website, to improve site performance, and to + measure the success of email marketing campaigns. In many instances, these technologies are + reliant on cookies to function properly, and so declining cookies will impair their + functioning. + + + + + + Third parties may serve cookies on your computer or mobile device to serve advertising + through our Website. These companies may use information about your visits to this and other + websites in order to provide relevant advertisements about goods and services that you may + be interested in. They may also employ technology that is used to measure the effectiveness + of advertisements. They can accomplish this by using cookies or web beacons to collect + information about your visits to this and other sites in order to provide relevant + advertisements about goods and services of potential interest to you. The information + collected through this process does not enable us or them to identify your name, contact + details, or other details that directly identify you unless you choose to provide these. + + + + + + We may update this Cookie Policy from time to time in order to reflect, for example, changes + to the cookies we use or for other operational, legal, or regulatory reasons. Please + therefore revisit this Cookie Policy regularly to stay informed about our use of cookies and + related technologies. + + The date at the top of this Cookie Policy indicates when it was last updated. + + + + + If you have any questions about our use of cookies or other technologies, please email us at{" "} + trevor@nerdware.cloud + + +
    +); + +// Exported as "Component" for react-router-dom lazy loading +export const Component = CookiePolicyPage; diff --git a/src/pages/CookiePolicyPage/index.ts b/src/pages/CookiePolicyPage/index.ts new file mode 100644 index 00000000..295a15ab --- /dev/null +++ b/src/pages/CookiePolicyPage/index.ts @@ -0,0 +1,2 @@ +export { Component } from "./CookiePolicyPage"; +// Exported as "Component" for react-router-dom lazy loading diff --git a/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemDataParser.ts b/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemDataParser.ts index 47499a6d..8c6a49d5 100644 --- a/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemDataParser.ts +++ b/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemDataParser.ts @@ -4,15 +4,15 @@ */ export interface ItemDataParser { initialDataAccum: TAccum; - dataAccumUpdater: DataParserAccumUpdater; + dataAccumUpdater: DataParserAccumUpdater; } export interface DataParserItem { [K: PropertyKey]: any; } -export interface DataParserAccum { - [K: string]: DataParserAccumValue; +export interface DataParserAccum { + [K: string]: any; } /** @@ -22,7 +22,7 @@ export interface DataParserAccum { * The generic _type_ parameter, `TItem`, specifies the type of the array items used * in the 2nd and 4th parameters of `Array.prototype.reduce`. */ -export type DataParserAccumUpdater = ( +export type DataParserAccumUpdater = ( accum: TAccum, item: TItem, index: number, diff --git a/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsPerMonthDataParser.ts b/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsPerMonthDataParser.ts index b192e8a7..a08c32a1 100644 --- a/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsPerMonthDataParser.ts +++ b/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsPerMonthDataParser.ts @@ -39,7 +39,10 @@ export class ItemsPerMonthDataParser // STATIC MEMBERS: static monthStartTimestamps: MonthStartTimestamps; static initialDataAccum: ItemsPerMonthDataParserAccum; - static dataAccumUpdater: DataParserAccumUpdater; + static dataAccumUpdater: DataParserAccumUpdater< + ItemsPerMonthDataParserItem, + ItemsPerMonthDataParserAccum + >; /** * Returns an integer timestamp equal to the first millisecond of the month of the diff --git a/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsPerStatusDataParser.ts b/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsPerStatusDataParser.ts index 9a5cc226..7d1f8b2a 100644 --- a/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsPerStatusDataParser.ts +++ b/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsPerStatusDataParser.ts @@ -15,20 +15,19 @@ export interface ItemsPerStatusDataParserAccum implements ItemDataParser> { initialDataAccum: ItemsPerStatusDataParserAccum; - dataAccumUpdater: DataParserAccumUpdater; + dataAccumUpdater: DataParserAccumUpdater>; constructor(itemStatuses: ReadonlyArray) { this.initialDataAccum = { STATUS_COUNTS: itemStatuses.reduce( (acc, status) => ({ ...acc, [status]: 0 }), - {} as ItemsPerStatusDataParserAccum["STATUS_COUNTS"] + {} as Record ), }; diff --git a/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsStatisticsDataParser.ts b/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsStatisticsDataParser.ts index 792ee881..ce5f50cf 100644 --- a/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsStatisticsDataParser.ts +++ b/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/ItemsStatisticsDataParser.ts @@ -33,7 +33,7 @@ export class ItemsStatisticsDataParser // Instance initialDataAccum is a reference to the static initialDataAccum initialDataAccum = ItemsStatisticsDataParser.initialDataAccum; - dataAccumUpdater: DataParserAccumUpdater; + dataAccumUpdater: DataParserAccumUpdater; constructor(getItemStat: GetItemStatFn) { this.initialDataAccum = { ...ItemsStatisticsDataParser.initialDataAccum }; diff --git a/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/UpcomingEventsDataParser.ts b/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/UpcomingEventsDataParser.ts index d192d3b6..9337ca79 100644 --- a/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/UpcomingEventsDataParser.ts +++ b/src/pages/Dashboard/DashboardDataContext/ItemDataParsers/UpcomingEventsDataParser.ts @@ -33,7 +33,7 @@ export class UpcomingEventsDataParser private static now = dayjs(); initialDataAccum: UpcomingEventsDataParserAccum; - dataAccumUpdater: DataParserAccumUpdater; + dataAccumUpdater: DataParserAccumUpdater>; constructor( getItemEvents: GetItemEventsFn, diff --git a/src/pages/Dashboard/DashboardDataContext/ItemsDataReducer.ts b/src/pages/Dashboard/DashboardDataContext/ItemsDataReducer.ts index b81d2c5c..45dd4b2d 100644 --- a/src/pages/Dashboard/DashboardDataContext/ItemsDataReducer.ts +++ b/src/pages/Dashboard/DashboardDataContext/ItemsDataReducer.ts @@ -18,7 +18,7 @@ import type { ItemDataParser, DataParserItem, DataParserAccum } from "./ItemData */ export class ItemsDataReducer< TItem extends DataParserItem, - TDataParsers extends Array> + TDataParsers extends Array>, > { // INSTANCE MEMBERS readonly initialDataAccum: CombinedReducerAccum; @@ -34,7 +34,7 @@ export class ItemsDataReducer< // Update combinedInitialDataAccum combinedInitialDataAccum: { ...accum.combinedInitialDataAccum, - ...itemDataParser.initialDataAccum, + ...(itemDataParser.initialDataAccum as Record), }, // Update arrayOfDataAccumUpdaterFns arrayOfDataAccumUpdaterFns: [ @@ -53,7 +53,10 @@ export class ItemsDataReducer< return arrayOfItems.reduce((itemsDataAccum, item, index, itemsArray) => { // For each item, each accum-updater function is called arrayOfDataAccumUpdaterFns.forEach((dataAccumUpdater) => { - itemsDataAccum = dataAccumUpdater(itemsDataAccum, item, index, itemsArray); + // prettier-ignore + itemsDataAccum = dataAccumUpdater( + itemsDataAccum, item, index, itemsArray + ) as CombinedReducerAccum; }); return itemsDataAccum; }, structuredClone(this.initialDataAccum)); @@ -63,5 +66,5 @@ export class ItemsDataReducer< type CombinedReducerAccum< TItem extends DataParserItem, - TDataParsers extends Array> + TDataParsers extends Array>, > = Simplify>; diff --git a/src/pages/InvoiceFormView/FormCreateInvoice.tsx b/src/pages/InvoiceFormView/FormCreateInvoice.tsx index a824f052..2920f963 100644 --- a/src/pages/InvoiceFormView/FormCreateInvoice.tsx +++ b/src/pages/InvoiceFormView/FormCreateInvoice.tsx @@ -47,7 +47,7 @@ export const FormCreateInvoice = ({ ...formValues, }, }, - }).catch((err) => logger.error(err)); + }).catch(logger.error); await playLottie(); diff --git a/src/pages/InvoiceFormView/inputs/InvoiceAmountInput.tsx b/src/pages/InvoiceFormView/inputs/InvoiceAmountInput.tsx index 2c940402..62721a64 100644 --- a/src/pages/InvoiceFormView/inputs/InvoiceAmountInput.tsx +++ b/src/pages/InvoiceFormView/inputs/InvoiceAmountInput.tsx @@ -5,7 +5,7 @@ import { inputAdornmentClasses } from "@mui/material/InputAdornment"; import { inputBaseClasses } from "@mui/material/InputBase"; import { inputLabelClasses } from "@mui/material/InputLabel"; import { typographyClasses } from "@mui/material/Typography"; -import { CurrencyInput } from "@/components/Form/inputs/CurrencyInput"; +import { CurrencyInput } from "@/components/Form/Inputs/CurrencyInput"; export const InvoiceAmountInput = styled(CurrencyInput)(({ gridArea }) => ({ gridArea: gridArea as string, diff --git a/src/pages/InvoiceFormView/inputs/InvoiceWorkOrderInput.tsx b/src/pages/InvoiceFormView/inputs/InvoiceWorkOrderInput.tsx index c62f1fcc..c51e977e 100644 --- a/src/pages/InvoiceFormView/inputs/InvoiceWorkOrderInput.tsx +++ b/src/pages/InvoiceFormView/inputs/InvoiceWorkOrderInput.tsx @@ -8,10 +8,10 @@ import { AutoCompleteWorkOrder, type AutoCompleteWorkOrderProps, type AutoCompleteWorkOrderOptions, -} from "@/components/Form/inputs/AutoCompleteWorkOrder"; +} from "@/components/Form/Inputs/AutoCompleteWorkOrder"; import { QUERIES } from "@/graphql/queries"; import { getTypeSafeError } from "@/utils/typeSafety/getTypeSafeError"; -import type { AutoCompleteOnChangeFn } from "@/components/Form/inputs/AutoComplete"; +import type { AutoCompleteOnChangeFn } from "@/components/Form/Inputs/AutoComplete"; import type { Invoice, WorkOrder } from "@/graphql/types"; import type { Simplify } from "type-fest"; diff --git a/src/pages/LandingPage/LandingPage.tsx b/src/pages/LandingPage/LandingPage.tsx index ebca3cee..fd05857d 100644 --- a/src/pages/LandingPage/LandingPage.tsx +++ b/src/pages/LandingPage/LandingPage.tsx @@ -6,11 +6,9 @@ import Text, { typographyClasses } from "@mui/material/Typography"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; import { THEMES } from "@/app/ThemeProvider/themes"; import { PhoneShapedContainer, containerClassNames } from "@/components/Containers"; +import { DemoInfoDialog } from "@/components/DevTools/DemoInfoDialog"; +import { LegalLinks } from "@/components/Navigation/LegalLinks"; import { NON_BREAKING_SPACE_CHAR } from "@/components/Text"; -import demoDesktopDashboardImageSrc from "@/images/demo_desktop_dashboard.webp"; -import demoDesktopDataGridImageSrc from "@/images/demo_desktop_workorders_datagrid.webp"; -import demoMobileCreateInvoiceImageSrc from "@/images/demo_mobile_create_invoice.webp"; -import demoMobileListViewImageSrc from "@/images/demo_mobile_workorders_list.webp"; import backgroundImageSrc from "@/images/landing_page_bg.webp"; import { APP_PATHS } from "@/routes/appPaths"; import { ProductImage } from "./ProductImage"; @@ -20,6 +18,7 @@ import { landingPageClassNames } from "./classNames"; * **Landing Page** - index route for RootAppRouter which renders when the path is `"/"`. */ export const LandingPage = () => { + const { isDialogVisible, closeDialog } = DemoInfoDialog.use(); const nav = useNavigate(); const goToRegister = () => nav(APP_PATHS.REGISTER); @@ -43,20 +42,17 @@ export const LandingPage = () => {
    - + - +
    - + - +
    @@ -70,6 +66,11 @@ export const LandingPage = () => { + {isDialogVisible && } +
    + + Fixit is a product of Nerdware, LLC © +
    ); }; @@ -89,13 +90,13 @@ const StyledDiv = styled("div")(({ theme: { palette, variables, breakpoints } }) gap: "1rem", padding: "0 2rem 3rem 2rem", - gridTemplateRows: "66vh minmax(0, 66vh) minmax(0, 66vh) minmax(0, 66vh)", + gridTemplateRows: "66vh minmax(0, 66vh) minmax(0, 66vh) minmax(0, 66vh) 8rem", gridTemplateColumns: "minmax(0, 1fr)", [breakpoints.up(600)]: { padding: "2rem", gap: "2rem", - gridTemplateRows: "repeat(auto-fit, 75vh)", + gridTemplateRows: "repeat(2, 75vh) 9rem", gridTemplateColumns: "repeat(2, minmax(0, 1fr))", }, @@ -255,4 +256,36 @@ const StyledDiv = styled("div")(({ theme: { palette, variables, breakpoints } }) objectFit: "contain", ...(palette.mode === "light" && { filter: "invert(25%) brightness(3)" }), }, + + // FOOTER + [`& > .${landingPageClassNames.footerRoot}`]: { + position: "absolute", + bottom: 0, + left: 0, + right: 0, + width: "100vw", + display: "flex", + flexDirection: "column", + justifyContent: "center", + alignItems: "center", + gap: "1.5rem", + padding: "2rem", + borderTop: `1px solid ${palette.divider}`, + boxShadow: `0 0 0.5rem ${palette.divider}`, + + [breakpoints.down(600)]: { + padding: "1.25rem 1.5rem 1.5rem 1.5rem", + flexDirection: "row", + justifyContent: "space-evenly", + gap: 0, + textAlign: "center", + "& > div": { + flexDirection: "column", + alignItems: "flex-start", + "& > hr": { + display: "none", + }, + }, + }, + }, })); diff --git a/src/pages/LandingPage/ProductImage.stories.tsx b/src/pages/LandingPage/ProductImage.stories.tsx index bff88d8a..4e4d347b 100644 --- a/src/pages/LandingPage/ProductImage.stories.tsx +++ b/src/pages/LandingPage/ProductImage.stories.tsx @@ -1,4 +1,4 @@ -import { ProductImage, PRODUCT_IMAGES } from "./ProductImage"; +import { ProductImage } from "./ProductImage"; import type { Meta, StoryObj } from "@storybook/react"; const meta = { @@ -27,17 +27,25 @@ export default meta; type Story = StoryObj; export const DashboardDesktopView = { - args: { ...PRODUCT_IMAGES[0] }, + args: { + label: "Fixit Dashboard demo", + }, } satisfies Story; export const CreateInvoiceMobileView = { - args: { ...PRODUCT_IMAGES[1] }, + args: { + label: "Fixit Create-Invoice on mobile", + }, } satisfies Story; export const DataGridDemo = { - args: { ...PRODUCT_IMAGES[2] }, + args: { + label: "Fixit work orders data-grid", + }, } satisfies Story; export const ListViewMobileDemo = { - args: { ...PRODUCT_IMAGES[3] }, + args: { + label: "Fixit work orders list-view on mobile", + }, } satisfies Story; diff --git a/src/pages/LandingPage/ProductImage.tsx b/src/pages/LandingPage/ProductImage.tsx index ee9d21cc..f8f7779b 100644 --- a/src/pages/LandingPage/ProductImage.tsx +++ b/src/pages/LandingPage/ProductImage.tsx @@ -2,13 +2,13 @@ import { useState } from "react"; import { styled } from "@mui/material/styles"; import Box, { type BoxProps } from "@mui/material/Box"; import Dialog, { dialogClasses } from "@mui/material/Dialog"; +import Tooltip from "@mui/material/Tooltip"; import { globalClassNames } from "@/app/GlobalStyles/classNames"; import { ImageCarousel, type ImageCarouselProps, type CarouselImageConfig, } from "@/components/ImageCarousel"; -import { NoMaxWidthTooltip } from "@/components/Tooltips"; import demoDesktopDashboardImageSrc from "@/images/demo_desktop_dashboard.webp"; import demoDesktopDataGridImageSrc from "@/images/demo_desktop_workorders_datagrid.webp"; import demoMobileCreateInvoiceImageSrc from "@/images/demo_mobile_create_invoice.webp"; @@ -17,7 +17,6 @@ import type { OverrideProperties } from "type-fest"; export const ProductImage = ({ label, - src, ImageCarouselProps = {}, ...boxProps }: ProductImageProps) => { @@ -26,21 +25,29 @@ export const ProductImage = ({ const handleOpen = () => setIsModalOpen(true); const handleClose = () => setIsModalOpen(false); + const productImgSrcIndex = PRODUCT_IMAGES.findIndex((image) => image.label === label); + + const src = PRODUCT_IMAGES?.[productImgSrcIndex]?.src; + + if (!src) { + throw new Error(`ProductImage received an invalid "label" prop: "${label}".`); + } + return ( <> - + - + {isModalOpen && ( image.label === label)} + initialImageIndex={productImgSrcIndex} showImageLabels {...ImageCarouselProps} /> @@ -50,11 +57,11 @@ export const ProductImage = ({ ); }; -export const PRODUCT_IMAGES = [ +const PRODUCT_IMAGES = [ { label: "Fixit Dashboard demo", src: demoDesktopDashboardImageSrc }, - { label: "Fixit Create-Invoice mobile demo", src: demoMobileCreateInvoiceImageSrc }, - { label: "Fixit Data-grid demo", src: demoDesktopDataGridImageSrc }, - { label: "Fixit List-view mobile demo", src: demoMobileListViewImageSrc }, + { label: "Fixit Create-Invoice on mobile", src: demoMobileCreateInvoiceImageSrc }, + { label: "Fixit work orders data-grid", src: demoDesktopDataGridImageSrc }, + { label: "Fixit work orders list-view on mobile", src: demoMobileListViewImageSrc }, ] as const satisfies Array; const StyledDialog = styled(Dialog)({ @@ -73,10 +80,10 @@ const StyledDialog = styled(Dialog)({ }); export type ProductImageProps = OverrideProperties< - CarouselImageConfig, + Omit, { label: (typeof PRODUCT_IMAGES)[number]["label"]; } > & { ImageCarouselProps?: Omit; -} & Omit; +} & Omit; diff --git a/src/pages/LandingPage/classNames.ts b/src/pages/LandingPage/classNames.ts index 86b20673..a89c7c6d 100644 --- a/src/pages/LandingPage/classNames.ts +++ b/src/pages/LandingPage/classNames.ts @@ -4,4 +4,5 @@ export const landingPageClassNames = { textContainer: "landing-page__text-container", graphicsContainer: "landing-page__graphics-container", + footerRoot: "landing-page__footer-root", } as const; diff --git a/src/pages/LoginPage/LoginForm.tsx b/src/pages/LoginPage/LoginForm.tsx index 01ba10a8..7bc8b182 100644 --- a/src/pages/LoginPage/LoginForm.tsx +++ b/src/pages/LoginPage/LoginForm.tsx @@ -2,7 +2,10 @@ import { useNavigate } from "react-router-dom"; import { toast } from "react-toastify"; import { object as yupObject, type InferType } from "yup"; import { useFetchStateContext } from "@/app/FetchStateContext"; -import { Form, FormSubmitButton, TextInput, PasswordInput } from "@/components/Form"; +import { GoogleAuthFormButton } from "@/app/GoogleOAuthContext/GoogleAuthFormButton"; +import { DividerWithText } from "@/components/DataDisplay"; +import { Form, FormSubmitButton } from "@/components/Form"; +import { EmailInput, PasswordInput } from "@/components/Form/Inputs"; import { yupCommonSchema, getInitialValuesFromSchema } from "@/components/Form/helpers"; import { ErrorDialog } from "@/components/Indicators"; import { APP_PATHS } from "@/routes/appPaths"; @@ -12,8 +15,16 @@ export const LoginForm = () => { const nav = useNavigate(); const { fetchWithState, error, clearError } = useFetchStateContext(); - const onSubmit = async (credentials: LoginFormValues) => { - const apiResponse = await fetchWithState(async () => await authService.login(credentials)); + const onSubmit = async ({ password, googleIDToken, ...values }: LoginFormValues) => { + const apiResponse = await fetchWithState( + async () => + await authService.login({ + ...(password + ? { password } // Send one of `password` or `googleIDToken` + : { googleIDToken: googleIDToken! }), + ...values, + }) + ); if (apiResponse?.token) { toast.success("Welcome back!", { toastId: "login-success" }); @@ -26,12 +37,16 @@ export const LoginForm = () => { initialValues={loginFormInitialValues} validationSchema={loginFormSchema} onSubmit={onSubmit} - sx={{ all: "inherit" }} > - + + {error && } + + OR + + } /> ); }; @@ -39,14 +54,15 @@ export const LoginForm = () => { /** * Yup Schema for above `Form`s "validationSchema" prop. */ -const loginFormSchema = yupObject({ +export const loginFormSchema = yupObject({ email: yupCommonSchema.email.required("Required"), - password: yupCommonSchema.password.required("Required"), + password: yupCommonSchema.password, + googleIDToken: yupCommonSchema.googleIDToken, }); /** * Object for above `Form`s "initialValues" prop. */ -const loginFormInitialValues = getInitialValuesFromSchema(loginFormSchema); +export const loginFormInitialValues = getInitialValuesFromSchema(loginFormSchema); -type LoginFormValues = InferType; +export type LoginFormValues = InferType; diff --git a/src/pages/LoginPage/LoginPage.tsx b/src/pages/LoginPage/LoginPage.tsx index e8de5972..e012aa05 100644 --- a/src/pages/LoginPage/LoginPage.tsx +++ b/src/pages/LoginPage/LoginPage.tsx @@ -1,7 +1,7 @@ import Box from "@mui/material/Box"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; import { Link } from "@/components/Navigation"; -import { AuthPageLayout } from "@/layouts/AuthPageLayout"; +import { AuthPageLayout, authPageLayoutClassNames } from "@/layouts/AuthPageLayout"; import { APP_PATHS } from "@/routes/appPaths"; import { LoginForm } from "./LoginForm"; @@ -9,13 +9,20 @@ import { LoginForm } from "./LoginForm"; * **LoginPage** - renders when path is "/login" */ export const LoginPage = () => ( - + ( - - - - Category - Examples - Collected - - - - - A. Identifiers - - Contact details, such as real name, alias, postal address, telephone or mobile contact - number, unique personal identifier, online identifier, Internet Protocol address, email - address, and account name - - NO - - - - B. Personal information categories listed in the California Customer Records statute - - - Name, contact information, education, employment, employment history, and financial - information - - NO - - - C. Protected classification characteristics under California or federal law - Gender and date of birth - NO - - - D. Commercial information - - Transaction information, purchase history, financial details, and payment information - - NO - - - E. Biometric information - Fingerprints and voiceprints - NO - - - F. Internet or other similar network activity - - Browsing history, search history, online behavior, interest data, and interactions with - our and other websites, applications, systems, and advertisements - - NO - - - G. Geolocation data - Device location - NO - - - H. Audio, electronic, visual, thermal, olfactory, or similar information - - Images and audio, video or call recordings created in connection with our business - activities - - NO - - - I. Professional or employment-related information - - Business contact details in order to provide you our Services at a business level or job - title, work history, and professional qualifications if you apply for a job with us - - NO - - - J. Education Information - Student records and directory information - NO - - - K. Inferences drawn from other personal information - - Inferences drawn from any of the collected personal information listed above to create a - profile or summary about, for example, an individual's preferences and characteristics - - NO - - - + ); - -const StyledTable = styled("table")(({ theme: { palette } }) => ({ - borderCollapse: "collapse", - - "& th,td": { - padding: "0.75rem", - border: `1px solid ${palette.grey[700]}`, - }, - - "& td:last-child": { - textAlign: "center", - }, -})); diff --git a/src/pages/PrivacyPolicyPage/PolicySection.tsx b/src/pages/PrivacyPolicyPage/PolicySection.tsx index 0cce4e5a..66586a89 100644 --- a/src/pages/PrivacyPolicyPage/PolicySection.tsx +++ b/src/pages/PrivacyPolicyPage/PolicySection.tsx @@ -9,7 +9,7 @@ export const PolicySection = ({ header, summary, children }: PolicySectionProps) {summary && } {children} diff --git a/src/pages/ProductsPage/ProductsPage.tsx b/src/pages/ProductsPage/ProductsPage.tsx index e31f6861..215acfa8 100644 --- a/src/pages/ProductsPage/ProductsPage.tsx +++ b/src/pages/ProductsPage/ProductsPage.tsx @@ -97,7 +97,7 @@ const StyledDiv = styled("div")(({ theme: { variables } }) => ({ margin: 0, }, - [`& .${navigationClassNames.legalLinksContainer}`]: { + [`& .${navigationClassNames.legalLinksRoot}`]: { marginTop: "1rem", ...(variables.isMobilePageLayout && { marginBottom: "2rem" }), // marginBottom on mobile to add more space at the bottom for the Stripe logo diff --git a/src/pages/RegisterPage/RegisterForm.tsx b/src/pages/RegisterPage/RegisterForm.tsx index 66478af2..af87421a 100644 --- a/src/pages/RegisterPage/RegisterForm.tsx +++ b/src/pages/RegisterPage/RegisterForm.tsx @@ -1,9 +1,11 @@ import { useNavigate } from "react-router-dom"; import { toast } from "react-toastify"; import { object as yupObject, type InferType } from "yup"; -import InputAdornment from "@mui/material/InputAdornment"; import { useFetchStateContext } from "@/app/FetchStateContext"; -import { Form, FormSubmitButton, TextInput, PasswordInput, PhoneInput } from "@/components/Form"; +import { GoogleAuthFormButton } from "@/app/GoogleOAuthContext/GoogleAuthFormButton"; +import { DividerWithText } from "@/components/DataDisplay"; +import { Form, FormSubmitButton } from "@/components/Form"; +import { UserHandleInput, EmailInput, PasswordInput, PhoneInput } from "@/components/Form/Inputs"; import { yupCommonSchema, getInitialValuesFromSchema } from "@/components/Form/helpers"; import { ErrorDialog } from "@/components/Indicators"; import { APP_PATHS } from "@/routes/appPaths"; @@ -13,43 +15,79 @@ export const RegisterForm = () => { const nav = useNavigate(); const { fetchWithState, error, clearError } = useFetchStateContext(); - const handleSubmit = async (values: RegisterFormValues) => { + const handleSubmit = async ({ + handle, + password, + googleIDToken, + ...values + }: RegisterFormValues) => { const apiResponse = await fetchWithState( async () => await authService.registerNewUser({ + handle: `@${handle}`, // <-- "@" prefix added to "handle" + ...(password + ? { password } // Send one of `password` or `googleIDToken` + : { googleIDToken: googleIDToken! }), ...values, - handle: `@${values.handle}`, // <-- "@" prefix added to "handle" }) ); if (apiResponse?.token) { - toast.success(`Welcome to Fixit - please select a subscription to get started!`, { + toast.success(`Welcome to Fixit — please select a subscription to get started!`, { toastId: "select-a-sub", }); nav(APP_PATHS.PRODUCTS); } }; - // TODO Show user password requirements - return ( initialValues={registerFormInitialValues} validationSchema={registerFormSchema} onSubmit={handleSubmit} - sx={{ all: "inherit" }} > - @, - }} - /> + - + + {error && } + + OR + + + text="signup_with" + beforeSetFormikState={({ values, errors, touched, ...formikState }) => ({ + ...formikState, + values: { + ...values, + /* Since the OAuth flow is intended to be expeditious, it's desirable to + ensure that the User can proceed to the next step without interruption. + To that end, optional fields like `phone` here are cleared/reset if their + value is invalid, thereby ensuring form submission isn't blocked. */ + phone: values.phone && !errors.phone ? values.phone : null, + }, + errors: { + ...errors, + phone: undefined, // <-- phone is set to null if invalid, so rm any existing errors + handle: !values.handle + ? "Please choose a user handle (this is how other users will identify you)" + : errors.handle, // <-- will be undefined unless the User's value is invalid + }, + touched: { + ...touched, + phone: true, + handle: true, + }, + })} + requiredFieldInputs={ + <> + + + + } + /> ); }; @@ -60,14 +98,21 @@ export const RegisterForm = () => { const registerFormSchema = yupObject({ handle: yupCommonSchema.string .lowercase() - .matches( - /^[a-z0-9_]{3,50}$/, - "Must be between 3-50 characters, and only contain letters, numbers, and underscores" - ) - .required("Please choose a handle (this is how other users will identify you)"), - phone: yupCommonSchema.phone.required("Please provide a phone number"), + .test({ + name: "is-right-length", + message: "User handles must be between 3-50 characters", + test: (value) => value?.length >= 3 && value?.length <= 50, + }) + .test({ + name: "no-banned-chars", + message: "User handles must only contain letters, numbers, and underscores", + test: (value) => /^[a-z0-9_]{3,50}$/i.test(value), + }) + .required("Please choose a user handle (this is how other users will identify you)"), email: yupCommonSchema.email.required("Please provide an email"), - password: yupCommonSchema.password.required("Please enter a password"), + phone: yupCommonSchema.phone.nullable().default(null), + password: yupCommonSchema.password, + googleIDToken: yupCommonSchema.googleIDToken, }); /** diff --git a/src/pages/RegisterPage/RegisterPage.tsx b/src/pages/RegisterPage/RegisterPage.tsx index cd13b66f..bbf4f170 100644 --- a/src/pages/RegisterPage/RegisterPage.tsx +++ b/src/pages/RegisterPage/RegisterPage.tsx @@ -14,7 +14,13 @@ import { RegisterForm } from "./RegisterForm"; export const RegisterPage = () => ( - + a": { display: "contents" }, + }} + > By registering your account, you agree to the Fixit{" "} Terms of Service and the{" "} @@ -22,7 +28,14 @@ export const RegisterPage = () => ( . - + ); diff --git a/src/pages/TermsOfServicePage/PolicySection.tsx b/src/pages/TermsOfServicePage/PolicySection.tsx index 56269e5a..d8845ff7 100644 --- a/src/pages/TermsOfServicePage/PolicySection.tsx +++ b/src/pages/TermsOfServicePage/PolicySection.tsx @@ -8,7 +8,7 @@ export const PolicySection = ({ header, children }: PolicySectionProps) => ( {children} diff --git a/src/pages/TermsOfServicePage/TermsOfServicePage.tsx b/src/pages/TermsOfServicePage/TermsOfServicePage.tsx index c98f18c3..aa787827 100644 --- a/src/pages/TermsOfServicePage/TermsOfServicePage.tsx +++ b/src/pages/TermsOfServicePage/TermsOfServicePage.tsx @@ -6,7 +6,7 @@ import { PolicySection } from "./PolicySection"; import { ToS_SECTIONS } from "./TermsOfServiceSections"; export const TermsOfServicePage = () => ( - + {/* SECTION 1. AGREEMENT TO TERMS */} @@ -111,10 +111,30 @@ export const TermsOfServicePage = () => ( We accept the following forms of payment:
      -
    • Visa
    • -
    • Mastercard
    • -
    • American Express
    • -
    • Discover
    • +
    • Cards:
    • +
        +
      • Visa
      • +
      • Mastercard
      • +
      • American Express
      • +
      • Discover
      • +
      • Diners Club
      • +
      • JCB
      • +
      • China UnionPay
      • +
      +
    • Digital Wallets:
    • +
        +
      • Apple Pay
      • +
      • Cash App Pay
      • +
      • Google Pay
      • +
      • Link
      • +
      +
    • Bank Redirects:
    • +
        +
      • Bancontact
      • +
      • EPS
      • +
      • giropay
      • +
      • iDEAL
      • +
    You may be required to purchase or pay a fee to access some of our services. You agree to @@ -136,7 +156,14 @@ export const TermsOfServicePage = () => ( We reserve the right to correct any errors or mistakes in pricing, even if we have already requested or received payment. We also reserve the right to refuse any order placed through - the Site. + the Site. We may, in our sole discretion, limit or cancel quantities purchased per person, + per household, or per order. These restrictions may include orders placed by or under the + same customer account, the same payment method, and/or orders that use the same billing or + shipping address. We reserve the right to limit or prohibit orders that, in our sole + judgment, appear to be placed by dealers, resellers, or distributors. If we make a change to + or cancel an order, we may attempt to notify you by contacting the e-mail and/or billing + address/phone number provided at the time the order was made. We also reserve the right to + remove, modify, or add accepted methods of payment at any time without notice.
    diff --git a/src/pages/WorkOrderFormView/FormCreateWO.tsx b/src/pages/WorkOrderFormView/FormCreateWO.tsx index 3adc96c4..05977f48 100644 --- a/src/pages/WorkOrderFormView/FormCreateWO.tsx +++ b/src/pages/WorkOrderFormView/FormCreateWO.tsx @@ -34,7 +34,7 @@ export const FormCreateWO = () => { ...formValues, }, }, - }).catch((err) => logger.error(err)); + }).catch(logger.error); await playLottie(); diff --git a/src/pages/WorkOrderFormView/FormUpdateWO.tsx b/src/pages/WorkOrderFormView/FormUpdateWO.tsx index 3e63c7f2..a0233795 100644 --- a/src/pages/WorkOrderFormView/FormUpdateWO.tsx +++ b/src/pages/WorkOrderFormView/FormUpdateWO.tsx @@ -20,7 +20,7 @@ export const FormUpdateWO = ({ existingWorkOrder }: { existingWorkOrder: WorkOrd workOrderID: existingWorkOrder.id, workOrder: formValues, }, - }).catch((err) => logger.error(err)); + }).catch(logger.error); await playLottie(); diff --git a/src/pages/WorkOrderFormView/schema.ts b/src/pages/WorkOrderFormView/schema.ts index bcdbd4c3..d47b681f 100644 --- a/src/pages/WorkOrderFormView/schema.ts +++ b/src/pages/WorkOrderFormView/schema.ts @@ -1,6 +1,6 @@ import { object as yupObject, string, date, type InferType } from "yup"; +import { yupBaseChecklistSchema } from "@/components/Form/Inputs/ChecklistInput/helpers"; import { yupCommonSchema } from "@/components/Form/helpers/yupCommonSchema"; -import { yupBaseChecklistSchema } from "@/components/Form/inputs/ChecklistInput/helpers"; import { WORK_ORDER_CATEGORIES, WORK_ORDER_PRIORITIES } from "@/types/WorkOrder"; export const workOrderFormSchema = yupObject({ diff --git a/src/routes/RootAppRouter.tsx b/src/routes/RootAppRouter.tsx index ea218949..7c8dbc68 100644 --- a/src/routes/RootAppRouter.tsx +++ b/src/routes/RootAppRouter.tsx @@ -38,6 +38,10 @@ const rootAppBrowserRouter = sentryCreateBrowserRouter( lazy: () => import(/* webpackChunkName: "PrivacyPolicyPage" */ "@/pages/PrivacyPolicyPage"), }, + { + path: APP_PATHS.COOKIES, + lazy: () => import(/* webpackChunkName: "CookiePolicyPage" */ "@/pages/CookiePolicyPage"), + }, { path: APP_PATHS.PRODUCTS, lazy: () => import(/* webpackChunkName: "ProductsPage" */ "@/pages/ProductsPage"), diff --git a/src/routes/appLinks.ts b/src/routes/appLinks.ts new file mode 100644 index 00000000..2f687de2 --- /dev/null +++ b/src/routes/appLinks.ts @@ -0,0 +1,6 @@ +/** + * An object containing commonly-used external links. + */ +export const APP_LINKS = { + REPO: "https://github.com/Nerdware-LLC/fixit-web#readme", +} as const satisfies Record; diff --git a/src/routes/appNavActions.tsx b/src/routes/appNavActions.tsx index d98ca612..e18bd4ef 100644 --- a/src/routes/appNavActions.tsx +++ b/src/routes/appNavActions.tsx @@ -42,7 +42,7 @@ export const APP_NAV_ACTIONS = { label: "Logout", doBeforeNav: () => { authenticatedUserStore.deauthenticate(); - toast("👋 See ya later!", { toastId: "logout" }); + toast("Successfully signed out 👋", { toastId: "logout", style: { textAlign: "center" } }); }, path: APP_PATHS.ROOT, icon: , @@ -61,11 +61,21 @@ export const APP_NAV_ACTIONS = { path: APP_PATHS.PRODUCTS, tooltip: "See pricing for Fixit products", }, + ToS: { + label: "Terms of Service", + path: APP_PATHS.ToS, + tooltip: "View our terms of service", + }, PRIVACY: { label: "Privacy", path: APP_PATHS.PRIVACY, tooltip: "View our privacy policy", }, + COOKIES: { + label: "Cookie Policy", + path: APP_PATHS.COOKIES, + tooltip: "View our cookie policy", + }, PRODUCTS: { label: "Select a Subscription", path: APP_PATHS.PRODUCTS, diff --git a/src/routes/appPaths.ts b/src/routes/appPaths.ts index 9c637fae..39438416 100644 --- a/src/routes/appPaths.ts +++ b/src/routes/appPaths.ts @@ -49,6 +49,7 @@ export const APP_PATHS = { LANDING_PAGE: ROOT, ToS: "/ToS", PRIVACY: `/privacy`, + COOKIES: `/cookie-policy`, REGISTER: `/register`, LOGIN: `/login`, PRODUCTS: `/products`, diff --git a/src/routes/getProtectedRouteLoader.tsx b/src/routes/getProtectedRouteLoader.tsx index 2b7f87a3..c39f972e 100644 --- a/src/routes/getProtectedRouteLoader.tsx +++ b/src/routes/getProtectedRouteLoader.tsx @@ -39,7 +39,7 @@ export const getProtectedRouteLoader = ( style: { backgroundColor: "transparent" }, // hide react-toastify's modal }); - throw redirect(APP_PATHS.ROOT); + throw redirect(APP_PATHS.PRODUCTS); } } diff --git a/src/routes/helpers.ts b/src/routes/helpers.ts index 6a05bc82..f585b79b 100644 --- a/src/routes/helpers.ts +++ b/src/routes/helpers.ts @@ -14,3 +14,12 @@ export const getItemViewPath = ( ) => { return `/${HOME}/${itemType}/${encodeURIComponent(id)}`; }; + +/** + * This is a helper function to determine if a given `urlStr` is an external URL. + * @param urlStr The URL to check. + * @returns `true` if the `urlStr` is an external URL, `false` otherwise. + */ +export const isExternalUrl = (urlStr?: string) => { + return urlStr && urlStr.startsWith("http") && !urlStr.includes("gofixit.app"); +}; diff --git a/src/services/authService.ts b/src/services/authService.ts index 7e127454..d9e5e300 100644 --- a/src/services/authService.ts +++ b/src/services/authService.ts @@ -12,6 +12,11 @@ export const authService = { ...userLoginArgs, }); }, + loginWithGoogleToken: async (googleTokenLoginArgs: GoogleTokenLoginParams) => { + return await httpService.post("/auth/google-token", { + ...googleTokenLoginArgs, + }); + }, refreshAuthToken: async () => { return await httpService.post("/auth/token"); }, @@ -20,3 +25,5 @@ export const authService = { export type RegisterNewUserParams = RestApiRequestBodyByPath["/auth/register"]; export type LoginParams = RestApiRequestBodyByPath["/auth/login"]; + +export type GoogleTokenLoginParams = RestApiRequestBodyByPath["/auth/google-token"]; diff --git a/src/services/httpService.ts b/src/services/httpService.ts index 5dcbc7d9..fbbaa99f 100644 --- a/src/services/httpService.ts +++ b/src/services/httpService.ts @@ -26,7 +26,7 @@ import type { axios.defaults.baseURL = ENV.API_URI; axios.defaults.signal = abortController.signal; axios.defaults.timeout = 10000; -axios.defaults.withCredentials = true; +axios.defaults.withCredentials = ENV.IS_DEPLOYED_ENV; // Before each REQUEST goes out, do this: axios.interceptors.request.use( diff --git a/src/stores/authenticatedUserStore.ts b/src/stores/authenticatedUserStore.ts index 2ca11740..408bde87 100644 --- a/src/stores/authenticatedUserStore.ts +++ b/src/stores/authenticatedUserStore.ts @@ -1,25 +1,49 @@ +import dayjs from "dayjs"; import { jwtDecode } from "jwt-decode"; import { apolloClient } from "@/app/ApolloProvider/apolloClient"; +import { googleLogout } from "@/app/GoogleOAuthContext/helpers"; import { ReactiveStore } from "./ReactiveStore"; import { LocalStorageValueManager } from "./helpers"; import { isActiveAccountStore } from "./isActiveAccountStore"; import { isAuthenticatedStore } from "./isAuthenticatedStore"; import { isConnectOnboardingCompleteStore } from "./isConnectOnboardingCompleteStore"; import type { AuthTokenPayload } from "@/graphql/types"; +import type { Except } from "type-fest"; /** - * A `LocalStorageValueManager` instance for the `"authToken"` key. + * The type of object stored in the {@link authenticatedUserStore}. * + * This type is based on the {@link AuthTokenPayload} type, with the following modifications: + * - No `__typename` field + * - All other fields are required/non-optional (missing values default to `null`) + */ +export type AuthenticatedUserObject = Required>; + +/** + * A `LocalStorageValueManager` instance for the `"authToken"` key. * Used by the {@link AuthenticatedUserStore} to manage the auth token. */ export const authTokenLocalStorage = new LocalStorageValueManager("authToken", null); -class AuthenticatedUserStore extends ReactiveStore { +/** + * A `LocalStorageValueManager` instance for the `"authTokenUpdatedAt"` key. + * Used to determine if the User should be shown the Google OAuth OneTap prompt on app load. + */ +export const authTokenUpdatedAtLocalStorage = new LocalStorageValueManager( + "authTokenUpdatedAt", + null +); + +class AuthenticatedUserStore extends ReactiveStore< + AuthenticatedUserObject | null, + AuthenticatedUserObject +> { /** * Process an auth token to authenticate the user. */ - processAuthToken(encodedAuthToken: string): AuthTokenPayload { + processAuthToken(encodedAuthToken: string): AuthenticatedUserObject { authTokenLocalStorage.set(encodedAuthToken); + authTokenUpdatedAtLocalStorage.set(dayjs().unix()); const tokenPayload: AuthTokenPayload = jwtDecode(encodedAuthToken); @@ -31,11 +55,47 @@ class AuthenticatedUserStore extends ReactiveStore _`If an "authToken" is present, but it's more than 10h old, it is removed from LocalStorage.`_ + */ + shouldAttemptAuthTokenRefresh(): boolean { + let shouldAttemptAuthTokenRefresh = false; + + if (authTokenLocalStorage.get()) { + // Get "authTokenUpdatedAt" unix timestamp from LocalStorage, default to "0" if not present + const authTokenUpdatedAt = authTokenUpdatedAtLocalStorage.get() ?? 0; + const tenHoursAgoTimestamp = dayjs().subtract(10, "hours").unix(); + + // If the token's updatedAt timestamp is less than 10h old, an attempt can be made to refresh it + if (authTokenUpdatedAt > tenHoursAgoTimestamp) shouldAttemptAuthTokenRefresh = true; + else authTokenLocalStorage.remove(); // rm the token if the timestamp is too old + } + + return shouldAttemptAuthTokenRefresh; } /** @@ -51,6 +111,7 @@ class AuthenticatedUserStore extends ReactiveStore makeFakeTextUpToNumChars(255), - userLogin: makeFakeUserLogin, userProfile: makeFakeUserProfile, userStripeConnectAccount: makeFakeUserStripeConnectAccount, userSubscription: makeFakeUserSubscription, diff --git a/src/tests/utils/makeFake/userLogin.ts b/src/tests/utils/makeFake/userLogin.ts deleted file mode 100644 index 9c315324..00000000 --- a/src/tests/utils/makeFake/userLogin.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { faker } from "@faker-js/faker/locale/en_US"; -import { isString } from "@nerdware/ts-type-safety-utils"; -import { getMakeFakeFn } from "./_helpers"; -import type { OpenApiSchemas } from "@/types/open-api"; -import type { UnionToIntersection } from "type-fest"; - -export const makeFakeUserLogin = ( - loginTypeOrOverrides: - | "LOCAL_AUTH" - | "GOOGLE_OAUTH" - | Partial> = {} -): Omit => { - return isString(loginTypeOrOverrides) - ? loginTypeOrOverrides === "GOOGLE_OAUTH" - ? makeFakeGoogleOAuthLoginCredentials() - : makeFakeLocalLoginCredentials() - : "googleID" in loginTypeOrOverrides || "googleAccessToken" in loginTypeOrOverrides - ? makeFakeGoogleOAuthLoginCredentials(loginTypeOrOverrides) - : makeFakeLocalLoginCredentials(loginTypeOrOverrides); -}; - -/////////////////////////////////////////////////////////////////////////////// -// FAKE LOCAL CREDENTIALS: - -type FakeLocalLoginCredentials = Omit; - -export const makeFakeLocalLoginCredentials = ( - overrides?: Partial -): FakeLocalLoginCredentials => ({ password: makeFakePassword(overrides) }); - -export const makeFakePassword = getMakeFakeFn( - "password", - () => faker.string.alphanumeric(15) -); - -/////////////////////////////////////////////////////////////////////////////// -// FAKE GOOGLE OAUTH CREDENTIALS: - -type FakeGoogleOAuthLoginCredentials = Omit; - -export const makeFakeGoogleOAuthLoginCredentials = ( - overrides?: Partial -): FakeGoogleOAuthLoginCredentials => ({ - googleID: makeFakeGoogleID(overrides), - googleAccessToken: makeFakeGoogleAccessToken(overrides), -}); - -export const makeFakeGoogleID = getMakeFakeFn( - "googleID", - () => `googleID-${faker.string.alphanumeric(10)}` -); - -export const makeFakeGoogleAccessToken = getMakeFakeFn( - "googleAccessToken", - () => `googleAccessToken-${faker.string.alphanumeric(10)}` -); diff --git a/src/types/__codegen__/open-api.ts b/src/types/__codegen__/open-api.ts index 066b81cf..fb2f8d29 100644 --- a/src/types/__codegen__/open-api.ts +++ b/src/types/__codegen__/open-api.ts @@ -89,6 +89,23 @@ export interface paths { patch?: never; trace?: never; }; + "/auth/google-token": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Processes JSON JWT payloads from GoogleID services (existing users only) */ + post: operations["GoogleToken"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/connect/account-link": { parameters: { query?: never; @@ -181,7 +198,7 @@ export interface components { UserRegistrationParams: components["schemas"]["LoginCredentials"] & components["schemas"]["ExpoPushTokenParam"] & { handle: components["schemas"]["Handle"]; email: components["schemas"]["Email"]; - phone: components["schemas"]["Phone"]; + phone?: components["schemas"]["Phone"]; profile?: components["schemas"]["UserProfileParams"]; }; LoginParams: components["schemas"]["LoginCredentials"] & components["schemas"]["ExpoPushTokenParam"]; @@ -194,8 +211,13 @@ export interface components { /** @description The user's login credentials for google-oauth authentication */ GoogleOAuthLoginCredentials: { email: components["schemas"]["Email"]; - googleID: components["schemas"]["GoogleID"]; - googleAccessToken: components["schemas"]["GoogleAccessToken"]; + googleIDToken: components["schemas"]["GoogleIDToken"]; + }; + /** @description An object which contains a base64-encoded JSON JWT from GoogleID services + * under the key "googleIDToken". + * */ + GoogleIDTokenField: { + googleIDToken: components["schemas"]["GoogleIDToken"]; }; /** @description Parameters for a user's profile. */ UserProfileParams: { @@ -501,10 +523,8 @@ export interface components { * @description A user's email address. */ Email: string; - /** @description The user's OAuth Google Access Token (auth: google-oauth). */ - GoogleAccessToken: string; - /** @description The user's OAuth Google ID (auth: google-oauth). */ - GoogleID: string; + /** @description A base64-encoded JSON JWT from GoogleID services (auth: google-oauth). */ + GoogleIDToken: string; /** @description A user's Fixit handle. */ Handle: string; /** @@ -526,7 +546,7 @@ export interface components { * stripped from the phone number upon receipt, so "+1 (555) 555-5555" will be * treated the same as "5555555555". * */ - Phone: string; + Phone: string | null; /** @description A user-provided promo code to apply a discount at checkout. */ PromoCode: string; /** @@ -659,6 +679,11 @@ export interface components { }; }; }; + GoogleTokenRequest: { + content: { + "application/json": components["schemas"]["GoogleIDTokenField"]; + }; + }; LoginRequest: { content: { "application/json": components["schemas"]["LoginParams"]; @@ -785,6 +810,22 @@ export interface operations { default: components["responses"]["UnexpectedResponse"]; }; }; + GoogleToken: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: components["requestBodies"]["GoogleTokenRequest"]; + responses: { + 200: components["responses"]["200AuthToken"]; + 400: components["responses"]["400InvalidUserInput"]; + 401: components["responses"]["401AuthenticationRequired"]; + "5XX": components["responses"]["5xxInternalServerError"]; + default: components["responses"]["UnexpectedResponse"]; + }; + }; ConnectAccountLink: { parameters: { query?: never; diff --git a/src/types/globals.d.ts b/src/types/globals.d.ts index 8c701cd8..2a833dd3 100644 --- a/src/types/globals.d.ts +++ b/src/types/globals.d.ts @@ -1,4 +1,5 @@ import type { JsonValue } from "type-fest"; +import type { GoogleOAuthClient } from "./googleOAuth"; declare global { /** @@ -17,4 +18,12 @@ declare global { parse(text: number, reviver?: (this: any, key: string, value: unknown) => unknown): number; parse(text: null, reviver?: (this: any, key: string, value: unknown) => unknown): null; } + + interface Window { + /** + * Google OAuth Client + * > The Google OAuth client library is loaded asynchronously via a script tag. + */ + google?: GoogleOAuthClient; + } } diff --git a/src/types/googleOAuth.ts b/src/types/googleOAuth.ts new file mode 100644 index 00000000..c03cf07e --- /dev/null +++ b/src/types/googleOAuth.ts @@ -0,0 +1,385 @@ +export type Context = "signin" | "signup" | "use"; + +export type UxMode = "popup" | "redirect"; + +export type ErrorCode = + | "invalid_request" + | "access_denied" + | "unauthorized_client" + | "unsupported_response_type" + | "invalid_scope" + | "server_error" + | "temporarily_unavailable"; + +export interface IdConfiguration { + /** Your application's client ID */ + client_id?: string; + /** Enables automatic selection on Google One Tap */ + auto_select?: boolean; + /** ID token callback handler */ + callback?: (credentialResponse: CredentialResponse) => void; + /** The Sign In With Google button UX flow */ + ux_mode?: UxMode; + /** The URL of your login endpoint */ + login_uri?: string; + /** The URL of your password credential handler endpoint */ + native_login_uri?: string; + /** The JavaScript password credential handler function name */ + native_callback?: (response: { id: string; password: string }) => void; + /** Controls whether to cancel the prompt if the user clicks outside of the prompt */ + cancel_on_tap_outside?: boolean; + /** The DOM ID of the One Tap prompt container element */ + prompt_parent_id?: string; + /** A random string for ID tokens */ + nonce?: string; + /** The title and words in the One Tap prompt */ + context?: Context; + /** If you need to call One Tap in the parent domain and its subdomains, pass the parent domain to this attribute so that a single shared cookie is used. */ + state_cookie_domain?: string; + /** The origins that are allowed to embed the intermediate iframe. One Tap will run in the intermediate iframe mode if this attribute presents */ + allowed_parent_origin?: string | string[]; + /** Overrides the default intermediate iframe behavior when users manually close One Tap */ + intermediate_iframe_close_callback?: () => void; + /** Enables upgraded One Tap UX on ITP browsers */ + itp_support?: boolean; + /** + * If your application knows the Workspace domain the user belongs to, use this to provide a hint + * to Google. For more information, see the [hd][google-oidc-hd] field in the OpenID Connect docs. + * + * [google-oidc-hd]: https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters + */ + hosted_domain?: string; + /** + * Allow the browser to control user sign-in prompts and mediate the sign-in flow between your website and Google. + * @default true + */ + use_fedcm_for_prompt?: boolean; +} + +export interface CredentialResponse { + /** This field is the returned ID token */ + credential: string; + /** This field sets how the credential is selected */ + select_by?: + | "auto" + | "user" + | "user_1tap" + | "user_2tap" + | "btn" + | "btn_confirm" + | "btn_add_session" + | "btn_confirm_add_session"; + clientId?: string; +} + +export interface GoogleCredentialResponse extends CredentialResponse { + client_id?: string; +} + +export interface GsiButtonConfiguration { + /** The button [type](https://developers.google.com/identity/gsi/web/reference/js-reference#type): icon, or standard button */ + type?: "standard" | "icon"; + /** The button [theme](https://developers.google.com/identity/gsi/web/reference/js-reference#theme). For example, filled_blue or filled_black */ + theme?: "outline" | "filled_blue" | "filled_black"; + /** The button [size](https://developers.google.com/identity/gsi/web/reference/js-reference#size). For example, small or large */ + size?: "large" | "medium" | "small"; + /** The button [text](https://developers.google.com/identity/gsi/web/reference/js-reference#text). For example, "Sign in with Google" or "Sign up with Google" */ + text?: "signin_with" | "signup_with" | "continue_with" | "signin"; + /** The button [shape](https://developers.google.com/identity/gsi/web/reference/js-reference#shape). For example, rectangular or circular */ + shape?: "rectangular" | "pill" | "circle" | "square"; + /** The Google [logo alignment](https://developers.google.com/identity/gsi/web/reference/js-reference#logo_alignment): left or center */ + logo_alignment?: "left" | "center"; + /** The button [width](https://developers.google.com/identity/gsi/web/reference/js-reference#width), in pixels */ + width?: string | number; + /** If set, then the button [language](https://developers.google.com/identity/gsi/web/reference/js-reference#locale) is rendered */ + locale?: string; + /** If set, this [function](https://developers.google.com/identity/gsi/web/reference/js-reference#click_listener) will be called when the Sign in with Google button is clicked. */ + click_listener?: () => void; +} + +/** + * @see https://developers.google.com/identity/gsi/web/guides/fedcm-migration + */ +export interface PromptMomentNotification { + /** Is this notification for a skipped moment? */ + isSkippedMoment: () => boolean; + /** Is this notification for a dismissed moment? */ + isDismissedMoment: () => boolean; + /** The detailed reason for the dismissa */ + getDismissedReason: () => "credential_returned" | "cancel_called" | "flow_restarted"; + /** Return a string for the moment type */ + getMomentType: () => "display" | "skipped" | "dismissed"; +} + +export interface TokenResponse { + /** The access token of a successful token response. */ + access_token: string; + /** The lifetime in seconds of the access token. */ + expires_in: number; + /** The hosted domain the signed-in user belongs to. */ + hd?: string; + /** The prompt value that was used from the possible list of values specified by TokenClientConfig or OverridableTokenClientConfig */ + prompt: string; + /** The type of the token issued. */ + token_type: string; + /** A space-delimited list of scopes that are approved by the user. */ + scope: string; + /** The string value that your application uses to maintain state between your authorization request and the response. */ + state?: string; + /** A single ASCII error code. */ + error?: ErrorCode; + /** Human-readable ASCII text providing additional information, used to assist the client developer in understanding the error that occurred. */ + error_description?: string; + /** A URI identifying a human-readable web page with information about the error, used to provide the client developer with additional information about the error. */ + error_uri?: string; +} + +export type NonOAuthError = { + /** + * Some non-OAuth errors, such as the popup window failed to open, or closed + * before an OAuth response was returned. + * + * https://developers.google.com/identity/oauth2/web/reference/js-reference#TokenClientConfig + * https://developers.google.com/identity/oauth2/web/reference/js-reference#CodeClientConfig + */ + type: "popup_failed_to_open" | "popup_closed" | "unknown"; +}; + +export interface TokenClientConfig { + /** + * The client ID for your application. You can find this value in the + * [API Console](https://console.cloud.google.com/apis/dashboard) + */ + client_id: string; + + /** + * A space-delimited list of scopes that identify the resources that your + * application could access on the user's behalf. These values inform the + * consent screen that Google displays to the user + */ + scope: string; + + /** + * Optional, defaults to true. Enables applications to use incremental authorization to + * request access to additional scopes in context. If you set this parameter's value to + * false and the authorization request is granted, then the new access token will only + * cover any scopes to which the scope requested in this TokenClientConfig. + */ + include_granted_scopes?: boolean; + + /** + * Required for popup UX. The JavaScript function name that handles returned code response + * The property will be ignored by the redirect UX + */ + callback?: (response: TokenResponse) => void; + + /** + * Optional. The JavaScript function that handles some non-OAuth errors, such as the + * popup window failed to open, or closed before an OAuth response was returned. + */ + error_callback?: (nonOAuthError: NonOAuthError) => void; + + /** + * Optional, defaults to 'select_account'. A space-delimited, case-sensitive list of prompts to present the user + */ + prompt?: "" | "none" | "consent" | "select_account"; + + /** + * Optional, defaults to true. If set to false, [more granular Google Account permissions][link] + * will be disabled for clients created before 2019. No effect for newer clients, since more + * granular permissions is always enabled for them. + * + * [link]: https://developers.googleblog.com/2018/10/more-granular-google-account.html + */ + enable_serial_consent?: boolean; + + /** + * Optional. If your app knows which user should authorize the request, it can use this property + * to provide a hint to Google. The email address for the target user. For more information, see + * the [login_hint](https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters) field in the OpenID Connect docs. + */ + hint?: string; + + /** + * Optional. If your application knows the Workspace domain the user belongs to, use this to + * provide a hint to Google. For more information, see the [hd][hd-link] field in the OIDC docs. + * + * [hd-link]: https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters + */ + hosted_domain?: string; + + /** + * Optional. Not recommended. Specifies any string value that your application uses to + * maintain state between your authorization request and the authorization server's response. + */ + state?: string; +} + +export interface OverridableTokenClientConfig { + /** + * Optional. A space-delimited, case-sensitive list of prompts to present the user. + */ + prompt?: "" | "none" | "consent" | "select_account"; + + /** + * Optional. If set to false, [more granular Google Account permissions][link] will be disabled + * for clients created before 2019. No effect for newer clients, since more granular permissions + * is always enabled for them. + * + * [link]: https://developers.googleblog.com/2018/10/more-granular-google-account.html + */ + enable_serial_consent?: boolean; + + /** + * Optional. If your application knows which user should authorize the request, it can use this + * property to provide a hint to Google. The email address for the target user. For more info, see + * the [login_hint](https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters) field in the OpenID Connect docs. + */ + hint?: string; + + /** + * Optional. Not recommended. Specifies any string value that your application uses to maintain + * state between your authorization request and the authorization server's response. + */ + state?: string; +} + +export interface CodeResponse { + /** The authorization code of a successful token response */ + code: string; + /** A space-delimited list of scopes that are approved by the user */ + scope: string; + /** The string value that your application uses to maintain state between your authorization request and the response */ + state?: string; + /** A single ASCII error code */ + error?: ErrorCode; + /** Human-readable ASCII text providing additional information, used to assist the client developer in understanding the error that occurred */ + error_description?: string; + /** A URI identifying a human-readable web page with information about the error, used to provide the client developer with additional information about the error */ + error_uri?: string; +} + +export interface CodeClientConfig { + /** + * Required. The client ID for your application. You can find this value in the [API Console](https://console.developers.google.com/) + */ + client_id: string; + + /** + * Required. A space-delimited list of scopes that identify the resources that your application + * could access on the user's behalf. These values inform the consent screen that Google displays + * to the user + */ + scope: string; + + /** + * Optional, defaults to true. Enables applications to use incremental authorization to + * request access to additional scopes in context. If you set this parameter's value to + * false and the authorization request is granted, then the new access token will only + * cover any scopes to which the scope requested in this CodeClientConfig. + */ + include_granted_scopes?: boolean; + + /** + * Required for redirect UX. Determines where the API server redirects the user after the user + * completes the authorization flow. The value must exactly match one of the authorized redirect + * URIs for the OAuth 2.0 client, which you configured in the API Console and must conform to our + * [Redirect URI validation](https://developers.google.com/identity/protocols/oauth2/web-server#uri-validation) rules. The property will be ignored by the popup UX + */ + redirect_uri?: string; + + /** + * Required for popup UX. The JavaScript function name that handles returned code response. + * The property will be ignored by the redirect UX + */ + callback?: (codeResponse: CodeResponse) => void; + + /** + * Optional. Recommended for redirect UX. Specifies any string value that your application uses + * to maintain state between your authorization request and the authorization server's response + */ + state?: string; + + /** + * Optional, defaults to true. If set to false, [more granular Google Account permissions][link] + * will be disabled for clients created before 2019. No effect for newer clients, since more + * granular permissions is always enabled for them + * + * [link]: https://developers.googleblog.com/2018/10/more-granular-google-account.html + */ + enable_serial_consent?: boolean; + + /** + * Optional. If your application knows which user should authorize the request, it can use this + * property to provide a hint to Google. The email address for the target user. For more info, see + * the [login_hint](https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters) field in the OpenID Connect docs + */ + hint?: string; + + /** + * Optional. If your application knows the Workspace domain the user belongs to, use this to + * provide a hint to Google. For more information, see the [hd][hd-link] field in the OIDC docs + * + * [hd-link]: https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters + */ + hosted_domain?: string; + + /** + * Optional. The UX mode to use for the authorization flow. + * By default, it will open the consent flow in a popup. Valid values are popup and redirect + */ + ux_mode?: "popup" | "redirect"; + + /** + * Optional, defaults to 'false'. Boolean value to prompt the user to select an account + */ + select_account?: boolean; +} + +export type MomentListener = (promptMomentNotification: PromptMomentNotification) => void; + +/** + * Google OAuth Client + * > The Google OAuth client library is loaded asynchronously via a script tag. + */ +export interface GoogleOAuthClient { + accounts: { + id: { + initialize: (input: IdConfiguration) => void; + prompt: (momentListener?: MomentListener) => void; + renderButton: (parent: HTMLElement, options: GsiButtonConfiguration) => void; + disableAutoSelect: () => void; + storeCredential: ( + credential: { id: string; password: string }, + callback?: () => void + ) => void; + cancel: () => void; + onGoogleLibraryLoad: (...args: unknown[]) => unknown; + revoke: (accessToken: string, done: () => void) => void; + }; + + oauth2: { + initTokenClient: (config: TokenClientConfig) => GoogleOAuthTokenClient; + initCodeClient: (config: CodeClientConfig) => GoogleOAuthCodeClient; + hasGrantedAnyScope: ( + tokenResponse: TokenResponse, + firstScope: string, + ...restScopes: string[] + ) => boolean; + hasGrantedAllScopes: ( + tokenResponse: TokenResponse, + firstScope: string, + ...restScopes: string[] + ) => boolean; + revoke: (accessToken: string, done?: () => void) => void; + }; + }; +} + +export interface GoogleOAuthTokenClient { + requestAccessToken: (overridableClientConfig?: OverridableTokenClientConfig) => void; +} + +export interface GoogleOAuthCodeClient { + requestCode: () => void; +} diff --git a/src/types/index.ts b/src/types/index.ts index dc63f5c9..4ae578c9 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,4 @@ +export * from "./googleOAuth"; export * from "./open-api"; export * from "./Invoice"; diff --git a/src/types/vite-env.d.ts b/src/types/vite-env.d.ts index c1e1f59a..b633690c 100644 --- a/src/types/vite-env.d.ts +++ b/src/types/vite-env.d.ts @@ -6,4 +6,5 @@ interface ImportMetaEnv { VITE_API_HOST?: string; VITE_API_BASE_PATH?: string; VITE_STRIPE_PUBLISHABLE_KEY?: string; + VITE_GOOGLE_OAUTH_CLIENT_ID?: string; } diff --git a/src/utils/typeSafety/dayjs.ts b/src/utils/typeSafety/dayjs.ts index 80f69f13..cfb307f1 100644 --- a/src/utils/typeSafety/dayjs.ts +++ b/src/utils/typeSafety/dayjs.ts @@ -1,3 +1,4 @@ +import { isSafeInteger } from "@nerdware/ts-type-safety-utils"; import dayjs, { type ConfigType as DayJsCtorParamType } from "dayjs"; /** @@ -50,11 +51,13 @@ export const isValidTimestamp = ( value?: unknown, onlyAllow13DigitNumbers: boolean = true ): value is ValidTimestamp => { + // Check for values types that break the dayjs ctor: if (!value || INVALID_TIMESTAMP_VALUE_TYPES.has(typeof value)) { return false; } - if (typeof value === "number" && onlyAllow13DigitNumbers && `${value}`.length !== 13) { + // If onlyAllow13DigitNumbers is true, check for non-13-digit numbers: + if (isSafeInteger(value) && onlyAllow13DigitNumbers && `${value}`.length !== 13) { return false; }