/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ import React, { useEffect, useState, KeyboardEvent } from "react"; import Tab from "./Tab"; import { ScrollMenu, VisibilityContext } from "react-horizontal-scrolling-menu"; import { LeftArrow, RightArrow } from "./Arrows"; interface Props { children: React.ReactNode; defaultActive: string; showArrows?: boolean; ariaLabelledById: string; } type scrollVisibilityApiType = React.ContextType; function Tabs(props: Props) { const [scrollMenuObj, setScrollMenuObj] = useState(); const [activeTab, setActiveTab] = useState(props.defaultActive); const tabsMap = new Map(); useEffect(() => { setActiveTab(props.defaultActive); }, [props.defaultActive]); function getActiveTabIndex(): number { for (let [key, value] of Array.from(tabsMap.entries())) { if (value === activeTab) { return key; } } return 0; } const onKeyDown = (e: KeyboardEvent) => { if (e.key === "ArrowRight") { const index = getActiveTabIndex(); if (index < tabsMap.size - 1) { setActiveTab(tabsMap.get(index + 1) || props.defaultActive); } } else if (e.key === "ArrowLeft") { const index = getActiveTabIndex(); if (index > 0) { setActiveTab(tabsMap.get(index - 1) || props.defaultActive); } } }; const activateTabItem = (tab: string, currentTab: HTMLElement) => { const rect = currentTab.getBoundingClientRect(); const wrapper = scrollMenuObj?.scrollContainer?.current; if (rect && wrapper) { const wrapperRect = wrapper.getBoundingClientRect(); if (rect.left < wrapperRect.left) { scrollMenuObj?.scrollPrev(); } else { const shownWidth = wrapperRect.right - rect.left; if (shownWidth < rect.width) { scrollMenuObj?.scrollNext(); } } } setActiveTab(tab); }; return (
{React.Children.map(props.children, (child: any, index) => { tabsMap.set(index, child.props.id); return ( ); })} {React.Children.map(props.children, (child) => { const childId = (child as any).props.id; if (childId !== activeTab) { return
; } return (
{(child as any).props.children}
); })}
); } function onWheel(apiObj: scrollVisibilityApiType, ev: React.WheelEvent): void { const isThouchpad = Math.abs(ev.deltaX) !== 0 || Math.abs(ev.deltaY) < 15; if (isThouchpad) { ev.stopPropagation(); return; } if (ev.deltaY < 0) { apiObj.scrollNext(); } else if (ev.deltaY > 0) { apiObj.scrollPrev(); } } export default Tabs;