import React, { useEffect, useRef, useState, useCallback } from "react"; import { Widget } from "../../../store/useWidgetStore"; import { MoveArrowLeft, MoveArrowRight } from "../../icons/SimulationIcons"; import { InfoIcon } from "../../icons/ExportCommonIcons"; import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore"; // Define the type for `Side` type Side = "top" | "bottom" | "left" | "right"; interface DisplayZoneProps { zonesData: { [key: string]: { activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; widgets: Widget[]; zoneId: string; zoneViewPortTarget: number[]; zoneViewPortPosition: number[]; }; }; selectedZone: { zoneName: string; activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; zoneId: string; zoneViewPortTarget: number[]; zoneViewPortPosition: number[]; widgets: { id: string; type: string; title: string; panel: Side; data: any; }[]; }; setSelectedZone: React.Dispatch< React.SetStateAction<{ zoneName: string; activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; zoneId: string; zoneViewPortTarget: number[]; zoneViewPortPosition: number[]; widgets: { id: string; type: string; title: string; panel: Side; data: any; }[]; }> >; } const DisplayZone: React.FC<DisplayZoneProps> = ({ zonesData, selectedZone, setSelectedZone, }) => { // Ref for the container element const containerRef = useRef<HTMLDivElement | null>(null); // State to track overflow visibility const [showLeftArrow, setShowLeftArrow] = useState(false); const [showRightArrow, setShowRightArrow] = useState(false); // Function to calculate overflow state const updateOverflowState = useCallback(() => { const container = containerRef.current; if (container) { const isOverflowing = container.scrollWidth > container.clientWidth; const canScrollLeft = container.scrollLeft > 0; const canScrollRight = container.scrollLeft + container.clientWidth < container.scrollWidth; setShowLeftArrow(isOverflowing && canScrollLeft); setShowRightArrow(isOverflowing && canScrollRight); } }, []); useEffect(() => { const container = containerRef.current; if (container) { // Initial calculation after the DOM has been rendered const handleInitialRender = () => { requestAnimationFrame(updateOverflowState); }; handleInitialRender(); // Update on window resize or scroll const handleResize = () => updateOverflowState(); const handleScroll = () => updateOverflowState(); // Add mouse wheel listener for horizontal scrolling const handleWheel = (event: WheelEvent) => { event.preventDefault(); // Prevent default vertical scrolling if (container) { container.scrollBy({ left: event.deltaY * 2, // Translate vertical scroll to horizontal scroll behavior: "smooth", }); } }; container.addEventListener("scroll", handleScroll); window.addEventListener("resize", handleResize); container.addEventListener("wheel", handleWheel, { passive: false }); return () => { container.removeEventListener("scroll", handleScroll); window.removeEventListener("resize", handleResize); container.removeEventListener("wheel", handleWheel); }; } }, [updateOverflowState]); // Handle scrolling with navigation arrows const handleScrollLeft = () => { const container = containerRef.current; if (container) { container.scrollBy({ left: -200, // Scroll left by 200px behavior: "smooth", }); } }; const handleScrollRight = () => { const container = containerRef.current; if (container) { container.scrollBy({ left: 200, // Scroll right by 200px behavior: "smooth", }); } }; return ( <div className={`zone-wrapper ${ selectedZone?.activeSides?.includes("bottom") && "bottom" }`} > {/* Left Arrow */} {showLeftArrow && ( <button className="arrow left-arrow" onClick={handleScrollLeft}> <MoveArrowLeft /> </button> )} {/* Zones Wrapper */} {Object.keys(zonesData).length !== 0 ? ( <div ref={containerRef} className="zones-wrapper"> {Object.keys(zonesData).map((zoneName, index) => ( <div key={index} className={`zone ${ selectedZone.zoneName === zoneName ? "active" : "" }`} onClick={() => { useDroppedObjectsStore.getState().setZone(zoneName, zonesData[zoneName]?.zoneId); setSelectedZone({ zoneName, activeSides: zonesData[zoneName].activeSides || [], panelOrder: zonesData[zoneName].panelOrder || [], lockedPanels: zonesData[zoneName].lockedPanels || [], widgets: zonesData[zoneName].widgets || [], zoneId: zonesData[zoneName]?.zoneId || "", zoneViewPortTarget: zonesData[zoneName].zoneViewPortTarget || [], zoneViewPortPosition: zonesData[zoneName].zoneViewPortPosition || [], }); }} > {zoneName} </div> ))} </div> ) : ( <div className="no-zone"> <InfoIcon /> No zones? Create one! </div> )} {/* Right Arrow */} {showRightArrow && ( <button className="arrow right-arrow" onClick={handleScrollRight}> <MoveArrowRight /> </button> )} </div> ); }; export default DisplayZone;