@crossed/ui
Version:
A universal & performant styling library for React Native, Next.js & React
152 lines (151 loc) • 4.62 kB
JavaScript
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import {
forwardRef,
memo,
useCallback,
useEffect,
useMemo,
useRef,
useState
} from "react";
import { Floating } from "../../overlay/Floating";
import {
SelectConfigProvider,
SelectValueProvider,
useSelectConfig,
useSelectValue
} from "./context";
import {
composeStyles,
createStyles,
inlineStyle,
useTheme
} from "@crossed/styled";
import { FadeIn, FadeOut } from "react-native-reanimated";
import { MenuList } from "../../display";
import { form } from "../../styles/form";
import { Input } from "../Input";
import Fuse from "fuse.js";
import { useSelect } from "./styles";
import { Focus } from "./Focus";
import { useFloatingContext } from "../../overlay/Floating/context";
import { Sheet } from "../../overlay/Sheet";
import { Spinner } from "../../display/Spinner";
import { gapStyles } from "../../styles";
import { List } from "./List";
const duration = 100;
const styles = createStyles(() => ({ dynamic: (e) => e }));
const SelectContent = memo(
forwardRef(({ floatingStyles, onSearch, loading }, ref) => {
useTheme();
const { onClose, open } = useFloatingContext();
const selectValue = useSelectValue();
const { items } = selectValue;
const configContext = useSelectConfig();
const { searchable, showSheet } = configContext;
const [search, setSearch] = useState("");
const handleChangeSearch = useCallback(
(value) => {
setSearch(value);
if (onSearch)
onSearch(value);
},
[onSearch, setSearch]
);
const fuse = useMemo(
() => new Fuse(items, {
keys: ["search", "value"]
}),
[items]
);
const data = useMemo(() => {
return search && !onSearch ? fuse.search(search).map(({ item }) => item) : items;
}, [fuse, search, items, onSearch]);
useEffect(() => {
var _a, _b;
if (!open) {
(_a = totoRef.current) == null ? void 0 : _a.hide();
setSearch("");
} else {
(_b = totoRef.current) == null ? void 0 : _b.show();
}
}, [open]);
const renderSearch = searchable ? /* @__PURE__ */ jsx(
Input,
{
formFieldStyle: inlineStyle(({ space }) => ({
base: {
flexGrow: 0,
marginTop: space.xxs,
marginHorizontal: space.xs
}
})),
value: search,
onChangeText: handleChangeSearch,
clearable: true,
autoFocus: true
}
) : null;
const totoRef = useRef();
return /* @__PURE__ */ jsx(Fragment, { children: showSheet ? /* @__PURE__ */ jsx(
Sheet.Content,
{
ref: totoRef,
onClose,
containerStyle: composeStyles(
searchable && inlineStyle(() => ({
base: { height: "100%" }
}))
),
children: /* @__PURE__ */ jsxs(Sheet.Padded, { testID: "content-select", children: [
/* @__PURE__ */ jsx(MenuList.Item, { children: renderSearch }),
loading ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(List, { data })
] })
}
) : /* @__PURE__ */ jsx(Floating.Portal, { children: /* @__PURE__ */ jsx(
Focus,
{
onEscapeKey: onClose,
onClickOutside: onClose,
enabled: open,
children: /* @__PURE__ */ jsx(
Floating.Content,
{
exiting: FadeOut.duration(duration),
entering: FadeIn.duration(duration),
style: composeStyles(
inlineStyle(({ boxShadow }) => ({
base: { zIndex: 100 },
web: { base: { boxShadow } }
}))
),
children: /* @__PURE__ */ jsx(SelectConfigProvider, { ...configContext, children: /* @__PURE__ */ jsx(SelectValueProvider, { ...selectValue, children: /* @__PURE__ */ jsxs(
MenuList,
{
testID: "content-select",
ref,
style: composeStyles(
form.input,
useSelect.content,
gapStyles.xs,
inlineStyle(() => ({
web: { base: { overflowY: "auto" } }
})),
styles.dynamic(floatingStyles)
),
children: [
renderSearch,
loading ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(List, { data })
]
}
) }) })
}
)
}
) }) });
})
);
export {
SelectContent
};
//# sourceMappingURL=Content.js.map