'use client'; import clsx from 'clsx'; import { useCallback } from 'react'; import { Button, type Key, ListBox, ListBoxItem, type ListBoxItemProps, Popover, type PopoverProps, Select, type SelectProps, SelectValue, } from 'react-aria-components'; import { useStore } from 'zustand'; import { getOrCreateStoreByKey } from './getOrCreateStoreByKey'; export type OpenAPISelectItem = { key: Key; label: string | React.ReactNode; }; interface OpenAPISelectProps extends Omit, 'children'> { items: T[]; children: React.ReactNode | ((item: T) => React.ReactNode); placement?: PopoverProps['placement']; stateKey?: string; /** * Icon to display in the select button. */ icon?: React.ReactNode; } export function useSelectState(stateKey = 'select-state', initialKey?: Key) { const store = useStore(getOrCreateStoreByKey(stateKey, initialKey)); return { key: store.key, setKey: useCallback((key: Key | null) => store.setKey(key), [store.setKey]), }; } export function OpenAPISelect(props: OpenAPISelectProps) { const { icon = '▼', items, children, className, placement, stateKey, selectedKey, onSelectionChange, } = props; const state = useSelectState(stateKey, items[0]?.key); const selected = items.find((item) => item.key === state.key) || items[0]; return ( ); } export function OpenAPISelectItem(props: ListBoxItemProps) { return ( clsx('openapi-select-item', { 'openapi-select-item-focused': isFocused, 'openapi-select-item-selected': isSelected, }) } /> ); }