{"version":3,"sources":["../../src/tabs/useTabs.ts","../../src/tabs/useTabs.props.ts"],"sourcesContent":["import { withHeadless } from '@primereact/core/headless';\nimport { useTabsProps } from '@primereact/types/shared/tabs';\nimport { findSingle, focus, getAttribute, getOffset, getOuterHeight, getOuterWidth } from '@primeuix/utils';\nimport * as React from 'react';\nimport { defaultProps } from './useTabs.props';\n\nexport const useTabs = withHeadless({\n    name: 'useTabs',\n    defaultProps,\n    setup: ({ props, elementRef }) => {\n        const [activeTabState, setActiveTabState] = React.useState<useTabsProps['value']>(props.value ?? undefined);\n        const [inkBarDimensionsState, setInkBarDimensionsState] = React.useState<React.CSSProperties>({});\n\n        const state = {\n            activeTab: activeTabState,\n            inkBarDimensions: inkBarDimensionsState\n        };\n\n        // methods\n        const updateValue = (value: string | number | undefined) => {\n            if (activeTabState !== value) {\n                setActiveTabState(value);\n                props.onValueChange?.({\n                    value\n                });\n            }\n        };\n\n        React.useEffect(() => {\n            if (props.value !== activeTabState) {\n                setActiveTabState(props.value);\n            }\n        }, [props.value]);\n\n        const isItemActive = (key: null | undefined | string | number): boolean => {\n            if (key === null || key === undefined) return false;\n\n            return activeTabState === key;\n        };\n\n        const updateInkBar = () => {\n            const tabs = elementRef?.current;\n\n            if (!tabs) return;\n\n            const activeTab = findSingle(tabs, '[data-pc-section=\"tab\"][data-p-active=\"true\"]');\n\n            if (!activeTab) return;\n\n            // Get elements and their offsets\n            const scrollContainer = tabs.querySelector('[data-pc-section=\"content\"]') as HTMLElement;\n\n            if (!scrollContainer) return;\n\n            const scrollLeft = scrollContainer?.scrollLeft || 0;\n\n            const activeTabOffset = getOffset(activeTab as HTMLElement);\n            const containerOffset = getOffset(tabs);\n            const scrollContainerOffset = getOffset(scrollContainer);\n\n            // Get dimensions\n            const tabWidth = getOuterWidth(activeTab as HTMLElement);\n            const tabHeight = getOuterHeight(activeTab as HTMLElement);\n            const scrollContainerHeight = getOuterHeight(scrollContainer);\n\n            // Calculate positions\n            const leftFromViewport = Number(activeTabOffset.left) - Number(scrollContainerOffset.left);\n            const relativeLeft = Number(activeTabOffset.left) - Number(containerOffset.left) + scrollLeft;\n            const relativeRight = scrollContainer.offsetWidth - (leftFromViewport + tabWidth);\n            const relativeTop = Number(activeTabOffset.top) - Number(scrollContainerOffset.top);\n            const relativeBottom = Number(scrollContainerOffset.top) + scrollContainerHeight - (tabHeight + Number(activeTabOffset.top));\n\n            return {\n                '--width': tabWidth + 'px',\n                '--height': tabHeight + 'px',\n                '--top': relativeTop + 'px',\n                '--left': relativeLeft + 'px',\n                '--right': relativeRight + 'px',\n                '--bottom': relativeBottom + 'px'\n            } as React.CSSProperties;\n        };\n\n        const focusTab = (tabElement: HTMLElement | null, direction: 'next' | 'previous' | 'first' | 'last'): void => {\n            const findTab = (listElement: HTMLElement): HTMLElement | null => {\n                return findSingle(listElement, '[data-pc-section=\"tab\"]') as HTMLElement | null;\n            };\n\n            const findAdjacentTab = (listElement: HTMLElement, direction: 'next' | 'previous', selfCheck = false): HTMLElement | null => {\n                const siblingProperty = direction === 'next' ? 'nextElementSibling' : 'previousElementSibling';\n                const element = selfCheck ? listElement : (listElement[siblingProperty] as HTMLElement | null);\n\n                if (!element) {\n                    return null;\n                }\n\n                if (getAttribute(element, 'data-p-disabled')) {\n                    return findAdjacentTab(element, direction);\n                }\n\n                return findTab(element);\n            };\n\n            const findBoundaryTab = (boundary: 'first' | 'last'): HTMLElement | null => {\n                const listElement = findSingle(elementRef?.current as HTMLElement, '[data-pc-section=\"tablist\"]') as HTMLElement | null;\n\n                if (!listElement) return null;\n\n                const tabSelector = '[data-pc-section=\"tab\"]';\n                let targetChild: HTMLElement | null = null;\n\n                if (boundary === 'first') {\n                    targetChild = listElement.querySelector(tabSelector) as HTMLElement | null;\n                } else {\n                    const allTabs = listElement.querySelectorAll(tabSelector);\n\n                    targetChild = allTabs.length > 0 ? (allTabs[allTabs.length - 1] as HTMLElement) : null;\n                }\n\n                if (!targetChild) return null;\n\n                const direction = boundary === 'first' ? 'next' : 'previous';\n\n                return findAdjacentTab(targetChild, direction, true);\n            };\n\n            if (!tabElement) return;\n\n            let targetTab: HTMLElement | null = null;\n\n            switch (direction) {\n                case 'next':\n                    targetTab = findAdjacentTab(tabElement, 'next');\n\n                    if (!targetTab) {\n                        targetTab = findBoundaryTab('first');\n                    }\n\n                    break;\n\n                case 'previous':\n                    targetTab = findAdjacentTab(tabElement, 'previous');\n\n                    if (!targetTab) {\n                        targetTab = findBoundaryTab('last');\n                    }\n\n                    break;\n\n                case 'first':\n                    targetTab = findBoundaryTab('first');\n                    break;\n\n                case 'last':\n                    targetTab = findBoundaryTab('last');\n                    break;\n            }\n\n            if (targetTab) {\n                focus(targetTab);\n            }\n        };\n\n        const onTabKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>, value: undefined | string | number) => {\n            switch (event.code) {\n                case 'ArrowRight':\n                    focusTab(event.currentTarget, 'next');\n                    break;\n\n                case 'ArrowLeft':\n                    focusTab(event.currentTarget, 'previous');\n                    break;\n\n                case 'Home':\n                    focusTab(event.currentTarget, 'first');\n                    break;\n\n                case 'End':\n                    focusTab(event.currentTarget, 'last');\n                    break;\n\n                case 'Enter':\n                case 'NumpadEnter':\n                case 'Space':\n                    updateValue(value);\n                    break;\n\n                case 'Tab':\n                    return;\n\n                default:\n                    break;\n            }\n\n            event.preventDefault();\n        };\n\n        const onTabClick = (event: React.MouseEvent<HTMLButtonElement>, value: undefined | string | number) => {\n            if (!props.selectOnFocus) {\n                updateValue(value);\n            }\n        };\n\n        const onTabFocus = (event: React.FocusEvent<HTMLButtonElement>, value: undefined | string | number) => {\n            if (props.selectOnFocus) {\n                updateValue(value);\n            }\n        };\n\n        // effects\n        React.useEffect(() => {\n            const raf = requestAnimationFrame(() => {\n                const dimensions = updateInkBar();\n\n                if (dimensions) {\n                    setInkBarDimensionsState(dimensions);\n                }\n            });\n\n            return () => cancelAnimationFrame(raf);\n        }, [activeTabState]);\n\n        return {\n            state,\n            // methods\n            updateValue,\n            isItemActive,\n            focusTab,\n            onTabKeyDown,\n            onTabClick,\n            onTabFocus\n        };\n    }\n});\n","import type { useTabsProps } from '@primereact/types/shared/tabs';\n\nexport const defaultProps: useTabsProps = {\n    value: undefined,\n    onValueChange: undefined,\n    selectOnFocus: false\n};\n"],"mappings":"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","names":["withHeadless","findSingle","focus","getAttribute","getOffset","getOuterHeight","getOuterWidth","React","defaultProps","useTabs","withHeadless","defaultProps","props","elementRef","_a","activeTabState","setActiveTabState","inkBarDimensionsState","setInkBarDimensionsState","state","updateValue","value","isItemActive","key","updateInkBar","tabs","activeTab","findSingle","scrollContainer","scrollLeft","activeTabOffset","getOffset","containerOffset","scrollContainerOffset","tabWidth","getOuterWidth","tabHeight","getOuterHeight","scrollContainerHeight","leftFromViewport","relativeLeft","relativeRight","relativeTop","relativeBottom","focusTab","tabElement","direction","findTab","listElement","findAdjacentTab","selfCheck","element","getAttribute","findBoundaryTab","boundary","tabSelector","targetChild","allTabs","targetTab","focus","onTabKeyDown","event","onTabClick","onTabFocus","raf","dimensions"]}