UNPKG

@shopify/react-async

Version:

Tools for creating powerful, asynchronously-loaded React components.

144 lines (143 loc) 6.13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var React = tslib_1.__importStar(require("react")); var prefetch_1 = require("./context/prefetch"); var EventListener_1 = require("./EventListener"); exports.INTENTION_DELAY_MS = 150; var ConnectedPrefetcher = /** @class */ (function (_super) { tslib_1.__extends(ConnectedPrefetcher, _super); function ConnectedPrefetcher() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.state = {}; _this.prefetchAgressively = shouldPrefetchAggressively(); _this.handlePressStart = function (_a) { var target = _a.target; _this.clearTimeout(); if (target == null) { return; } var url = closestUrlFromNode(target); if (url != null) { _this.setState({ url: url }); } }; _this.handlePointerLeave = function (_a) { var target = _a.target, relatedTarget = _a.relatedTarget; var url = _this.state.url; var _b = _this, timeout = _b.timeout, timeoutUrl = _b.timeoutUrl; if (target == null) { if (timeout) { _this.clearTimeout(); } return; } if (url == null && timeout == null) { return; } var closestUrl = closestUrlFromNode(target); var relatedUrl = relatedTarget && closestUrlFromNode(relatedTarget); if (timeout != null && urlsEqual(closestUrl, timeoutUrl) && !urlsEqual(relatedUrl, timeoutUrl)) { _this.clearTimeout(); } if (urlsEqual(closestUrl, url) && !urlsEqual(relatedUrl, url)) { _this.setState({ url: undefined }); } }; _this.handlePointerEnter = function (_a) { var target = _a.target; if (target == null) { return; } var _b = _this, timeoutUrl = _b.timeoutUrl, timeout = _b.timeout; var url = closestUrlFromNode(target); if (url == null) { return; } if (timeout) { if (urlsEqual(url, timeoutUrl)) { return; } else { _this.clearTimeout(); } } _this.timeoutUrl = url; _this.timeout = setTimeout(function () { _this.clearTimeout(); _this.setState({ url: url }); }, exports.INTENTION_DELAY_MS); }; return _this; } ConnectedPrefetcher.prototype.render = function () { var url = this.state.url; var manager = this.props.manager; var preloadMarkup = url ? (React.createElement("div", { style: { visibility: 'hidden' } }, findMatches(manager.registered, url).map(function (_a, index) { var render = _a.render, path = _a.path; // eslint-disable-next-line react/no-array-index-key return React.createElement("div", { key: "" + path + index }, render(url)); }))) : null; var expensiveListeners = this.prefetchAgressively ? (React.createElement(React.Fragment, null, React.createElement(EventListener_1.EventListener, { passive: true, event: "mouseover", handler: this.handlePointerEnter }), React.createElement(EventListener_1.EventListener, { passive: true, event: "focusin", handler: this.handlePointerEnter }), React.createElement(EventListener_1.EventListener, { passive: true, event: "mouseout", handler: this.handlePointerLeave }), React.createElement(EventListener_1.EventListener, { passive: true, event: "focusout", handler: this.handlePointerLeave }))) : null; return (React.createElement(React.Fragment, null, React.createElement(EventListener_1.EventListener, { passive: true, event: "mousedown", handler: this.handlePressStart }), React.createElement(EventListener_1.EventListener, { passive: true, event: "touchstart", handler: this.handlePressStart }), expensiveListeners, preloadMarkup)); }; ConnectedPrefetcher.prototype.clearTimeout = function () { if (this.timeout != null) { clearTimeout(this.timeout); this.timeout = undefined; this.timeoutUrl = undefined; } }; return ConnectedPrefetcher; }(React.PureComponent)); function Prefetcher(props) { return (React.createElement(prefetch_1.PrefetchContext.Consumer, null, function (manager) { return React.createElement(ConnectedPrefetcher, tslib_1.__assign({}, props, { manager: manager })); })); } exports.Prefetcher = Prefetcher; function shouldPrefetchAggressively() { return (typeof navigator === 'undefined' || !('connection' in navigator) || !navigator.connection.saveData); } function urlsEqual(first, second) { return ((first == null && first === second) || (first != null && second != null && first.href === second.href)); } function findMatches(records, url) { return tslib_1.__spread(records).filter(function (_a) { var match = _a.path; return matches(url, match); }); } function matches(url, matcher) { return typeof matcher === 'string' ? matcher === url.pathname : matcher.test(url.pathname); } function closestUrlFromNode(element) { if (!(element instanceof HTMLElement)) { return undefined; } // data-href is a hack for resource list doing the <a> as a sibling var closestUrl = element.closest('[href], [data-href]'); if (closestUrl == null || !(closestUrl instanceof HTMLElement)) { return undefined; } var url = closestUrl.getAttribute('href') || closestUrl.getAttribute('data-href'); try { return url ? new URL(url, window.location.href) : undefined; } catch (error) { return undefined; } }