import { memo, MutableRefObject, useLayoutEffect, useRef, useState } from 'react'; import { IoEllipsisHorizontal } from '@react-icons/all-files/io5/IoEllipsisHorizontal'; import { flexRender, Table } from '@tanstack/react-table'; import Color from 'color'; import { OntimeEvent, OntimeRundownEntry } from 'ontime-types'; import IconButton from '../../../../common/components/buttons/IconButton'; import { cx, getAccessibleColour } from '../../../../common/utils/styleUtils'; import { useCuesheetOptions } from '../../cuesheet.options'; import { useCuesheetTableMenu } from '../cuesheet-table-menu/useCuesheetTableMenu'; import style from '../CuesheetTable.module.scss'; interface EventRowProps { rowId: string; event: OntimeEvent; eventIndex: number; rowIndex: number; isPast?: boolean; selectedRef?: MutableRefObject; skip?: boolean; colour?: string; rowBgColour?: string; table: Table; /** hack to force re-rendering of the row when the column sizes change */ columnSizing: Record; } export default memo(EventRow, (prevProps, nextProps) => { return ( prevProps.rowId === nextProps.rowId && prevProps.event.revision === nextProps.event.revision && prevProps.eventIndex === nextProps.eventIndex && prevProps.rowIndex === nextProps.rowIndex && prevProps.isPast === nextProps.isPast && prevProps.selectedRef === nextProps.selectedRef && prevProps.rowBgColour === nextProps.rowBgColour && prevProps.table === nextProps.table && prevProps.columnSizing === nextProps.columnSizing ); }); function EventRow(props: EventRowProps) { const { rowId, event, eventIndex, rowIndex, isPast, selectedRef, rowBgColour, table } = props; const { hideIndexColumn, showActionMenu } = useCuesheetOptions(); const ownRef = useRef(null); const [isVisible, setIsVisible] = useState(false); const openMenu = useCuesheetTableMenu((store) => store.openMenu); useLayoutEffect(() => { const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setIsVisible(true); } }, { root: null, threshold: 0.01, }, ); const handleRefCurrent = ownRef.current; if (selectedRef) { setIsVisible(true); } else if (handleRefCurrent) { observer.observe(handleRefCurrent); } return () => { if (handleRefCurrent) { observer.unobserve(handleRefCurrent); } }; }, [ownRef, selectedRef]); const { color, backgroundColor } = getAccessibleColour(event.colour); const mutedText = Color(color).fade(0.4).hexa(); return ( {showActionMenu && ( { const rect = e.currentTarget.getBoundingClientRect(); const yPos = 8 + rect.y + rect.height / 2; openMenu({ x: rect.x, y: yPos }, event.id, rowIndex); }} > )} {!hideIndexColumn && ( {eventIndex} )} {isVisible ? table .getRow(rowId) ?.getVisibleCells() .map((cell) => { return ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ); }) : null} ); }