/** * 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. */ import { GetProps, useUncontrolled, withStaticProperties } from '@crossed/core'; import { useMemo, type ComponentType, useId, useState } from 'react'; import { createSelectMain } from './Select'; import { createSelectTrigger } from './SelectTrigger'; import { createSelectContent } from './SelectContent'; import { createSelectPortal } from './SelectPortal'; import { Provider } from './context'; import { createSelectItem } from './SelectItem'; import { createSelectDivider } from './SelectDivider'; import { createSelectLabel } from './SelectLabel'; export { Provider as ProviderSelect, useContext as useSelectContext, } from './context'; type Arg> = { context?: Context; }; export const createSelect = < SelectProps extends Record, TriggerProps extends Record, ContentProps extends Record, PortalProps extends Record, ItemProps extends Record, DividerProps extends Record, LabelProps extends Record, C extends Record, >( components: { Root: ComponentType; Trigger: ComponentType; Content: ComponentType; Portal: ComponentType; Item: ComponentType; Divider: ComponentType; Label: ComponentType; }, { context }: Arg = {} ) => { const { Root, Trigger, Content, Portal, Item, Divider, Label } = components; const Select = createSelectMain(Root); const SelectTrigger = createSelectTrigger(Trigger); const SelectContent = createSelectContent(Content); const SelectPortal = createSelectPortal(Portal); const SelectItem = createSelectItem(Item); const SelectDivider = createSelectDivider(Divider); const SelectLabel = createSelectLabel(Label); Select.displayName = 'Select'; SelectTrigger.displayName = 'Select.Trigger'; SelectContent.displayName = 'Select.Content'; SelectPortal.displayName = 'Select.Portal'; SelectItem.displayName = 'Select.Item'; SelectDivider.displayName = 'Select.Divider'; SelectLabel.displayName = 'Select.Label'; return withStaticProperties( ( props: GetProps & { value?: string; defaultValue?: string; onChange?: (_p: string) => void; } ) => { const id = useId(); const { value: valueProps, defaultValue = false, onChange, ...otherProps } = props; const [open, setOpen] = useState(false); const [value, setVBalue] = useUncontrolled({ value: valueProps, defaultValue, onChange, }); const contextProps = useMemo(() => { return Object.entries(context || {}).reduce( (acc, [key]) => { if ((props as any)[key]) { (acc as any)[key] = (props as any)[key]; } return acc; }, context || ({} as C) ); }, [props]); return (