319 lines
11 KiB
JavaScript
319 lines
11 KiB
JavaScript
"use client";
|
|
|
|
// packages/react/accordion/src/Accordion.tsx
|
|
import React from "react";
|
|
import { createContextScope } from "@radix-ui/react-context";
|
|
import { createCollection } from "@radix-ui/react-collection";
|
|
import { useComposedRefs } from "@radix-ui/react-compose-refs";
|
|
import { composeEventHandlers } from "@radix-ui/primitive";
|
|
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
import { Primitive } from "@radix-ui/react-primitive";
|
|
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
import { createCollapsibleScope } from "@radix-ui/react-collapsible";
|
|
import { useId } from "@radix-ui/react-id";
|
|
import { useDirection } from "@radix-ui/react-direction";
|
|
import { jsx } from "react/jsx-runtime";
|
|
var ACCORDION_NAME = "Accordion";
|
|
var ACCORDION_KEYS = ["Home", "End", "ArrowDown", "ArrowUp", "ArrowLeft", "ArrowRight"];
|
|
var [Collection, useCollection, createCollectionScope] = createCollection(ACCORDION_NAME);
|
|
var [createAccordionContext, createAccordionScope] = createContextScope(ACCORDION_NAME, [
|
|
createCollectionScope,
|
|
createCollapsibleScope
|
|
]);
|
|
var useCollapsibleScope = createCollapsibleScope();
|
|
var Accordion = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { type, ...accordionProps } = props;
|
|
const singleProps = accordionProps;
|
|
const multipleProps = accordionProps;
|
|
return /* @__PURE__ */ jsx(Collection.Provider, { scope: props.__scopeAccordion, children: type === "multiple" ? /* @__PURE__ */ jsx(AccordionImplMultiple, { ...multipleProps, ref: forwardedRef }) : /* @__PURE__ */ jsx(AccordionImplSingle, { ...singleProps, ref: forwardedRef }) });
|
|
}
|
|
);
|
|
Accordion.displayName = ACCORDION_NAME;
|
|
var [AccordionValueProvider, useAccordionValueContext] = createAccordionContext(ACCORDION_NAME);
|
|
var [AccordionCollapsibleProvider, useAccordionCollapsibleContext] = createAccordionContext(
|
|
ACCORDION_NAME,
|
|
{ collapsible: false }
|
|
);
|
|
var AccordionImplSingle = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const {
|
|
value: valueProp,
|
|
defaultValue,
|
|
onValueChange = () => {
|
|
},
|
|
collapsible = false,
|
|
...accordionSingleProps
|
|
} = props;
|
|
const [value, setValue] = useControllableState({
|
|
prop: valueProp,
|
|
defaultProp: defaultValue,
|
|
onChange: onValueChange
|
|
});
|
|
return /* @__PURE__ */ jsx(
|
|
AccordionValueProvider,
|
|
{
|
|
scope: props.__scopeAccordion,
|
|
value: value ? [value] : [],
|
|
onItemOpen: setValue,
|
|
onItemClose: React.useCallback(() => collapsible && setValue(""), [collapsible, setValue]),
|
|
children: /* @__PURE__ */ jsx(AccordionCollapsibleProvider, { scope: props.__scopeAccordion, collapsible, children: /* @__PURE__ */ jsx(AccordionImpl, { ...accordionSingleProps, ref: forwardedRef }) })
|
|
}
|
|
);
|
|
}
|
|
);
|
|
var AccordionImplMultiple = React.forwardRef((props, forwardedRef) => {
|
|
const {
|
|
value: valueProp,
|
|
defaultValue,
|
|
onValueChange = () => {
|
|
},
|
|
...accordionMultipleProps
|
|
} = props;
|
|
const [value = [], setValue] = useControllableState({
|
|
prop: valueProp,
|
|
defaultProp: defaultValue,
|
|
onChange: onValueChange
|
|
});
|
|
const handleItemOpen = React.useCallback(
|
|
(itemValue) => setValue((prevValue = []) => [...prevValue, itemValue]),
|
|
[setValue]
|
|
);
|
|
const handleItemClose = React.useCallback(
|
|
(itemValue) => setValue((prevValue = []) => prevValue.filter((value2) => value2 !== itemValue)),
|
|
[setValue]
|
|
);
|
|
return /* @__PURE__ */ jsx(
|
|
AccordionValueProvider,
|
|
{
|
|
scope: props.__scopeAccordion,
|
|
value,
|
|
onItemOpen: handleItemOpen,
|
|
onItemClose: handleItemClose,
|
|
children: /* @__PURE__ */ jsx(AccordionCollapsibleProvider, { scope: props.__scopeAccordion, collapsible: true, children: /* @__PURE__ */ jsx(AccordionImpl, { ...accordionMultipleProps, ref: forwardedRef }) })
|
|
}
|
|
);
|
|
});
|
|
var [AccordionImplProvider, useAccordionContext] = createAccordionContext(ACCORDION_NAME);
|
|
var AccordionImpl = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeAccordion, disabled, dir, orientation = "vertical", ...accordionProps } = props;
|
|
const accordionRef = React.useRef(null);
|
|
const composedRefs = useComposedRefs(accordionRef, forwardedRef);
|
|
const getItems = useCollection(__scopeAccordion);
|
|
const direction = useDirection(dir);
|
|
const isDirectionLTR = direction === "ltr";
|
|
const handleKeyDown = composeEventHandlers(props.onKeyDown, (event) => {
|
|
if (!ACCORDION_KEYS.includes(event.key)) return;
|
|
const target = event.target;
|
|
const triggerCollection = getItems().filter((item) => !item.ref.current?.disabled);
|
|
const triggerIndex = triggerCollection.findIndex((item) => item.ref.current === target);
|
|
const triggerCount = triggerCollection.length;
|
|
if (triggerIndex === -1) return;
|
|
event.preventDefault();
|
|
let nextIndex = triggerIndex;
|
|
const homeIndex = 0;
|
|
const endIndex = triggerCount - 1;
|
|
const moveNext = () => {
|
|
nextIndex = triggerIndex + 1;
|
|
if (nextIndex > endIndex) {
|
|
nextIndex = homeIndex;
|
|
}
|
|
};
|
|
const movePrev = () => {
|
|
nextIndex = triggerIndex - 1;
|
|
if (nextIndex < homeIndex) {
|
|
nextIndex = endIndex;
|
|
}
|
|
};
|
|
switch (event.key) {
|
|
case "Home":
|
|
nextIndex = homeIndex;
|
|
break;
|
|
case "End":
|
|
nextIndex = endIndex;
|
|
break;
|
|
case "ArrowRight":
|
|
if (orientation === "horizontal") {
|
|
if (isDirectionLTR) {
|
|
moveNext();
|
|
} else {
|
|
movePrev();
|
|
}
|
|
}
|
|
break;
|
|
case "ArrowDown":
|
|
if (orientation === "vertical") {
|
|
moveNext();
|
|
}
|
|
break;
|
|
case "ArrowLeft":
|
|
if (orientation === "horizontal") {
|
|
if (isDirectionLTR) {
|
|
movePrev();
|
|
} else {
|
|
moveNext();
|
|
}
|
|
}
|
|
break;
|
|
case "ArrowUp":
|
|
if (orientation === "vertical") {
|
|
movePrev();
|
|
}
|
|
break;
|
|
}
|
|
const clampedIndex = nextIndex % triggerCount;
|
|
triggerCollection[clampedIndex].ref.current?.focus();
|
|
});
|
|
return /* @__PURE__ */ jsx(
|
|
AccordionImplProvider,
|
|
{
|
|
scope: __scopeAccordion,
|
|
disabled,
|
|
direction: dir,
|
|
orientation,
|
|
children: /* @__PURE__ */ jsx(Collection.Slot, { scope: __scopeAccordion, children: /* @__PURE__ */ jsx(
|
|
Primitive.div,
|
|
{
|
|
...accordionProps,
|
|
"data-orientation": orientation,
|
|
ref: composedRefs,
|
|
onKeyDown: disabled ? void 0 : handleKeyDown
|
|
}
|
|
) })
|
|
}
|
|
);
|
|
}
|
|
);
|
|
var ITEM_NAME = "AccordionItem";
|
|
var [AccordionItemProvider, useAccordionItemContext] = createAccordionContext(ITEM_NAME);
|
|
var AccordionItem = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeAccordion, value, ...accordionItemProps } = props;
|
|
const accordionContext = useAccordionContext(ITEM_NAME, __scopeAccordion);
|
|
const valueContext = useAccordionValueContext(ITEM_NAME, __scopeAccordion);
|
|
const collapsibleScope = useCollapsibleScope(__scopeAccordion);
|
|
const triggerId = useId();
|
|
const open = value && valueContext.value.includes(value) || false;
|
|
const disabled = accordionContext.disabled || props.disabled;
|
|
return /* @__PURE__ */ jsx(
|
|
AccordionItemProvider,
|
|
{
|
|
scope: __scopeAccordion,
|
|
open,
|
|
disabled,
|
|
triggerId,
|
|
children: /* @__PURE__ */ jsx(
|
|
CollapsiblePrimitive.Root,
|
|
{
|
|
"data-orientation": accordionContext.orientation,
|
|
"data-state": getState(open),
|
|
...collapsibleScope,
|
|
...accordionItemProps,
|
|
ref: forwardedRef,
|
|
disabled,
|
|
open,
|
|
onOpenChange: (open2) => {
|
|
if (open2) {
|
|
valueContext.onItemOpen(value);
|
|
} else {
|
|
valueContext.onItemClose(value);
|
|
}
|
|
}
|
|
}
|
|
)
|
|
}
|
|
);
|
|
}
|
|
);
|
|
AccordionItem.displayName = ITEM_NAME;
|
|
var HEADER_NAME = "AccordionHeader";
|
|
var AccordionHeader = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeAccordion, ...headerProps } = props;
|
|
const accordionContext = useAccordionContext(ACCORDION_NAME, __scopeAccordion);
|
|
const itemContext = useAccordionItemContext(HEADER_NAME, __scopeAccordion);
|
|
return /* @__PURE__ */ jsx(
|
|
Primitive.h3,
|
|
{
|
|
"data-orientation": accordionContext.orientation,
|
|
"data-state": getState(itemContext.open),
|
|
"data-disabled": itemContext.disabled ? "" : void 0,
|
|
...headerProps,
|
|
ref: forwardedRef
|
|
}
|
|
);
|
|
}
|
|
);
|
|
AccordionHeader.displayName = HEADER_NAME;
|
|
var TRIGGER_NAME = "AccordionTrigger";
|
|
var AccordionTrigger = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeAccordion, ...triggerProps } = props;
|
|
const accordionContext = useAccordionContext(ACCORDION_NAME, __scopeAccordion);
|
|
const itemContext = useAccordionItemContext(TRIGGER_NAME, __scopeAccordion);
|
|
const collapsibleContext = useAccordionCollapsibleContext(TRIGGER_NAME, __scopeAccordion);
|
|
const collapsibleScope = useCollapsibleScope(__scopeAccordion);
|
|
return /* @__PURE__ */ jsx(Collection.ItemSlot, { scope: __scopeAccordion, children: /* @__PURE__ */ jsx(
|
|
CollapsiblePrimitive.Trigger,
|
|
{
|
|
"aria-disabled": itemContext.open && !collapsibleContext.collapsible || void 0,
|
|
"data-orientation": accordionContext.orientation,
|
|
id: itemContext.triggerId,
|
|
...collapsibleScope,
|
|
...triggerProps,
|
|
ref: forwardedRef
|
|
}
|
|
) });
|
|
}
|
|
);
|
|
AccordionTrigger.displayName = TRIGGER_NAME;
|
|
var CONTENT_NAME = "AccordionContent";
|
|
var AccordionContent = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeAccordion, ...contentProps } = props;
|
|
const accordionContext = useAccordionContext(ACCORDION_NAME, __scopeAccordion);
|
|
const itemContext = useAccordionItemContext(CONTENT_NAME, __scopeAccordion);
|
|
const collapsibleScope = useCollapsibleScope(__scopeAccordion);
|
|
return /* @__PURE__ */ jsx(
|
|
CollapsiblePrimitive.Content,
|
|
{
|
|
role: "region",
|
|
"aria-labelledby": itemContext.triggerId,
|
|
"data-orientation": accordionContext.orientation,
|
|
...collapsibleScope,
|
|
...contentProps,
|
|
ref: forwardedRef,
|
|
style: {
|
|
["--radix-accordion-content-height"]: "var(--radix-collapsible-content-height)",
|
|
["--radix-accordion-content-width"]: "var(--radix-collapsible-content-width)",
|
|
...props.style
|
|
}
|
|
}
|
|
);
|
|
}
|
|
);
|
|
AccordionContent.displayName = CONTENT_NAME;
|
|
function getState(open) {
|
|
return open ? "open" : "closed";
|
|
}
|
|
var Root2 = Accordion;
|
|
var Item = AccordionItem;
|
|
var Header = AccordionHeader;
|
|
var Trigger2 = AccordionTrigger;
|
|
var Content2 = AccordionContent;
|
|
export {
|
|
Accordion,
|
|
AccordionContent,
|
|
AccordionHeader,
|
|
AccordionItem,
|
|
AccordionTrigger,
|
|
Content2 as Content,
|
|
Header,
|
|
Item,
|
|
Root2 as Root,
|
|
Trigger2 as Trigger,
|
|
createAccordionScope
|
|
};
|
|
//# sourceMappingURL=index.mjs.map
|