@shopgate/pwa-common
Version:
Common library for the Shopgate Connect PWA.
164 lines (157 loc) • 5.36 kB
JavaScript
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { embeddedMedia, configuration } from '@shopgate/engage/core/collections';
import { CONFIGURATION_COLLECTION_KEY_UNIVERSAL_LINK_HANDLER } from '@shopgate/engage/core/constants';
import EmbeddedMedia from "../EmbeddedMedia";
import parseHTML from "../../helpers/html/parseHTML";
import connect from "./connector";
/**
* Checks if a link is a universal link.
* @param {string} link The link to check.
* @returns {boolean} True if the link is a universal link, false otherwise.
*/
import { jsx as _jsx } from "react/jsx-runtime";
const isUniversalLink = link => link.startsWith('http://') || link.startsWith('https://');
/**
* HtmlSanitizer component.
*/
let HtmlSanitizer = /*#__PURE__*/function (_Component) {
/**
* @param {Object} props The component props.
*/
function HtmlSanitizer(props) {
var _this;
_this = _Component.call(this, props) || this;
/**
* If the user tapped a link element, prevent the default behavior.
* @param {Object} event The touchstart event.
*/
_this.handleClick = event => {
// Prevent multiple clicks on links while the first one is still being processed.
if (_this.state.openingLink) {
event.preventDefault();
return;
}
_this.setState({
openingLink: true
});
const linkTag = event.target.closest('a');
if (!linkTag) return;
const href = linkTag.getAttribute('href');
const target = linkTag.getAttribute('target') || '';
if (!href) return;
event.preventDefault();
/**
* Runs async logic to open links to potentially resolve universal links.
*/
const openLink = async () => {
const universalLinkHandler = configuration.get(CONFIGURATION_COLLECTION_KEY_UNIVERSAL_LINK_HANDLER);
let link = href;
// If the universalLinkHandler is registered by an extension and the link looks like a
// qualified URL, we try to resolve it as a universal link.
if (typeof universalLinkHandler === 'function' && isUniversalLink(link)) {
const {
redirectLink = null,
handled = false
} = (await universalLinkHandler({
link
})) ?? {};
if (handled) {
_this.setState({
openingLink: false
});
return;
}
if (redirectLink) {
link = redirectLink;
}
}
_this.setState({
openingLink: false
});
if (!link) {
return;
}
if (_this.props.settings.handleClick) {
_this.props.settings.handleClick(link, target);
} else {
_this.props.navigate(link, target);
}
};
openLink();
};
_this.htmlContainer = /*#__PURE__*/React.createRef();
_this.state = {
openingLink: false
};
return _this;
}
/**
* Registers the event handler for when the user taps inside the html content.
*/
_inheritsLoose(HtmlSanitizer, _Component);
var _proto = HtmlSanitizer.prototype;
_proto.componentDidMount = function componentDidMount() {
embeddedMedia.add(this.htmlContainer.current);
}
/**
* Only update if the HTML changed.
* @param {Object} nextProps The next props for the component.
* @return {boolean}
*/;
_proto.shouldComponentUpdate = function shouldComponentUpdate(nextProps) {
return nextProps.children !== this.props.children || nextProps.comfortCookiesAccepted !== this.props.comfortCookiesAccepted || nextProps.statisticsCookiesAccepted !== this.props.statisticsCookiesAccepted;
}
/**
* Updates embedded media within the html container.
*/;
_proto.componentDidUpdate = function componentDidUpdate() {
embeddedMedia.add(this.htmlContainer.current);
}
/**
* Removes the event handler.
*/;
_proto.componentWillUnmount = function componentWillUnmount() {
embeddedMedia.remove(this.htmlContainer.current);
};
/**
* Renders the component.
* @returns {JSX}
*/
_proto.render = function render() {
const cookieConsentSettings = {
comfortCookiesAccepted: this.props.comfortCookiesAccepted,
statisticsCookiesAccepted: this.props.statisticsCookiesAccepted
};
const innerHTML = {
__html: parseHTML(this.props.children, this.props.decode, this.props.settings, this.props.processStyles, cookieConsentSettings)
};
const {
wrapper: Wrapper
} = this.props;
return /*#__PURE__*/_jsx(Wrapper, {
cookieConsentSettings: cookieConsentSettings,
children: /*#__PURE__*/_jsx("div", {
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML: innerHTML,
ref: this.htmlContainer,
className: classNames(this.props.className, 'common__html-sanitizer'),
onClickCapture: this.handleClick
})
});
};
return HtmlSanitizer;
}(Component);
HtmlSanitizer.defaultProps = {
children: '',
className: '',
decode: false,
processStyles: false,
settings: {},
wrapper: EmbeddedMedia,
comfortCookiesAccepted: false,
statisticsCookiesAccepted: false
};
export default connect(HtmlSanitizer);