@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
1 lines • 8.98 kB
Source Map (JSON)
{"version":3,"file":"MenuSearch.cjs","names":["factory","useProps","useMenuContext","createEventHandler","Input","classes"],"sources":["../../../../src/components/Menu/MenuSearch/MenuSearch.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { useMergedRef } from '@mantine/hooks';\nimport { createEventHandler, ElementProps, factory, Factory, useProps } from '../../../core';\nimport { Input, InputProps } from '../../Input/Input';\nimport { useMenuContext } from '../Menu.context';\nimport classes from '../Menu.module.css';\n\nconst ITEM_SELECTOR = '[data-menu-item]:not([data-disabled])';\nconst ACTIVE_SELECTOR = '[data-menu-active]';\n\nfunction getDropdown(node: HTMLElement | null): HTMLElement | null {\n return node?.closest('[data-menu-dropdown]') as HTMLElement | null;\n}\n\nfunction getItems(dropdown: HTMLElement | null): HTMLElement[] {\n if (!dropdown) {\n return [];\n }\n return Array.from(dropdown.querySelectorAll<HTMLElement>(ITEM_SELECTOR)).filter(\n (item) => item.closest('[data-menu-dropdown]') === dropdown\n );\n}\n\nfunction clearActive(dropdown: HTMLElement | null) {\n if (!dropdown) {\n return;\n }\n dropdown.querySelectorAll<HTMLElement>(ACTIVE_SELECTOR).forEach((node) => {\n if (node.closest('[data-menu-dropdown]') === dropdown) {\n node.removeAttribute('data-menu-active');\n }\n });\n}\n\nfunction setActive(item: HTMLElement | null, dropdown: HTMLElement | null) {\n clearActive(dropdown);\n if (item) {\n item.setAttribute('data-menu-active', 'true');\n item.scrollIntoView({ block: 'nearest' });\n }\n}\n\nfunction getActiveIndex(items: HTMLElement[]): number {\n return items.findIndex((item) => item.hasAttribute('data-menu-active'));\n}\n\nexport type MenuSearchStylesNames = 'search';\n\nexport interface MenuSearchProps extends InputProps, ElementProps<'input', 'size'> {\n /** If set, clears the search value after the menu close transition completes. Requires a controlled `value`/`onChange` pair. @default true */\n clearSearchOnClose?: boolean;\n}\n\nexport type MenuSearchFactory = Factory<{\n props: MenuSearchProps;\n ref: HTMLInputElement;\n stylesNames: MenuSearchStylesNames;\n compound: true;\n}>;\n\nconst defaultProps = {\n clearSearchOnClose: true,\n} satisfies Partial<MenuSearchProps>;\n\nexport const MenuSearch = factory<MenuSearchFactory>((props) => {\n const { classNames, styles, onKeyDown, onChange, size, clearSearchOnClose, ref, ...others } =\n useProps('MenuSearch', defaultProps, props);\n\n const ctx = useMenuContext();\n const inputRef = useRef<HTMLInputElement>(null);\n const mergedRef = useMergedRef(ref, inputRef);\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n useEffect(() => {\n const unregister = ctx.registerSearch();\n return unregister;\n }, [ctx.registerSearch]);\n\n useEffect(() => {\n if (clearSearchOnClose) {\n ctx.searchExitClearRef.current = () => {\n onChangeRef.current?.({\n currentTarget: { value: '' },\n } as unknown as React.ChangeEvent<HTMLInputElement>);\n };\n } else {\n ctx.searchExitClearRef.current = null;\n }\n }, [clearSearchOnClose, ctx.searchExitClearRef]);\n\n useEffect(() => {\n if (!ctx.opened) {\n const dropdown = getDropdown(inputRef.current);\n clearActive(dropdown);\n }\n }, [ctx.opened]);\n\n const handleChange = createEventHandler<any>(\n onChange,\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const dropdown = getDropdown(event.currentTarget);\n clearActive(dropdown);\n }\n );\n\n const handleKeyDown = createEventHandler<any>(\n onKeyDown,\n (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.defaultPrevented) {\n return;\n }\n\n const dropdown = getDropdown(event.currentTarget);\n const items = getItems(dropdown);\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n if (items.length === 0) {\n return;\n }\n const current = getActiveIndex(items);\n const next = current >= items.length - 1 ? (ctx.loop ? 0 : current) : current + 1;\n setActive(items[next] ?? null, dropdown);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n if (items.length === 0) {\n return;\n }\n const current = getActiveIndex(items);\n const next =\n current <= 0\n ? current === -1\n ? items.length - 1\n : ctx.loop\n ? items.length - 1\n : 0\n : current - 1;\n setActive(items[next] ?? null, dropdown);\n } else if (event.key === 'Home') {\n event.preventDefault();\n if (items.length > 0) {\n setActive(items[0]!, dropdown);\n }\n } else if (event.key === 'End') {\n event.preventDefault();\n if (items.length > 0) {\n setActive(items[items.length - 1]!, dropdown);\n }\n } else if (event.key === 'Enter') {\n if (event.nativeEvent.isComposing || (event.nativeEvent as KeyboardEvent).keyCode === 229) {\n return;\n }\n const activeIndex = getActiveIndex(items);\n const target = items[activeIndex];\n if (target) {\n event.preventDefault();\n if (target.hasAttribute('data-sub-menu-item')) {\n target.focus();\n target.dispatchEvent(\n new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true })\n );\n } else {\n target.click();\n }\n }\n }\n }\n );\n\n const _styles = ctx.getStyles('search');\n\n return (\n <Input\n data-autofocus\n data-mantine-stop-propagation\n type=\"search\"\n size={size}\n {...others}\n ref={mergedRef}\n classNames={[{ input: _styles.className }, classNames] as any}\n styles={[{ input: _styles.style }, styles] as any}\n onKeyDown={handleKeyDown}\n onChange={handleChange}\n __staticSelector=\"Menu\"\n />\n );\n});\n\nMenuSearch.classes = classes;\nMenuSearch.displayName = '@mantine/core/MenuSearch';\n"],"mappings":"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"}