@furystack/shades-common-components
Version:
153 lines • 7.03 kB
JavaScript
import { Shade, attachProps, createComponent } from '@furystack/shades';
import { ThemeProviderService } from '../services/theme-provider-service.js';
import { promisifyAnimation } from '../utils/promisify-animation.js';
const getBackground = (buttonProps, theme) => buttonProps.variant === 'contained'
? buttonProps.color
? buttonProps.disabled
? theme.palette[buttonProps.color].dark
: theme.palette[buttonProps.color].main
: buttonProps.disabled
? theme.button.disabledBackground
: theme.text.primary
: 'rgba(0,0,0,0)';
const getHoveredBackground = (buttonProps, theme, fallback) => buttonProps.variant === 'contained'
? buttonProps.color
? theme.palette[buttonProps.color].dark
: buttonProps.disabled
? theme.button.disabledBackground
: theme.text.secondary
: fallback();
const getBoxShadow = (buttonProps, theme) => buttonProps.variant === 'outlined'
? buttonProps.color
? `0px 0px 0px 1px ${buttonProps.disabled ? theme.palette[buttonProps.color].dark : theme.palette[buttonProps.color].main}`
: `0px 0px 0px 1px ${buttonProps.disabled ? theme.button.disabledBackground : theme.text.secondary}`
: 'none';
const getHoveredBoxShadow = (buttonProps, theme) => buttonProps.variant === 'outlined'
? buttonProps.color
? `0px 0px 0px 1px ${buttonProps.disabled ? theme.button.disabledBackground : theme.palette[buttonProps.color].light}`
: `0px 0px 0px 1px ${buttonProps.disabled ? theme.button.disabledBackground : theme.text.primary}`
: 'none';
const getTextColor = (buttonProps, theme, fallback) => buttonProps.variant !== 'contained'
? buttonProps.color
? buttonProps.disabled
? theme.palette[buttonProps.color].dark
: theme.palette[buttonProps.color].main
: theme.text.secondary
: fallback();
const getHoveredTextColor = (buttonProps, theme, fallback) => buttonProps.variant !== 'contained'
? buttonProps.color
? buttonProps.disabled
? theme.palette[buttonProps.color].dark
: theme.palette[buttonProps.color].light
: theme.text.primary
: fallback();
export const Button = Shade({
shadowDomName: 'shade-button',
elementBase: HTMLButtonElement,
elementBaseName: 'button',
constructed: ({ element }) => {
/**
* @param this The Document instance
* @param ev The Mouse event
*/
function mouseUp(ev) {
if (ev.target === element) {
void promisifyAnimation(element, [
{
filter: 'drop-shadow(1px 1px 10px rgba(0,0,0,.5))brightness(1)',
transform: 'scale(1)',
},
], { duration: 350, fill: 'forwards', easing: 'cubic-bezier(0.230, 1.000, 0.320, 1.000)' });
}
}
document.addEventListener('mouseup', mouseUp);
return () => {
document.removeEventListener('mouseup', mouseUp);
};
},
render: ({ props, children, injector, element, useDisposable }) => {
const mouseDownHandler = props.onmousedown;
const mouseUpHandler = props.onmouseup;
const themeProvider = injector.getInstance(ThemeProviderService);
const { theme } = themeProvider;
const background = getBackground(props, theme);
if (props.variant === 'contained') {
useDisposable('themeChanged', () => themeProvider.subscribe('themeChanged', () => {
const el = element;
el.style.color = getTextColor(props, themeProvider.theme, () => themeProvider.getTextColor(el.style.background || el.style.backgroundColor));
}));
}
const hoveredBackground = getHoveredBackground(props, theme, () => {
const { r, g, b } = themeProvider.getRgbFromColorString((props.color && theme.palette[props.color].main) || theme.text.primary);
return `rgba(${r}, ${g}, ${b}, 0.1)`;
});
const boxShadow = getBoxShadow(props, theme);
const hoveredBoxShadow = getHoveredBoxShadow(props, theme);
const getTextColorInner = () => getTextColor(props, theme, () => themeProvider.getTextColor(background));
const getHoveredTextColorInner = () => getHoveredTextColor(props, theme, () => themeProvider.getTextColor(background));
const tryAnimate = async (keyframes, options) => {
const el = element;
if (element) {
void promisifyAnimation(el, keyframes, options);
}
};
attachProps(element, {
...props,
onmousedown(ev) {
mouseDownHandler?.call(this, ev);
void tryAnimate([
{
filter: 'drop-shadow(-1px -1px 3px black)brightness(0.5)',
transform: 'scale(0.98)',
},
], { duration: 150, fill: 'forwards', easing: 'cubic-bezier(0.230, 1.000, 0.320, 1.000)' });
},
onmouseup(ev) {
mouseUpHandler?.call(this, ev);
},
onmouseenter: () => {
void tryAnimate([
{
background,
boxShadow,
color: getTextColorInner(),
},
{
background: hoveredBackground,
boxShadow: hoveredBoxShadow,
color: getHoveredTextColorInner(),
},
], { duration: 500, fill: 'forwards', easing: 'cubic-bezier(0.215, 0.610, 0.355, 1.000)' });
},
onmouseout: () => {
void tryAnimate([
{ background: hoveredBackground, boxShadow: hoveredBoxShadow, color: getHoveredTextColorInner() },
{ background, boxShadow, color: getTextColorInner() },
], {
duration: 500,
fill: 'forwards',
easing: 'cubic-bezier(0.215, 0.610, 0.355, 1.000)',
});
},
...props,
style: {
display: 'inline-flex',
cursor: props.disabled ? 'not-allowed' : 'pointer',
background,
boxShadow,
margin: '8px',
padding: '6px 16px',
border: 'none',
borderRadius: '4px',
textTransform: 'uppercase',
color: getTextColorInner(),
filter: 'drop-shadow(1px 1px 10px rgba(0,0,0,.5))',
backdropFilter: props.variant === 'outlined' ? 'blur(35px)' : undefined,
userSelect: 'none',
...props.style,
},
});
return createComponent(createComponent, null, children);
},
});
//# sourceMappingURL=button.js.map