@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
146 lines (142 loc) • 5.15 kB
JavaScript
"use client";
import { createContext as createContext$1 } from "../../utils/context.js";
import { runKeyAction } from "../../utils/dom.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, useEffect, useId, useState } from "react";
//#region src/components/accordion/use-accordion.ts
const { DescendantsContext: AccordionDescendantsContext, useDescendant: useAccordionDescendant, useDescendants: useAccordionDescendants } = createDescendants();
const [AccordionContext, useAccordionContext] = createContext$1({ name: "AccordionContext" });
const [AccordionItemContext, useAccordionItemContext] = createContext$1({ name: "AccordionItemContext" });
const useAccordion = ({ defaultIndex: defaultIndexProp, index: indexProp, multiple, toggle, onChange,...rest } = {}) => {
if ((indexProp || defaultIndexProp) != null && !(0, utils_exports.isArray)(indexProp || defaultIndexProp) && multiple) console.warn(`Accordion: If 'multiple' is passed, then 'index' or 'defaultIndex' must be an array.`);
if (multiple && toggle) console.warn(`Accordion: If 'multiple' is passed, 'toggle' will be ignored. Either remove 'toggle' or 'multiple' depending on whether you want multiple accordions visible or not`);
const descendants = useAccordionDescendants();
const [focusedIndex, setFocusedIndex] = useState(-1);
const [index, setIndex] = useControllableState({
defaultValue: () => multiple ? defaultIndexProp ?? [] : defaultIndexProp ?? -1,
value: indexProp,
onChange
});
const getRootProps = useCallback(({ ref,...props } = {}) => ({
...props,
...rest,
ref: mergeRefs(ref, rest.ref)
}), [rest]);
useEffect(() => {
return () => setFocusedIndex(-1);
}, []);
return {
descendants,
focusedIndex,
index,
multiple,
setFocusedIndex,
setIndex,
toggle,
getRootProps
};
};
const useAccordionItem = ({ disabled, index,...rest }) => {
const itemId = useId();
const panelId = useId();
const { index: selectedIndex, multiple, setFocusedIndex, setIndex, toggle } = useAccordionContext();
const { descendants, register } = useAccordionDescendant({ disabled });
const open = index !== -1 ? (0, utils_exports.isArray)(selectedIndex) ? selectedIndex.includes(index) : selectedIndex === index : false;
if (open && disabled) console.warn(`Accordion: Cannot open a disabled accordion item`);
const onChange = useCallback((open$1) => {
if (index === -1) return;
if (multiple && (0, utils_exports.isArray)(selectedIndex)) setIndex(open$1 ? selectedIndex.concat(index) : selectedIndex.filter((i) => i !== index));
else if (open$1) setIndex(index);
else if (toggle) setIndex(-1);
}, [
multiple,
toggle,
index,
selectedIndex,
setIndex
]);
const onFocus = useCallback(() => {
setFocusedIndex(index);
}, [setFocusedIndex, index]);
const onClick = useCallback(() => {
onChange(!open);
setFocusedIndex(index);
}, [
index,
setFocusedIndex,
open,
onChange
]);
const onKeyDown = useCallback((ev) => {
runKeyAction(ev, {
ArrowDown: () => {
descendants.enabledNextValue(index)?.node.focus();
},
ArrowUp: () => {
descendants.enabledPrevValue(index)?.node.focus();
},
End: () => {
descendants.enabledLastValue()?.node.focus();
},
Home: () => {
descendants.enabledFirstValue()?.node.focus();
}
});
}, [descendants, index]);
const getItemProps = useCallback(({ ref,...props } = {}) => ({
"data-expanded": (0, utils_exports.dataAttr)(open),
...props,
...rest,
ref: mergeRefs(ref, rest.ref)
}), [open, rest]);
const getButtonProps = useCallback(({ ref,...props } = {}) => ({
id: itemId,
type: "button",
"aria-controls": panelId,
"aria-disabled": (0, utils_exports.ariaAttr)(!multiple && !toggle && open || disabled),
"aria-expanded": open,
...props,
ref: mergeRefs(register, ref),
disabled,
onClick: (0, utils_exports.handlerAll)(props.onClick, onClick),
onFocus: (0, utils_exports.handlerAll)(props.onFocus, onFocus),
onKeyDown: (0, utils_exports.handlerAll)(props.onKeyDown, onKeyDown)
}), [
itemId,
open,
panelId,
multiple,
toggle,
disabled,
register,
onClick,
onFocus,
onKeyDown
]);
const getPanelProps = useCallback(({ "aria-labelledby": ariaLabelledby,...props } = {}) => ({
id: panelId,
"aria-labelledby": (0, utils_exports.cx)(ariaLabelledby, itemId),
role: "region",
...props
}), [itemId, panelId]);
return {
disabled,
open,
getButtonProps,
getIconProps: useCallback((props) => ({
"aria-disabled": (0, utils_exports.ariaAttr)(disabled),
"aria-expanded": open,
"aria-hidden": true,
role: "presentation",
...props
}), [open, disabled]),
getItemProps,
getPanelProps
};
};
//#endregion
export { AccordionContext, AccordionDescendantsContext, AccordionItemContext, useAccordion, useAccordionContext, useAccordionDescendant, useAccordionDescendants, useAccordionItem, useAccordionItemContext };
//# sourceMappingURL=use-accordion.js.map