@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
179 lines (175 loc) • 5.59 kB
JavaScript
"use client";
import { createContext as createContext$1 } from "../../utils/context.js";
import { runKeyAction } from "../../utils/dom.js";
import { useUpdateEffect } from "../../utils/effect.js";
import { mergeRefs } from "../../utils/ref.js";
import { utils_exports } from "../../utils/index.js";
import { useControllableState } from "../../hooks/use-controllable-state/index.js";
import { createDescendants } from "../../hooks/use-descendants/index.js";
import { useCallback, useId, useState } from "react";
//#region src/components/tabs/use-tabs.ts
const { DescendantsContext: TabDescendantsContext, useDescendant: useTabDescendant, useDescendants: useTabDescendants } = createDescendants();
const { DescendantsContext: TabPanelDescendantsContext, useDescendant: useTabPanelDescendant, useDescendants: useTabPanelDescendants } = createDescendants();
const [TabsContext, useTabsContext] = createContext$1({ name: "TabsContext" });
const useTabs = ({ id, defaultIndex = 0, index: indexProp, manual = false, orientation = "horizontal", onChange,...rest } = {}) => {
const uuid = useId();
const tabDescendants = useTabDescendants();
const tabPanelDescendants = useTabPanelDescendants();
const [index, setIndex] = useControllableState({
defaultValue: defaultIndex,
value: indexProp,
onChange
});
const [focusedIndex, setFocusedIndex] = useState(index);
const horizontal = orientation === "horizontal";
id ??= uuid;
const onFocusFirstTab = useCallback(() => {
const first = tabDescendants.enabledFirstValue();
if (first) first.node.focus();
}, [tabDescendants]);
const onFocusLastTab = useCallback(() => {
const last = tabDescendants.enabledLastValue();
if (last) last.node.focus();
}, [tabDescendants]);
const onFocusNextTab = useCallback(() => {
const next = tabDescendants.enabledNextValue(focusedIndex);
if (next) next.node.focus();
}, [tabDescendants, focusedIndex]);
const onFocusPrevTab = useCallback(() => {
const prev = tabDescendants.enabledPrevValue(focusedIndex);
if (prev) prev.node.focus();
}, [tabDescendants, focusedIndex]);
const onKeyDown = useCallback((ev) => {
runKeyAction(ev, {
ArrowDown: !horizontal ? onFocusNextTab : void 0,
ArrowLeft: horizontal ? onFocusPrevTab : void 0,
ArrowRight: horizontal ? onFocusNextTab : void 0,
ArrowUp: !horizontal ? onFocusPrevTab : void 0,
End: onFocusLastTab,
Home: onFocusFirstTab
});
}, [
horizontal,
onFocusNextTab,
onFocusPrevTab,
onFocusLastTab,
onFocusFirstTab
]);
useUpdateEffect(() => {
if ((0, utils_exports.isUndefined)(indexProp)) return;
setIndex(indexProp);
setFocusedIndex(indexProp);
}, [indexProp]);
const getRootProps = useCallback(({ ref,...props } = {}) => ({
"data-orientation": orientation,
...rest,
...props,
ref: mergeRefs(ref, rest.ref)
}), [orientation, rest]);
const getListProps = useCallback((props = {}) => ({
"aria-orientation": orientation,
role: "tablist",
...props,
onKeyDown: (0, utils_exports.handlerAll)(props.onKeyDown, onKeyDown)
}), [orientation, onKeyDown]);
return {
id,
focusedIndex,
index,
manual,
orientation,
setFocusedIndex,
setIndex,
tabDescendants,
tabPanelDescendants,
getListProps,
getRootProps
};
};
const useTab = ({ id, disabled, index,...rest }) => {
const { id: rootId, index: selectedIndex, manual, orientation, setFocusedIndex, setIndex } = useTabsContext();
const { register } = useTabDescendant({ disabled });
const tabPanelId = `${rootId}-panel-${index}`;
const selected = index === selectedIndex;
id ??= `${rootId}-tab-${index}`;
const onClick = useCallback(() => {
if (!disabled) setIndex(index);
}, [
index,
setIndex,
disabled
]);
const onFocus = useCallback(() => {
if (disabled) return;
setFocusedIndex(index);
if (!manual) setIndex(index);
}, [
setFocusedIndex,
index,
manual,
disabled,
setIndex
]);
return {
index,
selected,
getRootProps: useCallback(({ ref,...props } = {}) => ({
id,
type: "button",
"aria-controls": tabPanelId,
"aria-selected": selected,
"data-orientation": orientation,
disabled,
role: "tab",
tabIndex: selected ? 0 : -1,
...rest,
...props,
ref: mergeRefs(ref, register),
onClick: (0, utils_exports.handlerAll)(props.onClick, rest.onClick, onClick),
onFocus: (0, utils_exports.handlerAll)(props.onFocus, rest.onFocus, onFocus)
}), [
disabled,
id,
onClick,
onFocus,
orientation,
register,
rest,
selected,
tabPanelId
])
};
};
const useTabPanel = ({ id, "aria-labelledby": ariaLabelledbyProp, index,...rest }) => {
const { id: rootId, index: selectedIndex, orientation } = useTabsContext();
const { register } = useTabPanelDescendant();
const tabId = `${rootId}-tab-${index}`;
const selected = index === selectedIndex;
id ??= `${rootId}-panel-${index}`;
return {
index,
selected,
getRootProps: useCallback(({ ref, "aria-labelledby": ariaLabelledby,...props } = {}) => ({
id,
"aria-labelledby": (0, utils_exports.cx)(ariaLabelledbyProp, ariaLabelledby, tabId),
"data-orientation": orientation,
hidden: !selected,
role: "tabpanel",
tabIndex: selected ? 0 : -1,
...rest,
...props,
ref: mergeRefs(ref, register)
}), [
id,
ariaLabelledbyProp,
orientation,
register,
rest,
selected,
tabId
])
};
};
//#endregion
export { TabDescendantsContext, TabPanelDescendantsContext, TabsContext, useTab, useTabDescendant, useTabDescendants, useTabPanel, useTabPanelDescendant, useTabPanelDescendants, useTabs, useTabsContext };
//# sourceMappingURL=use-tabs.js.map