enviroment-adviser
Version:
A permanent toast that notifies you that you are not in production
114 lines (113 loc) • 4.41 kB
JavaScript
const css = `
#environment-adviser {
background-color: #ff0000;
color: white;
padding: 10px 20px;
border-radius: 5px;
font-family: sans-serif;
font-weight: bold;
cursor: pointer;
z-index: 9999;
}
`;
function addStyles() {
const styleSheet = document.createElement('style');
styleSheet.type = 'text/css';
styleSheet.innerText = css;
document.head.appendChild(styleSheet);
}
export function showEnvironmentAdviser(options) {
if (process.env.NODE_ENV === 'production') {
return;
}
const scale = options?.scale ?? 1;
const opacity = options?.opacity ?? 1;
const animation = options?.animation ?? 'none';
const speedMultiplier = options?.transitionSpeed ?? 1;
const duration = 1 / speedMultiplier;
const adviser = document.createElement('div');
adviser.id = 'environment-adviser';
adviser.textContent = `ENVIRONMENT: ${process.env.NODE_ENV}`;
adviser.style.position = 'fixed';
adviser.style.backgroundColor = '#ff0000';
adviser.style.color = 'white';
adviser.style.padding = `${0.625 * scale}rem ${1.25 * scale}rem`;
adviser.style.borderRadius = `${0.3125 * scale}rem`;
adviser.style.fontFamily = 'sans-serif';
adviser.style.fontWeight = 'bold';
adviser.style.fontSize = `${1 * scale}rem`;
adviser.style.cursor = 'pointer';
adviser.style.zIndex = '9999';
adviser.style.opacity = opacity.toString();
const styleSheet = document.createElement('style');
styleSheet.innerHTML = `
@keyframes adviser-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.adviser-spin { animation: adviser-spin ${duration}s linear; }
@keyframes adviser-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.2); } }
.adviser-pulse { animation: adviser-pulse ${duration}s ease-in-out; }
`;
document.head.appendChild(styleSheet);
document.body.appendChild(adviser);
const corners = ['top-right', 'bottom-right', 'bottom-left', 'top-left'];
let currentCornerIndex = 0;
let isMoving = false;
const setPosition = (cornerName) => {
const offsetRem = 1.25 * scale;
const { offsetHeight: elHeight, offsetWidth: elWidth } = adviser;
adviser.style.right = '';
adviser.style.bottom = '';
adviser.style.top = '';
adviser.style.left = '';
switch (cornerName) {
case 'top-right':
adviser.style.top = `${offsetRem}rem`;
adviser.style.left = `calc(100vw - ${elWidth}px - ${offsetRem}rem)`;
break;
case 'bottom-right':
adviser.style.top = `calc(100vh - ${elHeight}px - ${offsetRem}rem)`;
adviser.style.left = `calc(100vw - ${elWidth}px - ${offsetRem}rem)`;
break;
case 'bottom-left':
adviser.style.top = `calc(100vh - ${elHeight}px - ${offsetRem}rem)`;
adviser.style.left = `${offsetRem}rem`;
break;
case 'top-left':
adviser.style.top = `${offsetRem}rem`;
adviser.style.left = `${offsetRem}rem`;
break;
}
};
const moveAdviser = () => {
if (isMoving)
return;
isMoving = true;
currentCornerIndex = (currentCornerIndex + 1) % corners.length;
const nextCorner = corners[currentCornerIndex];
if (animation === 'slide') {
adviser.style.transition = `top ${duration}s linear, left ${duration}s linear`;
}
else {
adviser.style.transition = `all ${duration}s ease-in-out`;
}
if (animation === 'spin' || animation === 'pulse') {
adviser.classList.add(`adviser-${animation}`);
}
setPosition(nextCorner);
setTimeout(() => {
isMoving = false;
if (animation === 'spin' || animation === 'pulse') {
adviser.classList.remove(`adviser-${animation}`);
}
}, duration * 1000);
};
setTimeout(() => {
adviser.style.transition = 'none';
setPosition(corners[currentCornerIndex]);
}, 50);
window.addEventListener('resize', () => {
adviser.style.transition = 'none';
setPosition(corners[currentCornerIndex]);
});
adviser.addEventListener('mouseenter', moveAdviser);
adviser.addEventListener('click', moveAdviser);
}