/** * Copyright (c) Paymium. * * This source code is licensed under the MIT license found in the * LICENSE file in the root of this projects source tree. */ 'use client'; import { withStaticProperties } from '@crossed/core'; import { Text, type TextProps } from '../typography/Text'; import { Button, type ButtonTextProps, type ButtonProps, } from '../buttons/Button'; import { composeStyles, createStyles, CrossedMethods, useTheme, } from '@crossed/styled'; import { createContext, useContext } from 'react'; import { AlertTriangle, CheckCircle, Info, XCircle } from '@crossed/unicons'; import { Box } from '../layout/Box'; import { YBox, type YBoxProps } from '../layout/YBox'; import { match } from 'ts-pattern'; import { useMedia } from '../useMedia'; const titleStyle = createStyles((t) => ({ default: { base: { fontWeight: '600' } }, error: { base: { color: t.components.Banner.error.title } }, success: { base: { color: t.components.Banner.success.title } }, warning: { base: { color: t.components.Banner.warning.title } }, info: { base: { color: t.components.Banner.info.title } }, })); const descriptionStyle = createStyles((t) => ({ default: { base: { flex: 1 } }, error: { base: { color: t.components.Banner.error.subtitle } }, success: { base: { color: t.components.Banner.success.subtitle } }, warning: { base: { color: t.components.Banner.warning.subtitle } }, info: { base: { color: t.components.Banner.info.subtitle } }, })); const bannerStyles = createStyles( (t) => ({ icon: { base: { fontWeight: '600' }, variants: { status: { error: { base: { color: t.components.Banner.error.icon } }, success: { base: { color: t.components.Banner.success.icon } }, warning: { base: { color: t.components.Banner.warning.icon } }, info: { base: { color: t.components.Banner.info.icon } }, }, }, }, containerTitle: { base: { flexDirection: 'row', alignItems: 'center' }, }, containerIcon: { base: { borderRadius: 32, width: 32, height: 32 }, variants: {}, }, action: { media: { xs: { alignSelf: 'flex-end' }, md: { alignSelf: 'auto' } }, }, container: { base: { paddingLeft: t.space.xl, paddingRight: t.space.xl, paddingTop: t.space.xl, paddingBottom: t.space.xl, borderRadius: 8, borderWidth: 1, borderStyle: 'solid', }, variants: {}, media: { xs: { paddingVertical: t.space.md, paddingHorizontal: t.space.xl, }, md: { flexDirection: 'row', alignItems: 'center', paddingVertical: t.space.xl, paddingHorizontal: t.space['3xl'], }, }, }, }) as const ); const containerStyles = createStyles((t) => ({ error: { base: { borderColor: t.components.Banner.error.border, backgroundColor: t.components.Banner.error.background, }, }, success: { base: { borderColor: t.components.Banner.success.border, backgroundColor: t.components.Banner.success.background, }, }, warning: { base: { borderColor: t.components.Banner.warning.border, backgroundColor: t.components.Banner.warning.background, }, }, info: { base: { borderColor: t.components.Banner.info.border, backgroundColor: t.components.Banner.info.background, }, }, })); const containerIconStyles = createStyles((t) => ({ error: { base: { backgroundColor: t.components.Banner.error.backgroundIcon, }, }, success: { base: { backgroundColor: t.components.Banner.success.backgroundIcon, }, }, warning: { base: { backgroundColor: t.components.Banner.warning.backgroundIcon, }, }, info: { base: { backgroundColor: t.components.Banner.info.backgroundIcon, }, }, })); export type BannerProps = YBoxProps & { status?: keyof typeof containerStyles }; export const bannerContext = createContext>({}); const Container = ({ status = 'info', children, style, ...props }: BannerProps) => { const { md } = useMedia(); return ( {children} ); }; Container.displayName = 'Banner'; const BannerIcon = ({ style, }: { /** * Style of container Box */ style?: CrossedMethods; }) => { const { status } = useContext(bannerContext); const theme = useTheme(); const color = theme.components.Banner[status].icon; const Comp = match(status) .with('error', () => XCircle) .with('info', () => Info) .with('success', () => CheckCircle) .with('warning', () => AlertTriangle) .exhaustive(); return ( ); }; BannerIcon.displayName = 'Banner.Icon'; const BannerTitle = ({ style, ...props }: TextProps) => { const { status } = useContext(bannerContext); return ( ); }; BannerTitle.displayName = 'Banner.Title'; const BannerDescription = (props: TextProps) => { const { status } = useContext(bannerContext); return ( ); }; BannerDescription.displayName = 'Banner.Description'; const BannerAction = (props: ButtonProps) => { return (