@itwin/itwinui-react
Version:
A react component library for iTwinUI
299 lines (298 loc) • 7.8 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', {
value: true,
});
function _export(target, all) {
for (var name in all)
Object.defineProperty(target, name, {
enumerable: true,
get: all[name],
});
}
_export(exports, {
Toast: function () {
return Toast;
},
ToastPresentation: function () {
return ToastPresentation;
},
});
const _interop_require_default = require('@swc/helpers/_/_interop_require_default');
const _interop_require_wildcard = require('@swc/helpers/_/_interop_require_wildcard');
const _react = /*#__PURE__*/ _interop_require_wildcard._(require('react'));
const _classnames = /*#__PURE__*/ _interop_require_default._(
require('classnames'),
);
const _index = require('../../utils/index.js');
const _IconButton = require('../Buttons/IconButton.js');
const _Toaster = require('./Toaster.js');
const Toast = (props) => {
let {
content,
category,
type = 'temporary',
isVisible: isVisibleProp,
link,
duration = 7000,
hasCloseButton,
onRemove,
animateOutTo,
domProps,
} = props;
let closeTimeout = _react.useRef(0);
let { placement } = (0, _index.useSafeContext)(
_Toaster.ToasterStateContext,
).settings;
let placementPosition = placement.startsWith('top') ? 'top' : 'bottom';
let [visible, setVisible] = _react.useState(isVisibleProp ?? true);
let isVisible = isVisibleProp ?? visible;
let [height, setHeight] = _react.useState(0);
let thisElement = _react.useRef(null);
let [margin, setMargin] = _react.useState(0);
let marginStyle = () => {
if ('top' === placementPosition)
return {
marginBlockEnd: margin,
};
return {
marginBlockStart: margin,
};
};
_react.useEffect(() => {
if ('temporary' === type) setCloseTimeout(duration);
return () => {
clearCloseTimeout();
};
}, [duration, type]);
_react.useEffect(() => {
if (!isVisible && !animateOutTo) setMargin(-height);
}, [isVisible, animateOutTo, setMargin, height]);
let close = () => {
clearCloseTimeout();
setMargin(-height);
setVisible(false);
};
let setCloseTimeout = (timeout) => {
let definedWindow = (0, _index.getWindow)();
if (!definedWindow) return;
closeTimeout.current = definedWindow.setTimeout(() => {
close();
}, timeout);
};
let clearCloseTimeout = () => {
(0, _index.getWindow)()?.clearTimeout(closeTimeout.current);
};
let onRef = (ref) => {
if (ref) {
let { height } = ref.getBoundingClientRect();
setHeight(height);
}
};
let shouldBeMounted = useAnimateToastBasedOnVisibility(isVisible, {
thisElement,
animateOutTo,
onRemove,
});
return shouldBeMounted
? _react.createElement(
_index.Box,
{
ref: thisElement,
className: 'iui-toast-all',
style: {
height,
...marginStyle(),
},
},
_react.createElement(
'div',
{
ref: onRef,
},
_react.createElement(ToastPresentation, {
as: 'div',
category: category,
content: content,
link: link,
type: type,
hasCloseButton: hasCloseButton,
onClose: close,
...domProps?.toastProps,
contentProps: domProps?.contentProps,
}),
),
)
: null;
};
const ToastPresentation = _react.forwardRef((props, forwardedRef) => {
let {
content,
category,
type = 'temporary',
link,
hasCloseButton,
onClose,
className,
contentProps,
...rest
} = props;
let StatusIcon = _index.StatusIconMap[category];
return _react.createElement(
_index.Box,
{
className: (0, _classnames.default)(
`iui-toast iui-${category}`,
className,
),
ref: forwardedRef,
...rest,
},
_react.createElement(
_index.Box,
{
className: 'iui-status-area',
},
_react.createElement(StatusIcon, {
className: 'iui-icon',
}),
),
_react.createElement(
_index.Box,
{
as: 'div',
...contentProps,
className: (0, _classnames.default)(
'iui-message',
contentProps?.className,
),
},
content,
),
link &&
_react.createElement(
_index.ButtonBase,
{
...link,
className: (0, _classnames.default)(
'iui-anchor',
'iui-toast-anchor',
link.className,
),
title: void 0,
'data-iui-status': category,
'data-iui-underline': true,
},
link.title,
),
('persisting' === type || hasCloseButton) &&
_react.createElement(
_IconButton.IconButton,
{
size: 'small',
styleType: 'borderless',
onClick: onClose,
'aria-label': 'Close',
},
_react.createElement(_index.SvgCloseSmall, null),
),
);
});
const useAnimateToastBasedOnVisibility = (isVisible, args) => {
let { thisElement, animateOutTo, onRemove } = args;
let [shouldBeMounted, setShouldBeMounted] = _react.useState(isVisible);
let motionOk = (0, _index.useMediaQuery)(
'(prefers-reduced-motion: no-preference)',
);
let onRemoveRef = (0, _index.useLatestRef)(onRemove);
let [prevIsVisible, setPrevIsVisible] = _react.useState(void 0);
_react.useEffect(() => {
if (prevIsVisible !== isVisible) {
setPrevIsVisible(isVisible);
if (isVisible) safeAnimateIn();
else safeAnimateOut();
}
function calculateOutAnimation(node) {
let translateX = 0;
let translateY = 0;
if (animateOutTo && node) {
let { x: startX, y: startY } = node.getBoundingClientRect();
let { x: endX, y: endY } = animateOutTo.getBoundingClientRect();
translateX = endX - startX;
translateY = endY - startY;
}
return {
translateX,
translateY,
};
}
function safeAnimateIn() {
setShouldBeMounted(true);
queueMicrotask(() => {
animateIn();
});
}
function safeAnimateOut() {
if (motionOk) {
let animation = animateOut();
animation?.addEventListener('finish', () => {
setShouldBeMounted(false);
onRemoveRef.current?.();
});
} else {
setShouldBeMounted(false);
onRemoveRef.current?.();
}
}
function animateIn() {
if (!motionOk) return;
thisElement.current?.animate?.(
[
{
transform: 'translateY(15%)',
},
{
transform: 'translateY(0)',
},
],
{
duration: 240,
fill: 'forwards',
},
);
}
function animateOut() {
if (null == thisElement.current || !motionOk) return;
let { translateX, translateY } = calculateOutAnimation(
thisElement.current,
);
let animationDuration = animateOutTo ? 400 : 120;
let animation = thisElement.current?.animate?.(
[
{
transform: animateOutTo
? `scale(0.9) translate(${translateX}px,${translateY}px)`
: 'scale(0.9)',
opacity: 0,
transitionDuration: `${animationDuration}ms`,
transitionTimingFunction: 'cubic-bezier(0.4, 0, 1, 1)',
},
],
{
duration: animationDuration,
iterations: 1,
fill: 'forwards',
},
);
return animation;
}
}, [
isVisible,
prevIsVisible,
animateOutTo,
motionOk,
thisElement,
setShouldBeMounted,
onRemoveRef,
]);
return shouldBeMounted;
};