import classNames from 'classnames' ; import type { Dayjs } from 'dayjs' ; import dayjs from 'dayjs' ; import { memo } from 'react' ; import { useInView } from 'react-intersection-observer' ; import { Typography } from '../Typography' ; import { useTimetable } from './useTimetable' ; export interface SpellProps { readonly date : Readonly < Dayjs > ; readonly size : number ; } const SpellPure = ( props ) : JSX . Element => { const { date , size } = props ; const { scale , interval , getItemX , ref : timetable , itemHeight , } = useTimetable ( ) ; const { ref , inView } = useInView ( { root : timetable . current , rootMargin : '200px' , initialInView : Math . abs ( date . diff ( dayjs ( ) , 'minute' ) ) <= interval * 10 , } ) ; const width = scale * interval ; const x = getItemX ( date ) - width / 2 ; return ( < h4 id = { date . toISOString ( ) } className = { classNames ( 'absolute' , 'h-full' , 'transition-opacity' , 'duration-500' , inView ? 'opacity-100' : 'opacity-0' ) } style = { { width , transform : `translateX(${ x }px)` , } } ref = { ref } > < a href = { `#${ date . toISOString ( ) }` } className = { classNames ( 'flex' , 'flex-col' , 'items-center' , 'group' , 'w-full' , 'min-h-full' , 'focus:outline-none' , 'focus:ring' , 'ring-inset' , 'ring-primary-500' , 'dark:ring-primary-400' ) } aria - label = { `${ date . format ( 'LLL' ) }以降の配信予定` } > < Typography as = "time" size = "sm" weight = "semibold" align = "center" className = { classNames ( 'block' , 'grow-0' , 'shrink-0' , 'p-3' , 'group-focus:text-primary-500' , 'dark:group-focus:text-primary-400' , 'text-gray-800' , 'dark:text-neutral-200' ) } dateTime = { date . toISOString ( ) } > { date . format ( 'HH:mm' ) } < /Typography> < div role = "presentation" aria - hidden className = { classNames ( 'grow' , 'w-0' , 'min-h-full' , 'border-r' , 'border-gray-200' , 'dark:border-neutral-800' ) } style = { { height : `${ itemHeight * size }px` } } /> < /a> < /h4>); } ; export const Spell = memo ( SpellPure ) ;