UNPKG

@loke/ui

Version:
2 lines (1 loc) 7.97 kB
import{Collapsible,CollapsibleContent,CollapsibleTrigger,createCollapsibleScope}from"@loke/ui/collapsible";import{createCollection}from"@loke/ui/collection";import{composeEventHandlers}from"@loke/ui/compose-events";import{useComposedRefs}from"@loke/ui/compose-refs";import{createContextScope}from"@loke/ui/context";import{Primitive}from"@loke/ui/primitive";import{useControllableState}from"@loke/ui/use-controllable-state";import{useDirection}from"@loke/ui/use-direction";import{useId}from"@loke/ui/use-id";import React from"react";import{jsx}from"react/jsx-runtime";var ACCORDION_NAME="Accordion",ACCORDION_KEYS=["Home","End","ArrowDown","ArrowUp","ArrowLeft","ArrowRight"],[Collection,useCollection,createCollectionScope]=createCollection(ACCORDION_NAME),[createAccordionContext,createAccordionScope]=createContextScope(ACCORDION_NAME,[createCollectionScope,createCollapsibleScope]),useCollapsibleScope=createCollapsibleScope(),Accordion=React.forwardRef((props,forwardedRef)=>{let{type,...accordionProps}=props,singleProps=accordionProps,multipleProps=accordionProps;return jsx(Collection.Provider,{scope:props.__scopeAccordion,children:type==="multiple"?jsx(AccordionImplMultiple,{...multipleProps,ref:forwardedRef}):jsx(AccordionImplSingle,{...singleProps,ref:forwardedRef})})});Accordion.displayName=ACCORDION_NAME;var[AccordionValueProvider,useAccordionValueContext]=createAccordionContext(ACCORDION_NAME),[AccordionCollapsibleProvider,useAccordionCollapsibleContext]=createAccordionContext(ACCORDION_NAME,{collapsible:!1}),AccordionImplSingle=React.forwardRef((props,forwardedRef)=>{let{value:valueProp,defaultValue,onValueChange=()=>{},collapsible=!1,...accordionSingleProps}=props,[value,setValue]=useControllableState({caller:ACCORDION_NAME,defaultProp:defaultValue??"",onChange:onValueChange,prop:valueProp});return jsx(AccordionValueProvider,{onItemClose:React.useCallback(()=>collapsible&&setValue(""),[collapsible,setValue]),onItemOpen:setValue,scope:props.__scopeAccordion,value:React.useMemo(()=>value?[value]:[],[value]),children:jsx(AccordionCollapsibleProvider,{collapsible,scope:props.__scopeAccordion,children:jsx(AccordionImpl,{...accordionSingleProps,ref:forwardedRef})})})}),AccordionImplMultiple=React.forwardRef((props,forwardedRef)=>{let{value:valueProp,defaultValue,onValueChange=()=>{},...accordionMultipleProps}=props,[value,setValue]=useControllableState({caller:ACCORDION_NAME,defaultProp:defaultValue??[],onChange:onValueChange,prop:valueProp}),handleItemOpen=React.useCallback((itemValue)=>setValue((prevValue=[])=>[...prevValue,itemValue]),[setValue]),handleItemClose=React.useCallback((itemValue)=>setValue((prevValue=[])=>prevValue.filter((v)=>v!==itemValue)),[setValue]);return jsx(AccordionValueProvider,{onItemClose:handleItemClose,onItemOpen:handleItemOpen,scope:props.__scopeAccordion,value,children:jsx(AccordionCollapsibleProvider,{collapsible:!0,scope:props.__scopeAccordion,children:jsx(AccordionImpl,{...accordionMultipleProps,ref:forwardedRef})})})}),[AccordionImplProvider,useAccordionContext]=createAccordionContext(ACCORDION_NAME),AccordionImpl=React.forwardRef((props,forwardedRef)=>{let{__scopeAccordion,disabled,dir,orientation="vertical",...accordionProps}=props,accordionRef=React.useRef(null),composedRefs=useComposedRefs(accordionRef,forwardedRef),getItems=useCollection(__scopeAccordion),isDirectionLTR=useDirection(dir)==="ltr",handleKeyDown=composeEventHandlers(props.onKeyDown,(event)=>{if(!ACCORDION_KEYS.includes(event.key))return;let target=event.target,triggerCollection=getItems().filter((item)=>!item.ref.current?.disabled),triggerIndex=triggerCollection.findIndex((item)=>item.ref.current===target),triggerCount=triggerCollection.length;if(triggerIndex===-1)return;event.preventDefault();let nextIndex=triggerIndex,homeIndex=0,endIndex=triggerCount-1,moveNext=()=>{if(nextIndex=triggerIndex+1,nextIndex>endIndex)nextIndex=homeIndex},movePrev=()=>{if(nextIndex=triggerIndex-1,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}let clampedIndex=nextIndex%triggerCount;triggerCollection[clampedIndex].ref.current?.focus()});return jsx(AccordionImplProvider,{direction:dir,disabled,orientation,scope:__scopeAccordion,children:jsx(Collection.Slot,{scope:__scopeAccordion,children:jsx(Primitive.div,{...accordionProps,"data-orientation":orientation,onKeyDown:disabled?void 0:handleKeyDown,ref:composedRefs})})})}),ITEM_NAME="AccordionItem",[AccordionItemProvider,useAccordionItemContext]=createAccordionContext(ITEM_NAME),AccordionItem=React.forwardRef((props,forwardedRef)=>{let{__scopeAccordion,value,...accordionItemProps}=props,accordionContext=useAccordionContext(ITEM_NAME,__scopeAccordion),valueContext=useAccordionValueContext(ITEM_NAME,__scopeAccordion),collapsibleScope=useCollapsibleScope(__scopeAccordion),triggerId=useId(),open=Boolean(value&&valueContext.value.includes(value)),disabled=accordionContext.disabled||props.disabled;return jsx(AccordionItemProvider,{disabled,open,scope:__scopeAccordion,triggerId,children:jsx(Collapsible,{"data-orientation":accordionContext.orientation,"data-state":getState(open),...collapsibleScope,...accordionItemProps,disabled,onOpenChange:(o)=>{if(o)valueContext.onItemOpen(value);else valueContext.onItemClose(value)},open,ref:forwardedRef})})});AccordionItem.displayName=ITEM_NAME;var HEADER_NAME="AccordionHeader",AccordionHeader=React.forwardRef((props,forwardedRef)=>{let{__scopeAccordion,...headerProps}=props,accordionContext=useAccordionContext(ACCORDION_NAME,__scopeAccordion),itemContext=useAccordionItemContext(HEADER_NAME,__scopeAccordion);return jsx(Primitive.h3,{"data-disabled":itemContext.disabled?"":void 0,"data-orientation":accordionContext.orientation,"data-state":getState(itemContext.open),...headerProps,ref:forwardedRef})});AccordionHeader.displayName=HEADER_NAME;var TRIGGER_NAME="AccordionTrigger",AccordionTrigger=React.forwardRef((props,forwardedRef)=>{let{__scopeAccordion,...triggerProps}=props,accordionContext=useAccordionContext(ACCORDION_NAME,__scopeAccordion),itemContext=useAccordionItemContext(TRIGGER_NAME,__scopeAccordion),collapsibleContext=useAccordionCollapsibleContext(TRIGGER_NAME,__scopeAccordion),collapsibleScope=useCollapsibleScope(__scopeAccordion);return jsx(Collection.ItemSlot,{scope:__scopeAccordion,children:jsx(CollapsibleTrigger,{"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",AccordionContent=React.forwardRef((props,forwardedRef)=>{let{__scopeAccordion,...contentProps}=props,accordionContext=useAccordionContext(ACCORDION_NAME,__scopeAccordion),itemContext=useAccordionItemContext(CONTENT_NAME,__scopeAccordion),collapsibleScope=useCollapsibleScope(__scopeAccordion);return jsx(CollapsibleContent,{"aria-labelledby":itemContext.triggerId,"data-orientation":accordionContext.orientation,role:"region",...collapsibleScope,...contentProps,ref:forwardedRef,style:{"--loke-accordion-content-height":"var(--loke-collapsible-content-height)","--loke-accordion-content-width":"var(--loke-collapsible-content-width)",...props.style}})});AccordionContent.displayName=CONTENT_NAME;function getState(open){return open?"open":"closed"}var Root=Accordion,Item=AccordionItem,Header=AccordionHeader,Trigger=AccordionTrigger,Content=AccordionContent;export{createAccordionScope,Trigger,Root,Item,Header,Content,AccordionTrigger,AccordionItem,AccordionHeader,AccordionContent,Accordion};