shelving
Version:
Toolkit for using data in JavaScript.
38 lines (37 loc) • 2.03 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useInstance } from "../../react/useInstance.js";
import { useStore } from "../../react/useStore.js";
import { PayloadFetchStore } from "../../store/PayloadFetchStore.js";
import { NONE, SECOND } from "../../util/constants.js";
import { formatValue } from "../../util/format.js";
import { ErrorNotice } from "../misc/Catcher.js";
import { LOADING_NOTICE, Notice } from "../notice/Notice.js";
import { ArrayRadioInputs } from "./ArrayRadioInputs.js";
import { Popover } from "./Popover.js";
import { SchemaInput } from "./SchemaInput.js";
/**
* Combo box with query input.
* - Show an input based on a `schema` of type `I`
* - Values from the input are piped to an `onQuery()` callback.
* - Show a `<Popover>` that has a radio list of items to allow a final option of type `O` to be picked.
* - Errors / loading state / empty state are handled automatically.
*/
export function QueryInput({ empty = "No results", value, onValue, onQuery, formatter = formatValue, ...props }) {
const store = useStore(useInstance(PayloadFetchStore, NONE, undefined, onQuery, SECOND));
const busy = useStore(store.busy).value;
// Is popover open?
const isOpen = busy || !!store.reason || !!store.value;
const close = () => {
store.payload.value = NONE;
store.value = undefined;
};
return (_jsxs(Popover, { open: isOpen, onClose: close, children: [_jsx(SchemaInput, { ...props, value: value, onValue: v => {
if (v)
store.payload.value = v;
else
close();
} }), busy ? (LOADING_NOTICE) : store.reason ? (_jsx(ErrorNotice, { reason: store.reason })) : store.value?.length ? (_jsx(ArrayRadioInputs, { items: store.value, onValue: v => {
onValue(v); // Set the value.
close();
}, formatter: formatter, ...props })) : empty ? (_jsx(Notice, { children: empty })) : null] }));
}