plotly-icons
Version:
set of plotly icons
793 lines (616 loc) • 24.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _set = require('babel-runtime/core-js/set');
var _set2 = _interopRequireDefault(_set);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _url2 = require('url');
var _EventEmitter = require('../EventEmitter');
var _EventEmitter2 = _interopRequireDefault(_EventEmitter);
var _shallowEquals = require('../shallow-equals');
var _shallowEquals2 = _interopRequireDefault(_shallowEquals);
var _pQueue = require('../p-queue');
var _pQueue2 = _interopRequireDefault(_pQueue);
var _utils = require('../utils');
var _ = require('./');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* global __NEXT_DATA__ */
var historyUnavailableWarning = (0, _utils.execOnce)(function () {
(0, _utils.warn)('Warning: window.history is not available.');
});
var historyMethodWarning = (0, _utils.execOnce)(function (method) {
(0, _utils.warn)('Warning: window.history.' + method + ' is not available');
});
var Router = function () {
function Router(pathname, query, as) {
var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
pageLoader = _ref.pageLoader,
Component = _ref.Component,
ErrorComponent = _ref.ErrorComponent,
err = _ref.err;
(0, _classCallCheck3.default)(this, Router);
// represents the current component key
this.route = toRoute(pathname);
// set up the component cache (by route keys)
this.components = {};
// We should not keep the cache, if there's an error
// Otherwise, this cause issues when when going back and
// come again to the errored page.
if (Component !== ErrorComponent) {
this.components[this.route] = { Component: Component, err: err };
}
// Handling Router Events
this.events = new _EventEmitter2.default();
this.pageLoader = pageLoader;
this.prefetchQueue = new _pQueue2.default({ concurrency: 2 });
this.ErrorComponent = ErrorComponent;
this.pathname = pathname;
this.query = query;
this.asPath = as;
this.subscriptions = new _set2.default();
this.componentLoadCancel = null;
this.onPopState = this.onPopState.bind(this);
if (typeof window !== 'undefined') {
// in order for `e.state` to work on the `onpopstate` event
// we have to register the initial route upon initialization
this.changeState('replaceState', (0, _url2.format)({ pathname: pathname, query: query }), (0, _utils.getURL)());
window.addEventListener('popstate', this.onPopState);
}
}
(0, _createClass3.default)(Router, [{
key: 'onPopState',
value: function () {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(e) {
var pathname, query, _e$state, url, as, options;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (e.state) {
_context.next = 4;
break;
}
// We get state as undefined for two reasons.
// 1. With older safari (< 8) and older chrome (< 34)
// 2. When the URL changed with #
//
// In the both cases, we don't need to proceed and change the route.
// (as it's already changed)
// But we can simply replace the state with the new changes.
// Actually, for (1) we don't need to nothing. But it's hard to detect that event.
// So, doing the following for (1) does no harm.
pathname = this.pathname, query = this.query;
this.changeState('replaceState', (0, _url2.format)({ pathname: pathname, query: query }), (0, _utils.getURL)());
return _context.abrupt('return');
case 4:
_e$state = e.state, url = _e$state.url, as = _e$state.as, options = _e$state.options;
this.replace(url, as, options);
case 6:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
function onPopState(_x2) {
return _ref2.apply(this, arguments);
}
return onPopState;
}()
}, {
key: 'update',
value: function update(route, Component) {
var data = this.components[route];
if (!data) {
throw new Error('Cannot update unavailable route: ' + route);
}
var newData = (0, _extends3.default)({}, data, { Component: Component });
this.components[route] = newData;
if (route === this.route) {
this.notify(newData);
}
}
}, {
key: 'reload',
value: function () {
var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(route) {
var pathname, query, url, routeInfo, error;
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
delete this.components[route];
this.pageLoader.clearCache(route);
if (!(route !== this.route)) {
_context2.next = 4;
break;
}
return _context2.abrupt('return');
case 4:
pathname = this.pathname, query = this.query;
url = window.location.href;
this.events.emit('routeChangeStart', url);
_context2.next = 9;
return this.getRouteInfo(route, pathname, query, url);
case 9:
routeInfo = _context2.sent;
error = routeInfo.error;
if (!(error && error.cancelled)) {
_context2.next = 13;
break;
}
return _context2.abrupt('return');
case 13:
this.notify(routeInfo);
if (!error) {
_context2.next = 17;
break;
}
this.events.emit('routeChangeError', error, url);
throw error;
case 17:
this.events.emit('routeChangeComplete', url);
case 18:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
function reload(_x3) {
return _ref3.apply(this, arguments);
}
return reload;
}()
}, {
key: 'back',
value: function back() {
window.history.back();
}
}, {
key: 'push',
value: function push(url) {
var as = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : url;
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return this.change('pushState', url, as, options);
}
}, {
key: 'replace',
value: function replace(url) {
var as = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : url;
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return this.change('replaceState', url, as, options);
}
}, {
key: 'change',
value: function () {
var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(method, _url, _as, options) {
var url, as, _parse, pathname, query, route, _options$shallow, shallow, routeInfo, _routeInfo, error, hash;
return _regenerator2.default.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
// If url and as provided as an object representation,
// we'll format them into the string version here.
url = (typeof _url === 'undefined' ? 'undefined' : (0, _typeof3.default)(_url)) === 'object' ? (0, _url2.format)(_url) : _url;
as = (typeof _as === 'undefined' ? 'undefined' : (0, _typeof3.default)(_as)) === 'object' ? (0, _url2.format)(_as) : _as;
// Add the ending slash to the paths. So, we can serve the
// "<page>/index.html" directly for the SSR page.
if (__NEXT_DATA__.nextExport) {
as = (0, _._rewriteUrlForNextExport)(as);
}
this.abortComponentLoad(as);
// If the url change is only related to a hash change
// We should not proceed. We should only change the state.
if (!this.onlyAHashChange(as)) {
_context3.next = 8;
break;
}
this.changeState(method, url, as);
this.scrollToHash(as);
return _context3.abrupt('return', true);
case 8:
_parse = (0, _url2.parse)(url, true), pathname = _parse.pathname, query = _parse.query;
// If asked to change the current URL we should reload the current page
// (not location.reload() but reload getInitalProps and other Next.js stuffs)
// We also need to set the method = replaceState always
// as this should not go into the history (That's how browsers work)
if (!this.urlIsNew(pathname, query)) {
method = 'replaceState';
}
route = toRoute(pathname);
_options$shallow = options.shallow, shallow = _options$shallow === undefined ? false : _options$shallow;
routeInfo = null;
this.events.emit('routeChangeStart', as);
// If shallow === false and other conditions met, we reuse the
// existing routeInfo for this route.
// Because of this, getInitialProps would not run.
if (!(shallow && this.isShallowRoutingPossible(route))) {
_context3.next = 18;
break;
}
routeInfo = this.components[route];
_context3.next = 21;
break;
case 18:
_context3.next = 20;
return this.getRouteInfo(route, pathname, query, as);
case 20:
routeInfo = _context3.sent;
case 21:
_routeInfo = routeInfo, error = _routeInfo.error;
if (!(error && error.cancelled)) {
_context3.next = 24;
break;
}
return _context3.abrupt('return', false);
case 24:
this.events.emit('beforeHistoryChange', as);
this.changeState(method, url, as, options);
hash = window.location.hash.substring(1);
this.set(route, pathname, query, as, (0, _extends3.default)({}, routeInfo, { hash: hash }));
if (!error) {
_context3.next = 31;
break;
}
this.events.emit('routeChangeError', error, as);
throw error;
case 31:
this.events.emit('routeChangeComplete', as);
return _context3.abrupt('return', true);
case 33:
case 'end':
return _context3.stop();
}
}
}, _callee3, this);
}));
function change(_x8, _x9, _x10, _x11) {
return _ref4.apply(this, arguments);
}
return change;
}()
}, {
key: 'changeState',
value: function changeState(method, url, as) {
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
if (typeof window.history === 'undefined') {
historyUnavailableWarning();
return;
}
if (typeof window.history[method] === 'undefined') {
historyMethodWarning(method);
return;
}
if (method !== 'pushState' || (0, _utils.getURL)() !== as) {
window.history[method]({ url: url, as: as, options: options }, null, as);
}
}
}, {
key: 'getRouteInfo',
value: function () {
var _ref5 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4(route, pathname, query, as) {
var routeInfo, _routeInfo2, Component, ctx, _Component, _ctx;
return _regenerator2.default.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
routeInfo = null;
_context4.prev = 1;
routeInfo = this.components[route];
if (routeInfo) {
_context4.next = 8;
break;
}
_context4.next = 6;
return this.fetchComponent(route, as);
case 6:
_context4.t0 = _context4.sent;
routeInfo = {
Component: _context4.t0
};
case 8:
_routeInfo2 = routeInfo, Component = _routeInfo2.Component;
if (!(typeof Component !== 'function')) {
_context4.next = 11;
break;
}
throw new Error('The default export is not a React Component in page: "' + pathname + '"');
case 11:
ctx = { pathname: pathname, query: query, asPath: as };
_context4.next = 14;
return this.getInitialProps(Component, ctx);
case 14:
routeInfo.props = _context4.sent;
this.components[route] = routeInfo;
_context4.next = 33;
break;
case 18:
_context4.prev = 18;
_context4.t1 = _context4['catch'](1);
if (!(_context4.t1.code === 'PAGE_LOAD_ERROR')) {
_context4.next = 24;
break;
}
// If we can't load the page it could be one of following reasons
// 1. Page doesn't exists
// 2. Page does exist in a different zone
// 3. Internal error while loading the page
// So, doing a hard reload is the proper way to deal with this.
window.location.href = as;
// Changing the URL doesn't block executing the current code path.
// So, we need to mark it as a cancelled error and stop the routing logic.
_context4.t1.cancelled = true;
return _context4.abrupt('return', { error: _context4.t1 });
case 24:
if (!_context4.t1.cancelled) {
_context4.next = 26;
break;
}
return _context4.abrupt('return', { error: _context4.t1 });
case 26:
_Component = this.ErrorComponent;
routeInfo = { Component: _Component, err: _context4.t1 };
_ctx = { err: _context4.t1, pathname: pathname, query: query };
_context4.next = 31;
return this.getInitialProps(_Component, _ctx);
case 31:
routeInfo.props = _context4.sent;
routeInfo.error = _context4.t1;
case 33:
return _context4.abrupt('return', routeInfo);
case 34:
case 'end':
return _context4.stop();
}
}
}, _callee4, this, [[1, 18]]);
}));
function getRouteInfo(_x13, _x14, _x15, _x16) {
return _ref5.apply(this, arguments);
}
return getRouteInfo;
}()
}, {
key: 'set',
value: function set(route, pathname, query, as, data) {
this.route = route;
this.pathname = pathname;
this.query = query;
this.asPath = as;
this.notify(data);
}
}, {
key: 'onlyAHashChange',
value: function onlyAHashChange(as) {
if (!this.asPath) return false;
var _asPath$split = this.asPath.split('#'),
_asPath$split2 = (0, _slicedToArray3.default)(_asPath$split, 2),
oldUrlNoHash = _asPath$split2[0],
oldHash = _asPath$split2[1];
var _as$split = as.split('#'),
_as$split2 = (0, _slicedToArray3.default)(_as$split, 2),
newUrlNoHash = _as$split2[0],
newHash = _as$split2[1];
// If the urls are change, there's more than a hash change
if (oldUrlNoHash !== newUrlNoHash) {
return false;
}
// If the hash has changed, then it's a hash only change.
// This check is necessary to handle both the enter and
// leave hash === '' cases. The identity case falls through
// and is treated as a next reload.
return oldHash !== newHash;
}
}, {
key: 'scrollToHash',
value: function scrollToHash(as) {
var _as$split3 = as.split('#'),
_as$split4 = (0, _slicedToArray3.default)(_as$split3, 2),
hash = _as$split4[1];
var el = document.getElementById(hash);
if (el) {
el.scrollIntoView();
}
}
}, {
key: 'urlIsNew',
value: function urlIsNew(pathname, query) {
return this.pathname !== pathname || !(0, _shallowEquals2.default)(query, this.query);
}
}, {
key: 'isShallowRoutingPossible',
value: function isShallowRoutingPossible(route) {
return (
// If there's cached routeInfo for the route.
Boolean(this.components[route]) &&
// If the route is already rendered on the screen.
this.route === route
);
}
}, {
key: 'prefetch',
value: function () {
var _ref6 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee5(url) {
var _this = this;
var _parse2, pathname, route;
return _regenerator2.default.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
if (!(process.env.NODE_ENV === 'development')) {
_context5.next = 2;
break;
}
return _context5.abrupt('return');
case 2:
_parse2 = (0, _url2.parse)(url), pathname = _parse2.pathname;
route = toRoute(pathname);
return _context5.abrupt('return', this.prefetchQueue.add(function () {
return _this.fetchRoute(route);
}));
case 5:
case 'end':
return _context5.stop();
}
}
}, _callee5, this);
}));
function prefetch(_x17) {
return _ref6.apply(this, arguments);
}
return prefetch;
}()
}, {
key: 'fetchComponent',
value: function () {
var _ref7 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee6(route, as) {
var cancelled, cancel, Component, error;
return _regenerator2.default.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
cancelled = false;
cancel = this.componentLoadCancel = function () {
cancelled = true;
};
_context6.next = 4;
return this.fetchRoute(route);
case 4:
Component = _context6.sent;
if (!cancelled) {
_context6.next = 9;
break;
}
error = new Error('Abort fetching component for route: "' + route + '"');
error.cancelled = true;
throw error;
case 9:
if (cancel === this.componentLoadCancel) {
this.componentLoadCancel = null;
}
return _context6.abrupt('return', Component);
case 11:
case 'end':
return _context6.stop();
}
}
}, _callee6, this);
}));
function fetchComponent(_x18, _x19) {
return _ref7.apply(this, arguments);
}
return fetchComponent;
}()
}, {
key: 'getInitialProps',
value: function () {
var _ref8 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee7(Component, ctx) {
var cancelled, cancel, props, err;
return _regenerator2.default.wrap(function _callee7$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
cancelled = false;
cancel = function cancel() {
cancelled = true;
};
this.componentLoadCancel = cancel;
_context7.next = 5;
return (0, _utils.loadGetInitialProps)(Component, ctx);
case 5:
props = _context7.sent;
if (cancel === this.componentLoadCancel) {
this.componentLoadCancel = null;
}
if (!cancelled) {
_context7.next = 11;
break;
}
err = new Error('Loading initial props cancelled');
err.cancelled = true;
throw err;
case 11:
return _context7.abrupt('return', props);
case 12:
case 'end':
return _context7.stop();
}
}
}, _callee7, this);
}));
function getInitialProps(_x20, _x21) {
return _ref8.apply(this, arguments);
}
return getInitialProps;
}()
}, {
key: 'fetchRoute',
value: function () {
var _ref9 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee8(route) {
return _regenerator2.default.wrap(function _callee8$(_context8) {
while (1) {
switch (_context8.prev = _context8.next) {
case 0:
_context8.next = 2;
return this.pageLoader.loadPage(route);
case 2:
return _context8.abrupt('return', _context8.sent);
case 3:
case 'end':
return _context8.stop();
}
}
}, _callee8, this);
}));
function fetchRoute(_x22) {
return _ref9.apply(this, arguments);
}
return fetchRoute;
}()
}, {
key: 'abortComponentLoad',
value: function abortComponentLoad(as) {
if (this.componentLoadCancel) {
this.events.emit('routeChangeError', new Error('Route Cancelled'), as);
this.componentLoadCancel();
this.componentLoadCancel = null;
}
}
}, {
key: 'notify',
value: function notify(data) {
this.subscriptions.forEach(function (fn) {
return fn(data);
});
}
}, {
key: 'subscribe',
value: function subscribe(fn) {
var _this2 = this;
this.subscriptions.add(fn);
return function () {
return _this2.subscriptions.delete(fn);
};
}
}]);
return Router;
}();
exports.default = Router;
function toRoute(path) {
return path.replace(/\/$/, '') || '/';
}