From 20be316064b675c0c6b393cbce5c31ed746dd489 Mon Sep 17 00:00:00 2001 From: LauraPinilla <54566275+LauraPinilla@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:03:59 -0600 Subject: [PATCH 1/5] Adding recaptcha_v3 (#2031) * recaptcha_v3 * attending feedback * attending feedback * attending feedback * attending feedback * fixing package-lock.json * fixing package-lock * fixing package-lock * fixing lock file * fixing test and linting errors * fixing test * add tests * fixing tests * fixing linting errors --- blocks/identity-block/_index.scss | 12 ++ .../bot-challenge-protection/index.jsx | 91 ++++---- .../bot-challenge-protection/index.test.jsx | 30 ++- .../bot-challenge-protection/reCaptchaV3.js | 30 +++ .../identity-block/features/login/default.jsx | 54 +++-- .../features/login/default.test.jsx | 40 +++- blocks/identity-block/intl.json | 15 ++ blocks/identity-block/package-lock.json | 122 +++++++++-- blocks/identity-block/package.json | 3 +- blocks/identity-block/themes/commerce.json | 120 ++++++++++- blocks/identity-block/themes/news.json | 64 +++++- blocks/identity-block/utils/useRecaptcha.js | 62 ++++++ .../identity-block/utils/useRecaptcha.test.js | 199 ++++++++++++++++++ locale/en.json | 5 + package-lock.json | 17 +- package.json | 4 +- 16 files changed, 762 insertions(+), 106 deletions(-) create mode 100644 blocks/identity-block/components/bot-challenge-protection/reCaptchaV3.js create mode 100644 blocks/identity-block/utils/useRecaptcha.js create mode 100644 blocks/identity-block/utils/useRecaptcha.test.js diff --git a/blocks/identity-block/_index.scss b/blocks/identity-block/_index.scss index c430c88a87..237117212c 100644 --- a/blocks/identity-block/_index.scss +++ b/blocks/identity-block/_index.scss @@ -70,6 +70,18 @@ @include scss.block-components("login-form-privacy-statement"); @include scss.block-properties("login-form-privacy-statement"); } + &__sign-up-div { + @include scss.block-components("login-form-sign-up-div"); + @include scss.block-properties("login-form-sign-up-div"); + } + &__sign-up-button { + @include scss.block-components("login-form-sign-up-button"); + @include scss.block-properties("login-form-sign-up-button"); + } + &__login-form-error { + @include scss.block-components("login-form-error"); + @include scss.block-properties("login-form-error"); + } } .b-login-links { diff --git a/blocks/identity-block/components/bot-challenge-protection/index.jsx b/blocks/identity-block/components/bot-challenge-protection/index.jsx index fb2f70a6ca..e2ecc53ba7 100644 --- a/blocks/identity-block/components/bot-challenge-protection/index.jsx +++ b/blocks/identity-block/components/bot-challenge-protection/index.jsx @@ -1,64 +1,57 @@ -import React, { useState, useEffect } from "react"; -import { useFusionContext } from "fusion:context"; -import getProperties from "fusion:properties"; -import getTranslatedPhrases from "fusion:intl"; -import { Paragraph, useIdentity, useSales } from "@wpmedia/arc-themes-components"; +import React from "react"; import ReCAPTCHA from "react-google-recaptcha"; +import { GoogleReCaptchaProvider } from "react-google-recaptcha-v3"; -const BotChallengeProtection = ({ challengeIn, setCaptchaToken, className, captchaError, setCaptchaError }) => { - const { Identity, isInitialized } = useIdentity(); - const { Sales } = useSales(); - const [siteKey, setSiteKey] = useState(); +import { usePhrases, useIdentity, Paragraph } from "@wpmedia/arc-themes-components"; +import useRecaptcha, { RECAPTCHA_V2, RECAPTCHA_V3 } from "../../utils/useRecaptcha"; + +// eslint-disable-next-line +import RecaptchaV3 from "./reCaptchaV3"; + +export const ARCXP_CAPTCHA= "ArcXP_captchaToken" + +const BotChallengeProtection = ({ challengeIn, setCaptchaToken, className, captchaError, setCaptchaError, resetRecaptcha }) => { + + const { isInitialized } = useIdentity(); + const { recaptchaVersion, siteKey, isRecaptchaEnabled } = useRecaptcha(challengeIn); + const phrases = usePhrases(); const onChange = (value) => { setCaptchaToken(value); setCaptchaError(null); - localStorage.setItem('ArcXP_captchaToken', value); + localStorage.setItem(ARCXP_CAPTCHA, value); }; - useEffect(() => { - const checkCaptcha = async () => { - const config = await Identity.getConfig(); - const {recaptchaSiteKey, recaptchaScore } = config; - const isIdentityCaptchaEnabled = config?.[`${challengeIn}Recaptcha`]; - - if(['signup', 'signin', 'magicLink'].includes(challengeIn)) { - if (isIdentityCaptchaEnabled && recaptchaScore === '-1' && recaptchaSiteKey) { - setSiteKey(recaptchaSiteKey); - } - } - - if (challengeIn === 'checkout') { - const salesConfig = await Sales.getConfig(); - const isSalesCaptchaEnabled = salesConfig?.checkoutRecaptchaEnabled; - if (isSalesCaptchaEnabled && recaptchaScore === '-1' && recaptchaSiteKey) { - setSiteKey(recaptchaSiteKey); - } - } - - }; - checkCaptcha(); - - }, [Identity, Sales, challengeIn]); - - const { arcSite } = useFusionContext(); - const { locale } = getProperties(arcSite); - const phrases = getTranslatedPhrases(locale); - if (!isInitialized) { return null; } - return ( -
- {!!siteKey && {}} - />} - {captchaError && {phrases.t("identity-block.bot-protection-error")}} -
- ); + if (isRecaptchaEnabled && !!siteKey && !!recaptchaVersion) { + if (recaptchaVersion === RECAPTCHA_V2) { + return ( + /* istanbul ignore next */ +
+ {}}/> + {captchaError && {phrases.t("identity-block.bot-protection-error")}} +
+ ); + } + if (recaptchaVersion === RECAPTCHA_V3) { + return ( + /* istanbul ignore next */ + + + + ); + } + } else { + return null; + } + + return null; }; export default BotChallengeProtection; diff --git a/blocks/identity-block/components/bot-challenge-protection/index.test.jsx b/blocks/identity-block/components/bot-challenge-protection/index.test.jsx index b1f5a40b00..8b8ef85645 100644 --- a/blocks/identity-block/components/bot-challenge-protection/index.test.jsx +++ b/blocks/identity-block/components/bot-challenge-protection/index.test.jsx @@ -1,7 +1,10 @@ import React from "react"; -import { render, screen } from "@testing-library/react"; +import { render, screen, waitFor } from "@testing-library/react"; import { useIdentity } from "@wpmedia/arc-themes-components"; import BotChallengeProtection from "."; +import * as useRecaptcha from "../../utils/useRecaptcha"; + +jest.mock("../../utils/useRecaptcha"); const mockLogin = jest.fn(() => Promise.resolve()); @@ -12,8 +15,8 @@ const mockIdentity = { }; const mockSales = { - getConfig: jest.fn(() => {}) -} + getConfig: jest.fn(() => {}), +}; jest.mock("@wpmedia/arc-themes-components", () => ({ ...jest.requireActual("@wpmedia/arc-themes-components"), @@ -32,18 +35,33 @@ jest.mock("@wpmedia/arc-themes-components", () => ({ })); describe("Bot challenge protection", () => { - it("renders with required items", () => { + it("renders with required items", async () => { + useRecaptcha.default.mockReturnValue({ + recaptchaVersion: "V2", + siteKey: "123", + isRecaptchaEnabled: true, + }); + render(); - expect(screen.getByTestId("bot-challege-protection-container")).not.toBeNull(); + await waitFor(() => { + expect(screen.getByTestId("bot-challege-protection-container")).not.toBeNull(); + }); }); it("it does not render if identity is not initialized", () => { + + useRecaptcha.default.mockReturnValue({ + recaptchaVersion: "V2", + siteKey: "123", + isRecaptchaEnabled: true, + }); + useIdentity.mockImplementation(() => ({ isInitialized: false, Identity: { ...mockIdentity, }, - })) + })); render(); expect(screen.queryByTestId("bot-challege-protection-container")).toBeNull(); }); diff --git a/blocks/identity-block/components/bot-challenge-protection/reCaptchaV3.js b/blocks/identity-block/components/bot-challenge-protection/reCaptchaV3.js new file mode 100644 index 0000000000..ee869e705e --- /dev/null +++ b/blocks/identity-block/components/bot-challenge-protection/reCaptchaV3.js @@ -0,0 +1,30 @@ +import { useEffect, useCallback } from "react"; +import { useGoogleReCaptcha } from "react-google-recaptcha-v3"; + +// eslint-disable-next-line +import { ARCXP_CAPTCHA } from "./index"; + +/* istanbul ignore file */ +const RecaptchaV3 = ({ setCaptchaToken, resetRecaptcha }) => { + const { executeRecaptcha } = useGoogleReCaptcha(); + const handleReCaptcha3Verify = useCallback(async () => { + if (!executeRecaptcha) { + // eslint-disable-next-line + console.log("ArcXP - Execute recaptcha not yet available"); + return; + } + const token = await executeRecaptcha(); + setCaptchaToken(token); + localStorage.setItem(ARCXP_CAPTCHA, token); + /* eslint-disable-next-line */ + }, [executeRecaptcha]); + + useEffect(() => { + handleReCaptcha3Verify(); + /* eslint-disable-next-line */ + }, [executeRecaptcha, resetRecaptcha]); + + return null; +}; + +export default RecaptchaV3; diff --git a/blocks/identity-block/features/login/default.jsx b/blocks/identity-block/features/login/default.jsx index 349424939b..4faf237548 100644 --- a/blocks/identity-block/features/login/default.jsx +++ b/blocks/identity-block/features/login/default.jsx @@ -10,9 +10,22 @@ import useLogin from "../../components/login"; import BotChallengeProtection from "../../components/bot-challenge-protection"; import useOIDCLogin from "../../utils/useOIDCLogin"; import validateURL from "../../utils/validate-redirect-url"; +import { RECAPTCHA_LOGIN } from "../../utils/useRecaptcha"; const BLOCK_CLASS_NAME = "b-login-form"; +const errorCodes = { + 100015: "identity-block.login-form-error.account-is-disabled", + 130001: "identity-block.login-form-error.captcha-token-invalid", + 130051: "identity-block.login-form-error.unverified-email-address", + 100013: "identity-block.login-form-error.max-devices", + 0: "identity-block.login-form-error.invalid-email-password", +}; + +export function definedMessageByCode(code) { + return errorCodes[code] || errorCodes["0"]; +} + const Login = ({ customFields }) => { const { redirectURL, redirectToPreviousPage, loggedInPageLocation, OIDC } = customFields; @@ -23,9 +36,11 @@ const Login = ({ customFields }) => { const { locale } = getProperties(arcSite); const phrases = getTranslatedPhrases(locale); - const isOIDC = OIDC && url.searchParams.get("client_id") && url.searchParams.get("response_type") === "code"; + const isOIDC = + OIDC && url.searchParams.get("client_id") && url.searchParams.get("response_type") === "code"; const { Identity, isInitialized } = useIdentity(); const [captchaToken, setCaptchaToken] = useState(); + const [resetRecaptcha, setResetRecaptcha] = useState(true); const [error, setError] = useState(); const [captchaError, setCaptchaError] = useState(); const { loginRedirect } = useLogin({ @@ -45,7 +60,6 @@ const Login = ({ customFields }) => { { setError(null); @@ -63,19 +77,25 @@ const Login = ({ customFields }) => { } }) .catch((e) => { + setResetRecaptcha(!resetRecaptcha); if (e?.code === "130001") { setCaptchaError(true); } else { - setError(phrases.t("identity-block.login-form-error")); + setError(phrases.t(definedMessageByCode(e.code))); } if (grecaptcha) { grecaptcha.reset(); } - }) - } - } + + }); + }} > + {error ? ( +
+ {error} +
+ ) : null} { showDefaultError={false} type="password" /> - - {phrases.t("identity-block.privacy-statement")} + + + {phrases.t("identity-block.privacy-statement")} +
); }; @@ -120,10 +149,11 @@ Login.propTypes = { "The URL to which a user would be redirected to if visiting a login page when already logged in.", }), OIDC: PropTypes.bool.tag({ - name: 'Login with OIDC', - defaultValue: false, - description: 'Used when authenticating a third party site with OIDC PKCE flow. This will use an ArcXp Org as an auth provider', - }), + name: "Login with OIDC", + defaultValue: false, + description: + "Used when authenticating a third party site with OIDC PKCE flow. This will use an ArcXp Org as an auth provider", + }), }), }; diff --git a/blocks/identity-block/features/login/default.test.jsx b/blocks/identity-block/features/login/default.test.jsx index a5c8ace853..5c07d0d40b 100644 --- a/blocks/identity-block/features/login/default.test.jsx +++ b/blocks/identity-block/features/login/default.test.jsx @@ -68,9 +68,9 @@ describe("Identity Login Feature", () => { }); }); -describe("Identity Login Feature - rejected Login", () => { +describe("Identity Login Feature - rejected Login, general message", () => { beforeEach(() => { - mockLogin.mockImplementation(() => Promise.reject()); + mockLogin.mockRejectedValueOnce({ code: 0 }); global.grecaptcha = { reset: jest.fn() } @@ -97,7 +97,41 @@ describe("Identity Login Feature - rejected Login", () => { fireEvent.click(screen.getByRole("button")); await waitFor(() => expect(mockLogin).toHaveBeenCalled()); - await screen.findByText("identity-block.login-form-error"); + await screen.findByText("identity-block.login-form-error.invalid-email-password"); + }); +}); + +describe("Identity Login Feature - rejected Login, error code 130001", () => { + beforeEach(() => { + mockLogin.mockRejectedValueOnce({ code: 130001 }); + global.grecaptcha = { + reset: jest.fn() + } + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it("rejects the login", async () => { + + render(); + + await waitFor(() => expect(screen.getByLabelText("identity-block.email-label"))); + fireEvent.change(screen.getByLabelText("identity-block.email-label"), { + target: { value: "email@test.com" }, + }); + + await waitFor(() => expect(screen.getByLabelText("identity-block.password"))); + fireEvent.change(screen.getByLabelText("identity-block.password"), { + target: { value: "thisNotIsMyPassword" }, + }); + + await waitFor(() => expect(screen.getByRole("button"))); + fireEvent.click(screen.getByRole("button")); + + await waitFor(() => expect(mockLogin).toHaveBeenCalled()); + await screen.findByText("identity-block.login-form-error.captcha-token-invalid"); }); }); diff --git a/blocks/identity-block/intl.json b/blocks/identity-block/intl.json index b335b9cc9f..933752f1b1 100644 --- a/blocks/identity-block/intl.json +++ b/blocks/identity-block/intl.json @@ -1283,6 +1283,21 @@ "identity-block.log-in-headline": { "en": "Log in to your account" }, + "identity-block.login-form-error.account-is-disabled": { + "en": "Account is disabled." + }, + "identity-block.login-form-error.captcha-token-invalid": { + "en": "Captcha token invalid." + }, + "identity-block.login-form-error.unverified-email-address": { + "en": "Email Address is not verified." + }, + "identity-block.login-form-error.max-devices": { + "en": "User account has reached the max number of devices." + }, + "identity-block.login-form-error.invalid-email-password": { + "en": "Email or password is invalid. Try again." + }, "identity-block.privacy-statement": { "en": "By creating an account, you agree to the Terms of Service and acknowledge our Privacy Policy." }, diff --git a/blocks/identity-block/package-lock.json b/blocks/identity-block/package-lock.json index f812007dd1..9612e18a92 100644 --- a/blocks/identity-block/package-lock.json +++ b/blocks/identity-block/package-lock.json @@ -1,80 +1,162 @@ { "name": "@wpmedia/identity-block", "version": "5.20.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@arc-fusion/prop-types": { + "packages": { + "": { + "name": "@wpmedia/identity-block", + "version": "5.20.0", + "license": "CC-BY-NC-ND-4.0", + "dependencies": { + "@arc-fusion/prop-types": "^0.1.5", + "@arc-publishing/sdk-identity": "^1.79.0", + "react-google-recaptcha": "^3.1.0", + "react-google-recaptcha-v3": "^1.10.1" + }, + "peerDependencies": { + "@wpmedia/arc-themes-components": "*" + } + }, + "node_modules/@arc-fusion/prop-types": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@arc-fusion/prop-types/-/prop-types-0.1.5.tgz", "integrity": "sha512-12/1QGXYaGZWDw1vnTX8fltWf3BA7zc95Kn9MyXD/PhFAJBEbpvtD2R+NZ8NU+DMPYlYLP33tyI3NSddERZCAA==", - "requires": { + "dependencies": { "prop-types": "^15.7.2" } }, - "@arc-publishing/sdk-identity": { + "node_modules/@arc-publishing/sdk-identity": { "version": "1.79.0", "resolved": "https://registry.npmjs.org/@arc-publishing/sdk-identity/-/sdk-identity-1.79.0.tgz", - "integrity": "sha512-eblhb/AMa2uKr3/sWphlonIw5gKrz2KigUYnQDU2riWZn9Z+EECmQsbpbZbkWGDaTXrtkEX3DRqBIPJsPaEsXg==" + "integrity": "sha512-eblhb/AMa2uKr3/sWphlonIw5gKrz2KigUYnQDU2riWZn9Z+EECmQsbpbZbkWGDaTXrtkEX3DRqBIPJsPaEsXg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@wpmedia/arc-themes-components": { + "version": "0.0.1", + "resolved": "https://npm.pkg.github.com/download/@WPMedia/arc-themes-components/0.0.1/f9ff4b987c296ed8e615b4acbbf9fb8576e437e4", + "integrity": "sha512-2z4L9mf76dtwpIqDCIb70HxrlLW4KL5QkEeQSh9sHY0kkhz5MHx9rW8WcNSuYBmjbYr0rKtV3jl10Vt6WTgyUw==", + "license": "CC-BY-NC-ND-4.0", + "peer": true }, - "hoist-non-react-statics": { + "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "requires": { + "dependencies": { "react-is": "^16.7.0" } }, - "js-tokens": { + "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, - "loose-envify": { + "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { + "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" } }, - "object-assign": { + "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } }, - "prop-types": { + "node_modules/prop-types": { "version": "15.7.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { + "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.8.1" } }, - "react-async-script": { + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-async-script": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz", "integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==", - "requires": { + "dependencies": { "hoist-non-react-statics": "^3.3.0", "prop-types": "^15.5.0" + }, + "peerDependencies": { + "react": ">=16.4.1" } }, - "react-google-recaptcha": { + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-google-recaptcha": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz", "integrity": "sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==", - "requires": { + "dependencies": { "prop-types": "^15.5.0", "react-async-script": "^1.2.0" + }, + "peerDependencies": { + "react": ">=16.4.1" + } + }, + "node_modules/react-google-recaptcha-v3": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/react-google-recaptcha-v3/-/react-google-recaptcha-v3-1.10.1.tgz", + "integrity": "sha512-K3AYzSE0SasTn+XvV2tq+6YaxM+zQypk9rbCgG4OVUt7Rh4ze9basIKefoBz9sC0CNslJj9N1uwTTgRMJQbQJQ==", + "dependencies": { + "hoist-non-react-statics": "^3.3.2" + }, + "peerDependencies": { + "react": "^16.3 || ^17.0 || ^18.0", + "react-dom": "^17.0 || ^18.0" } }, - "react-is": { + "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } } } } diff --git a/blocks/identity-block/package.json b/blocks/identity-block/package.json index 2c008b9440..f084ccf379 100644 --- a/blocks/identity-block/package.json +++ b/blocks/identity-block/package.json @@ -31,6 +31,7 @@ "dependencies": { "@arc-fusion/prop-types": "^0.1.5", "@arc-publishing/sdk-identity": "^1.79.0", - "react-google-recaptcha": "^3.1.0" + "react-google-recaptcha": "^3.1.0", + "react-google-recaptcha-v3": "^1.10.1" } } diff --git a/blocks/identity-block/themes/commerce.json b/blocks/identity-block/themes/commerce.json index 82b1ed1fc2..849113dd61 100644 --- a/blocks/identity-block/themes/commerce.json +++ b/blocks/identity-block/themes/commerce.json @@ -240,21 +240,26 @@ "styles": { "default": { "font-family": "var(--font-family-primary)", + "padding-block-end": "var(--global-spacing-5)", "components": { "button": { "font-size": "var(--global-font-size-4)" }, "heading": { - "border-block-end-color": "var(--border-color)", - "border-block-end-style": "var(--global-border-style-1)", - "border-block-end-width": "var(--global-border-width-1)", - "font-size": "var(--global-font-size-9)", - "margin-block-end": "var(--global-spacing-4)", - "padding-block-end": "var(--global-spacing-2)", - "text-align": "center" + "font-size": "var(--heading-level-4-font-size)", + "font-family": "var(--font-family-secondary)", + "font-weight": 700, + "font-style": "normal", + "line-height": "140%", + "text-align": "center", + "padding-block-end": 0, + "padding-block-start": 0, + "padding-inline-end": 0, + "padding-inline-start": 0, + "margin-block-end": "var(--global-spacing-5)" }, "input": { - "margin-block-end": "var(--global-spacing-5)" + "margin-block-end": "var(--global-spacing-4)" }, "input-error-tip": { "color": "var(--status-color-danger)" @@ -280,12 +285,102 @@ } } }, + "login-form-bot-protection-section": { + "styles": { + "default": { + "margin-block-start": "var(--global-spacing-5)", + "margin-block-end": "var(--global-spacing-5)", + "components": { + "paragraph": { + "color": "#f00" + } + } + } + } + }, + "login-form-privacy-statement": { + "styles": { + "default": { + "display": "block", + "text-align": "center", + "inline-size": "100%", + "margin-block-start": 0, + "margin-block-end": "var(--global-spacing-5)", + "margin-inline-end": 0, + "margin-inline-start": 0, + "line-height": "150%", + "font-size": "0.75rem" + } + } + }, + "login-form-sign-up-div": { + "styles": { + "default": { + "display": "block", + "text-align": "center", + "inline-size": "100%", + "margin-block-start": 0, + "margin-block-end": "var(--global-spacing-5)", + "margin-inline-end": 0, + "margin-inline-start": 0, + "line-height": "150%", + "font-size": "1rem", + "components": { + "paragraph": { + "font-family": "var(--font-family-primary)", + "font-weight": "400", + "font-size": "1rem", + "line-height": "150%" + } + } + } + } + }, + "login-form-sign-up-button": { + "styles": { + "default": { + "font-family": "var(--font-family-primary)", + "font-weight": "400", + "font-size": "1rem", + "line-height": "150%", + "background-color": "transparent", + "text-decoration": "underline", + "cursor": "pointer" + } + } + }, + "login-form-error":{ + "styles": { + "default": { + "font-family": "var(--font-family-primary)", + "text-align": "center", + "margin-block-end": "var(--global-spacing-4)", + "components": { + "paragraph": { + "background-color": "var(--status-color-danger-subtle)", + "color": "var(--status-color-danger)", + "padding-block-end": "var(--global-spacing-1)", + "padding-block-start": "var(--global-spacing-1)", + "padding-inline-start": "var(--global-spacing-2)", + "padding-inline-end": "var(--global-spacing-2)" + } + } + }, + "desktop": {} + } + }, "login-links": { "styles": { "default": { + "font-family": "var(--font-family-primary)", "components": { + "paragraph": { + "text-align": "center", + "font-family": "var(--font-family-primary)" + }, "link": { - "text-align": "center" + "text-align": "center", + "font-family": "var(--font-family-primary)" }, "link-hover": { "color": "var(--text-color-subtle)" @@ -295,6 +390,13 @@ "desktop": {} } }, + "login-links-inner-link": { + "styles": { + "default": { + "text-decoration": "underline" + } + } + }, "reset-password": { "styles": { "default": { diff --git a/blocks/identity-block/themes/news.json b/blocks/identity-block/themes/news.json index 915ac4501b..849113dd61 100644 --- a/blocks/identity-block/themes/news.json +++ b/blocks/identity-block/themes/news.json @@ -239,7 +239,7 @@ "login-form": { "styles": { "default": { - "font-family": "Inter", + "font-family": "var(--font-family-primary)", "padding-block-end": "var(--global-spacing-5)", "components": { "button": { @@ -313,18 +313,74 @@ } } }, + "login-form-sign-up-div": { + "styles": { + "default": { + "display": "block", + "text-align": "center", + "inline-size": "100%", + "margin-block-start": 0, + "margin-block-end": "var(--global-spacing-5)", + "margin-inline-end": 0, + "margin-inline-start": 0, + "line-height": "150%", + "font-size": "1rem", + "components": { + "paragraph": { + "font-family": "var(--font-family-primary)", + "font-weight": "400", + "font-size": "1rem", + "line-height": "150%" + } + } + } + } + }, + "login-form-sign-up-button": { + "styles": { + "default": { + "font-family": "var(--font-family-primary)", + "font-weight": "400", + "font-size": "1rem", + "line-height": "150%", + "background-color": "transparent", + "text-decoration": "underline", + "cursor": "pointer" + } + } + }, + "login-form-error":{ + "styles": { + "default": { + "font-family": "var(--font-family-primary)", + "text-align": "center", + "margin-block-end": "var(--global-spacing-4)", + "components": { + "paragraph": { + "background-color": "var(--status-color-danger-subtle)", + "color": "var(--status-color-danger)", + "padding-block-end": "var(--global-spacing-1)", + "padding-block-start": "var(--global-spacing-1)", + "padding-inline-start": "var(--global-spacing-2)", + "padding-inline-end": "var(--global-spacing-2)" + } + } + }, + "desktop": {} + } + }, "login-links": { "styles": { "default": { - "font-family": "inter", + "font-family": "var(--font-family-primary)", "components": { "paragraph": { "text-align": "center", - "font-family": "inter" + "font-family": "var(--font-family-primary)" }, "link": { "text-align": "center", - "font-family": "inter" + "font-family": "var(--font-family-primary)" }, "link-hover": { "color": "var(--text-color-subtle)" diff --git a/blocks/identity-block/utils/useRecaptcha.js b/blocks/identity-block/utils/useRecaptcha.js new file mode 100644 index 0000000000..6e2c7602b5 --- /dev/null +++ b/blocks/identity-block/utils/useRecaptcha.js @@ -0,0 +1,62 @@ +import { useState, useMemo } from "react"; +import { useIdentity, useSales } from "@wpmedia/arc-themes-components"; + +export const RECAPTCHA_LOGIN = "signin"; +export const RECAPTCHA_SIGNUP = "signup"; +export const RECAPTCHA_MAGICLINK = "magicLink"; +export const RECAPTCHA_CHECKOUT = "checkout"; + +export const RECAPTCHA_V2 = "V2"; +export const RECAPTCHA_V3 = "V3"; + +const useRecaptcha = (challengeIn) => { + const { Identity } = useIdentity(); + const { Sales } = useSales(); + + const [recaptchaVersion, setRecaptchaVersion] = useState(); + const [siteKey, setSiteKey] = useState(); + const [isRecaptchaEnabled, setIsRecaptchaEnabled] = useState(false); + + const setRecaptchaInfo = (isCaptchaEnabled, recaptchaSiteKey, recaptchaScore) => { + if (isCaptchaEnabled && recaptchaSiteKey && !!String(recaptchaScore)) { + if (recaptchaScore === "-1") { + setSiteKey(recaptchaSiteKey); + setRecaptchaVersion(RECAPTCHA_V2); + setIsRecaptchaEnabled(true); + } else if (parseFloat(recaptchaScore) >= 0 && parseFloat(recaptchaScore) <= 1) { + setSiteKey(recaptchaSiteKey); + setRecaptchaVersion(RECAPTCHA_V3); + setIsRecaptchaEnabled(true); + } + } + }; + + const checkCaptcha = async () => { + const identityConfig = await Identity.getConfig(); + const { recaptchaSiteKey, recaptchaScore } = identityConfig; + if ([RECAPTCHA_LOGIN, RECAPTCHA_SIGNUP, RECAPTCHA_MAGICLINK].includes(challengeIn)) { + const isIdentityCaptchaEnabled = identityConfig?.[`${challengeIn}Recaptcha`]; + setRecaptchaInfo(isIdentityCaptchaEnabled, recaptchaSiteKey, recaptchaScore); + } + + if (challengeIn === RECAPTCHA_CHECKOUT) { + const salesConfig = await Sales.getConfig(); + const isSalesCaptchaEnabled = salesConfig?.checkoutRecaptchaEnabled; + setRecaptchaInfo(isSalesCaptchaEnabled, recaptchaSiteKey, recaptchaScore); + } + }; + + useMemo( + () => checkCaptcha(), + /* eslint-disable-next-line */ + [challengeIn], + ); + + return { + recaptchaVersion, + siteKey, + isRecaptchaEnabled, + }; +}; + +export default useRecaptcha; diff --git a/blocks/identity-block/utils/useRecaptcha.test.js b/blocks/identity-block/utils/useRecaptcha.test.js new file mode 100644 index 0000000000..9419b66f94 --- /dev/null +++ b/blocks/identity-block/utils/useRecaptcha.test.js @@ -0,0 +1,199 @@ +import { waitFor, renderHook } from "@testing-library/react"; +import { useIdentity } from "@wpmedia/arc-themes-components"; +import useRecaptcha from "./useRecaptcha"; + +// Mock setTimeout and clearTimeout +jest.useFakeTimers(); + +jest.mock("@arc-publishing/sdk-identity", () => ({ + __esModule: true, + default: { + apiOrigin: "", + options: jest.fn(), + }, +})); + +jest.mock("fusion:properties", () => + jest.fn(() => ({ + api: { + identity: { + origin: "https://corecomponents-arc-demo-3-prod.api.cdn.arcpublishing.com", + }, + retail: { + origin: "https://corecomponents-arc-demo-3-prod.api.cdn.arcpublishing.com", + endpoint: "/retail/public/v1/offer/live/", + }, + }, + })), +); + +jest.mock("fusion:context", () => ({ + __esModule: true, + useFusionContext: () => ({ + arcSite: "Test Site", + }), +})); + +const mockIdentity = { + getConfig: jest.fn(() => + Promise.resolve({ + signupRecaptcha: true, + signinRecaptcha: true, + magicLinkRecaptcha: true, + recaptchaScore: "-1", + recaptchaSiteKey: "6LemcOMhAAAAAEGptytQEAMK_SfH4ZAGJ_e4652C", + }), + ), +}; + +const mockSales = { + getConfig: jest.fn(() => + Promise.resolve({ + checkoutRecaptchaEnabled: true, + }), + ), +}; + +jest.mock("@wpmedia/arc-themes-components", () => ({ + ...jest.requireActual("@wpmedia/arc-themes-components"), + useIdentity: jest.fn(() => ({ + isInitialized: true, + Identity: { + ...mockIdentity, + }, + })), + useSales: jest.fn(() => ({ + isInitialized: true, + Sales: { + ...mockSales, + }, + })), +})); + +describe("useRecaptcha", () => { + it("reCaptcha v2 enabled for signIn", async () => { + const { result } = renderHook(() => useRecaptcha("signin")); + + expect(result.current.recaptchaVersion).toBe(undefined); + expect(result.current.siteKey).toBe(undefined); + expect(result.current.isRecaptchaEnabled).toBe(false); + + await waitFor(() => expect(result.current.recaptchaVersion).toEqual("V2")); + + await waitFor(() => expect(result.current.isRecaptchaEnabled).toEqual(true)); + + await waitFor(() => + expect(result.current.siteKey).toEqual("6LemcOMhAAAAAEGptytQEAMK_SfH4ZAGJ_e4652C"), + ); + }); + + it("reCaptcha v2 enabled for signUp", async () => { + const { result } = renderHook(() => useRecaptcha("signup")); + + expect(result.current.recaptchaVersion).toBe(undefined); + expect(result.current.siteKey).toBe(undefined); + expect(result.current.isRecaptchaEnabled).toBe(false); + + await waitFor(() => expect(result.current.recaptchaVersion).toEqual("V2")); + + await waitFor(() => expect(result.current.isRecaptchaEnabled).toEqual(true)); + + await waitFor(() => + expect(result.current.siteKey).toEqual("6LemcOMhAAAAAEGptytQEAMK_SfH4ZAGJ_e4652C"), + ); + }); + + it("reCaptcha v2 enabled for magicLink", async () => { + const { result } = renderHook(() => useRecaptcha("magicLink")); + + expect(result.current.recaptchaVersion).toBe(undefined); + expect(result.current.siteKey).toBe(undefined); + expect(result.current.isRecaptchaEnabled).toBe(false); + + await waitFor(() => expect(result.current.recaptchaVersion).toEqual("V2")); + + await waitFor(() => expect(result.current.isRecaptchaEnabled).toEqual(true)); + + await waitFor(() => + expect(result.current.siteKey).toEqual("6LemcOMhAAAAAEGptytQEAMK_SfH4ZAGJ_e4652C"), + ); + }); + + it("reCaptcha v2 enabled for checkout", async () => { + const { result } = renderHook(() => useRecaptcha("checkout")); + + expect(result.current.recaptchaVersion).toBe(undefined); + expect(result.current.siteKey).toBe(undefined); + expect(result.current.isRecaptchaEnabled).toBe(false); + + await waitFor(() => expect(result.current.recaptchaVersion).toEqual("V2")); + + await waitFor(() => expect(result.current.isRecaptchaEnabled).toEqual(true)); + + await waitFor(() => + expect(result.current.siteKey).toEqual("6LemcOMhAAAAAEGptytQEAMK_SfH4ZAGJ_e4652C"), + ); + }); + + it("reCaptcha v3 enabled for signIn", async () => { + useIdentity.mockReturnValueOnce({ + isInitialized: true, + Identity: { + getConfig: jest.fn(() => + Promise.resolve({ + signupRecaptcha: true, + signinRecaptcha: true, + magicLinkRecaptcha: true, + recaptchaScore: "0.5", + recaptchaSiteKey: "6LemcOMhAAAAAEGptytQEAMK_SfH4ZAGJ_e4652C", + }), + ), + }, + }); + + const { result } = renderHook(() => useRecaptcha("signin")); + + expect(result.current.recaptchaVersion).toBe(undefined); + expect(result.current.siteKey).toBe(undefined); + expect(result.current.isRecaptchaEnabled).toBe(false); + + await waitFor(() => expect(result.current.recaptchaVersion).toEqual("V3")); + + await waitFor(() => expect(result.current.isRecaptchaEnabled).toEqual(true)); + + await waitFor(() => + expect(result.current.siteKey).toEqual("6LemcOMhAAAAAEGptytQEAMK_SfH4ZAGJ_e4652C"), + ); + }); + + it("reCaptcha v2 disabled for signIn", async () => { + useIdentity.mockReturnValueOnce({ + isInitialized: true, + Identity: { + getConfig: jest.fn(() => + Promise.resolve({ + signupRecaptcha: false, + signinRecaptcha: false, + magicLinkRecaptcha: false, + recaptchaScore: "-1", + recaptchaSiteKey: "6LemcOMhAAAAAEGptytQEAMK_SfH4ZAGJ_e4652C", + }), + ), + }, + }); + + const { result } = renderHook(() => useRecaptcha("signin")); + + expect(result.current.recaptchaVersion).toBe(undefined); + expect(result.current.siteKey).toBe(undefined); + expect(result.current.isRecaptchaEnabled).toBe(false); + + await waitFor(() => expect(result.current.recaptchaVersion).toEqual(undefined)); + + await waitFor(() => expect(result.current.isRecaptchaEnabled).toEqual(false)); + + await waitFor(() => + expect(result.current.siteKey).toEqual(undefined), + ); + }); +}); diff --git a/locale/en.json b/locale/en.json index c375579f27..d8234a2270 100644 --- a/locale/en.json +++ b/locale/en.json @@ -131,6 +131,11 @@ "identity-block.log-in-headline": "Log in to your account", "identity-block.log-out": "Log Out", "identity-block.login-form-error": "There's been an error logging you in", + "identity-block.login-form-error.account-is-disabled": "Account is disabled.", + "identity-block.login-form-error.captcha-token-invalid": "Captcha token invalid.", + "identity-block.login-form-error.unverified-email-address": "Email Address is not verified.", + "identity-block.login-form-error.max-devices": "User account has reached the max number of devices.", + "identity-block.login-form-error.invalid-email-password": "Email or password is invalid. Try again.", "identity-block.login-links-forgot": "Forgot your password?", "identity-block.login-links-login": "Already have an account? Log in", "identity-block.login-links-signup": "Need to create an account? ", diff --git a/package-lock.json b/package-lock.json index 3370f9bcb4..5e972b8386 100644 --- a/package-lock.json +++ b/package-lock.json @@ -135,6 +135,8 @@ "prettier": "^3.0.3", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-google-recaptcha": "^3.1.0", + "react-google-recaptcha-v3": "^1.10.1", "react-oembed-container": "^1.0.1", "sass": "^1.69.4", "sass-loader": "^14.0.0", @@ -399,7 +401,8 @@ "dependencies": { "@arc-fusion/prop-types": "^0.1.5", "@arc-publishing/sdk-identity": "^1.79.0", - "react-google-recaptcha": "^3.1.0" + "react-google-recaptcha": "^3.1.0", + "react-google-recaptcha-v3": "^1.10.1" }, "peerDependencies": { "@wpmedia/arc-themes-components": "*" @@ -23288,6 +23291,18 @@ "react": ">=16.4.1" } }, + "node_modules/react-google-recaptcha-v3": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/react-google-recaptcha-v3/-/react-google-recaptcha-v3-1.10.1.tgz", + "integrity": "sha512-K3AYzSE0SasTn+XvV2tq+6YaxM+zQypk9rbCgG4OVUt7Rh4ze9basIKefoBz9sC0CNslJj9N1uwTTgRMJQbQJQ==", + "dependencies": { + "hoist-non-react-statics": "^3.3.2" + }, + "peerDependencies": { + "react": "^16.3 || ^17.0 || ^18.0", + "react-dom": "^17.0 || ^18.0" + } + }, "node_modules/react-helmet-async": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", diff --git a/package.json b/package.json index 6a51556799..666385e1e6 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,9 @@ "stylelint-config-sass-guidelines": "^10.0.0", "stylelint-no-unsupported-browser-features": "^7.0.0", "stylelint-order": "^6.0.4", - "stylelint-use-logical": "^2.1.0" + "stylelint-use-logical": "^2.1.0", + "react-google-recaptcha": "^3.1.0", + "react-google-recaptcha-v3": "^1.10.1" }, "dependencies": { "@wpmedia/ad-taboola-block": "file:blocks/ad-taboola-block", From a363e561cfa85353dee18f181f2f15e458d96f76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Mar 2024 11:06:06 -0400 Subject: [PATCH 2/5] Bump sanitize-html from 2.12.1 to 2.13.0 (#2055) Bumps [sanitize-html](https://github.com/apostrophecms/sanitize-html) from 2.12.1 to 2.13.0. - [Changelog](https://github.com/apostrophecms/sanitize-html/blob/main/CHANGELOG.md) - [Commits](https://github.com/apostrophecms/sanitize-html/compare/2.12.1...2.13.0) --- updated-dependencies: - dependency-name: sanitize-html dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Vito Galatro --- blocks/article-body-block/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/blocks/article-body-block/package-lock.json b/blocks/article-body-block/package-lock.json index 8026c4df51..e9e9a2e60d 100644 --- a/blocks/article-body-block/package-lock.json +++ b/blocks/article-body-block/package-lock.json @@ -102,9 +102,9 @@ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "postcss": { - "version": "8.4.37", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.37.tgz", - "integrity": "sha512-7iB/v/r7Woof0glKLH8b1SPHrsX7uhdO+Geb41QpF/+mWZHU3uxxSlN+UXGVit1PawOYDToO+AbZzhBzWRDwbQ==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "requires": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", @@ -135,9 +135,9 @@ } }, "sanitize-html": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.12.1.tgz", - "integrity": "sha512-Plh+JAn0UVDpBRP/xEjsk+xDCoOvMBwQUf/K+/cBAVuTbtX8bj2VB7S1sL1dssVpykqp0/KPSesHrqXtokVBpA==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.13.0.tgz", + "integrity": "sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==", "requires": { "deepmerge": "^4.2.2", "escape-string-regexp": "^4.0.0", From fff14304a7cd3b6cb855284f2e07e5a8e4dec7d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Mar 2024 11:14:17 -0400 Subject: [PATCH 3/5] Bump algoliasearch from 4.22.1 to 4.23.1 (#2052) Bumps [algoliasearch](https://github.com/algolia/algoliasearch-client-javascript) from 4.22.1 to 4.23.1. - [Release notes](https://github.com/algolia/algoliasearch-client-javascript/releases) - [Changelog](https://github.com/algolia/algoliasearch-client-javascript/blob/master/CHANGELOG.md) - [Commits](https://github.com/algolia/algoliasearch-client-javascript/compare/4.22.1...4.23.1) --- updated-dependencies: - dependency-name: algoliasearch dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../package-lock.json | 183 +++++++++-------- package-lock.json | 188 ++++++++++-------- 2 files changed, 205 insertions(+), 166 deletions(-) diff --git a/blocks/algolia-assortment-content-source-block/package-lock.json b/blocks/algolia-assortment-content-source-block/package-lock.json index 81e9c23c7c..385ea6b86e 100644 --- a/blocks/algolia-assortment-content-source-block/package-lock.json +++ b/blocks/algolia-assortment-content-source-block/package-lock.json @@ -5,139 +5,158 @@ "requires": true, "dependencies": { "@algolia/cache-browser-local-storage": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.1.tgz", - "integrity": "sha512-Sw6IAmOCvvP6QNgY9j+Hv09mvkvEIDKjYW8ow0UDDAxSXy664RBNQk3i/0nt7gvceOJ6jGmOTimaZoY1THmU7g==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.1.tgz", + "integrity": "sha512-1sAJYmXN9TOk6Hd8BUQOglxP9Kq9F0qlISsuWxH6y4UjevevgxhLvA6VrODJb1ghwwQi0nODXxwUhNh0sGF8xw==", "requires": { - "@algolia/cache-common": "4.22.1" + "@algolia/cache-common": "4.23.1" } }, "@algolia/cache-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.22.1.tgz", - "integrity": "sha512-TJMBKqZNKYB9TptRRjSUtevJeQVXRmg6rk9qgFKWvOy8jhCPdyNZV1nB3SKGufzvTVbomAukFR8guu/8NRKBTA==" + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.1.tgz", + "integrity": "sha512-w0sqXuwbGyIDsFDHTZzTv79rZjW7vc/6vCPdqYAAkiUlvvCdUo0cCWFXpbMpvYHBS2IXZXJaQY0R9yL/bmk9VQ==" }, "@algolia/cache-in-memory": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.22.1.tgz", - "integrity": "sha512-ve+6Ac2LhwpufuWavM/aHjLoNz/Z/sYSgNIXsinGofWOysPilQZPUetqLj8vbvi+DHZZaYSEP9H5SRVXnpsNNw==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.1.tgz", + "integrity": "sha512-Wy5J4c2vLi1Vfsc3qoM/trVtvN9BlV+X2hfiAhfTVclyney6fs/Rjus8lbadl1x5GjlPIgMNGxvr/A/wnJQUBw==", "requires": { - "@algolia/cache-common": "4.22.1" + "@algolia/cache-common": "4.23.1" } }, "@algolia/client-account": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.22.1.tgz", - "integrity": "sha512-k8m+oegM2zlns/TwZyi4YgCtyToackkOpE+xCaKCYfBfDtdGOaVZCM5YvGPtK+HGaJMIN/DoTL8asbM3NzHonw==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.1.tgz", + "integrity": "sha512-E8rALAfC7G1gruxW4zO3WgBkWQDJq1Crnxi45uo/KUYf78x+T7YwojyS42fHz//thbtPyPUC5WZCQlnzqgMZlg==", "requires": { - "@algolia/client-common": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.1", + "@algolia/client-search": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "@algolia/client-analytics": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.22.1.tgz", - "integrity": "sha512-1ssi9pyxyQNN4a7Ji9R50nSdISIumMFDwKNuwZipB6TkauJ8J7ha/uO60sPJFqQyqvvI+px7RSNRQT3Zrvzieg==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.1.tgz", + "integrity": "sha512-xtfp/M3TjHStStH/UQoxmt8SeVpxSgdZGcCY61+chG9fmbJHgeYtzECQu7SVZ+LPTW0nmyqMrpKQ9kFcgPnV1A==", "requires": { - "@algolia/client-common": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.1", + "@algolia/client-search": "4.23.1", + "@algolia/requester-common": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "@algolia/client-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.22.1.tgz", - "integrity": "sha512-IvaL5v9mZtm4k4QHbBGDmU3wa/mKokmqNBqPj0K7lcR8ZDKzUorhcGp/u8PkPC/e0zoHSTvRh7TRkGX3Lm7iOQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.1.tgz", + "integrity": "sha512-01lBsO8r4KeXWIDzVQoPMYwOndeAvSQk3xk3Bxwrt2ag5jrGswiq8DgEqPVx+PQw+7T5GY6dS25cYcdv1dVorA==", "requires": { - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/requester-common": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "@algolia/client-personalization": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.22.1.tgz", - "integrity": "sha512-sl+/klQJ93+4yaqZ7ezOttMQ/nczly/3GmgZXJ1xmoewP5jmdP/X/nV5U7EHHH3hCUEHeN7X1nsIhGPVt9E1cQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.1.tgz", + "integrity": "sha512-B8UEALAg1/6DaLuJOxYTfGBVrLZN4M7FoaYrjbHLw2oF5Y6bxe59Y5ug+lSbs6v9bWx7U9rNVpd8m2I8pobFcA==", "requires": { - "@algolia/client-common": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.1", + "@algolia/requester-common": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "@algolia/client-search": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.22.1.tgz", - "integrity": "sha512-yb05NA4tNaOgx3+rOxAmFztgMTtGBi97X7PC3jyNeGiwkAjOZc2QrdZBYyIdcDLoI09N0gjtpClcackoTN0gPA==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.1.tgz", + "integrity": "sha512-jeA1ZksO0N33SZhcLRa4paUI7LFJrrhtMlw27eIdPTVv/npV0dMLoNGPg3MuLSeZqRKqfpY7tTOBjRZFMhskLg==", "requires": { - "@algolia/client-common": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.1", + "@algolia/requester-common": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "@algolia/logger-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.22.1.tgz", - "integrity": "sha512-OnTFymd2odHSO39r4DSWRFETkBufnY2iGUZNrMXpIhF5cmFE8pGoINNPzwg02QLBlGSaLqdKy0bM8S0GyqPLBg==" + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.1.tgz", + "integrity": "sha512-hGsqJrpeZfw1Ng8ctWj9gg8zXlSmEMA0cfbBn3yoZa3so8oQZmB9uz57AJcJj1CfSBf+5SK8/AF4kjTungvgUA==" }, "@algolia/logger-console": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.22.1.tgz", - "integrity": "sha512-O99rcqpVPKN1RlpgD6H3khUWylU24OXlzkavUAMy6QZd1776QAcauE3oP8CmD43nbaTjBexZj2nGsBH9Tc0FVA==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.1.tgz", + "integrity": "sha512-6QYjtxsDwrdFeLoCcZmi9af/EbWkpUYSclx2d342EoayaY8S2tCORgqwzDmPPOpvi5Y6zPnDsj2BG7vrpK8bdg==", "requires": { - "@algolia/logger-common": "4.22.1" + "@algolia/logger-common": "4.23.1" + } + }, + "@algolia/recommend": { + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.1.tgz", + "integrity": "sha512-9Td+htxUYkUxrkaPOum9Q1jAy+NogxpwZ+Vvn3X+IBIfXECrNhIff+u1ddIirRM2rMphWrrO/3GWLZaKY7FOxw==", + "requires": { + "@algolia/cache-browser-local-storage": "4.23.1", + "@algolia/cache-common": "4.23.1", + "@algolia/cache-in-memory": "4.23.1", + "@algolia/client-common": "4.23.1", + "@algolia/client-search": "4.23.1", + "@algolia/logger-common": "4.23.1", + "@algolia/logger-console": "4.23.1", + "@algolia/requester-browser-xhr": "4.23.1", + "@algolia/requester-common": "4.23.1", + "@algolia/requester-node-http": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "@algolia/requester-browser-xhr": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.1.tgz", - "integrity": "sha512-dtQGYIg6MteqT1Uay3J/0NDqD+UciHy3QgRbk7bNddOJu+p3hzjTRYESqEnoX/DpEkaNYdRHUKNylsqMpgwaEw==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.1.tgz", + "integrity": "sha512-dM8acMp6sn1HRoQrUiBYQCZvTrFwLwFuHagZH88nKhL52bUrtZXH2qUQ8RMQBb9am71J9COLyMgZYdyR+u8Ktg==", "requires": { - "@algolia/requester-common": "4.22.1" + "@algolia/requester-common": "4.23.1" } }, "@algolia/requester-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.22.1.tgz", - "integrity": "sha512-dgvhSAtg2MJnR+BxrIFqlLtkLlVVhas9HgYKMk2Uxiy5m6/8HZBL40JVAMb2LovoPFs9I/EWIoFVjOrFwzn5Qg==" + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.1.tgz", + "integrity": "sha512-G9+ySLxPBtn2o6Mk4NoxPnkYtAe/isxrVy5LmJ4za+aYEdV5tvZpgvn+k4558T7XoRBrI2eQKyjnvQs7zJeCdw==" }, "@algolia/requester-node-http": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.22.1.tgz", - "integrity": "sha512-JfmZ3MVFQkAU+zug8H3s8rZ6h0ahHZL/SpMaSasTCGYR5EEJsCc8SI5UZ6raPN2tjxa5bxS13BRpGSBUens7EA==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.1.tgz", + "integrity": "sha512-prpVKKc/WRAtZqZx3A6Ds+D6bl3jgnY4Nw8BhCO9yzwMu5oXaOFsZrzFRBeVUJbtOWMc/DMP38vY6DpdV6NSfw==", "requires": { - "@algolia/requester-common": "4.22.1" + "@algolia/requester-common": "4.23.1" } }, "@algolia/transporter": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.22.1.tgz", - "integrity": "sha512-kzWgc2c9IdxMa3YqA6TN0NW5VrKYYW/BELIn7vnLyn+U/RFdZ4lxxt9/8yq3DKV5snvoDzzO4ClyejZRdV3lMQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.1.tgz", + "integrity": "sha512-8ucVx0hV7yIeTZUFsix31UEIJFRauPriWlzLBbDy9gRHrK45WbMQ1S9FliDdoY5OvbFxi0/5OKRj0Dw1EkbcJA==", "requires": { - "@algolia/cache-common": "4.22.1", - "@algolia/logger-common": "4.22.1", - "@algolia/requester-common": "4.22.1" + "@algolia/cache-common": "4.23.1", + "@algolia/logger-common": "4.23.1", + "@algolia/requester-common": "4.23.1" } }, "algoliasearch": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.1.tgz", - "integrity": "sha512-jwydKFQJKIx9kIZ8Jm44SdpigFwRGPESaxZBaHSV0XWN2yBJAOT4mT7ppvlrpA4UGzz92pqFnVKr/kaZXrcreg==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.1.tgz", + "integrity": "sha512-LNK5n23zDXVf8kaLMZrVDEy4ecxIFUDEsQlx+He1l+TCmP8eiheLVMi5eyZlU6qmmq3UWCxZmp6hzCXS/hvXEw==", "requires": { - "@algolia/cache-browser-local-storage": "4.22.1", - "@algolia/cache-common": "4.22.1", - "@algolia/cache-in-memory": "4.22.1", - "@algolia/client-account": "4.22.1", - "@algolia/client-analytics": "4.22.1", - "@algolia/client-common": "4.22.1", - "@algolia/client-personalization": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/logger-common": "4.22.1", - "@algolia/logger-console": "4.22.1", - "@algolia/requester-browser-xhr": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/requester-node-http": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/cache-browser-local-storage": "4.23.1", + "@algolia/cache-common": "4.23.1", + "@algolia/cache-in-memory": "4.23.1", + "@algolia/client-account": "4.23.1", + "@algolia/client-analytics": "4.23.1", + "@algolia/client-common": "4.23.1", + "@algolia/client-personalization": "4.23.1", + "@algolia/client-search": "4.23.1", + "@algolia/logger-common": "4.23.1", + "@algolia/logger-console": "4.23.1", + "@algolia/recommend": "4.23.1", + "@algolia/requester-browser-xhr": "4.23.1", + "@algolia/requester-common": "4.23.1", + "@algolia/requester-node-http": "4.23.1", + "@algolia/transporter": "4.23.1" } } } diff --git a/package-lock.json b/package-lock.json index 5e972b8386..fa118a4952 100644 --- a/package-lock.json +++ b/package-lock.json @@ -823,132 +823,151 @@ "dev": true }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.1.tgz", - "integrity": "sha512-Sw6IAmOCvvP6QNgY9j+Hv09mvkvEIDKjYW8ow0UDDAxSXy664RBNQk3i/0nt7gvceOJ6jGmOTimaZoY1THmU7g==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.1.tgz", + "integrity": "sha512-1sAJYmXN9TOk6Hd8BUQOglxP9Kq9F0qlISsuWxH6y4UjevevgxhLvA6VrODJb1ghwwQi0nODXxwUhNh0sGF8xw==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.22.1" + "@algolia/cache-common": "4.23.1" } }, "node_modules/@algolia/cache-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.22.1.tgz", - "integrity": "sha512-TJMBKqZNKYB9TptRRjSUtevJeQVXRmg6rk9qgFKWvOy8jhCPdyNZV1nB3SKGufzvTVbomAukFR8guu/8NRKBTA==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.1.tgz", + "integrity": "sha512-w0sqXuwbGyIDsFDHTZzTv79rZjW7vc/6vCPdqYAAkiUlvvCdUo0cCWFXpbMpvYHBS2IXZXJaQY0R9yL/bmk9VQ==", "dev": true }, "node_modules/@algolia/cache-in-memory": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.22.1.tgz", - "integrity": "sha512-ve+6Ac2LhwpufuWavM/aHjLoNz/Z/sYSgNIXsinGofWOysPilQZPUetqLj8vbvi+DHZZaYSEP9H5SRVXnpsNNw==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.1.tgz", + "integrity": "sha512-Wy5J4c2vLi1Vfsc3qoM/trVtvN9BlV+X2hfiAhfTVclyney6fs/Rjus8lbadl1x5GjlPIgMNGxvr/A/wnJQUBw==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.22.1" + "@algolia/cache-common": "4.23.1" } }, "node_modules/@algolia/client-account": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.22.1.tgz", - "integrity": "sha512-k8m+oegM2zlns/TwZyi4YgCtyToackkOpE+xCaKCYfBfDtdGOaVZCM5YvGPtK+HGaJMIN/DoTL8asbM3NzHonw==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.1.tgz", + "integrity": "sha512-E8rALAfC7G1gruxW4zO3WgBkWQDJq1Crnxi45uo/KUYf78x+T7YwojyS42fHz//thbtPyPUC5WZCQlnzqgMZlg==", "dev": true, "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.1", + "@algolia/client-search": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "node_modules/@algolia/client-analytics": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.22.1.tgz", - "integrity": "sha512-1ssi9pyxyQNN4a7Ji9R50nSdISIumMFDwKNuwZipB6TkauJ8J7ha/uO60sPJFqQyqvvI+px7RSNRQT3Zrvzieg==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.1.tgz", + "integrity": "sha512-xtfp/M3TjHStStH/UQoxmt8SeVpxSgdZGcCY61+chG9fmbJHgeYtzECQu7SVZ+LPTW0nmyqMrpKQ9kFcgPnV1A==", "dev": true, "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.1", + "@algolia/client-search": "4.23.1", + "@algolia/requester-common": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "node_modules/@algolia/client-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.22.1.tgz", - "integrity": "sha512-IvaL5v9mZtm4k4QHbBGDmU3wa/mKokmqNBqPj0K7lcR8ZDKzUorhcGp/u8PkPC/e0zoHSTvRh7TRkGX3Lm7iOQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.1.tgz", + "integrity": "sha512-01lBsO8r4KeXWIDzVQoPMYwOndeAvSQk3xk3Bxwrt2ag5jrGswiq8DgEqPVx+PQw+7T5GY6dS25cYcdv1dVorA==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/requester-common": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "node_modules/@algolia/client-personalization": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.22.1.tgz", - "integrity": "sha512-sl+/klQJ93+4yaqZ7ezOttMQ/nczly/3GmgZXJ1xmoewP5jmdP/X/nV5U7EHHH3hCUEHeN7X1nsIhGPVt9E1cQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.1.tgz", + "integrity": "sha512-B8UEALAg1/6DaLuJOxYTfGBVrLZN4M7FoaYrjbHLw2oF5Y6bxe59Y5ug+lSbs6v9bWx7U9rNVpd8m2I8pobFcA==", "dev": true, "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.1", + "@algolia/requester-common": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "node_modules/@algolia/client-search": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.22.1.tgz", - "integrity": "sha512-yb05NA4tNaOgx3+rOxAmFztgMTtGBi97X7PC3jyNeGiwkAjOZc2QrdZBYyIdcDLoI09N0gjtpClcackoTN0gPA==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.1.tgz", + "integrity": "sha512-jeA1ZksO0N33SZhcLRa4paUI7LFJrrhtMlw27eIdPTVv/npV0dMLoNGPg3MuLSeZqRKqfpY7tTOBjRZFMhskLg==", "dev": true, "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.1", + "@algolia/requester-common": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "node_modules/@algolia/logger-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.22.1.tgz", - "integrity": "sha512-OnTFymd2odHSO39r4DSWRFETkBufnY2iGUZNrMXpIhF5cmFE8pGoINNPzwg02QLBlGSaLqdKy0bM8S0GyqPLBg==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.1.tgz", + "integrity": "sha512-hGsqJrpeZfw1Ng8ctWj9gg8zXlSmEMA0cfbBn3yoZa3so8oQZmB9uz57AJcJj1CfSBf+5SK8/AF4kjTungvgUA==", "dev": true }, "node_modules/@algolia/logger-console": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.22.1.tgz", - "integrity": "sha512-O99rcqpVPKN1RlpgD6H3khUWylU24OXlzkavUAMy6QZd1776QAcauE3oP8CmD43nbaTjBexZj2nGsBH9Tc0FVA==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.1.tgz", + "integrity": "sha512-6QYjtxsDwrdFeLoCcZmi9af/EbWkpUYSclx2d342EoayaY8S2tCORgqwzDmPPOpvi5Y6zPnDsj2BG7vrpK8bdg==", "dev": true, "dependencies": { - "@algolia/logger-common": "4.22.1" + "@algolia/logger-common": "4.23.1" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.1.tgz", + "integrity": "sha512-9Td+htxUYkUxrkaPOum9Q1jAy+NogxpwZ+Vvn3X+IBIfXECrNhIff+u1ddIirRM2rMphWrrO/3GWLZaKY7FOxw==", + "dev": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.1", + "@algolia/cache-common": "4.23.1", + "@algolia/cache-in-memory": "4.23.1", + "@algolia/client-common": "4.23.1", + "@algolia/client-search": "4.23.1", + "@algolia/logger-common": "4.23.1", + "@algolia/logger-console": "4.23.1", + "@algolia/requester-browser-xhr": "4.23.1", + "@algolia/requester-common": "4.23.1", + "@algolia/requester-node-http": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.1.tgz", - "integrity": "sha512-dtQGYIg6MteqT1Uay3J/0NDqD+UciHy3QgRbk7bNddOJu+p3hzjTRYESqEnoX/DpEkaNYdRHUKNylsqMpgwaEw==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.1.tgz", + "integrity": "sha512-dM8acMp6sn1HRoQrUiBYQCZvTrFwLwFuHagZH88nKhL52bUrtZXH2qUQ8RMQBb9am71J9COLyMgZYdyR+u8Ktg==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.22.1" + "@algolia/requester-common": "4.23.1" } }, "node_modules/@algolia/requester-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.22.1.tgz", - "integrity": "sha512-dgvhSAtg2MJnR+BxrIFqlLtkLlVVhas9HgYKMk2Uxiy5m6/8HZBL40JVAMb2LovoPFs9I/EWIoFVjOrFwzn5Qg==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.1.tgz", + "integrity": "sha512-G9+ySLxPBtn2o6Mk4NoxPnkYtAe/isxrVy5LmJ4za+aYEdV5tvZpgvn+k4558T7XoRBrI2eQKyjnvQs7zJeCdw==", "dev": true }, "node_modules/@algolia/requester-node-http": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.22.1.tgz", - "integrity": "sha512-JfmZ3MVFQkAU+zug8H3s8rZ6h0ahHZL/SpMaSasTCGYR5EEJsCc8SI5UZ6raPN2tjxa5bxS13BRpGSBUens7EA==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.1.tgz", + "integrity": "sha512-prpVKKc/WRAtZqZx3A6Ds+D6bl3jgnY4Nw8BhCO9yzwMu5oXaOFsZrzFRBeVUJbtOWMc/DMP38vY6DpdV6NSfw==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.22.1" + "@algolia/requester-common": "4.23.1" } }, "node_modules/@algolia/transporter": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.22.1.tgz", - "integrity": "sha512-kzWgc2c9IdxMa3YqA6TN0NW5VrKYYW/BELIn7vnLyn+U/RFdZ4lxxt9/8yq3DKV5snvoDzzO4ClyejZRdV3lMQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.1.tgz", + "integrity": "sha512-8ucVx0hV7yIeTZUFsix31UEIJFRauPriWlzLBbDy9gRHrK45WbMQ1S9FliDdoY5OvbFxi0/5OKRj0Dw1EkbcJA==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.22.1", - "@algolia/logger-common": "4.22.1", - "@algolia/requester-common": "4.22.1" + "@algolia/cache-common": "4.23.1", + "@algolia/logger-common": "4.23.1", + "@algolia/requester-common": "4.23.1" } }, "node_modules/@ampproject/remapping": { @@ -9202,25 +9221,26 @@ } }, "node_modules/algoliasearch": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.1.tgz", - "integrity": "sha512-jwydKFQJKIx9kIZ8Jm44SdpigFwRGPESaxZBaHSV0XWN2yBJAOT4mT7ppvlrpA4UGzz92pqFnVKr/kaZXrcreg==", - "dev": true, - "dependencies": { - "@algolia/cache-browser-local-storage": "4.22.1", - "@algolia/cache-common": "4.22.1", - "@algolia/cache-in-memory": "4.22.1", - "@algolia/client-account": "4.22.1", - "@algolia/client-analytics": "4.22.1", - "@algolia/client-common": "4.22.1", - "@algolia/client-personalization": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/logger-common": "4.22.1", - "@algolia/logger-console": "4.22.1", - "@algolia/requester-browser-xhr": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/requester-node-http": "4.22.1", - "@algolia/transporter": "4.22.1" + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.1.tgz", + "integrity": "sha512-LNK5n23zDXVf8kaLMZrVDEy4ecxIFUDEsQlx+He1l+TCmP8eiheLVMi5eyZlU6qmmq3UWCxZmp6hzCXS/hvXEw==", + "dev": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.1", + "@algolia/cache-common": "4.23.1", + "@algolia/cache-in-memory": "4.23.1", + "@algolia/client-account": "4.23.1", + "@algolia/client-analytics": "4.23.1", + "@algolia/client-common": "4.23.1", + "@algolia/client-personalization": "4.23.1", + "@algolia/client-search": "4.23.1", + "@algolia/logger-common": "4.23.1", + "@algolia/logger-console": "4.23.1", + "@algolia/recommend": "4.23.1", + "@algolia/requester-browser-xhr": "4.23.1", + "@algolia/requester-common": "4.23.1", + "@algolia/requester-node-http": "4.23.1", + "@algolia/transporter": "4.23.1" } }, "node_modules/ansi-colors": { From ccebd26ec5b6100e1f9232f171167a82c6134942 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Mar 2024 12:19:33 -0400 Subject: [PATCH 4/5] Bump @babel/preset-react from 7.23.3 to 7.24.1 (#2050) Bumps [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) from 7.23.3 to 7.24.1. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.24.1/packages/babel-preset-react) --- updated-dependencies: - dependency-name: "@babel/preset-react" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index fa118a4952..844875ca65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2462,12 +2462,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" @@ -2511,13 +2511,13 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz", - "integrity": "sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.1.tgz", + "integrity": "sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2817,17 +2817,17 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.23.3.tgz", - "integrity": "sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.1.tgz", + "integrity": "sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-transform-react-display-name": "^7.23.3", - "@babel/plugin-transform-react-jsx": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-transform-react-display-name": "^7.24.1", + "@babel/plugin-transform-react-jsx": "^7.23.4", "@babel/plugin-transform-react-jsx-development": "^7.22.5", - "@babel/plugin-transform-react-pure-annotations": "^7.23.3" + "@babel/plugin-transform-react-pure-annotations": "^7.24.1" }, "engines": { "node": ">=6.9.0" From 4da53be3a062c2477b7321d882bb00061397cee0 Mon Sep 17 00:00:00 2001 From: malavikakoppula <83021791+malavikakoppula@users.noreply.github.com> Date: Thu, 28 Mar 2024 10:02:06 -0400 Subject: [PATCH 5/5] Added esc event listener to useEffect (#2044) * Added esc event listener to useEffect --------- Co-authored-by: Malavika Koppula --- .../features/leadart/default.jsx | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/blocks/lead-art-block/features/leadart/default.jsx b/blocks/lead-art-block/features/leadart/default.jsx index 0cd5136a9d..d79878b3de 100644 --- a/blocks/lead-art-block/features/leadart/default.jsx +++ b/blocks/lead-art-block/features/leadart/default.jsx @@ -1,5 +1,5 @@ /* eslint-disable camelcase */ -import React, { useState, useRef } from "react"; +import React, { useState, useRef, useEffect, useMemo } from "react"; import PropTypes from "@arc-fusion/prop-types"; import { useFusionContext } from "fusion:context"; import getProperties from "fusion:properties"; @@ -44,6 +44,26 @@ export const LeadArtPresentation = (props) => { viewportPercentage = 65 } = customFields; + const lead_art = useMemo(() => content?.promo_items?.lead_art || content?.promo_items?.basic || {}, [content]) ; + + useEffect(() => { + if (lead_art?.type === "image") { + if (document.fullscreenEnabled) { + document.addEventListener("fullscreenchange", () => { + if (!document.fullscreenElement) { + setIsOpen(false); + } + }); + } else if (document.webkitFullscreenEnabled) { + document.addEventListener("webkitfullscreenchange", () => { + if (!document.webkitFullscreenElement) { + setIsOpen(false); + } + }) + } + } + }, [lead_art]); + /* istanbul ignore next */ const toggleFullScreen = () => { // the full screen element is the div wrapping a lead art of type image @@ -259,7 +279,6 @@ export const LeadArtPresentation = (props) => { return null; }; - const lead_art = content?.promo_items?.lead_art || content?.promo_items?.basic || {}; const leadArtContent = getLeadArtContent(lead_art); if (leadArtContent) { return
{leadArtContent}
;