mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
commit
be144496e1
26 changed files with 221 additions and 191 deletions
|
|
@ -2,7 +2,7 @@ require('spatial-navigation-polyfill');
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
const { Router } = require('stremio-router');
|
const { Router } = require('stremio-router');
|
||||||
const { Core, KeyboardNavigation, ServicesProvider, Shell } = require('stremio/services');
|
const { Core, KeyboardNavigation, ServicesProvider, Shell } = require('stremio/services');
|
||||||
const { ToastsContainerProvider } = require('stremio/common/Toasts/ToastsContainerContext');
|
const { ToastProvider } = require('stremio/common');
|
||||||
const routerViewsConfig = require('./routerViewsConfig');
|
const routerViewsConfig = require('./routerViewsConfig');
|
||||||
const styles = require('./styles');
|
const styles = require('./styles');
|
||||||
|
|
||||||
|
|
@ -51,14 +51,14 @@ const App = () => {
|
||||||
<ServicesProvider services={services}>
|
<ServicesProvider services={services}>
|
||||||
{
|
{
|
||||||
shellInitialized && coreInitialized ?
|
shellInitialized && coreInitialized ?
|
||||||
<ToastsContainerProvider>
|
<ToastProvider className={styles['toasts-container']}>
|
||||||
<Router
|
<Router
|
||||||
className={styles['router']}
|
className={styles['router']}
|
||||||
homePath={'/'}
|
homePath={'/'}
|
||||||
viewsConfig={routerViewsConfig}
|
viewsConfig={routerViewsConfig}
|
||||||
onPathNotMatch={onPathNotMatch}
|
onPathNotMatch={onPathNotMatch}
|
||||||
/>
|
/>
|
||||||
</ToastsContainerProvider>
|
</ToastProvider>
|
||||||
:
|
:
|
||||||
<div className={styles['app-loader']} />
|
<div className={styles['app-loader']} />
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,23 @@ html {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
.toasts-container {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(1.2 * var(--nav-bar-size));
|
||||||
|
right: 0;
|
||||||
|
bottom: calc(1.2 * var(--nav-bar-size));
|
||||||
|
left: auto;
|
||||||
|
z-index: 1;
|
||||||
|
padding: 0 calc(1.2 * var(--nav-bar-size));
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: none;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: var(--scroll-bar-width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.router {
|
.router {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ const ColorInput = ({ className, value, dataset, onChange, ...props }) => {
|
||||||
ColorInput.propTypes = {
|
ColorInput.propTypes = {
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
value: PropTypes.string,
|
value: PropTypes.string,
|
||||||
dataset: PropTypes.objectOf(PropTypes.string),
|
dataset: PropTypes.object,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
onClick: PropTypes.func
|
onClick: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ MetaItem.propTypes = {
|
||||||
playIcon: PropTypes.bool,
|
playIcon: PropTypes.bool,
|
||||||
progress: PropTypes.number,
|
progress: PropTypes.number,
|
||||||
options: PropTypes.array,
|
options: PropTypes.array,
|
||||||
dataset: PropTypes.objectOf(PropTypes.string),
|
dataset: PropTypes.object,
|
||||||
optionOnSelect: PropTypes.func,
|
optionOnSelect: PropTypes.func,
|
||||||
onClick: PropTypes.func
|
onClick: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ ModalDialog.propTypes = {
|
||||||
PropTypes.arrayOf(PropTypes.node),
|
PropTypes.arrayOf(PropTypes.node),
|
||||||
PropTypes.node
|
PropTypes.node
|
||||||
]),
|
]),
|
||||||
dataset: PropTypes.objectOf(PropTypes.string),
|
dataset: PropTypes.object,
|
||||||
onCloseRequest: PropTypes.func
|
onCloseRequest: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ Multiselect.propTypes = {
|
||||||
})),
|
})),
|
||||||
selected: PropTypes.arrayOf(PropTypes.string),
|
selected: PropTypes.arrayOf(PropTypes.string),
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
dataset: PropTypes.objectOf(PropTypes.string),
|
dataset: PropTypes.object,
|
||||||
renderLabelContent: PropTypes.func,
|
renderLabelContent: PropTypes.func,
|
||||||
renderLabelText: PropTypes.func,
|
renderLabelText: PropTypes.func,
|
||||||
onOpen: PropTypes.func,
|
onOpen: PropTypes.func,
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ const PaginationInput = ({ className, label, dataset, onSelect, ...props }) => {
|
||||||
PaginationInput.propTypes = {
|
PaginationInput.propTypes = {
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
label: PropTypes.string,
|
label: PropTypes.string,
|
||||||
dataset: PropTypes.objectOf(PropTypes.string),
|
dataset: PropTypes.object,
|
||||||
onSelect: PropTypes.func
|
onSelect: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ Popup.propTypes = {
|
||||||
direction: PropTypes.oneOf(['top-left', 'bottom-left', 'top-right', 'bottom-right']),
|
direction: PropTypes.oneOf(['top-left', 'bottom-left', 'top-right', 'bottom-right']),
|
||||||
renderLabel: PropTypes.func.isRequired,
|
renderLabel: PropTypes.func.isRequired,
|
||||||
renderMenu: PropTypes.func.isRequired,
|
renderMenu: PropTypes.func.isRequired,
|
||||||
dataset: PropTypes.objectOf(PropTypes.string),
|
dataset: PropTypes.object,
|
||||||
onCloseRequest: PropTypes.func
|
onCloseRequest: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
10
src/common/Toast/ToastContext.js
Normal file
10
src/common/Toast/ToastContext.js
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
const ToastContext = React.createContext({
|
||||||
|
show: () => { },
|
||||||
|
clear: () => { }
|
||||||
|
});
|
||||||
|
|
||||||
|
ToastContext.displayName = 'ToastContext';
|
||||||
|
|
||||||
|
module.exports = ToastContext;
|
||||||
71
src/common/Toast/ToastItem/ToastItem.js
Normal file
71
src/common/Toast/ToastItem/ToastItem.js
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
const React = require('react');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
const classnames = require('classnames');
|
||||||
|
const Icon = require('stremio-icons/dom');
|
||||||
|
const Button = require('stremio/common/Button');
|
||||||
|
const styles = require('./styles');
|
||||||
|
|
||||||
|
const ToastItem = ({ type, title, message, icon, dataset, onSelect, onClose }) => {
|
||||||
|
const toastOnClick = React.useCallback((event) => {
|
||||||
|
if (!event.nativeEvent.selectPrevented && typeof onSelect === 'function') {
|
||||||
|
onSelect({
|
||||||
|
type: 'select',
|
||||||
|
dataset: dataset,
|
||||||
|
reactEvent: event,
|
||||||
|
nativeEvent: event.nativeEvent
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [dataset, onSelect]);
|
||||||
|
const closeButtonOnClick = React.useCallback((event) => {
|
||||||
|
event.nativeEvent.selectPrevented = true;
|
||||||
|
if (typeof onClose === 'function') {
|
||||||
|
onClose({
|
||||||
|
type: 'close',
|
||||||
|
dataset: dataset,
|
||||||
|
reactEvent: event,
|
||||||
|
nativeEvent: event.nativeEvent
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [dataset, onClose]);
|
||||||
|
return (
|
||||||
|
<Button className={classnames(styles['toast-item-container'], styles['success'], styles[type])} tabIndex={-1} onClick={toastOnClick}>
|
||||||
|
{
|
||||||
|
typeof icon === 'string' && icon.length > 0 ?
|
||||||
|
<div className={styles['icon-container']}>
|
||||||
|
<Icon className={styles['icon']} icon={icon} />
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
null
|
||||||
|
}
|
||||||
|
<div className={styles['info-container']}>
|
||||||
|
{
|
||||||
|
typeof title === 'string' && title.length > 0 ?
|
||||||
|
<div className={styles['title-container']}>{title}</div>
|
||||||
|
:
|
||||||
|
null
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typeof message === 'string' && message.length > 0 ?
|
||||||
|
<div className={styles['message-container']}>{message}</div>
|
||||||
|
:
|
||||||
|
null
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<Button className={styles['close-button-container']} title={'Close'} tabIndex={-1} onClick={closeButtonOnClick}>
|
||||||
|
<Icon className={styles['icon']} icon={'ic_x'} />
|
||||||
|
</Button>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ToastItem.propTypes = {
|
||||||
|
type: PropTypes.oneOf(['success', 'alert', 'error']),
|
||||||
|
title: PropTypes.string,
|
||||||
|
message: PropTypes.string,
|
||||||
|
icon: PropTypes.string,
|
||||||
|
dataset: PropTypes.object,
|
||||||
|
onSelect: PropTypes.func,
|
||||||
|
onClose: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = ToastItem;
|
||||||
3
src/common/Toast/ToastItem/index.js
Normal file
3
src/common/Toast/ToastItem/index.js
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
const ToastItem = require('./ToastItem');
|
||||||
|
|
||||||
|
module.exports = ToastItem;
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
.toast-container {
|
.toast-item-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
width: 25rem;
|
||||||
min-height: 6rem;
|
min-height: 6rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
border: thin solid;
|
border: thin solid;
|
||||||
color: var(--color-backgrounddarker);
|
|
||||||
fill: var(--color-backgrounddarker);
|
|
||||||
background-color: var(--color-surfacelighter);
|
background-color: var(--color-surfacelighter);
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
pointer-events: all;
|
box-shadow: 0 0.3rem 0.5rem var(--color-backgrounddarker40),
|
||||||
|
0 0.6rem 1rem var(--color-backgrounddarker20);
|
||||||
|
pointer-events: auto;
|
||||||
|
|
||||||
&.success {
|
&.success {
|
||||||
color: var(--color-signal5);
|
color: var(--color-signal5);
|
||||||
|
|
@ -26,10 +27,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-container {
|
.icon-container {
|
||||||
width: 5rem;
|
flex: none;
|
||||||
padding: 1rem;
|
align-self: stretch;
|
||||||
padding-right: 0;
|
width: 4.5rem;
|
||||||
overflow: visible;
|
padding: 1.2rem 0 1.2rem 1.2rem;
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
@ -38,33 +39,35 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-container {
|
.info-container {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
align-self: stretch;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
||||||
&.clickable {
|
.title-container {
|
||||||
cursor: pointer;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-caption {
|
.message-container {
|
||||||
font-weight: bold;
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-button-container {
|
.close-button-container {
|
||||||
flex: none;
|
flex: none;
|
||||||
|
align-self: flex-start;
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-surfacelight);
|
||||||
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--color-surfacelight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
72
src/common/Toast/ToastProvider.js
Normal file
72
src/common/Toast/ToastProvider.js
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
const React = require('react');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
const ToastItem = require('./ToastItem');
|
||||||
|
const ToastContext = require('./ToastContext');
|
||||||
|
|
||||||
|
const DEFAULT_TIMEOUT = 3000;
|
||||||
|
|
||||||
|
const ToastProvider = ({ className, children }) => {
|
||||||
|
const [container, setContainer] = React.useState(null);
|
||||||
|
const [items, dispatch] = React.useReducer(
|
||||||
|
(items, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'add':
|
||||||
|
return items.concat(action.item);
|
||||||
|
case 'remove':
|
||||||
|
return items.filter((item) => item.id !== action.id);
|
||||||
|
case 'clear':
|
||||||
|
return [];
|
||||||
|
default:
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
const itemOnClose = React.useCallback((event) => {
|
||||||
|
clearTimeout(event.dataset.id);
|
||||||
|
dispatch({ type: 'remove', id: event.dataset.id });
|
||||||
|
}, []);
|
||||||
|
const toast = React.useMemo(() => ({
|
||||||
|
show: (item) => {
|
||||||
|
const timeout = typeof item.timeout === 'number' && !isNaN(item.timeout) ?
|
||||||
|
item.timeout
|
||||||
|
:
|
||||||
|
DEFAULT_TIMEOUT;
|
||||||
|
const id = setTimeout(() => {
|
||||||
|
dispatch({ type: 'remove', id });
|
||||||
|
}, timeout);
|
||||||
|
dispatch({
|
||||||
|
type: 'add',
|
||||||
|
item: {
|
||||||
|
...item,
|
||||||
|
id,
|
||||||
|
dataset: {
|
||||||
|
...item.dataset,
|
||||||
|
id
|
||||||
|
},
|
||||||
|
onClose: itemOnClose
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
clear: () => {
|
||||||
|
dispatch({ type: 'clear' });
|
||||||
|
}
|
||||||
|
}), []);
|
||||||
|
return (
|
||||||
|
<ToastContext.Provider value={toast}>
|
||||||
|
{container instanceof HTMLElement ? children : null}
|
||||||
|
<div ref={setContainer} className={className}>
|
||||||
|
{items.map((item, index) => (
|
||||||
|
<ToastItem key={index} {...item} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</ToastContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ToastProvider.propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
children: PropTypes.node
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = ToastProvider;
|
||||||
7
src/common/Toast/index.js
Normal file
7
src/common/Toast/index.js
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
const ToastProvider = require('./ToastProvider');
|
||||||
|
const useToast = require('./useToast');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
ToastProvider,
|
||||||
|
useToast
|
||||||
|
};
|
||||||
8
src/common/Toast/useToast.js
Normal file
8
src/common/Toast/useToast.js
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
const React = require('react');
|
||||||
|
const ToastContext = require('./ToastContext');
|
||||||
|
|
||||||
|
const useToast = () => {
|
||||||
|
return React.useContext(ToastContext);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = useToast;
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
const React = require('react');
|
|
||||||
const PropTypes = require('prop-types');
|
|
||||||
const classnames = require('classnames');
|
|
||||||
const Icon = require('stremio-icons/dom');
|
|
||||||
const Button = require('stremio/common/Button');
|
|
||||||
const styles = require('./styles');
|
|
||||||
|
|
||||||
const Toast = ({ type, title, text, icon, closeButton, onClick, onClose }) => {
|
|
||||||
return (
|
|
||||||
<div className={classnames(styles['toast-container'], styles[type])}>
|
|
||||||
{
|
|
||||||
typeof icon === 'string' && icon.length > 0 ?
|
|
||||||
<div className={styles['icon-container']}>
|
|
||||||
<Icon className={styles['icon']} icon={icon} />
|
|
||||||
</div>
|
|
||||||
:
|
|
||||||
null
|
|
||||||
}
|
|
||||||
<div className={classnames(styles['message-container'], { [styles.clickable]: typeof onClick === 'function' })} onClick={onClick}>
|
|
||||||
{
|
|
||||||
typeof title === 'string' && title.length > 0 ?
|
|
||||||
<h1>{title}</h1>
|
|
||||||
:
|
|
||||||
null
|
|
||||||
}
|
|
||||||
{text}
|
|
||||||
</div>
|
|
||||||
{
|
|
||||||
closeButton ?
|
|
||||||
<Button className={styles['close-button-container']} title={'Close'} onClick={onClose}>
|
|
||||||
<Icon className={styles['icon']} icon={'ic_x'} />
|
|
||||||
</Button>
|
|
||||||
:
|
|
||||||
null
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Toast.propTypes = {
|
|
||||||
type: PropTypes.string,
|
|
||||||
title: PropTypes.string,
|
|
||||||
text: PropTypes.string,
|
|
||||||
icon: PropTypes.string,
|
|
||||||
closeButton: PropTypes.bool,
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
onClose: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Toast;
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
const Toast = require('./Toast');
|
|
||||||
|
|
||||||
module.exports = Toast;
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
const React = require('react');
|
|
||||||
const { Modal } = require('stremio-router');
|
|
||||||
const ModalsContainerContext = require('stremio-router/ModalsContainerContext/ModalsContainerContext');
|
|
||||||
const { useToastsContainer } = require('./ToastsContainerContext');
|
|
||||||
const Toast = require('./Toast');
|
|
||||||
|
|
||||||
const DEFAULT_TIMEOUT = 2000;
|
|
||||||
|
|
||||||
const Toasts = React.forwardRef(({ className }, ref) => {
|
|
||||||
const toastsContainer = useToastsContainer();
|
|
||||||
const [toasts, dispatch] = React.useReducer(
|
|
||||||
(state, action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case 'add':
|
|
||||||
return state.concat([action.item]);
|
|
||||||
case 'remove':
|
|
||||||
return state.filter(item => item !== action.item);
|
|
||||||
case 'removeAll':
|
|
||||||
state.forEach(item => clearTimeout(item.timerId));
|
|
||||||
return [];
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}, []
|
|
||||||
);
|
|
||||||
const hideAll = React.useCallback(() => {
|
|
||||||
dispatch({ type: 'removeAll' });
|
|
||||||
}, []);
|
|
||||||
const show = React.useCallback(({ type, icon, title, text, closeButton, timeout, onClick }) => {
|
|
||||||
timeout = timeout !== null && !isNaN(timeout) ? timeout : DEFAULT_TIMEOUT;
|
|
||||||
const close = () => {
|
|
||||||
clearTimeout(newItem.timerId);
|
|
||||||
dispatch({ type: 'remove', item: newItem });
|
|
||||||
};
|
|
||||||
|
|
||||||
const newItem = { type, icon, title, text, closeButton, timeout, onClick, onClose: close };
|
|
||||||
|
|
||||||
if (timeout !== 0) {
|
|
||||||
newItem.timerId = setTimeout(close, timeout);
|
|
||||||
}
|
|
||||||
dispatch({ type: 'add', item: newItem });
|
|
||||||
return close;
|
|
||||||
}, []);
|
|
||||||
React.useImperativeHandle(ref, () => ({ show, hideAll }));
|
|
||||||
|
|
||||||
return toasts.length === 0 ? null : (
|
|
||||||
<ModalsContainerContext.Provider value={toastsContainer}>
|
|
||||||
<Modal className={className} disabled={true}>
|
|
||||||
{toasts.map((toast, index) => (<Toast {...toast} key={index} />))}
|
|
||||||
</Modal>
|
|
||||||
</ModalsContainerContext.Provider>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = Toasts;
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
const React = require('react');
|
|
||||||
|
|
||||||
const ToastsContainerContext = React.createContext(null);
|
|
||||||
|
|
||||||
ToastsContainerContext.displayName = 'ToastsContainerContext';
|
|
||||||
|
|
||||||
module.exports = ToastsContainerContext;
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
const React = require('react');
|
|
||||||
const PropTypes = require('prop-types');
|
|
||||||
const ToastsContainerContext = require('./ToastsContainerContext');
|
|
||||||
const styles = require('./styles');
|
|
||||||
|
|
||||||
const ToastsContainerProvider = ({ children }) => {
|
|
||||||
const [container, setContainer] = React.useState(null);
|
|
||||||
return (
|
|
||||||
<ToastsContainerContext.Provider value={container}>
|
|
||||||
{container instanceof HTMLElement ? children : null}
|
|
||||||
<div ref={setContainer} className={styles['toasts-container']} />
|
|
||||||
</ToastsContainerContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ToastsContainerProvider.propTypes = {
|
|
||||||
children: PropTypes.node
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = ToastsContainerProvider;
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
const ToastsContainerProvider = require('./ToastsContainerProvider');
|
|
||||||
const useToastsContainer = require('./useToastsContainer');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
ToastsContainerProvider,
|
|
||||||
useToastsContainer
|
|
||||||
};
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
.toasts-container {
|
|
||||||
position: absolute;
|
|
||||||
top: var(--nav-bar-size);
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: auto !important;
|
|
||||||
z-index: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
const React = require('react');
|
|
||||||
const ToastsContainerContext = require('./ToastsContainerContext');
|
|
||||||
|
|
||||||
const useToastsContainer = () => {
|
|
||||||
return React.useContext(ToastsContainerContext);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = useToastsContainer;
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
const Toasts = require('./Toasts');
|
|
||||||
|
|
||||||
module.exports = Toasts;
|
|
||||||
|
|
@ -16,7 +16,7 @@ const Popup = require('./Popup');
|
||||||
const SharePrompt = require('./SharePrompt');
|
const SharePrompt = require('./SharePrompt');
|
||||||
const Slider = require('./Slider');
|
const Slider = require('./Slider');
|
||||||
const TextInput = require('./TextInput');
|
const TextInput = require('./TextInput');
|
||||||
const Toasts = require('./Toasts');
|
const { ToastProvider, useToast } = require('./Toast');
|
||||||
const routesRegexp = require('./routesRegexp');
|
const routesRegexp = require('./routesRegexp');
|
||||||
const useAnimationFrame = require('./useAnimationFrame');
|
const useAnimationFrame = require('./useAnimationFrame');
|
||||||
const useBinaryState = require('./useBinaryState');
|
const useBinaryState = require('./useBinaryState');
|
||||||
|
|
@ -47,7 +47,8 @@ module.exports = {
|
||||||
SharePrompt,
|
SharePrompt,
|
||||||
Slider,
|
Slider,
|
||||||
TextInput,
|
TextInput,
|
||||||
Toasts,
|
ToastProvider,
|
||||||
|
useToast,
|
||||||
routesRegexp,
|
routesRegexp,
|
||||||
useAnimationFrame,
|
useAnimationFrame,
|
||||||
useBinaryState,
|
useBinaryState,
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ Addon.propTypes = {
|
||||||
installed: PropTypes.bool,
|
installed: PropTypes.bool,
|
||||||
onToggle: PropTypes.func,
|
onToggle: PropTypes.func,
|
||||||
onShare: PropTypes.func,
|
onShare: PropTypes.func,
|
||||||
dataset: PropTypes.objectOf(PropTypes.string)
|
dataset: PropTypes.object
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Addon;
|
module.exports = Addon;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue