diff --git a/package.json b/package.json
index 31a55218a0..6a747d0326 100755
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/pwa-studio",
- "version": "14.1.0",
+ "version": "14.2.0-alpha.6",
"private": true,
"workspaces": [
"packages/babel-preset-peregrine",
@@ -47,6 +47,7 @@
},
"dependencies": {
"caniuse-lite": "~1.0.30001335",
+ "dompurify": "^2.3.8",
"path-to-regexp": "^8.2.0",
"qs": "^6.13.0",
"setimmediate": "^1.0.5"
diff --git a/packages/create-pwa/package.json b/packages/create-pwa/package.json
index b8a9169921..bca95b413c 100644
--- a/packages/create-pwa/package.json
+++ b/packages/create-pwa/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/create-pwa",
- "version": "2.4.6",
+ "version": "2.5.6-alpha.6",
"publishConfig": {
"access": "public"
},
@@ -29,8 +29,8 @@
},
"homepage": "https://github.com/magento/pwa-studio/tree/main/packages/create-pwa#readme",
"dependencies": {
- "@magento/pwa-buildpack": "~11.5.3",
- "@magento/venia-concept": "~14.1.0",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
+ "@magento/venia-concept": "14.2.0-alpha.6",
"chalk": "^2.4.2",
"change-case": "^3.1.0",
"compression": "~1.7.4",
diff --git a/packages/extensions/experience-platform-connector/package.json b/packages/extensions/experience-platform-connector/package.json
index d384b9a2c5..54050ae515 100644
--- a/packages/extensions/experience-platform-connector/package.json
+++ b/packages/extensions/experience-platform-connector/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/experience-platform-connector",
- "version": "1.0.8",
+ "version": "1.0.9-alpha.6",
"publishConfig": {
"access": "public"
},
@@ -18,8 +18,8 @@
"devDependencies": {},
"peerDependencies": {
"@apollo/client": "~3.5.0",
- "@magento/peregrine": "~14.4.1",
- "@magento/pwa-buildpack": "~11.5.3",
+ "@magento/peregrine": "14.5.1-alpha.6",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
"react": "~17.0.1"
},
"pwa-studio": {
diff --git a/packages/extensions/gomage-plugin-braintree-three-d-secure/package.json b/packages/extensions/gomage-plugin-braintree-three-d-secure/package.json
index e9cf101f9e..ff5884c851 100644
--- a/packages/extensions/gomage-plugin-braintree-three-d-secure/package.json
+++ b/packages/extensions/gomage-plugin-braintree-three-d-secure/package.json
@@ -1,13 +1,15 @@
{
"name": "@gomage/plugin-braintree-three-d-secure",
"version": "3.94.0",
+ "publishConfig": {
+ "access": "public"
+ },
"description": "GoMage Braintree 3D Secure",
"main": "./index.js",
"author": "GoMage",
"dependencies": {
"braintree-web-drop-in": "~1.43.0"
},
-
"scripts": {
"clean": " "
},
@@ -17,4 +19,4 @@
"intercept": "./intercept.js"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/extensions/upward-security-headers/package.json b/packages/extensions/upward-security-headers/package.json
index 3ee3e4be31..52a485c0b3 100644
--- a/packages/extensions/upward-security-headers/package.json
+++ b/packages/extensions/upward-security-headers/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/upward-security-headers",
- "version": "1.0.17",
+ "version": "1.1.17-alpha.6",
"publishConfig": {
"access": "public"
},
@@ -13,8 +13,8 @@
"author": "Adobe Commerce",
"license": "(OSL-3.0 OR AFL-3.0)",
"peerDependencies": {
- "@magento/pwa-buildpack": "~11.5.3",
- "@magento/venia-ui": "~11.5.0",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
+ "@magento/venia-ui": "11.6.0-alpha.6",
"webpack": "~4.46.0"
},
"pwa-studio": {
diff --git a/packages/extensions/venia-sample-backends/package.json b/packages/extensions/venia-sample-backends/package.json
index 2088d3990d..7450f7711f 100644
--- a/packages/extensions/venia-sample-backends/package.json
+++ b/packages/extensions/venia-sample-backends/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/venia-sample-backends",
- "version": "0.0.11",
+ "version": "0.0.12-alpha.6",
"publishConfig": {
"access": "public"
},
@@ -13,7 +13,7 @@
"repository": "github:magento/pwa-studio",
"license": "(OSL-3.0 OR AFL-3.0)",
"peerDependencies": {
- "@magento/pwa-buildpack": "~11.5.3",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
"node-fetch": "~2.3.0"
},
"pwa-studio": {
diff --git a/packages/extensions/venia-sample-eventing/package.json b/packages/extensions/venia-sample-eventing/package.json
index 985db76f0f..40393d3104 100644
--- a/packages/extensions/venia-sample-eventing/package.json
+++ b/packages/extensions/venia-sample-eventing/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/venia-sample-eventing",
- "version": "0.0.9",
+ "version": "0.0.10-alpha.6",
"publishConfig": {
"access": "public"
},
@@ -12,8 +12,8 @@
"repository": "github:magento/pwa-studio",
"license": "(OSL-3.0 OR AFL-3.0)",
"peerDependencies": {
- "@magento/peregrine": "~14.4.1",
- "@magento/pwa-buildpack": "~11.5.3",
+ "@magento/peregrine": "14.5.1-alpha.6",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
"react": "~17.0.1"
},
"pwa-studio": {
diff --git a/packages/extensions/venia-sample-language-packs/package.json b/packages/extensions/venia-sample-language-packs/package.json
index 73c3a70ff5..e3e58682b4 100644
--- a/packages/extensions/venia-sample-language-packs/package.json
+++ b/packages/extensions/venia-sample-language-packs/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/venia-sample-language-packs",
- "version": "0.0.17",
+ "version": "0.0.18-alpha.6",
"publishConfig": {
"access": "public"
},
@@ -12,8 +12,8 @@
"repository": "github:magento/pwa-studio",
"license": "(OSL-3.0 OR AFL-3.0)",
"peerDependencies": {
- "@magento/pwa-buildpack": "~11.5.3",
- "@magento/venia-ui": "~11.5.0"
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
+ "@magento/venia-ui": "11.6.0-alpha.6"
},
"pwa-studio": {
"targets": {
diff --git a/packages/extensions/venia-sample-payments-cashondelivery/intercept.js b/packages/extensions/venia-sample-payments-cashondelivery/intercept.js
index 3285cfc0fb..4806806e4f 100644
--- a/packages/extensions/venia-sample-payments-cashondelivery/intercept.js
+++ b/packages/extensions/venia-sample-payments-cashondelivery/intercept.js
@@ -20,22 +20,20 @@ module.exports = targets => {
checkoutPagePaymentTypes.tap(payments =>
payments.add({
paymentCode: 'cashondelivery',
- importPath:
- '@adobe/venia-sample-payments-cashondelivery/src/components/cashondelivery.js'
+ importPath: '@adobe/venia-sample-payments-cashondelivery/src/components/cashondelivery.js'
})
);
editablePaymentTypes.tap(editablePaymentTypes => {
editablePaymentTypes.add({
paymentCode: 'cashondelivery',
- importPath:
- '@adobe/venia-sample-payments-cashondelivery/src/components/editcod.js'
+ importPath: '@adobe/venia-sample-payments-cashondelivery/src/components/editcod.js'
+
});
});
summaryPagePaymentTypes.tap(paymentSummaries =>
paymentSummaries.add({
paymentCode: 'cashondelivery',
- importPath:
- '@adobe/venia-sample-payments-cashondelivery/src/components/summarycod.js'
+ importPath: '@adobe/venia-sample-payments-cashondelivery/src/components/summarycod.js'
})
);
};
diff --git a/packages/extensions/venia-sample-payments-cashondelivery/package.json b/packages/extensions/venia-sample-payments-cashondelivery/package.json
index de0e8f4b9b..dbe407e94a 100644
--- a/packages/extensions/venia-sample-payments-cashondelivery/package.json
+++ b/packages/extensions/venia-sample-payments-cashondelivery/package.json
@@ -12,9 +12,9 @@
"repository": "github:magento/pwa-studio",
"license": "(OSL-3.0 OR AFL-3.0)",
"peerDependencies": {
- "@magento/peregrine": "~14.4.1",
- "@magento/pwa-buildpack": "~11.5.3",
- "@magento/venia-ui": "~11.5.0",
+ "@magento/peregrine": "14.5.1-alpha.6",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
+ "@magento/venia-ui": "11.6.0-alpha.6",
"react": "~17.0.1",
"react-intl": "~5.20.0",
"react-router-dom": "~5.2.0"
diff --git a/packages/extensions/venia-sample-payments-checkmo/package.json b/packages/extensions/venia-sample-payments-checkmo/package.json
index 4c7d8cf74c..c9450e8582 100644
--- a/packages/extensions/venia-sample-payments-checkmo/package.json
+++ b/packages/extensions/venia-sample-payments-checkmo/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/venia-sample-payments-checkmo",
- "version": "0.0.15",
+ "version": "0.0.15-alpha.6",
"publishConfig": {
"access": "public"
},
@@ -12,9 +12,9 @@
"repository": "github:magento/pwa-studio",
"license": "(OSL-3.0 OR AFL-3.0)",
"peerDependencies": {
- "@magento/peregrine": "~14.4.1",
- "@magento/pwa-buildpack": "~11.5.3",
- "@magento/venia-ui": "~11.5.0",
+ "@magento/peregrine": "14.5.1-alpha.6",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
+ "@magento/venia-ui": "11.6.0-alpha.6",
"react": "~17.0.1",
"react-intl": "~5.20.0",
"react-router-dom": "~5.2.0"
diff --git a/packages/pagebuilder/lib/ContentTypes/Block/configAggregator.js b/packages/pagebuilder/lib/ContentTypes/Block/configAggregator.js
index 709260d5df..9830d5bd62 100644
--- a/packages/pagebuilder/lib/ContentTypes/Block/configAggregator.js
+++ b/packages/pagebuilder/lib/ContentTypes/Block/configAggregator.js
@@ -1,8 +1,16 @@
+import DOMPurify from 'dompurify';
import { getAdvanced } from '../../utils';
export default node => {
+ // Get the raw HTML content from the first child node
+ const rawHTML = node.childNodes[0] ? node.childNodes[0].innerHTML : '';
+
+ // Sanitize the raw HTML using DOMPurify
+ const sanitizedHTML = DOMPurify.sanitize(rawHTML);
+
return {
- richContent: node.childNodes[0] ? node.childNodes[0].innerHTML : '',
+ // Return the sanitized HTML content, along with the result from getAdvanced
+ richContent: sanitizedHTML,
...getAdvanced(node)
};
};
diff --git a/packages/pagebuilder/package.json b/packages/pagebuilder/package.json
index 645e457e23..19f7c74dac 100644
--- a/packages/pagebuilder/package.json
+++ b/packages/pagebuilder/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/pagebuilder",
- "version": "9.3.2",
+ "version": "9.3.3-alpha.6",
"publishConfig": {
"access": "public"
},
@@ -34,9 +34,9 @@
"homepage": "https://github.com/magento/pwa-studio/tree/main/packages/pagebuilder#readme",
"dependencies": {},
"devDependencies": {
- "@magento/peregrine": "~14.4.1",
- "@magento/pwa-buildpack": "~11.5.3",
- "@magento/venia-ui": "~11.5.0",
+ "@magento/peregrine": "14.5.1-alpha.6",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
+ "@magento/venia-ui": "11.6.0-alpha.6",
"@storybook/react": "~6.3.7",
"jarallax": "~1.11.1",
"load-google-maps-api": "~2.0.1",
@@ -50,9 +50,9 @@
"peerDependencies": {
"@apollo/client": "~3.5.0",
"@magento/babel-preset-peregrine": "~1.3.3",
- "@magento/peregrine": "~14.4.1",
- "@magento/pwa-buildpack": "~11.5.3",
- "@magento/venia-ui": "~11.5.0",
+ "@magento/peregrine": "14.5.1-alpha.6",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
+ "@magento/venia-ui": "11.6.0-alpha.6",
"jarallax": "~1.11.1",
"load-google-maps-api": "~2.0.1",
"lodash.escape": "~4.0.1",
diff --git a/packages/peregrine/lib/talons/FilterModal/__tests__/useFilterBlock.spec.js b/packages/peregrine/lib/talons/FilterModal/__tests__/useFilterBlock.spec.js
index 83b08a5de7..5aef1275e5 100644
--- a/packages/peregrine/lib/talons/FilterModal/__tests__/useFilterBlock.spec.js
+++ b/packages/peregrine/lib/talons/FilterModal/__tests__/useFilterBlock.spec.js
@@ -1,6 +1,6 @@
import React, { useEffect } from 'react';
import { act } from 'react-test-renderer';
-
+import { MemoryRouter } from 'react-router-dom';
import { createTestInstance } from '@magento/peregrine';
import { useFilterBlock } from '../useFilterBlock';
@@ -56,7 +56,11 @@ describe('#useFilterBlock', () => {
});
it('is closed by default', () => {
- createTestInstance();
+ createTestInstance(
+
+
+
+ );
expect(log).toHaveBeenCalledWith({
handleClick: expect.any(Function),
@@ -66,7 +70,11 @@ describe('#useFilterBlock', () => {
it('is open if passed initially open', () => {
givenInitiallyOpen();
- createTestInstance();
+ createTestInstance(
+
+
+
+ );
expect(log).toHaveBeenCalledWith({
handleClick: expect.any(Function),
@@ -76,7 +84,11 @@ describe('#useFilterBlock', () => {
it('is open if items are selected', () => {
givenSelectedItems();
- createTestInstance();
+ createTestInstance(
+
+
+
+ );
expect(log).toHaveBeenCalledWith({
handleClick: expect.any(Function),
@@ -85,7 +97,11 @@ describe('#useFilterBlock', () => {
});
it('can toggle visibility', () => {
- createTestInstance();
+ createTestInstance(
+
+
+
+ );
expect(typeof handleClickProp).toBe('function');
diff --git a/packages/peregrine/lib/talons/FilterModal/helpers.js b/packages/peregrine/lib/talons/FilterModal/helpers.js
index 5d3a7b163c..cd958399c2 100644
--- a/packages/peregrine/lib/talons/FilterModal/helpers.js
+++ b/packages/peregrine/lib/talons/FilterModal/helpers.js
@@ -54,7 +54,7 @@ export const getStateFromSearch = (initialValue, filterKeys, filterItems) => {
if (existingFilter) {
items.add(existingFilter);
- } else {
+ } else if (group !== 'price') {
console.warn(
`Existing filter ${value} not found in possible filters`
);
diff --git a/packages/peregrine/lib/talons/FilterModal/useFilterBlock.js b/packages/peregrine/lib/talons/FilterModal/useFilterBlock.js
index 8691516d95..e6542aa943 100644
--- a/packages/peregrine/lib/talons/FilterModal/useFilterBlock.js
+++ b/packages/peregrine/lib/talons/FilterModal/useFilterBlock.js
@@ -1,13 +1,20 @@
import { useCallback, useState, useEffect, useMemo } from 'react';
+import { useLocation } from 'react-router-dom';
export const useFilterBlock = props => {
- const { filterState, items, initialOpen } = props;
+ const { filterState, items, initialOpen, group } = props;
+ const location = useLocation();
const hasSelected = useMemo(() => {
+ const params = new URLSearchParams(location.search);
+ //expansion of price filter dropdown
+ if (group == 'price') {
+ return params.get('price[filter]') ? true : false;
+ }
return items.some(item => {
return filterState && filterState.has(item);
});
- }, [filterState, items]);
+ }, [filterState, items, group, location.search]);
const [isExpanded, setExpanded] = useState(hasSelected || initialOpen);
diff --git a/packages/peregrine/lib/talons/FilterSidebar/useFilterSidebar.js b/packages/peregrine/lib/talons/FilterSidebar/useFilterSidebar.js
index fbcc2bce3f..688e957db3 100644
--- a/packages/peregrine/lib/talons/FilterSidebar/useFilterSidebar.js
+++ b/packages/peregrine/lib/talons/FilterSidebar/useFilterSidebar.js
@@ -182,9 +182,10 @@ export const useFilterSidebar = props => {
}, [handleClose]);
const handleReset = useCallback(() => {
- filterApi.clear();
- setIsApplying(true);
- }, [filterApi, setIsApplying]);
+ //filterApi.clear();
+ //setIsApplying(true);
+ history.replace({ search: 'page=1' });
+ }, [history]);
const handleKeyDownActions = useCallback(
event => {
diff --git a/packages/peregrine/lib/talons/RootComponents/Category/__tests__/__snapshots__/useCategoryContent.spec.js.snap b/packages/peregrine/lib/talons/RootComponents/Category/__tests__/__snapshots__/useCategoryContent.spec.js.snap
index 8aa379def7..9ddebf6b30 100644
--- a/packages/peregrine/lib/talons/RootComponents/Category/__tests__/__snapshots__/useCategoryContent.spec.js.snap
+++ b/packages/peregrine/lib/talons/RootComponents/Category/__tests__/__snapshots__/useCategoryContent.spec.js.snap
@@ -5,6 +5,7 @@ Object {
"availableSortMethods": null,
"categoryDescription": "Jewelry category",
"categoryName": "Jewelry",
+ "filterOptions": undefined,
"filters": null,
"items": Array [
null,
@@ -17,6 +18,7 @@ Object {
null,
null,
],
+ "setFilterOptions": [Function],
"totalCount": null,
"totalPagesFromData": null,
}
@@ -32,6 +34,7 @@ Object {
],
"categoryDescription": "Jewelry category",
"categoryName": "Jewelry",
+ "filterOptions": undefined,
"filters": Array [
Object {
"label": "Label",
@@ -47,6 +50,7 @@ Object {
"name": "Necklace",
},
],
+ "setFilterOptions": [Function],
"totalCount": 2,
"totalPagesFromData": 1,
}
diff --git a/packages/peregrine/lib/talons/RootComponents/Category/__tests__/useCategoryContent.spec.js b/packages/peregrine/lib/talons/RootComponents/Category/__tests__/useCategoryContent.spec.js
index d22cfd685a..02f263a747 100644
--- a/packages/peregrine/lib/talons/RootComponents/Category/__tests__/useCategoryContent.spec.js
+++ b/packages/peregrine/lib/talons/RootComponents/Category/__tests__/useCategoryContent.spec.js
@@ -26,6 +26,18 @@ jest.mock('@apollo/client', () => {
};
});
+const mockGetFiltersAttributeCode = {
+ data: {
+ products: {
+ aggregations: [
+ {
+ label: 'Label'
+ }
+ ]
+ }
+ }
+};
+
const mockProductFiltersByCategoryData = {
data: {
products: {
@@ -91,6 +103,7 @@ const mockCategoryData = {
const mockGetSortMethods = jest.fn();
const mockGetFilters = jest.fn();
+const mockfilterData = jest.fn();
jest.mock('@magento/peregrine/lib/context/eventing', () => ({
useEventingContext: jest.fn().mockReturnValue([{}, { dispatch: jest.fn() }])
@@ -98,7 +111,6 @@ jest.mock('@magento/peregrine/lib/context/eventing', () => ({
const Component = props => {
const talonprops = useCategoryContent(props);
-
return ;
};
@@ -106,17 +118,18 @@ useQuery.mockReturnValue({ data: mockCategoryData });
describe('useCategoryContent tests', () => {
it('returns the proper shape', () => {
useLazyQuery
+ .mockReturnValueOnce([mockfilterData, mockGetFiltersAttributeCode])
.mockReturnValueOnce([
mockGetFilters,
mockProductFiltersByCategoryData
])
.mockReturnValueOnce([mockGetSortMethods, mockSortData]);
- const rendered = createTestInstance();
-
+ const testProps = Object.assign({}, mockProps, {
+ categoryId: 0
+ });
+ const rendered = createTestInstance();
const talonProps = rendered.root.findByType('i').props;
- expect(mockGetFilters).toHaveBeenCalled();
- expect(mockGetSortMethods).toHaveBeenCalled();
expect(useQuery).toHaveBeenCalled();
expect(useLazyQuery).toHaveBeenCalled();
expect(talonProps).toMatchSnapshot();
@@ -124,6 +137,7 @@ describe('useCategoryContent tests', () => {
it('handles default category id', () => {
useLazyQuery
+ .mockReturnValueOnce([mockfilterData, mockGetFiltersAttributeCode])
.mockReturnValueOnce([
mockGetFilters,
mockProductFiltersByCategoryData
diff --git a/packages/peregrine/lib/talons/RootComponents/Category/categoryContent.gql.js b/packages/peregrine/lib/talons/RootComponents/Category/categoryContent.gql.js
index 16e42557c4..eb7a7e36fa 100644
--- a/packages/peregrine/lib/talons/RootComponents/Category/categoryContent.gql.js
+++ b/packages/peregrine/lib/talons/RootComponents/Category/categoryContent.gql.js
@@ -1,10 +1,8 @@
import { gql } from '@apollo/client';
export const GET_PRODUCT_FILTERS_BY_CATEGORY = gql`
- query getProductFiltersByCategory(
- $categoryIdFilter: FilterEqualTypeInput!
- ) {
- products(filter: { category_uid: $categoryIdFilter }) {
+ query getProductFiltersByCategory($filters: ProductAttributeFilterInput!) {
+ products(filter: $filters) {
aggregations {
label
count
diff --git a/packages/peregrine/lib/talons/RootComponents/Category/useCategoryContent.js b/packages/peregrine/lib/talons/RootComponents/Category/useCategoryContent.js
index fde9369c5a..659fdb400a 100644
--- a/packages/peregrine/lib/talons/RootComponents/Category/useCategoryContent.js
+++ b/packages/peregrine/lib/talons/RootComponents/Category/useCategoryContent.js
@@ -1,4 +1,4 @@
-import { useEffect } from 'react';
+import { useEffect, useState, useMemo } from 'react';
import { useLazyQuery, useQuery } from '@apollo/client';
import mergeOperations from '../../../util/shallowMerge';
@@ -29,6 +29,92 @@ export const useCategoryContent = props => {
getCategoryAvailableSortMethodsQuery
} = operations;
+ const [
+ getFiltersAttributeCode,
+ { data: filterAttributeData }
+ ] = useLazyQuery(getProductFiltersByCategoryQuery, {
+ fetchPolicy: 'cache-and-network',
+ nextFetchPolicy: 'cache-first'
+ });
+
+ useEffect(() => {
+ if (categoryId) {
+ getFiltersAttributeCode({
+ variables: {
+ filters: {
+ category_uid: { eq: categoryId }
+ }
+ }
+ });
+ }
+ }, [categoryId, getFiltersAttributeCode]);
+
+ const availableFilterData = filterAttributeData
+ ? filterAttributeData.products?.aggregations
+ : null;
+ const availableFilters = availableFilterData
+ ?.map(eachitem => eachitem.attribute_code)
+ ?.sort();
+
+ const handlePriceFilter = priceFilter => {
+ if (priceFilter && priceFilter.size > 0) {
+ for (const price of priceFilter) {
+ const [from, to] = price.value.split('_');
+ return { price: { from, to } };
+ }
+ }
+ return {};
+ };
+
+ const [filterOptions, setFilterOptions] = useState();
+
+ const selectedFilters = useMemo(() => {
+ const filters = {};
+ if (filterOptions) {
+ for (const [group, items] of filterOptions.entries()) {
+ availableFilters?.map(eachitem => {
+ if (eachitem === group && group !== 'price') {
+ const sampleArray = [];
+ for (const item of items) {
+ sampleArray.push(item.value);
+ }
+ filters[group] = sampleArray;
+ }
+ });
+ }
+ }
+
+ if (filterOptions && filterOptions.has('price')) {
+ const priceFilter = filterOptions.get('price');
+ const priceRange = handlePriceFilter(priceFilter);
+ if (priceRange.price) {
+ filters.price = priceRange.price;
+ }
+ }
+
+ return filters;
+ }, [filterOptions, availableFilters]);
+
+ const dynamicQueryVariables = useMemo(() => {
+ const generateDynamicFiltersQuery = filterParams => {
+ let filterConditions = {
+ category_uid: { eq: categoryId }
+ };
+
+ Object.keys(filterParams).forEach(key => {
+ let filter = {};
+ if (key !== 'price') {
+ filter = { [key]: { in: filterParams[key] } };
+ }
+ filterConditions = { ...filterConditions, ...filter };
+ });
+
+ return filterConditions;
+ };
+
+ return generateDynamicFiltersQuery(selectedFilters);
+ }, [selectedFilters, categoryId]);
+
const placeholderItems = Array.from({ length: pageSize }).fill(null);
const [getFilters, { data: filterData }] = useLazyQuery(
@@ -60,18 +146,26 @@ export const useCategoryContent = props => {
);
const [, { dispatch }] = useEventingContext();
-
+ const [previousFilters, setPreviousFilters] = useState(null);
useEffect(() => {
- if (categoryId) {
+ if (
+ categoryId &&
+ JSON.stringify(selectedFilters) !== JSON.stringify(previousFilters)
+ ) {
getFilters({
variables: {
- categoryIdFilter: {
- eq: categoryId
- }
+ filters: dynamicQueryVariables
}
});
+ setPreviousFilters(selectedFilters);
}
- }, [categoryId, getFilters]);
+ }, [
+ categoryId,
+ selectedFilters,
+ dynamicQueryVariables,
+ previousFilters,
+ getFilters
+ ]);
useEffect(() => {
if (categoryId) {
@@ -85,7 +179,7 @@ export const useCategoryContent = props => {
}
}, [categoryId, getSortMethods]);
- const filters = filterData ? filterData.products.aggregations : null;
+ const filters = filterData ? filterData.products?.aggregations : null;
const items = data ? data.products.items : placeholderItems;
const totalPagesFromData = data
? data.products.page_info.total_pages
@@ -104,7 +198,7 @@ export const useCategoryContent = props => {
: null;
useEffect(() => {
- if (!categoryLoading && categoryData.categories.items.length > 0) {
+ if (!categoryLoading && categoryData?.categories.items.length > 0) {
dispatch({
type: 'CATEGORY_PAGE_VIEW',
payload: {
@@ -122,6 +216,8 @@ export const useCategoryContent = props => {
categoryName,
categoryDescription,
filters,
+ filterOptions,
+ setFilterOptions,
items,
totalCount,
totalPagesFromData
diff --git a/packages/peregrine/lib/util/htmlStringImgUrlConverter.js b/packages/peregrine/lib/util/htmlStringImgUrlConverter.js
index 96779fb97c..26631fa253 100644
--- a/packages/peregrine/lib/util/htmlStringImgUrlConverter.js
+++ b/packages/peregrine/lib/util/htmlStringImgUrlConverter.js
@@ -1,6 +1,6 @@
import makeUrl from './makeUrl';
import resolveLinkProps from './resolveLinkProps';
-
+import DOMPurify from 'dompurify';
/**
* Modifies html string images to use makeUrl as source and resolves links to use internal path.
*
@@ -9,7 +9,7 @@ import resolveLinkProps from './resolveLinkProps';
*/
const htmlStringImgUrlConverter = htmlString => {
const temporaryElement = document.createElement('div');
- temporaryElement.innerHTML = htmlString;
+ temporaryElement.innerHTML = DOMPurify.sanitize(htmlString);
for (const imgElement of temporaryElement.getElementsByTagName('img')) {
imgElement.src = makeUrl(imgElement.src, {
type: 'image-wysiwyg',
diff --git a/packages/peregrine/package.json b/packages/peregrine/package.json
index 432a36360b..01120b8b53 100644
--- a/packages/peregrine/package.json
+++ b/packages/peregrine/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/peregrine",
- "version": "14.4.1",
+ "version": "14.5.1-alpha.6",
"publishConfig": {
"access": "public"
},
diff --git a/packages/pwa-buildpack/package.json b/packages/pwa-buildpack/package.json
index 30a387040f..f6082bb012 100644
--- a/packages/pwa-buildpack/package.json
+++ b/packages/pwa-buildpack/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/pwa-buildpack",
- "version": "11.5.3",
+ "version": "11.5.4-alpha.6",
"publishConfig": {
"access": "public"
},
diff --git a/packages/venia-concept/package.json b/packages/venia-concept/package.json
index 773fefb630..f9efc908aa 100644
--- a/packages/venia-concept/package.json
+++ b/packages/venia-concept/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/venia-concept",
- "version": "14.1.0",
+ "version": "14.2.0-alpha.6",
"publishConfig": {
"access": "public"
},
@@ -35,8 +35,8 @@
},
"homepage": "https://github.com/magento/pwa-studio/tree/main/packages/venia-concept#readme",
"dependencies": {
- "@gomage/plugin-braintree-three-d-secure": "3.94.0",
- "@magento/pwa-buildpack": "~11.5.3"
+ "@gomage/plugin-braintree-three-d-secure": "~3.94.0",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6"
},
"devDependencies": {
"@adobe/apollo-link-mutation-queue": "~1.0.2",
@@ -51,14 +51,14 @@
"@babel/plugin-transform-runtime": "~7.4.4",
"@babel/preset-env": "~7.16.0",
"@babel/runtime": "~7.15.3",
- "@gomage/plugin-braintree-three-d-secure": "3.94.0",
+ "@gomage/plugin-braintree-three-d-secure": "~3.94.0",
"@magento/babel-preset-peregrine": "~1.3.3",
"@magento/eslint-config": "~1.5.0",
- "@magento/pagebuilder": "~9.3.2",
- "@magento/peregrine": "~14.4.1",
+ "@magento/pagebuilder": "9.3.3-alpha.6",
+ "@magento/peregrine": "14.5.1-alpha.6",
"@magento/pwa-theme-venia": "~2.4.0",
"@magento/upward-security-headers": "~1.0.14",
- "@magento/venia-ui": "~11.5.0",
+ "@magento/venia-ui": "11.6.0-alpha.6",
"@pmmmwh/react-refresh-webpack-plugin": "0.4.1",
"@storybook/react": "~6.3.7",
"@types/node": "16",
diff --git a/packages/venia-ui/lib/RootComponents/Category/categoryContent.js b/packages/venia-ui/lib/RootComponents/Category/categoryContent.js
index c3cbd4eb2e..d47c763499 100644
--- a/packages/venia-ui/lib/RootComponents/Category/categoryContent.js
+++ b/packages/venia-ui/lib/RootComponents/Category/categoryContent.js
@@ -50,6 +50,7 @@ const CategoryContent = props => {
categoryName,
categoryDescription,
filters,
+ setFilterOptions,
items,
totalCount,
totalPagesFromData
@@ -79,7 +80,7 @@ const CategoryContent = props => {
) : null;
const sidebar = shouldShowFilterButtons ? (
-
+
) : shouldShowFilterShimmer ? (
) : null;
diff --git a/packages/venia-ui/lib/components/FilterModal/CurrentFilters/__tests__/currentFilter.spec.js b/packages/venia-ui/lib/components/FilterModal/CurrentFilters/__tests__/currentFilter.spec.js
index 4176744cba..def763d4f1 100644
--- a/packages/venia-ui/lib/components/FilterModal/CurrentFilters/__tests__/currentFilter.spec.js
+++ b/packages/venia-ui/lib/components/FilterModal/CurrentFilters/__tests__/currentFilter.spec.js
@@ -1,5 +1,6 @@
import React from 'react';
import { act } from 'react-test-renderer';
+import { MemoryRouter } from 'react-router-dom';
import { createTestInstance } from '@magento/peregrine';
@@ -19,7 +20,11 @@ jest.mock('../../../Trigger', () => props => );
let inputProps = {};
const Component = () => {
- return ;
+ return (
+
+
+
+ );
};
const givenDefaultValues = () => {
diff --git a/packages/venia-ui/lib/components/FilterModal/CurrentFilters/currentFilter.js b/packages/venia-ui/lib/components/FilterModal/CurrentFilters/currentFilter.js
index 8578c5546d..91a42d7950 100644
--- a/packages/venia-ui/lib/components/FilterModal/CurrentFilters/currentFilter.js
+++ b/packages/venia-ui/lib/components/FilterModal/CurrentFilters/currentFilter.js
@@ -2,6 +2,7 @@ import React, { useCallback } from 'react';
import { useIntl } from 'react-intl';
import { shape, string, func } from 'prop-types';
import { X as Remove } from 'react-feather';
+import { useHistory, useLocation } from 'react-router-dom';
import { useStyle } from '../../../classify';
import Icon from '../../Icon';
@@ -12,13 +13,22 @@ const CurrentFilter = props => {
const { group, item, removeItem, onRemove } = props;
const classes = useStyle(defaultClasses, props.classes);
const { formatMessage } = useIntl();
+ const location = useLocation();
+ const history = useHistory();
const handleClick = useCallback(() => {
removeItem({ group, item });
if (typeof onRemove === 'function') {
onRemove(group, item);
}
- }, [group, item, removeItem, onRemove]);
+
+ if (group == 'price') {
+ // preserve all existing params
+ const params = new URLSearchParams(location.search);
+ params.delete('price[filter]');
+ history.replace({ search: params.toString() });
+ }
+ }, [group, item, removeItem, onRemove, history, location.search]);
const ariaLabel = formatMessage(
{
diff --git a/packages/venia-ui/lib/components/FilterModal/FilterList/__tests__/filterList.spec.js b/packages/venia-ui/lib/components/FilterModal/FilterList/__tests__/filterList.spec.js
index d13f05dec1..dba9b88aaf 100644
--- a/packages/venia-ui/lib/components/FilterModal/FilterList/__tests__/filterList.spec.js
+++ b/packages/venia-ui/lib/components/FilterModal/FilterList/__tests__/filterList.spec.js
@@ -1,4 +1,5 @@
import React from 'react';
+import { MemoryRouter } from 'react-router-dom';
import { createTestInstance } from '@magento/peregrine';
@@ -67,7 +68,11 @@ describe('#FilterList', () => {
});
it('renders without show more button', () => {
- const { root } = createTestInstance();
+ const { root } = createTestInstance(
+
+
+
+ );
expect(root.findAllByType(FilterItem)).toHaveLength(2);
expect(() => root.findByType('button')).toThrow();
@@ -76,7 +81,11 @@ describe('#FilterList', () => {
it('renders with show more button', () => {
givenShowMore();
- const { root } = createTestInstance();
+ const { root } = createTestInstance(
+
+
+
+ );
expect(() => root.findByType('button')).not.toThrow();
expect(root.findByType('button').children[0]).toBe(mockShowMore);
@@ -86,7 +95,11 @@ describe('#FilterList', () => {
givenShowMore();
givenExpanded();
- const { root } = createTestInstance();
+ const { root } = createTestInstance(
+
+
+
+ );
expect(() => root.findByType('button')).not.toThrow();
expect(root.findByType('button').children[0]).toBe(mockShowLess);
diff --git a/packages/venia-ui/lib/components/FilterModal/FilterList/filterList.js b/packages/venia-ui/lib/components/FilterModal/FilterList/filterList.js
index 0acf3d07c1..e1776f0230 100644
--- a/packages/venia-ui/lib/components/FilterModal/FilterList/filterList.js
+++ b/packages/venia-ui/lib/components/FilterModal/FilterList/filterList.js
@@ -1,4 +1,4 @@
-import React, { Fragment, useMemo } from 'react';
+import React, { Fragment, useMemo, useCallback } from 'react';
import { array, func, number, shape, string } from 'prop-types';
import { useIntl } from 'react-intl';
import setValidator from '@magento/peregrine/lib/validators/set';
@@ -8,6 +8,8 @@ import { useStyle } from '../../../classify';
import FilterItem from './filterItem';
import defaultClasses from './filterList.module.css';
import FilterItemRadioGroup from './filterItemRadioGroup';
+import RangeSlider from '../../RangeSlider/rangeSlider';
+import { useHistory, useLocation } from 'react-router-dom';
const labels = new WeakMap();
@@ -22,13 +24,46 @@ const FilterList = props => {
items,
onApply
} = props;
+ const { pathname, search } = useLocation();
+ const history = useHistory();
const classes = useStyle(defaultClasses, props.classes);
const talonProps = useFilterList({ filterState, items, itemCountToShow });
const { isListExpanded, handleListToggle } = talonProps;
const { formatMessage } = useIntl();
- // memoize item creation
- // search value is not referenced, so this array is stable
+ if (name === 'Price') {
+ var minRange = Number(items[0].value.split('_')[0]);
+ var maxRange = Number(items[items.length - 1].value.split('_')[1]);
+ if (filterState !== undefined) {
+ const filterArray = [...filterState];
+ var currentMinVal = Number(filterArray[0].value.split('_')[0]);
+ var currentMaxVal = Number(filterArray[0].value.split('_')[1]);
+ }
+ }
+
+ const handleChange = useCallback(
+ newValue => {
+ const test = String(search).split('&');
+ const filters = test.filter(element => {
+ return !element.includes('price');
+ });
+ const newSearch = filters.join('&');
+ const nextParams = new URLSearchParams(newSearch);
+
+ const DELIMITER = ',';
+ const title = String(newValue.min) + '-' + String(newValue.max);
+ const value = String(newValue.min) + '_' + String(newValue.max);
+ nextParams.append(
+ `${group}[filter]`,
+ `${title}${DELIMITER}${value}`
+ );
+
+ history.push({ pathname, search: String(nextParams) });
+ },
+ [group, history, pathname, search]
+ );
+
+ // Memoize item creation
const itemElements = useMemo(() => {
if (filterFrontendInput === 'boolean') {
const key = `item-${group}`;
@@ -51,36 +86,46 @@ const FilterList = props => {
);
}
- return items.map((item, index) => {
- const { title, value } = item;
- const key = `item-${group}-${value}`;
-
- if (!isListExpanded && index >= itemCountToShow) {
- return null;
- }
-
- // create an element for each item
- const element = (
-
-
+
-
+
);
+ } else {
+ return items.map((item, index) => {
+ const { title, value } = item;
+ const key = `item-${group}-${value}`;
+
+ if (!isListExpanded && index >= itemCountToShow) {
+ return null;
+ }
- // associate each element with its normalized title
- // titles are not unique, so use the element as the key
- labels.set(element, title.toUpperCase());
- return element;
- });
+ const element = (
+
+
+
+ );
+ labels.set(element, title.toUpperCase());
+ return element;
+ });
+ }
}, [
classes,
filterApi,
@@ -91,7 +136,12 @@ const FilterList = props => {
items,
isListExpanded,
itemCountToShow,
- onApply
+ onApply,
+ minRange,
+ maxRange,
+ currentMinVal,
+ currentMaxVal,
+ handleChange
]);
const showMoreLessItem = useMemo(() => {
diff --git a/packages/venia-ui/lib/components/FilterModal/filterBlock.js b/packages/venia-ui/lib/components/FilterModal/filterBlock.js
index d667d98810..b961c0a3ac 100644
--- a/packages/venia-ui/lib/components/FilterModal/filterBlock.js
+++ b/packages/venia-ui/lib/components/FilterModal/filterBlock.js
@@ -28,7 +28,8 @@ const FilterBlock = props => {
const talonProps = useFilterBlock({
filterState,
items,
- initialOpen
+ initialOpen,
+ group
});
const { handleClick, isExpanded } = talonProps;
const iconSrc = isExpanded ? ArrowUp : ArrowDown;
diff --git a/packages/venia-ui/lib/components/FilterSidebar/__tests__/filterSidebar.spec.js b/packages/venia-ui/lib/components/FilterSidebar/__tests__/filterSidebar.spec.js
index 9fafd2bbf0..54c5f42c2e 100644
--- a/packages/venia-ui/lib/components/FilterSidebar/__tests__/filterSidebar.spec.js
+++ b/packages/venia-ui/lib/components/FilterSidebar/__tests__/filterSidebar.spec.js
@@ -1,5 +1,6 @@
import React from 'react';
import { act } from 'react-test-renderer';
+import { MemoryRouter } from 'react-router-dom';
import { createTestInstance } from '@magento/peregrine';
@@ -51,6 +52,8 @@ const mockHandleApply = jest.fn();
const mockScrollTo = jest.fn();
+const mockFilterOptions = jest.fn();
+
const mockGetBoundingClientRect = jest.fn();
let mockFilterState;
@@ -125,7 +128,8 @@ const Component = () => {
const givenDefaultValues = () => {
inputProps = {
- filters: []
+ filters: [],
+ setFilterOptions: mockFilterOptions
};
mockFilterState = new Map();
@@ -133,13 +137,15 @@ const givenDefaultValues = () => {
const givenFilters = () => {
inputProps = {
- filters: mockFilters
+ filters: mockFilters,
+ setFilterOptions: mockFilterOptions
};
};
const givenSelectedFilters = () => {
inputProps = {
- filters: mockFilters
+ filters: mockFilters,
+ setFilterOptions: mockFilterOptions
};
mockFilterState = new Map([['group', 'item']]);
@@ -148,7 +154,8 @@ const givenSelectedFilters = () => {
const givenFiltersAndAmountToShow = () => {
inputProps = {
filters: mockFilters,
- filterCountToOpen: mockFiltersOpenCount
+ filterCountToOpen: mockFiltersOpenCount,
+ setFilterOptions: mockFilterOptions
};
};
@@ -161,7 +168,11 @@ describe('#FilterSidebar', () => {
});
it('renders without filters', () => {
- createTestInstance();
+ createTestInstance(
+
+
+
+ );
expect(mockFilterBlock).not.toHaveBeenCalled();
expect(mockCurrentFilters).toHaveBeenCalled();
@@ -170,7 +181,11 @@ describe('#FilterSidebar', () => {
it('renders with filters and no selected filters', () => {
givenFilters();
- const { root } = createTestInstance();
+ const { root } = createTestInstance(
+
+
+
+ );
expect(() => root.findByType(LinkButton)).toThrow();
expect(mockFilterBlock).toHaveBeenCalledTimes(mockFilters.length);
@@ -179,7 +194,11 @@ describe('#FilterSidebar', () => {
it('renders with filters and selected filter', () => {
givenSelectedFilters();
- const { root } = createTestInstance();
+ const { root } = createTestInstance(
+
+
+
+ );
expect(() => root.findByType(LinkButton)).not.toThrow();
expect(mockFilterBlock).toHaveBeenCalledTimes(mockFilters.length);
@@ -188,7 +207,11 @@ describe('#FilterSidebar', () => {
it('handles when a user applies a filter and ref is not provided', () => {
givenSelectedFilters();
- const { root } = createTestInstance();
+ const { root } = createTestInstance(
+
+
+
+ );
act(() => {
root.findAllByType(FilterBlock)[0].props.onApply();
@@ -206,17 +229,22 @@ describe('#FilterSidebar', () => {
value: mockScrollTo
});
- const { root } = createTestInstance(, {
- createNodeMock: () => {
- return {
- getBoundingClientRect: mockGetBoundingClientRect.mockReturnValue(
- {
- top: 250
- }
- )
- };
+ const { root } = createTestInstance(
+
+
+ ,
+ {
+ createNodeMock: () => {
+ return {
+ getBoundingClientRect: mockGetBoundingClientRect.mockReturnValue(
+ {
+ top: 250
+ }
+ )
+ };
+ }
}
- });
+ );
act(() => {
root.findAllByType(FilterBlock)[0].props.onApply();
@@ -229,7 +257,11 @@ describe('#FilterSidebar', () => {
it('accepts configurable amount of open filters', () => {
givenFiltersAndAmountToShow();
- createTestInstance();
+ createTestInstance(
+
+
+
+ );
expect(mockFilterBlock).toHaveBeenCalledTimes(mockFilters.length);
diff --git a/packages/venia-ui/lib/components/FilterSidebar/filterSidebar.js b/packages/venia-ui/lib/components/FilterSidebar/filterSidebar.js
index 4fa266eb8a..5c4abfa6bb 100644
--- a/packages/venia-ui/lib/components/FilterSidebar/filterSidebar.js
+++ b/packages/venia-ui/lib/components/FilterSidebar/filterSidebar.js
@@ -1,4 +1,4 @@
-import React, { useMemo, useCallback, useRef } from 'react';
+import React, { useMemo, useCallback, useRef, useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { array, arrayOf, shape, string, number } from 'prop-types';
import { useFilterSidebar } from '@magento/peregrine/lib/talons/FilterSidebar';
@@ -8,6 +8,7 @@ import LinkButton from '../LinkButton';
import CurrentFilters from '../FilterModal/CurrentFilters';
import FilterBlock from '../FilterModal/filterBlock';
import defaultClasses from './filterSidebar.module.css';
+import { useLocation } from 'react-router-dom';
const SCROLL_OFFSET = 150;
@@ -17,7 +18,7 @@ const SCROLL_OFFSET = 150;
* @param {Object} props.filters - filters to display
*/
const FilterSidebar = props => {
- const { filters, filterCountToOpen } = props;
+ const { filters, filterCountToOpen, setFilterOptions } = props;
const talonProps = useFilterSidebar({ filters });
const {
filterApi,
@@ -31,6 +32,32 @@ const FilterSidebar = props => {
const filterRef = useRef();
const classes = useStyle(defaultClasses, props.classes);
+ const location = useLocation();
+
+ //adding the price filter values to the filterstate
+ const priceFilters = Array.from(filterItems, ([group]) => {
+ if (group == 'price') {
+ // preserve all existing params
+ const params = new URLSearchParams(location.search);
+ const uniqueKeys = new Set(params.keys());
+ // iterate over existing param keys
+ for (const key of uniqueKeys) {
+ // if a key matches a known filter, add its items to the next state
+ if (key == 'price[filter]') {
+ const value = params.get('price[filter]');
+ const item = {
+ title: value.split(',')[0],
+ value: value.split(',')[1]
+ };
+ const filterVar = new Set();
+ filterVar.add(item);
+
+ //to display the price filter value after selecting the filter
+ filterState.set('price', new Set(filterVar));
+ }
+ }
+ }
+ });
const handleApplyFilter = useCallback(
(...args) => {
@@ -50,6 +77,12 @@ const FilterSidebar = props => {
[handleApply, filterRef]
);
+ useEffect(() => {
+ if (filterState) {
+ setFilterOptions(filterState);
+ }
+ }, [filterState, setFilterOptions]);
+
const filtersList = useMemo(
() =>
Array.from(filterItems, ([group, items], iteration) => {
@@ -115,6 +148,7 @@ const FilterSidebar = props => {
/>
+ {priceFilters}
{
+ const [minVal, setMinVal] = useState(initialMin || min);
+ const [maxVal, setMaxVal] = useState(initialMax || max);
+ const minValRef = useRef(minVal);
+ const maxValRef = useRef(maxVal);
+ const range = useRef(null);
+
+ // Convert value to percentage for positioning
+ const getPercent = useCallback(
+ value => Math.round(((value - min) / (max - min)) * 100),
+ [min, max]
+ );
+
+ // set width of the range to decrease from the left side
+ useEffect(() => {
+ const minPercent = getPercent(minVal);
+ const maxPercent = getPercent(maxValRef.current);
+
+ if (range.current) {
+ range.current.style.left = `${minPercent}%`;
+ range.current.style.width = `${maxPercent - minPercent}%`;
+ }
+ }, [minVal, getPercent]);
+
+ // set the width of the range to decrease from right side
+ useEffect(() => {
+ const minPercent = getPercent(minValRef.current);
+ const maxPercent = getPercent(maxVal);
+
+ if (range.current) {
+ range.current.style.width = `${maxPercent - minPercent}%`;
+ }
+ }, [maxVal, getPercent]);
+
+ // Handle min and max value changes
+ useEffect(() => {
+ if (minVal !== minValRef.current || maxVal !== maxValRef.current) {
+ onChange({ min: minVal, max: maxVal });
+ minValRef.current = minVal;
+ maxValRef.current = maxVal;
+ }
+ }, [minVal, maxVal, onChange]);
+
+ return (
+
+ {/* Display Price Value */}
+
+ {minVal}
+ {maxVal}
+
+
+ {/* Style the price range slider */}
+
+
+ );
+};
+
+export default PriceRangeSlider;
diff --git a/packages/venia-ui/lib/components/RangeSlider/rangeSlider.module.css b/packages/venia-ui/lib/components/RangeSlider/rangeSlider.module.css
new file mode 100644
index 0000000000..1fe684beac
--- /dev/null
+++ b/packages/venia-ui/lib/components/RangeSlider/rangeSlider.module.css
@@ -0,0 +1,76 @@
+.slider {
+ position: relative;
+}
+
+.trackslider,
+.rangeslider {
+ position: absolute;
+}
+
+.trackslider,
+.rangeslider {
+ border-radius: 4px;
+ height: 6px;
+}
+
+.trackslider {
+ background-color: #022140;
+ width: 100%;
+ z-index: 1;
+}
+
+.rangeslider {
+ z-index: 2;
+}
+
+.thumb,
+.thumb::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ -webkit-tap-highlight-color: transparent;
+}
+
+.thumb {
+ pointer-events: none;
+ position: absolute;
+ height: 0;
+ outline: none;
+}
+
+.thumbleft {
+ z-index: 3;
+}
+
+.thumbright {
+ z-index: 4;
+}
+
+.thumb::-webkit-slider-thumb {
+ background-color: #2954fe;
+ border-radius: 50%;
+ /* box-shadow: 0 0 1px 1px #f50707; */
+ /* border: 4px solid #ff0303; */
+ cursor: pointer;
+ height: 20px;
+ width: 20px;
+ margin-top: 4.5px;
+ pointer-events: all;
+ position: relative;
+ transition: transform 0.3s ease-in-out;
+}
+
+.thumb::-webkit-slider-thumb:hover {
+ transform: scale(1.2);
+}
+
+.thumb::-moz-range-thumb {
+ background-color: #0a0a0a;
+ border-radius: 50%;
+ /* box-shadow: 0 0 1px 1px #f50707; */
+ border: 4px solid #ff0303;
+ cursor: pointer;
+ height: 28px;
+ width: 28px;
+ margin-top: 4.5px;
+ pointer-events: all;
+ position: relative;
+}
diff --git a/packages/venia-ui/package.json b/packages/venia-ui/package.json
index c25b98268a..685c7caaf5 100644
--- a/packages/venia-ui/package.json
+++ b/packages/venia-ui/package.json
@@ -1,6 +1,6 @@
{
"name": "@magento/venia-ui",
- "version": "11.5.0",
+ "version": "11.6.0-alpha.6",
"publishConfig": {
"access": "public"
},
@@ -80,8 +80,8 @@
"peerDependencies": {
"@apollo/client": "~3.5.0",
"@magento/babel-preset-peregrine": "~1.3.3",
- "@magento/peregrine": "~14.4.1",
- "@magento/pwa-buildpack": "~11.5.3",
+ "@magento/peregrine": "14.5.1-alpha.6",
+ "@magento/pwa-buildpack": "11.5.4-alpha.6",
"apollo-cache-persist": "~0.1.1",
"braintree-web-drop-in": "~1.43.0",
"graphql": "~15.5.0",
diff --git a/pwa-devdocs/package.json b/pwa-devdocs/package.json
index 49a7c291dc..9bbf822946 100644
--- a/pwa-devdocs/package.json
+++ b/pwa-devdocs/package.json
@@ -1,7 +1,7 @@
{
"name": "pwa-devdocs",
"private": true,
- "version": "14.1.0",
+ "version": "14.2.0-alpha.6",
"description": "A documentation site for Magento PWA",
"main": "gulpfile.js",
"dependencies": {
diff --git a/venia-integration-tests/src/fixtures/googleMapApi/index.js b/venia-integration-tests/src/fixtures/googleMapApi/index.js
index b633c5f97b..203b1c4df0 100644
--- a/venia-integration-tests/src/fixtures/googleMapApi/index.js
+++ b/venia-integration-tests/src/fixtures/googleMapApi/index.js
@@ -1,3 +1,4 @@
+import DOMPurify from 'dompurify';
export const createGoogleMapApi = currentMapApi => {
return {
maps: {
@@ -85,7 +86,9 @@ export const createGoogleMapApi = currentMapApi => {
open(map) {
map.infoWindowContainer.style.maxWidth = this.maxWidth;
- map.infoWindowContainer.innerHTML = this.content;
+ map.infoWindowContainer.innerHTML = DOMPurify.sanitize(
+ this.content
+ );
}
close() {
diff --git a/yarn.lock b/yarn.lock
index 6e8fbe3edc..8ee6efba9a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8939,6 +8939,11 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1:
dependencies:
domelementtype "^2.2.0"
+dompurify@^2.3.8:
+ version "2.5.8"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.5.8.tgz#2809d89d7e528dc7a071dea440d7376df676f824"
+ integrity sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==
+
domutils@^2.5.2, domutils@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"