2D Run-and-gun shooter inspired by One Man's Doomsday, Counter-Strike, and Metal Slug.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.tsx 1.2 KiB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import {FormEventHandler, forwardRef, HTMLProps, ReactNode, useId} from 'react';
  2. export interface ComboBoxProps extends Omit<HTMLProps<HTMLInputElement>, 'list'> {
  3. onOptionSelect?: FormEventHandler<HTMLInputElement>;
  4. onCustomValueInput?: FormEventHandler<HTMLInputElement>;
  5. children?: ReactNode;
  6. }
  7. export const ComboBox = forwardRef<HTMLInputElement, ComboBoxProps>(({
  8. onOptionSelect,
  9. children,
  10. className = '',
  11. onInput,
  12. onCustomValueInput,
  13. ...etcProps
  14. }, ref) => {
  15. const id = useId();
  16. const handleInput: FormEventHandler<HTMLInputElement> = (e) => {
  17. onInput?.(e);
  18. const nativeEvent = e.nativeEvent as unknown as { inputType?: string };
  19. switch (nativeEvent.inputType) {
  20. case 'deleteContentBackward':
  21. case 'deleteContentForward':
  22. case 'insertText':
  23. // we type into the input
  24. onCustomValueInput?.(e);
  25. return;
  26. default:
  27. break;
  28. // we select from the datalist
  29. }
  30. onOptionSelect?.(e);
  31. }
  32. return (
  33. <>
  34. <datalist
  35. id={id}
  36. >
  37. {children}
  38. </datalist>
  39. <input
  40. {...etcProps}
  41. ref={ref}
  42. list={id}
  43. className={`w-full block h-12 px-4 ${className}`}
  44. onInput={handleInput}
  45. />
  46. </>
  47. )
  48. })