// // 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, memo } from 'react'; import { type Density, type Elevation } from '@dxos/react-ui-types'; import { useDensityContext, useElevationContext, useThemeContext } from '../../hooks'; import { type ThemedClassName } from '../../util'; interface ButtonProps extends ThemedClassName> { variant?: 'default' | 'primary' | 'outline' | 'ghost' | 'destructive'; density?: Density; elevation?: Elevation; asChild?: boolean; } type ButtonGroupContextValue = { inGroup?: boolean }; const BUTTON_GROUP_NAME = 'ButtonGroup'; const BUTTON_NAME = 'Button'; const [ButtonGroupProvider, useButtonGroupContext] = createContext(BUTTON_GROUP_NAME, { inGroup: false, }); const Button = memo( forwardRef( ( { classNames, children, density: propsDensity, elevation: propsElevation, variant = 'default', asChild, ...props }, ref, ) => { const { inGroup } = useButtonGroupContext(BUTTON_NAME); const { tx } = useThemeContext(); const elevation = useElevationContext(propsElevation); const density = useDensityContext(propsDensity); const Root = asChild ? Slot : Primitive.button; return ( {children} ); }, ), ); Button.displayName = BUTTON_NAME; type ButtonGroupProps = ThemedClassName> & { elevation?: Elevation; asChild?: boolean; }; const ButtonGroup = forwardRef( ({ children, elevation: propsElevation, classNames, asChild, ...props }, forwardedRef) => { const { tx } = useThemeContext(); const elevation = useElevationContext(propsElevation); const Root = asChild ? Slot : Primitive.div; return ( {children} ); }, ); ButtonGroup.displayName = BUTTON_GROUP_NAME; export { Button, ButtonGroup, BUTTON_GROUP_NAME, useButtonGroupContext }; export type { ButtonProps, ButtonGroupProps };