@loke/ui
Version:
2 lines (1 loc) • 33.7 kB
JavaScript
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{DismissableLayer}from"@loke/ui/dismissable-layer";import{useFocusGuards}from"@loke/ui/focus-guards";import{FocusScope}from"@loke/ui/focus-scope";import{clamp}from"@loke/ui/number";import*as PopperPrimitive from"@loke/ui/popper";import{createPopperScope}from"@loke/ui/popper";import{Portal as PortalPrimitive}from"@loke/ui/portal";import{Primitive}from"@loke/ui/primitive";import{createSlot}from"@loke/ui/slot";import{useCallbackRef}from"@loke/ui/use-callback-ref";import{useControllableState}from"@loke/ui/use-controllable-state";import{useDirection}from"@loke/ui/use-direction";import{useId}from"@loke/ui/use-id";import{useLayoutEffect}from"@loke/ui/use-layout-effect";import{usePrevious}from"@loke/ui/use-previous";import{VISUALLY_HIDDEN_STYLES}from"@loke/ui/visually-hidden";import{hideOthers}from"aria-hidden";import{forwardRef,useCallback,useEffect,useMemo,useRef,useState}from"react";import ReactDOM from"react-dom";import{RemoveScroll}from"react-remove-scroll";import{jsx,jsxs,Fragment}from"react/jsx-runtime";var OPEN_KEYS=[" ","Enter","ArrowUp","ArrowDown"],SELECTION_KEYS=[" ","Enter"],SELECT_NAME="Select",[Collection,useCollection,createCollectionScope]=createCollection(SELECT_NAME),[createSelectContext,createSelectScope]=createContextScope(SELECT_NAME,[createCollectionScope,createPopperScope]),usePopperScope=createPopperScope(),[SelectProvider,useSelectContext]=createSelectContext(SELECT_NAME),[SelectNativeOptionsProvider,useSelectNativeOptionsContext]=createSelectContext(SELECT_NAME),Select=(props)=>{let{__scopeSelect,children,open:openProp,defaultOpen,onOpenChange,value:valueProp,defaultValue,onValueChange,dir,name,autoComplete,disabled,required,form}=props,popperScope=usePopperScope(__scopeSelect),[trigger,setTrigger]=useState(null),[valueNode,setValueNode]=useState(null),[valueNodeHasChildren,setValueNodeHasChildren]=useState(!1),direction=useDirection(dir),[open,setOpen]=useControllableState({caller:SELECT_NAME,defaultProp:defaultOpen??!1,onChange:onOpenChange,prop:openProp}),[value,setValue]=useControllableState({caller:SELECT_NAME,defaultProp:defaultValue,onChange:onValueChange,prop:valueProp}),triggerPointerDownPosRef=useRef(null),isFormControl=trigger?form||!!trigger.closest("form"):!0,[nativeOptionsSet,setNativeOptionsSet]=useState(new Set),nativeSelectKey=Array.from(nativeOptionsSet).map((option)=>option.props.value).join(";");return jsx(PopperPrimitive.Root,{...popperScope,children:jsxs(SelectProvider,{contentId:useId(),dir:direction,disabled,onOpenChange:setOpen,onTriggerChange:setTrigger,onValueChange:setValue,onValueNodeChange:setValueNode,onValueNodeHasChildrenChange:setValueNodeHasChildren,open,required,scope:__scopeSelect,trigger,triggerPointerDownPosRef,value,valueNode,valueNodeHasChildren,children:[jsx(Collection.Provider,{scope:__scopeSelect,children:jsx(SelectNativeOptionsProvider,{onNativeOptionAdd:useCallback((option)=>{setNativeOptionsSet((prev)=>new Set(prev).add(option))},[]),onNativeOptionRemove:useCallback((option)=>{setNativeOptionsSet((prev)=>{let optionsSet=new Set(prev);return optionsSet.delete(option),optionsSet})},[]),scope:props.__scopeSelect,children})}),isFormControl?jsxs(SelectBubbleInput,{"aria-hidden":!0,autoComplete,disabled,form,name,onChange:(event)=>setValue(event.target.value),required,tabIndex:-1,value,children:[value===void 0?jsx("option",{value:""}):null,Array.from(nativeOptionsSet)]},nativeSelectKey):null]})})};Select.displayName=SELECT_NAME;var TRIGGER_NAME="SelectTrigger",SelectTrigger=forwardRef((props,forwardedRef)=>{let{__scopeSelect,disabled=!1,...triggerProps}=props,popperScope=usePopperScope(__scopeSelect),context=useSelectContext(TRIGGER_NAME,__scopeSelect),isDisabled=context.disabled||disabled,composedRefs=useComposedRefs(forwardedRef,context.onTriggerChange),getItems=useCollection(__scopeSelect),pointerTypeRef=useRef("touch"),[searchRef,handleTypeaheadSearch,resetTypeahead]=useTypeaheadSearch((search)=>{let enabledItems=getItems().filter((item)=>!item.disabled),currentItem=enabledItems.find((item)=>item.value===context.value),nextItem=findNextItem(enabledItems,search,currentItem);if(nextItem!==void 0)context.onValueChange(nextItem.value)}),handleOpen=(pointerEvent)=>{if(!isDisabled)context.onOpenChange(!0),resetTypeahead();if(pointerEvent)context.triggerPointerDownPosRef.current={x:Math.round(pointerEvent.pageX),y:Math.round(pointerEvent.pageY)}};return jsx(PopperPrimitive.Anchor,{asChild:!0,...popperScope,children:jsx(Primitive.button,{"aria-autocomplete":"none","aria-controls":context.contentId,"aria-expanded":context.open,"aria-required":context.required,"data-disabled":isDisabled?"":void 0,"data-placeholder":shouldShowPlaceholder(context.value)?"":void 0,"data-state":context.open?"open":"closed",dir:context.dir,disabled:isDisabled,role:"combobox",type:"button",...triggerProps,onClick:composeEventHandlers(triggerProps.onClick,(event)=>{if(event.currentTarget.focus(),pointerTypeRef.current!=="mouse")handleOpen(event)}),onKeyDown:composeEventHandlers(triggerProps.onKeyDown,(event)=>{let isTypingAhead=searchRef.current!=="";if(!(event.ctrlKey||event.altKey||event.metaKey)&&event.key.length===1)handleTypeaheadSearch(event.key);if(isTypingAhead&&event.key===" ")return;if(OPEN_KEYS.includes(event.key))handleOpen(),event.preventDefault()}),onPointerDown:composeEventHandlers(triggerProps.onPointerDown,(event)=>{pointerTypeRef.current=event.pointerType;let target=event.target;if(target.hasPointerCapture(event.pointerId))target.releasePointerCapture(event.pointerId);if(event.button===0&&event.ctrlKey===!1&&event.pointerType==="mouse")handleOpen(event),event.preventDefault()}),ref:composedRefs})})});SelectTrigger.displayName=TRIGGER_NAME;var VALUE_NAME="SelectValue",SelectValue=forwardRef((props,forwardedRef)=>{let{__scopeSelect,className,style,children,placeholder="",...valueProps}=props,context=useSelectContext(VALUE_NAME,__scopeSelect),{onValueNodeHasChildrenChange}=context,hasChildren=children!==void 0,composedRefs=useComposedRefs(forwardedRef,context.onValueNodeChange);return useLayoutEffect(()=>{onValueNodeHasChildrenChange(hasChildren)},[onValueNodeHasChildrenChange,hasChildren]),jsx(Primitive.span,{...valueProps,ref:composedRefs,style:{pointerEvents:"none"},children:shouldShowPlaceholder(context.value)?placeholder:children})});SelectValue.displayName=VALUE_NAME;var ICON_NAME="SelectIcon",SelectIcon=forwardRef((props,forwardedRef)=>{let{__scopeSelect,children,...iconProps}=props;return jsx(Primitive.span,{"aria-hidden":!0,...iconProps,ref:forwardedRef,children:children||"▼"})});SelectIcon.displayName=ICON_NAME;var PORTAL_NAME="SelectPortal",SelectPortal=(props)=>{return jsx(PortalPrimitive,{asChild:!0,...props})};SelectPortal.displayName=PORTAL_NAME;var CONTENT_NAME="SelectContent",SelectContent=forwardRef((props,forwardedRef)=>{let context=useSelectContext(CONTENT_NAME,props.__scopeSelect),[fragment,setFragment]=useState();if(useLayoutEffect(()=>{setFragment(new DocumentFragment)},[]),!context.open){let frag=fragment;return frag?ReactDOM.createPortal(jsx(SelectContentProvider,{scope:props.__scopeSelect,children:jsx(Collection.Slot,{scope:props.__scopeSelect,children:jsx("div",{children:props.children})})}),frag):null}return jsx(SelectContentImpl,{...props,ref:forwardedRef})});SelectContent.displayName=CONTENT_NAME;var CONTENT_MARGIN=10,[SelectContentProvider,useSelectContentContext]=createSelectContext(CONTENT_NAME),CONTENT_IMPL_NAME="SelectContentImpl",Slot=createSlot("SelectContent.RemoveScroll"),SelectContentImpl=forwardRef((props,forwardedRef)=>{let{__scopeSelect,position="item-aligned",onCloseAutoFocus,onEscapeKeyDown,onPointerDownOutside,side,sideOffset,align,alignOffset,arrowPadding,collisionBoundary,collisionPadding,sticky,hideWhenDetached,avoidCollisions,...contentProps}=props,context=useSelectContext(CONTENT_NAME,__scopeSelect),[content,setContent]=useState(null),[viewport,setViewport]=useState(null),composedRefs=useComposedRefs(forwardedRef,(node)=>setContent(node)),[selectedItem,setSelectedItem]=useState(null),[selectedItemText,setSelectedItemText]=useState(null),getItems=useCollection(__scopeSelect),[isPositioned,setIsPositioned]=useState(!1),firstValidItemFoundRef=useRef(!1);useEffect(()=>{if(content)return hideOthers(content)},[content]),useFocusGuards();let focusFirst=useCallback((candidates)=>{let[firstItem,...restItems]=getItems().map((item)=>item.ref.current),[lastItem]=restItems.slice(-1),PREVIOUSLY_FOCUSED_ELEMENT=document.activeElement;for(let candidate of candidates){if(candidate===PREVIOUSLY_FOCUSED_ELEMENT)return;if(candidate?.scrollIntoView({block:"nearest"}),candidate===firstItem&&viewport)viewport.scrollTop=0;if(candidate===lastItem&&viewport)viewport.scrollTop=viewport.scrollHeight;if(candidate?.focus(),document.activeElement!==PREVIOUSLY_FOCUSED_ELEMENT)return}},[getItems,viewport]),focusSelectedItem=useCallback(()=>focusFirst([selectedItem,content]),[focusFirst,selectedItem,content]);useEffect(()=>{if(isPositioned)focusSelectedItem()},[isPositioned,focusSelectedItem]);let{onOpenChange,triggerPointerDownPosRef}=context;useEffect(()=>{if(content){let pointerMoveDelta={x:0,y:0},handlePointerMove=(event)=>{pointerMoveDelta={x:Math.abs(Math.round(event.pageX)-(triggerPointerDownPosRef.current?.x??0)),y:Math.abs(Math.round(event.pageY)-(triggerPointerDownPosRef.current?.y??0))}},handlePointerUp=(event)=>{if(pointerMoveDelta.x<=10&&pointerMoveDelta.y<=10)event.preventDefault();else if(!content.contains(event.target))onOpenChange(!1);document.removeEventListener("pointermove",handlePointerMove),triggerPointerDownPosRef.current=null};if(triggerPointerDownPosRef.current!==null)document.addEventListener("pointermove",handlePointerMove),document.addEventListener("pointerup",handlePointerUp,{capture:!0,once:!0});return()=>{document.removeEventListener("pointermove",handlePointerMove),document.removeEventListener("pointerup",handlePointerUp,{capture:!0})}}},[content,onOpenChange,triggerPointerDownPosRef]),useEffect(()=>{let close=()=>onOpenChange(!1);return window.addEventListener("blur",close),window.addEventListener("resize",close),()=>{window.removeEventListener("blur",close),window.removeEventListener("resize",close)}},[onOpenChange]);let[searchRef,handleTypeaheadSearch]=useTypeaheadSearch((search)=>{let enabledItems=getItems().filter((item)=>!item.disabled),currentItem=enabledItems.find((item)=>item.ref.current===document.activeElement),nextItem=findNextItem(enabledItems,search,currentItem);if(nextItem)setTimeout(()=>nextItem.ref.current.focus())}),itemRefCallback=useCallback((node,value,disabled)=>{let isFirstValidItem=!(firstValidItemFoundRef.current||disabled);if(context.value!==void 0&&context.value===value||isFirstValidItem){if(setSelectedItem(node),isFirstValidItem)firstValidItemFoundRef.current=!0}},[context.value]),handleItemLeave=useCallback(()=>content?.focus(),[content]),itemTextRefCallback=useCallback((node,value,disabled)=>{let isFirstValidItem=!(firstValidItemFoundRef.current||disabled);if(context.value!==void 0&&context.value===value||isFirstValidItem)setSelectedItemText(node)},[context.value]),SelectPosition=position==="popper"?SelectPopperPosition:SelectItemAlignedPosition,popperContentProps=SelectPosition===SelectPopperPosition?{align,alignOffset,arrowPadding,avoidCollisions,collisionBoundary,collisionPadding,hideWhenDetached,side,sideOffset,sticky}:{};return jsx(SelectContentProvider,{content,focusSelectedItem,isPositioned,itemRefCallback,itemTextRefCallback,onItemLeave:handleItemLeave,onViewportChange:setViewport,position,scope:__scopeSelect,searchRef,selectedItem,selectedItemText,viewport,children:jsx(RemoveScroll,{allowPinchZoom:!0,as:Slot,children:jsx(FocusScope,{asChild:!0,onMountAutoFocus:(event)=>{event.preventDefault()},onUnmountAutoFocus:composeEventHandlers(onCloseAutoFocus,(event)=>{context.trigger?.focus({preventScroll:!0}),event.preventDefault()}),trapped:context.open,children:jsx(DismissableLayer,{asChild:!0,disableOutsidePointerEvents:!0,onDismiss:()=>context.onOpenChange(!1),onEscapeKeyDown,onFocusOutside:(event)=>event.preventDefault(),onPointerDownOutside,children:jsx(SelectPosition,{"data-state":context.open?"open":"closed",dir:context.dir,id:context.contentId,onContextMenu:(event)=>event.preventDefault(),role:"listbox",...contentProps,...popperContentProps,onKeyDown:composeEventHandlers(contentProps.onKeyDown,(event)=>{let isModifierKey=event.ctrlKey||event.altKey||event.metaKey;if(event.key==="Tab")event.preventDefault();if(!isModifierKey&&event.key.length===1)handleTypeaheadSearch(event.key);if(["ArrowUp","ArrowDown","Home","End"].includes(event.key)){let candidateNodes=getItems().filter((item)=>!item.disabled).flatMap((item)=>item.ref.current?[item.ref.current]:[]);if(["ArrowUp","End"].includes(event.key))candidateNodes=candidateNodes.slice().reverse();if(["ArrowUp","ArrowDown"].includes(event.key)){let currentElement=event.target,currentIndex=candidateNodes.indexOf(currentElement);candidateNodes=candidateNodes.slice(currentIndex+1)}setTimeout(()=>focusFirst(candidateNodes)),event.preventDefault()}}),onPlaced:()=>setIsPositioned(!0),ref:composedRefs,style:{display:"flex",flexDirection:"column",outline:"none",...contentProps.style}})})})})})});SelectContentImpl.displayName=CONTENT_IMPL_NAME;var ITEM_ALIGNED_POSITION_NAME="SelectItemAlignedPosition",SelectItemAlignedPosition=forwardRef((props,forwardedRef)=>{let{__scopeSelect,onPlaced,...popperProps}=props,context=useSelectContext(CONTENT_NAME,__scopeSelect),contentContext=useSelectContentContext(CONTENT_NAME,__scopeSelect),[contentWrapper,setContentWrapper]=useState(null),[content,setContent]=useState(null),composedRefs=useComposedRefs(forwardedRef,(node)=>setContent(node)),getItems=useCollection(__scopeSelect),shouldExpandOnScrollRef=useRef(!1),shouldRepositionRef=useRef(!0),{viewport,selectedItem,selectedItemText,focusSelectedItem}=contentContext,position=useCallback(()=>{if(context.trigger&&context.valueNode&&contentWrapper&&content&&viewport&&selectedItem&&selectedItemText){let triggerRect=context.trigger.getBoundingClientRect(),contentRect=content.getBoundingClientRect(),valueNodeRect=context.valueNode.getBoundingClientRect(),itemTextRect=selectedItemText.getBoundingClientRect();if(context.dir!=="rtl"){let itemTextOffset=itemTextRect.left-contentRect.left,left=valueNodeRect.left-itemTextOffset,leftDelta=triggerRect.left-left,minContentWidth=triggerRect.width+leftDelta,contentWidth=Math.max(minContentWidth,contentRect.width),rightEdge=window.innerWidth-CONTENT_MARGIN,clampedLeft=clamp(left,[CONTENT_MARGIN,Math.max(CONTENT_MARGIN,rightEdge-contentWidth)]);contentWrapper.style.minWidth=`${minContentWidth}px`,contentWrapper.style.left=`${clampedLeft}px`}else{let itemTextOffset=contentRect.right-itemTextRect.right,right=window.innerWidth-valueNodeRect.right-itemTextOffset,rightDelta=window.innerWidth-triggerRect.right-right,minContentWidth=triggerRect.width+rightDelta,contentWidth=Math.max(minContentWidth,contentRect.width),leftEdge=window.innerWidth-CONTENT_MARGIN,clampedRight=clamp(right,[CONTENT_MARGIN,Math.max(CONTENT_MARGIN,leftEdge-contentWidth)]);contentWrapper.style.minWidth=`${minContentWidth}px`,contentWrapper.style.right=`${clampedRight}px`}let items=getItems(),availableHeight=window.innerHeight-CONTENT_MARGIN*2,itemsHeight=viewport.scrollHeight,contentStyles=window.getComputedStyle(content),contentBorderTopWidth=Number.parseInt(contentStyles.borderTopWidth,10),contentPaddingTop=Number.parseInt(contentStyles.paddingTop,10),contentBorderBottomWidth=Number.parseInt(contentStyles.borderBottomWidth,10),contentPaddingBottom=Number.parseInt(contentStyles.paddingBottom,10),fullContentHeight=contentBorderTopWidth+contentPaddingTop+itemsHeight+contentPaddingBottom+contentBorderBottomWidth,minContentHeight=Math.min(selectedItem.offsetHeight*5,fullContentHeight),viewportStyles=window.getComputedStyle(viewport),viewportPaddingTop=Number.parseInt(viewportStyles.paddingTop,10),viewportPaddingBottom=Number.parseInt(viewportStyles.paddingBottom,10),topEdgeToTriggerMiddle=triggerRect.top+triggerRect.height/2-CONTENT_MARGIN,triggerMiddleToBottomEdge=availableHeight-topEdgeToTriggerMiddle,selectedItemHalfHeight=selectedItem.offsetHeight/2,itemOffsetMiddle=selectedItem.offsetTop+selectedItemHalfHeight,contentTopToItemMiddle=contentBorderTopWidth+contentPaddingTop+itemOffsetMiddle,itemMiddleToContentBottom=fullContentHeight-contentTopToItemMiddle;if(contentTopToItemMiddle<=topEdgeToTriggerMiddle){let lastItem=items.at(-1),isLastItem=lastItem!=null&&selectedItem===lastItem.ref.current;contentWrapper.style.bottom="0px";let viewportOffsetBottom=content.clientHeight-viewport.offsetTop-viewport.offsetHeight,clampedTriggerMiddleToBottomEdge=Math.max(triggerMiddleToBottomEdge,selectedItemHalfHeight+(isLastItem?viewportPaddingBottom:0)+viewportOffsetBottom+contentBorderBottomWidth),height=contentTopToItemMiddle+clampedTriggerMiddleToBottomEdge;contentWrapper.style.height=`${height}px`}else{let firstItem=items[0],isFirstItem=firstItem!=null&&selectedItem===firstItem.ref.current;contentWrapper.style.top="0px";let height=Math.max(topEdgeToTriggerMiddle,contentBorderTopWidth+viewport.offsetTop+(isFirstItem?viewportPaddingTop:0)+selectedItemHalfHeight)+itemMiddleToContentBottom;contentWrapper.style.height=`${height}px`,viewport.scrollTop=contentTopToItemMiddle-topEdgeToTriggerMiddle+viewport.offsetTop}contentWrapper.style.margin=`${CONTENT_MARGIN}px 0`,contentWrapper.style.minHeight=`${minContentHeight}px`,contentWrapper.style.maxHeight=`${availableHeight}px`,onPlaced?.(),requestAnimationFrame(()=>shouldExpandOnScrollRef.current=!0)}},[getItems,context.trigger,context.valueNode,contentWrapper,content,viewport,selectedItem,selectedItemText,context.dir,onPlaced]);useLayoutEffect(()=>position(),[position]);let[contentZIndex,setContentZIndex]=useState();useLayoutEffect(()=>{if(content)setContentZIndex(window.getComputedStyle(content).zIndex)},[content]);let handleScrollButtonChange=useCallback((node)=>{if(node&&shouldRepositionRef.current===!0)position(),focusSelectedItem?.(),shouldRepositionRef.current=!1},[position,focusSelectedItem]);return jsx(SelectViewportProvider,{contentWrapper,onScrollButtonChange:handleScrollButtonChange,scope:__scopeSelect,shouldExpandOnScrollRef,children:jsx("div",{ref:setContentWrapper,style:{display:"flex",flexDirection:"column",position:"fixed",zIndex:contentZIndex},children:jsx(Primitive.div,{...popperProps,ref:composedRefs,style:{boxSizing:"border-box",maxHeight:"100%",...popperProps.style}})})})});SelectItemAlignedPosition.displayName=ITEM_ALIGNED_POSITION_NAME;var POPPER_POSITION_NAME="SelectPopperPosition",SelectPopperPosition=forwardRef((props,forwardedRef)=>{let{__scopeSelect,align="start",collisionPadding=CONTENT_MARGIN,...popperProps}=props,popperScope=usePopperScope(__scopeSelect);return jsx(PopperPrimitive.Content,{...popperScope,...popperProps,align,collisionPadding,ref:forwardedRef,style:{boxSizing:"border-box",...popperProps.style,...{"--loke-select-content-available-height":"var(--loke-popper-available-height)","--loke-select-content-available-width":"var(--loke-popper-available-width)","--loke-select-content-transform-origin":"var(--loke-popper-transform-origin)","--loke-select-trigger-height":"var(--loke-popper-anchor-height)","--loke-select-trigger-width":"var(--loke-popper-anchor-width)"}}})});SelectPopperPosition.displayName=POPPER_POSITION_NAME;var[SelectViewportProvider,useSelectViewportContext]=createSelectContext(CONTENT_NAME,{}),VIEWPORT_NAME="SelectViewport",SelectViewport=forwardRef((props,forwardedRef)=>{let{__scopeSelect,nonce,...viewportProps}=props,contentContext=useSelectContentContext(VIEWPORT_NAME,__scopeSelect),viewportContext=useSelectViewportContext(VIEWPORT_NAME,__scopeSelect),composedRefs=useComposedRefs(forwardedRef,contentContext.onViewportChange),prevScrollTopRef=useRef(0);return jsxs(Fragment,{children:[jsx("style",{dangerouslySetInnerHTML:{__html:"[data-loke-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-loke-select-viewport]::-webkit-scrollbar{display:none}"},nonce}),jsx(Collection.Slot,{scope:__scopeSelect,children:jsx(Primitive.div,{"data-loke-select-viewport":"",role:"presentation",...viewportProps,onScroll:composeEventHandlers(viewportProps.onScroll,(event)=>{let viewport=event.currentTarget,{contentWrapper,shouldExpandOnScrollRef}=viewportContext;if(shouldExpandOnScrollRef?.current&&contentWrapper){let scrolledBy=Math.abs(prevScrollTopRef.current-viewport.scrollTop);if(scrolledBy>0){let availableHeight=window.innerHeight-CONTENT_MARGIN*2,cssMinHeight=Number.parseFloat(contentWrapper.style.minHeight),cssHeight=Number.parseFloat(contentWrapper.style.height),prevHeight=Math.max(cssMinHeight,cssHeight);if(prevHeight<availableHeight){let nextHeight=prevHeight+scrolledBy,clampedNextHeight=Math.min(availableHeight,nextHeight),heightDiff=nextHeight-clampedNextHeight;if(contentWrapper.style.height=`${clampedNextHeight}px`,contentWrapper.style.bottom==="0px")viewport.scrollTop=heightDiff>0?heightDiff:0,contentWrapper.style.justifyContent="flex-end"}}}prevScrollTopRef.current=viewport.scrollTop}),ref:composedRefs,style:{flex:1,overflow:"hidden auto",position:"relative",...viewportProps.style}})})]})});SelectViewport.displayName=VIEWPORT_NAME;var GROUP_NAME="SelectGroup",[SelectGroupContextProvider,useSelectGroupContext]=createSelectContext(GROUP_NAME),SelectGroup=forwardRef((props,forwardedRef)=>{let{__scopeSelect,...groupProps}=props,groupId=useId();return jsx(SelectGroupContextProvider,{id:groupId,scope:__scopeSelect,children:jsx(Primitive.div,{"aria-labelledby":groupId,role:"group",...groupProps,ref:forwardedRef})})});SelectGroup.displayName=GROUP_NAME;var LABEL_NAME="SelectLabel",SelectLabel=forwardRef((props,forwardedRef)=>{let{__scopeSelect,...labelProps}=props,groupContext=useSelectGroupContext(LABEL_NAME,__scopeSelect);return jsx(Primitive.div,{id:groupContext.id,...labelProps,ref:forwardedRef})});SelectLabel.displayName=LABEL_NAME;var ITEM_NAME="SelectItem",[SelectItemContextProvider,useSelectItemContext]=createSelectContext(ITEM_NAME),SelectItem=forwardRef((props,forwardedRef)=>{let{__scopeSelect,value,disabled=!1,textValue:textValueProp,...itemProps}=props,context=useSelectContext(ITEM_NAME,__scopeSelect),contentContext=useSelectContentContext(ITEM_NAME,__scopeSelect),isSelected=context.value===value,[textValue,setTextValue]=useState(textValueProp??""),[isFocused,setIsFocused]=useState(!1),composedRefs=useComposedRefs(forwardedRef,(node)=>contentContext.itemRefCallback?.(node,value,disabled)),textId=useId(),pointerTypeRef=useRef("touch"),handleSelect=()=>{if(!disabled)context.onValueChange(value),context.onOpenChange(!1)};if(value==="")throw Error("A <Select.Item /> must have a value prop that is not an empty string. This is because the Select value can be set to an empty string to clear the selection and show the placeholder.");return jsx(SelectItemContextProvider,{disabled,isSelected,onItemTextChange:useCallback((node)=>{setTextValue((prevTextValue)=>prevTextValue||(node?.textContent??"").trim())},[]),scope:__scopeSelect,textId,value,children:jsx(Collection.ItemSlot,{disabled,scope:__scopeSelect,textValue,value,children:jsx(Primitive.div,{"aria-disabled":disabled||void 0,"aria-labelledby":textId,"aria-selected":isSelected&&isFocused,"data-disabled":disabled?"":void 0,"data-highlighted":isFocused?"":void 0,"data-state":isSelected?"checked":"unchecked",role:"option",tabIndex:disabled?void 0:-1,...itemProps,onBlur:composeEventHandlers(itemProps.onBlur,()=>setIsFocused(!1)),onClick:composeEventHandlers(itemProps.onClick,()=>{if(pointerTypeRef.current!=="mouse")handleSelect()}),onFocus:composeEventHandlers(itemProps.onFocus,()=>setIsFocused(!0)),onKeyDown:composeEventHandlers(itemProps.onKeyDown,(event)=>{if(contentContext.searchRef?.current!==""&&event.key===" ")return;if(SELECTION_KEYS.includes(event.key))handleSelect();if(event.key===" ")event.preventDefault()}),onPointerDown:composeEventHandlers(itemProps.onPointerDown,(event)=>{pointerTypeRef.current=event.pointerType}),onPointerLeave:composeEventHandlers(itemProps.onPointerLeave,(event)=>{if(event.currentTarget===document.activeElement)contentContext.onItemLeave?.()}),onPointerMove:composeEventHandlers(itemProps.onPointerMove,(event)=>{if(pointerTypeRef.current=event.pointerType,disabled)contentContext.onItemLeave?.();else if(pointerTypeRef.current==="mouse")event.currentTarget.focus({preventScroll:!0})}),onPointerUp:composeEventHandlers(itemProps.onPointerUp,()=>{if(pointerTypeRef.current==="mouse")handleSelect()}),ref:composedRefs})})})});SelectItem.displayName=ITEM_NAME;var ITEM_TEXT_NAME="SelectItemText",SelectItemText=forwardRef((props,forwardedRef)=>{let{__scopeSelect,className,style,...itemTextProps}=props,context=useSelectContext(ITEM_TEXT_NAME,__scopeSelect),contentContext=useSelectContentContext(ITEM_TEXT_NAME,__scopeSelect),itemContext=useSelectItemContext(ITEM_TEXT_NAME,__scopeSelect),nativeOptionsContext=useSelectNativeOptionsContext(ITEM_TEXT_NAME,__scopeSelect),[itemTextNode,setItemTextNode]=useState(null),composedRefs=useComposedRefs(forwardedRef,(node)=>setItemTextNode(node),itemContext.onItemTextChange,(node)=>contentContext.itemTextRefCallback?.(node,itemContext.value,itemContext.disabled)),textContent=itemTextNode?.textContent,nativeOption=useMemo(()=>jsx("option",{disabled:itemContext.disabled,value:itemContext.value,children:textContent},itemContext.value),[itemContext.disabled,itemContext.value,textContent]),{onNativeOptionAdd,onNativeOptionRemove}=nativeOptionsContext;return useLayoutEffect(()=>{return onNativeOptionAdd(nativeOption),()=>onNativeOptionRemove(nativeOption)},[onNativeOptionAdd,onNativeOptionRemove,nativeOption]),jsxs(Fragment,{children:[jsx(Primitive.span,{id:itemContext.textId,...itemTextProps,ref:composedRefs}),itemContext.isSelected&&context.valueNode&&!context.valueNodeHasChildren?ReactDOM.createPortal(itemTextProps.children,context.valueNode):null]})});SelectItemText.displayName=ITEM_TEXT_NAME;var ITEM_INDICATOR_NAME="SelectItemIndicator",SelectItemIndicator=forwardRef((props,forwardedRef)=>{let{__scopeSelect,...itemIndicatorProps}=props;return useSelectItemContext(ITEM_INDICATOR_NAME,__scopeSelect).isSelected?jsx(Primitive.span,{"aria-hidden":!0,...itemIndicatorProps,ref:forwardedRef}):null});SelectItemIndicator.displayName=ITEM_INDICATOR_NAME;var SCROLL_UP_BUTTON_NAME="SelectScrollUpButton",SelectScrollUpButton=forwardRef((props,forwardedRef)=>{let contentContext=useSelectContentContext(SCROLL_UP_BUTTON_NAME,props.__scopeSelect),viewportContext=useSelectViewportContext(SCROLL_UP_BUTTON_NAME,props.__scopeSelect),[canScrollUp,setCanScrollUp]=useState(!1),composedRefs=useComposedRefs(forwardedRef,viewportContext.onScrollButtonChange);return useLayoutEffect(()=>{if(contentContext.viewport&&contentContext.isPositioned){let handleScroll=function(){let canScrollUpwards=viewport.scrollTop>0;setCanScrollUp(canScrollUpwards)},viewport=contentContext.viewport;return handleScroll(),viewport.addEventListener("scroll",handleScroll),()=>viewport.removeEventListener("scroll",handleScroll)}},[contentContext.viewport,contentContext.isPositioned]),canScrollUp?jsx(SelectScrollButtonImpl,{...props,onAutoScroll:()=>{let{viewport,selectedItem}=contentContext;if(viewport&&selectedItem)viewport.scrollTop-=selectedItem.offsetHeight},ref:composedRefs}):null});SelectScrollUpButton.displayName=SCROLL_UP_BUTTON_NAME;var SCROLL_DOWN_BUTTON_NAME="SelectScrollDownButton",SelectScrollDownButton=forwardRef((props,forwardedRef)=>{let contentContext=useSelectContentContext(SCROLL_DOWN_BUTTON_NAME,props.__scopeSelect),viewportContext=useSelectViewportContext(SCROLL_DOWN_BUTTON_NAME,props.__scopeSelect),[canScrollDown,setCanScrollDown]=useState(!1),composedRefs=useComposedRefs(forwardedRef,viewportContext.onScrollButtonChange);return useLayoutEffect(()=>{if(contentContext.viewport&&contentContext.isPositioned){let handleScroll=function(){let maxScroll=viewport.scrollHeight-viewport.clientHeight,canScrollDownwards=Math.ceil(viewport.scrollTop)<maxScroll;setCanScrollDown(canScrollDownwards)},viewport=contentContext.viewport;return handleScroll(),viewport.addEventListener("scroll",handleScroll),()=>viewport.removeEventListener("scroll",handleScroll)}},[contentContext.viewport,contentContext.isPositioned]),canScrollDown?jsx(SelectScrollButtonImpl,{...props,onAutoScroll:()=>{let{viewport,selectedItem}=contentContext;if(viewport&&selectedItem)viewport.scrollTop+=selectedItem.offsetHeight},ref:composedRefs}):null});SelectScrollDownButton.displayName=SCROLL_DOWN_BUTTON_NAME;var SelectScrollButtonImpl=forwardRef((props,forwardedRef)=>{let{__scopeSelect,onAutoScroll,...scrollIndicatorProps}=props,contentContext=useSelectContentContext("SelectScrollButton",__scopeSelect),autoScrollTimerRef=useRef(null),getItems=useCollection(__scopeSelect),clearAutoScrollTimer=useCallback(()=>{if(autoScrollTimerRef.current!==null)window.clearInterval(autoScrollTimerRef.current),autoScrollTimerRef.current=null},[]);return useEffect(()=>{return()=>clearAutoScrollTimer()},[clearAutoScrollTimer]),useLayoutEffect(()=>{getItems().find((item)=>item.ref.current===document.activeElement)?.ref.current?.scrollIntoView({block:"nearest"})},[getItems]),jsx(Primitive.div,{"aria-hidden":!0,...scrollIndicatorProps,onPointerDown:composeEventHandlers(scrollIndicatorProps.onPointerDown,()=>{if(autoScrollTimerRef.current===null)autoScrollTimerRef.current=window.setInterval(onAutoScroll,50)}),onPointerLeave:composeEventHandlers(scrollIndicatorProps.onPointerLeave,()=>{clearAutoScrollTimer()}),onPointerMove:composeEventHandlers(scrollIndicatorProps.onPointerMove,()=>{if(contentContext.onItemLeave?.(),autoScrollTimerRef.current===null)autoScrollTimerRef.current=window.setInterval(onAutoScroll,50)}),ref:forwardedRef,style:{flexShrink:0,...scrollIndicatorProps.style}})}),SEPARATOR_NAME="SelectSeparator",SelectSeparator=forwardRef((props,forwardedRef)=>{let{__scopeSelect,...separatorProps}=props;return jsx(Primitive.div,{"aria-hidden":!0,...separatorProps,ref:forwardedRef})});SelectSeparator.displayName=SEPARATOR_NAME;var ARROW_NAME="SelectArrow",SelectArrow=forwardRef((props,forwardedRef)=>{let{__scopeSelect,...arrowProps}=props,popperScope=usePopperScope(__scopeSelect),context=useSelectContext(ARROW_NAME,__scopeSelect),contentContext=useSelectContentContext(ARROW_NAME,__scopeSelect);return context.open&&contentContext.position==="popper"?jsx(PopperPrimitive.Arrow,{...popperScope,...arrowProps,ref:forwardedRef}):null});SelectArrow.displayName=ARROW_NAME;var BUBBLE_INPUT_NAME="SelectBubbleInput",SelectBubbleInput=forwardRef(({__scopeSelect,value,...props},forwardedRef)=>{let ref=useRef(null),composedRefs=useComposedRefs(forwardedRef,ref),prevValue=usePrevious(value);return useEffect(()=>{let select=ref.current;if(!select)return;let selectProto=window.HTMLSelectElement.prototype,setValue=Object.getOwnPropertyDescriptor(selectProto,"value").set;if(prevValue!==value&&setValue){let event=new Event("change",{bubbles:!0});setValue.call(select,value),select.dispatchEvent(event)}},[prevValue,value]),jsx(Primitive.select,{...props,defaultValue:value,ref:composedRefs,style:{...VISUALLY_HIDDEN_STYLES,...props.style}})});SelectBubbleInput.displayName=BUBBLE_INPUT_NAME;function shouldShowPlaceholder(value){return value===""||value===void 0}function useTypeaheadSearch(onSearchChange){let handleSearchChange=useCallbackRef(onSearchChange),searchRef=useRef(""),timerRef=useRef(0),handleTypeaheadSearch=useCallback((key)=>{let search=searchRef.current+key;handleSearchChange(search),function updateSearch(value){if(searchRef.current=value,window.clearTimeout(timerRef.current),value!=="")timerRef.current=window.setTimeout(()=>updateSearch(""),1000)}(search)},[handleSearchChange]),resetTypeahead=useCallback(()=>{searchRef.current="",window.clearTimeout(timerRef.current)},[]);return useEffect(()=>{return()=>window.clearTimeout(timerRef.current)},[]),[searchRef,handleTypeaheadSearch,resetTypeahead]}function findNextItem(items,search,currentItem){let normalizedSearch=search.length>1&&Array.from(search).every((char)=>char===search[0])?search[0]:search,currentItemIndex=currentItem?items.indexOf(currentItem):-1,wrappedItems=wrapArray(items,Math.max(currentItemIndex,0));if(normalizedSearch.length===1)wrappedItems=wrappedItems.filter((v)=>v!==currentItem);let nextItem=wrappedItems.find((item)=>item.textValue.toLowerCase().startsWith(normalizedSearch.toLowerCase()));return nextItem!==currentItem?nextItem:void 0}function wrapArray(array,startIndex){return array.map((_,index)=>array[(startIndex+index)%array.length])}var Root2=Select,Trigger=SelectTrigger,Value=SelectValue,Icon=SelectIcon,Portal=SelectPortal,Content2=SelectContent,Viewport=SelectViewport,Group=SelectGroup,Label=SelectLabel,Item=SelectItem,ItemText=SelectItemText,ItemIndicator=SelectItemIndicator,ScrollUpButton=SelectScrollUpButton,ScrollDownButton=SelectScrollDownButton,Separator=SelectSeparator,Arrow2=SelectArrow;export{createSelectScope,Viewport,Value,Trigger,Separator,SelectViewport,SelectValue,SelectTrigger,SelectSeparator,SelectScrollUpButton,SelectScrollDownButton,SelectPortal,SelectLabel,SelectItemText,SelectItemIndicator,SelectItem,SelectIcon,SelectGroup,SelectContent,SelectArrow,Select,ScrollUpButton,ScrollDownButton,Root2 as Root,Portal,Label,ItemText,ItemIndicator,Item,Icon,Group,Content2 as Content,Arrow2 as Arrow};