UNPKG

unified-video-framework

Version:

Cross-platform video player framework supporting iOS, Android, Web, Smart TVs (Samsung/LG), Roku, and more

156 lines 7.84 kB
import React, { useMemo, useRef, useEffect } from 'react'; import { DEFAULT_EPG_THEME } from '../types/EPGTypes.js'; import { generateTimeSlots, getCurrentTimePosition, formatTime } from '../utils/EPGUtils.js'; export const EPGTimelineHeader = ({ timelineStart, timelineEnd, containerWidth, currentTime = Date.now(), visibleHours = 4, slotDuration = 60, onTimeClick, scrollLeft = 0, onScroll, className = '', style = {}, theme: themeProp, }) => { const theme = { ...DEFAULT_EPG_THEME, ...themeProp }; const headerRef = useRef(null); const scrollContainerRef = useRef(null); const timeSlots = useMemo(() => { return generateTimeSlots(timelineStart, visibleHours, slotDuration); }, [timelineStart, visibleHours, slotDuration]); const currentTimePosition = useMemo(() => { return getCurrentTimePosition(currentTime, timelineStart, timelineEnd, containerWidth); }, [currentTime, timelineStart, timelineEnd, containerWidth]); const handleTimeSlotClick = (timestamp) => { if (onTimeClick) { onTimeClick(timestamp); } }; useEffect(() => { if (scrollContainerRef.current && scrollLeft !== undefined) { scrollContainerRef.current.scrollLeft = scrollLeft; } }, [scrollLeft]); const handleTimelineScroll = (e) => { if (onScroll) { onScroll(e.currentTarget.scrollLeft); } }; return (React.createElement("div", { ref: headerRef, className: `epg-timeline-header ${className}`, style: { position: 'relative', height: '60px', borderBottom: '1px solid rgba(255, 255, 255, 0.1)', backgroundColor: 'rgba(20, 20, 20, 0.5)', backdropFilter: 'blur(8px)', display: 'flex', ...style, } }, React.createElement("div", { style: { width: '200px', height: '100%', backgroundColor: 'rgba(20, 20, 20, 0.6)', borderRight: '1px solid rgba(255, 255, 255, 0.1)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '12px', fontWeight: '600', color: 'rgba(255, 255, 255, 0.5)', } }, "Channels"), React.createElement("div", { ref: scrollContainerRef, className: "epg-timeline-scroll-container", style: { flex: 1, height: '100%', overflow: 'auto', scrollbarWidth: 'none', msOverflowStyle: 'none', }, onScroll: handleTimelineScroll }, React.createElement("div", { className: "epg-timeline-slots", style: { position: 'relative', width: `${containerWidth}px`, height: '100%', display: 'flex', alignItems: 'center', } }, timeSlots.map((slot, index) => { const slotPosition = ((slot.timestamp - timelineStart) / (timelineEnd - timelineStart)) * containerWidth; return (React.createElement("div", { key: slot.timestamp, className: "epg-time-slot", style: { position: 'absolute', left: `${slotPosition}px`, height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'flex-start', cursor: 'pointer', paddingLeft: '8px', minWidth: '80px', borderLeft: index > 0 ? '1px solid #333' : 'none', }, onClick: () => handleTimeSlotClick(slot.timestamp) }, React.createElement("div", { className: "epg-time-label", style: { color: '#fff', fontSize: '14px', fontWeight: '600', lineHeight: '1.2', } }, slot.label), (index === 0 || slot.hour === 0) && (React.createElement("div", { className: "epg-date-label", style: { color: '#888', fontSize: '11px', lineHeight: '1.2', marginTop: '2px', } }, new Date(slot.timestamp).toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric', }))))); }), currentTimePosition > 0 && (React.createElement("div", { className: "epg-current-time-indicator", style: { position: 'absolute', left: `${currentTimePosition}px`, top: '0', bottom: '0', width: '2px', backgroundColor: theme.primaryColor, zIndex: 10, pointerEvents: 'none', } }, React.createElement("div", { style: { position: 'absolute', top: '8px', left: '50%', transform: 'translateX(-50%)', backgroundColor: theme.primaryColor, color: '#fff', fontSize: '10px', fontWeight: '600', padding: '2px 6px', borderRadius: '4px', whiteSpace: 'nowrap', boxShadow: '0 2px 4px rgba(0,0,0,0.3)', } }, "NOW"), React.createElement("div", { style: { position: 'absolute', bottom: '8px', left: '50%', transform: 'translateX(-50%)', backgroundColor: theme.primaryColor, color: '#fff', fontSize: '10px', fontWeight: '600', padding: '2px 6px', borderRadius: '4px', whiteSpace: 'nowrap', boxShadow: '0 2px 4px rgba(0,0,0,0.3)', } }, formatTime(currentTime)))), timeSlots.map((slot, index) => { if (index === 0) return null; const linePosition = ((slot.timestamp - timelineStart) / (timelineEnd - timelineStart)) * containerWidth; return (React.createElement("div", { key: `grid-${slot.timestamp}`, className: "epg-grid-line", style: { position: 'absolute', left: `${linePosition}px`, top: '0', bottom: '0', width: '1px', backgroundColor: 'rgba(255, 255, 255, 0.1)', opacity: 1, pointerEvents: 'none', } })); })), React.createElement("style", null, ` .epg-timeline-scroll-container::-webkit-scrollbar { display: none; } `)))); }; export default EPGTimelineHeader; //# sourceMappingURL=EPGTimelineHeader.js.map