import type { JSX } from "@solidjs/web"; import { createMemo } from "solid-js"; import { stringifyAsLabel } from "../internals/resolve-value-label"; import { useComboboxRootContext } from "../root/combobox-root-context"; export interface ComboboxValueProps { /** * Render function receiving `{ value }` (the raw selected value), or * static JSX that overrides the default stringification. */ children?: ((args: { value: Value }) => JSX.Element) | JSX.Element; /** * Placeholder content displayed when no value is selected. Overridden * by `children` when supplied. */ placeholder?: JSX.Element; } /** * Displays the stringified selected value. When a render-function child * is supplied, it's called with the current selected value and may return * custom JSX (e.g. for badge / icon rendering). * * Doesn't render its own HTML element. */ export function ComboboxValue( props: ComboboxValueProps, ): JSX.Element { const root = useComboboxRootContext(); const resolved = createMemo(() => { const sv = root.selectedValue(); const child = props.children; if (typeof child === "function") { // `selectedValue()` is `unknown` at runtime; the `Value` generic is a // typed convenience for callers, so cast at this boundary. return (child as (args: { value: Value }) => JSX.Element)({ value: sv as Value, }); } if (child != null) return child as JSX.Element; // No selected value → placeholder wins when supplied. const hasValue = Array.isArray(sv) ? sv.length > 0 : sv != null; if (!hasValue && props.placeholder != null) { return props.placeholder; } const itv = root.itemToStringLabel() as | ((item: unknown) => string) | undefined; if (Array.isArray(sv)) { return sv.map((v) => stringifyAsLabel(v, itv)).join(", ") as JSX.Element; } return stringifyAsLabel(sv, itv) as JSX.Element; }); return <>{resolved()}; }