FilamentSlotCircle.tsx 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. /**
  2. * FilamentSlotCircle renders a small color circle with the 1-based slot
  3. * number centered inside, matching the style used on AMS cards in PrintersPage.
  4. *
  5. * Props:
  6. * trayColor - 6-char hex color string WITHOUT leading '#' (e.g. "FF0000").
  7. * Pass undefined / empty string when the slot is empty.
  8. * trayType - Filament material string (e.g. "PLA"). Used to decide the
  9. * fallback background when there is no color but a type is known.
  10. * isEmpty - Whether the slot contains no filament.
  11. * slotNumber - 1-based slot number to display inside the circle.
  12. */
  13. interface FilamentSlotCircleProps {
  14. trayColor?: string | null;
  15. trayType?: string | null;
  16. isEmpty: boolean;
  17. slotNumber: number;
  18. }
  19. function isLightFilamentColor(hex: string): boolean {
  20. if (!hex || hex.length < 6) return false;
  21. const r = parseInt(hex.slice(0, 2), 16);
  22. const g = parseInt(hex.slice(2, 4), 16);
  23. const b = parseInt(hex.slice(4, 6), 16);
  24. return (0.299 * r + 0.587 * g + 0.114 * b) / 255 > 0.6;
  25. }
  26. export function FilamentSlotCircle({ trayColor, trayType, isEmpty, slotNumber }: FilamentSlotCircleProps) {
  27. return (
  28. <div
  29. className="w-3.5 h-3.5 rounded-full mx-auto mb-0.5 border-2 flex items-center justify-center"
  30. style={{
  31. backgroundColor: trayColor ? `#${trayColor}` : (trayType ? '#333' : 'transparent'),
  32. borderColor: isEmpty ? '#666' : 'rgba(255,255,255,0.1)',
  33. borderStyle: isEmpty ? 'dashed' : 'solid',
  34. }}
  35. >
  36. <span
  37. className="text-[6px] font-bold leading-none select-none"
  38. style={{ color: trayColor && isLightFilamentColor(trayColor) ? '#000' : '#fff' }}
  39. >
  40. {slotNumber}
  41. </span>
  42. </div>
  43. );
  44. }