// // Copyright 2022 DXOS.org // import { createContext } from '@radix-ui/react-context'; import { Primitive } from '@radix-ui/react-primitive'; import { Slot } from '@radix-ui/react-slot'; import React, { type ComponentPropsWithRef, forwardRef } from 'react'; import { useId } from '@dxos/react-hooks'; import { type MessageValence, type Elevation } from '@dxos/react-ui-types'; import { useElevationContext, useThemeContext } from '../../hooks'; import { type ThemedClassName } from '../../util'; import { Icon } from '../Icon'; const messageIcons: Record = { success: 'ph--check-circle--duotone', info: 'ph--info--duotone', warning: 'ph--warning--duotone', error: 'ph--warning-circle--duotone', neutral: 'ph--info--duotone', }; type MessageRootProps = ThemedClassName> & { valence?: MessageValence; elevation?: Elevation; asChild?: boolean; titleId?: string; descriptionId?: string; }; type MessageContextValue = { titleId?: string; descriptionId: string; valence: MessageValence }; const MESSAGE_NAME = 'Message'; const [MessageProvider, useMessageContext] = createContext(MESSAGE_NAME); const MessageRoot = forwardRef( ( { asChild, valence = 'neutral', elevation: propsElevation, classNames, titleId: propsTitleId, descriptionId: propsDescriptionId, children, ...props }, forwardedRef, ) => { const { tx } = useThemeContext(); const titleId = useId('message__title', propsTitleId); const descriptionId = useId('message__description', propsDescriptionId); const elevation = useElevationContext(propsElevation); const Root = asChild ? Slot : Primitive.div; return ( {children} ); }, ); MessageRoot.displayName = MESSAGE_NAME; type MessageTitleProps = Omit>, 'id'> & { asChild?: boolean; icon?: string; }; const MESSAGE_TITLE_NAME = 'MessageTitle'; const MessageTitle = forwardRef( ({ asChild, classNames, children, icon, ...props }, forwardedRef) => { const { tx } = useThemeContext(); const { titleId, valence } = useMessageContext(MESSAGE_TITLE_NAME); const Root = asChild ? Slot : Primitive.h2; return ( {!icon && valence === 'neutral' ? null : ( )} {children} ); }, ); MessageTitle.displayName = MESSAGE_TITLE_NAME; type MessageContentProps = Omit>, 'id'> & { asChild?: boolean; }; const MESSAGE_BODY_NAME = 'MessageContent'; const MessageContent = forwardRef( ({ asChild, classNames, children, ...props }, forwardedRef) => { const { tx } = useThemeContext(); const { descriptionId } = useMessageContext(MESSAGE_BODY_NAME); const Root = asChild ? Slot : Primitive.p; return ( {children} ); }, ); MessageContent.displayName = MESSAGE_BODY_NAME; export const Message = { Root: MessageRoot, Title: MessageTitle, Content: MessageContent }; export const Callout = Message; export type { MessageRootProps, MessageTitleProps, MessageContentProps }; export { messageIcons };