diff --git a/.husky/pre-commit b/.husky/pre-commit
index 9f5c7d2442..c16c90c8e5 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,4 +1 @@
-#!/bin/sh
-. "$(dirname "$0")/_/husky.sh"
-
-# npx lint-staged
+npm run lint:changed-feature-branch
diff --git a/.husky/pre-push b/.husky/pre-push
index c10402243b..f9908b77da 100755
--- a/.husky/pre-push
+++ b/.husky/pre-push
@@ -1,5 +1 @@
-#!/bin/sh
-. "$(dirname "$0")/_/husky.sh"
-
-# fetching latest changes `git fetch -a --depth 100` to ensure the base branch is up to date
-# git fetch -a --depth 100 && npm run lint:changed-feature-branch && npm run test:changed-feature-branch
+git fetch -a --depth 100 && npm run lint:changed-feature-branch && npm run test:changed-feature-branch
diff --git a/.storybook/themes/news.scss b/.storybook/themes/news.scss
index 3ed03266ae..0036f70055 100644
--- a/.storybook/themes/news.scss
+++ b/.storybook/themes/news.scss
@@ -2618,6 +2618,10 @@
),
),
),
+ "section-title-links": (
+ "display": flex,
+ "flex-wrap": wrap
+ ),
"share-bar": (
"background": var(--background-color),
"box-shadow": var(--global-box-shadow-1),
diff --git a/blocks/alert-bar-content-source-block/package-lock.json b/blocks/alert-bar-content-source-block/package-lock.json
index f1d66fd7c4..0cd9b3a2e0 100644
--- a/blocks/alert-bar-content-source-block/package-lock.json
+++ b/blocks/alert-bar-content-source-block/package-lock.json
@@ -10,11 +10,11 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
- "version": "1.6.5",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
- "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
+ "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
"requires": {
- "follow-redirects": "^1.15.4",
+ "follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
@@ -33,9 +33,9 @@
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"follow-redirects": {
- "version": "1.15.4",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
- "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw=="
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
},
"form-data": {
"version": "4.0.0",
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/blocks/article-body-block/package-lock.json b/blocks/article-body-block/package-lock.json
index bd0851d4b8..e9e9a2e60d 100644
--- a/blocks/article-body-block/package-lock.json
+++ b/blocks/article-body-block/package-lock.json
@@ -102,13 +102,13 @@
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
},
"postcss": {
- "version": "8.4.31",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
- "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"requires": {
- "nanoid": "^3.3.6",
+ "nanoid": "^3.3.7",
"picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
+ "source-map-js": "^1.2.0"
}
},
"prop-types": {
@@ -135,9 +135,9 @@
}
},
"sanitize-html": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.11.0.tgz",
- "integrity": "sha512-BG68EDHRaGKqlsNjJ2xUB7gpInPA8gVx/mvjO743hZaeMCZ2DwzW7xvsqZ+KNU4QKwj86HJ3uu2liISf2qBBUA==",
+ "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",
@@ -148,9 +148,9 @@
}
},
"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=="
}
}
}
diff --git a/blocks/author-content-source-block/package-lock.json b/blocks/author-content-source-block/package-lock.json
index 0f67256ce9..0b32c5e708 100644
--- a/blocks/author-content-source-block/package-lock.json
+++ b/blocks/author-content-source-block/package-lock.json
@@ -10,11 +10,11 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
- "version": "1.6.5",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
- "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
+ "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
"requires": {
- "follow-redirects": "^1.15.4",
+ "follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
@@ -33,9 +33,9 @@
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"follow-redirects": {
- "version": "1.15.4",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
- "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw=="
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
},
"form-data": {
"version": "4.0.0",
diff --git a/blocks/card-list-block/features/card-list/default.jsx b/blocks/card-list-block/features/card-list/default.jsx
index d2fec9bd79..cf9ce369d3 100644
--- a/blocks/card-list-block/features/card-list/default.jsx
+++ b/blocks/card-list-block/features/card-list/default.jsx
@@ -10,6 +10,7 @@ import {
Date,
formatAuthors,
formatURL,
+ getFocalFromANS,
getImageFromANS,
Heading,
HeadingSection,
@@ -84,21 +85,29 @@ const CardListItems = (props) => {
promo_items {
basic {
_id
- type
- url
auth {
${RESIZER_TOKEN_VERSION}
}
+ focal_point {
+ x
+ y
+ }
+ type
+ url
}
lead_art {
promo_items {
basic {
_id
- type
- url
auth {
${RESIZER_TOKEN_VERSION}
}
+ focal_point {
+ x
+ y
+ }
+ type
+ url
}
}
type
@@ -170,7 +179,7 @@ const CardListItems = (props) => {
ansImage,
aspectRatio: "4:3",
resizedOptions: {
- smart: true,
+ ...getFocalFromANS(ansImage),
},
responsiveImages: [377, 754, 1508],
width: 377,
@@ -230,7 +239,7 @@ const CardListItems = (props) => {
ansImage: itemAnsImage,
aspectRatio: "3:2",
resizedOptions: {
- smart: true,
+ ...getFocalFromANS(itemAnsImage),
},
responsiveImages: [105, 210, 420],
width: 105,
diff --git a/blocks/collections-content-source-block/package-lock.json b/blocks/collections-content-source-block/package-lock.json
index df770b56ec..950dba8852 100644
--- a/blocks/collections-content-source-block/package-lock.json
+++ b/blocks/collections-content-source-block/package-lock.json
@@ -10,11 +10,11 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
- "version": "1.6.5",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
- "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
+ "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
"requires": {
- "follow-redirects": "^1.15.4",
+ "follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
@@ -33,9 +33,9 @@
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"follow-redirects": {
- "version": "1.15.4",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
- "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw=="
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
},
"form-data": {
"version": "4.0.0",
diff --git a/blocks/commerce-product-content-source-block/package-lock.json b/blocks/commerce-product-content-source-block/package-lock.json
index 4d03a3d882..d162f0e21e 100644
--- a/blocks/commerce-product-content-source-block/package-lock.json
+++ b/blocks/commerce-product-content-source-block/package-lock.json
@@ -10,11 +10,11 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
- "version": "1.6.5",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
- "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
+ "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
"requires": {
- "follow-redirects": "^1.15.4",
+ "follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
@@ -33,9 +33,9 @@
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"follow-redirects": {
- "version": "1.15.4",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
- "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw=="
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
},
"form-data": {
"version": "4.0.0",
diff --git a/blocks/content-api-source-block/package-lock.json b/blocks/content-api-source-block/package-lock.json
index 328eb88188..de28af53fc 100644
--- a/blocks/content-api-source-block/package-lock.json
+++ b/blocks/content-api-source-block/package-lock.json
@@ -10,11 +10,11 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
- "version": "1.6.5",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
- "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
+ "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
"requires": {
- "follow-redirects": "^1.15.4",
+ "follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
@@ -33,9 +33,9 @@
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"follow-redirects": {
- "version": "1.15.4",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
- "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw=="
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
},
"form-data": {
"version": "4.0.0",
diff --git a/blocks/extra-large-promo-block/features/extra-large-promo/default.jsx b/blocks/extra-large-promo-block/features/extra-large-promo/default.jsx
index 8ebbf62e17..6d115cc0a0 100644
--- a/blocks/extra-large-promo-block/features/extra-large-promo/default.jsx
+++ b/blocks/extra-large-promo-block/features/extra-large-promo/default.jsx
@@ -11,6 +11,7 @@ import {
Conditional,
Date as DateComponent,
formatAuthors,
+ getFocalFromANS,
getImageFromANS,
getVideoFromANS,
Heading,
@@ -211,21 +212,29 @@ const ExtraLargePromo = ({ customFields }) => {
promo_items {
basic {
_id
- type
- url
auth {
${RESIZER_TOKEN_VERSION}
}
+ focal_point {
+ x
+ y
+ }
+ type
+ url
}
}
}
basic {
_id
- type
- url
auth {
${RESIZER_TOKEN_VERSION}
}
+ focal_point {
+ x
+ y
+ }
+ type
+ url
}
}
website_url
@@ -296,21 +305,22 @@ const ExtraLargePromo = ({ customFields }) => {
showByline && content?.credits?.by?.length > 0
? formatAuthors(content.credits.by, phrases.t("global.and-text"))
: null;
+ const ansImage = getImageFromANS(content);
const imageParams =
showImage &&
- (imageOverrideURL || (content && getImageFromANS(content))
+ (imageOverrideURL || ansImage
? {
ansImage: imageOverrideURL
? {
- _id: resizedImage ? imageOverrideId : "",
- url: imageOverrideURL,
- auth: resizedAuth || {},
- }
- : getImageFromANS(content),
+ _id: resizedImage ? imageOverrideId : "",
+ url: imageOverrideURL,
+ auth: resizedAuth || {},
+ }
+ : ansImage,
alt: content?.headlines?.basic || "",
aspectRatio: imageRatio,
resizedOptions: {
- smart: true,
+ ...getFocalFromANS(ansImage),
},
responsiveImages: [400, 600, 800, 1200],
width: 800,
diff --git a/blocks/header-nav-chain-block/chains/header-nav-chain-block/_children/nav-widget.jsx b/blocks/header-nav-chain-block/chains/header-nav-chain-block/_children/nav-widget.jsx
index c4b504e873..84e0ef5630 100644
--- a/blocks/header-nav-chain-block/chains/header-nav-chain-block/_children/nav-widget.jsx
+++ b/blocks/header-nav-chain-block/chains/header-nav-chain-block/_children/nav-widget.jsx
@@ -31,7 +31,7 @@ const NavWidget = ({
) : null) ||
(type === "menu" ? (
}
variant="secondary-reverse"
diff --git a/blocks/header-nav-chain-block/chains/header-nav-chain-block/_children/nav-widget.test.jsx b/blocks/header-nav-chain-block/chains/header-nav-chain-block/_children/nav-widget.test.jsx
index 501c1480cb..e550229f9c 100644
--- a/blocks/header-nav-chain-block/chains/header-nav-chain-block/_children/nav-widget.test.jsx
+++ b/blocks/header-nav-chain-block/chains/header-nav-chain-block/_children/nav-widget.test.jsx
@@ -10,6 +10,7 @@ jest.mock("fusion:properties", () =>
locale: "somelocale",
}))
);
+
jest.mock("fusion:context", () => ({
useFusionContext: jest.fn(() => ({
arcSite: "dagen",
diff --git a/blocks/header-nav-chain-block/chains/header-nav-chain-block/default.jsx b/blocks/header-nav-chain-block/chains/header-nav-chain-block/default.jsx
index da20a33f53..77b35aa976 100644
--- a/blocks/header-nav-chain-block/chains/header-nav-chain-block/default.jsx
+++ b/blocks/header-nav-chain-block/chains/header-nav-chain-block/default.jsx
@@ -19,6 +19,7 @@ export function PresentationalNav(props) {
const {
ariaLabelLink,
children,
+ closeNavigation,
customFields,
displayLinks,
horizontalLinksHierarchy,
@@ -100,8 +101,10 @@ export function PresentationalNav(props) {
className={`${BLOCK_CLASS_NAME}__flyout-overlay ${
isSectionDrawerOpen ? "open" : "closed"
}`}
+ data-testid="nav-chain-flyout-overlay"
direction="vertical"
justification="start"
+ onClick={closeNavigation}
>
e.stopPropagation()}
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
tabIndex={!sections.length ? "-1" : null}
>
@@ -273,6 +277,7 @@ const Nav = (props) => {
return (
children
);
+
jest.mock("fusion:properties", () => jest.fn(() => ({})));
+
jest.mock("fusion:context", () => ({
useFusionContext: jest.fn(() => ({
contextPath: "pf",
deployment: jest.fn(() => ({})).mockReturnValue("path/image.svg"),
})),
}));
+
jest.mock("fusion:content", () => ({
useContent: jest.fn(() => ({
children: [
@@ -273,6 +276,16 @@ describe("the header navigation feature for the default output type", () => {
fireEvent.click(within(navComponents).getByTestId("nav-chain-nav-section-button"));
expect(screen.queryAllByRole("link").length).toBe(0);
});
+
+ it("opens with the sections button and closes with the overlay", () => {
+ render();
+ const navComponents = screen.getByTestId("nav-chain-nav-components-desktop-left")
+ fireEvent.click(within(navComponents).getByTestId("nav-chain-nav-section-button"));
+ expect(screen.queryAllByRole("link").length).toBe(3);
+
+ fireEvent.click(screen.getByTestId("nav-chain-flyout-overlay"));
+ expect(screen.queryAllByRole("link").length).toBe(0);
+ });
});
describe("dealing with accessibility and screen readers", () => {
diff --git a/blocks/header-nav-chain-block/package-lock.json b/blocks/header-nav-chain-block/package-lock.json
index f91b57300b..5475f85adf 100644
--- a/blocks/header-nav-chain-block/package-lock.json
+++ b/blocks/header-nav-chain-block/package-lock.json
@@ -27,9 +27,9 @@
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
},
"use-debounce": {
- "version": "9.0.4",
- "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-9.0.4.tgz",
- "integrity": "sha512-6X8H/mikbrt0XE8e+JXRtZ8yYVvKkdYRfmIhWZYsP8rcNs9hk3APV8Ua2mFkKRLcJKVdnX2/Vwrmg2GWKUQEaQ=="
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.0.tgz",
+ "integrity": "sha512-XRjvlvCB46bah9IBXVnq/ACP2lxqXyZj0D9hj4K5OzNroMDpTEBg8Anuh1/UfRTRs7pLhQ+RiNxxwZu9+MVl1A=="
}
}
}
diff --git a/blocks/header-nav-chain-block/package.json b/blocks/header-nav-chain-block/package.json
index 064ea40888..c100ca4174 100644
--- a/blocks/header-nav-chain-block/package.json
+++ b/blocks/header-nav-chain-block/package.json
@@ -27,7 +27,7 @@
},
"dependencies": {
"focus-trap-react": "^10.2.3",
- "use-debounce": "^9.0.4"
+ "use-debounce": "^10.0.0"
},
"gitHead": "83fb8d6685958d85ddbfcfbf01d9a5c864cd6c95"
}
diff --git a/blocks/identity-block/_index.scss b/blocks/identity-block/_index.scss
index d8bcd60fab..237117212c 100644
--- a/blocks/identity-block/_index.scss
+++ b/blocks/identity-block/_index.scss
@@ -62,11 +62,35 @@
.b-login-form {
@include scss.block-components("login-form");
@include scss.block-properties("login-form");
+ &__bot-protection-section {
+ @include scss.block-components("login-form-bot-protection-section");
+ @include scss.block-properties("login-form-bot-protection-section");
+ }
+ &__privacy-statement {
+ @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 {
@include scss.block-components("login-links");
@include scss.block-properties("login-links");
+ &__inner-link {
+ @include scss.block-components("login-links-inner-link");
+ @include scss.block-properties("login-links-inner-link");
+ }
}
.b-reset-password {
diff --git a/blocks/identity-block/components/bot-challenge-protection/index.jsx b/blocks/identity-block/components/bot-challenge-protection/index.jsx
new file mode 100644
index 0000000000..e2ecc53ba7
--- /dev/null
+++ b/blocks/identity-block/components/bot-challenge-protection/index.jsx
@@ -0,0 +1,57 @@
+import React from "react";
+import ReCAPTCHA from "react-google-recaptcha";
+import { GoogleReCaptchaProvider } from "react-google-recaptcha-v3";
+
+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_CAPTCHA, value);
+ };
+
+ if (!isInitialized) {
+ return null;
+ }
+
+ 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
new file mode 100644
index 0000000000..8b8ef85645
--- /dev/null
+++ b/blocks/identity-block/components/bot-challenge-protection/index.test.jsx
@@ -0,0 +1,68 @@
+import React from "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());
+
+const mockIdentity = {
+ isLoggedIn: jest.fn(() => false),
+ getConfig: jest.fn(() => ({})),
+ login: mockLogin,
+};
+
+const mockSales = {
+ getConfig: jest.fn(() => {}),
+};
+
+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("Bot challenge protection", () => {
+ it("renders with required items", async () => {
+ useRecaptcha.default.mockReturnValue({
+ recaptchaVersion: "V2",
+ siteKey: "123",
+ isRecaptchaEnabled: true,
+ });
+
+ render();
+
+ 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/components/login/index.jsx b/blocks/identity-block/components/login/index.jsx
index 1435763ee4..88a7f7fb01 100644
--- a/blocks/identity-block/components/login/index.jsx
+++ b/blocks/identity-block/components/login/index.jsx
@@ -22,13 +22,12 @@ const useLogin = ({
if (window?.location?.search) {
const searchParams = new URLSearchParams(window.location.search.substring(1));
- //redirectURL could have additional params
+ // redirectURL could have additional params
const params = ["paymentMethodID"];
- const aditionalParams = params.map((p) => {
- const paramExist = searchParams.has(p)
- if(paramExist){
- return {[p]:searchParams.get(p)}
- }
+ const aditionalParams = params.filter((p) => {
+ const paramExist = searchParams.has(p);
+
+ return paramExist;
})
const fullURL = searchParams.get("redirect") ? appendURLParams(searchParams.get("redirect"), aditionalParams.filter(item => item !== undefined)) : null;
@@ -37,7 +36,9 @@ const useLogin = ({
}
if (redirectToPreviousPage && document?.referrer) {
- setRedirectToURL(document.referrer);
+ const redirectUrl = new URL(document.referrer);
+
+ setRedirectToURL(`${redirectUrl.pathname}${redirectUrl.search}`);
}
}, [redirectQueryParam, redirectToPreviousPage]);
@@ -56,6 +57,7 @@ const useLogin = ({
const checkLoggedInStatus = async () => {
const isLoggedIn = await Identity.isLoggedIn();
const validatedLoggedInPageLoc = validateURL(loggedInPageLocation);
+
if (isLoggedIn) {
if (isOIDC) {
loginByOIDC();
@@ -67,7 +69,7 @@ const useLogin = ({
if (Identity && !isAdmin) {
checkLoggedInStatus();
}
- }, [Identity, redirectQueryParam, loggedInPageLocation, isAdmin]);
+ }, [Identity, redirectQueryParam, loggedInPageLocation, isAdmin, loginByOIDC, isOIDC]);
return {
loginRedirect: redirectQueryParam || redirectToURL,
diff --git a/blocks/identity-block/components/login/index.test.jsx b/blocks/identity-block/components/login/index.test.jsx
index 55e5d5066d..f977f7076f 100644
--- a/blocks/identity-block/components/login/index.test.jsx
+++ b/blocks/identity-block/components/login/index.test.jsx
@@ -35,6 +35,10 @@ describe("useLogin()", () => {
beforeEach(() => {
Object.defineProperty(window, "location", {
writable: true,
+ value: {
+ href: 'http://localhost',
+ search: ''
+ }
});
useIdentity.mockImplementation(() => ({
isInitialized: true,
@@ -68,14 +72,14 @@ describe("useLogin()", () => {
});
it("uses document referrer", async () => {
- const referrerURL = "http://referrer.com";
+ const referrerURL = "http://referrer.com/article/1234";
Object.defineProperty(document, "referrer", {
value: referrerURL,
configurable: true,
});
await render();
fireEvent.click(screen.getByRole("button"));
- expect(window.location).toBe(referrerURL);
+ expect(window.location).toBe("/article/1234");
delete document.referrer;
});
diff --git a/blocks/identity-block/features/login-links/default.jsx b/blocks/identity-block/features/login-links/default.jsx
index a8d069d53f..4a1615492c 100644
--- a/blocks/identity-block/features/login-links/default.jsx
+++ b/blocks/identity-block/features/login-links/default.jsx
@@ -2,7 +2,7 @@ import React from "react";
import PropTypes from "@arc-fusion/prop-types";
import { useFusionContext } from "fusion:context";
import getTranslatedPhrases from "fusion:intl";
-import { Link, Stack } from "@wpmedia/arc-themes-components";
+import { Link, Paragraph, Stack } from "@wpmedia/arc-themes-components";
const BLOCK_CLASS_NAME = "b-login-links";
const defaultLoginURL = "/account/login/";
@@ -35,7 +35,7 @@ const LoginLinks = ({ customFields }) => {
{phrases.t("identity-block.login-links-forgot")}
) : null}
{showSignUp ? (
- {phrases.t("identity-block.login-links-signup")}
+ {phrases.t("identity-block.login-links-signup")}{phrases.t("identity-block.sign-up-natural")}
) : null}
);
diff --git a/blocks/identity-block/features/login/default.jsx b/blocks/identity-block/features/login/default.jsx
index 22d87f570a..4faf237548 100644
--- a/blocks/identity-block/features/login/default.jsx
+++ b/blocks/identity-block/features/login/default.jsx
@@ -1,29 +1,48 @@
-import React, { useState, useEffect } from "react";
+/* global grecaptcha */
+import React, { useState } from "react";
import PropTypes from "@arc-fusion/prop-types";
import { useFusionContext } from "fusion:context";
import getProperties from "fusion:properties";
import getTranslatedPhrases from "fusion:intl";
-import { Input, useIdentity } from "@wpmedia/arc-themes-components";
+import { Input, useIdentity, Paragraph } from "@wpmedia/arc-themes-components";
import HeadlinedSubmitForm from "../../components/headlined-submit-form";
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;
- const url_string = window.location.href;
- const url = new URL(url_string);
+ const urlString = window.location.href;
+ const url = new URL(urlString);
const { isAdmin, arcSite } = useFusionContext();
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({
isAdmin,
redirectURL,
@@ -41,10 +60,14 @@ const Login = ({ customFields }) => {
- Identity.login(email, password, {rememberMe: true})
+ headline={phrases.t("identity-block.log-in-headline")}
+ onSubmit={({ email, password }) => {
+ setError(null);
+ setCaptchaError(null);
+ return Identity.login(email, password, {
+ rememberMe: true,
+ recaptchaToken: captchaToken
+ })
.then(() => {
if (isOIDC) {
loginByOIDC();
@@ -53,12 +76,29 @@ const Login = ({ customFields }) => {
window.location = validatedURL;
}
})
- .catch(() => setError(phrases.t("identity-block.login-form-error")))
- }
+ .catch((e) => {
+ setResetRecaptcha(!resetRecaptcha);
+ if (e?.code === "130001") {
+ setCaptchaError(true);
+ }
+ else {
+ setError(phrases.t(definedMessageByCode(e.code)));
+ }
+ if (grecaptcha) {
+ grecaptcha.reset();
+ }
+
+ });
+ }}
>
+ {error ? (
+
+ ) : null}
{
showDefaultError={false}
type="password"
/>
+
+
+ {phrases.t("identity-block.privacy-statement")}
+
);
};
@@ -98,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 c316678b98..5c07d0d40b 100644
--- a/blocks/identity-block/features/login/default.test.jsx
+++ b/blocks/identity-block/features/login/default.test.jsx
@@ -1,11 +1,12 @@
import React from "react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
-import Login from "./default";
import { useIdentity } from "@wpmedia/arc-themes-components";
+import Login from "./default";
const defaultCustomFields = {
redirectURL: "",
redirectToPreviousPage: true,
+ signUpURL: ""
};
const mockLogin = jest.fn(() => Promise.resolve());
@@ -15,6 +16,10 @@ const mockIdentity = {
login: mockLogin,
};
+const mockSales = {
+ getConfig: jest.fn(() => {})
+}
+
jest.mock("@wpmedia/arc-themes-components", () => ({
...jest.requireActual("@wpmedia/arc-themes-components"),
useIdentity: jest.fn(() => ({
@@ -23,27 +28,33 @@ jest.mock("@wpmedia/arc-themes-components", () => ({
...mockIdentity,
},
})),
+ useSales: jest.fn(() => ({
+ isInitialized: true,
+ Sales: {
+ ...mockSales,
+ },
+ })),
}));
jest.mock("fusion:properties", () => jest.fn(() => ({})));
describe("Identity Login Feature", () => {
it("renders", () => {
render();
- expect(screen.queryByRole("form")).not.toBeNull();
+ expect(screen.getByRole("form")).not.toBeNull();
});
it("shows login form", () => {
render();
- expect(screen.queryByRole("form")).not.toBeNull();
+ expect(screen.getByRole("form")).not.toBeNull();
expect(screen.getByLabelText("identity-block.password")).not.toBeNull();
- expect(screen.getByLabelText("identity-block.email")).not.toBeNull();
+ expect(screen.getByLabelText("identity-block.email-label")).not.toBeNull();
});
it("submits the login form", async () => {
render();
- await waitFor(() => expect(screen.getByLabelText("identity-block.email")));
- fireEvent.change(screen.getByLabelText("identity-block.email"), {
+ 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")));
@@ -57,9 +68,45 @@ describe("Identity Login Feature", () => {
});
});
-describe("Identity Login Feature - rejected Login", () => {
+describe("Identity Login Feature - rejected Login, general message", () => {
+ beforeEach(() => {
+ mockLogin.mockRejectedValueOnce({ code: 0 });
+ 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.invalid-email-password");
+ });
+});
+
+describe("Identity Login Feature - rejected Login, error code 130001", () => {
beforeEach(() => {
- mockLogin.mockImplementation(() => Promise.reject());
+ mockLogin.mockRejectedValueOnce({ code: 130001 });
+ global.grecaptcha = {
+ reset: jest.fn()
+ }
});
afterEach(() => {
@@ -67,10 +114,11 @@ describe("Identity Login Feature - rejected Login", () => {
});
it("rejects the login", async () => {
+
render();
- await waitFor(() => expect(screen.getByLabelText("identity-block.email")));
- fireEvent.change(screen.getByLabelText("identity-block.email"), {
+ await waitFor(() => expect(screen.getByLabelText("identity-block.email-label")));
+ fireEvent.change(screen.getByLabelText("identity-block.email-label"), {
target: { value: "email@test.com" },
});
@@ -83,7 +131,7 @@ describe("Identity Login Feature - rejected Login", () => {
fireEvent.click(screen.getByRole("button"));
await waitFor(() => expect(mockLogin).toHaveBeenCalled());
- await waitFor(() => screen.getByText("identity-block.login-form-error"));
+ 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 3147bad767..933752f1b1 100644
--- a/blocks/identity-block/intl.json
+++ b/blocks/identity-block/intl.json
@@ -629,7 +629,7 @@
"bn": "কোনো অ্যাকাউন্ট নেই?\nসাইন আপ করুন",
"bo": "ཁྱེད་ལ་དྲ་གྲངས་མེད་དམ། ཐོ་འགོད།",
"de": "Sign up for an account.",
- "en": "Don't have an account? Sign up",
+ "en": "Need to create an account? ",
"es": "Sign up for an account.",
"fr": "Sign up for an account.",
"id": "Belum memiliki akun? Daftar",
@@ -1273,5 +1273,35 @@
"vi": "Tên người dùng",
"zh-CN": "用户名",
"zh-TW": "使用者名稱"
+ },
+ "identity-block.bot-protection-error": {
+ "en": "Please verify that you are not a robot."
+ },
+ "identity-block.email-label": {
+ "en": "Email"
+ },
+ "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."
+ },
+ "identity-block.sign-up-natural": {
+ "en": "Sign up"
}
}
\ No newline at end of file
diff --git a/blocks/identity-block/package-lock.json b/blocks/identity-block/package-lock.json
index 6e888512c4..9612e18a92 100644
--- a/blocks/identity-block/package-lock.json
+++ b/blocks/identity-block/package-lock.json
@@ -1,54 +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
+ },
+ "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==",
+ "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-is": {
+ "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==",
+ "dependencies": {
+ "hoist-non-react-statics": "^3.3.0",
+ "prop-types": "^15.5.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.4.1"
+ }
+ },
+ "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==",
+ "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"
+ }
+ },
+ "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 d5fbb51c1b..f084ccf379 100644
--- a/blocks/identity-block/package.json
+++ b/blocks/identity-block/package.json
@@ -30,6 +30,8 @@
},
"dependencies": {
"@arc-fusion/prop-types": "^0.1.5",
- "@arc-publishing/sdk-identity": "^1.79.0"
+ "@arc-publishing/sdk-identity": "^1.79.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 82b1ed1fc2..849113dd61 100644
--- a/blocks/identity-block/themes/news.json
+++ b/blocks/identity-block/themes/news.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/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/blocks/large-promo-block/features/large-promo/default.jsx b/blocks/large-promo-block/features/large-promo/default.jsx
index af4a0b5b08..80f557a635 100644
--- a/blocks/large-promo-block/features/large-promo/default.jsx
+++ b/blocks/large-promo-block/features/large-promo/default.jsx
@@ -18,6 +18,7 @@ import {
MediaItem,
Stack,
formatURL,
+ getFocalFromANS,
getImageFromANS,
getVideoFromANS,
isServerSide,
@@ -221,21 +222,29 @@ const LargePromoItem = ({ customFields, arcSite }) => {
promo_items {
basic {
_id
- type
- url
auth {
${RESIZER_TOKEN_VERSION}
}
+ focal_point {
+ x
+ y
+ }
+ type
+ url
}
}
}
basic {
_id
- type
- url
auth {
${RESIZER_TOKEN_VERSION}
}
+ focal_point {
+ x
+ y
+ }
+ type
+ url
}
}
embed_html
@@ -337,9 +346,10 @@ const LargePromoItem = ({ customFields, arcSite }) => {
const contentOverline = showOverline ? overlineText : null;
const contentUrl = content?.websites?.[arcSite]?.website_url;
const embedMarkup = playVideoInPlace && getVideoFromANS(content);
- const promoImageParams =
+ const ansImage = getImageFromANS(content);
+ const promoImageParams =
showImage &&
- (imageOverrideURL || (content && getImageFromANS(content))
+ (imageOverrideURL || ansImage
? {
ansImage: imageOverrideURL
? {
@@ -347,11 +357,11 @@ const LargePromoItem = ({ customFields, arcSite }) => {
url: imageOverrideURL,
auth: resizedAuth || {},
}
- : getImageFromANS(content),
+ : ansImage,
alt: content?.headlines?.basic || "",
aspectRatio: imageRatio,
resizedOptions: {
- smart: true,
+ ...getFocalFromANS(ansImage),
},
responsiveImages: [400, 600, 800, 1200],
width: 377,
diff --git a/blocks/lead-art-block/features/leadart/default.jsx b/blocks/lead-art-block/features/leadart/default.jsx
index c59397c39a..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";
@@ -9,6 +9,7 @@ import {
Carousel,
formatCredits,
formatPowaVideoEmbed,
+ getFocalFromANS,
Icon,
Image,
MediaItem,
@@ -43,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
@@ -140,12 +161,12 @@ export const LeadArtPresentation = (props) => {
{isOpen ? (