SignalEditorList.tsx 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import { useRef } from "react";
  2. import type { Signal } from "./model";
  3. import styles from "./ClockTimeline.module.css";
  4. import SelectSignal from "../Selector/SelectSignal";
  5. interface SignalEditorListProps {
  6. signals: Signal[];
  7. placeholder?: string;
  8. onAdd: (signal: Signal | null) => void;
  9. onUpdate: (index: number, signal: Signal | null) => void;
  10. onRemove: (index: number) => void;
  11. onReorder: (sourceIdx: number, targetIdx: number) => void;
  12. }
  13. export default function SignalEditorList({
  14. signals,
  15. placeholder,
  16. onAdd,
  17. onUpdate,
  18. onRemove,
  19. onReorder,
  20. }: SignalEditorListProps) {
  21. const draggedSignalIdx = useRef<number | null>(null);
  22. return (
  23. <div className={styles.signalList}>
  24. {signals.map((s, i) => (
  25. <span
  26. key={`${s.name}-${i}`}
  27. className={styles.signalChip}
  28. draggable={signals.length > 1}
  29. onDragStart={(e) => {
  30. draggedSignalIdx.current = i;
  31. e.dataTransfer.effectAllowed = "move";
  32. }}
  33. onDragOver={(e) => {
  34. e.preventDefault();
  35. e.dataTransfer.dropEffect = "move";
  36. }}
  37. onDrop={(e) => {
  38. e.preventDefault();
  39. const sourceIdx = draggedSignalIdx.current;
  40. if (sourceIdx !== null && sourceIdx !== i) {
  41. onReorder(sourceIdx, i);
  42. }
  43. draggedSignalIdx.current = null;
  44. }}
  45. onDragEnd={() => {
  46. draggedSignalIdx.current = null;
  47. }}
  48. >
  49. <SelectSignal value={s.name} onSelectSignal={(_, sig) => onUpdate(i, sig)} />
  50. {signals.length > 1 && (
  51. <button className={"button " + styles.signalRemove} onClick={() => onRemove(i)}>
  52. </button>
  53. )}
  54. </span>
  55. ))}
  56. <SelectSignal
  57. placeholder={placeholder}
  58. className={styles.signalEmpty}
  59. key={signals.length}
  60. onSelectSignal={(_, sig) => onAdd(sig)}
  61. />
  62. </div>
  63. );
  64. }