select.tsx 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. "use client";
  2. import type { ComponentRenderProps } from "./types";
  3. import {
  4. baseClass,
  5. getCustomClass,
  6. getOpenSelect,
  7. setOpenSelectValue,
  8. getSelectValue,
  9. setSelectValueForKey,
  10. } from "./utils";
  11. export function Select({ element }: ComponentRenderProps) {
  12. const { props, key } = element;
  13. const customClass = getCustomClass(props);
  14. const options = (props.options as string[]) || [];
  15. const selectedValue = getSelectValue(key);
  16. const isOpen = getOpenSelect() === key;
  17. return (
  18. <div className={`relative ${baseClass} ${customClass}`}>
  19. {props.label ? (
  20. <label className="text-[10px] text-muted-foreground block mb-0.5 text-left">
  21. {props.label as string}
  22. </label>
  23. ) : null}
  24. <div
  25. onClick={() => setOpenSelectValue(isOpen ? null : key)}
  26. className="h-7 w-full bg-card border border-border rounded px-2 text-xs flex items-center justify-between cursor-pointer hover:border-foreground/30 transition-colors"
  27. >
  28. <span
  29. className={
  30. selectedValue ? "text-foreground" : "text-muted-foreground/50"
  31. }
  32. >
  33. {selectedValue || (props.placeholder as string) || "Select..."}
  34. </span>
  35. <svg
  36. className={`w-3 h-3 transition-transform ${isOpen ? "rotate-180" : ""}`}
  37. fill="none"
  38. stroke="currentColor"
  39. viewBox="0 0 24 24"
  40. >
  41. <path
  42. strokeLinecap="round"
  43. strokeLinejoin="round"
  44. strokeWidth={2}
  45. d="M19 9l-7 7-7-7"
  46. />
  47. </svg>
  48. </div>
  49. {isOpen && options.length > 0 && (
  50. <div className="absolute z-10 top-full left-0 right-0 mt-1 bg-card border border-border rounded shadow-lg overflow-hidden">
  51. {options.map((opt, i) => (
  52. <div
  53. key={i}
  54. onClick={() => {
  55. setSelectValueForKey(key, opt);
  56. setOpenSelectValue(null);
  57. }}
  58. className={`px-2 py-1.5 text-xs text-left cursor-pointer hover:bg-muted transition-colors ${selectedValue === opt ? "bg-muted" : ""}`}
  59. >
  60. {opt}
  61. </div>
  62. ))}
  63. </div>
  64. )}
  65. </div>
  66. );
  67. }