@furystack/shades-common-components
Version:
Common UI components for FuryStack Shades
99 lines • 4.12 kB
JavaScript
import { Shade, createComponent } from '@furystack/shades';
import { cssVariableTheme } from '../services/css-variable-theme.js';
import { paletteMainColors } from '../services/palette-css-vars.js';
import { Icon } from './icons/icon.js';
import { Typography } from './typography.js';
import { checkCircle, errorCircle, forbidden, info as infoIcon, searchOff, serverError, warning as warningIcon, } from './icons/icon-definitions.js';
const statusColorMap = {
success: paletteMainColors.success.main,
error: paletteMainColors.error.main,
warning: paletteMainColors.warning.main,
info: paletteMainColors.info.main,
'403': paletteMainColors.warning.main,
'404': paletteMainColors.info.main,
'500': paletteMainColors.error.main,
};
const defaultIconDefs = {
success: checkCircle,
error: errorCircle,
warning: warningIcon,
info: infoIcon,
'403': forbidden,
'404': searchOff,
'500': serverError,
};
const getDefaultIcon = (status) => createComponent(Icon, { icon: defaultIconDefs[status], size: 64 });
const defaultTitles = {
success: 'Success',
error: 'Error',
warning: 'Warning',
info: 'Information',
'403': '403 - Forbidden',
'404': '404 - Not Found',
'500': '500 - Internal Server Error',
};
/**
* Result component for displaying operation outcomes, status pages, and feedback.
* Supports success, error, warning, info statuses and common HTTP error codes (403, 404, 500).
*/
export const Result = Shade({
customElementName: 'shade-result',
css: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
textAlign: 'center',
padding: `${cssVariableTheme.spacing.xl} ${cssVariableTheme.spacing.lg}`,
fontFamily: cssVariableTheme.typography.fontFamily,
boxSizing: 'border-box',
// ==========================================
// ICON
// ==========================================
'& .result-icon': {
fontSize: '64px',
lineHeight: '1',
marginBottom: cssVariableTheme.spacing.lg,
color: 'var(--result-status-color)',
},
// ==========================================
// TITLE
// ==========================================
'& .result-title': {
marginBottom: cssVariableTheme.spacing.sm,
},
'& .result-subtitle': {
marginBottom: cssVariableTheme.spacing.lg,
maxWidth: '480px',
},
// ==========================================
// EXTRA (actions area)
// ==========================================
'& .result-extra': {
display: 'flex',
gap: cssVariableTheme.spacing.md,
marginTop: cssVariableTheme.spacing.md,
flexWrap: 'wrap',
justifyContent: 'center',
},
},
render: ({ props, children, useHostProps }) => {
const { status, title, subtitle, icon, style } = props;
const displayIcon = icon ?? getDefaultIcon(status);
const statusColor = statusColorMap[status];
useHostProps({
'data-status': status,
style: {
'--result-status-color': statusColor,
...style,
},
});
const hasChildren = children && (Array.isArray(children) ? children.length > 0 : true);
return (createComponent(createComponent, null,
createComponent("span", { className: "result-icon", role: "img" }, displayIcon),
createComponent(Typography, { variant: "h5", className: "result-title", style: { margin: '0' } }, title),
subtitle ? (createComponent(Typography, { variant: "body2", color: "textSecondary", className: "result-subtitle", style: { margin: '0' } }, subtitle)) : null,
hasChildren ? createComponent("div", { className: "result-extra" }, children) : null));
},
});
export { getDefaultIcon as resultGetDefaultIcon, defaultIconDefs as resultDefaultIconDefs, defaultTitles as resultDefaultTitles, };
//# sourceMappingURL=result.js.map