@wizyvision/react-schedule
Version:
32,953 lines • 1.13 MB
JavaScript
import * as React from 'react';
import React__default, { Children, isValidElement, cloneElement, createContext, memo, useEffect, useLayoutEffect, useState, useCallback, useMemo, useContext } from 'react';
import { ThemeProvider, TableContainer, TableCell, Box, useTheme as useTheme$3, darken as darken$1, Typography as Typography$1, Tooltip, ListItemText, TableRow, FormControl, InputLabel, Select, MenuItem, Table, TableHead, TableBody, Button as Button$1, Menu, IconButton as IconButton$1 } from '@mui/material';
import { useThemeProps, styled as styled$3, useTheme as useTheme$2, alpha, createTheme as createTheme$1 } from '@mui/material/styles';
import { jsx, jsxs } from 'react/jsx-runtime';
import emStyled from '@emotion/styled';
import { ThemeContext } from '@emotion/react';
import Box$1 from '@mui/material/Box';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
import useMediaQuery from '@mui/material/useMediaQuery';
import { createSvgIcon } from '@mui/material/utils';
import Fade from '@mui/material/Fade';
import ButtonBase from '@mui/material/ButtonBase';
import ReactDOM from 'react-dom';
import IconButton from '@mui/material/IconButton';
import MuiTextField from '@mui/material/TextField';
import InputAdornment from '@mui/material/InputAdornment';
import Grow from '@mui/material/Grow';
import MuiPaper from '@mui/material/Paper';
import MuiPopper from '@mui/material/Popper';
import BaseFocusTrap from '@mui/material/Unstable_TrapFocus';
import Button from '@mui/material/Button';
import DialogActions from '@mui/material/DialogActions';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import Chip from '@mui/material/Chip';
import DialogContent from '@mui/material/DialogContent';
import MuiDialog, { dialogClasses } from '@mui/material/Dialog';
function _iterableToArrayLimit(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = !0,
o = !1;
try {
if (i = (t = t.call(r)).next, 0 === l) {
if (Object(t) !== t) return;
f = !1;
} else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = !0, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r && (o = o.filter(function (r) {
return Object.getOwnPropertyDescriptor(e, r).enumerable;
})), t.push.apply(t, o);
}
return t;
}
function _objectSpread2(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
_defineProperty$5(e, r, t[r]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
});
}
return e;
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : String(i);
}
function _defineProperty$5(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var propTypes = {exports: {}};
var reactIs$1 = {exports: {}};
var reactIs_production_min$1 = {};
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var hasRequiredReactIs_production_min$1;
function requireReactIs_production_min$1 () {
if (hasRequiredReactIs_production_min$1) return reactIs_production_min$1;
hasRequiredReactIs_production_min$1 = 1;
var b="function"===typeof Symbol&&Symbol.for,c=b?Symbol.for("react.element"):60103,d=b?Symbol.for("react.portal"):60106,e=b?Symbol.for("react.fragment"):60107,f=b?Symbol.for("react.strict_mode"):60108,g=b?Symbol.for("react.profiler"):60114,h=b?Symbol.for("react.provider"):60109,k=b?Symbol.for("react.context"):60110,l=b?Symbol.for("react.async_mode"):60111,m=b?Symbol.for("react.concurrent_mode"):60111,n=b?Symbol.for("react.forward_ref"):60112,p=b?Symbol.for("react.suspense"):60113,q=b?
Symbol.for("react.suspense_list"):60120,r=b?Symbol.for("react.memo"):60115,t=b?Symbol.for("react.lazy"):60116,v=b?Symbol.for("react.block"):60121,w=b?Symbol.for("react.fundamental"):60117,x=b?Symbol.for("react.responder"):60118,y=b?Symbol.for("react.scope"):60119;
function z(a){if("object"===typeof a&&null!==a){var u=a.$$typeof;switch(u){case c:switch(a=a.type,a){case l:case m:case e:case g:case f:case p:return a;default:switch(a=a&&a.$$typeof,a){case k:case n:case t:case r:case h:return a;default:return u}}case d:return u}}}function A(a){return z(a)===m}reactIs_production_min$1.AsyncMode=l;reactIs_production_min$1.ConcurrentMode=m;reactIs_production_min$1.ContextConsumer=k;reactIs_production_min$1.ContextProvider=h;reactIs_production_min$1.Element=c;reactIs_production_min$1.ForwardRef=n;reactIs_production_min$1.Fragment=e;reactIs_production_min$1.Lazy=t;reactIs_production_min$1.Memo=r;reactIs_production_min$1.Portal=d;
reactIs_production_min$1.Profiler=g;reactIs_production_min$1.StrictMode=f;reactIs_production_min$1.Suspense=p;reactIs_production_min$1.isAsyncMode=function(a){return A(a)||z(a)===l};reactIs_production_min$1.isConcurrentMode=A;reactIs_production_min$1.isContextConsumer=function(a){return z(a)===k};reactIs_production_min$1.isContextProvider=function(a){return z(a)===h};reactIs_production_min$1.isElement=function(a){return "object"===typeof a&&null!==a&&a.$$typeof===c};reactIs_production_min$1.isForwardRef=function(a){return z(a)===n};reactIs_production_min$1.isFragment=function(a){return z(a)===e};reactIs_production_min$1.isLazy=function(a){return z(a)===t};
reactIs_production_min$1.isMemo=function(a){return z(a)===r};reactIs_production_min$1.isPortal=function(a){return z(a)===d};reactIs_production_min$1.isProfiler=function(a){return z(a)===g};reactIs_production_min$1.isStrictMode=function(a){return z(a)===f};reactIs_production_min$1.isSuspense=function(a){return z(a)===p};
reactIs_production_min$1.isValidElementType=function(a){return "string"===typeof a||"function"===typeof a||a===e||a===m||a===g||a===f||a===p||a===q||"object"===typeof a&&null!==a&&(a.$$typeof===t||a.$$typeof===r||a.$$typeof===h||a.$$typeof===k||a.$$typeof===n||a.$$typeof===w||a.$$typeof===x||a.$$typeof===y||a.$$typeof===v)};reactIs_production_min$1.typeOf=z;
return reactIs_production_min$1;
}
var reactIs_development$1 = {};
/** @license React v16.13.1
* react-is.development.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var hasRequiredReactIs_development$1;
function requireReactIs_development$1 () {
if (hasRequiredReactIs_development$1) return reactIs_development$1;
hasRequiredReactIs_development$1 = 1;
if (process.env.NODE_ENV !== "production") {
(function() {
// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
// nor polyfill, then a plain number is used for performance.
var hasSymbol = typeof Symbol === 'function' && Symbol.for;
var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;
var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;
var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;
var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;
var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;
var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
// (unstable) APIs that have been removed. Can we remove the symbols?
var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf;
var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf;
var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1;
var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8;
var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4;
var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9;
var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5;
var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6;
var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7;
function isValidElementType(type) {
return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.
type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE);
}
function typeOf(object) {
if (typeof object === 'object' && object !== null) {
var $$typeof = object.$$typeof;
switch ($$typeof) {
case REACT_ELEMENT_TYPE:
var type = object.type;
switch (type) {
case REACT_ASYNC_MODE_TYPE:
case REACT_CONCURRENT_MODE_TYPE:
case REACT_FRAGMENT_TYPE:
case REACT_PROFILER_TYPE:
case REACT_STRICT_MODE_TYPE:
case REACT_SUSPENSE_TYPE:
return type;
default:
var $$typeofType = type && type.$$typeof;
switch ($$typeofType) {
case REACT_CONTEXT_TYPE:
case REACT_FORWARD_REF_TYPE:
case REACT_LAZY_TYPE:
case REACT_MEMO_TYPE:
case REACT_PROVIDER_TYPE:
return $$typeofType;
default:
return $$typeof;
}
}
case REACT_PORTAL_TYPE:
return $$typeof;
}
}
return undefined;
} // AsyncMode is deprecated along with isAsyncMode
var AsyncMode = REACT_ASYNC_MODE_TYPE;
var ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
var ContextConsumer = REACT_CONTEXT_TYPE;
var ContextProvider = REACT_PROVIDER_TYPE;
var Element = REACT_ELEMENT_TYPE;
var ForwardRef = REACT_FORWARD_REF_TYPE;
var Fragment = REACT_FRAGMENT_TYPE;
var Lazy = REACT_LAZY_TYPE;
var Memo = REACT_MEMO_TYPE;
var Portal = REACT_PORTAL_TYPE;
var Profiler = REACT_PROFILER_TYPE;
var StrictMode = REACT_STRICT_MODE_TYPE;
var Suspense = REACT_SUSPENSE_TYPE;
var hasWarnedAboutDeprecatedIsAsyncMode = false; // AsyncMode should be deprecated
function isAsyncMode(object) {
{
if (!hasWarnedAboutDeprecatedIsAsyncMode) {
hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint
console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 17+. Update your code to use ' + 'ReactIs.isConcurrentMode() instead. It has the exact same API.');
}
}
return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE;
}
function isConcurrentMode(object) {
return typeOf(object) === REACT_CONCURRENT_MODE_TYPE;
}
function isContextConsumer(object) {
return typeOf(object) === REACT_CONTEXT_TYPE;
}
function isContextProvider(object) {
return typeOf(object) === REACT_PROVIDER_TYPE;
}
function isElement(object) {
return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
}
function isForwardRef(object) {
return typeOf(object) === REACT_FORWARD_REF_TYPE;
}
function isFragment(object) {
return typeOf(object) === REACT_FRAGMENT_TYPE;
}
function isLazy(object) {
return typeOf(object) === REACT_LAZY_TYPE;
}
function isMemo(object) {
return typeOf(object) === REACT_MEMO_TYPE;
}
function isPortal(object) {
return typeOf(object) === REACT_PORTAL_TYPE;
}
function isProfiler(object) {
return typeOf(object) === REACT_PROFILER_TYPE;
}
function isStrictMode(object) {
return typeOf(object) === REACT_STRICT_MODE_TYPE;
}
function isSuspense(object) {
return typeOf(object) === REACT_SUSPENSE_TYPE;
}
reactIs_development$1.AsyncMode = AsyncMode;
reactIs_development$1.ConcurrentMode = ConcurrentMode;
reactIs_development$1.ContextConsumer = ContextConsumer;
reactIs_development$1.ContextProvider = ContextProvider;
reactIs_development$1.Element = Element;
reactIs_development$1.ForwardRef = ForwardRef;
reactIs_development$1.Fragment = Fragment;
reactIs_development$1.Lazy = Lazy;
reactIs_development$1.Memo = Memo;
reactIs_development$1.Portal = Portal;
reactIs_development$1.Profiler = Profiler;
reactIs_development$1.StrictMode = StrictMode;
reactIs_development$1.Suspense = Suspense;
reactIs_development$1.isAsyncMode = isAsyncMode;
reactIs_development$1.isConcurrentMode = isConcurrentMode;
reactIs_development$1.isContextConsumer = isContextConsumer;
reactIs_development$1.isContextProvider = isContextProvider;
reactIs_development$1.isElement = isElement;
reactIs_development$1.isForwardRef = isForwardRef;
reactIs_development$1.isFragment = isFragment;
reactIs_development$1.isLazy = isLazy;
reactIs_development$1.isMemo = isMemo;
reactIs_development$1.isPortal = isPortal;
reactIs_development$1.isProfiler = isProfiler;
reactIs_development$1.isStrictMode = isStrictMode;
reactIs_development$1.isSuspense = isSuspense;
reactIs_development$1.isValidElementType = isValidElementType;
reactIs_development$1.typeOf = typeOf;
})();
}
return reactIs_development$1;
}
var hasRequiredReactIs;
function requireReactIs () {
if (hasRequiredReactIs) return reactIs$1.exports;
hasRequiredReactIs = 1;
if (process.env.NODE_ENV === 'production') {
reactIs$1.exports = requireReactIs_production_min$1();
} else {
reactIs$1.exports = requireReactIs_development$1();
}
return reactIs$1.exports;
}
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
var objectAssign;
var hasRequiredObjectAssign;
function requireObjectAssign () {
if (hasRequiredObjectAssign) return objectAssign;
hasRequiredObjectAssign = 1;
/* eslint-disable no-unused-vars */
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
function toObject(val) {
if (val === null || val === undefined) {
throw new TypeError('Object.assign cannot be called with null or undefined');
}
return Object(val);
}
function shouldUseNative() {
try {
if (!Object.assign) {
return false;
}
// Detect buggy property enumeration order in older V8 versions.
// https://bugs.chromium.org/p/v8/issues/detail?id=4118
var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
test1[5] = 'de';
if (Object.getOwnPropertyNames(test1)[0] === '5') {
return false;
}
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
var test2 = {};
for (var i = 0; i < 10; i++) {
test2['_' + String.fromCharCode(i)] = i;
}
var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
return test2[n];
});
if (order2.join('') !== '0123456789') {
return false;
}
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
var test3 = {};
'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
test3[letter] = letter;
});
if (Object.keys(Object.assign({}, test3)).join('') !==
'abcdefghijklmnopqrst') {
return false;
}
return true;
} catch (err) {
// We don't expect any of the above to throw, but better to be safe.
return false;
}
}
objectAssign = shouldUseNative() ? Object.assign : function (target, source) {
var from;
var to = toObject(target);
var symbols;
for (var s = 1; s < arguments.length; s++) {
from = Object(arguments[s]);
for (var key in from) {
if (hasOwnProperty.call(from, key)) {
to[key] = from[key];
}
}
if (getOwnPropertySymbols) {
symbols = getOwnPropertySymbols(from);
for (var i = 0; i < symbols.length; i++) {
if (propIsEnumerable.call(from, symbols[i])) {
to[symbols[i]] = from[symbols[i]];
}
}
}
}
return to;
};
return objectAssign;
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var ReactPropTypesSecret_1;
var hasRequiredReactPropTypesSecret;
function requireReactPropTypesSecret () {
if (hasRequiredReactPropTypesSecret) return ReactPropTypesSecret_1;
hasRequiredReactPropTypesSecret = 1;
var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
ReactPropTypesSecret_1 = ReactPropTypesSecret;
return ReactPropTypesSecret_1;
}
var has;
var hasRequiredHas;
function requireHas () {
if (hasRequiredHas) return has;
hasRequiredHas = 1;
has = Function.call.bind(Object.prototype.hasOwnProperty);
return has;
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var checkPropTypes_1;
var hasRequiredCheckPropTypes;
function requireCheckPropTypes () {
if (hasRequiredCheckPropTypes) return checkPropTypes_1;
hasRequiredCheckPropTypes = 1;
var printWarning = function() {};
if (process.env.NODE_ENV !== 'production') {
var ReactPropTypesSecret = requireReactPropTypesSecret();
var loggedTypeFailures = {};
var has = requireHas();
printWarning = function(text) {
var message = 'Warning: ' + text;
if (typeof console !== 'undefined') {
console.error(message);
}
try {
// --- Welcome to debugging React ---
// This error was thrown as a convenience so that you can use this stack
// to find the callsite that caused this warning to fire.
throw new Error(message);
} catch (x) { /**/ }
};
}
/**
* Assert that the values match with the type specs.
* Error messages are memorized and will only be shown once.
*
* @param {object} typeSpecs Map of name to a ReactPropType
* @param {object} values Runtime values that need to be type-checked
* @param {string} location e.g. "prop", "context", "child context"
* @param {string} componentName Name of the component for error messages.
* @param {?Function} getStack Returns the component stack.
* @private
*/
function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
if (process.env.NODE_ENV !== 'production') {
for (var typeSpecName in typeSpecs) {
if (has(typeSpecs, typeSpecName)) {
var error;
// Prop type validation may throw. In case they do, we don't want to
// fail the render phase where it didn't fail before. So we log it.
// After these have been cleaned up, we'll let them throw.
try {
// This is intentionally an invariant that gets caught. It's the same
// behavior as without this statement except with a better message.
if (typeof typeSpecs[typeSpecName] !== 'function') {
var err = Error(
(componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' +
'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' +
'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.'
);
err.name = 'Invariant Violation';
throw err;
}
error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
} catch (ex) {
error = ex;
}
if (error && !(error instanceof Error)) {
printWarning(
(componentName || 'React class') + ': type specification of ' +
location + ' `' + typeSpecName + '` is invalid; the type checker ' +
'function must return `null` or an `Error` but returned a ' + typeof error + '. ' +
'You may have forgotten to pass an argument to the type checker ' +
'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' +
'shape all require an argument).'
);
}
if (error instanceof Error && !(error.message in loggedTypeFailures)) {
// Only monitor this failure once because there tends to be a lot of the
// same error.
loggedTypeFailures[error.message] = true;
var stack = getStack ? getStack() : '';
printWarning(
'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '')
);
}
}
}
}
}
/**
* Resets warning cache when testing.
*
* @private
*/
checkPropTypes.resetWarningCache = function() {
if (process.env.NODE_ENV !== 'production') {
loggedTypeFailures = {};
}
};
checkPropTypes_1 = checkPropTypes;
return checkPropTypes_1;
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var factoryWithTypeCheckers;
var hasRequiredFactoryWithTypeCheckers;
function requireFactoryWithTypeCheckers () {
if (hasRequiredFactoryWithTypeCheckers) return factoryWithTypeCheckers;
hasRequiredFactoryWithTypeCheckers = 1;
var ReactIs = requireReactIs();
var assign = requireObjectAssign();
var ReactPropTypesSecret = requireReactPropTypesSecret();
var has = requireHas();
var checkPropTypes = requireCheckPropTypes();
var printWarning = function() {};
if (process.env.NODE_ENV !== 'production') {
printWarning = function(text) {
var message = 'Warning: ' + text;
if (typeof console !== 'undefined') {
console.error(message);
}
try {
// --- Welcome to debugging React ---
// This error was thrown as a convenience so that you can use this stack
// to find the callsite that caused this warning to fire.
throw new Error(message);
} catch (x) {}
};
}
function emptyFunctionThatReturnsNull() {
return null;
}
factoryWithTypeCheckers = function(isValidElement, throwOnDirectAccess) {
/* global Symbol */
var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
/**
* Returns the iterator method function contained on the iterable object.
*
* Be sure to invoke the function with the iterable as context:
*
* var iteratorFn = getIteratorFn(myIterable);
* if (iteratorFn) {
* var iterator = iteratorFn.call(myIterable);
* ...
* }
*
* @param {?object} maybeIterable
* @return {?function}
*/
function getIteratorFn(maybeIterable) {
var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
if (typeof iteratorFn === 'function') {
return iteratorFn;
}
}
/**
* Collection of methods that allow declaration and validation of props that are
* supplied to React components. Example usage:
*
* var Props = require('ReactPropTypes');
* var MyArticle = React.createClass({
* propTypes: {
* // An optional string prop named "description".
* description: Props.string,
*
* // A required enum prop named "category".
* category: Props.oneOf(['News','Photos']).isRequired,
*
* // A prop named "dialog" that requires an instance of Dialog.
* dialog: Props.instanceOf(Dialog).isRequired
* },
* render: function() { ... }
* });
*
* A more formal specification of how these methods are used:
*
* type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
* decl := ReactPropTypes.{type}(.isRequired)?
*
* Each and every declaration produces a function with the same signature. This
* allows the creation of custom validation functions. For example:
*
* var MyLink = React.createClass({
* propTypes: {
* // An optional string or URI prop named "href".
* href: function(props, propName, componentName) {
* var propValue = props[propName];
* if (propValue != null && typeof propValue !== 'string' &&
* !(propValue instanceof URI)) {
* return new Error(
* 'Expected a string or an URI for ' + propName + ' in ' +
* componentName
* );
* }
* }
* },
* render: function() {...}
* });
*
* @internal
*/
var ANONYMOUS = '<<anonymous>>';
// Important!
// Keep this list in sync with production version in `./factoryWithThrowingShims.js`.
var ReactPropTypes = {
array: createPrimitiveTypeChecker('array'),
bigint: createPrimitiveTypeChecker('bigint'),
bool: createPrimitiveTypeChecker('boolean'),
func: createPrimitiveTypeChecker('function'),
number: createPrimitiveTypeChecker('number'),
object: createPrimitiveTypeChecker('object'),
string: createPrimitiveTypeChecker('string'),
symbol: createPrimitiveTypeChecker('symbol'),
any: createAnyTypeChecker(),
arrayOf: createArrayOfTypeChecker,
element: createElementTypeChecker(),
elementType: createElementTypeTypeChecker(),
instanceOf: createInstanceTypeChecker,
node: createNodeChecker(),
objectOf: createObjectOfTypeChecker,
oneOf: createEnumTypeChecker,
oneOfType: createUnionTypeChecker,
shape: createShapeTypeChecker,
exact: createStrictShapeTypeChecker,
};
/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
/*eslint-disable no-self-compare*/
function is(x, y) {
// SameValue algorithm
if (x === y) {
// Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y;
}
}
/*eslint-enable no-self-compare*/
/**
* We use an Error-like object for backward compatibility as people may call
* PropTypes directly and inspect their output. However, we don't use real
* Errors anymore. We don't inspect their stack anyway, and creating them
* is prohibitively expensive if they are created too often, such as what
* happens in oneOfType() for any type before the one that matched.
*/
function PropTypeError(message, data) {
this.message = message;
this.data = data && typeof data === 'object' ? data: {};
this.stack = '';
}
// Make `instanceof Error` still work for returned errors.
PropTypeError.prototype = Error.prototype;
function createChainableTypeChecker(validate) {
if (process.env.NODE_ENV !== 'production') {
var manualPropTypeCallCache = {};
var manualPropTypeWarningCount = 0;
}
function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {
componentName = componentName || ANONYMOUS;
propFullName = propFullName || propName;
if (secret !== ReactPropTypesSecret) {
if (throwOnDirectAccess) {
// New behavior only for users of `prop-types` package
var err = new Error(
'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
'Use `PropTypes.checkPropTypes()` to call them. ' +
'Read more at http://fb.me/use-check-prop-types'
);
err.name = 'Invariant Violation';
throw err;
} else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') {
// Old behavior for people using React.PropTypes
var cacheKey = componentName + ':' + propName;
if (
!manualPropTypeCallCache[cacheKey] &&
// Avoid spamming the console because they are often not actionable except for lib authors
manualPropTypeWarningCount < 3
) {
printWarning(
'You are manually calling a React.PropTypes validation ' +
'function for the `' + propFullName + '` prop on `' + componentName + '`. This is deprecated ' +
'and will throw in the standalone `prop-types` package. ' +
'You may be seeing this warning due to a third-party PropTypes ' +
'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.'
);
manualPropTypeCallCache[cacheKey] = true;
manualPropTypeWarningCount++;
}
}
}
if (props[propName] == null) {
if (isRequired) {
if (props[propName] === null) {
return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
}
return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
}
return null;
} else {
return validate(props, propName, componentName, location, propFullName);
}
}
var chainedCheckType = checkType.bind(null, false);
chainedCheckType.isRequired = checkType.bind(null, true);
return chainedCheckType;
}
function createPrimitiveTypeChecker(expectedType) {
function validate(props, propName, componentName, location, propFullName, secret) {
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== expectedType) {
// `propValue` being instance of, say, date/regexp, pass the 'object'
// check, but we can offer a more precise error message here rather than
// 'of type `object`'.
var preciseType = getPreciseType(propValue);
return new PropTypeError(
'Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'),
{expectedType: expectedType}
);
}
return null;
}
return createChainableTypeChecker(validate);
}
function createAnyTypeChecker() {
return createChainableTypeChecker(emptyFunctionThatReturnsNull);
}
function createArrayOfTypeChecker(typeChecker) {
function validate(props, propName, componentName, location, propFullName) {
if (typeof typeChecker !== 'function') {
return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');
}
var propValue = props[propName];
if (!Array.isArray(propValue)) {
var propType = getPropType(propValue);
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));
}
for (var i = 0; i < propValue.length; i++) {
var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret);
if (error instanceof Error) {
return error;
}
}
return null;
}
return createChainableTypeChecker(validate);
}
function createElementTypeChecker() {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
if (!isValidElement(propValue)) {
var propType = getPropType(propValue);
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.'));
}
return null;
}
return createChainableTypeChecker(validate);
}
function createElementTypeTypeChecker() {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
if (!ReactIs.isValidElementType(propValue)) {
var propType = getPropType(propValue);
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement type.'));
}
return null;
}
return createChainableTypeChecker(validate);
}
function createInstanceTypeChecker(expectedClass) {
function validate(props, propName, componentName, location, propFullName) {
if (!(props[propName] instanceof expectedClass)) {
var expectedClassName = expectedClass.name || ANONYMOUS;
var actualClassName = getClassName(props[propName]);
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));
}
return null;
}
return createChainableTypeChecker(validate);
}
function createEnumTypeChecker(expectedValues) {
if (!Array.isArray(expectedValues)) {
if (process.env.NODE_ENV !== 'production') {
if (arguments.length > 1) {
printWarning(
'Invalid arguments supplied to oneOf, expected an array, got ' + arguments.length + ' arguments. ' +
'A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).'
);
} else {
printWarning('Invalid argument supplied to oneOf, expected an array.');
}
}
return emptyFunctionThatReturnsNull;
}
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
for (var i = 0; i < expectedValues.length; i++) {
if (is(propValue, expectedValues[i])) {
return null;
}
}
var valuesString = JSON.stringify(expectedValues, function replacer(key, value) {
var type = getPreciseType(value);
if (type === 'symbol') {
return String(value);
}
return value;
});
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + String(propValue) + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));
}
return createChainableTypeChecker(validate);
}
function createObjectOfTypeChecker(typeChecker) {
function validate(props, propName, componentName, location, propFullName) {
if (typeof typeChecker !== 'function') {
return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');
}
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== 'object') {
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));
}
for (var key in propValue) {
if (has(propValue, key)) {
var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
if (error instanceof Error) {
return error;
}
}
}
return null;
}
return createChainableTypeChecker(validate);
}
function createUnionTypeChecker(arrayOfTypeCheckers) {
if (!Array.isArray(arrayOfTypeCheckers)) {
process.env.NODE_ENV !== 'production' ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : void 0;
return emptyFunctionThatReturnsNull;
}
for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
var checker = arrayOfTypeCheckers[i];
if (typeof checker !== 'function') {
printWarning(
'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' +
'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.'
);
return emptyFunctionThatReturnsNull;
}
}
function validate(props, propName, componentName, location, propFullName) {
var expectedTypes = [];
for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
var checker = arrayOfTypeCheckers[i];
var checkerResult = checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret);
if (checkerResult == null) {
return null;
}
if (checkerResult.data && has(checkerResult.data, 'expectedType')) {
expectedTypes.push(checkerResult.data.expectedType);
}
}
var expectedTypesMessage = (expectedTypes.length > 0) ? ', expected one of type [' + expectedTypes.join(', ') + ']': '';
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`' + expectedTypesMessage + '.'));
}
return createChainableTypeChecker(validate);
}
function createNodeChecker() {
function validate(props, propName, componentName, location, propFullName) {
if (!isNode(props[propName])) {
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));
}
return null;
}
return createChainableTypeChecker(validate);
}
function invalidValidatorError(componentName, location, propFullName, key, type) {
return new PropTypeError(
(componentName || 'React class') + ': ' + location + ' type `' + propFullName + '.' + key + '` is invalid; ' +
'it must be a function, usually from the `prop-types` package, but received `' + type + '`.'
);
}
function createShapeTypeChecker(shapeTypes) {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== 'object') {
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
}
for (var key in shapeTypes) {
var checker = shapeTypes[key];
if (typeof checker !== 'function') {
return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker));
}
var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
if (error) {
return error;
}
}
return null;
}
return createChainableTypeChecker(validate);
}
function createStrictShapeTypeChecker(shapeTypes) {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== 'object') {
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
}
// We need to check all keys in case some are required but missing from props.
var allKeys = assign({}, props[propName], shapeTypes);
for (var key in allKeys) {
var checker = shapeTypes[key];
if (has(shapeTypes, key) && typeof checker !== 'function') {
return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker));
}
if (!checker) {
return new PropTypeError(
'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' +
'\nBad object: ' + JSON.stringify(props[propName], null, ' ') +
'\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, ' ')
);
}
var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
if (error) {
return error;
}
}
return null;
}
return createChainableTypeChecker(validate);
}
function isNode(propValue) {
switch (typeof propValue) {
case 'number':
case 'string':
case 'undefined':
return true;
case 'boolean':
return !propValue;
case 'object':
if (Array.isArray(propValue)) {
return propValue.every(isNode);
}
if (propValue === null || isValidElement(propValue)) {
return true;
}
var iteratorFn = getIteratorFn(propValue);
if (iteratorFn) {
var iterator = iteratorFn.call(propValue);
var step;
if (iteratorFn !== propValue.entries) {
while (!(step = iterator.next()).done) {
if (!isNode(step.value)) {
return false;
}
}
} else {
// Iterator will provide entry [k,v] tuples rather than values.
while (!(step = iterator.next()).done) {
var entry = step.value;
if (entry) {
if (!isNode(entry[1])) {
return false;
}
}
}
}
} else {
return false;
}
return true;
default:
return false;
}
}
function isSymbol(propType, propValue) {
// Native Symbol.
if (propType === 'symbol') {
return true;
}
// falsy value can't be a Symbol
if (!propValue) {
return false;
}
// 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
if (propValue['@@toStringTag'] === 'Symbol') {
return true;
}
// Fallback for non-spec compliant Symbols which are polyfilled.
if (typeof Symbol === 'function' && propValue instanceof Symbol) {
return true;
}
return false;
}
// Equivalent of `typeof` but with special handling for array and regexp.
function getPropType(propValue) {
var propType = typeof propValue;
if (Array.isArray(propValue)) {
return 'array';
}
if (propValue instanceof RegExp) {
// Old webkits (at least until Android 4.0) return 'function' rather than
// 'object' for typeof a RegExp. We'll normalize this here so that /bla/
// passes PropTypes.object.
return 'object';
}
if (isSymbol(propType, propValue)) {
return 'symbol';
}
return propType;
}
// This handles more types than `getPropType`. Only used for error messages.
// See `createPrimitiveTypeChecker`.
function getPreciseType(propValue) {
if (typeof propValue === 'undefined' || propValue === null) {
return '' + propValue;
}
var propType = getPropType(propValue);
if (propType === 'object') {
if (propValue instanceof Date) {
return 'date';
} else if (propValue instanceof RegExp) {
return 'regexp';
}
}
return propType;
}
// Returns a string that is postfixed to a warning about an invalid type.
// For example, "undefined" or "of type array"
function getPostfixForTypeWarning(value) {
var type = getPreciseType(value);
switch (type) {
case 'array':
case 'object':
return 'an ' + type;
case 'boolean':
case 'date':
case 'regexp':
return 'a ' + type;
default:
return type;
}
}
// Returns class name of the object, if any.
function getClassName(propValue) {
if (!propValue.constructor || !propValue.constructor.name) {
return ANONYMOUS;
}
return propValue.constructor.name;
}
ReactPropTypes.checkPropTypes = checkPropTypes;
ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache;
ReactPropTypes.PropTypes = ReactPropTypes;
return ReactPropTypes;
};
return factoryWithTypeCheckers;
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var factoryWithThrowingShims;
var hasRequiredFactoryWithThrowingShims;
function requireFactoryWithThrowingShims () {
if (hasRequiredFactoryWithThrowingShims) return factoryWithThrowingShims;
hasRequiredFactoryWithThrowingShims = 1;
var ReactPropTypesSecret = requireReactPropTypesSecret();
function emptyFunction() {}
function emptyFunctionWithReset() {}
emptyFunctionWithReset.resetWarningCache = emptyFunction;
factoryWithThrowingShims = function() {
function shim(props, propName, componentName, location, propFullName, secret) {
if (secret === ReactPropTypesSecret) {
// It is still safe when called from React.
return;
}
var err = new Error(
'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
'Use PropTypes.checkPropTypes() to call them. ' +
'Read more at http://fb.me/use-check-prop-types'
);
err.name = 'Invariant Violation';
throw err;
} shim.isRequired = shim;
function getShim() {
return shim;
} // Important!
// Keep this list in sync with production version in `./factoryWithTypeCheckers.js`.
var ReactPropTypes = {
array: shim,
bigint: shim,
bool: shim,
func: shim,
number: shim,
object: shim,
string: shim,
symbol: shim,
any: shim,
arrayOf: getShim,
element: shim,
elementType: shim,
instanceOf: getShim,
node: shim,
objectOf: getShim,
oneOf: getShim,
oneOfType: getShim,
shape: getShim,
exact: getShim,
checkPropTypes: emptyFunctionWithReset,
resetWarningCache: emptyFunction
};
ReactPropTypes.PropTypes = ReactPropTypes;
return ReactPropTypes;
};
return factoryWithThrowingShims;
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
if (process.env.NODE_ENV !== 'production') {
var ReactIs = requireReactIs();
// By explicitly using `prop-types` you are opting into new development behavior.
// http://fb.me/prop-types-in-prod
var throwOnDirectAccess = true;
propTypes.exports = requireFactoryWithTypeCheckers()(ReactIs.isElement, throwOnDirectAccess);
} else {
// By explicitly using `prop-types` you are opting into new production behavior.
// http://fb.me/prop-types-in-prod
propTypes.exports = requireFactoryWithThrowingShims()();
}
var propTypesExports = propTypes.exports;
var PropTypes = /*@__PURE__*/getDefaultExportFromCjs(propTypesExports);
function toInteger(dirtyNumber) {
if (dirtyNumber === null || dirtyNumber === true || dirtyNumber === false) {
return NaN;
}
var number = Number(dirtyNumber);
if (isNaN(number)) {
return number;
}
return number < 0 ? Math.ceil(number) : Math.floor(number);
}
function requiredArgs(required, args) {
if (args.length < required) {
throw new TypeError(required + ' argument' + (required > 1 ? 's' : '') + ' required, but only ' + args.length + ' present');
}
}
/**
* @name toDate
* @category Common Helpers
* @summary Convert the given argument to an instance of Date.
*
* @description
* Convert the given argument to an instance of Date.
*
* If the argument is an instance of Date, the function returns its clone.
*
* If the argument is a number, it is treated as a timestamp.
*
* If the argument is none of the above, the function returns Invalid Date.
*
* **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.
*
* @param {Date|Number} argument - the value to convert
* @returns {Date} the parsed date in the local time zone
* @throws {TypeError} 1 argument required
*
* @example
* // Clone the date:
* const result = toDate(new Date(2014, 1, 11, 11, 30, 30))
* //=> Tue Feb 11 2014 11:30:30
*
* @example
* // Convert the timestamp to date:
* const result = toDate(1392098430000)
* //=> Tue Feb 11 2014 11:30:30
*/
function toDate(argument) {
requiredArgs(1, arguments);
var argStr = Object.prototype.toString.call(argument); // Clone the date
if (argument instanceof Date || typeof argument === 'object' && argStr === '[object Date]') {
// Prevent the date to lose the milliseconds when passed to new Date() in IE10
return new Date(argument.getTime());
} else if (typeof argument === 'number' || argStr === '[object Number]') {
return new Date(argument);
} else {
if ((typeof argument === 'string' || argStr === '[object String]') && typeof console !== 'undefined') {
// eslint-disable-next-line no-console
console.warn("Starting with v2.0.0-beta.1 date-fns doesn't accept strings as date arguments. Please use `parseISO` to parse strings. See: https://git.io/fjule"); // eslint-disable-next-line no-console
console.warn(new Error().stack);
}
return new Date(NaN);
}
}
/**
* @name addDays
* @category Day Helpers
* @summary Add the specified number of days to the given date.
*
* @description
* Add the specified number of days to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} amount - the amount of days to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
* @returns {Date} - the new date with the days added
* @throws {TypeError} - 2 arguments required
*
* @example
* // Add 10 days to 1 September 2014:
* const result = addDays(new Date(2014, 8, 1), 10)
* //=> Thu Sep 11 2014 00:00:00
*/
function addDays(dirtyDate, dirtyAmount) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var amount = toInteger(dirtyAmount);
if (isNaN(amount)) {
return new Date(NaN);
}
if (!amount) {
// If 0 days, no-op to avoid changing times in the hour before end of DST
return date;
}
date.setDate(date.getDate() + amount);
return date;
}
/**
* @name addMilliseconds
* @category Millisecond Helpers
* @summary Add the specified number of milliseconds to the given date.
*
* @description
* Add the specified number of milliseconds to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} amount - the amount of milliseconds to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
* @returns {Date} the new date with the milliseconds added
* @throws {TypeError} 2 arguments required
*
* @example
* // Add 750 milliseconds to 10 July 2014 12:45:30.000:
* const result = addMilliseconds(new Date(2014, 6, 10, 12, 45, 30, 0), 750)
* //=> Thu Jul 10 2014 12:45:30.750
*/
function addMilliseconds(dirtyDate, dirtyAmount) {
requiredArgs(2, arguments);
var timestamp = toDate(dirtyDate).getTime();
var amount = toInteger(dirtyAmount);
return new Date(timestamp + amount);
}
/**
* @name addSeconds
* @category Second Helpers
* @summary Add the specified number of seconds to the given date.
*
* @description
* Add the specified number of seconds to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} amount - the amount of seconds to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
* @returns {Date} the new date with the seconds added
* @throws {TypeError} 2 arguments required
*
* @example
* // Add 30 seconds to 10 July 2014 12:45:00:
* const result = addSeconds(new Date(2014, 6, 10, 12, 45, 0), 30)
* //=> Thu Jul 10 2014 12:45:30
*/
function addSeconds(dirtyDate, dirtyAmount) {
requiredArgs(2, arguments);
var amount = toInteger(dirtyAmount);
return addMilliseconds(dirtyDate, amount * 1000);
}
var MILLISECONDS_IN_MINUTE$3 = 60000;
/**
* @name addMinutes
* @category Minute Helpers
* @summary Add the specified number of minutes to the given date.
*
* @description
* Add the specified number of minutes to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} amount - the amount of minutes to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
* @returns {Date} the new date with the minutes added
* @throws {TypeError} 2 arguments required
*
* @example
* // Add 30 minutes to 10 July 2014 12:00:00:
* const result = addMinutes(new Date(2014, 6, 10, 12, 0), 30)
* //=> Thu Jul 10 2014 12:30:00
*/
function addMinutes(dirtyDate, dirtyAmount) {
requiredArgs(2, arguments);
var amount = toInteger(dirtyAmount);
return addMilliseconds(dirtyDate, amount * MILLISECONDS_IN_MINUTE$3);
}
var MILLISECONDS_IN_HOUR$3 = 3600000;
/**
* @name addHours
* @category Hour Helpers
* @summary Add the specified number of hours to the given date.
*
* @description
* Add the specified number of hours to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} amount - the amount of hours to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
* @returns {Date} the new date with the hours added
* @throws {TypeError} 2 arguments required
*
* @example
* // Add 2 hours to 10 July 2014 23:00:00:
* const result = addHours(new Date(2014, 6, 10, 23, 0), 2)
* //=> Fri Jul 11 2014 01:00:00
*/
function addHours(dirtyDate, dirtyAmount) {
requiredArgs(2, arguments);
var amount = toInteger(dirtyAmount);
return addMilliseconds(dirtyDate, amount * MILLISECONDS_IN_HOUR$3);
}
/**
* @name addWeeks
* @category Week Helpers
* @summary Add the specified number of weeks to the given date.
*
* @description
* Add the specified number of week to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} amount - the amount of weeks to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
* @returns {Date} the new date with the weeks added
* @throws {TypeError} 2 arguments required
*
* @example
* // Add 4 weeks to 1 September 2014:
* const result = addWeeks(new Date(2014, 8, 1), 4)
* //=> Mon Sep 29 2014 00:00:00
*/
function addWeeks(dirtyDate, dirtyAmount) {
requiredArgs(2, arguments);
var amount = toInteger(dirtyAmount);
var days = amount * 7;
return addDays(dirtyDate, days);
}
/**
* @name addMonths
* @category Month Helpers
* @summary Add the specified number of months to the given date.
*
* @description
* Add the specified number of months to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} amount - the amount of months to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
* @returns {Date} the new date with the months added
* @throws {TypeError} 2 arguments required
*
* @example
* // Add 5 months to 1 September 2014:
* const result = addMonths(new Date(2014, 8, 1), 5)
* //=> Sun Feb 01 2015 00:00:00
*/
function addMonths(dirtyDate, dirtyAmount) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var amount = toInteger(dirtyAmount);
if (isNaN(amount)) {
return new Date(NaN);
}
if (!amount) {
// If 0 months, no-op to avoid changing times in the hour before end of DST
return date;
}
var dayOfMonth = date.getDate(); // The JS Date object supports date math by accepting out-of-bounds values for
// month, day, etc. For example, new Date(2020, 0, 0) returns 31 Dec 2019 and
// new Date(2020, 13, 1) returns 1 Feb 2021. This is *almost* the behavior we
// want except that dates will wrap around the end of a month, meaning that
// new Date(2020, 13, 31) will return 3 Mar 2021 not 28 Feb 2021 as desired. So
// we'll default to the end of the desired month by adding 1 to the desired
// month and using a date of 0 to back up one day to the end of the desired
// month.
var endOfDesiredMonth = new Date(date.getTime());
endOfDesiredMonth.setMonth(date.getMonth() + amount + 1, 0);
var daysInMonth = endOfDesiredMonth.getDate();
if (dayOfMonth >= daysInMonth) {
// If we're already at the end of the month, then this is the correct date
// and we're done.
return endOfDesiredMonth;
} else {
// Otherwise, we now know that setting the original day-of-month value won't
// cause an overflow, so set the desired day-of-month. Note that we can't
// just set the date of `endOfDesiredMonth` because that object may have had
// its time changed in the unusual case where where a DST transition was on
// the last day of the month and its local time was in the hour skipped or
// repeated next to a DST transition. So we use `date` instead which is
// guaranteed to still have the original time.
date.setFullYear(endOfDesiredMonth.getFullYear(), endOfDesiredMonth.getMonth(), dayOfMonth);
return date;
}
}
/**
* @name addYears
* @category Year Helpers
* @summary Add the specified number of years to the given date.
*
* @description
* Add the specified number of years to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} amount - the amount of years to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
* @returns {Date} the new date with the years added
* @throws {TypeError} 2 arguments required
*
* @example
* // Add 5 years to 1 September 2014:
* const result = addYears(new Date(2014, 8, 1), 5)
* //=> Sun Sep 01 2019 00:00:00
*/
function addYears(dirtyDate, dirtyAmount) {
requiredArgs(2, arguments);
var amount = toInteger(dirtyAmount);
return addMonths(dirtyDate, amount * 12);
}
/**
* @name differenceInCalendarYears
* @category Year Helpers
* @summary Get the number of calendar years between the given dates.
*
* @description
* Get the number of calendar years between the given dates.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of calendar years
* @throws {TypeError} 2 arguments required
*
* @example
* // How many calendar years are between 31 December 2013 and 11 February 2015?
* const result = differenceInCalendarYears(
* new Date(2015, 1, 11),
* new Date(2013, 11, 31)
* )
* //=> 2
*/
function differenceInCalendarYears(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeft = toDate(dirtyDateLeft);
var dateRight = toDate(dirtyDateRight);
return dateLeft.getFullYear() - dateRight.getFullYear();
}
/**
* @name compareAsc
* @category Common Helpers
* @summary Compare the two dates and return -1, 0 or 1.
*
* @description
* Compare the two dates and return 1 if the first date is after the second,
* -1 if the first date is before the second or 0 if dates are equal.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the first date to compare
* @param {Date|Number} dateRight - the second date to compare
* @returns {Number} the result of the comparison
* @throws {TypeError} 2 arguments required
*
* @example
* // Compare 11 February 1987 and 10 July 1989:
* const result = compareAsc(new Date(1987, 1, 11), new Date(1989, 6, 10))
* //=> -1
*
* @example
* // Sort the array of dates:
* const result = [
* new Date(1995, 6, 2),
* new Date(1987, 1, 11),
* new Date(1989, 6, 10)
* ].sort(compareAsc)
* //=> [
* // Wed Feb 11 1987 00:00:00,
* // Mon Jul 10 1989 00:00:00,
* // Sun Jul 02 1995 00:00:00
* // ]
*/
function compareAsc(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeft = toDate(dirtyDateLeft);
var dateRight = toDate(dirtyDateRight);
var diff = dateLeft.getTime() - dateRight.getTime();
if (diff < 0) {
return -1;
} else if (diff > 0) {
return 1; // Return 0 if diff is 0; return NaN if diff is NaN
} else {
return diff;
}
}
/**
* @name differenceInYears
* @category Year Helpers
* @summary Get the number of full years between the given dates.
*
* @description
* Get the number of full years between the given dates.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of full years
* @throws {TypeError} 2 arguments required
*
* @example
* // How many full years are between 31 December 2013 and 11 February 2015?
* const result = differenceInYears(new Date(2015, 1, 11), new Date(2013, 11, 31))
* //=> 1
*/
function differenceInYears(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeft = toDate(dirtyDateLeft);
var dateRight = toDate(dirtyDateRight);
var sign = compareAsc(dateLeft, dateRight);
var difference = Math.abs(differenceInCalendarYears(dateLeft, dateRight)); // Set both dates to a valid leap year for accurate comparison when dealing
// with leap days
dateLeft.setFullYear(1584);
dateRight.setFullYear(1584); // Math.abs(diff in full years - diff in calendar years) === 1 if last calendar year is not full
// If so, result must be decreased by 1 in absolute value
var isLastYearNotFull = compareAsc(dateLeft, dateRight) === -sign;
var result = sign * (difference - Number(isLastYearNotFull)); // Prevent negative zero
return result === 0 ? 0 : result;
}
/**
* @name differenceInCalendarMonths
* @category Month Helpers
* @summary Get the number of calendar months between the given dates.
*
* @description
* Get the number of calendar months between the given dates.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of calendar months
* @throws {TypeError} 2 arguments required
*
* @example
* // How many calendar months are between 31 January 2014 and 1 September 2014?
* var result = differenceInCalendarMonths(
* new Date(2014, 8, 1),
* new Date(2014, 0, 31)
* )
* //=> 8
*/
function differenceInCalendarMonths(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeft = toDate(dirtyDateLeft);
var dateRight = toDate(dirtyDateRight);
var yearDiff = dateLeft.getFullYear() - dateRight.getFullYear();
var monthDiff = dateLeft.getMonth() - dateRight.getMonth();
return yearDiff * 12 + monthDiff;
}
/**
* @name endOfDay
* @category Day Helpers
* @summary Return the end of a day for the given date.
*
* @description
* Return the end of a day for the given date.
* The result will be in the local timezone.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the original date
* @returns {Date} the end of a day
* @throws {TypeError} 1 argument required
*
* @example
* // The end of a day for 2 September 2014 11:55:00:
* const result = endOfDay(new Date(2014, 8, 2, 11, 55, 0))
* //=> Tue Sep 02 2014 23:59:59.999
*/
function endOfDay(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
date.setHours(23, 59, 59, 999);
return date;
}
/**
* @name endOfMonth
* @category Month Helpers
* @summary Return the end of a month for the given date.
*
* @description
* Return the end of a month for the given date.
* The result will be in the local timezone.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the original date
* @returns {Date} the end of a month
* @throws {TypeError} 1 argument required
*
* @example
* // The end of a month for 2 September 2014 11:55:00:
* const result = endOfMonth(new Date(2014, 8, 2, 11, 55, 0))
* //=> Tue Sep 30 2014 23:59:59.999
*/
function endOfMonth(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var month = date.getMonth();
date.setFullYear(date.getFullYear(), month + 1, 0);
date.setHours(23, 59, 59, 999);
return date;
}
/**
* @name isLastDayOfMonth
* @category Month Helpers
* @summary Is the given date the last day of a month?
*
* @description
* Is the given date the last day of a month?
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to check
* @returns {Boolean} the date is the last day of a month
* @throws {TypeError} 1 argument required
*
* @example
* // Is 28 February 2014 the last day of a month?
* var result = isLastDayOfMonth(new Date(2014, 1, 28))
* //=> true
*/
function isLastDayOfMonth(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
return endOfDay(date).getTime() === endOfMonth(date).getTime();
}
/**
* @name differenceInMonths
* @category Month Helpers
* @summary Get the number of full months between the given dates.
*
* @description
* Get the number of full months between the given dates.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of full months
* @throws {TypeError} 2 arguments required
*
* @example
* // How many full months are between 31 January 2014 and 1 September 2014?
* var result = differenceInMonths(new Date(2014, 8, 1), new Date(2014, 0, 31))
* //=> 7
*/
function differenceInMonths(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeft = toDate(dirtyDateLeft);
var dateRight = toDate(dirtyDateRight);
var sign = compareAsc(dateLeft, dateRight);
var difference = Math.abs(differenceInCalendarMonths(dateLeft, dateRight));
var result; // Check for the difference of less than month
if (difference < 1) {
result = 0;
} else {
if (dateLeft.getMonth() === 1 && dateLeft.getDate() > 27) {
// This will check if the date is end of Feb and assign a higher end of month date
// to compare it with Jan
dateLeft.setDate(30);
}
dateLeft.setMonth(dateLeft.getMonth() - sign * difference); // Math.abs(diff in full months - diff in calendar months) === 1 if last calendar month is not full
// If so, result must be decreased by 1 in absolute value
var isLastMonthNotFull = compareAsc(dateLeft, dateRight) === -sign; // Check for cases of one full calendar month
if (isLastDayOfMonth(toDate(dirtyDateLeft)) && difference === 1 && compareAsc(dirtyDateLeft, dateRight) === 1) {
isLastMonthNotFull = false;
}
result = sign * (difference - Number(isLastMonthNotFull));
} // Prevent negative zero
return result === 0 ? 0 : result;
}
/**
* @name differenceInQuarters
* @category Quarter Helpers
* @summary Get the number of full quarters between the given dates.
*
* @description
* Get the number of full quarters between the given dates.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of full quarters
* @throws {TypeError} 2 arguments required
*
* @example
* // How many full quarters are between 31 December 2013 and 2 July 2014?
* var result = differenceInQuarters(new Date(2014, 6, 2), new Date(2013, 11, 31))
* //=> 2
*/
function differenceInQuarters(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var diff = differenceInMonths(dirtyDateLeft, dirtyDateRight) / 3;
return diff > 0 ? Math.floor(diff) : Math.ceil(diff);
}
/**
* Google Chrome as of 67.0.3396.87 introduced timezones with offset that includes seconds.
* They usually appear for dates that denote time before the timezones were introduced
* (e.g. for 'Europe/Prague' timezone the offset is GMT+00:57:44 before 1 October 1891
* and GMT+01:00:00 after that date)
*
* Date#getTimezoneOffset returns the offset in minutes and would return 57 for the example above,
* which would lead to incorrect calculations.
*
* This function returns the timezone offset in milliseconds that takes seconds in account.
*/
function getTimezoneOffsetInMilliseconds(date) {
var utcDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()));
utcDate.setUTCFullYear(date.getFullYear());
return date.getTime() - utcDate.getTime();
}
/**
* @name startOfDay
* @category Day Helpers
* @summary Return the start of a day for the given date.
*
* @description
* Return the start of a day for the given date.
* The result will be in the local timezone.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the original date
* @returns {Date} the start of a day
* @throws {TypeError} 1 argument required
*
* @example
* // The start of a day for 2 September 2014 11:55:00:
* const result = startOfDay(new Date(2014, 8, 2, 11, 55, 0))
* //=> Tue Sep 02 2014 00:00:00
*/
function startOfDay(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
date.setHours(0, 0, 0, 0);
return date;
}
var MILLISECONDS_IN_DAY$1 = 86400000;
/**
* @name differenceInCalendarDays
* @category Day Helpers
* @summary Get the number of calendar days between the given dates.
*
* @description
* Get the number of calendar days between the given dates. This means that the times are removed
* from the dates and then the difference in days is calculated.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of calendar days
* @throws {TypeError} 2 arguments required
*
* @example
* // How many calendar days are between
* // 2 July 2011 23:00:00 and 2 July 2012 00:00:00?
* const result = differenceInCalendarDays(
* new Date(2012, 6, 2, 0, 0),
* new Date(2011, 6, 2, 23, 0)
* )
* //=> 366
* // How many calendar days are between
* // 2 July 2011 23:59:00 and 3 July 2011 00:01:00?
* const result = differenceInCalendarDays(
* new Date(2011, 6, 3, 0, 1),
* new Date(2011, 6, 2, 23, 59)
* )
* //=> 1
*/
function differenceInCalendarDays(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var startOfDayLeft = startOfDay(dirtyDateLeft);
var startOfDayRight = startOfDay(dirtyDateRight);
var timestampLeft = startOfDayLeft.getTime() - getTimezoneOffsetInMilliseconds(startOfDayLeft);
var timestampRight = startOfDayRight.getTime() - getTimezoneOffsetInMilliseconds(startOfDayRight); // Round the number of days to the nearest integer
// because the number of milliseconds in a day is not constant
// (e.g. it's different in the day of the daylight saving time clock shift)
return Math.round((timestampLeft - timestampRight) / MILLISECONDS_IN_DAY$1);
}
// for accurate equality comparisons of UTC timestamps that end up
// having the same representation in local time, e.g. one hour before
// DST ends vs. the instant that DST ends.
function compareLocalAsc(dateLeft, dateRight) {
var diff = dateLeft.getFullYear() - dateRight.getFullYear() || dateLeft.getMonth() - dateRight.getMonth() || dateLeft.getDate() - dateRight.getDate() || dateLeft.getHours() - dateRight.getHours() || dateLeft.getMinutes() - dateRight.getMinutes() || dateLeft.getSeconds() - dateRight.getSeconds() || dateLeft.getMilliseconds() - dateRight.getMilliseconds();
if (diff < 0) {
return -1;
} else if (diff > 0) {
return 1; // Return 0 if diff is 0; return NaN if diff is NaN
} else {
return diff;
}
}
/**
* @name differenceInDays
* @category Day Helpers
* @summary Get the number of full days between the given dates.
*
* @description
* Get the number of full day periods between two dates. Fractional days are
* truncated towards zero.
*
* One "full day" is the distance between a local time in one day to the same
* local time on the next or previous day. A full day can sometimes be less than
* or more than 24 hours if a daylight savings change happens between two dates.
*
* To ignore DST and only measure exact 24-hour periods, use this instead:
* `Math.floor(differenceInHours(dateLeft, dateRight)/24)|0`.
*
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of full days according to the local timezone
* @throws {TypeError} 2 arguments required
*
* @example
* // How many full days are between
* // 2 July 2011 23:00:00 and 2 July 2012 00:00:00?
* const result = differenceInDays(
* new Date(2012, 6, 2, 0, 0),
* new Date(2011, 6, 2, 23, 0)
* )
* //=> 365
* // How many full days are between
* // 2 July 2011 23:59:00 and 3 July 2011 00:01:00?
* const result = differenceInDays(
* new Date(2011, 6, 3, 0, 1),
* new Date(2011, 6, 2, 23, 59)
* )
* //=> 0
* // How many full days are between
* // 1 March 2020 0:00 and 1 June 2020 0:00 ?
* // Note: because local time is used, the
* // result will always be 92 days, even in
* // time zones where DST starts and the
* // period has only 92*24-1 hours.
* const result = differenceInDays(
* new Date(2020, 5, 1),
* new Date(2020, 2, 1)
* )
//=> 92
*/
function differenceInDays(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeft = toDate(dirtyDateLeft);
var dateRight = toDate(dirtyDateRight);
var sign = compareLocalAsc(dateLeft, dateRight);
var difference = Math.abs(differenceInCalendarDays(dateLeft, dateRight));
dateLeft.setDate(dateLeft.getDate() - sign * difference); // Math.abs(diff in full days - diff in calendar days) === 1 if last calendar day is not full
// If so, result must be decreased by 1 in absolute value
var isLastDayNotFull = Number(compareLocalAsc(dateLeft, dateRight) === -sign);
var result = sign * (difference - isLastDayNotFull); // Prevent negative zero
return result === 0 ? 0 : result;
}
/**
* @name differenceInWeeks
* @category Week Helpers
* @summary Get the number of full weeks between the given dates.
*
* @description
* Get the number of full weeks between two dates. Fractional weeks are
* truncated towards zero.
*
* One "full week" is the distance between a local time in one day to the same
* local time 7 days earlier or later. A full week can sometimes be less than
* or more than 7*24 hours if a daylight savings change happens between two dates.
*
* To ignore DST and only measure exact 7*24-hour periods, use this instead:
* `Math.floor(differenceInHours(dateLeft, dateRight)/(7*24))|0`.
*
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of full weeks
* @throws {TypeError} 2 arguments required
*
* @example
* // How many full weeks are between 5 July 2014 and 20 July 2014?
* const result = differenceInWeeks(new Date(2014, 6, 20), new Date(2014, 6, 5))
* //=> 2
*
* // How many full weeks are between
* // 1 March 2020 0:00 and 6 June 2020 0:00 ?
* // Note: because local time is used, the
* // result will always be 8 weeks (54 days),
* // even if DST starts and the period has
* // only 54*24-1 hours.
* const result = differenceInWeeks(
* new Date(2020, 5, 1),
* new Date(2020, 2, 6)
* )
* //=> 8
*/
function differenceInWeeks(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var diff = differenceInDays(dirtyDateLeft, dirtyDateRight) / 7;
return diff > 0 ? Math.floor(diff) : Math.ceil(diff);
}
/**
* @name differenceInMilliseconds
* @category Millisecond Helpers
* @summary Get the number of milliseconds between the given dates.
*
* @description
* Get the number of milliseconds between the given dates.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of milliseconds
* @throws {TypeError} 2 arguments required
*
* @example
* // How many milliseconds are between
* // 2 July 2014 12:30:20.600 and 2 July 2014 12:30:21.700?
* const result = differenceInMilliseconds(
* new Date(2014, 6, 2, 12, 30, 21, 700),
* new Date(2014, 6, 2, 12, 30, 20, 600)
* )
* //=> 1100
*/
function differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeft = toDate(dirtyDateLeft);
var dateRight = toDate(dirtyDateRight);
return dateLeft.getTime() - dateRight.getTime();
}
var MILLISECONDS_IN_HOUR$2 = 3600000;
/**
* @name differenceInHours
* @category Hour Helpers
* @summary Get the number of hours between the given dates.
*
* @description
* Get the number of hours between the given dates.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of hours
* @throws {TypeError} 2 arguments required
*
* @example
* // How many hours are between 2 July 2014 06:50:00 and 2 July 2014 19:00:00?
* var result = differenceInHours(
* new Date(2014, 6, 2, 19, 0),
* new Date(2014, 6, 2, 6, 50)
* )
* //=> 12
*/
function differenceInHours(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var diff = differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) / MILLISECONDS_IN_HOUR$2;
return diff > 0 ? Math.floor(diff) : Math.ceil(diff);
}
var MILLISECONDS_IN_MINUTE$2 = 60000;
/**
* @name differenceInMinutes
* @category Minute Helpers
* @summary Get the number of minutes between the given dates.
*
* @description
* Get the signed number of full (rounded towards 0) minutes between the given dates.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of minutes
* @throws {TypeError} 2 arguments required
*
* @example
* // How many minutes are between 2 July 2014 12:07:59 and 2 July 2014 12:20:00?
* var result = differenceInMinutes(
* new Date(2014, 6, 2, 12, 20, 0),
* new Date(2014, 6, 2, 12, 7, 59)
* )
* //=> 12
*
* @example
* // How many minutes are from 10:01:59 to 10:00:00
* var result = differenceInMinutes(
* new Date(2000, 0, 1, 10, 0, 0),
* new Date(2000, 0, 1, 10, 1, 59)
* )
* //=> -1
*/
function differenceInMinutes(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var diff = differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) / MILLISECONDS_IN_MINUTE$2;
return diff > 0 ? Math.floor(diff) : Math.ceil(diff);
}
/**
* @name differenceInSeconds
* @category Second Helpers
* @summary Get the number of seconds between the given dates.
*
* @description
* Get the number of seconds between the given dates.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of seconds
* @throws {TypeError} 2 arguments required
*
* @example
* // How many seconds are between
* // 2 July 2014 12:30:07.999 and 2 July 2014 12:30:20.000?
* const result = differenceInSeconds(
* new Date(2014, 6, 2, 12, 30, 20, 0),
* new Date(2014, 6, 2, 12, 30, 7, 999)
* )
* //=> 12
*/
function differenceInSeconds(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var diff = differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) / 1000;
return diff > 0 ? Math.floor(diff) : Math.ceil(diff);
}
/**
* @name eachDayOfInterval
* @category Interval Helpers
* @summary Return the array of dates within the specified time interval.
*
* @description
* Return the array of dates within the specified time interval.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* - The function was renamed from `eachDay` to `eachDayOfInterval`.
* This change was made to mirror the use of the word "interval" in standard ISO 8601:2004 terminology:
*
* ```
* 2.1.3
* time interval
* part of the time axis limited by two instants
* ```
*
* Also, this function now accepts an object with `start` and `end` properties
* instead of two arguments as an interval.
* This function now throws `RangeError` if the start of the interval is after its end
* or if any date in the interval is `Invalid Date`.
*
* ```javascript
* // Before v2.0.0
*
* eachDay(new Date(2014, 0, 10), new Date(2014, 0, 20))
*
* // v2.0.0 onward
*
* eachDayOfInterval(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) }
* )
* ```
*
* @param {Interval} interval - the interval. See [Interval]{@link https://date-fns.org/docs/Interval}
* @param {Object} [options] - an object with options.
* @param {Number} [options.step=1] - the step to increment by. The value should be more than 1.
* @returns {Date[]} the array with starts of days from the day of the interval start to the day of the interval end
* @throws {TypeError} 1 argument required
* @throws {RangeError} `options.step` must be a number greater than 1
* @throws {RangeError} The start of an interval cannot be after its end
* @throws {RangeError} Date in interval cannot be `Invalid Date`
*
* @example
* // Each day between 6 October 2014 and 10 October 2014:
* const result = eachDayOfInterval({
* start: new Date(2014, 9, 6),
* end: new Date(2014, 9, 10)
* })
* //=> [
* // Mon Oct 06 2014 00:00:00,
* // Tue Oct 07 2014 00:00:00,
* // Wed Oct 08 2014 00:00:00,
* // Thu Oct 09 2014 00:00:00,
* // Fri Oct 10 2014 00:00:00
* // ]
*/
function eachDayOfInterval(dirtyInterval, options) {
requiredArgs(1, arguments);
var interval = dirtyInterval || {};
var startDate = toDate(interval.start);
var endDate = toDate(interval.end);
var endTime = endDate.getTime(); // Throw an exception if start date is after end date or if any date is `Invalid Date`
if (!(startDate.getTime() <= endTime)) {
throw new RangeError('Invalid interval');
}
var dates = [];
var currentDate = startDate;
currentDate.setHours(0, 0, 0, 0);
var step = options && 'step' in options ? Number(options.step) : 1;
if (step < 1 || isNaN(step)) throw new RangeError('`options.step` must be a number greater than 1');
while (currentDate.getTime() <= endTime) {
dates.push(toDate(currentDate));
currentDate.setDate(currentDate.getDate() + step);
currentDate.setHours(0, 0, 0, 0);
}
return dates;
}
/**
* @name endOfWeek
* @category Week Helpers
* @summary Return the end of a week for the given date.
*
* @description
* Return the end of a week for the given date.
* The result will be in the local timezone.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the original date
* @param {Object} [options] - an object with options.
* @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
* @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
* @returns {Date} the end of a week
* @throws {TypeError} 1 argument required
* @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
*
* @example
* // The end of a week for 2 September 2014 11:55:00:
* const result = endOfWeek(new Date(2014, 8, 2, 11, 55, 0))
* //=> Sat Sep 06 2014 23:59:59.999
*
* @example
* // If the week starts on Monday, the end of the week for 2 September 2014 11:55:00:
* const result = endOfWeek(new Date(2014, 8, 2, 11, 55, 0), { weekStartsOn: 1 })
* //=> Sun Sep 07 2014 23:59:59.999
*/
function endOfWeek(dirtyDate, dirtyOptions) {
requiredArgs(1, arguments);
var options = dirtyOptions || {};
var locale = options.locale;
var localeWeekStartsOn = locale && locale.options && locale.options.weekStartsOn;
var defaultWeekStartsOn = localeWeekStartsOn == null ? 0 : toInteger(localeWeekStartsOn);
var weekStartsOn = options.weekStartsOn == null ? defaultWeekStartsOn : toInteger(options.weekStartsOn); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');
}
var date = toDate(dirtyDate);
var day = date.getDay();
var diff = (day < weekStartsOn ? -7 : 0) + 6 - (day - weekStartsOn);
date.setDate(date.getDate() + diff);
date.setHours(23, 59, 59, 999);
return date;
}
/**
* @name endOfYear
* @category Year Helpers
* @summary Return the end of a year for the given date.
*
* @description
* Return the end of a year for the given date.
* The result will be in the local timezone.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the original date
* @returns {Date} the end of a year
* @throws {TypeError} 1 argument required
*
* @example
* // The end of a year for 2 September 2014 11:55:00:
* var result = endOfYear(new Date(2014, 8, 2, 11, 55, 00))
* //=> Wed Dec 31 2014 23:59:59.999
*/
function endOfYear(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var year = date.getFullYear();
date.setFullYear(year + 1, 0, 0);
date.setHours(23, 59, 59, 999);
return date;
}
/**
* @name isValid
* @category Common Helpers
* @summary Is the given date valid?
*
* @description
* Returns false if argument is Invalid Date and true otherwise.
* Argument is converted to Date using `toDate`. See [toDate]{@link https://date-fns.org/docs/toDate}
* Invalid Date is a Date, whose time value is NaN.
*
* Time value of Date: http://es5.github.io/#x15.9.1.1
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* - Now `isValid` doesn't throw an exception
* if the first argument is not an instance of Date.
* Instead, argument is converted beforehand using `toDate`.
*
* Examples:
*
* | `isValid` argument | Before v2.0.0 | v2.0.0 onward |
* |---------------------------|---------------|---------------|
* | `new Date()` | `true` | `true` |
* | `new Date('2016-01-01')` | `true` | `true` |
* | `new Date('')` | `false` | `false` |
* | `new Date(1488370835081)` | `true` | `true` |
* | `new Date(NaN)` | `false` | `false` |
* | `'2016-01-01'` | `TypeError` | `false` |
* | `''` | `TypeError` | `false` |
* | `1488370835081` | `TypeError` | `true` |
* | `NaN` | `TypeError` | `false` |
*
* We introduce this change to make *date-fns* consistent with ECMAScript behavior
* that try to coerce arguments to the expected type
* (which is also the case with other *date-fns* functions).
*
* @param {*} date - the date to check
* @returns {Boolean} the date is valid
* @throws {TypeError} 1 argument required
*
* @example
* // For the valid date:
* var result = isValid(new Date(2014, 1, 31))
* //=> true
*
* @example
* // For the value, convertable into a date:
* var result = isValid(1393804800000)
* //=> true
*
* @example
* // For the invalid date:
* var result = isValid(new Date(''))
* //=> false
*/
function isValid(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
return !isNaN(date);
}
var formatDistanceLocale = {
lessThanXSeconds: {
one: 'less than a second',
other: 'less than {{count}} seconds'
},
xSeconds: {
one: '1 second',
other: '{{count}} seconds'
},
halfAMinute: 'half a minute',
lessThanXMinutes: {
one: 'less than a minute',
other: 'less than {{count}} minutes'
},
xMinutes: {
one: '1 minute',
other: '{{count}} minutes'
},
aboutXHours: {
one: 'about 1 hour',
other: 'about {{count}} hours'
},
xHours: {
one: '1 hour',
other: '{{count}} hours'
},
xDays: {
one: '1 day',
other: '{{count}} days'
},
aboutXWeeks: {
one: 'about 1 week',
other: 'about {{count}} weeks'
},
xWeeks: {
one: '1 week',
other: '{{count}} weeks'
},
aboutXMonths: {
one: 'about 1 month',
other: 'about {{count}} months'
},
xMonths: {
one: '1 month',
other: '{{count}} months'
},
aboutXYears: {
one: 'about 1 year',
other: 'about {{count}} years'
},
xYears: {
one: '1 year',
other: '{{count}} years'
},
overXYears: {
one: 'over 1 year',
other: 'over {{count}} years'
},
almostXYears: {
one: 'almost 1 year',
other: 'almost {{count}} years'
}
};
function formatDistance(token, count, options) {
options = options || {};
var result;
if (typeof formatDistanceLocale[token] === 'string') {
result = formatDistanceLocale[token];
} else if (count === 1) {
result = formatDistanceLocale[token].one;
} else {
result = formatDistanceLocale[token].other.replace('{{count}}', count);
}
if (options.addSuffix) {
if (options.comparison > 0) {
return 'in ' + result;
} else {
return result + ' ago';
}
}
return result;
}
function buildFormatLongFn(args) {
return function () {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
// TODO: Remove String()
var width = options.width ? String(options.width) : args.defaultWidth;
var format = args.formats[width] || args.formats[args.defaultWidth];
return format;
};
}
var dateFormats = {
full: 'EEEE, MMMM do, y',
long: 'MMMM do, y',
medium: 'MMM d, y',
short: 'MM/dd/yyyy'
};
var timeFormats = {
full: 'h:mm:ss a zzzz',
long: 'h:mm:ss a z',
medium: 'h:mm:ss a',
short: 'h:mm a'
};
var dateTimeFormats = {
full: "{{date}} 'at' {{time}}",
long: "{{date}} 'at' {{time}}",
medium: '{{date}}, {{time}}',
short: '{{date}}, {{time}}'
};
var formatLong = {
date: buildFormatLongFn({
formats: dateFormats,
defaultWidth: 'full'
}),
time: buildFormatLongFn({
formats: timeFormats,
defaultWidth: 'full'
}),
dateTime: buildFormatLongFn({
formats: dateTimeFormats,
defaultWidth: 'full'
})
};
var formatLong$1 = formatLong;
var formatRelativeLocale = {
lastWeek: "'last' eeee 'at' p",
yesterday: "'yesterday at' p",
today: "'today at' p",
tomorrow: "'tomorrow at' p",
nextWeek: "eeee 'at' p",
other: 'P'
};
function formatRelative(token, _date, _baseDate, _options) {
return formatRelativeLocale[token];
}
function buildLocalizeFn(args) {
return function (dirtyIndex, dirtyOptions) {
var options = dirtyOptions || {};
var context = options.context ? String(options.context) : 'standalone';
var valuesArray;
if (context === 'formatting' && args.formattingValues) {
var defaultWidth = args.defaultFormattingWidth || args.defaultWidth;
var width = options.width ? String(options.width) : defaultWidth;
valuesArray = args.formattingValues[width] || args.formattingValues[defaultWidth];
} else {
var _defaultWidth = args.defaultWidth;
var _width = options.width ? String(options.width) : args.defaultWidth;
valuesArray = args.values[_width] || args.values[_defaultWidth];
}
var index = args.argumentCallback ? args.argumentCallback(dirtyIndex) : dirtyIndex; // @ts-ignore: For some reason TypeScript just don't want to match it, no matter how hard we try. I challange you to try to remove it!
return valuesArray[index];
};
}
var eraValues = {
narrow: ['B', 'A'],
abbreviated: ['BC', 'AD'],
wide: ['Before Christ', 'Anno Domini']
};
var quarterValues = {
narrow: ['1', '2', '3', '4'],
abbreviated: ['Q1', 'Q2', 'Q3', 'Q4'],
wide: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter']
}; // Note: in English, the names of days of the week and months are capitalized.
// If you are making a new locale based on this one, check if the same is true for the language you're working on.
// Generally, formatted dates should look like they are in the middle of a sentence,
// e.g. in Spanish language the weekdays and months should be in the lowercase.
var monthValues = {
narrow: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
abbreviated: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
wide: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
};
var dayValues = {
narrow: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
short: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
abbreviated: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
wide: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
};
var dayPeriodValues = {
narrow: {
am: 'a',
pm: 'p',
midnight: 'mi',
noon: 'n',
morning: 'morning',
afternoon: 'afternoon',
evening: 'evening',
night: 'night'
},
abbreviated: {
am: 'AM',
pm: 'PM',
midnight: 'midnight',
noon: 'noon',
morning: 'morning',
afternoon: 'afternoon',
evening: 'evening',
night: 'night'
},
wide: {
am: 'a.m.',
pm: 'p.m.',
midnight: 'midnight',
noon: 'noon',
morning: 'morning',
afternoon: 'afternoon',
evening: 'evening',
night: 'night'
}
};
var formattingDayPeriodValues = {
narrow: {
am: 'a',
pm: 'p',
midnight: 'mi',
noon: 'n',
morning: 'in the morning',
afternoon: 'in the afternoon',
evening: 'in the evening',
night: 'at night'
},
abbreviated: {
am: 'AM',
pm: 'PM',
midnight: 'midnight',
noon: 'noon',
morning: 'in the morning',
afternoon: 'in the afternoon',
evening: 'in the evening',
night: 'at night'
},
wide: {
am: 'a.m.',
pm: 'p.m.',
midnight: 'midnight',
noon: 'noon',
morning: 'in the morning',
afternoon: 'in the afternoon',
evening: 'in the evening',
night: 'at night'
}
};
function ordinalNumber(dirtyNumber, _dirtyOptions) {
var number = Number(dirtyNumber); // If ordinal numbers depend on context, for example,
// if they are different for different grammatical genders,
// use `options.unit`:
//
// var options = dirtyOptions || {}
// var unit = String(options.unit)
//
// where `unit` can be 'year', 'quarter', 'month', 'week', 'date', 'dayOfYear',
// 'day', 'hour', 'minute', 'second'
var rem100 = number % 100;
if (rem100 > 20 || rem100 < 10) {
switch (rem100 % 10) {
case 1:
return number + 'st';
case 2:
return number + 'nd';
case 3:
return number + 'rd';
}
}
return number + 'th';
}
var localize = {
ordinalNumber: ordinalNumber,
era: buildLocalizeFn({
values: eraValues,
defaultWidth: 'wide'
}),
quarter: buildLocalizeFn({
values: quarterValues,
defaultWidth: 'wide',
argumentCallback: function (quarter) {
return Number(quarter) - 1;
}
}),
month: buildLocalizeFn({
values: monthValues,
defaultWidth: 'wide'
}),
day: buildLocalizeFn({
values: dayValues,
defaultWidth: 'wide'
}),
dayPeriod: buildLocalizeFn({
values: dayPeriodValues,
defaultWidth: 'wide',
formattingValues: formattingDayPeriodValues,
defaultFormattingWidth: 'wide'
})
};
var localize$1 = localize;
function buildMatchPatternFn(args) {
return function (string) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var matchResult = string.match(args.matchPattern);
if (!matchResult) return null;
var matchedString = matchResult[0];
var parseResult = string.match(args.parsePattern);
if (!parseResult) return null;
var value = args.valueCallback ? args.valueCallback(parseResult[0]) : parseResult[0];
value = options.valueCallback ? options.valueCallback(value) : value;
var rest = string.slice(matchedString.length);
return {
value: value,
rest: rest
};
};
}
function buildMatchFn(args) {
return function (string) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var width = options.width;
var matchPattern = width && args.matchPatterns[width] || args.matchPatterns[args.defaultMatchWidth];
var matchResult = string.match(matchPattern);
if (!matchResult) {
return null;
}
var matchedString = matchResult[0];
var parsePatterns = width && args.parsePatterns[width] || args.parsePatterns[args.defaultParseWidth];
var key = Array.isArray(parsePatterns) ? findIndex(parsePatterns, function (pattern) {
return pattern.test(matchedString);
}) : findKey(parsePatterns, function (pattern) {
return pattern.test(matchedString);
});
var value;
value = args.valueCallback ? args.valueCallback(key) : key;
value = options.valueCallback ? options.valueCallback(value) : value;
var rest = string.slice(matchedString.length);
return {
value: value,
rest: rest
};
};
}
function findKey(object, predicate) {
for (var key in object) {
if (object.hasOwnProperty(key) && predicate(object[key])) {
return key;
}
}
return undefined;
}
function findIndex(array, predicate) {
for (var key = 0; key < array.length; key++) {
if (predicate(array[key])) {
return key;
}
}
return undefined;
}
var matchOrdinalNumberPattern = /^(\d+)(th|st|nd|rd)?/i;
var parseOrdinalNumberPattern = /\d+/i;
var matchEraPatterns = {
narrow: /^(b|a)/i,
abbreviated: /^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,
wide: /^(before christ|before common era|anno domini|common era)/i
};
var parseEraPatterns = {
any: [/^b/i, /^(a|c)/i]
};
var matchQuarterPatterns = {
narrow: /^[1234]/i,
abbreviated: /^q[1234]/i,
wide: /^[1234](th|st|nd|rd)? quarter/i
};
var parseQuarterPatterns = {
any: [/1/i, /2/i, /3/i, /4/i]
};
var matchMonthPatterns = {
narrow: /^[jfmasond]/i,
abbreviated: /^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,
wide: /^(january|february|march|april|may|june|july|august|september|october|november|december)/i
};
var parseMonthPatterns = {
narrow: [/^j/i, /^f/i, /^m/i, /^a/i, /^m/i, /^j/i, /^j/i, /^a/i, /^s/i, /^o/i, /^n/i, /^d/i],
any: [/^ja/i, /^f/i, /^mar/i, /^ap/i, /^may/i, /^jun/i, /^jul/i, /^au/i, /^s/i, /^o/i, /^n/i, /^d/i]
};
var matchDayPatterns = {
narrow: /^[smtwf]/i,
short: /^(su|mo|tu|we|th|fr|sa)/i,
abbreviated: /^(sun|mon|tue|wed|thu|fri|sat)/i,
wide: /^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i
};
var parseDayPatterns = {
narrow: [/^s/i, /^m/i, /^t/i, /^w/i, /^t/i, /^f/i, /^s/i],
any: [/^su/i, /^m/i, /^tu/i, /^w/i, /^th/i, /^f/i, /^sa/i]
};
var matchDayPeriodPatterns = {
narrow: /^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,
any: /^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i
};
var parseDayPeriodPatterns = {
any: {
am: /^a/i,
pm: /^p/i,
midnight: /^mi/i,
noon: /^no/i,
morning: /morning/i,
afternoon: /afternoon/i,
evening: /evening/i,
night: /night/i
}
};
var match = {
ordinalNumber: buildMatchPatternFn({
matchPattern: matchOrdinalNumberPattern,
parsePattern: parseOrdinalNumberPattern,
valueCallback: function (value) {
return parseInt(value, 10);
}
}),
era: buildMatchFn({
matchPatterns: matchEraPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseEraPatterns,
defaultParseWidth: 'any'
}),
quarter: buildMatchFn({
matchPatterns: matchQuarterPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseQuarterPatterns,
defaultParseWidth: 'any',
valueCallback: function (index) {
return index + 1;
}
}),
month: buildMatchFn({
matchPatterns: matchMonthPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseMonthPatterns,
defaultParseWidth: 'any'
}),
day: buildMatchFn({
matchPatterns: matchDayPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseDayPatterns,
defaultParseWidth: 'any'
}),
dayPeriod: buildMatchFn({
matchPatterns: matchDayPeriodPatterns,
defaultMatchWidth: 'any',
parsePatterns: parseDayPeriodPatterns,
defaultParseWidth: 'any'
})
};
var match$1 = match;
/**
* @type {Locale}
* @category Locales
* @summary English locale (United States).
* @language English
* @iso-639-2 eng
* @author Sasha Koss [@kossnocorp]{@link https://github.com/kossnocorp}
* @author Lesha Koss [@leshakoss]{@link https://github.com/leshakoss}
*/
var locale = {
code: 'en-US',
formatDistance: formatDistance,
formatLong: formatLong$1,
formatRelative: formatRelative,
localize: localize$1,
match: match$1,
options: {
weekStartsOn: 0
/* Sunday */
,
firstWeekContainsDate: 1
}
};
var enUS = locale;
/**
* @name subMilliseconds
* @category Millisecond Helpers
* @summary Subtract the specified number of milliseconds from the given date.
*
* @description
* Subtract the specified number of milliseconds from the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} amount - the amount of milliseconds to be subtracted. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
* @returns {Date} the new date with the milliseconds subtracted
* @throws {TypeError} 2 arguments required
*
* @example
* // Subtract 750 milliseconds from 10 July 2014 12:45:30.000:
* const result = subMilliseconds(new Date(2014, 6, 10, 12, 45, 30, 0), 750)
* //=> Thu Jul 10 2014 12:45:29.250
*/
function subMilliseconds(dirtyDate, dirtyAmount) {
requiredArgs(2, arguments);
var amount = toInteger(dirtyAmount);
return addMilliseconds(dirtyDate, -amount);
}
function addLeadingZeros(number, targetLength) {
var sign = number < 0 ? '-' : '';
var output = Math.abs(number).toString();
while (output.length < targetLength) {
output = '0' + output;
}
return sign + output;
}
/*
* | | Unit | | Unit |
* |-----|--------------------------------|-----|--------------------------------|
* | a | AM, PM | A* | |
* | d | Day of month | D | |
* | h | Hour [1-12] | H | Hour [0-23] |
* | m | Minute | M | Month |
* | s | Second | S | Fraction of second |
* | y | Year (abs) | Y | |
*
* Letters marked by * are not implemented but reserved by Unicode standard.
*/
var formatters$2 = {
// Year
y: function (date, token) {
// From http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_tokens
// | Year | y | yy | yyy | yyyy | yyyyy |
// |----------|-------|----|-------|-------|-------|
// | AD 1 | 1 | 01 | 001 | 0001 | 00001 |
// | AD 12 | 12 | 12 | 012 | 0012 | 00012 |
// | AD 123 | 123 | 23 | 123 | 0123 | 00123 |
// | AD 1234 | 1234 | 34 | 1234 | 1234 | 01234 |
// | AD 12345 | 12345 | 45 | 12345 | 12345 | 12345 |
var signedYear = date.getUTCFullYear(); // Returns 1 for 1 BC (which is year 0 in JavaScript)
var year = signedYear > 0 ? signedYear : 1 - signedYear;
return addLeadingZeros(token === 'yy' ? year % 100 : year, token.length);
},
// Month
M: function (date, token) {
var month = date.getUTCMonth();
return token === 'M' ? String(month + 1) : addLeadingZeros(month + 1, 2);
},
// Day of the month
d: function (date, token) {
return addLeadingZeros(date.getUTCDate(), token.length);
},
// AM or PM
a: function (date, token) {
var dayPeriodEnumValue = date.getUTCHours() / 12 >= 1 ? 'pm' : 'am';
switch (token) {
case 'a':
case 'aa':
return dayPeriodEnumValue.toUpperCase();
case 'aaa':
return dayPeriodEnumValue;
case 'aaaaa':
return dayPeriodEnumValue[0];
case 'aaaa':
default:
return dayPeriodEnumValue === 'am' ? 'a.m.' : 'p.m.';
}
},
// Hour [1-12]
h: function (date, token) {
return addLeadingZeros(date.getUTCHours() % 12 || 12, token.length);
},
// Hour [0-23]
H: function (date, token) {
return addLeadingZeros(date.getUTCHours(), token.length);
},
// Minute
m: function (date, token) {
return addLeadingZeros(date.getUTCMinutes(), token.length);
},
// Second
s: function (date, token) {
return addLeadingZeros(date.getUTCSeconds(), token.length);
},
// Fraction of second
S: function (date, token) {
var numberOfDigits = token.length;
var milliseconds = date.getUTCMilliseconds();
var fractionalSeconds = Math.floor(milliseconds * Math.pow(10, numberOfDigits - 3));
return addLeadingZeros(fractionalSeconds, token.length);
}
};
var lightFormatters = formatters$2;
var MILLISECONDS_IN_DAY = 86400000; // This function will be a part of public API when UTC function will be implemented.
// See issue: https://github.com/date-fns/date-fns/issues/376
function getUTCDayOfYear(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var timestamp = date.getTime();
date.setUTCMonth(0, 1);
date.setUTCHours(0, 0, 0, 0);
var startOfYearTimestamp = date.getTime();
var difference = timestamp - startOfYearTimestamp;
return Math.floor(difference / MILLISECONDS_IN_DAY) + 1;
}
// See issue: https://github.com/date-fns/date-fns/issues/376
function startOfUTCISOWeek(dirtyDate) {
requiredArgs(1, arguments);
var weekStartsOn = 1;
var date = toDate(dirtyDate);
var day = date.getUTCDay();
var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;
date.setUTCDate(date.getUTCDate() - diff);
date.setUTCHours(0, 0, 0, 0);
return date;
}
// See issue: https://github.com/date-fns/date-fns/issues/376
function getUTCISOWeekYear(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var year = date.getUTCFullYear();
var fourthOfJanuaryOfNextYear = new Date(0);
fourthOfJanuaryOfNextYear.setUTCFullYear(year + 1, 0, 4);
fourthOfJanuaryOfNextYear.setUTCHours(0, 0, 0, 0);
var startOfNextYear = startOfUTCISOWeek(fourthOfJanuaryOfNextYear);
var fourthOfJanuaryOfThisYear = new Date(0);
fourthOfJanuaryOfThisYear.setUTCFullYear(year, 0, 4);
fourthOfJanuaryOfThisYear.setUTCHours(0, 0, 0, 0);
var startOfThisYear = startOfUTCISOWeek(fourthOfJanuaryOfThisYear);
if (date.getTime() >= startOfNextYear.getTime()) {
return year + 1;
} else if (date.getTime() >= startOfThisYear.getTime()) {
return year;
} else {
return year - 1;
}
}
// See issue: https://github.com/date-fns/date-fns/issues/376
function startOfUTCISOWeekYear(dirtyDate) {
requiredArgs(1, arguments);
var year = getUTCISOWeekYear(dirtyDate);
var fourthOfJanuary = new Date(0);
fourthOfJanuary.setUTCFullYear(year, 0, 4);
fourthOfJanuary.setUTCHours(0, 0, 0, 0);
var date = startOfUTCISOWeek(fourthOfJanuary);
return date;
}
var MILLISECONDS_IN_WEEK$2 = 604800000; // This function will be a part of public API when UTC function will be implemented.
// See issue: https://github.com/date-fns/date-fns/issues/376
function getUTCISOWeek(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var diff = startOfUTCISOWeek(date).getTime() - startOfUTCISOWeekYear(date).getTime(); // Round the number of days to the nearest integer
// because the number of milliseconds in a week is not constant
// (e.g. it's different in the week of the daylight saving time clock shift)
return Math.round(diff / MILLISECONDS_IN_WEEK$2) + 1;
}
// See issue: https://github.com/date-fns/date-fns/issues/376
function startOfUTCWeek(dirtyDate, dirtyOptions) {
requiredArgs(1, arguments);
var options = dirtyOptions || {};
var locale = options.locale;
var localeWeekStartsOn = locale && locale.options && locale.options.weekStartsOn;
var defaultWeekStartsOn = localeWeekStartsOn == null ? 0 : toInteger(localeWeekStartsOn);
var weekStartsOn = options.weekStartsOn == null ? defaultWeekStartsOn : toInteger(options.weekStartsOn); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');
}
var date = toDate(dirtyDate);
var day = date.getUTCDay();
var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;
date.setUTCDate(date.getUTCDate() - diff);
date.setUTCHours(0, 0, 0, 0);
return date;
}
// See issue: https://github.com/date-fns/date-fns/issues/376
function getUTCWeekYear(dirtyDate, dirtyOptions) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate, dirtyOptions);
var year = date.getUTCFullYear();
var options = dirtyOptions || {};
var locale = options.locale;
var localeFirstWeekContainsDate = locale && locale.options && locale.options.firstWeekContainsDate;
var defaultFirstWeekContainsDate = localeFirstWeekContainsDate == null ? 1 : toInteger(localeFirstWeekContainsDate);
var firstWeekContainsDate = options.firstWeekContainsDate == null ? defaultFirstWeekContainsDate : toInteger(options.firstWeekContainsDate); // Test if weekStartsOn is between 1 and 7 _and_ is not NaN
if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {
throw new RangeError('firstWeekContainsDate must be between 1 and 7 inclusively');
}
var firstWeekOfNextYear = new Date(0);
firstWeekOfNextYear.setUTCFullYear(year + 1, 0, firstWeekContainsDate);
firstWeekOfNextYear.setUTCHours(0, 0, 0, 0);
var startOfNextYear = startOfUTCWeek(firstWeekOfNextYear, dirtyOptions);
var firstWeekOfThisYear = new Date(0);
firstWeekOfThisYear.setUTCFullYear(year, 0, firstWeekContainsDate);
firstWeekOfThisYear.setUTCHours(0, 0, 0, 0);
var startOfThisYear = startOfUTCWeek(firstWeekOfThisYear, dirtyOptions);
if (date.getTime() >= startOfNextYear.getTime()) {
return year + 1;
} else if (date.getTime() >= startOfThisYear.getTime()) {
return year;
} else {
return year - 1;
}
}
// See issue: https://github.com/date-fns/date-fns/issues/376
function startOfUTCWeekYear(dirtyDate, dirtyOptions) {
requiredArgs(1, arguments);
var options = dirtyOptions || {};
var locale = options.locale;
var localeFirstWeekContainsDate = locale && locale.options && locale.options.firstWeekContainsDate;
var defaultFirstWeekContainsDate = localeFirstWeekContainsDate == null ? 1 : toInteger(localeFirstWeekContainsDate);
var firstWeekContainsDate = options.firstWeekContainsDate == null ? defaultFirstWeekContainsDate : toInteger(options.firstWeekContainsDate);
var year = getUTCWeekYear(dirtyDate, dirtyOptions);
var firstWeek = new Date(0);
firstWeek.setUTCFullYear(year, 0, firstWeekContainsDate);
firstWeek.setUTCHours(0, 0, 0, 0);
var date = startOfUTCWeek(firstWeek, dirtyOptions);
return date;
}
var MILLISECONDS_IN_WEEK$1 = 604800000; // This function will be a part of public API when UTC function will be implemented.
// See issue: https://github.com/date-fns/date-fns/issues/376
function getUTCWeek(dirtyDate, options) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var diff = startOfUTCWeek(date, options).getTime() - startOfUTCWeekYear(date, options).getTime(); // Round the number of days to the nearest integer
// because the number of milliseconds in a week is not constant
// (e.g. it's different in the week of the daylight saving time clock shift)
return Math.round(diff / MILLISECONDS_IN_WEEK$1) + 1;
}
var dayPeriodEnum = {
am: 'am',
pm: 'pm',
midnight: 'midnight',
noon: 'noon',
morning: 'morning',
afternoon: 'afternoon',
evening: 'evening',
night: 'night'
};
/*
* | | Unit | | Unit |
* |-----|--------------------------------|-----|--------------------------------|
* | a | AM, PM | A* | Milliseconds in day |
* | b | AM, PM, noon, midnight | B | Flexible day period |
* | c | Stand-alone local day of week | C* | Localized hour w/ day period |
* | d | Day of month | D | Day of year |
* | e | Local day of week | E | Day of week |
* | f | | F* | Day of week in month |
* | g* | Modified Julian day | G | Era |
* | h | Hour [1-12] | H | Hour [0-23] |
* | i! | ISO day of week | I! | ISO week of year |
* | j* | Localized hour w/ day period | J* | Localized hour w/o day period |
* | k | Hour [1-24] | K | Hour [0-11] |
* | l* | (deprecated) | L | Stand-alone month |
* | m | Minute | M | Month |
* | n | | N | |
* | o! | Ordinal number modifier | O | Timezone (GMT) |
* | p! | Long localized time | P! | Long localized date |
* | q | Stand-alone quarter | Q | Quarter |
* | r* | Related Gregorian year | R! | ISO week-numbering year |
* | s | Second | S | Fraction of second |
* | t! | Seconds timestamp | T! | Milliseconds timestamp |
* | u | Extended year | U* | Cyclic year |
* | v* | Timezone (generic non-locat.) | V* | Timezone (location) |
* | w | Local week of year | W* | Week of month |
* | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |
* | y | Year (abs) | Y | Local week-numbering year |
* | z | Timezone (specific non-locat.) | Z* | Timezone (aliases) |
*
* Letters marked by * are not implemented but reserved by Unicode standard.
*
* Letters marked by ! are non-standard, but implemented by date-fns:
* - `o` modifies the previous token to turn it into an ordinal (see `format` docs)
* - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,
* i.e. 7 for Sunday, 1 for Monday, etc.
* - `I` is ISO week of year, as opposed to `w` which is local week of year.
* - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.
* `R` is supposed to be used in conjunction with `I` and `i`
* for universal ISO week-numbering date, whereas
* `Y` is supposed to be used in conjunction with `w` and `e`
* for week-numbering date specific to the locale.
* - `P` is long localized date format
* - `p` is long localized time format
*/
var formatters = {
// Era
G: function (date, token, localize) {
var era = date.getUTCFullYear() > 0 ? 1 : 0;
switch (token) {
// AD, BC
case 'G':
case 'GG':
case 'GGG':
return localize.era(era, {
width: 'abbreviated'
});
// A, B
case 'GGGGG':
return localize.era(era, {
width: 'narrow'
});
// Anno Domini, Before Christ
case 'GGGG':
default:
return localize.era(era, {
width: 'wide'
});
}
},
// Year
y: function (date, token, localize) {
// Ordinal number
if (token === 'yo') {
var signedYear = date.getUTCFullYear(); // Returns 1 for 1 BC (which is year 0 in JavaScript)
var year = signedYear > 0 ? signedYear : 1 - signedYear;
return localize.ordinalNumber(year, {
unit: 'year'
});
}
return lightFormatters.y(date, token);
},
// Local week-numbering year
Y: function (date, token, localize, options) {
var signedWeekYear = getUTCWeekYear(date, options); // Returns 1 for 1 BC (which is year 0 in JavaScript)
var weekYear = signedWeekYear > 0 ? signedWeekYear : 1 - signedWeekYear; // Two digit year
if (token === 'YY') {
var twoDigitYear = weekYear % 100;
return addLeadingZeros(twoDigitYear, 2);
} // Ordinal number
if (token === 'Yo') {
return localize.ordinalNumber(weekYear, {
unit: 'year'
});
} // Padding
return addLeadingZeros(weekYear, token.length);
},
// ISO week-numbering year
R: function (date, token) {
var isoWeekYear = getUTCISOWeekYear(date); // Padding
return addLeadingZeros(isoWeekYear, token.length);
},
// Extended year. This is a single number designating the year of this calendar system.
// The main difference between `y` and `u` localizers are B.C. years:
// | Year | `y` | `u` |
// |------|-----|-----|
// | AC 1 | 1 | 1 |
// | BC 1 | 1 | 0 |
// | BC 2 | 2 | -1 |
// Also `yy` always returns the last two digits of a year,
// while `uu` pads single digit years to 2 characters and returns other years unchanged.
u: function (date, token) {
var year = date.getUTCFullYear();
return addLeadingZeros(year, token.length);
},
// Quarter
Q: function (date, token, localize) {
var quarter = Math.ceil((date.getUTCMonth() + 1) / 3);
switch (token) {
// 1, 2, 3, 4
case 'Q':
return String(quarter);
// 01, 02, 03, 04
case 'QQ':
return addLeadingZeros(quarter, 2);
// 1st, 2nd, 3rd, 4th
case 'Qo':
return localize.ordinalNumber(quarter, {
unit: 'quarter'
});
// Q1, Q2, Q3, Q4
case 'QQQ':
return localize.quarter(quarter, {
width: 'abbreviated',
context: 'formatting'
});
// 1, 2, 3, 4 (narrow quarter; could be not numerical)
case 'QQQQQ':
return localize.quarter(quarter, {
width: 'narrow',
context: 'formatting'
});
// 1st quarter, 2nd quarter, ...
case 'QQQQ':
default:
return localize.quarter(quarter, {
width: 'wide',
context: 'formatting'
});
}
},
// Stand-alone quarter
q: function (date, token, localize) {
var quarter = Math.ceil((date.getUTCMonth() + 1) / 3);
switch (token) {
// 1, 2, 3, 4
case 'q':
return String(quarter);
// 01, 02, 03, 04
case 'qq':
return addLeadingZeros(quarter, 2);
// 1st, 2nd, 3rd, 4th
case 'qo':
return localize.ordinalNumber(quarter, {
unit: 'quarter'
});
// Q1, Q2, Q3, Q4
case 'qqq':
return localize.quarter(quarter, {
width: 'abbreviated',
context: 'standalone'
});
// 1, 2, 3, 4 (narrow quarter; could be not numerical)
case 'qqqqq':
return localize.quarter(quarter, {
width: 'narrow',
context: 'standalone'
});
// 1st quarter, 2nd quarter, ...
case 'qqqq':
default:
return localize.quarter(quarter, {
width: 'wide',
context: 'standalone'
});
}
},
// Month
M: function (date, token, localize) {
var month = date.getUTCMonth();
switch (token) {
case 'M':
case 'MM':
return lightFormatters.M(date, token);
// 1st, 2nd, ..., 12th
case 'Mo':
return localize.ordinalNumber(month + 1, {
unit: 'month'
});
// Jan, Feb, ..., Dec
case 'MMM':
return localize.month(month, {
width: 'abbreviated',
context: 'formatting'
});
// J, F, ..., D
case 'MMMMM':
return localize.month(month, {
width: 'narrow',
context: 'formatting'
});
// January, February, ..., December
case 'MMMM':
default:
return localize.month(month, {
width: 'wide',
context: 'formatting'
});
}
},
// Stand-alone month
L: function (date, token, localize) {
var month = date.getUTCMonth();
switch (token) {
// 1, 2, ..., 12
case 'L':
return String(month + 1);
// 01, 02, ..., 12
case 'LL':
return addLeadingZeros(month + 1, 2);
// 1st, 2nd, ..., 12th
case 'Lo':
return localize.ordinalNumber(month + 1, {
unit: 'month'
});
// Jan, Feb, ..., Dec
case 'LLL':
return localize.month(month, {
width: 'abbreviated',
context: 'standalone'
});
// J, F, ..., D
case 'LLLLL':
return localize.month(month, {
width: 'narrow',
context: 'standalone'
});
// January, February, ..., December
case 'LLLL':
default:
return localize.month(month, {
width: 'wide',
context: 'standalone'
});
}
},
// Local week of year
w: function (date, token, localize, options) {
var week = getUTCWeek(date, options);
if (token === 'wo') {
return localize.ordinalNumber(week, {
unit: 'week'
});
}
return addLeadingZeros(week, token.length);
},
// ISO week of year
I: function (date, token, localize) {
var isoWeek = getUTCISOWeek(date);
if (token === 'Io') {
return localize.ordinalNumber(isoWeek, {
unit: 'week'
});
}
return addLeadingZeros(isoWeek, token.length);
},
// Day of the month
d: function (date, token, localize) {
if (token === 'do') {
return localize.ordinalNumber(date.getUTCDate(), {
unit: 'date'
});
}
return lightFormatters.d(date, token);
},
// Day of year
D: function (date, token, localize) {
var dayOfYear = getUTCDayOfYear(date);
if (token === 'Do') {
return localize.ordinalNumber(dayOfYear, {
unit: 'dayOfYear'
});
}
return addLeadingZeros(dayOfYear, token.length);
},
// Day of week
E: function (date, token, localize) {
var dayOfWeek = date.getUTCDay();
switch (token) {
// Tue
case 'E':
case 'EE':
case 'EEE':
return localize.day(dayOfWeek, {
width: 'abbreviated',
context: 'formatting'
});
// T
case 'EEEEE':
return localize.day(dayOfWeek, {
width: 'narrow',
context: 'formatting'
});
// Tu
case 'EEEEEE':
return localize.day(dayOfWeek, {
width: 'short',
context: 'formatting'
});
// Tuesday
case 'EEEE':
default:
return localize.day(dayOfWeek, {
width: 'wide',
context: 'formatting'
});
}
},
// Local day of week
e: function (date, token, localize, options) {
var dayOfWeek = date.getUTCDay();
var localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;
switch (token) {
// Numerical value (Nth day of week with current locale or weekStartsOn)
case 'e':
return String(localDayOfWeek);
// Padded numerical value
case 'ee':
return addLeadingZeros(localDayOfWeek, 2);
// 1st, 2nd, ..., 7th
case 'eo':
return localize.ordinalNumber(localDayOfWeek, {
unit: 'day'
});
case 'eee':
return localize.day(dayOfWeek, {
width: 'abbreviated',
context: 'formatting'
});
// T
case 'eeeee':
return localize.day(dayOfWeek, {
width: 'narrow',
context: 'formatting'
});
// Tu
case 'eeeeee':
return localize.day(dayOfWeek, {
width: 'short',
context: 'formatting'
});
// Tuesday
case 'eeee':
default:
return localize.day(dayOfWeek, {
width: 'wide',
context: 'formatting'
});
}
},
// Stand-alone local day of week
c: function (date, token, localize, options) {
var dayOfWeek = date.getUTCDay();
var localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;
switch (token) {
// Numerical value (same as in `e`)
case 'c':
return String(localDayOfWeek);
// Padded numerical value
case 'cc':
return addLeadingZeros(localDayOfWeek, token.length);
// 1st, 2nd, ..., 7th
case 'co':
return localize.ordinalNumber(localDayOfWeek, {
unit: 'day'
});
case 'ccc':
return localize.day(dayOfWeek, {
width: 'abbreviated',
context: 'standalone'
});
// T
case 'ccccc':
return localize.day(dayOfWeek, {
width: 'narrow',
context: 'standalone'
});
// Tu
case 'cccccc':
return localize.day(dayOfWeek, {
width: 'short',
context: 'standalone'
});
// Tuesday
case 'cccc':
default:
return localize.day(dayOfWeek, {
width: 'wide',
context: 'standalone'
});
}
},
// ISO day of week
i: function (date, token, localize) {
var dayOfWeek = date.getUTCDay();
var isoDayOfWeek = dayOfWeek === 0 ? 7 : dayOfWeek;
switch (token) {
// 2
case 'i':
return String(isoDayOfWeek);
// 02
case 'ii':
return addLeadingZeros(isoDayOfWeek, token.length);
// 2nd
case 'io':
return localize.ordinalNumber(isoDayOfWeek, {
unit: 'day'
});
// Tue
case 'iii':
return localize.day(dayOfWeek, {
width: 'abbreviated',
context: 'formatting'
});
// T
case 'iiiii':
return localize.day(dayOfWeek, {
width: 'narrow',
context: 'formatting'
});
// Tu
case 'iiiiii':
return localize.day(dayOfWeek, {
width: 'short',
context: 'formatting'
});
// Tuesday
case 'iiii':
default:
return localize.day(dayOfWeek, {
width: 'wide',
context: 'formatting'
});
}
},
// AM or PM
a: function (date, token, localize) {
var hours = date.getUTCHours();
var dayPeriodEnumValue = hours / 12 >= 1 ? 'pm' : 'am';
switch (token) {
case 'a':
case 'aa':
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'abbreviated',
context: 'formatting'
});
case 'aaa':
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'abbreviated',
context: 'formatting'
}).toLowerCase();
case 'aaaaa':
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'narrow',
context: 'formatting'
});
case 'aaaa':
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'wide',
context: 'formatting'
});
}
},
// AM, PM, midnight, noon
b: function (date, token, localize) {
var hours = date.getUTCHours();
var dayPeriodEnumValue;
if (hours === 12) {
dayPeriodEnumValue = dayPeriodEnum.noon;
} else if (hours === 0) {
dayPeriodEnumValue = dayPeriodEnum.midnight;
} else {
dayPeriodEnumValue = hours / 12 >= 1 ? 'pm' : 'am';
}
switch (token) {
case 'b':
case 'bb':
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'abbreviated',
context: 'formatting'
});
case 'bbb':
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'abbreviated',
context: 'formatting'
}).toLowerCase();
case 'bbbbb':
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'narrow',
context: 'formatting'
});
case 'bbbb':
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'wide',
context: 'formatting'
});
}
},
// in the morning, in the afternoon, in the evening, at night
B: function (date, token, localize) {
var hours = date.getUTCHours();
var dayPeriodEnumValue;
if (hours >= 17) {
dayPeriodEnumValue = dayPeriodEnum.evening;
} else if (hours >= 12) {
dayPeriodEnumValue = dayPeriodEnum.afternoon;
} else if (hours >= 4) {
dayPeriodEnumValue = dayPeriodEnum.morning;
} else {
dayPeriodEnumValue = dayPeriodEnum.night;
}
switch (token) {
case 'B':
case 'BB':
case 'BBB':
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'abbreviated',
context: 'formatting'
});
case 'BBBBB':
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'narrow',
context: 'formatting'
});
case 'BBBB':
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: 'wide',
context: 'formatting'
});
}
},
// Hour [1-12]
h: function (date, token, localize) {
if (token === 'ho') {
var hours = date.getUTCHours() % 12;
if (hours === 0) hours = 12;
return localize.ordinalNumber(hours, {
unit: 'hour'
});
}
return lightFormatters.h(date, token);
},
// Hour [0-23]
H: function (date, token, localize) {
if (token === 'Ho') {
return localize.ordinalNumber(date.getUTCHours(), {
unit: 'hour'
});
}
return lightFormatters.H(date, token);
},
// Hour [0-11]
K: function (date, token, localize) {
var hours = date.getUTCHours() % 12;
if (token === 'Ko') {
return localize.ordinalNumber(hours, {
unit: 'hour'
});
}
return addLeadingZeros(hours, token.length);
},
// Hour [1-24]
k: function (date, token, localize) {
var hours = date.getUTCHours();
if (hours === 0) hours = 24;
if (token === 'ko') {
return localize.ordinalNumber(hours, {
unit: 'hour'
});
}
return addLeadingZeros(hours, token.length);
},
// Minute
m: function (date, token, localize) {
if (token === 'mo') {
return localize.ordinalNumber(date.getUTCMinutes(), {
unit: 'minute'
});
}
return lightFormatters.m(date, token);
},
// Second
s: function (date, token, localize) {
if (token === 'so') {
return localize.ordinalNumber(date.getUTCSeconds(), {
unit: 'second'
});
}
return lightFormatters.s(date, token);
},
// Fraction of second
S: function (date, token) {
return lightFormatters.S(date, token);
},
// Timezone (ISO-8601. If offset is 0, output is always `'Z'`)
X: function (date, token, _localize, options) {
var originalDate = options._originalDate || date;
var timezoneOffset = originalDate.getTimezoneOffset();
if (timezoneOffset === 0) {
return 'Z';
}
switch (token) {
// Hours and optional minutes
case 'X':
return formatTimezoneWithOptionalMinutes(timezoneOffset);
// Hours, minutes and optional seconds without `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `XX`
case 'XXXX':
case 'XX':
// Hours and minutes without `:` delimiter
return formatTimezone(timezoneOffset);
// Hours, minutes and optional seconds with `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `XXX`
case 'XXXXX':
case 'XXX': // Hours and minutes with `:` delimiter
default:
return formatTimezone(timezoneOffset, ':');
}
},
// Timezone (ISO-8601. If offset is 0, output is `'+00:00'` or equivalent)
x: function (date, token, _localize, options) {
var originalDate = options._originalDate || date;
var timezoneOffset = originalDate.getTimezoneOffset();
switch (token) {
// Hours and optional minutes
case 'x':
return formatTimezoneWithOptionalMinutes(timezoneOffset);
// Hours, minutes and optional seconds without `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `xx`
case 'xxxx':
case 'xx':
// Hours and minutes without `:` delimiter
return formatTimezone(timezoneOffset);
// Hours, minutes and optional seconds with `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `xxx`
case 'xxxxx':
case 'xxx': // Hours and minutes with `:` delimiter
default:
return formatTimezone(timezoneOffset, ':');
}
},
// Timezone (GMT)
O: function (date, token, _localize, options) {
var originalDate = options._originalDate || date;
var timezoneOffset = originalDate.getTimezoneOffset();
switch (token) {
// Short
case 'O':
case 'OO':
case 'OOO':
return 'GMT' + formatTimezoneShort(timezoneOffset, ':');
// Long
case 'OOOO':
default:
return 'GMT' + formatTimezone(timezoneOffset, ':');
}
},
// Timezone (specific non-location)
z: function (date, token, _localize, options) {
var originalDate = options._originalDate || date;
var timezoneOffset = originalDate.getTimezoneOffset();
switch (token) {
// Short
case 'z':
case 'zz':
case 'zzz':
return 'GMT' + formatTimezoneShort(timezoneOffset, ':');
// Long
case 'zzzz':
default:
return 'GMT' + formatTimezone(timezoneOffset, ':');
}
},
// Seconds timestamp
t: function (date, token, _localize, options) {
var originalDate = options._originalDate || date;
var timestamp = Math.floor(originalDate.getTime() / 1000);
return addLeadingZeros(timestamp, token.length);
},
// Milliseconds timestamp
T: function (date, token, _localize, options) {
var originalDate = options._originalDate || date;
var timestamp = originalDate.getTime();
return addLeadingZeros(timestamp, token.length);
}
};
function formatTimezoneShort(offset, dirtyDelimiter) {
var sign = offset > 0 ? '-' : '+';
var absOffset = Math.abs(offset);
var hours = Math.floor(absOffset / 60);
var minutes = absOffset % 60;
if (minutes === 0) {
return sign + String(hours);
}
var delimiter = dirtyDelimiter || '';
return sign + String(hours) + delimiter + addLeadingZeros(minutes, 2);
}
function formatTimezoneWithOptionalMinutes(offset, dirtyDelimiter) {
if (offset % 60 === 0) {
var sign = offset > 0 ? '-' : '+';
return sign + addLeadingZeros(Math.abs(offset) / 60, 2);
}
return formatTimezone(offset, dirtyDelimiter);
}
function formatTimezone(offset, dirtyDelimiter) {
var delimiter = dirtyDelimiter || '';
var sign = offset > 0 ? '-' : '+';
var absOffset = Math.abs(offset);
var hours = addLeadingZeros(Math.floor(absOffset / 60), 2);
var minutes = addLeadingZeros(absOffset % 60, 2);
return sign + hours + delimiter + minutes;
}
var formatters$1 = formatters;
function dateLongFormatter(pattern, formatLong) {
switch (pattern) {
case 'P':
return formatLong.date({
width: 'short'
});
case 'PP':
return formatLong.date({
width: 'medium'
});
case 'PPP':
return formatLong.date({
width: 'long'
});
case 'PPPP':
default:
return formatLong.date({
width: 'full'
});
}
}
function timeLongFormatter(pattern, formatLong) {
switch (pattern) {
case 'p':
return formatLong.time({
width: 'short'
});
case 'pp':
return formatLong.time({
width: 'medium'
});
case 'ppp':
return formatLong.time({
width: 'long'
});
case 'pppp':
default:
return formatLong.time({
width: 'full'
});
}
}
function dateTimeLongFormatter(pattern, formatLong) {
var matchResult = pattern.match(/(P+)(p+)?/);
var datePattern = matchResult[1];
var timePattern = matchResult[2];
if (!timePattern) {
return dateLongFormatter(pattern, formatLong);
}
var dateTimeFormat;
switch (datePattern) {
case 'P':
dateTimeFormat = formatLong.dateTime({
width: 'short'
});
break;
case 'PP':
dateTimeFormat = formatLong.dateTime({
width: 'medium'
});
break;
case 'PPP':
dateTimeFormat = formatLong.dateTime({
width: 'long'
});
break;
case 'PPPP':
default:
dateTimeFormat = formatLong.dateTime({
width: 'full'
});
break;
}
return dateTimeFormat.replace('{{date}}', dateLongFormatter(datePattern, formatLong)).replace('{{time}}', timeLongFormatter(timePattern, formatLong));
}
var longFormatters$2 = {
p: timeLongFormatter,
P: dateTimeLongFormatter
};
var longFormatters$3 = longFormatters$2;
var protectedDayOfYearTokens = ['D', 'DD'];
var protectedWeekYearTokens = ['YY', 'YYYY'];
function isProtectedDayOfYearToken(token) {
return protectedDayOfYearTokens.indexOf(token) !== -1;
}
function isProtectedWeekYearToken(token) {
return protectedWeekYearTokens.indexOf(token) !== -1;
}
function throwProtectedError(token, format, input) {
if (token === 'YYYY') {
throw new RangeError("Use `yyyy` instead of `YYYY` (in `".concat(format, "`) for formatting years to the input `").concat(input, "`; see: https://git.io/fxCyr"));
} else if (token === 'YY') {
throw new RangeError("Use `yy` instead of `YY` (in `".concat(format, "`) for formatting years to the input `").concat(input, "`; see: https://git.io/fxCyr"));
} else if (token === 'D') {
throw new RangeError("Use `d` instead of `D` (in `".concat(format, "`) for formatting days of the month to the input `").concat(input, "`; see: https://git.io/fxCyr"));
} else if (token === 'DD') {
throw new RangeError("Use `dd` instead of `DD` (in `".concat(format, "`) for formatting days of the month to the input `").concat(input, "`; see: https://git.io/fxCyr"));
}
}
// - [yYQqMLwIdDecihHKkms]o matches any available ordinal number token
// (one of the certain letters followed by `o`)
// - (\w)\1* matches any sequences of the same letter
// - '' matches two quote characters in a row
// - '(''|[^'])+('|$) matches anything surrounded by two quote characters ('),
// except a single quote symbol, which ends the sequence.
// Two quote characters do not end the sequence.
// If there is no matching single quote
// then the sequence will continue until the end of the string.
// - . matches any single character unmatched by previous parts of the RegExps
var formattingTokensRegExp$1 = /[yYQqMLwIdDecihHKkms]o|(\w)\1*|''|'(''|[^'])+('|$)|./g; // This RegExp catches symbols escaped by quotes, and also
// sequences of symbols P, p, and the combinations like `PPPPPPPppppp`
var longFormattingTokensRegExp$1 = /P+p+|P+|p+|''|'(''|[^'])+('|$)|./g;
var escapedStringRegExp$1 = /^'([^]*?)'?$/;
var doubleQuoteRegExp$1 = /''/g;
var unescapedLatinCharacterRegExp$1 = /[a-zA-Z]/;
/**
* @name format
* @category Common Helpers
* @summary Format the date.
*
* @description
* Return the formatted date string in the given format. The result may vary by locale.
*
* > ⚠️ Please note that the `format` tokens differ from Moment.js and other libraries.
* > See: https://git.io/fxCyr
*
* The characters wrapped between two single quotes characters (') are escaped.
* Two single quotes in a row, whether inside or outside a quoted sequence, represent a 'real' single quote.
* (see the last example)
*
* Format of the string is based on Unicode Technical Standard #35:
* https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
* with a few additions (see note 7 below the table).
*
* Accepted patterns:
* | Unit | Pattern | Result examples | Notes |
* |---------------------------------|---------|-----------------------------------|-------|
* | Era | G..GGG | AD, BC | |
* | | GGGG | Anno Domini, Before Christ | 2 |
* | | GGGGG | A, B | |
* | Calendar year | y | 44, 1, 1900, 2017 | 5 |
* | | yo | 44th, 1st, 0th, 17th | 5,7 |
* | | yy | 44, 01, 00, 17 | 5 |
* | | yyy | 044, 001, 1900, 2017 | 5 |
* | | yyyy | 0044, 0001, 1900, 2017 | 5 |
* | | yyyyy | ... | 3,5 |
* | Local week-numbering year | Y | 44, 1, 1900, 2017 | 5 |
* | | Yo | 44th, 1st, 1900th, 2017th | 5,7 |
* | | YY | 44, 01, 00, 17 | 5,8 |
* | | YYY | 044, 001, 1900, 2017 | 5 |
* | | YYYY | 0044, 0001, 1900, 2017 | 5,8 |
* | | YYYYY | ... | 3,5 |
* | ISO week-numbering year | R | -43, 0, 1, 1900, 2017 | 5,7 |
* | | RR | -43, 00, 01, 1900, 2017 | 5,7 |
* | | RRR | -043, 000, 001, 1900, 2017 | 5,7 |
* | | RRRR | -0043, 0000, 0001, 1900, 2017 | 5,7 |
* | | RRRRR | ... | 3,5,7 |
* | Extended year | u | -43, 0, 1, 1900, 2017 | 5 |
* | | uu | -43, 01, 1900, 2017 | 5 |
* | | uuu | -043, 001, 1900, 2017 | 5 |
* | | uuuu | -0043, 0001, 1900, 2017 | 5 |
* | | uuuuu | ... | 3,5 |
* | Quarter (formatting) | Q | 1, 2, 3, 4 | |
* | | Qo | 1st, 2nd, 3rd, 4th | 7 |
* | | QQ | 01, 02, 03, 04 | |
* | | QQQ | Q1, Q2, Q3, Q4 | |
* | | QQQQ | 1st quarter, 2nd quarter, ... | 2 |
* | | QQQQQ | 1, 2, 3, 4 | 4 |
* | Quarter (stand-alone) | q | 1, 2, 3, 4 | |
* | | qo | 1st, 2nd, 3rd, 4th | 7 |
* | | qq | 01, 02, 03, 04 | |
* | | qqq | Q1, Q2, Q3, Q4 | |
* | | qqqq | 1st quarter, 2nd quarter, ... | 2 |
* | | qqqqq | 1, 2, 3, 4 | 4 |
* | Month (formatting) | M | 1, 2, ..., 12 | |
* | | Mo | 1st, 2nd, ..., 12th | 7 |
* | | MM | 01, 02, ..., 12 | |
* | | MMM | Jan, Feb, ..., Dec | |
* | | MMMM | January, February, ..., December | 2 |
* | | MMMMM | J, F, ..., D | |
* | Month (stand-alone) | L | 1, 2, ..., 12 | |
* | | Lo | 1st, 2nd, ..., 12th | 7 |
* | | LL | 01, 02, ..., 12 | |
* | | LLL | Jan, Feb, ..., Dec | |
* | | LLLL | January, February, ..., December | 2 |
* | | LLLLL | J, F, ..., D | |
* | Local week of year | w | 1, 2, ..., 53 | |
* | | wo | 1st, 2nd, ..., 53th | 7 |
* | | ww | 01, 02, ..., 53 | |
* | ISO week of year | I | 1, 2, ..., 53 | 7 |
* | | Io | 1st, 2nd, ..., 53th | 7 |
* | | II | 01, 02, ..., 53 | 7 |
* | Day of month | d | 1, 2, ..., 31 | |
* | | do | 1st, 2nd, ..., 31st | 7 |
* | | dd | 01, 02, ..., 31 | |
* | Day of year | D | 1, 2, ..., 365, 366 | 9 |
* | | Do | 1st, 2nd, ..., 365th, 366th | 7 |
* | | DD | 01, 02, ..., 365, 366 | 9 |
* | | DDD | 001, 002, ..., 365, 366 | |
* | | DDDD | ... | 3 |
* | Day of week (formatting) | E..EEE | Mon, Tue, Wed, ..., Sun | |
* | | EEEE | Monday, Tuesday, ..., Sunday | 2 |
* | | EEEEE | M, T, W, T, F, S, S | |
* | | EEEEEE | Mo, Tu, We, Th, Fr, Su, Sa | |
* | ISO day of week (formatting) | i | 1, 2, 3, ..., 7 | 7 |
* | | io | 1st, 2nd, ..., 7th | 7 |
* | | ii | 01, 02, ..., 07 | 7 |
* | | iii | Mon, Tue, Wed, ..., Sun | 7 |
* | | iiii | Monday, Tuesday, ..., Sunday | 2,7 |
* | | iiiii | M, T, W, T, F, S, S | 7 |
* | | iiiiii | Mo, Tu, We, Th, Fr, Su, Sa | 7 |
* | Local day of week (formatting) | e | 2, 3, 4, ..., 1 | |
* | | eo | 2nd, 3rd, ..., 1st | 7 |
* | | ee | 02, 03, ..., 01 | |
* | | eee | Mon, Tue, Wed, ..., Sun | |
* | | eeee | Monday, Tuesday, ..., Sunday | 2 |
* | | eeeee | M, T, W, T, F, S, S | |
* | | eeeeee | Mo, Tu, We, Th, Fr, Su, Sa | |
* | Local day of week (stand-alone) | c | 2, 3, 4, ..., 1 | |
* | | co | 2nd, 3rd, ..., 1st | 7 |
* | | cc | 02, 03, ..., 01 | |
* | | ccc | Mon, Tue, Wed, ..., Sun | |
* | | cccc | Monday, Tuesday, ..., Sunday | 2 |
* | | ccccc | M, T, W, T, F, S, S | |
* | | cccccc | Mo, Tu, We, Th, Fr, Su, Sa | |
* | AM, PM | a..aa | AM, PM | |
* | | aaa | am, pm | |
* | | aaaa | a.m., p.m. | 2 |
* | | aaaaa | a, p | |
* | AM, PM, noon, midnight | b..bb | AM, PM, noon, midnight | |
* | | bbb | am, pm, noon, midnight | |
* | | bbbb | a.m., p.m., noon, midnight | 2 |
* | | bbbbb | a, p, n, mi | |
* | Flexible day period | B..BBB | at night, in the morning, ... | |
* | | BBBB | at night, in the morning, ... | 2 |
* | | BBBBB | at night, in the morning, ... | |
* | Hour [1-12] | h | 1, 2, ..., 11, 12 | |
* | | ho | 1st, 2nd, ..., 11th, 12th | 7 |
* | | hh | 01, 02, ..., 11, 12 | |
* | Hour [0-23] | H | 0, 1, 2, ..., 23 | |
* | | Ho | 0th, 1st, 2nd, ..., 23rd | 7 |
* | | HH | 00, 01, 02, ..., 23 | |
* | Hour [0-11] | K | 1, 2, ..., 11, 0 | |
* | | Ko | 1st, 2nd, ..., 11th, 0th | 7 |
* | | KK | 01, 02, ..., 11, 00 | |
* | Hour [1-24] | k | 24, 1, 2, ..., 23 | |
* | | ko | 24th, 1st, 2nd, ..., 23rd | 7 |
* | | kk | 24, 01, 02, ..., 23 | |
* | Minute | m | 0, 1, ..., 59 | |
* | | mo | 0th, 1st, ..., 59th | 7 |
* | | mm | 00, 01, ..., 59 | |
* | Second | s | 0, 1, ..., 59 | |
* | | so | 0th, 1st, ..., 59th | 7 |
* | | ss | 00, 01, ..., 59 | |
* | Fraction of second | S | 0, 1, ..., 9 | |
* | | SS | 00, 01, ..., 99 | |
* | | SSS | 000, 001, ..., 999 | |
* | | SSSS | ... | 3 |
* | Timezone (ISO-8601 w/ Z) | X | -08, +0530, Z | |
* | | XX | -0800, +0530, Z | |
* | | XXX | -08:00, +05:30, Z | |
* | | XXXX | -0800, +0530, Z, +123456 | 2 |
* | | XXXXX | -08:00, +05:30, Z, +12:34:56 | |
* | Timezone (ISO-8601 w/o Z) | x | -08, +0530, +00 | |
* | | xx | -0800, +0530, +0000 | |
* | | xxx | -08:00, +05:30, +00:00 | 2 |
* | | xxxx | -0800, +0530, +0000, +123456 | |
* | | xxxxx | -08:00, +05:30, +00:00, +12:34:56 | |
* | Timezone (GMT) | O...OOO | GMT-8, GMT+5:30, GMT+0 | |
* | | OOOO | GMT-08:00, GMT+05:30, GMT+00:00 | 2 |
* | Timezone (specific non-locat.) | z...zzz | GMT-8, GMT+5:30, GMT+0 | 6 |
* | | zzzz | GMT-08:00, GMT+05:30, GMT+00:00 | 2,6 |
* | Seconds timestamp | t | 512969520 | 7 |
* | | tt | ... | 3,7 |
* | Milliseconds timestamp | T | 512969520900 | 7 |
* | | TT | ... | 3,7 |
* | Long localized date | P | 04/29/1453 | 7 |
* | | PP | Apr 29, 1453 | 7 |
* | | PPP | April 29th, 1453 | 7 |
* | | PPPP | Friday, April 29th, 1453 | 2,7 |
* | Long localized time | p | 12:00 AM | 7 |
* | | pp | 12:00:00 AM | 7 |
* | | ppp | 12:00:00 AM GMT+2 | 7 |
* | | pppp | 12:00:00 AM GMT+02:00 | 2,7 |
* | Combination of date and time | Pp | 04/29/1453, 12:00 AM | 7 |
* | | PPpp | Apr 29, 1453, 12:00:00 AM | 7 |
* | | PPPppp | April 29th, 1453 at ... | 7 |
* | | PPPPpppp| Friday, April 29th, 1453 at ... | 2,7 |
* Notes:
* 1. "Formatting" units (e.g. formatting quarter) in the default en-US locale
* are the same as "stand-alone" units, but are different in some languages.
* "Formatting" units are declined according to the rules of the language
* in the context of a date. "Stand-alone" units are always nominative singular:
*
* `format(new Date(2017, 10, 6), 'do LLLL', {locale: cs}) //=> '6. listopad'`
*
* `format(new Date(2017, 10, 6), 'do MMMM', {locale: cs}) //=> '6. listopadu'`
*
* 2. Any sequence of the identical letters is a pattern, unless it is escaped by
* the single quote characters (see below).
* If the sequence is longer than listed in table (e.g. `EEEEEEEEEEE`)
* the output will be the same as default pattern for this unit, usually
* the longest one (in case of ISO weekdays, `EEEE`). Default patterns for units
* are marked with "2" in the last column of the table.
*
* `format(new Date(2017, 10, 6), 'MMM') //=> 'Nov'`
*
* `format(new Date(2017, 10, 6), 'MMMM') //=> 'November'`
*
* `format(new Date(2017, 10, 6), 'MMMMM') //=> 'N'`
*
* `format(new Date(2017, 10, 6), 'MMMMMM') //=> 'November'`
*
* `format(new Date(2017, 10, 6), 'MMMMMMM') //=> 'November'`
*
* 3. Some patterns could be unlimited length (such as `yyyyyyyy`).
* The output will be padded with zeros to match the length of the pattern.
*
* `format(new Date(2017, 10, 6), 'yyyyyyyy') //=> '00002017'`
*
* 4. `QQQQQ` and `qqqqq` could be not strictly numerical in some locales.
* These tokens represent the shortest form of the quarter.
*
* 5. The main difference between `y` and `u` patterns are B.C. years:
*
* | Year | `y` | `u` |
* |------|-----|-----|
* | AC 1 | 1 | 1 |
* | BC 1 | 1 | 0 |
* | BC 2 | 2 | -1 |
*
* Also `yy` always returns the last two digits of a year,
* while `uu` pads single digit years to 2 characters and returns other years unchanged:
*
* | Year | `yy` | `uu` |
* |------|------|------|
* | 1 | 01 | 01 |
* | 14 | 14 | 14 |
* | 376 | 76 | 376 |
* | 1453 | 53 | 1453 |
*
* The same difference is true for local and ISO week-numbering years (`Y` and `R`),
* except local week-numbering years are dependent on `options.weekStartsOn`
* and `options.firstWeekContainsDate` (compare [getISOWeekYear]{@link https://date-fns.org/docs/getISOWeekYear}
* and [getWeekYear]{@link https://date-fns.org/docs/getWeekYear}).
*
* 6. Specific non-location timezones are currently unavailable in `date-fns`,
* so right now these tokens fall back to GMT timezones.
*
* 7. These patterns are not in the Unicode Technical Standard #35:
* - `i`: ISO day of week
* - `I`: ISO week of year
* - `R`: ISO week-numbering year
* - `t`: seconds timestamp
* - `T`: milliseconds timestamp
* - `o`: ordinal number modifier
* - `P`: long localized date
* - `p`: long localized time
*
* 8. `YY` and `YYYY` tokens represent week-numbering years but they are often confused with years.
* You should enable `options.useAdditionalWeekYearTokens` to use them. See: https://git.io/fxCyr
*
* 9. `D` and `DD` tokens represent days of the year but they are ofthen confused with days of the month.
* You should enable `options.useAdditionalDayOfYearTokens` to use them. See: https://git.io/fxCyr
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* - The second argument is now required for the sake of explicitness.
*
* ```javascript
* // Before v2.0.0
* format(new Date(2016, 0, 1))
*
* // v2.0.0 onward
* format(new Date(2016, 0, 1), "yyyy-MM-dd'T'HH:mm:ss.SSSxxx")
* ```
*
* - New format string API for `format` function
* which is based on [Unicode Technical Standard #35](https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table).
* See [this post](https://blog.date-fns.org/post/unicode-tokens-in-date-fns-v2-sreatyki91jg) for more details.
*
* - Characters are now escaped using single quote symbols (`'`) instead of square brackets.
*
* @param {Date|Number} date - the original date
* @param {String} format - the string of tokens
* @param {Object} [options] - an object with options.
* @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
* @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
* @param {Number} [options.firstWeekContainsDate=1] - the day of January, which is
* @param {Boolean} [options.useAdditionalWeekYearTokens=false] - if true, allows usage of the week-numbering year tokens `YY` and `YYYY`;
* see: https://git.io/fxCyr
* @param {Boolean} [options.useAdditionalDayOfYearTokens=false] - if true, allows usage of the day of year tokens `D` and `DD`;
* see: https://git.io/fxCyr
* @returns {String} the formatted date string
* @throws {TypeError} 2 arguments required
* @throws {RangeError} `date` must not be Invalid Date
* @throws {RangeError} `options.locale` must contain `localize` property
* @throws {RangeError} `options.locale` must contain `formatLong` property
* @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
* @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7
* @throws {RangeError} use `yyyy` instead of `YYYY` for formatting years using [format provided] to the input [input provided]; see: https://git.io/fxCyr
* @throws {RangeError} use `yy` instead of `YY` for formatting years using [format provided] to the input [input provided]; see: https://git.io/fxCyr
* @throws {RangeError} use `d` instead of `D` for formatting days of the month using [format provided] to the input [input provided]; see: https://git.io/fxCyr
* @throws {RangeError} use `dd` instead of `DD` for formatting days of the month using [format provided] to the input [input provided]; see: https://git.io/fxCyr
* @throws {RangeError} format string contains an unescaped latin alphabet character
*
* @example
* // Represent 11 February 2014 in middle-endian format:
* var result = format(new Date(2014, 1, 11), 'MM/dd/yyyy')
* //=> '02/11/2014'
*
* @example
* // Represent 2 July 2014 in Esperanto:
* import { eoLocale } from 'date-fns/locale/eo'
* var result = format(new Date(2014, 6, 2), "do 'de' MMMM yyyy", {
* locale: eoLocale
* })
* //=> '2-a de julio 2014'
*
* @example
* // Escape string by single quote characters:
* var result = format(new Date(2014, 6, 2, 15), "h 'o''clock'")
* //=> "3 o'clock"
*/
function format(dirtyDate, dirtyFormatStr, dirtyOptions) {
requiredArgs(2, arguments);
var formatStr = String(dirtyFormatStr);
var options = dirtyOptions || {};
var locale = options.locale || enUS;
var localeFirstWeekContainsDate = locale.options && locale.options.firstWeekContainsDate;
var defaultFirstWeekContainsDate = localeFirstWeekContainsDate == null ? 1 : toInteger(localeFirstWeekContainsDate);
var firstWeekContainsDate = options.firstWeekContainsDate == null ? defaultFirstWeekContainsDate : toInteger(options.firstWeekContainsDate); // Test if weekStartsOn is between 1 and 7 _and_ is not NaN
if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {
throw new RangeError('firstWeekContainsDate must be between 1 and 7 inclusively');
}
var localeWeekStartsOn = locale.options && locale.options.weekStartsOn;
var defaultWeekStartsOn = localeWeekStartsOn == null ? 0 : toInteger(localeWeekStartsOn);
var weekStartsOn = options.weekStartsOn == null ? defaultWeekStartsOn : toInteger(options.weekStartsOn); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');
}
if (!locale.localize) {
throw new RangeError('locale must contain localize property');
}
if (!locale.formatLong) {
throw new RangeError('locale must contain formatLong property');
}
var originalDate = toDate(dirtyDate);
if (!isValid(originalDate)) {
throw new RangeError('Invalid time value');
} // Convert the date in system timezone to the same date in UTC+00:00 timezone.
// This ensures that when UTC functions will be implemented, locales will be compatible with them.
// See an issue about UTC functions: https://github.com/date-fns/date-fns/issues/376
var timezoneOffset = getTimezoneOffsetInMilliseconds(originalDate);
var utcDate = subMilliseconds(originalDate, timezoneOffset);
var formatterOptions = {
firstWeekContainsDate: firstWeekContainsDate,
weekStartsOn: weekStartsOn,
locale: locale,
_originalDate: originalDate
};
var result = formatStr.match(longFormattingTokensRegExp$1).map(function (substring) {
var firstCharacter = substring[0];
if (firstCharacter === 'p' || firstCharacter === 'P') {
var longFormatter = longFormatters$3[firstCharacter];
return longFormatter(substring, locale.formatLong, formatterOptions);
}
return substring;
}).join('').match(formattingTokensRegExp$1).map(function (substring) {
// Replace two single quote characters with one single quote character
if (substring === "''") {
return "'";
}
var firstCharacter = substring[0];
if (firstCharacter === "'") {
return cleanEscapedString$1(substring);
}
var formatter = formatters$1[firstCharacter];
if (formatter) {
if (!options.useAdditionalWeekYearTokens && isProtectedWeekYearToken(substring)) {
throwProtectedError(substring, dirtyFormatStr, dirtyDate);
}
if (!options.useAdditionalDayOfYearTokens && isProtectedDayOfYearToken(substring)) {
throwProtectedError(substring, dirtyFormatStr, dirtyDate);
}
return formatter(utcDate, substring, locale.localize, formatterOptions);
}
if (firstCharacter.match(unescapedLatinCharacterRegExp$1)) {
throw new RangeError('Format string contains an unescaped latin alphabet character `' + firstCharacter + '`');
}
return substring;
}).join('');
return result;
}
function cleanEscapedString$1(input) {
return input.match(escapedStringRegExp$1)[1].replace(doubleQuoteRegExp$1, "'");
}
/**
* @name getDate
* @category Day Helpers
* @summary Get the day of the month of the given date.
*
* @description
* Get the day of the month of the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the given date
* @returns {Number} the day of month
* @throws {TypeError} 1 argument required
*
* @example
* // Which day of the month is 29 February 2012?
* const result = getDate(new Date(2012, 1, 29))
* //=> 29
*/
function getDate(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var dayOfMonth = date.getDate();
return dayOfMonth;
}
/**
* @name getDaysInMonth
* @category Month Helpers
* @summary Get the number of days in a month of the given date.
*
* @description
* Get the number of days in a month of the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the given date
* @returns {Number} the number of days in a month
* @throws {TypeError} 1 argument required
*
* @example
* // How many days are in February 2000?
* const result = getDaysInMonth(new Date(2000, 1))
* //=> 29
*/
function getDaysInMonth(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var year = date.getFullYear();
var monthIndex = date.getMonth();
var lastDayOfMonth = new Date(0);
lastDayOfMonth.setFullYear(year, monthIndex + 1, 0);
lastDayOfMonth.setHours(0, 0, 0, 0);
return lastDayOfMonth.getDate();
}
/**
* @name getHours
* @category Hour Helpers
* @summary Get the hours of the given date.
*
* @description
* Get the hours of the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the given date
* @returns {Number} the hours
* @throws {TypeError} 1 argument required
*
* @example
* // Get the hours of 29 February 2012 11:45:00:
* const result = getHours(new Date(2012, 1, 29, 11, 45))
* //=> 11
*/
function getHours(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var hours = date.getHours();
return hours;
}
/**
* @name getMinutes
* @category Minute Helpers
* @summary Get the minutes of the given date.
*
* @description
* Get the minutes of the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the given date
* @returns {Number} the minutes
* @throws {TypeError} 1 argument required
*
* @example
* // Get the minutes of 29 February 2012 11:45:05:
* const result = getMinutes(new Date(2012, 1, 29, 11, 45, 5))
* //=> 45
*/
function getMinutes(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var minutes = date.getMinutes();
return minutes;
}
/**
* @name getMonth
* @category Month Helpers
* @summary Get the month of the given date.
*
* @description
* Get the month of the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the given date
* @returns {Number} the month
* @throws {TypeError} 1 argument required
*
* @example
* // Which month is 29 February 2012?
* const result = getMonth(new Date(2012, 1, 29))
* //=> 1
*/
function getMonth(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var month = date.getMonth();
return month;
}
/**
* @name getSeconds
* @category Second Helpers
* @summary Get the seconds of the given date.
*
* @description
* Get the seconds of the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the given date
* @returns {Number} the seconds
* @throws {TypeError} 1 argument required
*
* @example
* // Get the seconds of 29 February 2012 11:45:05.123:
* const result = getSeconds(new Date(2012, 1, 29, 11, 45, 5, 123))
* //=> 5
*/
function getSeconds(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var seconds = date.getSeconds();
return seconds;
}
/**
* @name getMilliseconds
* @category Millisecond Helpers
* @summary Get the milliseconds of the given date.
*
* @description
* Get the milliseconds of the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the given date
* @returns {Number} the milliseconds
* @throws {TypeError} 1 argument required
*
* @example
* // Get the milliseconds of 29 February 2012 11:45:05.123:
* const result = getMilliseconds(new Date(2012, 1, 29, 11, 45, 5, 123))
* //=> 123
*/
function getMilliseconds(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var milliseconds = date.getMilliseconds();
return milliseconds;
}
/**
* @name startOfWeek
* @category Week Helpers
* @summary Return the start of a week for the given date.
*
* @description
* Return the start of a week for the given date.
* The result will be in the local timezone.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the original date
* @param {Object} [options] - an object with options.
* @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
* @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
* @returns {Date} the start of a week
* @throws {TypeError} 1 argument required
* @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
*
* @example
* // The start of a week for 2 September 2014 11:55:00:
* const result = startOfWeek(new Date(2014, 8, 2, 11, 55, 0))
* //=> Sun Aug 31 2014 00:00:00
*
* @example
* // If the week starts on Monday, the start of the week for 2 September 2014 11:55:00:
* const result = startOfWeek(new Date(2014, 8, 2, 11, 55, 0), { weekStartsOn: 1 })
* //=> Mon Sep 01 2014 00:00:00
*/
function startOfWeek(dirtyDate, dirtyOptions) {
requiredArgs(1, arguments);
var options = dirtyOptions || {};
var locale = options.locale;
var localeWeekStartsOn = locale && locale.options && locale.options.weekStartsOn;
var defaultWeekStartsOn = localeWeekStartsOn == null ? 0 : toInteger(localeWeekStartsOn);
var weekStartsOn = options.weekStartsOn == null ? defaultWeekStartsOn : toInteger(options.weekStartsOn); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');
}
var date = toDate(dirtyDate);
var day = date.getDay();
var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;
date.setDate(date.getDate() - diff);
date.setHours(0, 0, 0, 0);
return date;
}
/**
* @name getWeekYear
* @category Week-Numbering Year Helpers
* @summary Get the local week-numbering year of the given date.
*
* @description
* Get the local week-numbering year of the given date.
* The exact calculation depends on the values of
* `options.weekStartsOn` (which is the index of the first day of the week)
* and `options.firstWeekContainsDate` (which is the day of January, which is always in
* the first week of the week-numbering year)
*
* Week numbering: https://en.wikipedia.org/wiki/Week#Week_numbering
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the given date
* @param {Object} [options] - an object with options.
* @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
* @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
* @param {1|2|3|4|5|6|7} [options.firstWeekContainsDate=1] - the day of January, which is always in the first week of the year
* @returns {Number} the local week-numbering year
* @throws {TypeError} 1 argument required
* @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
* @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7
*
* @example
* // Which week numbering year is 26 December 2004 with the default settings?
* const result = getWeekYear(new Date(2004, 11, 26))
* //=> 2005
*
* @example
* // Which week numbering year is 26 December 2004 if week starts on Saturday?
* const result = getWeekYear(new Date(2004, 11, 26), { weekStartsOn: 6 })
* //=> 2004
*
* @example
* // Which week numbering year is 26 December 2004 if the first week contains 4 January?
* const result = getWeekYear(new Date(2004, 11, 26), { firstWeekContainsDate: 4 })
* //=> 2004
*/
function getWeekYear(dirtyDate, options) {
var _options$locale, _options$locale$optio;
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var year = date.getFullYear();
var localeFirstWeekContainsDate = options === null || options === void 0 ? void 0 : (_options$locale = options.locale) === null || _options$locale === void 0 ? void 0 : (_options$locale$optio = _options$locale.options) === null || _options$locale$optio === void 0 ? void 0 : _options$locale$optio.firstWeekContainsDate;
var defaultFirstWeekContainsDate = localeFirstWeekContainsDate == null ? 1 : toInteger(localeFirstWeekContainsDate);
var firstWeekContainsDate = (options === null || options === void 0 ? void 0 : options.firstWeekContainsDate) == null ? defaultFirstWeekContainsDate : toInteger(options.firstWeekContainsDate); // Test if weekStartsOn is between 1 and 7 _and_ is not NaN
if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {
throw new RangeError('firstWeekContainsDate must be between 1 and 7 inclusively');
}
var firstWeekOfNextYear = new Date(0);
firstWeekOfNextYear.setFullYear(year + 1, 0, firstWeekContainsDate);
firstWeekOfNextYear.setHours(0, 0, 0, 0);
var startOfNextYear = startOfWeek(firstWeekOfNextYear, options);
var firstWeekOfThisYear = new Date(0);
firstWeekOfThisYear.setFullYear(year, 0, firstWeekContainsDate);
firstWeekOfThisYear.setHours(0, 0, 0, 0);
var startOfThisYear = startOfWeek(firstWeekOfThisYear, options);
if (date.getTime() >= startOfNextYear.getTime()) {
return year + 1;
} else if (date.getTime() >= startOfThisYear.getTime()) {
return year;
} else {
return year - 1;
}
}
/**
* @name startOfWeekYear
* @category Week-Numbering Year Helpers
* @summary Return the start of a local week-numbering year for the given date.
*
* @description
* Return the start of a local week-numbering year.
* The exact calculation depends on the values of
* `options.weekStartsOn` (which is the index of the first day of the week)
* and `options.firstWeekContainsDate` (which is the day of January, which is always in
* the first week of the week-numbering year)
*
* Week numbering: https://en.wikipedia.org/wiki/Week#Week_numbering
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the original date
* @param {Object} [options] - an object with options.
* @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
* @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
* @param {1|2|3|4|5|6|7} [options.firstWeekContainsDate=1] - the day of January, which is always in the first week of the year
* @returns {Date} the start of a week-numbering year
* @throws {TypeError} 1 argument required
* @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
* @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7
*
* @example
* // The start of an a week-numbering year for 2 July 2005 with default settings:
* var result = startOfWeekYear(new Date(2005, 6, 2))
* //=> Sun Dec 26 2004 00:00:00
*
* @example
* // The start of a week-numbering year for 2 July 2005
* // if Monday is the first day of week
* // and 4 January is always in the first week of the year:
* var result = startOfWeekYear(new Date(2005, 6, 2), {
* weekStartsOn: 1,
* firstWeekContainsDate: 4
* })
* //=> Mon Jan 03 2005 00:00:00
*/
function startOfWeekYear(dirtyDate, dirtyOptions) {
requiredArgs(1, arguments);
var options = dirtyOptions || {};
var locale = options.locale;
var localeFirstWeekContainsDate = locale && locale.options && locale.options.firstWeekContainsDate;
var defaultFirstWeekContainsDate = localeFirstWeekContainsDate == null ? 1 : toInteger(localeFirstWeekContainsDate);
var firstWeekContainsDate = options.firstWeekContainsDate == null ? defaultFirstWeekContainsDate : toInteger(options.firstWeekContainsDate);
var year = getWeekYear(dirtyDate, dirtyOptions);
var firstWeek = new Date(0);
firstWeek.setFullYear(year, 0, firstWeekContainsDate);
firstWeek.setHours(0, 0, 0, 0);
var date = startOfWeek(firstWeek, dirtyOptions);
return date;
}
var MILLISECONDS_IN_WEEK = 604800000;
/**
* @name getWeek
* @category Week Helpers
* @summary Get the local week index of the given date.
*
* @description
* Get the local week index of the given date.
* The exact calculation depends on the values of
* `options.weekStartsOn` (which is the index of the first day of the week)
* and `options.firstWeekContainsDate` (which is the day of January, which is always in
* the first week of the week-numbering year)
*
* Week numbering: https://en.wikipedia.org/wiki/Week#Week_numbering
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the given date
* @param {Object} [options] - an object with options.
* @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
* @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
* @param {1|2|3|4|5|6|7} [options.firstWeekContainsDate=1] - the day of January, which is always in the first week of the year
* @returns {Number} the week
* @throws {TypeError} 1 argument required
* @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
* @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7
*
* @example
* // Which week of the local week numbering year is 2 January 2005 with default options?
* const result = getISOWeek(new Date(2005, 0, 2))
* //=> 2
*
* // Which week of the local week numbering year is 2 January 2005,
* // if Monday is the first day of the week,
* // and the first week of the year always contains 4 January?
* const result = getISOWeek(new Date(2005, 0, 2), {
* weekStartsOn: 1,
* firstWeekContainsDate: 4
* })
* //=> 53
*/
function getWeek(dirtyDate, options) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var diff = startOfWeek(date, options).getTime() - startOfWeekYear(date, options).getTime(); // Round the number of days to the nearest integer
// because the number of milliseconds in a week is not constant
// (e.g. it's different in the week of the daylight saving time clock shift)
return Math.round(diff / MILLISECONDS_IN_WEEK) + 1;
}
/**
* @name getYear
* @category Year Helpers
* @summary Get the year of the given date.
*
* @description
* Get the year of the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the given date
* @returns {Number} the year
* @throws {TypeError} 1 argument required
*
* @example
* // Which year is 2 July 2014?
* const result = getYear(new Date(2014, 6, 2))
* //=> 2014
*/
function getYear(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
var year = date.getFullYear();
return year;
}
/**
* @name isAfter
* @category Common Helpers
* @summary Is the first date after the second one?
*
* @description
* Is the first date after the second one?
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date that should be after the other one to return true
* @param {Date|Number} dateToCompare - the date to compare with
* @returns {Boolean} the first date is after the second date
* @throws {TypeError} 2 arguments required
*
* @example
* // Is 10 July 1989 after 11 February 1987?
* var result = isAfter(new Date(1989, 6, 10), new Date(1987, 1, 11))
* //=> true
*/
function isAfter(dirtyDate, dirtyDateToCompare) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var dateToCompare = toDate(dirtyDateToCompare);
return date.getTime() > dateToCompare.getTime();
}
/**
* @name isBefore
* @category Common Helpers
* @summary Is the first date before the second one?
*
* @description
* Is the first date before the second one?
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date that should be before the other one to return true
* @param {Date|Number} dateToCompare - the date to compare with
* @returns {Boolean} the first date is before the second date
* @throws {TypeError} 2 arguments required
*
* @example
* // Is 10 July 1989 before 11 February 1987?
* var result = isBefore(new Date(1989, 6, 10), new Date(1987, 1, 11))
* //=> false
*/
function isBefore(dirtyDate, dirtyDateToCompare) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var dateToCompare = toDate(dirtyDateToCompare);
return date.getTime() < dateToCompare.getTime();
}
/**
* @name isEqual
* @category Common Helpers
* @summary Are the given dates equal?
*
* @description
* Are the given dates equal?
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the first date to compare
* @param {Date|Number} dateRight - the second date to compare
* @returns {Boolean} the dates are equal
* @throws {TypeError} 2 arguments required
*
* @example
* // Are 2 July 2014 06:30:45.000 and 2 July 2014 06:30:45.500 equal?
* var result = isEqual(
* new Date(2014, 6, 2, 6, 30, 45, 0),
* new Date(2014, 6, 2, 6, 30, 45, 500)
* )
* //=> false
*/
function isEqual(dirtyLeftDate, dirtyRightDate) {
requiredArgs(2, arguments);
var dateLeft = toDate(dirtyLeftDate);
var dateRight = toDate(dirtyRightDate);
return dateLeft.getTime() === dateRight.getTime();
}
/**
* @name isSameDay
* @category Day Helpers
* @summary Are the given dates in the same day?
*
* @description
* Are the given dates in the same day?
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the first date to check
* @param {Date|Number} dateRight - the second date to check
* @returns {Boolean} the dates are in the same day
* @throws {TypeError} 2 arguments required
*
* @example
* // Are 4 September 06:00:00 and 4 September 18:00:00 in the same day?
* var result = isSameDay(new Date(2014, 8, 4, 6, 0), new Date(2014, 8, 4, 18, 0))
* //=> true
*/
function isSameDay(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeftStartOfDay = startOfDay(dirtyDateLeft);
var dateRightStartOfDay = startOfDay(dirtyDateRight);
return dateLeftStartOfDay.getTime() === dateRightStartOfDay.getTime();
}
/**
* @name isSameYear
* @category Year Helpers
* @summary Are the given dates in the same year?
*
* @description
* Are the given dates in the same year?
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the first date to check
* @param {Date|Number} dateRight - the second date to check
* @returns {Boolean} the dates are in the same year
* @throws {TypeError} 2 arguments required
*
* @example
* // Are 2 September 2014 and 25 September 2014 in the same year?
* var result = isSameYear(new Date(2014, 8, 2), new Date(2014, 8, 25))
* //=> true
*/
function isSameYear(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeft = toDate(dirtyDateLeft);
var dateRight = toDate(dirtyDateRight);
return dateLeft.getFullYear() === dateRight.getFullYear();
}
/**
* @name isSameMonth
* @category Month Helpers
* @summary Are the given dates in the same month?
*
* @description
* Are the given dates in the same month?
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the first date to check
* @param {Date|Number} dateRight - the second date to check
* @returns {Boolean} the dates are in the same month
* @throws {TypeError} 2 arguments required
*
* @example
* // Are 2 September 2014 and 25 September 2014 in the same month?
* var result = isSameMonth(new Date(2014, 8, 2), new Date(2014, 8, 25))
* //=> true
*/
function isSameMonth(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeft = toDate(dirtyDateLeft);
var dateRight = toDate(dirtyDateRight);
return dateLeft.getFullYear() === dateRight.getFullYear() && dateLeft.getMonth() === dateRight.getMonth();
}
/**
* @name startOfHour
* @category Hour Helpers
* @summary Return the start of an hour for the given date.
*
* @description
* Return the start of an hour for the given date.
* The result will be in the local timezone.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the original date
* @returns {Date} the start of an hour
* @throws {TypeError} 1 argument required
*
* @example
* // The start of an hour for 2 September 2014 11:55:00:
* const result = startOfHour(new Date(2014, 8, 2, 11, 55))
* //=> Tue Sep 02 2014 11:00:00
*/
function startOfHour(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
date.setMinutes(0, 0, 0);
return date;
}
/**
* @name isSameHour
* @category Hour Helpers
* @summary Are the given dates in the same hour?
*
* @description
* Are the given dates in the same hour?
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} dateLeft - the first date to check
* @param {Date|Number} dateRight - the second date to check
* @returns {Boolean} the dates are in the same hour
* @throws {TypeError} 2 arguments required
*
* @example
* // Are 4 September 2014 06:00:00 and 4 September 06:30:00 in the same hour?
* var result = isSameHour(new Date(2014, 8, 4, 6, 0), new Date(2014, 8, 4, 6, 30))
* //=> true
*/
function isSameHour(dirtyDateLeft, dirtyDateRight) {
requiredArgs(2, arguments);
var dateLeftStartOfHour = startOfHour(dirtyDateLeft);
var dateRightStartOfHour = startOfHour(dirtyDateRight);
return dateLeftStartOfHour.getTime() === dateRightStartOfHour.getTime();
}
function assign(target, dirtyObject) {
if (target == null) {
throw new TypeError('assign requires that input parameter not be null or undefined');
}
dirtyObject = dirtyObject || {};
for (var property in dirtyObject) {
if (Object.prototype.hasOwnProperty.call(dirtyObject, property)) {
target[property] = dirtyObject[property];
}
}
return target;
}
// See issue: https://github.com/date-fns/date-fns/issues/376
function setUTCDay(dirtyDate, dirtyDay, dirtyOptions) {
requiredArgs(2, arguments);
var options = dirtyOptions || {};
var locale = options.locale;
var localeWeekStartsOn = locale && locale.options && locale.options.weekStartsOn;
var defaultWeekStartsOn = localeWeekStartsOn == null ? 0 : toInteger(localeWeekStartsOn);
var weekStartsOn = options.weekStartsOn == null ? defaultWeekStartsOn : toInteger(options.weekStartsOn); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');
}
var date = toDate(dirtyDate);
var day = toInteger(dirtyDay);
var currentDay = date.getUTCDay();
var remainder = day % 7;
var dayIndex = (remainder + 7) % 7;
var diff = (dayIndex < weekStartsOn ? 7 : 0) + day - currentDay;
date.setUTCDate(date.getUTCDate() + diff);
return date;
}
// See issue: https://github.com/date-fns/date-fns/issues/376
function setUTCISODay(dirtyDate, dirtyDay) {
requiredArgs(2, arguments);
var day = toInteger(dirtyDay);
if (day % 7 === 0) {
day = day - 7;
}
var weekStartsOn = 1;
var date = toDate(dirtyDate);
var currentDay = date.getUTCDay();
var remainder = day % 7;
var dayIndex = (remainder + 7) % 7;
var diff = (dayIndex < weekStartsOn ? 7 : 0) + day - currentDay;
date.setUTCDate(date.getUTCDate() + diff);
return date;
}
// See issue: https://github.com/date-fns/date-fns/issues/376
function setUTCISOWeek(dirtyDate, dirtyISOWeek) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var isoWeek = toInteger(dirtyISOWeek);
var diff = getUTCISOWeek(date) - isoWeek;
date.setUTCDate(date.getUTCDate() - diff * 7);
return date;
}
// See issue: https://github.com/date-fns/date-fns/issues/376
function setUTCWeek(dirtyDate, dirtyWeek, options) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var week = toInteger(dirtyWeek);
var diff = getUTCWeek(date, options) - week;
date.setUTCDate(date.getUTCDate() - diff * 7);
return date;
}
var MILLISECONDS_IN_HOUR$1 = 3600000;
var MILLISECONDS_IN_MINUTE$1 = 60000;
var MILLISECONDS_IN_SECOND = 1000;
var numericPatterns = {
month: /^(1[0-2]|0?\d)/,
// 0 to 12
date: /^(3[0-1]|[0-2]?\d)/,
// 0 to 31
dayOfYear: /^(36[0-6]|3[0-5]\d|[0-2]?\d?\d)/,
// 0 to 366
week: /^(5[0-3]|[0-4]?\d)/,
// 0 to 53
hour23h: /^(2[0-3]|[0-1]?\d)/,
// 0 to 23
hour24h: /^(2[0-4]|[0-1]?\d)/,
// 0 to 24
hour11h: /^(1[0-1]|0?\d)/,
// 0 to 11
hour12h: /^(1[0-2]|0?\d)/,
// 0 to 12
minute: /^[0-5]?\d/,
// 0 to 59
second: /^[0-5]?\d/,
// 0 to 59
singleDigit: /^\d/,
// 0 to 9
twoDigits: /^\d{1,2}/,
// 0 to 99
threeDigits: /^\d{1,3}/,
// 0 to 999
fourDigits: /^\d{1,4}/,
// 0 to 9999
anyDigitsSigned: /^-?\d+/,
singleDigitSigned: /^-?\d/,
// 0 to 9, -0 to -9
twoDigitsSigned: /^-?\d{1,2}/,
// 0 to 99, -0 to -99
threeDigitsSigned: /^-?\d{1,3}/,
// 0 to 999, -0 to -999
fourDigitsSigned: /^-?\d{1,4}/ // 0 to 9999, -0 to -9999
};
var timezonePatterns = {
basicOptionalMinutes: /^([+-])(\d{2})(\d{2})?|Z/,
basic: /^([+-])(\d{2})(\d{2})|Z/,
basicOptionalSeconds: /^([+-])(\d{2})(\d{2})((\d{2}))?|Z/,
extended: /^([+-])(\d{2}):(\d{2})|Z/,
extendedOptionalSeconds: /^([+-])(\d{2}):(\d{2})(:(\d{2}))?|Z/
};
function parseNumericPattern(pattern, string, valueCallback) {
var matchResult = string.match(pattern);
if (!matchResult) {
return null;
}
var value = parseInt(matchResult[0], 10);
return {
value: valueCallback ? valueCallback(value) : value,
rest: string.slice(matchResult[0].length)
};
}
function parseTimezonePattern(pattern, string) {
var matchResult = string.match(pattern);
if (!matchResult) {
return null;
} // Input is 'Z'
if (matchResult[0] === 'Z') {
return {
value: 0,
rest: string.slice(1)
};
}
var sign = matchResult[1] === '+' ? 1 : -1;
var hours = matchResult[2] ? parseInt(matchResult[2], 10) : 0;
var minutes = matchResult[3] ? parseInt(matchResult[3], 10) : 0;
var seconds = matchResult[5] ? parseInt(matchResult[5], 10) : 0;
return {
value: sign * (hours * MILLISECONDS_IN_HOUR$1 + minutes * MILLISECONDS_IN_MINUTE$1 + seconds * MILLISECONDS_IN_SECOND),
rest: string.slice(matchResult[0].length)
};
}
function parseAnyDigitsSigned(string, valueCallback) {
return parseNumericPattern(numericPatterns.anyDigitsSigned, string, valueCallback);
}
function parseNDigits(n, string, valueCallback) {
switch (n) {
case 1:
return parseNumericPattern(numericPatterns.singleDigit, string, valueCallback);
case 2:
return parseNumericPattern(numericPatterns.twoDigits, string, valueCallback);
case 3:
return parseNumericPattern(numericPatterns.threeDigits, string, valueCallback);
case 4:
return parseNumericPattern(numericPatterns.fourDigits, string, valueCallback);
default:
return parseNumericPattern(new RegExp('^\\d{1,' + n + '}'), string, valueCallback);
}
}
function parseNDigitsSigned(n, string, valueCallback) {
switch (n) {
case 1:
return parseNumericPattern(numericPatterns.singleDigitSigned, string, valueCallback);
case 2:
return parseNumericPattern(numericPatterns.twoDigitsSigned, string, valueCallback);
case 3:
return parseNumericPattern(numericPatterns.threeDigitsSigned, string, valueCallback);
case 4:
return parseNumericPattern(numericPatterns.fourDigitsSigned, string, valueCallback);
default:
return parseNumericPattern(new RegExp('^-?\\d{1,' + n + '}'), string, valueCallback);
}
}
function dayPeriodEnumToHours(enumValue) {
switch (enumValue) {
case 'morning':
return 4;
case 'evening':
return 17;
case 'pm':
case 'noon':
case 'afternoon':
return 12;
case 'am':
case 'midnight':
case 'night':
default:
return 0;
}
}
function normalizeTwoDigitYear(twoDigitYear, currentYear) {
var isCommonEra = currentYear > 0; // Absolute number of the current year:
// 1 -> 1 AC
// 0 -> 1 BC
// -1 -> 2 BC
var absCurrentYear = isCommonEra ? currentYear : 1 - currentYear;
var result;
if (absCurrentYear <= 50) {
result = twoDigitYear || 100;
} else {
var rangeEnd = absCurrentYear + 50;
var rangeEndCentury = Math.floor(rangeEnd / 100) * 100;
var isPreviousCentury = twoDigitYear >= rangeEnd % 100;
result = twoDigitYear + rangeEndCentury - (isPreviousCentury ? 100 : 0);
}
return isCommonEra ? result : 1 - result;
}
var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var DAYS_IN_MONTH_LEAP_YEAR = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // User for validation
function isLeapYearIndex$1(year) {
return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
}
/*
* | | Unit | | Unit |
* |-----|--------------------------------|-----|--------------------------------|
* | a | AM, PM | A* | Milliseconds in day |
* | b | AM, PM, noon, midnight | B | Flexible day period |
* | c | Stand-alone local day of week | C* | Localized hour w/ day period |
* | d | Day of month | D | Day of year |
* | e | Local day of week | E | Day of week |
* | f | | F* | Day of week in month |
* | g* | Modified Julian day | G | Era |
* | h | Hour [1-12] | H | Hour [0-23] |
* | i! | ISO day of week | I! | ISO week of year |
* | j* | Localized hour w/ day period | J* | Localized hour w/o day period |
* | k | Hour [1-24] | K | Hour [0-11] |
* | l* | (deprecated) | L | Stand-alone month |
* | m | Minute | M | Month |
* | n | | N | |
* | o! | Ordinal number modifier | O* | Timezone (GMT) |
* | p | | P | |
* | q | Stand-alone quarter | Q | Quarter |
* | r* | Related Gregorian year | R! | ISO week-numbering year |
* | s | Second | S | Fraction of second |
* | t! | Seconds timestamp | T! | Milliseconds timestamp |
* | u | Extended year | U* | Cyclic year |
* | v* | Timezone (generic non-locat.) | V* | Timezone (location) |
* | w | Local week of year | W* | Week of month |
* | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |
* | y | Year (abs) | Y | Local week-numbering year |
* | z* | Timezone (specific non-locat.) | Z* | Timezone (aliases) |
*
* Letters marked by * are not implemented but reserved by Unicode standard.
*
* Letters marked by ! are non-standard, but implemented by date-fns:
* - `o` modifies the previous token to turn it into an ordinal (see `parse` docs)
* - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,
* i.e. 7 for Sunday, 1 for Monday, etc.
* - `I` is ISO week of year, as opposed to `w` which is local week of year.
* - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.
* `R` is supposed to be used in conjunction with `I` and `i`
* for universal ISO week-numbering date, whereas
* `Y` is supposed to be used in conjunction with `w` and `e`
* for week-numbering date specific to the locale.
*/
var parsers = {
// Era
G: {
priority: 140,
parse: function (string, token, match, _options) {
switch (token) {
// AD, BC
case 'G':
case 'GG':
case 'GGG':
return match.era(string, {
width: 'abbreviated'
}) || match.era(string, {
width: 'narrow'
});
// A, B
case 'GGGGG':
return match.era(string, {
width: 'narrow'
});
// Anno Domini, Before Christ
case 'GGGG':
default:
return match.era(string, {
width: 'wide'
}) || match.era(string, {
width: 'abbreviated'
}) || match.era(string, {
width: 'narrow'
});
}
},
set: function (date, flags, value, _options) {
flags.era = value;
date.setUTCFullYear(value, 0, 1);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['R', 'u', 't', 'T']
},
// Year
y: {
// From http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns
// | Year | y | yy | yyy | yyyy | yyyyy |
// |----------|-------|----|-------|-------|-------|
// | AD 1 | 1 | 01 | 001 | 0001 | 00001 |
// | AD 12 | 12 | 12 | 012 | 0012 | 00012 |
// | AD 123 | 123 | 23 | 123 | 0123 | 00123 |
// | AD 1234 | 1234 | 34 | 1234 | 1234 | 01234 |
// | AD 12345 | 12345 | 45 | 12345 | 12345 | 12345 |
priority: 130,
parse: function (string, token, match, _options) {
var valueCallback = function (year) {
return {
year: year,
isTwoDigitYear: token === 'yy'
};
};
switch (token) {
case 'y':
return parseNDigits(4, string, valueCallback);
case 'yo':
return match.ordinalNumber(string, {
unit: 'year',
valueCallback: valueCallback
});
default:
return parseNDigits(token.length, string, valueCallback);
}
},
validate: function (_date, value, _options) {
return value.isTwoDigitYear || value.year > 0;
},
set: function (date, flags, value, _options) {
var currentYear = date.getUTCFullYear();
if (value.isTwoDigitYear) {
var normalizedTwoDigitYear = normalizeTwoDigitYear(value.year, currentYear);
date.setUTCFullYear(normalizedTwoDigitYear, 0, 1);
date.setUTCHours(0, 0, 0, 0);
return date;
}
var year = !('era' in flags) || flags.era === 1 ? value.year : 1 - value.year;
date.setUTCFullYear(year, 0, 1);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['Y', 'R', 'u', 'w', 'I', 'i', 'e', 'c', 't', 'T']
},
// Local week-numbering year
Y: {
priority: 130,
parse: function (string, token, match, _options) {
var valueCallback = function (year) {
return {
year: year,
isTwoDigitYear: token === 'YY'
};
};
switch (token) {
case 'Y':
return parseNDigits(4, string, valueCallback);
case 'Yo':
return match.ordinalNumber(string, {
unit: 'year',
valueCallback: valueCallback
});
default:
return parseNDigits(token.length, string, valueCallback);
}
},
validate: function (_date, value, _options) {
return value.isTwoDigitYear || value.year > 0;
},
set: function (date, flags, value, options) {
var currentYear = getUTCWeekYear(date, options);
if (value.isTwoDigitYear) {
var normalizedTwoDigitYear = normalizeTwoDigitYear(value.year, currentYear);
date.setUTCFullYear(normalizedTwoDigitYear, 0, options.firstWeekContainsDate);
date.setUTCHours(0, 0, 0, 0);
return startOfUTCWeek(date, options);
}
var year = !('era' in flags) || flags.era === 1 ? value.year : 1 - value.year;
date.setUTCFullYear(year, 0, options.firstWeekContainsDate);
date.setUTCHours(0, 0, 0, 0);
return startOfUTCWeek(date, options);
},
incompatibleTokens: ['y', 'R', 'u', 'Q', 'q', 'M', 'L', 'I', 'd', 'D', 'i', 't', 'T']
},
// ISO week-numbering year
R: {
priority: 130,
parse: function (string, token, _match, _options) {
if (token === 'R') {
return parseNDigitsSigned(4, string);
}
return parseNDigitsSigned(token.length, string);
},
set: function (_date, _flags, value, _options) {
var firstWeekOfYear = new Date(0);
firstWeekOfYear.setUTCFullYear(value, 0, 4);
firstWeekOfYear.setUTCHours(0, 0, 0, 0);
return startOfUTCISOWeek(firstWeekOfYear);
},
incompatibleTokens: ['G', 'y', 'Y', 'u', 'Q', 'q', 'M', 'L', 'w', 'd', 'D', 'e', 'c', 't', 'T']
},
// Extended year
u: {
priority: 130,
parse: function (string, token, _match, _options) {
if (token === 'u') {
return parseNDigitsSigned(4, string);
}
return parseNDigitsSigned(token.length, string);
},
set: function (date, _flags, value, _options) {
date.setUTCFullYear(value, 0, 1);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['G', 'y', 'Y', 'R', 'w', 'I', 'i', 'e', 'c', 't', 'T']
},
// Quarter
Q: {
priority: 120,
parse: function (string, token, match, _options) {
switch (token) {
// 1, 2, 3, 4
case 'Q':
case 'QQ':
// 01, 02, 03, 04
return parseNDigits(token.length, string);
// 1st, 2nd, 3rd, 4th
case 'Qo':
return match.ordinalNumber(string, {
unit: 'quarter'
});
// Q1, Q2, Q3, Q4
case 'QQQ':
return match.quarter(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.quarter(string, {
width: 'narrow',
context: 'formatting'
});
// 1, 2, 3, 4 (narrow quarter; could be not numerical)
case 'QQQQQ':
return match.quarter(string, {
width: 'narrow',
context: 'formatting'
});
// 1st quarter, 2nd quarter, ...
case 'QQQQ':
default:
return match.quarter(string, {
width: 'wide',
context: 'formatting'
}) || match.quarter(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.quarter(string, {
width: 'narrow',
context: 'formatting'
});
}
},
validate: function (_date, value, _options) {
return value >= 1 && value <= 4;
},
set: function (date, _flags, value, _options) {
date.setUTCMonth((value - 1) * 3, 1);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['Y', 'R', 'q', 'M', 'L', 'w', 'I', 'd', 'D', 'i', 'e', 'c', 't', 'T']
},
// Stand-alone quarter
q: {
priority: 120,
parse: function (string, token, match, _options) {
switch (token) {
// 1, 2, 3, 4
case 'q':
case 'qq':
// 01, 02, 03, 04
return parseNDigits(token.length, string);
// 1st, 2nd, 3rd, 4th
case 'qo':
return match.ordinalNumber(string, {
unit: 'quarter'
});
// Q1, Q2, Q3, Q4
case 'qqq':
return match.quarter(string, {
width: 'abbreviated',
context: 'standalone'
}) || match.quarter(string, {
width: 'narrow',
context: 'standalone'
});
// 1, 2, 3, 4 (narrow quarter; could be not numerical)
case 'qqqqq':
return match.quarter(string, {
width: 'narrow',
context: 'standalone'
});
// 1st quarter, 2nd quarter, ...
case 'qqqq':
default:
return match.quarter(string, {
width: 'wide',
context: 'standalone'
}) || match.quarter(string, {
width: 'abbreviated',
context: 'standalone'
}) || match.quarter(string, {
width: 'narrow',
context: 'standalone'
});
}
},
validate: function (_date, value, _options) {
return value >= 1 && value <= 4;
},
set: function (date, _flags, value, _options) {
date.setUTCMonth((value - 1) * 3, 1);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['Y', 'R', 'Q', 'M', 'L', 'w', 'I', 'd', 'D', 'i', 'e', 'c', 't', 'T']
},
// Month
M: {
priority: 110,
parse: function (string, token, match, _options) {
var valueCallback = function (value) {
return value - 1;
};
switch (token) {
// 1, 2, ..., 12
case 'M':
return parseNumericPattern(numericPatterns.month, string, valueCallback);
// 01, 02, ..., 12
case 'MM':
return parseNDigits(2, string, valueCallback);
// 1st, 2nd, ..., 12th
case 'Mo':
return match.ordinalNumber(string, {
unit: 'month',
valueCallback: valueCallback
});
// Jan, Feb, ..., Dec
case 'MMM':
return match.month(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.month(string, {
width: 'narrow',
context: 'formatting'
});
// J, F, ..., D
case 'MMMMM':
return match.month(string, {
width: 'narrow',
context: 'formatting'
});
// January, February, ..., December
case 'MMMM':
default:
return match.month(string, {
width: 'wide',
context: 'formatting'
}) || match.month(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.month(string, {
width: 'narrow',
context: 'formatting'
});
}
},
validate: function (_date, value, _options) {
return value >= 0 && value <= 11;
},
set: function (date, _flags, value, _options) {
date.setUTCMonth(value, 1);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['Y', 'R', 'q', 'Q', 'L', 'w', 'I', 'D', 'i', 'e', 'c', 't', 'T']
},
// Stand-alone month
L: {
priority: 110,
parse: function (string, token, match, _options) {
var valueCallback = function (value) {
return value - 1;
};
switch (token) {
// 1, 2, ..., 12
case 'L':
return parseNumericPattern(numericPatterns.month, string, valueCallback);
// 01, 02, ..., 12
case 'LL':
return parseNDigits(2, string, valueCallback);
// 1st, 2nd, ..., 12th
case 'Lo':
return match.ordinalNumber(string, {
unit: 'month',
valueCallback: valueCallback
});
// Jan, Feb, ..., Dec
case 'LLL':
return match.month(string, {
width: 'abbreviated',
context: 'standalone'
}) || match.month(string, {
width: 'narrow',
context: 'standalone'
});
// J, F, ..., D
case 'LLLLL':
return match.month(string, {
width: 'narrow',
context: 'standalone'
});
// January, February, ..., December
case 'LLLL':
default:
return match.month(string, {
width: 'wide',
context: 'standalone'
}) || match.month(string, {
width: 'abbreviated',
context: 'standalone'
}) || match.month(string, {
width: 'narrow',
context: 'standalone'
});
}
},
validate: function (_date, value, _options) {
return value >= 0 && value <= 11;
},
set: function (date, _flags, value, _options) {
date.setUTCMonth(value, 1);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['Y', 'R', 'q', 'Q', 'M', 'w', 'I', 'D', 'i', 'e', 'c', 't', 'T']
},
// Local week of year
w: {
priority: 100,
parse: function (string, token, match, _options) {
switch (token) {
case 'w':
return parseNumericPattern(numericPatterns.week, string);
case 'wo':
return match.ordinalNumber(string, {
unit: 'week'
});
default:
return parseNDigits(token.length, string);
}
},
validate: function (_date, value, _options) {
return value >= 1 && value <= 53;
},
set: function (date, _flags, value, options) {
return startOfUTCWeek(setUTCWeek(date, value, options), options);
},
incompatibleTokens: ['y', 'R', 'u', 'q', 'Q', 'M', 'L', 'I', 'd', 'D', 'i', 't', 'T']
},
// ISO week of year
I: {
priority: 100,
parse: function (string, token, match, _options) {
switch (token) {
case 'I':
return parseNumericPattern(numericPatterns.week, string);
case 'Io':
return match.ordinalNumber(string, {
unit: 'week'
});
default:
return parseNDigits(token.length, string);
}
},
validate: function (_date, value, _options) {
return value >= 1 && value <= 53;
},
set: function (date, _flags, value, options) {
return startOfUTCISOWeek(setUTCISOWeek(date, value, options), options);
},
incompatibleTokens: ['y', 'Y', 'u', 'q', 'Q', 'M', 'L', 'w', 'd', 'D', 'e', 'c', 't', 'T']
},
// Day of the month
d: {
priority: 90,
subPriority: 1,
parse: function (string, token, match, _options) {
switch (token) {
case 'd':
return parseNumericPattern(numericPatterns.date, string);
case 'do':
return match.ordinalNumber(string, {
unit: 'date'
});
default:
return parseNDigits(token.length, string);
}
},
validate: function (date, value, _options) {
var year = date.getUTCFullYear();
var isLeapYear = isLeapYearIndex$1(year);
var month = date.getUTCMonth();
if (isLeapYear) {
return value >= 1 && value <= DAYS_IN_MONTH_LEAP_YEAR[month];
} else {
return value >= 1 && value <= DAYS_IN_MONTH[month];
}
},
set: function (date, _flags, value, _options) {
date.setUTCDate(value);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['Y', 'R', 'q', 'Q', 'w', 'I', 'D', 'i', 'e', 'c', 't', 'T']
},
// Day of year
D: {
priority: 90,
subPriority: 1,
parse: function (string, token, match, _options) {
switch (token) {
case 'D':
case 'DD':
return parseNumericPattern(numericPatterns.dayOfYear, string);
case 'Do':
return match.ordinalNumber(string, {
unit: 'date'
});
default:
return parseNDigits(token.length, string);
}
},
validate: function (date, value, _options) {
var year = date.getUTCFullYear();
var isLeapYear = isLeapYearIndex$1(year);
if (isLeapYear) {
return value >= 1 && value <= 366;
} else {
return value >= 1 && value <= 365;
}
},
set: function (date, _flags, value, _options) {
date.setUTCMonth(0, value);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['Y', 'R', 'q', 'Q', 'M', 'L', 'w', 'I', 'd', 'E', 'i', 'e', 'c', 't', 'T']
},
// Day of week
E: {
priority: 90,
parse: function (string, token, match, _options) {
switch (token) {
// Tue
case 'E':
case 'EE':
case 'EEE':
return match.day(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.day(string, {
width: 'short',
context: 'formatting'
}) || match.day(string, {
width: 'narrow',
context: 'formatting'
});
// T
case 'EEEEE':
return match.day(string, {
width: 'narrow',
context: 'formatting'
});
// Tu
case 'EEEEEE':
return match.day(string, {
width: 'short',
context: 'formatting'
}) || match.day(string, {
width: 'narrow',
context: 'formatting'
});
// Tuesday
case 'EEEE':
default:
return match.day(string, {
width: 'wide',
context: 'formatting'
}) || match.day(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.day(string, {
width: 'short',
context: 'formatting'
}) || match.day(string, {
width: 'narrow',
context: 'formatting'
});
}
},
validate: function (_date, value, _options) {
return value >= 0 && value <= 6;
},
set: function (date, _flags, value, options) {
date = setUTCDay(date, value, options);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['D', 'i', 'e', 'c', 't', 'T']
},
// Local day of week
e: {
priority: 90,
parse: function (string, token, match, options) {
var valueCallback = function (value) {
var wholeWeekDays = Math.floor((value - 1) / 7) * 7;
return (value + options.weekStartsOn + 6) % 7 + wholeWeekDays;
};
switch (token) {
// 3
case 'e':
case 'ee':
// 03
return parseNDigits(token.length, string, valueCallback);
// 3rd
case 'eo':
return match.ordinalNumber(string, {
unit: 'day',
valueCallback: valueCallback
});
// Tue
case 'eee':
return match.day(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.day(string, {
width: 'short',
context: 'formatting'
}) || match.day(string, {
width: 'narrow',
context: 'formatting'
});
// T
case 'eeeee':
return match.day(string, {
width: 'narrow',
context: 'formatting'
});
// Tu
case 'eeeeee':
return match.day(string, {
width: 'short',
context: 'formatting'
}) || match.day(string, {
width: 'narrow',
context: 'formatting'
});
// Tuesday
case 'eeee':
default:
return match.day(string, {
width: 'wide',
context: 'formatting'
}) || match.day(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.day(string, {
width: 'short',
context: 'formatting'
}) || match.day(string, {
width: 'narrow',
context: 'formatting'
});
}
},
validate: function (_date, value, _options) {
return value >= 0 && value <= 6;
},
set: function (date, _flags, value, options) {
date = setUTCDay(date, value, options);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['y', 'R', 'u', 'q', 'Q', 'M', 'L', 'I', 'd', 'D', 'E', 'i', 'c', 't', 'T']
},
// Stand-alone local day of week
c: {
priority: 90,
parse: function (string, token, match, options) {
var valueCallback = function (value) {
var wholeWeekDays = Math.floor((value - 1) / 7) * 7;
return (value + options.weekStartsOn + 6) % 7 + wholeWeekDays;
};
switch (token) {
// 3
case 'c':
case 'cc':
// 03
return parseNDigits(token.length, string, valueCallback);
// 3rd
case 'co':
return match.ordinalNumber(string, {
unit: 'day',
valueCallback: valueCallback
});
// Tue
case 'ccc':
return match.day(string, {
width: 'abbreviated',
context: 'standalone'
}) || match.day(string, {
width: 'short',
context: 'standalone'
}) || match.day(string, {
width: 'narrow',
context: 'standalone'
});
// T
case 'ccccc':
return match.day(string, {
width: 'narrow',
context: 'standalone'
});
// Tu
case 'cccccc':
return match.day(string, {
width: 'short',
context: 'standalone'
}) || match.day(string, {
width: 'narrow',
context: 'standalone'
});
// Tuesday
case 'cccc':
default:
return match.day(string, {
width: 'wide',
context: 'standalone'
}) || match.day(string, {
width: 'abbreviated',
context: 'standalone'
}) || match.day(string, {
width: 'short',
context: 'standalone'
}) || match.day(string, {
width: 'narrow',
context: 'standalone'
});
}
},
validate: function (_date, value, _options) {
return value >= 0 && value <= 6;
},
set: function (date, _flags, value, options) {
date = setUTCDay(date, value, options);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['y', 'R', 'u', 'q', 'Q', 'M', 'L', 'I', 'd', 'D', 'E', 'i', 'e', 't', 'T']
},
// ISO day of week
i: {
priority: 90,
parse: function (string, token, match, _options) {
var valueCallback = function (value) {
if (value === 0) {
return 7;
}
return value;
};
switch (token) {
// 2
case 'i':
case 'ii':
// 02
return parseNDigits(token.length, string);
// 2nd
case 'io':
return match.ordinalNumber(string, {
unit: 'day'
});
// Tue
case 'iii':
return match.day(string, {
width: 'abbreviated',
context: 'formatting',
valueCallback: valueCallback
}) || match.day(string, {
width: 'short',
context: 'formatting',
valueCallback: valueCallback
}) || match.day(string, {
width: 'narrow',
context: 'formatting',
valueCallback: valueCallback
});
// T
case 'iiiii':
return match.day(string, {
width: 'narrow',
context: 'formatting',
valueCallback: valueCallback
});
// Tu
case 'iiiiii':
return match.day(string, {
width: 'short',
context: 'formatting',
valueCallback: valueCallback
}) || match.day(string, {
width: 'narrow',
context: 'formatting',
valueCallback: valueCallback
});
// Tuesday
case 'iiii':
default:
return match.day(string, {
width: 'wide',
context: 'formatting',
valueCallback: valueCallback
}) || match.day(string, {
width: 'abbreviated',
context: 'formatting',
valueCallback: valueCallback
}) || match.day(string, {
width: 'short',
context: 'formatting',
valueCallback: valueCallback
}) || match.day(string, {
width: 'narrow',
context: 'formatting',
valueCallback: valueCallback
});
}
},
validate: function (_date, value, _options) {
return value >= 1 && value <= 7;
},
set: function (date, _flags, value, options) {
date = setUTCISODay(date, value, options);
date.setUTCHours(0, 0, 0, 0);
return date;
},
incompatibleTokens: ['y', 'Y', 'u', 'q', 'Q', 'M', 'L', 'w', 'd', 'D', 'E', 'e', 'c', 't', 'T']
},
// AM or PM
a: {
priority: 80,
parse: function (string, token, match, _options) {
switch (token) {
case 'a':
case 'aa':
case 'aaa':
return match.dayPeriod(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.dayPeriod(string, {
width: 'narrow',
context: 'formatting'
});
case 'aaaaa':
return match.dayPeriod(string, {
width: 'narrow',
context: 'formatting'
});
case 'aaaa':
default:
return match.dayPeriod(string, {
width: 'wide',
context: 'formatting'
}) || match.dayPeriod(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.dayPeriod(string, {
width: 'narrow',
context: 'formatting'
});
}
},
set: function (date, _flags, value, _options) {
date.setUTCHours(dayPeriodEnumToHours(value), 0, 0, 0);
return date;
},
incompatibleTokens: ['b', 'B', 'H', 'K', 'k', 't', 'T']
},
// AM, PM, midnight
b: {
priority: 80,
parse: function (string, token, match, _options) {
switch (token) {
case 'b':
case 'bb':
case 'bbb':
return match.dayPeriod(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.dayPeriod(string, {
width: 'narrow',
context: 'formatting'
});
case 'bbbbb':
return match.dayPeriod(string, {
width: 'narrow',
context: 'formatting'
});
case 'bbbb':
default:
return match.dayPeriod(string, {
width: 'wide',
context: 'formatting'
}) || match.dayPeriod(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.dayPeriod(string, {
width: 'narrow',
context: 'formatting'
});
}
},
set: function (date, _flags, value, _options) {
date.setUTCHours(dayPeriodEnumToHours(value), 0, 0, 0);
return date;
},
incompatibleTokens: ['a', 'B', 'H', 'K', 'k', 't', 'T']
},
// in the morning, in the afternoon, in the evening, at night
B: {
priority: 80,
parse: function (string, token, match, _options) {
switch (token) {
case 'B':
case 'BB':
case 'BBB':
return match.dayPeriod(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.dayPeriod(string, {
width: 'narrow',
context: 'formatting'
});
case 'BBBBB':
return match.dayPeriod(string, {
width: 'narrow',
context: 'formatting'
});
case 'BBBB':
default:
return match.dayPeriod(string, {
width: 'wide',
context: 'formatting'
}) || match.dayPeriod(string, {
width: 'abbreviated',
context: 'formatting'
}) || match.dayPeriod(string, {
width: 'narrow',
context: 'formatting'
});
}
},
set: function (date, _flags, value, _options) {
date.setUTCHours(dayPeriodEnumToHours(value), 0, 0, 0);
return date;
},
incompatibleTokens: ['a', 'b', 't', 'T']
},
// Hour [1-12]
h: {
priority: 70,
parse: function (string, token, match, _options) {
switch (token) {
case 'h':
return parseNumericPattern(numericPatterns.hour12h, string);
case 'ho':
return match.ordinalNumber(string, {
unit: 'hour'
});
default:
return parseNDigits(token.length, string);
}
},
validate: function (_date, value, _options) {
return value >= 1 && value <= 12;
},
set: function (date, _flags, value, _options) {
var isPM = date.getUTCHours() >= 12;
if (isPM && value < 12) {
date.setUTCHours(value + 12, 0, 0, 0);
} else if (!isPM && value === 12) {
date.setUTCHours(0, 0, 0, 0);
} else {
date.setUTCHours(value, 0, 0, 0);
}
return date;
},
incompatibleTokens: ['H', 'K', 'k', 't', 'T']
},
// Hour [0-23]
H: {
priority: 70,
parse: function (string, token, match, _options) {
switch (token) {
case 'H':
return parseNumericPattern(numericPatterns.hour23h, string);
case 'Ho':
return match.ordinalNumber(string, {
unit: 'hour'
});
default:
return parseNDigits(token.length, string);
}
},
validate: function (_date, value, _options) {
return value >= 0 && value <= 23;
},
set: function (date, _flags, value, _options) {
date.setUTCHours(value, 0, 0, 0);
return date;
},
incompatibleTokens: ['a', 'b', 'h', 'K', 'k', 't', 'T']
},
// Hour [0-11]
K: {
priority: 70,
parse: function (string, token, match, _options) {
switch (token) {
case 'K':
return parseNumericPattern(numericPatterns.hour11h, string);
case 'Ko':
return match.ordinalNumber(string, {
unit: 'hour'
});
default:
return parseNDigits(token.length, string);
}
},
validate: function (_date, value, _options) {
return value >= 0 && value <= 11;
},
set: function (date, _flags, value, _options) {
var isPM = date.getUTCHours() >= 12;
if (isPM && value < 12) {
date.setUTCHours(value + 12, 0, 0, 0);
} else {
date.setUTCHours(value, 0, 0, 0);
}
return date;
},
incompatibleTokens: ['a', 'b', 'h', 'H', 'k', 't', 'T']
},
// Hour [1-24]
k: {
priority: 70,
parse: function (string, token, match, _options) {
switch (token) {
case 'k':
return parseNumericPattern(numericPatterns.hour24h, string);
case 'ko':
return match.ordinalNumber(string, {
unit: 'hour'
});
default:
return parseNDigits(token.length, string);
}
},
validate: function (_date, value, _options) {
return value >= 1 && value <= 24;
},
set: function (date, _flags, value, _options) {
var hours = value <= 24 ? value % 24 : value;
date.setUTCHours(hours, 0, 0, 0);
return date;
},
incompatibleTokens: ['a', 'b', 'h', 'H', 'K', 't', 'T']
},
// Minute
m: {
priority: 60,
parse: function (string, token, match, _options) {
switch (token) {
case 'm':
return parseNumericPattern(numericPatterns.minute, string);
case 'mo':
return match.ordinalNumber(string, {
unit: 'minute'
});
default:
return parseNDigits(token.length, string);
}
},
validate: function (_date, value, _options) {
return value >= 0 && value <= 59;
},
set: function (date, _flags, value, _options) {
date.setUTCMinutes(value, 0, 0);
return date;
},
incompatibleTokens: ['t', 'T']
},
// Second
s: {
priority: 50,
parse: function (string, token, match, _options) {
switch (token) {
case 's':
return parseNumericPattern(numericPatterns.second, string);
case 'so':
return match.ordinalNumber(string, {
unit: 'second'
});
default:
return parseNDigits(token.length, string);
}
},
validate: function (_date, value, _options) {
return value >= 0 && value <= 59;
},
set: function (date, _flags, value, _options) {
date.setUTCSeconds(value, 0);
return date;
},
incompatibleTokens: ['t', 'T']
},
// Fraction of second
S: {
priority: 30,
parse: function (string, token, _match, _options) {
var valueCallback = function (value) {
return Math.floor(value * Math.pow(10, -token.length + 3));
};
return parseNDigits(token.length, string, valueCallback);
},
set: function (date, _flags, value, _options) {
date.setUTCMilliseconds(value);
return date;
},
incompatibleTokens: ['t', 'T']
},
// Timezone (ISO-8601. +00:00 is `'Z'`)
X: {
priority: 10,
parse: function (string, token, _match, _options) {
switch (token) {
case 'X':
return parseTimezonePattern(timezonePatterns.basicOptionalMinutes, string);
case 'XX':
return parseTimezonePattern(timezonePatterns.basic, string);
case 'XXXX':
return parseTimezonePattern(timezonePatterns.basicOptionalSeconds, string);
case 'XXXXX':
return parseTimezonePattern(timezonePatterns.extendedOptionalSeconds, string);
case 'XXX':
default:
return parseTimezonePattern(timezonePatterns.extended, string);
}
},
set: function (date, flags, value, _options) {
if (flags.timestampIsSet) {
return date;
}
return new Date(date.getTime() - value);
},
incompatibleTokens: ['t', 'T', 'x']
},
// Timezone (ISO-8601)
x: {
priority: 10,
parse: function (string, token, _match, _options) {
switch (token) {
case 'x':
return parseTimezonePattern(timezonePatterns.basicOptionalMinutes, string);
case 'xx':
return parseTimezonePattern(timezonePatterns.basic, string);
case 'xxxx':
return parseTimezonePattern(timezonePatterns.basicOptionalSeconds, string);
case 'xxxxx':
return parseTimezonePattern(timezonePatterns.extendedOptionalSeconds, string);
case 'xxx':
default:
return parseTimezonePattern(timezonePatterns.extended, string);
}
},
set: function (date, flags, value, _options) {
if (flags.timestampIsSet) {
return date;
}
return new Date(date.getTime() - value);
},
incompatibleTokens: ['t', 'T', 'X']
},
// Seconds timestamp
t: {
priority: 40,
parse: function (string, _token, _match, _options) {
return parseAnyDigitsSigned(string);
},
set: function (_date, _flags, value, _options) {
return [new Date(value * 1000), {
timestampIsSet: true
}];
},
incompatibleTokens: '*'
},
// Milliseconds timestamp
T: {
priority: 20,
parse: function (string, _token, _match, _options) {
return parseAnyDigitsSigned(string);
},
set: function (_date, _flags, value, _options) {
return [new Date(value), {
timestampIsSet: true
}];
},
incompatibleTokens: '*'
}
};
var parsers$1 = parsers;
var TIMEZONE_UNIT_PRIORITY = 10; // This RegExp consists of three parts separated by `|`:
// - [yYQqMLwIdDecihHKkms]o matches any available ordinal number token
// (one of the certain letters followed by `o`)
// - (\w)\1* matches any sequences of the same letter
// - '' matches two quote characters in a row
// - '(''|[^'])+('|$) matches anything surrounded by two quote characters ('),
// except a single quote symbol, which ends the sequence.
// Two quote characters do not end the sequence.
// If there is no matching single quote
// then the sequence will continue until the end of the string.
// - . matches any single character unmatched by previous parts of the RegExps
var formattingTokensRegExp = /[yYQqMLwIdDecihHKkms]o|(\w)\1*|''|'(''|[^'])+('|$)|./g; // This RegExp catches symbols escaped by quotes, and also
// sequences of symbols P, p, and the combinations like `PPPPPPPppppp`
var longFormattingTokensRegExp = /P+p+|P+|p+|''|'(''|[^'])+('|$)|./g;
var escapedStringRegExp = /^'([^]*?)'?$/;
var doubleQuoteRegExp = /''/g;
var notWhitespaceRegExp = /\S/;
var unescapedLatinCharacterRegExp = /[a-zA-Z]/;
/**
* @name parse
* @category Common Helpers
* @summary Parse the date.
*
* @description
* Return the date parsed from string using the given format string.
*
* > ⚠️ Please note that the `format` tokens differ from Moment.js and other libraries.
* > See: https://git.io/fxCyr
*
* The characters in the format string wrapped between two single quotes characters (') are escaped.
* Two single quotes in a row, whether inside or outside a quoted sequence, represent a 'real' single quote.
*
* Format of the format string is based on Unicode Technical Standard #35:
* https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
* with a few additions (see note 5 below the table).
*
* Not all tokens are compatible. Combinations that don't make sense or could lead to bugs are prohibited
* and will throw `RangeError`. For example usage of 24-hour format token with AM/PM token will throw an exception:
*
* ```javascript
* parse('23 AM', 'HH a', new Date())
* //=> RangeError: The format string mustn't contain `HH` and `a` at the same time
* ```
*
* See the compatibility table: https://docs.google.com/spreadsheets/d/e/2PACX-1vQOPU3xUhplll6dyoMmVUXHKl_8CRDs6_ueLmex3SoqwhuolkuN3O05l4rqx5h1dKX8eb46Ul-CCSrq/pubhtml?gid=0&single=true
*
* Accepted format string patterns:
* | Unit |Prior| Pattern | Result examples | Notes |
* |---------------------------------|-----|---------|-----------------------------------|-------|
* | Era | 140 | G..GGG | AD, BC | |
* | | | GGGG | Anno Domini, Before Christ | 2 |
* | | | GGGGG | A, B | |
* | Calendar year | 130 | y | 44, 1, 1900, 2017, 9999 | 4 |
* | | | yo | 44th, 1st, 1900th, 9999999th | 4,5 |
* | | | yy | 44, 01, 00, 17 | 4 |
* | | | yyy | 044, 001, 123, 999 | 4 |
* | | | yyyy | 0044, 0001, 1900, 2017 | 4 |
* | | | yyyyy | ... | 2,4 |
* | Local week-numbering year | 130 | Y | 44, 1, 1900, 2017, 9000 | 4 |
* | | | Yo | 44th, 1st, 1900th, 9999999th | 4,5 |
* | | | YY | 44, 01, 00, 17 | 4,6 |
* | | | YYY | 044, 001, 123, 999 | 4 |
* | | | YYYY | 0044, 0001, 1900, 2017 | 4,6 |
* | | | YYYYY | ... | 2,4 |
* | ISO week-numbering year | 130 | R | -43, 1, 1900, 2017, 9999, -9999 | 4,5 |
* | | | RR | -43, 01, 00, 17 | 4,5 |
* | | | RRR | -043, 001, 123, 999, -999 | 4,5 |
* | | | RRRR | -0043, 0001, 2017, 9999, -9999 | 4,5 |
* | | | RRRRR | ... | 2,4,5 |
* | Extended year | 130 | u | -43, 1, 1900, 2017, 9999, -999 | 4 |
* | | | uu | -43, 01, 99, -99 | 4 |
* | | | uuu | -043, 001, 123, 999, -999 | 4 |
* | | | uuuu | -0043, 0001, 2017, 9999, -9999 | 4 |
* | | | uuuuu | ... | 2,4 |
* | Quarter (formatting) | 120 | Q | 1, 2, 3, 4 | |
* | | | Qo | 1st, 2nd, 3rd, 4th | 5 |
* | | | QQ | 01, 02, 03, 04 | |
* | | | QQQ | Q1, Q2, Q3, Q4 | |
* | | | QQQQ | 1st quarter, 2nd quarter, ... | 2 |
* | | | QQQQQ | 1, 2, 3, 4 | 4 |
* | Quarter (stand-alone) | 120 | q | 1, 2, 3, 4 | |
* | | | qo | 1st, 2nd, 3rd, 4th | 5 |
* | | | qq | 01, 02, 03, 04 | |
* | | | qqq | Q1, Q2, Q3, Q4 | |
* | | | qqqq | 1st quarter, 2nd quarter, ... | 2 |
* | | | qqqqq | 1, 2, 3, 4 | 3 |
* | Month (formatting) | 110 | M | 1, 2, ..., 12 | |
* | | | Mo | 1st, 2nd, ..., 12th | 5 |
* | | | MM | 01, 02, ..., 12 | |
* | | | MMM | Jan, Feb, ..., Dec | |
* | | | MMMM | January, February, ..., December | 2 |
* | | | MMMMM | J, F, ..., D | |
* | Month (stand-alone) | 110 | L | 1, 2, ..., 12 | |
* | | | Lo | 1st, 2nd, ..., 12th | 5 |
* | | | LL | 01, 02, ..., 12 | |
* | | | LLL | Jan, Feb, ..., Dec | |
* | | | LLLL | January, February, ..., December | 2 |
* | | | LLLLL | J, F, ..., D | |
* | Local week of year | 100 | w | 1, 2, ..., 53 | |
* | | | wo | 1st, 2nd, ..., 53th | 5 |
* | | | ww | 01, 02, ..., 53 | |
* | ISO week of year | 100 | I | 1, 2, ..., 53 | 5 |
* | | | Io | 1st, 2nd, ..., 53th | 5 |
* | | | II | 01, 02, ..., 53 | 5 |
* | Day of month | 90 | d | 1, 2, ..., 31 | |
* | | | do | 1st, 2nd, ..., 31st | 5 |
* | | | dd | 01, 02, ..., 31 | |
* | Day of year | 90 | D | 1, 2, ..., 365, 366 | 7 |
* | | | Do | 1st, 2nd, ..., 365th, 366th | 5 |
* | | | DD | 01, 02, ..., 365, 366 | 7 |
* | | | DDD | 001, 002, ..., 365, 366 | |
* | | | DDDD | ... | 2 |
* | Day of week (formatting) | 90 | E..EEE | Mon, Tue, Wed, ..., Sun | |
* | | | EEEE | Monday, Tuesday, ..., Sunday | 2 |
* | | | EEEEE | M, T, W, T, F, S, S | |
* | | | EEEEEE | Mo, Tu, We, Th, Fr, Su, Sa | |
* | ISO day of week (formatting) | 90 | i | 1, 2, 3, ..., 7 | 5 |
* | | | io | 1st, 2nd, ..., 7th | 5 |
* | | | ii | 01, 02, ..., 07 | 5 |
* | | | iii | Mon, Tue, Wed, ..., Sun | 5 |
* | | | iiii | Monday, Tuesday, ..., Sunday | 2,5 |
* | | | iiiii | M, T, W, T, F, S, S | 5 |
* | | | iiiiii | Mo, Tu, We, Th, Fr, Su, Sa | 5 |
* | Local day of week (formatting) | 90 | e | 2, 3, 4, ..., 1 | |
* | | | eo | 2nd, 3rd, ..., 1st | 5 |
* | | | ee | 02, 03, ..., 01 | |
* | | | eee | Mon, Tue, Wed, ..., Sun | |
* | | | eeee | Monday, Tuesday, ..., Sunday | 2 |
* | | | eeeee | M, T, W, T, F, S, S | |
* | | | eeeeee | Mo, Tu, We, Th, Fr, Su, Sa | |
* | Local day of week (stand-alone) | 90 | c | 2, 3, 4, ..., 1 | |
* | | | co | 2nd, 3rd, ..., 1st | 5 |
* | | | cc | 02, 03, ..., 01 | |
* | | | ccc | Mon, Tue, Wed, ..., Sun | |
* | | | cccc | Monday, Tuesday, ..., Sunday | 2 |
* | | | ccccc | M, T, W, T, F, S, S | |
* | | | cccccc | Mo, Tu, We, Th, Fr, Su, Sa | |
* | AM, PM | 80 | a..aaa | AM, PM | |
* | | | aaaa | a.m., p.m. | 2 |
* | | | aaaaa | a, p | |
* | AM, PM, noon, midnight | 80 | b..bbb | AM, PM, noon, midnight | |
* | | | bbbb | a.m., p.m., noon, midnight | 2 |
* | | | bbbbb | a, p, n, mi | |
* | Flexible day period | 80 | B..BBB | at night, in the morning, ... | |
* | | | BBBB | at night, in the morning, ... | 2 |
* | | | BBBBB | at night, in the morning, ... | |
* | Hour [1-12] | 70 | h | 1, 2, ..., 11, 12 | |
* | | | ho | 1st, 2nd, ..., 11th, 12th | 5 |
* | | | hh | 01, 02, ..., 11, 12 | |
* | Hour [0-23] | 70 | H | 0, 1, 2, ..., 23 | |
* | | | Ho | 0th, 1st, 2nd, ..., 23rd | 5 |
* | | | HH | 00, 01, 02, ..., 23 | |
* | Hour [0-11] | 70 | K | 1, 2, ..., 11, 0 | |
* | | | Ko | 1st, 2nd, ..., 11th, 0th | 5 |
* | | | KK | 01, 02, ..., 11, 00 | |
* | Hour [1-24] | 70 | k | 24, 1, 2, ..., 23 | |
* | | | ko | 24th, 1st, 2nd, ..., 23rd | 5 |
* | | | kk | 24, 01, 02, ..., 23 | |
* | Minute | 60 | m | 0, 1, ..., 59 | |
* | | | mo | 0th, 1st, ..., 59th | 5 |
* | | | mm | 00, 01, ..., 59 | |
* | Second | 50 | s | 0, 1, ..., 59 | |
* | | | so | 0th, 1st, ..., 59th | 5 |
* | | | ss | 00, 01, ..., 59 | |
* | Seconds timestamp | 40 | t | 512969520 | |
* | | | tt | ... | 2 |
* | Fraction of second | 30 | S | 0, 1, ..., 9 | |
* | | | SS | 00, 01, ..., 99 | |
* | | | SSS | 000, 0001, ..., 999 | |
* | | | SSSS | ... | 2 |
* | Milliseconds timestamp | 20 | T | 512969520900 | |
* | | | TT | ... | 2 |
* | Timezone (ISO-8601 w/ Z) | 10 | X | -08, +0530, Z | |
* | | | XX | -0800, +0530, Z | |
* | | | XXX | -08:00, +05:30, Z | |
* | | | XXXX | -0800, +0530, Z, +123456 | 2 |
* | | | XXXXX | -08:00, +05:30, Z, +12:34:56 | |
* | Timezone (ISO-8601 w/o Z) | 10 | x | -08, +0530, +00 | |
* | | | xx | -0800, +0530, +0000 | |
* | | | xxx | -08:00, +05:30, +00:00 | 2 |
* | | | xxxx | -0800, +0530, +0000, +123456 | |
* | | | xxxxx | -08:00, +05:30, +00:00, +12:34:56 | |
* | Long localized date | NA | P | 05/29/1453 | 5,8 |
* | | | PP | May 29, 1453 | |
* | | | PPP | May 29th, 1453 | |
* | | | PPPP | Sunday, May 29th, 1453 | 2,5,8 |
* | Long localized time | NA | p | 12:00 AM | 5,8 |
* | | | pp | 12:00:00 AM | |
* | Combination of date and time | NA | Pp | 05/29/1453, 12:00 AM | |
* | | | PPpp | May 29, 1453, 12:00:00 AM | |
* | | | PPPpp | May 29th, 1453 at ... | |
* | | | PPPPpp | Sunday, May 29th, 1453 at ... | 2,5,8 |
* Notes:
* 1. "Formatting" units (e.g. formatting quarter) in the default en-US locale
* are the same as "stand-alone" units, but are different in some languages.
* "Formatting" units are declined according to the rules of the language
* in the context of a date. "Stand-alone" units are always nominative singular.
* In `format` function, they will produce different result:
*
* `format(new Date(2017, 10, 6), 'do LLLL', {locale: cs}) //=> '6. listopad'`
*
* `format(new Date(2017, 10, 6), 'do MMMM', {locale: cs}) //=> '6. listopadu'`
*
* `parse` will try to match both formatting and stand-alone units interchangably.
*
* 2. Any sequence of the identical letters is a pattern, unless it is escaped by
* the single quote characters (see below).
* If the sequence is longer than listed in table:
* - for numerical units (`yyyyyyyy`) `parse` will try to match a number
* as wide as the sequence
* - for text units (`MMMMMMMM`) `parse` will try to match the widest variation of the unit.
* These variations are marked with "2" in the last column of the table.
*
* 3. `QQQQQ` and `qqqqq` could be not strictly numerical in some locales.
* These tokens represent the shortest form of the quarter.
*
* 4. The main difference between `y` and `u` patterns are B.C. years:
*
* | Year | `y` | `u` |
* |------|-----|-----|
* | AC 1 | 1 | 1 |
* | BC 1 | 1 | 0 |
* | BC 2 | 2 | -1 |
*
* Also `yy` will try to guess the century of two digit year by proximity with `referenceDate`:
*
* `parse('50', 'yy', new Date(2018, 0, 1)) //=> Sat Jan 01 2050 00:00:00`
*
* `parse('75', 'yy', new Date(2018, 0, 1)) //=> Wed Jan 01 1975 00:00:00`
*
* while `uu` will just assign the year as is:
*
* `parse('50', 'uu', new Date(2018, 0, 1)) //=> Sat Jan 01 0050 00:00:00`
*
* `parse('75', 'uu', new Date(2018, 0, 1)) //=> Tue Jan 01 0075 00:00:00`
*
* The same difference is true for local and ISO week-numbering years (`Y` and `R`),
* except local week-numbering years are dependent on `options.weekStartsOn`
* and `options.firstWeekContainsDate` (compare [setISOWeekYear]{@link https://date-fns.org/docs/setISOWeekYear}
* and [setWeekYear]{@link https://date-fns.org/docs/setWeekYear}).
*
* 5. These patterns are not in the Unicode Technical Standard #35:
* - `i`: ISO day of week
* - `I`: ISO week of year
* - `R`: ISO week-numbering year
* - `o`: ordinal number modifier
* - `P`: long localized date
* - `p`: long localized time
*
* 6. `YY` and `YYYY` tokens represent week-numbering years but they are often confused with years.
* You should enable `options.useAdditionalWeekYearTokens` to use them. See: https://git.io/fxCyr
*
* 7. `D` and `DD` tokens represent days of the year but they are ofthen confused with days of the month.
* You should enable `options.useAdditionalDayOfYearTokens` to use them. See: https://git.io/fxCyr
*
* 8. `P+` tokens do not have a defined priority since they are merely aliases to other tokens based
* on the given locale.
*
* using `en-US` locale: `P` => `MM/dd/yyyy`
* using `en-US` locale: `p` => `hh:mm a`
* using `pt-BR` locale: `P` => `dd/MM/yyyy`
* using `pt-BR` locale: `p` => `HH:mm`
*
* Values will be assigned to the date in the descending order of its unit's priority.
* Units of an equal priority overwrite each other in the order of appearance.
*
* If no values of higher priority are parsed (e.g. when parsing string 'January 1st' without a year),
* the values will be taken from 3rd argument `referenceDate` which works as a context of parsing.
*
* `referenceDate` must be passed for correct work of the function.
* If you're not sure which `referenceDate` to supply, create a new instance of Date:
* `parse('02/11/2014', 'MM/dd/yyyy', new Date())`
* In this case parsing will be done in the context of the current date.
* If `referenceDate` is `Invalid Date` or a value not convertible to valid `Date`,
* then `Invalid Date` will be returned.
*
* The result may vary by locale.
*
* If `formatString` matches with `dateString` but does not provides tokens, `referenceDate` will be returned.
*
* If parsing failed, `Invalid Date` will be returned.
* Invalid Date is a Date, whose time value is NaN.
* Time value of Date: http://es5.github.io/#x15.9.1.1
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* - Old `parse` was renamed to `toDate`.
* Now `parse` is a new function which parses a string using a provided format.
*
* ```javascript
* // Before v2.0.0
* parse('2016-01-01')
*
* // v2.0.0 onward (toDate no longer accepts a string)
* toDate(1392098430000) // Unix to timestamp
* toDate(new Date(2014, 1, 11, 11, 30, 30)) // Cloning the date
* parse('2016-01-01', 'yyyy-MM-dd', new Date())
* ```
*
* @param {String} dateString - the string to parse
* @param {String} formatString - the string of tokens
* @param {Date|Number} referenceDate - defines values missing from the parsed dateString
* @param {Object} [options] - an object with options.
* @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
* @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
* @param {1|2|3|4|5|6|7} [options.firstWeekContainsDate=1] - the day of January, which is always in the first week of the year
* @param {Boolean} [options.useAdditionalWeekYearTokens=false] - if true, allows usage of the week-numbering year tokens `YY` and `YYYY`;
* see: https://git.io/fxCyr
* @param {Boolean} [options.useAdditionalDayOfYearTokens=false] - if true, allows usage of the day of year tokens `D` and `DD`;
* see: https://git.io/fxCyr
* @returns {Date} the parsed date
* @throws {TypeError} 3 arguments required
* @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
* @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7
* @throws {RangeError} `options.locale` must contain `match` property
* @throws {RangeError} use `yyyy` instead of `YYYY` for formatting years using [format provided] to the input [input provided]; see: https://git.io/fxCyr
* @throws {RangeError} use `yy` instead of `YY` for formatting years using [format provided] to the input [input provided]; see: https://git.io/fxCyr
* @throws {RangeError} use `d` instead of `D` for formatting days of the month using [format provided] to the input [input provided]; see: https://git.io/fxCyr
* @throws {RangeError} use `dd` instead of `DD` for formatting days of the month using [format provided] to the input [input provided]; see: https://git.io/fxCyr
* @throws {RangeError} format string contains an unescaped latin alphabet character
*
* @example
* // Parse 11 February 2014 from middle-endian format:
* var result = parse('02/11/2014', 'MM/dd/yyyy', new Date())
* //=> Tue Feb 11 2014 00:00:00
*
* @example
* // Parse 28th of February in Esperanto locale in the context of 2010 year:
* import eo from 'date-fns/locale/eo'
* var result = parse('28-a de februaro', "do 'de' MMMM", new Date(2010, 0, 1), {
* locale: eo
* })
* //=> Sun Feb 28 2010 00:00:00
*/
function parse(dirtyDateString, dirtyFormatString, dirtyReferenceDate, dirtyOptions) {
requiredArgs(3, arguments);
var dateString = String(dirtyDateString);
var formatString = String(dirtyFormatString);
var options = dirtyOptions || {};
var locale = options.locale || enUS;
if (!locale.match) {
throw new RangeError('locale must contain match property');
}
var localeFirstWeekContainsDate = locale.options && locale.options.firstWeekContainsDate;
var defaultFirstWeekContainsDate = localeFirstWeekContainsDate == null ? 1 : toInteger(localeFirstWeekContainsDate);
var firstWeekContainsDate = options.firstWeekContainsDate == null ? defaultFirstWeekContainsDate : toInteger(options.firstWeekContainsDate); // Test if weekStartsOn is between 1 and 7 _and_ is not NaN
if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {
throw new RangeError('firstWeekContainsDate must be between 1 and 7 inclusively');
}
var localeWeekStartsOn = locale.options && locale.options.weekStartsOn;
var defaultWeekStartsOn = localeWeekStartsOn == null ? 0 : toInteger(localeWeekStartsOn);
var weekStartsOn = options.weekStartsOn == null ? defaultWeekStartsOn : toInteger(options.weekStartsOn); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');
}
if (formatString === '') {
if (dateString === '') {
return toDate(dirtyReferenceDate);
} else {
return new Date(NaN);
}
}
var subFnOptions = {
firstWeekContainsDate: firstWeekContainsDate,
weekStartsOn: weekStartsOn,
locale: locale
}; // If timezone isn't specified, it will be set to the system timezone
var setters = [{
priority: TIMEZONE_UNIT_PRIORITY,
subPriority: -1,
set: dateToSystemTimezone,
index: 0
}];
var i;
var tokens = formatString.match(longFormattingTokensRegExp).map(function (substring) {
var firstCharacter = substring[0];
if (firstCharacter === 'p' || firstCharacter === 'P') {
var longFormatter = longFormatters$3[firstCharacter];
return longFormatter(substring, locale.formatLong, subFnOptions);
}
return substring;
}).join('').match(formattingTokensRegExp);
var usedTokens = [];
for (i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (!options.useAdditionalWeekYearTokens && isProtectedWeekYearToken(token)) {
throwProtectedError(token, formatString, dirtyDateString);
}
if (!options.useAdditionalDayOfYearTokens && isProtectedDayOfYearToken(token)) {
throwProtectedError(token, formatString, dirtyDateString);
}
var firstCharacter = token[0];
var parser = parsers$1[firstCharacter];
if (parser) {
var incompatibleTokens = parser.incompatibleTokens;
if (Array.isArray(incompatibleTokens)) {
var incompatibleToken = void 0;
for (var _i = 0; _i < usedTokens.length; _i++) {
var usedToken = usedTokens[_i].token;
if (incompatibleTokens.indexOf(usedToken) !== -1 || usedToken === firstCharacter) {
incompatibleToken = usedTokens[_i];
break;
}
}
if (incompatibleToken) {
throw new RangeError("The format string mustn't contain `".concat(incompatibleToken.fullToken, "` and `").concat(token, "` at the same time"));
}
} else if (parser.incompatibleTokens === '*' && usedTokens.length) {
throw new RangeError("The format string mustn't contain `".concat(token, "` and any other token at the same time"));
}
usedTokens.push({
token: firstCharacter,
fullToken: token
});
var parseResult = parser.parse(dateString, token, locale.match, subFnOptions);
if (!parseResult) {
return new Date(NaN);
}
setters.push({
priority: parser.priority,
subPriority: parser.subPriority || 0,
set: parser.set,
validate: parser.validate,
value: parseResult.value,
index: setters.length
});
dateString = parseResult.rest;
} else {
if (firstCharacter.match(unescapedLatinCharacterRegExp)) {
throw new RangeError('Format string contains an unescaped latin alphabet character `' + firstCharacter + '`');
} // Replace two single quote characters with one single quote character
if (token === "''") {
token = "'";
} else if (firstCharacter === "'") {
token = cleanEscapedString(token);
} // Cut token from string, or, if string doesn't match the token, return Invalid Date
if (dateString.indexOf(token) === 0) {
dateString = dateString.slice(token.length);
} else {
return new Date(NaN);
}
}
} // Check if the remaining input contains something other than whitespace
if (dateString.length > 0 && notWhitespaceRegExp.test(dateString)) {
return new Date(NaN);
}
var uniquePrioritySetters = setters.map(function (setter) {
return setter.priority;
}).sort(function (a, b) {
return b - a;
}).filter(function (priority, index, array) {
return array.indexOf(priority) === index;
}).map(function (priority) {
return setters.filter(function (setter) {
return setter.priority === priority;
}).sort(function (a, b) {
return b.subPriority - a.subPriority;
});
}).map(function (setterArray) {
return setterArray[0];
});
var date = toDate(dirtyReferenceDate);
if (isNaN(date)) {
return new Date(NaN);
} // Convert the date in system timezone to the same date in UTC+00:00 timezone.
// This ensures that when UTC functions will be implemented, locales will be compatible with them.
// See an issue about UTC functions: https://github.com/date-fns/date-fns/issues/37
var utcDate = subMilliseconds(date, getTimezoneOffsetInMilliseconds(date));
var flags = {};
for (i = 0; i < uniquePrioritySetters.length; i++) {
var setter = uniquePrioritySetters[i];
if (setter.validate && !setter.validate(utcDate, setter.value, subFnOptions)) {
return new Date(NaN);
}
var result = setter.set(utcDate, flags, setter.value, subFnOptions); // Result is tuple (date, flags)
if (result[0]) {
utcDate = result[0];
assign(flags, result[1]); // Result is date
} else {
utcDate = result;
}
}
return utcDate;
}
function dateToSystemTimezone(date, flags) {
if (flags.timestampIsSet) {
return date;
}
var convertedDate = new Date(0);
convertedDate.setFullYear(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
convertedDate.setHours(date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());
return convertedDate;
}
function cleanEscapedString(input) {
return input.match(escapedStringRegExp)[1].replace(doubleQuoteRegExp, "'");
}
/**
* @name setDate
* @category Day Helpers
* @summary Set the day of the month to the given date.
*
* @description
* Set the day of the month to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} dayOfMonth - the day of the month of the new date
* @returns {Date} the new date with the day of the month set
* @throws {TypeError} 2 arguments required
*
* @example
* // Set the 30th day of the month to 1 September 2014:
* var result = setDate(new Date(2014, 8, 1), 30)
* //=> Tue Sep 30 2014 00:00:00
*/
function setDate(dirtyDate, dirtyDayOfMonth) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var dayOfMonth = toInteger(dirtyDayOfMonth);
date.setDate(dayOfMonth);
return date;
}
/**
* @name setHours
* @category Hour Helpers
* @summary Set the hours to the given date.
*
* @description
* Set the hours to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} hours - the hours of the new date
* @returns {Date} the new date with the hours set
* @throws {TypeError} 2 arguments required
*
* @example
* // Set 4 hours to 1 September 2014 11:30:00:
* var result = setHours(new Date(2014, 8, 1, 11, 30), 4)
* //=> Mon Sep 01 2014 04:30:00
*/
function setHours(dirtyDate, dirtyHours) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var hours = toInteger(dirtyHours);
date.setHours(hours);
return date;
}
/**
* @name setMinutes
* @category Minute Helpers
* @summary Set the minutes to the given date.
*
* @description
* Set the minutes to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} minutes - the minutes of the new date
* @returns {Date} the new date with the minutes set
* @throws {TypeError} 2 arguments required
*
* @example
* // Set 45 minutes to 1 September 2014 11:30:40:
* const result = setMinutes(new Date(2014, 8, 1, 11, 30, 40), 45)
* //=> Mon Sep 01 2014 11:45:40
*/
function setMinutes(dirtyDate, dirtyMinutes) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var minutes = toInteger(dirtyMinutes);
date.setMinutes(minutes);
return date;
}
/**
* @name setMonth
* @category Month Helpers
* @summary Set the month to the given date.
*
* @description
* Set the month to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} month - the month of the new date
* @returns {Date} the new date with the month set
* @throws {TypeError} 2 arguments required
*
* @example
* // Set February to 1 September 2014:
* const result = setMonth(new Date(2014, 8, 1), 1)
* //=> Sat Feb 01 2014 00:00:00
*/
function setMonth(dirtyDate, dirtyMonth) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var month = toInteger(dirtyMonth);
var year = date.getFullYear();
var day = date.getDate();
var dateWithDesiredMonth = new Date(0);
dateWithDesiredMonth.setFullYear(year, month, 15);
dateWithDesiredMonth.setHours(0, 0, 0, 0);
var daysInMonth = getDaysInMonth(dateWithDesiredMonth); // Set the last day of the new month
// if the original date was the last day of the longer month
date.setMonth(month, Math.min(day, daysInMonth));
return date;
}
/**
* @name setSeconds
* @category Second Helpers
* @summary Set the seconds to the given date.
*
* @description
* Set the seconds to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} seconds - the seconds of the new date
* @returns {Date} the new date with the seconds set
* @throws {TypeError} 2 arguments required
*
* @example
* // Set 45 seconds to 1 September 2014 11:30:40:
* const result = setSeconds(new Date(2014, 8, 1, 11, 30, 40), 45)
* //=> Mon Sep 01 2014 11:30:45
*/
function setSeconds(dirtyDate, dirtySeconds) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var seconds = toInteger(dirtySeconds);
date.setSeconds(seconds);
return date;
}
/**
* @name setMilliseconds
* @category Millisecond Helpers
* @summary Set the milliseconds to the given date.
*
* @description
* Set the milliseconds to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} milliseconds - the milliseconds of the new date
* @returns {Date} the new date with the milliseconds set
* @throws {TypeError} 2 arguments required
*
* @example
* // Set 300 milliseconds to 1 September 2014 11:30:40.500:
* const result = setMilliseconds(new Date(2014, 8, 1, 11, 30, 40, 500), 300)
* //=> Mon Sep 01 2014 11:30:40.300
*/
function setMilliseconds(dirtyDate, dirtyMilliseconds) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var milliseconds = toInteger(dirtyMilliseconds);
date.setMilliseconds(milliseconds);
return date;
}
/**
* @name setYear
* @category Year Helpers
* @summary Set the year to the given date.
*
* @description
* Set the year to the given date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the date to be changed
* @param {Number} year - the year of the new date
* @returns {Date} the new date with the year set
* @throws {TypeError} 2 arguments required
*
* @example
* // Set year 2013 to 1 September 2014:
* const result = setYear(new Date(2014, 8, 1), 2013)
* //=> Sun Sep 01 2013 00:00:00
*/
function setYear(dirtyDate, dirtyYear) {
requiredArgs(2, arguments);
var date = toDate(dirtyDate);
var year = toInteger(dirtyYear); // Check if date is Invalid Date because Date.prototype.setFullYear ignores the value of Invalid Date
if (isNaN(date.getTime())) {
return new Date(NaN);
}
date.setFullYear(year);
return date;
}
/**
* @name startOfMonth
* @category Month Helpers
* @summary Return the start of a month for the given date.
*
* @description
* Return the start of a month for the given date.
* The result will be in the local timezone.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the original date
* @returns {Date} the start of a month
* @throws {TypeError} 1 argument required
*
* @example
* // The start of a month for 2 September 2014 11:55:00:
* const result = startOfMonth(new Date(2014, 8, 2, 11, 55, 0))
* //=> Mon Sep 01 2014 00:00:00
*/
function startOfMonth(dirtyDate) {
requiredArgs(1, arguments);
var date = toDate(dirtyDate);
date.setDate(1);
date.setHours(0, 0, 0, 0);
return date;
}
/**
* @name startOfYear
* @category Year Helpers
* @summary Return the start of a year for the given date.
*
* @description
* Return the start of a year for the given date.
* The result will be in the local timezone.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {Date|Number} date - the original date
* @returns {Date} the start of a year
* @throws {TypeError} 1 argument required
*
* @example
* // The start of a year for 2 September 2014 11:55:00:
* const result = startOfYear(new Date(2014, 8, 2, 11, 55, 00))
* //=> Wed Jan 01 2014 00:00:00
*/
function startOfYear(dirtyDate) {
requiredArgs(1, arguments);
var cleanDate = toDate(dirtyDate);
var date = new Date(0);
date.setFullYear(cleanDate.getFullYear(), 0, 1);
date.setHours(0, 0, 0, 0);
return date;
}
var MILLISECONDS_IN_HOUR = 3600000;
var MILLISECONDS_IN_MINUTE = 60000;
var DEFAULT_ADDITIONAL_DIGITS = 2;
var patterns = {
dateTimeDelimiter: /[T ]/,
timeZoneDelimiter: /[Z ]/i,
timezone: /([Z+-].*)$/
};
var dateRegex = /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/;
var timeRegex = /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/;
var timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/;
/**
* @name parseISO
* @category Common Helpers
* @summary Parse ISO string
*
* @description
* Parse the given string in ISO 8601 format and return an instance of Date.
*
* Function accepts complete ISO 8601 formats as well as partial implementations.
* ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
*
* If the argument isn't a string, the function cannot parse the string or
* the values are invalid, it returns Invalid Date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* - The previous `parse` implementation was renamed to `parseISO`.
*
* ```javascript
* // Before v2.0.0
* parse('2016-01-01')
*
* // v2.0.0 onward
* parseISO('2016-01-01')
* ```
*
* - `parseISO` now validates separate date and time values in ISO-8601 strings
* and returns `Invalid Date` if the date is invalid.
*
* ```javascript
* parseISO('2018-13-32')
* //=> Invalid Date
* ```
*
* - `parseISO` now doesn't fall back to `new Date` constructor
* if it fails to parse a string argument. Instead, it returns `Invalid Date`.
*
* @param {String} argument - the value to convert
* @param {Object} [options] - an object with options.
* @param {0|1|2} [options.additionalDigits=2] - the additional number of digits in the extended year format
* @returns {Date} the parsed date in the local time zone
* @throws {TypeError} 1 argument required
* @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2
*
* @example
* // Convert string '2014-02-11T11:30:30' to date:
* var result = parseISO('2014-02-11T11:30:30')
* //=> Tue Feb 11 2014 11:30:30
*
* @example
* // Convert string '+02014101' to date,
* // if the additional number of digits in the extended year format is 1:
* var result = parseISO('+02014101', { additionalDigits: 1 })
* //=> Fri Apr 11 2014 00:00:00
*/
function parseISO(argument, dirtyOptions) {
requiredArgs(1, arguments);
var options = dirtyOptions || {};
var additionalDigits = options.additionalDigits == null ? DEFAULT_ADDITIONAL_DIGITS : toInteger(options.additionalDigits);
if (additionalDigits !== 2 && additionalDigits !== 1 && additionalDigits !== 0) {
throw new RangeError('additionalDigits must be 0, 1 or 2');
}
if (!(typeof argument === 'string' || Object.prototype.toString.call(argument) === '[object String]')) {
return new Date(NaN);
}
var dateStrings = splitDateString(argument);
var date;
if (dateStrings.date) {
var parseYearResult = parseYear(dateStrings.date, additionalDigits);
date = parseDate(parseYearResult.restDateString, parseYearResult.year);
}
if (isNaN(date) || !date) {
return new Date(NaN);
}
var timestamp = date.getTime();
var time = 0;
var offset;
if (dateStrings.time) {
time = parseTime(dateStrings.time);
if (isNaN(time) || time === null) {
return new Date(NaN);
}
}
if (dateStrings.timezone) {
offset = parseTimezone(dateStrings.timezone);
if (isNaN(offset)) {
return new Date(NaN);
}
} else {
var dirtyDate = new Date(timestamp + time); // js parsed string assuming it's in UTC timezone
// but we need it to be parsed in our timezone
// so we use utc values to build date in our timezone.
// Year values from 0 to 99 map to the years 1900 to 1999
// so set year explicitly with setFullYear.
var result = new Date(0);
result.setFullYear(dirtyDate.getUTCFullYear(), dirtyDate.getUTCMonth(), dirtyDate.getUTCDate());
result.setHours(dirtyDate.getUTCHours(), dirtyDate.getUTCMinutes(), dirtyDate.getUTCSeconds(), dirtyDate.getUTCMilliseconds());
return result;
}
return new Date(timestamp + time + offset);
}
function splitDateString(dateString) {
var dateStrings = {};
var array = dateString.split(patterns.dateTimeDelimiter);
var timeString; // The regex match should only return at maximum two array elements.
// [date], [time], or [date, time].
if (array.length > 2) {
return dateStrings;
}
if (/:/.test(array[0])) {
dateStrings.date = null;
timeString = array[0];
} else {
dateStrings.date = array[0];
timeString = array[1];
if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];
timeString = dateString.substr(dateStrings.date.length, dateString.length);
}
}
if (timeString) {
var token = patterns.timezone.exec(timeString);
if (token) {
dateStrings.time = timeString.replace(token[1], '');
dateStrings.timezone = token[1];
} else {
dateStrings.time = timeString;
}
}
return dateStrings;
}
function parseYear(dateString, additionalDigits) {
var regex = new RegExp('^(?:(\\d{4}|[+-]\\d{' + (4 + additionalDigits) + '})|(\\d{2}|[+-]\\d{' + (2 + additionalDigits) + '})$)');
var captures = dateString.match(regex); // Invalid ISO-formatted year
if (!captures) return {
year: null
};
var year = captures[1] && parseInt(captures[1]);
var century = captures[2] && parseInt(captures[2]);
return {
year: century == null ? year : century * 100,
restDateString: dateString.slice((captures[1] || captures[2]).length)
};
}
function parseDate(dateString, year) {
// Invalid ISO-formatted year
if (year === null) return null;
var captures = dateString.match(dateRegex); // Invalid ISO-formatted string
if (!captures) return null;
var isWeekDate = !!captures[4];
var dayOfYear = parseDateUnit(captures[1]);
var month = parseDateUnit(captures[2]) - 1;
var day = parseDateUnit(captures[3]);
var week = parseDateUnit(captures[4]);
var dayOfWeek = parseDateUnit(captures[5]) - 1;
if (isWeekDate) {
if (!validateWeekDate(year, week, dayOfWeek)) {
return new Date(NaN);
}
return dayOfISOWeekYear(year, week, dayOfWeek);
} else {
var date = new Date(0);
if (!validateDate$1(year, month, day) || !validateDayOfYearDate(year, dayOfYear)) {
return new Date(NaN);
}
date.setUTCFullYear(year, month, Math.max(dayOfYear, day));
return date;
}
}
function parseDateUnit(value) {
return value ? parseInt(value) : 1;
}
function parseTime(timeString) {
var captures = timeString.match(timeRegex);
if (!captures) return null; // Invalid ISO-formatted time
var hours = parseTimeUnit(captures[1]);
var minutes = parseTimeUnit(captures[2]);
var seconds = parseTimeUnit(captures[3]);
if (!validateTime(hours, minutes, seconds)) {
return NaN;
}
return hours * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE + seconds * 1000;
}
function parseTimeUnit(value) {
return value && parseFloat(value.replace(',', '.')) || 0;
}
function parseTimezone(timezoneString) {
if (timezoneString === 'Z') return 0;
var captures = timezoneString.match(timezoneRegex);
if (!captures) return 0;
var sign = captures[1] === '+' ? -1 : 1;
var hours = parseInt(captures[2]);
var minutes = captures[3] && parseInt(captures[3]) || 0;
if (!validateTimezone(hours, minutes)) {
return NaN;
}
return sign * (hours * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE);
}
function dayOfISOWeekYear(isoWeekYear, week, day) {
var date = new Date(0);
date.setUTCFullYear(isoWeekYear, 0, 4);
var fourthOfJanuaryDay = date.getUTCDay() || 7;
var diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;
date.setUTCDate(date.getUTCDate() + diff);
return date;
} // Validation functions
// February is null to handle the leap year (using ||)
var daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
function isLeapYearIndex(year) {
return year % 400 === 0 || year % 4 === 0 && year % 100;
}
function validateDate$1(year, month, date) {
return month >= 0 && month <= 11 && date >= 1 && date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28));
}
function validateDayOfYearDate(year, dayOfYear) {
return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);
}
function validateWeekDate(_year, week, day) {
return week >= 1 && week <= 53 && day >= 0 && day <= 6;
}
function validateTime(hours, minutes, seconds) {
if (hours === 24) {
return minutes === 0 && seconds === 0;
}
return seconds >= 0 && seconds < 60 && minutes >= 0 && minutes < 60 && hours >= 0 && hours < 25;
}
function validateTimezone(_hours, minutes) {
return minutes >= 0 && minutes <= 59;
}
/**
* @name formatISO
* @category Common Helpers
* @summary Format the date according to the ISO 8601 standard (http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a003169814.htm).
*
* @description
* Return the formatted date string in ISO 8601 format. Options may be passed to control the parts and notations of the date.
*
* @param {Date|Number} date - the original date
* @param {Object} [options] - an object with options.
* @param {'extended'|'basic'} [options.format='extended'] - if 'basic', hide delimiters between date and time values.
* @param {'complete'|'date'|'time'} [options.representation='complete'] - format date, time with time zone, or both.
* @returns {String} the formatted date string
* @throws {TypeError} 1 argument required
* @throws {RangeError} `date` must not be Invalid Date
* @throws {RangeError} `options.format` must be 'extended' or 'basic'
* @throws {RangeError} `options.represenation` must be 'date', 'time' or 'complete'
*
* @example
* // Represent 18 September 2019 in ISO 8601 format (UTC):
* const result = formatISO(new Date(2019, 8, 18, 19, 0, 52))
* //=> '2019-09-18T19:00:52Z'
*
* @example
* // Represent 18 September 2019 in ISO 8601, short format (UTC):
* const result = formatISO(new Date(2019, 8, 18, 19, 0, 52), { format: 'basic' })
* //=> '20190918T190052'
*
* @example
* // Represent 18 September 2019 in ISO 8601 format, date only:
* const result = formatISO(new Date(2019, 8, 18, 19, 0, 52), { representation: 'date' })
* //=> '2019-09-18'
*
* @example
* // Represent 18 September 2019 in ISO 8601 format, time only (UTC):
* const result = formatISO(new Date(2019, 8, 18, 19, 0, 52), { representation: 'time' })
* //=> '19:00:52Z'
*/
function formatISO(dirtyDate, dirtyOptions) {
if (arguments.length < 1) {
throw new TypeError("1 argument required, but only ".concat(arguments.length, " present"));
}
var originalDate = toDate(dirtyDate);
if (!isValid(originalDate)) {
throw new RangeError('Invalid time value');
}
var options = dirtyOptions || {};
var format = options.format == null ? 'extended' : String(options.format);
var representation = options.representation == null ? 'complete' : String(options.representation);
if (format !== 'extended' && format !== 'basic') {
throw new RangeError("format must be 'extended' or 'basic'");
}
if (representation !== 'date' && representation !== 'time' && representation !== 'complete') {
throw new RangeError("representation must be 'date', 'time', or 'complete'");
}
var result = '';
var tzOffset = '';
var dateDelimiter = format === 'extended' ? '-' : '';
var timeDelimiter = format === 'extended' ? ':' : ''; // Representation is either 'date' or 'complete'
if (representation !== 'time') {
var day = addLeadingZeros(originalDate.getDate(), 2);
var month = addLeadingZeros(originalDate.getMonth() + 1, 2);
var year = addLeadingZeros(originalDate.getFullYear(), 4); // yyyyMMdd or yyyy-MM-dd.
result = "".concat(year).concat(dateDelimiter).concat(month).concat(dateDelimiter).concat(day);
} // Representation is either 'time' or 'complete'
if (representation !== 'date') {
// Add the timezone.
var offset = originalDate.getTimezoneOffset();
if (offset !== 0) {
var absoluteOffset = Math.abs(offset);
var hourOffset = addLeadingZeros(Math.floor(absoluteOffset / 60), 2);
var minuteOffset = addLeadingZeros(absoluteOffset % 60, 2); // If less than 0, the sign is +, because it is ahead of time.
var sign = offset < 0 ? '+' : '-';
tzOffset = "".concat(sign).concat(hourOffset, ":").concat(minuteOffset);
} else {
tzOffset = 'Z';
}
var hour = addLeadingZeros(originalDate.getHours(), 2);
var minute = addLeadingZeros(originalDate.getMinutes(), 2);
var second = addLeadingZeros(originalDate.getSeconds(), 2); // If there's also date, separate it with time with 'T'
var separator = result === '' ? '' : 'T'; // Creates a time string consisting of hour, minute, and second, separated by delimiters, if defined.
var time = [hour, minute, second].join(timeDelimiter); // HHmmss or HH:mm:ss.
result = "".concat(result).concat(separator).concat(time).concat(tzOffset);
}
return result;
}
/**
* @name isWithinInterval
* @category Interval Helpers
* @summary Is the given date within the interval?
*
* @description
* Is the given date within the interval? (Including start and end.)
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* - The function was renamed from `isWithinRange` to `isWithinInterval`.
* This change was made to mirror the use of the word "interval" in standard ISO 8601:2004 terminology:
*
* ```
* 2.1.3
* time interval
* part of the time axis limited by two instants
* ```
*
* Also, this function now accepts an object with `start` and `end` properties
* instead of two arguments as an interval.
* This function now throws `RangeError` if the start of the interval is after its end
* or if any date in the interval is `Invalid Date`.
*
* ```javascript
* // Before v2.0.0
*
* isWithinRange(
* new Date(2014, 0, 3),
* new Date(2014, 0, 1), new Date(2014, 0, 7)
* )
*
* // v2.0.0 onward
*
* isWithinInterval(
* new Date(2014, 0, 3),
* { start: new Date(2014, 0, 1), end: new Date(2014, 0, 7) }
* )
* ```
*
* @param {Date|Number} date - the date to check
* @param {Interval} interval - the interval to check
* @returns {Boolean} the date is within the interval
* @throws {TypeError} 2 arguments required
* @throws {RangeError} The start of an interval cannot be after its end
* @throws {RangeError} Date in interval cannot be `Invalid Date`
*
* @example
* // For the date within the interval:
* isWithinInterval(new Date(2014, 0, 3), {
* start: new Date(2014, 0, 1),
* end: new Date(2014, 0, 7)
* })
* //=> true
*
* @example
* // For the date outside of the interval:
* isWithinInterval(new Date(2014, 0, 10), {
* start: new Date(2014, 0, 1),
* end: new Date(2014, 0, 7)
* })
* //=> false
*
* @example
* // For date equal to interval start:
* isWithinInterval(date, { start, end: date }) // => true
*
* @example
* // For date equal to interval end:
* isWithinInterval(date, { start: date, end }) // => true
*/
function isWithinInterval(dirtyDate, interval) {
requiredArgs(2, arguments);
var time = toDate(dirtyDate).getTime();
var startTime = toDate(interval.start).getTime();
var endTime = toDate(interval.end).getTime(); // Throw an exception if start date is after end date or if any date is `Invalid Date`
if (!(startTime <= endTime)) {
throw new RangeError('Invalid interval');
}
return time >= startTime && time <= endTime;
}
var longFormatters$1 = {exports: {}};
longFormatters$1.exports;
(function (module, exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
function dateLongFormatter(pattern, formatLong) {
switch (pattern) {
case 'P':
return formatLong.date({
width: 'short'
});
case 'PP':
return formatLong.date({
width: 'medium'
});
case 'PPP':
return formatLong.date({
width: 'long'
});
case 'PPPP':
default:
return formatLong.date({
width: 'full'
});
}
}
function timeLongFormatter(pattern, formatLong) {
switch (pattern) {
case 'p':
return formatLong.time({
width: 'short'
});
case 'pp':
return formatLong.time({
width: 'medium'
});
case 'ppp':
return formatLong.time({
width: 'long'
});
case 'pppp':
default:
return formatLong.time({
width: 'full'
});
}
}
function dateTimeLongFormatter(pattern, formatLong) {
var matchResult = pattern.match(/(P+)(p+)?/);
var datePattern = matchResult[1];
var timePattern = matchResult[2];
if (!timePattern) {
return dateLongFormatter(pattern, formatLong);
}
var dateTimeFormat;
switch (datePattern) {
case 'P':
dateTimeFormat = formatLong.dateTime({
width: 'short'
});
break;
case 'PP':
dateTimeFormat = formatLong.dateTime({
width: 'medium'
});
break;
case 'PPP':
dateTimeFormat = formatLong.dateTime({
width: 'long'
});
break;
case 'PPPP':
default:
dateTimeFormat = formatLong.dateTime({
width: 'full'
});
break;
}
return dateTimeFormat.replace('{{date}}', dateLongFormatter(datePattern, formatLong)).replace('{{time}}', timeLongFormatter(timePattern, formatLong));
}
var longFormatters = {
p: timeLongFormatter,
P: dateTimeLongFormatter
};
var _default = longFormatters;
exports.default = _default;
module.exports = exports.default;
} (longFormatters$1, longFormatters$1.exports));
var longFormattersExports = longFormatters$1.exports;
var longFormatters = /*@__PURE__*/getDefaultExportFromCjs(longFormattersExports);
function _extends() {
_extends = Object.assign ? Object.assign.bind() : 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);
}
/* eslint-disable class-methods-use-this */
const formatTokenMap = {
// Year
y: {
sectionType: 'year',
contentType: 'digit',
maxLength: 4
},
yy: 'year',
yyy: {
sectionType: 'year',
contentType: 'digit',
maxLength: 4
},
yyyy: 'year',
// Month
M: {
sectionType: 'month',
contentType: 'digit',
maxLength: 2
},
MM: 'month',
MMMM: {
sectionType: 'month',
contentType: 'letter'
},
MMM: {
sectionType: 'month',
contentType: 'letter'
},
L: {
sectionType: 'month',
contentType: 'digit',
maxLength: 2
},
LL: 'month',
LLL: {
sectionType: 'month',
contentType: 'letter'
},
LLLL: {
sectionType: 'month',
contentType: 'letter'
},
// Day of the month
d: {
sectionType: 'day',
contentType: 'digit',
maxLength: 2
},
dd: 'day',
do: {
sectionType: 'day',
contentType: 'digit-with-letter'
},
// Day of the week
E: {
sectionType: 'weekDay',
contentType: 'letter'
},
EE: {
sectionType: 'weekDay',
contentType: 'letter'
},
EEE: {
sectionType: 'weekDay',
contentType: 'letter'
},
EEEE: {
sectionType: 'weekDay',
contentType: 'letter'
},
EEEEE: {
sectionType: 'weekDay',
contentType: 'letter'
},
i: {
sectionType: 'weekDay',
contentType: 'digit',
maxLength: 1
},
ii: 'weekDay',
iii: {
sectionType: 'weekDay',
contentType: 'letter'
},
iiii: {
sectionType: 'weekDay',
contentType: 'letter'
},
e: {
sectionType: 'weekDay',
contentType: 'digit',
maxLength: 1
},
ee: 'weekDay',
eee: {
sectionType: 'weekDay',
contentType: 'letter'
},
eeee: {
sectionType: 'weekDay',
contentType: 'letter'
},
eeeee: {
sectionType: 'weekDay',
contentType: 'letter'
},
eeeeee: {
sectionType: 'weekDay',
contentType: 'letter'
},
c: {
sectionType: 'weekDay',
contentType: 'digit',
maxLength: 1
},
cc: 'weekDay',
ccc: {
sectionType: 'weekDay',
contentType: 'letter'
},
cccc: {
sectionType: 'weekDay',
contentType: 'letter'
},
ccccc: {
sectionType: 'weekDay',
contentType: 'letter'
},
cccccc: {
sectionType: 'weekDay',
contentType: 'letter'
},
// Meridiem
a: 'meridiem',
aa: 'meridiem',
aaa: 'meridiem',
// Hours
H: {
sectionType: 'hours',
contentType: 'digit',
maxLength: 2
},
HH: 'hours',
h: {
sectionType: 'hours',
contentType: 'digit',
maxLength: 2
},
hh: 'hours',
// Minutes
m: {
sectionType: 'minutes',
contentType: 'digit',
maxLength: 2
},
mm: 'minutes',
// Seconds
s: {
sectionType: 'seconds',
contentType: 'digit',
maxLength: 2
},
ss: 'seconds'
};
const defaultFormats = {
year: 'yyyy',
month: 'LLLL',
monthShort: 'MMM',
dayOfMonth: 'd',
weekday: 'EEEE',
weekdayShort: 'EEEEEE',
hours24h: 'HH',
hours12h: 'hh',
meridiem: 'aa',
minutes: 'mm',
seconds: 'ss',
fullDate: 'PP',
fullDateWithWeekday: 'PPPP',
keyboardDate: 'P',
shortDate: 'MMM d',
normalDate: 'd MMMM',
normalDateWithWeekday: 'EEE, MMM d',
monthAndYear: 'LLLL yyyy',
monthAndDate: 'MMMM d',
fullTime: 'p',
fullTime12h: 'hh:mm aa',
fullTime24h: 'HH:mm',
fullDateTime: 'PP p',
fullDateTime12h: 'PP hh:mm aa',
fullDateTime24h: 'PP HH:mm',
keyboardDateTime: 'P p',
keyboardDateTime12h: 'P hh:mm aa',
keyboardDateTime24h: 'P HH:mm'
};
/**
* Based on `@date-io/date-fns`
*
* MIT License
*
* Copyright (c) 2017 Dmitriy Kovalenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
class AdapterDateFnsBase {
constructor(props) {
this.isMUIAdapter = true;
this.isTimezoneCompatible = false;
this.lib = 'date-fns';
this.locale = void 0;
this.formats = void 0;
this.formatTokenMap = formatTokenMap;
this.escapedCharacters = {
start: "'",
end: "'"
};
this.longFormatters = void 0;
this.date = value => {
if (typeof value === 'undefined') {
return new Date();
}
if (value === null) {
return null;
}
return new Date(value);
};
this.dateWithTimezone = value => {
return this.date(value);
};
this.getTimezone = () => {
return 'default';
};
this.setTimezone = value => {
return value;
};
this.toJsDate = value => {
return value;
};
this.getCurrentLocaleCode = () => {
var _this$locale;
return ((_this$locale = this.locale) == null ? void 0 : _this$locale.code) || 'en-US';
};
// Note: date-fns input types are more lenient than this adapter, so we need to expose our more
// strict signature and delegate to the more lenient signature. Otherwise, we have downstream type errors upon usage.
this.is12HourCycleInCurrentLocale = () => {
if (this.locale) {
return /a/.test(this.locale.formatLong.time({
width: 'short'
}));
}
// By default, date-fns is using en-US locale with am/pm enabled
return true;
};
this.expandFormat = format => {
const longFormatRegexp = /P+p+|P+|p+|''|'(''|[^'])+('|$)|./g;
// @see https://github.com/date-fns/date-fns/blob/master/src/format/index.js#L31
return format.match(longFormatRegexp).map(token => {
const firstCharacter = token[0];
if (firstCharacter === 'p' || firstCharacter === 'P') {
const longFormatter = this.longFormatters[firstCharacter];
return longFormatter(token, this.locale.formatLong);
}
return token;
}).join('');
};
this.getFormatHelperText = format => {
return this.expandFormat(format).replace(/(aaa|aa|a)/g, '(a|p)m').toLocaleLowerCase();
};
this.isNull = value => {
return value === null;
};
this.formatNumber = numberToFormat => {
return numberToFormat;
};
this.getMeridiemText = ampm => {
return ampm === 'am' ? 'AM' : 'PM';
};
const {
locale,
formats,
longFormatters
} = props;
this.locale = locale;
this.formats = _extends({}, defaultFormats, formats);
this.longFormatters = longFormatters;
}
}
/* eslint-disable class-methods-use-this */
/**
* Based on `@date-io/date-fns`
*
* MIT License
*
* Copyright (c) 2017 Dmitriy Kovalenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
class AdapterDateFns extends AdapterDateFnsBase {
constructor({
locale,
formats
} = {}) {
if (typeof addDays !== 'function') {
throw new Error(['MUI: The `date-fns` package v3.x is not compatible with this adapter.', 'Please, install v2.x of the package or use the `AdapterDateFnsV3` instead.'].join('\n'));
}
super({
locale: locale != null ? locale : enUS,
formats,
longFormatters
});
this.parseISO = isoString => {
return parseISO(isoString);
};
this.toISO = value => {
return formatISO(value, {
format: 'extended'
});
};
this.parse = (value, format) => {
if (value === '') {
return null;
}
return parse(value, format, new Date(), {
locale: this.locale
});
};
this.isValid = value => {
return isValid(this.date(value));
};
this.format = (value, formatKey) => {
return this.formatByString(value, this.formats[formatKey]);
};
this.formatByString = (value, formatString) => {
return format(value, formatString, {
locale: this.locale
});
};
this.getDiff = (value, comparing, unit) => {
switch (unit) {
case 'years':
return differenceInYears(value, this.date(comparing));
case 'quarters':
return differenceInQuarters(value, this.date(comparing));
case 'months':
return differenceInMonths(value, this.date(comparing));
case 'weeks':
return differenceInWeeks(value, this.date(comparing));
case 'days':
return differenceInDays(value, this.date(comparing));
case 'hours':
return differenceInHours(value, this.date(comparing));
case 'minutes':
return differenceInMinutes(value, this.date(comparing));
case 'seconds':
return differenceInSeconds(value, this.date(comparing));
default:
{
return differenceInMilliseconds(value, this.date(comparing));
}
}
};
this.isEqual = (value, comparing) => {
if (value === null && comparing === null) {
return true;
}
return isEqual(value, comparing);
};
this.isSameYear = (value, comparing) => {
return isSameYear(value, comparing);
};
this.isSameMonth = (value, comparing) => {
return isSameMonth(value, comparing);
};
this.isSameDay = (value, comparing) => {
return isSameDay(value, comparing);
};
this.isSameHour = (value, comparing) => {
return isSameHour(value, comparing);
};
this.isAfter = (value, comparing) => {
return isAfter(value, comparing);
};
this.isAfterYear = (value, comparing) => {
return isAfter(value, endOfYear(comparing));
};
this.isAfterDay = (value, comparing) => {
return isAfter(value, endOfDay(comparing));
};
this.isBefore = (value, comparing) => {
return isBefore(value, comparing);
};
this.isBeforeYear = (value, comparing) => {
return isBefore(value, startOfYear(comparing));
};
this.isBeforeDay = (value, comparing) => {
return isBefore(value, startOfDay(comparing));
};
this.isWithinRange = (value, [start, end]) => {
return isWithinInterval(value, {
start,
end
});
};
this.startOfYear = value => {
return startOfYear(value);
};
this.startOfMonth = value => {
return startOfMonth(value);
};
this.startOfWeek = value => {
return startOfWeek(value, {
locale: this.locale
});
};
this.startOfDay = value => {
return startOfDay(value);
};
this.endOfYear = value => {
return endOfYear(value);
};
this.endOfMonth = value => {
return endOfMonth(value);
};
this.endOfWeek = value => {
return endOfWeek(value, {
locale: this.locale
});
};
this.endOfDay = value => {
return endOfDay(value);
};
this.addYears = (value, amount) => {
return addYears(value, amount);
};
this.addMonths = (value, amount) => {
return addMonths(value, amount);
};
this.addWeeks = (value, amount) => {
return addWeeks(value, amount);
};
this.addDays = (value, amount) => {
return addDays(value, amount);
};
this.addHours = (value, amount) => {
return addHours(value, amount);
};
this.addMinutes = (value, amount) => {
return addMinutes(value, amount);
};
this.addSeconds = (value, amount) => {
return addSeconds(value, amount);
};
this.getYear = value => {
return getYear(value);
};
this.getMonth = value => {
return getMonth(value);
};
this.getDate = value => {
return getDate(value);
};
this.getHours = value => {
return getHours(value);
};
this.getMinutes = value => {
return getMinutes(value);
};
this.getSeconds = value => {
return getSeconds(value);
};
this.getMilliseconds = value => {
return getMilliseconds(value);
};
this.setYear = (value, year) => {
return setYear(value, year);
};
this.setMonth = (value, month) => {
return setMonth(value, month);
};
this.setDate = (value, date) => {
return setDate(value, date);
};
this.setHours = (value, hours) => {
return setHours(value, hours);
};
this.setMinutes = (value, minutes) => {
return setMinutes(value, minutes);
};
this.setSeconds = (value, seconds) => {
return setSeconds(value, seconds);
};
this.setMilliseconds = (value, milliseconds) => {
return setMilliseconds(value, milliseconds);
};
this.getDaysInMonth = value => {
return getDaysInMonth(value);
};
this.getNextMonth = value => {
return addMonths(value, 1);
};
this.getPreviousMonth = value => {
return addMonths(value, -1);
};
this.getMonthArray = value => {
const firstMonth = startOfYear(value);
const monthArray = [firstMonth];
while (monthArray.length < 12) {
const prevMonth = monthArray[monthArray.length - 1];
monthArray.push(this.getNextMonth(prevMonth));
}
return monthArray;
};
this.mergeDateAndTime = (dateParam, timeParam) => {
return this.setSeconds(this.setMinutes(this.setHours(dateParam, this.getHours(timeParam)), this.getMinutes(timeParam)), this.getSeconds(timeParam));
};
this.getWeekdays = () => {
const now = new Date();
return eachDayOfInterval({
start: startOfWeek(now, {
locale: this.locale
}),
end: endOfWeek(now, {
locale: this.locale
})
}).map(day => this.formatByString(day, 'EEEEEE'));
};
this.getWeekArray = value => {
const start = startOfWeek(startOfMonth(value), {
locale: this.locale
});
const end = endOfWeek(endOfMonth(value), {
locale: this.locale
});
let count = 0;
let current = start;
const nestedWeeks = [];
while (isBefore(current, end)) {
const weekNumber = Math.floor(count / 7);
nestedWeeks[weekNumber] = nestedWeeks[weekNumber] || [];
nestedWeeks[weekNumber].push(current);
current = addDays(current, 1);
count += 1;
}
return nestedWeeks;
};
this.getWeekNumber = value => {
return getWeek(value, {
locale: this.locale
});
};
this.getYearRange = (start, end) => {
const startDate = startOfYear(start);
const endDate = endOfYear(end);
const years = [];
let current = startDate;
while (isBefore(current, endDate)) {
years.push(current);
current = addYears(current, 1);
}
return years;
};
}
}
function _objectWithoutPropertiesLoose$1(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;
}
function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
// https://github.com/sindresorhus/is-plain-obj/blob/main/index.js
function isPlainObject$1(item) {
if (typeof item !== 'object' || item === null) {
return false;
}
const prototype = Object.getPrototypeOf(item);
return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in item) && !(Symbol.iterator in item);
}
function deepClone(source) {
if (!isPlainObject$1(source)) {
return source;
}
const output = {};
Object.keys(source).forEach(key => {
output[key] = deepClone(source[key]);
});
return output;
}
function deepmerge(target, source, options = {
clone: true
}) {
const output = options.clone ? _extends({}, target) : target;
if (isPlainObject$1(target) && isPlainObject$1(source)) {
Object.keys(source).forEach(key => {
// Avoid prototype pollution
if (key === '__proto__') {
return;
}
if (isPlainObject$1(source[key]) && key in target && isPlainObject$1(target[key])) {
// Since `output` is a clone of `target` and we have narrowed `target` in this block we can cast to the same type.
output[key] = deepmerge(target[key], source[key], options);
} else if (options.clone) {
output[key] = isPlainObject$1(source[key]) ? deepClone(source[key]) : source[key];
} else {
output[key] = source[key];
}
});
}
return output;
}
/**
* WARNING: Don't import this directly.
* Use `MuiError` from `@mui/internal-babel-macros/MuiError.macro` instead.
* @param {number} code
*/
function formatMuiErrorMessage(code) {
// Apply babel-plugin-transform-template-literals in loose mode
// loose mode is safe if we're concatenating primitives
// see https://babeljs.io/docs/en/babel-plugin-transform-template-literals#loose
/* eslint-disable prefer-template */
let url = 'https://mui.com/production-error/?code=' + code;
for (let i = 1; i < arguments.length; i += 1) {
// rest params over-transpile for this case
// eslint-disable-next-line prefer-rest-params
url += '&args[]=' + encodeURIComponent(arguments[i]);
}
return 'Minified MUI error #' + code + '; visit ' + url + ' for the full message.';
/* eslint-enable prefer-template */
}
var reactIs = {exports: {}};
var reactIs_production_min = {};
/**
* @license React
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var hasRequiredReactIs_production_min;
function requireReactIs_production_min () {
if (hasRequiredReactIs_production_min) return reactIs_production_min;
hasRequiredReactIs_production_min = 1;
var b=Symbol.for("react.element"),c=Symbol.for("react.portal"),d=Symbol.for("react.fragment"),e=Symbol.for("react.strict_mode"),f=Symbol.for("react.profiler"),g=Symbol.for("react.provider"),h=Symbol.for("react.context"),k=Symbol.for("react.server_context"),l=Symbol.for("react.forward_ref"),m=Symbol.for("react.suspense"),n=Symbol.for("react.suspense_list"),p=Symbol.for("react.memo"),q=Symbol.for("react.lazy"),t=Symbol.for("react.offscreen"),u;u=Symbol.for("react.module.reference");
function v(a){if("object"===typeof a&&null!==a){var r=a.$$typeof;switch(r){case b:switch(a=a.type,a){case d:case f:case e:case m:case n:return a;default:switch(a=a&&a.$$typeof,a){case k:case h:case l:case q:case p:case g:return a;default:return r}}case c:return r}}}reactIs_production_min.ContextConsumer=h;reactIs_production_min.ContextProvider=g;reactIs_production_min.Element=b;reactIs_production_min.ForwardRef=l;reactIs_production_min.Fragment=d;reactIs_production_min.Lazy=q;reactIs_production_min.Memo=p;reactIs_production_min.Portal=c;reactIs_production_min.Profiler=f;reactIs_production_min.StrictMode=e;reactIs_production_min.Suspense=m;
reactIs_production_min.SuspenseList=n;reactIs_production_min.isAsyncMode=function(){return !1};reactIs_production_min.isConcurrentMode=function(){return !1};reactIs_production_min.isContextConsumer=function(a){return v(a)===h};reactIs_production_min.isContextProvider=function(a){return v(a)===g};reactIs_production_min.isElement=function(a){return "object"===typeof a&&null!==a&&a.$$typeof===b};reactIs_production_min.isForwardRef=function(a){return v(a)===l};reactIs_production_min.isFragment=function(a){return v(a)===d};reactIs_production_min.isLazy=function(a){return v(a)===q};reactIs_production_min.isMemo=function(a){return v(a)===p};
reactIs_production_min.isPortal=function(a){return v(a)===c};reactIs_production_min.isProfiler=function(a){return v(a)===f};reactIs_production_min.isStrictMode=function(a){return v(a)===e};reactIs_production_min.isSuspense=function(a){return v(a)===m};reactIs_production_min.isSuspenseList=function(a){return v(a)===n};
reactIs_production_min.isValidElementType=function(a){return "string"===typeof a||"function"===typeof a||a===d||a===f||a===e||a===m||a===n||a===t||"object"===typeof a&&null!==a&&(a.$$typeof===q||a.$$typeof===p||a.$$typeof===g||a.$$typeof===h||a.$$typeof===l||a.$$typeof===u||void 0!==a.getModuleId)?!0:!1};reactIs_production_min.typeOf=v;
return reactIs_production_min;
}
var reactIs_development = {};
/**
* @license React
* react-is.development.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var hasRequiredReactIs_development;
function requireReactIs_development () {
if (hasRequiredReactIs_development) return reactIs_development;
hasRequiredReactIs_development = 1;
if (process.env.NODE_ENV !== "production") {
(function() {
// ATTENTION
// When adding new symbols to this file,
// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
// The Symbol used to tag the ReactElement-like types.
var REACT_ELEMENT_TYPE = Symbol.for('react.element');
var REACT_PORTAL_TYPE = Symbol.for('react.portal');
var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');
var REACT_PROFILER_TYPE = Symbol.for('react.profiler');
var REACT_PROVIDER_TYPE = Symbol.for('react.provider');
var REACT_CONTEXT_TYPE = Symbol.for('react.context');
var REACT_SERVER_CONTEXT_TYPE = Symbol.for('react.server_context');
var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
var REACT_MEMO_TYPE = Symbol.for('react.memo');
var REACT_LAZY_TYPE = Symbol.for('react.lazy');
var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');
// -----------------------------------------------------------------------------
var enableScopeAPI = false; // Experimental Create Event Handle API.
var enableCacheElement = false;
var enableTransitionTracing = false; // No known bugs, but needs performance testing
var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber
// stuff. Intended to enable React core members to more easily debug scheduling
// issues in DEV builds.
var enableDebugTracing = false; // Track which Fiber(s) schedule render work.
var REACT_MODULE_REFERENCE;
{
REACT_MODULE_REFERENCE = Symbol.for('react.module.reference');
}
function isValidElementType(type) {
if (typeof type === 'string' || typeof type === 'function') {
return true;
} // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).
if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden || type === REACT_OFFSCREEN_TYPE || enableScopeAPI || enableCacheElement || enableTransitionTracing ) {
return true;
}
if (typeof type === 'object' && type !== null) {
if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object
// types supported by any Flight configuration anywhere since
// we don't know which Flight build this will end up being used
// with.
type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {
return true;
}
}
return false;
}
function typeOf(object) {
if (typeof object === 'object' && object !== null) {
var $$typeof = object.$$typeof;
switch ($$typeof) {
case REACT_ELEMENT_TYPE:
var type = object.type;
switch (type) {
case REACT_FRAGMENT_TYPE:
case REACT_PROFILER_TYPE:
case REACT_STRICT_MODE_TYPE:
case REACT_SUSPENSE_TYPE:
case REACT_SUSPENSE_LIST_TYPE:
return type;
default:
var $$typeofType = type && type.$$typeof;
switch ($$typeofType) {
case REACT_SERVER_CONTEXT_TYPE:
case REACT_CONTEXT_TYPE:
case REACT_FORWARD_REF_TYPE:
case REACT_LAZY_TYPE:
case REACT_MEMO_TYPE:
case REACT_PROVIDER_TYPE:
return $$typeofType;
default:
return $$typeof;
}
}
case REACT_PORTAL_TYPE:
return $$typeof;
}
}
return undefined;
}
var ContextConsumer = REACT_CONTEXT_TYPE;
var ContextProvider = REACT_PROVIDER_TYPE;
var Element = REACT_ELEMENT_TYPE;
var ForwardRef = REACT_FORWARD_REF_TYPE;
var Fragment = REACT_FRAGMENT_TYPE;
var Lazy = REACT_LAZY_TYPE;
var Memo = REACT_MEMO_TYPE;
var Portal = REACT_PORTAL_TYPE;
var Profiler = REACT_PROFILER_TYPE;
var StrictMode = REACT_STRICT_MODE_TYPE;
var Suspense = REACT_SUSPENSE_TYPE;
var SuspenseList = REACT_SUSPENSE_LIST_TYPE;
var hasWarnedAboutDeprecatedIsAsyncMode = false;
var hasWarnedAboutDeprecatedIsConcurrentMode = false; // AsyncMode should be deprecated
function isAsyncMode(object) {
{
if (!hasWarnedAboutDeprecatedIsAsyncMode) {
hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint
console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 18+.');
}
}
return false;
}
function isConcurrentMode(object) {
{
if (!hasWarnedAboutDeprecatedIsConcurrentMode) {
hasWarnedAboutDeprecatedIsConcurrentMode = true; // Using console['warn'] to evade Babel and ESLint
console['warn']('The ReactIs.isConcurrentMode() alias has been deprecated, ' + 'and will be removed in React 18+.');
}
}
return false;
}
function isContextConsumer(object) {
return typeOf(object) === REACT_CONTEXT_TYPE;
}
function isContextProvider(object) {
return typeOf(object) === REACT_PROVIDER_TYPE;
}
function isElement(object) {
return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
}
function isForwardRef(object) {
return typeOf(object) === REACT_FORWARD_REF_TYPE;
}
function isFragment(object) {
return typeOf(object) === REACT_FRAGMENT_TYPE;
}
function isLazy(object) {
return typeOf(object) === REACT_LAZY_TYPE;
}
function isMemo(object) {
return typeOf(object) === REACT_MEMO_TYPE;
}
function isPortal(object) {
return typeOf(object) === REACT_PORTAL_TYPE;
}
function isProfiler(object) {
return typeOf(object) === REACT_PROFILER_TYPE;
}
function isStrictMode(object) {
return typeOf(object) === REACT_STRICT_MODE_TYPE;
}
function isSuspense(object) {
return typeOf(object) === REACT_SUSPENSE_TYPE;
}
function isSuspenseList(object) {
return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;
}
reactIs_development.ContextConsumer = ContextConsumer;
reactIs_development.ContextProvider = ContextProvider;
reactIs_development.Element = Element;
reactIs_development.ForwardRef = ForwardRef;
reactIs_development.Fragment = Fragment;
reactIs_development.Lazy = Lazy;
reactIs_development.Memo = Memo;
reactIs_development.Portal = Portal;
reactIs_development.Profiler = Profiler;
reactIs_development.StrictMode = StrictMode;
reactIs_development.Suspense = Suspense;
reactIs_development.SuspenseList = SuspenseList;
reactIs_development.isAsyncMode = isAsyncMode;
reactIs_development.isConcurrentMode = isConcurrentMode;
reactIs_development.isContextConsumer = isContextConsumer;
reactIs_development.isContextProvider = isContextProvider;
reactIs_development.isElement = isElement;
reactIs_development.isForwardRef = isForwardRef;
reactIs_development.isFragment = isFragment;
reactIs_development.isLazy = isLazy;
reactIs_development.isMemo = isMemo;
reactIs_development.isPortal = isPortal;
reactIs_development.isProfiler = isProfiler;
reactIs_development.isStrictMode = isStrictMode;
reactIs_development.isSuspense = isSuspense;
reactIs_development.isSuspenseList = isSuspenseList;
reactIs_development.isValidElementType = isValidElementType;
reactIs_development.typeOf = typeOf;
})();
}
return reactIs_development;
}
if (process.env.NODE_ENV === 'production') {
reactIs.exports = requireReactIs_production_min();
} else {
reactIs.exports = requireReactIs_development();
}
var reactIsExports = reactIs.exports;
// Simplified polyfill for IE11 support
// https://github.com/JamesMGreene/Function.name/blob/58b314d4a983110c3682f1228f845d39ccca1817/Function.name.js#L3
const fnNameMatchRegex = /^\s*function(?:\s|\s*\/\*.*\*\/\s*)+([^(\s/]*)\s*/;
function getFunctionName(fn) {
const match = `${fn}`.match(fnNameMatchRegex);
const name = match && match[1];
return name || '';
}
function getFunctionComponentName(Component, fallback = '') {
return Component.displayName || Component.name || getFunctionName(Component) || fallback;
}
function getWrappedName(outerType, innerType, wrapperName) {
const functionName = getFunctionComponentName(innerType);
return outerType.displayName || (functionName !== '' ? `${wrapperName}(${functionName})` : wrapperName);
}
/**
* cherry-pick from
* https://github.com/facebook/react/blob/769b1f270e1251d9dbdce0fcbd9e92e502d059b8/packages/shared/getComponentName.js
* originally forked from recompose/getDisplayName with added IE11 support
*/
function getDisplayName(Component) {
if (Component == null) {
return undefined;
}
if (typeof Component === 'string') {
return Component;
}
if (typeof Component === 'function') {
return getFunctionComponentName(Component, 'Component');
}
// TypeScript can't have components as objects but they exist in the form of `memo` or `Suspense`
if (typeof Component === 'object') {
switch (Component.$$typeof) {
case reactIsExports.ForwardRef:
return getWrappedName(Component, Component.render, 'ForwardRef');
case reactIsExports.Memo:
return getWrappedName(Component, Component.type, 'memo');
default:
return undefined;
}
}
return undefined;
}
const refType = PropTypes.oneOfType([PropTypes.func, PropTypes.object]);
var refType$1 = refType;
// It should to be noted that this function isn't equivalent to `text-transform: capitalize`.
//
// A strict capitalization should uppercase the first letter of each word in the sentence.
// We only handle the first word.
function capitalize(string) {
if (typeof string !== 'string') {
throw new Error(process.env.NODE_ENV !== "production" ? `MUI: \`capitalize(string)\` expects a string argument.` : formatMuiErrorMessage(7));
}
return string.charAt(0).toUpperCase() + string.slice(1);
}
function ownerDocument(node) {
return node && node.ownerDocument || document;
}
/**
* TODO v5: consider making it private
*
* passes {value} to {ref}
*
* WARNING: Be sure to only call this inside a callback that is passed as a ref.
* Otherwise, make sure to cleanup the previous {ref} if it changes. See
* https://github.com/mui/material-ui/issues/13539
*
* Useful if you want to expose the ref of an inner component to the public API
* while still using it inside the component.
* @param ref A ref callback or ref object. If anything falsy, this is a no-op.
*/
function setRef$1(ref, value) {
if (typeof ref === 'function') {
ref(value);
} else if (ref) {
ref.current = value;
}
}
/**
* A version of `React.useLayoutEffect` that does not show a warning when server-side rendering.
* This is useful for effects that are only needed for client-side rendering but not for SSR.
*
* Before you use this hook, make sure to read https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85
* and confirm it doesn't apply to your use-case.
*/
const useEnhancedEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
var useEnhancedEffect$1 = useEnhancedEffect;
let globalId = 0;
function useGlobalId(idOverride) {
const [defaultId, setDefaultId] = React.useState(idOverride);
const id = idOverride || defaultId;
React.useEffect(() => {
if (defaultId == null) {
// Fallback to this default id when possible.
// Use the incrementing value for client-side rendering only.
// We can't use it server-side.
// If you want to use random values please consider the Birthday Problem: https://en.wikipedia.org/wiki/Birthday_problem
globalId += 1;
setDefaultId(`mui-${globalId}`);
}
}, [defaultId]);
return id;
}
// downstream bundlers may remove unnecessary concatenation, but won't remove toString call -- Workaround for https://github.com/webpack/webpack/issues/14814
const maybeReactUseId = React['useId'.toString()];
/**
*
* @example <div id={useId()} />
* @param idOverride
* @returns {string}
*/
function useId(idOverride) {
if (maybeReactUseId !== undefined) {
const reactId = maybeReactUseId();
return idOverride != null ? idOverride : reactId;
}
// eslint-disable-next-line react-hooks/rules-of-hooks -- `React.useId` is invariant at runtime.
return useGlobalId(idOverride);
}
function useControlled({
controlled,
default: defaultProp,
name,
state = 'value'
}) {
// isControlled is ignored in the hook dependency lists as it should never change.
const {
current: isControlled
} = React.useRef(controlled !== undefined);
const [valueState, setValue] = React.useState(defaultProp);
const value = isControlled ? controlled : valueState;
if (process.env.NODE_ENV !== 'production') {
React.useEffect(() => {
if (isControlled !== (controlled !== undefined)) {
console.error([`MUI: A component is changing the ${isControlled ? '' : 'un'}controlled ${state} state of ${name} to be ${isControlled ? 'un' : ''}controlled.`, 'Elements should not switch from uncontrolled to controlled (or vice versa).', `Decide between using a controlled or uncontrolled ${name} ` + 'element for the lifetime of the component.', "The nature of the state is determined during the first render. It's considered controlled if the value is not `undefined`.", 'More info: https://fb.me/react-controlled-components'].join('\n'));
}
}, [state, name, controlled]);
const {
current: defaultValue
} = React.useRef(defaultProp);
React.useEffect(() => {
if (!isControlled && defaultValue !== defaultProp) {
console.error([`MUI: A component is changing the default ${state} state of an uncontrolled ${name} after being initialized. ` + `To suppress this warning opt to use a controlled ${name}.`].join('\n'));
}
}, [JSON.stringify(defaultProp)]);
}
const setValueIfUncontrolled = React.useCallback(newValue => {
if (!isControlled) {
setValue(newValue);
}
}, []);
return [value, setValueIfUncontrolled];
}
/**
* Inspired by https://github.com/facebook/react/issues/14099#issuecomment-440013892
* See RFC in https://github.com/reactjs/rfcs/pull/220
*/
function useEventCallback(fn) {
const ref = React.useRef(fn);
useEnhancedEffect$1(() => {
ref.current = fn;
});
return React.useRef((...args) =>
// @ts-expect-error hide `this`
(0, ref.current)(...args)).current;
}
function useForkRef(...refs) {
/**
* This will create a new function if the refs passed to this hook change and are all defined.
* This means react will call the old forkRef with `null` and the new forkRef
* with the ref. Cleanup naturally emerges from this behavior.
*/
return React.useMemo(() => {
if (refs.every(ref => ref == null)) {
return null;
}
return instance => {
refs.forEach(ref => {
setRef$1(ref, instance);
});
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, refs);
}
function composeClasses(slots, getUtilityClass, classes = undefined) {
const output = {};
Object.keys(slots).forEach(
// `Object.keys(slots)` can't be wider than `T` because we infer `T` from `slots`.
// @ts-expect-error https://github.com/microsoft/TypeScript/pull/12253#issuecomment-263132208
slot => {
output[slot] = slots[slot].reduce((acc, key) => {
if (key) {
const utilityClass = getUtilityClass(key);
if (utilityClass !== '') {
acc.push(utilityClass);
}
if (classes && classes[key]) {
acc.push(classes[key]);
}
}
return acc;
}, []).join(' ');
});
return output;
}
const defaultGenerator = componentName => componentName;
const createClassNameGenerator = () => {
let generate = defaultGenerator;
return {
configure(generator) {
generate = generator;
},
generate(componentName) {
return generate(componentName);
},
reset() {
generate = defaultGenerator;
}
};
};
const ClassNameGenerator = createClassNameGenerator();
var ClassNameGenerator$1 = ClassNameGenerator;
const globalStateClasses = {
active: 'active',
checked: 'checked',
completed: 'completed',
disabled: 'disabled',
error: 'error',
expanded: 'expanded',
focused: 'focused',
focusVisible: 'focusVisible',
open: 'open',
readOnly: 'readOnly',
required: 'required',
selected: 'selected'
};
function generateUtilityClass(componentName, slot, globalStatePrefix = 'Mui') {
const globalStateClass = globalStateClasses[slot];
return globalStateClass ? `${globalStatePrefix}-${globalStateClass}` : `${ClassNameGenerator$1.generate(componentName)}-${slot}`;
}
function generateUtilityClasses(componentName, slots, globalStatePrefix = 'Mui') {
const result = {};
slots.forEach(slot => {
result[slot] = generateUtilityClass(componentName, slot, globalStatePrefix);
});
return result;
}
function clamp(val, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) {
return Math.max(min, Math.min(val, max));
}
const _excluded$q = ["localeText"];
const MuiPickersAdapterContext = /*#__PURE__*/React.createContext(null);
if (process.env.NODE_ENV !== 'production') {
MuiPickersAdapterContext.displayName = 'MuiPickersAdapterContext';
}
/**
* Demos:
*
* - [Date format and localization](https://mui.com/x/react-date-pickers/adapters-locale/)
* - [Calendar systems](https://mui.com/x/react-date-pickers/calendar-systems/)
* - [Translated components](https://mui.com/x/react-date-pickers/localization/)
* - [UTC and timezones](https://mui.com/x/react-date-pickers/timezone/)
*
* API:
*
* - [LocalizationProvider API](https://mui.com/x/api/date-pickers/localization-provider/)
*/
const LocalizationProvider = function LocalizationProvider(inProps) {
var _React$useContext;
const {
localeText: inLocaleText
} = inProps,
otherInProps = _objectWithoutPropertiesLoose$1(inProps, _excluded$q);
const {
utils: parentUtils,
localeText: parentLocaleText
} = (_React$useContext = React.useContext(MuiPickersAdapterContext)) != null ? _React$useContext : {
utils: undefined,
localeText: undefined
};
const props = useThemeProps({
// We don't want to pass the `localeText` prop to the theme, that way it will always return the theme value,
// We will then merge this theme value with our value manually
props: otherInProps,
name: 'MuiLocalizationProvider'
});
const {
children,
dateAdapter: DateAdapter,
dateFormats,
dateLibInstance,
adapterLocale,
localeText: themeLocaleText
} = props;
const localeText = React.useMemo(() => _extends({}, themeLocaleText, parentLocaleText, inLocaleText), [themeLocaleText, parentLocaleText, inLocaleText]);
const utils = React.useMemo(() => {
if (!DateAdapter) {
if (parentUtils) {
return parentUtils;
}
return null;
}
const adapter = new DateAdapter({
locale: adapterLocale,
formats: dateFormats,
instance: dateLibInstance
});
if (!adapter.isMUIAdapter) {
throw new Error(['MUI: The date adapter should be imported from `@mui/x-date-pickers` or `@mui/x-date-pickers-pro`, not from `@date-io`', "For example, `import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'` instead of `import AdapterDayjs from '@date-io/dayjs'`", 'More information on the installation documentation: https://mui.com/x/react-date-pickers/getting-started/#installation'].join(`\n`));
}
return adapter;
}, [DateAdapter, adapterLocale, dateFormats, dateLibInstance, parentUtils]);
const defaultDates = React.useMemo(() => {
if (!utils) {
return null;
}
return {
minDate: utils.date('1900-01-01T00:00:00.000'),
maxDate: utils.date('2099-12-31T00:00:00.000')
};
}, [utils]);
const contextValue = React.useMemo(() => {
return {
utils,
defaultDates,
localeText
};
}, [defaultDates, utils, localeText]);
return /*#__PURE__*/jsx(MuiPickersAdapterContext.Provider, {
value: contextValue,
children: children
});
};
process.env.NODE_ENV !== "production" ? LocalizationProvider.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* Locale for the date library you are using
*/
adapterLocale: PropTypes.any,
children: PropTypes.node,
/**
* Date library adapter class function.
* @see See the localization provider {@link https://mui.com/x/react-date-pickers/getting-started/#setup-your-date-library-adapter date adapter setup section} for more details.
*/
dateAdapter: PropTypes.func,
/**
* Formats that are used for any child pickers
*/
dateFormats: PropTypes.shape({
dayOfMonth: PropTypes.string,
fullDate: PropTypes.string,
fullDateTime: PropTypes.string,
fullDateTime12h: PropTypes.string,
fullDateTime24h: PropTypes.string,
fullDateWithWeekday: PropTypes.string,
fullTime: PropTypes.string,
fullTime12h: PropTypes.string,
fullTime24h: PropTypes.string,
hours12h: PropTypes.string,
hours24h: PropTypes.string,
keyboardDate: PropTypes.string,
keyboardDateTime: PropTypes.string,
keyboardDateTime12h: PropTypes.string,
keyboardDateTime24h: PropTypes.string,
meridiem: PropTypes.string,
minutes: PropTypes.string,
month: PropTypes.string,
monthAndDate: PropTypes.string,
monthAndYear: PropTypes.string,
monthShort: PropTypes.string,
normalDate: PropTypes.string,
normalDateWithWeekday: PropTypes.string,
seconds: PropTypes.string,
shortDate: PropTypes.string,
weekday: PropTypes.string,
weekdayShort: PropTypes.string,
year: PropTypes.string
}),
/**
* Date library instance you are using, if it has some global overrides
* ```jsx
* dateLibInstance={momentTimeZone}
* ```
*/
dateLibInstance: PropTypes.any,
/**
* Locale for components texts
*/
localeText: PropTypes.object
} : void 0;
const getPickersLocalization = pickersTranslations => {
return {
components: {
MuiLocalizationProvider: {
defaultProps: {
localeText: _extends({}, pickersTranslations)
}
}
}
};
};
// This object is not Partial<PickersLocaleText> because it is the default values
const enUSPickers = {
// Calendar navigation
previousMonth: 'Previous month',
nextMonth: 'Next month',
// View navigation
openPreviousView: 'open previous view',
openNextView: 'open next view',
calendarViewSwitchingButtonAriaLabel: view => view === 'year' ? 'year view is open, switch to calendar view' : 'calendar view is open, switch to year view',
// DateRange placeholders
start: 'Start',
end: 'End',
// Action bar
cancelButtonLabel: 'Cancel',
clearButtonLabel: 'Clear',
okButtonLabel: 'OK',
todayButtonLabel: 'Today',
// Toolbar titles
datePickerToolbarTitle: 'Select date',
dateTimePickerToolbarTitle: 'Select date & time',
timePickerToolbarTitle: 'Select time',
dateRangePickerToolbarTitle: 'Select date range',
// Clock labels
clockLabelText: (view, time, adapter) => `Select ${view}. ${time === null ? 'No time selected' : `Selected time is ${adapter.format(time, 'fullTime')}`}`,
hoursClockNumberText: hours => `${hours} hours`,
minutesClockNumberText: minutes => `${minutes} minutes`,
secondsClockNumberText: seconds => `${seconds} seconds`,
// Digital clock labels
selectViewText: view => `Select ${view}`,
// Calendar labels
calendarWeekNumberHeaderLabel: 'Week number',
calendarWeekNumberHeaderText: '#',
calendarWeekNumberAriaLabelText: weekNumber => `Week ${weekNumber}`,
calendarWeekNumberText: weekNumber => `${weekNumber}`,
// Open picker labels
openDatePickerDialogue: (value, utils) => value !== null && utils.isValid(value) ? `Choose date, selected date is ${utils.format(value, 'fullDate')}` : 'Choose date',
openTimePickerDialogue: (value, utils) => value !== null && utils.isValid(value) ? `Choose time, selected time is ${utils.format(value, 'fullTime')}` : 'Choose time',
fieldClearLabel: 'Clear value',
// Table labels
timeTableLabel: 'pick time',
dateTableLabel: 'pick date',
// Field section placeholders
fieldYearPlaceholder: params => 'Y'.repeat(params.digitAmount),
fieldMonthPlaceholder: params => params.contentType === 'letter' ? 'MMMM' : 'MM',
fieldDayPlaceholder: () => 'DD',
fieldWeekDayPlaceholder: params => params.contentType === 'letter' ? 'EEEE' : 'EE',
fieldHoursPlaceholder: () => 'hh',
fieldMinutesPlaceholder: () => 'mm',
fieldSecondsPlaceholder: () => 'ss',
fieldMeridiemPlaceholder: () => 'aa'
};
const DEFAULT_LOCALE = enUSPickers;
getPickersLocalization(enUSPickers);
const useLocalizationContext = () => {
const localization = React.useContext(MuiPickersAdapterContext);
if (localization === null) {
throw new Error(['MUI: Can not find the date and time pickers localization context.', 'It looks like you forgot to wrap your component in LocalizationProvider.', 'This can also happen if you are bundling multiple versions of the `@mui/x-date-pickers` package'].join('\n'));
}
if (localization.utils === null) {
throw new Error(['MUI: Can not find the date and time pickers adapter from its localization context.', 'It looks like you forgot to pass a `dateAdapter` to your LocalizationProvider.'].join('\n'));
}
const localeText = React.useMemo(() => _extends({}, DEFAULT_LOCALE, localization.localeText), [localization.localeText]);
return React.useMemo(() => _extends({}, localization, {
localeText
}), [localization, localeText]);
};
const useUtils = () => useLocalizationContext().utils;
const useDefaultDates = () => useLocalizationContext().defaultDates;
const useLocaleText = () => useLocalizationContext().localeText;
const useNow = timezone => {
const utils = useUtils();
const now = React.useRef();
if (now.current === undefined) {
now.current = utils.dateWithTimezone(undefined, timezone);
}
return now.current;
};
/**
* Determines if a given element is a DOM element name (i.e. not a React component).
*/
function isHostComponent(element) {
return typeof element === 'string';
}
/**
* Type of the ownerState based on the type of an element it applies to.
* This resolves to the provided OwnerState for React components and `undefined` for host components.
* Falls back to `OwnerState | undefined` when the exact type can't be determined in development time.
*/
/**
* Appends the ownerState object to the props, merging with the existing one if necessary.
*
* @param elementType Type of the element that owns the `existingProps`. If the element is a DOM node or undefined, `ownerState` is not applied.
* @param otherProps Props of the element.
* @param ownerState
*/
function appendOwnerState(elementType, otherProps, ownerState) {
if (elementType === undefined || isHostComponent(elementType)) {
return otherProps;
}
return _extends({}, otherProps, {
ownerState: _extends({}, otherProps.ownerState, ownerState)
});
}
/**
* Extracts event handlers from a given object.
* A prop is considered an event handler if it is a function and its name starts with `on`.
*
* @param object An object to extract event handlers from.
* @param excludeKeys An array of keys to exclude from the returned object.
*/
function extractEventHandlers(object, excludeKeys = []) {
if (object === undefined) {
return {};
}
const result = {};
Object.keys(object).filter(prop => prop.match(/^on[A-Z]/) && typeof object[prop] === 'function' && !excludeKeys.includes(prop)).forEach(prop => {
result[prop] = object[prop];
});
return result;
}
/**
* If `componentProps` is a function, calls it with the provided `ownerState`.
* Otherwise, just returns `componentProps`.
*/
function resolveComponentProps(componentProps, ownerState, slotState) {
if (typeof componentProps === 'function') {
return componentProps(ownerState, slotState);
}
return componentProps;
}
/**
* Removes event handlers from the given object.
* A field is considered an event handler if it is a function with a name beginning with `on`.
*
* @param object Object to remove event handlers from.
* @returns Object with event handlers removed.
*/
function omitEventHandlers(object) {
if (object === undefined) {
return {};
}
const result = {};
Object.keys(object).filter(prop => !(prop.match(/^on[A-Z]/) && typeof object[prop] === 'function')).forEach(prop => {
result[prop] = object[prop];
});
return result;
}
/**
* Merges the slot component internal props (usually coming from a hook)
* with the externally provided ones.
*
* The merge order is (the latter overrides the former):
* 1. The internal props (specified as a getter function to work with get*Props hook result)
* 2. Additional props (specified internally on a Base UI component)
* 3. External props specified on the owner component. These should only be used on a root slot.
* 4. External props specified in the `slotProps.*` prop.
* 5. The `className` prop - combined from all the above.
* @param parameters
* @returns
*/
function mergeSlotProps(parameters) {
const {
getSlotProps,
additionalProps,
externalSlotProps,
externalForwardedProps,
className
} = parameters;
if (!getSlotProps) {
// The simpler case - getSlotProps is not defined, so no internal event handlers are defined,
// so we can simply merge all the props without having to worry about extracting event handlers.
const joinedClasses = clsx(additionalProps == null ? void 0 : additionalProps.className, className, externalForwardedProps == null ? void 0 : externalForwardedProps.className, externalSlotProps == null ? void 0 : externalSlotProps.className);
const mergedStyle = _extends({}, additionalProps == null ? void 0 : additionalProps.style, externalForwardedProps == null ? void 0 : externalForwardedProps.style, externalSlotProps == null ? void 0 : externalSlotProps.style);
const props = _extends({}, additionalProps, externalForwardedProps, externalSlotProps);
if (joinedClasses.length > 0) {
props.className = joinedClasses;
}
if (Object.keys(mergedStyle).length > 0) {
props.style = mergedStyle;
}
return {
props,
internalRef: undefined
};
}
// In this case, getSlotProps is responsible for calling the external event handlers.
// We don't need to include them in the merged props because of this.
const eventHandlers = extractEventHandlers(_extends({}, externalForwardedProps, externalSlotProps));
const componentsPropsWithoutEventHandlers = omitEventHandlers(externalSlotProps);
const otherPropsWithoutEventHandlers = omitEventHandlers(externalForwardedProps);
const internalSlotProps = getSlotProps(eventHandlers);
// The order of classes is important here.
// Emotion (that we use in libraries consuming Base UI) depends on this order
// to properly override style. It requires the most important classes to be last
// (see https://github.com/mui/material-ui/pull/33205) for the related discussion.
const joinedClasses = clsx(internalSlotProps == null ? void 0 : internalSlotProps.className, additionalProps == null ? void 0 : additionalProps.className, className, externalForwardedProps == null ? void 0 : externalForwardedProps.className, externalSlotProps == null ? void 0 : externalSlotProps.className);
const mergedStyle = _extends({}, internalSlotProps == null ? void 0 : internalSlotProps.style, additionalProps == null ? void 0 : additionalProps.style, externalForwardedProps == null ? void 0 : externalForwardedProps.style, externalSlotProps == null ? void 0 : externalSlotProps.style);
const props = _extends({}, internalSlotProps, additionalProps, otherPropsWithoutEventHandlers, componentsPropsWithoutEventHandlers);
if (joinedClasses.length > 0) {
props.className = joinedClasses;
}
if (Object.keys(mergedStyle).length > 0) {
props.style = mergedStyle;
}
return {
props,
internalRef: internalSlotProps.ref
};
}
const _excluded$p = ["elementType", "externalSlotProps", "ownerState", "skipResolvingSlotProps"];
/**
* @ignore - do not document.
* Builds the props to be passed into the slot of an unstyled component.
* It merges the internal props of the component with the ones supplied by the user, allowing to customize the behavior.
* If the slot component is not a host component, it also merges in the `ownerState`.
*
* @param parameters.getSlotProps - A function that returns the props to be passed to the slot component.
*/
function useSlotProps(parameters) {
var _parameters$additiona;
const {
elementType,
externalSlotProps,
ownerState,
skipResolvingSlotProps = false
} = parameters,
rest = _objectWithoutPropertiesLoose$1(parameters, _excluded$p);
const resolvedComponentsProps = skipResolvingSlotProps ? {} : resolveComponentProps(externalSlotProps, ownerState);
const {
props: mergedProps,
internalRef
} = mergeSlotProps(_extends({}, rest, {
externalSlotProps: resolvedComponentsProps
}));
const ref = useForkRef(internalRef, resolvedComponentsProps == null ? void 0 : resolvedComponentsProps.ref, (_parameters$additiona = parameters.additionalProps) == null ? void 0 : _parameters$additiona.ref);
const props = appendOwnerState(elementType, _extends({}, mergedProps, {
ref
}), ownerState);
return props;
}
const ArrowDropDownIcon = createSvgIcon( /*#__PURE__*/jsx("path", {
d: "M7 10l5 5 5-5z"
}), 'ArrowDropDown');
/**
* @ignore - internal component.
*/
const ArrowLeftIcon = createSvgIcon( /*#__PURE__*/jsx("path", {
d: "M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z"
}), 'ArrowLeft');
/**
* @ignore - internal component.
*/
const ArrowRightIcon = createSvgIcon( /*#__PURE__*/jsx("path", {
d: "M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"
}), 'ArrowRight');
/**
* @ignore - internal component.
*/
const CalendarIcon = createSvgIcon( /*#__PURE__*/jsx("path", {
d: "M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z"
}), 'Calendar');
/**
* @ignore - internal component.
*/
createSvgIcon( /*#__PURE__*/jsxs(React.Fragment, {
children: [/*#__PURE__*/jsx("path", {
d: "M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
}), /*#__PURE__*/jsx("path", {
d: "M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"
})]
}), 'Clock');
/**
* @ignore - internal component.
*/
createSvgIcon( /*#__PURE__*/jsx("path", {
d: "M9 11H7v2h2v-2zm4 0h-2v2h2v-2zm4 0h-2v2h2v-2zm2-7h-1V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H5V9h14v11z"
}), 'DateRange');
/**
* @ignore - internal component.
*/
createSvgIcon( /*#__PURE__*/jsxs(React.Fragment, {
children: [/*#__PURE__*/jsx("path", {
d: "M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
}), /*#__PURE__*/jsx("path", {
d: "M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"
})]
}), 'Time');
/**
* @ignore - internal component.
*/
const ClearIcon = createSvgIcon( /*#__PURE__*/jsx("path", {
d: "M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"
}), 'Clear');
function getPickersArrowSwitcherUtilityClass(slot) {
return generateUtilityClass('MuiPickersArrowSwitcher', slot);
}
generateUtilityClasses('MuiPickersArrowSwitcher', ['root', 'spacer', 'button']);
const _excluded$o = ["children", "className", "slots", "slotProps", "isNextDisabled", "isNextHidden", "onGoToNext", "nextLabel", "isPreviousDisabled", "isPreviousHidden", "onGoToPrevious", "previousLabel"],
_excluded2$6 = ["ownerState"],
_excluded3$3 = ["ownerState"];
const PickersArrowSwitcherRoot = styled$3('div', {
name: 'MuiPickersArrowSwitcher',
slot: 'Root',
overridesResolver: (props, styles) => styles.root
})({
display: 'flex'
});
const PickersArrowSwitcherSpacer = styled$3('div', {
name: 'MuiPickersArrowSwitcher',
slot: 'Spacer',
overridesResolver: (props, styles) => styles.spacer
})(({
theme
}) => ({
width: theme.spacing(3)
}));
const PickersArrowSwitcherButton = styled$3(IconButton, {
name: 'MuiPickersArrowSwitcher',
slot: 'Button',
overridesResolver: (props, styles) => styles.button
})(({
ownerState
}) => _extends({}, ownerState.hidden && {
visibility: 'hidden'
}));
const useUtilityClasses$f = ownerState => {
const {
classes
} = ownerState;
const slots = {
root: ['root'],
spacer: ['spacer'],
button: ['button']
};
return composeClasses(slots, getPickersArrowSwitcherUtilityClass, classes);
};
const PickersArrowSwitcher = /*#__PURE__*/React.forwardRef(function PickersArrowSwitcher(inProps, ref) {
var _slots$previousIconBu, _slots$nextIconButton, _slots$leftArrowIcon, _slots$rightArrowIcon;
const theme = useTheme$2();
const isRTL = theme.direction === 'rtl';
const props = useThemeProps({
props: inProps,
name: 'MuiPickersArrowSwitcher'
});
const {
children,
className,
slots,
slotProps,
isNextDisabled,
isNextHidden,
onGoToNext,
nextLabel,
isPreviousDisabled,
isPreviousHidden,
onGoToPrevious,
previousLabel
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$o);
const ownerState = props;
const classes = useUtilityClasses$f(ownerState);
const nextProps = {
isDisabled: isNextDisabled,
isHidden: isNextHidden,
goTo: onGoToNext,
label: nextLabel
};
const previousProps = {
isDisabled: isPreviousDisabled,
isHidden: isPreviousHidden,
goTo: onGoToPrevious,
label: previousLabel
};
const PreviousIconButton = (_slots$previousIconBu = slots == null ? void 0 : slots.previousIconButton) != null ? _slots$previousIconBu : PickersArrowSwitcherButton;
const previousIconButtonProps = useSlotProps({
elementType: PreviousIconButton,
externalSlotProps: slotProps == null ? void 0 : slotProps.previousIconButton,
additionalProps: {
size: 'medium',
title: previousProps.label,
'aria-label': previousProps.label,
disabled: previousProps.isDisabled,
edge: 'end',
onClick: previousProps.goTo
},
ownerState: _extends({}, ownerState, {
hidden: previousProps.isHidden
}),
className: classes.button
});
const NextIconButton = (_slots$nextIconButton = slots == null ? void 0 : slots.nextIconButton) != null ? _slots$nextIconButton : PickersArrowSwitcherButton;
const nextIconButtonProps = useSlotProps({
elementType: NextIconButton,
externalSlotProps: slotProps == null ? void 0 : slotProps.nextIconButton,
additionalProps: {
size: 'medium',
title: nextProps.label,
'aria-label': nextProps.label,
disabled: nextProps.isDisabled,
edge: 'start',
onClick: nextProps.goTo
},
ownerState: _extends({}, ownerState, {
hidden: nextProps.isHidden
}),
className: classes.button
});
const LeftArrowIcon = (_slots$leftArrowIcon = slots == null ? void 0 : slots.leftArrowIcon) != null ? _slots$leftArrowIcon : ArrowLeftIcon;
// The spread is here to avoid this bug mui/material-ui#34056
const _useSlotProps = useSlotProps({
elementType: LeftArrowIcon,
externalSlotProps: slotProps == null ? void 0 : slotProps.leftArrowIcon,
additionalProps: {
fontSize: 'inherit'
},
ownerState: undefined
}),
leftArrowIconProps = _objectWithoutPropertiesLoose$1(_useSlotProps, _excluded2$6);
const RightArrowIcon = (_slots$rightArrowIcon = slots == null ? void 0 : slots.rightArrowIcon) != null ? _slots$rightArrowIcon : ArrowRightIcon;
// The spread is here to avoid this bug mui/material-ui#34056
const _useSlotProps2 = useSlotProps({
elementType: RightArrowIcon,
externalSlotProps: slotProps == null ? void 0 : slotProps.rightArrowIcon,
additionalProps: {
fontSize: 'inherit'
},
ownerState: undefined
}),
rightArrowIconProps = _objectWithoutPropertiesLoose$1(_useSlotProps2, _excluded3$3);
return /*#__PURE__*/jsxs(PickersArrowSwitcherRoot, _extends({
ref: ref,
className: clsx(classes.root, className),
ownerState: ownerState
}, other, {
children: [/*#__PURE__*/jsx(PreviousIconButton, _extends({}, previousIconButtonProps, {
children: isRTL ? /*#__PURE__*/jsx(RightArrowIcon, _extends({}, rightArrowIconProps)) : /*#__PURE__*/jsx(LeftArrowIcon, _extends({}, leftArrowIconProps))
})), children ? /*#__PURE__*/jsx(Typography, {
variant: "subtitle1",
component: "span",
children: children
}) : /*#__PURE__*/jsx(PickersArrowSwitcherSpacer, {
className: classes.spacer,
ownerState: ownerState
}), /*#__PURE__*/jsx(NextIconButton, _extends({}, nextIconButtonProps, {
children: isRTL ? /*#__PURE__*/jsx(LeftArrowIcon, _extends({}, leftArrowIconProps)) : /*#__PURE__*/jsx(RightArrowIcon, _extends({}, rightArrowIconProps))
}))]
}));
});
const areViewsEqual = (views, expectedViews) => {
if (views.length !== expectedViews.length) {
return false;
}
return expectedViews.every(expectedView => views.includes(expectedView));
};
const applyDefaultViewProps = ({
openTo,
defaultOpenTo,
views,
defaultViews
}) => {
const viewsWithDefault = views != null ? views : defaultViews;
let openToWithDefault;
if (openTo != null) {
openToWithDefault = openTo;
} else if (viewsWithDefault.includes(defaultOpenTo)) {
openToWithDefault = defaultOpenTo;
} else if (viewsWithDefault.length > 0) {
openToWithDefault = viewsWithDefault[0];
} else {
throw new Error('MUI: The `views` prop must contain at least one view');
}
return {
views: viewsWithDefault,
openTo: openToWithDefault
};
};
const timeViews = ['hours', 'minutes', 'seconds'];
const isTimeView = view => timeViews.includes(view);
const getSecondsInDay = (date, utils) => {
return utils.getHours(date) * 3600 + utils.getMinutes(date) * 60 + utils.getSeconds(date);
};
const createIsAfterIgnoreDatePart = (disableIgnoringDatePartForTimeValidation, utils) => (dateLeft, dateRight) => {
if (disableIgnoringDatePartForTimeValidation) {
return utils.isAfter(dateLeft, dateRight);
}
return getSecondsInDay(dateLeft, utils) > getSecondsInDay(dateRight, utils);
};
let warnedOnceNotValidView = false;
function useViews({
onChange,
onViewChange,
openTo,
view: inView,
views,
autoFocus,
focusedView: inFocusedView,
onFocusedViewChange
}) {
var _views, _views2;
if (process.env.NODE_ENV !== 'production') {
if (!warnedOnceNotValidView) {
if (inView != null && !views.includes(inView)) {
console.warn(`MUI: \`view="${inView}"\` is not a valid prop.`, `It must be an element of \`views=["${views.join('", "')}"]\`.`);
warnedOnceNotValidView = true;
}
if (inView == null && openTo != null && !views.includes(openTo)) {
console.warn(`MUI: \`openTo="${openTo}"\` is not a valid prop.`, `It must be an element of \`views=["${views.join('", "')}"]\`.`);
warnedOnceNotValidView = true;
}
}
}
const previousOpenTo = React.useRef(openTo);
const previousViews = React.useRef(views);
const defaultView = React.useRef(views.includes(openTo) ? openTo : views[0]);
const [view, setView] = useControlled({
name: 'useViews',
state: 'view',
controlled: inView,
default: defaultView.current
});
const defaultFocusedView = React.useRef(autoFocus ? view : null);
const [focusedView, setFocusedView] = useControlled({
name: 'useViews',
state: 'focusedView',
controlled: inFocusedView,
default: defaultFocusedView.current
});
React.useEffect(() => {
// Update the current view when `openTo` or `views` props change
if (previousOpenTo.current && previousOpenTo.current !== openTo || previousViews.current && previousViews.current.some(previousView => !views.includes(previousView))) {
setView(views.includes(openTo) ? openTo : views[0]);
previousViews.current = views;
previousOpenTo.current = openTo;
}
}, [openTo, setView, view, views]);
const viewIndex = views.indexOf(view);
const previousView = (_views = views[viewIndex - 1]) != null ? _views : null;
const nextView = (_views2 = views[viewIndex + 1]) != null ? _views2 : null;
const handleFocusedViewChange = useEventCallback((viewToFocus, hasFocus) => {
if (hasFocus) {
// Focus event
setFocusedView(viewToFocus);
} else {
// Blur event
setFocusedView(prevFocusedView => viewToFocus === prevFocusedView ? null : prevFocusedView // If false the blur is due to view switching
);
}
onFocusedViewChange == null || onFocusedViewChange(viewToFocus, hasFocus);
});
const handleChangeView = useEventCallback(newView => {
// always keep the focused view in sync
handleFocusedViewChange(newView, true);
if (newView === view) {
return;
}
setView(newView);
if (onViewChange) {
onViewChange(newView);
}
});
const goToNextView = useEventCallback(() => {
if (nextView) {
handleChangeView(nextView);
}
});
const setValueAndGoToNextView = useEventCallback((value, currentViewSelectionState, selectedView) => {
const isSelectionFinishedOnCurrentView = currentViewSelectionState === 'finish';
const hasMoreViews = selectedView ?
// handles case like `DateTimePicker`, where a view might return a `finish` selection state
// but we it's not the final view given all `views` -> overall selection state should be `partial`.
views.indexOf(selectedView) < views.length - 1 : Boolean(nextView);
const globalSelectionState = isSelectionFinishedOnCurrentView && hasMoreViews ? 'partial' : currentViewSelectionState;
onChange(value, globalSelectionState, selectedView);
// Detects if the selected view is not the active one.
// Can happen if multiple views are displayed, like in `DesktopDateTimePicker` or `MultiSectionDigitalClock`.
if (selectedView && selectedView !== view) {
const nextViewAfterSelected = views[views.indexOf(selectedView) + 1];
if (nextViewAfterSelected) {
// move to next view after the selected one
handleChangeView(nextViewAfterSelected);
}
} else if (isSelectionFinishedOnCurrentView) {
goToNextView();
}
});
return {
view,
setView: handleChangeView,
focusedView,
setFocusedView: handleFocusedViewChange,
nextView,
previousView,
// Always return up to date default view instead of the initial one (i.e. defaultView.current)
defaultView: views.includes(openTo) ? openTo : views[0],
goToNextView,
setValueAndGoToNextView
};
}
function useNextMonthDisabled(month, {
disableFuture,
maxDate,
timezone
}) {
const utils = useUtils();
return React.useMemo(() => {
const now = utils.dateWithTimezone(undefined, timezone);
const lastEnabledMonth = utils.startOfMonth(disableFuture && utils.isBefore(now, maxDate) ? now : maxDate);
return !utils.isAfter(lastEnabledMonth, month);
}, [disableFuture, maxDate, month, utils, timezone]);
}
function usePreviousMonthDisabled(month, {
disablePast,
minDate,
timezone
}) {
const utils = useUtils();
return React.useMemo(() => {
const now = utils.dateWithTimezone(undefined, timezone);
const firstEnabledMonth = utils.startOfMonth(disablePast && utils.isAfter(now, minDate) ? now : minDate);
return !utils.isBefore(firstEnabledMonth, month);
}, [disablePast, minDate, month, utils, timezone]);
}
const DAY_SIZE = 36;
const DAY_MARGIN = 2;
const DIALOG_WIDTH = 320;
const MAX_CALENDAR_HEIGHT = 280;
const VIEW_HEIGHT = 334;
const PickerViewRoot = styled$3('div')({
overflow: 'hidden',
width: DIALOG_WIDTH,
maxHeight: VIEW_HEIGHT,
display: 'flex',
flexDirection: 'column',
margin: '0 auto'
});
const findClosestEnabledDate = ({
date,
disableFuture,
disablePast,
maxDate,
minDate,
isDateDisabled,
utils,
timezone
}) => {
const today = utils.startOfDay(utils.dateWithTimezone(undefined, timezone));
if (disablePast && utils.isBefore(minDate, today)) {
minDate = today;
}
if (disableFuture && utils.isAfter(maxDate, today)) {
maxDate = today;
}
let forward = date;
let backward = date;
if (utils.isBefore(date, minDate)) {
forward = minDate;
backward = null;
}
if (utils.isAfter(date, maxDate)) {
if (backward) {
backward = maxDate;
}
forward = null;
}
while (forward || backward) {
if (forward && utils.isAfter(forward, maxDate)) {
forward = null;
}
if (backward && utils.isBefore(backward, minDate)) {
backward = null;
}
if (forward) {
if (!isDateDisabled(forward)) {
return forward;
}
forward = utils.addDays(forward, 1);
}
if (backward) {
if (!isDateDisabled(backward)) {
return backward;
}
backward = utils.addDays(backward, -1);
}
}
return null;
};
const replaceInvalidDateByNull = (utils, value) => value == null || !utils.isValid(value) ? null : value;
const applyDefaultDate = (utils, value, defaultValue) => {
if (value == null || !utils.isValid(value)) {
return defaultValue;
}
return value;
};
const areDatesEqual = (utils, a, b) => {
if (!utils.isValid(a) && a != null && !utils.isValid(b) && b != null) {
return true;
}
return utils.isEqual(a, b);
};
const getMonthsInYear = (utils, year) => {
const firstMonth = utils.startOfYear(year);
const months = [firstMonth];
while (months.length < 12) {
const prevMonth = months[months.length - 1];
months.push(utils.addMonths(prevMonth, 1));
}
return months;
};
const mergeDateAndTime = (utils, dateParam, timeParam) => {
let mergedDate = dateParam;
mergedDate = utils.setHours(mergedDate, utils.getHours(timeParam));
mergedDate = utils.setMinutes(mergedDate, utils.getMinutes(timeParam));
mergedDate = utils.setSeconds(mergedDate, utils.getSeconds(timeParam));
return mergedDate;
};
const getTodayDate = (utils, timezone, valueType) => valueType === 'date' ? utils.startOfDay(utils.dateWithTimezone(undefined, timezone)) : utils.dateWithTimezone(undefined, timezone);
const dateViews = ['year', 'month', 'day'];
const isDatePickerView = view => dateViews.includes(view);
const resolveDateFormat = (utils, {
format,
views
}, isInToolbar) => {
if (format != null) {
return format;
}
const formats = utils.formats;
if (areViewsEqual(views, ['year'])) {
return formats.year;
}
if (areViewsEqual(views, ['month'])) {
return formats.month;
}
if (areViewsEqual(views, ['day'])) {
return formats.dayOfMonth;
}
if (areViewsEqual(views, ['month', 'year'])) {
return `${formats.month} ${formats.year}`;
}
if (areViewsEqual(views, ['day', 'month'])) {
return `${formats.month} ${formats.dayOfMonth}`;
}
if (isInToolbar) {
// Little localization hack (Google is doing the same for android native pickers):
// For english localization it is convenient to include weekday into the date "Mon, Jun 1".
// For other locales using strings like "June 1", without weekday.
return /en/.test(utils.getCurrentLocaleCode()) ? formats.normalDateWithWeekday : formats.normalDate;
}
return formats.keyboardDate;
};
const getWeekdays = (utils, date) => {
const start = utils.startOfWeek(date);
return [0, 1, 2, 3, 4, 5, 6].map(diff => utils.addDays(start, diff));
};
/**
* Hooks making sure that:
* - The value returned by `onChange` always have the timezone of `props.value` or `props.defaultValue` if defined
* - The value rendered is always the one from `props.timezone` if defined
*/
const useValueWithTimezone = ({
timezone: timezoneProp,
value: valueProp,
defaultValue,
onChange,
valueManager
}) => {
var _ref, _ref2;
const utils = useUtils();
const firstDefaultValue = React.useRef(defaultValue);
const inputValue = (_ref = valueProp != null ? valueProp : firstDefaultValue.current) != null ? _ref : valueManager.emptyValue;
const inputTimezone = React.useMemo(() => valueManager.getTimezone(utils, inputValue), [utils, valueManager, inputValue]);
const setInputTimezone = useEventCallback(newValue => {
if (inputTimezone == null) {
return newValue;
}
return valueManager.setTimezone(utils, inputTimezone, newValue);
});
const timezoneToRender = (_ref2 = timezoneProp != null ? timezoneProp : inputTimezone) != null ? _ref2 : 'default';
const valueWithTimezoneToRender = React.useMemo(() => valueManager.setTimezone(utils, timezoneToRender, inputValue), [valueManager, utils, timezoneToRender, inputValue]);
const handleValueChange = useEventCallback((newValue, ...otherParams) => {
const newValueWithInputTimezone = setInputTimezone(newValue);
onChange == null || onChange(newValueWithInputTimezone, ...otherParams);
});
return {
value: valueWithTimezoneToRender,
handleValueChange,
timezone: timezoneToRender
};
};
/**
* Wrapper around `useControlled` and `useValueWithTimezone`
*/
const useControlledValueWithTimezone = ({
name,
timezone: timezoneProp,
value: valueProp,
defaultValue,
onChange: onChangeProp,
valueManager
}) => {
const [valueWithInputTimezone, setValue] = useControlled({
name,
state: 'value',
controlled: valueProp,
default: defaultValue != null ? defaultValue : valueManager.emptyValue
});
const onChange = useEventCallback((newValue, ...otherParams) => {
setValue(newValue);
onChangeProp == null || onChangeProp(newValue, ...otherParams);
});
return useValueWithTimezone({
timezone: timezoneProp,
value: valueWithInputTimezone,
defaultValue: undefined,
onChange,
valueManager
});
};
const SECTION_TYPE_GRANULARITY = {
year: 1,
month: 2,
day: 3,
hours: 4,
minutes: 5,
seconds: 6,
milliseconds: 7
};
const getSectionTypeGranularity = sections => Math.max(...sections.map(section => {
var _SECTION_TYPE_GRANULA;
return (_SECTION_TYPE_GRANULA = SECTION_TYPE_GRANULARITY[section.type]) != null ? _SECTION_TYPE_GRANULA : 1;
}));
const roundDate = (utils, granularity, date) => {
if (granularity === SECTION_TYPE_GRANULARITY.year) {
return utils.startOfYear(date);
}
if (granularity === SECTION_TYPE_GRANULARITY.month) {
return utils.startOfMonth(date);
}
if (granularity === SECTION_TYPE_GRANULARITY.day) {
return utils.startOfDay(date);
}
// We don't have startOfHour / startOfMinute / startOfSecond
let roundedDate = date;
if (granularity < SECTION_TYPE_GRANULARITY.minutes) {
roundedDate = utils.setMinutes(roundedDate, 0);
}
if (granularity < SECTION_TYPE_GRANULARITY.seconds) {
roundedDate = utils.setSeconds(roundedDate, 0);
}
if (granularity < SECTION_TYPE_GRANULARITY.milliseconds) {
roundedDate = utils.setMilliseconds(roundedDate, 0);
}
return roundedDate;
};
const getDefaultReferenceDate = ({
props,
utils,
granularity,
timezone,
getTodayDate: inGetTodayDate
}) => {
var _props$disableIgnorin;
let referenceDate = inGetTodayDate ? inGetTodayDate() : roundDate(utils, granularity, getTodayDate(utils, timezone));
if (props.minDate != null && utils.isAfterDay(props.minDate, referenceDate)) {
referenceDate = roundDate(utils, granularity, props.minDate);
}
if (props.maxDate != null && utils.isBeforeDay(props.maxDate, referenceDate)) {
referenceDate = roundDate(utils, granularity, props.maxDate);
}
const isAfter = createIsAfterIgnoreDatePart((_props$disableIgnorin = props.disableIgnoringDatePartForTimeValidation) != null ? _props$disableIgnorin : false, utils);
if (props.minTime != null && isAfter(props.minTime, referenceDate)) {
referenceDate = roundDate(utils, granularity, props.disableIgnoringDatePartForTimeValidation ? props.minTime : mergeDateAndTime(utils, referenceDate, props.minTime));
}
if (props.maxTime != null && isAfter(referenceDate, props.maxTime)) {
referenceDate = roundDate(utils, granularity, props.disableIgnoringDatePartForTimeValidation ? props.maxTime : mergeDateAndTime(utils, referenceDate, props.maxTime));
}
return referenceDate;
};
const getDateSectionConfigFromFormatToken = (utils, formatToken) => {
const config = utils.formatTokenMap[formatToken];
if (config == null) {
throw new Error([`MUI: The token "${formatToken}" is not supported by the Date and Time Pickers.`, 'Please try using another token or open an issue on https://github.com/mui/mui-x/issues/new/choose if you think it should be supported.'].join('\n'));
}
if (typeof config === 'string') {
return {
type: config,
contentType: config === 'meridiem' ? 'letter' : 'digit',
maxLength: undefined
};
}
return {
type: config.sectionType,
contentType: config.contentType,
maxLength: config.maxLength
};
};
const getDeltaFromKeyCode = keyCode => {
switch (keyCode) {
case 'ArrowUp':
return 1;
case 'ArrowDown':
return -1;
case 'PageUp':
return 5;
case 'PageDown':
return -5;
default:
return 0;
}
};
const getDaysInWeekStr = (utils, timezone, format) => {
const elements = [];
const now = utils.dateWithTimezone(undefined, timezone);
const startDate = utils.startOfWeek(now);
const endDate = utils.endOfWeek(now);
let current = startDate;
while (utils.isBefore(current, endDate)) {
elements.push(current);
current = utils.addDays(current, 1);
}
return elements.map(weekDay => utils.formatByString(weekDay, format));
};
const getLetterEditingOptions = (utils, timezone, sectionType, format) => {
switch (sectionType) {
case 'month':
{
return getMonthsInYear(utils, utils.dateWithTimezone(undefined, timezone)).map(month => utils.formatByString(month, format));
}
case 'weekDay':
{
return getDaysInWeekStr(utils, timezone, format);
}
case 'meridiem':
{
const now = utils.dateWithTimezone(undefined, timezone);
return [utils.startOfDay(now), utils.endOfDay(now)].map(date => utils.formatByString(date, format));
}
default:
{
return [];
}
}
};
const cleanLeadingZeros = (utils, valueStr, size) => {
let cleanValueStr = valueStr;
// Remove the leading zeros
cleanValueStr = Number(cleanValueStr).toString();
// Add enough leading zeros to fill the section
while (cleanValueStr.length < size) {
cleanValueStr = `0${cleanValueStr}`;
}
return cleanValueStr;
};
const cleanDigitSectionValue = (utils, timezone, value, sectionBoundaries, section) => {
if (process.env.NODE_ENV !== 'production') {
if (section.type !== 'day' && section.contentType === 'digit-with-letter') {
throw new Error([`MUI: The token "${section.format}" is a digit format with letter in it.'
This type of format is only supported for 'day' sections`].join('\n'));
}
}
if (section.type === 'day' && section.contentType === 'digit-with-letter') {
const date = utils.setDate(sectionBoundaries.longestMonth, value);
return utils.formatByString(date, section.format);
}
// queryValue without leading `0` (`01` => `1`)
const valueStr = value.toString();
if (section.hasLeadingZerosInInput) {
return cleanLeadingZeros(utils, valueStr, section.maxLength);
}
return valueStr;
};
const adjustSectionValue = (utils, timezone, section, keyCode, sectionsValueBoundaries, activeDate, stepsAttributes) => {
const delta = getDeltaFromKeyCode(keyCode);
const isStart = keyCode === 'Home';
const isEnd = keyCode === 'End';
const shouldSetAbsolute = section.value === '' || isStart || isEnd;
const adjustDigitSection = () => {
const sectionBoundaries = sectionsValueBoundaries[section.type]({
currentDate: activeDate,
format: section.format,
contentType: section.contentType
});
const getCleanValue = value => cleanDigitSectionValue(utils, timezone, value, sectionBoundaries, section);
const step = section.type === 'minutes' && stepsAttributes != null && stepsAttributes.minutesStep ? stepsAttributes.minutesStep : 1;
const currentSectionValue = parseInt(section.value, 10);
let newSectionValueNumber = currentSectionValue + delta * step;
if (shouldSetAbsolute) {
if (section.type === 'year' && !isEnd && !isStart) {
return utils.formatByString(utils.dateWithTimezone(undefined, timezone), section.format);
}
if (delta > 0 || isStart) {
newSectionValueNumber = sectionBoundaries.minimum;
} else {
newSectionValueNumber = sectionBoundaries.maximum;
}
}
if (newSectionValueNumber % step !== 0) {
if (delta < 0 || isStart) {
newSectionValueNumber += step - (step + newSectionValueNumber) % step; // for JS -3 % 5 = -3 (should be 2)
}
if (delta > 0 || isEnd) {
newSectionValueNumber -= newSectionValueNumber % step;
}
}
if (newSectionValueNumber > sectionBoundaries.maximum) {
return getCleanValue(sectionBoundaries.minimum + (newSectionValueNumber - sectionBoundaries.maximum - 1) % (sectionBoundaries.maximum - sectionBoundaries.minimum + 1));
}
if (newSectionValueNumber < sectionBoundaries.minimum) {
return getCleanValue(sectionBoundaries.maximum - (sectionBoundaries.minimum - newSectionValueNumber - 1) % (sectionBoundaries.maximum - sectionBoundaries.minimum + 1));
}
return getCleanValue(newSectionValueNumber);
};
const adjustLetterSection = () => {
const options = getLetterEditingOptions(utils, timezone, section.type, section.format);
if (options.length === 0) {
return section.value;
}
if (shouldSetAbsolute) {
if (delta > 0 || isStart) {
return options[0];
}
return options[options.length - 1];
}
const currentOptionIndex = options.indexOf(section.value);
const newOptionIndex = (currentOptionIndex + options.length + delta) % options.length;
return options[newOptionIndex];
};
if (section.contentType === 'digit' || section.contentType === 'digit-with-letter') {
return adjustDigitSection();
}
return adjustLetterSection();
};
const getSectionVisibleValue = (section, target) => {
let value = section.value || section.placeholder;
const hasLeadingZeros = target === 'non-input' ? section.hasLeadingZerosInFormat : section.hasLeadingZerosInInput;
if (target === 'non-input' && section.hasLeadingZerosInInput && !section.hasLeadingZerosInFormat) {
value = Number(value).toString();
}
// In the input, we add an empty character at the end of each section without leading zeros.
// This makes sure that `onChange` will always be fired.
// Otherwise, when your input value equals `1/dd/yyyy` (format `M/DD/YYYY` on DayJs),
// If you press `1`, on the first section, the new value is also `1/dd/yyyy`,
// So the browser will not fire the input `onChange`.
const shouldAddInvisibleSpace = ['input-rtl', 'input-ltr'].includes(target) && section.contentType === 'digit' && !hasLeadingZeros && value.length === 1;
if (shouldAddInvisibleSpace) {
value = `${value}\u200e`;
}
if (target === 'input-rtl') {
value = `\u2068${value}\u2069`;
}
return value;
};
const cleanString = dirtyString => dirtyString.replace(/[\u2066\u2067\u2068\u2069]/g, '');
const addPositionPropertiesToSections = (sections, isRTL) => {
let position = 0;
let positionInInput = isRTL ? 1 : 0;
const newSections = [];
for (let i = 0; i < sections.length; i += 1) {
const section = sections[i];
const renderedValue = getSectionVisibleValue(section, isRTL ? 'input-rtl' : 'input-ltr');
const sectionStr = `${section.startSeparator}${renderedValue}${section.endSeparator}`;
const sectionLength = cleanString(sectionStr).length;
const sectionLengthInInput = sectionStr.length;
// The ...InInput values consider the unicode characters but do include them in their indexes
const cleanedValue = cleanString(renderedValue);
const startInInput = positionInInput + renderedValue.indexOf(cleanedValue[0]) + section.startSeparator.length;
const endInInput = startInInput + cleanedValue.length;
newSections.push(_extends({}, section, {
start: position,
end: position + sectionLength,
startInInput,
endInInput
}));
position += sectionLength;
// Move position to the end of string associated to the current section
positionInInput += sectionLengthInInput;
}
return newSections;
};
const getSectionPlaceholder = (utils, timezone, localeText, sectionConfig, sectionFormat) => {
switch (sectionConfig.type) {
case 'year':
{
return localeText.fieldYearPlaceholder({
digitAmount: utils.formatByString(utils.dateWithTimezone(undefined, timezone), sectionFormat).length,
format: sectionFormat
});
}
case 'month':
{
return localeText.fieldMonthPlaceholder({
contentType: sectionConfig.contentType,
format: sectionFormat
});
}
case 'day':
{
return localeText.fieldDayPlaceholder({
format: sectionFormat
});
}
case 'weekDay':
{
return localeText.fieldWeekDayPlaceholder({
contentType: sectionConfig.contentType,
format: sectionFormat
});
}
case 'hours':
{
return localeText.fieldHoursPlaceholder({
format: sectionFormat
});
}
case 'minutes':
{
return localeText.fieldMinutesPlaceholder({
format: sectionFormat
});
}
case 'seconds':
{
return localeText.fieldSecondsPlaceholder({
format: sectionFormat
});
}
case 'meridiem':
{
return localeText.fieldMeridiemPlaceholder({
format: sectionFormat
});
}
default:
{
return sectionFormat;
}
}
};
const changeSectionValueFormat = (utils, valueStr, currentFormat, newFormat) => {
if (process.env.NODE_ENV !== 'production') {
if (getDateSectionConfigFromFormatToken(utils, currentFormat).type === 'weekDay') {
throw new Error("changeSectionValueFormat doesn't support week day formats");
}
}
return utils.formatByString(utils.parse(valueStr, currentFormat), newFormat);
};
const isFourDigitYearFormat = (utils, timezone, format) => utils.formatByString(utils.dateWithTimezone(undefined, timezone), format).length === 4;
const doesSectionFormatHaveLeadingZeros = (utils, timezone, contentType, sectionType, format) => {
if (contentType !== 'digit') {
return false;
}
const now = utils.dateWithTimezone(undefined, timezone);
switch (sectionType) {
// We can't use `changeSectionValueFormat`, because `utils.parse('1', 'YYYY')` returns `1971` instead of `1`.
case 'year':
{
if (isFourDigitYearFormat(utils, timezone, format)) {
const formatted0001 = utils.formatByString(utils.setYear(now, 1), format);
return formatted0001 === '0001';
}
const formatted2001 = utils.formatByString(utils.setYear(now, 2001), format);
return formatted2001 === '01';
}
case 'month':
{
return utils.formatByString(utils.startOfYear(now), format).length > 1;
}
case 'day':
{
return utils.formatByString(utils.startOfMonth(now), format).length > 1;
}
case 'weekDay':
{
return utils.formatByString(utils.startOfWeek(now), format).length > 1;
}
case 'hours':
{
return utils.formatByString(utils.setHours(now, 1), format).length > 1;
}
case 'minutes':
{
return utils.formatByString(utils.setMinutes(now, 1), format).length > 1;
}
case 'seconds':
{
return utils.formatByString(utils.setSeconds(now, 1), format).length > 1;
}
default:
{
throw new Error('Invalid section type');
}
}
};
const getEscapedPartsFromFormat = (utils, format) => {
const escapedParts = [];
const {
start: startChar,
end: endChar
} = utils.escapedCharacters;
const regExp = new RegExp(`(\\${startChar}[^\\${endChar}]*\\${endChar})+`, 'g');
let match = null;
// eslint-disable-next-line no-cond-assign
while (match = regExp.exec(format)) {
escapedParts.push({
start: match.index,
end: regExp.lastIndex - 1
});
}
return escapedParts;
};
const splitFormatIntoSections = (utils, timezone, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL) => {
let startSeparator = '';
const sections = [];
const now = utils.date();
const commitToken = token => {
if (token === '') {
return null;
}
const sectionConfig = getDateSectionConfigFromFormatToken(utils, token);
const hasLeadingZerosInFormat = doesSectionFormatHaveLeadingZeros(utils, timezone, sectionConfig.contentType, sectionConfig.type, token);
const hasLeadingZerosInInput = shouldRespectLeadingZeros ? hasLeadingZerosInFormat : sectionConfig.contentType === 'digit';
const isValidDate = date != null && utils.isValid(date);
let sectionValue = isValidDate ? utils.formatByString(date, token) : '';
let maxLength = null;
if (hasLeadingZerosInInput) {
if (hasLeadingZerosInFormat) {
maxLength = sectionValue === '' ? utils.formatByString(now, token).length : sectionValue.length;
} else {
if (sectionConfig.maxLength == null) {
throw new Error(`MUI: The token ${token} should have a 'maxDigitNumber' property on it's adapter`);
}
maxLength = sectionConfig.maxLength;
if (isValidDate) {
sectionValue = cleanLeadingZeros(utils, sectionValue, maxLength);
}
}
}
sections.push(_extends({}, sectionConfig, {
format: token,
maxLength,
value: sectionValue,
placeholder: getSectionPlaceholder(utils, timezone, localeText, sectionConfig, token),
hasLeadingZeros: hasLeadingZerosInFormat,
hasLeadingZerosInFormat,
hasLeadingZerosInInput,
startSeparator: sections.length === 0 ? startSeparator : '',
endSeparator: '',
modified: false
}));
return null;
};
// Expand the provided format
let formatExpansionOverflow = 10;
let prevFormat = format;
let nextFormat = utils.expandFormat(format);
while (nextFormat !== prevFormat) {
prevFormat = nextFormat;
nextFormat = utils.expandFormat(prevFormat);
formatExpansionOverflow -= 1;
if (formatExpansionOverflow < 0) {
throw new Error('MUI: The format expansion seems to be enter in an infinite loop. Please open an issue with the format passed to the picker component');
}
}
const expandedFormat = nextFormat;
// Get start/end indexes of escaped sections
const escapedParts = getEscapedPartsFromFormat(utils, expandedFormat);
// This RegExp test if the beginning of a string correspond to a supported token
const isTokenStartRegExp = new RegExp(`^(${Object.keys(utils.formatTokenMap).sort((a, b) => b.length - a.length) // Sort to put longest word first
.join('|')})`, 'g') // used to get access to lastIndex state
;
let currentTokenValue = '';
for (let i = 0; i < expandedFormat.length; i += 1) {
const escapedPartOfCurrentChar = escapedParts.find(escapeIndex => escapeIndex.start <= i && escapeIndex.end >= i);
const char = expandedFormat[i];
const isEscapedChar = escapedPartOfCurrentChar != null;
const potentialToken = `${currentTokenValue}${expandedFormat.slice(i)}`;
const regExpMatch = isTokenStartRegExp.test(potentialToken);
if (!isEscapedChar && char.match(/([A-Za-z]+)/) && regExpMatch) {
currentTokenValue = potentialToken.slice(0, isTokenStartRegExp.lastIndex);
i += isTokenStartRegExp.lastIndex - 1;
} else {
// If we are on the opening or closing character of an escaped part of the format,
// Then we ignore this character.
const isEscapeBoundary = isEscapedChar && (escapedPartOfCurrentChar == null ? void 0 : escapedPartOfCurrentChar.start) === i || (escapedPartOfCurrentChar == null ? void 0 : escapedPartOfCurrentChar.end) === i;
if (!isEscapeBoundary) {
commitToken(currentTokenValue);
currentTokenValue = '';
if (sections.length === 0) {
startSeparator += char;
} else {
sections[sections.length - 1].endSeparator += char;
}
}
}
}
commitToken(currentTokenValue);
return sections.map(section => {
const cleanSeparator = separator => {
let cleanedSeparator = separator;
if (isRTL && cleanedSeparator !== null && cleanedSeparator.includes(' ')) {
cleanedSeparator = `\u2069${cleanedSeparator}\u2066`;
}
if (formatDensity === 'spacious' && ['/', '.', '-'].includes(cleanedSeparator)) {
cleanedSeparator = ` ${cleanedSeparator} `;
}
return cleanedSeparator;
};
section.startSeparator = cleanSeparator(section.startSeparator);
section.endSeparator = cleanSeparator(section.endSeparator);
return section;
});
};
/**
* Some date libraries like `dayjs` don't support parsing from date with escaped characters.
* To make sure that the parsing works, we are building a format and a date without any separator.
*/
const getDateFromDateSections = (utils, sections) => {
// If we have both a day and a weekDay section,
// Then we skip the weekDay in the parsing because libraries like dayjs can't parse complicated formats containing a weekDay.
// dayjs(dayjs().format('dddd MMMM D YYYY'), 'dddd MMMM D YYYY')) // returns `Invalid Date` even if the format is valid.
const shouldSkipWeekDays = sections.some(section => section.type === 'day');
const sectionFormats = [];
const sectionValues = [];
for (let i = 0; i < sections.length; i += 1) {
const section = sections[i];
const shouldSkip = shouldSkipWeekDays && section.type === 'weekDay';
if (!shouldSkip) {
sectionFormats.push(section.format);
sectionValues.push(getSectionVisibleValue(section, 'non-input'));
}
}
const formatWithoutSeparator = sectionFormats.join(' ');
const dateWithoutSeparatorStr = sectionValues.join(' ');
return utils.parse(dateWithoutSeparatorStr, formatWithoutSeparator);
};
const createDateStrForInputFromSections = (sections, isRTL) => {
const formattedSections = sections.map(section => {
const dateValue = getSectionVisibleValue(section, isRTL ? 'input-rtl' : 'input-ltr');
return `${section.startSeparator}${dateValue}${section.endSeparator}`;
});
const dateStr = formattedSections.join('');
if (!isRTL) {
return dateStr;
}
// \u2066: start left-to-right isolation
// \u2067: start right-to-left isolation
// \u2068: start first strong character isolation
// \u2069: pop isolation
// wrap into an isolated group such that separators can split the string in smaller ones by adding \u2069\u2068
return `\u2066${dateStr}\u2069`;
};
const getSectionsBoundaries = (utils, timezone) => {
const today = utils.dateWithTimezone(undefined, timezone);
const endOfYear = utils.endOfYear(today);
const endOfDay = utils.endOfDay(today);
const {
maxDaysInMonth,
longestMonth
} = getMonthsInYear(utils, today).reduce((acc, month) => {
const daysInMonth = utils.getDaysInMonth(month);
if (daysInMonth > acc.maxDaysInMonth) {
return {
maxDaysInMonth: daysInMonth,
longestMonth: month
};
}
return acc;
}, {
maxDaysInMonth: 0,
longestMonth: null
});
return {
year: ({
format
}) => ({
minimum: 0,
maximum: isFourDigitYearFormat(utils, timezone, format) ? 9999 : 99
}),
month: () => ({
minimum: 1,
// Assumption: All years have the same amount of months
maximum: utils.getMonth(endOfYear) + 1
}),
day: ({
currentDate
}) => ({
minimum: 1,
maximum: currentDate != null && utils.isValid(currentDate) ? utils.getDaysInMonth(currentDate) : maxDaysInMonth,
longestMonth: longestMonth
}),
weekDay: ({
format,
contentType
}) => {
if (contentType === 'digit') {
const daysInWeek = getDaysInWeekStr(utils, timezone, format).map(Number);
return {
minimum: Math.min(...daysInWeek),
maximum: Math.max(...daysInWeek)
};
}
return {
minimum: 1,
maximum: 7
};
},
hours: ({
format
}) => {
const lastHourInDay = utils.getHours(endOfDay);
const hasMeridiem = utils.formatByString(utils.endOfDay(today), format) !== lastHourInDay.toString();
if (hasMeridiem) {
return {
minimum: 1,
maximum: Number(utils.formatByString(utils.startOfDay(today), format))
};
}
return {
minimum: 0,
maximum: lastHourInDay
};
},
minutes: () => ({
minimum: 0,
// Assumption: All years have the same amount of minutes
maximum: utils.getMinutes(endOfDay)
}),
seconds: () => ({
minimum: 0,
// Assumption: All years have the same amount of seconds
maximum: utils.getSeconds(endOfDay)
}),
meridiem: () => ({
minimum: 0,
maximum: 0
})
};
};
let warnedOnceInvalidSection = false;
const validateSections = (sections, valueType) => {
if (process.env.NODE_ENV !== 'production') {
if (!warnedOnceInvalidSection) {
const supportedSections = [];
if (['date', 'date-time'].includes(valueType)) {
supportedSections.push('weekDay', 'day', 'month', 'year');
}
if (['time', 'date-time'].includes(valueType)) {
supportedSections.push('hours', 'minutes', 'seconds', 'meridiem');
}
const invalidSection = sections.find(section => !supportedSections.includes(section.type));
if (invalidSection) {
console.warn(`MUI: The field component you are using is not compatible with the "${invalidSection.type} date section.`, `The supported date sections are ["${supportedSections.join('", "')}"]\`.`);
warnedOnceInvalidSection = true;
}
}
}
};
const transferDateSectionValue = (utils, timezone, section, dateToTransferFrom, dateToTransferTo) => {
switch (section.type) {
case 'year':
{
return utils.setYear(dateToTransferTo, utils.getYear(dateToTransferFrom));
}
case 'month':
{
return utils.setMonth(dateToTransferTo, utils.getMonth(dateToTransferFrom));
}
case 'weekDay':
{
const formattedDaysInWeek = getDaysInWeekStr(utils, timezone, section.format);
const dayInWeekStrOfActiveDate = utils.formatByString(dateToTransferFrom, section.format);
const dayInWeekOfActiveDate = formattedDaysInWeek.indexOf(dayInWeekStrOfActiveDate);
const dayInWeekOfNewSectionValue = formattedDaysInWeek.indexOf(section.value);
const diff = dayInWeekOfNewSectionValue - dayInWeekOfActiveDate;
return utils.addDays(dateToTransferFrom, diff);
}
case 'day':
{
return utils.setDate(dateToTransferTo, utils.getDate(dateToTransferFrom));
}
case 'meridiem':
{
const isAM = utils.getHours(dateToTransferFrom) < 12;
const mergedDateHours = utils.getHours(dateToTransferTo);
if (isAM && mergedDateHours >= 12) {
return utils.addHours(dateToTransferTo, -12);
}
if (!isAM && mergedDateHours < 12) {
return utils.addHours(dateToTransferTo, 12);
}
return dateToTransferTo;
}
case 'hours':
{
return utils.setHours(dateToTransferTo, utils.getHours(dateToTransferFrom));
}
case 'minutes':
{
return utils.setMinutes(dateToTransferTo, utils.getMinutes(dateToTransferFrom));
}
case 'seconds':
{
return utils.setSeconds(dateToTransferTo, utils.getSeconds(dateToTransferFrom));
}
default:
{
return dateToTransferTo;
}
}
};
const reliableSectionModificationOrder = {
year: 1,
month: 2,
day: 3,
weekDay: 4,
hours: 5,
minutes: 6,
seconds: 7,
meridiem: 8
};
const mergeDateIntoReferenceDate = (utils, timezone, dateToTransferFrom, sections, referenceDate, shouldLimitToEditedSections) =>
// cloning sections before sort to avoid mutating it
[...sections].sort((a, b) => reliableSectionModificationOrder[a.type] - reliableSectionModificationOrder[b.type]).reduce((mergedDate, section) => {
if (!shouldLimitToEditedSections || section.modified) {
return transferDateSectionValue(utils, timezone, section, dateToTransferFrom, mergedDate);
}
return mergedDate;
}, referenceDate);
const isAndroid = () => navigator.userAgent.toLowerCase().indexOf('android') > -1;
const getSectionOrder = (sections, isRTL) => {
const neighbors = {};
if (!isRTL) {
sections.forEach((_, index) => {
const leftIndex = index === 0 ? null : index - 1;
const rightIndex = index === sections.length - 1 ? null : index + 1;
neighbors[index] = {
leftIndex,
rightIndex
};
});
return {
neighbors,
startIndex: 0,
endIndex: sections.length - 1
};
}
const rtl2ltr = {};
const ltr2rtl = {};
let groupedSectionsStart = 0;
let groupedSectionsEnd = 0;
let RTLIndex = sections.length - 1;
while (RTLIndex >= 0) {
groupedSectionsEnd = sections.findIndex(
// eslint-disable-next-line @typescript-eslint/no-loop-func
(section, index) => {
var _section$endSeparator;
return index >= groupedSectionsStart && ((_section$endSeparator = section.endSeparator) == null ? void 0 : _section$endSeparator.includes(' ')) &&
// Special case where the spaces were not there in the initial input
section.endSeparator !== ' / ';
});
if (groupedSectionsEnd === -1) {
groupedSectionsEnd = sections.length - 1;
}
for (let i = groupedSectionsEnd; i >= groupedSectionsStart; i -= 1) {
ltr2rtl[i] = RTLIndex;
rtl2ltr[RTLIndex] = i;
RTLIndex -= 1;
}
groupedSectionsStart = groupedSectionsEnd + 1;
}
sections.forEach((_, index) => {
const rtlIndex = ltr2rtl[index];
const leftIndex = rtlIndex === 0 ? null : rtl2ltr[rtlIndex - 1];
const rightIndex = rtlIndex === sections.length - 1 ? null : rtl2ltr[rtlIndex + 1];
neighbors[index] = {
leftIndex,
rightIndex
};
});
return {
neighbors,
startIndex: rtl2ltr[0],
endIndex: rtl2ltr[sections.length - 1]
};
};
const _excluded$n = ["value", "referenceDate"];
const singleItemValueManager = {
emptyValue: null,
getTodayValue: getTodayDate,
getInitialReferenceValue: _ref => {
let {
value,
referenceDate
} = _ref,
params = _objectWithoutPropertiesLoose$1(_ref, _excluded$n);
if (value != null && params.utils.isValid(value)) {
return value;
}
if (referenceDate != null) {
return referenceDate;
}
return getDefaultReferenceDate(params);
},
cleanValue: replaceInvalidDateByNull,
areValuesEqual: areDatesEqual,
isSameError: (a, b) => a === b,
hasError: error => error != null,
defaultErrorState: null,
getTimezone: (utils, value) => value == null || !utils.isValid(value) ? null : utils.getTimezone(value),
setTimezone: (utils, timezone, value) => value == null ? null : utils.setTimezone(value, timezone)
};
const singleItemFieldValueManager = {
updateReferenceValue: (utils, value, prevReferenceValue) => value == null || !utils.isValid(value) ? prevReferenceValue : value,
getSectionsFromValue: (utils, date, prevSections, isRTL, getSectionsFromDate) => {
const shouldReUsePrevDateSections = !utils.isValid(date) && !!prevSections;
if (shouldReUsePrevDateSections) {
return prevSections;
}
return addPositionPropertiesToSections(getSectionsFromDate(date), isRTL);
},
getValueStrFromSections: createDateStrForInputFromSections,
getActiveDateManager: (utils, state) => ({
date: state.value,
referenceDate: state.referenceValue,
getSections: sections => sections,
getNewValuesFromNewActiveDate: newActiveDate => ({
value: newActiveDate,
referenceValue: newActiveDate == null || !utils.isValid(newActiveDate) ? state.referenceValue : newActiveDate
})
}),
parseValueStr: (valueStr, referenceValue, parseDate) => parseDate(valueStr.trim(), referenceValue)
};
// TODO v7: This file exist only to simplify typing between
// components/componentsProps and slots/slotProps
// Should be deleted when components/componentsProps are removed
const uncapitalizeObjectKeys = capitalizedObject => {
if (capitalizedObject === undefined) {
return undefined;
}
return Object.keys(capitalizedObject).reduce((acc, key) => _extends({}, acc, {
[`${key.slice(0, 1).toLowerCase()}${key.slice(1)}`]: capitalizedObject[key]
}), {});
};
function getPickersDayUtilityClass(slot) {
return generateUtilityClass('MuiPickersDay', slot);
}
const pickersDayClasses = generateUtilityClasses('MuiPickersDay', ['root', 'dayWithMargin', 'dayOutsideMonth', 'hiddenDaySpacingFiller', 'today', 'selected', 'disabled']);
const _excluded$m = ["autoFocus", "className", "day", "disabled", "disableHighlightToday", "disableMargin", "hidden", "isAnimating", "onClick", "onDaySelect", "onFocus", "onBlur", "onKeyDown", "onMouseDown", "onMouseEnter", "outsideCurrentMonth", "selected", "showDaysOutsideCurrentMonth", "children", "today", "isFirstVisibleCell", "isLastVisibleCell"];
const useUtilityClasses$e = ownerState => {
const {
selected,
disableMargin,
disableHighlightToday,
today,
disabled,
outsideCurrentMonth,
showDaysOutsideCurrentMonth,
classes
} = ownerState;
const isHiddenDaySpacingFiller = outsideCurrentMonth && !showDaysOutsideCurrentMonth;
const slots = {
root: ['root', selected && !isHiddenDaySpacingFiller && 'selected', disabled && 'disabled', !disableMargin && 'dayWithMargin', !disableHighlightToday && today && 'today', outsideCurrentMonth && showDaysOutsideCurrentMonth && 'dayOutsideMonth', isHiddenDaySpacingFiller && 'hiddenDaySpacingFiller'],
hiddenDaySpacingFiller: ['hiddenDaySpacingFiller']
};
return composeClasses(slots, getPickersDayUtilityClass, classes);
};
const styleArg = ({
theme,
ownerState
}) => _extends({}, theme.typography.caption, {
width: DAY_SIZE,
height: DAY_SIZE,
borderRadius: '50%',
padding: 0,
// explicitly setting to `transparent` to avoid potentially getting impacted by change from the overridden component
backgroundColor: 'transparent',
transition: theme.transitions.create('background-color', {
duration: theme.transitions.duration.short
}),
color: (theme.vars || theme).palette.text.primary,
'@media (pointer: fine)': {
'&:hover': {
backgroundColor: theme.vars ? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.hoverOpacity})` : alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity)
}
},
'&:focus': {
backgroundColor: theme.vars ? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.focusOpacity})` : alpha(theme.palette.primary.main, theme.palette.action.focusOpacity),
[`&.${pickersDayClasses.selected}`]: {
willChange: 'background-color',
backgroundColor: (theme.vars || theme).palette.primary.dark
}
},
[`&.${pickersDayClasses.selected}`]: {
color: (theme.vars || theme).palette.primary.contrastText,
backgroundColor: (theme.vars || theme).palette.primary.main,
fontWeight: theme.typography.fontWeightMedium,
'&:hover': {
willChange: 'background-color',
backgroundColor: (theme.vars || theme).palette.primary.dark
}
},
[`&.${pickersDayClasses.disabled}:not(.${pickersDayClasses.selected})`]: {
color: (theme.vars || theme).palette.text.disabled
},
[`&.${pickersDayClasses.disabled}&.${pickersDayClasses.selected}`]: {
opacity: 0.6
}
}, !ownerState.disableMargin && {
margin: `0 ${DAY_MARGIN}px`
}, ownerState.outsideCurrentMonth && ownerState.showDaysOutsideCurrentMonth && {
color: (theme.vars || theme).palette.text.secondary
}, !ownerState.disableHighlightToday && ownerState.today && {
[`&:not(.${pickersDayClasses.selected})`]: {
border: `1px solid ${(theme.vars || theme).palette.text.secondary}`
}
});
const overridesResolver = (props, styles) => {
const {
ownerState
} = props;
return [styles.root, !ownerState.disableMargin && styles.dayWithMargin, !ownerState.disableHighlightToday && ownerState.today && styles.today, !ownerState.outsideCurrentMonth && ownerState.showDaysOutsideCurrentMonth && styles.dayOutsideMonth, ownerState.outsideCurrentMonth && !ownerState.showDaysOutsideCurrentMonth && styles.hiddenDaySpacingFiller];
};
const PickersDayRoot = styled$3(ButtonBase, {
name: 'MuiPickersDay',
slot: 'Root',
overridesResolver
})(styleArg);
const PickersDayFiller = styled$3('div', {
name: 'MuiPickersDay',
slot: 'Root',
overridesResolver
})(({
theme,
ownerState
}) => _extends({}, styleArg({
theme,
ownerState
}), {
// visibility: 'hidden' does not work here as it hides the element from screen readers as well
opacity: 0,
pointerEvents: 'none'
}));
const noop$1 = () => {};
const PickersDayRaw = /*#__PURE__*/React.forwardRef(function PickersDay(inProps, forwardedRef) {
const props = useThemeProps({
props: inProps,
name: 'MuiPickersDay'
});
const {
autoFocus = false,
className,
day,
disabled = false,
disableHighlightToday = false,
disableMargin = false,
isAnimating,
onClick,
onDaySelect,
onFocus = noop$1,
onBlur = noop$1,
onKeyDown = noop$1,
onMouseDown = noop$1,
onMouseEnter = noop$1,
outsideCurrentMonth,
selected = false,
showDaysOutsideCurrentMonth = false,
children,
today: isToday = false
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$m);
const ownerState = _extends({}, props, {
autoFocus,
disabled,
disableHighlightToday,
disableMargin,
selected,
showDaysOutsideCurrentMonth,
today: isToday
});
const classes = useUtilityClasses$e(ownerState);
const utils = useUtils();
const ref = React.useRef(null);
const handleRef = useForkRef(ref, forwardedRef);
// Since this is rendered when a Popper is opened we can't use passive effects.
// Focusing in passive effects in Popper causes scroll jump.
useEnhancedEffect$1(() => {
if (autoFocus && !disabled && !isAnimating && !outsideCurrentMonth) {
// ref.current being null would be a bug in MUI
ref.current.focus();
}
}, [autoFocus, disabled, isAnimating, outsideCurrentMonth]);
// For day outside of current month, move focus from mouseDown to mouseUp
// Goal: have the onClick ends before sliding to the new month
const handleMouseDown = event => {
onMouseDown(event);
if (outsideCurrentMonth) {
event.preventDefault();
}
};
const handleClick = event => {
if (!disabled) {
onDaySelect(day);
}
if (outsideCurrentMonth) {
event.currentTarget.focus();
}
if (onClick) {
onClick(event);
}
};
if (outsideCurrentMonth && !showDaysOutsideCurrentMonth) {
return /*#__PURE__*/jsx(PickersDayFiller, {
className: clsx(classes.root, classes.hiddenDaySpacingFiller, className),
ownerState: ownerState,
role: other.role
});
}
return /*#__PURE__*/jsx(PickersDayRoot, _extends({
className: clsx(classes.root, className),
ref: handleRef,
centerRipple: true,
disabled: disabled,
tabIndex: selected ? 0 : -1,
onKeyDown: event => onKeyDown(event, day),
onFocus: event => onFocus(event, day),
onBlur: event => onBlur(event, day),
onMouseEnter: event => onMouseEnter(event, day),
onClick: handleClick,
onMouseDown: handleMouseDown
}, other, {
ownerState: ownerState,
children: !children ? utils.format(day, 'dayOfMonth') : children
}));
});
process.env.NODE_ENV !== "production" ? PickersDayRaw.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* A ref for imperative actions.
* It currently only supports `focusVisible()` action.
*/
action: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
current: PropTypes.shape({
focusVisible: PropTypes.func.isRequired
})
})]),
/**
* If `true`, the ripples are centered.
* They won't start at the cursor interaction position.
* @default false
*/
centerRipple: PropTypes.bool,
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object,
className: PropTypes.string,
component: PropTypes.elementType,
/**
* The date to show.
*/
day: PropTypes.any.isRequired,
/**
* If `true`, renders as disabled.
* @default false
*/
disabled: PropTypes.bool,
/**
* If `true`, today's date is rendering without highlighting with circle.
* @default false
*/
disableHighlightToday: PropTypes.bool,
/**
* If `true`, days are rendering without margin. Useful for displaying linked range of days.
* @default false
*/
disableMargin: PropTypes.bool,
/**
* If `true`, the ripple effect is disabled.
*
* ⚠️ Without a ripple there is no styling for :focus-visible by default. Be sure
* to highlight the element by applying separate styles with the `.Mui-focusVisible` class.
* @default false
*/
disableRipple: PropTypes.bool,
/**
* If `true`, the touch ripple effect is disabled.
* @default false
*/
disableTouchRipple: PropTypes.bool,
/**
* If `true`, the base button will have a keyboard focus ripple.
* @default false
*/
focusRipple: PropTypes.bool,
/**
* This prop can help identify which element has keyboard focus.
* The class name will be applied when the element gains the focus through keyboard interaction.
* It's a polyfill for the [CSS :focus-visible selector](https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo).
* The rationale for using this feature [is explained here](https://github.com/WICG/focus-visible/blob/HEAD/explainer.md).
* A [polyfill can be used](https://github.com/WICG/focus-visible) to apply a `focus-visible` class to other components
* if needed.
*/
focusVisibleClassName: PropTypes.string,
isAnimating: PropTypes.bool,
/**
* If `true`, day is the first visible cell of the month.
* Either the first day of the month or the first day of the week depending on `showDaysOutsideCurrentMonth`.
*/
isFirstVisibleCell: PropTypes.bool.isRequired,
/**
* If `true`, day is the last visible cell of the month.
* Either the last day of the month or the last day of the week depending on `showDaysOutsideCurrentMonth`.
*/
isLastVisibleCell: PropTypes.bool.isRequired,
onBlur: PropTypes.func,
onDaySelect: PropTypes.func.isRequired,
onFocus: PropTypes.func,
/**
* Callback fired when the component is focused with a keyboard.
* We trigger a `onFocus` callback too.
*/
onFocusVisible: PropTypes.func,
onKeyDown: PropTypes.func,
onMouseEnter: PropTypes.func,
/**
* If `true`, day is outside of month and will be hidden.
*/
outsideCurrentMonth: PropTypes.bool.isRequired,
/**
* If `true`, renders as selected.
* @default false
*/
selected: PropTypes.bool,
/**
* If `true`, days outside the current month are rendered:
*
* - if `fixedWeekNumber` is defined, renders days to have the weeks requested.
*
* - if `fixedWeekNumber` is not defined, renders day to fill the first and last week of the current month.
*
* - ignored if `calendars` equals more than `1` on range pickers.
* @default false
*/
showDaysOutsideCurrentMonth: PropTypes.bool,
style: PropTypes.object,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
/**
* @default 0
*/
tabIndex: PropTypes.number,
/**
* If `true`, renders as today date.
* @default false
*/
today: PropTypes.bool,
/**
* Props applied to the `TouchRipple` element.
*/
TouchRippleProps: PropTypes.object,
/**
* A ref that points to the `TouchRipple` element.
*/
touchRippleRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
current: PropTypes.shape({
pulsate: PropTypes.func.isRequired,
start: PropTypes.func.isRequired,
stop: PropTypes.func.isRequired
})
})])
} : void 0;
/**
* Demos:
*
* - [DateCalendar](https://mui.com/x/react-date-pickers/date-calendar/)
* API:
*
* - [PickersDay API](https://mui.com/x/api/date-pickers/pickers-day/)
*/
const PickersDay = /*#__PURE__*/React.memo(PickersDayRaw);
function useValidation(props, validate, isSameError, defaultErrorState) {
const {
value,
onError
} = props;
const adapter = useLocalizationContext();
const previousValidationErrorRef = React.useRef(defaultErrorState);
const validationError = validate({
adapter,
value,
props
});
React.useEffect(() => {
if (onError && !isSameError(validationError, previousValidationErrorRef.current)) {
onError(validationError, value);
}
previousValidationErrorRef.current = validationError;
}, [isSameError, onError, previousValidationErrorRef, validationError, value]);
return validationError;
}
const useFieldState = params => {
const utils = useUtils();
const localeText = useLocaleText();
const adapter = useLocalizationContext();
const theme = useTheme$2();
const isRTL = theme.direction === 'rtl';
const {
valueManager,
fieldValueManager,
valueType,
validator,
internalProps,
internalProps: {
value: valueProp,
defaultValue,
referenceDate: referenceDateProp,
onChange,
format,
formatDensity = 'dense',
selectedSections: selectedSectionsProp,
onSelectedSectionsChange,
shouldRespectLeadingZeros = false,
timezone: timezoneProp
}
} = params;
const {
timezone,
value: valueFromTheOutside,
handleValueChange
} = useValueWithTimezone({
timezone: timezoneProp,
value: valueProp,
defaultValue,
onChange,
valueManager
});
const sectionsValueBoundaries = React.useMemo(() => getSectionsBoundaries(utils, timezone), [utils, timezone]);
const getSectionsFromValue = React.useCallback((value, fallbackSections = null) => fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, isRTL, date => splitFormatIntoSections(utils, timezone, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL)), [fieldValueManager, format, localeText, isRTL, shouldRespectLeadingZeros, utils, formatDensity, timezone]);
const placeholder = React.useMemo(() => fieldValueManager.getValueStrFromSections(getSectionsFromValue(valueManager.emptyValue), isRTL), [fieldValueManager, getSectionsFromValue, valueManager.emptyValue, isRTL]);
const [state, setState] = React.useState(() => {
const sections = getSectionsFromValue(valueFromTheOutside);
validateSections(sections, valueType);
const stateWithoutReferenceDate = {
sections,
value: valueFromTheOutside,
referenceValue: valueManager.emptyValue,
tempValueStrAndroid: null
};
const granularity = getSectionTypeGranularity(sections);
const referenceValue = valueManager.getInitialReferenceValue({
referenceDate: referenceDateProp,
value: valueFromTheOutside,
utils,
props: internalProps,
granularity,
timezone
});
return _extends({}, stateWithoutReferenceDate, {
referenceValue
});
});
const [selectedSections, innerSetSelectedSections] = useControlled({
controlled: selectedSectionsProp,
default: null,
name: 'useField',
state: 'selectedSectionIndexes'
});
const setSelectedSections = newSelectedSections => {
innerSetSelectedSections(newSelectedSections);
onSelectedSectionsChange == null || onSelectedSectionsChange(newSelectedSections);
setState(prevState => _extends({}, prevState, {
selectedSectionQuery: null
}));
};
const selectedSectionIndexes = React.useMemo(() => {
if (selectedSections == null) {
return null;
}
if (selectedSections === 'all') {
return {
startIndex: 0,
endIndex: state.sections.length - 1,
shouldSelectBoundarySelectors: true
};
}
if (typeof selectedSections === 'number') {
return {
startIndex: selectedSections,
endIndex: selectedSections
};
}
if (typeof selectedSections === 'string') {
const selectedSectionIndex = state.sections.findIndex(section => section.type === selectedSections);
return {
startIndex: selectedSectionIndex,
endIndex: selectedSectionIndex
};
}
return selectedSections;
}, [selectedSections, state.sections]);
const publishValue = ({
value,
referenceValue,
sections
}) => {
setState(prevState => _extends({}, prevState, {
sections,
value,
referenceValue,
tempValueStrAndroid: null
}));
if (valueManager.areValuesEqual(utils, state.value, value)) {
return;
}
const context = {
validationError: validator({
adapter,
value,
props: _extends({}, internalProps, {
value,
timezone
})
})
};
handleValueChange(value, context);
};
const setSectionValue = (sectionIndex, newSectionValue) => {
const newSections = [...state.sections];
newSections[sectionIndex] = _extends({}, newSections[sectionIndex], {
value: newSectionValue,
modified: true
});
return addPositionPropertiesToSections(newSections, isRTL);
};
const clearValue = () => {
publishValue({
value: valueManager.emptyValue,
referenceValue: state.referenceValue,
sections: getSectionsFromValue(valueManager.emptyValue)
});
};
const clearActiveSection = () => {
if (selectedSectionIndexes == null) {
return;
}
const activeSection = state.sections[selectedSectionIndexes.startIndex];
const activeDateManager = fieldValueManager.getActiveDateManager(utils, state, activeSection);
const nonEmptySectionCountBefore = activeDateManager.getSections(state.sections).filter(section => section.value !== '').length;
const hasNoOtherNonEmptySections = nonEmptySectionCountBefore === (activeSection.value === '' ? 0 : 1);
const newSections = setSectionValue(selectedSectionIndexes.startIndex, '');
const newActiveDate = hasNoOtherNonEmptySections ? null : utils.date(new Date(''));
const newValues = activeDateManager.getNewValuesFromNewActiveDate(newActiveDate);
if ((newActiveDate != null && !utils.isValid(newActiveDate)) !== (activeDateManager.date != null && !utils.isValid(activeDateManager.date))) {
publishValue(_extends({}, newValues, {
sections: newSections
}));
} else {
setState(prevState => _extends({}, prevState, newValues, {
sections: newSections,
tempValueStrAndroid: null
}));
}
};
const updateValueFromValueStr = valueStr => {
const parseDateStr = (dateStr, referenceDate) => {
const date = utils.parse(dateStr, format);
if (date == null || !utils.isValid(date)) {
return null;
}
const sections = splitFormatIntoSections(utils, timezone, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL);
return mergeDateIntoReferenceDate(utils, timezone, date, sections, referenceDate, false);
};
const newValue = fieldValueManager.parseValueStr(valueStr, state.referenceValue, parseDateStr);
const newReferenceValue = fieldValueManager.updateReferenceValue(utils, newValue, state.referenceValue);
publishValue({
value: newValue,
referenceValue: newReferenceValue,
sections: getSectionsFromValue(newValue, state.sections)
});
};
const updateSectionValue = ({
activeSection,
newSectionValue,
shouldGoToNextSection
}) => {
/**
* 1. Decide which section should be focused
*/
if (shouldGoToNextSection && selectedSectionIndexes && selectedSectionIndexes.startIndex < state.sections.length - 1) {
setSelectedSections(selectedSectionIndexes.startIndex + 1);
} else if (selectedSectionIndexes && selectedSectionIndexes.startIndex !== selectedSectionIndexes.endIndex) {
setSelectedSections(selectedSectionIndexes.startIndex);
}
/**
* 2. Try to build a valid date from the new section value
*/
const activeDateManager = fieldValueManager.getActiveDateManager(utils, state, activeSection);
const newSections = setSectionValue(selectedSectionIndexes.startIndex, newSectionValue);
const newActiveDateSections = activeDateManager.getSections(newSections);
const newActiveDate = getDateFromDateSections(utils, newActiveDateSections);
let values;
let shouldPublish;
/**
* If the new date is valid,
* Then we merge the value of the modified sections into the reference date.
* This makes sure that we don't lose some information of the initial date (like the time on a date field).
*/
if (newActiveDate != null && utils.isValid(newActiveDate)) {
const mergedDate = mergeDateIntoReferenceDate(utils, timezone, newActiveDate, newActiveDateSections, activeDateManager.referenceDate, true);
values = activeDateManager.getNewValuesFromNewActiveDate(mergedDate);
shouldPublish = true;
} else {
values = activeDateManager.getNewValuesFromNewActiveDate(newActiveDate);
shouldPublish = (newActiveDate != null && !utils.isValid(newActiveDate)) !== (activeDateManager.date != null && !utils.isValid(activeDateManager.date));
}
/**
* Publish or update the internal state with the new value and sections.
*/
if (shouldPublish) {
return publishValue(_extends({}, values, {
sections: newSections
}));
}
return setState(prevState => _extends({}, prevState, values, {
sections: newSections,
tempValueStrAndroid: null
}));
};
const setTempAndroidValueStr = tempValueStrAndroid => setState(prev => _extends({}, prev, {
tempValueStrAndroid
}));
React.useEffect(() => {
const sections = getSectionsFromValue(state.value);
validateSections(sections, valueType);
setState(prevState => _extends({}, prevState, {
sections
}));
}, [format, utils.locale]); // eslint-disable-line react-hooks/exhaustive-deps
React.useEffect(() => {
let shouldUpdate = false;
if (!valueManager.areValuesEqual(utils, state.value, valueFromTheOutside)) {
shouldUpdate = true;
} else {
shouldUpdate = valueManager.getTimezone(utils, state.value) !== valueManager.getTimezone(utils, valueFromTheOutside);
}
if (shouldUpdate) {
setState(prevState => _extends({}, prevState, {
value: valueFromTheOutside,
referenceValue: fieldValueManager.updateReferenceValue(utils, valueFromTheOutside, prevState.referenceValue),
sections: getSectionsFromValue(valueFromTheOutside)
}));
}
}, [valueFromTheOutside]); // eslint-disable-line react-hooks/exhaustive-deps
return {
state,
selectedSectionIndexes,
setSelectedSections,
clearValue,
clearActiveSection,
updateSectionValue,
updateValueFromValueStr,
setTempAndroidValueStr,
sectionsValueBoundaries,
placeholder,
timezone
};
};
/**
* The letter editing and the numeric editing each define a `CharacterEditingApplier`.
* This function decides what the new section value should be and if the focus should switch to the next section.
*
* If it returns `null`, then the section value is not updated and the focus does not move.
*/
/**
* Function called by `applyQuery` which decides:
* - what is the new section value ?
* - should the query used to get this value be stored for the next key press ?
*
* If it returns `{ sectionValue: string; shouldGoToNextSection: boolean }`,
* Then we store the query and update the section with the new value.
*
* If it returns `{ saveQuery: true` },
* Then we store the query and don't update the section.
*
* If it returns `{ saveQuery: false },
* Then we do nothing.
*/
const QUERY_LIFE_DURATION_MS = 5000;
const isQueryResponseWithoutValue = response => response.saveQuery != null;
/**
* Update the active section value when the user pressed a key that is not a navigation key (arrow key for example).
* This hook has two main editing behaviors
*
* 1. The numeric editing when the user presses a digit
* 2. The letter editing when the user presses another key
*/
const useFieldCharacterEditing = ({
sections,
updateSectionValue,
sectionsValueBoundaries,
setTempAndroidValueStr,
timezone
}) => {
const utils = useUtils();
const [query, setQuery] = React.useState(null);
const resetQuery = useEventCallback(() => setQuery(null));
React.useEffect(() => {
var _sections$query$secti;
if (query != null && ((_sections$query$secti = sections[query.sectionIndex]) == null ? void 0 : _sections$query$secti.type) !== query.sectionType) {
resetQuery();
}
}, [sections, query, resetQuery]);
React.useEffect(() => {
if (query != null) {
const timeout = setTimeout(() => resetQuery(), QUERY_LIFE_DURATION_MS);
return () => {
window.clearTimeout(timeout);
};
}
return () => {};
}, [query, resetQuery]);
const applyQuery = ({
keyPressed,
sectionIndex
}, getFirstSectionValueMatchingWithQuery, isValidQueryValue) => {
const cleanKeyPressed = keyPressed.toLowerCase();
const activeSection = sections[sectionIndex];
// The current query targets the section being editing
// We can try to concatenated value
if (query != null && (!isValidQueryValue || isValidQueryValue(query.value)) && query.sectionIndex === sectionIndex) {
const concatenatedQueryValue = `${query.value}${cleanKeyPressed}`;
const queryResponse = getFirstSectionValueMatchingWithQuery(concatenatedQueryValue, activeSection);
if (!isQueryResponseWithoutValue(queryResponse)) {
setQuery({
sectionIndex,
value: concatenatedQueryValue,
sectionType: activeSection.type
});
return queryResponse;
}
}
const queryResponse = getFirstSectionValueMatchingWithQuery(cleanKeyPressed, activeSection);
if (isQueryResponseWithoutValue(queryResponse) && !queryResponse.saveQuery) {
resetQuery();
return null;
}
setQuery({
sectionIndex,
value: cleanKeyPressed,
sectionType: activeSection.type
});
if (isQueryResponseWithoutValue(queryResponse)) {
return null;
}
return queryResponse;
};
const applyLetterEditing = params => {
const findMatchingOptions = (format, options, queryValue) => {
const matchingValues = options.filter(option => option.toLowerCase().startsWith(queryValue));
if (matchingValues.length === 0) {
return {
saveQuery: false
};
}
return {
sectionValue: matchingValues[0],
shouldGoToNextSection: matchingValues.length === 1
};
};
const testQueryOnFormatAndFallbackFormat = (queryValue, activeSection, fallbackFormat, formatFallbackValue) => {
const getOptions = format => getLetterEditingOptions(utils, timezone, activeSection.type, format);
if (activeSection.contentType === 'letter') {
return findMatchingOptions(activeSection.format, getOptions(activeSection.format), queryValue);
}
// When editing a digit-format month / weekDay and the user presses a letter,
// We can support the letter editing by using the letter-format month / weekDay and re-formatting the result.
// We just have to make sure that the default month / weekDay format is a letter format,
if (fallbackFormat && formatFallbackValue != null && getDateSectionConfigFromFormatToken(utils, fallbackFormat).contentType === 'letter') {
const fallbackOptions = getOptions(fallbackFormat);
const response = findMatchingOptions(fallbackFormat, fallbackOptions, queryValue);
if (isQueryResponseWithoutValue(response)) {
return {
saveQuery: false
};
}
return _extends({}, response, {
sectionValue: formatFallbackValue(response.sectionValue, fallbackOptions)
});
}
return {
saveQuery: false
};
};
const getFirstSectionValueMatchingWithQuery = (queryValue, activeSection) => {
switch (activeSection.type) {
case 'month':
{
const formatFallbackValue = fallbackValue => changeSectionValueFormat(utils, fallbackValue, utils.formats.month, activeSection.format);
return testQueryOnFormatAndFallbackFormat(queryValue, activeSection, utils.formats.month, formatFallbackValue);
}
case 'weekDay':
{
const formatFallbackValue = (fallbackValue, fallbackOptions) => fallbackOptions.indexOf(fallbackValue).toString();
return testQueryOnFormatAndFallbackFormat(queryValue, activeSection, utils.formats.weekday, formatFallbackValue);
}
case 'meridiem':
{
return testQueryOnFormatAndFallbackFormat(queryValue, activeSection);
}
default:
{
return {
saveQuery: false
};
}
}
};
return applyQuery(params, getFirstSectionValueMatchingWithQuery);
};
const applyNumericEditing = params => {
const getNewSectionValue = (queryValue, section) => {
const queryValueNumber = Number(`${queryValue}`);
const sectionBoundaries = sectionsValueBoundaries[section.type]({
currentDate: null,
format: section.format,
contentType: section.contentType
});
if (queryValueNumber > sectionBoundaries.maximum) {
return {
saveQuery: false
};
}
// If the user types `0` on a month section,
// It is below the minimum, but we want to store the `0` in the query,
// So that when he pressed `1`, it will store `01` and move to the next section.
if (queryValueNumber < sectionBoundaries.minimum) {
return {
saveQuery: true
};
}
const shouldGoToNextSection = Number(`${queryValue}0`) > sectionBoundaries.maximum || queryValue.length === sectionBoundaries.maximum.toString().length;
const newSectionValue = cleanDigitSectionValue(utils, timezone, queryValueNumber, sectionBoundaries, section);
return {
sectionValue: newSectionValue,
shouldGoToNextSection
};
};
const getFirstSectionValueMatchingWithQuery = (queryValue, activeSection) => {
if (activeSection.contentType === 'digit' || activeSection.contentType === 'digit-with-letter') {
return getNewSectionValue(queryValue, activeSection);
}
// When editing a letter-format month and the user presses a digit,
// We can support the numeric editing by using the digit-format month and re-formatting the result.
if (activeSection.type === 'month') {
const hasLeadingZerosInFormat = doesSectionFormatHaveLeadingZeros(utils, timezone, 'digit', 'month', 'MM');
const response = getNewSectionValue(queryValue, {
type: activeSection.type,
format: 'MM',
hasLeadingZerosInFormat,
hasLeadingZerosInInput: true,
contentType: 'digit',
maxLength: 2
});
if (isQueryResponseWithoutValue(response)) {
return response;
}
const formattedValue = changeSectionValueFormat(utils, response.sectionValue, 'MM', activeSection.format);
return _extends({}, response, {
sectionValue: formattedValue
});
}
// When editing a letter-format weekDay and the user presses a digit,
// We can support the numeric editing by returning the nth day in the week day array.
if (activeSection.type === 'weekDay') {
const response = getNewSectionValue(queryValue, activeSection);
if (isQueryResponseWithoutValue(response)) {
return response;
}
const formattedValue = getDaysInWeekStr(utils, timezone, activeSection.format)[Number(response.sectionValue) - 1];
return _extends({}, response, {
sectionValue: formattedValue
});
}
return {
saveQuery: false
};
};
return applyQuery(params, getFirstSectionValueMatchingWithQuery, queryValue => !Number.isNaN(Number(queryValue)));
};
const applyCharacterEditing = useEventCallback(params => {
const activeSection = sections[params.sectionIndex];
const isNumericEditing = !Number.isNaN(Number(params.keyPressed));
const response = isNumericEditing ? applyNumericEditing(params) : applyLetterEditing(params);
if (response == null) {
setTempAndroidValueStr(null);
} else {
updateSectionValue({
activeSection,
newSectionValue: response.sectionValue,
shouldGoToNextSection: response.shouldGoToNextSection
});
}
});
return {
applyCharacterEditing,
resetCharacterQuery: resetQuery
};
};
/* Use it instead of .includes method for IE support */
function arrayIncludes(array, itemOrItems) {
if (Array.isArray(itemOrItems)) {
return itemOrItems.every(item => array.indexOf(item) !== -1);
}
return array.indexOf(itemOrItems) !== -1;
}
const onSpaceOrEnter = (innerFn, externalEvent) => event => {
if (event.key === 'Enter' || event.key === ' ') {
innerFn(event);
// prevent any side effects
event.preventDefault();
event.stopPropagation();
}
if (externalEvent) {
externalEvent(event);
}
};
// https://www.abeautifulsite.net/posts/finding-the-active-element-in-a-shadow-root/
const getActiveElement = (root = document) => {
const activeEl = root.activeElement;
if (!activeEl) {
return null;
}
if (activeEl.shadowRoot) {
return getActiveElement(activeEl.shadowRoot);
}
return activeEl;
};
const DEFAULT_DESKTOP_MODE_MEDIA_QUERY = '@media (pointer: fine)';
const _excluded$l = ["onClick", "onKeyDown", "onFocus", "onBlur", "onMouseUp", "onPaste", "error", "clearable", "onClear", "disabled"];
const useField = params => {
const utils = useUtils();
const {
state,
selectedSectionIndexes,
setSelectedSections,
clearValue,
clearActiveSection,
updateSectionValue,
updateValueFromValueStr,
setTempAndroidValueStr,
sectionsValueBoundaries,
placeholder,
timezone
} = useFieldState(params);
const {
inputRef: inputRefProp,
internalProps,
internalProps: {
readOnly = false,
unstableFieldRef,
minutesStep
},
forwardedProps: {
onClick,
onKeyDown,
onFocus,
onBlur,
onMouseUp,
onPaste,
error,
clearable,
onClear,
disabled
},
fieldValueManager,
valueManager,
validator
} = params,
otherForwardedProps = _objectWithoutPropertiesLoose$1(params.forwardedProps, _excluded$l);
const {
applyCharacterEditing,
resetCharacterQuery
} = useFieldCharacterEditing({
sections: state.sections,
updateSectionValue,
sectionsValueBoundaries,
setTempAndroidValueStr,
timezone
});
const inputRef = React.useRef(null);
const handleRef = useForkRef(inputRefProp, inputRef);
const focusTimeoutRef = React.useRef(undefined);
const theme = useTheme$2();
const isRTL = theme.direction === 'rtl';
const sectionOrder = React.useMemo(() => getSectionOrder(state.sections, isRTL), [state.sections, isRTL]);
const syncSelectionFromDOM = () => {
var _selectionStart;
if (readOnly) {
setSelectedSections(null);
return;
}
const browserStartIndex = (_selectionStart = inputRef.current.selectionStart) != null ? _selectionStart : 0;
let nextSectionIndex;
if (browserStartIndex <= state.sections[0].startInInput) {
// Special case if browser index is in invisible characters at the beginning
nextSectionIndex = 1;
} else if (browserStartIndex >= state.sections[state.sections.length - 1].endInInput) {
// If the click is after the last character of the input, then we want to select the 1st section.
nextSectionIndex = 1;
} else {
nextSectionIndex = state.sections.findIndex(section => section.startInInput - section.startSeparator.length > browserStartIndex);
}
const sectionIndex = nextSectionIndex === -1 ? state.sections.length - 1 : nextSectionIndex - 1;
setSelectedSections(sectionIndex);
};
const handleInputClick = useEventCallback((event, ...args) => {
// The click event on the clear button would propagate to the input, trigger this handler and result in a wrong section selection.
// We avoid this by checking if the call of `handleInputClick` is actually intended, or a side effect.
if (event.isDefaultPrevented()) {
return;
}
onClick == null || onClick(event, ...args);
syncSelectionFromDOM();
});
const handleInputMouseUp = useEventCallback(event => {
onMouseUp == null || onMouseUp(event);
// Without this, the browser will remove the selected when clicking inside an already-selected section.
event.preventDefault();
});
const handleInputFocus = useEventCallback((...args) => {
onFocus == null || onFocus(...args);
// The ref is guaranteed to be resolved at this point.
const input = inputRef.current;
window.clearTimeout(focusTimeoutRef.current);
focusTimeoutRef.current = setTimeout(() => {
// The ref changed, the component got remounted, the focus event is no longer relevant.
if (!input || input !== inputRef.current) {
return;
}
if (selectedSectionIndexes != null || readOnly) {
return;
}
if (
// avoid selecting all sections when focusing empty field without value
input.value.length && Number(input.selectionEnd) - Number(input.selectionStart) === input.value.length) {
setSelectedSections('all');
} else {
syncSelectionFromDOM();
}
});
});
const handleInputBlur = useEventCallback((...args) => {
onBlur == null || onBlur(...args);
setSelectedSections(null);
});
const handleInputPaste = useEventCallback(event => {
onPaste == null || onPaste(event);
if (readOnly) {
event.preventDefault();
return;
}
const pastedValue = event.clipboardData.getData('text');
if (selectedSectionIndexes && selectedSectionIndexes.startIndex === selectedSectionIndexes.endIndex) {
const activeSection = state.sections[selectedSectionIndexes.startIndex];
const lettersOnly = /^[a-zA-Z]+$/.test(pastedValue);
const digitsOnly = /^[0-9]+$/.test(pastedValue);
const digitsAndLetterOnly = /^(([a-zA-Z]+)|)([0-9]+)(([a-zA-Z]+)|)$/.test(pastedValue);
const isValidPastedValue = activeSection.contentType === 'letter' && lettersOnly || activeSection.contentType === 'digit' && digitsOnly || activeSection.contentType === 'digit-with-letter' && digitsAndLetterOnly;
if (isValidPastedValue) {
resetCharacterQuery();
updateSectionValue({
activeSection,
newSectionValue: pastedValue,
shouldGoToNextSection: true
});
// prevent default to avoid the input change handler being called
event.preventDefault();
return;
}
if (lettersOnly || digitsOnly) {
// The pasted value correspond to a single section but not the expected type
// skip the modification
event.preventDefault();
return;
}
}
event.preventDefault();
resetCharacterQuery();
updateValueFromValueStr(pastedValue);
});
const handleInputChange = useEventCallback(event => {
if (readOnly) {
return;
}
const targetValue = event.target.value;
if (targetValue === '') {
resetCharacterQuery();
clearValue();
return;
}
const eventData = event.nativeEvent.data;
// Calling `.fill(04/11/2022)` in playwright will trigger a change event with the requested content to insert in `event.nativeEvent.data`
// usual changes have only the currently typed character in the `event.nativeEvent.data`
const shouldUseEventData = eventData && eventData.length > 1;
const valueStr = shouldUseEventData ? eventData : targetValue;
const cleanValueStr = cleanString(valueStr);
// If no section is selected or eventData should be used, we just try to parse the new value
// This line is mostly triggered by imperative code / application tests.
if (selectedSectionIndexes == null || shouldUseEventData) {
updateValueFromValueStr(shouldUseEventData ? eventData : cleanValueStr);
return;
}
let keyPressed;
if (selectedSectionIndexes.startIndex === 0 && selectedSectionIndexes.endIndex === state.sections.length - 1 && cleanValueStr.length === 1) {
keyPressed = cleanValueStr;
} else {
const prevValueStr = cleanString(fieldValueManager.getValueStrFromSections(state.sections, isRTL));
let startOfDiffIndex = -1;
let endOfDiffIndex = -1;
for (let i = 0; i < prevValueStr.length; i += 1) {
if (startOfDiffIndex === -1 && prevValueStr[i] !== cleanValueStr[i]) {
startOfDiffIndex = i;
}
if (endOfDiffIndex === -1 && prevValueStr[prevValueStr.length - i - 1] !== cleanValueStr[cleanValueStr.length - i - 1]) {
endOfDiffIndex = i;
}
}
const activeSection = state.sections[selectedSectionIndexes.startIndex];
const hasDiffOutsideOfActiveSection = startOfDiffIndex < activeSection.start || prevValueStr.length - endOfDiffIndex - 1 > activeSection.end;
if (hasDiffOutsideOfActiveSection) {
// TODO: Support if the new date is valid
return;
}
// The active section being selected, the browser has replaced its value with the key pressed by the user.
const activeSectionEndRelativeToNewValue = cleanValueStr.length - prevValueStr.length + activeSection.end - cleanString(activeSection.endSeparator || '').length;
keyPressed = cleanValueStr.slice(activeSection.start + cleanString(activeSection.startSeparator || '').length, activeSectionEndRelativeToNewValue);
}
if (keyPressed.length === 0) {
if (isAndroid()) {
setTempAndroidValueStr(valueStr);
} else {
resetCharacterQuery();
clearActiveSection();
}
return;
}
applyCharacterEditing({
keyPressed,
sectionIndex: selectedSectionIndexes.startIndex
});
});
const handleInputKeyDown = useEventCallback(event => {
onKeyDown == null || onKeyDown(event);
// eslint-disable-next-line default-case
switch (true) {
// Select all
case event.key === 'a' && (event.ctrlKey || event.metaKey):
{
// prevent default to make sure that the next line "select all" while updating
// the internal state at the same time.
event.preventDefault();
setSelectedSections('all');
break;
}
// Move selection to next section
case event.key === 'ArrowRight':
{
event.preventDefault();
if (selectedSectionIndexes == null) {
setSelectedSections(sectionOrder.startIndex);
} else if (selectedSectionIndexes.startIndex !== selectedSectionIndexes.endIndex) {
setSelectedSections(selectedSectionIndexes.endIndex);
} else {
const nextSectionIndex = sectionOrder.neighbors[selectedSectionIndexes.startIndex].rightIndex;
if (nextSectionIndex !== null) {
setSelectedSections(nextSectionIndex);
}
}
break;
}
// Move selection to previous section
case event.key === 'ArrowLeft':
{
event.preventDefault();
if (selectedSectionIndexes == null) {
setSelectedSections(sectionOrder.endIndex);
} else if (selectedSectionIndexes.startIndex !== selectedSectionIndexes.endIndex) {
setSelectedSections(selectedSectionIndexes.startIndex);
} else {
const nextSectionIndex = sectionOrder.neighbors[selectedSectionIndexes.startIndex].leftIndex;
if (nextSectionIndex !== null) {
setSelectedSections(nextSectionIndex);
}
}
break;
}
// Reset the value of the selected section
case event.key === 'Delete':
{
event.preventDefault();
if (readOnly) {
break;
}
if (selectedSectionIndexes == null || selectedSectionIndexes.startIndex === 0 && selectedSectionIndexes.endIndex === state.sections.length - 1) {
clearValue();
} else {
clearActiveSection();
}
resetCharacterQuery();
break;
}
// Increment / decrement the selected section value
case ['ArrowUp', 'ArrowDown', 'Home', 'End', 'PageUp', 'PageDown'].includes(event.key):
{
event.preventDefault();
if (readOnly || selectedSectionIndexes == null) {
break;
}
const activeSection = state.sections[selectedSectionIndexes.startIndex];
const activeDateManager = fieldValueManager.getActiveDateManager(utils, state, activeSection);
const newSectionValue = adjustSectionValue(utils, timezone, activeSection, event.key, sectionsValueBoundaries, activeDateManager.date, {
minutesStep
});
updateSectionValue({
activeSection,
newSectionValue,
shouldGoToNextSection: false
});
break;
}
}
});
useEnhancedEffect$1(() => {
if (!inputRef.current) {
return;
}
if (selectedSectionIndexes == null) {
if (inputRef.current.scrollLeft) {
// Ensure that input content is not marked as selected.
// setting selection range to 0 causes issues in Safari.
// https://bugs.webkit.org/show_bug.cgi?id=224425
inputRef.current.scrollLeft = 0;
}
return;
}
const firstSelectedSection = state.sections[selectedSectionIndexes.startIndex];
const lastSelectedSection = state.sections[selectedSectionIndexes.endIndex];
let selectionStart = firstSelectedSection.startInInput;
let selectionEnd = lastSelectedSection.endInInput;
if (selectedSectionIndexes.shouldSelectBoundarySelectors) {
selectionStart -= firstSelectedSection.startSeparator.length;
selectionEnd += lastSelectedSection.endSeparator.length;
}
if (selectionStart !== inputRef.current.selectionStart || selectionEnd !== inputRef.current.selectionEnd) {
// Fix scroll jumping on iOS browser: https://github.com/mui/mui-x/issues/8321
const currentScrollTop = inputRef.current.scrollTop;
// On multi input range pickers we want to update selection range only for the active input
// This helps to avoid the focus jumping on Safari https://github.com/mui/mui-x/issues/9003
// because WebKit implements the `setSelectionRange` based on the spec: https://bugs.webkit.org/show_bug.cgi?id=224425
if (inputRef.current === getActiveElement(document)) {
inputRef.current.setSelectionRange(selectionStart, selectionEnd);
}
// Even reading this variable seems to do the trick, but also setting it just to make use of it
inputRef.current.scrollTop = currentScrollTop;
}
});
const validationError = useValidation(_extends({}, internalProps, {
value: state.value,
timezone
}), validator, valueManager.isSameError, valueManager.defaultErrorState);
const inputError = React.useMemo(() => {
// only override when `error` is undefined.
// in case of multi input fields, the `error` value is provided externally and will always be defined.
if (error !== undefined) {
return error;
}
return valueManager.hasError(validationError);
}, [valueManager, validationError, error]);
React.useEffect(() => {
if (!inputError && !selectedSectionIndexes) {
resetCharacterQuery();
}
}, [state.referenceValue, selectedSectionIndexes, inputError]); // eslint-disable-line react-hooks/exhaustive-deps
React.useEffect(() => {
// Select the right section when focused on mount (`autoFocus = true` on the input)
if (inputRef.current && inputRef.current === document.activeElement) {
setSelectedSections('all');
}
return () => window.clearTimeout(focusTimeoutRef.current);
}, []); // eslint-disable-line react-hooks/exhaustive-deps
// If `state.tempValueStrAndroid` is still defined when running `useEffect`,
// Then `onChange` has only been called once, which means the user pressed `Backspace` to reset the section.
// This causes a small flickering on Android,
// But we can't use `useEnhancedEffect` which is always called before the second `onChange` call and then would cause false positives.
React.useEffect(() => {
if (state.tempValueStrAndroid != null && selectedSectionIndexes != null) {
resetCharacterQuery();
clearActiveSection();
}
}, [state.tempValueStrAndroid]); // eslint-disable-line react-hooks/exhaustive-deps
const valueStr = React.useMemo(() => {
var _state$tempValueStrAn;
return (_state$tempValueStrAn = state.tempValueStrAndroid) != null ? _state$tempValueStrAn : fieldValueManager.getValueStrFromSections(state.sections, isRTL);
}, [state.sections, fieldValueManager, state.tempValueStrAndroid, isRTL]);
const inputMode = React.useMemo(() => {
if (selectedSectionIndexes == null) {
return 'text';
}
if (state.sections[selectedSectionIndexes.startIndex].contentType === 'letter') {
return 'text';
}
return 'numeric';
}, [selectedSectionIndexes, state.sections]);
const inputHasFocus = inputRef.current && inputRef.current === getActiveElement(document);
const areAllSectionsEmpty = valueManager.areValuesEqual(utils, state.value, valueManager.emptyValue);
const shouldShowPlaceholder = !inputHasFocus && areAllSectionsEmpty;
React.useImperativeHandle(unstableFieldRef, () => ({
getSections: () => state.sections,
getActiveSectionIndex: () => {
var _selectionStart2, _selectionEnd;
const browserStartIndex = (_selectionStart2 = inputRef.current.selectionStart) != null ? _selectionStart2 : 0;
const browserEndIndex = (_selectionEnd = inputRef.current.selectionEnd) != null ? _selectionEnd : 0;
if (browserStartIndex === 0 && browserEndIndex === 0) {
return null;
}
const nextSectionIndex = browserStartIndex <= state.sections[0].startInInput ? 1 // Special case if browser index is in invisible characters at the beginning.
: state.sections.findIndex(section => section.startInInput - section.startSeparator.length > browserStartIndex);
return nextSectionIndex === -1 ? state.sections.length - 1 : nextSectionIndex - 1;
},
setSelectedSections: activeSectionIndex => setSelectedSections(activeSectionIndex)
}));
const handleClearValue = useEventCallback((event, ...args) => {
var _inputRef$current;
event.preventDefault();
onClear == null || onClear(event, ...args);
clearValue();
inputRef == null || (_inputRef$current = inputRef.current) == null || _inputRef$current.focus();
setSelectedSections(0);
});
return _extends({
placeholder,
autoComplete: 'off',
disabled: Boolean(disabled)
}, otherForwardedProps, {
value: shouldShowPlaceholder ? '' : valueStr,
inputMode,
readOnly,
onClick: handleInputClick,
onFocus: handleInputFocus,
onBlur: handleInputBlur,
onPaste: handleInputPaste,
onChange: handleInputChange,
onKeyDown: handleInputKeyDown,
onMouseUp: handleInputMouseUp,
onClear: handleClearValue,
error: inputError,
ref: handleRef,
clearable: Boolean(clearable && !areAllSectionsEmpty && !readOnly && !disabled)
});
};
const validateDate = ({
props,
value,
adapter
}) => {
if (value === null) {
return null;
}
const {
shouldDisableDate,
shouldDisableMonth,
shouldDisableYear,
disablePast,
disableFuture,
timezone
} = props;
const now = adapter.utils.dateWithTimezone(undefined, timezone);
const minDate = applyDefaultDate(adapter.utils, props.minDate, adapter.defaultDates.minDate);
const maxDate = applyDefaultDate(adapter.utils, props.maxDate, adapter.defaultDates.maxDate);
switch (true) {
case !adapter.utils.isValid(value):
return 'invalidDate';
case Boolean(shouldDisableDate && shouldDisableDate(value)):
return 'shouldDisableDate';
case Boolean(shouldDisableMonth && shouldDisableMonth(value)):
return 'shouldDisableMonth';
case Boolean(shouldDisableYear && shouldDisableYear(value)):
return 'shouldDisableYear';
case Boolean(disableFuture && adapter.utils.isAfterDay(value, now)):
return 'disableFuture';
case Boolean(disablePast && adapter.utils.isBeforeDay(value, now)):
return 'disablePast';
case Boolean(minDate && adapter.utils.isBeforeDay(value, minDate)):
return 'minDate';
case Boolean(maxDate && adapter.utils.isAfterDay(value, maxDate)):
return 'maxDate';
default:
return null;
}
};
const DATE_VALIDATION_PROP_NAMES = ['disablePast', 'disableFuture', 'minDate', 'maxDate', 'shouldDisableDate', 'shouldDisableMonth', 'shouldDisableYear'];
const TIME_VALIDATION_PROP_NAMES = ['disablePast', 'disableFuture', 'minTime', 'maxTime', 'shouldDisableClock', 'shouldDisableTime', 'minutesStep', 'ampm', 'disableIgnoringDatePartForTimeValidation'];
const DATE_TIME_VALIDATION_PROP_NAMES = ['minDateTime', 'maxDateTime'];
const VALIDATION_PROP_NAMES = [...DATE_VALIDATION_PROP_NAMES, ...TIME_VALIDATION_PROP_NAMES, ...DATE_TIME_VALIDATION_PROP_NAMES];
/**
* Extract the validation props for the props received by a component.
* Limit the risk of forgetting some of them and reduce the bundle size.
*/
const extractValidationProps = props => VALIDATION_PROP_NAMES.reduce((extractedProps, propName) => {
if (props.hasOwnProperty(propName)) {
extractedProps[propName] = props[propName];
}
return extractedProps;
}, {});
const SHARED_FIELD_INTERNAL_PROP_NAMES = ['value', 'defaultValue', 'referenceDate', 'format', 'formatDensity', 'onChange', 'timezone', 'readOnly', 'onError', 'shouldRespectLeadingZeros', 'selectedSections', 'onSelectedSectionsChange', 'unstableFieldRef'];
const splitFieldInternalAndForwardedProps = (props, valueType) => {
const forwardedProps = _extends({}, props);
const internalProps = {};
const extractProp = propName => {
if (forwardedProps.hasOwnProperty(propName)) {
// @ts-ignore
internalProps[propName] = forwardedProps[propName];
delete forwardedProps[propName];
}
};
SHARED_FIELD_INTERNAL_PROP_NAMES.forEach(extractProp);
if (valueType === 'date') {
DATE_VALIDATION_PROP_NAMES.forEach(extractProp);
} else if (valueType === 'time') {
TIME_VALIDATION_PROP_NAMES.forEach(extractProp);
} else if (valueType === 'date-time') {
DATE_VALIDATION_PROP_NAMES.forEach(extractProp);
TIME_VALIDATION_PROP_NAMES.forEach(extractProp);
DATE_TIME_VALIDATION_PROP_NAMES.forEach(extractProp);
}
return {
forwardedProps,
internalProps
};
};
const useDefaultizedDateField = props => {
var _props$disablePast, _props$disableFuture, _props$format;
const utils = useUtils();
const defaultDates = useDefaultDates();
return _extends({}, props, {
disablePast: (_props$disablePast = props.disablePast) != null ? _props$disablePast : false,
disableFuture: (_props$disableFuture = props.disableFuture) != null ? _props$disableFuture : false,
format: (_props$format = props.format) != null ? _props$format : utils.formats.keyboardDate,
minDate: applyDefaultDate(utils, props.minDate, defaultDates.minDate),
maxDate: applyDefaultDate(utils, props.maxDate, defaultDates.maxDate)
});
};
const useDateField = ({
props: inProps,
inputRef
}) => {
const props = useDefaultizedDateField(inProps);
const {
forwardedProps,
internalProps
} = splitFieldInternalAndForwardedProps(props, 'date');
return useField({
inputRef,
forwardedProps,
internalProps,
valueManager: singleItemValueManager,
fieldValueManager: singleItemFieldValueManager,
validator: validateDate,
valueType: 'date'
});
};
const PickersModalDialogRoot = styled$3(MuiDialog)({
[`& .${dialogClasses.container}`]: {
outline: 0
},
[`& .${dialogClasses.paper}`]: {
outline: 0,
minWidth: DIALOG_WIDTH
}
});
const PickersModalDialogContent = styled$3(DialogContent)({
'&:first-of-type': {
padding: 0
}
});
function PickersModalDialog(props) {
var _slots$dialog, _slots$mobileTransiti;
const {
children,
onDismiss,
open,
slots,
slotProps
} = props;
const Dialog = (_slots$dialog = slots == null ? void 0 : slots.dialog) != null ? _slots$dialog : PickersModalDialogRoot;
const Transition = (_slots$mobileTransiti = slots == null ? void 0 : slots.mobileTransition) != null ? _slots$mobileTransiti : Fade;
return /*#__PURE__*/jsx(Dialog, _extends({
open: open,
onClose: onDismiss
}, slotProps == null ? void 0 : slotProps.dialog, {
TransitionComponent: Transition,
TransitionProps: slotProps == null ? void 0 : slotProps.mobileTransition,
PaperComponent: slots == null ? void 0 : slots.mobilePaper,
PaperProps: slotProps == null ? void 0 : slotProps.mobilePaper,
children: /*#__PURE__*/jsx(PickersModalDialogContent, {
children: children
})
}));
}
function getPickersPopperUtilityClass(slot) {
return generateUtilityClass('MuiPickersPopper', slot);
}
generateUtilityClasses('MuiPickersPopper', ['root', 'paper']);
const PREFERS_REDUCED_MOTION = '@media (prefers-reduced-motion: reduce)';
// detect if user agent has Android version < 10 or iOS version < 13
const mobileVersionMatches = typeof navigator !== 'undefined' && navigator.userAgent.match(/android\s(\d+)|OS\s(\d+)/i);
const androidVersion = mobileVersionMatches && mobileVersionMatches[1] ? parseInt(mobileVersionMatches[1], 10) : null;
const iOSVersion = mobileVersionMatches && mobileVersionMatches[2] ? parseInt(mobileVersionMatches[2], 10) : null;
const slowAnimationDevices = androidVersion && androidVersion < 10 || iOSVersion && iOSVersion < 13 || false;
const useDefaultReduceAnimations = () => {
const prefersReduced = useMediaQuery(PREFERS_REDUCED_MOTION, {
defaultMatches: false
});
return prefersReduced || slowAnimationDevices;
};
const _excluded$k = ["PaperComponent", "popperPlacement", "ownerState", "children", "paperSlotProps", "paperClasses", "onPaperClick", "onPaperTouchStart"];
const useUtilityClasses$d = ownerState => {
const {
classes
} = ownerState;
const slots = {
root: ['root'],
paper: ['paper']
};
return composeClasses(slots, getPickersPopperUtilityClass, classes);
};
const PickersPopperRoot = styled$3(MuiPopper, {
name: 'MuiPickersPopper',
slot: 'Root',
overridesResolver: (_, styles) => styles.root
})(({
theme
}) => ({
zIndex: theme.zIndex.modal
}));
const PickersPopperPaper = styled$3(MuiPaper, {
name: 'MuiPickersPopper',
slot: 'Paper',
overridesResolver: (_, styles) => styles.paper
})(({
ownerState
}) => _extends({
outline: 0,
transformOrigin: 'top center'
}, ownerState.placement.includes('top') && {
transformOrigin: 'bottom center'
}));
function clickedRootScrollbar(event, doc) {
return doc.documentElement.clientWidth < event.clientX || doc.documentElement.clientHeight < event.clientY;
}
/**
* Based on @mui/material/ClickAwayListener without the customization.
* We can probably strip away even more since children won't be portaled.
* @param {boolean} active Only listen to clicks when the popper is opened.
* @param {(event: MouseEvent | TouchEvent) => void} onClickAway The callback to call when clicking outside the popper.
* @returns {Array} The ref and event handler to listen to the outside clicks.
*/
function useClickAwayListener(active, onClickAway) {
const movedRef = React.useRef(false);
const syntheticEventRef = React.useRef(false);
const nodeRef = React.useRef(null);
const activatedRef = React.useRef(false);
React.useEffect(() => {
if (!active) {
return undefined;
}
// Ensure that this hook is not "activated" synchronously.
// https://github.com/facebook/react/issues/20074
function armClickAwayListener() {
activatedRef.current = true;
}
document.addEventListener('mousedown', armClickAwayListener, true);
document.addEventListener('touchstart', armClickAwayListener, true);
return () => {
document.removeEventListener('mousedown', armClickAwayListener, true);
document.removeEventListener('touchstart', armClickAwayListener, true);
activatedRef.current = false;
};
}, [active]);
// The handler doesn't take event.defaultPrevented into account:
//
// event.preventDefault() is meant to stop default behaviors like
// clicking a checkbox to check it, hitting a button to submit a form,
// and hitting left arrow to move the cursor in a text input etc.
// Only special HTML elements have these default behaviors.
const handleClickAway = useEventCallback(event => {
if (!activatedRef.current) {
return;
}
// Given developers can stop the propagation of the synthetic event,
// we can only be confident with a positive value.
const insideReactTree = syntheticEventRef.current;
syntheticEventRef.current = false;
const doc = ownerDocument(nodeRef.current);
// 1. IE11 support, which trigger the handleClickAway even after the unbind
// 2. The child might render null.
// 3. Behave like a blur listener.
if (!nodeRef.current ||
// is a TouchEvent?
'clientX' in event && clickedRootScrollbar(event, doc)) {
return;
}
// Do not act if user performed touchmove
if (movedRef.current) {
movedRef.current = false;
return;
}
let insideDOM;
// If not enough, can use https://github.com/DieterHolvoet/event-propagation-path/blob/master/propagationPath.js
if (event.composedPath) {
insideDOM = event.composedPath().indexOf(nodeRef.current) > -1;
} else {
insideDOM = !doc.documentElement.contains(event.target) || nodeRef.current.contains(event.target);
}
if (!insideDOM && !insideReactTree) {
onClickAway(event);
}
});
// Keep track of mouse/touch events that bubbled up through the portal.
const handleSynthetic = () => {
syntheticEventRef.current = true;
};
React.useEffect(() => {
if (active) {
const doc = ownerDocument(nodeRef.current);
const handleTouchMove = () => {
movedRef.current = true;
};
doc.addEventListener('touchstart', handleClickAway);
doc.addEventListener('touchmove', handleTouchMove);
return () => {
doc.removeEventListener('touchstart', handleClickAway);
doc.removeEventListener('touchmove', handleTouchMove);
};
}
return undefined;
}, [active, handleClickAway]);
React.useEffect(() => {
// TODO This behavior is not tested automatically
// It's unclear whether this is due to different update semantics in test (batched in act() vs discrete on click).
// Or if this is a timing related issues due to different Transition components
// Once we get rid of all the manual scheduling (e.g. setTimeout(update, 0)) we can revisit this code+test.
if (active) {
const doc = ownerDocument(nodeRef.current);
doc.addEventListener('click', handleClickAway);
return () => {
doc.removeEventListener('click', handleClickAway);
// cleanup `handleClickAway`
syntheticEventRef.current = false;
};
}
return undefined;
}, [active, handleClickAway]);
return [nodeRef, handleSynthetic, handleSynthetic];
}
const PickersPopperPaperWrapper = /*#__PURE__*/React.forwardRef((props, ref) => {
const {
PaperComponent,
popperPlacement,
ownerState: inOwnerState,
children,
paperSlotProps,
paperClasses,
onPaperClick,
onPaperTouchStart
// picks up the style props provided by `Transition`
// https://mui.com/material-ui/transitions/#child-requirement
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$k);
const ownerState = _extends({}, inOwnerState, {
placement: popperPlacement
});
const paperProps = useSlotProps({
elementType: PaperComponent,
externalSlotProps: paperSlotProps,
additionalProps: {
tabIndex: -1,
elevation: 8,
ref
},
className: paperClasses,
ownerState
});
return /*#__PURE__*/jsx(PaperComponent, _extends({}, other, paperProps, {
onClick: event => {
var _paperProps$onClick;
onPaperClick(event);
(_paperProps$onClick = paperProps.onClick) == null || _paperProps$onClick.call(paperProps, event);
},
onTouchStart: event => {
var _paperProps$onTouchSt;
onPaperTouchStart(event);
(_paperProps$onTouchSt = paperProps.onTouchStart) == null || _paperProps$onTouchSt.call(paperProps, event);
},
ownerState: ownerState,
children: children
}));
});
function PickersPopper(inProps) {
var _slots$desktopTransit, _slots$desktopTrapFoc, _slots$desktopPaper, _slots$popper;
const props = useThemeProps({
props: inProps,
name: 'MuiPickersPopper'
});
const {
anchorEl,
children,
containerRef = null,
shouldRestoreFocus,
onBlur,
onDismiss,
open,
role,
placement,
slots,
slotProps,
reduceAnimations: inReduceAnimations
} = props;
React.useEffect(() => {
function handleKeyDown(nativeEvent) {
// IE11, Edge (prior to using Blink?) use 'Esc'
if (open && (nativeEvent.key === 'Escape' || nativeEvent.key === 'Esc')) {
onDismiss();
}
}
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, [onDismiss, open]);
const lastFocusedElementRef = React.useRef(null);
React.useEffect(() => {
if (role === 'tooltip' || shouldRestoreFocus && !shouldRestoreFocus()) {
return;
}
if (open) {
lastFocusedElementRef.current = getActiveElement(document);
} else if (lastFocusedElementRef.current && lastFocusedElementRef.current instanceof HTMLElement) {
// make sure the button is flushed with updated label, before returning focus to it
// avoids issue, where screen reader could fail to announce selected date after selection
setTimeout(() => {
if (lastFocusedElementRef.current instanceof HTMLElement) {
lastFocusedElementRef.current.focus();
}
});
}
}, [open, role, shouldRestoreFocus]);
const [clickAwayRef, onPaperClick, onPaperTouchStart] = useClickAwayListener(open, onBlur != null ? onBlur : onDismiss);
const paperRef = React.useRef(null);
const handleRef = useForkRef(paperRef, containerRef);
const handlePaperRef = useForkRef(handleRef, clickAwayRef);
const ownerState = props;
const classes = useUtilityClasses$d(ownerState);
const defaultReduceAnimations = useDefaultReduceAnimations();
const reduceAnimations = inReduceAnimations != null ? inReduceAnimations : defaultReduceAnimations;
const handleKeyDown = event => {
if (event.key === 'Escape') {
// stop the propagation to avoid closing parent modal
event.stopPropagation();
onDismiss();
}
};
const Transition = ((_slots$desktopTransit = slots == null ? void 0 : slots.desktopTransition) != null ? _slots$desktopTransit : reduceAnimations) ? Fade : Grow;
const FocusTrap = (_slots$desktopTrapFoc = slots == null ? void 0 : slots.desktopTrapFocus) != null ? _slots$desktopTrapFoc : BaseFocusTrap;
const Paper = (_slots$desktopPaper = slots == null ? void 0 : slots.desktopPaper) != null ? _slots$desktopPaper : PickersPopperPaper;
const Popper = (_slots$popper = slots == null ? void 0 : slots.popper) != null ? _slots$popper : PickersPopperRoot;
const popperProps = useSlotProps({
elementType: Popper,
externalSlotProps: slotProps == null ? void 0 : slotProps.popper,
additionalProps: {
transition: true,
role,
open,
anchorEl,
placement,
onKeyDown: handleKeyDown
},
className: classes.root,
ownerState: props
});
return /*#__PURE__*/jsx(Popper, _extends({}, popperProps, {
children: ({
TransitionProps,
placement: popperPlacement
}) => /*#__PURE__*/jsx(FocusTrap, _extends({
open: open,
disableAutoFocus: true
// pickers are managing focus position manually
// without this prop the focus is returned to the button before `aria-label` is updated
// which would force screen readers to read too old label
,
disableRestoreFocus: true,
disableEnforceFocus: role === 'tooltip',
isEnabled: () => true
}, slotProps == null ? void 0 : slotProps.desktopTrapFocus, {
children: /*#__PURE__*/jsx(Transition, _extends({}, TransitionProps, slotProps == null ? void 0 : slotProps.desktopTransition, {
children: /*#__PURE__*/jsx(PickersPopperPaperWrapper, {
PaperComponent: Paper,
ownerState: ownerState,
popperPlacement: popperPlacement,
ref: handlePaperRef,
onPaperClick: onPaperClick,
onPaperTouchStart: onPaperTouchStart,
paperClasses: classes.paper,
paperSlotProps: slotProps == null ? void 0 : slotProps.desktopPaper,
children: children
})
}))
}))
}));
}
function getPickersToolbarUtilityClass(slot) {
return generateUtilityClass('MuiPickersToolbar', slot);
}
generateUtilityClasses('MuiPickersToolbar', ['root', 'content']);
const useUtilityClasses$c = ownerState => {
const {
classes,
isLandscape
} = ownerState;
const slots = {
root: ['root'],
content: ['content'],
penIconButton: ['penIconButton', isLandscape && 'penIconButtonLandscape']
};
return composeClasses(slots, getPickersToolbarUtilityClass, classes);
};
const PickersToolbarRoot = styled$3('div', {
name: 'MuiPickersToolbar',
slot: 'Root',
overridesResolver: (props, styles) => styles.root
})(({
theme,
ownerState
}) => _extends({
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
justifyContent: 'space-between',
padding: theme.spacing(2, 3)
}, ownerState.isLandscape && {
height: 'auto',
maxWidth: 160,
padding: 16,
justifyContent: 'flex-start',
flexWrap: 'wrap'
}));
const PickersToolbarContent = styled$3('div', {
name: 'MuiPickersToolbar',
slot: 'Content',
overridesResolver: (props, styles) => styles.content
})(({
ownerState
}) => {
var _ownerState$landscape;
return {
display: 'flex',
flexWrap: 'wrap',
width: '100%',
justifyContent: ownerState.isLandscape ? 'flex-start' : 'space-between',
flexDirection: ownerState.isLandscape ? (_ownerState$landscape = ownerState.landscapeDirection) != null ? _ownerState$landscape : 'column' : 'row',
flex: 1,
alignItems: ownerState.isLandscape ? 'flex-start' : 'center'
};
});
const PickersToolbar = /*#__PURE__*/React.forwardRef(function PickersToolbar(inProps, ref) {
const props = useThemeProps({
props: inProps,
name: 'MuiPickersToolbar'
});
const {
children,
className,
toolbarTitle,
hidden,
titleId
} = props;
const ownerState = props;
const classes = useUtilityClasses$c(ownerState);
if (hidden) {
return null;
}
return /*#__PURE__*/jsxs(PickersToolbarRoot, {
ref: ref,
className: clsx(classes.root, className),
ownerState: ownerState,
children: [/*#__PURE__*/jsx(Typography, {
color: "text.secondary",
variant: "overline",
id: titleId,
children: toolbarTitle
}), /*#__PURE__*/jsx(PickersToolbarContent, {
className: classes.content,
ownerState: ownerState,
children: children
})]
});
});
const useOpenState = ({
open,
onOpen,
onClose
}) => {
const isControllingOpenProp = React.useRef(typeof open === 'boolean').current;
const [openState, setIsOpenState] = React.useState(false);
// It is required to update inner state in useEffect in order to avoid situation when
// Our component is not mounted yet, but `open` state is set to `true` (e.g. initially opened)
React.useEffect(() => {
if (isControllingOpenProp) {
if (typeof open !== 'boolean') {
throw new Error('You must not mix controlling and uncontrolled mode for `open` prop');
}
setIsOpenState(open);
}
}, [isControllingOpenProp, open]);
const setIsOpen = React.useCallback(newIsOpen => {
if (!isControllingOpenProp) {
setIsOpenState(newIsOpen);
}
if (newIsOpen && onOpen) {
onOpen();
}
if (!newIsOpen && onClose) {
onClose();
}
}, [isControllingOpenProp, onOpen, onClose]);
return {
isOpen: openState,
setIsOpen
};
};
/**
* Decide if the new value should be published
* The published value will be passed to `onChange` if defined.
*/
const shouldPublishValue = params => {
const {
action,
hasChanged,
dateState,
isControlled
} = params;
const isCurrentValueTheDefaultValue = !isControlled && !dateState.hasBeenModifiedSinceMount;
// The field is responsible for only calling `onChange` when needed.
if (action.name === 'setValueFromField') {
return true;
}
if (action.name === 'setValueFromAction') {
// If the component is not controlled, and the value has not been modified since the mount,
// Then we want to publish the default value whenever the user pressed the "Accept", "Today" or "Clear" button.
if (isCurrentValueTheDefaultValue && ['accept', 'today', 'clear'].includes(action.pickerAction)) {
return true;
}
return hasChanged(dateState.lastPublishedValue);
}
if (action.name === 'setValueFromView' && action.selectionState !== 'shallow') {
// On the first view,
// If the value is not controlled, then clicking on any value (including the one equal to `defaultValue`) should call `onChange`
if (isCurrentValueTheDefaultValue) {
return true;
}
return hasChanged(dateState.lastPublishedValue);
}
if (action.name === 'setValueFromShortcut') {
// On the first view,
// If the value is not controlled, then clicking on any value (including the one equal to `defaultValue`) should call `onChange`
if (isCurrentValueTheDefaultValue) {
return true;
}
return hasChanged(dateState.lastPublishedValue);
}
return false;
};
/**
* Decide if the new value should be committed.
* The committed value will be passed to `onAccept` if defined.
* It will also be used as a reset target when calling the `cancel` picker action (when clicking on the "Cancel" button).
*/
const shouldCommitValue = params => {
const {
action,
hasChanged,
dateState,
isControlled,
closeOnSelect
} = params;
const isCurrentValueTheDefaultValue = !isControlled && !dateState.hasBeenModifiedSinceMount;
if (action.name === 'setValueFromAction') {
// If the component is not controlled, and the value has not been modified since the mount,
// Then we want to commit the default value whenever the user pressed the "Accept", "Today" or "Clear" button.
if (isCurrentValueTheDefaultValue && ['accept', 'today', 'clear'].includes(action.pickerAction)) {
return true;
}
return hasChanged(dateState.lastCommittedValue);
}
if (action.name === 'setValueFromView' && action.selectionState === 'finish' && closeOnSelect) {
// On picker where the 1st view is also the last view,
// If the value is not controlled, then clicking on any value (including the one equal to `defaultValue`) should call `onAccept`
if (isCurrentValueTheDefaultValue) {
return true;
}
return hasChanged(dateState.lastCommittedValue);
}
if (action.name === 'setValueFromShortcut') {
return action.changeImportance === 'accept' && hasChanged(dateState.lastCommittedValue);
}
return false;
};
/**
* Decide if the picker should be closed after the value is updated.
*/
const shouldClosePicker = params => {
const {
action,
closeOnSelect
} = params;
if (action.name === 'setValueFromAction') {
return true;
}
if (action.name === 'setValueFromView') {
return action.selectionState === 'finish' && closeOnSelect;
}
if (action.name === 'setValueFromShortcut') {
return action.changeImportance === 'accept';
}
return false;
};
/**
* Manage the value lifecycle of all the pickers.
*/
const usePickerValue = ({
props,
valueManager,
valueType,
wrapperVariant,
validator
}) => {
const {
onAccept,
onChange,
value: inValue,
defaultValue: inDefaultValue,
closeOnSelect = wrapperVariant === 'desktop',
selectedSections: selectedSectionsProp,
onSelectedSectionsChange,
timezone: timezoneProp
} = props;
const {
current: defaultValue
} = React.useRef(inDefaultValue);
const {
current: isControlled
} = React.useRef(inValue !== undefined);
/* eslint-disable react-hooks/rules-of-hooks, react-hooks/exhaustive-deps */
if (process.env.NODE_ENV !== 'production') {
React.useEffect(() => {
if (isControlled !== (inValue !== undefined)) {
console.error([`MUI: A component is changing the ${isControlled ? '' : 'un'}controlled value of a picker to be ${isControlled ? 'un' : ''}controlled.`, 'Elements should not switch from uncontrolled to controlled (or vice versa).', `Decide between using a controlled or uncontrolled value` + 'for the lifetime of the component.', "The nature of the state is determined during the first render. It's considered controlled if the value is not `undefined`.", 'More info: https://fb.me/react-controlled-components'].join('\n'));
}
}, [inValue]);
React.useEffect(() => {
if (!isControlled && defaultValue !== inDefaultValue) {
console.error([`MUI: A component is changing the defaultValue of an uncontrolled picker after being initialized. ` + `To suppress this warning opt to use a controlled value.`].join('\n'));
}
}, [JSON.stringify(defaultValue)]);
}
/* eslint-enable react-hooks/rules-of-hooks, react-hooks/exhaustive-deps */
const utils = useUtils();
const adapter = useLocalizationContext();
const [selectedSections, setSelectedSections] = useControlled({
controlled: selectedSectionsProp,
default: null,
name: 'usePickerValue',
state: 'selectedSections'
});
const {
isOpen,
setIsOpen
} = useOpenState(props);
const [dateState, setDateState] = React.useState(() => {
let initialValue;
if (inValue !== undefined) {
initialValue = inValue;
} else if (defaultValue !== undefined) {
initialValue = defaultValue;
} else {
initialValue = valueManager.emptyValue;
}
return {
draft: initialValue,
lastPublishedValue: initialValue,
lastCommittedValue: initialValue,
lastControlledValue: inValue,
hasBeenModifiedSinceMount: false
};
});
const {
timezone,
handleValueChange
} = useValueWithTimezone({
timezone: timezoneProp,
value: inValue,
defaultValue,
onChange,
valueManager
});
useValidation(_extends({}, props, {
value: dateState.draft,
timezone
}), validator, valueManager.isSameError, valueManager.defaultErrorState);
const updateDate = useEventCallback(action => {
const updaterParams = {
action,
dateState,
hasChanged: comparison => !valueManager.areValuesEqual(utils, action.value, comparison),
isControlled,
closeOnSelect
};
const shouldPublish = shouldPublishValue(updaterParams);
const shouldCommit = shouldCommitValue(updaterParams);
const shouldClose = shouldClosePicker(updaterParams);
setDateState(prev => _extends({}, prev, {
draft: action.value,
lastPublishedValue: shouldPublish ? action.value : prev.lastPublishedValue,
lastCommittedValue: shouldCommit ? action.value : prev.lastCommittedValue,
hasBeenModifiedSinceMount: true
}));
if (shouldPublish) {
const validationError = action.name === 'setValueFromField' ? action.context.validationError : validator({
adapter,
value: action.value,
props: _extends({}, props, {
value: action.value,
timezone
})
});
const context = {
validationError
};
// TODO v7: Remove 2nd condition
if (action.name === 'setValueFromShortcut' && action.shortcut != null) {
context.shortcut = action.shortcut;
}
handleValueChange(action.value, context);
}
if (shouldCommit && onAccept) {
onAccept(action.value);
}
if (shouldClose) {
setIsOpen(false);
}
});
if (inValue !== undefined && (dateState.lastControlledValue === undefined || !valueManager.areValuesEqual(utils, dateState.lastControlledValue, inValue))) {
const isUpdateComingFromPicker = valueManager.areValuesEqual(utils, dateState.draft, inValue);
setDateState(prev => _extends({}, prev, {
lastControlledValue: inValue
}, isUpdateComingFromPicker ? {} : {
lastCommittedValue: inValue,
lastPublishedValue: inValue,
draft: inValue,
hasBeenModifiedSinceMount: true
}));
}
const handleClear = useEventCallback(() => {
updateDate({
value: valueManager.emptyValue,
name: 'setValueFromAction',
pickerAction: 'clear'
});
});
const handleAccept = useEventCallback(() => {
updateDate({
value: dateState.lastPublishedValue,
name: 'setValueFromAction',
pickerAction: 'accept'
});
});
const handleDismiss = useEventCallback(() => {
updateDate({
value: dateState.lastPublishedValue,
name: 'setValueFromAction',
pickerAction: 'dismiss'
});
});
const handleCancel = useEventCallback(() => {
updateDate({
value: dateState.lastCommittedValue,
name: 'setValueFromAction',
pickerAction: 'cancel'
});
});
const handleSetToday = useEventCallback(() => {
updateDate({
value: valueManager.getTodayValue(utils, timezone, valueType),
name: 'setValueFromAction',
pickerAction: 'today'
});
});
const handleOpen = useEventCallback(() => setIsOpen(true));
const handleClose = useEventCallback(() => setIsOpen(false));
const handleChange = useEventCallback((newValue, selectionState = 'partial') => updateDate({
name: 'setValueFromView',
value: newValue,
selectionState
}));
// TODO v7: Make changeImportance and label mandatory.
const handleSelectShortcut = useEventCallback((newValue, changeImportance, shortcut) => updateDate({
name: 'setValueFromShortcut',
value: newValue,
changeImportance: changeImportance != null ? changeImportance : 'accept',
shortcut
}));
const handleChangeFromField = useEventCallback((newValue, context) => updateDate({
name: 'setValueFromField',
value: newValue,
context
}));
const handleFieldSelectedSectionsChange = useEventCallback(newSelectedSections => {
setSelectedSections(newSelectedSections);
onSelectedSectionsChange == null || onSelectedSectionsChange(newSelectedSections);
});
const actions = {
onClear: handleClear,
onAccept: handleAccept,
onDismiss: handleDismiss,
onCancel: handleCancel,
onSetToday: handleSetToday,
onOpen: handleOpen,
onClose: handleClose
};
const fieldResponse = {
value: dateState.draft,
onChange: handleChangeFromField,
selectedSections,
onSelectedSectionsChange: handleFieldSelectedSectionsChange
};
const viewValue = React.useMemo(() => valueManager.cleanValue(utils, dateState.draft), [utils, valueManager, dateState.draft]);
const viewResponse = {
value: viewValue,
onChange: handleChange,
onClose: handleClose,
open: isOpen,
onSelectedSectionsChange: handleFieldSelectedSectionsChange
};
const isValid = testedValue => {
const error = validator({
adapter,
value: testedValue,
props: _extends({}, props, {
value: testedValue,
timezone
})
});
return !valueManager.hasError(error);
};
const layoutResponse = _extends({}, actions, {
value: viewValue,
onChange: handleChange,
onSelectShortcut: handleSelectShortcut,
isValid
});
return {
open: isOpen,
fieldProps: fieldResponse,
viewProps: viewResponse,
layoutProps: layoutResponse,
actions
};
};
const _excluded$j = ["className", "sx"];
/**
* Props used to handle the views that are common to all pickers.
*/
/**
* Props used to handle the views of the pickers.
*/
/**
* Props used to handle the value of the pickers.
*/
/**
* Manage the views of all the pickers:
* - Handles the view switch
* - Handles the switch between UI views and field views
* - Handles the focus management when switching views
*/
const usePickerViews = ({
props,
propsFromPickerValue,
additionalViewProps,
inputRef,
autoFocusView
}) => {
const {
onChange,
open,
onSelectedSectionsChange,
onClose
} = propsFromPickerValue;
const {
views,
openTo,
onViewChange,
disableOpenPicker,
viewRenderers,
timezone
} = props;
const propsToForwardToView = _objectWithoutPropertiesLoose$1(props, _excluded$j);
const {
view,
setView,
defaultView,
focusedView,
setFocusedView,
setValueAndGoToNextView
} = useViews({
view: undefined,
views,
openTo,
onChange,
onViewChange,
autoFocus: autoFocusView
});
const {
hasUIView,
viewModeLookup
} = React.useMemo(() => views.reduce((acc, viewForReduce) => {
let viewMode;
if (disableOpenPicker) {
viewMode = 'field';
} else if (viewRenderers[viewForReduce] != null) {
viewMode = 'UI';
} else {
viewMode = 'field';
}
acc.viewModeLookup[viewForReduce] = viewMode;
if (viewMode === 'UI') {
acc.hasUIView = true;
}
return acc;
}, {
hasUIView: false,
viewModeLookup: {}
}), [disableOpenPicker, viewRenderers, views]);
const timeViewsCount = React.useMemo(() => views.reduce((acc, viewForReduce) => {
if (viewRenderers[viewForReduce] != null && isTimeView(viewForReduce)) {
return acc + 1;
}
return acc;
}, 0), [viewRenderers, views]);
const currentViewMode = viewModeLookup[view];
const shouldRestoreFocus = useEventCallback(() => currentViewMode === 'UI');
const [popperView, setPopperView] = React.useState(currentViewMode === 'UI' ? view : null);
if (popperView !== view && viewModeLookup[view] === 'UI') {
setPopperView(view);
}
useEnhancedEffect$1(() => {
// Handle case of `DateTimePicker` without time renderers
if (currentViewMode === 'field' && open) {
onClose();
setTimeout(() => {
// focusing the input before the range selection is done
// calling `onSelectedSectionsChange` outside of timeout results in an inconsistent behavior between Safari And Chrome
inputRef == null || inputRef.current.focus();
onSelectedSectionsChange(view);
});
}
}, [view]); // eslint-disable-line react-hooks/exhaustive-deps
useEnhancedEffect$1(() => {
if (!open) {
return;
}
let newView = view;
// If the current view is a field view, go to the last popper view
if (currentViewMode === 'field' && popperView != null) {
newView = popperView;
}
// If the current view is not the default view and both are UI views
if (newView !== defaultView && viewModeLookup[newView] === 'UI' && viewModeLookup[defaultView] === 'UI') {
newView = defaultView;
}
if (newView !== view) {
setView(newView);
}
setFocusedView(newView, true);
}, [open]); // eslint-disable-line react-hooks/exhaustive-deps
const layoutProps = {
views,
view: popperView,
onViewChange: setView
};
return {
hasUIView,
shouldRestoreFocus,
layoutProps,
renderCurrentView: () => {
if (popperView == null) {
return null;
}
const renderer = viewRenderers[popperView];
if (renderer == null) {
return null;
}
return renderer(_extends({}, propsToForwardToView, additionalViewProps, propsFromPickerValue, {
views,
timezone,
onChange: setValueAndGoToNextView,
view: popperView,
onViewChange: setView,
focusedView,
onFocusedViewChange: setFocusedView,
showViewSwitcher: timeViewsCount > 1,
timeViewsCount
}));
}
};
};
function getOrientation() {
if (typeof window === 'undefined') {
return 'portrait';
}
if (window.screen && window.screen.orientation && window.screen.orientation.angle) {
return Math.abs(window.screen.orientation.angle) === 90 ? 'landscape' : 'portrait';
}
// Support IOS safari
if (window.orientation) {
return Math.abs(Number(window.orientation)) === 90 ? 'landscape' : 'portrait';
}
return 'portrait';
}
const useIsLandscape = (views, customOrientation) => {
const [orientation, setOrientation] = React.useState(getOrientation);
useEnhancedEffect$1(() => {
const eventHandler = () => {
setOrientation(getOrientation());
};
window.addEventListener('orientationchange', eventHandler);
return () => {
window.removeEventListener('orientationchange', eventHandler);
};
}, []);
if (arrayIncludes(views, ['hours', 'minutes', 'seconds'])) {
// could not display 13:34:44 in landscape mode
return false;
}
const orientationToUse = customOrientation || orientation;
return orientationToUse === 'landscape';
};
/**
* Props used to create the layout of the views.
* Those props are exposed on all the pickers.
*/
/**
* Prepare the props for the view layout (managed by `PickersLayout`)
*/
const usePickerLayoutProps = ({
props,
propsFromPickerValue,
propsFromPickerViews,
wrapperVariant
}) => {
const {
orientation
} = props;
const isLandscape = useIsLandscape(propsFromPickerViews.views, orientation);
const layoutProps = _extends({}, propsFromPickerViews, propsFromPickerValue, {
isLandscape,
wrapperVariant,
disabled: props.disabled,
readOnly: props.readOnly
});
return {
layoutProps
};
};
const buildWarning = (message, gravity = 'warning') => {
let alreadyWarned = false;
const cleanMessage = Array.isArray(message) ? message.join('\n') : message;
return () => {
if (!alreadyWarned) {
alreadyWarned = true;
if (gravity === 'error') {
console.error(cleanMessage);
} else {
console.warn(cleanMessage);
}
}
};
};
const warnRenderInputIsDefined = buildWarning(['The `renderInput` prop has been removed in version 6.0 of the Date and Time Pickers.', 'You can replace it with the `textField` component slot in most cases.', 'For more information, please have a look at the migration guide (https://mui.com/x/migration/migration-pickers-v5/#input-renderer-required-in-v5).']);
const usePicker = ({
props,
valueManager,
valueType,
wrapperVariant,
inputRef,
additionalViewProps,
validator,
autoFocusView
}) => {
if (process.env.NODE_ENV !== 'production') {
if (props.renderInput != null) {
warnRenderInputIsDefined();
}
}
const pickerValueResponse = usePickerValue({
props,
valueManager,
valueType,
wrapperVariant,
validator
});
const pickerViewsResponse = usePickerViews({
props,
inputRef,
additionalViewProps,
autoFocusView,
propsFromPickerValue: pickerValueResponse.viewProps
});
const pickerLayoutResponse = usePickerLayoutProps({
props,
wrapperVariant,
propsFromPickerValue: pickerValueResponse.layoutProps,
propsFromPickerViews: pickerViewsResponse.layoutProps
});
return {
// Picker value
open: pickerValueResponse.open,
actions: pickerValueResponse.actions,
fieldProps: pickerValueResponse.fieldProps,
// Picker views
renderCurrentView: pickerViewsResponse.renderCurrentView,
hasUIView: pickerViewsResponse.hasUIView,
shouldRestoreFocus: pickerViewsResponse.shouldRestoreFocus,
// Picker layout
layoutProps: pickerLayoutResponse.layoutProps
};
};
function getPickersLayoutUtilityClass(slot) {
return generateUtilityClass('MuiPickersLayout', slot);
}
const pickersLayoutClasses = generateUtilityClasses('MuiPickersLayout', ['root', 'landscape', 'contentWrapper', 'toolbar', 'actionBar', 'tabs', 'shortcuts']);
const _excluded$i = ["onAccept", "onClear", "onCancel", "onSetToday", "actions"];
/**
* Demos:
*
* - [Custom slots and subcomponents](https://mui.com/x/react-date-pickers/custom-components/)
* - [Custom layout](https://mui.com/x/react-date-pickers/custom-layout/)
*
* API:
*
* - [PickersActionBar API](https://mui.com/x/api/date-pickers/pickers-action-bar/)
*/
function PickersActionBar(props) {
const {
onAccept,
onClear,
onCancel,
onSetToday,
actions
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$i);
const localeText = useLocaleText();
if (actions == null || actions.length === 0) {
return null;
}
const buttons = actions == null ? void 0 : actions.map(actionType => {
switch (actionType) {
case 'clear':
return /*#__PURE__*/jsx(Button, {
onClick: onClear,
children: localeText.clearButtonLabel
}, actionType);
case 'cancel':
return /*#__PURE__*/jsx(Button, {
onClick: onCancel,
children: localeText.cancelButtonLabel
}, actionType);
case 'accept':
return /*#__PURE__*/jsx(Button, {
onClick: onAccept,
children: localeText.okButtonLabel
}, actionType);
case 'today':
return /*#__PURE__*/jsx(Button, {
onClick: onSetToday,
children: localeText.todayButtonLabel
}, actionType);
default:
return null;
}
});
return /*#__PURE__*/jsx(DialogActions, _extends({}, other, {
children: buttons
}));
}
process.env.NODE_ENV !== "production" ? PickersActionBar.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* Ordered array of actions to display.
* If empty, does not display that action bar.
* @default `['cancel', 'accept']` for mobile and `[]` for desktop
*/
actions: PropTypes.arrayOf(PropTypes.oneOf(['accept', 'cancel', 'clear', 'today']).isRequired),
/**
* If `true`, the actions do not have additional margin.
* @default false
*/
disableSpacing: PropTypes.bool,
onAccept: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
onClear: PropTypes.func.isRequired,
onSetToday: PropTypes.func.isRequired,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
} : void 0;
const _excluded$h = ["items", "changeImportance", "isLandscape", "onChange", "isValid"],
_excluded2$5 = ["getValue"];
/**
* Demos:
*
* - [Shortcuts](https://mui.com/x/react-date-pickers/shortcuts/)
*
* API:
*
* - [PickersShortcuts API](https://mui.com/x/api/date-pickers/pickers-shortcuts/)
*/
function PickersShortcuts(props) {
const {
items,
changeImportance,
onChange,
isValid
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$h);
if (items == null || items.length === 0) {
return null;
}
const resolvedItems = items.map(_ref => {
let {
getValue
} = _ref,
item = _objectWithoutPropertiesLoose$1(_ref, _excluded2$5);
const newValue = getValue({
isValid
});
return {
label: item.label,
onClick: () => {
onChange(newValue, changeImportance, item);
},
disabled: !isValid(newValue)
};
});
return /*#__PURE__*/jsx(List, _extends({
dense: true,
sx: [{
maxHeight: VIEW_HEIGHT,
maxWidth: 200,
overflow: 'auto'
}, ...(Array.isArray(other.sx) ? other.sx : [other.sx])]
}, other, {
children: resolvedItems.map(item => {
return /*#__PURE__*/jsx(ListItem, {
children: /*#__PURE__*/jsx(Chip, _extends({}, item))
}, item.label);
})
}));
}
process.env.NODE_ENV !== "production" ? PickersShortcuts.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* Importance of the change when picking a shortcut:
* - "accept": fires `onChange`, fires `onAccept` and closes the picker.
* - "set": fires `onChange` but do not fire `onAccept` and does not close the picker.
* @default "accept"
*/
changeImportance: PropTypes.oneOf(['accept', 'set']),
className: PropTypes.string,
component: PropTypes.elementType,
/**
* If `true`, compact vertical padding designed for keyboard and mouse input is used for
* the list and list items.
* The prop is available to descendant components as the `dense` context.
* @default false
*/
dense: PropTypes.bool,
/**
* If `true`, vertical padding is removed from the list.
* @default false
*/
disablePadding: PropTypes.bool,
isLandscape: PropTypes.bool.isRequired,
isValid: PropTypes.func.isRequired,
/**
* Ordered array of shortcuts to display.
* If empty, does not display the shortcuts.
* @default `[]`
*/
items: PropTypes.arrayOf(PropTypes.shape({
getValue: PropTypes.func.isRequired,
label: PropTypes.string.isRequired
})),
onChange: PropTypes.func.isRequired,
style: PropTypes.object,
/**
* The content of the subheader, normally `ListSubheader`.
*/
subheader: PropTypes.node,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
} : void 0;
function toolbarHasView(toolbarProps) {
return toolbarProps.view !== null;
}
const useUtilityClasses$b = ownerState => {
const {
classes,
isLandscape
} = ownerState;
const slots = {
root: ['root', isLandscape && 'landscape'],
contentWrapper: ['contentWrapper'],
toolbar: ['toolbar'],
actionBar: ['actionBar'],
tabs: ['tabs'],
landscape: ['landscape'],
shortcuts: ['shortcuts']
};
return composeClasses(slots, getPickersLayoutUtilityClass, classes);
};
const usePickerLayout = props => {
var _slots$actionBar, _slots$shortcuts;
const {
wrapperVariant,
onAccept,
onClear,
onCancel,
onSetToday,
view,
views,
onViewChange,
value,
onChange,
onSelectShortcut,
isValid,
isLandscape,
disabled,
readOnly,
children,
components,
componentsProps,
slots: innerSlots,
slotProps: innerSlotProps
// TODO: Remove this "as" hack. It get introduced to mark `value` prop in PickersLayoutProps as not required.
// The true type should be
// - For pickers value: TDate | null
// - For range pickers value: [TDate | null, TDate | null]
} = props;
const slots = innerSlots != null ? innerSlots : uncapitalizeObjectKeys(components);
const slotProps = innerSlotProps != null ? innerSlotProps : componentsProps;
const classes = useUtilityClasses$b(props);
// Action bar
const ActionBar = (_slots$actionBar = slots == null ? void 0 : slots.actionBar) != null ? _slots$actionBar : PickersActionBar;
const actionBarProps = useSlotProps({
elementType: ActionBar,
externalSlotProps: slotProps == null ? void 0 : slotProps.actionBar,
additionalProps: {
onAccept,
onClear,
onCancel,
onSetToday,
actions: wrapperVariant === 'desktop' ? [] : ['cancel', 'accept'],
className: classes.actionBar
},
ownerState: _extends({}, props, {
wrapperVariant
})
});
const actionBar = /*#__PURE__*/jsx(ActionBar, _extends({}, actionBarProps));
// Toolbar
const Toolbar = slots == null ? void 0 : slots.toolbar;
const toolbarProps = useSlotProps({
elementType: Toolbar,
externalSlotProps: slotProps == null ? void 0 : slotProps.toolbar,
additionalProps: {
isLandscape,
onChange,
value,
view,
onViewChange,
views,
disabled,
readOnly,
className: classes.toolbar
},
ownerState: _extends({}, props, {
wrapperVariant
})
});
const toolbar = toolbarHasView(toolbarProps) && !!Toolbar ? /*#__PURE__*/jsx(Toolbar, _extends({}, toolbarProps)) : null;
// Content
const content = children;
// Tabs
const Tabs = slots == null ? void 0 : slots.tabs;
const tabs = view && Tabs ? /*#__PURE__*/jsx(Tabs, _extends({
view: view,
onViewChange: onViewChange,
className: classes.tabs
}, slotProps == null ? void 0 : slotProps.tabs)) : null;
// Shortcuts
const Shortcuts = (_slots$shortcuts = slots == null ? void 0 : slots.shortcuts) != null ? _slots$shortcuts : PickersShortcuts;
const shortcutsProps = useSlotProps({
elementType: Shortcuts,
externalSlotProps: slotProps == null ? void 0 : slotProps.shortcuts,
additionalProps: {
isValid,
isLandscape,
onChange: onSelectShortcut,
className: classes.shortcuts
},
ownerState: {
isValid,
isLandscape,
onChange: onSelectShortcut,
className: classes.shortcuts,
wrapperVariant
}
});
const shortcuts = view && !!Shortcuts ? /*#__PURE__*/jsx(Shortcuts, _extends({}, shortcutsProps)) : null;
return {
toolbar,
content,
tabs,
actionBar,
shortcuts
};
};
var usePickerLayout$1 = usePickerLayout;
const useUtilityClasses$a = ownerState => {
const {
isLandscape,
classes
} = ownerState;
const slots = {
root: ['root', isLandscape && 'landscape'],
contentWrapper: ['contentWrapper']
};
return composeClasses(slots, getPickersLayoutUtilityClass, classes);
};
const PickersLayoutRoot = styled$3('div', {
name: 'MuiPickersLayout',
slot: 'Root',
overridesResolver: (props, styles) => styles.root
})(({
theme,
ownerState
}) => ({
display: 'grid',
gridAutoColumns: 'max-content auto max-content',
gridAutoRows: 'max-content auto max-content',
[`& .${pickersLayoutClasses.toolbar}`]: ownerState.isLandscape ? {
gridColumn: theme.direction === 'rtl' ? 3 : 1,
gridRow: '2 / 3'
} : {
gridColumn: '2 / 4',
gridRow: 1
},
[`.${pickersLayoutClasses.shortcuts}`]: ownerState.isLandscape ? {
gridColumn: '2 / 4',
gridRow: 1
} : {
gridColumn: theme.direction === 'rtl' ? 3 : 1,
gridRow: '2 / 3'
},
[`& .${pickersLayoutClasses.actionBar}`]: {
gridColumn: '1 / 4',
gridRow: 3
}
}));
PickersLayoutRoot.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
as: PropTypes.elementType,
ownerState: PropTypes.shape({
isLandscape: PropTypes.bool.isRequired
}).isRequired,
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
};
const PickersLayoutContentWrapper = styled$3('div', {
name: 'MuiPickersLayout',
slot: 'ContentWrapper',
overridesResolver: (props, styles) => styles.contentWrapper
})({
gridColumn: 2,
gridRow: 2,
display: 'flex',
flexDirection: 'column'
});
/**
* Demos:
*
* - [Custom layout](https://mui.com/x/react-date-pickers/custom-layout/)
*
* API:
*
* - [PickersLayout API](https://mui.com/x/api/date-pickers/pickers-layout/)
*/
const PickersLayout = function PickersLayout(inProps) {
const props = useThemeProps({
props: inProps,
name: 'MuiPickersLayout'
});
const {
toolbar,
content,
tabs,
actionBar,
shortcuts
} = usePickerLayout$1(props);
const {
sx,
className,
isLandscape,
ref,
wrapperVariant
} = props;
const ownerState = props;
const classes = useUtilityClasses$a(ownerState);
return /*#__PURE__*/jsxs(PickersLayoutRoot, {
ref: ref,
sx: sx,
className: clsx(className, classes.root),
ownerState: ownerState,
children: [isLandscape ? shortcuts : toolbar, isLandscape ? toolbar : shortcuts, /*#__PURE__*/jsx(PickersLayoutContentWrapper, {
className: classes.contentWrapper,
children: wrapperVariant === 'desktop' ? /*#__PURE__*/jsxs(React.Fragment, {
children: [content, tabs]
}) : /*#__PURE__*/jsxs(React.Fragment, {
children: [tabs, content]
})
}), actionBar]
});
};
process.env.NODE_ENV !== "production" ? PickersLayout.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
children: PropTypes.node,
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object,
className: PropTypes.string,
/**
* Overridable components.
* @default {}
* @deprecated Please use `slots`.
*/
components: PropTypes.object,
/**
* The props used for each component slot.
* @default {}
* @deprecated Please use `slotProps`.
*/
componentsProps: PropTypes.object,
disabled: PropTypes.bool,
isLandscape: PropTypes.bool.isRequired,
isValid: PropTypes.func.isRequired,
onAccept: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onClear: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
onDismiss: PropTypes.func.isRequired,
onOpen: PropTypes.func.isRequired,
onSelectShortcut: PropTypes.func.isRequired,
onSetToday: PropTypes.func.isRequired,
onViewChange: PropTypes.func.isRequired,
/**
* Force rendering in particular orientation.
*/
orientation: PropTypes.oneOf(['landscape', 'portrait']),
readOnly: PropTypes.bool,
/**
* The props used for each component slot.
* @default {}
*/
slotProps: PropTypes.object,
/**
* Overridable component slots.
* @default {}
*/
slots: PropTypes.object,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
value: PropTypes.any,
view: PropTypes.oneOf(['day', 'hours', 'meridiem', 'minutes', 'month', 'seconds', 'year']),
views: PropTypes.arrayOf(PropTypes.oneOf(['day', 'hours', 'meridiem', 'minutes', 'month', 'seconds', 'year']).isRequired).isRequired,
wrapperVariant: PropTypes.oneOf(['desktop', 'mobile'])
} : void 0;
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
_setPrototypeOf(subClass, superClass);
}
/**
* Checks if a given element has a CSS class.
*
* @param element the element
* @param className the CSS class name
*/
function hasClass(element, className) {
if (element.classList) return !!className && element.classList.contains(className);
return (" " + (element.className.baseVal || element.className) + " ").indexOf(" " + className + " ") !== -1;
}
/**
* Adds a CSS class to a given element.
*
* @param element the element
* @param className the CSS class name
*/
function addClass(element, className) {
if (element.classList) element.classList.add(className);else if (!hasClass(element, className)) if (typeof element.className === 'string') element.className = element.className + " " + className;else element.setAttribute('class', (element.className && element.className.baseVal || '') + " " + className);
}
function replaceClassName(origClass, classToRemove) {
return origClass.replace(new RegExp("(^|\\s)" + classToRemove + "(?:\\s|$)", 'g'), '$1').replace(/\s+/g, ' ').replace(/^\s*|\s*$/g, '');
}
/**
* Removes a CSS class from a given element.
*
* @param element the element
* @param className the CSS class name
*/
function removeClass$1(element, className) {
if (element.classList) {
element.classList.remove(className);
} else if (typeof element.className === 'string') {
element.className = replaceClassName(element.className, className);
} else {
element.setAttribute('class', replaceClassName(element.className && element.className.baseVal || '', className));
}
}
var config = {
disabled: false
};
var timeoutsShape = process.env.NODE_ENV !== 'production' ? PropTypes.oneOfType([PropTypes.number, PropTypes.shape({
enter: PropTypes.number,
exit: PropTypes.number,
appear: PropTypes.number
}).isRequired]) : null;
var classNamesShape = process.env.NODE_ENV !== 'production' ? PropTypes.oneOfType([PropTypes.string, PropTypes.shape({
enter: PropTypes.string,
exit: PropTypes.string,
active: PropTypes.string
}), PropTypes.shape({
enter: PropTypes.string,
enterDone: PropTypes.string,
enterActive: PropTypes.string,
exit: PropTypes.string,
exitDone: PropTypes.string,
exitActive: PropTypes.string
})]) : null;
var TransitionGroupContext = React__default.createContext(null);
var forceReflow = function forceReflow(node) {
return node.scrollTop;
};
var UNMOUNTED = 'unmounted';
var EXITED = 'exited';
var ENTERING = 'entering';
var ENTERED = 'entered';
var EXITING = 'exiting';
/**
* The Transition component lets you describe a transition from one component
* state to another _over time_ with a simple declarative API. Most commonly
* it's used to animate the mounting and unmounting of a component, but can also
* be used to describe in-place transition states as well.
*
* ---
*
* **Note**: `Transition` is a platform-agnostic base component. If you're using
* transitions in CSS, you'll probably want to use
* [`CSSTransition`](https://reactcommunity.org/react-transition-group/css-transition)
* instead. It inherits all the features of `Transition`, but contains
* additional features necessary to play nice with CSS transitions (hence the
* name of the component).
*
* ---
*
* By default the `Transition` component does not alter the behavior of the
* component it renders, it only tracks "enter" and "exit" states for the
* components. It's up to you to give meaning and effect to those states. For
* example we can add styles to a component when it enters or exits:
*
* ```jsx
* import { Transition } from 'react-transition-group';
*
* const duration = 300;
*
* const defaultStyle = {
* transition: `opacity ${duration}ms ease-in-out`,
* opacity: 0,
* }
*
* const transitionStyles = {
* entering: { opacity: 1 },
* entered: { opacity: 1 },
* exiting: { opacity: 0 },
* exited: { opacity: 0 },
* };
*
* const Fade = ({ in: inProp }) => (
* <Transition in={inProp} timeout={duration}>
* {state => (
* <div style={{
* ...defaultStyle,
* ...transitionStyles[state]
* }}>
* I'm a fade Transition!
* </div>
* )}
* </Transition>
* );
* ```
*
* There are 4 main states a Transition can be in:
* - `'entering'`
* - `'entered'`
* - `'exiting'`
* - `'exited'`
*
* Transition state is toggled via the `in` prop. When `true` the component
* begins the "Enter" stage. During this stage, the component will shift from
* its current transition state, to `'entering'` for the duration of the
* transition and then to the `'entered'` stage once it's complete. Let's take
* the following example (we'll use the
* [useState](https://reactjs.org/docs/hooks-reference.html#usestate) hook):
*
* ```jsx
* function App() {
* const [inProp, setInProp] = useState(false);
* return (
* <div>
* <Transition in={inProp} timeout={500}>
* {state => (
* // ...
* )}
* </Transition>
* <button onClick={() => setInProp(true)}>
* Click to Enter
* </button>
* </div>
* );
* }
* ```
*
* When the button is clicked the component will shift to the `'entering'` state
* and stay there for 500ms (the value of `timeout`) before it finally switches
* to `'entered'`.
*
* When `in` is `false` the same thing happens except the state moves from
* `'exiting'` to `'exited'`.
*/
var Transition = /*#__PURE__*/function (_React$Component) {
_inheritsLoose(Transition, _React$Component);
function Transition(props, context) {
var _this;
_this = _React$Component.call(this, props, context) || this;
var parentGroup = context; // In the context of a TransitionGroup all enters are really appears
var appear = parentGroup && !parentGroup.isMounting ? props.enter : props.appear;
var initialStatus;
_this.appearStatus = null;
if (props.in) {
if (appear) {
initialStatus = EXITED;
_this.appearStatus = ENTERING;
} else {
initialStatus = ENTERED;
}
} else {
if (props.unmountOnExit || props.mountOnEnter) {
initialStatus = UNMOUNTED;
} else {
initialStatus = EXITED;
}
}
_this.state = {
status: initialStatus
};
_this.nextCallback = null;
return _this;
}
Transition.getDerivedStateFromProps = function getDerivedStateFromProps(_ref, prevState) {
var nextIn = _ref.in;
if (nextIn && prevState.status === UNMOUNTED) {
return {
status: EXITED
};
}
return null;
} // getSnapshotBeforeUpdate(prevProps) {
// let nextStatus = null
// if (prevProps !== this.props) {
// const { status } = this.state
// if (this.props.in) {
// if (status !== ENTERING && status !== ENTERED) {
// nextStatus = ENTERING
// }
// } else {
// if (status === ENTERING || status === ENTERED) {
// nextStatus = EXITING
// }
// }
// }
// return { nextStatus }
// }
;
var _proto = Transition.prototype;
_proto.componentDidMount = function componentDidMount() {
this.updateStatus(true, this.appearStatus);
};
_proto.componentDidUpdate = function componentDidUpdate(prevProps) {
var nextStatus = null;
if (prevProps !== this.props) {
var status = this.state.status;
if (this.props.in) {
if (status !== ENTERING && status !== ENTERED) {
nextStatus = ENTERING;
}
} else {
if (status === ENTERING || status === ENTERED) {
nextStatus = EXITING;
}
}
}
this.updateStatus(false, nextStatus);
};
_proto.componentWillUnmount = function componentWillUnmount() {
this.cancelNextCallback();
};
_proto.getTimeouts = function getTimeouts() {
var timeout = this.props.timeout;
var exit, enter, appear;
exit = enter = appear = timeout;
if (timeout != null && typeof timeout !== 'number') {
exit = timeout.exit;
enter = timeout.enter; // TODO: remove fallback for next major
appear = timeout.appear !== undefined ? timeout.appear : enter;
}
return {
exit: exit,
enter: enter,
appear: appear
};
};
_proto.updateStatus = function updateStatus(mounting, nextStatus) {
if (mounting === void 0) {
mounting = false;
}
if (nextStatus !== null) {
// nextStatus will always be ENTERING or EXITING.
this.cancelNextCallback();
if (nextStatus === ENTERING) {
if (this.props.unmountOnExit || this.props.mountOnEnter) {
var node = this.props.nodeRef ? this.props.nodeRef.current : ReactDOM.findDOMNode(this); // https://github.com/reactjs/react-transition-group/pull/749
// With unmountOnExit or mountOnEnter, the enter animation should happen at the transition between `exited` and `entering`.
// To make the animation happen, we have to separate each rendering and avoid being processed as batched.
if (node) forceReflow(node);
}
this.performEnter(mounting);
} else {
this.performExit();
}
} else if (this.props.unmountOnExit && this.state.status === EXITED) {
this.setState({
status: UNMOUNTED
});
}
};
_proto.performEnter = function performEnter(mounting) {
var _this2 = this;
var enter = this.props.enter;
var appearing = this.context ? this.context.isMounting : mounting;
var _ref2 = this.props.nodeRef ? [appearing] : [ReactDOM.findDOMNode(this), appearing],
maybeNode = _ref2[0],
maybeAppearing = _ref2[1];
var timeouts = this.getTimeouts();
var enterTimeout = appearing ? timeouts.appear : timeouts.enter; // no enter animation skip right to ENTERED
// if we are mounting and running this it means appear _must_ be set
if (!mounting && !enter || config.disabled) {
this.safeSetState({
status: ENTERED
}, function () {
_this2.props.onEntered(maybeNode);
});
return;
}
this.props.onEnter(maybeNode, maybeAppearing);
this.safeSetState({
status: ENTERING
}, function () {
_this2.props.onEntering(maybeNode, maybeAppearing);
_this2.onTransitionEnd(enterTimeout, function () {
_this2.safeSetState({
status: ENTERED
}, function () {
_this2.props.onEntered(maybeNode, maybeAppearing);
});
});
});
};
_proto.performExit = function performExit() {
var _this3 = this;
var exit = this.props.exit;
var timeouts = this.getTimeouts();
var maybeNode = this.props.nodeRef ? undefined : ReactDOM.findDOMNode(this); // no exit animation skip right to EXITED
if (!exit || config.disabled) {
this.safeSetState({
status: EXITED
}, function () {
_this3.props.onExited(maybeNode);
});
return;
}
this.props.onExit(maybeNode);
this.safeSetState({
status: EXITING
}, function () {
_this3.props.onExiting(maybeNode);
_this3.onTransitionEnd(timeouts.exit, function () {
_this3.safeSetState({
status: EXITED
}, function () {
_this3.props.onExited(maybeNode);
});
});
});
};
_proto.cancelNextCallback = function cancelNextCallback() {
if (this.nextCallback !== null) {
this.nextCallback.cancel();
this.nextCallback = null;
}
};
_proto.safeSetState = function safeSetState(nextState, callback) {
// This shouldn't be necessary, but there are weird race conditions with
// setState callbacks and unmounting in testing, so always make sure that
// we can cancel any pending setState callbacks after we unmount.
callback = this.setNextCallback(callback);
this.setState(nextState, callback);
};
_proto.setNextCallback = function setNextCallback(callback) {
var _this4 = this;
var active = true;
this.nextCallback = function (event) {
if (active) {
active = false;
_this4.nextCallback = null;
callback(event);
}
};
this.nextCallback.cancel = function () {
active = false;
};
return this.nextCallback;
};
_proto.onTransitionEnd = function onTransitionEnd(timeout, handler) {
this.setNextCallback(handler);
var node = this.props.nodeRef ? this.props.nodeRef.current : ReactDOM.findDOMNode(this);
var doesNotHaveTimeoutOrListener = timeout == null && !this.props.addEndListener;
if (!node || doesNotHaveTimeoutOrListener) {
setTimeout(this.nextCallback, 0);
return;
}
if (this.props.addEndListener) {
var _ref3 = this.props.nodeRef ? [this.nextCallback] : [node, this.nextCallback],
maybeNode = _ref3[0],
maybeNextCallback = _ref3[1];
this.props.addEndListener(maybeNode, maybeNextCallback);
}
if (timeout != null) {
setTimeout(this.nextCallback, timeout);
}
};
_proto.render = function render() {
var status = this.state.status;
if (status === UNMOUNTED) {
return null;
}
var _this$props = this.props,
children = _this$props.children;
_this$props.in;
_this$props.mountOnEnter;
_this$props.unmountOnExit;
_this$props.appear;
_this$props.enter;
_this$props.exit;
_this$props.timeout;
_this$props.addEndListener;
_this$props.onEnter;
_this$props.onEntering;
_this$props.onEntered;
_this$props.onExit;
_this$props.onExiting;
_this$props.onExited;
_this$props.nodeRef;
var childProps = _objectWithoutPropertiesLoose$1(_this$props, ["children", "in", "mountOnEnter", "unmountOnExit", "appear", "enter", "exit", "timeout", "addEndListener", "onEnter", "onEntering", "onEntered", "onExit", "onExiting", "onExited", "nodeRef"]);
return (
/*#__PURE__*/
// allows for nested Transitions
React__default.createElement(TransitionGroupContext.Provider, {
value: null
}, typeof children === 'function' ? children(status, childProps) : React__default.cloneElement(React__default.Children.only(children), childProps))
);
};
return Transition;
}(React__default.Component);
Transition.contextType = TransitionGroupContext;
Transition.propTypes = process.env.NODE_ENV !== "production" ? {
/**
* A React reference to DOM element that need to transition:
* https://stackoverflow.com/a/51127130/4671932
*
* - When `nodeRef` prop is used, `node` is not passed to callback functions
* (e.g. `onEnter`) because user already has direct access to the node.
* - When changing `key` prop of `Transition` in a `TransitionGroup` a new
* `nodeRef` need to be provided to `Transition` with changed `key` prop
* (see
* [test/CSSTransition-test.js](https://github.com/reactjs/react-transition-group/blob/13435f897b3ab71f6e19d724f145596f5910581c/test/CSSTransition-test.js#L362-L437)).
*/
nodeRef: PropTypes.shape({
current: typeof Element === 'undefined' ? PropTypes.any : function (propValue, key, componentName, location, propFullName, secret) {
var value = propValue[key];
return PropTypes.instanceOf(value && 'ownerDocument' in value ? value.ownerDocument.defaultView.Element : Element)(propValue, key, componentName, location, propFullName, secret);
}
}),
/**
* A `function` child can be used instead of a React element. This function is
* called with the current transition status (`'entering'`, `'entered'`,
* `'exiting'`, `'exited'`), which can be used to apply context
* specific props to a component.
*
* ```jsx
* <Transition in={this.state.in} timeout={150}>
* {state => (
* <MyComponent className={`fade fade-${state}`} />
* )}
* </Transition>
* ```
*/
children: PropTypes.oneOfType([PropTypes.func.isRequired, PropTypes.element.isRequired]).isRequired,
/**
* Show the component; triggers the enter or exit states
*/
in: PropTypes.bool,
/**
* By default the child component is mounted immediately along with
* the parent `Transition` component. If you want to "lazy mount" the component on the
* first `in={true}` you can set `mountOnEnter`. After the first enter transition the component will stay
* mounted, even on "exited", unless you also specify `unmountOnExit`.
*/
mountOnEnter: PropTypes.bool,
/**
* By default the child component stays mounted after it reaches the `'exited'` state.
* Set `unmountOnExit` if you'd prefer to unmount the component after it finishes exiting.
*/
unmountOnExit: PropTypes.bool,
/**
* By default the child component does not perform the enter transition when
* it first mounts, regardless of the value of `in`. If you want this
* behavior, set both `appear` and `in` to `true`.
*
* > **Note**: there are no special appear states like `appearing`/`appeared`, this prop
* > only adds an additional enter transition. However, in the
* > `<CSSTransition>` component that first enter transition does result in
* > additional `.appear-*` classes, that way you can choose to style it
* > differently.
*/
appear: PropTypes.bool,
/**
* Enable or disable enter transitions.
*/
enter: PropTypes.bool,
/**
* Enable or disable exit transitions.
*/
exit: PropTypes.bool,
/**
* The duration of the transition, in milliseconds.
* Required unless `addEndListener` is provided.
*
* You may specify a single timeout for all transitions:
*
* ```jsx
* timeout={500}
* ```
*
* or individually:
*
* ```jsx
* timeout={{
* appear: 500,
* enter: 300,
* exit: 500,
* }}
* ```
*
* - `appear` defaults to the value of `enter`
* - `enter` defaults to `0`
* - `exit` defaults to `0`
*
* @type {number | { enter?: number, exit?: number, appear?: number }}
*/
timeout: function timeout(props) {
var pt = timeoutsShape;
if (!props.addEndListener) pt = pt.isRequired;
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
return pt.apply(void 0, [props].concat(args));
},
/**
* Add a custom transition end trigger. Called with the transitioning
* DOM node and a `done` callback. Allows for more fine grained transition end
* logic. Timeouts are still used as a fallback if provided.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* ```jsx
* addEndListener={(node, done) => {
* // use the css transitionend event to mark the finish of a transition
* node.addEventListener('transitionend', done, false);
* }}
* ```
*/
addEndListener: PropTypes.func,
/**
* Callback fired before the "entering" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement, isAppearing: bool) -> void
*/
onEnter: PropTypes.func,
/**
* Callback fired after the "entering" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
onEntering: PropTypes.func,
/**
* Callback fired after the "entered" status is applied. An extra parameter
* `isAppearing` is supplied to indicate if the enter stage is occurring on the initial mount
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement, isAppearing: bool) -> void
*/
onEntered: PropTypes.func,
/**
* Callback fired before the "exiting" status is applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement) -> void
*/
onExit: PropTypes.func,
/**
* Callback fired after the "exiting" status is applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement) -> void
*/
onExiting: PropTypes.func,
/**
* Callback fired after the "exited" status is applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed
*
* @type Function(node: HtmlElement) -> void
*/
onExited: PropTypes.func
} : {}; // Name the function so it is clearer in the documentation
function noop() {}
Transition.defaultProps = {
in: false,
mountOnEnter: false,
unmountOnExit: false,
appear: false,
enter: true,
exit: true,
onEnter: noop,
onEntering: noop,
onEntered: noop,
onExit: noop,
onExiting: noop,
onExited: noop
};
Transition.UNMOUNTED = UNMOUNTED;
Transition.EXITED = EXITED;
Transition.ENTERING = ENTERING;
Transition.ENTERED = ENTERED;
Transition.EXITING = EXITING;
var Transition$1 = Transition;
var _addClass = function addClass$1(node, classes) {
return node && classes && classes.split(' ').forEach(function (c) {
return addClass(node, c);
});
};
var removeClass = function removeClass(node, classes) {
return node && classes && classes.split(' ').forEach(function (c) {
return removeClass$1(node, c);
});
};
/**
* A transition component inspired by the excellent
* [ng-animate](https://docs.angularjs.org/api/ngAnimate) library, you should
* use it if you're using CSS transitions or animations. It's built upon the
* [`Transition`](https://reactcommunity.org/react-transition-group/transition)
* component, so it inherits all of its props.
*
* `CSSTransition` applies a pair of class names during the `appear`, `enter`,
* and `exit` states of the transition. The first class is applied and then a
* second `*-active` class in order to activate the CSS transition. After the
* transition, matching `*-done` class names are applied to persist the
* transition state.
*
* ```jsx
* function App() {
* const [inProp, setInProp] = useState(false);
* return (
* <div>
* <CSSTransition in={inProp} timeout={200} classNames="my-node">
* <div>
* {"I'll receive my-node-* classes"}
* </div>
* </CSSTransition>
* <button type="button" onClick={() => setInProp(true)}>
* Click to Enter
* </button>
* </div>
* );
* }
* ```
*
* When the `in` prop is set to `true`, the child component will first receive
* the class `example-enter`, then the `example-enter-active` will be added in
* the next tick. `CSSTransition` [forces a
* reflow](https://github.com/reactjs/react-transition-group/blob/5007303e729a74be66a21c3e2205e4916821524b/src/CSSTransition.js#L208-L215)
* between before adding the `example-enter-active`. This is an important trick
* because it allows us to transition between `example-enter` and
* `example-enter-active` even though they were added immediately one after
* another. Most notably, this is what makes it possible for us to animate
* _appearance_.
*
* ```css
* .my-node-enter {
* opacity: 0;
* }
* .my-node-enter-active {
* opacity: 1;
* transition: opacity 200ms;
* }
* .my-node-exit {
* opacity: 1;
* }
* .my-node-exit-active {
* opacity: 0;
* transition: opacity 200ms;
* }
* ```
*
* `*-active` classes represent which styles you want to animate **to**, so it's
* important to add `transition` declaration only to them, otherwise transitions
* might not behave as intended! This might not be obvious when the transitions
* are symmetrical, i.e. when `*-enter-active` is the same as `*-exit`, like in
* the example above (minus `transition`), but it becomes apparent in more
* complex transitions.
*
* **Note**: If you're using the
* [`appear`](http://reactcommunity.org/react-transition-group/transition#Transition-prop-appear)
* prop, make sure to define styles for `.appear-*` classes as well.
*/
var CSSTransition = /*#__PURE__*/function (_React$Component) {
_inheritsLoose(CSSTransition, _React$Component);
function CSSTransition() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
_this.appliedClasses = {
appear: {},
enter: {},
exit: {}
};
_this.onEnter = function (maybeNode, maybeAppearing) {
var _this$resolveArgument = _this.resolveArguments(maybeNode, maybeAppearing),
node = _this$resolveArgument[0],
appearing = _this$resolveArgument[1];
_this.removeClasses(node, 'exit');
_this.addClass(node, appearing ? 'appear' : 'enter', 'base');
if (_this.props.onEnter) {
_this.props.onEnter(maybeNode, maybeAppearing);
}
};
_this.onEntering = function (maybeNode, maybeAppearing) {
var _this$resolveArgument2 = _this.resolveArguments(maybeNode, maybeAppearing),
node = _this$resolveArgument2[0],
appearing = _this$resolveArgument2[1];
var type = appearing ? 'appear' : 'enter';
_this.addClass(node, type, 'active');
if (_this.props.onEntering) {
_this.props.onEntering(maybeNode, maybeAppearing);
}
};
_this.onEntered = function (maybeNode, maybeAppearing) {
var _this$resolveArgument3 = _this.resolveArguments(maybeNode, maybeAppearing),
node = _this$resolveArgument3[0],
appearing = _this$resolveArgument3[1];
var type = appearing ? 'appear' : 'enter';
_this.removeClasses(node, type);
_this.addClass(node, type, 'done');
if (_this.props.onEntered) {
_this.props.onEntered(maybeNode, maybeAppearing);
}
};
_this.onExit = function (maybeNode) {
var _this$resolveArgument4 = _this.resolveArguments(maybeNode),
node = _this$resolveArgument4[0];
_this.removeClasses(node, 'appear');
_this.removeClasses(node, 'enter');
_this.addClass(node, 'exit', 'base');
if (_this.props.onExit) {
_this.props.onExit(maybeNode);
}
};
_this.onExiting = function (maybeNode) {
var _this$resolveArgument5 = _this.resolveArguments(maybeNode),
node = _this$resolveArgument5[0];
_this.addClass(node, 'exit', 'active');
if (_this.props.onExiting) {
_this.props.onExiting(maybeNode);
}
};
_this.onExited = function (maybeNode) {
var _this$resolveArgument6 = _this.resolveArguments(maybeNode),
node = _this$resolveArgument6[0];
_this.removeClasses(node, 'exit');
_this.addClass(node, 'exit', 'done');
if (_this.props.onExited) {
_this.props.onExited(maybeNode);
}
};
_this.resolveArguments = function (maybeNode, maybeAppearing) {
return _this.props.nodeRef ? [_this.props.nodeRef.current, maybeNode] // here `maybeNode` is actually `appearing`
: [maybeNode, maybeAppearing];
};
_this.getClassNames = function (type) {
var classNames = _this.props.classNames;
var isStringClassNames = typeof classNames === 'string';
var prefix = isStringClassNames && classNames ? classNames + "-" : '';
var baseClassName = isStringClassNames ? "" + prefix + type : classNames[type];
var activeClassName = isStringClassNames ? baseClassName + "-active" : classNames[type + "Active"];
var doneClassName = isStringClassNames ? baseClassName + "-done" : classNames[type + "Done"];
return {
baseClassName: baseClassName,
activeClassName: activeClassName,
doneClassName: doneClassName
};
};
return _this;
}
var _proto = CSSTransition.prototype;
_proto.addClass = function addClass(node, type, phase) {
var className = this.getClassNames(type)[phase + "ClassName"];
var _this$getClassNames = this.getClassNames('enter'),
doneClassName = _this$getClassNames.doneClassName;
if (type === 'appear' && phase === 'done' && doneClassName) {
className += " " + doneClassName;
} // This is to force a repaint,
// which is necessary in order to transition styles when adding a class name.
if (phase === 'active') {
if (node) forceReflow(node);
}
if (className) {
this.appliedClasses[type][phase] = className;
_addClass(node, className);
}
};
_proto.removeClasses = function removeClasses(node, type) {
var _this$appliedClasses$ = this.appliedClasses[type],
baseClassName = _this$appliedClasses$.base,
activeClassName = _this$appliedClasses$.active,
doneClassName = _this$appliedClasses$.done;
this.appliedClasses[type] = {};
if (baseClassName) {
removeClass(node, baseClassName);
}
if (activeClassName) {
removeClass(node, activeClassName);
}
if (doneClassName) {
removeClass(node, doneClassName);
}
};
_proto.render = function render() {
var _this$props = this.props;
_this$props.classNames;
var props = _objectWithoutPropertiesLoose$1(_this$props, ["classNames"]);
return /*#__PURE__*/React__default.createElement(Transition$1, _extends({}, props, {
onEnter: this.onEnter,
onEntered: this.onEntered,
onEntering: this.onEntering,
onExit: this.onExit,
onExiting: this.onExiting,
onExited: this.onExited
}));
};
return CSSTransition;
}(React__default.Component);
CSSTransition.defaultProps = {
classNames: ''
};
CSSTransition.propTypes = process.env.NODE_ENV !== "production" ? _extends({}, Transition$1.propTypes, {
/**
* The animation classNames applied to the component as it appears, enters,
* exits or has finished the transition. A single name can be provided, which
* will be suffixed for each stage, e.g. `classNames="fade"` applies:
*
* - `fade-appear`, `fade-appear-active`, `fade-appear-done`
* - `fade-enter`, `fade-enter-active`, `fade-enter-done`
* - `fade-exit`, `fade-exit-active`, `fade-exit-done`
*
* A few details to note about how these classes are applied:
*
* 1. They are _joined_ with the ones that are already defined on the child
* component, so if you want to add some base styles, you can use
* `className` without worrying that it will be overridden.
*
* 2. If the transition component mounts with `in={false}`, no classes are
* applied yet. You might be expecting `*-exit-done`, but if you think
* about it, a component cannot finish exiting if it hasn't entered yet.
*
* 2. `fade-appear-done` and `fade-enter-done` will _both_ be applied. This
* allows you to define different behavior for when appearing is done and
* when regular entering is done, using selectors like
* `.fade-enter-done:not(.fade-appear-done)`. For example, you could apply
* an epic entrance animation when element first appears in the DOM using
* [Animate.css](https://daneden.github.io/animate.css/). Otherwise you can
* simply use `fade-enter-done` for defining both cases.
*
* Each individual classNames can also be specified independently like:
*
* ```js
* classNames={{
* appear: 'my-appear',
* appearActive: 'my-active-appear',
* appearDone: 'my-done-appear',
* enter: 'my-enter',
* enterActive: 'my-active-enter',
* enterDone: 'my-done-enter',
* exit: 'my-exit',
* exitActive: 'my-active-exit',
* exitDone: 'my-done-exit',
* }}
* ```
*
* If you want to set these classes using CSS Modules:
*
* ```js
* import styles from './styles.css';
* ```
*
* you might want to use camelCase in your CSS file, that way could simply
* spread them instead of listing them one by one:
*
* ```js
* classNames={{ ...styles }}
* ```
*
* @type {string | {
* appear?: string,
* appearActive?: string,
* appearDone?: string,
* enter?: string,
* enterActive?: string,
* enterDone?: string,
* exit?: string,
* exitActive?: string,
* exitDone?: string,
* }}
*/
classNames: classNamesShape,
/**
* A `<Transition>` callback fired immediately after the 'enter' or 'appear' class is
* applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
onEnter: PropTypes.func,
/**
* A `<Transition>` callback fired immediately after the 'enter-active' or
* 'appear-active' class is applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
onEntering: PropTypes.func,
/**
* A `<Transition>` callback fired immediately after the 'enter' or
* 'appear' classes are **removed** and the `done` class is added to the DOM node.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
onEntered: PropTypes.func,
/**
* A `<Transition>` callback fired immediately after the 'exit' class is
* applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed
*
* @type Function(node: HtmlElement)
*/
onExit: PropTypes.func,
/**
* A `<Transition>` callback fired immediately after the 'exit-active' is applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed
*
* @type Function(node: HtmlElement)
*/
onExiting: PropTypes.func,
/**
* A `<Transition>` callback fired immediately after the 'exit' classes
* are **removed** and the `exit-done` class is added to the DOM node.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed
*
* @type Function(node: HtmlElement)
*/
onExited: PropTypes.func
}) : {};
var CSSTransition$1 = CSSTransition;
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
/**
* Given `this.props.children`, return an object mapping key to child.
*
* @param {*} children `this.props.children`
* @return {object} Mapping of key to child
*/
function getChildMapping(children, mapFn) {
var mapper = function mapper(child) {
return mapFn && isValidElement(child) ? mapFn(child) : child;
};
var result = Object.create(null);
if (children) Children.map(children, function (c) {
return c;
}).forEach(function (child) {
// run the map function here instead so that the key is the computed one
result[child.key] = mapper(child);
});
return result;
}
/**
* When you're adding or removing children some may be added or removed in the
* same render pass. We want to show *both* since we want to simultaneously
* animate elements in and out. This function takes a previous set of keys
* and a new set of keys and merges them with its best guess of the correct
* ordering. In the future we may expose some of the utilities in
* ReactMultiChild to make this easy, but for now React itself does not
* directly have this concept of the union of prevChildren and nextChildren
* so we implement it here.
*
* @param {object} prev prev children as returned from
* `ReactTransitionChildMapping.getChildMapping()`.
* @param {object} next next children as returned from
* `ReactTransitionChildMapping.getChildMapping()`.
* @return {object} a key set that contains all keys in `prev` and all keys
* in `next` in a reasonable order.
*/
function mergeChildMappings(prev, next) {
prev = prev || {};
next = next || {};
function getValueForKey(key) {
return key in next ? next[key] : prev[key];
} // For each key of `next`, the list of keys to insert before that key in
// the combined list
var nextKeysPending = Object.create(null);
var pendingKeys = [];
for (var prevKey in prev) {
if (prevKey in next) {
if (pendingKeys.length) {
nextKeysPending[prevKey] = pendingKeys;
pendingKeys = [];
}
} else {
pendingKeys.push(prevKey);
}
}
var i;
var childMapping = {};
for (var nextKey in next) {
if (nextKeysPending[nextKey]) {
for (i = 0; i < nextKeysPending[nextKey].length; i++) {
var pendingNextKey = nextKeysPending[nextKey][i];
childMapping[nextKeysPending[nextKey][i]] = getValueForKey(pendingNextKey);
}
}
childMapping[nextKey] = getValueForKey(nextKey);
} // Finally, add the keys which didn't appear before any key in `next`
for (i = 0; i < pendingKeys.length; i++) {
childMapping[pendingKeys[i]] = getValueForKey(pendingKeys[i]);
}
return childMapping;
}
function getProp(child, prop, props) {
return props[prop] != null ? props[prop] : child.props[prop];
}
function getInitialChildMapping(props, onExited) {
return getChildMapping(props.children, function (child) {
return cloneElement(child, {
onExited: onExited.bind(null, child),
in: true,
appear: getProp(child, 'appear', props),
enter: getProp(child, 'enter', props),
exit: getProp(child, 'exit', props)
});
});
}
function getNextChildMapping(nextProps, prevChildMapping, onExited) {
var nextChildMapping = getChildMapping(nextProps.children);
var children = mergeChildMappings(prevChildMapping, nextChildMapping);
Object.keys(children).forEach(function (key) {
var child = children[key];
if (!isValidElement(child)) return;
var hasPrev = (key in prevChildMapping);
var hasNext = (key in nextChildMapping);
var prevChild = prevChildMapping[key];
var isLeaving = isValidElement(prevChild) && !prevChild.props.in; // item is new (entering)
if (hasNext && (!hasPrev || isLeaving)) {
// console.log('entering', key)
children[key] = cloneElement(child, {
onExited: onExited.bind(null, child),
in: true,
exit: getProp(child, 'exit', nextProps),
enter: getProp(child, 'enter', nextProps)
});
} else if (!hasNext && hasPrev && !isLeaving) {
// item is old (exiting)
// console.log('leaving', key)
children[key] = cloneElement(child, {
in: false
});
} else if (hasNext && hasPrev && isValidElement(prevChild)) {
// item hasn't changed transition states
// copy over the last transition props;
// console.log('unchanged', key)
children[key] = cloneElement(child, {
onExited: onExited.bind(null, child),
in: prevChild.props.in,
exit: getProp(child, 'exit', nextProps),
enter: getProp(child, 'enter', nextProps)
});
}
});
return children;
}
var values$1 = Object.values || function (obj) {
return Object.keys(obj).map(function (k) {
return obj[k];
});
};
var defaultProps = {
component: 'div',
childFactory: function childFactory(child) {
return child;
}
};
/**
* The `<TransitionGroup>` component manages a set of transition components
* (`<Transition>` and `<CSSTransition>`) in a list. Like with the transition
* components, `<TransitionGroup>` is a state machine for managing the mounting
* and unmounting of components over time.
*
* Consider the example below. As items are removed or added to the TodoList the
* `in` prop is toggled automatically by the `<TransitionGroup>`.
*
* Note that `<TransitionGroup>` does not define any animation behavior!
* Exactly _how_ a list item animates is up to the individual transition
* component. This means you can mix and match animations across different list
* items.
*/
var TransitionGroup = /*#__PURE__*/function (_React$Component) {
_inheritsLoose(TransitionGroup, _React$Component);
function TransitionGroup(props, context) {
var _this;
_this = _React$Component.call(this, props, context) || this;
var handleExited = _this.handleExited.bind(_assertThisInitialized(_this)); // Initial children should all be entering, dependent on appear
_this.state = {
contextValue: {
isMounting: true
},
handleExited: handleExited,
firstRender: true
};
return _this;
}
var _proto = TransitionGroup.prototype;
_proto.componentDidMount = function componentDidMount() {
this.mounted = true;
this.setState({
contextValue: {
isMounting: false
}
});
};
_proto.componentWillUnmount = function componentWillUnmount() {
this.mounted = false;
};
TransitionGroup.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, _ref) {
var prevChildMapping = _ref.children,
handleExited = _ref.handleExited,
firstRender = _ref.firstRender;
return {
children: firstRender ? getInitialChildMapping(nextProps, handleExited) : getNextChildMapping(nextProps, prevChildMapping, handleExited),
firstRender: false
};
} // node is `undefined` when user provided `nodeRef` prop
;
_proto.handleExited = function handleExited(child, node) {
var currentChildMapping = getChildMapping(this.props.children);
if (child.key in currentChildMapping) return;
if (child.props.onExited) {
child.props.onExited(node);
}
if (this.mounted) {
this.setState(function (state) {
var children = _extends({}, state.children);
delete children[child.key];
return {
children: children
};
});
}
};
_proto.render = function render() {
var _this$props = this.props,
Component = _this$props.component,
childFactory = _this$props.childFactory,
props = _objectWithoutPropertiesLoose$1(_this$props, ["component", "childFactory"]);
var contextValue = this.state.contextValue;
var children = values$1(this.state.children).map(childFactory);
delete props.appear;
delete props.enter;
delete props.exit;
if (Component === null) {
return /*#__PURE__*/React__default.createElement(TransitionGroupContext.Provider, {
value: contextValue
}, children);
}
return /*#__PURE__*/React__default.createElement(TransitionGroupContext.Provider, {
value: contextValue
}, /*#__PURE__*/React__default.createElement(Component, props, children));
};
return TransitionGroup;
}(React__default.Component);
TransitionGroup.propTypes = process.env.NODE_ENV !== "production" ? {
/**
* `<TransitionGroup>` renders a `<div>` by default. You can change this
* behavior by providing a `component` prop.
* If you use React v16+ and would like to avoid a wrapping `<div>` element
* you can pass in `component={null}`. This is useful if the wrapping div
* borks your css styles.
*/
component: PropTypes.any,
/**
* A set of `<Transition>` components, that are toggled `in` and out as they
* leave. the `<TransitionGroup>` will inject specific transition props, so
* remember to spread them through if you are wrapping the `<Transition>` as
* with our `<Fade>` example.
*
* While this component is meant for multiple `Transition` or `CSSTransition`
* children, sometimes you may want to have a single transition child with
* content that you want to be transitioned out and in when you change it
* (e.g. routes, images etc.) In that case you can change the `key` prop of
* the transition child as you change its content, this will cause
* `TransitionGroup` to transition the child out and back in.
*/
children: PropTypes.node,
/**
* A convenience prop that enables or disables appear animations
* for all children. Note that specifying this will override any defaults set
* on individual children Transitions.
*/
appear: PropTypes.bool,
/**
* A convenience prop that enables or disables enter animations
* for all children. Note that specifying this will override any defaults set
* on individual children Transitions.
*/
enter: PropTypes.bool,
/**
* A convenience prop that enables or disables exit animations
* for all children. Note that specifying this will override any defaults set
* on individual children Transitions.
*/
exit: PropTypes.bool,
/**
* You may need to apply reactive updates to a child as it is exiting.
* This is generally done by using `cloneElement` however in the case of an exiting
* child the element has already been removed and not accessible to the consumer.
*
* If you do need to update a child as it leaves you can provide a `childFactory`
* to wrap every child, even the ones that are leaving.
*
* @type Function(child: ReactElement) -> ReactElement
*/
childFactory: PropTypes.func
} : {};
TransitionGroup.defaultProps = defaultProps;
var TransitionGroup$1 = TransitionGroup;
const getPickersSlideTransitionUtilityClass = slot => generateUtilityClass('MuiPickersSlideTransition', slot);
const pickersSlideTransitionClasses = generateUtilityClasses('MuiPickersSlideTransition', ['root', 'slideEnter-left', 'slideEnter-right', 'slideEnterActive', 'slideExit', 'slideExitActiveLeft-left', 'slideExitActiveLeft-right']);
const _excluded$g = ["children", "className", "reduceAnimations", "slideDirection", "transKey", "classes"];
const useUtilityClasses$9 = ownerState => {
const {
classes,
slideDirection
} = ownerState;
const slots = {
root: ['root'],
exit: ['slideExit'],
enterActive: ['slideEnterActive'],
enter: [`slideEnter-${slideDirection}`],
exitActive: [`slideExitActiveLeft-${slideDirection}`]
};
return composeClasses(slots, getPickersSlideTransitionUtilityClass, classes);
};
const PickersSlideTransitionRoot = styled$3(TransitionGroup$1, {
name: 'MuiPickersSlideTransition',
slot: 'Root',
overridesResolver: (_, styles) => [styles.root, {
[`.${pickersSlideTransitionClasses['slideEnter-left']}`]: styles['slideEnter-left']
}, {
[`.${pickersSlideTransitionClasses['slideEnter-right']}`]: styles['slideEnter-right']
}, {
[`.${pickersSlideTransitionClasses.slideEnterActive}`]: styles.slideEnterActive
}, {
[`.${pickersSlideTransitionClasses.slideExit}`]: styles.slideExit
}, {
[`.${pickersSlideTransitionClasses['slideExitActiveLeft-left']}`]: styles['slideExitActiveLeft-left']
}, {
[`.${pickersSlideTransitionClasses['slideExitActiveLeft-right']}`]: styles['slideExitActiveLeft-right']
}]
})(({
theme
}) => {
const slideTransition = theme.transitions.create('transform', {
duration: theme.transitions.duration.complex,
easing: 'cubic-bezier(0.35, 0.8, 0.4, 1)'
});
return {
display: 'block',
position: 'relative',
overflowX: 'hidden',
'& > *': {
position: 'absolute',
top: 0,
right: 0,
left: 0
},
[`& .${pickersSlideTransitionClasses['slideEnter-left']}`]: {
willChange: 'transform',
transform: 'translate(100%)',
zIndex: 1
},
[`& .${pickersSlideTransitionClasses['slideEnter-right']}`]: {
willChange: 'transform',
transform: 'translate(-100%)',
zIndex: 1
},
[`& .${pickersSlideTransitionClasses.slideEnterActive}`]: {
transform: 'translate(0%)',
transition: slideTransition
},
[`& .${pickersSlideTransitionClasses.slideExit}`]: {
transform: 'translate(0%)'
},
[`& .${pickersSlideTransitionClasses['slideExitActiveLeft-left']}`]: {
willChange: 'transform',
transform: 'translate(-100%)',
transition: slideTransition,
zIndex: 0
},
[`& .${pickersSlideTransitionClasses['slideExitActiveLeft-right']}`]: {
willChange: 'transform',
transform: 'translate(100%)',
transition: slideTransition,
zIndex: 0
}
};
});
/**
* @ignore - do not document.
*/
function PickersSlideTransition(inProps) {
const props = useThemeProps({
props: inProps,
name: 'MuiPickersSlideTransition'
});
const {
children,
className,
reduceAnimations,
transKey
// extracting `classes` from `other`
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$g);
const classes = useUtilityClasses$9(props);
const theme = useTheme$2();
if (reduceAnimations) {
return /*#__PURE__*/jsx("div", {
className: clsx(classes.root, className),
children: children
});
}
const transitionClasses = {
exit: classes.exit,
enterActive: classes.enterActive,
enter: classes.enter,
exitActive: classes.exitActive
};
return /*#__PURE__*/jsx(PickersSlideTransitionRoot, {
className: clsx(classes.root, className),
childFactory: element => /*#__PURE__*/React.cloneElement(element, {
classNames: transitionClasses
}),
role: "presentation",
children: /*#__PURE__*/jsx(CSSTransition$1, _extends({
mountOnEnter: true,
unmountOnExit: true,
timeout: theme.transitions.duration.complex,
classNames: transitionClasses
}, other, {
children: children
}), transKey)
});
}
const useIsDateDisabled = ({
shouldDisableDate,
shouldDisableMonth,
shouldDisableYear,
minDate,
maxDate,
disableFuture,
disablePast,
timezone
}) => {
const adapter = useLocalizationContext();
return React.useCallback(day => validateDate({
adapter,
value: day,
props: {
shouldDisableDate,
shouldDisableMonth,
shouldDisableYear,
minDate,
maxDate,
disableFuture,
disablePast,
timezone
}
}) !== null, [adapter, shouldDisableDate, shouldDisableMonth, shouldDisableYear, minDate, maxDate, disableFuture, disablePast, timezone]);
};
const getDayCalendarUtilityClass = slot => generateUtilityClass('MuiDayCalendar', slot);
generateUtilityClasses('MuiDayCalendar', ['root', 'header', 'weekDayLabel', 'loadingContainer', 'slideTransition', 'monthContainer', 'weekContainer', 'weekNumberLabel', 'weekNumber']);
const _excluded$f = ["parentProps", "day", "focusableDay", "selectedDays", "isDateDisabled", "currentMonthNumber", "isViewFocused"],
_excluded2$4 = ["ownerState"];
const useUtilityClasses$8 = ownerState => {
const {
classes
} = ownerState;
const slots = {
root: ['root'],
header: ['header'],
weekDayLabel: ['weekDayLabel'],
loadingContainer: ['loadingContainer'],
slideTransition: ['slideTransition'],
monthContainer: ['monthContainer'],
weekContainer: ['weekContainer'],
weekNumberLabel: ['weekNumberLabel'],
weekNumber: ['weekNumber']
};
return composeClasses(slots, getDayCalendarUtilityClass, classes);
};
const weeksContainerHeight = (DAY_SIZE + DAY_MARGIN * 2) * 6;
const PickersCalendarDayRoot = styled$3('div', {
name: 'MuiDayCalendar',
slot: 'Root',
overridesResolver: (_, styles) => styles.root
})({});
const PickersCalendarDayHeader = styled$3('div', {
name: 'MuiDayCalendar',
slot: 'Header',
overridesResolver: (_, styles) => styles.header
})({
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
});
const PickersCalendarWeekDayLabel = styled$3(Typography, {
name: 'MuiDayCalendar',
slot: 'WeekDayLabel',
overridesResolver: (_, styles) => styles.weekDayLabel
})(({
theme
}) => ({
width: 36,
height: 40,
margin: '0 2px',
textAlign: 'center',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
color: (theme.vars || theme).palette.text.secondary
}));
const PickersCalendarWeekNumberLabel = styled$3(Typography, {
name: 'MuiDayCalendar',
slot: 'WeekNumberLabel',
overridesResolver: (_, styles) => styles.weekNumberLabel
})(({
theme
}) => ({
width: 36,
height: 40,
margin: '0 2px',
textAlign: 'center',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
color: theme.palette.text.disabled
}));
const PickersCalendarWeekNumber = styled$3(Typography, {
name: 'MuiDayCalendar',
slot: 'WeekNumber',
overridesResolver: (_, styles) => styles.weekNumber
})(({
theme
}) => _extends({}, theme.typography.caption, {
width: DAY_SIZE,
height: DAY_SIZE,
padding: 0,
margin: `0 ${DAY_MARGIN}px`,
color: theme.palette.text.disabled,
fontSize: '0.75rem',
alignItems: 'center',
justifyContent: 'center',
display: 'inline-flex'
}));
const PickersCalendarLoadingContainer = styled$3('div', {
name: 'MuiDayCalendar',
slot: 'LoadingContainer',
overridesResolver: (_, styles) => styles.loadingContainer
})({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: weeksContainerHeight
});
const PickersCalendarSlideTransition = styled$3(PickersSlideTransition, {
name: 'MuiDayCalendar',
slot: 'SlideTransition',
overridesResolver: (_, styles) => styles.slideTransition
})({
minHeight: weeksContainerHeight
});
const PickersCalendarWeekContainer = styled$3('div', {
name: 'MuiDayCalendar',
slot: 'MonthContainer',
overridesResolver: (_, styles) => styles.monthContainer
})({
overflow: 'hidden'
});
const PickersCalendarWeek = styled$3('div', {
name: 'MuiDayCalendar',
slot: 'WeekContainer',
overridesResolver: (_, styles) => styles.weekContainer
})({
margin: `${DAY_MARGIN}px 0`,
display: 'flex',
justifyContent: 'center'
});
function WrappedDay(_ref) {
var _ref2, _slots$day, _slotProps$day;
let {
parentProps,
day,
focusableDay,
selectedDays,
isDateDisabled,
currentMonthNumber,
isViewFocused
} = _ref,
other = _objectWithoutPropertiesLoose$1(_ref, _excluded$f);
const {
disabled,
disableHighlightToday,
isMonthSwitchingAnimating,
showDaysOutsideCurrentMonth,
components,
componentsProps,
slots,
slotProps,
timezone
} = parentProps;
const utils = useUtils();
const now = useNow(timezone);
const isFocusableDay = focusableDay !== null && utils.isSameDay(day, focusableDay);
const isSelected = selectedDays.some(selectedDay => utils.isSameDay(selectedDay, day));
const isToday = utils.isSameDay(day, now);
const Day = (_ref2 = (_slots$day = slots == null ? void 0 : slots.day) != null ? _slots$day : components == null ? void 0 : components.Day) != null ? _ref2 : PickersDay;
// We don't want to pass to ownerState down, to avoid re-rendering all the day whenever a prop changes.
const _useSlotProps = useSlotProps({
elementType: Day,
externalSlotProps: (_slotProps$day = slotProps == null ? void 0 : slotProps.day) != null ? _slotProps$day : componentsProps == null ? void 0 : componentsProps.day,
additionalProps: _extends({
disableHighlightToday,
showDaysOutsideCurrentMonth,
role: 'gridcell',
isAnimating: isMonthSwitchingAnimating,
// it is used in date range dragging logic by accessing `dataset.timestamp`
'data-timestamp': utils.toJsDate(day).valueOf()
}, other),
ownerState: _extends({}, parentProps, {
day,
selected: isSelected
})
}),
dayProps = _objectWithoutPropertiesLoose$1(_useSlotProps, _excluded2$4);
const isDisabled = React.useMemo(() => disabled || isDateDisabled(day), [disabled, isDateDisabled, day]);
const outsideCurrentMonth = React.useMemo(() => utils.getMonth(day) !== currentMonthNumber, [utils, day, currentMonthNumber]);
const isFirstVisibleCell = React.useMemo(() => {
const startOfMonth = utils.startOfMonth(utils.setMonth(day, currentMonthNumber));
if (!showDaysOutsideCurrentMonth) {
return utils.isSameDay(day, startOfMonth);
}
return utils.isSameDay(day, utils.startOfWeek(startOfMonth));
}, [currentMonthNumber, day, showDaysOutsideCurrentMonth, utils]);
const isLastVisibleCell = React.useMemo(() => {
const endOfMonth = utils.endOfMonth(utils.setMonth(day, currentMonthNumber));
if (!showDaysOutsideCurrentMonth) {
return utils.isSameDay(day, endOfMonth);
}
return utils.isSameDay(day, utils.endOfWeek(endOfMonth));
}, [currentMonthNumber, day, showDaysOutsideCurrentMonth, utils]);
return /*#__PURE__*/jsx(Day, _extends({}, dayProps, {
day: day,
disabled: isDisabled,
autoFocus: isViewFocused && isFocusableDay,
today: isToday,
outsideCurrentMonth: outsideCurrentMonth,
isFirstVisibleCell: isFirstVisibleCell,
isLastVisibleCell: isLastVisibleCell,
selected: isSelected,
tabIndex: isFocusableDay ? 0 : -1,
"aria-selected": isSelected,
"aria-current": isToday ? 'date' : undefined
}));
}
/**
* @ignore - do not document.
*/
function DayCalendar(inProps) {
const props = useThemeProps({
props: inProps,
name: 'MuiDayCalendar'
});
const {
onFocusedDayChange,
className,
currentMonth,
selectedDays,
focusedDay,
loading,
onSelectedDaysChange,
onMonthSwitchingAnimationEnd,
readOnly,
reduceAnimations,
renderLoading = () => /*#__PURE__*/jsx("span", {
children: "..."
}),
slideDirection,
TransitionProps,
disablePast,
disableFuture,
minDate,
maxDate,
shouldDisableDate,
shouldDisableMonth,
shouldDisableYear,
dayOfWeekFormatter: dayOfWeekFormatterFromProps,
hasFocus,
onFocusedViewChange,
gridLabelId,
displayWeekNumber,
fixedWeekNumber,
autoFocus,
timezone
} = props;
const now = useNow(timezone);
const utils = useUtils();
const classes = useUtilityClasses$8(props);
const theme = useTheme$2();
const isRTL = theme.direction === 'rtl';
// before we could define this outside of the component scope, but now we need utils, which is only defined here
const dayOfWeekFormatter = dayOfWeekFormatterFromProps || ((_day, date) => utils.format(date, 'weekdayShort').charAt(0).toUpperCase());
const isDateDisabled = useIsDateDisabled({
shouldDisableDate,
shouldDisableMonth,
shouldDisableYear,
minDate,
maxDate,
disablePast,
disableFuture,
timezone
});
const localeText = useLocaleText();
const [internalHasFocus, setInternalHasFocus] = useControlled({
name: 'DayCalendar',
state: 'hasFocus',
controlled: hasFocus,
default: autoFocus != null ? autoFocus : false
});
const [internalFocusedDay, setInternalFocusedDay] = React.useState(() => focusedDay || now);
const handleDaySelect = useEventCallback(day => {
if (readOnly) {
return;
}
onSelectedDaysChange(day);
});
const focusDay = day => {
if (!isDateDisabled(day)) {
onFocusedDayChange(day);
setInternalFocusedDay(day);
onFocusedViewChange == null || onFocusedViewChange(true);
setInternalHasFocus(true);
}
};
const handleKeyDown = useEventCallback((event, day) => {
switch (event.key) {
case 'ArrowUp':
focusDay(utils.addDays(day, -7));
event.preventDefault();
break;
case 'ArrowDown':
focusDay(utils.addDays(day, 7));
event.preventDefault();
break;
case 'ArrowLeft':
{
const newFocusedDayDefault = utils.addDays(day, isRTL ? 1 : -1);
const nextAvailableMonth = utils.addMonths(day, isRTL ? 1 : -1);
const closestDayToFocus = findClosestEnabledDate({
utils,
date: newFocusedDayDefault,
minDate: isRTL ? newFocusedDayDefault : utils.startOfMonth(nextAvailableMonth),
maxDate: isRTL ? utils.endOfMonth(nextAvailableMonth) : newFocusedDayDefault,
isDateDisabled,
timezone
});
focusDay(closestDayToFocus || newFocusedDayDefault);
event.preventDefault();
break;
}
case 'ArrowRight':
{
const newFocusedDayDefault = utils.addDays(day, isRTL ? -1 : 1);
const nextAvailableMonth = utils.addMonths(day, isRTL ? -1 : 1);
const closestDayToFocus = findClosestEnabledDate({
utils,
date: newFocusedDayDefault,
minDate: isRTL ? utils.startOfMonth(nextAvailableMonth) : newFocusedDayDefault,
maxDate: isRTL ? newFocusedDayDefault : utils.endOfMonth(nextAvailableMonth),
isDateDisabled,
timezone
});
focusDay(closestDayToFocus || newFocusedDayDefault);
event.preventDefault();
break;
}
case 'Home':
focusDay(utils.startOfWeek(day));
event.preventDefault();
break;
case 'End':
focusDay(utils.endOfWeek(day));
event.preventDefault();
break;
case 'PageUp':
focusDay(utils.addMonths(day, 1));
event.preventDefault();
break;
case 'PageDown':
focusDay(utils.addMonths(day, -1));
event.preventDefault();
break;
}
});
const handleFocus = useEventCallback((event, day) => focusDay(day));
const handleBlur = useEventCallback((event, day) => {
if (internalHasFocus && utils.isSameDay(internalFocusedDay, day)) {
onFocusedViewChange == null || onFocusedViewChange(false);
}
});
const currentMonthNumber = utils.getMonth(currentMonth);
const validSelectedDays = React.useMemo(() => selectedDays.filter(day => !!day).map(day => utils.startOfDay(day)), [utils, selectedDays]);
// need a new ref whenever the `key` of the transition changes: http://reactcommunity.org/react-transition-group/transition/#Transition-prop-nodeRef.
const transitionKey = currentMonthNumber;
// eslint-disable-next-line react-hooks/exhaustive-deps
const slideNodeRef = React.useMemo(() => /*#__PURE__*/React.createRef(), [transitionKey]);
const startOfCurrentWeek = utils.startOfWeek(now);
const focusableDay = React.useMemo(() => {
const startOfMonth = utils.startOfMonth(currentMonth);
const endOfMonth = utils.endOfMonth(currentMonth);
if (isDateDisabled(internalFocusedDay) || utils.isAfterDay(internalFocusedDay, endOfMonth) || utils.isBeforeDay(internalFocusedDay, startOfMonth)) {
return findClosestEnabledDate({
utils,
date: internalFocusedDay,
minDate: startOfMonth,
maxDate: endOfMonth,
disablePast,
disableFuture,
isDateDisabled,
timezone
});
}
return internalFocusedDay;
}, [currentMonth, disableFuture, disablePast, internalFocusedDay, isDateDisabled, utils, timezone]);
const weeksToDisplay = React.useMemo(() => {
const currentMonthWithTimezone = utils.setTimezone(currentMonth, timezone);
const toDisplay = utils.getWeekArray(currentMonthWithTimezone);
let nextMonth = utils.addMonths(currentMonthWithTimezone, 1);
while (fixedWeekNumber && toDisplay.length < fixedWeekNumber) {
const additionalWeeks = utils.getWeekArray(nextMonth);
const hasCommonWeek = utils.isSameDay(toDisplay[toDisplay.length - 1][0], additionalWeeks[0][0]);
additionalWeeks.slice(hasCommonWeek ? 1 : 0).forEach(week => {
if (toDisplay.length < fixedWeekNumber) {
toDisplay.push(week);
}
});
nextMonth = utils.addMonths(nextMonth, 1);
}
return toDisplay;
}, [currentMonth, fixedWeekNumber, utils, timezone]);
return /*#__PURE__*/jsxs(PickersCalendarDayRoot, {
role: "grid",
"aria-labelledby": gridLabelId,
className: classes.root,
children: [/*#__PURE__*/jsxs(PickersCalendarDayHeader, {
role: "row",
className: classes.header,
children: [displayWeekNumber && /*#__PURE__*/jsx(PickersCalendarWeekNumberLabel, {
variant: "caption",
role: "columnheader",
"aria-label": localeText.calendarWeekNumberHeaderLabel,
className: classes.weekNumberLabel,
children: localeText.calendarWeekNumberHeaderText
}), getWeekdays(utils, now).map((weekday, i) => {
var _dayOfWeekFormatter;
const day = utils.format(weekday, 'weekdayShort');
return /*#__PURE__*/jsx(PickersCalendarWeekDayLabel, {
variant: "caption",
role: "columnheader",
"aria-label": utils.format(utils.addDays(startOfCurrentWeek, i), 'weekday'),
className: classes.weekDayLabel,
children: (_dayOfWeekFormatter = dayOfWeekFormatter == null ? void 0 : dayOfWeekFormatter(day, weekday)) != null ? _dayOfWeekFormatter : day
}, day + i.toString());
})]
}), loading ? /*#__PURE__*/jsx(PickersCalendarLoadingContainer, {
className: classes.loadingContainer,
children: renderLoading()
}) : /*#__PURE__*/jsx(PickersCalendarSlideTransition, _extends({
transKey: transitionKey,
onExited: onMonthSwitchingAnimationEnd,
reduceAnimations: reduceAnimations,
slideDirection: slideDirection,
className: clsx(className, classes.slideTransition)
}, TransitionProps, {
nodeRef: slideNodeRef,
children: /*#__PURE__*/jsx(PickersCalendarWeekContainer, {
ref: slideNodeRef,
role: "rowgroup",
className: classes.monthContainer,
children: weeksToDisplay.map((week, index) => /*#__PURE__*/jsxs(PickersCalendarWeek, {
role: "row",
className: classes.weekContainer
// fix issue of announcing row 1 as row 2
// caused by week day labels row
,
"aria-rowindex": index + 1,
children: [displayWeekNumber && /*#__PURE__*/jsx(PickersCalendarWeekNumber, {
className: classes.weekNumber,
role: "rowheader",
"aria-label": localeText.calendarWeekNumberAriaLabelText(utils.getWeekNumber(week[0])),
children: localeText.calendarWeekNumberText(utils.getWeekNumber(week[0]))
}), week.map((day, dayIndex) => /*#__PURE__*/jsx(WrappedDay, {
parentProps: props,
day: day,
selectedDays: validSelectedDays,
focusableDay: focusableDay,
onKeyDown: handleKeyDown,
onFocus: handleFocus,
onBlur: handleBlur,
onDaySelect: handleDaySelect,
isDateDisabled: isDateDisabled,
currentMonthNumber: currentMonthNumber,
isViewFocused: internalHasFocus
// fix issue of announcing column 1 as column 2 when `displayWeekNumber` is enabled
,
"aria-colindex": dayIndex + 1
}, day.toString()))]
}, `week-${week[0]}`))
})
}))]
});
}
const createCalendarStateReducer = (reduceAnimations, disableSwitchToMonthOnDayFocus, utils) => (state, action) => {
switch (action.type) {
case 'changeMonth':
return _extends({}, state, {
slideDirection: action.direction,
currentMonth: action.newMonth,
isMonthSwitchingAnimating: !reduceAnimations
});
case 'finishMonthSwitchingAnimation':
return _extends({}, state, {
isMonthSwitchingAnimating: false
});
case 'changeFocusedDay':
{
if (state.focusedDay != null && action.focusedDay != null && utils.isSameDay(action.focusedDay, state.focusedDay)) {
return state;
}
const needMonthSwitch = action.focusedDay != null && !disableSwitchToMonthOnDayFocus && !utils.isSameMonth(state.currentMonth, action.focusedDay);
return _extends({}, state, {
focusedDay: action.focusedDay,
isMonthSwitchingAnimating: needMonthSwitch && !reduceAnimations && !action.withoutMonthSwitchingAnimation,
currentMonth: needMonthSwitch ? utils.startOfMonth(action.focusedDay) : state.currentMonth,
slideDirection: action.focusedDay != null && utils.isAfterDay(action.focusedDay, state.currentMonth) ? 'left' : 'right'
});
}
default:
throw new Error('missing support');
}
};
const useCalendarState = params => {
const {
value,
referenceDate: referenceDateProp,
defaultCalendarMonth,
disableFuture,
disablePast,
disableSwitchToMonthOnDayFocus = false,
maxDate,
minDate,
onMonthChange,
reduceAnimations,
shouldDisableDate,
timezone
} = params;
const utils = useUtils();
const reducerFn = React.useRef(createCalendarStateReducer(Boolean(reduceAnimations), disableSwitchToMonthOnDayFocus, utils)).current;
const referenceDate = React.useMemo(() => {
let externalReferenceDate = null;
if (referenceDateProp) {
externalReferenceDate = referenceDateProp;
} else if (defaultCalendarMonth) {
// For `defaultCalendarMonth`, we just want to keep the month and the year to avoid a behavior change.
externalReferenceDate = utils.startOfMonth(defaultCalendarMonth);
}
return singleItemValueManager.getInitialReferenceValue({
value,
utils,
timezone,
props: params,
referenceDate: externalReferenceDate,
granularity: SECTION_TYPE_GRANULARITY.day
});
}, [] // eslint-disable-line react-hooks/exhaustive-deps
);
const [calendarState, dispatch] = React.useReducer(reducerFn, {
isMonthSwitchingAnimating: false,
focusedDay: referenceDate,
currentMonth: utils.startOfMonth(referenceDate),
slideDirection: 'left'
});
const handleChangeMonth = React.useCallback(payload => {
dispatch(_extends({
type: 'changeMonth'
}, payload));
if (onMonthChange) {
onMonthChange(payload.newMonth);
}
}, [onMonthChange]);
const changeMonth = React.useCallback(newDate => {
const newDateRequested = newDate;
if (utils.isSameMonth(newDateRequested, calendarState.currentMonth)) {
return;
}
handleChangeMonth({
newMonth: utils.startOfMonth(newDateRequested),
direction: utils.isAfterDay(newDateRequested, calendarState.currentMonth) ? 'left' : 'right'
});
}, [calendarState.currentMonth, handleChangeMonth, utils]);
const isDateDisabled = useIsDateDisabled({
shouldDisableDate,
minDate,
maxDate,
disableFuture,
disablePast,
timezone
});
const onMonthSwitchingAnimationEnd = React.useCallback(() => {
dispatch({
type: 'finishMonthSwitchingAnimation'
});
}, []);
const changeFocusedDay = useEventCallback((newFocusedDate, withoutMonthSwitchingAnimation) => {
if (!isDateDisabled(newFocusedDate)) {
dispatch({
type: 'changeFocusedDay',
focusedDay: newFocusedDate,
withoutMonthSwitchingAnimation
});
}
});
return {
referenceDate,
calendarState,
changeMonth,
changeFocusedDay,
isDateDisabled,
onMonthSwitchingAnimationEnd,
handleChangeMonth
};
};
const _excluded$e = ["ownerState"];
const useClearableField = ({
clearable,
fieldProps: forwardedFieldProps,
InputProps: ForwardedInputProps,
onClear,
slots,
slotProps,
components,
componentsProps
}) => {
var _ref, _slots$clearButton, _slotProps$clearButto, _ref2, _slots$clearIcon, _slotProps$clearIcon;
const localeText = useLocaleText();
const IconButton$1 = (_ref = (_slots$clearButton = slots == null ? void 0 : slots.clearButton) != null ? _slots$clearButton : components == null ? void 0 : components.ClearButton) != null ? _ref : IconButton;
// The spread is here to avoid this bug mui/material-ui#34056
const _useSlotProps = useSlotProps({
elementType: IconButton$1,
externalSlotProps: (_slotProps$clearButto = slotProps == null ? void 0 : slotProps.clearButton) != null ? _slotProps$clearButto : componentsProps == null ? void 0 : componentsProps.clearButton,
ownerState: {},
className: 'clearButton',
additionalProps: {
title: localeText.fieldClearLabel
}
}),
iconButtonProps = _objectWithoutPropertiesLoose$1(_useSlotProps, _excluded$e);
const EndClearIcon = (_ref2 = (_slots$clearIcon = slots == null ? void 0 : slots.clearIcon) != null ? _slots$clearIcon : components == null ? void 0 : components.ClearIcon) != null ? _ref2 : ClearIcon;
const endClearIconProps = useSlotProps({
elementType: EndClearIcon,
externalSlotProps: (_slotProps$clearIcon = slotProps == null ? void 0 : slotProps.clearIcon) != null ? _slotProps$clearIcon : componentsProps == null ? void 0 : componentsProps.clearIcon,
ownerState: {}
});
const InputProps = _extends({}, ForwardedInputProps, {
endAdornment: /*#__PURE__*/jsxs(React.Fragment, {
children: [clearable && /*#__PURE__*/jsx(InputAdornment, {
position: "end",
sx: {
marginRight: ForwardedInputProps != null && ForwardedInputProps.endAdornment ? -1 : -1.5
},
children: /*#__PURE__*/jsx(IconButton$1, _extends({}, iconButtonProps, {
onClick: onClear,
children: /*#__PURE__*/jsx(EndClearIcon, _extends({
fontSize: "small"
}, endClearIconProps))
}))
}), ForwardedInputProps == null ? void 0 : ForwardedInputProps.endAdornment]
})
});
const fieldProps = _extends({}, forwardedFieldProps, {
sx: [{
'& .clearButton': {
opacity: 1
},
'@media (pointer: fine)': {
'& .clearButton': {
opacity: 0
},
'&:hover, &:focus-within': {
'.clearButton': {
opacity: 1
}
}
}
}, ...(Array.isArray(forwardedFieldProps.sx) ? forwardedFieldProps.sx : [forwardedFieldProps.sx])]
});
return {
InputProps,
fieldProps
};
};
const _excluded$d = ["components", "componentsProps", "slots", "slotProps", "InputProps", "inputProps"],
_excluded2$3 = ["inputRef"],
_excluded3$2 = ["ref", "onPaste", "onKeyDown", "inputMode", "readOnly", "clearable", "onClear"];
/**
* Demos:
*
* - [DateField](http://mui.com/x/react-date-pickers/date-field/)
* - [Fields](https://mui.com/x/react-date-pickers/fields/)
*
* API:
*
* - [DateField API](https://mui.com/x/api/date-pickers/date-field/)
*/
const DateField = /*#__PURE__*/React.forwardRef(function DateField(inProps, ref) {
var _ref, _slots$textField, _slotProps$textField;
const themeProps = useThemeProps({
props: inProps,
name: 'MuiDateField'
});
const {
components,
componentsProps,
slots,
slotProps,
InputProps,
inputProps
} = themeProps,
other = _objectWithoutPropertiesLoose$1(themeProps, _excluded$d);
const ownerState = themeProps;
const TextField = (_ref = (_slots$textField = slots == null ? void 0 : slots.textField) != null ? _slots$textField : components == null ? void 0 : components.TextField) != null ? _ref : MuiTextField;
const _useSlotProps = useSlotProps({
elementType: TextField,
externalSlotProps: (_slotProps$textField = slotProps == null ? void 0 : slotProps.textField) != null ? _slotProps$textField : componentsProps == null ? void 0 : componentsProps.textField,
externalForwardedProps: other,
ownerState
}),
{
inputRef: externalInputRef
} = _useSlotProps,
textFieldProps = _objectWithoutPropertiesLoose$1(_useSlotProps, _excluded2$3);
// TODO: Remove when mui/material-ui#35088 will be merged
textFieldProps.inputProps = _extends({}, inputProps, textFieldProps.inputProps);
textFieldProps.InputProps = _extends({}, InputProps, textFieldProps.InputProps);
const _useDateField = useDateField({
props: textFieldProps,
inputRef: externalInputRef
}),
{
ref: inputRef,
onPaste,
onKeyDown,
inputMode,
readOnly,
clearable,
onClear
} = _useDateField,
fieldProps = _objectWithoutPropertiesLoose$1(_useDateField, _excluded3$2);
const {
InputProps: ProcessedInputProps,
fieldProps: processedFieldProps
} = useClearableField({
onClear,
clearable,
fieldProps,
InputProps: fieldProps.InputProps,
slots,
slotProps,
components,
componentsProps
});
return /*#__PURE__*/jsx(TextField, _extends({
ref: ref
}, processedFieldProps, {
InputProps: _extends({}, ProcessedInputProps, {
readOnly
}),
inputProps: _extends({}, fieldProps.inputProps, {
inputMode,
onPaste,
onKeyDown,
ref: inputRef
})
}));
});
process.env.NODE_ENV !== "production" ? DateField.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* If `true`, the `input` element is focused during the first mount.
* @default false
*/
autoFocus: PropTypes.bool,
className: PropTypes.string,
/**
* If `true`, a clear button will be shown in the field allowing value clearing.
* @default false
*/
clearable: PropTypes.bool,
/**
* The color of the component.
* It supports both default and custom theme colors, which can be added as shown in the
* [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
* @default 'primary'
*/
color: PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']),
component: PropTypes.elementType,
/**
* Overridable components.
* @default {}
* @deprecated Please use `slots`.
*/
components: PropTypes.object,
/**
* The props used for each component slot.
* @default {}
* @deprecated Please use `slotProps`.
*/
componentsProps: PropTypes.object,
/**
* The default value. Use when the component is not controlled.
*/
defaultValue: PropTypes.any,
/**
* If `true`, the component is disabled.
* @default false
*/
disabled: PropTypes.bool,
/**
* If `true`, disable values after the current date for date components, time for time components and both for date time components.
* @default false
*/
disableFuture: PropTypes.bool,
/**
* If `true`, disable values before the current date for date components, time for time components and both for date time components.
* @default false
*/
disablePast: PropTypes.bool,
/**
* If `true`, the component is displayed in focused state.
*/
focused: PropTypes.bool,
/**
* Format of the date when rendered in the input(s).
*/
format: PropTypes.string,
/**
* Density of the format when rendered in the input.
* Setting `formatDensity` to `"spacious"` will add a space before and after each `/`, `-` and `.` character.
* @default "dense"
*/
formatDensity: PropTypes.oneOf(['dense', 'spacious']),
/**
* Props applied to the [`FormHelperText`](/material-ui/api/form-helper-text/) element.
*/
FormHelperTextProps: PropTypes.object,
/**
* If `true`, the input will take up the full width of its container.
* @default false
*/
fullWidth: PropTypes.bool,
/**
* The helper text content.
*/
helperText: PropTypes.node,
/**
* If `true`, the label is hidden.
* This is used to increase density for a `FilledInput`.
* Be sure to add `aria-label` to the `input` element.
* @default false
*/
hiddenLabel: PropTypes.bool,
/**
* The id of the `input` element.
* Use this prop to make `label` and `helperText` accessible for screen readers.
*/
id: PropTypes.string,
/**
* Props applied to the [`InputLabel`](/material-ui/api/input-label/) element.
* Pointer events like `onClick` are enabled if and only if `shrink` is `true`.
*/
InputLabelProps: PropTypes.object,
/**
* [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.
*/
inputProps: PropTypes.object,
/**
* Props applied to the Input element.
* It will be a [`FilledInput`](/material-ui/api/filled-input/),
* [`OutlinedInput`](/material-ui/api/outlined-input/) or [`Input`](/material-ui/api/input/)
* component depending on the `variant` prop value.
*/
InputProps: PropTypes.object,
/**
* Pass a ref to the `input` element.
*/
inputRef: refType$1,
/**
* The label content.
*/
label: PropTypes.node,
/**
* If `dense` or `normal`, will adjust vertical spacing of this and contained components.
* @default 'none'
*/
margin: PropTypes.oneOf(['dense', 'none', 'normal']),
/**
* Maximal selectable date.
*/
maxDate: PropTypes.any,
/**
* Minimal selectable date.
*/
minDate: PropTypes.any,
/**
* Name attribute of the `input` element.
*/
name: PropTypes.string,
onBlur: PropTypes.func,
/**
* Callback fired when the value changes.
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value.
* @param {TValue} value The new value.
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
*/
onChange: PropTypes.func,
/**
* Callback fired when the clear button is clicked.
*/
onClear: PropTypes.func,
/**
* Callback fired when the error associated to the current value changes.
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value.
* @param {TError} error The new error.
* @param {TValue} value The value associated to the error.
*/
onError: PropTypes.func,
onFocus: PropTypes.func,
/**
* Callback fired when the selected sections change.
* @param {FieldSelectedSections} newValue The new selected sections.
*/
onSelectedSectionsChange: PropTypes.func,
/**
* It prevents the user from changing the value of the field
* (not from interacting with the field).
* @default false
*/
readOnly: PropTypes.bool,
/**
* The date used to generate a part of the new value that is not present in the format when both `value` and `defaultValue` are empty.
* For example, on time fields it will be used to determine the date to set.
* @default The closest valid date using the validation props, except callbacks such as `shouldDisableDate`. Value is rounded to the most granular section used.
*/
referenceDate: PropTypes.any,
/**
* If `true`, the label is displayed as required and the `input` element is required.
* @default false
*/
required: PropTypes.bool,
/**
* The currently selected sections.
* This prop accept four formats:
* 1. If a number is provided, the section at this index will be selected.
* 2. If an object with a `startIndex` and `endIndex` properties are provided, the sections between those two indexes will be selected.
* 3. If a string of type `FieldSectionType` is provided, the first section with that name will be selected.
* 4. If `null` is provided, no section will be selected
* If not provided, the selected sections will be handled internally.
*/
selectedSections: PropTypes.oneOfType([PropTypes.oneOf(['all', 'day', 'hours', 'meridiem', 'minutes', 'month', 'seconds', 'weekDay', 'year']), PropTypes.number, PropTypes.shape({
endIndex: PropTypes.number.isRequired,
startIndex: PropTypes.number.isRequired
})]),
/**
* Disable specific date.
*
* Warning: This function can be called multiple times (e.g. when rendering date calendar, checking if focus can be moved to a certain date, etc.). Expensive computations can impact performance.
*
* @template TDate
* @param {TDate} day The date to test.
* @returns {boolean} If `true` the date will be disabled.
*/
shouldDisableDate: PropTypes.func,
/**
* Disable specific month.
* @template TDate
* @param {TDate} month The month to test.
* @returns {boolean} If `true`, the month will be disabled.
*/
shouldDisableMonth: PropTypes.func,
/**
* Disable specific year.
* @template TDate
* @param {TDate} year The year to test.
* @returns {boolean} If `true`, the year will be disabled.
*/
shouldDisableYear: PropTypes.func,
/**
* If `true`, the format will respect the leading zeroes (e.g: on dayjs, the format `M/D/YYYY` will render `8/16/2018`)
* If `false`, the format will always add leading zeroes (e.g: on dayjs, the format `M/D/YYYY` will render `08/16/2018`)
*
* Warning n°1: Luxon is not able to respect the leading zeroes when using macro tokens (e.g: "DD"), so `shouldRespectLeadingZeros={true}` might lead to inconsistencies when using `AdapterLuxon`.
*
* Warning n°2: When `shouldRespectLeadingZeros={true}`, the field will add an invisible character on the sections containing a single digit to make sure `onChange` is fired.
* If you need to get the clean value from the input, you can remove this character using `input.value.replace(/\u200e/g, '')`.
*
* Warning n°3: When used in strict mode, dayjs and moment require to respect the leading zeros.
* This mean that when using `shouldRespectLeadingZeros={false}`, if you retrieve the value directly from the input (not listening to `onChange`) and your format contains tokens without leading zeros, the value will not be parsed by your library.
*
* @default `false`
*/
shouldRespectLeadingZeros: PropTypes.bool,
/**
* The size of the component.
*/
size: PropTypes.oneOf(['medium', 'small']),
/**
* The props used for each component slot.
* @default {}
*/
slotProps: PropTypes.object,
/**
* Overridable component slots.
* @default {}
*/
slots: PropTypes.object,
style: PropTypes.object,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
/**
* Choose which timezone to use for the value.
* Example: "default", "system", "UTC", "America/New_York".
* If you pass values from other timezones to some props, they will be converted to this timezone before being used.
* @see See the {@link https://mui.com/x/react-date-pickers/timezone/ timezones documention} for more details.
* @default The timezone of the `value` or `defaultValue` prop is defined, 'default' otherwise.
*/
timezone: PropTypes.string,
/**
* The ref object used to imperatively interact with the field.
*/
unstableFieldRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
/**
* The selected value.
* Used when the component is controlled.
*/
value: PropTypes.any,
/**
* The variant to use.
* @default 'outlined'
*/
variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
} : void 0;
const getPickersFadeTransitionGroupUtilityClass = slot => generateUtilityClass('MuiPickersFadeTransitionGroup', slot);
generateUtilityClasses('MuiPickersFadeTransitionGroup', ['root']);
const useUtilityClasses$7 = ownerState => {
const {
classes
} = ownerState;
const slots = {
root: ['root']
};
return composeClasses(slots, getPickersFadeTransitionGroupUtilityClass, classes);
};
const PickersFadeTransitionGroupRoot = styled$3(TransitionGroup$1, {
name: 'MuiPickersFadeTransitionGroup',
slot: 'Root',
overridesResolver: (_, styles) => styles.root
})({
display: 'block',
position: 'relative'
});
/**
* @ignore - do not document.
*/
function PickersFadeTransitionGroup(inProps) {
const props = useThemeProps({
props: inProps,
name: 'MuiPickersFadeTransitionGroup'
});
const {
children,
className,
reduceAnimations,
transKey
} = props;
const classes = useUtilityClasses$7(props);
const theme = useTheme$2();
if (reduceAnimations) {
return children;
}
return /*#__PURE__*/jsx(PickersFadeTransitionGroupRoot, {
className: clsx(classes.root, className),
children: /*#__PURE__*/jsx(Fade, {
appear: false,
mountOnEnter: true,
unmountOnExit: true,
timeout: {
appear: theme.transitions.duration.enteringScreen,
enter: theme.transitions.duration.enteringScreen,
exit: 0
},
children: children
}, transKey)
});
}
/**
* @mui/styled-engine v5.15.11
*
* @license MIT
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
function styled$2(tag, options) {
const stylesFactory = emStyled(tag, options);
if (process.env.NODE_ENV !== 'production') {
return (...styles) => {
const component = typeof tag === 'string' ? `"${tag}"` : 'component';
if (styles.length === 0) {
console.error([`MUI: Seems like you called \`styled(${component})()\` without a \`style\` argument.`, 'You must provide a `styles` argument: `styled("div")(styleYouForgotToPass)`.'].join('\n'));
} else if (styles.some(style => style === undefined)) {
console.error(`MUI: the styled(${component})(...args) API requires all its args to be defined.`);
}
return stylesFactory(...styles);
};
}
return stylesFactory;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
const internal_processStyles = (tag, processor) => {
// Emotion attaches all the styles as `__emotion_styles`.
// Ref: https://github.com/emotion-js/emotion/blob/16d971d0da229596d6bcc39d282ba9753c9ee7cf/packages/styled/src/base.js#L186
if (Array.isArray(tag.__emotion_styles)) {
tag.__emotion_styles = processor(tag.__emotion_styles);
}
};
const _excluded$c = ["values", "unit", "step"];
const sortBreakpointsValues = values => {
const breakpointsAsArray = Object.keys(values).map(key => ({
key,
val: values[key]
})) || [];
// Sort in ascending order
breakpointsAsArray.sort((breakpoint1, breakpoint2) => breakpoint1.val - breakpoint2.val);
return breakpointsAsArray.reduce((acc, obj) => {
return _extends({}, acc, {
[obj.key]: obj.val
});
}, {});
};
// Keep in mind that @media is inclusive by the CSS specification.
function createBreakpoints(breakpoints) {
const {
// The breakpoint **start** at this value.
// For instance with the first breakpoint xs: [xs, sm).
values = {
xs: 0,
// phone
sm: 600,
// tablet
md: 900,
// small laptop
lg: 1200,
// desktop
xl: 1536 // large screen
},
unit = 'px',
step = 5
} = breakpoints,
other = _objectWithoutPropertiesLoose$1(breakpoints, _excluded$c);
const sortedValues = sortBreakpointsValues(values);
const keys = Object.keys(sortedValues);
function up(key) {
const value = typeof values[key] === 'number' ? values[key] : key;
return `@media (min-width:${value}${unit})`;
}
function down(key) {
const value = typeof values[key] === 'number' ? values[key] : key;
return `@media (max-width:${value - step / 100}${unit})`;
}
function between(start, end) {
const endIndex = keys.indexOf(end);
return `@media (min-width:${typeof values[start] === 'number' ? values[start] : start}${unit}) and ` + `(max-width:${(endIndex !== -1 && typeof values[keys[endIndex]] === 'number' ? values[keys[endIndex]] : end) - step / 100}${unit})`;
}
function only(key) {
if (keys.indexOf(key) + 1 < keys.length) {
return between(key, keys[keys.indexOf(key) + 1]);
}
return up(key);
}
function not(key) {
// handle first and last key separately, for better readability
const keyIndex = keys.indexOf(key);
if (keyIndex === 0) {
return up(keys[1]);
}
if (keyIndex === keys.length - 1) {
return down(keys[keyIndex]);
}
return between(key, keys[keys.indexOf(key) + 1]).replace('@media', '@media not all and');
}
return _extends({
keys,
values: sortedValues,
up,
down,
between,
only,
not,
unit
}, other);
}
const shape = {
borderRadius: 4
};
var shape$1 = shape;
const responsivePropType = process.env.NODE_ENV !== 'production' ? PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.object, PropTypes.array]) : {};
var responsivePropType$1 = responsivePropType;
function merge(acc, item) {
if (!item) {
return acc;
}
return deepmerge(acc, item, {
clone: false // No need to clone deep, it's way faster.
});
}
// The breakpoint **start** at this value.
// For instance with the first breakpoint xs: [xs, sm[.
const values = {
xs: 0,
// phone
sm: 600,
// tablet
md: 900,
// small laptop
lg: 1200,
// desktop
xl: 1536 // large screen
};
const defaultBreakpoints = {
// Sorted ASC by size. That's important.
// It can't be configured as it's used statically for propTypes.
keys: ['xs', 'sm', 'md', 'lg', 'xl'],
up: key => `@media (min-width:${values[key]}px)`
};
function handleBreakpoints(props, propValue, styleFromPropValue) {
const theme = props.theme || {};
if (Array.isArray(propValue)) {
const themeBreakpoints = theme.breakpoints || defaultBreakpoints;
return propValue.reduce((acc, item, index) => {
acc[themeBreakpoints.up(themeBreakpoints.keys[index])] = styleFromPropValue(propValue[index]);
return acc;
}, {});
}
if (typeof propValue === 'object') {
const themeBreakpoints = theme.breakpoints || defaultBreakpoints;
return Object.keys(propValue).reduce((acc, breakpoint) => {
// key is breakpoint
if (Object.keys(themeBreakpoints.values || values).indexOf(breakpoint) !== -1) {
const mediaKey = themeBreakpoints.up(breakpoint);
acc[mediaKey] = styleFromPropValue(propValue[breakpoint], breakpoint);
} else {
const cssKey = breakpoint;
acc[cssKey] = propValue[cssKey];
}
return acc;
}, {});
}
const output = styleFromPropValue(propValue);
return output;
}
function createEmptyBreakpointObject(breakpointsInput = {}) {
var _breakpointsInput$key;
const breakpointsInOrder = (_breakpointsInput$key = breakpointsInput.keys) == null ? void 0 : _breakpointsInput$key.reduce((acc, key) => {
const breakpointStyleKey = breakpointsInput.up(key);
acc[breakpointStyleKey] = {};
return acc;
}, {});
return breakpointsInOrder || {};
}
function removeUnusedBreakpoints(breakpointKeys, style) {
return breakpointKeys.reduce((acc, key) => {
const breakpointOutput = acc[key];
const isBreakpointUnused = !breakpointOutput || Object.keys(breakpointOutput).length === 0;
if (isBreakpointUnused) {
delete acc[key];
}
return acc;
}, style);
}
function getPath(obj, path, checkVars = true) {
if (!path || typeof path !== 'string') {
return null;
}
// Check if CSS variables are used
if (obj && obj.vars && checkVars) {
const val = `vars.${path}`.split('.').reduce((acc, item) => acc && acc[item] ? acc[item] : null, obj);
if (val != null) {
return val;
}
}
return path.split('.').reduce((acc, item) => {
if (acc && acc[item] != null) {
return acc[item];
}
return null;
}, obj);
}
function getStyleValue(themeMapping, transform, propValueFinal, userValue = propValueFinal) {
let value;
if (typeof themeMapping === 'function') {
value = themeMapping(propValueFinal);
} else if (Array.isArray(themeMapping)) {
value = themeMapping[propValueFinal] || userValue;
} else {
value = getPath(themeMapping, propValueFinal) || userValue;
}
if (transform) {
value = transform(value, userValue, themeMapping);
}
return value;
}
function style$1(options) {
const {
prop,
cssProperty = options.prop,
themeKey,
transform
} = options;
// false positive
// eslint-disable-next-line react/function-component-definition
const fn = props => {
if (props[prop] == null) {
return null;
}
const propValue = props[prop];
const theme = props.theme;
const themeMapping = getPath(theme, themeKey) || {};
const styleFromPropValue = propValueFinal => {
let value = getStyleValue(themeMapping, transform, propValueFinal);
if (propValueFinal === value && typeof propValueFinal === 'string') {
// Haven't found value
value = getStyleValue(themeMapping, transform, `${prop}${propValueFinal === 'default' ? '' : capitalize(propValueFinal)}`, propValueFinal);
}
if (cssProperty === false) {
return value;
}
return {
[cssProperty]: value
};
};
return handleBreakpoints(props, propValue, styleFromPropValue);
};
fn.propTypes = process.env.NODE_ENV !== 'production' ? {
[prop]: responsivePropType$1
} : {};
fn.filterProps = [prop];
return fn;
}
function memoize$1(fn) {
const cache = {};
return arg => {
if (cache[arg] === undefined) {
cache[arg] = fn(arg);
}
return cache[arg];
};
}
const properties = {
m: 'margin',
p: 'padding'
};
const directions = {
t: 'Top',
r: 'Right',
b: 'Bottom',
l: 'Left',
x: ['Left', 'Right'],
y: ['Top', 'Bottom']
};
const aliases = {
marginX: 'mx',
marginY: 'my',
paddingX: 'px',
paddingY: 'py'
};
// memoize() impact:
// From 300,000 ops/sec
// To 350,000 ops/sec
const getCssProperties = memoize$1(prop => {
// It's not a shorthand notation.
if (prop.length > 2) {
if (aliases[prop]) {
prop = aliases[prop];
} else {
return [prop];
}
}
const [a, b] = prop.split('');
const property = properties[a];
const direction = directions[b] || '';
return Array.isArray(direction) ? direction.map(dir => property + dir) : [property + direction];
});
const marginKeys = ['m', 'mt', 'mr', 'mb', 'ml', 'mx', 'my', 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'marginX', 'marginY', 'marginInline', 'marginInlineStart', 'marginInlineEnd', 'marginBlock', 'marginBlockStart', 'marginBlockEnd'];
const paddingKeys = ['p', 'pt', 'pr', 'pb', 'pl', 'px', 'py', 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'paddingX', 'paddingY', 'paddingInline', 'paddingInlineStart', 'paddingInlineEnd', 'paddingBlock', 'paddingBlockStart', 'paddingBlockEnd'];
const spacingKeys = [...marginKeys, ...paddingKeys];
function createUnaryUnit(theme, themeKey, defaultValue, propName) {
var _getPath;
const themeSpacing = (_getPath = getPath(theme, themeKey, false)) != null ? _getPath : defaultValue;
if (typeof themeSpacing === 'number') {
return abs => {
if (typeof abs === 'string') {
return abs;
}
if (process.env.NODE_ENV !== 'production') {
if (typeof abs !== 'number') {
console.error(`MUI: Expected ${propName} argument to be a number or a string, got ${abs}.`);
}
}
return themeSpacing * abs;
};
}
if (Array.isArray(themeSpacing)) {
return abs => {
if (typeof abs === 'string') {
return abs;
}
if (process.env.NODE_ENV !== 'production') {
if (!Number.isInteger(abs)) {
console.error([`MUI: The \`theme.${themeKey}\` array type cannot be combined with non integer values.` + `You should either use an integer value that can be used as index, or define the \`theme.${themeKey}\` as a number.`].join('\n'));
} else if (abs > themeSpacing.length - 1) {
console.error([`MUI: The value provided (${abs}) overflows.`, `The supported values are: ${JSON.stringify(themeSpacing)}.`, `${abs} > ${themeSpacing.length - 1}, you need to add the missing values.`].join('\n'));
}
}
return themeSpacing[abs];
};
}
if (typeof themeSpacing === 'function') {
return themeSpacing;
}
if (process.env.NODE_ENV !== 'production') {
console.error([`MUI: The \`theme.${themeKey}\` value (${themeSpacing}) is invalid.`, 'It should be a number, an array or a function.'].join('\n'));
}
return () => undefined;
}
function createUnarySpacing(theme) {
return createUnaryUnit(theme, 'spacing', 8, 'spacing');
}
function getValue(transformer, propValue) {
if (typeof propValue === 'string' || propValue == null) {
return propValue;
}
const abs = Math.abs(propValue);
const transformed = transformer(abs);
if (propValue >= 0) {
return transformed;
}
if (typeof transformed === 'number') {
return -transformed;
}
return `-${transformed}`;
}
function getStyleFromPropValue(cssProperties, transformer) {
return propValue => cssProperties.reduce((acc, cssProperty) => {
acc[cssProperty] = getValue(transformer, propValue);
return acc;
}, {});
}
function resolveCssProperty(props, keys, prop, transformer) {
// Using a hash computation over an array iteration could be faster, but with only 28 items,
// it's doesn't worth the bundle size.
if (keys.indexOf(prop) === -1) {
return null;
}
const cssProperties = getCssProperties(prop);
const styleFromPropValue = getStyleFromPropValue(cssProperties, transformer);
const propValue = props[prop];
return handleBreakpoints(props, propValue, styleFromPropValue);
}
function style(props, keys) {
const transformer = createUnarySpacing(props.theme);
return Object.keys(props).map(prop => resolveCssProperty(props, keys, prop, transformer)).reduce(merge, {});
}
function margin(props) {
return style(props, marginKeys);
}
margin.propTypes = process.env.NODE_ENV !== 'production' ? marginKeys.reduce((obj, key) => {
obj[key] = responsivePropType$1;
return obj;
}, {}) : {};
margin.filterProps = marginKeys;
function padding(props) {
return style(props, paddingKeys);
}
padding.propTypes = process.env.NODE_ENV !== 'production' ? paddingKeys.reduce((obj, key) => {
obj[key] = responsivePropType$1;
return obj;
}, {}) : {};
padding.filterProps = paddingKeys;
process.env.NODE_ENV !== 'production' ? spacingKeys.reduce((obj, key) => {
obj[key] = responsivePropType$1;
return obj;
}, {}) : {};
// The different signatures imply different meaning for their arguments that can't be expressed structurally.
// We express the difference with variable names.
function createSpacing(spacingInput = 8) {
// Already transformed.
if (spacingInput.mui) {
return spacingInput;
}
// Material Design layouts are visually balanced. Most measurements align to an 8dp grid, which aligns both spacing and the overall layout.
// Smaller components, such as icons, can align to a 4dp grid.
// https://m2.material.io/design/layout/understanding-layout.html
const transform = createUnarySpacing({
spacing: spacingInput
});
const spacing = (...argsInput) => {
if (process.env.NODE_ENV !== 'production') {
if (!(argsInput.length <= 4)) {
console.error(`MUI: Too many arguments provided, expected between 0 and 4, got ${argsInput.length}`);
}
}
const args = argsInput.length === 0 ? [1] : argsInput;
return args.map(argument => {
const output = transform(argument);
return typeof output === 'number' ? `${output}px` : output;
}).join(' ');
};
spacing.mui = true;
return spacing;
}
function compose(...styles) {
const handlers = styles.reduce((acc, style) => {
style.filterProps.forEach(prop => {
acc[prop] = style;
});
return acc;
}, {});
// false positive
// eslint-disable-next-line react/function-component-definition
const fn = props => {
return Object.keys(props).reduce((acc, prop) => {
if (handlers[prop]) {
return merge(acc, handlers[prop](props));
}
return acc;
}, {});
};
fn.propTypes = process.env.NODE_ENV !== 'production' ? styles.reduce((acc, style) => Object.assign(acc, style.propTypes), {}) : {};
fn.filterProps = styles.reduce((acc, style) => acc.concat(style.filterProps), []);
return fn;
}
function borderTransform(value) {
if (typeof value !== 'number') {
return value;
}
return `${value}px solid`;
}
function createBorderStyle(prop, transform) {
return style$1({
prop,
themeKey: 'borders',
transform
});
}
const border = createBorderStyle('border', borderTransform);
const borderTop = createBorderStyle('borderTop', borderTransform);
const borderRight = createBorderStyle('borderRight', borderTransform);
const borderBottom = createBorderStyle('borderBottom', borderTransform);
const borderLeft = createBorderStyle('borderLeft', borderTransform);
const borderColor = createBorderStyle('borderColor');
const borderTopColor = createBorderStyle('borderTopColor');
const borderRightColor = createBorderStyle('borderRightColor');
const borderBottomColor = createBorderStyle('borderBottomColor');
const borderLeftColor = createBorderStyle('borderLeftColor');
const outline = createBorderStyle('outline', borderTransform);
const outlineColor = createBorderStyle('outlineColor');
// false positive
// eslint-disable-next-line react/function-component-definition
const borderRadius = props => {
if (props.borderRadius !== undefined && props.borderRadius !== null) {
const transformer = createUnaryUnit(props.theme, 'shape.borderRadius', 4, 'borderRadius');
const styleFromPropValue = propValue => ({
borderRadius: getValue(transformer, propValue)
});
return handleBreakpoints(props, props.borderRadius, styleFromPropValue);
}
return null;
};
borderRadius.propTypes = process.env.NODE_ENV !== 'production' ? {
borderRadius: responsivePropType$1
} : {};
borderRadius.filterProps = ['borderRadius'];
compose(border, borderTop, borderRight, borderBottom, borderLeft, borderColor, borderTopColor, borderRightColor, borderBottomColor, borderLeftColor, borderRadius, outline, outlineColor);
// false positive
// eslint-disable-next-line react/function-component-definition
const gap = props => {
if (props.gap !== undefined && props.gap !== null) {
const transformer = createUnaryUnit(props.theme, 'spacing', 8, 'gap');
const styleFromPropValue = propValue => ({
gap: getValue(transformer, propValue)
});
return handleBreakpoints(props, props.gap, styleFromPropValue);
}
return null;
};
gap.propTypes = process.env.NODE_ENV !== 'production' ? {
gap: responsivePropType$1
} : {};
gap.filterProps = ['gap'];
// false positive
// eslint-disable-next-line react/function-component-definition
const columnGap = props => {
if (props.columnGap !== undefined && props.columnGap !== null) {
const transformer = createUnaryUnit(props.theme, 'spacing', 8, 'columnGap');
const styleFromPropValue = propValue => ({
columnGap: getValue(transformer, propValue)
});
return handleBreakpoints(props, props.columnGap, styleFromPropValue);
}
return null;
};
columnGap.propTypes = process.env.NODE_ENV !== 'production' ? {
columnGap: responsivePropType$1
} : {};
columnGap.filterProps = ['columnGap'];
// false positive
// eslint-disable-next-line react/function-component-definition
const rowGap = props => {
if (props.rowGap !== undefined && props.rowGap !== null) {
const transformer = createUnaryUnit(props.theme, 'spacing', 8, 'rowGap');
const styleFromPropValue = propValue => ({
rowGap: getValue(transformer, propValue)
});
return handleBreakpoints(props, props.rowGap, styleFromPropValue);
}
return null;
};
rowGap.propTypes = process.env.NODE_ENV !== 'production' ? {
rowGap: responsivePropType$1
} : {};
rowGap.filterProps = ['rowGap'];
const gridColumn = style$1({
prop: 'gridColumn'
});
const gridRow = style$1({
prop: 'gridRow'
});
const gridAutoFlow = style$1({
prop: 'gridAutoFlow'
});
const gridAutoColumns = style$1({
prop: 'gridAutoColumns'
});
const gridAutoRows = style$1({
prop: 'gridAutoRows'
});
const gridTemplateColumns = style$1({
prop: 'gridTemplateColumns'
});
const gridTemplateRows = style$1({
prop: 'gridTemplateRows'
});
const gridTemplateAreas = style$1({
prop: 'gridTemplateAreas'
});
const gridArea = style$1({
prop: 'gridArea'
});
compose(gap, columnGap, rowGap, gridColumn, gridRow, gridAutoFlow, gridAutoColumns, gridAutoRows, gridTemplateColumns, gridTemplateRows, gridTemplateAreas, gridArea);
function paletteTransform(value, userValue) {
if (userValue === 'grey') {
return userValue;
}
return value;
}
const color = style$1({
prop: 'color',
themeKey: 'palette',
transform: paletteTransform
});
const bgcolor = style$1({
prop: 'bgcolor',
cssProperty: 'backgroundColor',
themeKey: 'palette',
transform: paletteTransform
});
const backgroundColor = style$1({
prop: 'backgroundColor',
themeKey: 'palette',
transform: paletteTransform
});
compose(color, bgcolor, backgroundColor);
function sizingTransform(value) {
return value <= 1 && value !== 0 ? `${value * 100}%` : value;
}
const width = style$1({
prop: 'width',
transform: sizingTransform
});
const maxWidth = props => {
if (props.maxWidth !== undefined && props.maxWidth !== null) {
const styleFromPropValue = propValue => {
var _props$theme, _props$theme2;
const breakpoint = ((_props$theme = props.theme) == null || (_props$theme = _props$theme.breakpoints) == null || (_props$theme = _props$theme.values) == null ? void 0 : _props$theme[propValue]) || values[propValue];
if (!breakpoint) {
return {
maxWidth: sizingTransform(propValue)
};
}
if (((_props$theme2 = props.theme) == null || (_props$theme2 = _props$theme2.breakpoints) == null ? void 0 : _props$theme2.unit) !== 'px') {
return {
maxWidth: `${breakpoint}${props.theme.breakpoints.unit}`
};
}
return {
maxWidth: breakpoint
};
};
return handleBreakpoints(props, props.maxWidth, styleFromPropValue);
}
return null;
};
maxWidth.filterProps = ['maxWidth'];
const minWidth = style$1({
prop: 'minWidth',
transform: sizingTransform
});
const height = style$1({
prop: 'height',
transform: sizingTransform
});
const maxHeight = style$1({
prop: 'maxHeight',
transform: sizingTransform
});
const minHeight = style$1({
prop: 'minHeight',
transform: sizingTransform
});
style$1({
prop: 'size',
cssProperty: 'width',
transform: sizingTransform
});
style$1({
prop: 'size',
cssProperty: 'height',
transform: sizingTransform
});
const boxSizing = style$1({
prop: 'boxSizing'
});
compose(width, maxWidth, minWidth, height, maxHeight, minHeight, boxSizing);
const defaultSxConfig = {
// borders
border: {
themeKey: 'borders',
transform: borderTransform
},
borderTop: {
themeKey: 'borders',
transform: borderTransform
},
borderRight: {
themeKey: 'borders',
transform: borderTransform
},
borderBottom: {
themeKey: 'borders',
transform: borderTransform
},
borderLeft: {
themeKey: 'borders',
transform: borderTransform
},
borderColor: {
themeKey: 'palette'
},
borderTopColor: {
themeKey: 'palette'
},
borderRightColor: {
themeKey: 'palette'
},
borderBottomColor: {
themeKey: 'palette'
},
borderLeftColor: {
themeKey: 'palette'
},
outline: {
themeKey: 'borders',
transform: borderTransform
},
outlineColor: {
themeKey: 'palette'
},
borderRadius: {
themeKey: 'shape.borderRadius',
style: borderRadius
},
// palette
color: {
themeKey: 'palette',
transform: paletteTransform
},
bgcolor: {
themeKey: 'palette',
cssProperty: 'backgroundColor',
transform: paletteTransform
},
backgroundColor: {
themeKey: 'palette',
transform: paletteTransform
},
// spacing
p: {
style: padding
},
pt: {
style: padding
},
pr: {
style: padding
},
pb: {
style: padding
},
pl: {
style: padding
},
px: {
style: padding
},
py: {
style: padding
},
padding: {
style: padding
},
paddingTop: {
style: padding
},
paddingRight: {
style: padding
},
paddingBottom: {
style: padding
},
paddingLeft: {
style: padding
},
paddingX: {
style: padding
},
paddingY: {
style: padding
},
paddingInline: {
style: padding
},
paddingInlineStart: {
style: padding
},
paddingInlineEnd: {
style: padding
},
paddingBlock: {
style: padding
},
paddingBlockStart: {
style: padding
},
paddingBlockEnd: {
style: padding
},
m: {
style: margin
},
mt: {
style: margin
},
mr: {
style: margin
},
mb: {
style: margin
},
ml: {
style: margin
},
mx: {
style: margin
},
my: {
style: margin
},
margin: {
style: margin
},
marginTop: {
style: margin
},
marginRight: {
style: margin
},
marginBottom: {
style: margin
},
marginLeft: {
style: margin
},
marginX: {
style: margin
},
marginY: {
style: margin
},
marginInline: {
style: margin
},
marginInlineStart: {
style: margin
},
marginInlineEnd: {
style: margin
},
marginBlock: {
style: margin
},
marginBlockStart: {
style: margin
},
marginBlockEnd: {
style: margin
},
// display
displayPrint: {
cssProperty: false,
transform: value => ({
'@media print': {
display: value
}
})
},
display: {},
overflow: {},
textOverflow: {},
visibility: {},
whiteSpace: {},
// flexbox
flexBasis: {},
flexDirection: {},
flexWrap: {},
justifyContent: {},
alignItems: {},
alignContent: {},
order: {},
flex: {},
flexGrow: {},
flexShrink: {},
alignSelf: {},
justifyItems: {},
justifySelf: {},
// grid
gap: {
style: gap
},
rowGap: {
style: rowGap
},
columnGap: {
style: columnGap
},
gridColumn: {},
gridRow: {},
gridAutoFlow: {},
gridAutoColumns: {},
gridAutoRows: {},
gridTemplateColumns: {},
gridTemplateRows: {},
gridTemplateAreas: {},
gridArea: {},
// positions
position: {},
zIndex: {
themeKey: 'zIndex'
},
top: {},
right: {},
bottom: {},
left: {},
// shadows
boxShadow: {
themeKey: 'shadows'
},
// sizing
width: {
transform: sizingTransform
},
maxWidth: {
style: maxWidth
},
minWidth: {
transform: sizingTransform
},
height: {
transform: sizingTransform
},
maxHeight: {
transform: sizingTransform
},
minHeight: {
transform: sizingTransform
},
boxSizing: {},
// typography
fontFamily: {
themeKey: 'typography'
},
fontSize: {
themeKey: 'typography'
},
fontStyle: {
themeKey: 'typography'
},
fontWeight: {
themeKey: 'typography'
},
letterSpacing: {},
textTransform: {},
lineHeight: {},
textAlign: {},
typography: {
cssProperty: false,
themeKey: 'typography'
}
};
var defaultSxConfig$1 = defaultSxConfig;
function objectsHaveSameKeys(...objects) {
const allKeys = objects.reduce((keys, object) => keys.concat(Object.keys(object)), []);
const union = new Set(allKeys);
return objects.every(object => union.size === Object.keys(object).length);
}
function callIfFn(maybeFn, arg) {
return typeof maybeFn === 'function' ? maybeFn(arg) : maybeFn;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
function unstable_createStyleFunctionSx() {
function getThemeValue(prop, val, theme, config) {
const props = {
[prop]: val,
theme
};
const options = config[prop];
if (!options) {
return {
[prop]: val
};
}
const {
cssProperty = prop,
themeKey,
transform,
style
} = options;
if (val == null) {
return null;
}
// TODO v6: remove, see https://github.com/mui/material-ui/pull/38123
if (themeKey === 'typography' && val === 'inherit') {
return {
[prop]: val
};
}
const themeMapping = getPath(theme, themeKey) || {};
if (style) {
return style(props);
}
const styleFromPropValue = propValueFinal => {
let value = getStyleValue(themeMapping, transform, propValueFinal);
if (propValueFinal === value && typeof propValueFinal === 'string') {
// Haven't found value
value = getStyleValue(themeMapping, transform, `${prop}${propValueFinal === 'default' ? '' : capitalize(propValueFinal)}`, propValueFinal);
}
if (cssProperty === false) {
return value;
}
return {
[cssProperty]: value
};
};
return handleBreakpoints(props, val, styleFromPropValue);
}
function styleFunctionSx(props) {
var _theme$unstable_sxCon;
const {
sx,
theme = {}
} = props || {};
if (!sx) {
return null; // Emotion & styled-components will neglect null
}
const config = (_theme$unstable_sxCon = theme.unstable_sxConfig) != null ? _theme$unstable_sxCon : defaultSxConfig$1;
/*
* Receive `sxInput` as object or callback
* and then recursively check keys & values to create media query object styles.
* (the result will be used in `styled`)
*/
function traverse(sxInput) {
let sxObject = sxInput;
if (typeof sxInput === 'function') {
sxObject = sxInput(theme);
} else if (typeof sxInput !== 'object') {
// value
return sxInput;
}
if (!sxObject) {
return null;
}
const emptyBreakpoints = createEmptyBreakpointObject(theme.breakpoints);
const breakpointsKeys = Object.keys(emptyBreakpoints);
let css = emptyBreakpoints;
Object.keys(sxObject).forEach(styleKey => {
const value = callIfFn(sxObject[styleKey], theme);
if (value !== null && value !== undefined) {
if (typeof value === 'object') {
if (config[styleKey]) {
css = merge(css, getThemeValue(styleKey, value, theme, config));
} else {
const breakpointsValues = handleBreakpoints({
theme
}, value, x => ({
[styleKey]: x
}));
if (objectsHaveSameKeys(breakpointsValues, value)) {
css[styleKey] = styleFunctionSx({
sx: value,
theme
});
} else {
css = merge(css, breakpointsValues);
}
}
} else {
css = merge(css, getThemeValue(styleKey, value, theme, config));
}
}
});
return removeUnusedBreakpoints(breakpointsKeys, css);
}
return Array.isArray(sx) ? sx.map(traverse) : traverse(sx);
}
return styleFunctionSx;
}
const styleFunctionSx = unstable_createStyleFunctionSx();
styleFunctionSx.filterProps = ['sx'];
var styleFunctionSx$1 = styleFunctionSx;
/**
* A universal utility to style components with multiple color modes. Always use it from the theme object.
* It works with:
* - [Basic theme](https://mui.com/material-ui/customization/dark-mode/)
* - [CSS theme variables](https://mui.com/material-ui/experimental-api/css-theme-variables/overview/)
* - Zero-runtime engine
*
* Tips: Use an array over object spread and place `theme.applyStyles()` last.
*
* ✅ [{ background: '#e5e5e5' }, theme.applyStyles('dark', { background: '#1c1c1c' })]
*
* 🚫 { background: '#e5e5e5', ...theme.applyStyles('dark', { background: '#1c1c1c' })}
*
* @example
* 1. using with `styled`:
* ```jsx
* const Component = styled('div')(({ theme }) => [
* { background: '#e5e5e5' },
* theme.applyStyles('dark', {
* background: '#1c1c1c',
* color: '#fff',
* }),
* ]);
* ```
*
* @example
* 2. using with `sx` prop:
* ```jsx
* <Box sx={theme => [
* { background: '#e5e5e5' },
* theme.applyStyles('dark', {
* background: '#1c1c1c',
* color: '#fff',
* }),
* ]}
* />
* ```
*
* @example
* 3. theming a component:
* ```jsx
* extendTheme({
* components: {
* MuiButton: {
* styleOverrides: {
* root: ({ theme }) => [
* { background: '#e5e5e5' },
* theme.applyStyles('dark', {
* background: '#1c1c1c',
* color: '#fff',
* }),
* ],
* },
* }
* }
* })
*```
*/
function applyStyles(key, styles) {
// @ts-expect-error this is 'any' type
const theme = this;
if (theme.vars && typeof theme.getColorSchemeSelector === 'function') {
// If CssVarsProvider is used as a provider,
// returns '* :where([data-mui-color-scheme="light|dark"]) &'
const selector = theme.getColorSchemeSelector(key).replace(/(\[[^\]]+\])/, '*:where($1)');
return {
[selector]: styles
};
}
if (theme.palette.mode === key) {
return styles;
}
return {};
}
const _excluded$b = ["breakpoints", "palette", "spacing", "shape"];
function createTheme(options = {}, ...args) {
const {
breakpoints: breakpointsInput = {},
palette: paletteInput = {},
spacing: spacingInput,
shape: shapeInput = {}
} = options,
other = _objectWithoutPropertiesLoose$1(options, _excluded$b);
const breakpoints = createBreakpoints(breakpointsInput);
const spacing = createSpacing(spacingInput);
let muiTheme = deepmerge({
breakpoints,
direction: 'ltr',
components: {},
// Inject component definitions.
palette: _extends({
mode: 'light'
}, paletteInput),
spacing,
shape: _extends({}, shape$1, shapeInput)
}, other);
muiTheme.applyStyles = applyStyles;
muiTheme = args.reduce((acc, argument) => deepmerge(acc, argument), muiTheme);
muiTheme.unstable_sxConfig = _extends({}, defaultSxConfig$1, other == null ? void 0 : other.unstable_sxConfig);
muiTheme.unstable_sx = function sx(props) {
return styleFunctionSx$1({
sx: props,
theme: this
});
};
return muiTheme;
}
function isObjectEmpty(obj) {
return Object.keys(obj).length === 0;
}
function useTheme$1(defaultTheme = null) {
const contextTheme = React.useContext(ThemeContext);
return !contextTheme || isObjectEmpty(contextTheme) ? defaultTheme : contextTheme;
}
const systemDefaultTheme$1 = createTheme();
function useTheme(defaultTheme = systemDefaultTheme$1) {
return useTheme$1(defaultTheme);
}
const _excluded$a = ["ownerState"],
_excluded2$2 = ["variants"],
_excluded3$1 = ["name", "slot", "skipVariantsResolver", "skipSx", "overridesResolver"];
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
// https://github.com/emotion-js/emotion/blob/26ded6109fcd8ca9875cc2ce4564fee678a3f3c5/packages/styled/src/utils.js#L40
function isStringTag(tag) {
return typeof tag === 'string' &&
// 96 is one less than the char code
// for "a" so this is checking that
// it's a lowercase character
tag.charCodeAt(0) > 96;
}
// Update /system/styled/#api in case if this changes
function shouldForwardProp(prop) {
return prop !== 'ownerState' && prop !== 'theme' && prop !== 'sx' && prop !== 'as';
}
const systemDefaultTheme = createTheme();
const lowercaseFirstLetter = string => {
if (!string) {
return string;
}
return string.charAt(0).toLowerCase() + string.slice(1);
};
function resolveTheme({
defaultTheme,
theme,
themeId
}) {
return isEmpty(theme) ? defaultTheme : theme[themeId] || theme;
}
function defaultOverridesResolver(slot) {
if (!slot) {
return null;
}
return (props, styles) => styles[slot];
}
function processStyleArg(callableStyle, _ref) {
let {
ownerState
} = _ref,
props = _objectWithoutPropertiesLoose$1(_ref, _excluded$a);
const resolvedStylesArg = typeof callableStyle === 'function' ? callableStyle(_extends({
ownerState
}, props)) : callableStyle;
if (Array.isArray(resolvedStylesArg)) {
return resolvedStylesArg.flatMap(resolvedStyle => processStyleArg(resolvedStyle, _extends({
ownerState
}, props)));
}
if (!!resolvedStylesArg && typeof resolvedStylesArg === 'object' && Array.isArray(resolvedStylesArg.variants)) {
const {
variants = []
} = resolvedStylesArg,
otherStyles = _objectWithoutPropertiesLoose$1(resolvedStylesArg, _excluded2$2);
let result = otherStyles;
variants.forEach(variant => {
let isMatch = true;
if (typeof variant.props === 'function') {
isMatch = variant.props(_extends({
ownerState
}, props, ownerState));
} else {
Object.keys(variant.props).forEach(key => {
if ((ownerState == null ? void 0 : ownerState[key]) !== variant.props[key] && props[key] !== variant.props[key]) {
isMatch = false;
}
});
}
if (isMatch) {
if (!Array.isArray(result)) {
result = [result];
}
result.push(typeof variant.style === 'function' ? variant.style(_extends({
ownerState
}, props, ownerState)) : variant.style);
}
});
return result;
}
return resolvedStylesArg;
}
function createStyled(input = {}) {
const {
themeId,
defaultTheme = systemDefaultTheme,
rootShouldForwardProp = shouldForwardProp,
slotShouldForwardProp = shouldForwardProp
} = input;
const systemSx = props => {
return styleFunctionSx$1(_extends({}, props, {
theme: resolveTheme(_extends({}, props, {
defaultTheme,
themeId
}))
}));
};
systemSx.__mui_systemSx = true;
return (tag, inputOptions = {}) => {
// Filter out the `sx` style function from the previous styled component to prevent unnecessary styles generated by the composite components.
internal_processStyles(tag, styles => styles.filter(style => !(style != null && style.__mui_systemSx)));
const {
name: componentName,
slot: componentSlot,
skipVariantsResolver: inputSkipVariantsResolver,
skipSx: inputSkipSx,
// TODO v6: remove `lowercaseFirstLetter()` in the next major release
// For more details: https://github.com/mui/material-ui/pull/37908
overridesResolver = defaultOverridesResolver(lowercaseFirstLetter(componentSlot))
} = inputOptions,
options = _objectWithoutPropertiesLoose$1(inputOptions, _excluded3$1);
// if skipVariantsResolver option is defined, take the value, otherwise, true for root and false for other slots.
const skipVariantsResolver = inputSkipVariantsResolver !== undefined ? inputSkipVariantsResolver :
// TODO v6: remove `Root` in the next major release
// For more details: https://github.com/mui/material-ui/pull/37908
componentSlot && componentSlot !== 'Root' && componentSlot !== 'root' || false;
const skipSx = inputSkipSx || false;
let label;
if (process.env.NODE_ENV !== 'production') {
if (componentName) {
// TODO v6: remove `lowercaseFirstLetter()` in the next major release
// For more details: https://github.com/mui/material-ui/pull/37908
label = `${componentName}-${lowercaseFirstLetter(componentSlot || 'Root')}`;
}
}
let shouldForwardPropOption = shouldForwardProp;
// TODO v6: remove `Root` in the next major release
// For more details: https://github.com/mui/material-ui/pull/37908
if (componentSlot === 'Root' || componentSlot === 'root') {
shouldForwardPropOption = rootShouldForwardProp;
} else if (componentSlot) {
// any other slot specified
shouldForwardPropOption = slotShouldForwardProp;
} else if (isStringTag(tag)) {
// for string (html) tag, preserve the behavior in emotion & styled-components.
shouldForwardPropOption = undefined;
}
const defaultStyledResolver = styled$2(tag, _extends({
shouldForwardProp: shouldForwardPropOption,
label
}, options));
const transformStyleArg = stylesArg => {
// On the server Emotion doesn't use React.forwardRef for creating components, so the created
// component stays as a function. This condition makes sure that we do not interpolate functions
// which are basically components used as a selectors.
if (typeof stylesArg === 'function' && stylesArg.__emotion_real !== stylesArg || isPlainObject$1(stylesArg)) {
return props => processStyleArg(stylesArg, _extends({}, props, {
theme: resolveTheme({
theme: props.theme,
defaultTheme,
themeId
})
}));
}
return stylesArg;
};
const muiStyledResolver = (styleArg, ...expressions) => {
let transformedStyleArg = transformStyleArg(styleArg);
const expressionsWithDefaultTheme = expressions ? expressions.map(transformStyleArg) : [];
if (componentName && overridesResolver) {
expressionsWithDefaultTheme.push(props => {
const theme = resolveTheme(_extends({}, props, {
defaultTheme,
themeId
}));
if (!theme.components || !theme.components[componentName] || !theme.components[componentName].styleOverrides) {
return null;
}
const styleOverrides = theme.components[componentName].styleOverrides;
const resolvedStyleOverrides = {};
// TODO: v7 remove iteration and use `resolveStyleArg(styleOverrides[slot])` directly
Object.entries(styleOverrides).forEach(([slotKey, slotStyle]) => {
resolvedStyleOverrides[slotKey] = processStyleArg(slotStyle, _extends({}, props, {
theme
}));
});
return overridesResolver(props, resolvedStyleOverrides);
});
}
if (componentName && !skipVariantsResolver) {
expressionsWithDefaultTheme.push(props => {
var _theme$components;
const theme = resolveTheme(_extends({}, props, {
defaultTheme,
themeId
}));
const themeVariants = theme == null || (_theme$components = theme.components) == null || (_theme$components = _theme$components[componentName]) == null ? void 0 : _theme$components.variants;
return processStyleArg({
variants: themeVariants
}, _extends({}, props, {
theme
}));
});
}
if (!skipSx) {
expressionsWithDefaultTheme.push(systemSx);
}
const numOfCustomFnsApplied = expressionsWithDefaultTheme.length - expressions.length;
if (Array.isArray(styleArg) && numOfCustomFnsApplied > 0) {
const placeholders = new Array(numOfCustomFnsApplied).fill('');
// If the type is array, than we need to add placeholders in the template for the overrides, variants and the sx styles.
transformedStyleArg = [...styleArg, ...placeholders];
transformedStyleArg.raw = [...styleArg.raw, ...placeholders];
}
const Component = defaultStyledResolver(transformedStyleArg, ...expressionsWithDefaultTheme);
if (process.env.NODE_ENV !== 'production') {
let displayName;
if (componentName) {
displayName = `${componentName}${capitalize(componentSlot || '')}`;
}
if (displayName === undefined) {
displayName = `Styled(${getDisplayName(tag)})`;
}
Component.displayName = displayName;
}
if (tag.muiName) {
Component.muiName = tag.muiName;
}
return Component;
};
if (defaultStyledResolver.withConfig) {
muiStyledResolver.withConfig = defaultStyledResolver.withConfig;
}
return muiStyledResolver;
};
}
const styled = createStyled();
var styled$1 = styled;
/**
* Returns a number whose value is limited to the given range.
* @param {number} value The value to be clamped
* @param {number} min The lower boundary of the output range
* @param {number} max The upper boundary of the output range
* @returns {number} A number in the range [min, max]
*/
function clampWrapper(value, min = 0, max = 1) {
if (process.env.NODE_ENV !== 'production') {
if (value < min || value > max) {
console.error(`MUI: The value provided ${value} is out of range [${min}, ${max}].`);
}
}
return clamp(value, min, max);
}
/**
* Converts a color from CSS hex format to CSS rgb format.
* @param {string} color - Hex color, i.e. #nnn or #nnnnnn
* @returns {string} A CSS rgb color string
*/
function hexToRgb(color) {
color = color.slice(1);
const re = new RegExp(`.{1,${color.length >= 6 ? 2 : 1}}`, 'g');
let colors = color.match(re);
if (colors && colors[0].length === 1) {
colors = colors.map(n => n + n);
}
return colors ? `rgb${colors.length === 4 ? 'a' : ''}(${colors.map((n, index) => {
return index < 3 ? parseInt(n, 16) : Math.round(parseInt(n, 16) / 255 * 1000) / 1000;
}).join(', ')})` : '';
}
/**
* Returns an object with the type and values of a color.
*
* Note: Does not support rgb % values.
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla(), color()
* @returns {object} - A MUI color object: {type: string, values: number[]}
*/
function decomposeColor(color) {
// Idempotent
if (color.type) {
return color;
}
if (color.charAt(0) === '#') {
return decomposeColor(hexToRgb(color));
}
const marker = color.indexOf('(');
const type = color.substring(0, marker);
if (['rgb', 'rgba', 'hsl', 'hsla', 'color'].indexOf(type) === -1) {
throw new Error(process.env.NODE_ENV !== "production" ? `MUI: Unsupported \`${color}\` color.
The following formats are supported: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla(), color().` : formatMuiErrorMessage(9, color));
}
let values = color.substring(marker + 1, color.length - 1);
let colorSpace;
if (type === 'color') {
values = values.split(' ');
colorSpace = values.shift();
if (values.length === 4 && values[3].charAt(0) === '/') {
values[3] = values[3].slice(1);
}
if (['srgb', 'display-p3', 'a98-rgb', 'prophoto-rgb', 'rec-2020'].indexOf(colorSpace) === -1) {
throw new Error(process.env.NODE_ENV !== "production" ? `MUI: unsupported \`${colorSpace}\` color space.
The following color spaces are supported: srgb, display-p3, a98-rgb, prophoto-rgb, rec-2020.` : formatMuiErrorMessage(10, colorSpace));
}
} else {
values = values.split(',');
}
values = values.map(value => parseFloat(value));
return {
type,
values,
colorSpace
};
}
/**
* Converts a color object with type and values to a string.
* @param {object} color - Decomposed color
* @param {string} color.type - One of: 'rgb', 'rgba', 'hsl', 'hsla', 'color'
* @param {array} color.values - [n,n,n] or [n,n,n,n]
* @returns {string} A CSS color string
*/
function recomposeColor(color) {
const {
type,
colorSpace
} = color;
let {
values
} = color;
if (type.indexOf('rgb') !== -1) {
// Only convert the first 3 values to int (i.e. not alpha)
values = values.map((n, i) => i < 3 ? parseInt(n, 10) : n);
} else if (type.indexOf('hsl') !== -1) {
values[1] = `${values[1]}%`;
values[2] = `${values[2]}%`;
}
if (type.indexOf('color') !== -1) {
values = `${colorSpace} ${values.join(' ')}`;
} else {
values = `${values.join(', ')}`;
}
return `${type}(${values})`;
}
/**
* Darkens a color.
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla(), color()
* @param {number} coefficient - multiplier in the range 0 - 1
* @returns {string} A CSS color string. Hex input values are returned as rgb
*/
function darken(color, coefficient) {
color = decomposeColor(color);
coefficient = clampWrapper(coefficient);
if (color.type.indexOf('hsl') !== -1) {
color.values[2] *= 1 - coefficient;
} else if (color.type.indexOf('rgb') !== -1 || color.type.indexOf('color') !== -1) {
for (let i = 0; i < 3; i += 1) {
color.values[i] *= 1 - coefficient;
}
}
return recomposeColor(color);
}
/**
* Lightens a color.
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla(), color()
* @param {number} coefficient - multiplier in the range 0 - 1
* @returns {string} A CSS color string. Hex input values are returned as rgb
*/
function lighten(color, coefficient) {
color = decomposeColor(color);
coefficient = clampWrapper(coefficient);
if (color.type.indexOf('hsl') !== -1) {
color.values[2] += (100 - color.values[2]) * coefficient;
} else if (color.type.indexOf('rgb') !== -1) {
for (let i = 0; i < 3; i += 1) {
color.values[i] += (255 - color.values[i]) * coefficient;
}
} else if (color.type.indexOf('color') !== -1) {
for (let i = 0; i < 3; i += 1) {
color.values[i] += (1 - color.values[i]) * coefficient;
}
}
return recomposeColor(color);
}
function getPickersMonthUtilityClass(slot) {
return generateUtilityClass('MuiPickersMonth', slot);
}
const pickersMonthClasses = generateUtilityClasses('MuiPickersMonth', ['root', 'monthButton', 'disabled', 'selected']);
const _excluded$9 = ["autoFocus", "children", "disabled", "selected", "value", "tabIndex", "onClick", "onKeyDown", "onFocus", "onBlur", "aria-current", "aria-label", "monthsPerRow"];
const useUtilityClasses$6 = ownerState => {
const {
disabled,
selected,
classes
} = ownerState;
const slots = {
root: ['root'],
monthButton: ['monthButton', disabled && 'disabled', selected && 'selected']
};
return composeClasses(slots, getPickersMonthUtilityClass, classes);
};
const PickersMonthRoot = styled$3('div', {
name: 'MuiPickersMonth',
slot: 'Root',
overridesResolver: (_, styles) => [styles.root]
})(({
ownerState
}) => ({
flexBasis: ownerState.monthsPerRow === 3 ? '33.3%' : '25%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}));
const PickersMonthButton = styled$3('button', {
name: 'MuiPickersMonth',
slot: 'MonthButton',
overridesResolver: (_, styles) => [styles.monthButton, {
[`&.${pickersMonthClasses.disabled}`]: styles.disabled
}, {
[`&.${pickersMonthClasses.selected}`]: styles.selected
}]
})(({
theme
}) => _extends({
color: 'unset',
backgroundColor: 'transparent',
border: 0,
outline: 0
}, theme.typography.subtitle1, {
margin: '8px 0',
height: 36,
width: 72,
borderRadius: 18,
cursor: 'pointer',
'&:focus': {
backgroundColor: theme.vars ? `rgba(${theme.vars.palette.action.activeChannel} / ${theme.vars.palette.action.hoverOpacity})` : alpha(theme.palette.action.active, theme.palette.action.hoverOpacity)
},
'&:hover': {
backgroundColor: theme.vars ? `rgba(${theme.vars.palette.action.activeChannel} / ${theme.vars.palette.action.hoverOpacity})` : alpha(theme.palette.action.active, theme.palette.action.hoverOpacity)
},
'&:disabled': {
cursor: 'auto',
pointerEvents: 'none'
},
[`&.${pickersMonthClasses.disabled}`]: {
color: (theme.vars || theme).palette.text.secondary
},
[`&.${pickersMonthClasses.selected}`]: {
color: (theme.vars || theme).palette.primary.contrastText,
backgroundColor: (theme.vars || theme).palette.primary.main,
'&:focus, &:hover': {
backgroundColor: (theme.vars || theme).palette.primary.dark
}
}
}));
/**
* @ignore - do not document.
*/
const PickersMonth = /*#__PURE__*/React.memo(function PickersMonth(inProps) {
const props = useThemeProps({
props: inProps,
name: 'MuiPickersMonth'
});
const {
autoFocus,
children,
disabled,
selected,
value,
tabIndex,
onClick,
onKeyDown,
onFocus,
onBlur,
'aria-current': ariaCurrent,
'aria-label': ariaLabel
// We don't want to forward this prop to the root element
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$9);
const ref = React.useRef(null);
const classes = useUtilityClasses$6(props);
useEnhancedEffect$1(() => {
if (autoFocus) {
var _ref$current;
(_ref$current = ref.current) == null || _ref$current.focus();
}
}, [autoFocus]);
return /*#__PURE__*/jsx(PickersMonthRoot, _extends({
className: classes.root,
ownerState: props
}, other, {
children: /*#__PURE__*/jsx(PickersMonthButton, {
ref: ref,
disabled: disabled,
type: "button",
role: "radio",
tabIndex: disabled ? -1 : tabIndex,
"aria-current": ariaCurrent,
"aria-checked": selected,
"aria-label": ariaLabel,
onClick: event => onClick(event, value),
onKeyDown: event => onKeyDown(event, value),
onFocus: event => onFocus(event, value),
onBlur: event => onBlur(event, value),
className: classes.monthButton,
ownerState: props,
children: children
})
}));
});
function getMonthCalendarUtilityClass(slot) {
return generateUtilityClass('MuiMonthCalendar', slot);
}
generateUtilityClasses('MuiMonthCalendar', ['root']);
const _excluded$8 = ["className", "value", "defaultValue", "referenceDate", "disabled", "disableFuture", "disablePast", "maxDate", "minDate", "onChange", "shouldDisableMonth", "readOnly", "disableHighlightToday", "autoFocus", "onMonthFocus", "hasFocus", "onFocusedViewChange", "monthsPerRow", "timezone", "gridLabelId"];
const useUtilityClasses$5 = ownerState => {
const {
classes
} = ownerState;
const slots = {
root: ['root']
};
return composeClasses(slots, getMonthCalendarUtilityClass, classes);
};
function useMonthCalendarDefaultizedProps(props, name) {
const utils = useUtils();
const defaultDates = useDefaultDates();
const themeProps = useThemeProps({
props,
name
});
return _extends({
disableFuture: false,
disablePast: false
}, themeProps, {
minDate: applyDefaultDate(utils, themeProps.minDate, defaultDates.minDate),
maxDate: applyDefaultDate(utils, themeProps.maxDate, defaultDates.maxDate)
});
}
const MonthCalendarRoot = styled$3('div', {
name: 'MuiMonthCalendar',
slot: 'Root',
overridesResolver: (props, styles) => styles.root
})({
display: 'flex',
flexWrap: 'wrap',
alignContent: 'stretch',
padding: '0 4px',
width: DIALOG_WIDTH,
// avoid padding increasing width over defined
boxSizing: 'border-box'
});
/**
* Demos:
*
* - [DateCalendar](https://mui.com/x/react-date-pickers/date-calendar/)
*
* API:
*
* - [MonthCalendar API](https://mui.com/x/api/date-pickers/month-calendar/)
*/
const MonthCalendar = /*#__PURE__*/React.forwardRef(function MonthCalendar(inProps, ref) {
const props = useMonthCalendarDefaultizedProps(inProps, 'MuiMonthCalendar');
const {
className,
value: valueProp,
defaultValue,
referenceDate: referenceDateProp,
disabled,
disableFuture,
disablePast,
maxDate,
minDate,
onChange,
shouldDisableMonth,
readOnly,
disableHighlightToday,
autoFocus = false,
onMonthFocus,
hasFocus,
onFocusedViewChange,
monthsPerRow = 3,
timezone: timezoneProp,
gridLabelId
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$8);
const {
value,
handleValueChange,
timezone
} = useControlledValueWithTimezone({
name: 'MonthCalendar',
timezone: timezoneProp,
value: valueProp,
defaultValue,
onChange: onChange,
valueManager: singleItemValueManager
});
const now = useNow(timezone);
const theme = useTheme();
const utils = useUtils();
const referenceDate = React.useMemo(() => singleItemValueManager.getInitialReferenceValue({
value,
utils,
props,
timezone,
referenceDate: referenceDateProp,
granularity: SECTION_TYPE_GRANULARITY.month
}), [] // eslint-disable-line react-hooks/exhaustive-deps
);
const ownerState = props;
const classes = useUtilityClasses$5(ownerState);
const todayMonth = React.useMemo(() => utils.getMonth(now), [utils, now]);
const selectedMonth = React.useMemo(() => {
if (value != null) {
return utils.getMonth(value);
}
if (disableHighlightToday) {
return null;
}
return utils.getMonth(referenceDate);
}, [value, utils, disableHighlightToday, referenceDate]);
const [focusedMonth, setFocusedMonth] = React.useState(() => selectedMonth || todayMonth);
const [internalHasFocus, setInternalHasFocus] = useControlled({
name: 'MonthCalendar',
state: 'hasFocus',
controlled: hasFocus,
default: autoFocus != null ? autoFocus : false
});
const changeHasFocus = useEventCallback(newHasFocus => {
setInternalHasFocus(newHasFocus);
if (onFocusedViewChange) {
onFocusedViewChange(newHasFocus);
}
});
const isMonthDisabled = React.useCallback(dateToValidate => {
const firstEnabledMonth = utils.startOfMonth(disablePast && utils.isAfter(now, minDate) ? now : minDate);
const lastEnabledMonth = utils.startOfMonth(disableFuture && utils.isBefore(now, maxDate) ? now : maxDate);
const monthToValidate = utils.startOfMonth(dateToValidate);
if (utils.isBefore(monthToValidate, firstEnabledMonth)) {
return true;
}
if (utils.isAfter(monthToValidate, lastEnabledMonth)) {
return true;
}
if (!shouldDisableMonth) {
return false;
}
return shouldDisableMonth(monthToValidate);
}, [disableFuture, disablePast, maxDate, minDate, now, shouldDisableMonth, utils]);
const handleMonthSelection = useEventCallback((event, month) => {
if (readOnly) {
return;
}
const newDate = utils.setMonth(value != null ? value : referenceDate, month);
handleValueChange(newDate);
});
const focusMonth = useEventCallback(month => {
if (!isMonthDisabled(utils.setMonth(value != null ? value : referenceDate, month))) {
setFocusedMonth(month);
changeHasFocus(true);
if (onMonthFocus) {
onMonthFocus(month);
}
}
});
React.useEffect(() => {
setFocusedMonth(prevFocusedMonth => selectedMonth !== null && prevFocusedMonth !== selectedMonth ? selectedMonth : prevFocusedMonth);
}, [selectedMonth]);
const handleKeyDown = useEventCallback((event, month) => {
const monthsInYear = 12;
const monthsInRow = 3;
switch (event.key) {
case 'ArrowUp':
focusMonth((monthsInYear + month - monthsInRow) % monthsInYear);
event.preventDefault();
break;
case 'ArrowDown':
focusMonth((monthsInYear + month + monthsInRow) % monthsInYear);
event.preventDefault();
break;
case 'ArrowLeft':
focusMonth((monthsInYear + month + (theme.direction === 'ltr' ? -1 : 1)) % monthsInYear);
event.preventDefault();
break;
case 'ArrowRight':
focusMonth((monthsInYear + month + (theme.direction === 'ltr' ? 1 : -1)) % monthsInYear);
event.preventDefault();
break;
}
});
const handleMonthFocus = useEventCallback((event, month) => {
focusMonth(month);
});
const handleMonthBlur = useEventCallback((event, month) => {
if (focusedMonth === month) {
changeHasFocus(false);
}
});
return /*#__PURE__*/jsx(MonthCalendarRoot, _extends({
ref: ref,
className: clsx(classes.root, className),
ownerState: ownerState,
role: "radiogroup",
"aria-labelledby": gridLabelId
}, other, {
children: getMonthsInYear(utils, value != null ? value : referenceDate).map(month => {
const monthNumber = utils.getMonth(month);
const monthText = utils.format(month, 'monthShort');
const monthLabel = utils.format(month, 'month');
const isSelected = monthNumber === selectedMonth;
const isDisabled = disabled || isMonthDisabled(month);
return /*#__PURE__*/jsx(PickersMonth, {
selected: isSelected,
value: monthNumber,
onClick: handleMonthSelection,
onKeyDown: handleKeyDown,
autoFocus: internalHasFocus && monthNumber === focusedMonth,
disabled: isDisabled,
tabIndex: monthNumber === focusedMonth ? 0 : -1,
onFocus: handleMonthFocus,
onBlur: handleMonthBlur,
"aria-current": todayMonth === monthNumber ? 'date' : undefined,
"aria-label": monthLabel,
monthsPerRow: monthsPerRow,
children: monthText
}, monthText);
})
}));
});
process.env.NODE_ENV !== "production" ? MonthCalendar.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
autoFocus: PropTypes.bool,
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object,
/**
* className applied to the root element.
*/
className: PropTypes.string,
/**
* The default selected value.
* Used when the component is not controlled.
*/
defaultValue: PropTypes.any,
/**
* If `true` picker is disabled
*/
disabled: PropTypes.bool,
/**
* If `true`, disable values after the current date for date components, time for time components and both for date time components.
* @default false
*/
disableFuture: PropTypes.bool,
/**
* If `true`, today's date is rendering without highlighting with circle.
* @default false
*/
disableHighlightToday: PropTypes.bool,
/**
* If `true`, disable values before the current date for date components, time for time components and both for date time components.
* @default false
*/
disablePast: PropTypes.bool,
gridLabelId: PropTypes.string,
hasFocus: PropTypes.bool,
/**
* Maximal selectable date.
*/
maxDate: PropTypes.any,
/**
* Minimal selectable date.
*/
minDate: PropTypes.any,
/**
* Months rendered per row.
* @default 3
*/
monthsPerRow: PropTypes.oneOf([3, 4]),
/**
* Callback fired when the value changes.
* @template TDate
* @param {TDate} value The new value.
*/
onChange: PropTypes.func,
onFocusedViewChange: PropTypes.func,
onMonthFocus: PropTypes.func,
/**
* If `true` picker is readonly
*/
readOnly: PropTypes.bool,
/**
* The date used to generate the new value when both `value` and `defaultValue` are empty.
* @default The closest valid month using the validation props, except callbacks such as `shouldDisableMonth`.
*/
referenceDate: PropTypes.any,
/**
* Disable specific month.
* @template TDate
* @param {TDate} month The month to test.
* @returns {boolean} If `true`, the month will be disabled.
*/
shouldDisableMonth: PropTypes.func,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
/**
* Choose which timezone to use for the value.
* Example: "default", "system", "UTC", "America/New_York".
* If you pass values from other timezones to some props, they will be converted to this timezone before being used.
* @see See the {@link https://mui.com/x/react-date-pickers/timezone/ timezones documention} for more details.
* @default The timezone of the `value` or `defaultValue` prop is defined, 'default' otherwise.
*/
timezone: PropTypes.string,
/**
* The selected value.
* Used when the component is controlled.
*/
value: PropTypes.any
} : void 0;
function getPickersYearUtilityClass(slot) {
return generateUtilityClass('MuiPickersYear', slot);
}
const pickersYearClasses = generateUtilityClasses('MuiPickersYear', ['root', 'yearButton', 'selected', 'disabled']);
const _excluded$7 = ["autoFocus", "className", "children", "disabled", "selected", "value", "tabIndex", "onClick", "onKeyDown", "onFocus", "onBlur", "aria-current", "yearsPerRow"];
const useUtilityClasses$4 = ownerState => {
const {
disabled,
selected,
classes
} = ownerState;
const slots = {
root: ['root'],
yearButton: ['yearButton', disabled && 'disabled', selected && 'selected']
};
return composeClasses(slots, getPickersYearUtilityClass, classes);
};
const PickersYearRoot = styled$3('div', {
name: 'MuiPickersYear',
slot: 'Root',
overridesResolver: (_, styles) => [styles.root]
})(({
ownerState
}) => ({
flexBasis: ownerState.yearsPerRow === 3 ? '33.3%' : '25%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}));
const PickersYearButton = styled$3('button', {
name: 'MuiPickersYear',
slot: 'YearButton',
overridesResolver: (_, styles) => [styles.yearButton, {
[`&.${pickersYearClasses.disabled}`]: styles.disabled
}, {
[`&.${pickersYearClasses.selected}`]: styles.selected
}]
})(({
theme
}) => _extends({
color: 'unset',
backgroundColor: 'transparent',
border: 0,
outline: 0
}, theme.typography.subtitle1, {
margin: '6px 0',
height: 36,
width: 72,
borderRadius: 18,
cursor: 'pointer',
'&:focus': {
backgroundColor: theme.vars ? `rgba(${theme.vars.palette.action.activeChannel} / ${theme.vars.palette.action.focusOpacity})` : alpha(theme.palette.action.active, theme.palette.action.focusOpacity)
},
'&:hover': {
backgroundColor: theme.vars ? `rgba(${theme.vars.palette.action.activeChannel} / ${theme.vars.palette.action.hoverOpacity})` : alpha(theme.palette.action.active, theme.palette.action.hoverOpacity)
},
'&:disabled': {
cursor: 'auto',
pointerEvents: 'none'
},
[`&.${pickersYearClasses.disabled}`]: {
color: (theme.vars || theme).palette.text.secondary
},
[`&.${pickersYearClasses.selected}`]: {
color: (theme.vars || theme).palette.primary.contrastText,
backgroundColor: (theme.vars || theme).palette.primary.main,
'&:focus, &:hover': {
backgroundColor: (theme.vars || theme).palette.primary.dark
}
}
}));
/**
* @ignore - internal component.
*/
const PickersYear = /*#__PURE__*/React.memo(function PickersYear(inProps) {
const props = useThemeProps({
props: inProps,
name: 'MuiPickersYear'
});
const {
autoFocus,
className,
children,
disabled,
selected,
value,
tabIndex,
onClick,
onKeyDown,
onFocus,
onBlur,
'aria-current': ariaCurrent
// We don't want to forward this prop to the root element
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$7);
const ref = React.useRef(null);
const classes = useUtilityClasses$4(props);
// We can't forward the `autoFocus` to the button because it is a native button, not a MUI Button
React.useEffect(() => {
if (autoFocus) {
// `ref.current` being `null` would be a bug in MUI.
ref.current.focus();
}
}, [autoFocus]);
return /*#__PURE__*/jsx(PickersYearRoot, _extends({
className: clsx(classes.root, className),
ownerState: props
}, other, {
children: /*#__PURE__*/jsx(PickersYearButton, {
ref: ref,
disabled: disabled,
type: "button",
role: "radio",
tabIndex: disabled ? -1 : tabIndex,
"aria-current": ariaCurrent,
"aria-checked": selected,
onClick: event => onClick(event, value),
onKeyDown: event => onKeyDown(event, value),
onFocus: event => onFocus(event, value),
onBlur: event => onBlur(event, value),
className: classes.yearButton,
ownerState: props,
children: children
})
}));
});
function getYearCalendarUtilityClass(slot) {
return generateUtilityClass('MuiYearCalendar', slot);
}
generateUtilityClasses('MuiYearCalendar', ['root']);
const _excluded$6 = ["autoFocus", "className", "value", "defaultValue", "referenceDate", "disabled", "disableFuture", "disablePast", "maxDate", "minDate", "onChange", "readOnly", "shouldDisableYear", "disableHighlightToday", "onYearFocus", "hasFocus", "onFocusedViewChange", "yearsPerRow", "timezone", "gridLabelId"];
const useUtilityClasses$3 = ownerState => {
const {
classes
} = ownerState;
const slots = {
root: ['root']
};
return composeClasses(slots, getYearCalendarUtilityClass, classes);
};
function useYearCalendarDefaultizedProps(props, name) {
var _themeProps$yearsPerR;
const utils = useUtils();
const defaultDates = useDefaultDates();
const themeProps = useThemeProps({
props,
name
});
return _extends({
disablePast: false,
disableFuture: false
}, themeProps, {
yearsPerRow: (_themeProps$yearsPerR = themeProps.yearsPerRow) != null ? _themeProps$yearsPerR : 3,
minDate: applyDefaultDate(utils, themeProps.minDate, defaultDates.minDate),
maxDate: applyDefaultDate(utils, themeProps.maxDate, defaultDates.maxDate)
});
}
const YearCalendarRoot = styled$3('div', {
name: 'MuiYearCalendar',
slot: 'Root',
overridesResolver: (props, styles) => styles.root
})({
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
overflowY: 'auto',
height: '100%',
padding: '0 4px',
width: DIALOG_WIDTH,
maxHeight: MAX_CALENDAR_HEIGHT,
// avoid padding increasing width over defined
boxSizing: 'border-box',
position: 'relative'
});
/**
* Demos:
*
* - [DateCalendar](https://mui.com/x/react-date-pickers/date-calendar/)
*
* API:
*
* - [YearCalendar API](https://mui.com/x/api/date-pickers/year-calendar/)
*/
const YearCalendar = /*#__PURE__*/React.forwardRef(function YearCalendar(inProps, ref) {
const props = useYearCalendarDefaultizedProps(inProps, 'MuiYearCalendar');
const {
autoFocus,
className,
value: valueProp,
defaultValue,
referenceDate: referenceDateProp,
disabled,
disableFuture,
disablePast,
maxDate,
minDate,
onChange,
readOnly,
shouldDisableYear,
disableHighlightToday,
onYearFocus,
hasFocus,
onFocusedViewChange,
yearsPerRow,
timezone: timezoneProp,
gridLabelId
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$6);
const {
value,
handleValueChange,
timezone
} = useControlledValueWithTimezone({
name: 'YearCalendar',
timezone: timezoneProp,
value: valueProp,
defaultValue,
onChange: onChange,
valueManager: singleItemValueManager
});
const now = useNow(timezone);
const theme = useTheme();
const utils = useUtils();
const referenceDate = React.useMemo(() => singleItemValueManager.getInitialReferenceValue({
value,
utils,
props,
timezone,
referenceDate: referenceDateProp,
granularity: SECTION_TYPE_GRANULARITY.year
}), [] // eslint-disable-line react-hooks/exhaustive-deps
);
const ownerState = props;
const classes = useUtilityClasses$3(ownerState);
const todayYear = React.useMemo(() => utils.getYear(now), [utils, now]);
const selectedYear = React.useMemo(() => {
if (value != null) {
return utils.getYear(value);
}
if (disableHighlightToday) {
return null;
}
return utils.getYear(referenceDate);
}, [value, utils, disableHighlightToday, referenceDate]);
const [focusedYear, setFocusedYear] = React.useState(() => selectedYear || todayYear);
const [internalHasFocus, setInternalHasFocus] = useControlled({
name: 'YearCalendar',
state: 'hasFocus',
controlled: hasFocus,
default: autoFocus != null ? autoFocus : false
});
const changeHasFocus = useEventCallback(newHasFocus => {
setInternalHasFocus(newHasFocus);
if (onFocusedViewChange) {
onFocusedViewChange(newHasFocus);
}
});
const isYearDisabled = React.useCallback(dateToValidate => {
if (disablePast && utils.isBeforeYear(dateToValidate, now)) {
return true;
}
if (disableFuture && utils.isAfterYear(dateToValidate, now)) {
return true;
}
if (minDate && utils.isBeforeYear(dateToValidate, minDate)) {
return true;
}
if (maxDate && utils.isAfterYear(dateToValidate, maxDate)) {
return true;
}
if (!shouldDisableYear) {
return false;
}
const yearToValidate = utils.startOfYear(dateToValidate);
return shouldDisableYear(yearToValidate);
}, [disableFuture, disablePast, maxDate, minDate, now, shouldDisableYear, utils]);
const handleYearSelection = useEventCallback((event, year) => {
if (readOnly) {
return;
}
const newDate = utils.setYear(value != null ? value : referenceDate, year);
handleValueChange(newDate);
});
const focusYear = useEventCallback(year => {
if (!isYearDisabled(utils.setYear(value != null ? value : referenceDate, year))) {
setFocusedYear(year);
changeHasFocus(true);
onYearFocus == null || onYearFocus(year);
}
});
React.useEffect(() => {
setFocusedYear(prevFocusedYear => selectedYear !== null && prevFocusedYear !== selectedYear ? selectedYear : prevFocusedYear);
}, [selectedYear]);
const handleKeyDown = useEventCallback((event, year) => {
switch (event.key) {
case 'ArrowUp':
focusYear(year - yearsPerRow);
event.preventDefault();
break;
case 'ArrowDown':
focusYear(year + yearsPerRow);
event.preventDefault();
break;
case 'ArrowLeft':
focusYear(year + (theme.direction === 'ltr' ? -1 : 1));
event.preventDefault();
break;
case 'ArrowRight':
focusYear(year + (theme.direction === 'ltr' ? 1 : -1));
event.preventDefault();
break;
}
});
const handleYearFocus = useEventCallback((event, year) => {
focusYear(year);
});
const handleYearBlur = useEventCallback((event, year) => {
if (focusedYear === year) {
changeHasFocus(false);
}
});
const scrollerRef = React.useRef(null);
const handleRef = useForkRef(ref, scrollerRef);
React.useEffect(() => {
if (autoFocus || scrollerRef.current === null) {
return;
}
const tabbableButton = scrollerRef.current.querySelector('[tabindex="0"]');
if (!tabbableButton) {
return;
}
// Taken from useScroll in x-data-grid, but vertically centered
const offsetHeight = tabbableButton.offsetHeight;
const offsetTop = tabbableButton.offsetTop;
const clientHeight = scrollerRef.current.clientHeight;
const scrollTop = scrollerRef.current.scrollTop;
const elementBottom = offsetTop + offsetHeight;
if (offsetHeight > clientHeight || offsetTop < scrollTop) {
// Button already visible
return;
}
scrollerRef.current.scrollTop = elementBottom - clientHeight / 2 - offsetHeight / 2;
}, [autoFocus]);
return /*#__PURE__*/jsx(YearCalendarRoot, _extends({
ref: handleRef,
className: clsx(classes.root, className),
ownerState: ownerState,
role: "radiogroup",
"aria-labelledby": gridLabelId
}, other, {
children: utils.getYearRange(minDate, maxDate).map(year => {
const yearNumber = utils.getYear(year);
const isSelected = yearNumber === selectedYear;
const isDisabled = disabled || isYearDisabled(year);
return /*#__PURE__*/jsx(PickersYear, {
selected: isSelected,
value: yearNumber,
onClick: handleYearSelection,
onKeyDown: handleKeyDown,
autoFocus: internalHasFocus && yearNumber === focusedYear,
disabled: isDisabled,
tabIndex: yearNumber === focusedYear ? 0 : -1,
onFocus: handleYearFocus,
onBlur: handleYearBlur,
"aria-current": todayYear === yearNumber ? 'date' : undefined,
yearsPerRow: yearsPerRow,
children: utils.format(year, 'year')
}, utils.format(year, 'year'));
})
}));
});
process.env.NODE_ENV !== "production" ? YearCalendar.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
autoFocus: PropTypes.bool,
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object,
/**
* className applied to the root element.
*/
className: PropTypes.string,
/**
* The default selected value.
* Used when the component is not controlled.
*/
defaultValue: PropTypes.any,
/**
* If `true` picker is disabled
*/
disabled: PropTypes.bool,
/**
* If `true`, disable values after the current date for date components, time for time components and both for date time components.
* @default false
*/
disableFuture: PropTypes.bool,
/**
* If `true`, today's date is rendering without highlighting with circle.
* @default false
*/
disableHighlightToday: PropTypes.bool,
/**
* If `true`, disable values before the current date for date components, time for time components and both for date time components.
* @default false
*/
disablePast: PropTypes.bool,
gridLabelId: PropTypes.string,
hasFocus: PropTypes.bool,
/**
* Maximal selectable date.
*/
maxDate: PropTypes.any,
/**
* Minimal selectable date.
*/
minDate: PropTypes.any,
/**
* Callback fired when the value changes.
* @template TDate
* @param {TDate} value The new value.
*/
onChange: PropTypes.func,
onFocusedViewChange: PropTypes.func,
onYearFocus: PropTypes.func,
/**
* If `true` picker is readonly
*/
readOnly: PropTypes.bool,
/**
* The date used to generate the new value when both `value` and `defaultValue` are empty.
* @default The closest valid year using the validation props, except callbacks such as `shouldDisableYear`.
*/
referenceDate: PropTypes.any,
/**
* Disable specific year.
* @template TDate
* @param {TDate} year The year to test.
* @returns {boolean} If `true`, the year will be disabled.
*/
shouldDisableYear: PropTypes.func,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
/**
* Choose which timezone to use for the value.
* Example: "default", "system", "UTC", "America/New_York".
* If you pass values from other timezones to some props, they will be converted to this timezone before being used.
* @see See the {@link https://mui.com/x/react-date-pickers/timezone/ timezones documention} for more details.
* @default The timezone of the `value` or `defaultValue` prop is defined, 'default' otherwise.
*/
timezone: PropTypes.string,
/**
* The selected value.
* Used when the component is controlled.
*/
value: PropTypes.any,
/**
* Years rendered per row.
* @default 3
*/
yearsPerRow: PropTypes.oneOf([3, 4])
} : void 0;
const getPickersCalendarHeaderUtilityClass = slot => generateUtilityClass('MuiPickersCalendarHeader', slot);
const pickersCalendarHeaderClasses = generateUtilityClasses('MuiPickersCalendarHeader', ['root', 'labelContainer', 'label', 'switchViewButton', 'switchViewIcon']);
const _excluded$5 = ["slots", "slotProps", "components", "componentsProps", "currentMonth", "disabled", "disableFuture", "disablePast", "maxDate", "minDate", "onMonthChange", "onViewChange", "view", "reduceAnimations", "views", "labelId", "className", "timezone"],
_excluded2$1 = ["ownerState"];
const useUtilityClasses$2 = ownerState => {
const {
classes
} = ownerState;
const slots = {
root: ['root'],
labelContainer: ['labelContainer'],
label: ['label'],
switchViewButton: ['switchViewButton'],
switchViewIcon: ['switchViewIcon']
};
return composeClasses(slots, getPickersCalendarHeaderUtilityClass, classes);
};
const PickersCalendarHeaderRoot = styled$3('div', {
name: 'MuiPickersCalendarHeader',
slot: 'Root',
overridesResolver: (_, styles) => styles.root
})({
display: 'flex',
alignItems: 'center',
marginTop: 16,
marginBottom: 8,
paddingLeft: 24,
paddingRight: 12,
// prevent jumping in safari
maxHeight: 30,
minHeight: 30
});
const PickersCalendarHeaderLabelContainer = styled$3('div', {
name: 'MuiPickersCalendarHeader',
slot: 'LabelContainer',
overridesResolver: (_, styles) => styles.labelContainer
})(({
theme
}) => _extends({
display: 'flex',
overflow: 'hidden',
alignItems: 'center',
cursor: 'pointer',
marginRight: 'auto'
}, theme.typography.body1, {
fontWeight: theme.typography.fontWeightMedium
}));
const PickersCalendarHeaderLabel = styled$3('div', {
name: 'MuiPickersCalendarHeader',
slot: 'Label',
overridesResolver: (_, styles) => styles.label
})({
marginRight: 6
});
const PickersCalendarHeaderSwitchViewButton = styled$3(IconButton, {
name: 'MuiPickersCalendarHeader',
slot: 'SwitchViewButton',
overridesResolver: (_, styles) => styles.switchViewButton
})(({
ownerState
}) => _extends({
marginRight: 'auto'
}, ownerState.view === 'year' && {
[`.${pickersCalendarHeaderClasses.switchViewIcon}`]: {
transform: 'rotate(180deg)'
}
}));
const PickersCalendarHeaderSwitchViewIcon = styled$3(ArrowDropDownIcon, {
name: 'MuiPickersCalendarHeader',
slot: 'SwitchViewIcon',
overridesResolver: (_, styles) => styles.switchViewIcon
})(({
theme
}) => ({
willChange: 'transform',
transition: theme.transitions.create('transform'),
transform: 'rotate(0deg)'
}));
/**
* Demos:
*
* - [DateCalendar](https://mui.com/x/react-date-pickers/date-calendar/)
* - [DateRangeCalendar](https://mui.com/x/react-date-pickers/date-range-calendar/)
* - [Custom slots and subcomponents](https://mui.com/x/react-date-pickers/custom-components/)
*
* API:
*
* - [PickersCalendarHeader API](https://mui.com/x/api/date-pickers/pickers-calendar-header/)
*/
const PickersCalendarHeader = /*#__PURE__*/React.forwardRef(function PickersCalendarHeader(inProps, ref) {
var _ref, _slots$switchViewButt, _ref2, _slots$switchViewIcon;
const localeText = useLocaleText();
const utils = useUtils();
const props = useThemeProps({
props: inProps,
name: 'MuiPickersCalendarHeader'
});
const {
slots,
slotProps,
components,
currentMonth: month,
disabled,
disableFuture,
disablePast,
maxDate,
minDate,
onMonthChange,
onViewChange,
view,
reduceAnimations,
views,
labelId,
className,
timezone
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$5);
const ownerState = props;
const classes = useUtilityClasses$2(props);
const SwitchViewButton = (_ref = (_slots$switchViewButt = slots == null ? void 0 : slots.switchViewButton) != null ? _slots$switchViewButt : components == null ? void 0 : components.SwitchViewButton) != null ? _ref : PickersCalendarHeaderSwitchViewButton;
const switchViewButtonProps = useSlotProps({
elementType: SwitchViewButton,
externalSlotProps: slotProps == null ? void 0 : slotProps.switchViewButton,
additionalProps: {
size: 'small',
'aria-label': localeText.calendarViewSwitchingButtonAriaLabel(view)
},
ownerState,
className: classes.switchViewButton
});
const SwitchViewIcon = (_ref2 = (_slots$switchViewIcon = slots == null ? void 0 : slots.switchViewIcon) != null ? _slots$switchViewIcon : components == null ? void 0 : components.SwitchViewIcon) != null ? _ref2 : PickersCalendarHeaderSwitchViewIcon;
// The spread is here to avoid this bug mui/material-ui#34056
const _useSlotProps = useSlotProps({
elementType: SwitchViewIcon,
externalSlotProps: slotProps == null ? void 0 : slotProps.switchViewIcon,
ownerState: undefined,
className: classes.switchViewIcon
}),
switchViewIconProps = _objectWithoutPropertiesLoose$1(_useSlotProps, _excluded2$1);
const selectNextMonth = () => onMonthChange(utils.addMonths(month, 1), 'left');
const selectPreviousMonth = () => onMonthChange(utils.addMonths(month, -1), 'right');
const isNextMonthDisabled = useNextMonthDisabled(month, {
disableFuture,
maxDate,
timezone
});
const isPreviousMonthDisabled = usePreviousMonthDisabled(month, {
disablePast,
minDate,
timezone
});
const handleToggleView = () => {
if (views.length === 1 || !onViewChange || disabled) {
return;
}
if (views.length === 2) {
onViewChange(views.find(el => el !== view) || views[0]);
} else {
// switching only between first 2
const nextIndexToOpen = views.indexOf(view) !== 0 ? 0 : 1;
onViewChange(views[nextIndexToOpen]);
}
};
// No need to display more information
if (views.length === 1 && views[0] === 'year') {
return null;
}
return /*#__PURE__*/jsxs(PickersCalendarHeaderRoot, _extends({}, other, {
ownerState: ownerState,
className: clsx(className, classes.root),
ref: ref,
children: [/*#__PURE__*/jsxs(PickersCalendarHeaderLabelContainer, {
role: "presentation",
onClick: handleToggleView,
ownerState: ownerState
// putting this on the label item element below breaks when using transition
,
"aria-live": "polite",
className: classes.labelContainer,
children: [/*#__PURE__*/jsx(PickersFadeTransitionGroup, {
reduceAnimations: reduceAnimations,
transKey: utils.format(month, 'monthAndYear'),
children: /*#__PURE__*/jsx(PickersCalendarHeaderLabel, {
id: labelId,
ownerState: ownerState,
className: classes.label,
children: utils.format(month, 'monthAndYear')
})
}), views.length > 1 && !disabled && /*#__PURE__*/jsx(SwitchViewButton, _extends({}, switchViewButtonProps, {
children: /*#__PURE__*/jsx(SwitchViewIcon, _extends({}, switchViewIconProps))
}))]
}), /*#__PURE__*/jsx(Fade, {
in: view === 'day',
children: /*#__PURE__*/jsx(PickersArrowSwitcher, {
slots: slots,
slotProps: slotProps,
onGoToPrevious: selectPreviousMonth,
isPreviousDisabled: isPreviousMonthDisabled,
previousLabel: localeText.previousMonth,
onGoToNext: selectNextMonth,
isNextDisabled: isNextMonthDisabled,
nextLabel: localeText.nextMonth
})
})]
}));
});
process.env.NODE_ENV !== "production" ? PickersCalendarHeader.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object,
/**
* className applied to the root element.
*/
className: PropTypes.string,
/**
* Overridable components.
* @default {}
* @deprecated Please use `slots`.
*/
components: PropTypes.object,
/**
* The props used for each component slot.
* @default {}
* @deprecated Please use `slotProps`.
*/
componentsProps: PropTypes.object,
currentMonth: PropTypes.any.isRequired,
disabled: PropTypes.bool,
disableFuture: PropTypes.bool,
disablePast: PropTypes.bool,
labelId: PropTypes.string,
maxDate: PropTypes.any.isRequired,
minDate: PropTypes.any.isRequired,
onMonthChange: PropTypes.func.isRequired,
onViewChange: PropTypes.func,
reduceAnimations: PropTypes.bool.isRequired,
/**
* The props used for each component slot.
* @default {}
*/
slotProps: PropTypes.object,
/**
* Overridable component slots.
* @default {}
*/
slots: PropTypes.object,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
timezone: PropTypes.string.isRequired,
view: PropTypes.oneOf(['day', 'month', 'year']).isRequired,
views: PropTypes.arrayOf(PropTypes.oneOf(['day', 'month', 'year']).isRequired).isRequired
} : void 0;
const getDateCalendarUtilityClass = slot => generateUtilityClass('MuiDateCalendar', slot);
generateUtilityClasses('MuiDateCalendar', ['root', 'viewTransitionContainer']);
const _excluded$4 = ["autoFocus", "onViewChange", "value", "defaultValue", "referenceDate", "disableFuture", "disablePast", "defaultCalendarMonth", "onChange", "onYearChange", "onMonthChange", "reduceAnimations", "shouldDisableDate", "shouldDisableMonth", "shouldDisableYear", "view", "views", "openTo", "className", "disabled", "readOnly", "minDate", "maxDate", "disableHighlightToday", "focusedView", "onFocusedViewChange", "showDaysOutsideCurrentMonth", "fixedWeekNumber", "dayOfWeekFormatter", "components", "componentsProps", "slots", "slotProps", "loading", "renderLoading", "displayWeekNumber", "yearsPerRow", "monthsPerRow", "timezone"];
const useUtilityClasses$1 = ownerState => {
const {
classes
} = ownerState;
const slots = {
root: ['root'],
viewTransitionContainer: ['viewTransitionContainer']
};
return composeClasses(slots, getDateCalendarUtilityClass, classes);
};
function useDateCalendarDefaultizedProps(props, name) {
var _themeProps$loading, _themeProps$disablePa, _themeProps$disableFu, _themeProps$openTo, _themeProps$views, _themeProps$reduceAni, _themeProps$renderLoa;
const utils = useUtils();
const defaultDates = useDefaultDates();
const defaultReduceAnimations = useDefaultReduceAnimations();
const themeProps = useThemeProps({
props,
name
});
return _extends({}, themeProps, {
loading: (_themeProps$loading = themeProps.loading) != null ? _themeProps$loading : false,
disablePast: (_themeProps$disablePa = themeProps.disablePast) != null ? _themeProps$disablePa : false,
disableFuture: (_themeProps$disableFu = themeProps.disableFuture) != null ? _themeProps$disableFu : false,
openTo: (_themeProps$openTo = themeProps.openTo) != null ? _themeProps$openTo : 'day',
views: (_themeProps$views = themeProps.views) != null ? _themeProps$views : ['year', 'day'],
reduceAnimations: (_themeProps$reduceAni = themeProps.reduceAnimations) != null ? _themeProps$reduceAni : defaultReduceAnimations,
renderLoading: (_themeProps$renderLoa = themeProps.renderLoading) != null ? _themeProps$renderLoa : () => /*#__PURE__*/jsx("span", {
children: "..."
}),
minDate: applyDefaultDate(utils, themeProps.minDate, defaultDates.minDate),
maxDate: applyDefaultDate(utils, themeProps.maxDate, defaultDates.maxDate)
});
}
const DateCalendarRoot = styled$3(PickerViewRoot, {
name: 'MuiDateCalendar',
slot: 'Root',
overridesResolver: (props, styles) => styles.root
})({
display: 'flex',
flexDirection: 'column',
height: VIEW_HEIGHT
});
const DateCalendarViewTransitionContainer = styled$3(PickersFadeTransitionGroup, {
name: 'MuiDateCalendar',
slot: 'ViewTransitionContainer',
overridesResolver: (props, styles) => styles.viewTransitionContainer
})({});
/**
* Demos:
*
* - [DatePicker](https://mui.com/x/react-date-pickers/date-picker/)
* - [DateCalendar](https://mui.com/x/react-date-pickers/date-calendar/)
* - [Validation](https://mui.com/x/react-date-pickers/validation/)
*
* API:
*
* - [DateCalendar API](https://mui.com/x/api/date-pickers/date-calendar/)
*/
const DateCalendar = /*#__PURE__*/React.forwardRef(function DateCalendar(inProps, ref) {
var _ref, _slots$calendarHeader, _slotProps$calendarHe;
const utils = useUtils();
const id = useId();
const props = useDateCalendarDefaultizedProps(inProps, 'MuiDateCalendar');
const {
autoFocus,
onViewChange,
value: valueProp,
defaultValue,
referenceDate: referenceDateProp,
disableFuture,
disablePast,
defaultCalendarMonth,
onChange,
onYearChange,
onMonthChange,
reduceAnimations,
shouldDisableDate,
shouldDisableMonth,
shouldDisableYear,
view: inView,
views,
openTo,
className,
disabled,
readOnly,
minDate,
maxDate,
disableHighlightToday,
focusedView: inFocusedView,
onFocusedViewChange,
showDaysOutsideCurrentMonth,
fixedWeekNumber,
dayOfWeekFormatter,
components,
componentsProps,
slots,
slotProps,
loading,
renderLoading,
displayWeekNumber,
yearsPerRow,
monthsPerRow,
timezone: timezoneProp
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$4);
const {
value,
handleValueChange,
timezone
} = useControlledValueWithTimezone({
name: 'DateCalendar',
timezone: timezoneProp,
value: valueProp,
defaultValue,
onChange,
valueManager: singleItemValueManager
});
const {
view,
setView,
focusedView,
setFocusedView,
goToNextView,
setValueAndGoToNextView
} = useViews({
view: inView,
views,
openTo,
onChange: handleValueChange,
onViewChange,
autoFocus,
focusedView: inFocusedView,
onFocusedViewChange
});
const {
referenceDate,
calendarState,
changeFocusedDay,
changeMonth,
handleChangeMonth,
isDateDisabled,
onMonthSwitchingAnimationEnd
} = useCalendarState({
value,
defaultCalendarMonth,
referenceDate: referenceDateProp,
reduceAnimations,
onMonthChange,
minDate,
maxDate,
shouldDisableDate,
disablePast,
disableFuture,
timezone
});
// When disabled, limit the view to the selected date
const minDateWithDisabled = disabled && value || minDate;
const maxDateWithDisabled = disabled && value || maxDate;
const gridLabelId = `${id}-grid-label`;
const hasFocus = focusedView !== null;
const CalendarHeader = (_ref = (_slots$calendarHeader = slots == null ? void 0 : slots.calendarHeader) != null ? _slots$calendarHeader : components == null ? void 0 : components.CalendarHeader) != null ? _ref : PickersCalendarHeader;
const calendarHeaderProps = useSlotProps({
elementType: CalendarHeader,
externalSlotProps: (_slotProps$calendarHe = slotProps == null ? void 0 : slotProps.calendarHeader) != null ? _slotProps$calendarHe : componentsProps == null ? void 0 : componentsProps.calendarHeader,
additionalProps: {
views,
view,
currentMonth: calendarState.currentMonth,
onViewChange: setView,
onMonthChange: (newMonth, direction) => handleChangeMonth({
newMonth,
direction
}),
minDate: minDateWithDisabled,
maxDate: maxDateWithDisabled,
disabled,
disablePast,
disableFuture,
reduceAnimations,
timezone,
labelId: gridLabelId,
slots,
slotProps
},
ownerState: props
});
const handleDateMonthChange = useEventCallback(newDate => {
const startOfMonth = utils.startOfMonth(newDate);
const endOfMonth = utils.endOfMonth(newDate);
const closestEnabledDate = isDateDisabled(newDate) ? findClosestEnabledDate({
utils,
date: newDate,
minDate: utils.isBefore(minDate, startOfMonth) ? startOfMonth : minDate,
maxDate: utils.isAfter(maxDate, endOfMonth) ? endOfMonth : maxDate,
disablePast,
disableFuture,
isDateDisabled,
timezone
}) : newDate;
if (closestEnabledDate) {
setValueAndGoToNextView(closestEnabledDate, 'finish');
onMonthChange == null || onMonthChange(startOfMonth);
} else {
goToNextView();
changeMonth(startOfMonth);
}
changeFocusedDay(closestEnabledDate, true);
});
const handleDateYearChange = useEventCallback(newDate => {
const startOfYear = utils.startOfYear(newDate);
const endOfYear = utils.endOfYear(newDate);
const closestEnabledDate = isDateDisabled(newDate) ? findClosestEnabledDate({
utils,
date: newDate,
minDate: utils.isBefore(minDate, startOfYear) ? startOfYear : minDate,
maxDate: utils.isAfter(maxDate, endOfYear) ? endOfYear : maxDate,
disablePast,
disableFuture,
isDateDisabled,
timezone
}) : newDate;
if (closestEnabledDate) {
setValueAndGoToNextView(closestEnabledDate, 'finish');
onYearChange == null || onYearChange(closestEnabledDate);
} else {
goToNextView();
changeMonth(startOfYear);
}
changeFocusedDay(closestEnabledDate, true);
});
const handleSelectedDayChange = useEventCallback(day => {
if (day) {
// If there is a date already selected, then we want to keep its time
return handleValueChange(mergeDateAndTime(utils, day, value != null ? value : referenceDate), 'finish', view);
}
return handleValueChange(day, 'finish', view);
});
React.useEffect(() => {
if (value != null && utils.isValid(value)) {
changeMonth(value);
}
}, [value]); // eslint-disable-line
const ownerState = props;
const classes = useUtilityClasses$1(ownerState);
const baseDateValidationProps = {
disablePast,
disableFuture,
maxDate,
minDate
};
const commonViewProps = {
disableHighlightToday,
readOnly,
disabled,
timezone,
gridLabelId
};
const prevOpenViewRef = React.useRef(view);
React.useEffect(() => {
// If the view change and the focus was on the previous view
// Then we update the focus.
if (prevOpenViewRef.current === view) {
return;
}
if (focusedView === prevOpenViewRef.current) {
setFocusedView(view, true);
}
prevOpenViewRef.current = view;
}, [focusedView, setFocusedView, view]);
const selectedDays = React.useMemo(() => [value], [value]);
return /*#__PURE__*/jsxs(DateCalendarRoot, _extends({
ref: ref,
className: clsx(classes.root, className),
ownerState: ownerState
}, other, {
children: [/*#__PURE__*/jsx(CalendarHeader, _extends({}, calendarHeaderProps)), /*#__PURE__*/jsx(DateCalendarViewTransitionContainer, {
reduceAnimations: reduceAnimations,
className: classes.viewTransitionContainer,
transKey: view,
ownerState: ownerState,
children: /*#__PURE__*/jsxs("div", {
children: [view === 'year' && /*#__PURE__*/jsx(YearCalendar, _extends({}, baseDateValidationProps, commonViewProps, {
value: value,
onChange: handleDateYearChange,
shouldDisableYear: shouldDisableYear,
hasFocus: hasFocus,
onFocusedViewChange: isViewFocused => setFocusedView('year', isViewFocused),
yearsPerRow: yearsPerRow,
referenceDate: referenceDate
})), view === 'month' && /*#__PURE__*/jsx(MonthCalendar, _extends({}, baseDateValidationProps, commonViewProps, {
hasFocus: hasFocus,
className: className,
value: value,
onChange: handleDateMonthChange,
shouldDisableMonth: shouldDisableMonth,
onFocusedViewChange: isViewFocused => setFocusedView('month', isViewFocused),
monthsPerRow: monthsPerRow,
referenceDate: referenceDate
})), view === 'day' && /*#__PURE__*/jsx(DayCalendar, _extends({}, calendarState, baseDateValidationProps, commonViewProps, {
onMonthSwitchingAnimationEnd: onMonthSwitchingAnimationEnd,
onFocusedDayChange: changeFocusedDay,
reduceAnimations: reduceAnimations,
selectedDays: selectedDays,
onSelectedDaysChange: handleSelectedDayChange,
shouldDisableDate: shouldDisableDate,
shouldDisableMonth: shouldDisableMonth,
shouldDisableYear: shouldDisableYear,
hasFocus: hasFocus,
onFocusedViewChange: isViewFocused => setFocusedView('day', isViewFocused),
showDaysOutsideCurrentMonth: showDaysOutsideCurrentMonth,
fixedWeekNumber: fixedWeekNumber,
dayOfWeekFormatter: dayOfWeekFormatter,
displayWeekNumber: displayWeekNumber,
components: components,
componentsProps: componentsProps,
slots: slots,
slotProps: slotProps,
loading: loading,
renderLoading: renderLoading
}))]
})
})]
}));
});
process.env.NODE_ENV !== "production" ? DateCalendar.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* If `true`, the main element is focused during the first mount.
* This main element is:
* - the element chosen by the visible view if any (i.e: the selected day on the `day` view).
* - the `input` element if there is a field rendered.
*/
autoFocus: PropTypes.bool,
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object,
className: PropTypes.string,
/**
* Overridable components.
* @default {}
* @deprecated Please use `slots`.
*/
components: PropTypes.object,
/**
* The props used for each component slot.
* @default {}
* @deprecated Please use `slotProps`.
*/
componentsProps: PropTypes.object,
/**
* Formats the day of week displayed in the calendar header.
* @param {string} day The day of week provided by the adapter. Deprecated, will be removed in v7: Use `date` instead.
* @param {TDate} date The date of the day of week provided by the adapter.
* @returns {string} The name to display.
* @default (_day: string, date: TDate) => adapter.format(date, 'weekdayShort').charAt(0).toUpperCase()
*/
dayOfWeekFormatter: PropTypes.func,
/**
* Default calendar month displayed when `value` and `defaultValue` are empty.
* @deprecated Consider using `referenceDate` instead.
*/
defaultCalendarMonth: PropTypes.any,
/**
* The default selected value.
* Used when the component is not controlled.
*/
defaultValue: PropTypes.any,
/**
* If `true`, the picker and text field are disabled.
* @default false
*/
disabled: PropTypes.bool,
/**
* If `true`, disable values after the current date for date components, time for time components and both for date time components.
* @default false
*/
disableFuture: PropTypes.bool,
/**
* If `true`, today's date is rendering without highlighting with circle.
* @default false
*/
disableHighlightToday: PropTypes.bool,
/**
* If `true`, disable values before the current date for date components, time for time components and both for date time components.
* @default false
*/
disablePast: PropTypes.bool,
/**
* If `true`, the week number will be display in the calendar.
*/
displayWeekNumber: PropTypes.bool,
/**
* Calendar will show more weeks in order to match this value.
* Put it to 6 for having fix number of week in Gregorian calendars
* @default undefined
*/
fixedWeekNumber: PropTypes.number,
/**
* Controlled focused view.
*/
focusedView: PropTypes.oneOf(['day', 'month', 'year']),
/**
* If `true`, calls `renderLoading` instead of rendering the day calendar.
* Can be used to preload information and show it in calendar.
* @default false
*/
loading: PropTypes.bool,
/**
* Maximal selectable date.
*/
maxDate: PropTypes.any,
/**
* Minimal selectable date.
*/
minDate: PropTypes.any,
/**
* Months rendered per row.
* @default 3
*/
monthsPerRow: PropTypes.oneOf([3, 4]),
/**
* Callback fired when the value changes.
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @template TView The view type. Will be one of date or time views.
* @param {TValue} value The new value.
* @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
* @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
*/
onChange: PropTypes.func,
/**
* Callback fired on focused view change.
* @template TView
* @param {TView} view The new view to focus or not.
* @param {boolean} hasFocus `true` if the view should be focused.
*/
onFocusedViewChange: PropTypes.func,
/**
* Callback fired on month change.
* @template TDate
* @param {TDate} month The new month.
*/
onMonthChange: PropTypes.func,
/**
* Callback fired on view change.
* @template TView
* @param {TView} view The new view.
*/
onViewChange: PropTypes.func,
/**
* Callback fired on year change.
* @template TDate
* @param {TDate} year The new year.
*/
onYearChange: PropTypes.func,
/**
* The default visible view.
* Used when the component view is not controlled.
* Must be a valid option from `views` list.
*/
openTo: PropTypes.oneOf(['day', 'month', 'year']),
/**
* Make picker read only.
* @default false
*/
readOnly: PropTypes.bool,
/**
* If `true`, disable heavy animations.
* @default `@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13
*/
reduceAnimations: PropTypes.bool,
/**
* The date used to generate the new value when both `value` and `defaultValue` are empty.
* @default The closest valid date using the validation props, except callbacks such as `shouldDisableDate`.
*/
referenceDate: PropTypes.any,
/**
* Component displaying when passed `loading` true.
* @returns {React.ReactNode} The node to render when loading.
* @default () => <span data-mui-test="loading-progress">...</span>
*/
renderLoading: PropTypes.func,
/**
* Disable specific date.
*
* Warning: This function can be called multiple times (e.g. when rendering date calendar, checking if focus can be moved to a certain date, etc.). Expensive computations can impact performance.
*
* @template TDate
* @param {TDate} day The date to test.
* @returns {boolean} If `true` the date will be disabled.
*/
shouldDisableDate: PropTypes.func,
/**
* Disable specific month.
* @template TDate
* @param {TDate} month The month to test.
* @returns {boolean} If `true`, the month will be disabled.
*/
shouldDisableMonth: PropTypes.func,
/**
* Disable specific year.
* @template TDate
* @param {TDate} year The year to test.
* @returns {boolean} If `true`, the year will be disabled.
*/
shouldDisableYear: PropTypes.func,
/**
* If `true`, days outside the current month are rendered:
*
* - if `fixedWeekNumber` is defined, renders days to have the weeks requested.
*
* - if `fixedWeekNumber` is not defined, renders day to fill the first and last week of the current month.
*
* - ignored if `calendars` equals more than `1` on range pickers.
* @default false
*/
showDaysOutsideCurrentMonth: PropTypes.bool,
/**
* The props used for each component slot.
* @default {}
*/
slotProps: PropTypes.object,
/**
* Overridable component slots.
* @default {}
*/
slots: PropTypes.object,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
/**
* Choose which timezone to use for the value.
* Example: "default", "system", "UTC", "America/New_York".
* If you pass values from other timezones to some props, they will be converted to this timezone before being used.
* @see See the {@link https://mui.com/x/react-date-pickers/timezone/ timezones documention} for more details.
* @default The timezone of the `value` or `defaultValue` prop is defined, 'default' otherwise.
*/
timezone: PropTypes.string,
/**
* The selected value.
* Used when the component is controlled.
*/
value: PropTypes.any,
/**
* The visible view.
* Used when the component view is controlled.
* Must be a valid option from `views` list.
*/
view: PropTypes.oneOf(['day', 'month', 'year']),
/**
* Available views.
*/
views: PropTypes.arrayOf(PropTypes.oneOf(['day', 'month', 'year']).isRequired),
/**
* Years rendered per row.
* @default 3
*/
yearsPerRow: PropTypes.oneOf([3, 4])
} : void 0;
function getDatePickerToolbarUtilityClass(slot) {
return generateUtilityClass('MuiDatePickerToolbar', slot);
}
generateUtilityClasses('MuiDatePickerToolbar', ['root', 'title']);
const _excluded$3 = ["value", "isLandscape", "onChange", "toolbarFormat", "toolbarPlaceholder", "views", "className"];
const useUtilityClasses = ownerState => {
const {
classes
} = ownerState;
const slots = {
root: ['root'],
title: ['title']
};
return composeClasses(slots, getDatePickerToolbarUtilityClass, classes);
};
const DatePickerToolbarRoot = styled$3(PickersToolbar, {
name: 'MuiDatePickerToolbar',
slot: 'Root',
overridesResolver: (_, styles) => styles.root
})({});
const DatePickerToolbarTitle = styled$3(Typography, {
name: 'MuiDatePickerToolbar',
slot: 'Title',
overridesResolver: (_, styles) => styles.title
})(({
ownerState
}) => _extends({}, ownerState.isLandscape && {
margin: 'auto 16px auto auto'
}));
/**
* Demos:
*
* - [DatePicker](https://mui.com/x/react-date-pickers/date-picker/)
* - [Custom components](https://mui.com/x/react-date-pickers/custom-components/)
*
* API:
*
* - [DatePickerToolbar API](https://mui.com/x/api/date-pickers/date-picker-toolbar/)
*/
const DatePickerToolbar = /*#__PURE__*/React.forwardRef(function DatePickerToolbar(inProps, ref) {
const props = useThemeProps({
props: inProps,
name: 'MuiDatePickerToolbar'
});
const {
value,
isLandscape,
toolbarFormat,
toolbarPlaceholder = '––',
views,
className
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded$3);
const utils = useUtils();
const localeText = useLocaleText();
const classes = useUtilityClasses(props);
const dateText = React.useMemo(() => {
if (!value) {
return toolbarPlaceholder;
}
const formatFromViews = resolveDateFormat(utils, {
format: toolbarFormat,
views
}, true);
return utils.formatByString(value, formatFromViews);
}, [value, toolbarFormat, toolbarPlaceholder, utils, views]);
const ownerState = props;
return /*#__PURE__*/jsx(DatePickerToolbarRoot, _extends({
ref: ref,
toolbarTitle: localeText.datePickerToolbarTitle,
isLandscape: isLandscape,
className: clsx(classes.root, className)
}, other, {
children: /*#__PURE__*/jsx(DatePickerToolbarTitle, {
variant: "h4",
align: isLandscape ? 'left' : 'center',
ownerState: ownerState,
className: classes.title,
children: dateText
})
}));
});
process.env.NODE_ENV !== "production" ? DatePickerToolbar.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object,
/**
* className applied to the root component.
*/
className: PropTypes.string,
disabled: PropTypes.bool,
/**
* If `true`, show the toolbar even in desktop mode.
* @default `true` for Desktop, `false` for Mobile.
*/
hidden: PropTypes.bool,
isLandscape: PropTypes.bool.isRequired,
onChange: PropTypes.func.isRequired,
/**
* Callback called when a toolbar is clicked
* @template TView
* @param {TView} view The view to open
*/
onViewChange: PropTypes.func.isRequired,
readOnly: PropTypes.bool,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
titleId: PropTypes.string,
/**
* Toolbar date format.
*/
toolbarFormat: PropTypes.string,
/**
* Toolbar value placeholder—it is displayed when the value is empty.
* @default "––"
*/
toolbarPlaceholder: PropTypes.node,
value: PropTypes.any,
/**
* Currently visible picker view.
*/
view: PropTypes.oneOf(['day', 'month', 'year']).isRequired,
views: PropTypes.arrayOf(PropTypes.oneOf(['day', 'month', 'year']).isRequired).isRequired
} : void 0;
function useDatePickerDefaultizedProps(props, name) {
var _themeProps$slots, _themeProps$disableFu, _themeProps$disablePa, _themeProps$slotProps;
const utils = useUtils();
const defaultDates = useDefaultDates();
const themeProps = useThemeProps({
props,
name
});
const localeText = React.useMemo(() => {
var _themeProps$localeTex;
if (((_themeProps$localeTex = themeProps.localeText) == null ? void 0 : _themeProps$localeTex.toolbarTitle) == null) {
return themeProps.localeText;
}
return _extends({}, themeProps.localeText, {
datePickerToolbarTitle: themeProps.localeText.toolbarTitle
});
}, [themeProps.localeText]);
const slots = (_themeProps$slots = themeProps.slots) != null ? _themeProps$slots : uncapitalizeObjectKeys(themeProps.components);
return _extends({}, themeProps, {
localeText
}, applyDefaultViewProps({
views: themeProps.views,
openTo: themeProps.openTo,
defaultViews: ['year', 'day'],
defaultOpenTo: 'day'
}), {
disableFuture: (_themeProps$disableFu = themeProps.disableFuture) != null ? _themeProps$disableFu : false,
disablePast: (_themeProps$disablePa = themeProps.disablePast) != null ? _themeProps$disablePa : false,
minDate: applyDefaultDate(utils, themeProps.minDate, defaultDates.minDate),
maxDate: applyDefaultDate(utils, themeProps.maxDate, defaultDates.maxDate),
slots: _extends({
toolbar: DatePickerToolbar
}, slots),
slotProps: (_themeProps$slotProps = themeProps.slotProps) != null ? _themeProps$slotProps : themeProps.componentsProps
});
}
const _excluded$2 = ["props", "getOpenDialogAriaText"],
_excluded2 = ["ownerState"],
_excluded3 = ["ownerState"];
/**
* Hook managing all the single-date desktop pickers:
* - DesktopDatePicker
* - DesktopDateTimePicker
* - DesktopTimePicker
*/
const useDesktopPicker = _ref => {
var _innerSlotProps$toolb, _innerSlotProps$toolb2, _slots$inputAdornment, _slots$openPickerButt, _slots$layout;
let {
props,
getOpenDialogAriaText
} = _ref,
pickerParams = _objectWithoutPropertiesLoose$1(_ref, _excluded$2);
const {
slots,
slotProps: innerSlotProps,
className,
sx,
format,
formatDensity,
timezone,
name,
label,
inputRef,
readOnly,
disabled,
autoFocus,
localeText,
reduceAnimations
} = props;
const utils = useUtils();
const internalInputRef = React.useRef(null);
const containerRef = React.useRef(null);
const labelId = useId();
const isToolbarHidden = (_innerSlotProps$toolb = innerSlotProps == null || (_innerSlotProps$toolb2 = innerSlotProps.toolbar) == null ? void 0 : _innerSlotProps$toolb2.hidden) != null ? _innerSlotProps$toolb : false;
const {
open,
actions,
hasUIView,
layoutProps,
renderCurrentView,
shouldRestoreFocus,
fieldProps: pickerFieldProps
} = usePicker(_extends({}, pickerParams, {
props,
inputRef: internalInputRef,
autoFocusView: true,
additionalViewProps: {},
wrapperVariant: 'desktop'
}));
const InputAdornment$1 = (_slots$inputAdornment = slots.inputAdornment) != null ? _slots$inputAdornment : InputAdornment;
const _useSlotProps = useSlotProps({
elementType: InputAdornment$1,
externalSlotProps: innerSlotProps == null ? void 0 : innerSlotProps.inputAdornment,
additionalProps: {
position: 'end'
},
ownerState: props
}),
inputAdornmentProps = _objectWithoutPropertiesLoose$1(_useSlotProps, _excluded2);
const OpenPickerButton = (_slots$openPickerButt = slots.openPickerButton) != null ? _slots$openPickerButt : IconButton;
const _useSlotProps2 = useSlotProps({
elementType: OpenPickerButton,
externalSlotProps: innerSlotProps == null ? void 0 : innerSlotProps.openPickerButton,
additionalProps: {
disabled: disabled || readOnly,
onClick: open ? actions.onClose : actions.onOpen,
'aria-label': getOpenDialogAriaText(pickerFieldProps.value, utils),
edge: inputAdornmentProps.position
},
ownerState: props
}),
openPickerButtonProps = _objectWithoutPropertiesLoose$1(_useSlotProps2, _excluded3);
const OpenPickerIcon = slots.openPickerIcon;
const Field = slots.field;
const fieldProps = useSlotProps({
elementType: Field,
externalSlotProps: innerSlotProps == null ? void 0 : innerSlotProps.field,
additionalProps: _extends({}, pickerFieldProps, isToolbarHidden && {
id: labelId
}, {
readOnly,
disabled,
className,
sx,
format,
formatDensity,
timezone,
label,
name,
autoFocus: autoFocus && !props.open,
focused: open ? true : undefined
}),
ownerState: props
});
// TODO: Move to `useSlotProps` when https://github.com/mui/material-ui/pull/35088 will be merged
if (hasUIView) {
fieldProps.InputProps = _extends({}, fieldProps.InputProps, {
ref: containerRef,
[`${inputAdornmentProps.position}Adornment`]: /*#__PURE__*/jsx(InputAdornment$1, _extends({}, inputAdornmentProps, {
children: /*#__PURE__*/jsx(OpenPickerButton, _extends({}, openPickerButtonProps, {
children: /*#__PURE__*/jsx(OpenPickerIcon, _extends({}, innerSlotProps == null ? void 0 : innerSlotProps.openPickerIcon))
}))
}))
});
}
const slotsForField = _extends({
textField: slots.textField,
clearIcon: slots.clearIcon,
clearButton: slots.clearButton
}, fieldProps.slots);
const Layout = (_slots$layout = slots.layout) != null ? _slots$layout : PickersLayout;
const handleInputRef = useForkRef(internalInputRef, fieldProps.inputRef, inputRef);
let labelledById = labelId;
if (isToolbarHidden) {
if (label) {
labelledById = `${labelId}-label`;
} else {
labelledById = undefined;
}
}
const slotProps = _extends({}, innerSlotProps, {
toolbar: _extends({}, innerSlotProps == null ? void 0 : innerSlotProps.toolbar, {
titleId: labelId
}),
popper: _extends({
'aria-labelledby': labelledById
}, innerSlotProps == null ? void 0 : innerSlotProps.popper)
});
const renderPicker = () => /*#__PURE__*/jsxs(LocalizationProvider, {
localeText: localeText,
children: [/*#__PURE__*/jsx(Field, _extends({}, fieldProps, {
slots: slotsForField,
slotProps: slotProps,
inputRef: handleInputRef
})), /*#__PURE__*/jsx(PickersPopper, _extends({
role: "dialog",
placement: "bottom-start",
anchorEl: containerRef.current
}, actions, {
open: open,
slots: slots,
slotProps: slotProps,
shouldRestoreFocus: shouldRestoreFocus,
reduceAnimations: reduceAnimations,
children: /*#__PURE__*/jsx(Layout, _extends({}, layoutProps, slotProps == null ? void 0 : slotProps.layout, {
slots: slots,
slotProps: slotProps,
children: renderCurrentView()
}))
}))]
});
return {
renderPicker
};
};
const renderDateViewCalendar = ({
view,
onViewChange,
views,
focusedView,
onFocusedViewChange,
value,
defaultValue,
referenceDate,
onChange,
className,
classes,
disableFuture,
disablePast,
minDate,
maxDate,
shouldDisableDate,
shouldDisableMonth,
shouldDisableYear,
reduceAnimations,
onMonthChange,
monthsPerRow,
onYearChange,
yearsPerRow,
defaultCalendarMonth,
components,
componentsProps,
slots,
slotProps,
loading,
renderLoading,
disableHighlightToday,
readOnly,
disabled,
showDaysOutsideCurrentMonth,
dayOfWeekFormatter,
sx,
autoFocus,
fixedWeekNumber,
displayWeekNumber,
timezone
}) => /*#__PURE__*/jsx(DateCalendar, {
view: view,
onViewChange: onViewChange,
views: views.filter(isDatePickerView),
focusedView: focusedView && isDatePickerView(focusedView) ? focusedView : null,
onFocusedViewChange: onFocusedViewChange,
value: value,
defaultValue: defaultValue,
referenceDate: referenceDate,
onChange: onChange,
className: className,
classes: classes,
disableFuture: disableFuture,
disablePast: disablePast,
minDate: minDate,
maxDate: maxDate,
shouldDisableDate: shouldDisableDate,
shouldDisableMonth: shouldDisableMonth,
shouldDisableYear: shouldDisableYear,
reduceAnimations: reduceAnimations,
onMonthChange: onMonthChange,
monthsPerRow: monthsPerRow,
onYearChange: onYearChange,
yearsPerRow: yearsPerRow,
defaultCalendarMonth: defaultCalendarMonth,
components: components,
componentsProps: componentsProps,
slots: slots,
slotProps: slotProps,
loading: loading,
renderLoading: renderLoading,
disableHighlightToday: disableHighlightToday,
readOnly: readOnly,
disabled: disabled,
showDaysOutsideCurrentMonth: showDaysOutsideCurrentMonth,
dayOfWeekFormatter: dayOfWeekFormatter,
sx: sx,
autoFocus: autoFocus,
fixedWeekNumber: fixedWeekNumber,
displayWeekNumber: displayWeekNumber,
timezone: timezone
});
/**
* Demos:
*
* - [DatePicker](https://mui.com/x/react-date-pickers/date-picker/)
* - [Validation](https://mui.com/x/react-date-pickers/validation/)
*
* API:
*
* - [DesktopDatePicker API](https://mui.com/x/api/date-pickers/desktop-date-picker/)
*/
const DesktopDatePicker = /*#__PURE__*/React.forwardRef(function DesktopDatePicker(inProps, ref) {
var _defaultizedProps$yea, _defaultizedProps$slo2, _props$localeText$ope, _props$localeText;
const localeText = useLocaleText();
const utils = useUtils();
// Props with the default values common to all date pickers
const defaultizedProps = useDatePickerDefaultizedProps(inProps, 'MuiDesktopDatePicker');
const viewRenderers = _extends({
day: renderDateViewCalendar,
month: renderDateViewCalendar,
year: renderDateViewCalendar
}, defaultizedProps.viewRenderers);
// Props with the default values specific to the desktop variant
const props = _extends({}, defaultizedProps, {
viewRenderers,
format: resolveDateFormat(utils, defaultizedProps, false),
yearsPerRow: (_defaultizedProps$yea = defaultizedProps.yearsPerRow) != null ? _defaultizedProps$yea : 4,
slots: _extends({
openPickerIcon: CalendarIcon,
field: DateField
}, defaultizedProps.slots),
slotProps: _extends({}, defaultizedProps.slotProps, {
field: ownerState => {
var _defaultizedProps$slo;
return _extends({}, resolveComponentProps((_defaultizedProps$slo = defaultizedProps.slotProps) == null ? void 0 : _defaultizedProps$slo.field, ownerState), extractValidationProps(defaultizedProps), {
ref
});
},
toolbar: _extends({
hidden: true
}, (_defaultizedProps$slo2 = defaultizedProps.slotProps) == null ? void 0 : _defaultizedProps$slo2.toolbar)
})
});
const {
renderPicker
} = useDesktopPicker({
props,
valueManager: singleItemValueManager,
valueType: 'date',
getOpenDialogAriaText: (_props$localeText$ope = (_props$localeText = props.localeText) == null ? void 0 : _props$localeText.openDatePickerDialogue) != null ? _props$localeText$ope : localeText.openDatePickerDialogue,
validator: validateDate
});
return renderPicker();
});
DesktopDatePicker.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* If `true`, the main element is focused during the first mount.
* This main element is:
* - the element chosen by the visible view if any (i.e: the selected day on the `day` view).
* - the `input` element if there is a field rendered.
*/
autoFocus: PropTypes.bool,
/**
* Class name applied to the root element.
*/
className: PropTypes.string,
/**
* If `true`, the popover or modal will close after submitting the full date.
* @default `true` for desktop, `false` for mobile (based on the chosen wrapper and `desktopModeMediaQuery` prop).
*/
closeOnSelect: PropTypes.bool,
/**
* Overridable components.
* @default {}
* @deprecated Please use `slots`.
*/
components: PropTypes.object,
/**
* The props used for each component slot.
* @default {}
* @deprecated Please use `slotProps`.
*/
componentsProps: PropTypes.object,
/**
* Formats the day of week displayed in the calendar header.
* @param {string} day The day of week provided by the adapter. Deprecated, will be removed in v7: Use `date` instead.
* @param {TDate} date The date of the day of week provided by the adapter.
* @returns {string} The name to display.
* @default (_day: string, date: TDate) => adapter.format(date, 'weekdayShort').charAt(0).toUpperCase()
*/
dayOfWeekFormatter: PropTypes.func,
/**
* Default calendar month displayed when `value` and `defaultValue` are empty.
* @deprecated Consider using `referenceDate` instead.
*/
defaultCalendarMonth: PropTypes.any,
/**
* The default value.
* Used when the component is not controlled.
*/
defaultValue: PropTypes.any,
/**
* If `true`, the picker and text field are disabled.
* @default false
*/
disabled: PropTypes.bool,
/**
* If `true`, disable values after the current date for date components, time for time components and both for date time components.
* @default false
*/
disableFuture: PropTypes.bool,
/**
* If `true`, today's date is rendering without highlighting with circle.
* @default false
*/
disableHighlightToday: PropTypes.bool,
/**
* If `true`, the open picker button will not be rendered (renders only the field).
* @default false
*/
disableOpenPicker: PropTypes.bool,
/**
* If `true`, disable values before the current date for date components, time for time components and both for date time components.
* @default false
*/
disablePast: PropTypes.bool,
/**
* If `true`, the week number will be display in the calendar.
*/
displayWeekNumber: PropTypes.bool,
/**
* Calendar will show more weeks in order to match this value.
* Put it to 6 for having fix number of week in Gregorian calendars
* @default undefined
*/
fixedWeekNumber: PropTypes.number,
/**
* Format of the date when rendered in the input(s).
* Defaults to localized format based on the used `views`.
*/
format: PropTypes.string,
/**
* Density of the format when rendered in the input.
* Setting `formatDensity` to `"spacious"` will add a space before and after each `/`, `-` and `.` character.
* @default "dense"
*/
formatDensity: PropTypes.oneOf(['dense', 'spacious']),
/**
* Pass a ref to the `input` element.
*/
inputRef: refType$1,
/**
* The label content.
*/
label: PropTypes.node,
/**
* If `true`, calls `renderLoading` instead of rendering the day calendar.
* Can be used to preload information and show it in calendar.
* @default false
*/
loading: PropTypes.bool,
/**
* Locale for components texts.
* Allows overriding texts coming from `LocalizationProvider` and `theme`.
*/
localeText: PropTypes.object,
/**
* Maximal selectable date.
*/
maxDate: PropTypes.any,
/**
* Minimal selectable date.
*/
minDate: PropTypes.any,
/**
* Months rendered per row.
* @default 3
*/
monthsPerRow: PropTypes.oneOf([3, 4]),
/**
* Name attribute used by the `input` element in the Field.
*/
name: PropTypes.string,
/**
* Callback fired when the value is accepted.
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @param {TValue} value The value that was just accepted.
*/
onAccept: PropTypes.func,
/**
* Callback fired when the value changes.
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value.
* @param {TValue} value The new value.
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
*/
onChange: PropTypes.func,
/**
* Callback fired when the popup requests to be closed.
* Use in controlled mode (see `open`).
*/
onClose: PropTypes.func,
/**
* Callback fired when the error associated to the current value changes.
* If the error has a non-null value, then the `TextField` will be rendered in `error` state.
*
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value.
* @param {TError} error The new error describing why the current value is not valid.
* @param {TValue} value The value associated to the error.
*/
onError: PropTypes.func,
/**
* Callback fired on month change.
* @template TDate
* @param {TDate} month The new month.
*/
onMonthChange: PropTypes.func,
/**
* Callback fired when the popup requests to be opened.
* Use in controlled mode (see `open`).
*/
onOpen: PropTypes.func,
/**
* Callback fired when the selected sections change.
* @param {FieldSelectedSections} newValue The new selected sections.
*/
onSelectedSectionsChange: PropTypes.func,
/**
* Callback fired on view change.
* @template TView
* @param {TView} view The new view.
*/
onViewChange: PropTypes.func,
/**
* Callback fired on year change.
* @template TDate
* @param {TDate} year The new year.
*/
onYearChange: PropTypes.func,
/**
* Control the popup or dialog open state.
* @default false
*/
open: PropTypes.bool,
/**
* The default visible view.
* Used when the component view is not controlled.
* Must be a valid option from `views` list.
*/
openTo: PropTypes.oneOf(['day', 'month', 'year']),
/**
* Force rendering in particular orientation.
*/
orientation: PropTypes.oneOf(['landscape', 'portrait']),
readOnly: PropTypes.bool,
/**
* If `true`, disable heavy animations.
* @default `@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13
*/
reduceAnimations: PropTypes.bool,
/**
* The date used to generate the new value when both `value` and `defaultValue` are empty.
* @default The closest valid date-time using the validation props, except callbacks like `shouldDisable<...>`.
*/
referenceDate: PropTypes.any,
/**
* Component displaying when passed `loading` true.
* @returns {React.ReactNode} The node to render when loading.
* @default () => <span data-mui-test="loading-progress">...</span>
*/
renderLoading: PropTypes.func,
/**
* The currently selected sections.
* This prop accept four formats:
* 1. If a number is provided, the section at this index will be selected.
* 2. If an object with a `startIndex` and `endIndex` properties are provided, the sections between those two indexes will be selected.
* 3. If a string of type `FieldSectionType` is provided, the first section with that name will be selected.
* 4. If `null` is provided, no section will be selected
* If not provided, the selected sections will be handled internally.
*/
selectedSections: PropTypes.oneOfType([PropTypes.oneOf(['all', 'day', 'hours', 'meridiem', 'minutes', 'month', 'seconds', 'weekDay', 'year']), PropTypes.number, PropTypes.shape({
endIndex: PropTypes.number.isRequired,
startIndex: PropTypes.number.isRequired
})]),
/**
* Disable specific date.
*
* Warning: This function can be called multiple times (e.g. when rendering date calendar, checking if focus can be moved to a certain date, etc.). Expensive computations can impact performance.
*
* @template TDate
* @param {TDate} day The date to test.
* @returns {boolean} If `true` the date will be disabled.
*/
shouldDisableDate: PropTypes.func,
/**
* Disable specific month.
* @template TDate
* @param {TDate} month The month to test.
* @returns {boolean} If `true`, the month will be disabled.
*/
shouldDisableMonth: PropTypes.func,
/**
* Disable specific year.
* @template TDate
* @param {TDate} year The year to test.
* @returns {boolean} If `true`, the year will be disabled.
*/
shouldDisableYear: PropTypes.func,
/**
* If `true`, days outside the current month are rendered:
*
* - if `fixedWeekNumber` is defined, renders days to have the weeks requested.
*
* - if `fixedWeekNumber` is not defined, renders day to fill the first and last week of the current month.
*
* - ignored if `calendars` equals more than `1` on range pickers.
* @default false
*/
showDaysOutsideCurrentMonth: PropTypes.bool,
/**
* The props used for each component slot.
* @default {}
*/
slotProps: PropTypes.object,
/**
* Overridable component slots.
* @default {}
*/
slots: PropTypes.object,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
/**
* Choose which timezone to use for the value.
* Example: "default", "system", "UTC", "America/New_York".
* If you pass values from other timezones to some props, they will be converted to this timezone before being used.
* @see See the {@link https://mui.com/x/react-date-pickers/timezone/ timezones documention} for more details.
* @default The timezone of the `value` or `defaultValue` prop is defined, 'default' otherwise.
*/
timezone: PropTypes.string,
/**
* The selected value.
* Used when the component is controlled.
*/
value: PropTypes.any,
/**
* The visible view.
* Used when the component view is controlled.
* Must be a valid option from `views` list.
*/
view: PropTypes.oneOf(['day', 'month', 'year']),
/**
* Define custom view renderers for each section.
* If `null`, the section will only have field editing.
* If `undefined`, internally defined view will be the used.
*/
viewRenderers: PropTypes.shape({
day: PropTypes.func,
month: PropTypes.func,
year: PropTypes.func
}),
/**
* Available views.
*/
views: PropTypes.arrayOf(PropTypes.oneOf(['day', 'month', 'year']).isRequired),
/**
* Years rendered per row.
* @default 4
*/
yearsPerRow: PropTypes.oneOf([3, 4])
};
const _excluded$1 = ["props", "getOpenDialogAriaText"];
/**
* Hook managing all the single-date mobile pickers:
* - MobileDatePicker
* - MobileDateTimePicker
* - MobileTimePicker
*/
const useMobilePicker = _ref => {
var _innerSlotProps$toolb, _innerSlotProps$toolb2, _slots$layout;
let {
props,
getOpenDialogAriaText
} = _ref,
pickerParams = _objectWithoutPropertiesLoose$1(_ref, _excluded$1);
const {
slots,
slotProps: innerSlotProps,
className,
sx,
format,
formatDensity,
timezone,
name,
label,
inputRef,
readOnly,
disabled,
localeText
} = props;
const utils = useUtils();
const internalInputRef = React.useRef(null);
const labelId = useId();
const isToolbarHidden = (_innerSlotProps$toolb = innerSlotProps == null || (_innerSlotProps$toolb2 = innerSlotProps.toolbar) == null ? void 0 : _innerSlotProps$toolb2.hidden) != null ? _innerSlotProps$toolb : false;
const {
open,
actions,
layoutProps,
renderCurrentView,
fieldProps: pickerFieldProps
} = usePicker(_extends({}, pickerParams, {
props,
inputRef: internalInputRef,
autoFocusView: true,
additionalViewProps: {},
wrapperVariant: 'mobile'
}));
const Field = slots.field;
const fieldProps = useSlotProps({
elementType: Field,
externalSlotProps: innerSlotProps == null ? void 0 : innerSlotProps.field,
additionalProps: _extends({}, pickerFieldProps, isToolbarHidden && {
id: labelId
}, !(disabled || readOnly) && {
onClick: actions.onOpen,
onKeyDown: onSpaceOrEnter(actions.onOpen)
}, {
readOnly: readOnly != null ? readOnly : true,
disabled,
className,
sx,
format,
formatDensity,
timezone,
label,
name
}),
ownerState: props
});
// TODO: Move to `useSlotProps` when https://github.com/mui/material-ui/pull/35088 will be merged
fieldProps.inputProps = _extends({}, fieldProps.inputProps, {
'aria-label': getOpenDialogAriaText(pickerFieldProps.value, utils)
});
const slotsForField = _extends({
textField: slots.textField
}, fieldProps.slots);
const Layout = (_slots$layout = slots.layout) != null ? _slots$layout : PickersLayout;
const handleInputRef = useForkRef(internalInputRef, fieldProps.inputRef, inputRef);
let labelledById = labelId;
if (isToolbarHidden) {
if (label) {
labelledById = `${labelId}-label`;
} else {
labelledById = undefined;
}
}
const slotProps = _extends({}, innerSlotProps, {
toolbar: _extends({}, innerSlotProps == null ? void 0 : innerSlotProps.toolbar, {
titleId: labelId
}),
mobilePaper: _extends({
'aria-labelledby': labelledById
}, innerSlotProps == null ? void 0 : innerSlotProps.mobilePaper)
});
const renderPicker = () => /*#__PURE__*/jsxs(LocalizationProvider, {
localeText: localeText,
children: [/*#__PURE__*/jsx(Field, _extends({}, fieldProps, {
slots: slotsForField,
slotProps: slotProps,
inputRef: handleInputRef
})), /*#__PURE__*/jsx(PickersModalDialog, _extends({}, actions, {
open: open,
slots: slots,
slotProps: slotProps,
children: /*#__PURE__*/jsx(Layout, _extends({}, layoutProps, slotProps == null ? void 0 : slotProps.layout, {
slots: slots,
slotProps: slotProps,
children: renderCurrentView()
}))
}))]
});
return {
renderPicker
};
};
/**
* Demos:
*
* - [DatePicker](https://mui.com/x/react-date-pickers/date-picker/)
* - [Validation](https://mui.com/x/react-date-pickers/validation/)
*
* API:
*
* - [MobileDatePicker API](https://mui.com/x/api/date-pickers/mobile-date-picker/)
*/
const MobileDatePicker = /*#__PURE__*/React.forwardRef(function MobileDatePicker(inProps, ref) {
var _defaultizedProps$slo2, _props$localeText$ope, _props$localeText;
const localeText = useLocaleText();
const utils = useUtils();
// Props with the default values common to all date pickers
const defaultizedProps = useDatePickerDefaultizedProps(inProps, 'MuiMobileDatePicker');
const viewRenderers = _extends({
day: renderDateViewCalendar,
month: renderDateViewCalendar,
year: renderDateViewCalendar
}, defaultizedProps.viewRenderers);
// Props with the default values specific to the mobile variant
const props = _extends({}, defaultizedProps, {
viewRenderers,
format: resolveDateFormat(utils, defaultizedProps, false),
slots: _extends({
field: DateField
}, defaultizedProps.slots),
slotProps: _extends({}, defaultizedProps.slotProps, {
field: ownerState => {
var _defaultizedProps$slo;
return _extends({}, resolveComponentProps((_defaultizedProps$slo = defaultizedProps.slotProps) == null ? void 0 : _defaultizedProps$slo.field, ownerState), extractValidationProps(defaultizedProps), {
ref
});
},
toolbar: _extends({
hidden: false
}, (_defaultizedProps$slo2 = defaultizedProps.slotProps) == null ? void 0 : _defaultizedProps$slo2.toolbar)
})
});
const {
renderPicker
} = useMobilePicker({
props,
valueManager: singleItemValueManager,
valueType: 'date',
getOpenDialogAriaText: (_props$localeText$ope = (_props$localeText = props.localeText) == null ? void 0 : _props$localeText.openDatePickerDialogue) != null ? _props$localeText$ope : localeText.openDatePickerDialogue,
validator: validateDate
});
return renderPicker();
});
MobileDatePicker.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* If `true`, the main element is focused during the first mount.
* This main element is:
* - the element chosen by the visible view if any (i.e: the selected day on the `day` view).
* - the `input` element if there is a field rendered.
*/
autoFocus: PropTypes.bool,
/**
* Class name applied to the root element.
*/
className: PropTypes.string,
/**
* If `true`, the popover or modal will close after submitting the full date.
* @default `true` for desktop, `false` for mobile (based on the chosen wrapper and `desktopModeMediaQuery` prop).
*/
closeOnSelect: PropTypes.bool,
/**
* Overridable components.
* @default {}
* @deprecated Please use `slots`.
*/
components: PropTypes.object,
/**
* The props used for each component slot.
* @default {}
* @deprecated Please use `slotProps`.
*/
componentsProps: PropTypes.object,
/**
* Formats the day of week displayed in the calendar header.
* @param {string} day The day of week provided by the adapter. Deprecated, will be removed in v7: Use `date` instead.
* @param {TDate} date The date of the day of week provided by the adapter.
* @returns {string} The name to display.
* @default (_day: string, date: TDate) => adapter.format(date, 'weekdayShort').charAt(0).toUpperCase()
*/
dayOfWeekFormatter: PropTypes.func,
/**
* Default calendar month displayed when `value` and `defaultValue` are empty.
* @deprecated Consider using `referenceDate` instead.
*/
defaultCalendarMonth: PropTypes.any,
/**
* The default value.
* Used when the component is not controlled.
*/
defaultValue: PropTypes.any,
/**
* If `true`, the picker and text field are disabled.
* @default false
*/
disabled: PropTypes.bool,
/**
* If `true`, disable values after the current date for date components, time for time components and both for date time components.
* @default false
*/
disableFuture: PropTypes.bool,
/**
* If `true`, today's date is rendering without highlighting with circle.
* @default false
*/
disableHighlightToday: PropTypes.bool,
/**
* If `true`, the open picker button will not be rendered (renders only the field).
* @default false
*/
disableOpenPicker: PropTypes.bool,
/**
* If `true`, disable values before the current date for date components, time for time components and both for date time components.
* @default false
*/
disablePast: PropTypes.bool,
/**
* If `true`, the week number will be display in the calendar.
*/
displayWeekNumber: PropTypes.bool,
/**
* Calendar will show more weeks in order to match this value.
* Put it to 6 for having fix number of week in Gregorian calendars
* @default undefined
*/
fixedWeekNumber: PropTypes.number,
/**
* Format of the date when rendered in the input(s).
* Defaults to localized format based on the used `views`.
*/
format: PropTypes.string,
/**
* Density of the format when rendered in the input.
* Setting `formatDensity` to `"spacious"` will add a space before and after each `/`, `-` and `.` character.
* @default "dense"
*/
formatDensity: PropTypes.oneOf(['dense', 'spacious']),
/**
* Pass a ref to the `input` element.
*/
inputRef: refType$1,
/**
* The label content.
*/
label: PropTypes.node,
/**
* If `true`, calls `renderLoading` instead of rendering the day calendar.
* Can be used to preload information and show it in calendar.
* @default false
*/
loading: PropTypes.bool,
/**
* Locale for components texts.
* Allows overriding texts coming from `LocalizationProvider` and `theme`.
*/
localeText: PropTypes.object,
/**
* Maximal selectable date.
*/
maxDate: PropTypes.any,
/**
* Minimal selectable date.
*/
minDate: PropTypes.any,
/**
* Months rendered per row.
* @default 3
*/
monthsPerRow: PropTypes.oneOf([3, 4]),
/**
* Name attribute used by the `input` element in the Field.
*/
name: PropTypes.string,
/**
* Callback fired when the value is accepted.
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @param {TValue} value The value that was just accepted.
*/
onAccept: PropTypes.func,
/**
* Callback fired when the value changes.
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value.
* @param {TValue} value The new value.
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
*/
onChange: PropTypes.func,
/**
* Callback fired when the popup requests to be closed.
* Use in controlled mode (see `open`).
*/
onClose: PropTypes.func,
/**
* Callback fired when the error associated to the current value changes.
* If the error has a non-null value, then the `TextField` will be rendered in `error` state.
*
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value.
* @param {TError} error The new error describing why the current value is not valid.
* @param {TValue} value The value associated to the error.
*/
onError: PropTypes.func,
/**
* Callback fired on month change.
* @template TDate
* @param {TDate} month The new month.
*/
onMonthChange: PropTypes.func,
/**
* Callback fired when the popup requests to be opened.
* Use in controlled mode (see `open`).
*/
onOpen: PropTypes.func,
/**
* Callback fired when the selected sections change.
* @param {FieldSelectedSections} newValue The new selected sections.
*/
onSelectedSectionsChange: PropTypes.func,
/**
* Callback fired on view change.
* @template TView
* @param {TView} view The new view.
*/
onViewChange: PropTypes.func,
/**
* Callback fired on year change.
* @template TDate
* @param {TDate} year The new year.
*/
onYearChange: PropTypes.func,
/**
* Control the popup or dialog open state.
* @default false
*/
open: PropTypes.bool,
/**
* The default visible view.
* Used when the component view is not controlled.
* Must be a valid option from `views` list.
*/
openTo: PropTypes.oneOf(['day', 'month', 'year']),
/**
* Force rendering in particular orientation.
*/
orientation: PropTypes.oneOf(['landscape', 'portrait']),
readOnly: PropTypes.bool,
/**
* If `true`, disable heavy animations.
* @default `@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13
*/
reduceAnimations: PropTypes.bool,
/**
* The date used to generate the new value when both `value` and `defaultValue` are empty.
* @default The closest valid date-time using the validation props, except callbacks like `shouldDisable<...>`.
*/
referenceDate: PropTypes.any,
/**
* Component displaying when passed `loading` true.
* @returns {React.ReactNode} The node to render when loading.
* @default () => <span data-mui-test="loading-progress">...</span>
*/
renderLoading: PropTypes.func,
/**
* The currently selected sections.
* This prop accept four formats:
* 1. If a number is provided, the section at this index will be selected.
* 2. If an object with a `startIndex` and `endIndex` properties are provided, the sections between those two indexes will be selected.
* 3. If a string of type `FieldSectionType` is provided, the first section with that name will be selected.
* 4. If `null` is provided, no section will be selected
* If not provided, the selected sections will be handled internally.
*/
selectedSections: PropTypes.oneOfType([PropTypes.oneOf(['all', 'day', 'hours', 'meridiem', 'minutes', 'month', 'seconds', 'weekDay', 'year']), PropTypes.number, PropTypes.shape({
endIndex: PropTypes.number.isRequired,
startIndex: PropTypes.number.isRequired
})]),
/**
* Disable specific date.
*
* Warning: This function can be called multiple times (e.g. when rendering date calendar, checking if focus can be moved to a certain date, etc.). Expensive computations can impact performance.
*
* @template TDate
* @param {TDate} day The date to test.
* @returns {boolean} If `true` the date will be disabled.
*/
shouldDisableDate: PropTypes.func,
/**
* Disable specific month.
* @template TDate
* @param {TDate} month The month to test.
* @returns {boolean} If `true`, the month will be disabled.
*/
shouldDisableMonth: PropTypes.func,
/**
* Disable specific year.
* @template TDate
* @param {TDate} year The year to test.
* @returns {boolean} If `true`, the year will be disabled.
*/
shouldDisableYear: PropTypes.func,
/**
* If `true`, days outside the current month are rendered:
*
* - if `fixedWeekNumber` is defined, renders days to have the weeks requested.
*
* - if `fixedWeekNumber` is not defined, renders day to fill the first and last week of the current month.
*
* - ignored if `calendars` equals more than `1` on range pickers.
* @default false
*/
showDaysOutsideCurrentMonth: PropTypes.bool,
/**
* The props used for each component slot.
* @default {}
*/
slotProps: PropTypes.object,
/**
* Overridable component slots.
* @default {}
*/
slots: PropTypes.object,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
/**
* Choose which timezone to use for the value.
* Example: "default", "system", "UTC", "America/New_York".
* If you pass values from other timezones to some props, they will be converted to this timezone before being used.
* @see See the {@link https://mui.com/x/react-date-pickers/timezone/ timezones documention} for more details.
* @default The timezone of the `value` or `defaultValue` prop is defined, 'default' otherwise.
*/
timezone: PropTypes.string,
/**
* The selected value.
* Used when the component is controlled.
*/
value: PropTypes.any,
/**
* The visible view.
* Used when the component view is controlled.
* Must be a valid option from `views` list.
*/
view: PropTypes.oneOf(['day', 'month', 'year']),
/**
* Define custom view renderers for each section.
* If `null`, the section will only have field editing.
* If `undefined`, internally defined view will be the used.
*/
viewRenderers: PropTypes.shape({
day: PropTypes.func,
month: PropTypes.func,
year: PropTypes.func
}),
/**
* Available views.
*/
views: PropTypes.arrayOf(PropTypes.oneOf(['day', 'month', 'year']).isRequired),
/**
* Years rendered per row.
* @default 3
*/
yearsPerRow: PropTypes.oneOf([3, 4])
};
const _excluded = ["desktopModeMediaQuery"];
/**
* Demos:
*
* - [DatePicker](https://mui.com/x/react-date-pickers/date-picker/)
* - [Validation](https://mui.com/x/react-date-pickers/validation/)
*
* API:
*
* - [DatePicker API](https://mui.com/x/api/date-pickers/date-picker/)
*/
const DatePicker = /*#__PURE__*/React.forwardRef(function DatePicker(inProps, ref) {
const props = useThemeProps({
props: inProps,
name: 'MuiDatePicker'
});
const {
desktopModeMediaQuery = DEFAULT_DESKTOP_MODE_MEDIA_QUERY
} = props,
other = _objectWithoutPropertiesLoose$1(props, _excluded);
// defaults to `true` in environments where `window.matchMedia` would not be available (i.e. test/jsdom)
const isDesktop = useMediaQuery(desktopModeMediaQuery, {
defaultMatches: true
});
if (isDesktop) {
return /*#__PURE__*/jsx(DesktopDatePicker, _extends({
ref: ref
}, other));
}
return /*#__PURE__*/jsx(MobileDatePicker, _extends({
ref: ref
}, other));
});
process.env.NODE_ENV !== "production" ? DatePicker.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* If `true`, the main element is focused during the first mount.
* This main element is:
* - the element chosen by the visible view if any (i.e: the selected day on the `day` view).
* - the `input` element if there is a field rendered.
*/
autoFocus: PropTypes.bool,
/**
* Class name applied to the root element.
*/
className: PropTypes.string,
/**
* If `true`, the popover or modal will close after submitting the full date.
* @default `true` for desktop, `false` for mobile (based on the chosen wrapper and `desktopModeMediaQuery` prop).
*/
closeOnSelect: PropTypes.bool,
/**
* Overridable components.
* @default {}
* @deprecated Please use `slots`.
*/
components: PropTypes.object,
/**
* The props used for each component slot.
* @default {}
* @deprecated Please use `slotProps`.
*/
componentsProps: PropTypes.object,
/**
* Formats the day of week displayed in the calendar header.
* @param {string} day The day of week provided by the adapter. Deprecated, will be removed in v7: Use `date` instead.
* @param {TDate} date The date of the day of week provided by the adapter.
* @returns {string} The name to display.
* @default (_day: string, date: TDate) => adapter.format(date, 'weekdayShort').charAt(0).toUpperCase()
*/
dayOfWeekFormatter: PropTypes.func,
/**
* Default calendar month displayed when `value` and `defaultValue` are empty.
* @deprecated Consider using `referenceDate` instead.
*/
defaultCalendarMonth: PropTypes.any,
/**
* The default value.
* Used when the component is not controlled.
*/
defaultValue: PropTypes.any,
/**
* CSS media query when `Mobile` mode will be changed to `Desktop`.
* @default '@media (pointer: fine)'
* @example '@media (min-width: 720px)' or theme.breakpoints.up("sm")
*/
desktopModeMediaQuery: PropTypes.string,
/**
* If `true`, the picker and text field are disabled.
* @default false
*/
disabled: PropTypes.bool,
/**
* If `true`, disable values after the current date for date components, time for time components and both for date time components.
* @default false
*/
disableFuture: PropTypes.bool,
/**
* If `true`, today's date is rendering without highlighting with circle.
* @default false
*/
disableHighlightToday: PropTypes.bool,
/**
* If `true`, the open picker button will not be rendered (renders only the field).
* @default false
*/
disableOpenPicker: PropTypes.bool,
/**
* If `true`, disable values before the current date for date components, time for time components and both for date time components.
* @default false
*/
disablePast: PropTypes.bool,
/**
* If `true`, the week number will be display in the calendar.
*/
displayWeekNumber: PropTypes.bool,
/**
* Calendar will show more weeks in order to match this value.
* Put it to 6 for having fix number of week in Gregorian calendars
* @default undefined
*/
fixedWeekNumber: PropTypes.number,
/**
* Format of the date when rendered in the input(s).
* Defaults to localized format based on the used `views`.
*/
format: PropTypes.string,
/**
* Density of the format when rendered in the input.
* Setting `formatDensity` to `"spacious"` will add a space before and after each `/`, `-` and `.` character.
* @default "dense"
*/
formatDensity: PropTypes.oneOf(['dense', 'spacious']),
/**
* Pass a ref to the `input` element.
*/
inputRef: refType$1,
/**
* The label content.
*/
label: PropTypes.node,
/**
* If `true`, calls `renderLoading` instead of rendering the day calendar.
* Can be used to preload information and show it in calendar.
* @default false
*/
loading: PropTypes.bool,
/**
* Locale for components texts.
* Allows overriding texts coming from `LocalizationProvider` and `theme`.
*/
localeText: PropTypes.object,
/**
* Maximal selectable date.
*/
maxDate: PropTypes.any,
/**
* Minimal selectable date.
*/
minDate: PropTypes.any,
/**
* Months rendered per row.
* @default 3
*/
monthsPerRow: PropTypes.oneOf([3, 4]),
/**
* Name attribute used by the `input` element in the Field.
*/
name: PropTypes.string,
/**
* Callback fired when the value is accepted.
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @param {TValue} value The value that was just accepted.
*/
onAccept: PropTypes.func,
/**
* Callback fired when the value changes.
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value.
* @param {TValue} value The new value.
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
*/
onChange: PropTypes.func,
/**
* Callback fired when the popup requests to be closed.
* Use in controlled mode (see `open`).
*/
onClose: PropTypes.func,
/**
* Callback fired when the error associated to the current value changes.
* If the error has a non-null value, then the `TextField` will be rendered in `error` state.
*
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
* @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value.
* @param {TError} error The new error describing why the current value is not valid.
* @param {TValue} value The value associated to the error.
*/
onError: PropTypes.func,
/**
* Callback fired on month change.
* @template TDate
* @param {TDate} month The new month.
*/
onMonthChange: PropTypes.func,
/**
* Callback fired when the popup requests to be opened.
* Use in controlled mode (see `open`).
*/
onOpen: PropTypes.func,
/**
* Callback fired when the selected sections change.
* @param {FieldSelectedSections} newValue The new selected sections.
*/
onSelectedSectionsChange: PropTypes.func,
/**
* Callback fired on view change.
* @template TView
* @param {TView} view The new view.
*/
onViewChange: PropTypes.func,
/**
* Callback fired on year change.
* @template TDate
* @param {TDate} year The new year.
*/
onYearChange: PropTypes.func,
/**
* Control the popup or dialog open state.
* @default false
*/
open: PropTypes.bool,
/**
* The default visible view.
* Used when the component view is not controlled.
* Must be a valid option from `views` list.
*/
openTo: PropTypes.oneOf(['day', 'month', 'year']),
/**
* Force rendering in particular orientation.
*/
orientation: PropTypes.oneOf(['landscape', 'portrait']),
readOnly: PropTypes.bool,
/**
* If `true`, disable heavy animations.
* @default `@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13
*/
reduceAnimations: PropTypes.bool,
/**
* The date used to generate the new value when both `value` and `defaultValue` are empty.
* @default The closest valid date-time using the validation props, except callbacks like `shouldDisable<...>`.
*/
referenceDate: PropTypes.any,
/**
* Component displaying when passed `loading` true.
* @returns {React.ReactNode} The node to render when loading.
* @default () => <span data-mui-test="loading-progress">...</span>
*/
renderLoading: PropTypes.func,
/**
* The currently selected sections.
* This prop accept four formats:
* 1. If a number is provided, the section at this index will be selected.
* 2. If an object with a `startIndex` and `endIndex` properties are provided, the sections between those two indexes will be selected.
* 3. If a string of type `FieldSectionType` is provided, the first section with that name will be selected.
* 4. If `null` is provided, no section will be selected
* If not provided, the selected sections will be handled internally.
*/
selectedSections: PropTypes.oneOfType([PropTypes.oneOf(['all', 'day', 'hours', 'meridiem', 'minutes', 'month', 'seconds', 'weekDay', 'year']), PropTypes.number, PropTypes.shape({
endIndex: PropTypes.number.isRequired,
startIndex: PropTypes.number.isRequired
})]),
/**
* Disable specific date.
*
* Warning: This function can be called multiple times (e.g. when rendering date calendar, checking if focus can be moved to a certain date, etc.). Expensive computations can impact performance.
*
* @template TDate
* @param {TDate} day The date to test.
* @returns {boolean} If `true` the date will be disabled.
*/
shouldDisableDate: PropTypes.func,
/**
* Disable specific month.
* @template TDate
* @param {TDate} month The month to test.
* @returns {boolean} If `true`, the month will be disabled.
*/
shouldDisableMonth: PropTypes.func,
/**
* Disable specific year.
* @template TDate
* @param {TDate} year The year to test.
* @returns {boolean} If `true`, the year will be disabled.
*/
shouldDisableYear: PropTypes.func,
/**
* If `true`, days outside the current month are rendered:
*
* - if `fixedWeekNumber` is defined, renders days to have the weeks requested.
*
* - if `fixedWeekNumber` is not defined, renders day to fill the first and last week of the current month.
*
* - ignored if `calendars` equals more than `1` on range pickers.
* @default false
*/
showDaysOutsideCurrentMonth: PropTypes.bool,
/**
* The props used for each component slot.
* @default {}
*/
slotProps: PropTypes.object,
/**
* Overridable component slots.
* @default {}
*/
slots: PropTypes.object,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
/**
* Choose which timezone to use for the value.
* Example: "default", "system", "UTC", "America/New_York".
* If you pass values from other timezones to some props, they will be converted to this timezone before being used.
* @see See the {@link https://mui.com/x/react-date-pickers/timezone/ timezones documention} for more details.
* @default The timezone of the `value` or `defaultValue` prop is defined, 'default' otherwise.
*/
timezone: PropTypes.string,
/**
* The selected value.
* Used when the component is controlled.
*/
value: PropTypes.any,
/**
* The visible view.
* Used when the component view is controlled.
* Must be a valid option from `views` list.
*/
view: PropTypes.oneOf(['day', 'month', 'year']),
/**
* Define custom view renderers for each section.
* If `null`, the section will only have field editing.
* If `undefined`, internally defined view will be the used.
*/
viewRenderers: PropTypes.shape({
day: PropTypes.func,
month: PropTypes.func,
year: PropTypes.func
}),
/**
* Available views.
*/
views: PropTypes.arrayOf(PropTypes.oneOf(['day', 'month', 'year']).isRequired),
/**
* Years rendered per row.
* @default 4 on desktop, 3 on mobile
*/
yearsPerRow: PropTypes.oneOf([3, 4])
} : void 0;
/**
* Create the React Context
*/ const DndContext = createContext({
dragDropManager: undefined
});
/**
* Adapted from React: https://github.com/facebook/react/blob/master/packages/shared/formatProdErrorMessage.js
*
* Do not require this module directly! Use normal throw error calls. These messages will be replaced with error codes
* during build.
* @param {number} code
*/
function formatProdErrorMessage(code) {
return "Minified Redux error #" + code + "; visit https://redux.js.org/Errors?code=" + code + " for the full message or " + 'use the non-minified dev environment for full errors. ';
}
// Inlined version of the `symbol-observable` polyfill
var $$observable = (function () {
return typeof Symbol === 'function' && Symbol.observable || '@@observable';
})();
/**
* These are private action types reserved by Redux.
* For any unknown actions, you must return the current state.
* If the current state is undefined, you must return the initial state.
* Do not reference these action types directly in your code.
*/
var randomString = function randomString() {
return Math.random().toString(36).substring(7).split('').join('.');
};
var ActionTypes = {
INIT: "@@redux/INIT" + randomString(),
REPLACE: "@@redux/REPLACE" + randomString(),
PROBE_UNKNOWN_ACTION: function PROBE_UNKNOWN_ACTION() {
return "@@redux/PROBE_UNKNOWN_ACTION" + randomString();
}
};
/**
* @param {any} obj The object to inspect.
* @returns {boolean} True if the argument appears to be a plain object.
*/
function isPlainObject(obj) {
if (typeof obj !== 'object' || obj === null) return false;
var proto = obj;
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto);
}
return Object.getPrototypeOf(obj) === proto;
}
// Inlined / shortened version of `kindOf` from https://github.com/jonschlinkert/kind-of
function miniKindOf(val) {
if (val === void 0) return 'undefined';
if (val === null) return 'null';
var type = typeof val;
switch (type) {
case 'boolean':
case 'string':
case 'number':
case 'symbol':
case 'function':
{
return type;
}
}
if (Array.isArray(val)) return 'array';
if (isDate(val)) return 'date';
if (isError(val)) return 'error';
var constructorName = ctorName(val);
switch (constructorName) {
case 'Symbol':
case 'Promise':
case 'WeakMap':
case 'WeakSet':
case 'Map':
case 'Set':
return constructorName;
} // other
return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
}
function ctorName(val) {
return typeof val.constructor === 'function' ? val.constructor.name : null;
}
function isError(val) {
return val instanceof Error || typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number';
}
function isDate(val) {
if (val instanceof Date) return true;
return typeof val.toDateString === 'function' && typeof val.getDate === 'function' && typeof val.setDate === 'function';
}
function kindOf(val) {
var typeOfVal = typeof val;
if (process.env.NODE_ENV !== 'production') {
typeOfVal = miniKindOf(val);
}
return typeOfVal;
}
/**
* @deprecated
*
* **We recommend using the `configureStore` method
* of the `@reduxjs/toolkit` package**, which replaces `createStore`.
*
* Redux Toolkit is our recommended approach for writing Redux logic today,
* including store setup, reducers, data fetching, and more.
*
* **For more details, please read this Redux docs page:**
* **https://redux.js.org/introduction/why-rtk-is-redux-today**
*
* `configureStore` from Redux Toolkit is an improved version of `createStore` that
* simplifies setup and helps avoid common bugs.
*
* You should not be using the `redux` core package by itself today, except for learning purposes.
* The `createStore` method from the core `redux` package will not be removed, but we encourage
* all users to migrate to using Redux Toolkit for all Redux code.
*
* If you want to use `createStore` without this visual deprecation warning, use
* the `legacy_createStore` import instead:
*
* `import { legacy_createStore as createStore} from 'redux'`
*
*/
function createStore(reducer, preloadedState, enhancer) {
var _ref2;
if (typeof preloadedState === 'function' && typeof enhancer === 'function' || typeof enhancer === 'function' && typeof arguments[3] === 'function') {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(0) : 'It looks like you are passing several store enhancers to ' + 'createStore(). This is not supported. Instead, compose them ' + 'together to a single function. See https://redux.js.org/tutorials/fundamentals/part-4-store#creating-a-store-with-enhancers for an example.');
}
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState;
preloadedState = undefined;
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(1) : "Expected the enhancer to be a function. Instead, received: '" + kindOf(enhancer) + "'");
}
return enhancer(createStore)(reducer, preloadedState);
}
if (typeof reducer !== 'function') {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(2) : "Expected the root reducer to be a function. Instead, received: '" + kindOf(reducer) + "'");
}
var currentReducer = reducer;
var currentState = preloadedState;
var currentListeners = [];
var nextListeners = currentListeners;
var isDispatching = false;
/**
* This makes a shallow copy of currentListeners so we can use
* nextListeners as a temporary list while dispatching.
*
* This prevents any bugs around consumers calling
* subscribe/unsubscribe in the middle of a dispatch.
*/
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice();
}
}
/**
* Reads the state tree managed by the store.
*
* @returns {any} The current state tree of your application.
*/
function getState() {
if (isDispatching) {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(3) : 'You may not call store.getState() while the reducer is executing. ' + 'The reducer has already received the state as an argument. ' + 'Pass it down from the top reducer instead of reading it from the store.');
}
return currentState;
}
/**
* Adds a change listener. It will be called any time an action is dispatched,
* and some part of the state tree may potentially have changed. You may then
* call `getState()` to read the current state tree inside the callback.
*
* You may call `dispatch()` from a change listener, with the following
* caveats:
*
* 1. The subscriptions are snapshotted just before every `dispatch()` call.
* If you subscribe or unsubscribe while the listeners are being invoked, this
* will not have any effect on the `dispatch()` that is currently in progress.
* However, the next `dispatch()` call, whether nested or not, will use a more
* recent snapshot of the subscription list.
*
* 2. The listener should not expect to see all state changes, as the state
* might have been updated multiple times during a nested `dispatch()` before
* the listener is called. It is, however, guaranteed that all subscribers
* registered before the `dispatch()` started will be called with the latest
* state by the time it exits.
*
* @param {Function} listener A callback to be invoked on every dispatch.
* @returns {Function} A function to remove this change listener.
*/
function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(4) : "Expected the listener to be a function. Instead, received: '" + kindOf(listener) + "'");
}
if (isDispatching) {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(5) : 'You may not call store.subscribe() while the reducer is executing. ' + 'If you would like to be notified after the store has been updated, subscribe from a ' + 'component and invoke store.getState() in the callback to access the latest state. ' + 'See https://redux.js.org/api/store#subscribelistener for more details.');
}
var isSubscribed = true;
ensureCanMutateNextListeners();
nextListeners.push(listener);
return function unsubscribe() {
if (!isSubscribed) {
return;
}
if (isDispatching) {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(6) : 'You may not unsubscribe from a store listener while the reducer is executing. ' + 'See https://redux.js.org/api/store#subscribelistener for more details.');
}
isSubscribed = false;
ensureCanMutateNextListeners();
var index = nextListeners.indexOf(listener);
nextListeners.splice(index, 1);
currentListeners = null;
};
}
/**
* Dispatches an action. It is the only way to trigger a state change.
*
* The `reducer` function, used to create the store, will be called with the
* current state tree and the given `action`. Its return value will
* be considered the **next** state of the tree, and the change listeners
* will be notified.
*
* The base implementation only supports plain object actions. If you want to
* dispatch a Promise, an Observable, a thunk, or something else, you need to
* wrap your store creating function into the corresponding middleware. For
* example, see the documentation for the `redux-thunk` package. Even the
* middleware will eventually dispatch plain object actions using this method.
*
* @param {Object} action A plain object representing “what changed”. It is
* a good idea to keep actions serializable so you can record and replay user
* sessions, or use the time travelling `redux-devtools`. An action must have
* a `type` property which may not be `undefined`. It is a good idea to use
* string constants for action types.
*
* @returns {Object} For convenience, the same action object you dispatched.
*
* Note that, if you use a custom middleware, it may wrap `dispatch()` to
* return something else (for example, a Promise you can await).
*/
function dispatch(action) {
if (!isPlainObject(action)) {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(7) : "Actions must be plain objects. Instead, the actual type was: '" + kindOf(action) + "'. You may need to add middleware to your store setup to handle dispatching other values, such as 'redux-thunk' to handle dispatching functions. See https://redux.js.org/tutorials/fundamentals/part-4-store#middleware and https://redux.js.org/tutorials/fundamentals/part-6-async-logic#using-the-redux-thunk-middleware for examples.");
}
if (typeof action.type === 'undefined') {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(8) : 'Actions may not have an undefined "type" property. You may have misspelled an action type string constant.');
}
if (isDispatching) {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(9) : 'Reducers may not dispatch actions.');
}
try {
isDispatching = true;
currentState = currentReducer(currentState, action);
} finally {
isDispatching = false;
}
var listeners = currentListeners = nextListeners;
for (var i = 0; i < listeners.length; i++) {
var listener = listeners[i];
listener();
}
return action;
}
/**
* Replaces the reducer currently used by the store to calculate the state.
*
* You might need this if your app implements code splitting and you want to
* load some of the reducers dynamically. You might also need this if you
* implement a hot reloading mechanism for Redux.
*
* @param {Function} nextReducer The reducer for the store to use instead.
* @returns {void}
*/
function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(10) : "Expected the nextReducer to be a function. Instead, received: '" + kindOf(nextReducer));
}
currentReducer = nextReducer; // This action has a similiar effect to ActionTypes.INIT.
// Any reducers that existed in both the new and old rootReducer
// will receive the previous state. This effectively populates
// the new state tree with any relevant data from the old one.
dispatch({
type: ActionTypes.REPLACE
});
}
/**
* Interoperability point for observable/reactive libraries.
* @returns {observable} A minimal observable of state changes.
* For more information, see the observable proposal:
* https://github.com/tc39/proposal-observable
*/
function observable() {
var _ref;
var outerSubscribe = subscribe;
return _ref = {
/**
* The minimal observable subscription method.
* @param {Object} observer Any object that can be used as an observer.
* The observer object should have a `next` method.
* @returns {subscription} An object with an `unsubscribe` method that can
* be used to unsubscribe the observable from the store, and prevent further
* emission of values from the observable.
*/
subscribe: function subscribe(observer) {
if (typeof observer !== 'object' || observer === null) {
throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(11) : "Expected the observer to be an object. Instead, received: '" + kindOf(observer) + "'");
}
function observeState() {
if (observer.next) {
observer.next(getState());
}
}
observeState();
var unsubscribe = outerSubscribe(observeState);
return {
unsubscribe: unsubscribe
};
}
}, _ref[$$observable] = function () {
return this;
}, _ref;
} // When a store is created, an "INIT" action is dispatched so that every
// reducer returns their initial state. This effectively populates
// the initial state tree.
dispatch({
type: ActionTypes.INIT
});
return _ref2 = {
dispatch: dispatch,
subscribe: subscribe,
getState: getState,
replaceReducer: replaceReducer
}, _ref2[$$observable] = observable, _ref2;
}
/**
* Use invariant() to assert state which your program assumes to be true.
*
* Provide sprintf-style format (only %s is supported) and arguments
* to provide information about what broke and what you were
* expecting.
*
* The invariant message will be stripped in production, but the invariant
* will remain to ensure logic does not differ in production.
*/ function invariant(condition, format, ...args) {
if (isProduction()) {
if (format === undefined) {
throw new Error('invariant requires an error message argument');
}
}
if (!condition) {
let error;
if (format === undefined) {
error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
} else {
let argIndex = 0;
error = new Error(format.replace(/%s/g, function() {
return args[argIndex++];
}));
error.name = 'Invariant Violation';
}
error.framesToPop = 1 // we don't care about invariant's own frame
;
throw error;
}
}
function isProduction() {
return typeof process !== 'undefined' && process.env['NODE_ENV'] === 'production';
}
// cheap lodash replacements
/**
* drop-in replacement for _.get
* @param obj
* @param path
* @param defaultValue
*/ function get(obj, path, defaultValue) {
return path.split('.').reduce((a, c)=>a && a[c] ? a[c] : defaultValue || null
, obj);
}
/**
* drop-in replacement for _.without
*/ function without$1(items, item) {
return items.filter((i)=>i !== item
);
}
/**
* drop-in replacement for _.isString
* @param input
*/ function isObject(input) {
return typeof input === 'object';
}
/**
* replacement for _.xor
* @param itemsA
* @param itemsB
*/ function xor(itemsA, itemsB) {
const map = new Map();
const insertItem = (item)=>{
map.set(item, map.has(item) ? map.get(item) + 1 : 1);
};
itemsA.forEach(insertItem);
itemsB.forEach(insertItem);
const result = [];
map.forEach((count, key)=>{
if (count === 1) {
result.push(key);
}
});
return result;
}
/**
* replacement for _.intersection
* @param itemsA
* @param itemsB
*/ function intersection(itemsA, itemsB) {
return itemsA.filter((t)=>itemsB.indexOf(t) > -1
);
}
const INIT_COORDS = 'dnd-core/INIT_COORDS';
const BEGIN_DRAG = 'dnd-core/BEGIN_DRAG';
const PUBLISH_DRAG_SOURCE = 'dnd-core/PUBLISH_DRAG_SOURCE';
const HOVER = 'dnd-core/HOVER';
const DROP = 'dnd-core/DROP';
const END_DRAG = 'dnd-core/END_DRAG';
function setClientOffset(clientOffset, sourceClientOffset) {
return {
type: INIT_COORDS,
payload: {
sourceClientOffset: sourceClientOffset || null,
clientOffset: clientOffset || null
}
};
}
const ResetCoordinatesAction = {
type: INIT_COORDS,
payload: {
clientOffset: null,
sourceClientOffset: null
}
};
function createBeginDrag(manager) {
return function beginDrag(sourceIds = [], options = {
publishSource: true
}) {
const { publishSource =true , clientOffset , getSourceClientOffset , } = options;
const monitor = manager.getMonitor();
const registry = manager.getRegistry();
// Initialize the coordinates using the client offset
manager.dispatch(setClientOffset(clientOffset));
verifyInvariants$1(sourceIds, monitor, registry);
// Get the draggable source
const sourceId = getDraggableSource(sourceIds, monitor);
if (sourceId == null) {
manager.dispatch(ResetCoordinatesAction);
return;
}
// Get the source client offset
let sourceClientOffset = null;
if (clientOffset) {
if (!getSourceClientOffset) {
throw new Error('getSourceClientOffset must be defined');
}
verifyGetSourceClientOffsetIsFunction(getSourceClientOffset);
sourceClientOffset = getSourceClientOffset(sourceId);
}
// Initialize the full coordinates
manager.dispatch(setClientOffset(clientOffset, sourceClientOffset));
const source = registry.getSource(sourceId);
const item = source.beginDrag(monitor, sourceId);
// If source.beginDrag returns null, this is an indicator to cancel the drag
if (item == null) {
return undefined;
}
verifyItemIsObject(item);
registry.pinSource(sourceId);
const itemType = registry.getSourceType(sourceId);
return {
type: BEGIN_DRAG,
payload: {
itemType,
item,
sourceId,
clientOffset: clientOffset || null,
sourceClientOffset: sourceClientOffset || null,
isSourcePublic: !!publishSource
}
};
};
}
function verifyInvariants$1(sourceIds, monitor, registry) {
invariant(!monitor.isDragging(), 'Cannot call beginDrag while dragging.');
sourceIds.forEach(function(sourceId) {
invariant(registry.getSource(sourceId), 'Expected sourceIds to be registered.');
});
}
function verifyGetSourceClientOffsetIsFunction(getSourceClientOffset) {
invariant(typeof getSourceClientOffset === 'function', 'When clientOffset is provided, getSourceClientOffset must be a function.');
}
function verifyItemIsObject(item) {
invariant(isObject(item), 'Item must be an object.');
}
function getDraggableSource(sourceIds, monitor) {
let sourceId = null;
for(let i = sourceIds.length - 1; i >= 0; i--){
if (monitor.canDragSource(sourceIds[i])) {
sourceId = sourceIds[i];
break;
}
}
return sourceId;
}
function _defineProperty$4(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread$4(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_defineProperty$4(target, key, source[key]);
});
}
return target;
}
function createDrop(manager) {
return function drop(options = {}) {
const monitor = manager.getMonitor();
const registry = manager.getRegistry();
verifyInvariants(monitor);
const targetIds = getDroppableTargets(monitor);
// Multiple actions are dispatched here, which is why this doesn't return an action
targetIds.forEach((targetId, index)=>{
const dropResult = determineDropResult(targetId, index, registry, monitor);
const action = {
type: DROP,
payload: {
dropResult: _objectSpread$4({}, options, dropResult)
}
};
manager.dispatch(action);
});
};
}
function verifyInvariants(monitor) {
invariant(monitor.isDragging(), 'Cannot call drop while not dragging.');
invariant(!monitor.didDrop(), 'Cannot call drop twice during one drag operation.');
}
function determineDropResult(targetId, index, registry, monitor) {
const target = registry.getTarget(targetId);
let dropResult = target ? target.drop(monitor, targetId) : undefined;
verifyDropResultType(dropResult);
if (typeof dropResult === 'undefined') {
dropResult = index === 0 ? {} : monitor.getDropResult();
}
return dropResult;
}
function verifyDropResultType(dropResult) {
invariant(typeof dropResult === 'undefined' || isObject(dropResult), 'Drop result must either be an object or undefined.');
}
function getDroppableTargets(monitor) {
const targetIds = monitor.getTargetIds().filter(monitor.canDropOnTarget, monitor);
targetIds.reverse();
return targetIds;
}
function createEndDrag(manager) {
return function endDrag() {
const monitor = manager.getMonitor();
const registry = manager.getRegistry();
verifyIsDragging(monitor);
const sourceId = monitor.getSourceId();
if (sourceId != null) {
const source = registry.getSource(sourceId, true);
source.endDrag(monitor, sourceId);
registry.unpinSource();
}
return {
type: END_DRAG
};
};
}
function verifyIsDragging(monitor) {
invariant(monitor.isDragging(), 'Cannot call endDrag while not dragging.');
}
function matchesType(targetType, draggedItemType) {
if (draggedItemType === null) {
return targetType === null;
}
return Array.isArray(targetType) ? targetType.some((t)=>t === draggedItemType
) : targetType === draggedItemType;
}
function createHover(manager) {
return function hover(targetIdsArg, { clientOffset } = {}) {
verifyTargetIdsIsArray(targetIdsArg);
const targetIds = targetIdsArg.slice(0);
const monitor = manager.getMonitor();
const registry = manager.getRegistry();
const draggedItemType = monitor.getItemType();
removeNonMatchingTargetIds(targetIds, registry, draggedItemType);
checkInvariants(targetIds, monitor, registry);
hoverAllTargets(targetIds, monitor, registry);
return {
type: HOVER,
payload: {
targetIds,
clientOffset: clientOffset || null
}
};
};
}
function verifyTargetIdsIsArray(targetIdsArg) {
invariant(Array.isArray(targetIdsArg), 'Expected targetIds to be an array.');
}
function checkInvariants(targetIds, monitor, registry) {
invariant(monitor.isDragging(), 'Cannot call hover while not dragging.');
invariant(!monitor.didDrop(), 'Cannot call hover after drop.');
for(let i = 0; i < targetIds.length; i++){
const targetId = targetIds[i];
invariant(targetIds.lastIndexOf(targetId) === i, 'Expected targetIds to be unique in the passed array.');
const target = registry.getTarget(targetId);
invariant(target, 'Expected targetIds to be registered.');
}
}
function removeNonMatchingTargetIds(targetIds, registry, draggedItemType) {
// Remove those targetIds that don't match the targetType. This
// fixes shallow isOver which would only be non-shallow because of
// non-matching targets.
for(let i = targetIds.length - 1; i >= 0; i--){
const targetId = targetIds[i];
const targetType = registry.getTargetType(targetId);
if (!matchesType(targetType, draggedItemType)) {
targetIds.splice(i, 1);
}
}
}
function hoverAllTargets(targetIds, monitor, registry) {
// Finally call hover on all matching targets.
targetIds.forEach(function(targetId) {
const target = registry.getTarget(targetId);
target.hover(monitor, targetId);
});
}
function createPublishDragSource(manager) {
return function publishDragSource() {
const monitor = manager.getMonitor();
if (monitor.isDragging()) {
return {
type: PUBLISH_DRAG_SOURCE
};
}
return;
};
}
function createDragDropActions(manager) {
return {
beginDrag: createBeginDrag(manager),
publishDragSource: createPublishDragSource(manager),
hover: createHover(manager),
drop: createDrop(manager),
endDrag: createEndDrag(manager)
};
}
class DragDropManagerImpl {
receiveBackend(backend) {
this.backend = backend;
}
getMonitor() {
return this.monitor;
}
getBackend() {
return this.backend;
}
getRegistry() {
return this.monitor.registry;
}
getActions() {
/* eslint-disable-next-line @typescript-eslint/no-this-alias */ const manager = this;
const { dispatch } = this.store;
function bindActionCreator(actionCreator) {
return (...args)=>{
const action = actionCreator.apply(manager, args);
if (typeof action !== 'undefined') {
dispatch(action);
}
};
}
const actions = createDragDropActions(this);
return Object.keys(actions).reduce((boundActions, key)=>{
const action = actions[key];
boundActions[key] = bindActionCreator(action);
return boundActions;
}, {});
}
dispatch(action) {
this.store.dispatch(action);
}
constructor(store, monitor){
this.isSetUp = false;
this.handleRefCountChange = ()=>{
const shouldSetUp = this.store.getState().refCount > 0;
if (this.backend) {
if (shouldSetUp && !this.isSetUp) {
this.backend.setup();
this.isSetUp = true;
} else if (!shouldSetUp && this.isSetUp) {
this.backend.teardown();
this.isSetUp = false;
}
}
};
this.store = store;
this.monitor = monitor;
store.subscribe(this.handleRefCountChange);
}
}
/**
* Coordinate addition
* @param a The first coordinate
* @param b The second coordinate
*/ function add(a, b) {
return {
x: a.x + b.x,
y: a.y + b.y
};
}
/**
* Coordinate subtraction
* @param a The first coordinate
* @param b The second coordinate
*/ function subtract(a, b) {
return {
x: a.x - b.x,
y: a.y - b.y
};
}
/**
* Returns the cartesian distance of the drag source component's position, based on its position
* at the time when the current drag operation has started, and the movement difference.
*
* Returns null if no item is being dragged.
*
* @param state The offset state to compute from
*/ function getSourceClientOffset(state) {
const { clientOffset , initialClientOffset , initialSourceClientOffset } = state;
if (!clientOffset || !initialClientOffset || !initialSourceClientOffset) {
return null;
}
return subtract(add(clientOffset, initialSourceClientOffset), initialClientOffset);
}
/**
* Determines the x,y offset between the client offset and the initial client offset
*
* @param state The offset state to compute from
*/ function getDifferenceFromInitialOffset(state) {
const { clientOffset , initialClientOffset } = state;
if (!clientOffset || !initialClientOffset) {
return null;
}
return subtract(clientOffset, initialClientOffset);
}
const NONE = [];
const ALL = [];
NONE.__IS_NONE__ = true;
ALL.__IS_ALL__ = true;
/**
* Determines if the given handler IDs are dirty or not.
*
* @param dirtyIds The set of dirty handler ids
* @param handlerIds The set of handler ids to check
*/ function areDirty(dirtyIds, handlerIds) {
if (dirtyIds === NONE) {
return false;
}
if (dirtyIds === ALL || typeof handlerIds === 'undefined') {
return true;
}
const commonIds = intersection(handlerIds, dirtyIds);
return commonIds.length > 0;
}
class DragDropMonitorImpl {
subscribeToStateChange(listener, options = {}) {
const { handlerIds } = options;
invariant(typeof listener === 'function', 'listener must be a function.');
invariant(typeof handlerIds === 'undefined' || Array.isArray(handlerIds), 'handlerIds, when specified, must be an array of strings.');
let prevStateId = this.store.getState().stateId;
const handleChange = ()=>{
const state = this.store.getState();
const currentStateId = state.stateId;
try {
const canSkipListener = currentStateId === prevStateId || currentStateId === prevStateId + 1 && !areDirty(state.dirtyHandlerIds, handlerIds);
if (!canSkipListener) {
listener();
}
} finally{
prevStateId = currentStateId;
}
};
return this.store.subscribe(handleChange);
}
subscribeToOffsetChange(listener) {
invariant(typeof listener === 'function', 'listener must be a function.');
let previousState = this.store.getState().dragOffset;
const handleChange = ()=>{
const nextState = this.store.getState().dragOffset;
if (nextState === previousState) {
return;
}
previousState = nextState;
listener();
};
return this.store.subscribe(handleChange);
}
canDragSource(sourceId) {
if (!sourceId) {
return false;
}
const source = this.registry.getSource(sourceId);
invariant(source, `Expected to find a valid source. sourceId=${sourceId}`);
if (this.isDragging()) {
return false;
}
return source.canDrag(this, sourceId);
}
canDropOnTarget(targetId) {
// undefined on initial render
if (!targetId) {
return false;
}
const target = this.registry.getTarget(targetId);
invariant(target, `Expected to find a valid target. targetId=${targetId}`);
if (!this.isDragging() || this.didDrop()) {
return false;
}
const targetType = this.registry.getTargetType(targetId);
const draggedItemType = this.getItemType();
return matchesType(targetType, draggedItemType) && target.canDrop(this, targetId);
}
isDragging() {
return Boolean(this.getItemType());
}
isDraggingSource(sourceId) {
// undefined on initial render
if (!sourceId) {
return false;
}
const source = this.registry.getSource(sourceId, true);
invariant(source, `Expected to find a valid source. sourceId=${sourceId}`);
if (!this.isDragging() || !this.isSourcePublic()) {
return false;
}
const sourceType = this.registry.getSourceType(sourceId);
const draggedItemType = this.getItemType();
if (sourceType !== draggedItemType) {
return false;
}
return source.isDragging(this, sourceId);
}
isOverTarget(targetId, options = {
shallow: false
}) {
// undefined on initial render
if (!targetId) {
return false;
}
const { shallow } = options;
if (!this.isDragging()) {
return false;
}
const targetType = this.registry.getTargetType(targetId);
const draggedItemType = this.getItemType();
if (draggedItemType && !matchesType(targetType, draggedItemType)) {
return false;
}
const targetIds = this.getTargetIds();
if (!targetIds.length) {
return false;
}
const index = targetIds.indexOf(targetId);
if (shallow) {
return index === targetIds.length - 1;
} else {
return index > -1;
}
}
getItemType() {
return this.store.getState().dragOperation.itemType;
}
getItem() {
return this.store.getState().dragOperation.item;
}
getSourceId() {
return this.store.getState().dragOperation.sourceId;
}
getTargetIds() {
return this.store.getState().dragOperation.targetIds;
}
getDropResult() {
return this.store.getState().dragOperation.dropResult;
}
didDrop() {
return this.store.getState().dragOperation.didDrop;
}
isSourcePublic() {
return Boolean(this.store.getState().dragOperation.isSourcePublic);
}
getInitialClientOffset() {
return this.store.getState().dragOffset.initialClientOffset;
}
getInitialSourceClientOffset() {
return this.store.getState().dragOffset.initialSourceClientOffset;
}
getClientOffset() {
return this.store.getState().dragOffset.clientOffset;
}
getSourceClientOffset() {
return getSourceClientOffset(this.store.getState().dragOffset);
}
getDifferenceFromInitialOffset() {
return getDifferenceFromInitialOffset(this.store.getState().dragOffset);
}
constructor(store, registry){
this.store = store;
this.registry = registry;
}
}
// Safari 6 and 6.1 for desktop, iPad, and iPhone are the only browsers that
// have WebKitMutationObserver but not un-prefixed MutationObserver.
// Must use `global` or `self` instead of `window` to work in both frames and web
// workers. `global` is a provision of Browserify, Mr, Mrs, or Mop.
/* globals self */ const scope = typeof global !== 'undefined' ? global : self;
const BrowserMutationObserver = scope.MutationObserver || scope.WebKitMutationObserver;
function makeRequestCallFromTimer(callback) {
return function requestCall() {
// We dispatch a timeout with a specified delay of 0 for engines that
// can reliably accommodate that request. This will usually be snapped
// to a 4 milisecond delay, but once we're flushing, there's no delay
// between events.
const timeoutHandle = setTimeout(handleTimer, 0);
// However, since this timer gets frequently dropped in Firefox
// workers, we enlist an interval handle that will try to fire
// an event 20 times per second until it succeeds.
const intervalHandle = setInterval(handleTimer, 50);
function handleTimer() {
// Whichever timer succeeds will cancel both timers and
// execute the callback.
clearTimeout(timeoutHandle);
clearInterval(intervalHandle);
callback();
}
};
}
// To request a high priority event, we induce a mutation observer by toggling
// the text of a text node between "1" and "-1".
function makeRequestCallFromMutationObserver(callback) {
let toggle = 1;
const observer = new BrowserMutationObserver(callback);
const node = document.createTextNode('');
observer.observe(node, {
characterData: true
});
return function requestCall() {
toggle = -toggle;
node.data = toggle;
};
}
const makeRequestCall = typeof BrowserMutationObserver === 'function' ? // reliably everywhere they are implemented.
// They are implemented in all modern browsers.
//
// - Android 4-4.3
// - Chrome 26-34
// - Firefox 14-29
// - Internet Explorer 11
// - iPad Safari 6-7.1
// - iPhone Safari 7-7.1
// - Safari 6-7
makeRequestCallFromMutationObserver : // task queue, are implemented in Internet Explorer 10, Safari 5.0-1, and Opera
// 11-12, and in web workers in many engines.
// Although message channels yield to any queued rendering and IO tasks, they
// would be better than imposing the 4ms delay of timers.
// However, they do not work reliably in Internet Explorer or Safari.
// Internet Explorer 10 is the only browser that has setImmediate but does
// not have MutationObservers.
// Although setImmediate yields to the browser's renderer, it would be
// preferrable to falling back to setTimeout since it does not have
// the minimum 4ms penalty.
// Unfortunately there appears to be a bug in Internet Explorer 10 Mobile (and
// Desktop to a lesser extent) that renders both setImmediate and
// MessageChannel useless for the purposes of ASAP.
// https://github.com/kriskowal/q/issues/396
// Timers are implemented universally.
// We fall back to timers in workers in most engines, and in foreground
// contexts in the following browsers.
// However, note that even this simple case requires nuances to operate in a
// broad spectrum of browsers.
//
// - Firefox 3-13
// - Internet Explorer 6-9
// - iPad Safari 4.3
// - Lynx 2.8.7
makeRequestCallFromTimer;
class AsapQueue {
// Use the fastest means possible to execute a task in its own turn, with
// priority over other events including IO, animation, reflow, and redraw
// events in browsers.
//
// An exception thrown by a task will permanently interrupt the processing of
// subsequent tasks. The higher level `asap` function ensures that if an
// exception is thrown by a task, that the task queue will continue flushing as
// soon as possible, but if you use `rawAsap` directly, you are responsible to
// either ensure that no exceptions are thrown from your task, or to manually
// call `rawAsap.requestFlush` if an exception is thrown.
enqueueTask(task) {
const { queue: q , requestFlush } = this;
if (!q.length) {
requestFlush();
this.flushing = true;
}
// Equivalent to push, but avoids a function call.
q[q.length] = task;
}
constructor(){
this.queue = [];
// We queue errors to ensure they are thrown in right order (FIFO).
// Array-as-queue is good enough here, since we are just dealing with exceptions.
this.pendingErrors = [];
// Once a flush has been requested, no further calls to `requestFlush` are
// necessary until the next `flush` completes.
// @ts-ignore
this.flushing = false;
// The position of the next task to execute in the task queue. This is
// preserved between calls to `flush` so that it can be resumed if
// a task throws an exception.
this.index = 0;
// If a task schedules additional tasks recursively, the task queue can grow
// unbounded. To prevent memory exhaustion, the task queue will periodically
// truncate already-completed tasks.
this.capacity = 1024;
// The flush function processes all tasks that have been scheduled with
// `rawAsap` unless and until one of those tasks throws an exception.
// If a task throws an exception, `flush` ensures that its state will remain
// consistent and will resume where it left off when called again.
// However, `flush` does not make any arrangements to be called again if an
// exception is thrown.
this.flush = ()=>{
const { queue: q } = this;
while(this.index < q.length){
const currentIndex = this.index;
// Advance the index before calling the task. This ensures that we will
// begin flushing on the next task the task throws an error.
this.index++;
q[currentIndex].call();
// Prevent leaking memory for long chains of recursive calls to `asap`.
// If we call `asap` within tasks scheduled by `asap`, the queue will
// grow, but to avoid an O(n) walk for every task we execute, we don't
// shift tasks off the queue after they have been executed.
// Instead, we periodically shift 1024 tasks off the queue.
if (this.index > this.capacity) {
// Manually shift all values starting at the index back to the
// beginning of the queue.
for(let scan = 0, newLength = q.length - this.index; scan < newLength; scan++){
q[scan] = q[scan + this.index];
}
q.length -= this.index;
this.index = 0;
}
}
q.length = 0;
this.index = 0;
this.flushing = false;
};
// In a web browser, exceptions are not fatal. However, to avoid
// slowing down the queue of pending tasks, we rethrow the error in a
// lower priority turn.
this.registerPendingError = (err)=>{
this.pendingErrors.push(err);
this.requestErrorThrow();
};
// `requestFlush` requests that the high priority event queue be flushed as
// soon as possible.
// This is useful to prevent an error thrown in a task from stalling the event
// queue if the exception handled by Node.js’s
// `process.on("uncaughtException")` or by a domain.
// `requestFlush` is implemented using a strategy based on data collected from
// every available SauceLabs Selenium web driver worker at time of writing.
// https://docs.google.com/spreadsheets/d/1mG-5UYGup5qxGdEMWkhP6BWCz053NUb2E1QoUTU16uA/edit#gid=783724593
this.requestFlush = makeRequestCall(this.flush);
this.requestErrorThrow = makeRequestCallFromTimer(()=>{
// Throw first error
if (this.pendingErrors.length) {
throw this.pendingErrors.shift();
}
});
}
} // The message channel technique was discovered by Malte Ubl and was the
// original foundation for this library.
// http://www.nonblocking.io/2011/06/windownexttick.html
// Safari 6.0.5 (at least) intermittently fails to create message ports on a
// page's first load. Thankfully, this version of Safari supports
// MutationObservers, so we don't need to fall back in that case.
// function makeRequestCallFromMessageChannel(callback) {
// var channel = new MessageChannel();
// channel.port1.onmessage = callback;
// return function requestCall() {
// channel.port2.postMessage(0);
// };
// }
// For reasons explained above, we are also unable to use `setImmediate`
// under any circumstances.
// Even if we were, there is another bug in Internet Explorer 10.
// It is not sufficient to assign `setImmediate` to `requestFlush` because
// `setImmediate` must be called *by name* and therefore must be wrapped in a
// closure.
// Never forget.
// function makeRequestCallFromSetImmediate(callback) {
// return function requestCall() {
// setImmediate(callback);
// };
// }
// Safari 6.0 has a problem where timers will get lost while the user is
// scrolling. This problem does not impact ASAP because Safari 6.0 supports
// mutation observers, so that implementation is used instead.
// However, if we ever elect to use timers in Safari, the prevalent work-around
// is to add a scroll event listener that calls for a flush.
// `setTimeout` does not call the passed callback if the delay is less than
// approximately 7 in web workers in Firefox 8 through 18, and sometimes not
// even then.
// This is for `asap.js` only.
// Its name will be periodically randomized to break any code that depends on
// // its existence.
// rawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer
// ASAP was originally a nextTick shim included in Q. This was factored out
// into this ASAP package. It was later adapted to RSVP which made further
// amendments. These decisions, particularly to marginalize MessageChannel and
// to capture the MutationObserver implementation in a closure, were integrated
// back into ASAP proper.
// https://github.com/tildeio/rsvp.js/blob/cddf7232546a9cf858524b75cde6f9edf72620a7/lib/rsvp/asap.js
// `call`, just like a function.
class RawTask {
call() {
try {
this.task && this.task();
} catch (error) {
this.onError(error);
} finally{
this.task = null;
this.release(this);
}
}
constructor(onError, release){
this.onError = onError;
this.release = release;
this.task = null;
}
}
class TaskFactory {
create(task) {
const tasks = this.freeTasks;
const t1 = tasks.length ? tasks.pop() : new RawTask(this.onError, (t)=>tasks[tasks.length] = t
);
t1.task = task;
return t1;
}
constructor(onError){
this.onError = onError;
this.freeTasks = [];
}
}
const asapQueue = new AsapQueue();
const taskFactory = new TaskFactory(asapQueue.registerPendingError);
/**
* Calls a task as soon as possible after returning, in its own event, with priority
* over other events like animation, reflow, and repaint. An error thrown from an
* event will not interrupt, nor even substantially slow down the processing of
* other events, but will be rather postponed to a lower priority event.
* @param {{call}} task A callable object, typically a function that takes no
* arguments.
*/ function asap(task) {
asapQueue.enqueueTask(taskFactory.create(task));
}
const ADD_SOURCE = 'dnd-core/ADD_SOURCE';
const ADD_TARGET = 'dnd-core/ADD_TARGET';
const REMOVE_SOURCE = 'dnd-core/REMOVE_SOURCE';
const REMOVE_TARGET = 'dnd-core/REMOVE_TARGET';
function addSource(sourceId) {
return {
type: ADD_SOURCE,
payload: {
sourceId
}
};
}
function addTarget(targetId) {
return {
type: ADD_TARGET,
payload: {
targetId
}
};
}
function removeSource(sourceId) {
return {
type: REMOVE_SOURCE,
payload: {
sourceId
}
};
}
function removeTarget(targetId) {
return {
type: REMOVE_TARGET,
payload: {
targetId
}
};
}
function validateSourceContract(source) {
invariant(typeof source.canDrag === 'function', 'Expected canDrag to be a function.');
invariant(typeof source.beginDrag === 'function', 'Expected beginDrag to be a function.');
invariant(typeof source.endDrag === 'function', 'Expected endDrag to be a function.');
}
function validateTargetContract(target) {
invariant(typeof target.canDrop === 'function', 'Expected canDrop to be a function.');
invariant(typeof target.hover === 'function', 'Expected hover to be a function.');
invariant(typeof target.drop === 'function', 'Expected beginDrag to be a function.');
}
function validateType(type, allowArray) {
if (allowArray && Array.isArray(type)) {
type.forEach((t)=>validateType(t, false)
);
return;
}
invariant(typeof type === 'string' || typeof type === 'symbol', allowArray ? 'Type can only be a string, a symbol, or an array of either.' : 'Type can only be a string or a symbol.');
}
var HandlerRole;
(function(HandlerRole) {
HandlerRole["SOURCE"] = "SOURCE";
HandlerRole["TARGET"] = "TARGET";
})(HandlerRole || (HandlerRole = {}));
let nextUniqueId = 0;
function getNextUniqueId() {
return nextUniqueId++;
}
function getNextHandlerId(role) {
const id = getNextUniqueId().toString();
switch(role){
case HandlerRole.SOURCE:
return `S${id}`;
case HandlerRole.TARGET:
return `T${id}`;
default:
throw new Error(`Unknown Handler Role: ${role}`);
}
}
function parseRoleFromHandlerId(handlerId) {
switch(handlerId[0]){
case 'S':
return HandlerRole.SOURCE;
case 'T':
return HandlerRole.TARGET;
default:
throw new Error(`Cannot parse handler ID: ${handlerId}`);
}
}
function mapContainsValue(map, searchValue) {
const entries = map.entries();
let isDone = false;
do {
const { done , value: [, value] , } = entries.next();
if (value === searchValue) {
return true;
}
isDone = !!done;
}while (!isDone)
return false;
}
class HandlerRegistryImpl {
addSource(type, source) {
validateType(type);
validateSourceContract(source);
const sourceId = this.addHandler(HandlerRole.SOURCE, type, source);
this.store.dispatch(addSource(sourceId));
return sourceId;
}
addTarget(type, target) {
validateType(type, true);
validateTargetContract(target);
const targetId = this.addHandler(HandlerRole.TARGET, type, target);
this.store.dispatch(addTarget(targetId));
return targetId;
}
containsHandler(handler) {
return mapContainsValue(this.dragSources, handler) || mapContainsValue(this.dropTargets, handler);
}
getSource(sourceId, includePinned = false) {
invariant(this.isSourceId(sourceId), 'Expected a valid source ID.');
const isPinned = includePinned && sourceId === this.pinnedSourceId;
const source = isPinned ? this.pinnedSource : this.dragSources.get(sourceId);
return source;
}
getTarget(targetId) {
invariant(this.isTargetId(targetId), 'Expected a valid target ID.');
return this.dropTargets.get(targetId);
}
getSourceType(sourceId) {
invariant(this.isSourceId(sourceId), 'Expected a valid source ID.');
return this.types.get(sourceId);
}
getTargetType(targetId) {
invariant(this.isTargetId(targetId), 'Expected a valid target ID.');
return this.types.get(targetId);
}
isSourceId(handlerId) {
const role = parseRoleFromHandlerId(handlerId);
return role === HandlerRole.SOURCE;
}
isTargetId(handlerId) {
const role = parseRoleFromHandlerId(handlerId);
return role === HandlerRole.TARGET;
}
removeSource(sourceId) {
invariant(this.getSource(sourceId), 'Expected an existing source.');
this.store.dispatch(removeSource(sourceId));
asap(()=>{
this.dragSources.delete(sourceId);
this.types.delete(sourceId);
});
}
removeTarget(targetId) {
invariant(this.getTarget(targetId), 'Expected an existing target.');
this.store.dispatch(removeTarget(targetId));
this.dropTargets.delete(targetId);
this.types.delete(targetId);
}
pinSource(sourceId) {
const source = this.getSource(sourceId);
invariant(source, 'Expected an existing source.');
this.pinnedSourceId = sourceId;
this.pinnedSource = source;
}
unpinSource() {
invariant(this.pinnedSource, 'No source is pinned at the time.');
this.pinnedSourceId = null;
this.pinnedSource = null;
}
addHandler(role, type, handler) {
const id = getNextHandlerId(role);
this.types.set(id, type);
if (role === HandlerRole.SOURCE) {
this.dragSources.set(id, handler);
} else if (role === HandlerRole.TARGET) {
this.dropTargets.set(id, handler);
}
return id;
}
constructor(store){
this.types = new Map();
this.dragSources = new Map();
this.dropTargets = new Map();
this.pinnedSourceId = null;
this.pinnedSource = null;
this.store = store;
}
}
const strictEquality = (a, b)=>a === b
;
/**
* Determine if two cartesian coordinate offsets are equal
* @param offsetA
* @param offsetB
*/ function areCoordsEqual(offsetA, offsetB) {
if (!offsetA && !offsetB) {
return true;
} else if (!offsetA || !offsetB) {
return false;
} else {
return offsetA.x === offsetB.x && offsetA.y === offsetB.y;
}
}
/**
* Determines if two arrays of items are equal
* @param a The first array of items
* @param b The second array of items
*/ function areArraysEqual(a, b, isEqual = strictEquality) {
if (a.length !== b.length) {
return false;
}
for(let i = 0; i < a.length; ++i){
if (!isEqual(a[i], b[i])) {
return false;
}
}
return true;
}
function reduce$5(// eslint-disable-next-line @typescript-eslint/no-unused-vars
_state = NONE, action) {
switch(action.type){
case HOVER:
break;
case ADD_SOURCE:
case ADD_TARGET:
case REMOVE_TARGET:
case REMOVE_SOURCE:
return NONE;
case BEGIN_DRAG:
case PUBLISH_DRAG_SOURCE:
case END_DRAG:
case DROP:
default:
return ALL;
}
const { targetIds =[] , prevTargetIds =[] } = action.payload;
const result = xor(targetIds, prevTargetIds);
const didChange = result.length > 0 || !areArraysEqual(targetIds, prevTargetIds);
if (!didChange) {
return NONE;
}
// Check the target ids at the innermost position. If they are valid, add them
// to the result
const prevInnermostTargetId = prevTargetIds[prevTargetIds.length - 1];
const innermostTargetId = targetIds[targetIds.length - 1];
if (prevInnermostTargetId !== innermostTargetId) {
if (prevInnermostTargetId) {
result.push(prevInnermostTargetId);
}
if (innermostTargetId) {
result.push(innermostTargetId);
}
}
return result;
}
function _defineProperty$3(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread$3(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_defineProperty$3(target, key, source[key]);
});
}
return target;
}
const initialState$1 = {
initialSourceClientOffset: null,
initialClientOffset: null,
clientOffset: null
};
function reduce$4(state = initialState$1, action) {
const { payload } = action;
switch(action.type){
case INIT_COORDS:
case BEGIN_DRAG:
return {
initialSourceClientOffset: payload.sourceClientOffset,
initialClientOffset: payload.clientOffset,
clientOffset: payload.clientOffset
};
case HOVER:
if (areCoordsEqual(state.clientOffset, payload.clientOffset)) {
return state;
}
return _objectSpread$3({}, state, {
clientOffset: payload.clientOffset
});
case END_DRAG:
case DROP:
return initialState$1;
default:
return state;
}
}
function _defineProperty$2(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread$2(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_defineProperty$2(target, key, source[key]);
});
}
return target;
}
const initialState = {
itemType: null,
item: null,
sourceId: null,
targetIds: [],
dropResult: null,
didDrop: false,
isSourcePublic: null
};
function reduce$3(state = initialState, action) {
const { payload } = action;
switch(action.type){
case BEGIN_DRAG:
return _objectSpread$2({}, state, {
itemType: payload.itemType,
item: payload.item,
sourceId: payload.sourceId,
isSourcePublic: payload.isSourcePublic,
dropResult: null,
didDrop: false
});
case PUBLISH_DRAG_SOURCE:
return _objectSpread$2({}, state, {
isSourcePublic: true
});
case HOVER:
return _objectSpread$2({}, state, {
targetIds: payload.targetIds
});
case REMOVE_TARGET:
if (state.targetIds.indexOf(payload.targetId) === -1) {
return state;
}
return _objectSpread$2({}, state, {
targetIds: without$1(state.targetIds, payload.targetId)
});
case DROP:
return _objectSpread$2({}, state, {
dropResult: payload.dropResult,
didDrop: true,
targetIds: []
});
case END_DRAG:
return _objectSpread$2({}, state, {
itemType: null,
item: null,
sourceId: null,
dropResult: null,
didDrop: false,
isSourcePublic: null,
targetIds: []
});
default:
return state;
}
}
function reduce$2(state = 0, action) {
switch(action.type){
case ADD_SOURCE:
case ADD_TARGET:
return state + 1;
case REMOVE_SOURCE:
case REMOVE_TARGET:
return state - 1;
default:
return state;
}
}
function reduce$1(state = 0) {
return state + 1;
}
function _defineProperty$1(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread$1(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_defineProperty$1(target, key, source[key]);
});
}
return target;
}
function reduce(state = {}, action) {
return {
dirtyHandlerIds: reduce$5(state.dirtyHandlerIds, {
type: action.type,
payload: _objectSpread$1({}, action.payload, {
prevTargetIds: get(state, 'dragOperation.targetIds', [])
})
}),
dragOffset: reduce$4(state.dragOffset, action),
refCount: reduce$2(state.refCount, action),
dragOperation: reduce$3(state.dragOperation, action),
stateId: reduce$1(state.stateId)
};
}
function createDragDropManager(backendFactory, globalContext = undefined, backendOptions = {}, debugMode = false) {
const store = makeStoreInstance(debugMode);
const monitor = new DragDropMonitorImpl(store, new HandlerRegistryImpl(store));
const manager = new DragDropManagerImpl(store, monitor);
const backend = backendFactory(manager, globalContext, backendOptions);
manager.receiveBackend(backend);
return manager;
}
function makeStoreInstance(debugMode) {
// TODO: if we ever make a react-native version of this,
// we'll need to consider how to pull off dev-tooling
const reduxDevTools = typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__;
return createStore(reduce, debugMode && reduxDevTools && reduxDevTools({
name: 'dnd-core',
instanceId: 'dnd-core'
}));
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for(i = 0; i < sourceSymbolKeys.length; i++){
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
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;
}
let refCount = 0;
const INSTANCE_SYM = Symbol.for('__REACT_DND_CONTEXT_INSTANCE__');
var DndProvider = /*#__PURE__*/ memo(function DndProvider(_param) {
var { children } = _param, props = _objectWithoutProperties(_param, [
"children"
]);
const [manager, isGlobalInstance] = getDndContextValue(props) // memoized from props
;
/**
* If the global context was used to store the DND context
* then where theres no more references to it we should
* clean it up to avoid memory leaks
*/ useEffect(()=>{
if (isGlobalInstance) {
const context = getGlobalContext();
++refCount;
return ()=>{
if (--refCount === 0) {
context[INSTANCE_SYM] = null;
}
};
}
return;
}, []);
return /*#__PURE__*/ jsx(DndContext.Provider, {
value: manager,
children: children
});
});
function getDndContextValue(props) {
if ('manager' in props) {
const manager = {
dragDropManager: props.manager
};
return [
manager,
false
];
}
const manager = createSingletonDndContext(props.backend, props.context, props.options, props.debugMode);
const isGlobalInstance = !props.context;
return [
manager,
isGlobalInstance
];
}
function createSingletonDndContext(backend, context = getGlobalContext(), options, debugMode) {
const ctx = context;
if (!ctx[INSTANCE_SYM]) {
ctx[INSTANCE_SYM] = {
dragDropManager: createDragDropManager(backend, context, options, debugMode)
};
}
return ctx[INSTANCE_SYM];
}
function getGlobalContext() {
return typeof global !== 'undefined' ? global : window;
}
// do not edit .js files directly - edit src/index.jst
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;
};
var equal = /*@__PURE__*/getDefaultExportFromCjs(fastDeepEqual);
// suppress the useLayoutEffect warning on server side.
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
/**
*
* @param monitor The monitor to collect state from
* @param collect The collecting function
* @param onUpdate A method to invoke when updates occur
*/ function useCollector(monitor, collect, onUpdate) {
const [collected, setCollected] = useState(()=>collect(monitor)
);
const updateCollected = useCallback(()=>{
const nextValue = collect(monitor);
// This needs to be a deep-equality check because some monitor-collected values
// include XYCoord objects that may be equivalent, but do not have instance equality.
if (!equal(collected, nextValue)) {
setCollected(nextValue);
if (onUpdate) {
onUpdate();
}
}
}, [
collected,
monitor,
onUpdate
]);
// update the collected properties after react renders.
// Note that the "Dustbin Stress Test" fails if this is not
// done when the component updates
useIsomorphicLayoutEffect(updateCollected);
return [
collected,
updateCollected
];
}
function useMonitorOutput(monitor, collect, onCollect) {
const [collected, updateCollected] = useCollector(monitor, collect, onCollect);
useIsomorphicLayoutEffect(function subscribeToMonitorStateChange() {
const handlerId = monitor.getHandlerId();
if (handlerId == null) {
return;
}
return monitor.subscribeToStateChange(updateCollected, {
handlerIds: [
handlerId
]
});
}, [
monitor,
updateCollected
]);
return collected;
}
function useCollectedProps(collector, monitor, connector) {
return useMonitorOutput(monitor, collector || (()=>({})
), ()=>connector.reconnect()
);
}
function useOptionalFactory(arg, deps) {
const memoDeps = [
...deps || []
];
if (deps == null && typeof arg !== 'function') {
memoDeps.push(arg);
}
return useMemo(()=>{
return typeof arg === 'function' ? arg() : arg;
}, memoDeps);
}
function useConnectDragSource(connector) {
return useMemo(()=>connector.hooks.dragSource()
, [
connector
]);
}
function useConnectDragPreview(connector) {
return useMemo(()=>connector.hooks.dragPreview()
, [
connector
]);
}
let isCallingCanDrag = false;
let isCallingIsDragging = false;
class DragSourceMonitorImpl {
receiveHandlerId(sourceId) {
this.sourceId = sourceId;
}
getHandlerId() {
return this.sourceId;
}
canDrag() {
invariant(!isCallingCanDrag, 'You may not call monitor.canDrag() inside your canDrag() implementation. ' + 'Read more: http://react-dnd.github.io/react-dnd/docs/api/drag-source-monitor');
try {
isCallingCanDrag = true;
return this.internalMonitor.canDragSource(this.sourceId);
} finally{
isCallingCanDrag = false;
}
}
isDragging() {
if (!this.sourceId) {
return false;
}
invariant(!isCallingIsDragging, 'You may not call monitor.isDragging() inside your isDragging() implementation. ' + 'Read more: http://react-dnd.github.io/react-dnd/docs/api/drag-source-monitor');
try {
isCallingIsDragging = true;
return this.internalMonitor.isDraggingSource(this.sourceId);
} finally{
isCallingIsDragging = false;
}
}
subscribeToStateChange(listener, options) {
return this.internalMonitor.subscribeToStateChange(listener, options);
}
isDraggingSource(sourceId) {
return this.internalMonitor.isDraggingSource(sourceId);
}
isOverTarget(targetId, options) {
return this.internalMonitor.isOverTarget(targetId, options);
}
getTargetIds() {
return this.internalMonitor.getTargetIds();
}
isSourcePublic() {
return this.internalMonitor.isSourcePublic();
}
getSourceId() {
return this.internalMonitor.getSourceId();
}
subscribeToOffsetChange(listener) {
return this.internalMonitor.subscribeToOffsetChange(listener);
}
canDragSource(sourceId) {
return this.internalMonitor.canDragSource(sourceId);
}
canDropOnTarget(targetId) {
return this.internalMonitor.canDropOnTarget(targetId);
}
getItemType() {
return this.internalMonitor.getItemType();
}
getItem() {
return this.internalMonitor.getItem();
}
getDropResult() {
return this.internalMonitor.getDropResult();
}
didDrop() {
return this.internalMonitor.didDrop();
}
getInitialClientOffset() {
return this.internalMonitor.getInitialClientOffset();
}
getInitialSourceClientOffset() {
return this.internalMonitor.getInitialSourceClientOffset();
}
getSourceClientOffset() {
return this.internalMonitor.getSourceClientOffset();
}
getClientOffset() {
return this.internalMonitor.getClientOffset();
}
getDifferenceFromInitialOffset() {
return this.internalMonitor.getDifferenceFromInitialOffset();
}
constructor(manager){
this.sourceId = null;
this.internalMonitor = manager.getMonitor();
}
}
let isCallingCanDrop = false;
class DropTargetMonitorImpl {
receiveHandlerId(targetId) {
this.targetId = targetId;
}
getHandlerId() {
return this.targetId;
}
subscribeToStateChange(listener, options) {
return this.internalMonitor.subscribeToStateChange(listener, options);
}
canDrop() {
// Cut out early if the target id has not been set. This should prevent errors
// where the user has an older version of dnd-core like in
// https://github.com/react-dnd/react-dnd/issues/1310
if (!this.targetId) {
return false;
}
invariant(!isCallingCanDrop, 'You may not call monitor.canDrop() inside your canDrop() implementation. ' + 'Read more: http://react-dnd.github.io/react-dnd/docs/api/drop-target-monitor');
try {
isCallingCanDrop = true;
return this.internalMonitor.canDropOnTarget(this.targetId);
} finally{
isCallingCanDrop = false;
}
}
isOver(options) {
if (!this.targetId) {
return false;
}
return this.internalMonitor.isOverTarget(this.targetId, options);
}
getItemType() {
return this.internalMonitor.getItemType();
}
getItem() {
return this.internalMonitor.getItem();
}
getDropResult() {
return this.internalMonitor.getDropResult();
}
didDrop() {
return this.internalMonitor.didDrop();
}
getInitialClientOffset() {
return this.internalMonitor.getInitialClientOffset();
}
getInitialSourceClientOffset() {
return this.internalMonitor.getInitialSourceClientOffset();
}
getSourceClientOffset() {
return this.internalMonitor.getSourceClientOffset();
}
getClientOffset() {
return this.internalMonitor.getClientOffset();
}
getDifferenceFromInitialOffset() {
return this.internalMonitor.getDifferenceFromInitialOffset();
}
constructor(manager){
this.targetId = null;
this.internalMonitor = manager.getMonitor();
}
}
function registerTarget(type, target, manager) {
const registry = manager.getRegistry();
const targetId = registry.addTarget(type, target);
return [
targetId,
()=>registry.removeTarget(targetId)
];
}
function registerSource(type, source, manager) {
const registry = manager.getRegistry();
const sourceId = registry.addSource(type, source);
return [
sourceId,
()=>registry.removeSource(sourceId)
];
}
function shallowEqual(objA, objB, compare, compareContext) {
let compareResult = compare ? compare.call(compareContext, objA, objB) : void 0;
if (compareResult !== void 0) {
return !!compareResult;
}
if (objA === objB) {
return true;
}
if (typeof objA !== 'object' || !objA || typeof objB !== 'object' || !objB) {
return false;
}
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
const bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);
// Test for A's keys different from B.
for(let idx = 0; idx < keysA.length; idx++){
const key = keysA[idx];
if (!bHasOwnProperty(key)) {
return false;
}
const valueA = objA[key];
const valueB = objB[key];
compareResult = compare ? compare.call(compareContext, valueA, valueB, key) : void 0;
if (compareResult === false || compareResult === void 0 && valueA !== valueB) {
return false;
}
}
return true;
}
function isRef(obj) {
return(// eslint-disable-next-line no-prototype-builtins
obj !== null && typeof obj === 'object' && Object.prototype.hasOwnProperty.call(obj, 'current'));
}
function throwIfCompositeComponentElement(element) {
// Custom components can no longer be wrapped directly in React DnD 2.0
// so that we don't need to depend on findDOMNode() from react-dom.
if (typeof element.type === 'string') {
return;
}
const displayName = element.type.displayName || element.type.name || 'the component';
throw new Error('Only native element nodes can now be passed to React DnD connectors.' + `You can either wrap ${displayName} into a <div>, or turn it into a ` + 'drag source or a drop target itself.');
}
function wrapHookToRecognizeElement(hook) {
return (elementOrNode = null, options = null)=>{
// When passed a node, call the hook straight away.
if (!isValidElement(elementOrNode)) {
const node = elementOrNode;
hook(node, options);
// return the node so it can be chained (e.g. when within callback refs
// <div ref={node => connectDragSource(connectDropTarget(node))}/>
return node;
}
// If passed a ReactElement, clone it and attach this function as a ref.
// This helps us achieve a neat API where user doesn't even know that refs
// are being used under the hood.
const element = elementOrNode;
throwIfCompositeComponentElement(element);
// When no options are passed, use the hook directly
const ref = options ? (node)=>hook(node, options)
: hook;
return cloneWithRef(element, ref);
};
}
function wrapConnectorHooks(hooks) {
const wrappedHooks = {};
Object.keys(hooks).forEach((key)=>{
const hook = hooks[key];
// ref objects should be passed straight through without wrapping
if (key.endsWith('Ref')) {
wrappedHooks[key] = hooks[key];
} else {
const wrappedHook = wrapHookToRecognizeElement(hook);
wrappedHooks[key] = ()=>wrappedHook
;
}
});
return wrappedHooks;
}
function setRef(ref, node) {
if (typeof ref === 'function') {
ref(node);
} else {
ref.current = node;
}
}
function cloneWithRef(element, newRef) {
const previousRef = element.ref;
invariant(typeof previousRef !== 'string', 'Cannot connect React DnD to an element with an existing string ref. ' + 'Please convert it to use a callback ref instead, or wrap it into a <span> or <div>. ' + 'Read more: https://reactjs.org/docs/refs-and-the-dom.html#callback-refs');
if (!previousRef) {
// When there is no ref on the element, use the new ref directly
return cloneElement(element, {
ref: newRef
});
} else {
return cloneElement(element, {
ref: (node)=>{
setRef(previousRef, node);
setRef(newRef, node);
}
});
}
}
class SourceConnector {
receiveHandlerId(newHandlerId) {
if (this.handlerId === newHandlerId) {
return;
}
this.handlerId = newHandlerId;
this.reconnect();
}
get connectTarget() {
return this.dragSource;
}
get dragSourceOptions() {
return this.dragSourceOptionsInternal;
}
set dragSourceOptions(options) {
this.dragSourceOptionsInternal = options;
}
get dragPreviewOptions() {
return this.dragPreviewOptionsInternal;
}
set dragPreviewOptions(options) {
this.dragPreviewOptionsInternal = options;
}
reconnect() {
const didChange = this.reconnectDragSource();
this.reconnectDragPreview(didChange);
}
reconnectDragSource() {
const dragSource = this.dragSource;
// if nothing has changed then don't resubscribe
const didChange = this.didHandlerIdChange() || this.didConnectedDragSourceChange() || this.didDragSourceOptionsChange();
if (didChange) {
this.disconnectDragSource();
}
if (!this.handlerId) {
return didChange;
}
if (!dragSource) {
this.lastConnectedDragSource = dragSource;
return didChange;
}
if (didChange) {
this.lastConnectedHandlerId = this.handlerId;
this.lastConnectedDragSource = dragSource;
this.lastConnectedDragSourceOptions = this.dragSourceOptions;
this.dragSourceUnsubscribe = this.backend.connectDragSource(this.handlerId, dragSource, this.dragSourceOptions);
}
return didChange;
}
reconnectDragPreview(forceDidChange = false) {
const dragPreview = this.dragPreview;
// if nothing has changed then don't resubscribe
const didChange = forceDidChange || this.didHandlerIdChange() || this.didConnectedDragPreviewChange() || this.didDragPreviewOptionsChange();
if (didChange) {
this.disconnectDragPreview();
}
if (!this.handlerId) {
return;
}
if (!dragPreview) {
this.lastConnectedDragPreview = dragPreview;
return;
}
if (didChange) {
this.lastConnectedHandlerId = this.handlerId;
this.lastConnectedDragPreview = dragPreview;
this.lastConnectedDragPreviewOptions = this.dragPreviewOptions;
this.dragPreviewUnsubscribe = this.backend.connectDragPreview(this.handlerId, dragPreview, this.dragPreviewOptions);
}
}
didHandlerIdChange() {
return this.lastConnectedHandlerId !== this.handlerId;
}
didConnectedDragSourceChange() {
return this.lastConnectedDragSource !== this.dragSource;
}
didConnectedDragPreviewChange() {
return this.lastConnectedDragPreview !== this.dragPreview;
}
didDragSourceOptionsChange() {
return !shallowEqual(this.lastConnectedDragSourceOptions, this.dragSourceOptions);
}
didDragPreviewOptionsChange() {
return !shallowEqual(this.lastConnectedDragPreviewOptions, this.dragPreviewOptions);
}
disconnectDragSource() {
if (this.dragSourceUnsubscribe) {
this.dragSourceUnsubscribe();
this.dragSourceUnsubscribe = undefined;
}
}
disconnectDragPreview() {
if (this.dragPreviewUnsubscribe) {
this.dragPreviewUnsubscribe();
this.dragPreviewUnsubscribe = undefined;
this.dragPreviewNode = null;
this.dragPreviewRef = null;
}
}
get dragSource() {
return this.dragSourceNode || this.dragSourceRef && this.dragSourceRef.current;
}
get dragPreview() {
return this.dragPreviewNode || this.dragPreviewRef && this.dragPreviewRef.current;
}
clearDragSource() {
this.dragSourceNode = null;
this.dragSourceRef = null;
}
clearDragPreview() {
this.dragPreviewNode = null;
this.dragPreviewRef = null;
}
constructor(backend){
this.hooks = wrapConnectorHooks({
dragSource: (node, options)=>{
this.clearDragSource();
this.dragSourceOptions = options || null;
if (isRef(node)) {
this.dragSourceRef = node;
} else {
this.dragSourceNode = node;
}
this.reconnectDragSource();
},
dragPreview: (node, options)=>{
this.clearDragPreview();
this.dragPreviewOptions = options || null;
if (isRef(node)) {
this.dragPreviewRef = node;
} else {
this.dragPreviewNode = node;
}
this.reconnectDragPreview();
}
});
this.handlerId = null;
// The drop target may either be attached via ref or connect function
this.dragSourceRef = null;
this.dragSourceOptionsInternal = null;
// The drag preview may either be attached via ref or connect function
this.dragPreviewRef = null;
this.dragPreviewOptionsInternal = null;
this.lastConnectedHandlerId = null;
this.lastConnectedDragSource = null;
this.lastConnectedDragSourceOptions = null;
this.lastConnectedDragPreview = null;
this.lastConnectedDragPreviewOptions = null;
this.backend = backend;
}
}
class TargetConnector {
get connectTarget() {
return this.dropTarget;
}
reconnect() {
// if nothing has changed then don't resubscribe
const didChange = this.didHandlerIdChange() || this.didDropTargetChange() || this.didOptionsChange();
if (didChange) {
this.disconnectDropTarget();
}
const dropTarget = this.dropTarget;
if (!this.handlerId) {
return;
}
if (!dropTarget) {
this.lastConnectedDropTarget = dropTarget;
return;
}
if (didChange) {
this.lastConnectedHandlerId = this.handlerId;
this.lastConnectedDropTarget = dropTarget;
this.lastConnectedDropTargetOptions = this.dropTargetOptions;
this.unsubscribeDropTarget = this.backend.connectDropTarget(this.handlerId, dropTarget, this.dropTargetOptions);
}
}
receiveHandlerId(newHandlerId) {
if (newHandlerId === this.handlerId) {
return;
}
this.handlerId = newHandlerId;
this.reconnect();
}
get dropTargetOptions() {
return this.dropTargetOptionsInternal;
}
set dropTargetOptions(options) {
this.dropTargetOptionsInternal = options;
}
didHandlerIdChange() {
return this.lastConnectedHandlerId !== this.handlerId;
}
didDropTargetChange() {
return this.lastConnectedDropTarget !== this.dropTarget;
}
didOptionsChange() {
return !shallowEqual(this.lastConnectedDropTargetOptions, this.dropTargetOptions);
}
disconnectDropTarget() {
if (this.unsubscribeDropTarget) {
this.unsubscribeDropTarget();
this.unsubscribeDropTarget = undefined;
}
}
get dropTarget() {
return this.dropTargetNode || this.dropTargetRef && this.dropTargetRef.current;
}
clearDropTarget() {
this.dropTargetRef = null;
this.dropTargetNode = null;
}
constructor(backend){
this.hooks = wrapConnectorHooks({
dropTarget: (node, options)=>{
this.clearDropTarget();
this.dropTargetOptions = options;
if (isRef(node)) {
this.dropTargetRef = node;
} else {
this.dropTargetNode = node;
}
this.reconnect();
}
});
this.handlerId = null;
// The drop target may either be attached via ref or connect function
this.dropTargetRef = null;
this.dropTargetOptionsInternal = null;
this.lastConnectedHandlerId = null;
this.lastConnectedDropTarget = null;
this.lastConnectedDropTargetOptions = null;
this.backend = backend;
}
}
/**
* A hook to retrieve the DragDropManager from Context
*/ function useDragDropManager() {
const { dragDropManager } = useContext(DndContext);
invariant(dragDropManager != null, 'Expected drag drop context');
return dragDropManager;
}
function useDragSourceConnector(dragSourceOptions, dragPreviewOptions) {
const manager = useDragDropManager();
const connector = useMemo(()=>new SourceConnector(manager.getBackend())
, [
manager
]);
useIsomorphicLayoutEffect(()=>{
connector.dragSourceOptions = dragSourceOptions || null;
connector.reconnect();
return ()=>connector.disconnectDragSource()
;
}, [
connector,
dragSourceOptions
]);
useIsomorphicLayoutEffect(()=>{
connector.dragPreviewOptions = dragPreviewOptions || null;
connector.reconnect();
return ()=>connector.disconnectDragPreview()
;
}, [
connector,
dragPreviewOptions
]);
return connector;
}
function useDragSourceMonitor() {
const manager = useDragDropManager();
return useMemo(()=>new DragSourceMonitorImpl(manager)
, [
manager
]);
}
class DragSourceImpl {
beginDrag() {
const spec = this.spec;
const monitor = this.monitor;
let result = null;
if (typeof spec.item === 'object') {
result = spec.item;
} else if (typeof spec.item === 'function') {
result = spec.item(monitor);
} else {
result = {};
}
return result !== null && result !== void 0 ? result : null;
}
canDrag() {
const spec = this.spec;
const monitor = this.monitor;
if (typeof spec.canDrag === 'boolean') {
return spec.canDrag;
} else if (typeof spec.canDrag === 'function') {
return spec.canDrag(monitor);
} else {
return true;
}
}
isDragging(globalMonitor, target) {
const spec = this.spec;
const monitor = this.monitor;
const { isDragging } = spec;
return isDragging ? isDragging(monitor) : target === globalMonitor.getSourceId();
}
endDrag() {
const spec = this.spec;
const monitor = this.monitor;
const connector = this.connector;
const { end } = spec;
if (end) {
end(monitor.getItem(), monitor);
}
connector.reconnect();
}
constructor(spec, monitor, connector){
this.spec = spec;
this.monitor = monitor;
this.connector = connector;
}
}
function useDragSource(spec, monitor, connector) {
const handler = useMemo(()=>new DragSourceImpl(spec, monitor, connector)
, [
monitor,
connector
]);
useEffect(()=>{
handler.spec = spec;
}, [
spec
]);
return handler;
}
function useDragType(spec) {
return useMemo(()=>{
const result = spec.type;
invariant(result != null, 'spec.type must be defined');
return result;
}, [
spec
]);
}
function useRegisteredDragSource(spec, monitor, connector) {
const manager = useDragDropManager();
const handler = useDragSource(spec, monitor, connector);
const itemType = useDragType(spec);
useIsomorphicLayoutEffect(function registerDragSource() {
if (itemType != null) {
const [handlerId, unregister] = registerSource(itemType, handler, manager);
monitor.receiveHandlerId(handlerId);
connector.receiveHandlerId(handlerId);
return unregister;
}
return;
}, [
manager,
monitor,
connector,
handler,
itemType
]);
}
/**
* useDragSource hook
* @param sourceSpec The drag source specification (object or function, function preferred)
* @param deps The memoization deps array to use when evaluating spec changes
*/ function useDrag(specArg, deps) {
const spec = useOptionalFactory(specArg, deps);
invariant(!spec.begin, `useDrag::spec.begin was deprecated in v14. Replace spec.begin() with spec.item(). (see more here - https://react-dnd.github.io/react-dnd/docs/api/use-drag)`);
const monitor = useDragSourceMonitor();
const connector = useDragSourceConnector(spec.options, spec.previewOptions);
useRegisteredDragSource(spec, monitor, connector);
return [
useCollectedProps(spec.collect, monitor, connector),
useConnectDragSource(connector),
useConnectDragPreview(connector),
];
}
function useConnectDropTarget(connector) {
return useMemo(()=>connector.hooks.dropTarget()
, [
connector
]);
}
function useDropTargetConnector(options) {
const manager = useDragDropManager();
const connector = useMemo(()=>new TargetConnector(manager.getBackend())
, [
manager
]);
useIsomorphicLayoutEffect(()=>{
connector.dropTargetOptions = options || null;
connector.reconnect();
return ()=>connector.disconnectDropTarget()
;
}, [
options
]);
return connector;
}
function useDropTargetMonitor() {
const manager = useDragDropManager();
return useMemo(()=>new DropTargetMonitorImpl(manager)
, [
manager
]);
}
/**
* Internal utility hook to get an array-version of spec.accept.
* The main utility here is that we aren't creating a new array on every render if a non-array spec.accept is passed in.
* @param spec
*/ function useAccept(spec) {
const { accept } = spec;
return useMemo(()=>{
invariant(spec.accept != null, 'accept must be defined');
return Array.isArray(accept) ? accept : [
accept
];
}, [
accept
]);
}
class DropTargetImpl {
canDrop() {
const spec = this.spec;
const monitor = this.monitor;
return spec.canDrop ? spec.canDrop(monitor.getItem(), monitor) : true;
}
hover() {
const spec = this.spec;
const monitor = this.monitor;
if (spec.hover) {
spec.hover(monitor.getItem(), monitor);
}
}
drop() {
const spec = this.spec;
const monitor = this.monitor;
if (spec.drop) {
return spec.drop(monitor.getItem(), monitor);
}
return;
}
constructor(spec, monitor){
this.spec = spec;
this.monitor = monitor;
}
}
function useDropTarget(spec, monitor) {
const dropTarget = useMemo(()=>new DropTargetImpl(spec, monitor)
, [
monitor
]);
useEffect(()=>{
dropTarget.spec = spec;
}, [
spec
]);
return dropTarget;
}
function useRegisteredDropTarget(spec, monitor, connector) {
const manager = useDragDropManager();
const dropTarget = useDropTarget(spec, monitor);
const accept = useAccept(spec);
useIsomorphicLayoutEffect(function registerDropTarget() {
const [handlerId, unregister] = registerTarget(accept, dropTarget, manager);
monitor.receiveHandlerId(handlerId);
connector.receiveHandlerId(handlerId);
return unregister;
}, [
manager,
monitor,
dropTarget,
connector,
accept.map((a)=>a.toString()
).join('|'),
]);
}
/**
* useDropTarget Hook
* @param spec The drop target specification (object or function, function preferred)
* @param deps The memoization deps array to use when evaluating spec changes
*/ function useDrop(specArg, deps) {
const spec = useOptionalFactory(specArg, deps);
const monitor = useDropTargetMonitor();
const connector = useDropTargetConnector(spec.options);
useRegisteredDropTarget(spec, monitor, connector);
return [
useCollectedProps(spec.collect, monitor, connector),
useConnectDropTarget(connector),
];
}
// cheap lodash replacements
function memoize(fn) {
let result = null;
const memoized = ()=>{
if (result == null) {
result = fn();
}
return result;
};
return memoized;
}
/**
* drop-in replacement for _.without
*/ function without(items, item) {
return items.filter((i)=>i !== item
);
}
function union(itemsA, itemsB) {
const set = new Set();
const insertItem = (item)=>set.add(item)
;
itemsA.forEach(insertItem);
itemsB.forEach(insertItem);
const result = [];
set.forEach((key)=>result.push(key)
);
return result;
}
class EnterLeaveCounter {
enter(enteringNode) {
const previousLength = this.entered.length;
const isNodeEntered = (node)=>this.isNodeInDocument(node) && (!node.contains || node.contains(enteringNode))
;
this.entered = union(this.entered.filter(isNodeEntered), [
enteringNode
]);
return previousLength === 0 && this.entered.length > 0;
}
leave(leavingNode) {
const previousLength = this.entered.length;
this.entered = without(this.entered.filter(this.isNodeInDocument), leavingNode);
return previousLength > 0 && this.entered.length === 0;
}
reset() {
this.entered = [];
}
constructor(isNodeInDocument){
this.entered = [];
this.isNodeInDocument = isNodeInDocument;
}
}
class NativeDragSource {
initializeExposedProperties() {
Object.keys(this.config.exposeProperties).forEach((property)=>{
Object.defineProperty(this.item, property, {
configurable: true,
enumerable: true,
get () {
// eslint-disable-next-line no-console
console.warn(`Browser doesn't allow reading "${property}" until the drop event.`);
return null;
}
});
});
}
loadDataTransfer(dataTransfer) {
if (dataTransfer) {
const newProperties = {};
Object.keys(this.config.exposeProperties).forEach((property)=>{
const propertyFn = this.config.exposeProperties[property];
if (propertyFn != null) {
newProperties[property] = {
value: propertyFn(dataTransfer, this.config.matchesTypes),
configurable: true,
enumerable: true
};
}
});
Object.defineProperties(this.item, newProperties);
}
}
canDrag() {
return true;
}
beginDrag() {
return this.item;
}
isDragging(monitor, handle) {
return handle === monitor.getSourceId();
}
endDrag() {
// empty
}
constructor(config){
this.config = config;
this.item = {};
this.initializeExposedProperties();
}
}
const FILE = '__NATIVE_FILE__';
const URL = '__NATIVE_URL__';
const TEXT = '__NATIVE_TEXT__';
const HTML = '__NATIVE_HTML__';
var NativeTypes = /*#__PURE__*/Object.freeze({
__proto__: null,
FILE: FILE,
URL: URL,
TEXT: TEXT,
HTML: HTML
});
function getDataFromDataTransfer(dataTransfer, typesToTry, defaultValue) {
const result = typesToTry.reduce((resultSoFar, typeToTry)=>resultSoFar || dataTransfer.getData(typeToTry)
, '');
return result != null ? result : defaultValue;
}
const nativeTypesConfig = {
[FILE]: {
exposeProperties: {
files: (dataTransfer)=>Array.prototype.slice.call(dataTransfer.files)
,
items: (dataTransfer)=>dataTransfer.items
,
dataTransfer: (dataTransfer)=>dataTransfer
},
matchesTypes: [
'Files'
]
},
[HTML]: {
exposeProperties: {
html: (dataTransfer, matchesTypes)=>getDataFromDataTransfer(dataTransfer, matchesTypes, '')
,
dataTransfer: (dataTransfer)=>dataTransfer
},
matchesTypes: [
'Html',
'text/html'
]
},
[URL]: {
exposeProperties: {
urls: (dataTransfer, matchesTypes)=>getDataFromDataTransfer(dataTransfer, matchesTypes, '').split('\n')
,
dataTransfer: (dataTransfer)=>dataTransfer
},
matchesTypes: [
'Url',
'text/uri-list'
]
},
[TEXT]: {
exposeProperties: {
text: (dataTransfer, matchesTypes)=>getDataFromDataTransfer(dataTransfer, matchesTypes, '')
,
dataTransfer: (dataTransfer)=>dataTransfer
},
matchesTypes: [
'Text',
'text/plain'
]
}
};
function createNativeDragSource(type, dataTransfer) {
const config = nativeTypesConfig[type];
if (!config) {
throw new Error(`native type ${type} has no configuration`);
}
const result = new NativeDragSource(config);
result.loadDataTransfer(dataTransfer);
return result;
}
function matchNativeItemType(dataTransfer) {
if (!dataTransfer) {
return null;
}
const dataTransferTypes = Array.prototype.slice.call(dataTransfer.types || []);
return Object.keys(nativeTypesConfig).filter((nativeItemType)=>{
const typeConfig = nativeTypesConfig[nativeItemType];
if (!(typeConfig === null || typeConfig === void 0 ? void 0 : typeConfig.matchesTypes)) {
return false;
}
return typeConfig.matchesTypes.some((t)=>dataTransferTypes.indexOf(t) > -1
);
})[0] || null;
}
const isFirefox = memoize(()=>/firefox/i.test(navigator.userAgent)
);
const isSafari = memoize(()=>Boolean(window.safari)
);
class MonotonicInterpolant {
interpolate(x) {
const { xs , ys , c1s , c2s , c3s } = this;
// The rightmost point in the dataset should give an exact result
let i = xs.length - 1;
if (x === xs[i]) {
return ys[i];
}
// Search for the interval x is in, returning the corresponding y if x is one of the original xs
let low = 0;
let high = c3s.length - 1;
let mid;
while(low <= high){
mid = Math.floor(0.5 * (low + high));
const xHere = xs[mid];
if (xHere < x) {
low = mid + 1;
} else if (xHere > x) {
high = mid - 1;
} else {
return ys[mid];
}
}
i = Math.max(0, high);
// Interpolate
const diff = x - xs[i];
const diffSq = diff * diff;
return ys[i] + c1s[i] * diff + c2s[i] * diffSq + c3s[i] * diff * diffSq;
}
constructor(xs, ys){
const { length } = xs;
// Rearrange xs and ys so that xs is sorted
const indexes = [];
for(let i = 0; i < length; i++){
indexes.push(i);
}
indexes.sort((a, b)=>xs[a] < xs[b] ? -1 : 1
);
const dxs = [];
const ms = [];
let dx;
let dy;
for(let i1 = 0; i1 < length - 1; i1++){
dx = xs[i1 + 1] - xs[i1];
dy = ys[i1 + 1] - ys[i1];
dxs.push(dx);
ms.push(dy / dx);
}
// Get degree-1 coefficients
const c1s = [
ms[0]
];
for(let i2 = 0; i2 < dxs.length - 1; i2++){
const m2 = ms[i2];
const mNext = ms[i2 + 1];
if (m2 * mNext <= 0) {
c1s.push(0);
} else {
dx = dxs[i2];
const dxNext = dxs[i2 + 1];
const common = dx + dxNext;
c1s.push(3 * common / ((common + dxNext) / m2 + (common + dx) / mNext));
}
}
c1s.push(ms[ms.length - 1]);
// Get degree-2 and degree-3 coefficients
const c2s = [];
const c3s = [];
let m;
for(let i3 = 0; i3 < c1s.length - 1; i3++){
m = ms[i3];
const c1 = c1s[i3];
const invDx = 1 / dxs[i3];
const common = c1 + c1s[i3 + 1] - m - m;
c2s.push((m - c1 - common) * invDx);
c3s.push(common * invDx * invDx);
}
this.xs = xs;
this.ys = ys;
this.c1s = c1s;
this.c2s = c2s;
this.c3s = c3s;
}
}
const ELEMENT_NODE = 1;
function getNodeClientOffset(node) {
const el = node.nodeType === ELEMENT_NODE ? node : node.parentElement;
if (!el) {
return null;
}
const { top , left } = el.getBoundingClientRect();
return {
x: left,
y: top
};
}
function getEventClientOffset(e) {
return {
x: e.clientX,
y: e.clientY
};
}
function isImageNode(node) {
var ref;
return node.nodeName === 'IMG' && (isFirefox() || !((ref = document.documentElement) === null || ref === void 0 ? void 0 : ref.contains(node)));
}
function getDragPreviewSize(isImage, dragPreview, sourceWidth, sourceHeight) {
let dragPreviewWidth = isImage ? dragPreview.width : sourceWidth;
let dragPreviewHeight = isImage ? dragPreview.height : sourceHeight;
// Work around @2x coordinate discrepancies in browsers
if (isSafari() && isImage) {
dragPreviewHeight /= window.devicePixelRatio;
dragPreviewWidth /= window.devicePixelRatio;
}
return {
dragPreviewWidth,
dragPreviewHeight
};
}
function getDragPreviewOffset(sourceNode, dragPreview, clientOffset, anchorPoint, offsetPoint) {
// The browsers will use the image intrinsic size under different conditions.
// Firefox only cares if it's an image, but WebKit also wants it to be detached.
const isImage = isImageNode(dragPreview);
const dragPreviewNode = isImage ? sourceNode : dragPreview;
const dragPreviewNodeOffsetFromClient = getNodeClientOffset(dragPreviewNode);
const offsetFromDragPreview = {
x: clientOffset.x - dragPreviewNodeOffsetFromClient.x,
y: clientOffset.y - dragPreviewNodeOffsetFromClient.y
};
const { offsetWidth: sourceWidth , offsetHeight: sourceHeight } = sourceNode;
const { anchorX , anchorY } = anchorPoint;
const { dragPreviewWidth , dragPreviewHeight } = getDragPreviewSize(isImage, dragPreview, sourceWidth, sourceHeight);
const calculateYOffset = ()=>{
const interpolantY = new MonotonicInterpolant([
0,
0.5,
1
], [
// Dock to the top
offsetFromDragPreview.y,
// Align at the center
(offsetFromDragPreview.y / sourceHeight) * dragPreviewHeight,
// Dock to the bottom
offsetFromDragPreview.y + dragPreviewHeight - sourceHeight,
]);
let y = interpolantY.interpolate(anchorY);
// Work around Safari 8 positioning bug
if (isSafari() && isImage) {
// We'll have to wait for @3x to see if this is entirely correct
y += (window.devicePixelRatio - 1) * dragPreviewHeight;
}
return y;
};
const calculateXOffset = ()=>{
// Interpolate coordinates depending on anchor point
// If you know a simpler way to do this, let me know
const interpolantX = new MonotonicInterpolant([
0,
0.5,
1
], [
// Dock to the left
offsetFromDragPreview.x,
// Align at the center
(offsetFromDragPreview.x / sourceWidth) * dragPreviewWidth,
// Dock to the right
offsetFromDragPreview.x + dragPreviewWidth - sourceWidth,
]);
return interpolantX.interpolate(anchorX);
};
// Force offsets if specified in the options.
const { offsetX , offsetY } = offsetPoint;
const isManualOffsetX = offsetX === 0 || offsetX;
const isManualOffsetY = offsetY === 0 || offsetY;
return {
x: isManualOffsetX ? offsetX : calculateXOffset(),
y: isManualOffsetY ? offsetY : calculateYOffset()
};
}
class OptionsReader {
get window() {
if (this.globalContext) {
return this.globalContext;
} else if (typeof window !== 'undefined') {
return window;
}
return undefined;
}
get document() {
var ref;
if ((ref = this.globalContext) === null || ref === void 0 ? void 0 : ref.document) {
return this.globalContext.document;
} else if (this.window) {
return this.window.document;
} else {
return undefined;
}
}
get rootElement() {
var ref;
return ((ref = this.optionsArgs) === null || ref === void 0 ? void 0 : ref.rootElement) || this.window;
}
constructor(globalContext, options){
this.ownerDocument = null;
this.globalContext = globalContext;
this.optionsArgs = options;
}
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
class HTML5BackendImpl {
/**
* Generate profiling statistics for the HTML5Backend.
*/ profile() {
var ref, ref1;
return {
sourcePreviewNodes: this.sourcePreviewNodes.size,
sourcePreviewNodeOptions: this.sourcePreviewNodeOptions.size,
sourceNodeOptions: this.sourceNodeOptions.size,
sourceNodes: this.sourceNodes.size,
dragStartSourceIds: ((ref = this.dragStartSourceIds) === null || ref === void 0 ? void 0 : ref.length) || 0,
dropTargetIds: this.dropTargetIds.length,
dragEnterTargetIds: this.dragEnterTargetIds.length,
dragOverTargetIds: ((ref1 = this.dragOverTargetIds) === null || ref1 === void 0 ? void 0 : ref1.length) || 0
};
}
// public for test
get window() {
return this.options.window;
}
get document() {
return this.options.document;
}
/**
* Get the root element to use for event subscriptions
*/ get rootElement() {
return this.options.rootElement;
}
setup() {
const root = this.rootElement;
if (root === undefined) {
return;
}
if (root.__isReactDndBackendSetUp) {
throw new Error('Cannot have two HTML5 backends at the same time.');
}
root.__isReactDndBackendSetUp = true;
this.addEventListeners(root);
}
teardown() {
const root = this.rootElement;
if (root === undefined) {
return;
}
root.__isReactDndBackendSetUp = false;
this.removeEventListeners(this.rootElement);
this.clearCurrentDragSourceNode();
if (this.asyncEndDragFrameId) {
var ref;
(ref = this.window) === null || ref === void 0 ? void 0 : ref.cancelAnimationFrame(this.asyncEndDragFrameId);
}
}
connectDragPreview(sourceId, node, options) {
this.sourcePreviewNodeOptions.set(sourceId, options);
this.sourcePreviewNodes.set(sourceId, node);
return ()=>{
this.sourcePreviewNodes.delete(sourceId);
this.sourcePreviewNodeOptions.delete(sourceId);
};
}
connectDragSource(sourceId, node, options) {
this.sourceNodes.set(sourceId, node);
this.sourceNodeOptions.set(sourceId, options);
const handleDragStart = (e)=>this.handleDragStart(e, sourceId)
;
const handleSelectStart = (e)=>this.handleSelectStart(e)
;
node.setAttribute('draggable', 'true');
node.addEventListener('dragstart', handleDragStart);
node.addEventListener('selectstart', handleSelectStart);
return ()=>{
this.sourceNodes.delete(sourceId);
this.sourceNodeOptions.delete(sourceId);
node.removeEventListener('dragstart', handleDragStart);
node.removeEventListener('selectstart', handleSelectStart);
node.setAttribute('draggable', 'false');
};
}
connectDropTarget(targetId, node) {
const handleDragEnter = (e)=>this.handleDragEnter(e, targetId)
;
const handleDragOver = (e)=>this.handleDragOver(e, targetId)
;
const handleDrop = (e)=>this.handleDrop(e, targetId)
;
node.addEventListener('dragenter', handleDragEnter);
node.addEventListener('dragover', handleDragOver);
node.addEventListener('drop', handleDrop);
return ()=>{
node.removeEventListener('dragenter', handleDragEnter);
node.removeEventListener('dragover', handleDragOver);
node.removeEventListener('drop', handleDrop);
};
}
addEventListeners(target) {
// SSR Fix (https://github.com/react-dnd/react-dnd/pull/813
if (!target.addEventListener) {
return;
}
target.addEventListener('dragstart', this.handleTopDragStart);
target.addEventListener('dragstart', this.handleTopDragStartCapture, true);
target.addEventListener('dragend', this.handleTopDragEndCapture, true);
target.addEventListener('dragenter', this.handleTopDragEnter);
target.addEventListener('dragenter', this.handleTopDragEnterCapture, true);
target.addEventListener('dragleave', this.handleTopDragLeaveCapture, true);
target.addEventListener('dragover', this.handleTopDragOver);
target.addEventListener('dragover', this.handleTopDragOverCapture, true);
target.addEventListener('drop', this.handleTopDrop);
target.addEventListener('drop', this.handleTopDropCapture, true);
}
removeEventListeners(target) {
// SSR Fix (https://github.com/react-dnd/react-dnd/pull/813
if (!target.removeEventListener) {
return;
}
target.removeEventListener('dragstart', this.handleTopDragStart);
target.removeEventListener('dragstart', this.handleTopDragStartCapture, true);
target.removeEventListener('dragend', this.handleTopDragEndCapture, true);
target.removeEventListener('dragenter', this.handleTopDragEnter);
target.removeEventListener('dragenter', this.handleTopDragEnterCapture, true);
target.removeEventListener('dragleave', this.handleTopDragLeaveCapture, true);
target.removeEventListener('dragover', this.handleTopDragOver);
target.removeEventListener('dragover', this.handleTopDragOverCapture, true);
target.removeEventListener('drop', this.handleTopDrop);
target.removeEventListener('drop', this.handleTopDropCapture, true);
}
getCurrentSourceNodeOptions() {
const sourceId = this.monitor.getSourceId();
const sourceNodeOptions = this.sourceNodeOptions.get(sourceId);
return _objectSpread({
dropEffect: this.altKeyPressed ? 'copy' : 'move'
}, sourceNodeOptions || {});
}
getCurrentDropEffect() {
if (this.isDraggingNativeItem()) {
// It makes more sense to default to 'copy' for native resources
return 'copy';
}
return this.getCurrentSourceNodeOptions().dropEffect;
}
getCurrentSourcePreviewNodeOptions() {
const sourceId = this.monitor.getSourceId();
const sourcePreviewNodeOptions = this.sourcePreviewNodeOptions.get(sourceId);
return _objectSpread({
anchorX: 0.5,
anchorY: 0.5,
captureDraggingState: false
}, sourcePreviewNodeOptions || {});
}
isDraggingNativeItem() {
const itemType = this.monitor.getItemType();
return Object.keys(NativeTypes).some((key)=>NativeTypes[key] === itemType
);
}
beginDragNativeItem(type, dataTransfer) {
this.clearCurrentDragSourceNode();
this.currentNativeSource = createNativeDragSource(type, dataTransfer);
this.currentNativeHandle = this.registry.addSource(type, this.currentNativeSource);
this.actions.beginDrag([
this.currentNativeHandle
]);
}
setCurrentDragSourceNode(node) {
this.clearCurrentDragSourceNode();
this.currentDragSourceNode = node;
// A timeout of > 0 is necessary to resolve Firefox issue referenced
// See:
// * https://github.com/react-dnd/react-dnd/pull/928
// * https://github.com/react-dnd/react-dnd/issues/869
const MOUSE_MOVE_TIMEOUT = 1000;
// Receiving a mouse event in the middle of a dragging operation
// means it has ended and the drag source node disappeared from DOM,
// so the browser didn't dispatch the dragend event.
//
// We need to wait before we start listening for mousemove events.
// This is needed because the drag preview needs to be drawn or else it fires an 'mousemove' event
// immediately in some browsers.
//
// See:
// * https://github.com/react-dnd/react-dnd/pull/928
// * https://github.com/react-dnd/react-dnd/issues/869
//
this.mouseMoveTimeoutTimer = setTimeout(()=>{
var ref;
return (ref = this.rootElement) === null || ref === void 0 ? void 0 : ref.addEventListener('mousemove', this.endDragIfSourceWasRemovedFromDOM, true);
}, MOUSE_MOVE_TIMEOUT);
}
clearCurrentDragSourceNode() {
if (this.currentDragSourceNode) {
this.currentDragSourceNode = null;
if (this.rootElement) {
var ref;
(ref = this.window) === null || ref === void 0 ? void 0 : ref.clearTimeout(this.mouseMoveTimeoutTimer || undefined);
this.rootElement.removeEventListener('mousemove', this.endDragIfSourceWasRemovedFromDOM, true);
}
this.mouseMoveTimeoutTimer = null;
return true;
}
return false;
}
handleDragStart(e, sourceId) {
if (e.defaultPrevented) {
return;
}
if (!this.dragStartSourceIds) {
this.dragStartSourceIds = [];
}
this.dragStartSourceIds.unshift(sourceId);
}
handleDragEnter(_e, targetId) {
this.dragEnterTargetIds.unshift(targetId);
}
handleDragOver(_e, targetId) {
if (this.dragOverTargetIds === null) {
this.dragOverTargetIds = [];
}
this.dragOverTargetIds.unshift(targetId);
}
handleDrop(_e, targetId) {
this.dropTargetIds.unshift(targetId);
}
constructor(manager, globalContext, options){
this.sourcePreviewNodes = new Map();
this.sourcePreviewNodeOptions = new Map();
this.sourceNodes = new Map();
this.sourceNodeOptions = new Map();
this.dragStartSourceIds = null;
this.dropTargetIds = [];
this.dragEnterTargetIds = [];
this.currentNativeSource = null;
this.currentNativeHandle = null;
this.currentDragSourceNode = null;
this.altKeyPressed = false;
this.mouseMoveTimeoutTimer = null;
this.asyncEndDragFrameId = null;
this.dragOverTargetIds = null;
this.lastClientOffset = null;
this.hoverRafId = null;
this.getSourceClientOffset = (sourceId)=>{
const source = this.sourceNodes.get(sourceId);
return source && getNodeClientOffset(source) || null;
};
this.endDragNativeItem = ()=>{
if (!this.isDraggingNativeItem()) {
return;
}
this.actions.endDrag();
if (this.currentNativeHandle) {
this.registry.removeSource(this.currentNativeHandle);
}
this.currentNativeHandle = null;
this.currentNativeSource = null;
};
this.isNodeInDocument = (node)=>{
// Check the node either in the main document or in the current context
return Boolean(node && this.document && this.document.body && this.document.body.contains(node));
};
this.endDragIfSourceWasRemovedFromDOM = ()=>{
const node = this.currentDragSourceNode;
if (node == null || this.isNodeInDocument(node)) {
return;
}
if (this.clearCurrentDragSourceNode() && this.monitor.isDragging()) {
this.actions.endDrag();
}
this.cancelHover();
};
this.scheduleHover = (dragOverTargetIds)=>{
if (this.hoverRafId === null && typeof requestAnimationFrame !== 'undefined') {
this.hoverRafId = requestAnimationFrame(()=>{
if (this.monitor.isDragging()) {
this.actions.hover(dragOverTargetIds || [], {
clientOffset: this.lastClientOffset
});
}
this.hoverRafId = null;
});
}
};
this.cancelHover = ()=>{
if (this.hoverRafId !== null && typeof cancelAnimationFrame !== 'undefined') {
cancelAnimationFrame(this.hoverRafId);
this.hoverRafId = null;
}
};
this.handleTopDragStartCapture = ()=>{
this.clearCurrentDragSourceNode();
this.dragStartSourceIds = [];
};
this.handleTopDragStart = (e)=>{
if (e.defaultPrevented) {
return;
}
const { dragStartSourceIds } = this;
this.dragStartSourceIds = null;
const clientOffset = getEventClientOffset(e);
// Avoid crashing if we missed a drop event or our previous drag died
if (this.monitor.isDragging()) {
this.actions.endDrag();
this.cancelHover();
}
// Don't publish the source just yet (see why below)
this.actions.beginDrag(dragStartSourceIds || [], {
publishSource: false,
getSourceClientOffset: this.getSourceClientOffset,
clientOffset
});
const { dataTransfer } = e;
const nativeType = matchNativeItemType(dataTransfer);
if (this.monitor.isDragging()) {
if (dataTransfer && typeof dataTransfer.setDragImage === 'function') {
// Use custom drag image if user specifies it.
// If child drag source refuses drag but parent agrees,
// use parent's node as drag image. Neither works in IE though.
const sourceId = this.monitor.getSourceId();
const sourceNode = this.sourceNodes.get(sourceId);
const dragPreview = this.sourcePreviewNodes.get(sourceId) || sourceNode;
if (dragPreview) {
const { anchorX , anchorY , offsetX , offsetY } = this.getCurrentSourcePreviewNodeOptions();
const anchorPoint = {
anchorX,
anchorY
};
const offsetPoint = {
offsetX,
offsetY
};
const dragPreviewOffset = getDragPreviewOffset(sourceNode, dragPreview, clientOffset, anchorPoint, offsetPoint);
dataTransfer.setDragImage(dragPreview, dragPreviewOffset.x, dragPreviewOffset.y);
}
}
try {
// Firefox won't drag without setting data
dataTransfer === null || dataTransfer === void 0 ? void 0 : dataTransfer.setData('application/json', {});
} catch (err) {
// IE doesn't support MIME types in setData
}
// Store drag source node so we can check whether
// it is removed from DOM and trigger endDrag manually.
this.setCurrentDragSourceNode(e.target);
// Now we are ready to publish the drag source.. or are we not?
const { captureDraggingState } = this.getCurrentSourcePreviewNodeOptions();
if (!captureDraggingState) {
// Usually we want to publish it in the next tick so that browser
// is able to screenshot the current (not yet dragging) state.
//
// It also neatly avoids a situation where render() returns null
// in the same tick for the source element, and browser freaks out.
setTimeout(()=>this.actions.publishDragSource()
, 0);
} else {
// In some cases the user may want to override this behavior, e.g.
// to work around IE not supporting custom drag previews.
//
// When using a custom drag layer, the only way to prevent
// the default drag preview from drawing in IE is to screenshot
// the dragging state in which the node itself has zero opacity
// and height. In this case, though, returning null from render()
// will abruptly end the dragging, which is not obvious.
//
// This is the reason such behavior is strictly opt-in.
this.actions.publishDragSource();
}
} else if (nativeType) {
// A native item (such as URL) dragged from inside the document
this.beginDragNativeItem(nativeType);
} else if (dataTransfer && !dataTransfer.types && (e.target && !e.target.hasAttribute || !e.target.hasAttribute('draggable'))) {
// Looks like a Safari bug: dataTransfer.types is null, but there was no draggable.
// Just let it drag. It's a native type (URL or text) and will be picked up in
// dragenter handler.
return;
} else {
// If by this time no drag source reacted, tell browser not to drag.
e.preventDefault();
}
};
this.handleTopDragEndCapture = ()=>{
if (this.clearCurrentDragSourceNode() && this.monitor.isDragging()) {
// Firefox can dispatch this event in an infinite loop
// if dragend handler does something like showing an alert.
// Only proceed if we have not handled it already.
this.actions.endDrag();
}
this.cancelHover();
};
this.handleTopDragEnterCapture = (e)=>{
this.dragEnterTargetIds = [];
if (this.isDraggingNativeItem()) {
var ref;
(ref = this.currentNativeSource) === null || ref === void 0 ? void 0 : ref.loadDataTransfer(e.dataTransfer);
}
const isFirstEnter = this.enterLeaveCounter.enter(e.target);
if (!isFirstEnter || this.monitor.isDragging()) {
return;
}
const { dataTransfer } = e;
const nativeType = matchNativeItemType(dataTransfer);
if (nativeType) {
// A native item (such as file or URL) dragged from outside the document
this.beginDragNativeItem(nativeType, dataTransfer);
}
};
this.handleTopDragEnter = (e)=>{
const { dragEnterTargetIds } = this;
this.dragEnterTargetIds = [];
if (!this.monitor.isDragging()) {
// This is probably a native item type we don't understand.
return;
}
this.altKeyPressed = e.altKey;
// If the target changes position as the result of `dragenter`, `dragover` might still
// get dispatched despite target being no longer there. The easy solution is to check
// whether there actually is a target before firing `hover`.
if (dragEnterTargetIds.length > 0) {
this.actions.hover(dragEnterTargetIds, {
clientOffset: getEventClientOffset(e)
});
}
const canDrop = dragEnterTargetIds.some((targetId)=>this.monitor.canDropOnTarget(targetId)
);
if (canDrop) {
// IE requires this to fire dragover events
e.preventDefault();
if (e.dataTransfer) {
e.dataTransfer.dropEffect = this.getCurrentDropEffect();
}
}
};
this.handleTopDragOverCapture = (e)=>{
this.dragOverTargetIds = [];
if (this.isDraggingNativeItem()) {
var ref;
(ref = this.currentNativeSource) === null || ref === void 0 ? void 0 : ref.loadDataTransfer(e.dataTransfer);
}
};
this.handleTopDragOver = (e)=>{
const { dragOverTargetIds } = this;
this.dragOverTargetIds = [];
if (!this.monitor.isDragging()) {
// This is probably a native item type we don't understand.
// Prevent default "drop and blow away the whole document" action.
e.preventDefault();
if (e.dataTransfer) {
e.dataTransfer.dropEffect = 'none';
}
return;
}
this.altKeyPressed = e.altKey;
this.lastClientOffset = getEventClientOffset(e);
this.scheduleHover(dragOverTargetIds);
const canDrop = (dragOverTargetIds || []).some((targetId)=>this.monitor.canDropOnTarget(targetId)
);
if (canDrop) {
// Show user-specified drop effect.
e.preventDefault();
if (e.dataTransfer) {
e.dataTransfer.dropEffect = this.getCurrentDropEffect();
}
} else if (this.isDraggingNativeItem()) {
// Don't show a nice cursor but still prevent default
// "drop and blow away the whole document" action.
e.preventDefault();
} else {
e.preventDefault();
if (e.dataTransfer) {
e.dataTransfer.dropEffect = 'none';
}
}
};
this.handleTopDragLeaveCapture = (e)=>{
if (this.isDraggingNativeItem()) {
e.preventDefault();
}
const isLastLeave = this.enterLeaveCounter.leave(e.target);
if (!isLastLeave) {
return;
}
if (this.isDraggingNativeItem()) {
setTimeout(()=>this.endDragNativeItem()
, 0);
}
this.cancelHover();
};
this.handleTopDropCapture = (e)=>{
this.dropTargetIds = [];
if (this.isDraggingNativeItem()) {
var ref;
e.preventDefault();
(ref = this.currentNativeSource) === null || ref === void 0 ? void 0 : ref.loadDataTransfer(e.dataTransfer);
} else if (matchNativeItemType(e.dataTransfer)) {
// Dragging some elements, like <a> and <img> may still behave like a native drag event,
// even if the current drag event matches a user-defined type.
// Stop the default behavior when we're not expecting a native item to be dropped.
e.preventDefault();
}
this.enterLeaveCounter.reset();
};
this.handleTopDrop = (e)=>{
const { dropTargetIds } = this;
this.dropTargetIds = [];
this.actions.hover(dropTargetIds, {
clientOffset: getEventClientOffset(e)
});
this.actions.drop({
dropEffect: this.getCurrentDropEffect()
});
if (this.isDraggingNativeItem()) {
this.endDragNativeItem();
} else if (this.monitor.isDragging()) {
this.actions.endDrag();
}
this.cancelHover();
};
this.handleSelectStart = (e)=>{
const target = e.target;
// Only IE requires us to explicitly say
// we want drag drop operation to start
if (typeof target.dragDrop !== 'function') {
return;
}
// Inputs and textareas should be selectable
if (target.tagName === 'INPUT' || target.tagName === 'SELECT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
return;
}
// For other targets, ask IE
// to enable drag and drop
e.preventDefault();
target.dragDrop();
};
this.options = new OptionsReader(globalContext, options);
this.actions = manager.getActions();
this.monitor = manager.getMonitor();
this.registry = manager.getRegistry();
this.enterLeaveCounter = new EnterLeaveCounter(this.isNodeInDocument);
}
}
const HTML5Backend = function createBackend(manager, context, options) {
return new HTML5BackendImpl(manager, context, options);
};
var theme = createTheme$1({
palette: {
drop: {
main: alpha('#303f9f', 0.5),
light: alpha('#303f9f', 0.35),
mainTwo: alpha('#5e35b1', 0.5),
lightTwo: alpha('#5e35b1', 0.35)
},
slotBg: {
main: 'transparent'
},
drag: {
main: '#E0E0E0'
},
borderRightColor: {
main: '#666666',
light: 'rgba(0, 0, 0, 0.05)'
}
}
});
var SchedulerContext = /*#__PURE__*/createContext();
var SchedulerProvider = function SchedulerProvider(props) {
var children = props.children,
SlotProps = props.SlotProps,
AppointmentProps = props.AppointmentProps,
groupId = props.groupId,
groups = props.groups,
users = props.users,
onGroupChange = props.onGroupChange,
appointmentList = props.appointmentList,
onAppointmentChange = props.onAppointmentChange,
durationOptions = props.durationOptions,
_props$duration = props.duration,
duration = _props$duration === void 0 ? 60 : _props$duration,
onDurationChange = props.onDurationChange,
date = props.date,
onDateChange = props.onDateChange,
onPrevDate = props.onPrevDate,
onNextDate = props.onNextDate,
color = props.color,
resourceLabel = props.resourceLabel,
isLoading = props.isLoading,
customCanDrop = props.customCanDrop,
groupLabel = props.groupLabel,
onAppointmentClick = props.onAppointmentClick;
var locales = {
en: enUS
};
var value = {
groupId: groupId,
groups: groups,
users: users,
onGroupChange: onGroupChange,
appointmentList: appointmentList,
onAppointmentChange: onAppointmentChange,
durationOptions: durationOptions,
duration: duration,
onDurationChange: onDurationChange,
date: date,
onDateChange: onDateChange,
onPrevDate: onPrevDate,
onNextDate: onNextDate,
SlotProps: SlotProps,
AppointmentProps: AppointmentProps,
color: color,
resourceLabel: resourceLabel,
customCanDrop: customCanDrop,
isLoading: isLoading,
groupLabel: groupLabel,
onAppointmentClick: onAppointmentClick
};
return /*#__PURE__*/React__default.createElement(DndProvider, {
backend: HTML5Backend
}, /*#__PURE__*/React__default.createElement(SchedulerContext.Provider, {
value: value
}, /*#__PURE__*/React__default.createElement(ThemeProvider, {
theme: color || theme
}, /*#__PURE__*/React__default.createElement(LocalizationProvider, {
dateAdapter: AdapterDateFns,
adapterLocale: locales['en']
}, children))));
};
var useSchedulerContext = function useSchedulerContext() {
return useContext(SchedulerContext);
};
function commonjsRequire(path) {
throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
}
var moment$1 = {exports: {}};
moment$1.exports;
(function (module, exports) {
(function (global, factory) {
module.exports = factory() ;
}(commonjsGlobal, (function () {
var hookCallback;
function hooks() {
return hookCallback.apply(null, arguments);
}
// This is done to register the method called with moment()
// without creating circular dependencies.
function setHookCallback(callback) {
hookCallback = callback;
}
function isArray(input) {
return (
input instanceof Array ||
Object.prototype.toString.call(input) === '[object Array]'
);
}
function isObject(input) {
// IE8 will treat undefined and null as object if it wasn't for
// input != null
return (
input != null &&
Object.prototype.toString.call(input) === '[object Object]'
);
}
function hasOwnProp(a, b) {
return Object.prototype.hasOwnProperty.call(a, b);
}
function isObjectEmpty(obj) {
if (Object.getOwnPropertyNames) {
return Object.getOwnPropertyNames(obj).length === 0;
} else {
var k;
for (k in obj) {
if (hasOwnProp(obj, k)) {
return false;
}
}
return true;
}
}
function isUndefined(input) {
return input === void 0;
}
function isNumber(input) {
return (
typeof input === 'number' ||
Object.prototype.toString.call(input) === '[object Number]'
);
}
function isDate(input) {
return (
input instanceof Date ||
Object.prototype.toString.call(input) === '[object Date]'
);
}
function map(arr, fn) {
var res = [],
i,
arrLen = arr.length;
for (i = 0; i < arrLen; ++i) {
res.push(fn(arr[i], i));
}
return res;
}
function extend(a, b) {
for (var i in b) {
if (hasOwnProp(b, i)) {
a[i] = b[i];
}
}
if (hasOwnProp(b, 'toString')) {
a.toString = b.toString;
}
if (hasOwnProp(b, 'valueOf')) {
a.valueOf = b.valueOf;
}
return a;
}
function createUTC(input, format, locale, strict) {
return createLocalOrUTC(input, format, locale, strict, true).utc();
}
function defaultParsingFlags() {
// We need to deep clone this object.
return {
empty: false,
unusedTokens: [],
unusedInput: [],
overflow: -2,
charsLeftOver: 0,
nullInput: false,
invalidEra: null,
invalidMonth: null,
invalidFormat: false,
userInvalidated: false,
iso: false,
parsedDateParts: [],
era: null,
meridiem: null,
rfc2822: false,
weekdayMismatch: false,
};
}
function getParsingFlags(m) {
if (m._pf == null) {
m._pf = defaultParsingFlags();
}
return m._pf;
}
var some;
if (Array.prototype.some) {
some = Array.prototype.some;
} else {
some = function (fun) {
var t = Object(this),
len = t.length >>> 0,
i;
for (i = 0; i < len; i++) {
if (i in t && fun.call(this, t[i], i, t)) {
return true;
}
}
return false;
};
}
function isValid(m) {
var flags = null,
parsedParts = false,
isNowValid = m._d && !isNaN(m._d.getTime());
if (isNowValid) {
flags = getParsingFlags(m);
parsedParts = some.call(flags.parsedDateParts, function (i) {
return i != null;
});
isNowValid =
flags.overflow < 0 &&
!flags.empty &&
!flags.invalidEra &&
!flags.invalidMonth &&
!flags.invalidWeekday &&
!flags.weekdayMismatch &&
!flags.nullInput &&
!flags.invalidFormat &&
!flags.userInvalidated &&
(!flags.meridiem || (flags.meridiem && parsedParts));
if (m._strict) {
isNowValid =
isNowValid &&
flags.charsLeftOver === 0 &&
flags.unusedTokens.length === 0 &&
flags.bigHour === undefined;
}
}
if (Object.isFrozen == null || !Object.isFrozen(m)) {
m._isValid = isNowValid;
} else {
return isNowValid;
}
return m._isValid;
}
function createInvalid(flags) {
var m = createUTC(NaN);
if (flags != null) {
extend(getParsingFlags(m), flags);
} else {
getParsingFlags(m).userInvalidated = true;
}
return m;
}
// Plugins that add properties should also add the key here (null value),
// so we can properly clone ourselves.
var momentProperties = (hooks.momentProperties = []),
updateInProgress = false;
function copyConfig(to, from) {
var i,
prop,
val,
momentPropertiesLen = momentProperties.length;
if (!isUndefined(from._isAMomentObject)) {
to._isAMomentObject = from._isAMomentObject;
}
if (!isUndefined(from._i)) {
to._i = from._i;
}
if (!isUndefined(from._f)) {
to._f = from._f;
}
if (!isUndefined(from._l)) {
to._l = from._l;
}
if (!isUndefined(from._strict)) {
to._strict = from._strict;
}
if (!isUndefined(from._tzm)) {
to._tzm = from._tzm;
}
if (!isUndefined(from._isUTC)) {
to._isUTC = from._isUTC;
}
if (!isUndefined(from._offset)) {
to._offset = from._offset;
}
if (!isUndefined(from._pf)) {
to._pf = getParsingFlags(from);
}
if (!isUndefined(from._locale)) {
to._locale = from._locale;
}
if (momentPropertiesLen > 0) {
for (i = 0; i < momentPropertiesLen; i++) {
prop = momentProperties[i];
val = from[prop];
if (!isUndefined(val)) {
to[prop] = val;
}
}
}
return to;
}
// Moment prototype object
function Moment(config) {
copyConfig(this, config);
this._d = new Date(config._d != null ? config._d.getTime() : NaN);
if (!this.isValid()) {
this._d = new Date(NaN);
}
// Prevent infinite loop in case updateOffset creates new moment
// objects.
if (updateInProgress === false) {
updateInProgress = true;
hooks.updateOffset(this);
updateInProgress = false;
}
}
function isMoment(obj) {
return (
obj instanceof Moment || (obj != null && obj._isAMomentObject != null)
);
}
function warn(msg) {
if (
hooks.suppressDeprecationWarnings === false &&
typeof console !== 'undefined' &&
console.warn
) {
console.warn('Deprecation warning: ' + msg);
}
}
function deprecate(msg, fn) {
var firstTime = true;
return extend(function () {
if (hooks.deprecationHandler != null) {
hooks.deprecationHandler(null, msg);
}
if (firstTime) {
var args = [],
arg,
i,
key,
argLen = arguments.length;
for (i = 0; i < argLen; i++) {
arg = '';
if (typeof arguments[i] === 'object') {
arg += '\n[' + i + '] ';
for (key in arguments[0]) {
if (hasOwnProp(arguments[0], key)) {
arg += key + ': ' + arguments[0][key] + ', ';
}
}
arg = arg.slice(0, -2); // Remove trailing comma and space
} else {
arg = arguments[i];
}
args.push(arg);
}
warn(
msg +
'\nArguments: ' +
Array.prototype.slice.call(args).join('') +
'\n' +
new Error().stack
);
firstTime = false;
}
return fn.apply(this, arguments);
}, fn);
}
var deprecations = {};
function deprecateSimple(name, msg) {
if (hooks.deprecationHandler != null) {
hooks.deprecationHandler(name, msg);
}
if (!deprecations[name]) {
warn(msg);
deprecations[name] = true;
}
}
hooks.suppressDeprecationWarnings = false;
hooks.deprecationHandler = null;
function isFunction(input) {
return (
(typeof Function !== 'undefined' && input instanceof Function) ||
Object.prototype.toString.call(input) === '[object Function]'
);
}
function set(config) {
var prop, i;
for (i in config) {
if (hasOwnProp(config, i)) {
prop = config[i];
if (isFunction(prop)) {
this[i] = prop;
} else {
this['_' + i] = prop;
}
}
}
this._config = config;
// Lenient ordinal parsing accepts just a number in addition to
// number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
// TODO: Remove "ordinalParse" fallback in next major release.
this._dayOfMonthOrdinalParseLenient = new RegExp(
(this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
'|' +
/\d{1,2}/.source
);
}
function mergeConfigs(parentConfig, childConfig) {
var res = extend({}, parentConfig),
prop;
for (prop in childConfig) {
if (hasOwnProp(childConfig, prop)) {
if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
res[prop] = {};
extend(res[prop], parentConfig[prop]);
extend(res[prop], childConfig[prop]);
} else if (childConfig[prop] != null) {
res[prop] = childConfig[prop];
} else {
delete res[prop];
}
}
}
for (prop in parentConfig) {
if (
hasOwnProp(parentConfig, prop) &&
!hasOwnProp(childConfig, prop) &&
isObject(parentConfig[prop])
) {
// make sure changes to properties don't modify parent config
res[prop] = extend({}, res[prop]);
}
}
return res;
}
function Locale(config) {
if (config != null) {
this.set(config);
}
}
var keys;
if (Object.keys) {
keys = Object.keys;
} else {
keys = function (obj) {
var i,
res = [];
for (i in obj) {
if (hasOwnProp(obj, i)) {
res.push(i);
}
}
return res;
};
}
var defaultCalendar = {
sameDay: '[Today at] LT',
nextDay: '[Tomorrow at] LT',
nextWeek: 'dddd [at] LT',
lastDay: '[Yesterday at] LT',
lastWeek: '[Last] dddd [at] LT',
sameElse: 'L',
};
function calendar(key, mom, now) {
var output = this._calendar[key] || this._calendar['sameElse'];
return isFunction(output) ? output.call(mom, now) : output;
}
function zeroFill(number, targetLength, forceSign) {
var absNumber = '' + Math.abs(number),
zerosToFill = targetLength - absNumber.length,
sign = number >= 0;
return (
(sign ? (forceSign ? '+' : '') : '-') +
Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) +
absNumber
);
}
var formattingTokens =
/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,
localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
formatFunctions = {},
formatTokenFunctions = {};
// token: 'M'
// padded: ['MM', 2]
// ordinal: 'Mo'
// callback: function () { this.month() + 1 }
function addFormatToken(token, padded, ordinal, callback) {
var func = callback;
if (typeof callback === 'string') {
func = function () {
return this[callback]();
};
}
if (token) {
formatTokenFunctions[token] = func;
}
if (padded) {
formatTokenFunctions[padded[0]] = function () {
return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
};
}
if (ordinal) {
formatTokenFunctions[ordinal] = function () {
return this.localeData().ordinal(
func.apply(this, arguments),
token
);
};
}
}
function removeFormattingTokens(input) {
if (input.match(/\[[\s\S]/)) {
return input.replace(/^\[|\]$/g, '');
}
return input.replace(/\\/g, '');
}
function makeFormatFunction(format) {
var array = format.match(formattingTokens),
i,
length;
for (i = 0, length = array.length; i < length; i++) {
if (formatTokenFunctions[array[i]]) {
array[i] = formatTokenFunctions[array[i]];
} else {
array[i] = removeFormattingTokens(array[i]);
}
}
return function (mom) {
var output = '',
i;
for (i = 0; i < length; i++) {
output += isFunction(array[i])
? array[i].call(mom, format)
: array[i];
}
return output;
};
}
// format date using native date object
function formatMoment(m, format) {
if (!m.isValid()) {
return m.localeData().invalidDate();
}
format = expandFormat(format, m.localeData());
formatFunctions[format] =
formatFunctions[format] || makeFormatFunction(format);
return formatFunctions[format](m);
}
function expandFormat(format, locale) {
var i = 5;
function replaceLongDateFormatTokens(input) {
return locale.longDateFormat(input) || input;
}
localFormattingTokens.lastIndex = 0;
while (i >= 0 && localFormattingTokens.test(format)) {
format = format.replace(
localFormattingTokens,
replaceLongDateFormatTokens
);
localFormattingTokens.lastIndex = 0;
i -= 1;
}
return format;
}
var defaultLongDateFormat = {
LTS: 'h:mm:ss A',
LT: 'h:mm A',
L: 'MM/DD/YYYY',
LL: 'MMMM D, YYYY',
LLL: 'MMMM D, YYYY h:mm A',
LLLL: 'dddd, MMMM D, YYYY h:mm A',
};
function longDateFormat(key) {
var format = this._longDateFormat[key],
formatUpper = this._longDateFormat[key.toUpperCase()];
if (format || !formatUpper) {
return format;
}
this._longDateFormat[key] = formatUpper
.match(formattingTokens)
.map(function (tok) {
if (
tok === 'MMMM' ||
tok === 'MM' ||
tok === 'DD' ||
tok === 'dddd'
) {
return tok.slice(1);
}
return tok;
})
.join('');
return this._longDateFormat[key];
}
var defaultInvalidDate = 'Invalid date';
function invalidDate() {
return this._invalidDate;
}
var defaultOrdinal = '%d',
defaultDayOfMonthOrdinalParse = /\d{1,2}/;
function ordinal(number) {
return this._ordinal.replace('%d', number);
}
var defaultRelativeTime = {
future: 'in %s',
past: '%s ago',
s: 'a few seconds',
ss: '%d seconds',
m: 'a minute',
mm: '%d minutes',
h: 'an hour',
hh: '%d hours',
d: 'a day',
dd: '%d days',
w: 'a week',
ww: '%d weeks',
M: 'a month',
MM: '%d months',
y: 'a year',
yy: '%d years',
};
function relativeTime(number, withoutSuffix, string, isFuture) {
var output = this._relativeTime[string];
return isFunction(output)
? output(number, withoutSuffix, string, isFuture)
: output.replace(/%d/i, number);
}
function pastFuture(diff, output) {
var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
return isFunction(format) ? format(output) : format.replace(/%s/i, output);
}
var aliases = {
D: 'date',
dates: 'date',
date: 'date',
d: 'day',
days: 'day',
day: 'day',
e: 'weekday',
weekdays: 'weekday',
weekday: 'weekday',
E: 'isoWeekday',
isoweekdays: 'isoWeekday',
isoweekday: 'isoWeekday',
DDD: 'dayOfYear',
dayofyears: 'dayOfYear',
dayofyear: 'dayOfYear',
h: 'hour',
hours: 'hour',
hour: 'hour',
ms: 'millisecond',
milliseconds: 'millisecond',
millisecond: 'millisecond',
m: 'minute',
minutes: 'minute',
minute: 'minute',
M: 'month',
months: 'month',
month: 'month',
Q: 'quarter',
quarters: 'quarter',
quarter: 'quarter',
s: 'second',
seconds: 'second',
second: 'second',
gg: 'weekYear',
weekyears: 'weekYear',
weekyear: 'weekYear',
GG: 'isoWeekYear',
isoweekyears: 'isoWeekYear',
isoweekyear: 'isoWeekYear',
w: 'week',
weeks: 'week',
week: 'week',
W: 'isoWeek',
isoweeks: 'isoWeek',
isoweek: 'isoWeek',
y: 'year',
years: 'year',
year: 'year',
};
function normalizeUnits(units) {
return typeof units === 'string'
? aliases[units] || aliases[units.toLowerCase()]
: undefined;
}
function normalizeObjectUnits(inputObject) {
var normalizedInput = {},
normalizedProp,
prop;
for (prop in inputObject) {
if (hasOwnProp(inputObject, prop)) {
normalizedProp = normalizeUnits(prop);
if (normalizedProp) {
normalizedInput[normalizedProp] = inputObject[prop];
}
}
}
return normalizedInput;
}
var priorities = {
date: 9,
day: 11,
weekday: 11,
isoWeekday: 11,
dayOfYear: 4,
hour: 13,
millisecond: 16,
minute: 14,
month: 8,
quarter: 7,
second: 15,
weekYear: 1,
isoWeekYear: 1,
week: 5,
isoWeek: 5,
year: 1,
};
function getPrioritizedUnits(unitsObj) {
var units = [],
u;
for (u in unitsObj) {
if (hasOwnProp(unitsObj, u)) {
units.push({ unit: u, priority: priorities[u] });
}
}
units.sort(function (a, b) {
return a.priority - b.priority;
});
return units;
}
var match1 = /\d/, // 0 - 9
match2 = /\d\d/, // 00 - 99
match3 = /\d{3}/, // 000 - 999
match4 = /\d{4}/, // 0000 - 9999
match6 = /[+-]?\d{6}/, // -999999 - 999999
match1to2 = /\d\d?/, // 0 - 99
match3to4 = /\d\d\d\d?/, // 999 - 9999
match5to6 = /\d\d\d\d\d\d?/, // 99999 - 999999
match1to3 = /\d{1,3}/, // 0 - 999
match1to4 = /\d{1,4}/, // 0 - 9999
match1to6 = /[+-]?\d{1,6}/, // -999999 - 999999
matchUnsigned = /\d+/, // 0 - inf
matchSigned = /[+-]?\d+/, // -inf - inf
matchOffset = /Z|[+-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi, // +00 -00 +00:00 -00:00 +0000 -0000 or Z
matchTimestamp = /[+-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
// any word (or two) characters or numbers including two/three word month in arabic.
// includes scottish gaelic two word and hyphenated months
matchWord =
/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,
match1to2NoLeadingZero = /^[1-9]\d?/, // 1-99
match1to2HasZero = /^([1-9]\d|\d)/, // 0-99
regexes;
regexes = {};
function addRegexToken(token, regex, strictRegex) {
regexes[token] = isFunction(regex)
? regex
: function (isStrict, localeData) {
return isStrict && strictRegex ? strictRegex : regex;
};
}
function getParseRegexForToken(token, config) {
if (!hasOwnProp(regexes, token)) {
return new RegExp(unescapeFormat(token));
}
return regexes[token](config._strict, config._locale);
}
// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
function unescapeFormat(s) {
return regexEscape(
s
.replace('\\', '')
.replace(
/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,
function (matched, p1, p2, p3, p4) {
return p1 || p2 || p3 || p4;
}
)
);
}
function regexEscape(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
function absFloor(number) {
if (number < 0) {
// -0 -> 0
return Math.ceil(number) || 0;
} else {
return Math.floor(number);
}
}
function toInt(argumentForCoercion) {
var coercedNumber = +argumentForCoercion,
value = 0;
if (coercedNumber !== 0 && isFinite(coercedNumber)) {
value = absFloor(coercedNumber);
}
return value;
}
var tokens = {};
function addParseToken(token, callback) {
var i,
func = callback,
tokenLen;
if (typeof token === 'string') {
token = [token];
}
if (isNumber(callback)) {
func = function (input, array) {
array[callback] = toInt(input);
};
}
tokenLen = token.length;
for (i = 0; i < tokenLen; i++) {
tokens[token[i]] = func;
}
}
function addWeekParseToken(token, callback) {
addParseToken(token, function (input, array, config, token) {
config._w = config._w || {};
callback(input, config._w, config, token);
});
}
function addTimeToArrayFromToken(token, input, config) {
if (input != null && hasOwnProp(tokens, token)) {
tokens[token](input, config._a, config, token);
}
}
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
var YEAR = 0,
MONTH = 1,
DATE = 2,
HOUR = 3,
MINUTE = 4,
SECOND = 5,
MILLISECOND = 6,
WEEK = 7,
WEEKDAY = 8;
// FORMATTING
addFormatToken('Y', 0, 0, function () {
var y = this.year();
return y <= 9999 ? zeroFill(y, 4) : '+' + y;
});
addFormatToken(0, ['YY', 2], 0, function () {
return this.year() % 100;
});
addFormatToken(0, ['YYYY', 4], 0, 'year');
addFormatToken(0, ['YYYYY', 5], 0, 'year');
addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
// PARSING
addRegexToken('Y', matchSigned);
addRegexToken('YY', match1to2, match2);
addRegexToken('YYYY', match1to4, match4);
addRegexToken('YYYYY', match1to6, match6);
addRegexToken('YYYYYY', match1to6, match6);
addParseToken(['YYYYY', 'YYYYYY'], YEAR);
addParseToken('YYYY', function (input, array) {
array[YEAR] =
input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
});
addParseToken('YY', function (input, array) {
array[YEAR] = hooks.parseTwoDigitYear(input);
});
addParseToken('Y', function (input, array) {
array[YEAR] = parseInt(input, 10);
});
// HELPERS
function daysInYear(year) {
return isLeapYear(year) ? 366 : 365;
}
// HOOKS
hooks.parseTwoDigitYear = function (input) {
return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
};
// MOMENTS
var getSetYear = makeGetSet('FullYear', true);
function getIsLeapYear() {
return isLeapYear(this.year());
}
function makeGetSet(unit, keepTime) {
return function (value) {
if (value != null) {
set$1(this, unit, value);
hooks.updateOffset(this, keepTime);
return this;
} else {
return get(this, unit);
}
};
}
function get(mom, unit) {
if (!mom.isValid()) {
return NaN;
}
var d = mom._d,
isUTC = mom._isUTC;
switch (unit) {
case 'Milliseconds':
return isUTC ? d.getUTCMilliseconds() : d.getMilliseconds();
case 'Seconds':
return isUTC ? d.getUTCSeconds() : d.getSeconds();
case 'Minutes':
return isUTC ? d.getUTCMinutes() : d.getMinutes();
case 'Hours':
return isUTC ? d.getUTCHours() : d.getHours();
case 'Date':
return isUTC ? d.getUTCDate() : d.getDate();
case 'Day':
return isUTC ? d.getUTCDay() : d.getDay();
case 'Month':
return isUTC ? d.getUTCMonth() : d.getMonth();
case 'FullYear':
return isUTC ? d.getUTCFullYear() : d.getFullYear();
default:
return NaN; // Just in case
}
}
function set$1(mom, unit, value) {
var d, isUTC, year, month, date;
if (!mom.isValid() || isNaN(value)) {
return;
}
d = mom._d;
isUTC = mom._isUTC;
switch (unit) {
case 'Milliseconds':
return void (isUTC
? d.setUTCMilliseconds(value)
: d.setMilliseconds(value));
case 'Seconds':
return void (isUTC ? d.setUTCSeconds(value) : d.setSeconds(value));
case 'Minutes':
return void (isUTC ? d.setUTCMinutes(value) : d.setMinutes(value));
case 'Hours':
return void (isUTC ? d.setUTCHours(value) : d.setHours(value));
case 'Date':
return void (isUTC ? d.setUTCDate(value) : d.setDate(value));
// case 'Day': // Not real
// return void (isUTC ? d.setUTCDay(value) : d.setDay(value));
// case 'Month': // Not used because we need to pass two variables
// return void (isUTC ? d.setUTCMonth(value) : d.setMonth(value));
case 'FullYear':
break; // See below ...
default:
return; // Just in case
}
year = value;
month = mom.month();
date = mom.date();
date = date === 29 && month === 1 && !isLeapYear(year) ? 28 : date;
void (isUTC
? d.setUTCFullYear(year, month, date)
: d.setFullYear(year, month, date));
}
// MOMENTS
function stringGet(units) {
units = normalizeUnits(units);
if (isFunction(this[units])) {
return this[units]();
}
return this;
}
function stringSet(units, value) {
if (typeof units === 'object') {
units = normalizeObjectUnits(units);
var prioritized = getPrioritizedUnits(units),
i,
prioritizedLen = prioritized.length;
for (i = 0; i < prioritizedLen; i++) {
this[prioritized[i].unit](units[prioritized[i].unit]);
}
} else {
units = normalizeUnits(units);
if (isFunction(this[units])) {
return this[units](value);
}
}
return this;
}
function mod(n, x) {
return ((n % x) + x) % x;
}
var indexOf;
if (Array.prototype.indexOf) {
indexOf = Array.prototype.indexOf;
} else {
indexOf = function (o) {
// I know
var i;
for (i = 0; i < this.length; ++i) {
if (this[i] === o) {
return i;
}
}
return -1;
};
}
function daysInMonth(year, month) {
if (isNaN(year) || isNaN(month)) {
return NaN;
}
var modMonth = mod(month, 12);
year += (month - modMonth) / 12;
return modMonth === 1
? isLeapYear(year)
? 29
: 28
: 31 - ((modMonth % 7) % 2);
}
// FORMATTING
addFormatToken('M', ['MM', 2], 'Mo', function () {
return this.month() + 1;
});
addFormatToken('MMM', 0, 0, function (format) {
return this.localeData().monthsShort(this, format);
});
addFormatToken('MMMM', 0, 0, function (format) {
return this.localeData().months(this, format);
});
// PARSING
addRegexToken('M', match1to2, match1to2NoLeadingZero);
addRegexToken('MM', match1to2, match2);
addRegexToken('MMM', function (isStrict, locale) {
return locale.monthsShortRegex(isStrict);
});
addRegexToken('MMMM', function (isStrict, locale) {
return locale.monthsRegex(isStrict);
});
addParseToken(['M', 'MM'], function (input, array) {
array[MONTH] = toInt(input) - 1;
});
addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
var month = config._locale.monthsParse(input, token, config._strict);
// if we didn't find a month name, mark the date as invalid.
if (month != null) {
array[MONTH] = month;
} else {
getParsingFlags(config).invalidMonth = input;
}
});
// LOCALES
var defaultLocaleMonths =
'January_February_March_April_May_June_July_August_September_October_November_December'.split(
'_'
),
defaultLocaleMonthsShort =
'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,
defaultMonthsShortRegex = matchWord,
defaultMonthsRegex = matchWord;
function localeMonths(m, format) {
if (!m) {
return isArray(this._months)
? this._months
: this._months['standalone'];
}
return isArray(this._months)
? this._months[m.month()]
: this._months[
(this._months.isFormat || MONTHS_IN_FORMAT).test(format)
? 'format'
: 'standalone'
][m.month()];
}
function localeMonthsShort(m, format) {
if (!m) {
return isArray(this._monthsShort)
? this._monthsShort
: this._monthsShort['standalone'];
}
return isArray(this._monthsShort)
? this._monthsShort[m.month()]
: this._monthsShort[
MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'
][m.month()];
}
function handleStrictParse(monthName, format, strict) {
var i,
ii,
mom,
llc = monthName.toLocaleLowerCase();
if (!this._monthsParse) {
// this is not used
this._monthsParse = [];
this._longMonthsParse = [];
this._shortMonthsParse = [];
for (i = 0; i < 12; ++i) {
mom = createUTC([2000, i]);
this._shortMonthsParse[i] = this.monthsShort(
mom,
''
).toLocaleLowerCase();
this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
}
}
if (strict) {
if (format === 'MMM') {
ii = indexOf.call(this._shortMonthsParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._longMonthsParse, llc);
return ii !== -1 ? ii : null;
}
} else {
if (format === 'MMM') {
ii = indexOf.call(this._shortMonthsParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._longMonthsParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._longMonthsParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._shortMonthsParse, llc);
return ii !== -1 ? ii : null;
}
}
}
function localeMonthsParse(monthName, format, strict) {
var i, mom, regex;
if (this._monthsParseExact) {
return handleStrictParse.call(this, monthName, format, strict);
}
if (!this._monthsParse) {
this._monthsParse = [];
this._longMonthsParse = [];
this._shortMonthsParse = [];
}
// TODO: add sorting
// Sorting makes sure if one month (or abbr) is a prefix of another
// see sorting in computeMonthsParse
for (i = 0; i < 12; i++) {
// make the regex if we don't have it already
mom = createUTC([2000, i]);
if (strict && !this._longMonthsParse[i]) {
this._longMonthsParse[i] = new RegExp(
'^' + this.months(mom, '').replace('.', '') + '$',
'i'
);
this._shortMonthsParse[i] = new RegExp(
'^' + this.monthsShort(mom, '').replace('.', '') + '$',
'i'
);
}
if (!strict && !this._monthsParse[i]) {
regex =
'^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
}
// test the regex
if (
strict &&
format === 'MMMM' &&
this._longMonthsParse[i].test(monthName)
) {
return i;
} else if (
strict &&
format === 'MMM' &&
this._shortMonthsParse[i].test(monthName)
) {
return i;
} else if (!strict && this._monthsParse[i].test(monthName)) {
return i;
}
}
}
// MOMENTS
function setMonth(mom, value) {
if (!mom.isValid()) {
// No op
return mom;
}
if (typeof value === 'string') {
if (/^\d+$/.test(value)) {
value = toInt(value);
} else {
value = mom.localeData().monthsParse(value);
// TODO: Another silent failure?
if (!isNumber(value)) {
return mom;
}
}
}
var month = value,
date = mom.date();
date = date < 29 ? date : Math.min(date, daysInMonth(mom.year(), month));
void (mom._isUTC
? mom._d.setUTCMonth(month, date)
: mom._d.setMonth(month, date));
return mom;
}
function getSetMonth(value) {
if (value != null) {
setMonth(this, value);
hooks.updateOffset(this, true);
return this;
} else {
return get(this, 'Month');
}
}
function getDaysInMonth() {
return daysInMonth(this.year(), this.month());
}
function monthsShortRegex(isStrict) {
if (this._monthsParseExact) {
if (!hasOwnProp(this, '_monthsRegex')) {
computeMonthsParse.call(this);
}
if (isStrict) {
return this._monthsShortStrictRegex;
} else {
return this._monthsShortRegex;
}
} else {
if (!hasOwnProp(this, '_monthsShortRegex')) {
this._monthsShortRegex = defaultMonthsShortRegex;
}
return this._monthsShortStrictRegex && isStrict
? this._monthsShortStrictRegex
: this._monthsShortRegex;
}
}
function monthsRegex(isStrict) {
if (this._monthsParseExact) {
if (!hasOwnProp(this, '_monthsRegex')) {
computeMonthsParse.call(this);
}
if (isStrict) {
return this._monthsStrictRegex;
} else {
return this._monthsRegex;
}
} else {
if (!hasOwnProp(this, '_monthsRegex')) {
this._monthsRegex = defaultMonthsRegex;
}
return this._monthsStrictRegex && isStrict
? this._monthsStrictRegex
: this._monthsRegex;
}
}
function computeMonthsParse() {
function cmpLenRev(a, b) {
return b.length - a.length;
}
var shortPieces = [],
longPieces = [],
mixedPieces = [],
i,
mom,
shortP,
longP;
for (i = 0; i < 12; i++) {
// make the regex if we don't have it already
mom = createUTC([2000, i]);
shortP = regexEscape(this.monthsShort(mom, ''));
longP = regexEscape(this.months(mom, ''));
shortPieces.push(shortP);
longPieces.push(longP);
mixedPieces.push(longP);
mixedPieces.push(shortP);
}
// Sorting makes sure if one month (or abbr) is a prefix of another it
// will match the longer piece.
shortPieces.sort(cmpLenRev);
longPieces.sort(cmpLenRev);
mixedPieces.sort(cmpLenRev);
this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
this._monthsShortRegex = this._monthsRegex;
this._monthsStrictRegex = new RegExp(
'^(' + longPieces.join('|') + ')',
'i'
);
this._monthsShortStrictRegex = new RegExp(
'^(' + shortPieces.join('|') + ')',
'i'
);
}
function createDate(y, m, d, h, M, s, ms) {
// can't just apply() to create a date:
// https://stackoverflow.com/q/181348
var date;
// the date constructor remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
// preserve leap years using a full 400 year cycle, then reset
date = new Date(y + 400, m, d, h, M, s, ms);
if (isFinite(date.getFullYear())) {
date.setFullYear(y);
}
} else {
date = new Date(y, m, d, h, M, s, ms);
}
return date;
}
function createUTCDate(y) {
var date, args;
// the Date.UTC function remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
args = Array.prototype.slice.call(arguments);
// preserve leap years using a full 400 year cycle, then reset
args[0] = y + 400;
date = new Date(Date.UTC.apply(null, args));
if (isFinite(date.getUTCFullYear())) {
date.setUTCFullYear(y);
}
} else {
date = new Date(Date.UTC.apply(null, arguments));
}
return date;
}
// start-of-first-week - start-of-year
function firstWeekOffset(year, dow, doy) {
var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
fwd = 7 + dow - doy,
// first-week day local weekday -- which local weekday is fwd
fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
return -fwdlw + fwd - 1;
}
// https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
var localWeekday = (7 + weekday - dow) % 7,
weekOffset = firstWeekOffset(year, dow, doy),
dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
resYear,
resDayOfYear;
if (dayOfYear <= 0) {
resYear = year - 1;
resDayOfYear = daysInYear(resYear) + dayOfYear;
} else if (dayOfYear > daysInYear(year)) {
resYear = year + 1;
resDayOfYear = dayOfYear - daysInYear(year);
} else {
resYear = year;
resDayOfYear = dayOfYear;
}
return {
year: resYear,
dayOfYear: resDayOfYear,
};
}
function weekOfYear(mom, dow, doy) {
var weekOffset = firstWeekOffset(mom.year(), dow, doy),
week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
resWeek,
resYear;
if (week < 1) {
resYear = mom.year() - 1;
resWeek = week + weeksInYear(resYear, dow, doy);
} else if (week > weeksInYear(mom.year(), dow, doy)) {
resWeek = week - weeksInYear(mom.year(), dow, doy);
resYear = mom.year() + 1;
} else {
resYear = mom.year();
resWeek = week;
}
return {
week: resWeek,
year: resYear,
};
}
function weeksInYear(year, dow, doy) {
var weekOffset = firstWeekOffset(year, dow, doy),
weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
}
// FORMATTING
addFormatToken('w', ['ww', 2], 'wo', 'week');
addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
// PARSING
addRegexToken('w', match1to2, match1to2NoLeadingZero);
addRegexToken('ww', match1to2, match2);
addRegexToken('W', match1to2, match1to2NoLeadingZero);
addRegexToken('WW', match1to2, match2);
addWeekParseToken(
['w', 'ww', 'W', 'WW'],
function (input, week, config, token) {
week[token.substr(0, 1)] = toInt(input);
}
);
// HELPERS
// LOCALES
function localeWeek(mom) {
return weekOfYear(mom, this._week.dow, this._week.doy).week;
}
var defaultLocaleWeek = {
dow: 0, // Sunday is the first day of the week.
doy: 6, // The week that contains Jan 6th is the first week of the year.
};
function localeFirstDayOfWeek() {
return this._week.dow;
}
function localeFirstDayOfYear() {
return this._week.doy;
}
// MOMENTS
function getSetWeek(input) {
var week = this.localeData().week(this);
return input == null ? week : this.add((input - week) * 7, 'd');
}
function getSetISOWeek(input) {
var week = weekOfYear(this, 1, 4).week;
return input == null ? week : this.add((input - week) * 7, 'd');
}
// FORMATTING
addFormatToken('d', 0, 'do', 'day');
addFormatToken('dd', 0, 0, function (format) {
return this.localeData().weekdaysMin(this, format);
});
addFormatToken('ddd', 0, 0, function (format) {
return this.localeData().weekdaysShort(this, format);
});
addFormatToken('dddd', 0, 0, function (format) {
return this.localeData().weekdays(this, format);
});
addFormatToken('e', 0, 0, 'weekday');
addFormatToken('E', 0, 0, 'isoWeekday');
// PARSING
addRegexToken('d', match1to2);
addRegexToken('e', match1to2);
addRegexToken('E', match1to2);
addRegexToken('dd', function (isStrict, locale) {
return locale.weekdaysMinRegex(isStrict);
});
addRegexToken('ddd', function (isStrict, locale) {
return locale.weekdaysShortRegex(isStrict);
});
addRegexToken('dddd', function (isStrict, locale) {
return locale.weekdaysRegex(isStrict);
});
addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
var weekday = config._locale.weekdaysParse(input, token, config._strict);
// if we didn't get a weekday name, mark the date as invalid
if (weekday != null) {
week.d = weekday;
} else {
getParsingFlags(config).invalidWeekday = input;
}
});
addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
week[token] = toInt(input);
});
// HELPERS
function parseWeekday(input, locale) {
if (typeof input !== 'string') {
return input;
}
if (!isNaN(input)) {
return parseInt(input, 10);
}
input = locale.weekdaysParse(input);
if (typeof input === 'number') {
return input;
}
return null;
}
function parseIsoWeekday(input, locale) {
if (typeof input === 'string') {
return locale.weekdaysParse(input) % 7 || 7;
}
return isNaN(input) ? null : input;
}
// LOCALES
function shiftWeekdays(ws, n) {
return ws.slice(n, 7).concat(ws.slice(0, n));
}
var defaultLocaleWeekdays =
'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
defaultWeekdaysRegex = matchWord,
defaultWeekdaysShortRegex = matchWord,
defaultWeekdaysMinRegex = matchWord;
function localeWeekdays(m, format) {
var weekdays = isArray(this._weekdays)
? this._weekdays
: this._weekdays[
m && m !== true && this._weekdays.isFormat.test(format)
? 'format'
: 'standalone'
];
return m === true
? shiftWeekdays(weekdays, this._week.dow)
: m
? weekdays[m.day()]
: weekdays;
}
function localeWeekdaysShort(m) {
return m === true
? shiftWeekdays(this._weekdaysShort, this._week.dow)
: m
? this._weekdaysShort[m.day()]
: this._weekdaysShort;
}
function localeWeekdaysMin(m) {
return m === true
? shiftWeekdays(this._weekdaysMin, this._week.dow)
: m
? this._weekdaysMin[m.day()]
: this._weekdaysMin;
}
function handleStrictParse$1(weekdayName, format, strict) {
var i,
ii,
mom,
llc = weekdayName.toLocaleLowerCase();
if (!this._weekdaysParse) {
this._weekdaysParse = [];
this._shortWeekdaysParse = [];
this._minWeekdaysParse = [];
for (i = 0; i < 7; ++i) {
mom = createUTC([2000, 1]).day(i);
this._minWeekdaysParse[i] = this.weekdaysMin(
mom,
''
).toLocaleLowerCase();
this._shortWeekdaysParse[i] = this.weekdaysShort(
mom,
''
).toLocaleLowerCase();
this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
}
}
if (strict) {
if (format === 'dddd') {
ii = indexOf.call(this._weekdaysParse, llc);
return ii !== -1 ? ii : null;
} else if (format === 'ddd') {
ii = indexOf.call(this._shortWeekdaysParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._minWeekdaysParse, llc);
return ii !== -1 ? ii : null;
}
} else {
if (format === 'dddd') {
ii = indexOf.call(this._weekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._shortWeekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._minWeekdaysParse, llc);
return ii !== -1 ? ii : null;
} else if (format === 'ddd') {
ii = indexOf.call(this._shortWeekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._weekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._minWeekdaysParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._minWeekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._weekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._shortWeekdaysParse, llc);
return ii !== -1 ? ii : null;
}
}
}
function localeWeekdaysParse(weekdayName, format, strict) {
var i, mom, regex;
if (this._weekdaysParseExact) {
return handleStrictParse$1.call(this, weekdayName, format, strict);
}
if (!this._weekdaysParse) {
this._weekdaysParse = [];
this._minWeekdaysParse = [];
this._shortWeekdaysParse = [];
this._fullWeekdaysParse = [];
}
for (i = 0; i < 7; i++) {
// make the regex if we don't have it already
mom = createUTC([2000, 1]).day(i);
if (strict && !this._fullWeekdaysParse[i]) {
this._fullWeekdaysParse[i] = new RegExp(
'^' + this.weekdays(mom, '').replace('.', '\\.?') + '$',
'i'
);
this._shortWeekdaysParse[i] = new RegExp(
'^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$',
'i'
);
this._minWeekdaysParse[i] = new RegExp(
'^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$',
'i'
);
}
if (!this._weekdaysParse[i]) {
regex =
'^' +
this.weekdays(mom, '') +
'|^' +
this.weekdaysShort(mom, '') +
'|^' +
this.weekdaysMin(mom, '');
this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
}
// test the regex
if (
strict &&
format === 'dddd' &&
this._fullWeekdaysParse[i].test(weekdayName)
) {
return i;
} else if (
strict &&
format === 'ddd' &&
this._shortWeekdaysParse[i].test(weekdayName)
) {
return i;
} else if (
strict &&
format === 'dd' &&
this._minWeekdaysParse[i].test(weekdayName)
) {
return i;
} else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
return i;
}
}
}
// MOMENTS
function getSetDayOfWeek(input) {
if (!this.isValid()) {
return input != null ? this : NaN;
}
var day = get(this, 'Day');
if (input != null) {
input = parseWeekday(input, this.localeData());
return this.add(input - day, 'd');
} else {
return day;
}
}
function getSetLocaleDayOfWeek(input) {
if (!this.isValid()) {
return input != null ? this : NaN;
}
var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
return input == null ? weekday : this.add(input - weekday, 'd');
}
function getSetISODayOfWeek(input) {
if (!this.isValid()) {
return input != null ? this : NaN;
}
// behaves the same as moment#day except
// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
// as a setter, sunday should belong to the previous week.
if (input != null) {
var weekday = parseIsoWeekday(input, this.localeData());
return this.day(this.day() % 7 ? weekday : weekday - 7);
} else {
return this.day() || 7;
}
}
function weekdaysRegex(isStrict) {
if (this._weekdaysParseExact) {
if (!hasOwnProp(this, '_weekdaysRegex')) {
computeWeekdaysParse.call(this);
}
if (isStrict) {
return this._weekdaysStrictRegex;
} else {
return this._weekdaysRegex;
}
} else {
if (!hasOwnProp(this, '_weekdaysRegex')) {
this._weekdaysRegex = defaultWeekdaysRegex;
}
return this._weekdaysStrictRegex && isStrict
? this._weekdaysStrictRegex
: this._weekdaysRegex;
}
}
function weekdaysShortRegex(isStrict) {
if (this._weekdaysParseExact) {
if (!hasOwnProp(this, '_weekdaysRegex')) {
computeWeekdaysParse.call(this);
}
if (isStrict) {
return this._weekdaysShortStrictRegex;
} else {
return this._weekdaysShortRegex;
}
} else {
if (!hasOwnProp(this, '_weekdaysShortRegex')) {
this._weekdaysShortRegex = defaultWeekdaysShortRegex;
}
return this._weekdaysShortStrictRegex && isStrict
? this._weekdaysShortStrictRegex
: this._weekdaysShortRegex;
}
}
function weekdaysMinRegex(isStrict) {
if (this._weekdaysParseExact) {
if (!hasOwnProp(this, '_weekdaysRegex')) {
computeWeekdaysParse.call(this);
}
if (isStrict) {
return this._weekdaysMinStrictRegex;
} else {
return this._weekdaysMinRegex;
}
} else {
if (!hasOwnProp(this, '_weekdaysMinRegex')) {
this._weekdaysMinRegex = defaultWeekdaysMinRegex;
}
return this._weekdaysMinStrictRegex && isStrict
? this._weekdaysMinStrictRegex
: this._weekdaysMinRegex;
}
}
function computeWeekdaysParse() {
function cmpLenRev(a, b) {
return b.length - a.length;
}
var minPieces = [],
shortPieces = [],
longPieces = [],
mixedPieces = [],
i,
mom,
minp,
shortp,
longp;
for (i = 0; i < 7; i++) {
// make the regex if we don't have it already
mom = createUTC([2000, 1]).day(i);
minp = regexEscape(this.weekdaysMin(mom, ''));
shortp = regexEscape(this.weekdaysShort(mom, ''));
longp = regexEscape(this.weekdays(mom, ''));
minPieces.push(minp);
shortPieces.push(shortp);
longPieces.push(longp);
mixedPieces.push(minp);
mixedPieces.push(shortp);
mixedPieces.push(longp);
}
// Sorting makes sure if one weekday (or abbr) is a prefix of another it
// will match the longer piece.
minPieces.sort(cmpLenRev);
shortPieces.sort(cmpLenRev);
longPieces.sort(cmpLenRev);
mixedPieces.sort(cmpLenRev);
this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
this._weekdaysShortRegex = this._weekdaysRegex;
this._weekdaysMinRegex = this._weekdaysRegex;
this._weekdaysStrictRegex = new RegExp(
'^(' + longPieces.join('|') + ')',
'i'
);
this._weekdaysShortStrictRegex = new RegExp(
'^(' + shortPieces.join('|') + ')',
'i'
);
this._weekdaysMinStrictRegex = new RegExp(
'^(' + minPieces.join('|') + ')',
'i'
);
}
// FORMATTING
function hFormat() {
return this.hours() % 12 || 12;
}
function kFormat() {
return this.hours() || 24;
}
addFormatToken('H', ['HH', 2], 0, 'hour');
addFormatToken('h', ['hh', 2], 0, hFormat);
addFormatToken('k', ['kk', 2], 0, kFormat);
addFormatToken('hmm', 0, 0, function () {
return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
});
addFormatToken('hmmss', 0, 0, function () {
return (
'' +
hFormat.apply(this) +
zeroFill(this.minutes(), 2) +
zeroFill(this.seconds(), 2)
);
});
addFormatToken('Hmm', 0, 0, function () {
return '' + this.hours() + zeroFill(this.minutes(), 2);
});
addFormatToken('Hmmss', 0, 0, function () {
return (
'' +
this.hours() +
zeroFill(this.minutes(), 2) +
zeroFill(this.seconds(), 2)
);
});
function meridiem(token, lowercase) {
addFormatToken(token, 0, 0, function () {
return this.localeData().meridiem(
this.hours(),
this.minutes(),
lowercase
);
});
}
meridiem('a', true);
meridiem('A', false);
// PARSING
function matchMeridiem(isStrict, locale) {
return locale._meridiemParse;
}
addRegexToken('a', matchMeridiem);
addRegexToken('A', matchMeridiem);
addRegexToken('H', match1to2, match1to2HasZero);
addRegexToken('h', match1to2, match1to2NoLeadingZero);
addRegexToken('k', match1to2, match1to2NoLeadingZero);
addRegexToken('HH', match1to2, match2);
addRegexToken('hh', match1to2, match2);
addRegexToken('kk', match1to2, match2);
addRegexToken('hmm', match3to4);
addRegexToken('hmmss', match5to6);
addRegexToken('Hmm', match3to4);
addRegexToken('Hmmss', match5to6);
addParseToken(['H', 'HH'], HOUR);
addParseToken(['k', 'kk'], function (input, array, config) {
var kInput = toInt(input);
array[HOUR] = kInput === 24 ? 0 : kInput;
});
addParseToken(['a', 'A'], function (input, array, config) {
config._isPm = config._locale.isPM(input);
config._meridiem = input;
});
addParseToken(['h', 'hh'], function (input, array, config) {
array[HOUR] = toInt(input);
getParsingFlags(config).bigHour = true;
});
addParseToken('hmm', function (input, array, config) {
var pos = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos));
array[MINUTE] = toInt(input.substr(pos));
getParsingFlags(config).bigHour = true;
});
addParseToken('hmmss', function (input, array, config) {
var pos1 = input.length - 4,
pos2 = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos1));
array[MINUTE] = toInt(input.substr(pos1, 2));
array[SECOND] = toInt(input.substr(pos2));
getParsingFlags(config).bigHour = true;
});
addParseToken('Hmm', function (input, array, config) {
var pos = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos));
array[MINUTE] = toInt(input.substr(pos));
});
addParseToken('Hmmss', function (input, array, config) {
var pos1 = input.length - 4,
pos2 = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos1));
array[MINUTE] = toInt(input.substr(pos1, 2));
array[SECOND] = toInt(input.substr(pos2));
});
// LOCALES
function localeIsPM(input) {
// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
// Using charAt should be more compatible.
return (input + '').toLowerCase().charAt(0) === 'p';
}
var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i,
// Setting the hour should keep the time, because the user explicitly
// specified which hour they want. So trying to maintain the same hour (in
// a new timezone) makes sense. Adding/subtracting hours does not follow
// this rule.
getSetHour = makeGetSet('Hours', true);
function localeMeridiem(hours, minutes, isLower) {
if (hours > 11) {
return isLower ? 'pm' : 'PM';
} else {
return isLower ? 'am' : 'AM';
}
}
var baseConfig = {
calendar: defaultCalendar,
longDateFormat: defaultLongDateFormat,
invalidDate: defaultInvalidDate,
ordinal: defaultOrdinal,
dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
relativeTime: defaultRelativeTime,
months: defaultLocaleMonths,
monthsShort: defaultLocaleMonthsShort,
week: defaultLocaleWeek,
weekdays: defaultLocaleWeekdays,
weekdaysMin: defaultLocaleWeekdaysMin,
weekdaysShort: defaultLocaleWeekdaysShort,
meridiemParse: defaultLocaleMeridiemParse,
};
// internal storage for locale config files
var locales = {},
localeFamilies = {},
globalLocale;
function commonPrefix(arr1, arr2) {
var i,
minl = Math.min(arr1.length, arr2.length);
for (i = 0; i < minl; i += 1) {
if (arr1[i] !== arr2[i]) {
return i;
}
}
return minl;
}
function normalizeLocale(key) {
return key ? key.toLowerCase().replace('_', '-') : key;
}
// pick the locale from the array
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
function chooseLocale(names) {
var i = 0,
j,
next,
locale,
split;
while (i < names.length) {
split = normalizeLocale(names[i]).split('-');
j = split.length;
next = normalizeLocale(names[i + 1]);
next = next ? next.split('-') : null;
while (j > 0) {
locale = loadLocale(split.slice(0, j).join('-'));
if (locale) {
return locale;
}
if (
next &&
next.length >= j &&
commonPrefix(split, next) >= j - 1
) {
//the next array item is better than a shallower substring of this one
break;
}
j--;
}
i++;
}
return globalLocale;
}
function isLocaleNameSane(name) {
// Prevent names that look like filesystem paths, i.e contain '/' or '\'
// Ensure name is available and function returns boolean
return !!(name && name.match('^[^/\\\\]*$'));
}
function loadLocale(name) {
var oldLocale = null,
aliasedRequire;
// TODO: Find a better way to register and load all the locales in Node
if (
locales[name] === undefined &&
'object' !== 'undefined' &&
module &&
module.exports &&
isLocaleNameSane(name)
) {
try {
oldLocale = globalLocale._abbr;
aliasedRequire = commonjsRequire;
aliasedRequire('./locale/' + name);
getSetGlobalLocale(oldLocale);
} catch (e) {
// mark as not found to avoid repeating expensive file require call causing high CPU
// when trying to find en-US, en_US, en-us for every format call
locales[name] = null; // null means not found
}
}
return locales[name];
}
// This function will load locale and then set the global locale. If
// no arguments are passed in, it will simply return the current global
// locale key.
function getSetGlobalLocale(key, values) {
var data;
if (key) {
if (isUndefined(values)) {
data = getLocale(key);
} else {
data = defineLocale(key, values);
}
if (data) {
// moment.duration._locale = moment._locale = data;
globalLocale = data;
} else {
if (typeof console !== 'undefined' && console.warn) {
//warn user if arguments are passed but the locale could not be set
console.warn(
'Locale ' + key + ' not found. Did you forget to load it?'
);
}
}
}
return globalLocale._abbr;
}
function defineLocale(name, config) {
if (config !== null) {
var locale,
parentConfig = baseConfig;
config.abbr = name;
if (locales[name] != null) {
deprecateSimple(
'defineLocaleOverride',
'use moment.updateLocale(localeName, config) to change ' +
'an existing locale. moment.defineLocale(localeName, ' +
'config) should only be used for creating a new locale ' +
'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'
);
parentConfig = locales[name]._config;
} else if (config.parentLocale != null) {
if (locales[config.parentLocale] != null) {
parentConfig = locales[config.parentLocale]._config;
} else {
locale = loadLocale(config.parentLocale);
if (locale != null) {
parentConfig = locale._config;
} else {
if (!localeFamilies[config.parentLocale]) {
localeFamilies[config.parentLocale] = [];
}
localeFamilies[config.parentLocale].push({
name: name,
config: config,
});
return null;
}
}
}
locales[name] = new Locale(mergeConfigs(parentConfig, config));
if (localeFamilies[name]) {
localeFamilies[name].forEach(function (x) {
defineLocale(x.name, x.config);
});
}
// backwards compat for now: also set the locale
// make sure we set the locale AFTER all child locales have been
// created, so we won't end up with the child locale set.
getSetGlobalLocale(name);
return locales[name];
} else {
// useful for testing
delete locales[name];
return null;
}
}
function updateLocale(name, config) {
if (config != null) {
var locale,
tmpLocale,
parentConfig = baseConfig;
if (locales[name] != null && locales[name].parentLocale != null) {
// Update existing child locale in-place to avoid memory-leaks
locales[name].set(mergeConfigs(locales[name]._config, config));
} else {
// MERGE
tmpLocale = loadLocale(name);
if (tmpLocale != null) {
parentConfig = tmpLocale._config;
}
config = mergeConfigs(parentConfig, config);
if (tmpLocale == null) {
// updateLocale is called for creating a new locale
// Set abbr so it will have a name (getters return
// undefined otherwise).
config.abbr = name;
}
locale = new Locale(config);
locale.parentLocale = locales[name];
locales[name] = locale;
}
// backwards compat for now: also set the locale
getSetGlobalLocale(name);
} else {
// pass null for config to unupdate, useful for tests
if (locales[name] != null) {
if (locales[name].parentLocale != null) {
locales[name] = locales[name].parentLocale;
if (name === getSetGlobalLocale()) {
getSetGlobalLocale(name);
}
} else if (locales[name] != null) {
delete locales[name];
}
}
}
return locales[name];
}
// returns locale data
function getLocale(key) {
var locale;
if (key && key._locale && key._locale._abbr) {
key = key._locale._abbr;
}
if (!key) {
return globalLocale;
}
if (!isArray(key)) {
//short-circuit everything else
locale = loadLocale(key);
if (locale) {
return locale;
}
key = [key];
}
return chooseLocale(key);
}
function listLocales() {
return keys(locales);
}
function checkOverflow(m) {
var overflow,
a = m._a;
if (a && getParsingFlags(m).overflow === -2) {
overflow =
a[MONTH] < 0 || a[MONTH] > 11
? MONTH
: a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH])
? DATE
: a[HOUR] < 0 ||
a[HOUR] > 24 ||
(a[HOUR] === 24 &&
(a[MINUTE] !== 0 ||
a[SECOND] !== 0 ||
a[MILLISECOND] !== 0))
? HOUR
: a[MINUTE] < 0 || a[MINUTE] > 59
? MINUTE
: a[SECOND] < 0 || a[SECOND] > 59
? SECOND
: a[MILLISECOND] < 0 || a[MILLISECOND] > 999
? MILLISECOND
: -1;
if (
getParsingFlags(m)._overflowDayOfYear &&
(overflow < YEAR || overflow > DATE)
) {
overflow = DATE;
}
if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
overflow = WEEK;
}
if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
overflow = WEEKDAY;
}
getParsingFlags(m).overflow = overflow;
}
return m;
}
// iso 8601 regex
// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
var extendedIsoRegex =
/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
basicIsoRegex =
/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
tzRegex = /Z|[+-]\d\d(?::?\d\d)?/,
isoDates = [
['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
['GGGG-[W]WW', /\d{4}-W\d\d/, false],
['YYYY-DDD', /\d{4}-\d{3}/],
['YYYY-MM', /\d{4}-\d\d/, false],
['YYYYYYMMDD', /[+-]\d{10}/],
['YYYYMMDD', /\d{8}/],
['GGGG[W]WWE', /\d{4}W\d{3}/],
['GGGG[W]WW', /\d{4}W\d{2}/, false],
['YYYYDDD', /\d{7}/],
['YYYYMM', /\d{6}/, false],
['YYYY', /\d{4}/, false],
],
// iso time formats and regexes
isoTimes = [
['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
['HH:mm:ss', /\d\d:\d\d:\d\d/],
['HH:mm', /\d\d:\d\d/],
['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
['HHmmss', /\d\d\d\d\d\d/],
['HHmm', /\d\d\d\d/],
['HH', /\d\d/],
],
aspNetJsonRegex = /^\/?Date\((-?\d+)/i,
// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
rfc2822 =
/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,
obsOffsets = {
UT: 0,
GMT: 0,
EDT: -4 * 60,
EST: -5 * 60,
CDT: -5 * 60,
CST: -6 * 60,
MDT: -6 * 60,
MST: -7 * 60,
PDT: -7 * 60,
PST: -8 * 60,
};
// date from iso format
function configFromISO(config) {
var i,
l,
string = config._i,
match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
allowTime,
dateFormat,
timeFormat,
tzFormat,
isoDatesLen = isoDates.length,
isoTimesLen = isoTimes.length;
if (match) {
getParsingFlags(config).iso = true;
for (i = 0, l = isoDatesLen; i < l; i++) {
if (isoDates[i][1].exec(match[1])) {
dateFormat = isoDates[i][0];
allowTime = isoDates[i][2] !== false;
break;
}
}
if (dateFormat == null) {
config._isValid = false;
return;
}
if (match[3]) {
for (i = 0, l = isoTimesLen; i < l; i++) {
if (isoTimes[i][1].exec(match[3])) {
// match[2] should be 'T' or space
timeFormat = (match[2] || ' ') + isoTimes[i][0];
break;
}
}
if (timeFormat == null) {
config._isValid = false;
return;
}
}
if (!allowTime && timeFormat != null) {
config._isValid = false;
return;
}
if (match[4]) {
if (tzRegex.exec(match[4])) {
tzFormat = 'Z';
} else {
config._isValid = false;
return;
}
}
config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
configFromStringAndFormat(config);
} else {
config._isValid = false;
}
}
function extractFromRFC2822Strings(
yearStr,
monthStr,
dayStr,
hourStr,
minuteStr,
secondStr
) {
var result = [
untruncateYear(yearStr),
defaultLocaleMonthsShort.indexOf(monthStr),
parseInt(dayStr, 10),
parseInt(hourStr, 10),
parseInt(minuteStr, 10),
];
if (secondStr) {
result.push(parseInt(secondStr, 10));
}
return result;
}
function untruncateYear(yearStr) {
var year = parseInt(yearStr, 10);
if (year <= 49) {
return 2000 + year;
} else if (year <= 999) {
return 1900 + year;
}
return year;
}
function preprocessRFC2822(s) {
// Remove comments and folding whitespace and replace multiple-spaces with a single space
return s
.replace(/\([^()]*\)|[\n\t]/g, ' ')
.replace(/(\s\s+)/g, ' ')
.replace(/^\s\s*/, '')
.replace(/\s\s*$/, '');
}
function checkWeekday(weekdayStr, parsedInput, config) {
if (weekdayStr) {
// TODO: Replace the vanilla JS Date object with an independent day-of-week check.
var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
weekdayActual = new Date(
parsedInput[0],
parsedInput[1],
parsedInput[2]
).getDay();
if (weekdayProvided !== weekdayActual) {
getParsingFlags(config).weekdayMismatch = true;
config._isValid = false;
return false;
}
}
return true;
}
function calculateOffset(obsOffset, militaryOffset, numOffset) {
if (obsOffset) {
return obsOffsets[obsOffset];
} else if (militaryOffset) {
// the only allowed military tz is Z
return 0;
} else {
var hm = parseInt(numOffset, 10),
m = hm % 100,
h = (hm - m) / 100;
return h * 60 + m;
}
}
// date and time from ref 2822 format
function configFromRFC2822(config) {
var match = rfc2822.exec(preprocessRFC2822(config._i)),
parsedArray;
if (match) {
parsedArray = extractFromRFC2822Strings(
match[4],
match[3],
match[2],
match[5],
match[6],
match[7]
);
if (!checkWeekday(match[1], parsedArray, config)) {
return;
}
config._a = parsedArray;
config._tzm = calculateOffset(match[8], match[9], match[10]);
config._d = createUTCDate.apply(null, config._a);
config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
getParsingFlags(config).rfc2822 = true;
} else {
config._isValid = false;
}
}
// date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict
function configFromString(config) {
var matched = aspNetJsonRegex.exec(config._i);
if (matched !== null) {
config._d = new Date(+matched[1]);
return;
}
configFromISO(config);
if (config._isValid === false) {
delete config._isValid;
} else {
return;
}
configFromRFC2822(config);
if (config._isValid === false) {
delete config._isValid;
} else {
return;
}
if (config._strict) {
config._isValid = false;
} else {
// Final attempt, use Input Fallback
hooks.createFromInputFallback(config);
}
}
hooks.createFromInputFallback = deprecate(
'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
'discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.',
function (config) {
config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
}
);
// Pick the first defined of two or three arguments.
function defaults(a, b, c) {
if (a != null) {
return a;
}
if (b != null) {
return b;
}
return c;
}
function currentDateArray(config) {
// hooks is actually the exported moment object
var nowValue = new Date(hooks.now());
if (config._useUTC) {
return [
nowValue.getUTCFullYear(),
nowValue.getUTCMonth(),
nowValue.getUTCDate(),
];
}
return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
}
// convert an array to a date.
// the array should mirror the parameters below
// note: all values past the year are optional and will default to the lowest possible value.
// [year, month, day , hour, minute, second, millisecond]
function configFromArray(config) {
var i,
date,
input = [],
currentDate,
expectedWeekday,
yearToUse;
if (config._d) {
return;
}
currentDate = currentDateArray(config);
//compute day of the year from weeks and weekdays
if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
dayOfYearFromWeekInfo(config);
}
//if the day of the year is set, figure out what it is
if (config._dayOfYear != null) {
yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
if (
config._dayOfYear > daysInYear(yearToUse) ||
config._dayOfYear === 0
) {
getParsingFlags(config)._overflowDayOfYear = true;
}
date = createUTCDate(yearToUse, 0, config._dayOfYear);
config._a[MONTH] = date.getUTCMonth();
config._a[DATE] = date.getUTCDate();
}
// Default to current date.
// * if no year, month, day of month are given, default to today
// * if day of month is given, default month and year
// * if month is given, default only year
// * if year is given, don't default anything
for (i = 0; i < 3 && config._a[i] == null; ++i) {
config._a[i] = input[i] = currentDate[i];
}
// Zero out whatever was not defaulted, including time
for (; i < 7; i++) {
config._a[i] = input[i] =
config._a[i] == null ? (i === 2 ? 1 : 0) : config._a[i];
}
// Check for 24:00:00.000
if (
config._a[HOUR] === 24 &&
config._a[MINUTE] === 0 &&
config._a[SECOND] === 0 &&
config._a[MILLISECOND] === 0
) {
config._nextDay = true;
config._a[HOUR] = 0;
}
config._d = (config._useUTC ? createUTCDate : createDate).apply(
null,
input
);
expectedWeekday = config._useUTC
? config._d.getUTCDay()
: config._d.getDay();
// Apply timezone offset from input. The actual utcOffset can be changed
// with parseZone.
if (config._tzm != null) {
config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
}
if (config._nextDay) {
config._a[HOUR] = 24;
}
// check for mismatching day of week
if (
config._w &&
typeof config._w.d !== 'undefined' &&
config._w.d !== expectedWeekday
) {
getParsingFlags(config).weekdayMismatch = true;
}
}
function dayOfYearFromWeekInfo(config) {
var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow, curWeek;
w = config._w;
if (w.GG != null || w.W != null || w.E != null) {
dow = 1;
doy = 4;
// TODO: We need to take the current isoWeekYear, but that depends on
// how we interpret now (local, utc, fixed offset). So create
// a now version of current config (take local/utc/offset flags, and
// create now).
weekYear = defaults(
w.GG,
config._a[YEAR],
weekOfYear(createLocal(), 1, 4).year
);
week = defaults(w.W, 1);
weekday = defaults(w.E, 1);
if (weekday < 1 || weekday > 7) {
weekdayOverflow = true;
}
} else {
dow = config._locale._week.dow;
doy = config._locale._week.doy;
curWeek = weekOfYear(createLocal(), dow, doy);
weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
// Default to current week.
week = defaults(w.w, curWeek.week);
if (w.d != null) {
// weekday -- low day numbers are considered next week
weekday = w.d;
if (weekday < 0 || weekday > 6) {
weekdayOverflow = true;
}
} else if (w.e != null) {
// local weekday -- counting starts from beginning of week
weekday = w.e + dow;
if (w.e < 0 || w.e > 6) {
weekdayOverflow = true;
}
} else {
// default to beginning of week
weekday = dow;
}
}
if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
getParsingFlags(config)._overflowWeeks = true;
} else if (weekdayOverflow != null) {
getParsingFlags(config)._overflowWeekday = true;
} else {
temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
config._a[YEAR] = temp.year;
config._dayOfYear = temp.dayOfYear;
}
}
// constant that refers to the ISO standard
hooks.ISO_8601 = function () {};
// constant that refers to the RFC 2822 form
hooks.RFC_2822 = function () {};
// date from string and format string
function configFromStringAndFormat(config) {
// TODO: Move this to another part of the creation flow to prevent circular deps
if (config._f === hooks.ISO_8601) {
configFromISO(config);
return;
}
if (config._f === hooks.RFC_2822) {
configFromRFC2822(config);
return;
}
config._a = [];
getParsingFlags(config).empty = true;
// This array is used to make a Date, either with `new Date` or `Date.UTC`
var string = '' + config._i,
i,
parsedInput,
tokens,
token,
skipped,
stringLength = string.length,
totalParsedInputLength = 0,
era,
tokenLen;
tokens =
expandFormat(config._f, config._locale).match(formattingTokens) || [];
tokenLen = tokens.length;
for (i = 0; i < tokenLen; i++) {
token = tokens[i];
parsedInput = (string.match(getParseRegexForToken(token, config)) ||
[])[0];
if (parsedInput) {
skipped = string.substr(0, string.indexOf(parsedInput));
if (skipped.length > 0) {
getParsingFlags(config).unusedInput.push(skipped);
}
string = string.slice(
string.indexOf(parsedInput) + parsedInput.length
);
totalParsedInputLength += parsedInput.length;
}
// don't parse if it's not a known token
if (formatTokenFunctions[token]) {
if (parsedInput) {
getParsingFlags(config).empty = false;
} else {
getParsingFlags(config).unusedTokens.push(token);
}
addTimeToArrayFromToken(token, parsedInput, config);
} else if (config._strict && !parsedInput) {
getParsingFlags(config).unusedTokens.push(token);
}
}
// add remaining unparsed input length to the string
getParsingFlags(config).charsLeftOver =
stringLength - totalParsedInputLength;
if (string.length > 0) {
getParsingFlags(config).unusedInput.push(string);
}
// clear _12h flag if hour is <= 12
if (
config._a[HOUR] <= 12 &&
getParsingFlags(config).bigHour === true &&
config._a[HOUR] > 0
) {
getParsingFlags(config).bigHour = undefined;
}
getParsingFlags(config).parsedDateParts = config._a.slice(0);
getParsingFlags(config).meridiem = config._meridiem;
// handle meridiem
config._a[HOUR] = meridiemFixWrap(
config._locale,
config._a[HOUR],
config._meridiem
);
// handle era
era = getParsingFlags(config).era;
if (era !== null) {
config._a[YEAR] = config._locale.erasConvertYear(era, config._a[YEAR]);
}
configFromArray(config);
checkOverflow(config);
}
function meridiemFixWrap(locale, hour, meridiem) {
var isPm;
if (meridiem == null) {
// nothing to do
return hour;
}
if (locale.meridiemHour != null) {
return locale.meridiemHour(hour, meridiem);
} else if (locale.isPM != null) {
// Fallback
isPm = locale.isPM(meridiem);
if (isPm && hour < 12) {
hour += 12;
}
if (!isPm && hour === 12) {
hour = 0;
}
return hour;
} else {
// this is not supposed to happen
return hour;
}
}
// date from string and array of format strings
function configFromStringAndArray(config) {
var tempConfig,
bestMoment,
scoreToBeat,
i,
currentScore,
validFormatFound,
bestFormatIsValid = false,
configfLen = config._f.length;
if (configfLen === 0) {
getParsingFlags(config).invalidFormat = true;
config._d = new Date(NaN);
return;
}
for (i = 0; i < configfLen; i++) {
currentScore = 0;
validFormatFound = false;
tempConfig = copyConfig({}, config);
if (config._useUTC != null) {
tempConfig._useUTC = config._useUTC;
}
tempConfig._f = config._f[i];
configFromStringAndFormat(tempConfig);
if (isValid(tempConfig)) {
validFormatFound = true;
}
// if there is any input that was not parsed add a penalty for that format
currentScore += getParsingFlags(tempConfig).charsLeftOver;
//or tokens
currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
getParsingFlags(tempConfig).score = currentScore;
if (!bestFormatIsValid) {
if (
scoreToBeat == null ||
currentScore < scoreToBeat ||
validFormatFound
) {
scoreToBeat = currentScore;
bestMoment = tempConfig;
if (validFormatFound) {
bestFormatIsValid = true;
}
}
} else {
if (currentScore < scoreToBeat) {
scoreToBeat = currentScore;
bestMoment = tempConfig;
}
}
}
extend(config, bestMoment || tempConfig);
}
function configFromObject(config) {
if (config._d) {
return;
}
var i = normalizeObjectUnits(config._i),
dayOrDate = i.day === undefined ? i.date : i.day;
config._a = map(
[i.year, i.month, dayOrDate, i.hour, i.minute, i.second, i.millisecond],
function (obj) {
return obj && parseInt(obj, 10);
}
);
configFromArray(config);
}
function createFromConfig(config) {
var res = new Moment(checkOverflow(prepareConfig(config)));
if (res._nextDay) {
// Adding is smart enough around DST
res.add(1, 'd');
res._nextDay = undefined;
}
return res;
}
function prepareConfig(config) {
var input = config._i,
format = config._f;
config._locale = config._locale || getLocale(config._l);
if (input === null || (format === undefined && input === '')) {
return createInvalid({ nullInput: true });
}
if (typeof input === 'string') {
config._i = input = config._locale.preparse(input);
}
if (isMoment(input)) {
return new Moment(checkOverflow(input));
} else if (isDate(input)) {
config._d = input;
} else if (isArray(format)) {
configFromStringAndArray(config);
} else if (format) {
configFromStringAndFormat(config);
} else {
configFromInput(config);
}
if (!isValid(config)) {
config._d = null;
}
return config;
}
function configFromInput(config) {
var input = config._i;
if (isUndefined(input)) {
config._d = new Date(hooks.now());
} else if (isDate(input)) {
config._d = new Date(input.valueOf());
} else if (typeof input === 'string') {
configFromString(config);
} else if (isArray(input)) {
config._a = map(input.slice(0), function (obj) {
return parseInt(obj, 10);
});
configFromArray(config);
} else if (isObject(input)) {
configFromObject(config);
} else if (isNumber(input)) {
// from milliseconds
config._d = new Date(input);
} else {
hooks.createFromInputFallback(config);
}
}
function createLocalOrUTC(input, format, locale, strict, isUTC) {
var c = {};
if (format === true || format === false) {
strict = format;
format = undefined;
}
if (locale === true || locale === false) {
strict = locale;
locale = undefined;
}
if (
(isObject(input) && isObjectEmpty(input)) ||
(isArray(input) && input.length === 0)
) {
input = undefined;
}
// object construction must be done this way.
// https://github.com/moment/moment/issues/1423
c._isAMomentObject = true;
c._useUTC = c._isUTC = isUTC;
c._l = locale;
c._i = input;
c._f = format;
c._strict = strict;
return createFromConfig(c);
}
function createLocal(input, format, locale, strict) {
return createLocalOrUTC(input, format, locale, strict, false);
}
var prototypeMin = deprecate(
'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
function () {
var other = createLocal.apply(null, arguments);
if (this.isValid() && other.isValid()) {
return other < this ? this : other;
} else {
return createInvalid();
}
}
),
prototypeMax = deprecate(
'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
function () {
var other = createLocal.apply(null, arguments);
if (this.isValid() && other.isValid()) {
return other > this ? this : other;
} else {
return createInvalid();
}
}
);
// Pick a moment m from moments so that m[fn](other) is true for all
// other. This relies on the function fn to be transitive.
//
// moments should either be an array of moment objects or an array, whose
// first element is an array of moment objects.
function pickBy(fn, moments) {
var res, i;
if (moments.length === 1 && isArray(moments[0])) {
moments = moments[0];
}
if (!moments.length) {
return createLocal();
}
res = moments[0];
for (i = 1; i < moments.length; ++i) {
if (!moments[i].isValid() || moments[i][fn](res)) {
res = moments[i];
}
}
return res;
}
// TODO: Use [].sort instead?
function min() {
var args = [].slice.call(arguments, 0);
return pickBy('isBefore', args);
}
function max() {
var args = [].slice.call(arguments, 0);
return pickBy('isAfter', args);
}
var now = function () {
return Date.now ? Date.now() : +new Date();
};
var ordering = [
'year',
'quarter',
'month',
'week',
'day',
'hour',
'minute',
'second',
'millisecond',
];
function isDurationValid(m) {
var key,
unitHasDecimal = false,
i,
orderLen = ordering.length;
for (key in m) {
if (
hasOwnProp(m, key) &&
!(
indexOf.call(ordering, key) !== -1 &&
(m[key] == null || !isNaN(m[key]))
)
) {
return false;
}
}
for (i = 0; i < orderLen; ++i) {
if (m[ordering[i]]) {
if (unitHasDecimal) {
return false; // only allow non-integers for smallest unit
}
if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
unitHasDecimal = true;
}
}
}
return true;
}
function isValid$1() {
return this._isValid;
}
function createInvalid$1() {
return createDuration(NaN);
}
function Duration(duration) {
var normalizedInput = normalizeObjectUnits(duration),
years = normalizedInput.year || 0,
quarters = normalizedInput.quarter || 0,
months = normalizedInput.month || 0,
weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
days = normalizedInput.day || 0,
hours = normalizedInput.hour || 0,
minutes = normalizedInput.minute || 0,
seconds = normalizedInput.second || 0,
milliseconds = normalizedInput.millisecond || 0;
this._isValid = isDurationValid(normalizedInput);
// representation for dateAddRemove
this._milliseconds =
+milliseconds +
seconds * 1e3 + // 1000
minutes * 6e4 + // 1000 * 60
hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
// Because of dateAddRemove treats 24 hours as different from a
// day when working around DST, we need to store them separately
this._days = +days + weeks * 7;
// It is impossible to translate months into days without knowing
// which months you are are talking about, so we have to store
// it separately.
this._months = +months + quarters * 3 + years * 12;
this._data = {};
this._locale = getLocale();
this._bubble();
}
function isDuration(obj) {
return obj instanceof Duration;
}
function absRound(number) {
if (number < 0) {
return Math.round(-1 * number) * -1;
} else {
return Math.round(number);
}
}
// compare two arrays, return the number of differences
function compareArrays(array1, array2, dontConvert) {
var len = Math.min(array1.length, array2.length),
lengthDiff = Math.abs(array1.length - array2.length),
diffs = 0,
i;
for (i = 0; i < len; i++) {
if (
(dontConvert && array1[i] !== array2[i]) ||
(!dontConvert && toInt(array1[i]) !== toInt(array2[i]))
) {
diffs++;
}
}
return diffs + lengthDiff;
}
// FORMATTING
function offset(token, separator) {
addFormatToken(token, 0, 0, function () {
var offset = this.utcOffset(),
sign = '+';
if (offset < 0) {
offset = -offset;
sign = '-';
}
return (
sign +
zeroFill(~~(offset / 60), 2) +
separator +
zeroFill(~~offset % 60, 2)
);
});
}
offset('Z', ':');
offset('ZZ', '');
// PARSING
addRegexToken('Z', matchShortOffset);
addRegexToken('ZZ', matchShortOffset);
addParseToken(['Z', 'ZZ'], function (input, array, config) {
config._useUTC = true;
config._tzm = offsetFromString(matchShortOffset, input);
});
// HELPERS
// timezone chunker
// '+10:00' > ['10', '00']
// '-1530' > ['-15', '30']
var chunkOffset = /([\+\-]|\d\d)/gi;
function offsetFromString(matcher, string) {
var matches = (string || '').match(matcher),
chunk,
parts,
minutes;
if (matches === null) {
return null;
}
chunk = matches[matches.length - 1] || [];
parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
minutes = +(parts[1] * 60) + toInt(parts[2]);
return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes;
}
// Return a moment from input, that is local/utc/zone equivalent to model.
function cloneWithOffset(input, model) {
var res, diff;
if (model._isUTC) {
res = model.clone();
diff =
(isMoment(input) || isDate(input)
? input.valueOf()
: createLocal(input).valueOf()) - res.valueOf();
// Use low-level api, because this fn is low-level api.
res._d.setTime(res._d.valueOf() + diff);
hooks.updateOffset(res, false);
return res;
} else {
return createLocal(input).local();
}
}
function getDateOffset(m) {
// On Firefox.24 Date#getTimezoneOffset returns a floating point.
// https://github.com/moment/moment/pull/1871
return -Math.round(m._d.getTimezoneOffset());
}
// HOOKS
// This function will be called whenever a moment is mutated.
// It is intended to keep the offset in sync with the timezone.
hooks.updateOffset = function () {};
// MOMENTS
// keepLocalTime = true means only change the timezone, without
// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
// +0200, so we adjust the time as needed, to be valid.
//
// Keeping the time actually adds/subtracts (one hour)
// from the actual represented time. That is why we call updateOffset
// a second time. In case it wants us to change the offset again
// _changeInProgress == true case, then we have to adjust, because
// there is no such time in the given timezone.
function getSetOffset(input, keepLocalTime, keepMinutes) {
var offset = this._offset || 0,
localAdjust;
if (!this.isValid()) {
return input != null ? this : NaN;
}
if (input != null) {
if (typeof input === 'string') {
input = offsetFromString(matchShortOffset, input);
if (input === null) {
return this;
}
} else if (Math.abs(input) < 16 && !keepMinutes) {
input = input * 60;
}
if (!this._isUTC && keepLocalTime) {
localAdjust = getDateOffset(this);
}
this._offset = input;
this._isUTC = true;
if (localAdjust != null) {
this.add(localAdjust, 'm');
}
if (offset !== input) {
if (!keepLocalTime || this._changeInProgress) {
addSubtract(
this,
createDuration(input - offset, 'm'),
1,
false
);
} else if (!this._changeInProgress) {
this._changeInProgress = true;
hooks.updateOffset(this, true);
this._changeInProgress = null;
}
}
return this;
} else {
return this._isUTC ? offset : getDateOffset(this);
}
}
function getSetZone(input, keepLocalTime) {
if (input != null) {
if (typeof input !== 'string') {
input = -input;
}
this.utcOffset(input, keepLocalTime);
return this;
} else {
return -this.utcOffset();
}
}
function setOffsetToUTC(keepLocalTime) {
return this.utcOffset(0, keepLocalTime);
}
function setOffsetToLocal(keepLocalTime) {
if (this._isUTC) {
this.utcOffset(0, keepLocalTime);
this._isUTC = false;
if (keepLocalTime) {
this.subtract(getDateOffset(this), 'm');
}
}
return this;
}
function setOffsetToParsedOffset() {
if (this._tzm != null) {
this.utcOffset(this._tzm, false, true);
} else if (typeof this._i === 'string') {
var tZone = offsetFromString(matchOffset, this._i);
if (tZone != null) {
this.utcOffset(tZone);
} else {
this.utcOffset(0, true);
}
}
return this;
}
function hasAlignedHourOffset(input) {
if (!this.isValid()) {
return false;
}
input = input ? createLocal(input).utcOffset() : 0;
return (this.utcOffset() - input) % 60 === 0;
}
function isDaylightSavingTime() {
return (
this.utcOffset() > this.clone().month(0).utcOffset() ||
this.utcOffset() > this.clone().month(5).utcOffset()
);
}
function isDaylightSavingTimeShifted() {
if (!isUndefined(this._isDSTShifted)) {
return this._isDSTShifted;
}
var c = {},
other;
copyConfig(c, this);
c = prepareConfig(c);
if (c._a) {
other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
this._isDSTShifted =
this.isValid() && compareArrays(c._a, other.toArray()) > 0;
} else {
this._isDSTShifted = false;
}
return this._isDSTShifted;
}
function isLocal() {
return this.isValid() ? !this._isUTC : false;
}
function isUtcOffset() {
return this.isValid() ? this._isUTC : false;
}
function isUtc() {
return this.isValid() ? this._isUTC && this._offset === 0 : false;
}
// ASP.NET json date format regex
var aspNetRegex = /^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,
// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
// and further modified to allow for strings containing both week and day
isoRegex =
/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
function createDuration(input, key) {
var duration = input,
// matching against regexp is expensive, do it on demand
match = null,
sign,
ret,
diffRes;
if (isDuration(input)) {
duration = {
ms: input._milliseconds,
d: input._days,
M: input._months,
};
} else if (isNumber(input) || !isNaN(+input)) {
duration = {};
if (key) {
duration[key] = +input;
} else {
duration.milliseconds = +input;
}
} else if ((match = aspNetRegex.exec(input))) {
sign = match[1] === '-' ? -1 : 1;
duration = {
y: 0,
d: toInt(match[DATE]) * sign,
h: toInt(match[HOUR]) * sign,
m: toInt(match[MINUTE]) * sign,
s: toInt(match[SECOND]) * sign,
ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign, // the millisecond decimal point is included in the match
};
} else if ((match = isoRegex.exec(input))) {
sign = match[1] === '-' ? -1 : 1;
duration = {
y: parseIso(match[2], sign),
M: parseIso(match[3], sign),
w: parseIso(match[4], sign),
d: parseIso(match[5], sign),
h: parseIso(match[6], sign),
m: parseIso(match[7], sign),
s: parseIso(match[8], sign),
};
} else if (duration == null) {
// checks for null or undefined
duration = {};
} else if (
typeof duration === 'object' &&
('from' in duration || 'to' in duration)
) {
diffRes = momentsDifference(
createLocal(duration.from),
createLocal(duration.to)
);
duration = {};
duration.ms = diffRes.milliseconds;
duration.M = diffRes.months;
}
ret = new Duration(duration);
if (isDuration(input) && hasOwnProp(input, '_locale')) {
ret._locale = input._locale;
}
if (isDuration(input) && hasOwnProp(input, '_isValid')) {
ret._isValid = input._isValid;
}
return ret;
}
createDuration.fn = Duration.prototype;
createDuration.invalid = createInvalid$1;
function parseIso(inp, sign) {
// We'd normally use ~~inp for this, but unfortunately it also
// converts floats to ints.
// inp may be undefined, so careful calling replace on it.
var res = inp && parseFloat(inp.replace(',', '.'));
// apply sign while we're at it
return (isNaN(res) ? 0 : res) * sign;
}
function positiveMomentsDifference(base, other) {
var res = {};
res.months =
other.month() - base.month() + (other.year() - base.year()) * 12;
if (base.clone().add(res.months, 'M').isAfter(other)) {
--res.months;
}
res.milliseconds = +other - +base.clone().add(res.months, 'M');
return res;
}
function momentsDifference(base, other) {
var res;
if (!(base.isValid() && other.isValid())) {
return { milliseconds: 0, months: 0 };
}
other = cloneWithOffset(other, base);
if (base.isBefore(other)) {
res = positiveMomentsDifference(base, other);
} else {
res = positiveMomentsDifference(other, base);
res.milliseconds = -res.milliseconds;
res.months = -res.months;
}
return res;
}
// TODO: remove 'name' arg after deprecation is removed
function createAdder(direction, name) {
return function (val, period) {
var dur, tmp;
//invert the arguments, but complain about it
if (period !== null && !isNaN(+period)) {
deprecateSimple(
name,
'moment().' +
name +
'(period, number) is deprecated. Please use moment().' +
name +
'(number, period). ' +
'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'
);
tmp = val;
val = period;
period = tmp;
}
dur = createDuration(val, period);
addSubtract(this, dur, direction);
return this;
};
}
function addSubtract(mom, duration, isAdding, updateOffset) {
var milliseconds = duration._milliseconds,
days = absRound(duration._days),
months = absRound(duration._months);
if (!mom.isValid()) {
// No op
return;
}
updateOffset = updateOffset == null ? true : updateOffset;
if (months) {
setMonth(mom, get(mom, 'Month') + months * isAdding);
}
if (days) {
set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
}
if (milliseconds) {
mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
}
if (updateOffset) {
hooks.updateOffset(mom, days || months);
}
}
var add = createAdder(1, 'add'),
subtract = createAdder(-1, 'subtract');
function isString(input) {
return typeof input === 'string' || input instanceof String;
}
// type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void; // null | undefined
function isMomentInput(input) {
return (
isMoment(input) ||
isDate(input) ||
isString(input) ||
isNumber(input) ||
isNumberOrStringArray(input) ||
isMomentInputObject(input) ||
input === null ||
input === undefined
);
}
function isMomentInputObject(input) {
var objectTest = isObject(input) && !isObjectEmpty(input),
propertyTest = false,
properties = [
'years',
'year',
'y',
'months',
'month',
'M',
'days',
'day',
'd',
'dates',
'date',
'D',
'hours',
'hour',
'h',
'minutes',
'minute',
'm',
'seconds',
'second',
's',
'milliseconds',
'millisecond',
'ms',
],
i,
property,
propertyLen = properties.length;
for (i = 0; i < propertyLen; i += 1) {
property = properties[i];
propertyTest = propertyTest || hasOwnProp(input, property);
}
return objectTest && propertyTest;
}
function isNumberOrStringArray(input) {
var arrayTest = isArray(input),
dataTypeTest = false;
if (arrayTest) {
dataTypeTest =
input.filter(function (item) {
return !isNumber(item) && isString(input);
}).length === 0;
}
return arrayTest && dataTypeTest;
}
function isCalendarSpec(input) {
var objectTest = isObject(input) && !isObjectEmpty(input),
propertyTest = false,
properties = [
'sameDay',
'nextDay',
'lastDay',
'nextWeek',
'lastWeek',
'sameElse',
],
i,
property;
for (i = 0; i < properties.length; i += 1) {
property = properties[i];
propertyTest = propertyTest || hasOwnProp(input, property);
}
return objectTest && propertyTest;
}
function getCalendarFormat(myMoment, now) {
var diff = myMoment.diff(now, 'days', true);
return diff < -6
? 'sameElse'
: diff < -1
? 'lastWeek'
: diff < 0
? 'lastDay'
: diff < 1
? 'sameDay'
: diff < 2
? 'nextDay'
: diff < 7
? 'nextWeek'
: 'sameElse';
}
function calendar$1(time, formats) {
// Support for single parameter, formats only overload to the calendar function
if (arguments.length === 1) {
if (!arguments[0]) {
time = undefined;
formats = undefined;
} else if (isMomentInput(arguments[0])) {
time = arguments[0];
formats = undefined;
} else if (isCalendarSpec(arguments[0])) {
formats = arguments[0];
time = undefined;
}
}
// We want to compare the start of today, vs this.
// Getting start-of-today depends on whether we're local/utc/offset or not.
var now = time || createLocal(),
sod = cloneWithOffset(now, this).startOf('day'),
format = hooks.calendarFormat(this, sod) || 'sameElse',
output =
formats &&
(isFunction(formats[format])
? formats[format].call(this, now)
: formats[format]);
return this.format(
output || this.localeData().calendar(format, this, createLocal(now))
);
}
function clone() {
return new Moment(this);
}
function isAfter(input, units) {
var localInput = isMoment(input) ? input : createLocal(input);
if (!(this.isValid() && localInput.isValid())) {
return false;
}
units = normalizeUnits(units) || 'millisecond';
if (units === 'millisecond') {
return this.valueOf() > localInput.valueOf();
} else {
return localInput.valueOf() < this.clone().startOf(units).valueOf();
}
}
function isBefore(input, units) {
var localInput = isMoment(input) ? input : createLocal(input);
if (!(this.isValid() && localInput.isValid())) {
return false;
}
units = normalizeUnits(units) || 'millisecond';
if (units === 'millisecond') {
return this.valueOf() < localInput.valueOf();
} else {
return this.clone().endOf(units).valueOf() < localInput.valueOf();
}
}
function isBetween(from, to, units, inclusivity) {
var localFrom = isMoment(from) ? from : createLocal(from),
localTo = isMoment(to) ? to : createLocal(to);
if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
return false;
}
inclusivity = inclusivity || '()';
return (
(inclusivity[0] === '('
? this.isAfter(localFrom, units)
: !this.isBefore(localFrom, units)) &&
(inclusivity[1] === ')'
? this.isBefore(localTo, units)
: !this.isAfter(localTo, units))
);
}
function isSame(input, units) {
var localInput = isMoment(input) ? input : createLocal(input),
inputMs;
if (!(this.isValid() && localInput.isValid())) {
return false;
}
units = normalizeUnits(units) || 'millisecond';
if (units === 'millisecond') {
return this.valueOf() === localInput.valueOf();
} else {
inputMs = localInput.valueOf();
return (
this.clone().startOf(units).valueOf() <= inputMs &&
inputMs <= this.clone().endOf(units).valueOf()
);
}
}
function isSameOrAfter(input, units) {
return this.isSame(input, units) || this.isAfter(input, units);
}
function isSameOrBefore(input, units) {
return this.isSame(input, units) || this.isBefore(input, units);
}
function diff(input, units, asFloat) {
var that, zoneDelta, output;
if (!this.isValid()) {
return NaN;
}
that = cloneWithOffset(input, this);
if (!that.isValid()) {
return NaN;
}
zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
units = normalizeUnits(units);
switch (units) {
case 'year':
output = monthDiff(this, that) / 12;
break;
case 'month':
output = monthDiff(this, that);
break;
case 'quarter':
output = monthDiff(this, that) / 3;
break;
case 'second':
output = (this - that) / 1e3;
break; // 1000
case 'minute':
output = (this - that) / 6e4;
break; // 1000 * 60
case 'hour':
output = (this - that) / 36e5;
break; // 1000 * 60 * 60
case 'day':
output = (this - that - zoneDelta) / 864e5;
break; // 1000 * 60 * 60 * 24, negate dst
case 'week':
output = (this - that - zoneDelta) / 6048e5;
break; // 1000 * 60 * 60 * 24 * 7, negate dst
default:
output = this - that;
}
return asFloat ? output : absFloor(output);
}
function monthDiff(a, b) {
if (a.date() < b.date()) {
// end-of-month calculations work correct when the start month has more
// days than the end month.
return -monthDiff(b, a);
}
// difference in months
var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
// b is in (anchor - 1 month, anchor + 1 month)
anchor = a.clone().add(wholeMonthDiff, 'months'),
anchor2,
adjust;
if (b - anchor < 0) {
anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
// linear across the month
adjust = (b - anchor) / (anchor - anchor2);
} else {
anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
// linear across the month
adjust = (b - anchor) / (anchor2 - anchor);
}
//check for negative zero, return zero if negative zero
return -(wholeMonthDiff + adjust) || 0;
}
hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
function toString() {
return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
}
function toISOString(keepOffset) {
if (!this.isValid()) {
return null;
}
var utc = keepOffset !== true,
m = utc ? this.clone().utc() : this;
if (m.year() < 0 || m.year() > 9999) {
return formatMoment(
m,
utc
? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'
: 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ'
);
}
if (isFunction(Date.prototype.toISOString)) {
// native implementation is ~50x faster, use it when we can
if (utc) {
return this.toDate().toISOString();
} else {
return new Date(this.valueOf() + this.utcOffset() * 60 * 1000)
.toISOString()
.replace('Z', formatMoment(m, 'Z'));
}
}
return formatMoment(
m,
utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ'
);
}
/**
* Return a human readable representation of a moment that can
* also be evaluated to get a new moment which is the same
*
* @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
*/
function inspect() {
if (!this.isValid()) {
return 'moment.invalid(/* ' + this._i + ' */)';
}
var func = 'moment',
zone = '',
prefix,
year,
datetime,
suffix;
if (!this.isLocal()) {
func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
zone = 'Z';
}
prefix = '[' + func + '("]';
year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';
datetime = '-MM-DD[T]HH:mm:ss.SSS';
suffix = zone + '[")]';
return this.format(prefix + year + datetime + suffix);
}
function format(inputString) {
if (!inputString) {
inputString = this.isUtc()
? hooks.defaultFormatUtc
: hooks.defaultFormat;
}
var output = formatMoment(this, inputString);
return this.localeData().postformat(output);
}
function from(time, withoutSuffix) {
if (
this.isValid() &&
((isMoment(time) && time.isValid()) || createLocal(time).isValid())
) {
return createDuration({ to: this, from: time })
.locale(this.locale())
.humanize(!withoutSuffix);
} else {
return this.localeData().invalidDate();
}
}
function fromNow(withoutSuffix) {
return this.from(createLocal(), withoutSuffix);
}
function to(time, withoutSuffix) {
if (
this.isValid() &&
((isMoment(time) && time.isValid()) || createLocal(time).isValid())
) {
return createDuration({ from: this, to: time })
.locale(this.locale())
.humanize(!withoutSuffix);
} else {
return this.localeData().invalidDate();
}
}
function toNow(withoutSuffix) {
return this.to(createLocal(), withoutSuffix);
}
// If passed a locale key, it will set the locale for this
// instance. Otherwise, it will return the locale configuration
// variables for this instance.
function locale(key) {
var newLocaleData;
if (key === undefined) {
return this._locale._abbr;
} else {
newLocaleData = getLocale(key);
if (newLocaleData != null) {
this._locale = newLocaleData;
}
return this;
}
}
var lang = deprecate(
'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
function (key) {
if (key === undefined) {
return this.localeData();
} else {
return this.locale(key);
}
}
);
function localeData() {
return this._locale;
}
var MS_PER_SECOND = 1000,
MS_PER_MINUTE = 60 * MS_PER_SECOND,
MS_PER_HOUR = 60 * MS_PER_MINUTE,
MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
// actual modulo - handles negative numbers (for dates before 1970):
function mod$1(dividend, divisor) {
return ((dividend % divisor) + divisor) % divisor;
}
function localStartOfDate(y, m, d) {
// the date constructor remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
// preserve leap years using a full 400 year cycle, then reset
return new Date(y + 400, m, d) - MS_PER_400_YEARS;
} else {
return new Date(y, m, d).valueOf();
}
}
function utcStartOfDate(y, m, d) {
// Date.UTC remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
// preserve leap years using a full 400 year cycle, then reset
return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
} else {
return Date.UTC(y, m, d);
}
}
function startOf(units) {
var time, startOfDate;
units = normalizeUnits(units);
if (units === undefined || units === 'millisecond' || !this.isValid()) {
return this;
}
startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
switch (units) {
case 'year':
time = startOfDate(this.year(), 0, 1);
break;
case 'quarter':
time = startOfDate(
this.year(),
this.month() - (this.month() % 3),
1
);
break;
case 'month':
time = startOfDate(this.year(), this.month(), 1);
break;
case 'week':
time = startOfDate(
this.year(),
this.month(),
this.date() - this.weekday()
);
break;
case 'isoWeek':
time = startOfDate(
this.year(),
this.month(),
this.date() - (this.isoWeekday() - 1)
);
break;
case 'day':
case 'date':
time = startOfDate(this.year(), this.month(), this.date());
break;
case 'hour':
time = this._d.valueOf();
time -= mod$1(
time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
MS_PER_HOUR
);
break;
case 'minute':
time = this._d.valueOf();
time -= mod$1(time, MS_PER_MINUTE);
break;
case 'second':
time = this._d.valueOf();
time -= mod$1(time, MS_PER_SECOND);
break;
}
this._d.setTime(time);
hooks.updateOffset(this, true);
return this;
}
function endOf(units) {
var time, startOfDate;
units = normalizeUnits(units);
if (units === undefined || units === 'millisecond' || !this.isValid()) {
return this;
}
startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
switch (units) {
case 'year':
time = startOfDate(this.year() + 1, 0, 1) - 1;
break;
case 'quarter':
time =
startOfDate(
this.year(),
this.month() - (this.month() % 3) + 3,
1
) - 1;
break;
case 'month':
time = startOfDate(this.year(), this.month() + 1, 1) - 1;
break;
case 'week':
time =
startOfDate(
this.year(),
this.month(),
this.date() - this.weekday() + 7
) - 1;
break;
case 'isoWeek':
time =
startOfDate(
this.year(),
this.month(),
this.date() - (this.isoWeekday() - 1) + 7
) - 1;
break;
case 'day':
case 'date':
time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
break;
case 'hour':
time = this._d.valueOf();
time +=
MS_PER_HOUR -
mod$1(
time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
MS_PER_HOUR
) -
1;
break;
case 'minute':
time = this._d.valueOf();
time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
break;
case 'second':
time = this._d.valueOf();
time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
break;
}
this._d.setTime(time);
hooks.updateOffset(this, true);
return this;
}
function valueOf() {
return this._d.valueOf() - (this._offset || 0) * 60000;
}
function unix() {
return Math.floor(this.valueOf() / 1000);
}
function toDate() {
return new Date(this.valueOf());
}
function toArray() {
var m = this;
return [
m.year(),
m.month(),
m.date(),
m.hour(),
m.minute(),
m.second(),
m.millisecond(),
];
}
function toObject() {
var m = this;
return {
years: m.year(),
months: m.month(),
date: m.date(),
hours: m.hours(),
minutes: m.minutes(),
seconds: m.seconds(),
milliseconds: m.milliseconds(),
};
}
function toJSON() {
// new Date(NaN).toJSON() === null
return this.isValid() ? this.toISOString() : null;
}
function isValid$2() {
return isValid(this);
}
function parsingFlags() {
return extend({}, getParsingFlags(this));
}
function invalidAt() {
return getParsingFlags(this).overflow;
}
function creationData() {
return {
input: this._i,
format: this._f,
locale: this._locale,
isUTC: this._isUTC,
strict: this._strict,
};
}
addFormatToken('N', 0, 0, 'eraAbbr');
addFormatToken('NN', 0, 0, 'eraAbbr');
addFormatToken('NNN', 0, 0, 'eraAbbr');
addFormatToken('NNNN', 0, 0, 'eraName');
addFormatToken('NNNNN', 0, 0, 'eraNarrow');
addFormatToken('y', ['y', 1], 'yo', 'eraYear');
addFormatToken('y', ['yy', 2], 0, 'eraYear');
addFormatToken('y', ['yyy', 3], 0, 'eraYear');
addFormatToken('y', ['yyyy', 4], 0, 'eraYear');
addRegexToken('N', matchEraAbbr);
addRegexToken('NN', matchEraAbbr);
addRegexToken('NNN', matchEraAbbr);
addRegexToken('NNNN', matchEraName);
addRegexToken('NNNNN', matchEraNarrow);
addParseToken(
['N', 'NN', 'NNN', 'NNNN', 'NNNNN'],
function (input, array, config, token) {
var era = config._locale.erasParse(input, token, config._strict);
if (era) {
getParsingFlags(config).era = era;
} else {
getParsingFlags(config).invalidEra = input;
}
}
);
addRegexToken('y', matchUnsigned);
addRegexToken('yy', matchUnsigned);
addRegexToken('yyy', matchUnsigned);
addRegexToken('yyyy', matchUnsigned);
addRegexToken('yo', matchEraYearOrdinal);
addParseToken(['y', 'yy', 'yyy', 'yyyy'], YEAR);
addParseToken(['yo'], function (input, array, config, token) {
var match;
if (config._locale._eraYearOrdinalRegex) {
match = input.match(config._locale._eraYearOrdinalRegex);
}
if (config._locale.eraYearOrdinalParse) {
array[YEAR] = config._locale.eraYearOrdinalParse(input, match);
} else {
array[YEAR] = parseInt(input, 10);
}
});
function localeEras(m, format) {
var i,
l,
date,
eras = this._eras || getLocale('en')._eras;
for (i = 0, l = eras.length; i < l; ++i) {
switch (typeof eras[i].since) {
case 'string':
// truncate time
date = hooks(eras[i].since).startOf('day');
eras[i].since = date.valueOf();
break;
}
switch (typeof eras[i].until) {
case 'undefined':
eras[i].until = +Infinity;
break;
case 'string':
// truncate time
date = hooks(eras[i].until).startOf('day').valueOf();
eras[i].until = date.valueOf();
break;
}
}
return eras;
}
function localeErasParse(eraName, format, strict) {
var i,
l,
eras = this.eras(),
name,
abbr,
narrow;
eraName = eraName.toUpperCase();
for (i = 0, l = eras.length; i < l; ++i) {
name = eras[i].name.toUpperCase();
abbr = eras[i].abbr.toUpperCase();
narrow = eras[i].narrow.toUpperCase();
if (strict) {
switch (format) {
case 'N':
case 'NN':
case 'NNN':
if (abbr === eraName) {
return eras[i];
}
break;
case 'NNNN':
if (name === eraName) {
return eras[i];
}
break;
case 'NNNNN':
if (narrow === eraName) {
return eras[i];
}
break;
}
} else if ([name, abbr, narrow].indexOf(eraName) >= 0) {
return eras[i];
}
}
}
function localeErasConvertYear(era, year) {
var dir = era.since <= era.until ? +1 : -1;
if (year === undefined) {
return hooks(era.since).year();
} else {
return hooks(era.since).year() + (year - era.offset) * dir;
}
}
function getEraName() {
var i,
l,
val,
eras = this.localeData().eras();
for (i = 0, l = eras.length; i < l; ++i) {
// truncate time
val = this.clone().startOf('day').valueOf();
if (eras[i].since <= val && val <= eras[i].until) {
return eras[i].name;
}
if (eras[i].until <= val && val <= eras[i].since) {
return eras[i].name;
}
}
return '';
}
function getEraNarrow() {
var i,
l,
val,
eras = this.localeData().eras();
for (i = 0, l = eras.length; i < l; ++i) {
// truncate time
val = this.clone().startOf('day').valueOf();
if (eras[i].since <= val && val <= eras[i].until) {
return eras[i].narrow;
}
if (eras[i].until <= val && val <= eras[i].since) {
return eras[i].narrow;
}
}
return '';
}
function getEraAbbr() {
var i,
l,
val,
eras = this.localeData().eras();
for (i = 0, l = eras.length; i < l; ++i) {
// truncate time
val = this.clone().startOf('day').valueOf();
if (eras[i].since <= val && val <= eras[i].until) {
return eras[i].abbr;
}
if (eras[i].until <= val && val <= eras[i].since) {
return eras[i].abbr;
}
}
return '';
}
function getEraYear() {
var i,
l,
dir,
val,
eras = this.localeData().eras();
for (i = 0, l = eras.length; i < l; ++i) {
dir = eras[i].since <= eras[i].until ? +1 : -1;
// truncate time
val = this.clone().startOf('day').valueOf();
if (
(eras[i].since <= val && val <= eras[i].until) ||
(eras[i].until <= val && val <= eras[i].since)
) {
return (
(this.year() - hooks(eras[i].since).year()) * dir +
eras[i].offset
);
}
}
return this.year();
}
function erasNameRegex(isStrict) {
if (!hasOwnProp(this, '_erasNameRegex')) {
computeErasParse.call(this);
}
return isStrict ? this._erasNameRegex : this._erasRegex;
}
function erasAbbrRegex(isStrict) {
if (!hasOwnProp(this, '_erasAbbrRegex')) {
computeErasParse.call(this);
}
return isStrict ? this._erasAbbrRegex : this._erasRegex;
}
function erasNarrowRegex(isStrict) {
if (!hasOwnProp(this, '_erasNarrowRegex')) {
computeErasParse.call(this);
}
return isStrict ? this._erasNarrowRegex : this._erasRegex;
}
function matchEraAbbr(isStrict, locale) {
return locale.erasAbbrRegex(isStrict);
}
function matchEraName(isStrict, locale) {
return locale.erasNameRegex(isStrict);
}
function matchEraNarrow(isStrict, locale) {
return locale.erasNarrowRegex(isStrict);
}
function matchEraYearOrdinal(isStrict, locale) {
return locale._eraYearOrdinalRegex || matchUnsigned;
}
function computeErasParse() {
var abbrPieces = [],
namePieces = [],
narrowPieces = [],
mixedPieces = [],
i,
l,
erasName,
erasAbbr,
erasNarrow,
eras = this.eras();
for (i = 0, l = eras.length; i < l; ++i) {
erasName = regexEscape(eras[i].name);
erasAbbr = regexEscape(eras[i].abbr);
erasNarrow = regexEscape(eras[i].narrow);
namePieces.push(erasName);
abbrPieces.push(erasAbbr);
narrowPieces.push(erasNarrow);
mixedPieces.push(erasName);
mixedPieces.push(erasAbbr);
mixedPieces.push(erasNarrow);
}
this._erasRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
this._erasNameRegex = new RegExp('^(' + namePieces.join('|') + ')', 'i');
this._erasAbbrRegex = new RegExp('^(' + abbrPieces.join('|') + ')', 'i');
this._erasNarrowRegex = new RegExp(
'^(' + narrowPieces.join('|') + ')',
'i'
);
}
// FORMATTING
addFormatToken(0, ['gg', 2], 0, function () {
return this.weekYear() % 100;
});
addFormatToken(0, ['GG', 2], 0, function () {
return this.isoWeekYear() % 100;
});
function addWeekYearFormatToken(token, getter) {
addFormatToken(0, [token, token.length], 0, getter);
}
addWeekYearFormatToken('gggg', 'weekYear');
addWeekYearFormatToken('ggggg', 'weekYear');
addWeekYearFormatToken('GGGG', 'isoWeekYear');
addWeekYearFormatToken('GGGGG', 'isoWeekYear');
// ALIASES
// PARSING
addRegexToken('G', matchSigned);
addRegexToken('g', matchSigned);
addRegexToken('GG', match1to2, match2);
addRegexToken('gg', match1to2, match2);
addRegexToken('GGGG', match1to4, match4);
addRegexToken('gggg', match1to4, match4);
addRegexToken('GGGGG', match1to6, match6);
addRegexToken('ggggg', match1to6, match6);
addWeekParseToken(
['gggg', 'ggggg', 'GGGG', 'GGGGG'],
function (input, week, config, token) {
week[token.substr(0, 2)] = toInt(input);
}
);
addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
week[token] = hooks.parseTwoDigitYear(input);
});
// MOMENTS
function getSetWeekYear(input) {
return getSetWeekYearHelper.call(
this,
input,
this.week(),
this.weekday() + this.localeData()._week.dow,
this.localeData()._week.dow,
this.localeData()._week.doy
);
}
function getSetISOWeekYear(input) {
return getSetWeekYearHelper.call(
this,
input,
this.isoWeek(),
this.isoWeekday(),
1,
4
);
}
function getISOWeeksInYear() {
return weeksInYear(this.year(), 1, 4);
}
function getISOWeeksInISOWeekYear() {
return weeksInYear(this.isoWeekYear(), 1, 4);
}
function getWeeksInYear() {
var weekInfo = this.localeData()._week;
return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
}
function getWeeksInWeekYear() {
var weekInfo = this.localeData()._week;
return weeksInYear(this.weekYear(), weekInfo.dow, weekInfo.doy);
}
function getSetWeekYearHelper(input, week, weekday, dow, doy) {
var weeksTarget;
if (input == null) {
return weekOfYear(this, dow, doy).year;
} else {
weeksTarget = weeksInYear(input, dow, doy);
if (week > weeksTarget) {
week = weeksTarget;
}
return setWeekAll.call(this, input, week, weekday, dow, doy);
}
}
function setWeekAll(weekYear, week, weekday, dow, doy) {
var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
this.year(date.getUTCFullYear());
this.month(date.getUTCMonth());
this.date(date.getUTCDate());
return this;
}
// FORMATTING
addFormatToken('Q', 0, 'Qo', 'quarter');
// PARSING
addRegexToken('Q', match1);
addParseToken('Q', function (input, array) {
array[MONTH] = (toInt(input) - 1) * 3;
});
// MOMENTS
function getSetQuarter(input) {
return input == null
? Math.ceil((this.month() + 1) / 3)
: this.month((input - 1) * 3 + (this.month() % 3));
}
// FORMATTING
addFormatToken('D', ['DD', 2], 'Do', 'date');
// PARSING
addRegexToken('D', match1to2, match1to2NoLeadingZero);
addRegexToken('DD', match1to2, match2);
addRegexToken('Do', function (isStrict, locale) {
// TODO: Remove "ordinalParse" fallback in next major release.
return isStrict
? locale._dayOfMonthOrdinalParse || locale._ordinalParse
: locale._dayOfMonthOrdinalParseLenient;
});
addParseToken(['D', 'DD'], DATE);
addParseToken('Do', function (input, array) {
array[DATE] = toInt(input.match(match1to2)[0]);
});
// MOMENTS
var getSetDayOfMonth = makeGetSet('Date', true);
// FORMATTING
addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
// PARSING
addRegexToken('DDD', match1to3);
addRegexToken('DDDD', match3);
addParseToken(['DDD', 'DDDD'], function (input, array, config) {
config._dayOfYear = toInt(input);
});
// HELPERS
// MOMENTS
function getSetDayOfYear(input) {
var dayOfYear =
Math.round(
(this.clone().startOf('day') - this.clone().startOf('year')) / 864e5
) + 1;
return input == null ? dayOfYear : this.add(input - dayOfYear, 'd');
}
// FORMATTING
addFormatToken('m', ['mm', 2], 0, 'minute');
// PARSING
addRegexToken('m', match1to2, match1to2HasZero);
addRegexToken('mm', match1to2, match2);
addParseToken(['m', 'mm'], MINUTE);
// MOMENTS
var getSetMinute = makeGetSet('Minutes', false);
// FORMATTING
addFormatToken('s', ['ss', 2], 0, 'second');
// PARSING
addRegexToken('s', match1to2, match1to2HasZero);
addRegexToken('ss', match1to2, match2);
addParseToken(['s', 'ss'], SECOND);
// MOMENTS
var getSetSecond = makeGetSet('Seconds', false);
// FORMATTING
addFormatToken('S', 0, 0, function () {
return ~~(this.millisecond() / 100);
});
addFormatToken(0, ['SS', 2], 0, function () {
return ~~(this.millisecond() / 10);
});
addFormatToken(0, ['SSS', 3], 0, 'millisecond');
addFormatToken(0, ['SSSS', 4], 0, function () {
return this.millisecond() * 10;
});
addFormatToken(0, ['SSSSS', 5], 0, function () {
return this.millisecond() * 100;
});
addFormatToken(0, ['SSSSSS', 6], 0, function () {
return this.millisecond() * 1000;
});
addFormatToken(0, ['SSSSSSS', 7], 0, function () {
return this.millisecond() * 10000;
});
addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
return this.millisecond() * 100000;
});
addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
return this.millisecond() * 1000000;
});
// PARSING
addRegexToken('S', match1to3, match1);
addRegexToken('SS', match1to3, match2);
addRegexToken('SSS', match1to3, match3);
var token, getSetMillisecond;
for (token = 'SSSS'; token.length <= 9; token += 'S') {
addRegexToken(token, matchUnsigned);
}
function parseMs(input, array) {
array[MILLISECOND] = toInt(('0.' + input) * 1000);
}
for (token = 'S'; token.length <= 9; token += 'S') {
addParseToken(token, parseMs);
}
getSetMillisecond = makeGetSet('Milliseconds', false);
// FORMATTING
addFormatToken('z', 0, 0, 'zoneAbbr');
addFormatToken('zz', 0, 0, 'zoneName');
// MOMENTS
function getZoneAbbr() {
return this._isUTC ? 'UTC' : '';
}
function getZoneName() {
return this._isUTC ? 'Coordinated Universal Time' : '';
}
var proto = Moment.prototype;
proto.add = add;
proto.calendar = calendar$1;
proto.clone = clone;
proto.diff = diff;
proto.endOf = endOf;
proto.format = format;
proto.from = from;
proto.fromNow = fromNow;
proto.to = to;
proto.toNow = toNow;
proto.get = stringGet;
proto.invalidAt = invalidAt;
proto.isAfter = isAfter;
proto.isBefore = isBefore;
proto.isBetween = isBetween;
proto.isSame = isSame;
proto.isSameOrAfter = isSameOrAfter;
proto.isSameOrBefore = isSameOrBefore;
proto.isValid = isValid$2;
proto.lang = lang;
proto.locale = locale;
proto.localeData = localeData;
proto.max = prototypeMax;
proto.min = prototypeMin;
proto.parsingFlags = parsingFlags;
proto.set = stringSet;
proto.startOf = startOf;
proto.subtract = subtract;
proto.toArray = toArray;
proto.toObject = toObject;
proto.toDate = toDate;
proto.toISOString = toISOString;
proto.inspect = inspect;
if (typeof Symbol !== 'undefined' && Symbol.for != null) {
proto[Symbol.for('nodejs.util.inspect.custom')] = function () {
return 'Moment<' + this.format() + '>';
};
}
proto.toJSON = toJSON;
proto.toString = toString;
proto.unix = unix;
proto.valueOf = valueOf;
proto.creationData = creationData;
proto.eraName = getEraName;
proto.eraNarrow = getEraNarrow;
proto.eraAbbr = getEraAbbr;
proto.eraYear = getEraYear;
proto.year = getSetYear;
proto.isLeapYear = getIsLeapYear;
proto.weekYear = getSetWeekYear;
proto.isoWeekYear = getSetISOWeekYear;
proto.quarter = proto.quarters = getSetQuarter;
proto.month = getSetMonth;
proto.daysInMonth = getDaysInMonth;
proto.week = proto.weeks = getSetWeek;
proto.isoWeek = proto.isoWeeks = getSetISOWeek;
proto.weeksInYear = getWeeksInYear;
proto.weeksInWeekYear = getWeeksInWeekYear;
proto.isoWeeksInYear = getISOWeeksInYear;
proto.isoWeeksInISOWeekYear = getISOWeeksInISOWeekYear;
proto.date = getSetDayOfMonth;
proto.day = proto.days = getSetDayOfWeek;
proto.weekday = getSetLocaleDayOfWeek;
proto.isoWeekday = getSetISODayOfWeek;
proto.dayOfYear = getSetDayOfYear;
proto.hour = proto.hours = getSetHour;
proto.minute = proto.minutes = getSetMinute;
proto.second = proto.seconds = getSetSecond;
proto.millisecond = proto.milliseconds = getSetMillisecond;
proto.utcOffset = getSetOffset;
proto.utc = setOffsetToUTC;
proto.local = setOffsetToLocal;
proto.parseZone = setOffsetToParsedOffset;
proto.hasAlignedHourOffset = hasAlignedHourOffset;
proto.isDST = isDaylightSavingTime;
proto.isLocal = isLocal;
proto.isUtcOffset = isUtcOffset;
proto.isUtc = isUtc;
proto.isUTC = isUtc;
proto.zoneAbbr = getZoneAbbr;
proto.zoneName = getZoneName;
proto.dates = deprecate(
'dates accessor is deprecated. Use date instead.',
getSetDayOfMonth
);
proto.months = deprecate(
'months accessor is deprecated. Use month instead',
getSetMonth
);
proto.years = deprecate(
'years accessor is deprecated. Use year instead',
getSetYear
);
proto.zone = deprecate(
'moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/',
getSetZone
);
proto.isDSTShifted = deprecate(
'isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information',
isDaylightSavingTimeShifted
);
function createUnix(input) {
return createLocal(input * 1000);
}
function createInZone() {
return createLocal.apply(null, arguments).parseZone();
}
function preParsePostFormat(string) {
return string;
}
var proto$1 = Locale.prototype;
proto$1.calendar = calendar;
proto$1.longDateFormat = longDateFormat;
proto$1.invalidDate = invalidDate;
proto$1.ordinal = ordinal;
proto$1.preparse = preParsePostFormat;
proto$1.postformat = preParsePostFormat;
proto$1.relativeTime = relativeTime;
proto$1.pastFuture = pastFuture;
proto$1.set = set;
proto$1.eras = localeEras;
proto$1.erasParse = localeErasParse;
proto$1.erasConvertYear = localeErasConvertYear;
proto$1.erasAbbrRegex = erasAbbrRegex;
proto$1.erasNameRegex = erasNameRegex;
proto$1.erasNarrowRegex = erasNarrowRegex;
proto$1.months = localeMonths;
proto$1.monthsShort = localeMonthsShort;
proto$1.monthsParse = localeMonthsParse;
proto$1.monthsRegex = monthsRegex;
proto$1.monthsShortRegex = monthsShortRegex;
proto$1.week = localeWeek;
proto$1.firstDayOfYear = localeFirstDayOfYear;
proto$1.firstDayOfWeek = localeFirstDayOfWeek;
proto$1.weekdays = localeWeekdays;
proto$1.weekdaysMin = localeWeekdaysMin;
proto$1.weekdaysShort = localeWeekdaysShort;
proto$1.weekdaysParse = localeWeekdaysParse;
proto$1.weekdaysRegex = weekdaysRegex;
proto$1.weekdaysShortRegex = weekdaysShortRegex;
proto$1.weekdaysMinRegex = weekdaysMinRegex;
proto$1.isPM = localeIsPM;
proto$1.meridiem = localeMeridiem;
function get$1(format, index, field, setter) {
var locale = getLocale(),
utc = createUTC().set(setter, index);
return locale[field](utc, format);
}
function listMonthsImpl(format, index, field) {
if (isNumber(format)) {
index = format;
format = undefined;
}
format = format || '';
if (index != null) {
return get$1(format, index, field, 'month');
}
var i,
out = [];
for (i = 0; i < 12; i++) {
out[i] = get$1(format, i, field, 'month');
}
return out;
}
// ()
// (5)
// (fmt, 5)
// (fmt)
// (true)
// (true, 5)
// (true, fmt, 5)
// (true, fmt)
function listWeekdaysImpl(localeSorted, format, index, field) {
if (typeof localeSorted === 'boolean') {
if (isNumber(format)) {
index = format;
format = undefined;
}
format = format || '';
} else {
format = localeSorted;
index = format;
localeSorted = false;
if (isNumber(format)) {
index = format;
format = undefined;
}
format = format || '';
}
var locale = getLocale(),
shift = localeSorted ? locale._week.dow : 0,
i,
out = [];
if (index != null) {
return get$1(format, (index + shift) % 7, field, 'day');
}
for (i = 0; i < 7; i++) {
out[i] = get$1(format, (i + shift) % 7, field, 'day');
}
return out;
}
function listMonths(format, index) {
return listMonthsImpl(format, index, 'months');
}
function listMonthsShort(format, index) {
return listMonthsImpl(format, index, 'monthsShort');
}
function listWeekdays(localeSorted, format, index) {
return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
}
function listWeekdaysShort(localeSorted, format, index) {
return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
}
function listWeekdaysMin(localeSorted, format, index) {
return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
}
getSetGlobalLocale('en', {
eras: [
{
since: '0001-01-01',
until: +Infinity,
offset: 1,
name: 'Anno Domini',
narrow: 'AD',
abbr: 'AD',
},
{
since: '0000-12-31',
until: -Infinity,
offset: 1,
name: 'Before Christ',
narrow: 'BC',
abbr: 'BC',
},
],
dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
ordinal: function (number) {
var b = number % 10,
output =
toInt((number % 100) / 10) === 1
? 'th'
: b === 1
? 'st'
: b === 2
? 'nd'
: b === 3
? 'rd'
: 'th';
return number + output;
},
});
// Side effect imports
hooks.lang = deprecate(
'moment.lang is deprecated. Use moment.locale instead.',
getSetGlobalLocale
);
hooks.langData = deprecate(
'moment.langData is deprecated. Use moment.localeData instead.',
getLocale
);
var mathAbs = Math.abs;
function abs() {
var data = this._data;
this._milliseconds = mathAbs(this._milliseconds);
this._days = mathAbs(this._days);
this._months = mathAbs(this._months);
data.milliseconds = mathAbs(data.milliseconds);
data.seconds = mathAbs(data.seconds);
data.minutes = mathAbs(data.minutes);
data.hours = mathAbs(data.hours);
data.months = mathAbs(data.months);
data.years = mathAbs(data.years);
return this;
}
function addSubtract$1(duration, input, value, direction) {
var other = createDuration(input, value);
duration._milliseconds += direction * other._milliseconds;
duration._days += direction * other._days;
duration._months += direction * other._months;
return duration._bubble();
}
// supports only 2.0-style add(1, 's') or add(duration)
function add$1(input, value) {
return addSubtract$1(this, input, value, 1);
}
// supports only 2.0-style subtract(1, 's') or subtract(duration)
function subtract$1(input, value) {
return addSubtract$1(this, input, value, -1);
}
function absCeil(number) {
if (number < 0) {
return Math.floor(number);
} else {
return Math.ceil(number);
}
}
function bubble() {
var milliseconds = this._milliseconds,
days = this._days,
months = this._months,
data = this._data,
seconds,
minutes,
hours,
years,
monthsFromDays;
// if we have a mix of positive and negative values, bubble down first
// check: https://github.com/moment/moment/issues/2166
if (
!(
(milliseconds >= 0 && days >= 0 && months >= 0) ||
(milliseconds <= 0 && days <= 0 && months <= 0)
)
) {
milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
days = 0;
months = 0;
}
// The following code bubbles up values, see the tests for
// examples of what that means.
data.milliseconds = milliseconds % 1000;
seconds = absFloor(milliseconds / 1000);
data.seconds = seconds % 60;
minutes = absFloor(seconds / 60);
data.minutes = minutes % 60;
hours = absFloor(minutes / 60);
data.hours = hours % 24;
days += absFloor(hours / 24);
// convert days to months
monthsFromDays = absFloor(daysToMonths(days));
months += monthsFromDays;
days -= absCeil(monthsToDays(monthsFromDays));
// 12 months -> 1 year
years = absFloor(months / 12);
months %= 12;
data.days = days;
data.months = months;
data.years = years;
return this;
}
function daysToMonths(days) {
// 400 years have 146097 days (taking into account leap year rules)
// 400 years have 12 months === 4800
return (days * 4800) / 146097;
}
function monthsToDays(months) {
// the reverse of daysToMonths
return (months * 146097) / 4800;
}
function as(units) {
if (!this.isValid()) {
return NaN;
}
var days,
months,
milliseconds = this._milliseconds;
units = normalizeUnits(units);
if (units === 'month' || units === 'quarter' || units === 'year') {
days = this._days + milliseconds / 864e5;
months = this._months + daysToMonths(days);
switch (units) {
case 'month':
return months;
case 'quarter':
return months / 3;
case 'year':
return months / 12;
}
} else {
// handle milliseconds separately because of floating point math errors (issue #1867)
days = this._days + Math.round(monthsToDays(this._months));
switch (units) {
case 'week':
return days / 7 + milliseconds / 6048e5;
case 'day':
return days + milliseconds / 864e5;
case 'hour':
return days * 24 + milliseconds / 36e5;
case 'minute':
return days * 1440 + milliseconds / 6e4;
case 'second':
return days * 86400 + milliseconds / 1000;
// Math.floor prevents floating point math errors here
case 'millisecond':
return Math.floor(days * 864e5) + milliseconds;
default:
throw new Error('Unknown unit ' + units);
}
}
}
function makeAs(alias) {
return function () {
return this.as(alias);
};
}
var asMilliseconds = makeAs('ms'),
asSeconds = makeAs('s'),
asMinutes = makeAs('m'),
asHours = makeAs('h'),
asDays = makeAs('d'),
asWeeks = makeAs('w'),
asMonths = makeAs('M'),
asQuarters = makeAs('Q'),
asYears = makeAs('y'),
valueOf$1 = asMilliseconds;
function clone$1() {
return createDuration(this);
}
function get$2(units) {
units = normalizeUnits(units);
return this.isValid() ? this[units + 's']() : NaN;
}
function makeGetter(name) {
return function () {
return this.isValid() ? this._data[name] : NaN;
};
}
var milliseconds = makeGetter('milliseconds'),
seconds = makeGetter('seconds'),
minutes = makeGetter('minutes'),
hours = makeGetter('hours'),
days = makeGetter('days'),
months = makeGetter('months'),
years = makeGetter('years');
function weeks() {
return absFloor(this.days() / 7);
}
var round = Math.round,
thresholds = {
ss: 44, // a few seconds to seconds
s: 45, // seconds to minute
m: 45, // minutes to hour
h: 22, // hours to day
d: 26, // days to month/week
w: null, // weeks to month
M: 11, // months to year
};
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
}
function relativeTime$1(posNegDuration, withoutSuffix, thresholds, locale) {
var duration = createDuration(posNegDuration).abs(),
seconds = round(duration.as('s')),
minutes = round(duration.as('m')),
hours = round(duration.as('h')),
days = round(duration.as('d')),
months = round(duration.as('M')),
weeks = round(duration.as('w')),
years = round(duration.as('y')),
a =
(seconds <= thresholds.ss && ['s', seconds]) ||
(seconds < thresholds.s && ['ss', seconds]) ||
(minutes <= 1 && ['m']) ||
(minutes < thresholds.m && ['mm', minutes]) ||
(hours <= 1 && ['h']) ||
(hours < thresholds.h && ['hh', hours]) ||
(days <= 1 && ['d']) ||
(days < thresholds.d && ['dd', days]);
if (thresholds.w != null) {
a =
a ||
(weeks <= 1 && ['w']) ||
(weeks < thresholds.w && ['ww', weeks]);
}
a = a ||
(months <= 1 && ['M']) ||
(months < thresholds.M && ['MM', months]) ||
(years <= 1 && ['y']) || ['yy', years];
a[2] = withoutSuffix;
a[3] = +posNegDuration > 0;
a[4] = locale;
return substituteTimeAgo.apply(null, a);
}
// This function allows you to set the rounding function for relative time strings
function getSetRelativeTimeRounding(roundingFunction) {
if (roundingFunction === undefined) {
return round;
}
if (typeof roundingFunction === 'function') {
round = roundingFunction;
return true;
}
return false;
}
// This function allows you to set a threshold for relative time strings
function getSetRelativeTimeThreshold(threshold, limit) {
if (thresholds[threshold] === undefined) {
return false;
}
if (limit === undefined) {
return thresholds[threshold];
}
thresholds[threshold] = limit;
if (threshold === 's') {
thresholds.ss = limit - 1;
}
return true;
}
function humanize(argWithSuffix, argThresholds) {
if (!this.isValid()) {
return this.localeData().invalidDate();
}
var withSuffix = false,
th = thresholds,
locale,
output;
if (typeof argWithSuffix === 'object') {
argThresholds = argWithSuffix;
argWithSuffix = false;
}
if (typeof argWithSuffix === 'boolean') {
withSuffix = argWithSuffix;
}
if (typeof argThresholds === 'object') {
th = Object.assign({}, thresholds, argThresholds);
if (argThresholds.s != null && argThresholds.ss == null) {
th.ss = argThresholds.s - 1;
}
}
locale = this.localeData();
output = relativeTime$1(this, !withSuffix, th, locale);
if (withSuffix) {
output = locale.pastFuture(+this, output);
}
return locale.postformat(output);
}
var abs$1 = Math.abs;
function sign(x) {
return (x > 0) - (x < 0) || +x;
}
function toISOString$1() {
// for ISO strings we do not use the normal bubbling rules:
// * milliseconds bubble up until they become hours
// * days do not bubble at all
// * months bubble up until they become years
// This is because there is no context-free conversion between hours and days
// (think of clock changes)
// and also not between days and months (28-31 days per month)
if (!this.isValid()) {
return this.localeData().invalidDate();
}
var seconds = abs$1(this._milliseconds) / 1000,
days = abs$1(this._days),
months = abs$1(this._months),
minutes,
hours,
years,
s,
total = this.asSeconds(),
totalSign,
ymSign,
daysSign,
hmsSign;
if (!total) {
// this is the same as C#'s (Noda) and python (isodate)...
// but not other JS (goog.date)
return 'P0D';
}
// 3600 seconds -> 60 minutes -> 1 hour
minutes = absFloor(seconds / 60);
hours = absFloor(minutes / 60);
seconds %= 60;
minutes %= 60;
// 12 months -> 1 year
years = absFloor(months / 12);
months %= 12;
// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
totalSign = total < 0 ? '-' : '';
ymSign = sign(this._months) !== sign(total) ? '-' : '';
daysSign = sign(this._days) !== sign(total) ? '-' : '';
hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
return (
totalSign +
'P' +
(years ? ymSign + years + 'Y' : '') +
(months ? ymSign + months + 'M' : '') +
(days ? daysSign + days + 'D' : '') +
(hours || minutes || seconds ? 'T' : '') +
(hours ? hmsSign + hours + 'H' : '') +
(minutes ? hmsSign + minutes + 'M' : '') +
(seconds ? hmsSign + s + 'S' : '')
);
}
var proto$2 = Duration.prototype;
proto$2.isValid = isValid$1;
proto$2.abs = abs;
proto$2.add = add$1;
proto$2.subtract = subtract$1;
proto$2.as = as;
proto$2.asMilliseconds = asMilliseconds;
proto$2.asSeconds = asSeconds;
proto$2.asMinutes = asMinutes;
proto$2.asHours = asHours;
proto$2.asDays = asDays;
proto$2.asWeeks = asWeeks;
proto$2.asMonths = asMonths;
proto$2.asQuarters = asQuarters;
proto$2.asYears = asYears;
proto$2.valueOf = valueOf$1;
proto$2._bubble = bubble;
proto$2.clone = clone$1;
proto$2.get = get$2;
proto$2.milliseconds = milliseconds;
proto$2.seconds = seconds;
proto$2.minutes = minutes;
proto$2.hours = hours;
proto$2.days = days;
proto$2.weeks = weeks;
proto$2.months = months;
proto$2.years = years;
proto$2.humanize = humanize;
proto$2.toISOString = toISOString$1;
proto$2.toString = toISOString$1;
proto$2.toJSON = toISOString$1;
proto$2.locale = locale;
proto$2.localeData = localeData;
proto$2.toIsoString = deprecate(
'toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)',
toISOString$1
);
proto$2.lang = lang;
// FORMATTING
addFormatToken('X', 0, 0, 'unix');
addFormatToken('x', 0, 0, 'valueOf');
// PARSING
addRegexToken('x', matchSigned);
addRegexToken('X', matchTimestamp);
addParseToken('X', function (input, array, config) {
config._d = new Date(parseFloat(input) * 1000);
});
addParseToken('x', function (input, array, config) {
config._d = new Date(toInt(input));
});
//! moment.js
hooks.version = '2.30.1';
setHookCallback(createLocal);
hooks.fn = proto;
hooks.min = min;
hooks.max = max;
hooks.now = now;
hooks.utc = createUTC;
hooks.unix = createUnix;
hooks.months = listMonths;
hooks.isDate = isDate;
hooks.locale = getSetGlobalLocale;
hooks.invalid = createInvalid;
hooks.duration = createDuration;
hooks.isMoment = isMoment;
hooks.weekdays = listWeekdays;
hooks.parseZone = createInZone;
hooks.localeData = getLocale;
hooks.isDuration = isDuration;
hooks.monthsShort = listMonthsShort;
hooks.weekdaysMin = listWeekdaysMin;
hooks.defineLocale = defineLocale;
hooks.updateLocale = updateLocale;
hooks.locales = listLocales;
hooks.weekdaysShort = listWeekdaysShort;
hooks.normalizeUnits = normalizeUnits;
hooks.relativeTimeRounding = getSetRelativeTimeRounding;
hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
hooks.calendarFormat = getCalendarFormat;
hooks.prototype = proto;
// currently HTML5 input type only supports 24-hour formats
hooks.HTML5_FMT = {
DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // <input type="datetime-local" />
DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // <input type="datetime-local" step="1" />
DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // <input type="datetime-local" step="0.001" />
DATE: 'YYYY-MM-DD', // <input type="date" />
TIME: 'HH:mm', // <input type="time" />
TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" />
TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" />
WEEK: 'GGGG-[W]WW', // <input type="week" />
MONTH: 'YYYY-MM', // <input type="month" />
};
return hooks;
})));
} (moment$1, moment$1.exports));
var momentExports = moment$1.exports;
var moment = /*@__PURE__*/getDefaultExportFromCjs(momentExports);
var shiftStartTime = function shiftStartTime(date) {
return moment(date).set({
hours: 8,
minutes: 0,
seconds: 0,
milliseconds: 0
});
};
var shiftEndTime = function shiftEndTime(date) {
return moment(date).set({
hours: 23,
minutes: 59,
seconds: 59,
milliseconds: 999
});
};
function generateTimeSlotsForShift(date, intervalInMinutes) {
var startOfDay = moment(shiftStartTime(date));
var endOfDay = moment(shiftEndTime(date));
var timeSlots = [];
var currentTimeSlot = moment(startOfDay);
while (currentTimeSlot <= endOfDay) {
timeSlots.push(currentTimeSlot.format('hh:mm a'));
currentTimeSlot.add(intervalInMinutes, 'minutes');
if (currentTimeSlot.hours() > 23) {
currentTimeSlot = moment(shiftStartTime(currentTimeSlot)).add(1, 'days');
}
}
return timeSlots;
}
var StyledTableContainer = styled$1(TableContainer)({
width: '100%',
height: '100%',
maxHeight: 700,
maxWidth: '-webkit-fill-available',
position: 'relative',
border: '1px solid rgba(0,0,0,0.12)',
backgroundColor: '#FFFFFF',
overflow: 'auto'
});
var StickyCell = styled$1(TableCell)({
left: 0,
position: 'sticky',
zIndex: 900,
backgroundColor: 'white',
minWidth: 200,
padding: 0,
borderRight: '2px solid rgba(0,0,0,0.2)'
});
var ResourceCell = styled$1(Box)({
border: 'none',
width: 200,
paddingLeft: 8,
paddingRight: 8
});
var StyledBox = styled$1(Box)({
display: 'flex',
alignItems: 'center'
});
var TimeSlots = styled$1(TableCell)({
textAlign: 'left',
backgroundColor: '#FFFFFF',
borderRight: '1px solid rgba(0,0,0,0.05)',
fontSize: '14px',
fontWeight: '600'
});
function getSortAppointments(appointments, user) {
return appointments.filter(function (event) {
return user.id === event.user.id;
}).sort(function (a, b) {
var _a$schedule, _b$schedule;
return ((_a$schedule = a.schedule) === null || _a$schedule === void 0 ? void 0 : _a$schedule.startDate) - ((_b$schedule = b.schedule) === null || _b$schedule === void 0 ? void 0 : _b$schedule.startDate);
});
}
function getFilteredAppointments(appointmentList, user, timeSlot, date, duration, concurrentMapping) {
return appointmentList.filter(function (appointment) {
return appointment.user.id === user.id;
}).filter(function (appointment) {
var _appointment$schedule;
var startDate = moment((_appointment$schedule = appointment.schedule) === null || _appointment$schedule === void 0 ? void 0 : _appointment$schedule.startDate);
var currentDate = moment(date);
var slotStartTime = moment("".concat(currentDate.format('YYYY-MM-DD'), " ").concat(timeSlot), 'YYYY-MM-DD hh:mm a');
var slotEndTime = moment(slotStartTime).add(duration, 'minutes');
return startDate.isSame(currentDate, 'day') && (startDate.isAfter(slotStartTime) || slotStartTime.isSame(startDate)) && startDate.isBefore(slotEndTime);
}).map(function (appointment) {
var height = concurrentMapping[appointment.id];
return _objectSpread2(_objectSpread2({}, appointment), {}, {
height: height
});
});
}
var getUpdatedAppointments = function getUpdatedAppointments(appointments, appointment, date, timeSlot, duration, user) {
var slotDate = moment(date, 'ddd MMM DD YYYY HH:mm:ss [GMT]ZZ').format('YYYY-MM-DD') + ' ' + timeSlot;
var slotStartTime = moment(slotDate);
var existingIndex = appointments.findIndex(function (existingAppointment) {
return existingAppointment.id === appointment.id;
});
var updatedAppointments = _objectSpread2(_objectSpread2({}, appointment), {}, {
user: user,
schedule: {
startDate: slotStartTime.toDate(),
endDate: moment(slotStartTime).add(duration, 'minutes').toDate()
}
});
if (existingIndex !== -1) {
updatedAppointments = _objectSpread2(_objectSpread2({}, appointment), {}, {
user: user,
schedule: {
startDate: slotStartTime.toDate(),
endDate: moment(slotStartTime).add(moment(appointment.schedule.endDate).diff(moment(appointment.schedule.startDate), 'minutes'),
// Keep the original duration
'minutes').toDate()
}
});
}
return updatedAppointments;
};
var getAppointmentDuration = function getAppointmentDuration(schedule) {
var startDate = moment(schedule.startDate);
var endDate = moment(schedule.endDate);
var duration = moment.duration(endDate.diff(startDate));
if (duration.asHours() < 1) {
return duration.asMinutes() + ' minutes';
} else if (duration.asHours() > 1) {
return duration.asHours() + ' hours';
} else {
return duration.asHours() + ' hour';
}
};
var WIDTH = 100;
var HEIGHT = 65;
var MIN_HEIGHT = 35;
var MIN_ROWS = 7;
var HEIGHT_REDUCTION_CONCURRENT = 5;
var slotBg = function slotBg(canDrop, isOver, slotBackground, theme) {
var _ref = slotBackground || {},
dropBg = _ref.dropBg,
overBg = _ref.overBg;
var backgroundColor = '#FFFFFF';
if (canDrop && isOver) {
backgroundColor = dropBg || '#FFFFFF'; // Highlight color when canDrop and isOver
} else if (canDrop) {
backgroundColor = overBg || '#FFFFFF'; // Color when only canDrop is true
}
return backgroundColor;
};
var getSlotWidth = function getSlotWidth(slotDuration) {
switch (slotDuration) {
case 15:
return WIDTH / 2;
default:
return WIDTH;
}
};
var getAppointmentWidth = function getAppointmentWidth(timeSlot, start, end, duration) {
var slotStart = moment(timeSlot, 'hh:mm a');
var slotEnd = moment(slotStart).add(duration, 'minutes');
var appointmentStart = moment(start);
var appointmentEnd = moment(end);
var totalMinutesInSlot = moment.duration(slotEnd.diff(slotStart)).asMinutes();
var appointmentDuration = moment.duration(appointmentEnd.diff(appointmentStart)).asMinutes();
var width = appointmentDuration / totalMinutesInSlot * getSlotWidth(duration) + 2;
return width + 'px';
};
var getDurationWidth = function getDurationWidth(timeSlot, duration, slotWidth) {
// Parse the timeSlot to a moment object
var slotStart = moment(timeSlot, 'hh:mm a'); // Assuming timeSlot is in 24-hour format
// Calculate the end time of the time slot based on the duration
var slotEnd = moment(slotStart).add(duration, 'minutes');
// Calculate the width based on the difference between slotStart and slotEnd
var totalMinutesInSlot = slotEnd.diff(slotStart, 'minutes');
var width = totalMinutesInSlot / 30 * slotWidth; // Assuming slotWidth is in pixels
return width;
};
var getAppointmentHeight = function getAppointmentHeight(concurrentCount) {
var height = HEIGHT;
var computedHeight = HEIGHT - HEIGHT_REDUCTION_CONCURRENT * concurrentCount;
height = Math.max(MIN_HEIGHT, computedHeight);
return height;
};
var Slot = styled$1(TableCell)(function (props) {
props.index;
var bg = props.bg,
width = props.width;
var _useSchedulerContext = useSchedulerContext(),
SlotProps = _useSchedulerContext.SlotProps;
var _ref = SlotProps || {},
style = _ref.style;
var theme = useTheme$3();
// const borderRightColor = () => {
// let color = theme.palette.borderRightColor.light
// switch (secondaryDuration) {
// case 15:
// color = index % 4 !== 3 ?
// theme.palette.borderRightColor.light
// : theme.palette.borderRightColor.main;
// break;
// default:
// color = index % 2 !== 1 ?
// theme.palette.borderRightColor.light
// : theme.palette.borderRightColor.main;
// break;
// }
// return color;
// };
// const borderRightStyle = () => {
// switch (secondaryDuration) {
// case 15:
// if (index % 2 !== 1) {
// return 'none';
// }
// return 'solid';
// default:
// return 'solid';
// }
// };
return _objectSpread2({
paddingTop: theme.spacing(1),
paddingBottom: theme.spacing(1),
paddingLeft: 0,
paddingRight: 0,
position: 'relative',
backgroundColor: bg,
transition: bg + '0.3s ease',
width: width,
height: HEIGHT,
overflow: 'visible',
verticalAlign: 'top',
borderRightWidth: '1px',
borderRightStyle: 'solid',
borderRightColor: 'rgba(0, 0, 0, 0.05)'
}, style);
});
var AppointmentContainer = styled$1('div')(function (props) {
var isDragging = props.isDragging,
height = props.height,
width = props.width,
appointmentColor = props.appointmentColor;
var _useSchedulerContext = useSchedulerContext(),
AppointmentProps = _useSchedulerContext.AppointmentProps;
var _ref = AppointmentProps || {},
style = _ref.style;
var backgroundColor = isDragging ? lighten(appointmentColor, 0.5) : appointmentColor;
return _objectSpread2({
backgroundColor: backgroundColor,
zIndex: '2',
position: 'relative',
top: 0,
left: 0,
borderRadius: 4,
width: width,
cursor: 'move',
marginTop: '1px',
border: '1px solid ' + darken(appointmentColor, 0.25),
color: darken(appointmentColor, 0.7),
overflow: 'hidden',
whiteSpace: 'pre-wrap',
textOverflow: 'ellipsis',
height: height || HEIGHT + 'px'
}, style);
});
function AppointmentItem(props) {
var _useSchedulerContext = useSchedulerContext(),
onAppointmentClick = _useSchedulerContext.onAppointmentClick;
var appointment = props.appointment,
width = props.width,
height = props.height;
var classes = useStyles$1();
var _useDrag = useDrag({
type: 'APPOINTMENT',
item: {
appointment: appointment
},
collect: function collect(monitor) {
return {
isDragging: !!monitor.isDragging()
};
}
}),
_useDrag2 = _slicedToArray(_useDrag, 2),
isDragging = _useDrag2[0].isDragging,
drag = _useDrag2[1];
var color = appointment.user.color;
var textColor = darken$1(color, 0.5);
var duration = getAppointmentDuration(appointment.schedule);
var apptItems = ["".concat(appointment.title), "".concat(appointment.user.name, " | Duration: ").concat(duration)];
var tip = apptItems.join('\n');
var tooltipMessage = /*#__PURE__*/React__default.createElement("div", {
style: classes.tooltip
}, tip);
var primaryText = /*#__PURE__*/React__default.createElement("div", {
style: _objectSpread2({
color: textColor
}, classes.name)
}, appointment.user.name, /*#__PURE__*/React__default.createElement("span", {
style: {
color: textColor
}
}, " | "), "Duration: ", duration);
var secondaryText = /*#__PURE__*/React__default.createElement("div", {
style: classes.titleContainer
}, /*#__PURE__*/React__default.createElement(Typography$1, {
variant: "body2",
sx: _objectSpread2({
color: textColor
}, classes.title)
}, appointment.title));
return /*#__PURE__*/React__default.createElement(AppointmentContainer, {
key: appointment.id,
ref: drag,
isDragging: isDragging,
height: height,
width: width,
appointmentColor: color,
onClick: function onClick() {
return onAppointmentClick(appointment.id);
}
}, /*#__PURE__*/React__default.createElement("div", {
style: classes.wrapper
}, /*#__PURE__*/React__default.createElement(Tooltip, {
title: tooltipMessage
}, /*#__PURE__*/React__default.createElement(ListItemText, {
primary: primaryText,
secondary: secondaryText
}))));
}
var useStyles$1 = function useStyles() {
return {
wrapper: {
padding: 4
},
titleContainer: {
display: 'flex',
alignItems: 'center'
},
title: {
fontWeight: 'bold',
fontSize: '16px',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden'
},
id: _defineProperty$5(_defineProperty$5({
fontSize: '400'
}, "fontSize", '16px'), "whiteSpace", 'nowrap'),
name: {
fontSize: '13px',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden'
},
tooltip: {
whiteSpace: 'pre-line',
padding: 1
}
};
};
function Appointments(props) {
var appointments = props.appointments,
timeSlot = props.timeSlot,
secondaryDuration = props.secondaryDuration;
return appointments && (appointments === null || appointments === void 0 ? void 0 : appointments.map(function (appointment) {
var startDate = appointment.schedule.startDate;
var endDate = appointment.schedule.endDate;
var height = getAppointmentHeight(appointment.height);
return /*#__PURE__*/React__default.createElement(AppointmentItem, {
key: appointment.id,
appointment: appointment,
width: getAppointmentWidth(timeSlot, startDate, endDate, secondaryDuration),
height: height
});
}));
}
function UserTimeSlot(props) {
var user = props.user,
timeSlot = props.timeSlot,
index = props.index;
var _useSchedulerContext = useSchedulerContext(),
appointmentList = _useSchedulerContext.appointmentList,
onAppointmentChange = _useSchedulerContext.onAppointmentChange,
duration = _useSchedulerContext.duration,
date = _useSchedulerContext.date,
SlotProps = _useSchedulerContext.SlotProps;
_useSchedulerContext.color;
var customCanDrop = _useSchedulerContext.customCanDrop;
var _ref = SlotProps || {},
_ref$secondaryDuratio = _ref.secondaryDuration,
secondaryDuration = _ref$secondaryDuratio === void 0 ? 30 : _ref$secondaryDuratio,
slotBackground = _ref.slotBackground;
useTheme$3();
var dropRef = React__default.useRef(null);
var _useDrop = useDrop({
accept: 'APPOINTMENT',
canDrop: function canDrop(appointment) {
return customCanDrop ? customCanDrop(appointment) : true;
},
drop: function drop(appointment, monitor) {
var dropTargetRect = dropRef.current.getBoundingClientRect();
// Get the cursor offset
var clientOffset = monitor.getClientOffset();
if (clientOffset.x >= dropTargetRect.left && clientOffset.x <= dropTargetRect.right && clientOffset.y >= dropTargetRect.top && clientOffset.y <= dropTargetRect.bottom) {
var droppedAppointment = appointment.appointment;
var updatedAppointments = getUpdatedAppointments(appointmentList, droppedAppointment, date, timeSlot, duration, user);
onAppointmentChange(updatedAppointments);
}
},
collect: function collect(monitor) {
return {
isOver: monitor.isOver({
shallow: true
}),
canDrop: monitor.canDrop(),
item: monitor.getItem()
};
}
}),
_useDrop2 = _slicedToArray(_useDrop, 2),
_useDrop2$ = _useDrop2[0],
isOver = _useDrop2$.isOver,
canDrop = _useDrop2$.canDrop,
item = _useDrop2$.item,
drop = _useDrop2[1];
var sortedAppointments = getSortAppointments(appointmentList, user);
var concurrentAppointments = {};
var previousConcurrentCount = 0;
sortedAppointments.forEach(function (event, index) {
var startDate = moment(event.schedule.startDate);
var count = sortedAppointments.reduce(function (acc, otherEvent, otherIndex) {
if (index !== otherIndex && moment(otherEvent.schedule.startDate).isBefore(startDate) && moment(otherEvent.schedule.endDate).isAfter(startDate)) {
return acc + 1;
}
return acc;
}, 0);
concurrentAppointments[event.id] = count > 0 ? count + previousConcurrentCount : 0;
// Update previousConcurrentCount for the next event
previousConcurrentCount = count > 0 ? concurrentAppointments[event.id] : 0;
});
var filteredAppointments = getFilteredAppointments(appointmentList, user, timeSlot, date, secondaryDuration, concurrentAppointments);
var _useState = useState(null),
_useState2 = _slicedToArray(_useState, 2);
_useState2[0];
var setClickedIndex = _useState2[1];
var handleClick = function handleClick(_index) {
setClickedIndex(_index);
};
// console.log(clickedIndex === index)
// console.log(index)
var width = getSlotWidth(secondaryDuration);
getDurationWidth(timeSlot, duration, width);
var bg = slotBg(canDrop, isOver, slotBackground);
var calculateIsOverWidth = function calculateIsOverWidth() {
var _item$appointment, _item$appointment2;
var start = moment(item === null || item === void 0 || (_item$appointment = item.appointment) === null || _item$appointment === void 0 || (_item$appointment = _item$appointment.schedule) === null || _item$appointment === void 0 ? void 0 : _item$appointment.startDate);
var end = moment(item === null || item === void 0 || (_item$appointment2 = item.appointment) === null || _item$appointment2 === void 0 || (_item$appointment2 = _item$appointment2.schedule) === null || _item$appointment2 === void 0 ? void 0 : _item$appointment2.endDate);
var existingDuration = moment.duration(end.diff(start)).asMinutes();
if (existingDuration) {
return getDurationWidth(timeSlot, existingDuration, width);
}
return getDurationWidth(timeSlot, duration, width);
};
drop(dropRef);
return /*#__PURE__*/React__default.createElement(Slot, {
colSpan: 1,
ref: dropRef,
index: index,
width: width || '100%',
onClick: function onClick() {
return handleClick(index);
}
}, /*#__PURE__*/React__default.createElement("div", {
style: {
overflow: 'visible',
width: width,
height: '100%'
}
}, isOver && /*#__PURE__*/React__default.createElement("div", {
style: {
backgroundColor: bg,
width: calculateIsOverWidth(),
height: '100%',
position: 'absolute',
top: 0
}
}), /*#__PURE__*/React__default.createElement(Appointments, {
appointments: filteredAppointments,
secondaryDuration: secondaryDuration,
timeSlot: timeSlot
})));
}
var StyledAvatar = styled$1(Box$1)({
height: '40px',
width: '40px',
marginRight: 2,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '2px'
});
function ResourceName(props) {
var name = props.name,
color = props.color;
return /*#__PURE__*/React__default.createElement(Grid, {
container: true,
fullWidth: true
}, /*#__PURE__*/React__default.createElement(Grid, {
item: true,
xs: 3
}, /*#__PURE__*/React__default.createElement(StyledAvatar, {
sx: {
backgroundColor: color,
borderColor: darken(color, 0.35)
}
}, /*#__PURE__*/React__default.createElement(Typography, {
variant: "body1",
sx: {
color: darken(color, 0.5),
fontSize: '16px',
fontWeight: '600'
}
}, Array.from(name)[0]))), /*#__PURE__*/React__default.createElement(Grid, {
item: true,
xs: 9,
sx: {
display: 'flex',
alignItems: 'center'
}
}, name));
}
function Calendar() {
var _useSchedulerContext = useSchedulerContext(),
date = _useSchedulerContext.date,
users = _useSchedulerContext.users,
SlotProps = _useSchedulerContext.SlotProps,
groups = _useSchedulerContext.groups,
onGroupChange = _useSchedulerContext.onGroupChange,
groupId = _useSchedulerContext.groupId,
resourceLabel = _useSchedulerContext.resourceLabel,
minRows = _useSchedulerContext.minRows,
isLoading = _useSchedulerContext.isLoading,
groupLabel = _useSchedulerContext.groupLabel;
var _ref = SlotProps || {},
_ref$primaryDuration = _ref.primaryDuration,
primaryDuration = _ref$primaryDuration === void 0 ? 60 : _ref$primaryDuration,
secondaryDuration = _ref.secondaryDuration,
colSpan = _ref.colSpan;
var classes = useStyles();
var timeSlotsHead = generateTimeSlotsForShift(date, primaryDuration);
var timeSlotsBody = generateTimeSlotsForShift(date, secondaryDuration);
var _useState = useState(0),
_useState2 = _slicedToArray(_useState, 2),
additionalRows = _useState2[0],
setAdditionalRows = _useState2[1];
var minimumRows = minRows || MIN_ROWS;
useEffect(function () {
if (users.length <= minimumRows) {
setAdditionalRows(minimumRows - users.length);
} else {
setAdditionalRows(0);
}
}, [users]);
var tableHead = /*#__PURE__*/React__default.createElement(TableRow, {
sx: classes.tableRow
}, /*#__PURE__*/React__default.createElement(StickyCell, {
sx: classes.resourceHead,
align: "left"
}, /*#__PURE__*/React__default.createElement(StyledBox, null, /*#__PURE__*/React__default.createElement(ResourceCell, null, /*#__PURE__*/React__default.createElement(Typography$1, {
sx: classes.resourceLabelText
}, resourceLabel))), /*#__PURE__*/React__default.createElement(ResourceCell, {
sx: {
marginTop: 2
}
}, /*#__PURE__*/React__default.createElement(FormControl, {
size: "small",
fullWidth: true
}, /*#__PURE__*/React__default.createElement(InputLabel, {
id: "groups"
}, groupLabel || 'Groups'), /*#__PURE__*/React__default.createElement(Select, {
labelId: "groups",
id: "groups",
value: groupId,
label: groupLabel || 'Groups',
onChange: onGroupChange,
size: "small"
}, groups.map(function (group) {
return /*#__PURE__*/React__default.createElement(MenuItem, {
value: group.id
}, group.name);
}))))), timeSlotsHead.map(function (slot) {
return /*#__PURE__*/React__default.createElement(TimeSlots, {
key: slot,
colSpan: colSpan
}, slot);
}));
var userSlots = users.map(function (user) {
return /*#__PURE__*/React__default.createElement(TableRow, {
key: user.name
}, /*#__PURE__*/React__default.createElement(StickyCell, {
align: "left"
}, /*#__PURE__*/React__default.createElement(ResourceCell, {
sx: classes.resourceBody
}, /*#__PURE__*/React__default.createElement(ResourceName, {
name: user.name,
color: user.color
}))), timeSlotsBody.map(function (slot, index) {
return /*#__PURE__*/React__default.createElement(UserTimeSlot, {
key: "".concat(user.name, "-").concat(slot),
index: index,
user: user,
timeSlot: slot
});
}));
});
var width = getSlotWidth(secondaryDuration);
var emptySlots = timeSlotsBody.map(function (slot, index) {
return /*#__PURE__*/React__default.createElement(Slot, {
key: index,
colSpan: 1,
width: width,
sx: {
borderBottom: isLoading && 'none'
}
}, /*#__PURE__*/React__default.createElement("div", {
style: {
width: width,
height: '100%'
}
}, "\xA0"));
});
var additionalRowsContent = Array.from({
length: !isLoading && users.length ? additionalRows : minimumRows
}, function (_, index) {
return /*#__PURE__*/React__default.createElement(TableRow, {
key: "additional-row-".concat(index)
}, /*#__PURE__*/React__default.createElement(StickyCell, {
align: "left",
sx: {
borderBottom: isLoading && 'none'
}
}, /*#__PURE__*/React__default.createElement(StyledBox, null, /*#__PURE__*/React__default.createElement(ResourceCell, {
sx: classes.resourceBody
}))), emptySlots);
});
return /*#__PURE__*/React__default.createElement(StyledTableContainer, null, /*#__PURE__*/React__default.createElement(Table, {
sx: classes.table,
stickyHeader: true
}, /*#__PURE__*/React__default.createElement(TableHead, null, tableHead), /*#__PURE__*/React__default.createElement(TableBody, null, !isLoading && userSlots, additionalRowsContent)));
}
var useStyles = function useStyles() {
return {
table: {
width: '100%',
height: '100%'
},
resourceLabelText: {
fontSize: '16px',
fontWeight: 'bold'
},
tableRow: {
backgroundColor: 'white',
position: 'sticky',
top: 0,
zIndex: 1000
},
resourceHead: {
paddingTop: 2,
paddingBottom: 2,
paddingRight: 2,
textTransform: 'capitalize'
},
resourceBody: {
fontSize: '14px',
display: 'flex',
alignItems: 'center'
}
};
};
var AppointmentPropTypes = PropTypes.shape({
/**
* Set the background color for the appointment when it is being dragged
*/
dragBgColor: PropTypes.string,
/**
* You can override the styles
*/
style: PropTypes.object
});
var AppointmentDefaultValue = {
dragBgColor: '#E0E0E0',
style: {}
};
var SlotBackgroundPropTypes = PropTypes.shape({
/**
* set background of drop, when the appointment can be drop in the slot
*/
dropBg: PropTypes.string,
/**
* set background of drop, when the appointment is over the slot
*/
overBg: PropTypes.string
});
var SlotPropTypes = PropTypes.shape({
/**
* Set the primary duration - Primary Duration is the duration in header of the scheduler
* @default 60
*/
primaryDuration: PropTypes.number,
/**
* Set the secondary duration, Secondary Duration is the duration inside each Primary Duration
* @default 30
*/
secondaryDuration: PropTypes.number,
/**
* colSpan should be set accordingly to secondaryDuration
* @default 2
*/
colSpan: PropTypes.number,
/**
* component is used to wrapped the whole scheduler
*/
component: PropTypes.node,
/**
* Override the style
*/
style: PropTypes.object,
/**
* Override the slot background when it is to be dropped or its just over the slot
*/
slotBackground: SlotBackgroundPropTypes
});
var SlotDefaultValues = {
primaryDuration: 60,
secondaryDuration: 30,
colSpan: 2,
component: /*#__PURE__*/React__default.createElement("div", null),
style: PropTypes.object,
slotBackground: {
dropBg: undefined,
overBg: undefined
}
};
function ButtonField(props) {
var setOpen = props.setOpen,
value = props.value,
id = props.id,
disabled = props.disabled,
_props$InputProps = props.InputProps,
_props$InputProps2 = _props$InputProps === void 0 ? {} : _props$InputProps,
ref = _props$InputProps2.ref,
_props$inputProps = props.inputProps,
_props$inputProps2 = _props$inputProps === void 0 ? {} : _props$inputProps,
ariaLabel = _props$inputProps2['aria-label'];
var theme = useTheme();
// Convert the timestamp to a Date object
var date = new Date(value);
var handleOpen = function handleOpen() {
setOpen === null || setOpen === void 0 || setOpen(function (prev) {
return !prev;
});
};
return /*#__PURE__*/React__default.createElement(Button$1, {
endIcon: /*#__PURE__*/React__default.createElement(ArrowDropDownIcon, null),
onClick: handleOpen,
id: id,
disabled: disabled,
ref: ref,
"aria-label": ariaLabel
}, /*#__PURE__*/React__default.createElement(Typography$1, {
sx: {
textTransform: 'capitalize',
color: theme.palette.primary.main,
fontSize: '18px'
}
}, moment(date).format('ddd, MMM DD, YYYY')));
}
function SchedulerDatePicker(props) {
var _useSchedulerContext = useSchedulerContext(),
date = _useSchedulerContext.date,
onDateChange = _useSchedulerContext.onDateChange;
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
open = _useState2[0],
setOpen = _useState2[1];
var theme = useTheme();
var handleOpen = function handleOpen() {
setOpen(true);
};
var handleClose = function handleClose() {
setOpen(false);
};
return /*#__PURE__*/React__default.createElement(DatePicker, {
PopperProps: {
disablePortal: true
},
autoOk: true,
value: date,
onChange: onDateChange,
open: open,
onClose: handleClose,
onOpen: handleOpen,
slots: _objectSpread2({
field: ButtonField
}, props.slots),
slotProps: {
field: {
setOpen: setOpen
}
},
sx: {
'& .MuiPickersDay-daySelected': {
backgroundColor: theme.palette.primary.main,
// Use main color from theme.palette[color]
color: theme.palette.primary.contrastText // Use contrast text color from theme.palette[color]
},
'& .MuiPickersDay-daySelected:hover': {
backgroundColor: theme.palette.primary.main.light // Use light color from theme.palette[color] on hover
}
}
});
}
function DurationPicker() {
var _useSchedulerContext = useSchedulerContext(),
durationOptions = _useSchedulerContext.durationOptions,
duration = _useSchedulerContext.duration,
onDurationChange = _useSchedulerContext.onDurationChange;
var theme = useTheme();
var _useState = useState(null),
_useState2 = _slicedToArray(_useState, 2),
anchorEl = _useState2[0],
setAnchorEl = _useState2[1];
var optionValue = function optionValue(option) {
switch (true) {
case option === 60:
return "".concat(option / 60, " hour");
case option > 59:
return "".concat(option / 60, " hours");
case option === 15:
return "".concat(option, " minutes");
default:
return "".concat(option, " minutes");
}
};
var handleButtonClick = function handleButtonClick(event) {
setAnchorEl(event.currentTarget);
};
var handleMenuItemClick = function handleMenuItemClick(option) {
onDurationChange && onDurationChange(option);
setAnchorEl(null);
};
var handleClose = function handleClose() {
setAnchorEl(null);
};
var options = durationOptions === null || durationOptions === void 0 ? void 0 : durationOptions.map(function (option) {
return /*#__PURE__*/React__default.createElement(MenuItem, {
key: option,
onClick: function onClick() {
return handleMenuItemClick(option);
},
value: option,
selected: option === duration
}, optionValue(option));
});
return /*#__PURE__*/React__default.createElement("div", {
style: {
display: 'flex',
alignItems: 'center'
}
}, /*#__PURE__*/React__default.createElement(Typography$1, {
sx: {
marginRight: '8px'
}
}, "Default Duration:"), /*#__PURE__*/React__default.createElement(Button$1, {
"aria-controls": "duration-options-menu",
"aria-haspopup": "true",
endIcon: /*#__PURE__*/React__default.createElement(ArrowDropDownIcon, null),
onClick: handleButtonClick,
sx: {
border: 'none',
textTransform: 'lowercase'
}
}, /*#__PURE__*/React__default.createElement(Typography$1, {
sx: {
color: theme.palette.primary.main,
fontSize: '16px'
}
}, optionValue(duration))), /*#__PURE__*/React__default.createElement(Menu, {
id: "duration-options-menu",
anchorEl: anchorEl,
open: Boolean(anchorEl),
onClose: handleClose
}, options));
}
function TodayButton() {
var _useSchedulerContext = useSchedulerContext(),
onDateChange = _useSchedulerContext.onDateChange;
function handleDateChange() {
var dateNow = new Date();
onDateChange(dateNow);
}
return /*#__PURE__*/React__default.createElement(Button$1, {
onClick: handleDateChange,
sx: {
textTransform: 'capitalize',
fontSize: '16px'
}
}, "Today");
}
function ActionButton(props) {
var icon = props.icon,
onClick = props.onClick,
name = props.name;
return /*#__PURE__*/React__default.createElement(IconButton$1, {
key: name,
onClick: onClick
}, icon);
}
function DateNavigation() {
var _useSchedulerContext = useSchedulerContext(),
onPrevDate = _useSchedulerContext.onPrevDate,
onNextDate = _useSchedulerContext.onNextDate;
var actions = [/*#__PURE__*/React__default.createElement(ActionButton, {
key: "nextDate",
name: "nextDate",
icon: /*#__PURE__*/React__default.createElement(ArrowLeftIcon, null),
onClick: onNextDate
}), /*#__PURE__*/React__default.createElement(ActionButton, {
key: "prevDate",
name: "prevDate",
icon: /*#__PURE__*/React__default.createElement(ArrowRightIcon, null),
onClick: onPrevDate
})];
return /*#__PURE__*/React__default.createElement("div", null, actions);
}
function NavigateDateAction() {
return /*#__PURE__*/React__default.createElement("div", {
style: {
display: 'flex',
alignItems: 'center'
}
}, /*#__PURE__*/React__default.createElement(TodayButton, null), /*#__PURE__*/React__default.createElement(DateNavigation, null));
}
function Header() {
return /*#__PURE__*/React__default.createElement("div", {
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between'
}
}, /*#__PURE__*/React__default.createElement(NavigateDateAction, null), /*#__PURE__*/React__default.createElement(SchedulerDatePicker, null), /*#__PURE__*/React__default.createElement(DurationPicker, null));
}
/**
* <p>Scheduler is composed of different libraries such as React-DND, moment, and MUI.</p>
*
* <p>This was created to accomodate the use case for scheduling apppointments for each user in each slot. The Scheduler component has the following functionalities:</p>
*
* <ul style="list-style: none;">
* <li>1. Changing the date for Scheduler
* <ul style="list-style: none;">
* <li> 1.1. Can set the date for today
* <li> 1.2. Can change the date previously or the next date
* <li> 1.3. Manually changing the date in date picker
* </ul>
* <li>2. Changing the duration of the appointment, before it was about to dropped inside the Scheduler
* <li>3. Drag and drop from outside to inside of the Scheduler
* <li>4. Drag and drop across the Scheduler
* <li>5. Concurrent appointments
* </ul>
* */
var Scheduler = function Scheduler(props) {
return /*#__PURE__*/React__default.createElement(SchedulerProvider, props, /*#__PURE__*/React__default.createElement("div", {
style: {
overflow: 'hidden',
width: '100%',
height: '100%'
}
}, /*#__PURE__*/React__default.createElement(Header, null), /*#__PURE__*/React__default.createElement(Calendar, null)));
};
Scheduler.propTypes = {
/**
* Selected `groupId` to filter the users
* @default ''
*/
groupId: PropTypes.string,
/**
* `groups` is the list of groupId to filter the users
* @default []
*/
groups: PropTypes.array,
/**
* `users` is displayed in the first column. This prop is required.
* @default []
*/
users: PropTypes.array.isRequired,
/**
* `appointmentList` is a list of scheduled appointment with user. This list can be set with `onAppointmentChange`. This prop is required.
* @default []
*/
appointmentList: PropTypes.array.isRequired,
/**
* `onAppointmentChange` handles the changes for `appointmentList`. This prop is required.
*/
onAppointmentChange: PropTypes.func.isRequired,
/**
* `durationOptions` is an array of numbers to be set for each appointment that can be dropped inside the scheduler. This prop is required.
* @default [30,60,120]
*/
durationOptions: PropTypes.array.isRequired,
/**
* `duration` is the selected duration among `durationOptions`. This prop is required.
* @default 60
*/
duration: PropTypes.number.isRequired,
/**
* Handles changing duration
*/
onDurationChange: PropTypes.func,
/**
* Default date is set to current date
*/
date: PropTypes.instanceOf(Date),
/**
* Handles to change the date
*/
onDateChange: PropTypes.func,
/**
* Handles to go to the previous date
*/
onPrevDate: PropTypes.func,
/**
* Handles to go to the next date
*/
onNextDate: PropTypes.func,
/**
* This is to customized the Slots
*/
SlotProps: SlotPropTypes,
/**
* This is to customized the Slots
*/
AppointmentProps: AppointmentPropTypes,
/**
* Color is used to change the theme of the scheduler: `primary` | `secondary`
* @default `primary`
*/
color: PropTypes.object,
/**
* Change the resource label
* @default `"Users"`
*/
resourceLabel: PropTypes.string,
/**
* Customized can drop function whether it returns true of false
*/
customCanDrop: PropTypes.func,
/**
* Customized group label
*/
groupLabel: PropTypes.string
};
Scheduler.defaultProps = {
groupId: '',
groups: [],
users: [],
appointmentList: [],
durationOptions: [30, 60, 120],
duration: 60,
date: Date.now(),
color: _objectSpread2({}, theme),
SlotProps: SlotDefaultValues,
AppointmentProps: AppointmentDefaultValue,
resourceLabel: 'Users',
groupLabel: 'Groups'
};
export { Scheduler as default };