/** @jsxRuntime classic */
/** @jsx jsx */
import { type ElementType, type ReactNode, createContext, useContext } from 'react'
import { jsx, forwardRefWithAs, useTheme } from '@keystone-ui/core'
// todo - these also exist at ../../types
export type SizeType = 'small' | 'medium'
export type ShapeType = 'square' | 'round'
/**
* What is this thing?
* ------------------------------
* We expose primitive components for adorning inputs with icons and buttons.
* There's some awkard requirements surrounding size and shape that's best to
* consolidate in one place.
*/
const AdornmentContext = createContext<{ shape: ShapeType, size: SizeType }>({
shape: 'square',
size: 'medium',
})
const useAdornmentContext = () => useContext(AdornmentContext)
// Adornment Wrapper
// ------------------------------
export type AdornmentWrapperProps = {
children: ReactNode
shape: ShapeType
size: SizeType
}
export const AdornmentWrapper = ({ children, shape, size }: AdornmentWrapperProps) => {
return (
{children}
)
}
// Adornment Element
// ------------------------------
const alignmentPaddingMap = {
left: 'marginLeft',
right: 'marginRight',
}
type AdornmentProps = {
align: 'left' | 'right'
as?: ElementType
}
export const Adornment = forwardRefWithAs<'div', AdornmentProps>(
({ align, as: Tag = 'div', ...props }, ref) => {
const { shape, size } = useAdornmentContext()
const { controlSizes } = useTheme()
const { indicatorBoxSize, paddingX } = controlSizes[size]
// optical alignment shifts towards the middle of the container with the large
// border radius on "round" inputs. use padding rather than margin to optimise
// the hit-area of interactive elements
const offsetStyles =
shape === 'round'
? {
[alignmentPaddingMap[align]]: paddingX / 4,
}
: null
return (
)
}
)