react-carousel-query
Version:
A infinite carousel component made with react that handles the pagination for you.
1,745 lines (1,433 loc) • 50 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
var clientLogger = require('@storybook/client-logger');
var memoize = require('memoizerific');
var qs = require('qs');
var React = require('react');
function _interopDefaultLegacy(e) {
return e && typeof e === 'object' && 'default' in e ? e : {
'default': e
};
}
var memoize__default = /*#__PURE__*/_interopDefaultLegacy(memoize);
var qs__default = /*#__PURE__*/_interopDefaultLegacy(qs);
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
var fastDeepEqual = function equal(a, b) {
if (a === b) return true;
if (a && b && typeof a == 'object' && typeof b == 'object') {
if (a.constructor !== b.constructor) return false;
var length, i, keys;
if (Array.isArray(a)) {
length = a.length;
if (length != b.length) return false;
for (i = length; i-- !== 0;) if (!equal(a[i], b[i])) return false;
return true;
}
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
keys = Object.keys(a);
length = keys.length;
if (length !== Object.keys(b).length) return false;
for (i = length; i-- !== 0;) if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
for (i = length; i-- !== 0;) {
var key = keys[i];
if (!equal(a[key], b[key])) return false;
}
return true;
} // true if both NaN, false otherwise
return a !== a && b !== b;
};
/** Detect free variable `global` from Node.js. */
var freeGlobal$1 = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
var _freeGlobal = freeGlobal$1;
var freeGlobal = _freeGlobal;
/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
/** Used as a reference to the global object. */
var root$1 = freeGlobal || freeSelf || Function('return this')();
var _root = root$1;
var root = _root;
/** Built-in value references. */
var Symbol$3 = root.Symbol;
var _Symbol = Symbol$3;
var Symbol$2 = _Symbol;
/** Used for built-in method references. */
var objectProto$2 = Object.prototype;
/** Used to check objects for own properties. */
var hasOwnProperty$1 = objectProto$2.hasOwnProperty;
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var nativeObjectToString$1 = objectProto$2.toString;
/** Built-in value references. */
var symToStringTag$1 = Symbol$2 ? Symbol$2.toStringTag : undefined;
/**
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the raw `toStringTag`.
*/
function getRawTag$1(value) {
var isOwn = hasOwnProperty$1.call(value, symToStringTag$1),
tag = value[symToStringTag$1];
try {
value[symToStringTag$1] = undefined;
var unmasked = true;
} catch (e) {}
var result = nativeObjectToString$1.call(value);
if (unmasked) {
if (isOwn) {
value[symToStringTag$1] = tag;
} else {
delete value[symToStringTag$1];
}
}
return result;
}
var _getRawTag = getRawTag$1;
/** Used for built-in method references. */
var objectProto$1 = Object.prototype;
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var nativeObjectToString = objectProto$1.toString;
/**
* Converts `value` to a string using `Object.prototype.toString`.
*
* @private
* @param {*} value The value to convert.
* @returns {string} Returns the converted string.
*/
function objectToString$1(value) {
return nativeObjectToString.call(value);
}
var _objectToString = objectToString$1;
var Symbol$1 = _Symbol,
getRawTag = _getRawTag,
objectToString = _objectToString;
/** `Object#toString` result references. */
var nullTag = '[object Null]',
undefinedTag = '[object Undefined]';
/** Built-in value references. */
var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : undefined;
/**
* The base implementation of `getTag` without fallbacks for buggy environments.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the `toStringTag`.
*/
function baseGetTag$1(value) {
if (value == null) {
return value === undefined ? undefinedTag : nullTag;
}
return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
}
var _baseGetTag = baseGetTag$1;
/**
* Creates a unary function that invokes `func` with its argument transformed.
*
* @private
* @param {Function} func The function to wrap.
* @param {Function} transform The argument transform.
* @returns {Function} Returns the new function.
*/
function overArg$1(func, transform) {
return function (arg) {
return func(transform(arg));
};
}
var _overArg = overArg$1;
var overArg = _overArg;
/** Built-in value references. */
var getPrototype$1 = overArg(Object.getPrototypeOf, Object);
var _getPrototype = getPrototype$1;
/**
* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* _.isObjectLike({});
* // => true
*
* _.isObjectLike([1, 2, 3]);
* // => true
*
* _.isObjectLike(_.noop);
* // => false
*
* _.isObjectLike(null);
* // => false
*/
function isObjectLike$1(value) {
return value != null && typeof value == 'object';
}
var isObjectLike_1 = isObjectLike$1;
var baseGetTag = _baseGetTag,
getPrototype = _getPrototype,
isObjectLike = isObjectLike_1;
/** `Object#toString` result references. */
var objectTag = '[object Object]';
/** Used for built-in method references. */
var funcProto = Function.prototype,
objectProto = Object.prototype;
/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/** Used to infer the `Object` constructor. */
var objectCtorString = funcToString.call(Object);
/**
* Checks if `value` is a plain object, that is, an object created by the
* `Object` constructor or one with a `[[Prototype]]` of `null`.
*
* @static
* @memberOf _
* @since 0.8.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
* @example
*
* function Foo() {
* this.a = 1;
* }
*
* _.isPlainObject(new Foo);
* // => false
*
* _.isPlainObject([1, 2, 3]);
* // => false
*
* _.isPlainObject({ 'x': 0, 'y': 0 });
* // => true
*
* _.isPlainObject(Object.create(null));
* // => true
*/
function isPlainObject(value) {
if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
return false;
}
var proto = getPrototype(value);
if (proto === null) {
return true;
}
var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
return typeof Ctor == 'function' && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
}
var isPlainObject_1 = isPlainObject;
function dedent(templ) {
var values = [];
for (var _i = 1; _i < arguments.length; _i++) {
values[_i - 1] = arguments[_i];
}
var strings = Array.from(typeof templ === 'string' ? [templ] : templ);
strings[strings.length - 1] = strings[strings.length - 1].replace(/\r?\n([\t ]*)$/, '');
var indentLengths = strings.reduce(function (arr, str) {
var matches = str.match(/\n([\t ]+|(?!\s).)/g);
if (matches) {
return arr.concat(matches.map(function (match) {
var _a, _b;
return (_b = (_a = match.match(/[\t ]/g)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
}));
}
return arr;
}, []);
if (indentLengths.length) {
var pattern_1 = new RegExp("\n[\t ]{" + Math.min.apply(Math, indentLengths) + "}", 'g');
strings = strings.map(function (str) {
return str.replace(pattern_1, '\n');
});
}
strings[0] = strings[0].replace(/^\r?\n/, '');
var string = strings[0];
values.forEach(function (value, i) {
var endentations = string.match(/(?:^|\n)( *)$/);
var endentation = endentations ? endentations[1] : '';
var indentedValue = value;
if (typeof value === 'string' && value.includes('\n')) {
indentedValue = String(value).split('\n').map(function (str, i) {
return i === 0 ? str : "" + endentation + str;
}).join('\n');
}
string += indentedValue + strings[i + 1];
});
return string;
}
const splitPathRegex = /\/([^/]+)\/(?:(.*)_)?([^/]+)?/;
const parsePath$2 = memoize__default["default"](1000)(path => {
const result = {
viewMode: undefined,
storyId: undefined,
refId: undefined
};
if (path) {
const [, viewMode, refId, storyId] = path.toLowerCase().match(splitPathRegex) || [];
if (viewMode) {
Object.assign(result, {
viewMode,
storyId,
refId
});
}
}
return result;
});
const DEEPLY_EQUAL = Symbol('Deeply equal');
const deepDiff = (value, update) => {
if (typeof value !== typeof update) return update;
if (fastDeepEqual(value, update)) return DEEPLY_EQUAL;
if (Array.isArray(value) && Array.isArray(update)) {
const res = update.reduce((acc, upd, index) => {
const diff = deepDiff(value[index], upd);
if (diff !== DEEPLY_EQUAL) acc[index] = diff;
return acc;
}, new Array(update.length));
if (update.length >= value.length) return res;
return res.concat(new Array(value.length - update.length).fill(undefined));
}
if (isPlainObject_1(value) && isPlainObject_1(update)) {
return Object.keys(Object.assign(Object.assign({}, value), update)).reduce((acc, key) => {
const diff = deepDiff(value === null || value === void 0 ? void 0 : value[key], update === null || update === void 0 ? void 0 : update[key]);
return diff === DEEPLY_EQUAL ? acc : Object.assign(acc, {
[key]: diff
});
}, {});
}
return update;
}; // Keep this in sync with validateArgs in core-client/src/preview/parseArgsParam.ts
const VALIDATION_REGEXP = /^[a-zA-Z0-9 _-]*$/;
const NUMBER_REGEXP = /^-?[0-9]+(\.[0-9]+)?$/;
const HEX_REGEXP = /^#([a-f0-9]{3,4}|[a-f0-9]{6}|[a-f0-9]{8})$/i;
const COLOR_REGEXP = /^(rgba?|hsla?)\(([0-9]{1,3}),\s?([0-9]{1,3})%?,\s?([0-9]{1,3})%?,?\s?([0-9](\.[0-9]{1,2})?)?\)$/i;
const validateArgs = (key = '', value) => {
if (key === null) return false;
if (key === '' || !VALIDATION_REGEXP.test(key)) return false;
if (value === null || value === undefined) return true; // encoded as `!null` or `!undefined`
if (value instanceof Date) return true; // encoded as modified ISO string
if (typeof value === 'number' || typeof value === 'boolean') return true;
if (typeof value === 'string') {
return VALIDATION_REGEXP.test(value) || NUMBER_REGEXP.test(value) || HEX_REGEXP.test(value) || COLOR_REGEXP.test(value);
}
if (Array.isArray(value)) {
return value.every(v => validateArgs(key, v));
}
if (isPlainObject_1(value)) {
return Object.entries(value).every(([k, v]) => validateArgs(k, v));
}
return false;
};
const encodeSpecialValues = value => {
if (value === undefined) return '!undefined';
if (value === null) return '!null';
if (typeof value === 'string') {
if (HEX_REGEXP.test(value)) return `!hex(${value.slice(1)})`;
if (COLOR_REGEXP.test(value)) return `!${value.replace(/[\s%]/g, '')}`;
return value;
}
if (Array.isArray(value)) return value.map(encodeSpecialValues);
if (isPlainObject_1(value)) {
return Object.entries(value).reduce((acc, [key, val]) => Object.assign(acc, {
[key]: encodeSpecialValues(val)
}), {});
}
return value;
};
const QS_OPTIONS = {
encode: false,
delimiter: ';',
allowDots: true,
format: 'RFC1738',
serializeDate: date => `!date(${date.toISOString()})`
};
const buildArgsParam = (initialArgs, args) => {
const update = deepDiff(initialArgs, args);
if (!update || update === DEEPLY_EQUAL) return '';
const object = Object.entries(update).reduce((acc, [key, value]) => {
if (validateArgs(key, value)) return Object.assign(acc, {
[key]: value
});
clientLogger.once.warn(dedent`
Omitted potentially unsafe URL args.
More info: https://storybook.js.org/docs/react/writing-stories/args#setting-args-through-the-url
`);
return acc;
}, {});
return qs__default["default"].stringify(encodeSpecialValues(object), QS_OPTIONS).replace(/ /g, '+').split(';').map(part => part.replace('=', ':')).join(';');
};
const queryFromString = memoize__default["default"](1000)(s => qs__default["default"].parse(s, {
ignoreQueryPrefix: true
}));
const queryFromLocation = location => queryFromString(location.search);
const stringifyQuery = query => qs__default["default"].stringify(query, {
addQueryPrefix: true,
encode: false
});
const getMatch = memoize__default["default"](1000)((current, target, startsWith = true) => {
const startsWithTarget = current && startsWith && current.startsWith(target);
const currentIsTarget = typeof target === 'string' && current === target;
const matchTarget = current && target && current.match(target);
if (startsWithTarget || currentIsTarget || matchTarget) {
return {
path: current
};
}
return null;
});
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
}
var win;
if (typeof window !== "undefined") {
win = window;
} else if (typeof commonjsGlobal !== "undefined") {
win = commonjsGlobal;
} else if (typeof self !== "undefined") {
win = self;
} else {
win = {};
}
var window_1 = win;
function _extends$1() {
_extends$1 = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends$1.apply(this, arguments);
}
/**
* Actions represent the type of change to a location value.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#action
*/
var Action$1;
(function (Action) {
/**
* A POP indicates a change to an arbitrary index in the history stack, such
* as a back or forward navigation. It does not describe the direction of the
* navigation, only that the current index changed.
*
* Note: This is the default action for newly created history objects.
*/
Action["Pop"] = "POP";
/**
* A PUSH indicates a new entry being added to the history stack, such as when
* a link is clicked and a new page loads. When this happens, all subsequent
* entries in the stack are lost.
*/
Action["Push"] = "PUSH";
/**
* A REPLACE indicates the entry at the current index in the history stack
* being replaced by a new one.
*/
Action["Replace"] = "REPLACE";
})(Action$1 || (Action$1 = {}));
var readOnly = process.env.NODE_ENV !== "production" ? function (obj) {
return Object.freeze(obj);
} : function (obj) {
return obj;
};
function warning$1(cond, message) {
if (!cond) {
// eslint-disable-next-line no-console
if (typeof console !== 'undefined') console.warn(message);
try {
// Welcome to debugging history!
//
// This error is thrown as a convenience so you can more easily
// find the source for a warning that appears in the console by
// enabling "pause on exceptions" in your JavaScript debugger.
throw new Error(message); // eslint-disable-next-line no-empty
} catch (e) {}
}
}
var BeforeUnloadEventType = 'beforeunload';
var PopStateEventType = 'popstate';
/**
* Browser history stores the location in regular URLs. This is the standard for
* most web apps, but it requires some configuration on the server to ensure you
* serve the same app at multiple URLs.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory
*/
function createBrowserHistory(options) {
if (options === void 0) {
options = {};
}
var _options = options,
_options$window = _options.window,
window = _options$window === void 0 ? document.defaultView : _options$window;
var globalHistory = window.history;
function getIndexAndLocation() {
var _window$location = window.location,
pathname = _window$location.pathname,
search = _window$location.search,
hash = _window$location.hash;
var state = globalHistory.state || {};
return [state.idx, readOnly({
pathname: pathname,
search: search,
hash: hash,
state: state.usr || null,
key: state.key || 'default'
})];
}
var blockedPopTx = null;
function handlePop() {
if (blockedPopTx) {
blockers.call(blockedPopTx);
blockedPopTx = null;
} else {
var nextAction = Action$1.Pop;
var _getIndexAndLocation = getIndexAndLocation(),
nextIndex = _getIndexAndLocation[0],
nextLocation = _getIndexAndLocation[1];
if (blockers.length) {
if (nextIndex != null) {
var delta = index - nextIndex;
if (delta) {
// Revert the POP
blockedPopTx = {
action: nextAction,
location: nextLocation,
retry: function retry() {
go(delta * -1);
}
};
go(delta);
}
} else {
// Trying to POP to a location with no index. We did not create
// this location, so we can't effectively block the navigation.
process.env.NODE_ENV !== "production" ? warning$1(false, // TODO: Write up a doc that explains our blocking strategy in
// detail and link to it here so people can understand better what
// is going on and how to avoid it.
"You are trying to block a POP navigation to a location that was not " + "created by the history library. The block will fail silently in " + "production, but in general you should do all navigation with the " + "history library (instead of using window.history.pushState directly) " + "to avoid this situation.") : void 0;
}
} else {
applyTx(nextAction);
}
}
}
window.addEventListener(PopStateEventType, handlePop);
var action = Action$1.Pop;
var _getIndexAndLocation2 = getIndexAndLocation(),
index = _getIndexAndLocation2[0],
location = _getIndexAndLocation2[1];
var listeners = createEvents();
var blockers = createEvents();
if (index == null) {
index = 0;
globalHistory.replaceState(_extends$1({}, globalHistory.state, {
idx: index
}), '');
}
function createHref(to) {
return typeof to === 'string' ? to : createPath(to);
} // state defaults to `null` because `window.history.state` does
function getNextLocation(to, state) {
if (state === void 0) {
state = null;
}
return readOnly(_extends$1({
pathname: location.pathname,
hash: '',
search: ''
}, typeof to === 'string' ? parsePath$1(to) : to, {
state: state,
key: createKey()
}));
}
function getHistoryStateAndUrl(nextLocation, index) {
return [{
usr: nextLocation.state,
key: nextLocation.key,
idx: index
}, createHref(nextLocation)];
}
function allowTx(action, location, retry) {
return !blockers.length || (blockers.call({
action: action,
location: location,
retry: retry
}), false);
}
function applyTx(nextAction) {
action = nextAction;
var _getIndexAndLocation3 = getIndexAndLocation();
index = _getIndexAndLocation3[0];
location = _getIndexAndLocation3[1];
listeners.call({
action: action,
location: location
});
}
function push(to, state) {
var nextAction = Action$1.Push;
var nextLocation = getNextLocation(to, state);
function retry() {
push(to, state);
}
if (allowTx(nextAction, nextLocation, retry)) {
var _getHistoryStateAndUr = getHistoryStateAndUrl(nextLocation, index + 1),
historyState = _getHistoryStateAndUr[0],
url = _getHistoryStateAndUr[1]; // TODO: Support forced reloading
// try...catch because iOS limits us to 100 pushState calls :/
try {
globalHistory.pushState(historyState, '', url);
} catch (error) {
// They are going to lose state here, but there is no real
// way to warn them about it since the page will refresh...
window.location.assign(url);
}
applyTx(nextAction);
}
}
function replace(to, state) {
var nextAction = Action$1.Replace;
var nextLocation = getNextLocation(to, state);
function retry() {
replace(to, state);
}
if (allowTx(nextAction, nextLocation, retry)) {
var _getHistoryStateAndUr2 = getHistoryStateAndUrl(nextLocation, index),
historyState = _getHistoryStateAndUr2[0],
url = _getHistoryStateAndUr2[1]; // TODO: Support forced reloading
globalHistory.replaceState(historyState, '', url);
applyTx(nextAction);
}
}
function go(delta) {
globalHistory.go(delta);
}
var history = {
get action() {
return action;
},
get location() {
return location;
},
createHref: createHref,
push: push,
replace: replace,
go: go,
back: function back() {
go(-1);
},
forward: function forward() {
go(1);
},
listen: function listen(listener) {
return listeners.push(listener);
},
block: function block(blocker) {
var unblock = blockers.push(blocker);
if (blockers.length === 1) {
window.addEventListener(BeforeUnloadEventType, promptBeforeUnload);
}
return function () {
unblock(); // Remove the beforeunload listener so the document may
// still be salvageable in the pagehide event.
// See https://html.spec.whatwg.org/#unloading-documents
if (!blockers.length) {
window.removeEventListener(BeforeUnloadEventType, promptBeforeUnload);
}
};
}
};
return history;
}
function promptBeforeUnload(event) {
// Cancel the event.
event.preventDefault(); // Chrome (and legacy IE) requires returnValue to be set.
event.returnValue = '';
}
function createEvents() {
var handlers = [];
return {
get length() {
return handlers.length;
},
push: function push(fn) {
handlers.push(fn);
return function () {
handlers = handlers.filter(function (handler) {
return handler !== fn;
});
};
},
call: function call(arg) {
handlers.forEach(function (fn) {
return fn && fn(arg);
});
}
};
}
function createKey() {
return Math.random().toString(36).substr(2, 8);
}
/**
* Creates a string URL path from the given pathname, search, and hash components.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createpath
*/
function createPath(_ref) {
var _ref$pathname = _ref.pathname,
pathname = _ref$pathname === void 0 ? '/' : _ref$pathname,
_ref$search = _ref.search,
search = _ref$search === void 0 ? '' : _ref$search,
_ref$hash = _ref.hash,
hash = _ref$hash === void 0 ? '' : _ref$hash;
if (search && search !== '?') pathname += search.charAt(0) === '?' ? search : '?' + search;
if (hash && hash !== '#') pathname += hash.charAt(0) === '#' ? hash : '#' + hash;
return pathname;
}
/**
* Parses a string URL path into its separate pathname, search, and hash components.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#parsepath
*/
function parsePath$1(path) {
var parsedPath = {};
if (path) {
var hashIndex = path.indexOf('#');
if (hashIndex >= 0) {
parsedPath.hash = path.substr(hashIndex);
path = path.substr(0, hashIndex);
}
var searchIndex = path.indexOf('?');
if (searchIndex >= 0) {
parsedPath.search = path.substr(searchIndex);
path = path.substr(0, searchIndex);
}
if (path) {
parsedPath.pathname = path;
}
}
return parsedPath;
}
/**
* Actions represent the type of change to a location value.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#action
*/
var Action;
(function (Action) {
/**
* A POP indicates a change to an arbitrary index in the history stack, such
* as a back or forward navigation. It does not describe the direction of the
* navigation, only that the current index changed.
*
* Note: This is the default action for newly created history objects.
*/
Action["Pop"] = "POP";
/**
* A PUSH indicates a new entry being added to the history stack, such as when
* a link is clicked and a new page loads. When this happens, all subsequent
* entries in the stack are lost.
*/
Action["Push"] = "PUSH";
/**
* A REPLACE indicates the entry at the current index in the history stack
* being replaced by a new one.
*/
Action["Replace"] = "REPLACE";
})(Action || (Action = {}));
process.env.NODE_ENV !== "production" ? function (obj) {
return Object.freeze(obj);
} : function (obj) {
return obj;
};
/**
* Parses a string URL path into its separate pathname, search, and hash components.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#parsepath
*/
function parsePath(path) {
var parsedPath = {};
if (path) {
var hashIndex = path.indexOf('#');
if (hashIndex >= 0) {
parsedPath.hash = path.substr(hashIndex);
path = path.substr(0, hashIndex);
}
var searchIndex = path.indexOf('?');
if (searchIndex >= 0) {
parsedPath.search = path.substr(searchIndex);
path = path.substr(0, searchIndex);
}
if (path) {
parsedPath.pathname = path;
}
}
return parsedPath;
}
/**
* React Router v6.0.2
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
function invariant(cond, message) {
if (!cond) throw new Error(message);
}
function warning(cond, message) {
if (!cond) {
// eslint-disable-next-line no-console
if (typeof console !== "undefined") console.warn(message);
try {
// Welcome to debugging React Router!
//
// This error is thrown as a convenience so you can more easily
// find the source for a warning that appears in the console by
// enabling "pause on exceptions" in your JavaScript debugger.
throw new Error(message); // eslint-disable-next-line no-empty
} catch (e) {}
}
} // CONTEXT
///////////////////////////////////////////////////////////////////////////////
/**
* A Navigator is a "location changer"; it's how you get to different locations.
*
* Every history instance conforms to the Navigator interface, but the
* distinction is useful primarily when it comes to the low-level <Router> API
* where both the location and a navigator must be provided separately in order
* to avoid "tearing" that may occur in a suspense-enabled app if the action
* and/or location were to be read directly from the history instance.
*/
const NavigationContext = /*#__PURE__*/React.createContext(null);
if (process.env.NODE_ENV !== "production") {
NavigationContext.displayName = "Navigation";
}
const LocationContext = /*#__PURE__*/React.createContext(null);
if (process.env.NODE_ENV !== "production") {
LocationContext.displayName = "Location";
}
const RouteContext = /*#__PURE__*/React.createContext({
outlet: null,
matches: []
});
if (process.env.NODE_ENV !== "production") {
RouteContext.displayName = "Route";
} ///////////////////////////////////////////////////////////////////////////////
/**
* Provides location context for the rest of the app.
*
* Note: You usually won't render a <Router> directly. Instead, you'll render a
* router that is more specific to your environment such as a <BrowserRouter>
* in web browsers or a <StaticRouter> for server rendering.
*
* @see https://reactrouter.com/docs/en/v6/api#router
*/
function Router(_ref3) {
let {
basename: basenameProp = "/",
children = null,
location: locationProp,
navigationType = Action.Pop,
navigator,
static: staticProp = false
} = _ref3;
!!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, "You cannot render a <Router> inside another <Router>." + " You should never have more than one in your app.") : invariant(false) : void 0;
let basename = normalizePathname(basenameProp);
let navigationContext = React.useMemo(() => ({
basename,
navigator,
static: staticProp
}), [basename, navigator, staticProp]);
if (typeof locationProp === "string") {
locationProp = parsePath(locationProp);
}
let {
pathname = "/",
search = "",
hash = "",
state = null,
key = "default"
} = locationProp;
let location = React.useMemo(() => {
let trailingPathname = stripBasename(pathname, basename);
if (trailingPathname == null) {
return null;
}
return {
pathname: trailingPathname,
search,
hash,
state,
key
};
}, [basename, pathname, search, hash, state, key]);
process.env.NODE_ENV !== "production" ? warning(location != null, "<Router basename=\"" + basename + "\"> is not able to match the URL " + ("\"" + pathname + search + hash + "\" because it does not start with the ") + "basename, so the <Router> won't render anything.") : void 0;
if (location == null) {
return null;
}
return /*#__PURE__*/React.createElement(NavigationContext.Provider, {
value: navigationContext
}, /*#__PURE__*/React.createElement(LocationContext.Provider, {
children: children,
value: {
location,
navigationType
}
}));
} // HOOKS
///////////////////////////////////////////////////////////////////////////////
/**
* Returns the full href for the given "to" value. This is useful for building
* custom links that are also accessible and preserve right-click behavior.
*
* @see https://reactrouter.com/docs/en/v6/api#usehref
*/
function useHref(to) {
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
"useHref() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
let {
basename,
navigator
} = React.useContext(NavigationContext);
let {
hash,
pathname,
search
} = useResolvedPath(to);
let joinedPathname = pathname;
if (basename !== "/") {
let toPathname = getToPathname(to);
let endsWithSlash = toPathname != null && toPathname.endsWith("/");
joinedPathname = pathname === "/" ? basename + (endsWithSlash ? "/" : "") : joinPaths([basename, pathname]);
}
return navigator.createHref({
pathname: joinedPathname,
search,
hash
});
}
/**
* Returns true if this component is a descendant of a <Router>.
*
* @see https://reactrouter.com/docs/en/v6/api#useinroutercontext
*/
function useInRouterContext() {
return React.useContext(LocationContext) != null;
}
/**
* Returns the current location object, which represents the current URL in web
* browsers.
*
* Note: If you're using this it may mean you're doing some of your own
* "routing" in your app, and we'd like to know what your use case is. We may
* be able to provide something higher-level to better suit your needs.
*
* @see https://reactrouter.com/docs/en/v6/api#uselocation
*/
function useLocation() {
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
"useLocation() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
return React.useContext(LocationContext).location;
}
/**
* The interface for the navigate() function returned from useNavigate().
*/
/**
* Returns an imperative method for changing the location. Used by <Link>s, but
* may also be used by other elements to change the location.
*
* @see https://reactrouter.com/docs/en/v6/api#usenavigate
*/
function useNavigate$1() {
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
"useNavigate() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
let {
basename,
navigator
} = React.useContext(NavigationContext);
let {
matches
} = React.useContext(RouteContext);
let {
pathname: locationPathname
} = useLocation();
let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
let activeRef = React.useRef(false);
React.useEffect(() => {
activeRef.current = true;
});
let navigate = React.useCallback(function (to, options) {
if (options === void 0) {
options = {};
}
process.env.NODE_ENV !== "production" ? warning(activeRef.current, "You should call navigate() in a React.useEffect(), not when " + "your component is first rendered.") : void 0;
if (!activeRef.current) return;
if (typeof to === "number") {
navigator.go(to);
return;
}
let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname);
if (basename !== "/") {
path.pathname = joinPaths([basename, path.pathname]);
}
(!!options.replace ? navigator.replace : navigator.push)(path, options.state);
}, [basename, navigator, routePathnamesJson, locationPathname]);
return navigate;
}
/**
* Resolves the pathname of the given `to` value against the current location.
*
* @see https://reactrouter.com/docs/en/v6/api#useresolvedpath
*/
function useResolvedPath(to) {
let {
matches
} = React.useContext(RouteContext);
let {
pathname: locationPathname
} = useLocation();
let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname), [to, routePathnamesJson, locationPathname]);
}
/**
* Returns a resolved path object relative to the given pathname.
*
* @see https://reactrouter.com/docs/en/v6/api#resolvepath
*/
function resolvePath(to, fromPathname) {
if (fromPathname === void 0) {
fromPathname = "/";
}
let {
pathname: toPathname,
search = "",
hash = ""
} = typeof to === "string" ? parsePath(to) : to;
let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;
return {
pathname,
search: normalizeSearch(search),
hash: normalizeHash(hash)
};
}
function resolvePathname(relativePath, fromPathname) {
let segments = fromPathname.replace(/\/+$/, "").split("/");
let relativeSegments = relativePath.split("/");
relativeSegments.forEach(segment => {
if (segment === "..") {
// Keep the root "" segment so the pathname starts at /
if (segments.length > 1) segments.pop();
} else if (segment !== ".") {
segments.push(segment);
}
});
return segments.length > 1 ? segments.join("/") : "/";
}
function resolveTo(toArg, routePathnames, locationPathname) {
let to = typeof toArg === "string" ? parsePath(toArg) : toArg;
let toPathname = toArg === "" || to.pathname === "" ? "/" : to.pathname; // If a pathname is explicitly provided in `to`, it should be relative to the
// route context. This is explained in `Note on `<Link to>` values` in our
// migration guide from v5 as a means of disambiguation between `to` values
// that begin with `/` and those that do not. However, this is problematic for
// `to` values that do not provide a pathname. `to` can simply be a search or
// hash string, in which case we should assume that the navigation is relative
// to the current location's pathname and *not* the route pathname.
let from;
if (toPathname == null) {
from = locationPathname;
} else {
let routePathnameIndex = routePathnames.length - 1;
if (toPathname.startsWith("..")) {
let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one
// URL segment". This is a key difference from how <a href> works and a
// major reason we call this a "to" value instead of a "href".
while (toSegments[0] === "..") {
toSegments.shift();
routePathnameIndex -= 1;
}
to.pathname = toSegments.join("/");
} // If there are more ".." segments than parent routes, resolve relative to
// the root / URL.
from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
}
let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original to value had one.
if (toPathname && toPathname !== "/" && toPathname.endsWith("/") && !path.pathname.endsWith("/")) {
path.pathname += "/";
}
return path;
}
function getToPathname(to) {
// Empty strings should be treated the same as / paths
return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? parsePath(to).pathname : to.pathname;
}
function stripBasename(pathname, basename) {
if (basename === "/") return pathname;
if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
return null;
}
let nextChar = pathname.charAt(basename.length);
if (nextChar && nextChar !== "/") {
// pathname does not start with basename/
return null;
}
return pathname.slice(basename.length) || "/";
}
const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/");
const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash; ///////////////////////////////////////////////////////////////////////////////
/**
* React Router DOM v6.0.2
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
const _excluded = ["onClick", "reloadDocument", "replace", "state", "target", "to"],
_excluded2 = ["aria-current", "caseSensitive", "className", "end", "style", "to"]; // COMPONENTS
////////////////////////////////////////////////////////////////////////////////
/**
* A <Router> for use in web browsers. Provides the cleanest URLs.
*/
function BrowserRouter(_ref) {
let {
basename,
children,
window
} = _ref;
let historyRef = React.useRef();
if (historyRef.current == null) {
historyRef.current = createBrowserHistory({
window
});
}
let history = historyRef.current;
let [state, setState] = React.useState({
action: history.action,
location: history.location
});
React.useLayoutEffect(() => history.listen(setState), [history]);
return /*#__PURE__*/React.createElement(Router, {
basename: basename,
children: children,
location: state.location,
navigationType: state.action,
navigator: history
});
}
function isModifiedEvent(event) {
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
}
/**
* The public API for rendering a history-aware <a>.
*/
const Link$1 = /*#__PURE__*/React.forwardRef(function LinkWithRef(_ref3, ref) {
let {
onClick,
reloadDocument,
replace = false,
state,
target,
to
} = _ref3,
rest = _objectWithoutPropertiesLoose(_ref3, _excluded);
let href = useHref(to);
let internalOnClick = useLinkClickHandler(to, {
replace,
state,
target
});
function handleClick(event) {
if (onClick) onClick(event);
if (!event.defaultPrevented && !reloadDocument) {
internalOnClick(event);
}
}
return (
/*#__PURE__*/
// eslint-disable-next-line jsx-a11y/anchor-has-content
React.createElement("a", _extends({}, rest, {
href: href,
onClick: handleClick,
ref: ref,
target: target
}))
);
});
if (process.env.NODE_ENV !== "production") {
Link$1.displayName = "Link";
}
/**
* A <Link> wrapper that knows if it's "active" or not.
*/
const NavLink = /*#__PURE__*/React.forwardRef(function NavLinkWithRef(_ref4, ref) {
let {
"aria-current": ariaCurrentProp = "page",
caseSensitive = false,
className: classNameProp = "",
end = false,
style: styleProp,
to
} = _ref4,
rest = _objectWithoutPropertiesLoose(_ref4, _excluded2);
let location = useLocation();
let path = useResolvedPath(to);
let locationPathname = location.pathname;
let toPathname = path.pathname;
if (!caseSensitive) {
locationPathname = locationPathname.toLowerCase();
toPathname = toPathname.toLowerCase();
}
let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(toPathname.length) === "/";
let ariaCurrent = isActive ? ariaCurrentProp : undefined;
let className;
if (typeof classNameProp === "function") {
className = classNameProp({
isActive
});
} else {
// If the className prop is not a function, we use a default `active`
// class for <NavLink />s that are active. In v5 `active` was the default
// value for `activeClassName`, but we are removing that API and can still
// use the old default behavior for a cleaner upgrade path and keep the
// simple styling rules working as they currently do.
className = [classNameProp, isActive ? "active" : null].filter(Boolean).join(" ");
}
let style = typeof styleProp === "function" ? styleProp({
isActive
}) : styleProp;
return /*#__PURE__*/React.createElement(Link$1, _extends({}, rest, {
"aria-current": ariaCurrent,
className: className,
ref: ref,
style: style,
to: to
}));
});
if (process.env.NODE_ENV !== "production") {
NavLink.displayName = "NavLink";
} ////////////////////////////////////////////////////////////////////////////////
// HOOKS
////////////////////////////////////////////////////////////////////////////////
/**
* Handles the click behavior for router `<Link>` components. This is useful if
* you need to create custom `<Link>` components with the same click behavior we
* use in our exported `<Link>`.
*/
function useLinkClickHandler(to, _temp) {
let {
target,
replace: replaceProp,
state
} = _temp === void 0 ? {} : _temp;
let navigate = useNavigate$1();
let location = useLocation();
let path = useResolvedPath(to);
return React.useCallback(event => {
if (event.button === 0 && ( // Ignore everything but left clicks
!target || target === "_self") && // Let browser handle "target=_blank" etc.
!isModifiedEvent(event) // Ignore clicks with modifier keys
) {
event.preventDefault(); // If the URL hasn't changed, a regular <a> will do a replace instead of
// a push, so do the same here.
let replace = !!replaceProp || createPath(location) === createPath(path);
navigate(to, {
replace,
state
});
}
}, [location, navigate, path, replaceProp, state, target, to]);
}
const ToggleVisibility = ({
hidden,
children
}) => React__default["default"].createElement("div", {
hidden: hidden
}, children);
const {
document: document$1
} = window_1;
const getBase = () => `${document$1.location.pathname}?`; // const queryNavigate: NavigateFn = (to: string | number, options?: NavigateOptions<{}>) =>
// typeof to === 'number' ? navigate(to) : navigate(`${getBase()}path=${to}`, options);
const useNavigate = () => {
const navigate = useNavigate$1();
return React.useCallback((to, _a = {}) => {
var {
plain
} = _a,
options = __rest(_a, ["plain"]);
if (typeof to === 'string' && to.startsWith('#')) {
document$1.location.hash = to;
return undefined;
}
if (typeof to === 'string') {
const target = plain ? to : `?path=${to}`;
return navigate(target, options);
}
if (typeof to === 'number') {
return navigate(to);
}
return undefined;
}, []);
}; // A component that will navigate to a new location/path when clicked
const Link = _a => {
var {
to,
children
} = _a,
rest = __rest(_a, ["to", "children"]);
return React__default["default"].createElement(Link$1, Object.assign({
to: `${getBase()}path=${to}`
}, rest), children);
};
Link.displayName = 'QueryLink'; // A render-prop component where children is called with a location
// and will be called whenever it changes when it changes
const Location = ({
children
}) => {
const location = useLocation();
const {
path,
singleStory
} = queryFromString(location.search);
const {
viewMode,
storyId,
refId
} = parsePath$2(path);
return React__default["default"].createElement(React__default["default"].Fragment, null, children({
path,
location,
viewMode,
storyId,
refId,
singleStory: singleStory === 'true'
}));
};
Location.displayName = 'QueryLocation'; // A render-prop component for rendering when a certain path is hit.
// It's immensely similar to `Location` but it receives an addition data property: `match`.
// match has a truthy value when the path is hit.
const Match = ({
children,
path: targetPath,
startsWith = false
}) => React__default["default"].createElement(Location, null, _a => {
var {
path: urlPath
} = _a,
rest = __rest(_a, ["path"]);
return children(Object.assign({
match: getMatch(urlPath, targetPath, startsWith)
}, rest));
});
Match.displayName = 'QueryMatch'; // A component to conditionally render children based on matching a target path
const Route = ({
path,
children,
startsWith = false,
hideOnly = false
}) => React__default["default"].createElement(Match, {
path: path,
startsWith: startsWith
}, ({
match
}) => {
if (hideOnly) {
return React__default["default"].createElement(ToggleVisibility, {
hidden: !match
}, children);
}
return match ? children : null;
});
Route.displayName = 'Route';
const LocationProvider = (...args) => BrowserRouter(...args);
const BaseLocationProvider = (...args) => Router(...args);
exports.BaseLocationProvider = BaseLocationProvider;
exports.DEEPLY_EQUAL = DEEPLY_EQUAL;
exports.Link = Link;
exports.Location = Location;
exports.LocationProvider = LocationProvider;
exports.Match = Match;
exports.Route = Route;
exports.buildArgsParam = buildArgsParam;
exports.deepDiff = deepDiff;
exports.getMatch = getMatch;
exports.parsePath = parsePath$2;
exports.queryFromLocation = queryFromLocation;
exports.queryFromString = queryFromString;
exports.stringifyQuery = stringifyQuery;
exports.useNavigate = useNaviga