@fidely-ui/react
Version:
Fidely UI is a modern, beautifully crafted React design system powered by Ark UI and Panda CSS, delivering accessible and themeable components for building exceptional web apps
49 lines (48 loc) • 2.52 kB
JavaScript
'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import { cx } from '@fidely-ui/styled-system/css';
import { commandInput } from '@fidely-ui/styled-system/recipes';
import { Group } from '../group/index';
import { Kbd } from '../kbd/index';
import { Flex } from '../flex/index';
import { Text } from '../text/index';
import { isMobileDevice } from '../../utils/is-mobile-device';
import { FiSearch } from '../icons/FiSearch';
export const CommandInput = React.forwardRef(function CommandInput(props, ref) {
const { shortcut, onOpen, placeholder = 'Search...', leftElement, className, ...rest } = props;
const slotStyles = commandInput();
const [isMobile, setIsMobile] = React.useState(false);
const [resolvedShortcut, setResolvedShortcut] = React.useState(null);
React.useEffect(() => {
const mobile = isMobileDevice();
setIsMobile(mobile);
if (!mobile) {
const isMac = /Mac|iPod|iPhone|iPad/.test(navigator.userAgent);
setResolvedShortcut(shortcut ?? (isMac ? '⌘ + K' : 'Ctrl + K'));
}
}, [shortcut]);
React.useEffect(() => {
if (isMobile || !resolvedShortcut)
return;
const parts = resolvedShortcut.split('+').map((p) => p.trim().toLowerCase());
const handleKeyDown = (e) => {
const pressed = [];
if (e.metaKey)
pressed.push('⌘');
if (e.ctrlKey)
pressed.push('ctrl');
pressed.push(e.key.toLowerCase());
const combo = pressed.join(' ');
const target = parts.join(' ').toLowerCase();
if (combo === target) {
e.preventDefault();
onOpen?.();
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [resolvedShortcut, onOpen, isMobile]);
return (_jsxs(Group, { as: "button", ref: ref, onClick: onOpen, "aria-haspopup": "dialog", "aria-expanded": false, className: cx(slotStyles, className), ...rest, children: [_jsxs(Flex, { alignItems: "center", gap: "2", children: [leftElement ?? _jsx(FiSearch, {}), _jsx(Text, { color: "fg.muted", children: placeholder })] }), !isMobile && resolvedShortcut ? (_jsx(Flex, { gap: "1", children: resolvedShortcut.split('+').map((key, i) => (_jsx(Kbd, { children: key.trim() }, i))) })) : null] }));
});
CommandInput.displayName = 'CommandInput';