`.\r\n * @returns {Function} A `useDispatch` hook bound to the specified context.\r\n */\n\nexport function createDispatchHook(context) {\n if (context === void 0) {\n context = ReactReduxContext;\n }\n\n var useStore = context === ReactReduxContext ? useDefaultStore : createStoreHook(context);\n return function useDispatch() {\n var store = useStore();\n return store.dispatch;\n };\n}\n/**\r\n * A hook to access the redux `dispatch` function.\r\n *\r\n * @returns {any|function} redux store's `dispatch` function\r\n *\r\n * @example\r\n *\r\n * import React, { useCallback } from 'react'\r\n * import { useDispatch } from 'react-redux'\r\n *\r\n * export const CounterComponent = ({ value }) => {\r\n * const dispatch = useDispatch()\r\n * const increaseCounter = useCallback(() => dispatch({ type: 'increase-counter' }), [])\r\n * return (\r\n * \r\n * {value} \r\n * Increase counter \r\n *
\r\n * )\r\n * }\r\n */\n\nexport var useDispatch = /*#__PURE__*/createDispatchHook();","import { useReducer, useRef, useMemo, useContext, useDebugValue } from 'react';\nimport { useReduxContext as useDefaultReduxContext } from './useReduxContext';\nimport { createSubscription } from '../utils/Subscription';\nimport { useIsomorphicLayoutEffect } from '../utils/useIsomorphicLayoutEffect';\nimport { ReactReduxContext } from '../components/Context';\n\nvar refEquality = function refEquality(a, b) {\n return a === b;\n};\n\nfunction useSelectorWithStoreAndSubscription(selector, equalityFn, store, contextSub) {\n var _useReducer = useReducer(function (s) {\n return s + 1;\n }, 0),\n forceRender = _useReducer[1];\n\n var subscription = useMemo(function () {\n return createSubscription(store, contextSub);\n }, [store, contextSub]);\n var latestSubscriptionCallbackError = useRef();\n var latestSelector = useRef();\n var latestStoreState = useRef();\n var latestSelectedState = useRef();\n var storeState = store.getState();\n var selectedState;\n\n try {\n if (selector !== latestSelector.current || storeState !== latestStoreState.current || latestSubscriptionCallbackError.current) {\n var newSelectedState = selector(storeState); // ensure latest selected state is reused so that a custom equality function can result in identical references\n\n if (latestSelectedState.current === undefined || !equalityFn(newSelectedState, latestSelectedState.current)) {\n selectedState = newSelectedState;\n } else {\n selectedState = latestSelectedState.current;\n }\n } else {\n selectedState = latestSelectedState.current;\n }\n } catch (err) {\n if (latestSubscriptionCallbackError.current) {\n err.message += \"\\nThe error may be correlated with this previous error:\\n\" + latestSubscriptionCallbackError.current.stack + \"\\n\\n\";\n }\n\n throw err;\n }\n\n useIsomorphicLayoutEffect(function () {\n latestSelector.current = selector;\n latestStoreState.current = storeState;\n latestSelectedState.current = selectedState;\n latestSubscriptionCallbackError.current = undefined;\n });\n useIsomorphicLayoutEffect(function () {\n function checkForUpdates() {\n try {\n var newStoreState = store.getState(); // Avoid calling selector multiple times if the store's state has not changed\n\n if (newStoreState === latestStoreState.current) {\n return;\n }\n\n var _newSelectedState = latestSelector.current(newStoreState);\n\n if (equalityFn(_newSelectedState, latestSelectedState.current)) {\n return;\n }\n\n latestSelectedState.current = _newSelectedState;\n latestStoreState.current = newStoreState;\n } catch (err) {\n // we ignore all errors here, since when the component\n // is re-rendered, the selectors are called again, and\n // will throw again, if neither props nor store state\n // changed\n latestSubscriptionCallbackError.current = err;\n }\n\n forceRender();\n }\n\n subscription.onStateChange = checkForUpdates;\n subscription.trySubscribe();\n checkForUpdates();\n return function () {\n return subscription.tryUnsubscribe();\n };\n }, [store, subscription]);\n return selectedState;\n}\n/**\r\n * Hook factory, which creates a `useSelector` hook bound to a given context.\r\n *\r\n * @param {React.Context} [context=ReactReduxContext] Context passed to your ``.\r\n * @returns {Function} A `useSelector` hook bound to the specified context.\r\n */\n\n\nexport function createSelectorHook(context) {\n if (context === void 0) {\n context = ReactReduxContext;\n }\n\n var useReduxContext = context === ReactReduxContext ? useDefaultReduxContext : function () {\n return useContext(context);\n };\n return function useSelector(selector, equalityFn) {\n if (equalityFn === void 0) {\n equalityFn = refEquality;\n }\n\n if (process.env.NODE_ENV !== 'production') {\n if (!selector) {\n throw new Error(\"You must pass a selector to useSelector\");\n }\n\n if (typeof selector !== 'function') {\n throw new Error(\"You must pass a function as a selector to useSelector\");\n }\n\n if (typeof equalityFn !== 'function') {\n throw new Error(\"You must pass a function as an equality function to useSelector\");\n }\n }\n\n var _useReduxContext = useReduxContext(),\n store = _useReduxContext.store,\n contextSub = _useReduxContext.subscription;\n\n var selectedState = useSelectorWithStoreAndSubscription(selector, equalityFn, store, contextSub);\n useDebugValue(selectedState);\n return selectedState;\n };\n}\n/**\r\n * A hook to access the redux store's state. This hook takes a selector function\r\n * as an argument. The selector is called with the store state.\r\n *\r\n * This hook takes an optional equality comparison function as the second parameter\r\n * that allows you to customize the way the selected state is compared to determine\r\n * whether the component needs to be re-rendered.\r\n *\r\n * @param {Function} selector the selector function\r\n * @param {Function=} equalityFn the function that will be used to determine equality\r\n *\r\n * @returns {any} the selected state\r\n *\r\n * @example\r\n *\r\n * import React from 'react'\r\n * import { useSelector } from 'react-redux'\r\n *\r\n * export const CounterComponent = () => {\r\n * const counter = useSelector(state => state.counter)\r\n * return {counter}
\r\n * }\r\n */\n\nexport var useSelector = /*#__PURE__*/createSelectorHook();","export * from './exports';\nimport { unstable_batchedUpdates as batch } from './utils/reactBatchedUpdates';\nimport { setBatch } from './utils/batch'; // Enable batched updates in our subscriptions for use\n// with standard React renderers (ReactDOM, React Native)\n\nsetBatch(batch);\nexport { batch };","/* eslint-disable @scandipwa/scandipwa-guidelines/export-level-one */\nimport i18n from '@scandipwa/webpack-i18n-runtime/src/util/i18n';\n\nfunction injectValues(string, ...values) {\n // eslint-disable-next-line fp/no-let\n let i = 0;\n return string.replace(/%s/g, () => values[i++]);\n}\n\nfunction translateString(string) {\n return i18n.currentTranslation[string] || string;\n}\n\nfunction getTranslatedStringWithInjectedValues(string, values) {\n return injectValues(translateString(string), ...values);\n}\n\nexport default function __(string, ...values) {\n return getTranslatedStringWithInjectedValues(string, values);\n}\n","function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {\n try {\n var info = gen[key](arg);\n var value = info.value;\n } catch (error) {\n reject(error);\n return;\n }\n\n if (info.done) {\n resolve(value);\n } else {\n Promise.resolve(value).then(_next, _throw);\n }\n}\n\nexport default function _asyncToGenerator(fn) {\n return function () {\n var self = this,\n args = arguments;\n return new Promise(function (resolve, reject) {\n var gen = fn.apply(self, args);\n\n function _next(value) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"next\", value);\n }\n\n function _throw(err) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"throw\", err);\n }\n\n _next(undefined);\n });\n };\n}","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport * from './Request';\nexport * from './Mutation';\nexport * from './Query';\nexport * from './Error';\nexport { default as QueryDispatcher } from './QueryDispatcher';\n","export default function _getPrototypeOf(o) {\n _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {\n return o.__proto__ || Object.getPrototypeOf(o);\n };\n return _getPrototypeOf(o);\n}","import superPropBase from \"@babel/runtime/helpers/esm/superPropBase\";\nexport default function _get(target, property, receiver) {\n if (typeof Reflect !== \"undefined\" && Reflect.get) {\n _get = Reflect.get;\n } else {\n _get = function _get(target, property, receiver) {\n var base = superPropBase(target, property);\n if (!base) return;\n var desc = Object.getOwnPropertyDescriptor(base, property);\n\n if (desc.get) {\n return desc.get.call(receiver);\n }\n\n return desc.value;\n };\n }\n\n return _get(target, property, receiver || target);\n}","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport const SHOW_NOTIFICATION = 'SHOW_NOTIFICATION';\nexport const HIDE_NOTIFICATION = 'HIDE_NOTIFICATION';\n\n/**\n * Show notification (append to notification to global notification map).\n * @param {String} msgType\n * @param {String} msgText\n * @param {any} msgDebug\n * @return {void}\n * @namespace Scandipwa/Store/Notification/Action/showNotification */\nexport const showNotification = (msgType, msgText, msgDebug) => ({\n type: SHOW_NOTIFICATION,\n msgType,\n msgText,\n msgDebug\n});\n\n/**\n * Hide notification with specific id (drop notification from global list).\n * @param {number} id\n * @return {void}\n * @namespace Scandipwa/Store/Notification/Action/hideNotification */\nexport const hideNotification = (id) => ({\n type: HIDE_NOTIFICATION,\n id\n});\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\nexport const BEFORE_ITEMS_TYPE = 'BEFORE_ITEMS_TYPE';\nexport const SWITCH_ITEMS_TYPE = 'SWITCH_ITEMS_TYPE';\nexport const AFTER_ITEMS_TYPE = 'AFTER_ITEMS_TYPE';\n\n// BEFORE_ITEMS_TYPE\nexport const NOTIFICATION_LIST = 'NOTIFICATION_LIST';\nexport const NAVIGATION_TABS = 'NAVIGATION_TABS';\nexport const DEMO_NOTICE = 'DEMO_NOTICE';\nexport const HEADER = 'HEADER';\nexport const BREADCRUMBS = 'BREADCRUMBS';\nexport const NEW_VERSION_POPUP = 'NEW_VERSION_POPUP';\n\n// SWITCH_ITEMS_TYPE\nexport const HOME = 'HOME';\nexport const SEARCH = 'SEARCH';\nexport const CMS_PAGE = 'CMS_PAGE';\nexport const CART = 'CART';\nexport const CHECKOUT = 'CHECKOUT';\nexport const CHANGE_PASSWORD = 'CHANGE_PASSWORD';\nexport const CREATE_ACCOUNT = 'CREATE_ACCOUNT';\nexport const LOGIN = 'LOGIN';\nexport const ACCOUNT_FORGOT_PASSWORD = 'ACCOUNT_FORGOT_PASSWORD';\nexport const FORGOT_PASSWORD = 'FORGOT_PASSWORD';\nexport const CONFIRM_ACCOUNT = 'CONFIRM_ACCOUNT';\nexport const MY_ACCOUNT = 'MY_ACCOUNT';\nexport const MY_ACCOUNT_ORDER = 'MY_ACCOUNT_ORDER';\nexport const MY_ACCOUNT_ORDERS = 'MY_ACCOUNT_ORDERS';\nexport const MY_ACCOUNT_DOWNLOADABLE = 'MY_ACCOUNT_DOWNLOADABLE';\nexport const MY_ACCOUNT_WISHLIST = 'MY_ACCOUNT_WISHLIST';\nexport const MY_ACCOUNT_ADDRESS = 'MY_ACCOUNT_ADDRESS';\nexport const MY_ACCOUNT_NEWSLETTER = 'MY_ACCOUNT_NEWSLETTER';\nexport const MENU = 'MENU';\nexport const SHARED_WISHLIST = 'SHARED_WISHLIST';\nexport const CONTACT_PAGE = 'CONTACT_PAGE';\nexport const COMPARE = 'COMPARE';\nexport const STYLE_GUIDE = 'STYLE_GUIDE';\nexport const URL_REWRITES = 'URL_REWRITES';\nexport const PRINT_ORDER = 'PRINT_ORDER';\n\n// AFTER_ITEMS_TYPE\nexport const FOOTER = 'FOOTER';\nexport const COOKIE_POPUP = 'COOKIE_POPUP';\n\nexport const URL_ONLY_MAIN_ITEMS_RENDER = [\n '/sales/order/print',\n '/styleguide'\n];\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\nexport * from 'SourceComponent/Router/Router.config';\n\nexport const NOTIFICATIONS = 'NOTIFICATIONS';\nexport const BEFORE_ITEMS_TYPE = 'BEFORE_ITEMS_TYPE';\nexport const SWITCH_ITEMS_TYPE = 'SWITCH_ITEMS_TYPE';\nexport const AFTER_ITEMS_TYPE = 'AFTER_ITEMS_TYPE';\nexport const MOBILE_WIDTH = 767;\nexport const HEADER_IS_MOBILE_UNTIL = 1180;\nexport const CACHE_NAME = 'app-runtime-static';\nexport const STORE_CODE_UAE = 'ar';\nexport const STORE_CODE_KSA_AR = 'ksa_ar';\nexport const STORE_CODE_KSA_EN = 'ksa_en';\nexport const STORE_CODE_EN = 'en';\nexport const CUSTOMER_EMAIL_COOKIE = 'customer_email';\nexport const SWITCH_STORE_LANGUAGE = 'switch_store_language';\n","import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose';\nimport React from 'react';\nimport PropTypes from 'prop-types';\nimport { createMemoryHistory, createLocation, locationsAreEqual, createPath } from 'history';\nimport warning from 'tiny-warning';\nimport invariant from 'tiny-invariant';\nimport _extends from '@babel/runtime/helpers/esm/extends';\nimport pathToRegexp from 'path-to-regexp';\nimport { isValidElementType } from 'react-is';\nimport _objectWithoutPropertiesLoose from '@babel/runtime/helpers/esm/objectWithoutPropertiesLoose';\nimport hoistStatics from 'hoist-non-react-statics';\n\nvar MAX_SIGNED_31_BIT_INT = 1073741823;\nvar commonjsGlobal = typeof globalThis !== \"undefined\" // 'global proper'\n? // eslint-disable-next-line no-undef\nglobalThis : typeof window !== \"undefined\" ? window // Browser\n: typeof global !== \"undefined\" ? global // node.js\n: {};\n\nfunction getUniqueId() {\n var key = \"__global_unique_id__\";\n return commonjsGlobal[key] = (commonjsGlobal[key] || 0) + 1;\n} // Inlined Object.is polyfill.\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n\n\nfunction objectIs(x, y) {\n if (x === y) {\n return x !== 0 || 1 / x === 1 / y;\n } else {\n // eslint-disable-next-line no-self-compare\n return x !== x && y !== y;\n }\n}\n\nfunction createEventEmitter(value) {\n var handlers = [];\n return {\n on: function on(handler) {\n handlers.push(handler);\n },\n off: function off(handler) {\n handlers = handlers.filter(function (h) {\n return h !== handler;\n });\n },\n get: function get() {\n return value;\n },\n set: function set(newValue, changedBits) {\n value = newValue;\n handlers.forEach(function (handler) {\n return handler(value, changedBits);\n });\n }\n };\n}\n\nfunction onlyChild(children) {\n return Array.isArray(children) ? children[0] : children;\n}\n\nfunction createReactContext(defaultValue, calculateChangedBits) {\n var _Provider$childContex, _Consumer$contextType;\n\n var contextProp = \"__create-react-context-\" + getUniqueId() + \"__\";\n\n var Provider = /*#__PURE__*/function (_React$Component) {\n _inheritsLoose(Provider, _React$Component);\n\n function Provider() {\n var _this;\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;\n _this.emitter = createEventEmitter(_this.props.value);\n return _this;\n }\n\n var _proto = Provider.prototype;\n\n _proto.getChildContext = function getChildContext() {\n var _ref;\n\n return _ref = {}, _ref[contextProp] = this.emitter, _ref;\n };\n\n _proto.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {\n if (this.props.value !== nextProps.value) {\n var oldValue = this.props.value;\n var newValue = nextProps.value;\n var changedBits;\n\n if (objectIs(oldValue, newValue)) {\n changedBits = 0; // No change\n } else {\n changedBits = typeof calculateChangedBits === \"function\" ? calculateChangedBits(oldValue, newValue) : MAX_SIGNED_31_BIT_INT;\n\n if (process.env.NODE_ENV !== \"production\") {\n process.env.NODE_ENV !== \"production\" ? warning((changedBits & MAX_SIGNED_31_BIT_INT) === changedBits, \"calculateChangedBits: Expected the return value to be a \" + \"31-bit integer. Instead received: \" + changedBits) : void 0;\n }\n\n changedBits |= 0;\n\n if (changedBits !== 0) {\n this.emitter.set(nextProps.value, changedBits);\n }\n }\n }\n };\n\n _proto.render = function render() {\n return this.props.children;\n };\n\n return Provider;\n }(React.Component);\n\n Provider.childContextTypes = (_Provider$childContex = {}, _Provider$childContex[contextProp] = PropTypes.object.isRequired, _Provider$childContex);\n\n var Consumer = /*#__PURE__*/function (_React$Component2) {\n _inheritsLoose(Consumer, _React$Component2);\n\n function Consumer() {\n var _this2;\n\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n\n _this2 = _React$Component2.call.apply(_React$Component2, [this].concat(args)) || this;\n _this2.observedBits = void 0;\n _this2.state = {\n value: _this2.getValue()\n };\n\n _this2.onUpdate = function (newValue, changedBits) {\n var observedBits = _this2.observedBits | 0;\n\n if ((observedBits & changedBits) !== 0) {\n _this2.setState({\n value: _this2.getValue()\n });\n }\n };\n\n return _this2;\n }\n\n var _proto2 = Consumer.prototype;\n\n _proto2.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {\n var observedBits = nextProps.observedBits;\n this.observedBits = observedBits === undefined || observedBits === null ? MAX_SIGNED_31_BIT_INT // Subscribe to all changes by default\n : observedBits;\n };\n\n _proto2.componentDidMount = function componentDidMount() {\n if (this.context[contextProp]) {\n this.context[contextProp].on(this.onUpdate);\n }\n\n var observedBits = this.props.observedBits;\n this.observedBits = observedBits === undefined || observedBits === null ? MAX_SIGNED_31_BIT_INT // Subscribe to all changes by default\n : observedBits;\n };\n\n _proto2.componentWillUnmount = function componentWillUnmount() {\n if (this.context[contextProp]) {\n this.context[contextProp].off(this.onUpdate);\n }\n };\n\n _proto2.getValue = function getValue() {\n if (this.context[contextProp]) {\n return this.context[contextProp].get();\n } else {\n return defaultValue;\n }\n };\n\n _proto2.render = function render() {\n return onlyChild(this.props.children)(this.state.value);\n };\n\n return Consumer;\n }(React.Component);\n\n Consumer.contextTypes = (_Consumer$contextType = {}, _Consumer$contextType[contextProp] = PropTypes.object, _Consumer$contextType);\n return {\n Provider: Provider,\n Consumer: Consumer\n };\n}\n\n// MIT License\nvar createContext = React.createContext || createReactContext;\n\n// TODO: Replace with React.createContext once we can assume React 16+\n\nvar createNamedContext = function createNamedContext(name) {\n var context = createContext();\n context.displayName = name;\n return context;\n};\n\nvar historyContext = /*#__PURE__*/createNamedContext(\"Router-History\");\n\nvar context = /*#__PURE__*/createNamedContext(\"Router\");\n\n/**\n * The public API for putting history on context.\n */\n\nvar Router = /*#__PURE__*/function (_React$Component) {\n _inheritsLoose(Router, _React$Component);\n\n Router.computeRootMatch = function computeRootMatch(pathname) {\n return {\n path: \"/\",\n url: \"/\",\n params: {},\n isExact: pathname === \"/\"\n };\n };\n\n function Router(props) {\n var _this;\n\n _this = _React$Component.call(this, props) || this;\n _this.state = {\n location: props.history.location\n }; // This is a bit of a hack. We have to start listening for location\n // changes here in the constructor in case there are any s\n // on the initial render. If there are, they will replace/push when\n // they mount and since cDM fires in children before parents, we may\n // get a new location before the is mounted.\n\n _this._isMounted = false;\n _this._pendingLocation = null;\n\n if (!props.staticContext) {\n _this.unlisten = props.history.listen(function (location) {\n _this._pendingLocation = location;\n });\n }\n\n return _this;\n }\n\n var _proto = Router.prototype;\n\n _proto.componentDidMount = function componentDidMount() {\n var _this2 = this;\n\n this._isMounted = true;\n\n if (this.unlisten) {\n // Any pre-mount location changes have been captured at\n // this point, so unregister the listener.\n this.unlisten();\n }\n\n if (!this.props.staticContext) {\n this.unlisten = this.props.history.listen(function (location) {\n if (_this2._isMounted) {\n _this2.setState({\n location: location\n });\n }\n });\n }\n\n if (this._pendingLocation) {\n this.setState({\n location: this._pendingLocation\n });\n }\n };\n\n _proto.componentWillUnmount = function componentWillUnmount() {\n if (this.unlisten) {\n this.unlisten();\n this._isMounted = false;\n this._pendingLocation = null;\n }\n };\n\n _proto.render = function render() {\n return /*#__PURE__*/React.createElement(context.Provider, {\n value: {\n history: this.props.history,\n location: this.state.location,\n match: Router.computeRootMatch(this.state.location.pathname),\n staticContext: this.props.staticContext\n }\n }, /*#__PURE__*/React.createElement(historyContext.Provider, {\n children: this.props.children || null,\n value: this.props.history\n }));\n };\n\n return Router;\n}(React.Component);\n\nif (process.env.NODE_ENV !== \"production\") {\n Router.propTypes = {\n children: PropTypes.node,\n history: PropTypes.object.isRequired,\n staticContext: PropTypes.object\n };\n\n Router.prototype.componentDidUpdate = function (prevProps) {\n process.env.NODE_ENV !== \"production\" ? warning(prevProps.history === this.props.history, \"You cannot change \") : void 0;\n };\n}\n\n/**\n * The public API for a that stores location in memory.\n */\n\nvar MemoryRouter = /*#__PURE__*/function (_React$Component) {\n _inheritsLoose(MemoryRouter, _React$Component);\n\n function MemoryRouter() {\n var _this;\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;\n _this.history = createMemoryHistory(_this.props);\n return _this;\n }\n\n var _proto = MemoryRouter.prototype;\n\n _proto.render = function render() {\n return /*#__PURE__*/React.createElement(Router, {\n history: this.history,\n children: this.props.children\n });\n };\n\n return MemoryRouter;\n}(React.Component);\n\nif (process.env.NODE_ENV !== \"production\") {\n MemoryRouter.propTypes = {\n initialEntries: PropTypes.array,\n initialIndex: PropTypes.number,\n getUserConfirmation: PropTypes.func,\n keyLength: PropTypes.number,\n children: PropTypes.node\n };\n\n MemoryRouter.prototype.componentDidMount = function () {\n process.env.NODE_ENV !== \"production\" ? warning(!this.props.history, \" ignores the history prop. To use a custom history, \" + \"use `import { Router }` instead of `import { MemoryRouter as Router }`.\") : void 0;\n };\n}\n\nvar Lifecycle = /*#__PURE__*/function (_React$Component) {\n _inheritsLoose(Lifecycle, _React$Component);\n\n function Lifecycle() {\n return _React$Component.apply(this, arguments) || this;\n }\n\n var _proto = Lifecycle.prototype;\n\n _proto.componentDidMount = function componentDidMount() {\n if (this.props.onMount) this.props.onMount.call(this, this);\n };\n\n _proto.componentDidUpdate = function componentDidUpdate(prevProps) {\n if (this.props.onUpdate) this.props.onUpdate.call(this, this, prevProps);\n };\n\n _proto.componentWillUnmount = function componentWillUnmount() {\n if (this.props.onUnmount) this.props.onUnmount.call(this, this);\n };\n\n _proto.render = function render() {\n return null;\n };\n\n return Lifecycle;\n}(React.Component);\n\n/**\n * The public API for prompting the user before navigating away from a screen.\n */\n\nfunction Prompt(_ref) {\n var message = _ref.message,\n _ref$when = _ref.when,\n when = _ref$when === void 0 ? true : _ref$when;\n return /*#__PURE__*/React.createElement(context.Consumer, null, function (context) {\n !context ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"You should not use outside a \") : invariant(false) : void 0;\n if (!when || context.staticContext) return null;\n var method = context.history.block;\n return /*#__PURE__*/React.createElement(Lifecycle, {\n onMount: function onMount(self) {\n self.release = method(message);\n },\n onUpdate: function onUpdate(self, prevProps) {\n if (prevProps.message !== message) {\n self.release();\n self.release = method(message);\n }\n },\n onUnmount: function onUnmount(self) {\n self.release();\n },\n message: message\n });\n });\n}\n\nif (process.env.NODE_ENV !== \"production\") {\n var messageType = PropTypes.oneOfType([PropTypes.func, PropTypes.string]);\n Prompt.propTypes = {\n when: PropTypes.bool,\n message: messageType.isRequired\n };\n}\n\nvar cache = {};\nvar cacheLimit = 10000;\nvar cacheCount = 0;\n\nfunction compilePath(path) {\n if (cache[path]) return cache[path];\n var generator = pathToRegexp.compile(path);\n\n if (cacheCount < cacheLimit) {\n cache[path] = generator;\n cacheCount++;\n }\n\n return generator;\n}\n/**\n * Public API for generating a URL pathname from a path and parameters.\n */\n\n\nfunction generatePath(path, params) {\n if (path === void 0) {\n path = \"/\";\n }\n\n if (params === void 0) {\n params = {};\n }\n\n return path === \"/\" ? path : compilePath(path)(params, {\n pretty: true\n });\n}\n\n/**\n * The public API for navigating programmatically with a component.\n */\n\nfunction Redirect(_ref) {\n var computedMatch = _ref.computedMatch,\n to = _ref.to,\n _ref$push = _ref.push,\n push = _ref$push === void 0 ? false : _ref$push;\n return /*#__PURE__*/React.createElement(context.Consumer, null, function (context) {\n !context ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"You should not use outside a \") : invariant(false) : void 0;\n var history = context.history,\n staticContext = context.staticContext;\n var method = push ? history.push : history.replace;\n var location = createLocation(computedMatch ? typeof to === \"string\" ? generatePath(to, computedMatch.params) : _extends({}, to, {\n pathname: generatePath(to.pathname, computedMatch.params)\n }) : to); // When rendering in a static context,\n // set the new location immediately.\n\n if (staticContext) {\n method(location);\n return null;\n }\n\n return /*#__PURE__*/React.createElement(Lifecycle, {\n onMount: function onMount() {\n method(location);\n },\n onUpdate: function onUpdate(self, prevProps) {\n var prevLocation = createLocation(prevProps.to);\n\n if (!locationsAreEqual(prevLocation, _extends({}, location, {\n key: prevLocation.key\n }))) {\n method(location);\n }\n },\n to: to\n });\n });\n}\n\nif (process.env.NODE_ENV !== \"production\") {\n Redirect.propTypes = {\n push: PropTypes.bool,\n from: PropTypes.string,\n to: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired\n };\n}\n\nvar cache$1 = {};\nvar cacheLimit$1 = 10000;\nvar cacheCount$1 = 0;\n\nfunction compilePath$1(path, options) {\n var cacheKey = \"\" + options.end + options.strict + options.sensitive;\n var pathCache = cache$1[cacheKey] || (cache$1[cacheKey] = {});\n if (pathCache[path]) return pathCache[path];\n var keys = [];\n var regexp = pathToRegexp(path, keys, options);\n var result = {\n regexp: regexp,\n keys: keys\n };\n\n if (cacheCount$1 < cacheLimit$1) {\n pathCache[path] = result;\n cacheCount$1++;\n }\n\n return result;\n}\n/**\n * Public API for matching a URL pathname to a path.\n */\n\n\nfunction matchPath(pathname, options) {\n if (options === void 0) {\n options = {};\n }\n\n if (typeof options === \"string\" || Array.isArray(options)) {\n options = {\n path: options\n };\n }\n\n var _options = options,\n path = _options.path,\n _options$exact = _options.exact,\n exact = _options$exact === void 0 ? false : _options$exact,\n _options$strict = _options.strict,\n strict = _options$strict === void 0 ? false : _options$strict,\n _options$sensitive = _options.sensitive,\n sensitive = _options$sensitive === void 0 ? false : _options$sensitive;\n var paths = [].concat(path);\n return paths.reduce(function (matched, path) {\n if (!path && path !== \"\") return null;\n if (matched) return matched;\n\n var _compilePath = compilePath$1(path, {\n end: exact,\n strict: strict,\n sensitive: sensitive\n }),\n regexp = _compilePath.regexp,\n keys = _compilePath.keys;\n\n var match = regexp.exec(pathname);\n if (!match) return null;\n var url = match[0],\n values = match.slice(1);\n var isExact = pathname === url;\n if (exact && !isExact) return null;\n return {\n path: path,\n // the path used to match\n url: path === \"/\" && url === \"\" ? \"/\" : url,\n // the matched portion of the URL\n isExact: isExact,\n // whether or not we matched exactly\n params: keys.reduce(function (memo, key, index) {\n memo[key.name] = values[index];\n return memo;\n }, {})\n };\n }, null);\n}\n\nfunction isEmptyChildren(children) {\n return React.Children.count(children) === 0;\n}\n\nfunction evalChildrenDev(children, props, path) {\n var value = children(props);\n process.env.NODE_ENV !== \"production\" ? warning(value !== undefined, \"You returned `undefined` from the `children` function of \" + (\", but you \") + \"should have returned a React element or `null`\") : void 0;\n return value || null;\n}\n/**\n * The public API for matching a single path and rendering.\n */\n\n\nvar Route = /*#__PURE__*/function (_React$Component) {\n _inheritsLoose(Route, _React$Component);\n\n function Route() {\n return _React$Component.apply(this, arguments) || this;\n }\n\n var _proto = Route.prototype;\n\n _proto.render = function render() {\n var _this = this;\n\n return /*#__PURE__*/React.createElement(context.Consumer, null, function (context$1) {\n !context$1 ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"You should not use outside a \") : invariant(false) : void 0;\n var location = _this.props.location || context$1.location;\n var match = _this.props.computedMatch ? _this.props.computedMatch // already computed the match for us\n : _this.props.path ? matchPath(location.pathname, _this.props) : context$1.match;\n\n var props = _extends({}, context$1, {\n location: location,\n match: match\n });\n\n var _this$props = _this.props,\n children = _this$props.children,\n component = _this$props.component,\n render = _this$props.render; // Preact uses an empty array as children by\n // default, so use null if that's the case.\n\n if (Array.isArray(children) && isEmptyChildren(children)) {\n children = null;\n }\n\n return /*#__PURE__*/React.createElement(context.Provider, {\n value: props\n }, props.match ? children ? typeof children === \"function\" ? process.env.NODE_ENV !== \"production\" ? evalChildrenDev(children, props, _this.props.path) : children(props) : children : component ? /*#__PURE__*/React.createElement(component, props) : render ? render(props) : null : typeof children === \"function\" ? process.env.NODE_ENV !== \"production\" ? evalChildrenDev(children, props, _this.props.path) : children(props) : null);\n });\n };\n\n return Route;\n}(React.Component);\n\nif (process.env.NODE_ENV !== \"production\") {\n Route.propTypes = {\n children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),\n component: function component(props, propName) {\n if (props[propName] && !isValidElementType(props[propName])) {\n return new Error(\"Invalid prop 'component' supplied to 'Route': the prop is not a valid React component\");\n }\n },\n exact: PropTypes.bool,\n location: PropTypes.object,\n path: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),\n render: PropTypes.func,\n sensitive: PropTypes.bool,\n strict: PropTypes.bool\n };\n\n Route.prototype.componentDidMount = function () {\n process.env.NODE_ENV !== \"production\" ? warning(!(this.props.children && !isEmptyChildren(this.props.children) && this.props.component), \"You should not use and in the same route; will be ignored\") : void 0;\n process.env.NODE_ENV !== \"production\" ? warning(!(this.props.children && !isEmptyChildren(this.props.children) && this.props.render), \"You should not use and in the same route; will be ignored\") : void 0;\n process.env.NODE_ENV !== \"production\" ? warning(!(this.props.component && this.props.render), \"You should not use and in the same route; will be ignored\") : void 0;\n };\n\n Route.prototype.componentDidUpdate = function (prevProps) {\n process.env.NODE_ENV !== \"production\" ? warning(!(this.props.location && !prevProps.location), ' elements should not change from uncontrolled to controlled (or vice versa). You initially used no \"location\" prop and then provided one on a subsequent render.') : void 0;\n process.env.NODE_ENV !== \"production\" ? warning(!(!this.props.location && prevProps.location), ' elements should not change from controlled to uncontrolled (or vice versa). You provided a \"location\" prop initially but omitted it on a subsequent render.') : void 0;\n };\n}\n\nfunction addLeadingSlash(path) {\n return path.charAt(0) === \"/\" ? path : \"/\" + path;\n}\n\nfunction addBasename(basename, location) {\n if (!basename) return location;\n return _extends({}, location, {\n pathname: addLeadingSlash(basename) + location.pathname\n });\n}\n\nfunction stripBasename(basename, location) {\n if (!basename) return location;\n var base = addLeadingSlash(basename);\n if (location.pathname.indexOf(base) !== 0) return location;\n return _extends({}, location, {\n pathname: location.pathname.substr(base.length)\n });\n}\n\nfunction createURL(location) {\n return typeof location === \"string\" ? location : createPath(location);\n}\n\nfunction staticHandler(methodName) {\n return function () {\n process.env.NODE_ENV !== \"production\" ? invariant(false, \"You cannot %s with \", methodName) : invariant(false) ;\n };\n}\n\nfunction noop() {}\n/**\n * The public top-level API for a \"static\" , so-called because it\n * can't actually change the current location. Instead, it just records\n * location changes in a context object. Useful mainly in testing and\n * server-rendering scenarios.\n */\n\n\nvar StaticRouter = /*#__PURE__*/function (_React$Component) {\n _inheritsLoose(StaticRouter, _React$Component);\n\n function StaticRouter() {\n var _this;\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;\n\n _this.handlePush = function (location) {\n return _this.navigateTo(location, \"PUSH\");\n };\n\n _this.handleReplace = function (location) {\n return _this.navigateTo(location, \"REPLACE\");\n };\n\n _this.handleListen = function () {\n return noop;\n };\n\n _this.handleBlock = function () {\n return noop;\n };\n\n return _this;\n }\n\n var _proto = StaticRouter.prototype;\n\n _proto.navigateTo = function navigateTo(location, action) {\n var _this$props = this.props,\n _this$props$basename = _this$props.basename,\n basename = _this$props$basename === void 0 ? \"\" : _this$props$basename,\n _this$props$context = _this$props.context,\n context = _this$props$context === void 0 ? {} : _this$props$context;\n context.action = action;\n context.location = addBasename(basename, createLocation(location));\n context.url = createURL(context.location);\n };\n\n _proto.render = function render() {\n var _this$props2 = this.props,\n _this$props2$basename = _this$props2.basename,\n basename = _this$props2$basename === void 0 ? \"\" : _this$props2$basename,\n _this$props2$context = _this$props2.context,\n context = _this$props2$context === void 0 ? {} : _this$props2$context,\n _this$props2$location = _this$props2.location,\n location = _this$props2$location === void 0 ? \"/\" : _this$props2$location,\n rest = _objectWithoutPropertiesLoose(_this$props2, [\"basename\", \"context\", \"location\"]);\n\n var history = {\n createHref: function createHref(path) {\n return addLeadingSlash(basename + createURL(path));\n },\n action: \"POP\",\n location: stripBasename(basename, createLocation(location)),\n push: this.handlePush,\n replace: this.handleReplace,\n go: staticHandler(\"go\"),\n goBack: staticHandler(\"goBack\"),\n goForward: staticHandler(\"goForward\"),\n listen: this.handleListen,\n block: this.handleBlock\n };\n return /*#__PURE__*/React.createElement(Router, _extends({}, rest, {\n history: history,\n staticContext: context\n }));\n };\n\n return StaticRouter;\n}(React.Component);\n\nif (process.env.NODE_ENV !== \"production\") {\n StaticRouter.propTypes = {\n basename: PropTypes.string,\n context: PropTypes.object,\n location: PropTypes.oneOfType([PropTypes.string, PropTypes.object])\n };\n\n StaticRouter.prototype.componentDidMount = function () {\n process.env.NODE_ENV !== \"production\" ? warning(!this.props.history, \" ignores the history prop. To use a custom history, \" + \"use `import { Router }` instead of `import { StaticRouter as Router }`.\") : void 0;\n };\n}\n\n/**\n * The public API for rendering the first that matches.\n */\n\nvar Switch = /*#__PURE__*/function (_React$Component) {\n _inheritsLoose(Switch, _React$Component);\n\n function Switch() {\n return _React$Component.apply(this, arguments) || this;\n }\n\n var _proto = Switch.prototype;\n\n _proto.render = function render() {\n var _this = this;\n\n return /*#__PURE__*/React.createElement(context.Consumer, null, function (context) {\n !context ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"You should not use outside a \") : invariant(false) : void 0;\n var location = _this.props.location || context.location;\n var element, match; // We use React.Children.forEach instead of React.Children.toArray().find()\n // here because toArray adds keys to all child elements and we do not want\n // to trigger an unmount/remount for two s that render the same\n // component at different URLs.\n\n React.Children.forEach(_this.props.children, function (child) {\n if (match == null && /*#__PURE__*/React.isValidElement(child)) {\n element = child;\n var path = child.props.path || child.props.from;\n match = path ? matchPath(location.pathname, _extends({}, child.props, {\n path: path\n })) : context.match;\n }\n });\n return match ? /*#__PURE__*/React.cloneElement(element, {\n location: location,\n computedMatch: match\n }) : null;\n });\n };\n\n return Switch;\n}(React.Component);\n\nif (process.env.NODE_ENV !== \"production\") {\n Switch.propTypes = {\n children: PropTypes.node,\n location: PropTypes.object\n };\n\n Switch.prototype.componentDidUpdate = function (prevProps) {\n process.env.NODE_ENV !== \"production\" ? warning(!(this.props.location && !prevProps.location), ' elements should not change from uncontrolled to controlled (or vice versa). You initially used no \"location\" prop and then provided one on a subsequent render.') : void 0;\n process.env.NODE_ENV !== \"production\" ? warning(!(!this.props.location && prevProps.location), ' elements should not change from controlled to uncontrolled (or vice versa). You provided a \"location\" prop initially but omitted it on a subsequent render.') : void 0;\n };\n}\n\n/**\n * A public higher-order component to access the imperative API\n */\n\nfunction withRouter(Component) {\n var displayName = \"withRouter(\" + (Component.displayName || Component.name) + \")\";\n\n var C = function C(props) {\n var wrappedComponentRef = props.wrappedComponentRef,\n remainingProps = _objectWithoutPropertiesLoose(props, [\"wrappedComponentRef\"]);\n\n return /*#__PURE__*/React.createElement(context.Consumer, null, function (context) {\n !context ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"You should not use <\" + displayName + \" /> outside a \") : invariant(false) : void 0;\n return /*#__PURE__*/React.createElement(Component, _extends({}, remainingProps, context, {\n ref: wrappedComponentRef\n }));\n });\n };\n\n C.displayName = displayName;\n C.WrappedComponent = Component;\n\n if (process.env.NODE_ENV !== \"production\") {\n C.propTypes = {\n wrappedComponentRef: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.object])\n };\n }\n\n return hoistStatics(C, Component);\n}\n\nvar useContext = React.useContext;\nfunction useHistory() {\n if (process.env.NODE_ENV !== \"production\") {\n !(typeof useContext === \"function\") ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"You must use React >= 16.8 in order to use useHistory()\") : invariant(false) : void 0;\n }\n\n return useContext(historyContext);\n}\nfunction useLocation() {\n if (process.env.NODE_ENV !== \"production\") {\n !(typeof useContext === \"function\") ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"You must use React >= 16.8 in order to use useLocation()\") : invariant(false) : void 0;\n }\n\n return useContext(context).location;\n}\nfunction useParams() {\n if (process.env.NODE_ENV !== \"production\") {\n !(typeof useContext === \"function\") ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"You must use React >= 16.8 in order to use useParams()\") : invariant(false) : void 0;\n }\n\n var match = useContext(context).match;\n return match ? match.params : {};\n}\nfunction useRouteMatch(path) {\n if (process.env.NODE_ENV !== \"production\") {\n !(typeof useContext === \"function\") ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"You must use React >= 16.8 in order to use useRouteMatch()\") : invariant(false) : void 0;\n }\n\n var location = useLocation();\n var match = useContext(context).match;\n return path ? matchPath(location.pathname, path) : match;\n}\n\nif (process.env.NODE_ENV !== \"production\") {\n if (typeof window !== \"undefined\") {\n var global$1 = window;\n var key = \"__react_router_build__\";\n var buildNames = {\n cjs: \"CommonJS\",\n esm: \"ES modules\",\n umd: \"UMD\"\n };\n\n if (global$1[key] && global$1[key] !== \"esm\") {\n var initialBuildName = buildNames[global$1[key]];\n var secondaryBuildName = buildNames[\"esm\"]; // TODO: Add link to article that explains in detail how to avoid\n // loading 2 different builds.\n\n throw new Error(\"You are loading the \" + secondaryBuildName + \" build of React Router \" + (\"on a page that is already running the \" + initialBuildName + \" \") + \"build, so things won't work right.\");\n }\n\n global$1[key] = \"esm\";\n }\n}\n\nexport { MemoryRouter, Prompt, Redirect, Route, Router, StaticRouter, Switch, historyContext as __HistoryContext, context as __RouterContext, generatePath, matchPath, useHistory, useLocation, useParams, useRouteMatch, withRouter };\n//# sourceMappingURL=react-router.js.map\n","/* eslint-disable import/prefer-default-export */\n\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\nimport { appendWithStoreCode } from 'Util/Url';\n\nexport const SHIPPING_STEP = 'SHIPPING_STEP';\nexport const BILLING_STEP = 'BILLING_STEP';\nexport const DETAILS_STEP = 'DETAILS_STEP';\n\nexport const PAYMENT_TOTALS = 'PAYMENT_TOTALS';\nexport const ORDER_ID_KEY = 'ORDER_ID';\nexport const SHIPPING_ADDRESS_KEY = 'SHIPPING_ADDRESS';\nexport const BILLING_ADDRESS_KEY = 'BILLING_ADDRESS';\nexport const PAYMENT_METHOD_KEY = 'PAYMENT_METHOD';\nexport const PAYMENT_METHOD_CODE_KEY = 'PAYMENT_METHOD_CODE';\n\nexport const CHECKOUT_URL = '/checkout';\nexport const BILLING_URL = '/checkout/billing';\nexport const SHIPPING_URL = '/checkout/shipping';\nexport const SUCCESS_URL = '/checkout/success';\n\nexport const UPDATE_EMAIL_CHECK_FREQUENCY = 1500;\n\nexport const TEMP_GUEST_ADDRESS_DATA = 'TEMP_GUEST_ADDRESS_DATA';\nexport const TEMP_GUEST_EMAIL = 'TEMP_GUEST_EMAIL';\nexport const ONE_DAY_IN_SECONDS = 86400;\n\nexport const BILLING_URL_STEP = 'billing';\nexport const SHIPPING_URL_STEP = 'shipping';\nexport const DETAILS_URL_STEP = 'success';\n\nexport const EXPRESS_METHOD_ORDER_ID = 'EXPRESS_METHOD_ORDER_ID';\n\nexport const CHECKOUT_URL_REGEX = new RegExp(`^(${appendWithStoreCode('')})?${CHECKOUT_URL}(/)?$`);\nexport const RECOMMENDER_CHECKOUT_PAGE_ID = 'checkout1';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport { default } from './Field.container';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport const GRAPHQL_AUTH = 'graphql-authentication';\nexport * from './Token';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport * from './Price';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\n// TODO: maybe consider moving to IndexedDB insead of localStorage\n\n/**\n * Set of helpers related to Browser Database\n * @class CSS\n * @namespace Scandipwa/Util/BrowserDatabase */\nexport class BrowserDatabase {\n /**\n * Loads data from browser storage\n * @param {String} location Name of the local storage\n * @return {Object} Object stored in a specified path\n * @memberof BrowserDatabase\n */\n getItem(location) {\n try {\n const entryObject = JSON.parse(localStorage.getItem(location));\n const { data, expiration, createdAt } = entryObject;\n const MILLISECONDS_TO_SECONDS = 1000;\n\n if (expiration && Date.now() - createdAt > expiration * MILLISECONDS_TO_SECONDS) {\n localStorage.removeItem(location);\n return null;\n }\n\n return data || entryObject;\n } catch {\n return null;\n }\n }\n\n /**\n * Save data to local storage\n * @param {Any} data The value to save to local storage\n * @param {String} location Name of the local storage\n * @param {Number} expiration Time to store entry (in seconds)\n * @return {Void}\n * @memberof BrowserDatabase\n */\n setItem(data, location, expiration = null) {\n localStorage.setItem(location, JSON.stringify({\n data,\n expiration,\n createdAt: Date.now()\n }));\n }\n\n /**\n * Delete item from local storage\n * @param {String} location\n * @memberof BrowserDatabase\n */\n deleteItem(location) {\n localStorage.removeItem(location);\n }\n\n /**\n * Loads data from browser session storage\n * @param {String} location Name of the local storage\n * @return {Object} Object stored in a specified path\n * @memberof BrowserDatabase\n */\n getInclTax(location) {\n try {\n const entryObject = JSON.parse(localStorage.getItem(location));\n const { data, expiration, createdAt } = entryObject;\n const MILLISECONDS_TO_SECONDS = 1000;\n\n if (expiration && Date.now() - createdAt > expiration * MILLISECONDS_TO_SECONDS) {\n localStorage.removeItem(location);\n return null;\n }\n\n return data;\n } catch {\n return null;\n }\n }\n\n /**\n * Loads data from browser session storage\n * @param {String} location Name of the local storage\n * @return {Object} Object stored in a specified path\n * @memberof BrowserDatabase\n */\n getSessionItem(location) {\n try {\n const entryObject = JSON.parse(sessionStorage.getItem(location));\n const { data, expiration, createdAt } = entryObject;\n const MILLISECONDS_TO_SECONDS = 1000;\n\n if (expiration && Date.now() - createdAt > expiration * MILLISECONDS_TO_SECONDS) {\n sessionStorage.removeItem(location);\n return null;\n }\n\n return data || entryObject;\n } catch {\n return null;\n }\n }\n\n /**\n * Save data to session storage\n * @param {Any} data The value to save to local storage\n * @param {String} location Name of the local storage\n * @param {Number} expiration Time to store entry (in seconds)\n * @return {Void}\n * @memberof BrowserDatabase\n */\n setSessionItem(data, location, expiration) {\n sessionStorage.setItem(location, JSON.stringify({\n data,\n expiration,\n createdAt: Date.now()\n }));\n }\n\n /**\n * Delete item from session storage\n * @param {String} location\n * @memberof BrowserDatabase\n */\n deleteSessionItem(location) {\n sessionStorage.removeItem(location);\n }\n}\n\nexport default new BrowserDatabase();\n","/**\n * Adyen Payments compatibility for ScandiPWA\n * @copyright Scandiweb, Inc. All rights reserved.\n */\n\nexport const ADYEN_PAYMENTS_ID = 'ADYEN_PAYMENTS_ID';\n\n// vvv Adyen Payment method codes\nexport const ADYEN_GC_METHOD_CODE = 'giftcard';\nexport const ADYEN_CC_METHOD_CODE = 'adyen_cc';\nexport const ADYEN_HPP_METHOD_CODE = 'adyen_hpp';\nexport const ADYEN_BOLETO_METHOD_CODE = 'adyen_boleto';\nexport const ADYEN_CC_VAULT_METHOD_CODE = 'adyen_cc_vault';\nexport const ADYEN_ONECLICK_METHOD_CODE = 'adyen_oneclick';\nexport const ADYEN_POS_CLOUD_METHOD_CODE = 'adyen_pos_cloud';\nexport const ADYEN_GOOGLE_PAY_METHOD_CODE = 'adyen_googlepay';\nexport const ADYEN_APPLE_PAY_METHOD_CODE = 'adyen_applepay';\n\n// vvv Adyen HPP payment types\nexport const ADYEN_CARD_PAYMENT_TYPE = 'card';\nexport const ADYEN_SCHEME_PAYMENT_TYPE = 'scheme';\nexport const ADYEN_PAYPAL_PAYMENT_TYPE = 'paypal';\nexport const ADYEN_APPLE_PAY_PAYMENT_TYPE = 'applepay';\nexport const ADYEN_GOOGLE_PAY_PAYMENT_TYPE = 'googlepay';\nexport const ADYEN_AMAZON_PAY_PAYMENT_TYPE = 'amazonpay';\n\n// vvv ThreeDS2\nexport const THREE_DS2_POPUP_ID = 'three-ds2-popup';\nexport const THREE_DS2_DIV_ID = 'adyen-checkout-threeds2-popup';\n\n/** @namespace Scandiweb/AdyenPayments/Util/Adyen/getCheckoutEnvironment */\nexport const getCheckoutEnvironment = (isDemoMode) => (isDemoMode ? 'test' : 'live');\n\n/** @namespace Scandiweb/AdyenPayments/Util/Adyen/formatAdyenPayementExtraDetails */\nexport const formatAdyenPayementExtraDetails = (paymentMethodsExtraDetails) => paymentMethodsExtraDetails\n .reduce((acc, paymentInfo) => {\n const { type } = paymentInfo;\n\n return { ...acc, [type]: paymentInfo };\n }, {});\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport const PRODUCT_TYPE = {\n configurable: 'configurable',\n grouped: 'grouped',\n simple: 'simple',\n bundle: 'bundle',\n downloadable: 'downloadable',\n virtual: 'virtual'\n};\n\nexport default PRODUCT_TYPE;\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nimport PropTypes from 'prop-types';\n\nexport const ModsType = PropTypes.objectOf(PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.bool\n]));\n\nexport const MixType = PropTypes.shape({\n block: PropTypes.string,\n elem: PropTypes.string,\n mods: ModsType\n});\n\nMixType.mix = MixType;\n\nexport const ChildrenType = PropTypes.oneOfType([\n PropTypes.arrayOf(PropTypes.node),\n PropTypes.node\n]);\n\nexport const RefType = PropTypes.oneOfType([\n PropTypes.func,\n PropTypes.shape({ current: PropTypes.instanceOf(Element) })\n]);\n\nexport const MetaTitleType = PropTypes.oneOfType([PropTypes.string, PropTypes.object]);\n","/* eslint-disable import/prefer-default-export */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\n/**\n * No-operate function.\n * Can be used as a fallback if real function wasn't passed.\n * In this case instead of creating empty function every time we can reuse existing.\n * Examples: default props, argument default values.\n * @namespace Util/Common/Index/noopFn\n */\nexport const noopFn = () => {};\n\n/** @namespace Util/Common/Index/decodeString */\nexport const decodeString = (string) => {\n try {\n return decodeURIComponent(string);\n } catch (e) {\n return string;\n }\n};\n","/* eslint-disable spaced-comment */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nimport { PRODUCT_TYPE } from 'Component/Product/Product.config';\nimport { STOCK_TYPE } from 'Component/Product/Stock.config';\nimport { formatPrice } from 'Util/Price';\n\nexport const DEFAULT_MIN_PRODUCTS = 1;\nexport const DEFAULT_MAX_PRODUCTS = 999;\n\nexport const MIN_SALE_QTY = 'min_sale_qty';\nexport const MAX_SALE_QTY = 'max_sale_qty';\nexport const SALABLE_QTY = 'salable_qty';\n\n/** @namespace Util/Product/Extract/getFieldQty */\nexport const getFieldQty = (product, field) => {\n if (field === MIN_SALE_QTY || field === MAX_SALE_QTY) {\n const { stock_item: { [field]: qty } = {} } = product;\n\n return qty;\n }\n\n const { [field]: qty } = product;\n\n return qty;\n};\n\n/**\n * Returns product quantity for specific field (with fallback value)\n * @param product\n * @param defaultValue\n * @param field\n * @param configIndex\n * @returns {*}\n * @namespace Util/Product/Extract/getQuantity\n */\nexport const getQuantity = (product, defaultValue, field, configIndex = -1) => {\n if (!product) {\n return defaultValue;\n }\n\n const qty = getFieldQty(product, field);\n\n if (!qty) {\n return defaultValue;\n }\n\n const { variants } = product;\n\n if ((!configIndex && !variants) || configIndex === -1) {\n return qty;\n }\n\n const variantQty = getFieldQty(variants[configIndex] || {}, field);\n\n return variantQty || qty;\n};\n\n/**\n * Returns minimum purchasable item quantity\n * @param product\n * @param configIndex\n * @returns {*}\n * @namespace Util/Product/Extract/getMinQuantity\n */\nexport const getMinQuantity = (product, configIndex = -1) => (\n getQuantity(product, DEFAULT_MIN_PRODUCTS, MIN_SALE_QTY, configIndex)\n);\n\n/**\n * Returns maximum purchasable item quantity.\n * @param product\n * @param configIndex\n * @returns {*}\n * @namespace Util/Product/Extract/getMaxQuantity\n */\nexport const getMaxQuantity = (product, configIndex = -1) => {\n const maxQuantity = getQuantity(product, DEFAULT_MAX_PRODUCTS, MAX_SALE_QTY, configIndex);\n const salableQuantity = getQuantity(product, DEFAULT_MAX_PRODUCTS, SALABLE_QTY, configIndex);\n\n return Math.min(maxQuantity, salableQuantity);\n};\n\n/**\n * Returns active products name\n * @param product\n * @param configIndex\n * @returns {*}\n * @namespace Util/Product/Extract/getName\n */\nexport const getName = (product, configIndex = -1) => {\n const { variants = [] } = product;\n\n const {\n name = ''\n } = variants[configIndex] || product;\n\n return name;\n};\n\n/**\n * Returns whether or not product is in stock (true if in stock | false if out of stock)\n * @param product\n * @param parentProduct\n * @returns {boolean}\n * @namespace Util/Product/Extract/getProductInStock\n */\nexport const getProductInStock = (product, parentProduct = {}) => {\n if (!product) {\n return false;\n }\n\n const {\n type_id: type,\n variants = [],\n items = [],\n stock_item: {\n in_stock: inStock = true\n } = {}\n } = product;\n\n if (type === PRODUCT_TYPE.bundle) {\n const { items = [] } = product;\n const requiredItems = items.filter(({ required }) => required);\n const requiredItemsInStock = requiredItems.filter(\n ({ options }) => options.some(({ product }) => getProductInStock(product))\n );\n\n return inStock && requiredItemsInStock.length === requiredItems.length;\n }\n\n if (type === PRODUCT_TYPE.configurable && parentProduct === product) {\n return inStock && !!variants.some((variant) => getProductInStock(variant, product));\n }\n\n const { type_id: parentTypeId = false } = parentProduct;\n\n if (parentTypeId === PRODUCT_TYPE.configurable && parentProduct !== product) {\n const {\n stock_item: {\n in_stock: parentInStock = true\n } = {},\n stock_status: parentStockStatus\n } = parentProduct;\n\n return parentInStock && parentStockStatus !== STOCK_TYPE.OUT_OF_STOCK && getProductInStock(product);\n }\n\n if (type === PRODUCT_TYPE.grouped) {\n return inStock && !!items.some(({ product }) => getProductInStock(product));\n }\n\n const { stock_status: stockStatus } = product;\n\n return stockStatus !== STOCK_TYPE.OUT_OF_STOCK && (inStock || stockStatus === STOCK_TYPE.IN_STOCK);\n};\n\n/**\n * Checks if items in Grouped Product are in stock\n * @param product: productGroup\n * @param products: products in stock\n * @namespace Util/Product/Extract/getGroupedProductsInStockQuantity */\n\nexport const getGroupedProductsInStockQuantity = ({ items = [] }) => items.reduce((acc, {\n product, product: { id }, qty = 1\n}) => (getProductInStock(product) ? { ...acc, [id]: qty } : acc), {});\n\n/**\n * Checks if bundle option exist in options (ignoring quantity)\n * @param uid\n * @param options\n * @namespace Util/Product/Extract/getBundleOption\n */\nexport const getBundleOption = (uid, options = []) => {\n const uidParts = atob(uid).split('/');\n\n return options.find(({ uid: linkedUid }) => {\n const linkedUidParts = atob(linkedUid).split('/');\n\n if (uidParts.length !== linkedUidParts.length) {\n return false;\n }\n\n // eslint-disable-next-line fp/no-loops,fp/no-let\n for (let i = 0; i < uidParts.length - 1; i++) {\n if (uidParts[i] !== linkedUidParts[i]) {\n return false;\n }\n }\n\n return true;\n });\n};\n\n/**\n * Returns price object for product.\n * @param priceRange\n * @param dynamicPrice\n * @param adjustedPrice\n * @param type\n * @param options\n * @returns {{originalPrice: {maxFinalPriceExclTax: {valueFormatted: string}, minFinalPrice: {valueFormatted: string}, minFinalPriceExclTax: {valueFormatted: string}, maxFinalPrice: {valueFormatted: string}}, price: {originalPriceExclTax: {currency: string, value: (number|number)}, originalPrice: {currency: string, value: (number|number)}, finalPriceExclTax: {currency: string, value: (number|number)}, finalPrice: {currency: string, value: (number|number)}, discount: {percentOff: number}}}}\n * @namespace Util/Product/Extract/getPrice\n */\nexport const getPrice = (\n priceRange,\n dynamicPrice = false,\n adjustedPrice = {},\n type = PRODUCT_TYPE.simple,\n options = []\n) => {\n const priceAcc = type === PRODUCT_TYPE.bundle\n ? 'default_final_price'\n : 'regular_price';\n const priceExcTaxAcc = type === PRODUCT_TYPE.bundle || type === PRODUCT_TYPE.configurable\n ? 'default_final_price_excl_tax'\n : 'regular_price_excl_tax';\n const accessRange = type === PRODUCT_TYPE.virtual || type === PRODUCT_TYPE.downloadable\n ? 'maximum_price'\n : 'minimum_price';\n\n const {\n [accessRange]: {\n [priceAcc]: { currency = 'USD', value: basePrice = 0 } = {},\n [priceExcTaxAcc]: { value: basePriceExclTax = 0 } = {},\n discount: {\n percent_off: percentOffRef = 0,\n amount_off: amountOff = 0\n } = {}\n } = {},\n minimum_price: {\n regular_price: minRegularPrice = {},\n final_price: minFinalPrice = {},\n final_price_excl_tax: minFinalPriceExclTax = {}\n } = {},\n maximum_price: {\n regular_price: maxRegularPrice = {},\n final_price: maxFinalPrice = {},\n final_price_excl_tax: maxFinalPriceExclTax = {}\n } = {}\n } = priceRange || {};\n\n // Fixes decimal misplacement for discount\n // eslint-disable-next-line no-magic-numbers\n const percentOffCalc = (amountOff / basePrice) * 100;\n // eslint-disable-next-line no-magic-numbers\n const percentOff = Math.round(percentOffCalc * 100) / 100 === percentOffRef\n ? percentOffCalc\n : percentOffRef;\n\n // eslint-disable-next-line no-magic-numbers\n const discountValue = (1 - percentOff / 100);\n // eslint-disable-next-line no-magic-numbers\n const discountValueRevert = discountValue === 0 ? 1 : discountValue;\n\n const basePriceExclDiscount = priceAcc === 'default_final_price'\n ? basePrice / discountValueRevert\n : basePrice;\n const basePriceExclDiscountExclTax = priceAcc === 'default_final_price'\n ? basePriceExclTax / discountValueRevert\n : basePriceExclTax;\n\n const priceValue = { value: dynamicPrice ? 0 : basePriceExclDiscount * discountValue, currency };\n const priceValueExclTax = { value: dynamicPrice ? 0 : basePriceExclDiscountExclTax * discountValue, currency };\n const priceValueExclDiscount = { value: dynamicPrice ? 0 : basePriceExclDiscount, currency };\n const priceValueExclDiscountExclTax = { value: dynamicPrice ? 0 : basePriceExclDiscountExclTax, currency };\n\n // Adds adjusted price\n Object.keys(adjustedPrice || {}).forEach((key) => {\n const { [key]: group } = adjustedPrice;\n const {\n inclTax = 0,\n exclTax = 0,\n requiresDiscountCalculations = true,\n hasDiscountCalculated = false\n } = group;\n\n if (requiresDiscountCalculations) {\n if (hasDiscountCalculated) {\n priceValue.value += inclTax;\n priceValueExclTax.value += exclTax;\n priceValueExclDiscount.value += inclTax / discountValueRevert;\n priceValueExclDiscountExclTax.value += exclTax / discountValueRevert;\n } else {\n priceValue.value += inclTax * discountValue;\n priceValueExclTax.value += exclTax * discountValue;\n priceValueExclDiscount.value += inclTax;\n priceValueExclDiscountExclTax.value += exclTax;\n }\n } else {\n priceValue.value += inclTax;\n priceValueExclTax.value += exclTax;\n priceValueExclDiscount.value += inclTax;\n priceValueExclDiscountExclTax.value += exclTax;\n }\n });\n\n // Adds formatted price option\n priceValue.valueFormatted = formatPrice(priceValue.value, currency);\n priceValueExclTax.valueFormatted = formatPrice(priceValueExclTax.value, currency);\n priceValueExclDiscount.valueFormatted = formatPrice(priceValueExclDiscount.value, currency);\n priceValueExclDiscountExclTax.valueFormatted = formatPrice(priceValueExclDiscountExclTax.value, currency);\n\n const configuration = {\n containsOptions: options && !!options.length,\n containsOptionsWithPrice: false,\n containsRequiredOptions: false,\n containsRequiredOptionsWithPrice: false\n };\n\n if (options) {\n configuration.containsOptionsWithPrice = !!options.find(\n ({ value = [] }) => Array.isArray(value) && value.find(({ price }) => price)\n );\n const requiredOptions = options.filter(({ required }) => required);\n\n configuration.containsRequiredOptions = !!requiredOptions.length;\n\n if (requiredOptions.length) {\n configuration.containsRequiredOptionsWithPrice = !!requiredOptions.find(\n ({ value = [] }) => Array.isArray(value) && value.find(({ price }) => price)\n );\n }\n }\n\n return {\n price: {\n finalPrice: priceValue,\n finalPriceExclTax: priceValueExclTax,\n originalPrice: priceValueExclDiscount,\n originalPriceExclTax: priceValueExclDiscountExclTax,\n discount: {\n percentOff\n }\n },\n originalPrice: {\n minRegularPrice: {\n ...minRegularPrice,\n valueFormatted: formatPrice(minRegularPrice.value || 0, currency)\n },\n minFinalPrice: {\n ...minFinalPrice,\n valueFormatted: formatPrice(minFinalPrice.value || 0, currency)\n },\n minFinalPriceExclTax: {\n ...minFinalPriceExclTax,\n valueFormatted: formatPrice(minFinalPriceExclTax.value || 0, currency)\n },\n maxRegularPrice: {\n ...maxRegularPrice,\n valueFormatted: formatPrice(maxRegularPrice.value || 0, currency)\n },\n maxFinalPrice: {\n ...maxFinalPrice,\n valueFormatted: formatPrice(maxFinalPrice.value || 0, currency)\n },\n maxFinalPriceExclTax: {\n ...maxFinalPriceExclTax,\n valueFormatted: formatPrice(maxFinalPriceExclTax.value || 0, currency)\n }\n },\n configuration\n };\n};\n\n/**\n * Generates adjusted price from entered product options\n *\n * @param product\n * @param downloadableLinks\n * @param enteredOptions\n * @param selectedOptions\n * @namespace Util/Product/Extract/getAdjustedPrice\n */\nexport const getAdjustedPrice = (product, downloadableLinks, enteredOptions, selectedOptions) => {\n const {\n downloadable_product_links = [],\n options = [],\n items = [],\n dynamic_price: dynamicPrice = false,\n type_id: typeId\n } = product;\n\n const adjustedPrice = {\n downloadable: {\n exclTax: 0,\n inclTax: 0,\n requiresDiscountCalculations: true,\n hasDiscountCalculated: false\n },\n bundle: {\n exclTax: 0,\n inclTax: 0,\n requiresDiscountCalculations: true,\n hasDiscountCalculated: true\n },\n config: {\n exclTax: 0,\n inclTax: 0,\n requiresDiscountCalculations: false\n }\n };\n\n //#region DOWNLOADABLE\n if (typeId === PRODUCT_TYPE.downloadable) {\n downloadableLinks.forEach((uid) => {\n const link = downloadable_product_links.find(({ uid: linkUid }) => linkUid === uid);\n\n if (link) {\n const { price } = link;\n\n adjustedPrice.downloadable.exclTax += price;\n adjustedPrice.downloadable.inclTax += price;\n }\n });\n }\n //#endregion\n\n //#region BUNDLE\n if (typeId === PRODUCT_TYPE.bundle) {\n selectedOptions.forEach((uid) => {\n items.forEach(({ options = [] }) => {\n const uidParts = atob(uid).split('/');\n const option = Array.isArray(options) && getBundleOption(uid, options);\n const quantity = +uidParts[uidParts.length - 1];\n\n if (option) {\n const {\n finalOptionPrice,\n finalOptionPriceExclTax,\n product: {\n price_range: optionProductPriceRange = {},\n type_id: optionProductType,\n dynamic_price: optionProductDynamic\n },\n can_change_quantity: canChangeQuantity = false\n } = option;\n\n if (!dynamicPrice) {\n const multiplier = canChangeQuantity ? quantity : quantity;\n\n adjustedPrice.bundle.exclTax += finalOptionPriceExclTax * multiplier;\n adjustedPrice.bundle.inclTax += finalOptionPrice * multiplier;\n } else {\n const {\n price: {\n finalPrice: { value: priceInclTax = 0 } = {},\n finalPriceExclTax: { value: priceExclTax = 0 } = {}\n }\n } = getPrice(\n optionProductPriceRange, optionProductDynamic, {}, optionProductType\n ) || {};\n\n adjustedPrice.bundle.inclTax += priceInclTax * quantity;\n adjustedPrice.bundle.exclTax += priceExclTax * quantity;\n }\n }\n });\n });\n }\n //#endregion\n\n //#region CONFIGURABLE\n enteredOptions.forEach(({ uid }) => {\n const option = options.find(({ uid: linkUid }) => linkUid === uid);\n\n if (option) {\n const { value: { priceExclTax = 0, priceInclTax = 0 } = {} } = option;\n\n adjustedPrice.config.inclTax += priceInclTax;\n adjustedPrice.config.exclTax += priceExclTax;\n }\n });\n\n selectedOptions.forEach((uid) => {\n options.forEach(({ value = [] }) => {\n const option = Array.isArray(value) && value.find(({ uid: linkedUid }) => linkedUid === uid);\n\n if (option) {\n const { priceExclTax = 0, priceInclTax = 0 } = option;\n\n adjustedPrice.config.inclTax += priceInclTax;\n adjustedPrice.config.exclTax += priceExclTax;\n }\n });\n });\n //#endregion\n\n return adjustedPrice;\n};\n\n//#region SubLabel\n/**\n * Returns ProductCustomizable Text/TextArea Option Sublabel based on Maximum characters setup in BE\n * @param maxCharacters\n * @param value\n * @namespace Util/Product/Extract/getSubLabelFromMaxCharacters\n */\nexport const getSubLabelFromMaxCharacters = (maxCharacters, value = '') => {\n const valueLength = value.length;\n const remainingCharacters = maxCharacters - valueLength;\n\n if (maxCharacters > 0) {\n if (valueLength > 0 && valueLength <= maxCharacters) {\n return __('Maximum %s characters (%s remaining)', maxCharacters, remainingCharacters);\n }\n\n if (valueLength >= maxCharacters) {\n return null;\n }\n\n return __('Maximum %s characters', maxCharacters);\n }\n\n return null;\n};\n//#endregion\n\n//#region IMAGE\n/**\n * Returns product image based on variable field, on fail placeholder\n * @param product\n * @param field\n * @namespace Util/Product/Extract/getImage\n */\nexport const getImage = (product, field) => {\n const { [field]: { url = 'no_selection' } = {} } = product;\n\n return url && url !== 'no_selection' ? url : '';\n};\n\n/**\n * Returns products thumbnail image\n * @param product\n * @namespace Util/Product/Extract/getThumbnailImage\n */\nexport const getThumbnailImage = (product) => getImage(product, 'thumbnail');\n\n/**\n * Returns products small image\n * @param product\n * @namespace Util/Product/Extract/getSmallImage\n */\nexport const getSmallImage = (product) => getImage(product, 'small_image');\n\n/**\n * Returns products base image\n * @param product\n * @namespace Util/Product/Extract/getBaseImage\n */\nexport const getBaseImage = (product) => getImage(product, 'image');\n//#endregion\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport * from './Url';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nimport { createBrowserHistory } from 'history';\n\nexport const history = createBrowserHistory({ basename: '/' });\nexport default history;\n","/* eslint-disable no-param-reassign */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n*/\nimport { combineReducers, createStore } from 'redux';\n\n/**\n * Configure the store\n * @namespace Util/Store/Index/configureStore\n */\nexport function configureStore(store) {\n // Add a dictionary to keep track of the registered async reducers\n store.asyncReducers = {};\n\n // Create an inject reducer function\n // This function adds the async reducer, and creates a new combined reducer\n store.injectReducer = (key, asyncReducer) => {\n store.asyncReducers[key] = asyncReducer;\n store.replaceReducer(combineReducers(store.asyncReducers));\n };\n\n // Return the modified store\n return store;\n}\n\n/** @namespace Util/Store/Index/noopReducer */\nexport const noopReducer = (state) => state;\n\nexport const getStore = (() => {\n // Initialize the store\n const store = configureStore(createStore(\n noopReducer,\n ( // enable Redux dev-tools only in development\n process.env.NODE_ENV === 'development'\n && window.__REDUX_DEVTOOLS_EXTENSION__\n ) && window.__REDUX_DEVTOOLS_EXTENSION__({\n trace: true\n })\n ));\n\n return function storeGetter() {\n return store;\n };\n})();\n\nexport default getStore;\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport { default } from './isMobile';\nexport * from './isMobile';\n","/* eslint-disable max-len */\nimport { VALIDATION_INPUT_TYPE } from 'SourceUtil/Validator/Config';\n\nexport * from 'SourceUtil/Validator/Config';\n\nexport const VALIDATION_MESSAGES = {\n // #region VALIDATION RULE MSG\n isRequired: __('This field is required!'),\n match: __('Incorrect input!'),\n range: __('Value is out of range!'), // Range values are also in Validator.js as they require args\n group: __('Field contains issues!'),\n fileExtension: __('Incorrect File extension upload!'),\n // #endregion\n\n // #region VALIDATION RULE MSG\n [VALIDATION_INPUT_TYPE.alpha]: __('Incorrect input! Only letters allowed!'),\n [VALIDATION_INPUT_TYPE.alphaSpace]: __('Incorrect input! Only words allowed!'),\n [VALIDATION_INPUT_TYPE.alphaNumeric]: __('Incorrect input! Alpha-Numeric value required!'),\n [VALIDATION_INPUT_TYPE.alphaDash]: __('Incorrect input! Alpha-Dash value required!'),\n [VALIDATION_INPUT_TYPE.url]: __('Incorrect input! URL required!'),\n [VALIDATION_INPUT_TYPE.numeric]: __('Incorrect input! Numeric value required!'),\n [VALIDATION_INPUT_TYPE.numericDash]: __('Incorrect input! Numeric-Dash value required!'),\n [VALIDATION_INPUT_TYPE.integer]: __('Incorrect input! Integer required!'),\n [VALIDATION_INPUT_TYPE.natural]: __('Incorrect input! Natural number required!'),\n [VALIDATION_INPUT_TYPE.naturalNoZero]: __('Incorrect input!'),\n [VALIDATION_INPUT_TYPE.email]: __('Please enter a valid email address'),\n [VALIDATION_INPUT_TYPE.emailList]: __('Incorrect list of emails!'),\n [VALIDATION_INPUT_TYPE.date]: __('Incorrect date input!'),\n [VALIDATION_INPUT_TYPE.password]: __('Incorrect password input!'),\n [VALIDATION_INPUT_TYPE.phone]: __('Incorrect phone input!')\n // #endregion\n};\n\nexport const VALIDATION_RULES = {\n // Text\n [VALIDATION_INPUT_TYPE.alpha]: /^[a-z]+$/i,\n [VALIDATION_INPUT_TYPE.alphaSpace]: /^[a-z\\s]+$/i,\n [VALIDATION_INPUT_TYPE.alphaNumeric]: /^[a-z0-9]+$/i,\n [VALIDATION_INPUT_TYPE.alphaDash]: /^[a-z0-9_\\\\-]+$/i,\n [VALIDATION_INPUT_TYPE.url]: /^((http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)|)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\\\/]))?$/,\n\n // Numbers\n [VALIDATION_INPUT_TYPE.numeric]: /^[0-9]+$/,\n [VALIDATION_INPUT_TYPE.numericDash]: /^[\\d\\-\\s]+$/,\n [VALIDATION_INPUT_TYPE.integer]: /^\\\\-?[0-9]+$/,\n [VALIDATION_INPUT_TYPE.decimal]: /^\\\\-?[0-9]*\\.?[0-9]+$/,\n [VALIDATION_INPUT_TYPE.natural]: /^[0-9]+$/i,\n [VALIDATION_INPUT_TYPE.naturalNoZero]: /^[1-9][0-9]*$/i,\n\n // Inputs\n [VALIDATION_INPUT_TYPE.email]: /^(([^<>()\\\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z0-9]{2,}))$/,\n [VALIDATION_INPUT_TYPE.date]: /\\d{4}-\\d{1,2}-\\d{1,2}/,\n [VALIDATION_INPUT_TYPE.phone]: /^[\\\\+]?[(]?[0-9]{3}[)]?[-\\s\\\\.]?[0-9]{3}[-\\s\\\\.]?[0-9]{4,6}$/im,\n [VALIDATION_INPUT_TYPE.emailList]: /^(([a-zA-Z0-9_\\\\-\\\\.]+)@([a-zA-Z0-9_\\\\-\\\\.]+)\\.([a-zA-Z]{2,5}){1,25})+([,\\s]+(([a-zA-Z0-9_\\\\-\\\\.]+)@([a-zA-Z0-9_\\\\-\\\\.]+)\\.([a-zA-Z]{2,5}){1,25})+)*$/\n};\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport * from './Cart';\nexport * from './Token';\n","import objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nexport default function _objectWithoutProperties(source, excluded) {\n if (source == null) return {};\n var target = objectWithoutPropertiesLoose(source, excluded);\n var key, i;\n\n if (Object.getOwnPropertySymbols) {\n var sourceSymbolKeys = Object.getOwnPropertySymbols(source);\n\n for (i = 0; i < sourceSymbolKeys.length; i++) {\n key = sourceSymbolKeys[i];\n if (excluded.indexOf(key) >= 0) continue;\n if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;\n target[key] = source[key];\n }\n }\n\n return target;\n}","export default function _objectWithoutPropertiesLoose(source, excluded) {\n if (source == null) return {};\n var target = {};\n var sourceKeys = Object.keys(source);\n var key, i;\n\n for (i = 0; i < sourceKeys.length; i++) {\n key = sourceKeys[i];\n if (excluded.indexOf(key) >= 0) continue;\n target[key] = source[key];\n }\n\n return target;\n}","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport * from './Product';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport { default } from './isArabic';\nexport * from './isArabic';\n","export const SHOW_VAT_NUMBER_REQUIRED = 'req';\nexport const SHOW_VAT_NUMBER_OPTIONAL = 'opt';\nexport const CONFIRMATION_REQUIRED = 'confirmation_required';\n// new configs\nexport const REGISTER_EMAIL_ID = 'register-email';\nexport const REGISTER_CONFIRM_EMAIL_ID = 'register-confirm-email';\nexport const REGISTER_PASSWORD_ID = 'register-password';\nexport const REGISTER_CONFIRM_PASSWORD_ID = 'register-confirm-password';\nexport const REGISTER_FIRSTNAME_ID = 'register-firstname';\nexport const REGISTER_LASTNAME_ID = 'register-lastname';\nexport const REGISTER_SUBSCRIBE_ID = 'register-is_subscribed';\nexport const ARABIC_LOCALE = 'ar_SA';\nexport const ENGLISH_LOCALE = 'en_US';\n","/**\n * @author Vladislavs Zimnikovs \n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package puma-mx\n */\n\n/**\n * Event list\n */\nexport const EVENT_GENERAL = 'general';\nexport const EVENT_IMPRESSION = 'productImpression';\nexport const EVENT_PRODUCT_CLICK = 'productClick';\nexport const EVENT_ADD_TO_CART = 'addToCart';\nexport const EVENT_REMOVE_FROM_CART = 'removeFromCart';\nexport const EVENT_PRODUCT_DETAIL = 'productDetail';\nexport const EVENT_PURCHASE = 'purchase';\nexport const EVENT_CHECKOUT = 'checkout';\nexport const EVENT_CHECKOUT_OPTION = 'checkoutOption';\nexport const EVENT_USER_REGISTER = 'userRegister';\nexport const EVENT_USER_LOGIN = 'userLogin';\nexport const EVENT_NOT_FOUND = 'notFound';\nexport const EVENT_CATEGORY_FILTERS = 'categoryFilters';\nexport const EVENT_ADDITIONAL = 'additional';\nexport const EVENT_PAGE_DATA = 'pageData';\nexport const EVENT_ORDER_CONFIRMATION = 'orderConfirmation';\nexport const EVENT_GENERAL_GA4 = 'general_ga4';\nexport const EVENT_SELECT_ITEM_GA4 = 'select_item';\nexport const EVENT_VIEW_ITEM_LIST_GA4 = 'view_item_list';\nexport const EVENT_CATEGORY_SORT_CHANGE_GA4 = 'sort_selected';\nexport const EVENT_CATEGORY_REFINEMENT_SELECT_GA4 = 'refinement_selected';\nexport const EVENT_VIEW_ITEM_GA4 = 'view_item';\nexport const EVENT_ADD_TO_CART_GA4 = 'add_to_cart';\nexport const EVENT_VIEW_CART_GA4 = 'view_cart';\nexport const EVENT_BEGIN_CHECKOUT_GA4 = 'begin_checkout';\nexport const EVENT_ADD_SHIPPING_INFO_GA4 = 'add_shipping_info';\nexport const EVENT_ADD_PAYMENT_INFO_GA4 = 'add_payment_info';\nexport const EVENT_REMOVE_FROM_CART_GA4 = 'remove_from_cart';\nexport const EVENT_ADD_TO_WISHLIST_GA4 = 'add_to_wishlist';\nexport const EVENT_VIEW_PROMOTION = 'view_promotion';\nexport const EVENT_SELECT_PROMOTION = 'select_promotion';\nexport const EVENT_PURCHASE_GA4 = 'ga4_purchase';\n\n/**\n * Const\n */\nexport const DATA_LAYER_NAME = 'dataLayer';\nexport const GROUPED_PRODUCTS_PREFIX = 'GROUPED_PRODUCTS_';\nexport const GROUPED_PRODUCTS_GUEST = `${ GROUPED_PRODUCTS_PREFIX }GUEST`;\n\nexport const GTM_INJECTION_TIMEOUT = 500;\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport { default } from './Loader.component';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport { default, getFixedElementHeight, getElementHeight } from './CSS';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport const TOGGLE_OVERLAY = 'TOGGLE_OVERLAY';\nexport const HIDE_ACTIVE_OVERLAY = 'HIDE_ACTIVE_OVERLAY';\nexport const HIDE_ACTIVE_POPUP = 'HIDE_ACTIVE_POPUP';\nexport const FORCE_SHOW_SUBSCRIPTION_POPUP = 'FORCE_SHOW_SUBSCRIPTION_POPUP';\n\n/** @namespace Scandipwa/Store/Overlay/Action/toggleOverlayByKey */\nexport const toggleOverlayByKey = (overlayKey, payload) => ({\n type: TOGGLE_OVERLAY,\n overlayKey,\n payload\n});\n\n/** @namespace Scandipwa/Store/Overlay/Action/hideActiveOverlay */\nexport const hideActiveOverlay = () => ({\n type: HIDE_ACTIVE_OVERLAY\n});\n\n/** @namespace Scandipwa/Store/Overlay/Action/hideActivePopup */\nexport const hideActivePopup = (shouldPopupClose = true) => ({\n type: HIDE_ACTIVE_POPUP,\n payload: shouldPopupClose\n});\n\n/** @namespace Scandipwa/Store/Overlay/Action/setForceShowPopup */\nexport const setForceShowPopup = (forceShowSubscriptionPopup = false) => ({\n type: FORCE_SHOW_SUBSCRIPTION_POPUP,\n forceShowSubscriptionPopup\n});\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport const AMPM_FORMAT = {\n AM: __('AM'),\n PM: __('PM')\n};\n\nexport const DEFAULT_MONTH_DAYS = 31;\nexport const MONTHS_COUNT = 12;\nexport const MINUTES_COUNT = 60;\nexport const HOURS_12H_COUNT = 12;\nexport const HOURS_24H_COUNT = 24;\n\nexport const FIELD_NAME_ATTR = 'data-field';\nexport const FIELD_TYPE_ATTR = 'data-type';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport const IMAGE_LOADING = 'IMAGE_LOADING';\nexport const IMAGE_LOADED = 'IMAGE_LOADED';\nexport const IMAGE_NOT_FOUND = 'IMAGE_NOT_FOUND';\nexport const IMAGE_NOT_SPECIFIED = 'IMAGE_NOT_SPECIFIED';\nexport const IMAGE_HUNDRED_PERCENT = '100%';\n","/* eslint-disable spaced-comment */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport const VALIDATION_INPUT_TYPE_TEXT = {\n alpha: 'alpha',\n alphaSpace: 'alphaSpace',\n alphaNumeric: 'alphaNumeric',\n alphaDash: 'alphaDash',\n url: 'url'\n};\n\nexport const VALIDATION_INPUT_TYPE_NUMBER = {\n numeric: 'numeric',\n numericDash: 'numericDash',\n integer: 'integer',\n decimal: 'decimal',\n natural: 'natural',\n naturalNoZero: 'naturalNoZero'\n};\n\nexport const VALIDATION_INPUT_TYPE_INPUT = {\n email: 'email',\n password: 'password',\n date: 'date',\n phone: 'phone',\n emailList: 'emailList'\n};\n\nexport const VALIDATION_INPUT_TYPE = {\n ...VALIDATION_INPUT_TYPE_TEXT,\n ...VALIDATION_INPUT_TYPE_NUMBER,\n ...VALIDATION_INPUT_TYPE_INPUT\n};\n\nexport const VALIDATION_MESSAGES = {\n //#region VALIDATION RULE MSG\n isRequired: __('This field is required!'),\n match: __('Incorrect input!'),\n range: __('Value is out of range!'), // Range values are also in Validator.js as they require args\n group: __('Field contains issues!'),\n fileExtension: __('Incorrect File extension upload!'),\n //#endregion\n\n //#region VALIDATION RULE MSG\n [VALIDATION_INPUT_TYPE.alpha]: __('Incorrect input! Only letters allowed!'),\n [VALIDATION_INPUT_TYPE.alphaSpace]: __('Incorrect input! Only words allowed!'),\n [VALIDATION_INPUT_TYPE.alphaNumeric]: __('Incorrect input! Alpha-Numeric value required!'),\n [VALIDATION_INPUT_TYPE.alphaDash]: __('Incorrect input! Alpha-Dash value required!'),\n [VALIDATION_INPUT_TYPE.url]: __('Incorrect input! URL required!'),\n [VALIDATION_INPUT_TYPE.numeric]: __('Incorrect input! Numeric value required!'),\n [VALIDATION_INPUT_TYPE.numericDash]: __('Incorrect input! Numeric-Dash value required!'),\n [VALIDATION_INPUT_TYPE.integer]: __('Incorrect input! Integer required!'),\n [VALIDATION_INPUT_TYPE.natural]: __('Incorrect input! Natural number required!'),\n [VALIDATION_INPUT_TYPE.naturalNoZero]: __('Incorrect input!'),\n [VALIDATION_INPUT_TYPE.email]: __('Incorrect email format!'),\n [VALIDATION_INPUT_TYPE.emailList]: __('Incorrect list of emails!'),\n [VALIDATION_INPUT_TYPE.date]: __('Incorrect date input!'),\n [VALIDATION_INPUT_TYPE.password]: __('Incorrect password input!'),\n [VALIDATION_INPUT_TYPE.phone]: __('Incorrect phone input!')\n //#endregion\n};\n\nexport const VALIDATION_RULES = {\n // Text\n [VALIDATION_INPUT_TYPE.alpha]: /^[a-z]+$/i,\n [VALIDATION_INPUT_TYPE.alphaSpace]: /^[a-z\\s]+$/i,\n [VALIDATION_INPUT_TYPE.alphaNumeric]: /^[a-z0-9]+$/i,\n [VALIDATION_INPUT_TYPE.alphaDash]: /^[a-z0-9_\\\\-]+$/i,\n [VALIDATION_INPUT_TYPE.url]: /^((http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)|)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\\\/]))?$/,\n\n // Numbers\n [VALIDATION_INPUT_TYPE.numeric]: /^[0-9]+$/,\n [VALIDATION_INPUT_TYPE.numericDash]: /^[\\d\\-\\s]+$/,\n [VALIDATION_INPUT_TYPE.integer]: /^\\\\-?[0-9]+$/,\n [VALIDATION_INPUT_TYPE.decimal]: /^\\\\-?[0-9]*\\.?[0-9]+$/,\n [VALIDATION_INPUT_TYPE.natural]: /^[0-9]+$/i,\n [VALIDATION_INPUT_TYPE.naturalNoZero]: /^[1-9][0-9]*$/i,\n\n // Inputs\n // eslint-disable-next-line max-len\n [VALIDATION_INPUT_TYPE.email]: /^(([^<>()\\\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z0-9]{2,}))$/,\n [VALIDATION_INPUT_TYPE.date]: /\\d{4}-\\d{1,2}-\\d{1,2}/,\n [VALIDATION_INPUT_TYPE.phone]: /^[\\\\+]?[(]?[0-9]{3}[)]?[-\\s\\\\.]?[0-9]{3}[-\\s\\\\.]?[0-9]{4,6}$/im,\n // eslint-disable-next-line max-len\n [VALIDATION_INPUT_TYPE.emailList]: /^(([a-zA-Z0-9_\\\\-\\\\.]+)@([a-zA-Z0-9_\\\\-\\\\.]+)\\.([a-zA-Z]{2,5}){1,25})+([,\\s]+(([a-zA-Z0-9_\\\\-\\\\.]+)@([a-zA-Z0-9_\\\\-\\\\.]+)\\.([a-zA-Z]{2,5}){1,25})+)*$/\n};\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nimport PropTypes from 'prop-types';\n\nimport { MetaTitleType } from 'Type/Common.type';\nimport { PriceType } from 'Type/Price.type';\nimport { UrlRewriteType } from 'Type/Router.type';\nimport { StockStatusType } from 'Type/StockStatus.type';\n\nexport const AttributeType = PropTypes.shape({\n attribute_code: PropTypes.string,\n attribute_type: PropTypes.string,\n attribute_value: PropTypes.string,\n attribute_label: PropTypes.string,\n attribute_options: PropTypes.objectOf(PropTypes.shape({\n label: PropTypes.string,\n value: PropTypes.string\n })),\n has_swatch: PropTypes.bool,\n is_boolean: PropTypes.bool\n});\n\nexport const AttributesType = PropTypes.oneOfType([\n PropTypes.objectOf(AttributeType),\n PropTypes.arrayOf(PropTypes.objectOf(AttributeType))\n]);\n\nexport const FilterAttributeType = PropTypes.shape({\n attribute_code: PropTypes.string,\n attribute_label: PropTypes.string,\n attribute_position: PropTypes.number,\n attribute_values: PropTypes.arrayOf(PropTypes.string),\n attribute_type: PropTypes.string,\n attribute_options: PropTypes.objectOf(PropTypes.shape({\n label: PropTypes.string,\n count: PropTypes.number,\n value_string: PropTypes.string,\n swatch_data: PropTypes.shape({ type: PropTypes.string, value: PropTypes.string })\n })),\n is_boolean: PropTypes.bool,\n has_swatch: PropTypes.bool\n});\n\nexport const BreadcrumbsType = PropTypes.arrayOf(\n PropTypes.shape({\n name: PropTypes.string,\n url_path: PropTypes.string\n })\n);\n\nexport const ImageType = PropTypes.shape({\n path: PropTypes.string,\n url: PropTypes.string\n});\n\nexport const CategoryType = PropTypes.shape({\n name: PropTypes.string,\n url_path: PropTypes.string,\n breadcrumbs: BreadcrumbsType\n});\n\nexport const CategoriesType = PropTypes.arrayOf(CategoryType);\n\nexport const ThumbnailType = PropTypes.shape({\n height: PropTypes.string,\n type: PropTypes.string,\n url: PropTypes.string,\n width: PropTypes.string\n});\n\nexport const MediaItemType = PropTypes.shape({\n thumbnail: ThumbnailType,\n file: PropTypes.string,\n video_content: PropTypes.shape({\n media_type: PropTypes.string,\n video_description: PropTypes.string,\n video_metadata: PropTypes.string,\n video_provider: PropTypes.string,\n video_title: PropTypes.string,\n video_url: PropTypes.string\n }),\n id: PropTypes.number,\n media_type: PropTypes.string,\n label: PropTypes.string\n});\n\nexport const MediaType = PropTypes.arrayOf(MediaItemType);\n\nexport const ProductLinksType = PropTypes.arrayOf(\n PropTypes.shape({\n link_type: PropTypes.string,\n linked_product_sku: PropTypes.string,\n position: PropTypes.number\n })\n);\n\nexport const ReviewSummaryShape = {\n rating_summary: PropTypes.number,\n review_count: PropTypes.number\n};\n\nexport const RatingVoteType = PropTypes.shape({\n vote_id: PropTypes.number,\n rating_code: PropTypes.string,\n percent: PropTypes.number\n});\n\nexport const ReviewsType = PropTypes.arrayOf(\n PropTypes.shape({\n review_id: PropTypes.number,\n nickname: PropTypes.string,\n title: PropTypes.string,\n detail: PropTypes.string,\n created_at: PropTypes.string,\n rating_votes: PropTypes.arrayOf(RatingVoteType)\n })\n);\n\nexport const DescriptionType = PropTypes.shape({ html: PropTypes.string });\n\nexport const StockItemType = PropTypes.shape({\n in_stock: PropTypes.bool,\n min_sale_qty: PropTypes.number,\n max_sale_qty: PropTypes.number,\n qty_increments: PropTypes.number\n});\n\nexport const OptionValueType = PropTypes.shape({\n option_type_id: PropTypes.number,\n price: PropTypes.number,\n price_type: PropTypes.string,\n sku: PropTypes.string,\n sort_order: PropTypes.number,\n title: PropTypes.string\n});\n\nexport const OptionsType = PropTypes.arrayOf(\n PropTypes.shape({\n option_id: PropTypes.number,\n required: PropTypes.bool,\n sort_order: PropTypes.number,\n title: PropTypes.string,\n values: PropTypes.arrayOf(OptionValueType)\n })\n);\n\nexport const ValueType = PropTypes.shape({\n uid: PropTypes.string,\n option_type_id: PropTypes.number,\n price: PropTypes.number,\n priceInclTax: PropTypes.number,\n priceExclTax: PropTypes.number,\n price_type: PropTypes.string,\n currency: PropTypes.string,\n sku: PropTypes.string,\n title: PropTypes.string,\n sort_order: PropTypes.number\n});\n\nexport const PriceTierType = PropTypes.shape({\n discount: PropTypes.shape({ amount_off: PropTypes.number, percent_off: PropTypes.number }),\n final_price: PropTypes.shape({ currency: PropTypes.string, value: PropTypes.number }),\n quantity: PropTypes.number\n});\n\nexport const CustomizableOptionShape = {\n price: PropTypes.number,\n priceInclTax: PropTypes.number,\n priceExclTax: PropTypes.number,\n price_type: PropTypes.string,\n currency: PropTypes.string,\n sku: PropTypes.string\n};\n\nexport const CustomizableOptionType = PropTypes.shape({\n ...CustomizableOptionShape,\n uid: PropTypes.string,\n option_type_id: PropTypes.number,\n title: PropTypes.string,\n sort_order: PropTypes.number\n});\n\nexport const InputOptionType = PropTypes.shape({\n ...CustomizableOptionShape,\n max_characters: PropTypes.number\n});\n\nexport const FileOptionType = PropTypes.shape({\n ...CustomizableOptionShape,\n file_extension: PropTypes.string\n});\n\nexport const CustomizableOptionsType = PropTypes.oneOfType([\n FileOptionType,\n InputOptionType,\n PropTypes.arrayOf(CustomizableOptionType)\n]);\n\nexport const ItemShape = {\n attributes: AttributesType,\n configurable_options: AttributesType,\n id: PropTypes.number,\n image: ImageType,\n name: PropTypes.string,\n options: CustomizableOptionsType,\n price_range: PriceType,\n price_tiers: PropTypes.arrayOf(PriceTierType),\n ...ReviewSummaryShape,\n review_summary: PropTypes.shape(ReviewSummaryShape),\n short_description: DescriptionType,\n sku: PropTypes.string,\n small_image: ImageType,\n special_from_date: PropTypes.string,\n special_to_date: PropTypes.string,\n stock_item: StockItemType,\n stock_status: StockStatusType,\n thumbnail: ImageType,\n type_id: PropTypes.string,\n uid: PropTypes.string,\n url: PropTypes.string,\n url_rewrites: PropTypes.arrayOf(UrlRewriteType)\n};\nexport const ItemType = PropTypes.shape(ItemShape);\n\nexport const ItemsType = PropTypes.arrayOf(ItemType);\n\nItemType.variants = ItemsType;\n\nexport const PagesType = PropTypes.objectOf(ItemsType);\n\nexport const QuantityType = PropTypes.oneOfType([\n PropTypes.number,\n PropTypes.shape({\n [PropTypes.string]: PropTypes.number\n })\n]);\n\nexport const ItemOptionsType = PropTypes.arrayOf(\n PropTypes.shape({\n can_change_quantity: PropTypes.bool,\n id: PropTypes.number,\n is_default: PropTypes.bool,\n label: PropTypes.string,\n position: PropTypes.number,\n price: PropTypes.number,\n price_type: PropTypes.string,\n quantity: QuantityType,\n uid: PropTypes.string,\n product: PropTypes.shape({\n name: PropTypes.string,\n stock_status: PropTypes.string,\n price_range: PriceType\n }),\n regularOptionPrice: PropTypes.number,\n regularOptionPriceExclTax: PropTypes.number,\n finalOptionPrice: PropTypes.number,\n finalOptionPriceExclTax: PropTypes.number\n })\n);\n\nexport const ProductItemsType = PropTypes.arrayOf(\n PropTypes.shape({\n option_id: PropTypes.number,\n options: ItemOptionsType,\n position: PropTypes.number,\n required: PropTypes.bool,\n sku: PropTypes.string,\n title: PropTypes.string,\n type: PropTypes.string\n })\n);\n\nexport const ProductType = PropTypes.shape({\n canonical_url: PropTypes.string,\n categories: CategoriesType,\n description: DescriptionType,\n media_gallery_entries: MediaType,\n meta_description: PropTypes.string,\n meta_keyword: PropTypes.string,\n meta_title: MetaTitleType,\n product_links: ProductLinksType,\n special_price: PropTypes.number,\n url_key: PropTypes.string,\n quantity: PropTypes.number,\n items: ProductItemsType,\n reviews: ReviewsType,\n ...ItemShape\n});\n\nexport const DownloadableSamplesType = PropTypes.arrayOf(\n PropTypes.shape({\n sample_url: PropTypes.oneOfType([ProductType, PropTypes.string]),\n sort_order: PropTypes.number,\n title: PropTypes.string\n })\n);\n\nexport const PriceConfiguration = PropTypes.shape({\n containsOptions: PropTypes.bool,\n containsOptionsWithPrice: PropTypes.bool,\n containsRequiredOptions: PropTypes.bool,\n containsRequiredOptionsWithPrice: PropTypes.bool\n});\n\nexport const MagentoProductType = PropTypes.shape({\n entered_options: PropTypes.arrayOf(PropTypes.shape({\n uid: PropTypes.string,\n value: PropTypes.string\n })),\n quantity: QuantityType,\n selected_options: PropTypes.arrayOf(PropTypes.string),\n sku: PropTypes.string\n});\n\nexport const ProductCardPropsType = PropTypes.shape({\n siblingsHaveBrands: PropTypes.bool,\n siblingsHavePriceBadge: PropTypes.bool,\n siblingsHaveTierPrice: PropTypes.bool,\n siblingsHaveConfigurableOptions: PropTypes.bool\n});\n\nexport const OptionsListType = PropTypes.arrayOf(\n PropTypes.shape({\n value: CustomizableOptionsType,\n title: PropTypes.string,\n required: PropTypes.bool,\n sort_order: PropTypes.number,\n type: PropTypes.string,\n uid: PropTypes.string\n })\n);\n\nexport const LinkedProductsType = PropTypes.objectOf(\n PropTypes.shape({\n items: PropTypes.arrayOf(ProductType),\n total_count: PropTypes.number\n })\n);\n","/*\n * @category Puma\n * @author Deniss Dubinins \n * @license http://opensource.org/licenses/OSL-3.0 The Open Software License 3.0 (OSL-3.0)\n * @copyright Copyright (c) 2021 Scandiweb, Inc (https://scandiweb.com)\n */\n\nimport PropTypes from 'prop-types';\n\nexport * from 'SourceType/ProductList.type';\n\nexport const AttributeType = PropTypes.shape({\n attribute_code: PropTypes.string,\n attribute_type: PropTypes.string,\n attribute_value: PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.number\n ]),\n attribute_label: PropTypes.string,\n attribute_options: PropTypes.objectOf(PropTypes.shape({\n label: PropTypes.string,\n value: PropTypes.string\n }))\n});\n","export * from 'SourceComponent/Header/Header.config';\n\nexport const MENU_MOBILE = 'MOBILE_MENU';\n","/* eslint-disable import/prefer-default-export */\n\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport const STATE_SIGN_IN = 'signIn';\nexport const STATE_FORGOT_PASSWORD = 'forgotPassword';\nexport const STATE_FORGOT_PASSWORD_SUCCESS = 'forgotPasswordSuccess';\nexport const STATE_CREATE_ACCOUNT = 'createAccount';\nexport const STATE_LOGGED_IN = 'loggedIn';\nexport const STATE_CONFIRM_EMAIL = 'confirmEmail';\nexport const STATE_GUEST = 'guest';\nexport const PASSWORD_LENGTH = 7;\n\nexport const CUSTOMER_ACCOUNT_OVERLAY_KEY = 'customer_account';\n\nexport const ARABIC_LOCALE = 'ar_SA';\nexport const ENGLISH_LOCALE = 'en_US';\n","/**\n * @author Vladislavs Zimnikovs \n * @author Janis Verins \n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package puma-mx\n */\n\nimport Event, { EVENT_GTM_PAGE_DATA } from '../../../../util/Event';\nimport BaseEventEvent from '../BaseEvent.event';\nimport CategoryRefinementsDataEventHandler, {\n CATEGORY_REFINEMENTS_DATA_OBJECT\n} from './Handlers/CategoryRefinementsDataEvent.handler';\nimport CheckoutProductsPageDataEventHandler from './Handlers/CheckoutProductsPageDataEvent.handler';\nimport CustomerDataEventHandler from './Handlers/CustomerDataEvent.handler';\nimport EventPageDataEventHandler from './Handlers/EventPageDataEvent.handler';\nimport FormDataEventHandler, { FORM_DATA_OBJECT } from './Handlers/FormDataEvent.handler';\nimport NavigationPageDataEventHandler from './Handlers/NavigationPageDataEvent.handler';\nimport OrderPageDataEventHandler from './Handlers/OrderPageDataEvent.handler';\nimport ProductPageDataEventHandler, { PDP_DATA_OBJECT } from './Handlers/ProductPageDataEvent.handler';\nimport ProductsPageDataEventHandler, { PLP_DATA_OBJECT } from './Handlers/ProductsPageDataEvent.handler';\n\nexport const PLP_TYPE = 'plp_type';\nexport const ORDER_TYPE = 'order_type';\nexport const CHECKOUT_PRODUCTS_TYPE = 'checkout_product_type';\nexport const PDP_TYPE = 'pdp_type';\nexport const FORM_TYPE = 'form_type';\nexport const NAVIGATION_TYPE = 'navigation_type';\nexport const EVENT_TYPE = 'event_type';\nexport const ON_SITE_SEARCH_TYPE = 'on_site_search_type';\nexport const CATEGORY_REFINEMENTS_TYPE = 'category_refinements_type';\nexport const CUSTOMER_TYPE = 'customer_type';\n\n/** @namespace Gtm/Component/GoogleTagManager/Events/PageDataEvent/PageData/Event */\nexport class PageDataEvent extends BaseEventEvent {\n eventTypesHandlers = {\n [PLP_TYPE]: this.handlePlpDataUpdate.bind(this),\n [ORDER_TYPE]: this.handleOrderDataUpdate.bind(this),\n [CHECKOUT_PRODUCTS_TYPE]: this.handleCheckoutProductsDataUpdate.bind(this),\n [PDP_TYPE]: this.handlePdpDataUpdate.bind(this),\n [FORM_TYPE]: this.handleFormDataUpdate.bind(this),\n [NAVIGATION_TYPE]: this.handleNavigationUpdate.bind(this),\n [EVENT_TYPE]: this.handleEventDataUpdate.bind(this),\n [CATEGORY_REFINEMENTS_TYPE]: this.handleCategoryRefinementsUpdate.bind(this),\n [CUSTOMER_TYPE]: this.handleCustomerDataUpdate.bind(this)\n };\n\n bindEvent() {\n Event.observer(EVENT_GTM_PAGE_DATA, (data) => {\n this.handle(data);\n });\n }\n\n handler(data) {\n const { type, ...layerData } = data;\n\n if (window.pageData === undefined) {\n window.pageData = {};\n }\n\n this.eventTypesHandlers[type](layerData);\n }\n\n handlePlpDataUpdate(data) {\n const productsPageDataEventHandler = new ProductsPageDataEventHandler(this.getAppState());\n const products = productsPageDataEventHandler.getProductsPageData(data, this.getPageType());\n this.pushPageData(PLP_DATA_OBJECT, products, 'plpData');\n }\n\n handleOrderDataUpdate(data) {\n const orderPageDataEventHandler = new OrderPageDataEventHandler(this.getAppState());\n const orderPageData = orderPageDataEventHandler.getOrderPageData(data);\n this.pushPageData('order', orderPageData, 'orderData');\n }\n\n handleCheckoutProductsDataUpdate() {\n const checkoutProductsPageDataEventHandler = new CheckoutProductsPageDataEventHandler(this.getAppState());\n const checkoutProducts = checkoutProductsPageDataEventHandler.getCheckoutProducts();\n this.pushPageData('products', checkoutProducts, 'checkoutProductsData');\n }\n\n handlePdpDataUpdate(data) {\n const productPageDataEventHandler = new ProductPageDataEventHandler(this.getAppState());\n const product = productPageDataEventHandler.getProductPageData(data);\n this.pushPageData(PDP_DATA_OBJECT, product, 'pdpData');\n this.handleProductVariantsDataUpdate(data);\n }\n\n handleFormDataUpdate(data) {\n const formDataEventHandler = new FormDataEventHandler(this.getAppState());\n const form = formDataEventHandler.getFormData(data);\n this.pushPageData(FORM_DATA_OBJECT, form, 'formData');\n }\n\n handleCustomerDataUpdate() {\n const customerDataEventHandler = new CustomerDataEventHandler(this.getAppState());\n const customer = customerDataEventHandler.getCustomerData();\n this.pushPageData('customer', customer, 'customerData');\n }\n\n handleNavigationUpdate(data) {\n const navigationPageDataEventHandler = new NavigationPageDataEventHandler(\n this.getAppState(),\n this.getPageType(),\n data\n );\n const navigation = navigationPageDataEventHandler.getNavigationData(data);\n this.pushPageData('navigation', navigation, 'navigationData');\n }\n\n handleEventDataUpdate(data) {\n const eventPageDataEventHandler = new EventPageDataEventHandler(this.getAppState());\n const event = eventPageDataEventHandler.getEventsData(data);\n this.pushPageData('event', event);\n }\n\n handleCategoryRefinementsUpdate(data) {\n const categoryRefinementsDataEventHandler = new CategoryRefinementsDataEventHandler(this.getAppState());\n const categoryRefinements = categoryRefinementsDataEventHandler.getRefinements(data);\n this.pushPageData(CATEGORY_REFINEMENTS_DATA_OBJECT, categoryRefinements, 'categoryRefinements');\n }\n\n handleProductVariantsDataUpdate(data) {\n const productPageDataEventHandler = new ProductPageDataEventHandler(this.getAppState());\n window.productVariants = productPageDataEventHandler.getProductVariantsData(data);\n }\n\n /**\n * Event to be fired every time when pageData object is updated.\n */\n firePageDataEvent(event = '') {\n const PAGE_DATA_EVENT = 'pageData';\n\n if (window.dataLayer === 'undefined') {\n window.dataLayer = [];\n }\n\n window.dataLayer.push({ event: PAGE_DATA_EVENT.concat(' | ').concat(event) });\n }\n\n pushPageData(dataType, data, eventKey = false) {\n if (window.pageData && dataType === 'customer' && window.pageData[dataType]) {\n if (window.pageData.customer) {\n const { email } = window.pageData.customer;\n window.pageData[dataType] = { ...data, email };\n }\n } else {\n window.pageData[dataType] = data;\n }\n\n if (!eventKey) {\n return;\n }\n\n this.firePageDataEvent(eventKey);\n }\n}\n\nexport default PageDataEvent;\n","/* eslint-disable import/no-cycle */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport { default } from './Product';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport const UPDATE_CUSTOMER_SIGN_IN_STATUS = 'UPDATE_CUSTOMER_SIGN_IN_STATUS';\nexport const UPDATE_CUSTOMER_DETAILS = 'UPDATE_CUSTOMER_DETAILS';\nexport const UPDATE_CUSTOMER_PASSWORD_RESET_STATUS = 'UPDATE_CUSTOMER_PASSWORD_RESET_STATUS';\nexport const UPDATE_CUSTOMER_PASSWORD_FORGOT_STATUS = 'UPDATE_CUSTOMER_PASSWORD_FORGOT_STATUS';\nexport const UPDATE_CUSTOMER_LOADED = 'UPDATE_CUSTOMER_LOADED';\nexport const UPDATE_CUSTOMER_IS_LOADING = 'UPDATE_CUSTOMER_IS_LOADING';\nexport const UPDATE_CUSTOMER_PASSWORD_FORGOT_EMAIL = 'UPDATE_CUSTOMER_PASSWORD_FORGOT_EMAIL';\nexport const UPDATE_CUSTOMER_IS_LOCKED = 'UPDATE_CUSTOMER_IS_LOCKED';\n\n/** @namespace Scandipwa/Store/MyAccount/Action/updateCustomerSignInStatus */\nexport const updateCustomerSignInStatus = (status) => ({\n type: UPDATE_CUSTOMER_SIGN_IN_STATUS,\n status\n});\n\n/** @namespace Scandipwa/Store/MyAccount/Action/updateCustomerDetails */\nexport const updateCustomerDetails = (customer) => ({\n type: UPDATE_CUSTOMER_DETAILS,\n customer\n});\n\n/** @namespace Scandipwa/Store/MyAccount/Action/updateCustomerPasswordResetStatus */\nexport const updateCustomerPasswordResetStatus = (status, message) => ({\n type: UPDATE_CUSTOMER_PASSWORD_RESET_STATUS,\n status,\n message\n});\n\n/** @namespace Scandipwa/Store/MyAccount/Action/updateCustomerPasswordForgotStatus */\nexport const updateCustomerPasswordForgotStatus = () => ({\n type: UPDATE_CUSTOMER_PASSWORD_FORGOT_STATUS\n});\n\n/** @namespace Scandipwa/Store/MyAccount/Action/updateIsLoading */\nexport const updateIsLoading = (isLoading) => ({\n type: UPDATE_CUSTOMER_IS_LOADING,\n isLoading\n});\n\n/** @namespace Scandipwa/Store/MyAccount/Action/updateCustomerPasswordForgotEmail */\nexport const updateCustomerPasswordForgotEmail = (email) => ({\n type: UPDATE_CUSTOMER_PASSWORD_FORGOT_EMAIL,\n email\n});\n\n/** @namespace Scandipwa/Store/MyAccount/Action/updateIsLocked */\nexport const updateIsLocked = (isLocked) => ({\n type: UPDATE_CUSTOMER_IS_LOCKED,\n isLocked\n});\n","/* eslint-disable @scandipwa/scandipwa-guidelines/use-namespace */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nimport ParentBaseEvent from '../events/BaseEvent.event';\nimport ProductHelper from '../GA4_utils';\nimport { EVENT_VIEW_ITEM_LIST_GA4 } from '../GoogleTagManager.config';\n\n/**\n * Base event for GTM PWA events\n */\nexport class BaseEventEvent extends ParentBaseEvent {\n /**\n * Prepare cart data\n *\n * @param itemsProp\n * @return {{quantity: number, price: number, name: string, variant: string, id: string, availability: boolean, category: string, brand: string}[]}\n */\n prepareCartData(itemsProp = null) {\n const {\n total_quantity = 0,\n items: cartItems = [],\n groupedProducts = {}\n } = this.getCartProductData();\n\n const items = itemsProp || cartItems;\n\n const itemsData = items\n .map((item) => ({\n ...ProductHelper.getItemData(item),\n quantity: ProductHelper.getQuantity(item)\n }));\n\n if (total_quantity !== 0) {\n Object.values(groupedProducts || {}).forEach(({ data }) => itemsData.push(data));\n }\n\n return itemsData;\n }\n\n /**\n * Get data from impression\n *\n * @param product\n * @param addPosition\n * @param noIndex\n */\n getItemListData(product, addPosition = false, noIndex = false) {\n const data = this.getProductFromImpression(product) || {};\n\n if (Object.keys(data).length) {\n const {\n index = 0,\n item_list_id = '',\n item_list_name = ''\n } = data;\n\n if (addPosition) {\n const { item_list_position } = data;\n\n return {\n index, item_list_id, item_list_name, item_list_position\n };\n }\n\n if (noIndex) {\n return {\n item_list_id, item_list_name\n };\n }\n\n return {\n index, item_list_id, item_list_name\n };\n }\n\n return {};\n }\n\n /**\n * Get product position in impression\n *\n * @return {*}\n * @param clickedProduct\n */\n getProductFromImpression(clickedProduct) {\n const { impressions_ga4 = [] } = this.getStorage(EVENT_VIEW_ITEM_LIST_GA4);\n const id = ProductHelper.getSku(clickedProduct);\n const { sku } = clickedProduct;\n\n return impressions_ga4.find(({ item_id: impressionId }) => (\n impressionId === id || impressionId === sku\n ));\n }\n\n /**\n * Get cart sub total\n *\n * @return {string}\n */\n getItemsTotal() {\n return this.getAppState().CartReducer.cartTotals?.prices?.grand_total?.value || 0;\n }\n\n /**\n * Get cart items with 'index', 'item_list_id' and 'item_list_name'\n * attributes if available\n *\n * @param itemsProp\n * @returns {*}\n */\n getCartItemsWithListData(itemsProp = null) {\n const items = itemsProp || this.getCartProductData().items;\n\n return items.map(\n (item) => ({\n ...ProductHelper.getItemData(item),\n ...this.getItemListData(item.product),\n quantity: ProductHelper.getQuantity(item)\n })\n );\n }\n}\n\nexport default BaseEventEvent;\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport { default } from './Link.container';\n","/* eslint-disable import/no-cycle */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport { default } from './Product';\n","/* eslint-disable max-lines */\n/* eslint-disable @scandipwa/scandipwa-guidelines/use-namespace */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nimport { CUSTOMER } from 'Store/MyAccount/MyAccount.dispatcher';\nimport BrowserDatabase from 'Util/BrowserDatabase';\nimport { roundPrice } from 'Util/Price';\n\nimport ProductHelper from '../utils';\n\nexport const URL_REWRITE = 'url-rewrite';\n\nexport const DATA_RECHECK_TIMEOUT = 2000;\nexport const EVENT_HANDLE_DELAY = 2000;\n\n/**\n * Base event for GTM PWA events\n */\nexport class BaseEventEvent {\n /**\n *\n * @type {GoogleTagManager}\n */\n gtmReference = null;\n\n /**\n * Current event name\n *\n * @type {string}\n */\n eventName = '';\n\n /**\n * Time when last event was fired\n *\n * @type {Object}\n */\n lastEventTime = {};\n\n /**\n * Event delay\n *\n * @type {number}\n */\n eventHandleDelay = EVENT_HANDLE_DELAY;\n\n /**\n * Constructor\n *\n * @param eventName\n * @param gtmReference\n */\n constructor(eventName, gtmReference) {\n this.eventName = eventName;\n this.gtmReference = gtmReference;\n }\n\n /**\n * Bind event trigger, when triggered call handler\n * Called by GTM main component\n */\n bindEvent() {\n }\n\n /**\n * Called, when event should be unmounted and destructed\n * Called by GTM main component\n */\n destruct() {\n }\n\n /**\n * Check that we have loaded all data, if no, load or wait until will be loaded\n */\n checkDataExists(...args) {\n if (this.isLoadingData) {\n return false;\n }\n\n if (\n Object.entries(this.getAppState().ConfigReducer).length === 0 // If config data is not loaded yet\n || (this.getAppState().CartReducer.isLoading && !window.location.pathname.includes('checkout/success'))\n || (this.isSignedIn()\n && Object.entries(BrowserDatabase.getItem(CUSTOMER) || {}).length === 0) // If customer data is not loaded yet\n || this.getPageType() === ''\n ) {\n this.isLoadingData = true;\n\n // Wait until all data is loaded\n setTimeout(() => {\n this.isLoadingData = false;\n this.handle(...args);\n }, DATA_RECHECK_TIMEOUT);\n\n return false;\n }\n\n return true;\n }\n\n /**\n * Handle event fire\n * Process event logic\n */\n handle(...args) {\n if (!this.checkDataExists(...args)) {\n return;\n }\n\n // Set little delay on event fire. make it async, to do not block main code\n setTimeout(() => {\n this.handler(...args);\n }, this.eventHandleDelay);\n }\n\n /**\n * Handle Event\n */\n handler() {\n }\n\n /**\n * Get element by class name\n *\n * @param className\n * @param container\n *\n * @return {boolean}\n */\n getElementByClass(className, container = document) {\n const elements = container.getElementsByClassName(className);\n\n if (elements && elements.length) {\n const [element] = elements;\n\n return element || false;\n }\n\n return false;\n }\n\n /**\n * Check if given element in window viewport\n *\n * @param element\n */\n elementInViewPort(element) {\n const doomElement = typeof element === 'object'\n ? element\n : this.getElementByClass(element);\n\n if (doomElement) {\n const bounds = doomElement.getBoundingClientRect();\n const viewPortHeight = window.innerHeight || document.body.clientHeight;\n\n return (bounds.y + bounds.height) > 0 && (bounds.y - bounds.height) < viewPortHeight;\n }\n\n return false;\n }\n\n /**\n * Check if handle event is fired too often\n *\n * @param delay\n * @param type\n *\n * @return {boolean}\n */\n spamProtection(delay, type = 'default') {\n const previousEventTime = this.lastEventTime[type] || 0;\n this.lastEventTime[type] = Date.now();\n\n return previousEventTime + delay > this.lastEventTime[type];\n }\n\n /**\n * Push data to google tag manager\n *\n * @param event\n * @param data\n */\n pushEventData(data) {\n this.getGTM().processDataPush(this.eventName, data);\n }\n\n /**\n * Get current application state\n *\n * @return {{}}\n */\n getAppState() {\n return this.getGTM().props.state;\n }\n\n /**\n * Get reference to GoogleTagManager\n *\n * @return {GoogleTagManager}\n */\n getGTM() {\n return this.gtmReference;\n }\n\n /**\n * Get application dispatch\n *\n * @return {function}\n */\n getAppDispatch() {\n return this.getGTM().props.dispatch;\n }\n\n /**\n * Get Store currency code\n *\n * @return {string}\n */\n getCurrencyCode() {\n return this.getAppState().ConfigReducer.default_display_currency_code;\n }\n\n /**\n * Get page type\n *\n * @return {string}\n */\n getPageType() {\n const { currentRouteName } = window;\n const appState = this.getAppState();\n const {\n UrlRewritesReducer: {\n urlRewrite: {\n type\n } = {}\n } = {}\n } = appState;\n\n if (currentRouteName === URL_REWRITE) {\n return (type || '').toLowerCase();\n }\n\n if (currentRouteName === 'checkout' && window.location.pathname.includes('success')) {\n return ('success');\n }\n\n if (!currentRouteName && window.location.pathname.includes('search-results')) {\n return ('search');\n }\n\n return (currentRouteName || '').toLowerCase();\n }\n\n /**\n * if user is signed in\n *\n * @return {*|boolean}\n */\n isSignedIn() {\n return this.getAppState().MyAccountReducer.isSignedIn || false;\n }\n\n /**\n * Get reference to the event storage\n *\n * @param event\n * @return {*}\n */\n getStorage(event = this.eventName) {\n return this.getGTM().getEventDataStorage(event);\n }\n\n /**\n * Clean event storage\n *\n * @param event\n */\n cleanStorage(event = this.eventName) {\n this.getGTM().resetEventDataStorage(event);\n }\n\n /**\n * Set storage data\n *\n * @param data\n * @param event\n */\n setStorage(data, event = this.eventName) {\n this.getGTM().setEventStorage(event, data);\n }\n\n /**\n * Set grouped products\n *\n * @param groupedProducts\n */\n setGroupedProducts(groupedProducts) {\n this.getGTM().setGroupedProducts(groupedProducts);\n }\n\n /**\n * Get grouped products\n *\n * @param groupedProducts\n */\n getGroupedProducts() {\n return this.getGTM().getGroupedProducts();\n }\n\n /**\n * Prepare cart data\n *\n * @return {{quantity: number, price: number, name: string, variant: string, id: string, availability: boolean, category: string, brand: string}[]}\n */\n prepareCartData() {\n const {\n total_quantity = 0,\n items = [],\n prices: {\n quote_currency_code = 'EUR',\n grand_total: { value: grandTotal = 0 } = {}\n } = {},\n groupedProducts = {}\n } = this.getCartProductData();\n\n const itemsData = items\n .map((item) => ({\n ...ProductHelper.getItemData(item),\n quantity: ProductHelper.getQuantity(item)\n }));\n\n if (total_quantity !== 0) {\n Object.values(groupedProducts || {}).forEach(({ data }) => itemsData.push(data));\n }\n\n return {\n total_quantity,\n total: +roundPrice(grandTotal),\n currency: quote_currency_code,\n itemsData\n };\n }\n\n /**\n * Get cart products\n *\n * @return {initialState.productsInCart|{}}\n */\n getCartProductData() {\n const appState = this.getAppState();\n const cartData = appState.CartReducer.cartTotals;\n\n const groupedProducts = this.getGroupedProducts();\n\n return { ...cartData, groupedProducts };\n }\n}\n\nexport default BaseEventEvent;\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nimport FIELD_TYPE from 'Component/Field/Field.config';\nimport PRODUCT_TYPE from 'Component/Product/Product.config';\nimport { NONE_RADIO_OPTION } from 'Component/ProductCustomizableOption/ProductCustomizableOption.config';\nimport { formatPrice } from 'Util/Price';\n\nimport { getProductInStock } from './Extract';\nimport { ADD_TO_CART } from './Product';\n\nexport const PRICE_TYPE_PERCENT = 'PERCENT';\n\n/**\n * Generates correct UID for bundle with changed quantity\n * UID is encoded in base64, original value is bundle/option_id/item_id/quantity\n *\n * @param uid\n * @param quantity\n * @namespace Util/Product/Transform/getEncodedBundleUid\n */\nexport const getEncodedBundleUid = (uid, quantity) => {\n const decoded = atob(uid);\n const parts = decoded.split('/');\n // eslint-disable-next-line no-magic-numbers\n const newUid = parts.length === 3\n ? `bundle/${parts[1]}/${quantity}`\n : `bundle/${parts[1]}/${parts[2]}/${quantity}`;\n\n return btoa(newUid);\n};\n\n/** @namespace Util/Product/Transform/getBundleOptions */\nexport const getBundleOptions = (buyRequest) => {\n const { bundle_option = {}, bundle_option_qty = {} } = JSON.parse(buyRequest);\n\n if (!bundle_option) {\n return [];\n }\n\n return Object.entries(bundle_option).reduce((prev, [option, variant]) => {\n const qty = bundle_option_qty[option] || 1;\n\n if (Array.isArray(variant) && variant.every((val) => typeof (val) === 'string')) {\n return [...prev, ...variant.map((val) => btoa(`bundle/${option}/${val}/${qty}`))];\n }\n\n return [...prev, ...Object.keys(variant).map((id) => btoa(`bundle/${option}/${id}/${qty}`))];\n }, []);\n};\n\n/** @namespace Util/Product/Transform/getCustomizableOptions */\nexport const getCustomizableOptions = (buyRequest) => {\n const { options = {} } = JSON.parse(buyRequest);\n\n // handle null\n if (!options) {\n return [];\n }\n\n return Object.entries(options).reduce((prev, [option, variant]) => {\n if (typeof variant === 'string') {\n return [...prev, btoa(`custom-option/${option}/${variant}`)];\n }\n\n if (Array.isArray(variant)) {\n return [...prev, ...variant.map((id) => btoa(`custom-option/${option}/${id}`))];\n }\n\n if (typeof variant === 'object' && (variant.date_internal || variant.date)) {\n const { date_internal, date } = variant;\n\n return [...prev, btoa(`custom-option/${option}/${date_internal || date}`)];\n }\n\n // Handle case when we need to pass previously uploaded file as selected option\n // Normally files are passed via entered_options, but when customer adds product with attachment from wishlist,\n // we need to reference data of the already uploaded file\n if (typeof variant === 'object' && variant.type === 'application/octet-stream') {\n return [...prev, btoa(`custom-option/${option}/file-${btoa(JSON.stringify(variant))}`)];\n }\n\n return prev;\n },\n []);\n};\n\n/** @namespace Util/Product/Transform/getDownloadableOptions */\nexport const getDownloadableOptions = (buyRequest) => {\n const { links } = JSON.parse(buyRequest);\n\n if (!links) {\n return [];\n }\n\n const linksData = Object.entries(links);\n\n if (typeof linksData === 'string') {\n return btoa(`downloadable/${links}`);\n }\n\n return links.map((link) => btoa(`downloadable/${link}`));\n};\n\n/** @namespace Util/Product/Transform/getConfigurableOptions */\nexport const getConfigurableOptions = (buyRequest) => {\n const { super_attribute } = JSON.parse(buyRequest);\n\n if (!super_attribute) {\n return [];\n }\n\n return Object.entries(super_attribute).map(([attr, value]) => btoa(`configurable/${attr}/${value}`));\n};\n\n/** @namespace Util/Product/Transform/getSelectedOptions */\nexport const getSelectedOptions = (buyRequest) => [\n ...getBundleOptions(buyRequest),\n ...getCustomizableOptions(buyRequest),\n ...getDownloadableOptions(buyRequest),\n ...getConfigurableOptions(buyRequest)\n];\n\n/** @namespace Util/Product/Transform/transformParameters */\nexport const transformParameters = (parameters = [], attributes = {}) => Object.entries(parameters)\n .map(([attrCode, selectedValue]) => {\n const attrId = attributes[attrCode]?.attribute_id;\n\n return btoa(`configurable/${attrId}/${selectedValue}`);\n });\n\n/**\n * Generates label for bundle option\n *\n * @param option\n * @param currencyCode\n * @returns {{baseLabel: string, priceLabel: string}}\n * @namespace Util/Product/Transform/bundleOptionToLabel\n */\nexport const bundleOptionToLabel = (option, currencyCode = 'USD') => {\n const {\n price,\n finalOptionPrice,\n price_type: priceType,\n can_change_quantity: canChangeQuantity,\n quantity,\n label,\n product\n } = option || {};\n\n const noPrice = price === 0 && finalOptionPrice === 0;\n const priceLabel = noPrice ? '' : `+ ${ formatPrice(finalOptionPrice, currencyCode) }`;\n const percentLabel = (noPrice || priceType !== PRICE_TYPE_PERCENT) ? '' : `(${ price }%)`;\n // Accessing name here, because product may be passed as null - which prevents from assigning its\n // default value, thus resulting in error\n const fallbackLabel = product ? product.name : __('Option');\n const renderLabel = label ?? fallbackLabel;\n\n return {\n baseLabel: !canChangeQuantity && quantity >= 0 ? `${ quantity } x ${ renderLabel } ` : `${ renderLabel } `,\n priceLabel: `${ priceLabel } ${ percentLabel }`\n };\n};\n\n/**\n * Converts bundle products options into select field options,\n * meaning into [uid:label] pair\n *\n * @param options\n * @namespace Util/Product/Transform/bundleOptionsToSelectTransform\n */\nexport const bundleOptionsToSelectTransform = (options, currencyCode = 'USD', quantity = {}) => (\n options.reduce((result = [], option) => {\n const {\n uid: sourceUid = '',\n quantity: defaultQuantity = 1,\n position,\n product,\n is_default\n } = option;\n\n const isAvailable = getProductInStock(product);\n\n const {\n priceLabel,\n baseLabel\n } = bundleOptionToLabel(option, currencyCode);\n\n const { [sourceUid]: currentQty = defaultQuantity } = quantity;\n const uid = getEncodedBundleUid(sourceUid, currentQty);\n\n result.push({\n id: sourceUid,\n name: sourceUid,\n value: uid,\n label: baseLabel,\n subLabel: priceLabel,\n sort_order: position,\n isAvailable,\n isDefault: is_default\n });\n\n return result;\n }, [])\n);\n\n/**\n * Generates label for customizable option\n *\n * @param option\n * @param currencyCode\n * @returns {{baseLabel: string, priceLabel: string}}\n * @namespace Util/Product/Transform/customizableOptionToLabel\n */\nexport const customizableOptionToLabel = (option, currencyCode = 'USD') => {\n const {\n price,\n priceInclTax,\n price_type,\n title\n } = option || {};\n const noPrice = price === 0 && priceInclTax === 0;\n const priceLabel = noPrice ? '' : `+ ${ formatPrice(priceInclTax, currencyCode) }`;\n const percentLabel = (noPrice || price_type !== PRICE_TYPE_PERCENT) ? '' : ` (${ price }%)`;\n\n return {\n baseLabel: title,\n priceLabel: `${ priceLabel } ${ percentLabel }`\n };\n};\n\n/**\n * Converts customizable products options into select field options,\n * meaning into [uid:label] pair\n *\n * @param options\n * @namespace Util/Product/Transform/customizableOptionsToSelectTransform\n */\nexport const customizableOptionsToSelectTransform = (options, currencyCode = 'USD') => (\n options.reduce((result = [], option) => {\n const {\n uid,\n title,\n position,\n sort_order = 0\n } = option;\n\n const {\n priceLabel,\n baseLabel\n } = customizableOptionToLabel(option, currencyCode);\n\n result.push({\n id: uid,\n name: title,\n value: uid,\n label: baseLabel,\n subLabel: priceLabel,\n sort_order: position || sort_order\n });\n\n return result;\n }, [])\n);\n\n/**\n * Generates Magento type product interface for performing\n * actions (add to cart, wishlist, exc.)\n * @param product\n * @param quantity\n * @param enteredOptions\n * @param selectedOptions\n * @returns {*[]}\n * @namespace Util/Product/Transform/magentoProductTransform\n */\nexport const magentoProductTransform = (\n action = ADD_TO_CART,\n product,\n quantity = 1,\n enteredOptions = [],\n selectedOptions = []\n) => {\n const { sku, type_id: typeId } = product;\n\n const productData = [];\n\n if (typeId === PRODUCT_TYPE.grouped && action === ADD_TO_CART) {\n if (Object.keys(quantity).length === 0) {\n return productData;\n }\n\n const { items } = product;\n const groupedProducts = [];\n\n items.forEach(({ product: { id } }) => {\n const { [id]: groupedQuantity = 0 } = quantity;\n\n groupedProducts.push(btoa(`grouped/${id}/${groupedQuantity}`));\n });\n\n productData.push({\n sku,\n quantity: 1,\n selected_options: [...selectedOptions, ...groupedProducts],\n entered_options: enteredOptions\n });\n } else {\n const baseProductToAdd = {\n sku,\n quantity,\n selected_options: selectedOptions,\n entered_options: enteredOptions\n };\n\n productData.push(baseProductToAdd);\n }\n\n return productData;\n};\n\n/**\n *\n * @param options\n * @param isRequired\n * @param type\n * @returns {[{uid: string, price: number, priceInclTax: number, title: *, is_default: boolean},...*]|*}\n * @namespace Util/Product/Transform/nonRequiredRadioOptions\n */\nexport const nonRequiredRadioOptions = (\n options, isRequired = false, type = FIELD_TYPE.radio\n) => {\n if (isRequired || type !== FIELD_TYPE.radio) {\n return options;\n }\n\n const hasDefault = options.find(({ is_default, product }) => is_default && getProductInStock(product));\n\n return [\n {\n ...NONE_RADIO_OPTION,\n is_default: !hasDefault\n },\n ...options\n ];\n};\n\nexport default bundleOptionsToSelectTransform;\n","export default function _extends() {\n _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n };\n return _extends.apply(this, arguments);\n}","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport const FIELD_DATE_TYPE = {\n date: 'date',\n dateTime: 'dateTime',\n time: 'time'\n};\n\nexport const TIME_FORMAT = {\n H12: '12h',\n H24: '24h'\n};\n\nexport const DATE_FIELDS_COUNT = 3;\n","/**\n * Puma\n * @category ScandiPWA\n * @author Ricards Nedosvitnijs \n * @copyright Copyright (c) 2021 Scandiweb, Ltd (https://scandiweb.com)\n */\n\nimport { STORE_CODE_KSA_AR, STORE_CODE_KSA_EN } from 'Component/Router/Router.config';\nimport BrowserDatabase from 'Util/BrowserDatabase';\n\n/** @namespace Scandipwa/Util/Arabic/isKsa/isKsa */\nexport const isKsa = () => (BrowserDatabase.getItem('config')?.storeConfig?.code\n ? BrowserDatabase.getItem('config').storeConfig.code === STORE_CODE_KSA_EN\n || BrowserDatabase.getItem('config').storeConfig.code === STORE_CODE_KSA_AR\n : false);\n\nexport default isKsa;\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport { SHOW_POPUP, showPopup } from 'SourceStore/Popup/Popup.action';\n\nexport const CLEAR_POPUP_STATE = 'CLEAR_POPUP_STATE';\n\n/** @namespace Scandipwa/Store/Popup/Action/clearPopupState */\nexport const clearPopupState = () => ({\n type: CLEAR_POPUP_STATE\n});\n","/** * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\nexport const UPDATE_SHIPPING_FIELDS = 'UPDATE_SHIPPING_FIELDS';\nexport const UPDATE_EMAIL = 'UPDATE_EMAIL';\nexport const UPDATE_EMAIL_AVAILABLE = 'UPDATE_EMAIL_AVAILABLE';\nexport const UPDATE_CHECKOUT_STATUS = 'UPDATE_CHECKOUT_STATUS';\nexport const UPDATE_CHECKOUT_STATE = 'UPDATE_CHECKOUT_STATE';\nexport const UPDATE_PAYMENT_METHODS = 'UPDATE_PAYMENT_METHODS';\nexport const UPDATE_PAYMENT_TOTALS = 'UPDATE_PAYMENT_TOTALS';\nexport const UPDATE_SHIPPING_METHODS = 'UPDATE_SHIPPING_METHODS';\nexport const UPDATE_SHIPPING_ADDRESS = 'UPDATE_SHIPPING_ADDRESS';\nexport const UPDATE_IS_SAME_AS_SHIPPING = 'UPDATE_IS_SAME_AS_SHIPPING';\n\n/** @namespace Scandipwa/Store/Checkout/Action/updateShippingFields */\nexport const updateShippingFields = (shippingFields) => ({\n type: UPDATE_SHIPPING_FIELDS,\n shippingFields\n});\n\n/** @namespace Scandipwa/Store/Checkout/Action/updateEmail */\nexport const updateEmail = (email) => ({\n type: UPDATE_EMAIL,\n email\n});\n\n/** @namespace Scandipwa/Store/Checkout/Action/updateEmailAvailable */\nexport const updateEmailAvailable = (isEmailAvailable) => ({\n type: UPDATE_EMAIL_AVAILABLE,\n isEmailAvailable\n});\n\n/**\n * Update checkout loading status\n * @param {Object} status\n * @namespace Scandipwa/Store/Checkout/Action/updateCheckoutStatus */\nexport const updateCheckoutStatus = (status) => ({\n type: UPDATE_CHECKOUT_STATUS,\n status\n});\n\n/**\n * Update checkout state\n * @param {Object} state\n * @namespace Scandipwa/Store/Checkout/Action/updateCheckoutState */\nexport const updateCheckoutState = (state) => ({\n type: UPDATE_CHECKOUT_STATE,\n state\n});\n\n/**\n * Update checkout payment totals\n * @param {Object} totals\n * @namespace Scandipwa/Store/Checkout/Action/updatePaymentTotals */\nexport const updatePaymentTotals = (totals) => ({\n type: UPDATE_PAYMENT_TOTALS,\n totals\n});\n\n/**\n * Update checkout shipping methods\n * @param {Object} shippingMethods\n * @namespace Scandipwa/Store/Checkout/Action/updateShippingMethods */\nexport const updateShippingMethods = (shippingMethods) => ({\n type: UPDATE_SHIPPING_METHODS,\n shippingMethods\n});\n\n/**\n * Update checkout shipping address\n * @param {Object} shippingAddress\n * @namespace Scandipwa/Store/Checkout/Action/updateShippingAddress */\nexport const updateShippingAddress = (shippingAddress) => ({\n type: UPDATE_SHIPPING_ADDRESS,\n shippingAddress\n});\n\n/**\n * Update isSameAsShipping state\n * @param {Boolean} isSameAsShipping\n * @namespace Scandipwa/Store/Checkout/Action/updateIsSameAsShipping */\nexport const updateIsSameAsShipping = (isSameAsShipping) => ({\n type: UPDATE_IS_SAME_AS_SHIPPING,\n isSameAsShipping\n});\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport const UPDATE_EVENT_DATA = 'UPDATE_EVENT_DATA';\n\n/** @namespace Scandipwa/Store/Event/Action/updateEventData */\nexport const updateEventData = (eventData) => ({\n type: UPDATE_EVENT_DATA,\n eventData\n});\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nimport { FIELD_NAME_ATTR, FIELD_TYPE_ATTR, HOURS_12H_COUNT } from 'Component/DateSelect/DateSelect.config';\nimport FIELD_TYPE from 'Component/Field/Field.config';\nimport { DATE_FIELDS_COUNT, FIELD_DATE_TYPE, TIME_FORMAT } from 'Component/FieldDate/FieldDate.config';\n\n/**\n * Appends 0 to value if its less than passed attribute;\n * @param value\n * @param lessThan\n * @returns {string|*}\n * @namespace Util/Form/Extract/zeroBasedValue\n */\n// eslint-disable-next-line no-magic-numbers\nexport const zeroBasedValue = (value, lessThan = 10) => (\n (+value < lessThan) ? `0${value}` : value\n);\n\n/** @namespace Util/Form/Extract/adjustHours */\nexport const adjustHours = (hours, timeFormat) => {\n if (timeFormat === TIME_FORMAT.H12) {\n if (hours > HOURS_12H_COUNT) {\n return hours % HOURS_12H_COUNT;\n }\n\n if (hours === 0) {\n return HOURS_12H_COUNT;\n }\n }\n\n return hours;\n};\n\n/**\n * Converts date to magento supported format\n * @returns {string|*}\n * @namespace Util/Form/Extract/getDateValue\n */\nexport const getDateValue = (dateValue) => {\n try {\n const date = new Date(dateValue);\n const day = zeroBasedValue(date.getDate());\n const month = zeroBasedValue(date.getMonth() + 1);\n const year = date.getFullYear();\n const hours = zeroBasedValue(date.getHours());\n const minutes = zeroBasedValue(date.getMinutes());\n const seconds = zeroBasedValue(date.getSeconds());\n\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;\n } catch {\n return dateValue;\n }\n};\n\n/** @namespace Util/Form/Extract/calcYearRangeAttributes */\nexport const calcYearRangeAttributes = (startYear, endYear) => {\n const currentYear = new Date().getFullYear();\n\n // https://docs.magento.com/user-guide/stores/attribute-date-time-options.html\n // blank year range defaults to current year\n if (!startYear && !endYear) {\n return { minYear: currentYear, maxYear: currentYear };\n }\n\n // if start or end date is empty it defaults to current year\n // if it creates an invalid range, the only filled in year is used both as start and end of the range\n // e.g. `2020,` => `2020,2021`, `,2022` => `2021,2022`, `,2020` => `2020,2020`, `2022,` => `2022,2022`\n const minYear = startYear || (endYear && currentYear <= endYear ? currentYear : endYear);\n const maxYear = endYear || (startYear && currentYear >= startYear ? currentYear : startYear);\n\n return { minYear, maxYear };\n};\n\n/** @namespace Util/Form/Extract/getYearRangeAttributes */\nexport const getYearRangeAttributes = (yearRange = ',', isYear = false) => {\n const [startYear, endYear] = yearRange.split(',');\n\n const { minYear, maxYear } = calcYearRangeAttributes(startYear, endYear);\n\n if (isYear) {\n return { minYear, maxYear };\n }\n\n return {\n minDate: new Date(`${minYear}-01-01T00:00:00.000`),\n maxDate: new Date(`${maxYear}-12-31T23:59:59.999`)\n };\n};\n\n/** @namespace Util/Form/Extract/isMagentoDateFormatValid */\nexport const isMagentoDateFormatValid = (dateFieldsOrder) => new RegExp(Array(DATE_FIELDS_COUNT)\n .fill('[dmy]').join(','))\n .test(dateFieldsOrder);\n\n/** @namespace Util/Form/Extract/getTimeFormat */\nexport const getTimeFormat = (timeFormat) => (timeFormat === TIME_FORMAT.H12 ? 'h:mm aa' : 'HH:mm');\n\n/** @namespace Util/Form/Extract/getDateFormat */\nexport const getDateFormat = (dateFieldsOrder) => {\n if (!isMagentoDateFormatValid(dateFieldsOrder)) {\n return 'dd/MM/yyyy';\n }\n\n const dateMap = {\n d: 'dd',\n m: 'MM',\n y: 'yyyy'\n };\n\n return dateFieldsOrder.split(',').map((field) => dateMap[field]).join('/');\n};\n\n/** @namespace Util/Form/Extract/getDateTimeFormat */\nexport const getDateTimeFormat = (type, dateFieldsOrder, timeFormat) => {\n const timePart = type === FIELD_DATE_TYPE.time || type === FIELD_DATE_TYPE.dateTime\n ? getTimeFormat(timeFormat)\n : '';\n\n const datePart = type === FIELD_DATE_TYPE.date || type === FIELD_DATE_TYPE.dateTime\n ? getDateFormat(dateFieldsOrder)\n : '';\n\n return `${datePart } ${ timePart}`.trim();\n};\n\n/** @namespace Util/Form/Extract/adjustAmpmHours */\nexport const adjustAmpmHours = (hours, ampm) => {\n if (ampm === 'PM') {\n return (hours % HOURS_12H_COUNT) + HOURS_12H_COUNT;\n }\n\n if (ampm === 'AM') {\n return hours % HOURS_12H_COUNT;\n }\n\n return hours;\n};\n\n/** @namespace Util/Form/Extract/transformDateFieldsData */\nexport const transformDateFieldsData = (datesData) => Object.entries(datesData).reduce((prev, [name, data]) => {\n const {\n type,\n year,\n month,\n day,\n hours,\n minutes,\n ampm\n } = data;\n\n const hoursAdjusted = adjustAmpmHours(Number(hours), ampm);\n\n if (type === FIELD_DATE_TYPE.date && year && month && day) {\n return [...prev, {\n name,\n type,\n value: `${year}-${month}-${day} 00:00:00`\n }];\n }\n\n if (type === FIELD_DATE_TYPE.dateTime && year && month && day && hours && minutes) {\n return [...prev, {\n name,\n type,\n value: `${year}-${month}-${day} ${hoursAdjusted}:${minutes}:00`\n }];\n }\n\n if (type === FIELD_DATE_TYPE.time && hours && minutes) {\n return [...prev, {\n name,\n type,\n value: `2000-01-01 ${hoursAdjusted}:${minutes}:00`\n }];\n }\n\n return prev;\n}, []);\n\n/** @namespace Util/Form/Extract/groupDateFieldsData */\nexport const groupDateFieldsData = (fields) => Array.from(fields)\n .reduce((prev, field) => {\n const dataType = field.getAttribute(FIELD_TYPE_ATTR);\n\n if (!Object.values(FIELD_DATE_TYPE).includes(dataType)) {\n return prev;\n }\n\n const { name, value } = field;\n const fieldName = field.getAttribute(FIELD_NAME_ATTR);\n const { [name]: prevData } = prev;\n\n return {\n ...prev,\n [name]: {\n ...prevData,\n type: dataType,\n [fieldName]: value\n }\n };\n }, {});\n\n/**\n * Returns fields values from DOM/Form\n * @param DOM\n * @param excludeEmpty\n * @param ignoreTypes\n * @param asObject\n * @returns {{}|*[]}\n * @namespace Util/Form/Extract/getFieldsData\n */\nexport const getFieldsData = (DOM, excludeEmpty = false, ignoreTypes = [], asObject = false) => {\n const fields = DOM.querySelectorAll('input, textarea, select');\n const output = [];\n\n const dateFieldsGrouped = groupDateFieldsData(fields);\n\n output.push(...transformDateFieldsData(dateFieldsGrouped));\n\n fields.forEach((field) => {\n if (Object.values(FIELD_DATE_TYPE).includes(field.getAttribute(FIELD_TYPE_ATTR))) {\n return;\n }\n\n const { tagName } = field;\n const tag = tagName.toLowerCase();\n const type = tag === FIELD_TYPE.textarea || tag === FIELD_TYPE.select || tag === FIELD_TYPE.button\n ? tag : field.type;\n\n if (ignoreTypes.some((ignoreType) => ignoreType === type)) {\n return;\n }\n\n // eslint-disable-next-line no-nested-ternary\n const value = type === FIELD_TYPE.checkbox || type === FIELD_TYPE.radio\n // eslint-disable-next-line no-nested-ternary\n ? (field.checked ? field.value === 'on' ? true : field.value : false)\n : type === FIELD_TYPE.file\n ? field.fileData\n : field.value;\n\n const dateValue = field.getAttribute('data-date');\n const formattedValue = dateValue ? getDateValue(dateValue) : value;\n\n if (!excludeEmpty || value) {\n output.push({\n name: field.name,\n type,\n value: formattedValue,\n field\n });\n }\n });\n\n if (asObject) {\n const objectOutput = {};\n\n output.forEach((field) => {\n const { name } = field;\n\n objectOutput[name] = field;\n });\n\n return objectOutput;\n }\n\n return output;\n};\n\nexport default getFieldsData;\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport { default } from './TextPlaceholder.component';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport { default } from './Image.container';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport const ANIMATION_DURATION = 400;\nexport const ACTIVE_SLIDE_PERCENT = 0.1;\nexport const START_SLIDE_COUNT = 5;\nexport const SLIDE_TRANSFORM_CLICK_LIMIT = 10;\nexport const HEIGHT_TRANSITION_SPEED_ON_MOUNT = 300;\n","/**\n * @author Vladislavs Zimnikovs \n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package puma-mx\n */\n\nimport { CheckoutQuery as SourceQuery } from 'SourceQuery/Checkout.query';\nimport { Field } from 'Util/Query';\n\n/** @namespace Scandipwa/Query/Checkout/Query */\nexport class CheckoutQuery extends SourceQuery {\n _getOrderField() {\n return new Field('order')\n .addFieldList([\n 'id',\n 'order_id',\n 'redirectUrl',\n 'threeDS2',\n 'type',\n 'token',\n 'status_label'\n ]);\n }\n\n getStoreName() {\n return new Field('getEmailGeneralName');\n }\n\n getNewsletterSubscribeMutation(email, first_name, last_name) {\n const mutation = new Field('addEmailSubscriptionFromCheckout')\n .addArgument('email', 'String!', email)\n .addArgument('first_name', 'String!', first_name)\n .addArgument('last_name', 'String!', last_name);\n\n return mutation;\n }\n\n _getPaymentMethodFields() {\n return ['code', 'title', 'img_src'];\n }\n}\n\nexport default new CheckoutQuery();\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\nimport { FIELD_RADIO_NONE } from 'Component/Field/Field.config';\n\nexport const CONFIG_FIELD_TYPE = {\n text: 'field',\n radio: 'radio',\n checkbox: 'checkbox',\n textarea: 'area',\n select: 'drop_down',\n file: 'file',\n date: 'date',\n dateTime: 'date_time',\n time: 'time',\n multi: 'multiple'\n};\n\nexport const NONE_RADIO_OPTION = {\n title: __('None'),\n label: __('None'),\n uid: FIELD_RADIO_NONE,\n price: 0,\n finalOptionPrice: 0,\n can_change_quantity: false,\n priceInclTax: 0\n};\n\nexport default CONFIG_FIELD_TYPE;\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nimport PropTypes from 'prop-types';\n\nexport const LocationType = PropTypes.shape({\n pathname: PropTypes.string,\n search: PropTypes.string,\n // eslint-disable-next-line react/forbid-prop-types\n state: PropTypes.object,\n hash: PropTypes.string,\n key: PropTypes.string\n});\n\nexport const HistoryType = PropTypes.shape({\n length: PropTypes.number,\n action: PropTypes.string,\n location: LocationType\n});\n\nexport const MatchType = PropTypes.shape({\n path: PropTypes.string,\n url: PropTypes.string,\n // eslint-disable-next-line react/forbid-prop-types\n params: PropTypes.object,\n isExact: PropTypes.bool\n});\n\nexport const UrlRewriteType = PropTypes.shape({\n id: PropTypes.number,\n type: PropTypes.string,\n sku: PropTypes.string,\n notFound: PropTypes.bool\n});\n\nexport const LinkType = PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.shape({\n pathname: PropTypes.string\n })\n]);\n\nexport const NavigationStateType = PropTypes.shape(\n {\n name: PropTypes.string.isRequired,\n title: PropTypes.string\n }\n);\n\nexport const NavigationStateHistoryType = PropTypes.shape({\n navigationStateHistory: PropTypes.arrayOf(NavigationStateType),\n navigationState: NavigationStateType\n});\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nimport MyAccountQuery from 'Query/MyAccount.query';\nimport { updateCustomerDetails, updateCustomerSignInStatus } from 'SourceStore/MyAccount/MyAccount.action';\nimport {\n MyAccountDispatcher as SourceMyAccountDispatcher\n} from 'SourceStore/MyAccount/MyAccount.dispatcher';\nimport { updateIsLocked } from 'Store/MyAccount/MyAccount.action';\nimport { showNotification } from 'Store/Notification/Notification.action';\nimport { ORDERS } from 'Store/Order/Order.reducer';\nimport { clearComparedProducts } from 'Store/ProductCompare/ProductCompare.action';\nimport {\n deleteAuthorizationToken,\n getAuthorizationToken,\n GRAPHQL_AUTH,\n isSignedIn\n} from 'Util/Auth';\nimport BrowserDatabase from 'Util/BrowserDatabase';\nimport { deleteCartId } from 'Util/Cart';\nimport { removeUid } from 'Util/Compare';\nimport { prepareQuery } from 'Util/Query';\nimport { executePost, fetchMutation, getErrorMessage } from 'Util/Request';\nimport { appendWithStoreCode } from 'Util/Url';\n\nexport const CartDispatcher = import(\n /* webpackMode: \"lazy\", webpackChunkName: \"accountDispatchers\" */\n 'Store/Cart/Cart.dispatcher'\n);\n\nexport const WishlistDispatcher = import(\n /* webpackMode: \"lazy\", webpackChunkName: \"dispatchers\" */\n 'Store/Wishlist/Wishlist.dispatcher'\n);\n\nexport const ProductCompareDispatcher = import(\n /* webpackMode: \"lazy\", webpackChunkName: \"dispatchers\" */\n 'Store/ProductCompare/ProductCompare.dispatcher'\n);\n\nexport const CUSTOMER = 'customer';\n\nexport const ONE_MONTH_IN_SECONDS = 2628000;\n\n/**\n * My account actions\n * @class MyAccount\n * @namespace Scandipwa/Store/MyAccount/Dispatcher */\nexport class MyAccountDispatcher extends SourceMyAccountDispatcher {\n requestCustomerData(dispatch) {\n const query = MyAccountQuery.getCustomerQuery();\n\n const customer = BrowserDatabase.getItem(CUSTOMER) || {};\n if (customer.id) {\n dispatch(updateCustomerDetails(customer));\n }\n\n return executePost(prepareQuery([query])).then(\n /** @namespace Scandipwa/Store/MyAccount/Dispatcher/MyAccountDispatcher/requestCustomerData/executePost/then */\n ({ customer }) => {\n if (!getAuthorizationToken()) {\n return;\n }\n\n const customerData = this.mergePrevAndCurrentCustomerData(customer);\n dispatch(updateIsLocked(false));\n dispatch(updateCustomerDetails(customerData));\n BrowserDatabase.setItem(customerData, CUSTOMER, ONE_MONTH_IN_SECONDS);\n },\n /** @namespace Scandipwa/Store/MyAccount/Dispatcher/MyAccountDispatcher/requestCustomerData/executePost/then/catch */\n (error) => {\n const { extensions: { category } } = error[0];\n\n if (category === GRAPHQL_AUTH) {\n dispatch(updateIsLocked(true));\n }\n dispatch(showNotification('error', getErrorMessage(error)));\n\n if (window.location.href.includes('/customer/account')) {\n window.location.reload();\n } else {\n window.location.href = appendWithStoreCode('/customer/account');\n }\n }\n );\n }\n\n mergePrevAndCurrentCustomerData(customer) {\n const prevCustomerData = BrowserDatabase.getItem(CUSTOMER);\n const selectedAddressObject = {\n selectedAddressId: prevCustomerData?.selectedAddressId,\n selectedBillingId: prevCustomerData?.selectedBillingId\n };\n\n if (prevCustomerData && prevCustomerData.addresses && prevCustomerData.addresses.length > 0) {\n const tmpAddress = prevCustomerData.addresses.find((item) => item.id === -1);\n\n if (tmpAddress && !customer.addresses.find((item) => item.id === -1)) {\n return {\n ...customer,\n ...selectedAddressObject,\n addresses: [...customer.addresses, tmpAddress],\n newAddressId: -1\n };\n }\n\n return {\n ...customer,\n ...selectedAddressObject,\n newAddressId: prevCustomerData.newAddressId\n };\n }\n\n return { ...customer, ...selectedAddressObject };\n }\n\n logout(authTokenExpired = false, isWithNotification = true, dispatch) {\n if (authTokenExpired) {\n if (isWithNotification) {\n dispatch(showNotification('error', __('Your session is over, you are logged out!')));\n }\n\n this.handleForceRedirectToLoginPage();\n } else {\n if (isSignedIn()) {\n fetchMutation(MyAccountQuery.getRevokeAccountToken());\n deleteAuthorizationToken();\n }\n\n if (isWithNotification) {\n dispatch(showNotification('success', __('You are successfully logged out!')));\n }\n }\n\n deleteCartId();\n BrowserDatabase.deleteItem(ORDERS);\n BrowserDatabase.deleteItem(CUSTOMER);\n removeUid();\n\n dispatch(updateCustomerSignInStatus(false));\n dispatch(updateCustomerDetails({}));\n\n // After logout cart, wishlist and compared product list is always empty.\n // There is no need to fetch it from the backend.\n CartDispatcher.then(\n ({ default: dispatcher }) => {\n dispatcher.resetGuestCart(dispatch);\n dispatcher.createGuestEmptyCart(dispatch);\n }\n );\n WishlistDispatcher.then(\n ({ default: dispatcher }) => dispatcher.resetWishlist(dispatch)\n );\n\n dispatch(clearComparedProducts());\n dispatch(updateCustomerDetails({}));\n }\n}\n\nexport default new MyAccountDispatcher();\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport * from './Validator';\n","import {\n MyAccountQuery as SourceMyAccountQuery\n} from 'SourceQuery/MyAccount.query';\nimport { Field } from 'Util/Query';\n\n/**\n * MyAccount Mutations\n * @class MyAccount\n * @namespace Scandipwa/Query/MyAccount/Query */\nexport class MyAccountQuery extends SourceMyAccountQuery {\n _getCustomerFields() {\n return [\n 'created_at',\n 'confirmation_required',\n 'group_id',\n 'prefix',\n 'firstname',\n 'middlename',\n 'lastname',\n 'suffix',\n 'email',\n 'default_billing',\n 'default_shipping',\n 'dob',\n 'taxvat',\n 'id',\n 'is_subscribed',\n // Using alternate config key to prevent collisions with PWA core configuration\n 'is_subscribed_bool',\n this._getAddressesField()\n ];\n }\n\n getEmarsysPreferencesLink(email) {\n return new Field('EmarsysGetPreferences')\n .addArgument('email', 'String!', email);\n }\n}\n\nexport default new MyAccountQuery();\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport * from './Browser';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nexport * from 'SourceStore/Config/Config.action';\n\nexport const SET_SITE_BASE_LOADED = 'SET_SITE_BASE_LOADED';\n\n/** @namespace Scandipwa/Store/Config/Action/setSiteBaseLoaded */\nexport const setSiteBaseLoaded = () => ({\n type: SET_SITE_BASE_LOADED\n});\n","'use strict';\n\nfunction checkDCE() {\n /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\n if (\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'\n ) {\n return;\n }\n if (process.env.NODE_ENV !== 'production') {\n // This branch is unreachable because this function is only called\n // in production, but the condition is true only in development.\n // Therefore if the branch is still here, dead code elimination wasn't\n // properly applied.\n // Don't change the message. React DevTools relies on it. Also make sure\n // this message doesn't occur elsewhere in this function, or it will cause\n // a false positive.\n throw new Error('^_^');\n }\n try {\n // Verify that the code above has been dead code eliminated (DCE'd).\n __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);\n } catch (err) {\n // DevTools shouldn't crash React, no matter what.\n // We should still report in case we break this code.\n console.error(err);\n }\n}\n\nif (process.env.NODE_ENV === 'production') {\n // DCE check should happen before ReactDOM bundle executes so that\n // DevTools can report bad minification during injection.\n checkDCE();\n module.exports = require('./cjs/react-dom.production.min.js');\n} else {\n module.exports = require('./cjs/react-dom.development.js');\n}\n","/* eslint-disable no-restricted-globals,@scandipwa/scandipwa-guidelines/use-namespace */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nimport BrowserDatabase from 'Util/BrowserDatabase';\n\n// eslint-disable-next-line import/no-cycle\nimport ParentProduct from '../utils/Product';\n\nexport const SIZE_ATTRIBUTE = 'size';\nexport const GENDER_ATTRIBUTE = 'gender';\nexport const COLOR_ATTRIBUTE = 'color';\nexport const NOT_APPLICABLE = 'N/A';\nexport const GENDER_LIST = {\n 7850: 'Female',\n 4311: 'Unisex',\n 7849: 'Male',\n 4705: 'Girls',\n 4397: 'Men',\n 4298: 'Women'\n};\n\n/**\n * Product helper, contain all related to product data prepare methods\n */\nexport class Product extends ParentProduct {\n /**\n * Get item data as object\n *\n * @param item\n * @param category\n * @return {{item_id, affiliation: string, price: number, discount: *, item_name, item_category2: *, currency: *, item_category3: *, item_brand: string, item_category: *, item_variant}}\n */\n static getItemData(item, category = '') {\n if (item && Object.values(item).length) {\n const { product = {}, sku = '' } = item;\n const configurableVariantIndex = this.getSelectedVariantIndex(product, sku);\n\n return {\n ...this.getProductData({ ...product, configurableVariantIndex }, category),\n item_variant: sku\n };\n }\n\n return {};\n }\n\n static getAttribute(variant, parentAttributes, attributeName) {\n const {\n attribute_value: attribute_variant_value = ''\n } = variant?.attributes?.[attributeName] || {};\n const {\n attribute_value: attribute_product_value = '',\n attribute_options = {}\n } = parentAttributes[attributeName] || {};\n const attributeValue = attribute_variant_value || attribute_product_value;\n\n if (attributeName === GENDER_ATTRIBUTE) {\n const gender = variant.gender ? GENDER_LIST[variant.gender] : GENDER_LIST[attributeValue];\n\n return gender?.toLowerCase() || NOT_APPLICABLE;\n }\n\n const { label = NOT_APPLICABLE } = attribute_options[attributeValue] || {};\n\n return label.toLowerCase() || NOT_APPLICABLE;\n }\n\n /**\n * Get product data as object\n *\n * @param product\n * @param category\n * @return {{item_id, affiliation: string, price: number, discount: *, item_name, item_category2: *, currency: *, item_category3: *, item_brand: (string|string), item_category: *}}\n */\n static getProductData(product, category = '') {\n const {\n sku,\n name,\n type_id,\n variants = [],\n attributes = {},\n configurableVariantIndex = this.getSelectedVariantIndex(product, sku)\n } = product;\n const selectedVariant = variants[configurableVariantIndex] || product;\n\n return {\n item_id: sku,\n item_name: name,\n price: this.getPrice(selectedVariant, type_id),\n discount: this.getDiscount(selectedVariant),\n item_brand: category.toLowerCase(),\n item_category: this.getAttribute(selectedVariant, attributes, SIZE_ATTRIBUTE),\n item_category2: this.getAttribute(selectedVariant, attributes, GENDER_ATTRIBUTE),\n item_category3: this.getAttribute(selectedVariant, attributes, COLOR_ATTRIBUTE),\n currency: BrowserDatabase.getItem('cart_totals')?.prices?.quote_currency_code,\n affiliation: window.location.hostname\n };\n }\n\n /**\n * Get product discount\n *\n * @param product\n * @returns {*}\n */\n static getDiscount(product) {\n const productDiscount = product.price_range.minimum_price.discount;\n\n return productDiscount.amount_off || productDiscount.percent_off;\n }\n}\n\nexport default Product;\n","/* eslint-disable import/prefer-default-export */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport const LOADING_TIME = 500;\n\nexport const DISPLAY_MODE_PRODUCTS = 'PRODUCTS';\n\nexport const DISPLAY_MODE_CMS_BLOCK = 'PAGE';\n\nexport const DISPLAY_MODE_BOTH = 'PRODUCTS_AND_PAGE';\n\nexport const LAYOUT_KEY = 'layout';\nexport const GRID_LAYOUT = 'grid';\nexport const LIST_LAYOUT = 'list';\n\nexport const SORT_DIRECTION_TYPE = {\n asc: 'ASC',\n desc: 'DESC'\n};\n","export * from 'SourceRoute/CategoryPage/CategoryPage.config';\nexport const SCROLL_TO_TOP_TIMEOUT = 800;\nexport const PREVIOUS_CATEGORY_URL_COOKIE = 'previous_category_link';\nexport const ONLINE_FROM_ATTRIBUTE = 'online_from';\nexport const DEFAULT_ONLINE_FROM_DIRECTION = 'DESC';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport const LEFT = 'left';\nexport const RIGHT = 'right';\nexport const TOP = 'top';\nexport const BOTTOM = 'bottom';\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport const ADD_PRODUCT_TO_CART = 'ADD_PRODUCT_TO_CART';\nexport const REMOVE_PRODUCT_FROM_CART = 'REMOVE_PRODUCT_FROM_CART';\nexport const UPDATE_TOTALS = 'UPDATE_TOTALS';\nexport const APPLY_COUPON_TO_CART = 'APPLY_COUPON_TO_CART';\nexport const REMOVE_COUPON_FROM_CART = 'REMOVE_COUPON_FROM_CART';\nexport const UPDATE_SHIPPING_PRICE = 'UPDATE_SHIPPING_PRICE';\nexport const UPDATE_IS_LOADING_CART = 'UPDATE_IS_LOADING_CART';\n\n/**\n * Update product list with new list (rewrite if already exists).\n * @param {Array} items List of products returned from fetch\n * @param {Number} totalItems Total number of products in this filter\n * @return {void}\n * @namespace Store/Cart/Action/addProductToCart\n */\nexport const addProductToCart = (newProduct) => ({\n type: ADD_PRODUCT_TO_CART,\n newProduct\n});\n\n/**\n * Remove specified product from cart\n * @param {Object} product Product which should be removed\n * @return {void}\n * @namespace Store/Cart/Action/removeProductFromCart\n */\nexport const removeProductFromCart = (product) => ({\n type: REMOVE_PRODUCT_FROM_CART,\n product\n});\n\n/**\n * Update totals block\n * @param {Object} totals Object of calculated totals\n * @return {void}\n * @namespace Store/Cart/Action/updateTotals\n */\nexport const updateTotals = (cartData) => ({\n type: UPDATE_TOTALS,\n cartData\n});\n\n/**\n * Update shipment price in totals block\n * @param {Object} data\n * @return {void}\n * @namespace Store/Cart/Action/updateShippingPrice\n */\nexport const updateShippingPrice = (data) => ({\n type: UPDATE_SHIPPING_PRICE,\n data\n});\n\n/**\n * Apply coupon to cart\n * @param {String} string Coupon code\n * @return {void}\n * @namespace Store/Cart/Action/applyCouponToCart\n */\nexport const applyCouponToCart = (couponCode) => ({\n type: APPLY_COUPON_TO_CART,\n couponCode\n});\n\n/**\n * Remove coupon from cart\n * @return {void}\n * @namespace Store/Cart/Action/removeCouponFromCart\n */\nexport const removeCouponFromCart = () => ({\n type: REMOVE_COUPON_FROM_CART\n});\n\n/** @namespace Store/Cart/Action/updateIsLoadingCart */\nexport const updateIsLoadingCart = (isLoading) => ({\n type: UPDATE_IS_LOADING_CART,\n isLoading\n});\n","/* eslint-disable no-magic-numbers */\n/* eslint-disable max-lines */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nimport BrowserDatabase from 'Util/BrowserDatabase';\n\nimport { LOCALE_PATTERN } from '../../General.event';\n\nexport const PAGE_TYPE_PDP = 'pdp';\nexport const PAGE_TYPE_PRODUCT = 'product';\nexport const PAGE_TYPE_CATEGORY = 'category';\nexport const PAGE_TYPE_CHECKOUT = 'checkout';\nexport const PAGE_TYPE_ACCOUNT = 'customer_account';\nexport const PAGE_TYPE_ACCOUNT_ADD_ADDRESS = 'account_add_address';\nexport const PAGE_TYPE_CMS = 'cms-page';\nexport const PAGE_TYPE_CART = 'cart';\nexport const PAGE_TYPE_SEARCH = 'search';\nexport const PAGE_TYPE_HOME = 'home';\n\nexport const MOBILE_BP = 768;\nexport const TABLET_BP = 1024;\nexport const MOBILE_VIEWPORT = 'mobile';\nexport const TABLET_VIEWPORT = 'tablet';\nexport const DESKTOP_VIEWPORT = 'desktop';\n\nexport const PAGE_CART_UNIQUE_ID = 'checkout_cart_index';\nexport const PAGE_CHECKOUT_UNIQUE_ID = 'checkout_index_index';\nexport const PAGE_ACCOUNT_LOGIN_UNIQUE_ID = 'customer_account_login';\nexport const PAGE_ACCOUNT_DASHBOARD_UNIQUE_ID = 'customer_account_index';\nexport const PAGE_HOME_UNIQUE_ID = 'cms_index_index';\nexport const PAGE_CMS_UNIQUE_ID = 'cms_page_view';\nexport const PAGE_SITEMAP_UNIQUE_ID = 'sitemap_index_index';\n\nexport const UAE_SITE_NAME = 'ae shop';\nexport const KSA_SITE_NAME = 'sa shop';\nexport const MX_SITE_NAME = 'mx shop';\n\n/** @namespace Gtm/Component/GoogleTagManager/Events/PageDataEvent/Handlers/NavigationPageDataEvent/Handler */\nexport class NavigationPageDataEventHandler {\n // eslint-disable-next-line @scandipwa/scandipwa-guidelines/use-magic-construct\n constructor(appState, pageType, data) {\n const { specialPageType } = data;\n\n this.appState = appState;\n this.pageType = specialPageType || pageType;\n }\n\n pageTypeList = [\n {\n type: PAGE_TYPE_PDP,\n modifiedPageType: 'product detail'\n },\n {\n type: PAGE_TYPE_PRODUCT,\n modifiedPageType: 'product detail'\n },\n {\n type: PAGE_TYPE_CATEGORY,\n modifiedPageType: 'product listing'\n },\n {\n type: PAGE_TYPE_CHECKOUT,\n exceptionPageType: 'order confirmation',\n regex: /success|payment\\/verify|payment\\/*\\/success|tabby\\/result\\/success/\n },\n {\n type: PAGE_TYPE_ACCOUNT,\n modifiedPageType: 'account'\n },\n {\n type: PAGE_TYPE_ACCOUNT_ADD_ADDRESS,\n modifiedPageType: 'account'\n },\n {\n type: PAGE_TYPE_CMS,\n exceptionPageType: 'contact',\n regex: /contact-us/\n }\n ];\n\n modifiedSubSections = {\n [PAGE_TYPE_PDP]: {\n subSection1: 'product details'\n },\n [PAGE_TYPE_PRODUCT]: {\n subSection1: 'product details'\n },\n [PAGE_TYPE_CHECKOUT]: {\n subSection1: 'checkout'\n },\n [PAGE_TYPE_CART]: {\n subSection1: 'checkout'\n },\n [PAGE_TYPE_ACCOUNT]: {\n subSection1: 'account'\n },\n [PAGE_TYPE_ACCOUNT_ADD_ADDRESS]: {\n subSection1: 'account',\n subSection2: 'address'\n }\n };\n\n /**\n * Returns navigation object data for pageData object\n *\n * @returns {{pageType: (*), subSection3: string, subSection4: string, subSection1: string, subSection2: string, contentTitle: *, destinationURL: string, localLanguage: *}}\n */\n getNavigationData(data) {\n this.updateEventData(data);\n\n return {\n contentTitle: this.getContentTitle(),\n destinationURL: this.getDestinationUrl(),\n localLanguage: this.getLanguage(),\n pageType: this.getPageType() || this.pageType,\n currency: this.getCurrency(),\n environment: this.getEnvironment(),\n localeCountry: this.getLocaleCountry(),\n viewport: this.getViewport(),\n uniquePageId: this.getUniquePageId(),\n site: this.getSite(),\n releaseVersion: this.getReleaseVersion(),\n ...this.getSubSections()\n };\n }\n\n /**\n * Updates event object data for pageData object as it depends on pageType value\n *\n * @param data\n */\n updateEventData(data) {\n const {\n eventData = {},\n updateEventData\n } = data;\n\n eventData.eventType = this.getPageType() || this.pageType;\n\n if (updateEventData) {\n updateEventData(eventData);\n }\n }\n\n /**\n * Returns page type\n *\n * @returns {*}\n */\n getPageType() {\n const { location: pathname } = window;\n\n const pageType = this.pageTypeList.find(({ type }) => type === this.pageType) || {};\n\n const { regex, exceptionPageType, modifiedPageType } = pageType;\n\n if (regex && regex.test(pathname)) {\n return exceptionPageType;\n }\n\n return modifiedPageType;\n }\n\n /**\n * Returns the entire url where action is taking place\n *\n * @returns {string}\n */\n getDestinationUrl() {\n const { location: { href } } = window;\n\n return href;\n }\n\n /**\n * Returns store language\n *\n * @returns {*}\n */\n getLanguage() {\n const { ConfigReducer: { locale = '' } } = this.appState;\n const match = locale.match(LOCALE_PATTERN);\n\n return match && match[1] ? match[1] : '';\n }\n\n /**\n * Returns page currency\n *\n * @return {string}\n */\n getCurrency() {\n const {\n ConfigReducer: {\n default_display_currency_code\n }\n } = this.appState;\n\n return default_display_currency_code;\n }\n\n /**\n * Returns ENV type\n *\n * @return {string}\n */\n getEnvironment() {\n return process.env.NODE_ENV || 'development';\n }\n\n /**\n * Returns locale country\n *\n * @returns {string}\n */\n getLocaleCountry() {\n const {\n ConfigReducer: {\n default_country\n }\n } = this.appState;\n\n return default_country;\n }\n\n /**\n * Returns viewport type according to window width\n *\n * @returns {string}\n */\n getViewport() {\n const { innerWidth: windowWidth } = window;\n\n if (windowWidth < MOBILE_BP) {\n return MOBILE_VIEWPORT;\n }\n\n if (windowWidth < TABLET_BP) {\n return TABLET_VIEWPORT;\n }\n\n return DESKTOP_VIEWPORT;\n }\n\n /**\n * Return unique page id according to page type\n *\n * @returns {string}\n */\n getUniquePageId() {\n const {\n CategoryReducer: {\n category: {\n name: categoryName\n } = {}\n },\n ProductReducer: {\n product: {\n name: productName\n } = {}\n },\n UrlRewritesReducer: {\n urlRewrite: {\n id\n }\n }\n } = this.appState;\n\n switch (this.pageType) {\n case PAGE_TYPE_PDP:\n case PAGE_TYPE_PRODUCT:\n return productName;\n case PAGE_TYPE_CATEGORY:\n return categoryName;\n case PAGE_TYPE_ACCOUNT:\n // eslint-disable-next-line no-extra-boolean-cast\n return !!BrowserDatabase.getItem('auth_token') // Check if user is authorized\n ? PAGE_ACCOUNT_DASHBOARD_UNIQUE_ID\n : PAGE_ACCOUNT_LOGIN_UNIQUE_ID;\n case PAGE_TYPE_CART:\n return PAGE_CART_UNIQUE_ID;\n case PAGE_TYPE_CHECKOUT:\n return PAGE_CHECKOUT_UNIQUE_ID;\n case PAGE_TYPE_HOME:\n return PAGE_CMS_UNIQUE_ID;\n case PAGE_TYPE_CMS:\n return this.isPageSiteMap()\n ? PAGE_SITEMAP_UNIQUE_ID\n : `${PAGE_CMS_UNIQUE_ID}_page_id=${id}`;\n default:\n return this.pageType;\n }\n }\n\n /**\n * Returns site\n * PumaPWA - Should me MX_SITE_NAME for MX store\n *\n * @returns {string}\n */\n getSite() {\n const { ConfigReducer: { store_code = '' } } = this.appState;\n\n if (store_code.includes('ksa')) {\n return KSA_SITE_NAME;\n }\n\n return UAE_SITE_NAME;\n }\n\n /**\n * Returns release version - version number from a static files\n * Works only in production mode. For dev mode returns null\n *\n * @returns {string|null}\n */\n getReleaseVersion() {\n const { publicPath } = window;\n\n if (!publicPath || publicPath.length <= 1) {\n return null;\n }\n\n const regex = '/version(.*)/frontend';\n const versionNumber = publicPath.match(new RegExp(regex));\n\n return versionNumber?.[1];\n }\n\n /**\n * Returns content title\n *\n * @returns {*}\n */\n getContentTitle() {\n const {\n MetaReducer: {\n title\n },\n CategoryReducer: {\n category: {\n name: categoryName\n }\n },\n ProductReducer: {\n product: {\n name: productName\n }\n }\n } = this.appState;\n\n switch (this.pageType) {\n case PAGE_TYPE_PDP:\n case PAGE_TYPE_PRODUCT:\n return productName;\n case PAGE_TYPE_CATEGORY:\n return categoryName;\n default:\n return title;\n }\n }\n\n /**\n * Returns url subsections\n *\n * @returns {{subSection3: string, subSection4: string, subSection1: string, subSection2: string}}\n */\n getSubSections() {\n const { location: { pathname } } = window;\n const { ConfigReducer: { code } } = this.appState;\n\n const subSections = pathname.split('/').filter((pathname) => pathname !== code);\n const modifiedSubSections = this.modifiedSubSections[this.pageType];\n\n if (modifiedSubSections) {\n return modifiedSubSections;\n }\n\n return {\n subSection1: subSections[1] || '',\n subSection2: subSections[2] || '',\n subSection3: subSections[3] || '',\n subSection4: subSections[4] || ''\n };\n }\n\n /**\n * Return if current cms page is sitemap page\n *\n * @returns {boolean}\n */\n isPageSiteMap() {\n const { location: { pathname } } = window;\n\n return (new RegExp('sitemap')).test(pathname);\n }\n}\n\nexport default NavigationPageDataEventHandler;\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nexport const TYPE_PRODUCT = 'PRODUCT';\nexport const TYPE_CMS_PAGE = 'CMS_PAGE';\nexport const TYPE_CATEGORY = 'CATEGORY';\nexport const TYPE_NOTFOUND = 'NOT_FOUND';\n","/* eslint-disable @scandipwa/scandipwa-guidelines/no-arrow-functions-in-class */\n/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nimport { getAuthorizationToken, isSignedIn, refreshAuthorizationToken } from 'Util/Auth';\nimport { refreshUid } from 'Util/Compare';\nimport { getCurrency } from 'Util/Currency';\nimport { ONE_MONTH_IN_SECONDS } from 'Util/Request/QueryDispatcher';\n\nimport { hash } from './Hash';\n\nexport const GRAPHQL_URI = '/graphql';\nexport const WINDOW_ID = 'WINDOW_ID';\n\n/** @namespace Util/Request/getWindowId */\nexport const getWindowId = () => {\n const result = sessionStorage.getItem(WINDOW_ID);\n\n if (!result) {\n const id = Date.now();\n\n sessionStorage.setItem(WINDOW_ID, id);\n\n return id;\n }\n\n return result;\n};\n\n/** @namespace Util/Request/getStoreCodePath */\nexport const getStoreCodePath = () => {\n const path = location.pathname;\n // eslint-disable-next-line no-undef\n const firstPathPart = path.split('/')[1];\n\n if (window.storeList.includes(firstPathPart)) {\n return `/${ firstPathPart }`;\n }\n\n return '';\n};\n\n/** @namespace Util/Request/getGraphqlEndpoint */\nexport const getGraphqlEndpoint = () => getStoreCodePath().concat(GRAPHQL_URI);\n\n/**\n * Append authorization token to header object\n * @param {Object} headers\n * @returns {Object} Headers with appended authorization\n * @namespace Util/Request/appendTokenToHeaders\n */\nexport const appendTokenToHeaders = (headers) => {\n const token = getAuthorizationToken();\n\n return {\n ...headers,\n Authorization: token ? `Bearer ${token}` : ''\n };\n};\n\n/**\n *\n * @param {String} query Request body\n * @param {Object} variables Request variables\n * @param {String} url GraphQL url\n * @returns {*}\n * @namespace Util/Request/formatURI\n */\nexport const formatURI = (query, variables, url) => {\n // eslint-disable-next-line no-param-reassign\n variables._currency = getCurrency();\n\n const stringifyVariables = Object.keys(variables).reduce(\n (acc, variable) => [...acc, `${ variable }=${ JSON.stringify(variables[variable]) }`],\n [`?hash=${ hash(query) }`]\n );\n\n return `${ url }${ stringifyVariables.join('&') }`;\n};\n\n/**\n *\n * @param {String} uri\n * @param {String} name\n * @returns {Promise}\n * @namespace Util/Request/getFetch\n */\nexport const getFetch = (uri, name, signal) => fetch(uri,\n {\n method: 'GET',\n signal,\n headers: appendTokenToHeaders({\n 'Content-Type': 'application/json',\n 'Application-Model': `${ name }_${ getWindowId() }`,\n Accept: 'application/json'\n })\n });\n\n/**\n *\n * @param {String} graphQlURI\n * @param {{}} query Request body\n * @param {Int} cacheTTL\n * @namespace Util/Request/putPersistedQuery\n */\nexport const putPersistedQuery = (graphQlURI, query, cacheTTL) => fetch(`${ graphQlURI }?hash=${ hash(query) }`,\n {\n method: 'PUT',\n body: JSON.stringify(query),\n headers: {\n 'Content-Type': 'application/json',\n 'SW-Cache-Age': Number.isInteger(cacheTTL) ? cacheTTL : ONE_MONTH_IN_SECONDS\n }\n });\n\n/**\n *\n * @param {String} graphQlURI\n * @param {String} queryObject\n * @param {String} name\n * @returns {Promise}\n * @namespace Util/Request/postFetch\n */\nexport const postFetch = (graphQlURI, query, variables) => fetch(graphQlURI,\n {\n method: 'POST',\n body: JSON.stringify({ query, variables }),\n headers: appendTokenToHeaders({\n 'Content-Type': 'application/json',\n Accept: 'application/json'\n })\n });\n\n/**\n * Checks for errors in response, if they exist, rejects promise\n * @param {Object} res Response from GraphQL endpoint\n * @return {Promise} Handled GraphqlQL results promise\n * @namespace Util/Request/checkForErrors\n */\nexport const checkForErrors = (res) => new Promise((resolve, reject) => {\n const { errors, data } = res;\n\n return errors ? reject(errors) : resolve(data);\n});\n\n/**\n * Handle connection errors\n * @param {any} err Error from fetch\n * @return {void} Simply console error\n * @namespace Util/Request/handleConnectionError\n */\nexport const handleConnectionError = (err, msg) => {\n // eslint-disable-next-line no-console\n console.error(msg, err);\n}; // TODO: Add to logs pool\n\n/**\n * Parse response and check wether it contains errors\n * @param {{}} queryObject prepared with `prepareDocument()` from `Util/Query` request body object\n * @return {Promise} Fetch promise to GraphQL endpoint\n * @namespace Util/Request/parseResponse\n */\nexport const parseResponse = async (response) => {\n try {\n const data = await response.json();\n\n return checkForErrors(data);\n } catch (err) {\n handleConnectionError(err, 'Can not parse JSON!');\n\n throw err;\n }\n};\n\nexport const HTTP_503_SERVICE_UNAVAILABLE = 503;\nexport const HTTP_410_GONE = 410;\nexport const HTTP_201_CREATED = 201;\n\n/**\n * Make GET request to endpoint (via ServiceWorker)\n * @param {{}} queryObject prepared with `prepareDocument()` from `Util/Query` request body object\n * @param {String} name Name of model for ServiceWorker to send BroadCasts updates to\n * @param {Number} cacheTTL Cache TTL (in seconds) for ServiceWorker to cache responses\n * @return {Promise} Fetch promise to GraphQL endpoint\n * @namespace Util/Request/executeGet\n */\nexport const executeGet = async (queryObject, name, cacheTTL, signal) => {\n const { query, variables } = queryObject;\n const uri = formatURI(query, variables, getGraphqlEndpoint());\n\n if (isSignedIn()) {\n refreshAuthorizationToken();\n refreshUid();\n }\n\n // Fetch only throws on network error, http errors have to be handled manually.\n try {\n const result = await getFetch(uri, name, signal);\n\n if (result.status === HTTP_410_GONE) {\n const putResponse = await putPersistedQuery(getGraphqlEndpoint(), query, cacheTTL);\n\n if (putResponse.status === HTTP_201_CREATED) {\n return parseResponse(await getFetch(uri, name, signal));\n }\n }\n\n if (result.status === HTTP_503_SERVICE_UNAVAILABLE) {\n handleConnectionError(result.status, result.statusText);\n throw new Error(result.statusText);\n }\n\n // Successful and all other http responses go here:\n return parseResponse(result);\n } catch (error) {\n // Network error\n handleConnectionError(error, 'executeGet failed');\n throw new Error(error);\n }\n};\n\n/**\n * Make POST request to endpoint\n * @param {{}} queryObject prepared with `prepareDocument()` from `Util/Query` request body object\n * @return {Promise} Fetch promise to GraphQL endpoint\n * @namespace Util/Request/executePost\n */\nexport const executePost = async (queryObject) => {\n const { query, variables } = queryObject;\n\n if (isSignedIn()) {\n refreshAuthorizationToken();\n refreshUid();\n }\n\n try {\n const response = await postFetch(getGraphqlEndpoint(), query, variables);\n\n return parseResponse(response);\n } catch (err) {\n handleConnectionError(err, 'executePost failed');\n\n throw new Error(err);\n }\n};\n\n/**\n * Listen to the BroadCast connection\n * @param {String} name Name of model for ServiceWorker to send BroadCasts updates to\n * @return {Promise} Broadcast message promise\n * @namespace Util/Request/listenForBroadCast\n */\nexport const listenForBroadCast = (name) => new Promise((resolve) => {\n const { BroadcastChannel } = window;\n const windowId = getWindowId();\n\n if (BroadcastChannel) {\n const bc = new BroadcastChannel(`${ name }_${ windowId }`);\n\n bc.onmessage = (update) => {\n const { data: { payload: body } } = update;\n\n resolve(checkForErrors(body));\n };\n }\n});\n\n/** @namespace Util/Request/debounce */\nexport const debounce = (callback, delay) => {\n // eslint-disable-next-line fp/no-let\n let timeout;\n\n return (...args) => {\n const context = this;\n\n clearTimeout(timeout);\n timeout = setTimeout(() => callback.apply(context, args), delay);\n };\n};\n\n/** @namespace Util/Request */\nexport class Debouncer {\n timeout;\n\n handler = () => {};\n\n startDebounce = (callback, delay) => (...args) => {\n const context = this;\n\n clearTimeout(this.timeout);\n this.handler = () => callback.apply(context, args);\n this.timeout = setTimeout(this.handler, delay);\n };\n\n cancelDebounce = () => {\n clearTimeout(this.timeout);\n };\n\n cancelDebounceAndExecuteImmediately = () => {\n clearTimeout(this.timeout);\n this.handler();\n };\n}\n","function isAbsolute(pathname) {\n return pathname.charAt(0) === '/';\n}\n\n// About 1.5x faster than the two-arg version of Array#splice()\nfunction spliceOne(list, index) {\n for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) {\n list[i] = list[k];\n }\n\n list.pop();\n}\n\n// This implementation is based heavily on node's url.parse\nfunction resolvePathname(to, from) {\n if (from === undefined) from = '';\n\n var toParts = (to && to.split('/')) || [];\n var fromParts = (from && from.split('/')) || [];\n\n var isToAbs = to && isAbsolute(to);\n var isFromAbs = from && isAbsolute(from);\n var mustEndAbs = isToAbs || isFromAbs;\n\n if (to && isAbsolute(to)) {\n // to is absolute\n fromParts = toParts;\n } else if (toParts.length) {\n // to is relative, drop the filename\n fromParts.pop();\n fromParts = fromParts.concat(toParts);\n }\n\n if (!fromParts.length) return '/';\n\n var hasTrailingSlash;\n if (fromParts.length) {\n var last = fromParts[fromParts.length - 1];\n hasTrailingSlash = last === '.' || last === '..' || last === '';\n } else {\n hasTrailingSlash = false;\n }\n\n var up = 0;\n for (var i = fromParts.length; i >= 0; i--) {\n var part = fromParts[i];\n\n if (part === '.') {\n spliceOne(fromParts, i);\n } else if (part === '..') {\n spliceOne(fromParts, i);\n up++;\n } else if (up) {\n spliceOne(fromParts, i);\n up--;\n }\n }\n\n if (!mustEndAbs) for (; up--; up) fromParts.unshift('..');\n\n if (\n mustEndAbs &&\n fromParts[0] !== '' &&\n (!fromParts[0] || !isAbsolute(fromParts[0]))\n )\n fromParts.unshift('');\n\n var result = fromParts.join('/');\n\n if (hasTrailingSlash && result.substr(-1) !== '/') result += '/';\n\n return result;\n}\n\nexport default resolvePathname;\n","function valueOf(obj) {\n return obj.valueOf ? obj.valueOf() : Object.prototype.valueOf.call(obj);\n}\n\nfunction valueEqual(a, b) {\n // Test for strict equality first.\n if (a === b) return true;\n\n // Otherwise, if either of them == null they are not equal.\n if (a == null || b == null) return false;\n\n if (Array.isArray(a)) {\n return (\n Array.isArray(b) &&\n a.length === b.length &&\n a.every(function(item, index) {\n return valueEqual(item, b[index]);\n })\n );\n }\n\n if (typeof a === 'object' || typeof b === 'object') {\n var aValue = valueOf(a);\n var bValue = valueOf(b);\n\n if (aValue !== a || bValue !== b) return valueEqual(aValue, bValue);\n\n return Object.keys(Object.assign({}, a, b)).every(function(key) {\n return valueEqual(a[key], b[key]);\n });\n }\n\n return false;\n}\n\nexport default valueEqual;\n","import _extends from '@babel/runtime/helpers/esm/extends';\nimport resolvePathname from 'resolve-pathname';\nimport valueEqual from 'value-equal';\nimport warning from 'tiny-warning';\nimport invariant from 'tiny-invariant';\n\nfunction addLeadingSlash(path) {\n return path.charAt(0) === '/' ? path : '/' + path;\n}\nfunction stripLeadingSlash(path) {\n return path.charAt(0) === '/' ? path.substr(1) : path;\n}\nfunction hasBasename(path, prefix) {\n return path.toLowerCase().indexOf(prefix.toLowerCase()) === 0 && '/?#'.indexOf(path.charAt(prefix.length)) !== -1;\n}\nfunction stripBasename(path, prefix) {\n return hasBasename(path, prefix) ? path.substr(prefix.length) : path;\n}\nfunction stripTrailingSlash(path) {\n return path.charAt(path.length - 1) === '/' ? path.slice(0, -1) : path;\n}\nfunction parsePath(path) {\n var pathname = path || '/';\n var search = '';\n var hash = '';\n var hashIndex = pathname.indexOf('#');\n\n if (hashIndex !== -1) {\n hash = pathname.substr(hashIndex);\n pathname = pathname.substr(0, hashIndex);\n }\n\n var searchIndex = pathname.indexOf('?');\n\n if (searchIndex !== -1) {\n search = pathname.substr(searchIndex);\n pathname = pathname.substr(0, searchIndex);\n }\n\n return {\n pathname: pathname,\n search: search === '?' ? '' : search,\n hash: hash === '#' ? '' : hash\n };\n}\nfunction createPath(location) {\n var pathname = location.pathname,\n search = location.search,\n hash = location.hash;\n var path = pathname || '/';\n if (search && search !== '?') path += search.charAt(0) === '?' ? search : \"?\" + search;\n if (hash && hash !== '#') path += hash.charAt(0) === '#' ? hash : \"#\" + hash;\n return path;\n}\n\nfunction createLocation(path, state, key, currentLocation) {\n var location;\n\n if (typeof path === 'string') {\n // Two-arg form: push(path, state)\n location = parsePath(path);\n location.state = state;\n } else {\n // One-arg form: push(location)\n location = _extends({}, path);\n if (location.pathname === undefined) location.pathname = '';\n\n if (location.search) {\n if (location.search.charAt(0) !== '?') location.search = '?' + location.search;\n } else {\n location.search = '';\n }\n\n if (location.hash) {\n if (location.hash.charAt(0) !== '#') location.hash = '#' + location.hash;\n } else {\n location.hash = '';\n }\n\n if (state !== undefined && location.state === undefined) location.state = state;\n }\n\n try {\n location.pathname = decodeURI(location.pathname);\n } catch (e) {\n if (e instanceof URIError) {\n throw new URIError('Pathname \"' + location.pathname + '\" could not be decoded. ' + 'This is likely caused by an invalid percent-encoding.');\n } else {\n throw e;\n }\n }\n\n if (key) location.key = key;\n\n if (currentLocation) {\n // Resolve incomplete/relative pathname relative to current location.\n if (!location.pathname) {\n location.pathname = currentLocation.pathname;\n } else if (location.pathname.charAt(0) !== '/') {\n location.pathname = resolvePathname(location.pathname, currentLocation.pathname);\n }\n } else {\n // When there is no prior location and pathname is empty, set it to /\n if (!location.pathname) {\n location.pathname = '/';\n }\n }\n\n return location;\n}\nfunction locationsAreEqual(a, b) {\n return a.pathname === b.pathname && a.search === b.search && a.hash === b.hash && a.key === b.key && valueEqual(a.state, b.state);\n}\n\nfunction createTransitionManager() {\n var prompt = null;\n\n function setPrompt(nextPrompt) {\n process.env.NODE_ENV !== \"production\" ? warning(prompt == null, 'A history supports only one prompt at a time') : void 0;\n prompt = nextPrompt;\n return function () {\n if (prompt === nextPrompt) prompt = null;\n };\n }\n\n function confirmTransitionTo(location, action, getUserConfirmation, callback) {\n // TODO: If another transition starts while we're still confirming\n // the previous one, we may end up in a weird state. Figure out the\n // best way to handle this.\n if (prompt != null) {\n var result = typeof prompt === 'function' ? prompt(location, action) : prompt;\n\n if (typeof result === 'string') {\n if (typeof getUserConfirmation === 'function') {\n getUserConfirmation(result, callback);\n } else {\n process.env.NODE_ENV !== \"production\" ? warning(false, 'A history needs a getUserConfirmation function in order to use a prompt message') : void 0;\n callback(true);\n }\n } else {\n // Return false from a transition hook to cancel the transition.\n callback(result !== false);\n }\n } else {\n callback(true);\n }\n }\n\n var listeners = [];\n\n function appendListener(fn) {\n var isActive = true;\n\n function listener() {\n if (isActive) fn.apply(void 0, arguments);\n }\n\n listeners.push(listener);\n return function () {\n isActive = false;\n listeners = listeners.filter(function (item) {\n return item !== listener;\n });\n };\n }\n\n function notifyListeners() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n listeners.forEach(function (listener) {\n return listener.apply(void 0, args);\n });\n }\n\n return {\n setPrompt: setPrompt,\n confirmTransitionTo: confirmTransitionTo,\n appendListener: appendListener,\n notifyListeners: notifyListeners\n };\n}\n\nvar canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);\nfunction getConfirmation(message, callback) {\n callback(window.confirm(message)); // eslint-disable-line no-alert\n}\n/**\n * Returns true if the HTML5 history API is supported. Taken from Modernizr.\n *\n * https://github.com/Modernizr/Modernizr/blob/master/LICENSE\n * https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js\n * changed to avoid false negatives for Windows Phones: https://github.com/reactjs/react-router/issues/586\n */\n\nfunction supportsHistory() {\n var ua = window.navigator.userAgent;\n if ((ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) && ua.indexOf('Mobile Safari') !== -1 && ua.indexOf('Chrome') === -1 && ua.indexOf('Windows Phone') === -1) return false;\n return window.history && 'pushState' in window.history;\n}\n/**\n * Returns true if browser fires popstate on hash change.\n * IE10 and IE11 do not.\n */\n\nfunction supportsPopStateOnHashChange() {\n return window.navigator.userAgent.indexOf('Trident') === -1;\n}\n/**\n * Returns false if using go(n) with hash history causes a full page reload.\n */\n\nfunction supportsGoWithoutReloadUsingHash() {\n return window.navigator.userAgent.indexOf('Firefox') === -1;\n}\n/**\n * Returns true if a given popstate event is an extraneous WebKit event.\n * Accounts for the fact that Chrome on iOS fires real popstate events\n * containing undefined state when pressing the back button.\n */\n\nfunction isExtraneousPopstateEvent(event) {\n return event.state === undefined && navigator.userAgent.indexOf('CriOS') === -1;\n}\n\nvar PopStateEvent = 'popstate';\nvar HashChangeEvent = 'hashchange';\n\nfunction getHistoryState() {\n try {\n return window.history.state || {};\n } catch (e) {\n // IE 11 sometimes throws when accessing window.history.state\n // See https://github.com/ReactTraining/history/pull/289\n return {};\n }\n}\n/**\n * Creates a history object that uses the HTML5 history API including\n * pushState, replaceState, and the popstate event.\n */\n\n\nfunction createBrowserHistory(props) {\n if (props === void 0) {\n props = {};\n }\n\n !canUseDOM ? process.env.NODE_ENV !== \"production\" ? invariant(false, 'Browser history needs a DOM') : invariant(false) : void 0;\n var globalHistory = window.history;\n var canUseHistory = supportsHistory();\n var needsHashChangeListener = !supportsPopStateOnHashChange();\n var _props = props,\n _props$forceRefresh = _props.forceRefresh,\n forceRefresh = _props$forceRefresh === void 0 ? false : _props$forceRefresh,\n _props$getUserConfirm = _props.getUserConfirmation,\n getUserConfirmation = _props$getUserConfirm === void 0 ? getConfirmation : _props$getUserConfirm,\n _props$keyLength = _props.keyLength,\n keyLength = _props$keyLength === void 0 ? 6 : _props$keyLength;\n var basename = props.basename ? stripTrailingSlash(addLeadingSlash(props.basename)) : '';\n\n function getDOMLocation(historyState) {\n var _ref = historyState || {},\n key = _ref.key,\n state = _ref.state;\n\n var _window$location = window.location,\n pathname = _window$location.pathname,\n search = _window$location.search,\n hash = _window$location.hash;\n var path = pathname + search + hash;\n process.env.NODE_ENV !== \"production\" ? warning(!basename || hasBasename(path, basename), 'You are attempting to use a basename on a page whose URL path does not begin ' + 'with the basename. Expected path \"' + path + '\" to begin with \"' + basename + '\".') : void 0;\n if (basename) path = stripBasename(path, basename);\n return createLocation(path, state, key);\n }\n\n function createKey() {\n return Math.random().toString(36).substr(2, keyLength);\n }\n\n var transitionManager = createTransitionManager();\n\n function setState(nextState) {\n _extends(history, nextState);\n\n history.length = globalHistory.length;\n transitionManager.notifyListeners(history.location, history.action);\n }\n\n function handlePopState(event) {\n // Ignore extraneous popstate events in WebKit.\n if (isExtraneousPopstateEvent(event)) return;\n handlePop(getDOMLocation(event.state));\n }\n\n function handleHashChange() {\n handlePop(getDOMLocation(getHistoryState()));\n }\n\n var forceNextPop = false;\n\n function handlePop(location) {\n if (forceNextPop) {\n forceNextPop = false;\n setState();\n } else {\n var action = 'POP';\n transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {\n if (ok) {\n setState({\n action: action,\n location: location\n });\n } else {\n revertPop(location);\n }\n });\n }\n }\n\n function revertPop(fromLocation) {\n var toLocation = history.location; // TODO: We could probably make this more reliable by\n // keeping a list of keys we've seen in sessionStorage.\n // Instead, we just default to 0 for keys we don't know.\n\n var toIndex = allKeys.indexOf(toLocation.key);\n if (toIndex === -1) toIndex = 0;\n var fromIndex = allKeys.indexOf(fromLocation.key);\n if (fromIndex === -1) fromIndex = 0;\n var delta = toIndex - fromIndex;\n\n if (delta) {\n forceNextPop = true;\n go(delta);\n }\n }\n\n var initialLocation = getDOMLocation(getHistoryState());\n var allKeys = [initialLocation.key]; // Public interface\n\n function createHref(location) {\n return basename + createPath(location);\n }\n\n function push(path, state) {\n process.env.NODE_ENV !== \"production\" ? warning(!(typeof path === 'object' && path.state !== undefined && state !== undefined), 'You should avoid providing a 2nd state argument to push when the 1st ' + 'argument is a location-like object that already has state; it is ignored') : void 0;\n var action = 'PUSH';\n var location = createLocation(path, state, createKey(), history.location);\n transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {\n if (!ok) return;\n var href = createHref(location);\n var key = location.key,\n state = location.state;\n\n if (canUseHistory) {\n globalHistory.pushState({\n key: key,\n state: state\n }, null, href);\n\n if (forceRefresh) {\n window.location.href = href;\n } else {\n var prevIndex = allKeys.indexOf(history.location.key);\n var nextKeys = allKeys.slice(0, prevIndex + 1);\n nextKeys.push(location.key);\n allKeys = nextKeys;\n setState({\n action: action,\n location: location\n });\n }\n } else {\n process.env.NODE_ENV !== \"production\" ? warning(state === undefined, 'Browser history cannot push state in browsers that do not support HTML5 history') : void 0;\n window.location.href = href;\n }\n });\n }\n\n function replace(path, state) {\n process.env.NODE_ENV !== \"production\" ? warning(!(typeof path === 'object' && path.state !== undefined && state !== undefined), 'You should avoid providing a 2nd state argument to replace when the 1st ' + 'argument is a location-like object that already has state; it is ignored') : void 0;\n var action = 'REPLACE';\n var location = createLocation(path, state, createKey(), history.location);\n transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {\n if (!ok) return;\n var href = createHref(location);\n var key = location.key,\n state = location.state;\n\n if (canUseHistory) {\n globalHistory.replaceState({\n key: key,\n state: state\n }, null, href);\n\n if (forceRefresh) {\n window.location.replace(href);\n } else {\n var prevIndex = allKeys.indexOf(history.location.key);\n if (prevIndex !== -1) allKeys[prevIndex] = location.key;\n setState({\n action: action,\n location: location\n });\n }\n } else {\n process.env.NODE_ENV !== \"production\" ? warning(state === undefined, 'Browser history cannot replace state in browsers that do not support HTML5 history') : void 0;\n window.location.replace(href);\n }\n });\n }\n\n function go(n) {\n globalHistory.go(n);\n }\n\n function goBack() {\n go(-1);\n }\n\n function goForward() {\n go(1);\n }\n\n var listenerCount = 0;\n\n function checkDOMListeners(delta) {\n listenerCount += delta;\n\n if (listenerCount === 1 && delta === 1) {\n window.addEventListener(PopStateEvent, handlePopState);\n if (needsHashChangeListener) window.addEventListener(HashChangeEvent, handleHashChange);\n } else if (listenerCount === 0) {\n window.removeEventListener(PopStateEvent, handlePopState);\n if (needsHashChangeListener) window.removeEventListener(HashChangeEvent, handleHashChange);\n }\n }\n\n var isBlocked = false;\n\n function block(prompt) {\n if (prompt === void 0) {\n prompt = false;\n }\n\n var unblock = transitionManager.setPrompt(prompt);\n\n if (!isBlocked) {\n checkDOMListeners(1);\n isBlocked = true;\n }\n\n return function () {\n if (isBlocked) {\n isBlocked = false;\n checkDOMListeners(-1);\n }\n\n return unblock();\n };\n }\n\n function listen(listener) {\n var unlisten = transitionManager.appendListener(listener);\n checkDOMListeners(1);\n return function () {\n checkDOMListeners(-1);\n unlisten();\n };\n }\n\n var history = {\n length: globalHistory.length,\n action: 'POP',\n location: initialLocation,\n createHref: createHref,\n push: push,\n replace: replace,\n go: go,\n goBack: goBack,\n goForward: goForward,\n block: block,\n listen: listen\n };\n return history;\n}\n\nvar HashChangeEvent$1 = 'hashchange';\nvar HashPathCoders = {\n hashbang: {\n encodePath: function encodePath(path) {\n return path.charAt(0) === '!' ? path : '!/' + stripLeadingSlash(path);\n },\n decodePath: function decodePath(path) {\n return path.charAt(0) === '!' ? path.substr(1) : path;\n }\n },\n noslash: {\n encodePath: stripLeadingSlash,\n decodePath: addLeadingSlash\n },\n slash: {\n encodePath: addLeadingSlash,\n decodePath: addLeadingSlash\n }\n};\n\nfunction stripHash(url) {\n var hashIndex = url.indexOf('#');\n return hashIndex === -1 ? url : url.slice(0, hashIndex);\n}\n\nfunction getHashPath() {\n // We can't use window.location.hash here because it's not\n // consistent across browsers - Firefox will pre-decode it!\n var href = window.location.href;\n var hashIndex = href.indexOf('#');\n return hashIndex === -1 ? '' : href.substring(hashIndex + 1);\n}\n\nfunction pushHashPath(path) {\n window.location.hash = path;\n}\n\nfunction replaceHashPath(path) {\n window.location.replace(stripHash(window.location.href) + '#' + path);\n}\n\nfunction createHashHistory(props) {\n if (props === void 0) {\n props = {};\n }\n\n !canUseDOM ? process.env.NODE_ENV !== \"production\" ? invariant(false, 'Hash history needs a DOM') : invariant(false) : void 0;\n var globalHistory = window.history;\n var canGoWithoutReload = supportsGoWithoutReloadUsingHash();\n var _props = props,\n _props$getUserConfirm = _props.getUserConfirmation,\n getUserConfirmation = _props$getUserConfirm === void 0 ? getConfirmation : _props$getUserConfirm,\n _props$hashType = _props.hashType,\n hashType = _props$hashType === void 0 ? 'slash' : _props$hashType;\n var basename = props.basename ? stripTrailingSlash(addLeadingSlash(props.basename)) : '';\n var _HashPathCoders$hashT = HashPathCoders[hashType],\n encodePath = _HashPathCoders$hashT.encodePath,\n decodePath = _HashPathCoders$hashT.decodePath;\n\n function getDOMLocation() {\n var path = decodePath(getHashPath());\n process.env.NODE_ENV !== \"production\" ? warning(!basename || hasBasename(path, basename), 'You are attempting to use a basename on a page whose URL path does not begin ' + 'with the basename. Expected path \"' + path + '\" to begin with \"' + basename + '\".') : void 0;\n if (basename) path = stripBasename(path, basename);\n return createLocation(path);\n }\n\n var transitionManager = createTransitionManager();\n\n function setState(nextState) {\n _extends(history, nextState);\n\n history.length = globalHistory.length;\n transitionManager.notifyListeners(history.location, history.action);\n }\n\n var forceNextPop = false;\n var ignorePath = null;\n\n function locationsAreEqual$$1(a, b) {\n return a.pathname === b.pathname && a.search === b.search && a.hash === b.hash;\n }\n\n function handleHashChange() {\n var path = getHashPath();\n var encodedPath = encodePath(path);\n\n if (path !== encodedPath) {\n // Ensure we always have a properly-encoded hash.\n replaceHashPath(encodedPath);\n } else {\n var location = getDOMLocation();\n var prevLocation = history.location;\n if (!forceNextPop && locationsAreEqual$$1(prevLocation, location)) return; // A hashchange doesn't always == location change.\n\n if (ignorePath === createPath(location)) return; // Ignore this change; we already setState in push/replace.\n\n ignorePath = null;\n handlePop(location);\n }\n }\n\n function handlePop(location) {\n if (forceNextPop) {\n forceNextPop = false;\n setState();\n } else {\n var action = 'POP';\n transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {\n if (ok) {\n setState({\n action: action,\n location: location\n });\n } else {\n revertPop(location);\n }\n });\n }\n }\n\n function revertPop(fromLocation) {\n var toLocation = history.location; // TODO: We could probably make this more reliable by\n // keeping a list of paths we've seen in sessionStorage.\n // Instead, we just default to 0 for paths we don't know.\n\n var toIndex = allPaths.lastIndexOf(createPath(toLocation));\n if (toIndex === -1) toIndex = 0;\n var fromIndex = allPaths.lastIndexOf(createPath(fromLocation));\n if (fromIndex === -1) fromIndex = 0;\n var delta = toIndex - fromIndex;\n\n if (delta) {\n forceNextPop = true;\n go(delta);\n }\n } // Ensure the hash is encoded properly before doing anything else.\n\n\n var path = getHashPath();\n var encodedPath = encodePath(path);\n if (path !== encodedPath) replaceHashPath(encodedPath);\n var initialLocation = getDOMLocation();\n var allPaths = [createPath(initialLocation)]; // Public interface\n\n function createHref(location) {\n var baseTag = document.querySelector('base');\n var href = '';\n\n if (baseTag && baseTag.getAttribute('href')) {\n href = stripHash(window.location.href);\n }\n\n return href + '#' + encodePath(basename + createPath(location));\n }\n\n function push(path, state) {\n process.env.NODE_ENV !== \"production\" ? warning(state === undefined, 'Hash history cannot push state; it is ignored') : void 0;\n var action = 'PUSH';\n var location = createLocation(path, undefined, undefined, history.location);\n transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {\n if (!ok) return;\n var path = createPath(location);\n var encodedPath = encodePath(basename + path);\n var hashChanged = getHashPath() !== encodedPath;\n\n if (hashChanged) {\n // We cannot tell if a hashchange was caused by a PUSH, so we'd\n // rather setState here and ignore the hashchange. The caveat here\n // is that other hash histories in the page will consider it a POP.\n ignorePath = path;\n pushHashPath(encodedPath);\n var prevIndex = allPaths.lastIndexOf(createPath(history.location));\n var nextPaths = allPaths.slice(0, prevIndex + 1);\n nextPaths.push(path);\n allPaths = nextPaths;\n setState({\n action: action,\n location: location\n });\n } else {\n process.env.NODE_ENV !== \"production\" ? warning(false, 'Hash history cannot PUSH the same path; a new entry will not be added to the history stack') : void 0;\n setState();\n }\n });\n }\n\n function replace(path, state) {\n process.env.NODE_ENV !== \"production\" ? warning(state === undefined, 'Hash history cannot replace state; it is ignored') : void 0;\n var action = 'REPLACE';\n var location = createLocation(path, undefined, undefined, history.location);\n transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {\n if (!ok) return;\n var path = createPath(location);\n var encodedPath = encodePath(basename + path);\n var hashChanged = getHashPath() !== encodedPath;\n\n if (hashChanged) {\n // We cannot tell if a hashchange was caused by a REPLACE, so we'd\n // rather setState here and ignore the hashchange. The caveat here\n // is that other hash histories in the page will consider it a POP.\n ignorePath = path;\n replaceHashPath(encodedPath);\n }\n\n var prevIndex = allPaths.indexOf(createPath(history.location));\n if (prevIndex !== -1) allPaths[prevIndex] = path;\n setState({\n action: action,\n location: location\n });\n });\n }\n\n function go(n) {\n process.env.NODE_ENV !== \"production\" ? warning(canGoWithoutReload, 'Hash history go(n) causes a full page reload in this browser') : void 0;\n globalHistory.go(n);\n }\n\n function goBack() {\n go(-1);\n }\n\n function goForward() {\n go(1);\n }\n\n var listenerCount = 0;\n\n function checkDOMListeners(delta) {\n listenerCount += delta;\n\n if (listenerCount === 1 && delta === 1) {\n window.addEventListener(HashChangeEvent$1, handleHashChange);\n } else if (listenerCount === 0) {\n window.removeEventListener(HashChangeEvent$1, handleHashChange);\n }\n }\n\n var isBlocked = false;\n\n function block(prompt) {\n if (prompt === void 0) {\n prompt = false;\n }\n\n var unblock = transitionManager.setPrompt(prompt);\n\n if (!isBlocked) {\n checkDOMListeners(1);\n isBlocked = true;\n }\n\n return function () {\n if (isBlocked) {\n isBlocked = false;\n checkDOMListeners(-1);\n }\n\n return unblock();\n };\n }\n\n function listen(listener) {\n var unlisten = transitionManager.appendListener(listener);\n checkDOMListeners(1);\n return function () {\n checkDOMListeners(-1);\n unlisten();\n };\n }\n\n var history = {\n length: globalHistory.length,\n action: 'POP',\n location: initialLocation,\n createHref: createHref,\n push: push,\n replace: replace,\n go: go,\n goBack: goBack,\n goForward: goForward,\n block: block,\n listen: listen\n };\n return history;\n}\n\nfunction clamp(n, lowerBound, upperBound) {\n return Math.min(Math.max(n, lowerBound), upperBound);\n}\n/**\n * Creates a history object that stores locations in memory.\n */\n\n\nfunction createMemoryHistory(props) {\n if (props === void 0) {\n props = {};\n }\n\n var _props = props,\n getUserConfirmation = _props.getUserConfirmation,\n _props$initialEntries = _props.initialEntries,\n initialEntries = _props$initialEntries === void 0 ? ['/'] : _props$initialEntries,\n _props$initialIndex = _props.initialIndex,\n initialIndex = _props$initialIndex === void 0 ? 0 : _props$initialIndex,\n _props$keyLength = _props.keyLength,\n keyLength = _props$keyLength === void 0 ? 6 : _props$keyLength;\n var transitionManager = createTransitionManager();\n\n function setState(nextState) {\n _extends(history, nextState);\n\n history.length = history.entries.length;\n transitionManager.notifyListeners(history.location, history.action);\n }\n\n function createKey() {\n return Math.random().toString(36).substr(2, keyLength);\n }\n\n var index = clamp(initialIndex, 0, initialEntries.length - 1);\n var entries = initialEntries.map(function (entry) {\n return typeof entry === 'string' ? createLocation(entry, undefined, createKey()) : createLocation(entry, undefined, entry.key || createKey());\n }); // Public interface\n\n var createHref = createPath;\n\n function push(path, state) {\n process.env.NODE_ENV !== \"production\" ? warning(!(typeof path === 'object' && path.state !== undefined && state !== undefined), 'You should avoid providing a 2nd state argument to push when the 1st ' + 'argument is a location-like object that already has state; it is ignored') : void 0;\n var action = 'PUSH';\n var location = createLocation(path, state, createKey(), history.location);\n transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {\n if (!ok) return;\n var prevIndex = history.index;\n var nextIndex = prevIndex + 1;\n var nextEntries = history.entries.slice(0);\n\n if (nextEntries.length > nextIndex) {\n nextEntries.splice(nextIndex, nextEntries.length - nextIndex, location);\n } else {\n nextEntries.push(location);\n }\n\n setState({\n action: action,\n location: location,\n index: nextIndex,\n entries: nextEntries\n });\n });\n }\n\n function replace(path, state) {\n process.env.NODE_ENV !== \"production\" ? warning(!(typeof path === 'object' && path.state !== undefined && state !== undefined), 'You should avoid providing a 2nd state argument to replace when the 1st ' + 'argument is a location-like object that already has state; it is ignored') : void 0;\n var action = 'REPLACE';\n var location = createLocation(path, state, createKey(), history.location);\n transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {\n if (!ok) return;\n history.entries[history.index] = location;\n setState({\n action: action,\n location: location\n });\n });\n }\n\n function go(n) {\n var nextIndex = clamp(history.index + n, 0, history.entries.length - 1);\n var action = 'POP';\n var location = history.entries[nextIndex];\n transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {\n if (ok) {\n setState({\n action: action,\n location: location,\n index: nextIndex\n });\n } else {\n // Mimic the behavior of DOM histories by\n // causing a render after a cancelled POP.\n setState();\n }\n });\n }\n\n function goBack() {\n go(-1);\n }\n\n function goForward() {\n go(1);\n }\n\n function canGo(n) {\n var nextIndex = history.index + n;\n return nextIndex >= 0 && nextIndex < history.entries.length;\n }\n\n function block(prompt) {\n if (prompt === void 0) {\n prompt = false;\n }\n\n return transitionManager.setPrompt(prompt);\n }\n\n function listen(listener) {\n return transitionManager.appendListener(listener);\n }\n\n var history = {\n length: entries.length,\n action: 'POP',\n location: entries[index],\n index: index,\n entries: entries,\n createHref: createHref,\n push: push,\n replace: replace,\n go: go,\n goBack: goBack,\n goForward: goForward,\n canGo: canGo,\n block: block,\n listen: listen\n };\n return history;\n}\n\nexport { createBrowserHistory, createHashHistory, createMemoryHistory, createLocation, locationsAreEqual, parsePath, createPath };\n","/* eslint-disable max-lines */\n/* eslint-disable consistent-return */\n// eslint-disable @scandipwa/scandipwa-guidelines/no-duplicate-namespaces\n\n/**\n * @author Vladislavs Zimnikovs \n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package puma-mx\n */\n\nimport { IS_CART_RESET, SHOULD_RESET_CART } from 'Component/CheckoutSuccess/CheckoutSuccess.container';\nimport CartQuery from 'Query/Cart.query';\nimport { ORDER_ID_KEY } from 'Route/Checkout/Checkout.config';\nimport {\n CartDispatcher as SourceCartDispatcher\n} from 'SourceStore/Cart/Cart.dispatcher';\nimport { setPromosData } from 'Store/Analytics/Analytics.action';\nimport { updateIsLoadingCart } from 'Store/Cart/Cart.action';\nimport { CART_TOTALS } from 'Store/Cart/Cart.reducer';\nimport { updateEmail, updateShippingFields } from 'Store/Checkout/Checkout.action';\nimport { PAYMENT_TOTALS } from 'Store/Checkout/Checkout.dispatcher';\nimport { showNotification } from 'Store/Notification/Notification.action';\nimport { getAuthorizationToken, isSignedIn } from 'Util/Auth';\nimport BrowserDatabase from 'Util/BrowserDatabase';\nimport { getCartId } from 'Util/Cart';\nimport { fetchMutation, fetchQuery, getErrorMessage } from 'Util/Request';\nimport getStore from 'Util/Store';\n\nimport {\n CHECKOUTCOM_PAGEDATA_ORDER_STORAGE,\n CHECKOUTCOM_PAYMENT_TOTALS_STORAGE\n} from '../../../packages/@scandipwa/checkoutcom/src/plugin/Checkout.container.plugin';\nimport {\n TABBY_PAGEDATA_ORDER_STORAGE,\n TABBY_PAYMENT_TOTALS_STORAGE\n} from '../../../packages/@scandipwa/tabby/src/plugin/Checkout.container.plugin';\nimport {\n TAMARA_PAGEDATA_ORDER_STORAGE,\n TAMARA_PAYMENT_TOTALS_STORAGE\n} from '../../../packages/@scandipwa/tamara/src/plugin/Checkout.container.plugin';\n\nexport const GUEST_QUOTE_ID = 'guest_quote_id';\n\n/** @namespace Scandipwa/Store/Cart/Dispatcher */\nexport class CartDispatcher extends SourceCartDispatcher {\n async addProductToCart(dispatch, options = {}) {\n const { products = [], cartId: userCartId } = options;\n\n const cartId = userCartId || getCartId();\n\n if (!Array.isArray(products) || products.length === 0) {\n dispatch(showNotification('error', __('No product data!')));\n\n return Promise.reject();\n }\n\n try {\n if (!cartId) {\n return Promise.reject();\n }\n\n const { addProductsToCart: { user_errors: errors = [] } = {} } = await fetchMutation(\n CartQuery.getAddProductToCartMutation(cartId, products)\n );\n\n if (Array.isArray(errors) && errors.length > 0) {\n errors.forEach((error) => {\n dispatch(showNotification('error', __(getErrorMessage(error))));\n });\n\n return Promise.reject();\n }\n\n await this.updateInitialCartData(dispatch);\n } catch (error) {\n if (!navigator.onLine) {\n dispatch(showNotification('error', __('Not possible to fetch while offline')));\n\n return Promise.reject();\n }\n\n dispatch(showNotification('error', __(getErrorMessage(error))));\n\n return Promise.reject();\n }\n\n return Promise.resolve();\n }\n\n async applyCouponToCart(dispatch, couponCode, onShippingEstimationFieldsChange, saveAddressInformation) {\n const isCustomerSignedIn = isSignedIn();\n const cartId = getCartId();\n\n if (!isCustomerSignedIn && !cartId) {\n return false;\n }\n\n const callback = (getCouponData, cartData) => {\n this._updateCartData(cartData, dispatch);\n dispatch(showNotification('success', __('Coupon was applied!')));\n dispatch(setPromosData(getCouponData));\n };\n\n return fetchMutation(CartQuery.getApplyCouponMutation(\n couponCode, cartId\n )).then(\n /** @namespace Scandipwa/Store/Cart/Dispatcher/CartDispatcher/applyCouponToCart/fetchMutation/then */\n ({ applyCouponToCart: { cartData, getCouponData } }) => {\n if (onShippingEstimationFieldsChange && saveAddressInformation) {\n return onShippingEstimationFieldsChange(\n this.prepareCouponAddress()\n ).then(\n /** @namespace Scandipwa/Store/Cart/Dispatcher/CartDispatcher/applyCouponToCart/fetchMutation/then/onShippingEstimationFieldsChange/then */\n () => {\n callback(getCouponData, cartData);\n return true;\n }, /** @namespace Scandipwa/Store/Cart/Dispatcher/CartDispatcher/applyCouponToCart/fetchMutation/then/onShippingEstimationFieldsChange/then/catch */\n (error) => {\n dispatch(showNotification('error', error[0].message));\n return false;\n }\n );\n }\n\n callback(getCouponData, cartData);\n return true;\n },\n /** @namespace Scandipwa/Store/Cart/Dispatcher/CartDispatcher/applyCouponToCart/fetchMutation/then/catch */\n (error) => {\n dispatch(showNotification('error', error[0].message));\n return false;\n }\n );\n }\n\n async removeCouponFromCart(dispatch, onShippingEstimationFieldsChange, saveAddressInformation) {\n const isCustomerSignedIn = isSignedIn();\n const cartId = getCartId();\n\n if (!isCustomerSignedIn && !cartId) {\n return;\n }\n\n const callback = (cartData) => {\n this._updateCartData(cartData, dispatch);\n dispatch(showNotification('success', __('Coupon was removed!')));\n dispatch(setPromosData({}));\n };\n\n return fetchMutation(CartQuery.getRemoveCouponMutation(\n cartId\n )).then(\n /** @namespace Scandipwa/Store/Cart/Dispatcher/CartDispatcher/removeCouponFromCart/fetchMutation/then */\n ({ removeCouponFromCart: { cartData } }) => {\n if (onShippingEstimationFieldsChange && saveAddressInformation) {\n return onShippingEstimationFieldsChange(\n this.prepareCouponAddress()\n ).then(\n /** @namespace Scandipwa/Store/Cart/Dispatcher/CartDispatcher/removeCouponFromCart/fetchMutation/then/onShippingEstimationFieldsChange/then */\n () => {\n callback(cartData);\n }\n );\n }\n\n callback(cartData);\n },\n /** @namespace Scandipwa/Store/Cart/Dispatcher/CartDispatcher/removeCouponFromCart/fetchMutation/then/dispatch/catch */\n (error) => dispatch(showNotification('error', error[0].message))\n );\n }\n\n prepareCouponAddress() {\n const {\n ConfigReducer: { default_country },\n MyAccountReducer: { customer: signedCustomer }\n } = getStore().getState();\n const { addresses, selectedAddressId } = signedCustomer;\n\n if (isSignedIn() && selectedAddressId) {\n const selectedAddress = addresses.find(({ id }) => id === selectedAddressId);\n\n if (selectedAddress) {\n const {\n city,\n postcode,\n region: { region, region_id }\n } = selectedAddress;\n\n return {\n city,\n country_id: default_country,\n region_id,\n region,\n postcode\n };\n }\n }\n\n return {\n city: '',\n country_id: default_country,\n region_id: 0,\n region: '',\n postcode: ''\n };\n }\n\n isVariantOutOfStock(variants, sku) {\n const index = variants.findIndex(({ product: { sku: vSku } }) => sku === vSku);\n\n if (index !== -1) {\n return variants[index].product.stock_status === 'OUT_OF_STOCK';\n }\n\n return true;\n }\n\n removeOutdatedItems(data, dispatch) {\n const { pathname } = window.location;\n\n if (/checkout|tabby|tamara/.test(pathname)) {\n return;\n }\n\n try {\n const { items = [] } = data;\n\n items.map((item) => {\n if (\n (item.product.type_id === 'configurable'\n && item.product.variants.length === 0)\n || this.isVariantOutOfStock(item.product.variants, item.sku)\n ) {\n return fetchMutation(CartQuery.getRemoveCartItemMutation(\n item.id,\n getCartId()\n )).then(\n /** @namespace Scandipwa/Store/Cart/Dispatcher/CartDispatcher/removeOutdatedItems/items/map/fetchMutation/then */\n ({ removeItemFromCart: { cartData } }) => {\n this._updateCartData(cartData, dispatch);\n dispatch(showNotification(\n 'info',\n `Product ${item.product.name} was removed from the cart, as it is not longer available`\n ));\n },\n /** @namespace Scandipwa/Store/Cart/Dispatcher/CartDispatcher/removeOutdatedItems/items/map/fetchMutation/then/dispatch/catch */\n (error) => dispatch(showNotification('error', error[0].message))\n );\n }\n\n return null;\n });\n } catch (error) {\n // Do nothing\n }\n }\n\n async updateInitialCartData(dispatch, isForCustomer = false, disableLoader = false, isInitRequest = false) {\n try {\n if (!disableLoader) {\n dispatch(updateIsLoadingCart(true));\n }\n\n const { pathname } = window.location;\n const shouldResetCart = BrowserDatabase.getItem(SHOULD_RESET_CART);\n\n if (/checkout_com\\/payment\\/fail/.test(pathname) && !shouldResetCart) {\n return;\n }\n\n if (/tabby\\/result\\/cancel|tabby\\/result\\/failure/.test(pathname) && !shouldResetCart) {\n return;\n }\n\n if (/tamara\\/payment\\/.+\\/cancel|tamara\\/payment\\/.+\\/failure/.test(pathname) && !shouldResetCart) {\n return;\n }\n\n if (shouldResetCart) {\n BrowserDatabase.deleteItem(SHOULD_RESET_CART);\n BrowserDatabase.deleteItem(ORDER_ID_KEY);\n BrowserDatabase.deleteItem(CHECKOUTCOM_PAYMENT_TOTALS_STORAGE);\n BrowserDatabase.deleteItem(CHECKOUTCOM_PAGEDATA_ORDER_STORAGE);\n BrowserDatabase.deleteItem(TAMARA_PAGEDATA_ORDER_STORAGE);\n BrowserDatabase.deleteItem(TAMARA_PAYMENT_TOTALS_STORAGE);\n BrowserDatabase.deleteItem(TABBY_PAGEDATA_ORDER_STORAGE);\n BrowserDatabase.deleteItem(TABBY_PAYMENT_TOTALS_STORAGE);\n BrowserDatabase.deleteItem(PAYMENT_TOTALS);\n BrowserDatabase.deleteItem(GUEST_QUOTE_ID);\n BrowserDatabase.deleteItem(CART_TOTALS);\n BrowserDatabase.setItem(1, IS_CART_RESET);\n }\n\n if (/tamara\\/payment\\/.+\\/success/.test(pathname) && isInitRequest) {\n return;\n }\n\n const quoteId = await this._getCartId(dispatch);\n const {\n cartData = {},\n cartData: {\n is_virtual = false,\n shipping_address: {\n selected_shipping_method: {\n address,\n address: {\n street = null,\n email = ''\n } = {}\n } = {},\n method_code\n } = {}\n } = {}\n } = await fetchQuery(\n CartQuery.getCartQuery(\n quoteId\n )\n );\n\n if (address && street) {\n if (!is_virtual) {\n await dispatch(\n updateShippingFields({\n ...this.prepareCheckoutAddressFormat(address),\n method_code\n })\n );\n }\n\n await dispatch(updateEmail(email));\n }\n\n if (isForCustomer && !getAuthorizationToken()) {\n dispatch(updateIsLoadingCart(false));\n\n return null;\n }\n\n await this._updateCartData(cartData, dispatch);\n await this.removeOutdatedItems(cartData, dispatch);\n\n if (!disableLoader) {\n dispatch(updateIsLoadingCart(false));\n }\n\n return null;\n } catch (error) {\n dispatch(updateIsLoadingCart(false));\n\n if (isInitRequest) {\n if (!isSignedIn()) {\n return this.createGuestEmptyCart(dispatch);\n }\n }\n\n return null;\n }\n }\n}\n\nexport default new CartDispatcher();\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/scandipwa\n * @link https://github.com/scandipwa/scandipwa\n */\n\nimport PropTypes from 'prop-types';\n\nimport { VALIDATION_INPUT_TYPE } from 'Util/Validator/Config';\n\nexport const LabelType = PropTypes.oneOfType([PropTypes.string, PropTypes.node]);\n\nexport const OptionType = PropTypes.shape({\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n label: LabelType,\n value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])\n});\n\nexport const CustomErrorMessagesType = PropTypes.shape({\n onRequirementFail: PropTypes.string,\n onInputTypeFail: PropTypes.string,\n onMatchFail: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),\n onRangeFailMin: PropTypes.string,\n onRangeFailMax: PropTypes.string,\n onExtensionFail: PropTypes.string\n});\n\nexport const ValidationRuleType = PropTypes.shape({\n isRequired: PropTypes.bool,\n inputType: PropTypes.oneOf(Object.values(VALIDATION_INPUT_TYPE)),\n match: PropTypes.func,\n customErrorMessages: CustomErrorMessagesType\n});\n\nexport const EventsType = PropTypes.objectOf(PropTypes.func);\n\nexport const FieldAttrType = PropTypes.object;\n\nexport const FieldOptionsType = PropTypes.arrayOf(\n PropTypes.shape({\n id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n label: LabelType,\n value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])\n })\n);\n\nexport const ValuesShape = PropTypes.shape({\n value: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),\n type: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),\n name: PropTypes.oneOfType([PropTypes.string, PropTypes.bool])\n});\n\nexport const ErrorMessageShape = PropTypes.shape({\n injectables: PropTypes.arrayOf(PropTypes.string),\n value: PropTypes.string\n});\n\nexport const errorFieldShape = PropTypes.arrayOf(PropTypes.shape({\n errorMessages: PropTypes.arrayOf(ErrorMessageShape),\n ...ValuesShape\n}));\n\nexport const FieldGroupValidationResponseType = PropTypes.oneOfType([PropTypes.shape({\n errorFields: PropTypes.arrayOf(errorFieldShape),\n errorMessages: PropTypes.arrayOf(ErrorMessageShape),\n values: PropTypes.arrayOf(ValuesShape)\n}), PropTypes.bool]);\n\nexport const DateType = PropTypes.oneOfType([PropTypes.number, PropTypes.string]);\n","/**\n * @author Vladislavs Zimnikovs \n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package puma-mx\n */\n\nimport { CartQuery as SourceQuery } from 'SourceQuery/Cart.query';\nimport Field from 'Util/Query/Field';\n\n/** @namespace Scandipwa/Query/Cart/Query */\nexport class CartQuery extends SourceQuery {\n getApplyCouponMutation(couponCode, quoteId) {\n const input = {\n cart_id: quoteId,\n coupon_code: couponCode\n };\n\n return new Field('applyCouponToCart')\n .addArgument('input', 'ApplyCouponToCartInput', input)\n .addField(this._getCouponDataFields(couponCode))\n .addField(this._getCart());\n }\n\n getCouponDataQuery(couponCode) {\n return this._getCouponDataFields(couponCode);\n }\n\n _getCouponDataFields(couponCode) {\n return new Field('getCouponData')\n .addArgument('couponCode', 'String!', couponCode)\n .addFieldList(['id', 'code', 'name', 'type', 'amount']);\n }\n\n _getPricesFields() {\n return [\n ...super._getPricesFields(),\n 'shipping_incl_tax'\n ];\n }\n\n _getCartItemFields() {\n return [\n 'qty',\n 'sku',\n 'price',\n 'price_incl_tax',\n 'item_id',\n 'row_total',\n 'row_total_incl_tax',\n 'tax_amount',\n 'tax_percent',\n 'discount_amount',\n 'discount_percent',\n 'base_row_total_incl_tax',\n this._getCustomizableOptionsFields(),\n this._getBundleOptionsField(),\n this._getProductField()\n ];\n }\n}\n\nexport default new CartQuery();\n","/**\n * ScandiPWA - Progressive Web App for Magento\n *\n * Copyright © Scandiweb, Inc. All rights reserved.\n * See LICENSE for license details.\n *\n * @license OSL-3.0 (Open Software License (\"OSL\") v. 3.0)\n * @package scandipwa/base-theme\n * @link https://github.com/scandipwa/base-theme\n */\n\nimport { isEventEnabled, isFakeCheckoutPage } from '../EventConfig';\n\n/**\n * Event utility\n *\n * Should be used only for data collecting or 3'rd service integration.\n * For React internal data flows use react specified data flows architecture\n * @namespace Gtm/Util/Event\n */\nexport class Event {\n /**\n * Dispatch global event\n *\n * @param name Event name\n * @param data Object of passed data to event observer\n *\n * @return {boolean}\n */\n static dispatch(name, data = {}) {\n if (!isEventEnabled(name) || isFakeCheckoutPage()) {\n return false;\n }\n\n window.dispatchEvent(new CustomEvent(name, { detail: data }));\n\n return true;\n }\n\n /**\n * Event observer\n * Returns callback wrapper as observer identity\n *\n * @param name Event name\n * @param callback Observer callback\n *\n * @return {function|boolean}\n */\n static observer(name, callback) {\n if (callback && typeof callback === 'function' && isEventEnabled(name)) {\n const callbackWrapper = ({ detail: data }) => {\n callback.call(this, data);\n };\n\n window.addEventListener(name, callbackWrapper, false);\n\n return callbackWrapper;\n }\n\n return false;\n }\n\n /**\n * Remove event observer for defined listener\n *\n * @param name Event name\n * @param listener Callback used for observer (function)\n *\n * @return {boolean}\n */\n static removeObserver(name, listener) {\n if (!isEventEnabled(name)) {\n return false;\n }\n\n window.removeEventListener(name, listener, false);\n\n return true;\n }\n}\n\nexport default Event;\n","var attributesToProps = require('./attributes-to-props');\nvar utilities = require('./utilities');\n\n/**\n * Converts DOM nodes to React elements.\n *\n * @param {DomElement[]} nodes - The DOM nodes.\n * @param {Object} [options={}] - The additional options.\n * @param {Function} [options.replace] - The replacer.\n * @param {Object} [options.library] - The library (React, Preact, etc.).\n * @return {String|ReactElement|ReactElement[]}\n */\nfunction domToReact(nodes, options) {\n options = options || {};\n\n var React = options.library || require('react');\n var cloneElement = React.cloneElement;\n var createElement = React.createElement;\n var isValidElement = React.isValidElement;\n\n var result = [];\n var node;\n var hasReplace = typeof options.replace === 'function';\n var replaceElement;\n var props;\n var children;\n var data;\n var trim = options.trim;\n\n for (var i = 0, len = nodes.length; i < len; i++) {\n node = nodes[i];\n\n // replace with custom React element (if present)\n if (hasReplace) {\n replaceElement = options.replace(node);\n\n if (isValidElement(replaceElement)) {\n // set \"key\" prop for sibling elements\n // https://fb.me/react-warning-keys\n if (len > 1) {\n replaceElement = cloneElement(replaceElement, {\n key: replaceElement.key || i\n });\n }\n result.push(replaceElement);\n continue;\n }\n }\n\n if (node.type === 'text') {\n // if trim option is enabled, skip whitespace text nodes\n if (trim) {\n data = node.data.trim();\n if (data) {\n result.push(node.data);\n }\n } else {\n result.push(node.data);\n }\n continue;\n }\n\n props = node.attribs;\n if (!shouldPassAttributesUnaltered(node)) {\n props = attributesToProps(node.attribs);\n }\n\n children = null;\n\n switch (node.type) {\n case 'script':\n case 'style':\n // prevent text in