Started adding frontend notifications, fixing firefox file upload bug
This commit is contained in:
36
goTorrentWebUI/node_modules/react-toastify/src/DefaultCloseButton.js
generated
vendored
Normal file
36
goTorrentWebUI/node_modules/react-toastify/src/DefaultCloseButton.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* eslint react/require-default-props: 0 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { css } from 'glamor';
|
||||
|
||||
const rule = isDefault =>
|
||||
css({
|
||||
color: isDefault ? '#000' : '#fff',
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px',
|
||||
background: 'transparent',
|
||||
outline: 'none',
|
||||
border: 'none',
|
||||
padding: 0,
|
||||
cursor: 'pointer',
|
||||
opacity: isDefault ? '0.3' : '0.7',
|
||||
transition: '.3s ease',
|
||||
alignSelf: 'flex-start',
|
||||
':hover, :focus': {
|
||||
opacity: 1
|
||||
}
|
||||
});
|
||||
|
||||
function DefaultCloseButton({ closeToast, type }) {
|
||||
return (
|
||||
<button {...rule(type === 'default')} type="button" onClick={closeToast}>
|
||||
✖
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
DefaultCloseButton.propTypes = {
|
||||
closeToast: PropTypes.func
|
||||
};
|
||||
|
||||
export default DefaultCloseButton;
|
44
goTorrentWebUI/node_modules/react-toastify/src/DefaultTransition.js
generated
vendored
Normal file
44
goTorrentWebUI/node_modules/react-toastify/src/DefaultTransition.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import Transition from 'react-transition-group/Transition';
|
||||
import { css } from 'glamor';
|
||||
|
||||
import getAnimation from './animation';
|
||||
|
||||
const animate = {
|
||||
animationDuration: '0.75s',
|
||||
animationFillMode: 'both'
|
||||
};
|
||||
|
||||
const animation = pos => {
|
||||
const { enter, exit } = getAnimation(pos);
|
||||
const enterAnimation = css.keyframes('enter', {
|
||||
'from, 60%, 75%, 90%, to': {
|
||||
animationTimingFunction: 'cubic-bezier(0.215, 0.610, 0.355, 1.000)'
|
||||
},
|
||||
...enter
|
||||
});
|
||||
const exitAnimation = css.keyframes('exit', exit);
|
||||
|
||||
return {
|
||||
enter: css({ ...animate, animationName: enterAnimation }),
|
||||
exit: css({ ...animate, animationName: exitAnimation })
|
||||
};
|
||||
};
|
||||
|
||||
function DefaultTransition({ children, position, ...props }) {
|
||||
const { enter, exit } = animation(position);
|
||||
|
||||
return (
|
||||
<Transition
|
||||
{...props}
|
||||
timeout={750}
|
||||
onEnter={node => node.classList.add(enter)}
|
||||
onEntered={node => node.classList.remove(enter)}
|
||||
onExit={node => node.classList.add(exit)}
|
||||
>
|
||||
{children}
|
||||
</Transition>
|
||||
);
|
||||
}
|
||||
|
||||
export default DefaultTransition;
|
79
goTorrentWebUI/node_modules/react-toastify/src/ProgressBar.js
generated
vendored
Normal file
79
goTorrentWebUI/node_modules/react-toastify/src/ProgressBar.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { css } from 'glamor';
|
||||
|
||||
import { TYPE } from './constant';
|
||||
import style from './style';
|
||||
|
||||
const trackProgress = css.keyframes('track-progress', {
|
||||
'0%': { width: '100%' },
|
||||
'100%': { width: 0 }
|
||||
});
|
||||
|
||||
const progress = (type, isRunning, hide, delay) =>
|
||||
css({
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
height: '5px',
|
||||
zIndex: style.zIndex,
|
||||
opacity: hide ? 0 : 0.7,
|
||||
animation: `${trackProgress} linear 1`,
|
||||
animationPlayState: isRunning ? 'running' : 'paused',
|
||||
animationDuration: `${delay}ms`,
|
||||
backgroundColor: 'rgba(255,255,255,.7)',
|
||||
...(type === 'default' ? { background: style.colorProgressDefault } : {})
|
||||
});
|
||||
|
||||
function ProgressBar({ delay, isRunning, closeToast, type, hide, className }) {
|
||||
return (
|
||||
<div
|
||||
{...(typeof className !== 'string'
|
||||
? css(progress(type, isRunning, hide, delay), className)
|
||||
: progress(type, isRunning, hide, delay))}
|
||||
{...typeof className === 'string' && { className }}
|
||||
onAnimationEnd={closeToast}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
ProgressBar.propTypes = {
|
||||
/**
|
||||
* The animation delay which determine when to close the toast
|
||||
*/
|
||||
delay: PropTypes.number.isRequired,
|
||||
|
||||
/**
|
||||
* Whether or not the animation is running or paused
|
||||
*/
|
||||
isRunning: PropTypes.bool.isRequired,
|
||||
|
||||
/**
|
||||
* Func to close the current toast
|
||||
*/
|
||||
closeToast: PropTypes.func.isRequired,
|
||||
|
||||
/**
|
||||
* Optional type : info, success ...
|
||||
*/
|
||||
type: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Hide or not the progress bar
|
||||
*/
|
||||
hide: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Optionnal className
|
||||
*/
|
||||
className: PropTypes.oneOfType([PropTypes.string, PropTypes.object])
|
||||
};
|
||||
|
||||
ProgressBar.defaultProps = {
|
||||
type: TYPE.DEFAULT,
|
||||
hide: false,
|
||||
className: ''
|
||||
};
|
||||
|
||||
export default ProgressBar;
|
184
goTorrentWebUI/node_modules/react-toastify/src/Toast.js
generated
vendored
Normal file
184
goTorrentWebUI/node_modules/react-toastify/src/Toast.js
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { css } from 'glamor';
|
||||
|
||||
import ProgressBar from './ProgressBar';
|
||||
import { POSITION, TYPE } from './constant';
|
||||
import style from './style';
|
||||
import {
|
||||
falseOrElement,
|
||||
falseOrDelay,
|
||||
objectValues
|
||||
} from './util/propValidator';
|
||||
|
||||
const toast = type =>
|
||||
css({
|
||||
position: 'relative',
|
||||
minHeight: '48px',
|
||||
marginBottom: '1rem',
|
||||
padding: '8px',
|
||||
borderRadius: '1px',
|
||||
boxShadow:
|
||||
'0 1px 10px 0 rgba(0, 0, 0, .1), 0 2px 15px 0 rgba(0, 0, 0, .05)',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
maxHeight: '800px',
|
||||
overflow: 'hidden',
|
||||
fontFamily: style.fontFamily,
|
||||
cursor: 'pointer',
|
||||
background: style[`color${type.charAt(0).toUpperCase()}${type.slice(1)}`],
|
||||
...(type === 'default' ? { color: '#aaa' } : {}),
|
||||
[`@media ${style.mobile}`]: {
|
||||
marginBottom: 0
|
||||
}
|
||||
});
|
||||
|
||||
const body = css({
|
||||
margin: 'auto 0',
|
||||
flex: 1
|
||||
});
|
||||
|
||||
class Toast extends Component {
|
||||
static propTypes = {
|
||||
closeButton: falseOrElement.isRequired,
|
||||
autoClose: falseOrDelay.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
closeToast: PropTypes.func.isRequired,
|
||||
position: PropTypes.oneOf(objectValues(POSITION)).isRequired,
|
||||
pauseOnHover: PropTypes.bool.isRequired,
|
||||
closeOnClick: PropTypes.bool.isRequired,
|
||||
transition: PropTypes.func.isRequired,
|
||||
isDocumentHidden: PropTypes.bool.isRequired,
|
||||
in: PropTypes.bool,
|
||||
onExited: PropTypes.func,
|
||||
hideProgressBar: PropTypes.bool,
|
||||
onOpen: PropTypes.func,
|
||||
onClose: PropTypes.func,
|
||||
type: PropTypes.oneOf(objectValues(TYPE)),
|
||||
className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
bodyClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
progressClassName: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.object
|
||||
]),
|
||||
updateId: PropTypes.number
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
type: TYPE.DEFAULT,
|
||||
in: true,
|
||||
hideProgressBar: false,
|
||||
onOpen: null,
|
||||
onClose: null,
|
||||
className: '',
|
||||
bodyClassName: '',
|
||||
progressClassName: '',
|
||||
updateId: null
|
||||
};
|
||||
|
||||
state = {
|
||||
isRunning: true
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.onOpen !== null && this.props.onOpen(this.getChildrenProps());
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.isDocumentHidden !== nextProps.isDocumentHidden) {
|
||||
this.setState({
|
||||
isRunning: !nextProps.isDocumentHidden
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.onClose !== null && this.props.onClose(this.getChildrenProps());
|
||||
}
|
||||
|
||||
getChildrenProps() {
|
||||
return this.props.children.props;
|
||||
}
|
||||
|
||||
getToastProps() {
|
||||
const toastProps = {};
|
||||
|
||||
if (this.props.autoClose !== false && this.props.pauseOnHover === true) {
|
||||
toastProps.onMouseEnter = this.pauseToast;
|
||||
toastProps.onMouseLeave = this.playToast;
|
||||
}
|
||||
typeof this.props.className === 'string' &&
|
||||
(toastProps.className = this.props.className);
|
||||
this.props.closeOnClick && (toastProps.onClick = this.props.closeToast);
|
||||
|
||||
return toastProps;
|
||||
}
|
||||
|
||||
pauseToast = () => {
|
||||
this.setState({ isRunning: false });
|
||||
};
|
||||
|
||||
playToast = () => {
|
||||
this.setState({ isRunning: true });
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
closeButton,
|
||||
children,
|
||||
autoClose,
|
||||
type,
|
||||
hideProgressBar,
|
||||
closeToast,
|
||||
transition: Transition,
|
||||
position,
|
||||
onExited,
|
||||
className,
|
||||
bodyClassName,
|
||||
progressClassName,
|
||||
updateId
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Transition
|
||||
in={this.props.in}
|
||||
appear
|
||||
unmountOnExit
|
||||
onExited={onExited}
|
||||
position={position}
|
||||
>
|
||||
<div
|
||||
{...(typeof className !== 'string'
|
||||
? css(toast(type), className)
|
||||
: toast(type))}
|
||||
{...this.getToastProps()}
|
||||
>
|
||||
<div
|
||||
{...(typeof bodyClassName !== 'string'
|
||||
? css(body, bodyClassName)
|
||||
: body)}
|
||||
{...typeof bodyClassName === 'string' && {
|
||||
className: bodyClassName
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
{closeButton !== false && closeButton}
|
||||
{autoClose !== false && (
|
||||
<ProgressBar
|
||||
key={`pb-${updateId}`}
|
||||
delay={autoClose}
|
||||
isRunning={this.state.isRunning}
|
||||
closeToast={closeToast}
|
||||
hide={hideProgressBar}
|
||||
type={type}
|
||||
className={progressClassName}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Transition>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Toast;
|
368
goTorrentWebUI/node_modules/react-toastify/src/ToastContainer.js
generated
vendored
Normal file
368
goTorrentWebUI/node_modules/react-toastify/src/ToastContainer.js
generated
vendored
Normal file
@@ -0,0 +1,368 @@
|
||||
import React, { Component, isValidElement, cloneElement } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { css } from 'glamor';
|
||||
import TransitionGroup from 'react-transition-group/TransitionGroup';
|
||||
|
||||
import Toast from './Toast';
|
||||
import DefaultCloseButton from './DefaultCloseButton';
|
||||
import DefaultTransition from './DefaultTransition';
|
||||
import { POSITION, ACTION } from './constant';
|
||||
import style from './style';
|
||||
import EventManager from './util/EventManager';
|
||||
import {
|
||||
falseOrDelay,
|
||||
falseOrElement,
|
||||
isValidDelay,
|
||||
objectValues
|
||||
} from './util/propValidator';
|
||||
|
||||
const toastPosition = pos => {
|
||||
const positionKey = pos.toUpperCase().replace('-', '_');
|
||||
const positionRule =
|
||||
typeof POSITION[positionKey] !== 'undefined'
|
||||
? style[positionKey]
|
||||
: style.TOP_RIGHT;
|
||||
|
||||
/** define margin for center toast based on toast witdh */
|
||||
if (
|
||||
positionKey.indexOf('CENTER') !== -1 &&
|
||||
typeof positionRule.marginLeft === 'undefined'
|
||||
) {
|
||||
positionRule.marginLeft = `-${parseInt(style.width, 10) / 2}px`;
|
||||
}
|
||||
|
||||
return css(
|
||||
positionRule,
|
||||
css({
|
||||
[`@media ${style.mobile}`]: {
|
||||
left: 0,
|
||||
margin: 0,
|
||||
position: 'fixed',
|
||||
...(pos.substring(0, 3) === 'top' ? { top: 0 } : { bottom: 0 })
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const container = (disablePointer, position) =>
|
||||
css(
|
||||
{
|
||||
zIndex: style.zIndex,
|
||||
position: 'fixed',
|
||||
padding: '4px',
|
||||
width: style.width,
|
||||
boxSizing: 'border-box',
|
||||
color: '#fff',
|
||||
...(disablePointer ? { pointerEvents: 'none' } : {}),
|
||||
[`@media ${style.mobile}`]: {
|
||||
width: '100vw',
|
||||
padding: 0
|
||||
}
|
||||
},
|
||||
toastPosition(position)
|
||||
);
|
||||
|
||||
class ToastContainer extends Component {
|
||||
static propTypes = {
|
||||
/**
|
||||
* Set toast position
|
||||
*/
|
||||
position: PropTypes.oneOf(objectValues(POSITION)),
|
||||
|
||||
/**
|
||||
* Disable or set autoClose delay
|
||||
*/
|
||||
autoClose: falseOrDelay,
|
||||
|
||||
/**
|
||||
* Disable or set a custom react element for the close button
|
||||
*/
|
||||
closeButton: falseOrElement,
|
||||
|
||||
/**
|
||||
* Hide or not progress bar when autoClose is enabled
|
||||
*/
|
||||
hideProgressBar: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Pause toast duration on hover
|
||||
*/
|
||||
pauseOnHover: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Dismiss toast on click
|
||||
*/
|
||||
closeOnClick: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Newest on top
|
||||
*/
|
||||
newestOnTop: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* An optional className
|
||||
*/
|
||||
className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
|
||||
/**
|
||||
* An optional style
|
||||
*/
|
||||
style: PropTypes.object,
|
||||
|
||||
/**
|
||||
* An optional className for the toast
|
||||
*/
|
||||
toastClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
|
||||
/**
|
||||
* An optional className for the toast body
|
||||
*/
|
||||
bodyClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
|
||||
/**
|
||||
* An optional className for the toast progress bar
|
||||
*/
|
||||
progressClassName: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.object
|
||||
]),
|
||||
|
||||
/**
|
||||
* Define enter and exit transition using react-transition-group
|
||||
*/
|
||||
transition: PropTypes.func
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
position: POSITION.TOP_RIGHT,
|
||||
transition: DefaultTransition,
|
||||
autoClose: 5000,
|
||||
hideProgressBar: false,
|
||||
closeButton: <DefaultCloseButton />,
|
||||
pauseOnHover: true,
|
||||
closeOnClick: true,
|
||||
newestOnTop: false,
|
||||
className: null,
|
||||
style: null,
|
||||
toastClassName: '',
|
||||
bodyClassName: '',
|
||||
progressClassName: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* Hold toast ids
|
||||
*/
|
||||
state = {
|
||||
toast: [],
|
||||
isDocumentHidden: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Hold toast's informations:
|
||||
* - what to render
|
||||
* - position
|
||||
* - raw content
|
||||
* - options
|
||||
*/
|
||||
collection = {};
|
||||
|
||||
componentDidMount() {
|
||||
const { SHOW, CLEAR, MOUNTED } = ACTION;
|
||||
EventManager.on(SHOW, (content, options) => this.show(content, options))
|
||||
.on(CLEAR, id => (id !== null ? this.removeToast(id) : this.clear()))
|
||||
.emit(MOUNTED, this);
|
||||
document.addEventListener('visibilitychange', this.isDocumentHidden);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
EventManager.off(ACTION.SHOW);
|
||||
EventManager.off(ACTION.CLEAR);
|
||||
document.removeEventListener('visibilitychange', this.isDocumentHidden);
|
||||
}
|
||||
|
||||
isDocumentHidden = () => this.setState({ isDocumentHidden: document.hidden });
|
||||
|
||||
isToastActive = id => this.state.toast.indexOf(parseInt(id, 10)) !== -1;
|
||||
|
||||
removeToast(id) {
|
||||
this.setState({
|
||||
toast: this.state.toast.filter(v => v !== parseInt(id, 10))
|
||||
});
|
||||
}
|
||||
|
||||
makeCloseButton(toastClose, toastId, type) {
|
||||
let closeButton = this.props.closeButton;
|
||||
|
||||
if (isValidElement(toastClose) || toastClose === false) {
|
||||
closeButton = toastClose;
|
||||
}
|
||||
|
||||
return closeButton === false
|
||||
? false
|
||||
: cloneElement(closeButton, {
|
||||
closeToast: () => this.removeToast(toastId),
|
||||
type: type
|
||||
});
|
||||
}
|
||||
|
||||
getAutoCloseDelay(toastAutoClose) {
|
||||
return toastAutoClose === false || isValidDelay(toastAutoClose)
|
||||
? toastAutoClose
|
||||
: this.props.autoClose;
|
||||
}
|
||||
|
||||
isFunction(object) {
|
||||
return !!(object && object.constructor && object.call && object.apply);
|
||||
}
|
||||
|
||||
canBeRendered(content) {
|
||||
return (
|
||||
isValidElement(content) ||
|
||||
typeof content === 'string' ||
|
||||
typeof content === 'number' ||
|
||||
this.isFunction(content)
|
||||
);
|
||||
}
|
||||
|
||||
show(content, options) {
|
||||
if (!this.canBeRendered(content)) {
|
||||
throw new Error(
|
||||
`The element you provided cannot be rendered. You provided an element of type ${typeof content}`
|
||||
);
|
||||
}
|
||||
const toastId = options.toastId;
|
||||
const closeToast = () => this.removeToast(toastId);
|
||||
const toastOptions = {
|
||||
id: toastId,
|
||||
type: options.type,
|
||||
closeToast: closeToast,
|
||||
updateId: options.updateId,
|
||||
position: options.position || this.props.position,
|
||||
transition: options.transition || this.props.transition,
|
||||
className: options.className || this.props.toastClassName,
|
||||
bodyClassName: options.bodyClassName || this.props.bodyClassName,
|
||||
closeButton: this.makeCloseButton(
|
||||
options.closeButton,
|
||||
toastId,
|
||||
options.type
|
||||
),
|
||||
pauseOnHover:
|
||||
options.pauseOnHover !== null
|
||||
? options.pauseOnHover
|
||||
: this.props.pauseOnHover,
|
||||
closeOnClick:
|
||||
options.closeOnClick !== null
|
||||
? options.closeOnClick
|
||||
: this.props.closeOnClick,
|
||||
progressClassName:
|
||||
options.progressClassName || this.props.progressClassName,
|
||||
autoClose: this.getAutoCloseDelay(
|
||||
options.autoClose !== false
|
||||
? parseInt(options.autoClose, 10)
|
||||
: options.autoClose
|
||||
),
|
||||
hideProgressBar:
|
||||
typeof options.hideProgressBar === 'boolean'
|
||||
? options.hideProgressBar
|
||||
: this.props.hideProgressBar
|
||||
};
|
||||
|
||||
this.isFunction(options.onOpen) && (toastOptions.onOpen = options.onOpen);
|
||||
|
||||
this.isFunction(options.onClose) &&
|
||||
(toastOptions.onClose = options.onClose);
|
||||
|
||||
/**
|
||||
* add closeToast function to react component only
|
||||
*/
|
||||
if (
|
||||
isValidElement(content) &&
|
||||
typeof content.type !== 'string' &&
|
||||
typeof content.type !== 'number'
|
||||
) {
|
||||
content = cloneElement(content, {
|
||||
closeToast
|
||||
});
|
||||
} else if (this.isFunction(content)) {
|
||||
content = content({ closeToast });
|
||||
}
|
||||
|
||||
this.collection = Object.assign({}, this.collection, {
|
||||
[toastId]: {
|
||||
position: toastOptions.position,
|
||||
options: toastOptions,
|
||||
content: content
|
||||
}
|
||||
});
|
||||
|
||||
this.setState({
|
||||
toast:
|
||||
toastOptions.updateId !== null
|
||||
? [...this.state.toast]
|
||||
: [...this.state.toast, toastId]
|
||||
});
|
||||
}
|
||||
|
||||
makeToast(content, options) {
|
||||
return (
|
||||
<Toast
|
||||
{...options}
|
||||
isDocumentHidden={this.state.isDocumentHidden}
|
||||
key={`toast-${options.id}`}
|
||||
>
|
||||
{content}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.setState({ toast: [] });
|
||||
}
|
||||
|
||||
renderToast() {
|
||||
const toastToRender = {};
|
||||
const { className, style, newestOnTop } = this.props;
|
||||
const collection = newestOnTop
|
||||
? Object.keys(this.collection).reverse()
|
||||
: Object.keys(this.collection);
|
||||
|
||||
collection.forEach(toastId => {
|
||||
const item = this.collection[toastId];
|
||||
toastToRender[item.position] || (toastToRender[item.position] = []);
|
||||
|
||||
if (this.state.toast.indexOf(parseInt(toastId, 10)) !== -1) {
|
||||
toastToRender[item.position].push(
|
||||
this.makeToast(item.content, item.options)
|
||||
);
|
||||
} else {
|
||||
toastToRender[item.position].push(null);
|
||||
delete this.collection[toastId];
|
||||
}
|
||||
});
|
||||
|
||||
return Object.keys(toastToRender).map(position => {
|
||||
const disablePointer =
|
||||
toastToRender[position].length === 1 &&
|
||||
toastToRender[position][0] === null;
|
||||
|
||||
return (
|
||||
<TransitionGroup
|
||||
{...(typeof className !== 'string'
|
||||
? css(container(disablePointer, position), className)
|
||||
: container(disablePointer, position))}
|
||||
{...typeof className === 'string' && { className }}
|
||||
{...style !== null && { style }}
|
||||
key={`container-${position}`}
|
||||
>
|
||||
{toastToRender[position]}
|
||||
</TransitionGroup>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div>{this.renderToast()}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
export default ToastContainer;
|
143
goTorrentWebUI/node_modules/react-toastify/src/animation.js
generated
vendored
Normal file
143
goTorrentWebUI/node_modules/react-toastify/src/animation.js
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
import { POSITION } from './constant';
|
||||
|
||||
export default function getAnimation(pos) {
|
||||
switch (pos) {
|
||||
case POSITION.TOP_RIGHT:
|
||||
case POSITION.BOTTOM_RIGHT:
|
||||
default:
|
||||
return {
|
||||
enter: {
|
||||
from: {
|
||||
opacity: 0,
|
||||
transform: 'translate3d(3000px, 0, 0)'
|
||||
},
|
||||
'60%': {
|
||||
opacity: 1,
|
||||
transform: 'translate3d(-25px, 0, 0)'
|
||||
},
|
||||
'75%': {
|
||||
transform: 'translate3d(10px, 0, 0)'
|
||||
},
|
||||
'90%': {
|
||||
transform: 'translate3d(-5px, 0, 0)'
|
||||
},
|
||||
to: {
|
||||
transform: 'none'
|
||||
}
|
||||
},
|
||||
exit: {
|
||||
'20%': {
|
||||
opacity: 1,
|
||||
transform: 'translate3d(-20px, 0, 0)'
|
||||
},
|
||||
to: {
|
||||
opacity: 0,
|
||||
transform: 'translate3d(2000px, 0, 0)'
|
||||
}
|
||||
}
|
||||
};
|
||||
case POSITION.TOP_LEFT:
|
||||
case POSITION.BOTTOM_LEFT:
|
||||
return {
|
||||
enter: {
|
||||
'0%': {
|
||||
opacity: 0,
|
||||
transform: 'translate3d(-3000px, 0, 0)'
|
||||
},
|
||||
'60%': {
|
||||
opacity: 1,
|
||||
transform: 'translate3d(25px, 0, 0)'
|
||||
},
|
||||
'75%': {
|
||||
transform: 'translate3d(-10px, 0, 0)'
|
||||
},
|
||||
'90%': {
|
||||
transform: 'translate3d(5px, 0, 0)'
|
||||
},
|
||||
to: {
|
||||
transform: 'none'
|
||||
}
|
||||
},
|
||||
exit: {
|
||||
'20%': {
|
||||
opacity: 1,
|
||||
transform: 'translate3d(20px, 0, 0)'
|
||||
},
|
||||
to: {
|
||||
opacity: 0,
|
||||
transform: 'translate3d(-2000px, 0, 0)'
|
||||
}
|
||||
}
|
||||
};
|
||||
case POSITION.BOTTOM_CENTER:
|
||||
return {
|
||||
enter: {
|
||||
from: {
|
||||
opacity: 0,
|
||||
transform: 'translate3d(0, 3000px, 0)'
|
||||
},
|
||||
'60%': {
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, -20px, 0)'
|
||||
},
|
||||
'75%': {
|
||||
transform: 'translate3d(0, 10px, 0)'
|
||||
},
|
||||
'90%': {
|
||||
transform: 'translate3d(0, -5px, 0)'
|
||||
},
|
||||
to: {
|
||||
transform: 'translate3d(0, 0, 0)'
|
||||
}
|
||||
},
|
||||
exit: {
|
||||
'20%': {
|
||||
transform: 'translate3d(0, 10px, 0)'
|
||||
},
|
||||
'40%, 45%': {
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, -20px, 0)'
|
||||
},
|
||||
to: {
|
||||
opacity: 0,
|
||||
transform: 'translate3d(0, 2000px, 0)'
|
||||
}
|
||||
}
|
||||
};
|
||||
case POSITION.TOP_CENTER:
|
||||
return {
|
||||
enter: {
|
||||
'0%': {
|
||||
opacity: 0,
|
||||
transform: 'translate3d(0, -3000px, 0)'
|
||||
},
|
||||
'60%': {
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, 25px, 0)'
|
||||
},
|
||||
'75%': {
|
||||
transform: 'translate3d(0, -10px, 0)'
|
||||
},
|
||||
'90%': {
|
||||
transform: 'translate3d(0, 5px, 0)'
|
||||
},
|
||||
to: {
|
||||
transform: 'none'
|
||||
}
|
||||
},
|
||||
exit: {
|
||||
'20%': {
|
||||
transform: 'translate3d(0, -10px, 0)'
|
||||
},
|
||||
'40%, 45%': {
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, 20px, 0)'
|
||||
},
|
||||
to: {
|
||||
opacity: 0,
|
||||
transform: 'translate3d(0, -2000px, 0)'
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
21
goTorrentWebUI/node_modules/react-toastify/src/constant.js
generated
vendored
Normal file
21
goTorrentWebUI/node_modules/react-toastify/src/constant.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
export const POSITION = {
|
||||
TOP_LEFT: 'top-left',
|
||||
TOP_RIGHT: 'top-right',
|
||||
TOP_CENTER: 'top-center',
|
||||
BOTTOM_LEFT: 'bottom-left',
|
||||
BOTTOM_RIGHT: 'bottom-right',
|
||||
BOTTOM_CENTER: 'bottom-center'
|
||||
};
|
||||
|
||||
export const TYPE = {
|
||||
INFO: 'info',
|
||||
SUCCESS: 'success',
|
||||
WARNING: 'warning',
|
||||
ERROR: 'error',
|
||||
DEFAULT: 'default'
|
||||
};
|
||||
export const ACTION = {
|
||||
SHOW: 'SHOW_TOAST',
|
||||
CLEAR: 'CLEAR_TOAST',
|
||||
MOUNTED: 'CONTAINER_MOUNTED'
|
||||
};
|
5
goTorrentWebUI/node_modules/react-toastify/src/index.js
generated
vendored
Normal file
5
goTorrentWebUI/node_modules/react-toastify/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import ToastContainer from './ToastContainer';
|
||||
import toaster from './toaster';
|
||||
import { defineStyle } from './style';
|
||||
|
||||
export { ToastContainer, toaster as toast, defineStyle as style };
|
45
goTorrentWebUI/node_modules/react-toastify/src/style.js
generated
vendored
Normal file
45
goTorrentWebUI/node_modules/react-toastify/src/style.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
const style = {
|
||||
width: '320px',
|
||||
colorDefault: '#fff',
|
||||
colorInfo: '#3498db',
|
||||
colorSuccess: '#07bc0c',
|
||||
colorWarning: '#f1c40f',
|
||||
colorError: '#e74c3c',
|
||||
colorProgressDefault:
|
||||
'linear-gradient(to right, #4cd964, #5ac8fa, #007aff, #34aadc, #5856d6, #ff2d55)',
|
||||
mobile: 'only screen and (max-width : 480px)',
|
||||
fontFamily: 'sans-serif',
|
||||
zIndex: 9999,
|
||||
TOP_LEFT: {
|
||||
top: '1em',
|
||||
left: '1em'
|
||||
},
|
||||
TOP_CENTER: {
|
||||
top: '1em',
|
||||
left: '50%'
|
||||
},
|
||||
TOP_RIGHT: {
|
||||
top: '1em',
|
||||
right: '1em'
|
||||
},
|
||||
BOTTOM_LEFT: {
|
||||
bottom: '1em',
|
||||
left: '1em'
|
||||
},
|
||||
BOTTOM_CENTER: {
|
||||
bottom: '1em',
|
||||
left: '50%'
|
||||
},
|
||||
BOTTOM_RIGHT: {
|
||||
bottom: '1em',
|
||||
right: '1em'
|
||||
}
|
||||
};
|
||||
|
||||
export function defineStyle(props) {
|
||||
for (let prop in props) {
|
||||
style[prop] = props[prop];
|
||||
}
|
||||
}
|
||||
|
||||
export default style;
|
114
goTorrentWebUI/node_modules/react-toastify/src/toaster.js
generated
vendored
Normal file
114
goTorrentWebUI/node_modules/react-toastify/src/toaster.js
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
import EventManager from './util/EventManager';
|
||||
import { POSITION, TYPE, ACTION } from './constant';
|
||||
|
||||
const defaultOptions = {
|
||||
type: TYPE.DEFAULT,
|
||||
autoClose: null,
|
||||
closeButton: null,
|
||||
hideProgressBar: null,
|
||||
position: null,
|
||||
pauseOnHover: null,
|
||||
closeOnClick: null,
|
||||
className: null,
|
||||
bodyClassName: null,
|
||||
progressClassName: null,
|
||||
transition: null,
|
||||
updateId: null
|
||||
};
|
||||
|
||||
let container = null;
|
||||
let queue = [];
|
||||
let toastId = 0;
|
||||
|
||||
/**
|
||||
* Merge provided options with the defaults settings and generate the toastId
|
||||
* @param {*} options
|
||||
*/
|
||||
function mergeOptions(options, type) {
|
||||
return Object.assign({}, defaultOptions, options, {
|
||||
type: type,
|
||||
toastId: ++toastId
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch toast. If the container is not mounted, the toast is enqueued
|
||||
* @param {*} content
|
||||
* @param {*} options
|
||||
*/
|
||||
function emitEvent(content, options) {
|
||||
if (container !== null) {
|
||||
EventManager.emit(ACTION.SHOW, content, options);
|
||||
} else {
|
||||
queue.push({ action: ACTION.SHOW, content, options });
|
||||
}
|
||||
|
||||
return options.toastId;
|
||||
}
|
||||
|
||||
const toaster = Object.assign(
|
||||
(content, options) =>
|
||||
emitEvent(
|
||||
content,
|
||||
mergeOptions(options, (options && options.type) || TYPE.DEFAULT)
|
||||
),
|
||||
{
|
||||
success: (content, options) =>
|
||||
emitEvent(content, mergeOptions(options, TYPE.SUCCESS)),
|
||||
info: (content, options) =>
|
||||
emitEvent(content, mergeOptions(options, TYPE.INFO)),
|
||||
warn: (content, options) =>
|
||||
emitEvent(content, mergeOptions(options, TYPE.WARNING)),
|
||||
warning: (content, options) =>
|
||||
emitEvent(content, mergeOptions(options, TYPE.WARNING)),
|
||||
error: (content, options) =>
|
||||
emitEvent(content, mergeOptions(options, TYPE.ERROR)),
|
||||
dismiss: (id = null) => container && EventManager.emit(ACTION.CLEAR, id),
|
||||
isActive: () => false,
|
||||
update(id, options) {
|
||||
if (container && typeof container.collection[id] !== 'undefined') {
|
||||
const {
|
||||
options: oldOptions,
|
||||
content: oldContent
|
||||
} = container.collection[id];
|
||||
const updateId =
|
||||
oldOptions.updateId !== null ? oldOptions.updateId + 1 : 1;
|
||||
|
||||
const nextOptions = Object.assign({}, oldOptions, options, {
|
||||
toastId: id,
|
||||
updateId: updateId
|
||||
});
|
||||
const content =
|
||||
typeof nextOptions.render !== 'undefined'
|
||||
? nextOptions.render
|
||||
: oldContent;
|
||||
delete nextOptions.render;
|
||||
|
||||
return emitEvent(content, nextOptions);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
{
|
||||
POSITION,
|
||||
TYPE
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Wait until the ToastContainer is mounted to dispatch the toast
|
||||
* and attach isActive method
|
||||
*/
|
||||
EventManager.on(ACTION.MOUNTED, containerInstance => {
|
||||
container = containerInstance;
|
||||
|
||||
toaster.isActive = id => container.isToastActive(id);
|
||||
|
||||
queue.forEach(item => {
|
||||
EventManager.emit(item.action, item.content, item.options);
|
||||
});
|
||||
queue = [];
|
||||
});
|
||||
|
||||
export default toaster;
|
33
goTorrentWebUI/node_modules/react-toastify/src/util/EventManager.js
generated
vendored
Normal file
33
goTorrentWebUI/node_modules/react-toastify/src/util/EventManager.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
const eventManager = {
|
||||
eventList: new Map(),
|
||||
|
||||
on(event, callback) {
|
||||
this.eventList.has(event) || this.eventList.set(event, []);
|
||||
|
||||
this.eventList.get(event).push(callback);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
off(event = null) {
|
||||
return this.eventList.delete(event);
|
||||
},
|
||||
|
||||
emit(event, ...args) {
|
||||
if (!this.eventList.has(event)) {
|
||||
/* eslint no-console: 0 */
|
||||
console.warn(
|
||||
`<${event}> Event is not registered. Did you forgot to bind the event ?`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.eventList
|
||||
.get(event)
|
||||
.forEach(callback => setTimeout(() => callback.call(this, ...args), 0));
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
export default eventManager;
|
45
goTorrentWebUI/node_modules/react-toastify/src/util/propValidator.js
generated
vendored
Normal file
45
goTorrentWebUI/node_modules/react-toastify/src/util/propValidator.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
import { isValidElement } from 'react';
|
||||
|
||||
export function isValidDelay(val) {
|
||||
return typeof val === 'number' && !isNaN(val) && val > 0;
|
||||
}
|
||||
|
||||
export function objectValues(obj) {
|
||||
return Object.keys(obj).map(key => obj[key]);
|
||||
}
|
||||
|
||||
function withRequired(fn) {
|
||||
fn.isRequired = function(props, propName, componentName) {
|
||||
const prop = props[propName];
|
||||
|
||||
if (typeof prop === 'undefined') {
|
||||
return new Error(`The prop ${propName} is marked as required in
|
||||
${componentName}, but its value is undefined.`);
|
||||
}
|
||||
|
||||
fn(props, propName, componentName);
|
||||
};
|
||||
return fn;
|
||||
}
|
||||
|
||||
export const falseOrDelay = withRequired((props, propName, componentName) => {
|
||||
const prop = props[propName];
|
||||
|
||||
if (prop !== false && !isValidDelay(prop)) {
|
||||
return new Error(`${componentName} expect ${propName}
|
||||
to be a valid Number > 0 or equal to false. ${prop} given.`);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
export const falseOrElement = withRequired((props, propName, componentName) => {
|
||||
const prop = props[propName];
|
||||
|
||||
if (prop !== false && !isValidElement(prop)) {
|
||||
return new Error(`${componentName} expect ${propName}
|
||||
to be a valid react element or equal to false. ${prop} given.`);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
Reference in New Issue
Block a user