@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
115 lines (114 loc) • 4.45 kB
JavaScript
"use client";
import { createEventHandler } from "../../../core/utils/create-event-handler/create-event-handler.mjs";
import { useProps } from "../../../core/MantineProvider/use-props/use-props.mjs";
import { factory } from "../../../core/factory/factory.mjs";
import { Input } from "../../Input/Input.mjs";
import { useMenuContext } from "../Menu.context.mjs";
import Menu_module_default from "../Menu.module.mjs";
import { useEffect, useRef } from "react";
import { useMergedRef } from "@mantine/hooks";
import { jsx } from "react/jsx-runtime";
//#region packages/@mantine/core/src/components/Menu/MenuSearch/MenuSearch.tsx
const ITEM_SELECTOR = "[data-menu-item]:not([data-disabled])";
const ACTIVE_SELECTOR = "[data-menu-active]";
function getDropdown(node) {
return node?.closest("[data-menu-dropdown]");
}
function getItems(dropdown) {
if (!dropdown) return [];
return Array.from(dropdown.querySelectorAll(ITEM_SELECTOR)).filter((item) => item.closest("[data-menu-dropdown]") === dropdown);
}
function clearActive(dropdown) {
if (!dropdown) return;
dropdown.querySelectorAll(ACTIVE_SELECTOR).forEach((node) => {
if (node.closest("[data-menu-dropdown]") === dropdown) node.removeAttribute("data-menu-active");
});
}
function setActive(item, dropdown) {
clearActive(dropdown);
if (item) {
item.setAttribute("data-menu-active", "true");
item.scrollIntoView({ block: "nearest" });
}
}
function getActiveIndex(items) {
return items.findIndex((item) => item.hasAttribute("data-menu-active"));
}
const defaultProps = { clearSearchOnClose: true };
const MenuSearch = factory((props) => {
const { classNames, styles, onKeyDown, onChange, size, clearSearchOnClose, ref, ...others } = useProps("MenuSearch", defaultProps, props);
const ctx = useMenuContext();
const inputRef = useRef(null);
const mergedRef = useMergedRef(ref, inputRef);
const onChangeRef = useRef(onChange);
onChangeRef.current = onChange;
useEffect(() => {
return ctx.registerSearch();
}, [ctx.registerSearch]);
useEffect(() => {
if (clearSearchOnClose) ctx.searchExitClearRef.current = () => {
onChangeRef.current?.({ currentTarget: { value: "" } });
};
else ctx.searchExitClearRef.current = null;
}, [clearSearchOnClose, ctx.searchExitClearRef]);
useEffect(() => {
if (!ctx.opened) clearActive(getDropdown(inputRef.current));
}, [ctx.opened]);
const handleChange = createEventHandler(onChange, (event) => {
clearActive(getDropdown(event.currentTarget));
});
const handleKeyDown = createEventHandler(onKeyDown, (event) => {
if (event.defaultPrevented) return;
const dropdown = getDropdown(event.currentTarget);
const items = getItems(dropdown);
if (event.key === "ArrowDown") {
event.preventDefault();
if (items.length === 0) return;
const current = getActiveIndex(items);
setActive(items[current >= items.length - 1 ? ctx.loop ? 0 : current : current + 1] ?? null, dropdown);
} else if (event.key === "ArrowUp") {
event.preventDefault();
if (items.length === 0) return;
const current = getActiveIndex(items);
setActive(items[current <= 0 ? current === -1 ? items.length - 1 : ctx.loop ? items.length - 1 : 0 : current - 1] ?? null, dropdown);
} else if (event.key === "Home") {
event.preventDefault();
if (items.length > 0) setActive(items[0], dropdown);
} else if (event.key === "End") {
event.preventDefault();
if (items.length > 0) setActive(items[items.length - 1], dropdown);
} else if (event.key === "Enter") {
if (event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) return;
const target = items[getActiveIndex(items)];
if (target) {
event.preventDefault();
if (target.hasAttribute("data-sub-menu-item")) {
target.focus();
target.dispatchEvent(new KeyboardEvent("keydown", {
key: "ArrowRight",
bubbles: true
}));
} else target.click();
}
}
});
const _styles = ctx.getStyles("search");
return /* @__PURE__ */ jsx(Input, {
"data-autofocus": true,
"data-mantine-stop-propagation": true,
type: "search",
size,
...others,
ref: mergedRef,
classNames: [{ input: _styles.className }, classNames],
styles: [{ input: _styles.style }, styles],
onKeyDown: handleKeyDown,
onChange: handleChange,
__staticSelector: "Menu"
});
});
MenuSearch.classes = Menu_module_default;
MenuSearch.displayName = "@mantine/core/MenuSearch";
//#endregion
export { MenuSearch };
//# sourceMappingURL=MenuSearch.mjs.map