@zag-js/combobox 0.53.0 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,2 +1,1447 @@
1
- import{createAnatomy}from"@zag-js/anatomy";var anatomy=createAnatomy("combobox").parts("root","label","input","positioner","control","trigger","content","clearTrigger","item","itemText","itemIndicator","itemGroup","itemGroupLabel");var parts=anatomy.build();import{Collection}from"@zag-js/collection";import{ref}from"@zag-js/core";var collection=options=>{return ref(new Collection(options))};collection.empty=()=>{return ref(new Collection({items:[]}))};import{clickIfLink,getEventKey,isContextMenuEvent,isLeftClick}from"@zag-js/dom-event";import{ariaAttr,dataAttr,isComposingEvent,isDownloadingEvent,isOpeningInNewTab}from"@zag-js/dom-query";import{getPlacementStyles}from"@zag-js/popper";import{createScope,query}from"@zag-js/dom-query";var dom=createScope({getRootId:ctx=>ctx.ids?.root??`combobox:${ctx.id}`,getLabelId:ctx=>ctx.ids?.label??`combobox:${ctx.id}:label`,getControlId:ctx=>ctx.ids?.control??`combobox:${ctx.id}:control`,getInputId:ctx=>ctx.ids?.input??`combobox:${ctx.id}:input`,getContentId:ctx=>ctx.ids?.content??`combobox:${ctx.id}:content`,getPositionerId:ctx=>ctx.ids?.positioner??`combobox:${ctx.id}:popper`,getTriggerId:ctx=>ctx.ids?.trigger??`combobox:${ctx.id}:toggle-btn`,getClearTriggerId:ctx=>ctx.ids?.clearTrigger??`combobox:${ctx.id}:clear-btn`,getItemGroupId:(ctx,id)=>ctx.ids?.itemGroup?.(id)??`combobox:${ctx.id}:optgroup:${id}`,getItemGroupLabelId:(ctx,id)=>ctx.ids?.itemGroupLabel?.(id)??`combobox:${ctx.id}:optgroup-label:${id}`,getItemId:(ctx,id)=>`combobox:${ctx.id}:option:${id}`,getContentEl:ctx=>dom.getById(ctx,dom.getContentId(ctx)),getInputEl:ctx=>dom.getById(ctx,dom.getInputId(ctx)),getPositionerEl:ctx=>dom.getById(ctx,dom.getPositionerId(ctx)),getControlEl:ctx=>dom.getById(ctx,dom.getControlId(ctx)),getTriggerEl:ctx=>dom.getById(ctx,dom.getTriggerId(ctx)),getClearTriggerEl:ctx=>dom.getById(ctx,dom.getClearTriggerId(ctx)),getHighlightedItemEl:ctx=>{const value=ctx.highlightedValue;if(value==null)return;return query(dom.getContentEl(ctx),`[role=option][data-value="${CSS.escape(value)}"`)},focusInputEl:ctx=>{const inputEl=dom.getInputEl(ctx);if(dom.getActiveElement(ctx)===inputEl)return;inputEl?.focus({preventScroll:true})},focusTriggerEl:ctx=>{const triggerEl=dom.getTriggerEl(ctx);if(dom.getActiveElement(ctx)===triggerEl)return;triggerEl?.focus({preventScroll:true})}});function connect(state,send,normalize){const translations=state.context.translations;const collection2=state.context.collection;const disabled=state.context.disabled;const interactive=state.context.isInteractive;const invalid=state.context.invalid;const readOnly=state.context.readOnly;const open=state.hasTag("open");const focused=state.hasTag("focused");const composite=state.context.composite;const highlightedValue=state.context.highlightedValue;const popperStyles=getPlacementStyles({...state.context.positioning,placement:state.context.currentPlacement});function getItemState(props){const{item}=props;const disabled2=collection2.isItemDisabled(item);const value=collection2.itemToValue(item);return{value,disabled:Boolean(disabled2||disabled2),highlighted:highlightedValue===value,selected:state.context.value.includes(value)}}return{focused,open,inputValue:state.context.inputValue,highlightedValue,highlightedItem:state.context.highlightedItem,value:state.context.value,valueAsString:state.context.valueAsString,hasSelectedItems:state.context.hasSelectedItems,selectedItems:state.context.selectedItems,collection:state.context.collection,reposition(options={}){send({type:"POSITIONING.SET",options})},setCollection(collection3){send({type:"COLLECTION.SET",value:collection3})},setHighlightValue(value){send({type:"HIGHLIGHTED_VALUE.SET",value})},selectValue(value){send({type:"ITEM.SELECT",value})},setValue(value){send({type:"VALUE.SET",value})},setInputValue(value){send({type:"INPUT_VALUE.SET",value})},clearValue(value){if(value!=null){send({type:"ITEM.CLEAR",value})}else{send("VALUE.CLEAR")}},focus(){dom.getInputEl(state.context)?.focus()},setOpen(nextOpen){if(nextOpen===open)return;send(nextOpen?"OPEN":"CLOSE")},rootProps:normalize.element({...parts.root.attrs,dir:state.context.dir,id:dom.getRootId(state.context),"data-invalid":dataAttr(invalid),"data-readonly":dataAttr(readOnly)}),labelProps:normalize.label({...parts.label.attrs,dir:state.context.dir,htmlFor:dom.getInputId(state.context),id:dom.getLabelId(state.context),"data-readonly":dataAttr(readOnly),"data-disabled":dataAttr(disabled),"data-invalid":dataAttr(invalid),"data-focus":dataAttr(focused),onClick(event){if(composite)return;event.preventDefault();dom.getTriggerEl(state.context)?.focus({preventScroll:true})}}),controlProps:normalize.element({...parts.control.attrs,dir:state.context.dir,id:dom.getControlId(state.context),"data-state":open?"open":"closed","data-focus":dataAttr(focused),"data-disabled":dataAttr(disabled),"data-invalid":dataAttr(invalid)}),positionerProps:normalize.element({...parts.positioner.attrs,dir:state.context.dir,id:dom.getPositionerId(state.context),style:popperStyles.floating}),inputProps:normalize.input({...parts.input.attrs,dir:state.context.dir,"aria-invalid":ariaAttr(invalid),"data-invalid":dataAttr(invalid),name:state.context.name,form:state.context.form,disabled,autoFocus:state.context.autoFocus,autoComplete:"off",autoCorrect:"off",autoCapitalize:"none",spellCheck:"false",readOnly,placeholder:state.context.placeholder,id:dom.getInputId(state.context),type:"text",role:"combobox",defaultValue:state.context.inputValue,"aria-autocomplete":state.context.autoComplete?"both":"list","aria-controls":dom.getContentId(state.context),"aria-expanded":open,"data-state":open?"open":"closed","aria-activedescendant":highlightedValue?dom.getItemId(state.context,highlightedValue):void 0,onClick(event){if(event.defaultPrevented)return;if(!state.context.openOnClick)return;if(!interactive)return;send("INPUT.CLICK")},onFocus(){if(disabled)return;send("INPUT.FOCUS")},onBlur(){if(disabled)return;send("INPUT.BLUR")},onChange(event){send({type:"INPUT.CHANGE",value:event.currentTarget.value})},onKeyDown(event){if(event.defaultPrevented)return;if(!interactive)return;if(event.ctrlKey||event.shiftKey||isComposingEvent(event))return;const openOnKeyPress=state.context.openOnKeyPress;const isModifierKey=event.ctrlKey||event.metaKey||event.shiftKey;const keypress=true;const keymap={ArrowDown(event2){if(!openOnKeyPress&&!open)return;send({type:event2.altKey?"OPEN":"INPUT.ARROW_DOWN",keypress});event2.preventDefault()},ArrowUp(){if(!openOnKeyPress&&!open)return;send({type:event.altKey?"CLOSE":"INPUT.ARROW_UP",keypress});event.preventDefault()},Home(event2){if(isModifierKey)return;send({type:"INPUT.HOME",keypress});if(open){event2.preventDefault()}},End(event2){if(isModifierKey)return;send({type:"INPUT.END",keypress});if(open){event2.preventDefault()}},Enter(event2){send({type:"INPUT.ENTER",keypress});if(open){event2.preventDefault()}const itemEl=dom.getHighlightedItemEl(state.context);clickIfLink(itemEl)},Escape(){send({type:"INPUT.ESCAPE",keypress});event.preventDefault()}};const key=getEventKey(event,state.context);const exec=keymap[key];exec?.(event)}}),getTriggerProps(props={}){return normalize.button({...parts.trigger.attrs,dir:state.context.dir,id:dom.getTriggerId(state.context),"aria-haspopup":composite?"listbox":"dialog",type:"button",tabIndex:props.focusable?void 0:-1,"aria-label":translations.triggerLabel,"aria-expanded":open,"data-state":open?"open":"closed","aria-controls":open?dom.getContentId(state.context):void 0,disabled,"data-focusable":dataAttr(props.focusable),"data-readonly":dataAttr(readOnly),"data-disabled":dataAttr(disabled),onFocus(){if(!props.focusable)return;send({type:"INPUT.FOCUS",src:"trigger"})},onClick(event){if(event.defaultPrevented)return;if(!interactive)return;if(!isLeftClick(event))return;send("TRIGGER.CLICK")},onPointerDown(event){if(!interactive)return;if(event.pointerType==="touch")return;event.preventDefault();queueMicrotask(()=>{dom.getInputEl(state.context)?.focus({preventScroll:true})})},onKeyDown(event){if(event.defaultPrevented)return;if(composite)return;const keyMap={ArrowDown(){send({type:"INPUT.ARROW_DOWN",src:"trigger"})},ArrowUp(){send({type:"INPUT.ARROW_UP",src:"trigger"})}};const key=getEventKey(event,state.context);const exec=keyMap[key];if(exec){exec(event);event.preventDefault()}}})},contentProps:normalize.element({...parts.content.attrs,dir:state.context.dir,id:dom.getContentId(state.context),role:!composite?"dialog":"listbox",tabIndex:-1,hidden:!open,"data-state":open?"open":"closed","aria-labelledby":dom.getLabelId(state.context),"aria-multiselectable":state.context.multiple&&composite?true:void 0,onPointerDown(event){event.preventDefault()}}),listProps:normalize.element({role:!composite?"listbox":void 0,"aria-labelledby":dom.getLabelId(state.context),"aria-multiselectable":state.context.multiple&&!composite?true:void 0}),clearTriggerProps:normalize.button({...parts.clearTrigger.attrs,dir:state.context.dir,id:dom.getClearTriggerId(state.context),type:"button",tabIndex:-1,disabled,"aria-label":translations.clearTriggerLabel,"aria-controls":dom.getInputId(state.context),hidden:!state.context.value.length,onPointerDown(event){event.preventDefault()},onClick(event){if(event.defaultPrevented)return;if(!interactive)return;send({type:"VALUE.CLEAR",src:"clear-trigger"})}}),getItemState,getItemProps(props){const itemState=getItemState(props);const value=itemState.value;return normalize.element({...parts.item.attrs,dir:state.context.dir,id:dom.getItemId(state.context,value),role:"option",tabIndex:-1,"data-highlighted":dataAttr(itemState.highlighted),"data-state":itemState.selected?"checked":"unchecked","aria-selected":itemState.highlighted,"aria-disabled":itemState.disabled,"data-disabled":dataAttr(itemState.disabled),"data-value":itemState.value,onPointerMove(){if(itemState.disabled)return;if(itemState.highlighted)return;send({type:"ITEM.POINTER_MOVE",value})},onPointerLeave(){if(props.persistFocus)return;if(itemState.disabled)return;const mouseMoved=state.previousEvent.type.includes("POINTER");if(!mouseMoved)return;send({type:"ITEM.POINTER_LEAVE",value})},onPointerUp(event){if(isDownloadingEvent(event))return;if(isOpeningInNewTab(event))return;if(isContextMenuEvent(event))return;if(itemState.disabled)return;send({type:"ITEM.CLICK",src:"pointerup",value})},onTouchEnd(event){event.preventDefault();event.stopPropagation()}})},getItemTextProps(props){const itemState=getItemState(props);return normalize.element({...parts.itemText.attrs,dir:state.context.dir,"data-disabled":dataAttr(itemState.disabled),"data-highlighted":dataAttr(itemState.highlighted)})},getItemIndicatorProps(props){const itemState=getItemState(props);return normalize.element({"aria-hidden":true,...parts.itemIndicator.attrs,dir:state.context.dir,"data-state":itemState.selected?"checked":"unchecked",hidden:!itemState.selected})},getItemGroupProps(props){const{id}=props;return normalize.element({...parts.itemGroup.attrs,dir:state.context.dir,id:dom.getItemGroupId(state.context,id),"aria-labelledby":dom.getItemGroupLabelId(state.context,id)})},getItemGroupLabelProps(props){const{htmlFor}=props;return normalize.element({...parts.itemGroupLabel.attrs,dir:state.context.dir,id:dom.getItemGroupLabelId(state.context,htmlFor),role:"group"})}}}import{ariaHidden}from"@zag-js/aria-hidden";import{createMachine,guards}from"@zag-js/core";import{trackDismissableElement}from"@zag-js/dismissable";import{observeAttributes,observeChildren,raf,scrollIntoView}from"@zag-js/dom-query";import{getPlacement}from"@zag-js/popper";import{addOrRemove,compact,isArray,isBoolean,isEqual,match}from"@zag-js/utils";var{and,not}=guards;function machine(userContext){const ctx=compact(userContext);return createMachine({id:"combobox",initial:ctx.open?"suggesting":"idle",context:{loopFocus:true,openOnClick:false,value:[],highlightedValue:null,inputValue:"",allowCustomValue:false,closeOnSelect:!ctx.multiple,inputBehavior:"none",selectionBehavior:"replace",openOnKeyPress:true,openOnChange:true,composite:true,...ctx,highlightedItem:null,selectedItems:[],valueAsString:"",collection:ctx.collection??collection.empty(),positioning:{placement:"bottom",flip:false,sameWidth:true,...ctx.positioning},translations:{triggerLabel:"Toggle suggestions",clearTriggerLabel:"Clear value",...ctx.translations}},created:["syncInitialValues","syncSelectionBehavior"],computed:{isInputValueEmpty:ctx2=>ctx2.inputValue.length===0,isInteractive:ctx2=>!(ctx2.readOnly||ctx2.disabled),autoComplete:ctx2=>ctx2.inputBehavior==="autocomplete",autoHighlight:ctx2=>ctx2.inputBehavior==="autohighlight",hasSelectedItems:ctx2=>ctx2.value.length>0},watch:{value:["syncSelectedItems"],inputValue:["syncInputValue"],highlightedValue:["syncHighlightedItem","autofillInputValue"],multiple:["syncSelectionBehavior"],open:["toggleVisibility"]},on:{"HIGHLIGHTED_VALUE.SET":{actions:["setHighlightedItem"]},"ITEM.SELECT":{actions:["selectItem"]},"ITEM.CLEAR":{actions:["clearItem"]},"VALUE.SET":{actions:["setSelectedItems"]},"INPUT_VALUE.SET":{actions:"setInputValue"},"COLLECTION.SET":{actions:["setCollection"]},"POSITIONING.SET":{actions:["reposition"]}},states:{idle:{tags:["idle","closed"],entry:["scrollContentToTop","clearHighlightedItem"],on:{"CONTROLLED.OPEN":{target:"interacting"},"TRIGGER.CLICK":[{guard:"isOpenControlled",actions:["setInitialFocus","highlightFirstSelectedItem","invokeOnOpen"]},{target:"interacting",actions:["setInitialFocus","highlightFirstSelectedItem","invokeOnOpen"]}],"INPUT.CLICK":[{guard:"isOpenControlled",actions:["highlightFirstSelectedItem","invokeOnOpen"]},{target:"interacting",actions:["highlightFirstSelectedItem","invokeOnOpen"]}],"INPUT.FOCUS":{target:"focused"},OPEN:[{guard:"isOpenControlled",actions:["invokeOnOpen"]},{target:"interacting",actions:["invokeOnOpen"]}],"VALUE.CLEAR":{target:"focused",actions:["clearInputValue","clearSelectedItems","setInitialFocus"]}}},focused:{tags:["focused","closed"],entry:["scrollContentToTop","clearHighlightedItem"],on:{"CONTROLLED.OPEN":[{guard:"isChangeEvent",target:"suggesting"},{target:"interacting"}],"INPUT.CHANGE":[{guard:and("isOpenControlled","openOnChange"),actions:["setInputValue","invokeOnOpen","highlightFirstItemIfNeeded"]},{guard:"openOnChange",target:"suggesting",actions:["setInputValue","invokeOnOpen","highlightFirstItemIfNeeded"]},{actions:"setInputValue"}],"LAYER.INTERACT_OUTSIDE":{target:"idle"},"INPUT.ESCAPE":{guard:and("isCustomValue",not("allowCustomValue")),actions:"revertInputValue"},"INPUT.BLUR":{target:"idle"},"INPUT.CLICK":[{guard:"isOpenControlled",actions:["highlightFirstSelectedItem","invokeOnOpen"]},{target:"interacting",actions:["highlightFirstSelectedItem","invokeOnOpen"]}],"TRIGGER.CLICK":[{guard:"isOpenControlled",actions:["setInitialFocus","highlightFirstSelectedItem","invokeOnOpen"]},{target:"interacting",actions:["setInitialFocus","highlightFirstSelectedItem","invokeOnOpen"]}],"INPUT.ARROW_DOWN":[{guard:and("isOpenControlled","autoComplete"),actions:["invokeOnOpen"]},{guard:"autoComplete",target:"interacting",actions:["invokeOnOpen"]},{guard:"isOpenControlled",actions:["highlightFirstOrSelectedItem","invokeOnOpen"]},{target:"interacting",actions:["highlightFirstOrSelectedItem","invokeOnOpen"]}],"INPUT.ARROW_UP":[{guard:"autoComplete",target:"interacting",actions:"invokeOnOpen"},{guard:"autoComplete",target:"interacting",actions:"invokeOnOpen"},{target:"interacting",actions:["highlightLastOrSelectedItem","invokeOnOpen"]},{target:"interacting",actions:["highlightLastOrSelectedItem","invokeOnOpen"]}],OPEN:[{guard:"isOpenControlled",actions:["invokeOnOpen"]},{target:"interacting",actions:["invokeOnOpen"]}],"VALUE.CLEAR":{actions:["clearInputValue","clearSelectedItems"]}}},interacting:{tags:["open","focused"],entry:["setInitialFocus"],activities:["scrollToHighlightedItem","trackDismissableLayer","computePlacement","hideOtherElements"],on:{"CONTROLLED.CLOSE":[{guard:"restoreFocus",target:"focused",actions:["setFinalFocus"]},{target:"idle"}],"INPUT.HOME":{actions:["highlightFirstItem"]},"INPUT.END":{actions:["highlightLastItem"]},"INPUT.ARROW_DOWN":[{guard:and("autoComplete","isLastItemHighlighted"),actions:["clearHighlightedItem","scrollContentToTop"]},{actions:["highlightNextItem"]}],"INPUT.ARROW_UP":[{guard:and("autoComplete","isFirstItemHighlighted"),actions:"clearHighlightedItem"},{actions:"highlightPrevItem"}],"INPUT.ENTER":[{guard:and("isOpenControlled","closeOnSelect"),actions:["selectHighlightedItem","invokeOnClose"]},{guard:"closeOnSelect",target:"focused",actions:["selectHighlightedItem","invokeOnClose","setFinalFocus"]},{actions:["selectHighlightedItem"]}],"INPUT.CHANGE":[{guard:"autoComplete",target:"suggesting",actions:["setInputValue","invokeOnOpen"]},{target:"suggesting",actions:["clearHighlightedItem","setInputValue","invokeOnOpen"]}],"ITEM.POINTER_MOVE":{actions:["setHighlightedItem"]},"ITEM.POINTER_LEAVE":{actions:["clearHighlightedItem"]},"ITEM.CLICK":[{guard:and("isOpenControlled","closeOnSelect"),actions:["selectItem","invokeOnClose"]},{guard:"closeOnSelect",target:"focused",actions:["selectItem","invokeOnClose","setFinalFocus"]},{actions:["selectItem"]}],"LAYER.ESCAPE":[{guard:and("isOpenControlled","autoComplete"),actions:["syncInputValue","invokeOnClose"]},{guard:"autoComplete",target:"focused",actions:["syncInputValue","invokeOnClose"]},{guard:"isOpenControlled",actions:"invokeOnClose"},{target:"focused",actions:["invokeOnClose","setFinalFocus"]}],"TRIGGER.CLICK":[{guard:"isOpenControlled",actions:"invokeOnClose"},{target:"focused",actions:"invokeOnClose"}],"LAYER.INTERACT_OUTSIDE":[{guard:and("isOpenControlled","isCustomValue",not("allowCustomValue")),actions:["revertInputValue","invokeOnClose"]},{guard:and("isCustomValue",not("allowCustomValue")),target:"idle",actions:["revertInputValue","invokeOnClose"]},{guard:"isOpenControlled",actions:"invokeOnClose"},{target:"idle",actions:"invokeOnClose"}],CLOSE:[{guard:"isOpenControlled",actions:["invokeOnClose"]},{target:"focused",actions:["invokeOnClose","setFinalFocus"]}],"VALUE.CLEAR":[{guard:"isOpenControlled",actions:["clearInputValue","clearSelectedItems","invokeOnClose"]},{target:"focused",actions:["clearInputValue","clearSelectedItems","invokeOnClose","setFinalFocus"]}]}},suggesting:{tags:["open","focused"],activities:["trackDismissableLayer","scrollToHighlightedItem","computePlacement","trackChildNodes","hideOtherElements"],entry:["setInitialFocus"],on:{"CONTROLLED.CLOSE":[{guard:"restoreFocus",target:"focused",actions:["setFinalFocus"]},{target:"idle"}],CHILDREN_CHANGE:{actions:["highlightFirstItem"]},"INPUT.ARROW_DOWN":{target:"interacting",actions:["highlightNextItem"]},"INPUT.ARROW_UP":{target:"interacting",actions:["highlightPrevItem"]},"INPUT.HOME":{target:"interacting",actions:["highlightFirstItem"]},"INPUT.END":{target:"interacting",actions:["highlightLastItem"]},"INPUT.ENTER":[{guard:and("isOpenControlled","closeOnSelect"),actions:["selectHighlightedItem","invokeOnClose"]},{guard:"closeOnSelect",target:"focused",actions:["selectHighlightedItem","invokeOnClose","setFinalFocus"]},{actions:["selectHighlightedItem"]}],"INPUT.CHANGE":[{guard:"autoHighlight",actions:["setInputValue"]},{actions:["setInputValue"]}],"LAYER.ESCAPE":[{guard:"isOpenControlled",actions:["invokeOnClose"]},{target:"focused",actions:["invokeOnClose"]}],"ITEM.POINTER_MOVE":{target:"interacting",actions:["setHighlightedItem"]},"ITEM.POINTER_LEAVE":{actions:["clearHighlightedItem"]},"LAYER.INTERACT_OUTSIDE":[{guard:and("isOpenControlled","isCustomValue",not("allowCustomValue")),actions:["revertInputValue","invokeOnClose"]},{guard:and("isCustomValue",not("allowCustomValue")),target:"idle",actions:["revertInputValue","invokeOnClose"]},{guard:"isOpenControlled",actions:["invokeOnClose"]},{target:"idle",actions:["invokeOnClose"]}],"TRIGGER.CLICK":[{guard:"isOpenControlled",actions:["invokeOnClose"]},{target:"focused",actions:["invokeOnClose"]}],"ITEM.CLICK":[{guard:and("isOpenControlled","closeOnSelect"),actions:["selectItem","invokeOnClose"]},{guard:"closeOnSelect",target:"focused",actions:["selectItem","invokeOnClose","setFinalFocus"]},{actions:["selectItem"]}],CLOSE:[{guard:"isOpenControlled",actions:["invokeOnClose"]},{target:"focused",actions:["invokeOnClose","setFinalFocus"]}],"VALUE.CLEAR":[{guard:"isOpenControlled",actions:["clearInputValue","clearSelectedItems","invokeOnClose"]},{target:"focused",actions:["clearInputValue","clearSelectedItems","invokeOnClose","setFinalFocus"]}]}}}},{guards:{isInputValueEmpty:ctx2=>ctx2.isInputValueEmpty,autoComplete:ctx2=>ctx2.autoComplete&&!ctx2.multiple,autoHighlight:ctx2=>ctx2.autoHighlight,isFirstItemHighlighted:ctx2=>ctx2.collection.first()===ctx2.highlightedValue,isLastItemHighlighted:ctx2=>ctx2.collection.last()===ctx2.highlightedValue,isCustomValue:ctx2=>ctx2.inputValue!==ctx2.valueAsString,allowCustomValue:ctx2=>!!ctx2.allowCustomValue,hasHighlightedItem:ctx2=>ctx2.highlightedValue!=null,closeOnSelect:ctx2=>!!ctx2.closeOnSelect,isOpenControlled:ctx2=>!!ctx2["open.controlled"],openOnChange:(ctx2,evt)=>{if(isBoolean(ctx2.openOnChange))return ctx2.openOnChange;return!!ctx2.openOnChange?.({inputValue:evt.value})},restoreFocus:(_ctx,evt)=>evt.restoreFocus==null?true:!!evt.restoreFocus,isChangeEvent:(_ctx,evt)=>evt.previousEvent?.type==="INPUT.CHANGE"},activities:{trackDismissableLayer(ctx2,_evt,{send}){if(ctx2.disableLayer)return;const contentEl=()=>dom.getContentEl(ctx2);return trackDismissableElement(contentEl,{defer:true,exclude:()=>[dom.getInputEl(ctx2),dom.getTriggerEl(ctx2),dom.getClearTriggerEl(ctx2)],onFocusOutside:ctx2.onFocusOutside,onPointerDownOutside:ctx2.onPointerDownOutside,onInteractOutside:ctx2.onInteractOutside,onEscapeKeyDown(event){event.preventDefault();event.stopPropagation();send("LAYER.ESCAPE")},onDismiss(){send({type:"LAYER.INTERACT_OUTSIDE",restoreFocus:false})}})},hideOtherElements(ctx2){return ariaHidden([dom.getInputEl(ctx2),dom.getContentEl(ctx2),dom.getTriggerEl(ctx2)])},computePlacement(ctx2){const controlEl=()=>dom.getControlEl(ctx2);const positionerEl=()=>dom.getPositionerEl(ctx2);ctx2.currentPlacement=ctx2.positioning.placement;return getPlacement(controlEl,positionerEl,{...ctx2.positioning,defer:true,onComplete(data){ctx2.currentPlacement=data.placement}})},trackChildNodes(ctx2,_evt,{send}){if(!ctx2.autoHighlight)return;const exec=()=>send("CHILDREN_CHANGE");const contentEl=()=>dom.getContentEl(ctx2);return observeChildren(contentEl,{callback:exec,defer:true})},scrollToHighlightedItem(ctx2,_evt,{getState}){const inputEl=dom.getInputEl(ctx2);let cleanups=[];const exec=immediate=>{const state=getState();const pointer=state.event.type.includes("POINTER");if(pointer||!ctx2.highlightedValue)return;const itemEl=dom.getHighlightedItemEl(ctx2);const contentEl=dom.getContentEl(ctx2);if(ctx2.scrollToIndexFn){const highlightedIndex=ctx2.collection.indexOf(ctx2.highlightedValue);ctx2.scrollToIndexFn({index:highlightedIndex,immediate});return}const rafCleanup2=raf(()=>{scrollIntoView(itemEl,{rootEl:contentEl,block:"nearest"})});cleanups.push(rafCleanup2)};const rafCleanup=raf(()=>exec(true));cleanups.push(rafCleanup);const observerCleanup=observeAttributes(inputEl,{attributes:["aria-activedescendant"],callback:()=>exec(false)});cleanups.push(observerCleanup);return()=>{cleanups.forEach(cleanup=>cleanup())}}},actions:{reposition(ctx2,evt){const controlEl=()=>dom.getControlEl(ctx2);const positionerEl=()=>dom.getPositionerEl(ctx2);getPlacement(controlEl,positionerEl,{...ctx2.positioning,...evt.options,defer:true,listeners:false,onComplete(data){ctx2.currentPlacement=data.placement}})},setHighlightedItem(ctx2,evt){if(evt.value==null)return;set.highlightedValue(ctx2,evt.value)},clearHighlightedItem(ctx2){set.highlightedValue(ctx2,null,true)},selectHighlightedItem(ctx2){set.value(ctx2,ctx2.highlightedValue)},selectItem(ctx2,evt){if(evt.value==null)return;set.value(ctx2,evt.value)},clearItem(ctx2,evt){if(evt.value==null)return;const value=ctx2.value.filter(v=>v!==evt.value);set.value(ctx2,value)},setInitialFocus(ctx2){raf(()=>{dom.focusInputEl(ctx2)})},setFinalFocus(ctx2){raf(()=>{const triggerEl=dom.getTriggerEl(ctx2);if(triggerEl?.dataset.focusable==null){dom.focusInputEl(ctx2)}else{dom.focusTriggerEl(ctx2)}})},syncInputValue(ctx2){const inputEl=dom.getInputEl(ctx2);if(!inputEl)return;inputEl.value=ctx2.inputValue;queueMicrotask(()=>{const{selectionStart,selectionEnd}=inputEl;if(Math.abs((selectionEnd??0)-(selectionStart??0))!==0)return;if(selectionStart!==0)return;inputEl.setSelectionRange(inputEl.value.length,inputEl.value.length)})},setInputValue(ctx2,evt){set.inputValue(ctx2,evt.value)},clearInputValue(ctx2){set.inputValue(ctx2,"")},revertInputValue(ctx2){const inputValue=match(ctx2.selectionBehavior,{replace:ctx2.hasSelectedItems?ctx2.valueAsString:"",preserve:ctx2.inputValue,clear:""});set.inputValue(ctx2,inputValue)},syncInitialValues(ctx2){const selectedItems=ctx2.collection.items(ctx2.value);const valueAsString=ctx2.collection.itemsToString(selectedItems);ctx2.highlightedItem=ctx2.collection.item(ctx2.highlightedValue);ctx2.selectedItems=selectedItems;ctx2.valueAsString=valueAsString;ctx2.inputValue=match(ctx2.selectionBehavior,{preserve:ctx2.inputValue||valueAsString,replace:valueAsString,clear:""})},syncSelectionBehavior(ctx2){if(ctx2.multiple){ctx2.selectionBehavior="clear"}},setSelectedItems(ctx2,evt){if(!isArray(evt.value))return;set.value(ctx2,evt.value)},clearSelectedItems(ctx2){set.value(ctx2,[])},scrollContentToTop(ctx2){if(ctx2.scrollToIndexFn){ctx2.scrollToIndexFn({index:0,immediate:true})}else{const contentEl=dom.getContentEl(ctx2);if(!contentEl)return;contentEl.scrollTop=0}},invokeOnOpen(ctx2){ctx2.onOpenChange?.({open:true})},invokeOnClose(ctx2){ctx2.onOpenChange?.({open:false})},highlightFirstItem(ctx2){raf(()=>{const value=ctx2.collection.first();set.highlightedValue(ctx2,value)})},highlightFirstItemIfNeeded(ctx2){if(!ctx2.autoHighlight)return;raf(()=>{const value=ctx2.collection.first();set.highlightedValue(ctx2,value)})},highlightLastItem(ctx2){raf(()=>{const value=ctx2.collection.last();set.highlightedValue(ctx2,value)})},highlightNextItem(ctx2){let value=null;if(ctx2.highlightedValue){value=ctx2.collection.next(ctx2.highlightedValue);if(!value&&ctx2.loopFocus)value=ctx2.collection.first()}else{value=ctx2.collection.first()}set.highlightedValue(ctx2,value)},highlightPrevItem(ctx2){let value=null;if(ctx2.highlightedValue){value=ctx2.collection.prev(ctx2.highlightedValue);if(!value&&ctx2.loopFocus)value=ctx2.collection.last()}else{value=ctx2.collection.last()}set.highlightedValue(ctx2,value)},highlightFirstSelectedItem(ctx2){raf(()=>{const[value]=ctx2.collection.sort(ctx2.value);set.highlightedValue(ctx2,value)})},highlightFirstOrSelectedItem(ctx2){raf(()=>{let value=null;if(ctx2.hasSelectedItems){value=ctx2.collection.sort(ctx2.value)[0]}else{value=ctx2.collection.first()}set.highlightedValue(ctx2,value)})},highlightLastOrSelectedItem(ctx2){raf(()=>{let value=null;if(ctx2.hasSelectedItems){value=ctx2.collection.sort(ctx2.value)[0]}else{value=ctx2.collection.last()}set.highlightedValue(ctx2,value)})},autofillInputValue(ctx2,evt){const inputEl=dom.getInputEl(ctx2);if(!ctx2.autoComplete||!inputEl||!evt.keypress)return;const valueText=ctx2.collection.valueToString(ctx2.highlightedValue);raf(()=>{inputEl.value=valueText||ctx2.inputValue})},setCollection(ctx2,evt){ctx2.collection=evt.value},syncSelectedItems(ctx2){sync.valueChange(ctx2)},syncHighlightedItem(ctx2){sync.highlightChange(ctx2)},toggleVisibility(ctx2,evt,{send}){send({type:ctx2.open?"CONTROLLED.OPEN":"CONTROLLED.CLOSE",previousEvent:evt})}}})}var sync={valueChange:ctx=>{const prevSelectedItems=ctx.selectedItems;ctx.selectedItems=ctx.value.map(v=>{const foundItem=prevSelectedItems.find(item=>ctx.collection.itemToValue(item)===v);if(foundItem)return foundItem;return ctx.collection.item(v)});const valueAsString=ctx.collection.itemsToString(ctx.selectedItems);ctx.valueAsString=valueAsString;let inputValue;if(ctx.getSelectionValue){inputValue=ctx.getSelectionValue({inputValue:ctx.inputValue,selectedItems:Array.from(ctx.selectedItems),valueAsString})}else{inputValue=match(ctx.selectionBehavior,{replace:ctx.valueAsString,preserve:ctx.inputValue,clear:""})}set.inputValue(ctx,inputValue)},highlightChange:ctx=>{ctx.highlightedItem=ctx.collection.item(ctx.highlightedValue)}};var invoke={valueChange:ctx=>{sync.valueChange(ctx);ctx.onValueChange?.({value:Array.from(ctx.value),items:Array.from(ctx.selectedItems)})},highlightChange:ctx=>{sync.highlightChange(ctx);ctx.onHighlightChange?.({highlightedValue:ctx.highlightedValue,highlightedItem:ctx.highlightedItem})},inputChange:ctx=>{ctx.onInputValueChange?.({inputValue:ctx.inputValue})}};var set={value:(ctx,value,force=false)=>{if(isEqual(ctx.value,value))return;if(value==null&&!force)return;if(value==null&&force){ctx.value=[];invoke.valueChange(ctx);return}if(isArray(value)){ctx.value=value}else if(value!=null){ctx.value=ctx.multiple?addOrRemove(ctx.value,value):[value]}invoke.valueChange(ctx)},highlightedValue:(ctx,value,force=false)=>{if(isEqual(ctx.highlightedValue,value))return;if(!value&&!force)return;ctx.highlightedValue=value||null;invoke.highlightChange(ctx)},inputValue:(ctx,value)=>{if(isEqual(ctx.inputValue,value))return;ctx.inputValue=value;invoke.inputChange(ctx)}};export{anatomy,collection,connect,machine};
1
+ // src/combobox.anatomy.ts
2
+ import { createAnatomy } from "@zag-js/anatomy";
3
+ var anatomy = createAnatomy("combobox").parts(
4
+ "root",
5
+ "label",
6
+ "input",
7
+ "positioner",
8
+ "control",
9
+ "trigger",
10
+ "content",
11
+ "clearTrigger",
12
+ "item",
13
+ "itemText",
14
+ "itemIndicator",
15
+ "itemGroup",
16
+ "itemGroupLabel"
17
+ );
18
+ var parts = anatomy.build();
19
+
20
+ // src/combobox.collection.ts
21
+ import { Collection } from "@zag-js/collection";
22
+ import { ref } from "@zag-js/core";
23
+ var collection = (options) => {
24
+ return ref(new Collection(options));
25
+ };
26
+ collection.empty = () => {
27
+ return ref(new Collection({ items: [] }));
28
+ };
29
+
30
+ // src/combobox.connect.ts
31
+ import { clickIfLink, getEventKey, isContextMenuEvent, isLeftClick } from "@zag-js/dom-event";
32
+ import { ariaAttr, dataAttr, isComposingEvent, isDownloadingEvent, isOpeningInNewTab } from "@zag-js/dom-query";
33
+ import { getPlacementStyles } from "@zag-js/popper";
34
+
35
+ // src/combobox.dom.ts
36
+ import { createScope, query } from "@zag-js/dom-query";
37
+ var dom = createScope({
38
+ getRootId: (ctx) => ctx.ids?.root ?? `combobox:${ctx.id}`,
39
+ getLabelId: (ctx) => ctx.ids?.label ?? `combobox:${ctx.id}:label`,
40
+ getControlId: (ctx) => ctx.ids?.control ?? `combobox:${ctx.id}:control`,
41
+ getInputId: (ctx) => ctx.ids?.input ?? `combobox:${ctx.id}:input`,
42
+ getContentId: (ctx) => ctx.ids?.content ?? `combobox:${ctx.id}:content`,
43
+ getPositionerId: (ctx) => ctx.ids?.positioner ?? `combobox:${ctx.id}:popper`,
44
+ getTriggerId: (ctx) => ctx.ids?.trigger ?? `combobox:${ctx.id}:toggle-btn`,
45
+ getClearTriggerId: (ctx) => ctx.ids?.clearTrigger ?? `combobox:${ctx.id}:clear-btn`,
46
+ getItemGroupId: (ctx, id) => ctx.ids?.itemGroup?.(id) ?? `combobox:${ctx.id}:optgroup:${id}`,
47
+ getItemGroupLabelId: (ctx, id) => ctx.ids?.itemGroupLabel?.(id) ?? `combobox:${ctx.id}:optgroup-label:${id}`,
48
+ getItemId: (ctx, id) => `combobox:${ctx.id}:option:${id}`,
49
+ getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
50
+ getInputEl: (ctx) => dom.getById(ctx, dom.getInputId(ctx)),
51
+ getPositionerEl: (ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
52
+ getControlEl: (ctx) => dom.getById(ctx, dom.getControlId(ctx)),
53
+ getTriggerEl: (ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
54
+ getClearTriggerEl: (ctx) => dom.getById(ctx, dom.getClearTriggerId(ctx)),
55
+ getHighlightedItemEl: (ctx) => {
56
+ const value = ctx.highlightedValue;
57
+ if (value == null)
58
+ return;
59
+ return query(dom.getContentEl(ctx), `[role=option][data-value="${CSS.escape(value)}"`);
60
+ },
61
+ focusInputEl: (ctx) => {
62
+ const inputEl = dom.getInputEl(ctx);
63
+ if (dom.getActiveElement(ctx) === inputEl)
64
+ return;
65
+ inputEl?.focus({ preventScroll: true });
66
+ },
67
+ focusTriggerEl: (ctx) => {
68
+ const triggerEl = dom.getTriggerEl(ctx);
69
+ if (dom.getActiveElement(ctx) === triggerEl)
70
+ return;
71
+ triggerEl?.focus({ preventScroll: true });
72
+ }
73
+ });
74
+
75
+ // src/combobox.connect.ts
76
+ function connect(state, send, normalize) {
77
+ const translations = state.context.translations;
78
+ const collection2 = state.context.collection;
79
+ const disabled = state.context.disabled;
80
+ const interactive = state.context.isInteractive;
81
+ const invalid = state.context.invalid;
82
+ const readOnly = state.context.readOnly;
83
+ const open = state.hasTag("open");
84
+ const focused = state.hasTag("focused");
85
+ const composite = state.context.composite;
86
+ const highlightedValue = state.context.highlightedValue;
87
+ const popperStyles = getPlacementStyles({
88
+ ...state.context.positioning,
89
+ placement: state.context.currentPlacement
90
+ });
91
+ function getItemState(props) {
92
+ const { item } = props;
93
+ const disabled2 = collection2.isItemDisabled(item);
94
+ const value = collection2.itemToValue(item);
95
+ return {
96
+ value,
97
+ disabled: Boolean(disabled2 || disabled2),
98
+ highlighted: highlightedValue === value,
99
+ selected: state.context.value.includes(value)
100
+ };
101
+ }
102
+ return {
103
+ focused,
104
+ open,
105
+ inputValue: state.context.inputValue,
106
+ highlightedValue,
107
+ highlightedItem: state.context.highlightedItem,
108
+ value: state.context.value,
109
+ valueAsString: state.context.valueAsString,
110
+ hasSelectedItems: state.context.hasSelectedItems,
111
+ selectedItems: state.context.selectedItems,
112
+ collection: state.context.collection,
113
+ reposition(options = {}) {
114
+ send({ type: "POSITIONING.SET", options });
115
+ },
116
+ setCollection(collection3) {
117
+ send({ type: "COLLECTION.SET", value: collection3 });
118
+ },
119
+ setHighlightValue(value) {
120
+ send({ type: "HIGHLIGHTED_VALUE.SET", value });
121
+ },
122
+ selectValue(value) {
123
+ send({ type: "ITEM.SELECT", value });
124
+ },
125
+ setValue(value) {
126
+ send({ type: "VALUE.SET", value });
127
+ },
128
+ setInputValue(value) {
129
+ send({ type: "INPUT_VALUE.SET", value });
130
+ },
131
+ clearValue(value) {
132
+ if (value != null) {
133
+ send({ type: "ITEM.CLEAR", value });
134
+ } else {
135
+ send("VALUE.CLEAR");
136
+ }
137
+ },
138
+ focus() {
139
+ dom.getInputEl(state.context)?.focus();
140
+ },
141
+ setOpen(nextOpen) {
142
+ if (nextOpen === open)
143
+ return;
144
+ send(nextOpen ? "OPEN" : "CLOSE");
145
+ },
146
+ getRootProps() {
147
+ return normalize.element({
148
+ ...parts.root.attrs,
149
+ dir: state.context.dir,
150
+ id: dom.getRootId(state.context),
151
+ "data-invalid": dataAttr(invalid),
152
+ "data-readonly": dataAttr(readOnly)
153
+ });
154
+ },
155
+ getLabelProps() {
156
+ return normalize.label({
157
+ ...parts.label.attrs,
158
+ dir: state.context.dir,
159
+ htmlFor: dom.getInputId(state.context),
160
+ id: dom.getLabelId(state.context),
161
+ "data-readonly": dataAttr(readOnly),
162
+ "data-disabled": dataAttr(disabled),
163
+ "data-invalid": dataAttr(invalid),
164
+ "data-focus": dataAttr(focused),
165
+ onClick(event) {
166
+ if (composite)
167
+ return;
168
+ event.preventDefault();
169
+ dom.getTriggerEl(state.context)?.focus({ preventScroll: true });
170
+ }
171
+ });
172
+ },
173
+ getControlProps() {
174
+ return normalize.element({
175
+ ...parts.control.attrs,
176
+ dir: state.context.dir,
177
+ id: dom.getControlId(state.context),
178
+ "data-state": open ? "open" : "closed",
179
+ "data-focus": dataAttr(focused),
180
+ "data-disabled": dataAttr(disabled),
181
+ "data-invalid": dataAttr(invalid)
182
+ });
183
+ },
184
+ getPositionerProps() {
185
+ return normalize.element({
186
+ ...parts.positioner.attrs,
187
+ dir: state.context.dir,
188
+ id: dom.getPositionerId(state.context),
189
+ style: popperStyles.floating
190
+ });
191
+ },
192
+ getInputProps() {
193
+ return normalize.input({
194
+ ...parts.input.attrs,
195
+ dir: state.context.dir,
196
+ "aria-invalid": ariaAttr(invalid),
197
+ "data-invalid": dataAttr(invalid),
198
+ name: state.context.name,
199
+ form: state.context.form,
200
+ disabled,
201
+ autoFocus: state.context.autoFocus,
202
+ autoComplete: "off",
203
+ autoCorrect: "off",
204
+ autoCapitalize: "none",
205
+ spellCheck: "false",
206
+ readOnly,
207
+ placeholder: state.context.placeholder,
208
+ id: dom.getInputId(state.context),
209
+ type: "text",
210
+ role: "combobox",
211
+ defaultValue: state.context.inputValue,
212
+ "aria-autocomplete": state.context.autoComplete ? "both" : "list",
213
+ "aria-controls": dom.getContentId(state.context),
214
+ "aria-expanded": open,
215
+ "data-state": open ? "open" : "closed",
216
+ "aria-activedescendant": highlightedValue ? dom.getItemId(state.context, highlightedValue) : void 0,
217
+ onClick(event) {
218
+ if (event.defaultPrevented)
219
+ return;
220
+ if (!state.context.openOnClick)
221
+ return;
222
+ if (!interactive)
223
+ return;
224
+ send("INPUT.CLICK");
225
+ },
226
+ onFocus() {
227
+ if (disabled)
228
+ return;
229
+ send("INPUT.FOCUS");
230
+ },
231
+ onBlur() {
232
+ if (disabled)
233
+ return;
234
+ send("INPUT.BLUR");
235
+ },
236
+ onChange(event) {
237
+ send({ type: "INPUT.CHANGE", value: event.currentTarget.value });
238
+ },
239
+ onKeyDown(event) {
240
+ if (event.defaultPrevented)
241
+ return;
242
+ if (!interactive)
243
+ return;
244
+ if (event.ctrlKey || event.shiftKey || isComposingEvent(event))
245
+ return;
246
+ const openOnKeyPress = state.context.openOnKeyPress;
247
+ const isModifierKey = event.ctrlKey || event.metaKey || event.shiftKey;
248
+ const keypress = true;
249
+ const keymap = {
250
+ ArrowDown(event2) {
251
+ if (!openOnKeyPress && !open)
252
+ return;
253
+ send({ type: event2.altKey ? "OPEN" : "INPUT.ARROW_DOWN", keypress });
254
+ event2.preventDefault();
255
+ },
256
+ ArrowUp() {
257
+ if (!openOnKeyPress && !open)
258
+ return;
259
+ send({ type: event.altKey ? "CLOSE" : "INPUT.ARROW_UP", keypress });
260
+ event.preventDefault();
261
+ },
262
+ Home(event2) {
263
+ if (isModifierKey)
264
+ return;
265
+ send({ type: "INPUT.HOME", keypress });
266
+ if (open) {
267
+ event2.preventDefault();
268
+ }
269
+ },
270
+ End(event2) {
271
+ if (isModifierKey)
272
+ return;
273
+ send({ type: "INPUT.END", keypress });
274
+ if (open) {
275
+ event2.preventDefault();
276
+ }
277
+ },
278
+ Enter(event2) {
279
+ send({ type: "INPUT.ENTER", keypress });
280
+ if (open) {
281
+ event2.preventDefault();
282
+ }
283
+ const itemEl = dom.getHighlightedItemEl(state.context);
284
+ clickIfLink(itemEl);
285
+ },
286
+ Escape() {
287
+ send({ type: "INPUT.ESCAPE", keypress });
288
+ event.preventDefault();
289
+ }
290
+ };
291
+ const key = getEventKey(event, state.context);
292
+ const exec = keymap[key];
293
+ exec?.(event);
294
+ }
295
+ });
296
+ },
297
+ getTriggerProps(props = {}) {
298
+ return normalize.button({
299
+ ...parts.trigger.attrs,
300
+ dir: state.context.dir,
301
+ id: dom.getTriggerId(state.context),
302
+ "aria-haspopup": composite ? "listbox" : "dialog",
303
+ type: "button",
304
+ tabIndex: props.focusable ? void 0 : -1,
305
+ "aria-label": translations.triggerLabel,
306
+ "aria-expanded": open,
307
+ "data-state": open ? "open" : "closed",
308
+ "aria-controls": open ? dom.getContentId(state.context) : void 0,
309
+ disabled,
310
+ "data-focusable": dataAttr(props.focusable),
311
+ "data-readonly": dataAttr(readOnly),
312
+ "data-disabled": dataAttr(disabled),
313
+ onFocus() {
314
+ if (!props.focusable)
315
+ return;
316
+ send({ type: "INPUT.FOCUS", src: "trigger" });
317
+ },
318
+ onClick(event) {
319
+ if (event.defaultPrevented)
320
+ return;
321
+ if (!interactive)
322
+ return;
323
+ if (!isLeftClick(event))
324
+ return;
325
+ send("TRIGGER.CLICK");
326
+ },
327
+ onPointerDown(event) {
328
+ if (!interactive)
329
+ return;
330
+ if (event.pointerType === "touch")
331
+ return;
332
+ event.preventDefault();
333
+ queueMicrotask(() => {
334
+ dom.getInputEl(state.context)?.focus({ preventScroll: true });
335
+ });
336
+ },
337
+ onKeyDown(event) {
338
+ if (event.defaultPrevented)
339
+ return;
340
+ if (composite)
341
+ return;
342
+ const keyMap = {
343
+ ArrowDown() {
344
+ send({ type: "INPUT.ARROW_DOWN", src: "trigger" });
345
+ },
346
+ ArrowUp() {
347
+ send({ type: "INPUT.ARROW_UP", src: "trigger" });
348
+ }
349
+ };
350
+ const key = getEventKey(event, state.context);
351
+ const exec = keyMap[key];
352
+ if (exec) {
353
+ exec(event);
354
+ event.preventDefault();
355
+ }
356
+ }
357
+ });
358
+ },
359
+ getContentProps() {
360
+ return normalize.element({
361
+ ...parts.content.attrs,
362
+ dir: state.context.dir,
363
+ id: dom.getContentId(state.context),
364
+ role: !composite ? "dialog" : "listbox",
365
+ tabIndex: -1,
366
+ hidden: !open,
367
+ "data-state": open ? "open" : "closed",
368
+ "aria-labelledby": dom.getLabelId(state.context),
369
+ "aria-multiselectable": state.context.multiple && composite ? true : void 0,
370
+ onPointerDown(event) {
371
+ event.preventDefault();
372
+ }
373
+ });
374
+ },
375
+ getListProps() {
376
+ return normalize.element({
377
+ role: !composite ? "listbox" : void 0,
378
+ "aria-labelledby": dom.getLabelId(state.context),
379
+ "aria-multiselectable": state.context.multiple && !composite ? true : void 0
380
+ });
381
+ },
382
+ getClearTriggerProps() {
383
+ return normalize.button({
384
+ ...parts.clearTrigger.attrs,
385
+ dir: state.context.dir,
386
+ id: dom.getClearTriggerId(state.context),
387
+ type: "button",
388
+ tabIndex: -1,
389
+ disabled,
390
+ "aria-label": translations.clearTriggerLabel,
391
+ "aria-controls": dom.getInputId(state.context),
392
+ hidden: !state.context.value.length,
393
+ onPointerDown(event) {
394
+ event.preventDefault();
395
+ },
396
+ onClick(event) {
397
+ if (event.defaultPrevented)
398
+ return;
399
+ if (!interactive)
400
+ return;
401
+ send({ type: "VALUE.CLEAR", src: "clear-trigger" });
402
+ }
403
+ });
404
+ },
405
+ getItemState,
406
+ getItemProps(props) {
407
+ const itemState = getItemState(props);
408
+ const value = itemState.value;
409
+ return normalize.element({
410
+ ...parts.item.attrs,
411
+ dir: state.context.dir,
412
+ id: dom.getItemId(state.context, value),
413
+ role: "option",
414
+ tabIndex: -1,
415
+ "data-highlighted": dataAttr(itemState.highlighted),
416
+ "data-state": itemState.selected ? "checked" : "unchecked",
417
+ "aria-selected": itemState.highlighted,
418
+ "aria-disabled": itemState.disabled,
419
+ "data-disabled": dataAttr(itemState.disabled),
420
+ "data-value": itemState.value,
421
+ onPointerMove() {
422
+ if (itemState.disabled)
423
+ return;
424
+ if (itemState.highlighted)
425
+ return;
426
+ send({ type: "ITEM.POINTER_MOVE", value });
427
+ },
428
+ onPointerLeave() {
429
+ if (props.persistFocus)
430
+ return;
431
+ if (itemState.disabled)
432
+ return;
433
+ const mouseMoved = state.previousEvent.type.includes("POINTER");
434
+ if (!mouseMoved)
435
+ return;
436
+ send({ type: "ITEM.POINTER_LEAVE", value });
437
+ },
438
+ onPointerUp(event) {
439
+ if (isDownloadingEvent(event))
440
+ return;
441
+ if (isOpeningInNewTab(event))
442
+ return;
443
+ if (isContextMenuEvent(event))
444
+ return;
445
+ if (itemState.disabled)
446
+ return;
447
+ send({ type: "ITEM.CLICK", src: "pointerup", value });
448
+ },
449
+ onTouchEnd(event) {
450
+ event.preventDefault();
451
+ event.stopPropagation();
452
+ }
453
+ });
454
+ },
455
+ getItemTextProps(props) {
456
+ const itemState = getItemState(props);
457
+ return normalize.element({
458
+ ...parts.itemText.attrs,
459
+ dir: state.context.dir,
460
+ "data-disabled": dataAttr(itemState.disabled),
461
+ "data-highlighted": dataAttr(itemState.highlighted)
462
+ });
463
+ },
464
+ getItemIndicatorProps(props) {
465
+ const itemState = getItemState(props);
466
+ return normalize.element({
467
+ "aria-hidden": true,
468
+ ...parts.itemIndicator.attrs,
469
+ dir: state.context.dir,
470
+ "data-state": itemState.selected ? "checked" : "unchecked",
471
+ hidden: !itemState.selected
472
+ });
473
+ },
474
+ getItemGroupProps(props) {
475
+ const { id } = props;
476
+ return normalize.element({
477
+ ...parts.itemGroup.attrs,
478
+ dir: state.context.dir,
479
+ id: dom.getItemGroupId(state.context, id),
480
+ "aria-labelledby": dom.getItemGroupLabelId(state.context, id)
481
+ });
482
+ },
483
+ getItemGroupLabelProps(props) {
484
+ const { htmlFor } = props;
485
+ return normalize.element({
486
+ ...parts.itemGroupLabel.attrs,
487
+ dir: state.context.dir,
488
+ id: dom.getItemGroupLabelId(state.context, htmlFor),
489
+ role: "group"
490
+ });
491
+ }
492
+ };
493
+ }
494
+
495
+ // src/combobox.machine.ts
496
+ import { ariaHidden } from "@zag-js/aria-hidden";
497
+ import { createMachine, guards } from "@zag-js/core";
498
+ import { trackDismissableElement } from "@zag-js/dismissable";
499
+ import { observeAttributes, observeChildren, raf, scrollIntoView } from "@zag-js/dom-query";
500
+ import { getPlacement } from "@zag-js/popper";
501
+ import { addOrRemove, compact, isArray, isBoolean, isEqual, match } from "@zag-js/utils";
502
+ var { and, not } = guards;
503
+ function machine(userContext) {
504
+ const ctx = compact(userContext);
505
+ return createMachine(
506
+ {
507
+ id: "combobox",
508
+ initial: ctx.open ? "suggesting" : "idle",
509
+ context: {
510
+ loopFocus: true,
511
+ openOnClick: false,
512
+ value: [],
513
+ highlightedValue: null,
514
+ inputValue: "",
515
+ allowCustomValue: false,
516
+ closeOnSelect: !ctx.multiple,
517
+ inputBehavior: "none",
518
+ selectionBehavior: "replace",
519
+ openOnKeyPress: true,
520
+ openOnChange: true,
521
+ composite: true,
522
+ ...ctx,
523
+ highlightedItem: null,
524
+ selectedItems: [],
525
+ valueAsString: "",
526
+ collection: ctx.collection ?? collection.empty(),
527
+ positioning: {
528
+ placement: "bottom",
529
+ flip: false,
530
+ sameWidth: true,
531
+ ...ctx.positioning
532
+ },
533
+ translations: {
534
+ triggerLabel: "Toggle suggestions",
535
+ clearTriggerLabel: "Clear value",
536
+ ...ctx.translations
537
+ }
538
+ },
539
+ created: ["syncInitialValues", "syncSelectionBehavior"],
540
+ computed: {
541
+ isInputValueEmpty: (ctx2) => ctx2.inputValue.length === 0,
542
+ isInteractive: (ctx2) => !(ctx2.readOnly || ctx2.disabled),
543
+ autoComplete: (ctx2) => ctx2.inputBehavior === "autocomplete",
544
+ autoHighlight: (ctx2) => ctx2.inputBehavior === "autohighlight",
545
+ hasSelectedItems: (ctx2) => ctx2.value.length > 0
546
+ },
547
+ watch: {
548
+ value: ["syncSelectedItems"],
549
+ inputValue: ["syncInputValue"],
550
+ highlightedValue: ["syncHighlightedItem", "autofillInputValue"],
551
+ multiple: ["syncSelectionBehavior"],
552
+ open: ["toggleVisibility"]
553
+ },
554
+ on: {
555
+ "HIGHLIGHTED_VALUE.SET": {
556
+ actions: ["setHighlightedItem"]
557
+ },
558
+ "ITEM.SELECT": {
559
+ actions: ["selectItem"]
560
+ },
561
+ "ITEM.CLEAR": {
562
+ actions: ["clearItem"]
563
+ },
564
+ "VALUE.SET": {
565
+ actions: ["setSelectedItems"]
566
+ },
567
+ "INPUT_VALUE.SET": {
568
+ actions: "setInputValue"
569
+ },
570
+ "COLLECTION.SET": {
571
+ actions: ["setCollection"]
572
+ },
573
+ "POSITIONING.SET": {
574
+ actions: ["reposition"]
575
+ }
576
+ },
577
+ states: {
578
+ idle: {
579
+ tags: ["idle", "closed"],
580
+ entry: ["scrollContentToTop", "clearHighlightedItem"],
581
+ on: {
582
+ "CONTROLLED.OPEN": {
583
+ target: "interacting"
584
+ },
585
+ "TRIGGER.CLICK": [
586
+ {
587
+ guard: "isOpenControlled",
588
+ actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
589
+ },
590
+ {
591
+ target: "interacting",
592
+ actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
593
+ }
594
+ ],
595
+ "INPUT.CLICK": [
596
+ {
597
+ guard: "isOpenControlled",
598
+ actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
599
+ },
600
+ {
601
+ target: "interacting",
602
+ actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
603
+ }
604
+ ],
605
+ "INPUT.FOCUS": {
606
+ target: "focused"
607
+ },
608
+ OPEN: [
609
+ {
610
+ guard: "isOpenControlled",
611
+ actions: ["invokeOnOpen"]
612
+ },
613
+ {
614
+ target: "interacting",
615
+ actions: ["invokeOnOpen"]
616
+ }
617
+ ],
618
+ "VALUE.CLEAR": {
619
+ target: "focused",
620
+ actions: ["clearInputValue", "clearSelectedItems", "setInitialFocus"]
621
+ }
622
+ }
623
+ },
624
+ focused: {
625
+ tags: ["focused", "closed"],
626
+ entry: ["scrollContentToTop", "clearHighlightedItem"],
627
+ on: {
628
+ "CONTROLLED.OPEN": [
629
+ {
630
+ guard: "isChangeEvent",
631
+ target: "suggesting"
632
+ },
633
+ {
634
+ target: "interacting"
635
+ }
636
+ ],
637
+ "INPUT.CHANGE": [
638
+ {
639
+ guard: and("isOpenControlled", "openOnChange"),
640
+ actions: ["setInputValue", "invokeOnOpen", "highlightFirstItemIfNeeded"]
641
+ },
642
+ {
643
+ guard: "openOnChange",
644
+ target: "suggesting",
645
+ actions: ["setInputValue", "invokeOnOpen", "highlightFirstItemIfNeeded"]
646
+ },
647
+ {
648
+ actions: "setInputValue"
649
+ }
650
+ ],
651
+ "LAYER.INTERACT_OUTSIDE": {
652
+ target: "idle"
653
+ },
654
+ "INPUT.ESCAPE": {
655
+ guard: and("isCustomValue", not("allowCustomValue")),
656
+ actions: "revertInputValue"
657
+ },
658
+ "INPUT.BLUR": {
659
+ target: "idle"
660
+ },
661
+ "INPUT.CLICK": [
662
+ {
663
+ guard: "isOpenControlled",
664
+ actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
665
+ },
666
+ {
667
+ target: "interacting",
668
+ actions: ["highlightFirstSelectedItem", "invokeOnOpen"]
669
+ }
670
+ ],
671
+ "TRIGGER.CLICK": [
672
+ {
673
+ guard: "isOpenControlled",
674
+ actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
675
+ },
676
+ {
677
+ target: "interacting",
678
+ actions: ["setInitialFocus", "highlightFirstSelectedItem", "invokeOnOpen"]
679
+ }
680
+ ],
681
+ "INPUT.ARROW_DOWN": [
682
+ // == group 1 ==
683
+ {
684
+ guard: and("isOpenControlled", "autoComplete"),
685
+ actions: ["invokeOnOpen"]
686
+ },
687
+ {
688
+ guard: "autoComplete",
689
+ target: "interacting",
690
+ actions: ["invokeOnOpen"]
691
+ },
692
+ // == group 2 ==
693
+ {
694
+ guard: "isOpenControlled",
695
+ actions: ["highlightFirstOrSelectedItem", "invokeOnOpen"]
696
+ },
697
+ {
698
+ target: "interacting",
699
+ actions: ["highlightFirstOrSelectedItem", "invokeOnOpen"]
700
+ }
701
+ ],
702
+ "INPUT.ARROW_UP": [
703
+ // == group 1 ==
704
+ {
705
+ guard: "autoComplete",
706
+ target: "interacting",
707
+ actions: "invokeOnOpen"
708
+ },
709
+ {
710
+ guard: "autoComplete",
711
+ target: "interacting",
712
+ actions: "invokeOnOpen"
713
+ },
714
+ // == group 2 ==
715
+ {
716
+ target: "interacting",
717
+ actions: ["highlightLastOrSelectedItem", "invokeOnOpen"]
718
+ },
719
+ {
720
+ target: "interacting",
721
+ actions: ["highlightLastOrSelectedItem", "invokeOnOpen"]
722
+ }
723
+ ],
724
+ OPEN: [
725
+ {
726
+ guard: "isOpenControlled",
727
+ actions: ["invokeOnOpen"]
728
+ },
729
+ {
730
+ target: "interacting",
731
+ actions: ["invokeOnOpen"]
732
+ }
733
+ ],
734
+ "VALUE.CLEAR": {
735
+ actions: ["clearInputValue", "clearSelectedItems"]
736
+ }
737
+ }
738
+ },
739
+ interacting: {
740
+ tags: ["open", "focused"],
741
+ entry: ["setInitialFocus"],
742
+ activities: ["scrollToHighlightedItem", "trackDismissableLayer", "computePlacement", "hideOtherElements"],
743
+ on: {
744
+ "CONTROLLED.CLOSE": [
745
+ {
746
+ guard: "restoreFocus",
747
+ target: "focused",
748
+ actions: ["setFinalFocus"]
749
+ },
750
+ {
751
+ target: "idle"
752
+ }
753
+ ],
754
+ "INPUT.HOME": {
755
+ actions: ["highlightFirstItem"]
756
+ },
757
+ "INPUT.END": {
758
+ actions: ["highlightLastItem"]
759
+ },
760
+ "INPUT.ARROW_DOWN": [
761
+ {
762
+ guard: and("autoComplete", "isLastItemHighlighted"),
763
+ actions: ["clearHighlightedItem", "scrollContentToTop"]
764
+ },
765
+ {
766
+ actions: ["highlightNextItem"]
767
+ }
768
+ ],
769
+ "INPUT.ARROW_UP": [
770
+ {
771
+ guard: and("autoComplete", "isFirstItemHighlighted"),
772
+ actions: "clearHighlightedItem"
773
+ },
774
+ {
775
+ actions: "highlightPrevItem"
776
+ }
777
+ ],
778
+ "INPUT.ENTER": [
779
+ {
780
+ guard: and("isOpenControlled", "closeOnSelect"),
781
+ actions: ["selectHighlightedItem", "invokeOnClose"]
782
+ },
783
+ {
784
+ guard: "closeOnSelect",
785
+ target: "focused",
786
+ actions: ["selectHighlightedItem", "invokeOnClose", "setFinalFocus"]
787
+ },
788
+ {
789
+ actions: ["selectHighlightedItem"]
790
+ }
791
+ ],
792
+ "INPUT.CHANGE": [
793
+ {
794
+ guard: "autoComplete",
795
+ target: "suggesting",
796
+ actions: ["setInputValue", "invokeOnOpen"]
797
+ },
798
+ {
799
+ target: "suggesting",
800
+ actions: ["clearHighlightedItem", "setInputValue", "invokeOnOpen"]
801
+ }
802
+ ],
803
+ "ITEM.POINTER_MOVE": {
804
+ actions: ["setHighlightedItem"]
805
+ },
806
+ "ITEM.POINTER_LEAVE": {
807
+ actions: ["clearHighlightedItem"]
808
+ },
809
+ "ITEM.CLICK": [
810
+ {
811
+ guard: and("isOpenControlled", "closeOnSelect"),
812
+ actions: ["selectItem", "invokeOnClose"]
813
+ },
814
+ {
815
+ guard: "closeOnSelect",
816
+ target: "focused",
817
+ actions: ["selectItem", "invokeOnClose", "setFinalFocus"]
818
+ },
819
+ {
820
+ actions: ["selectItem"]
821
+ }
822
+ ],
823
+ "LAYER.ESCAPE": [
824
+ {
825
+ guard: and("isOpenControlled", "autoComplete"),
826
+ actions: ["syncInputValue", "invokeOnClose"]
827
+ },
828
+ {
829
+ guard: "autoComplete",
830
+ target: "focused",
831
+ actions: ["syncInputValue", "invokeOnClose"]
832
+ },
833
+ {
834
+ guard: "isOpenControlled",
835
+ actions: "invokeOnClose"
836
+ },
837
+ {
838
+ target: "focused",
839
+ actions: ["invokeOnClose", "setFinalFocus"]
840
+ }
841
+ ],
842
+ "TRIGGER.CLICK": [
843
+ {
844
+ guard: "isOpenControlled",
845
+ actions: "invokeOnClose"
846
+ },
847
+ {
848
+ target: "focused",
849
+ actions: "invokeOnClose"
850
+ }
851
+ ],
852
+ "LAYER.INTERACT_OUTSIDE": [
853
+ // == group 1 ==
854
+ {
855
+ guard: and("isOpenControlled", "isCustomValue", not("allowCustomValue")),
856
+ actions: ["revertInputValue", "invokeOnClose"]
857
+ },
858
+ {
859
+ guard: and("isCustomValue", not("allowCustomValue")),
860
+ target: "idle",
861
+ actions: ["revertInputValue", "invokeOnClose"]
862
+ },
863
+ // == group 2 ==
864
+ {
865
+ guard: "isOpenControlled",
866
+ actions: "invokeOnClose"
867
+ },
868
+ {
869
+ target: "idle",
870
+ actions: "invokeOnClose"
871
+ }
872
+ ],
873
+ CLOSE: [
874
+ {
875
+ guard: "isOpenControlled",
876
+ actions: ["invokeOnClose"]
877
+ },
878
+ {
879
+ target: "focused",
880
+ actions: ["invokeOnClose", "setFinalFocus"]
881
+ }
882
+ ],
883
+ "VALUE.CLEAR": [
884
+ {
885
+ guard: "isOpenControlled",
886
+ actions: ["clearInputValue", "clearSelectedItems", "invokeOnClose"]
887
+ },
888
+ {
889
+ target: "focused",
890
+ actions: ["clearInputValue", "clearSelectedItems", "invokeOnClose", "setFinalFocus"]
891
+ }
892
+ ]
893
+ }
894
+ },
895
+ suggesting: {
896
+ tags: ["open", "focused"],
897
+ activities: [
898
+ "trackDismissableLayer",
899
+ "scrollToHighlightedItem",
900
+ "computePlacement",
901
+ "trackChildNodes",
902
+ "hideOtherElements"
903
+ ],
904
+ entry: ["setInitialFocus"],
905
+ on: {
906
+ "CONTROLLED.CLOSE": [
907
+ {
908
+ guard: "restoreFocus",
909
+ target: "focused",
910
+ actions: ["setFinalFocus"]
911
+ },
912
+ {
913
+ target: "idle"
914
+ }
915
+ ],
916
+ CHILDREN_CHANGE: {
917
+ actions: ["highlightFirstItem"]
918
+ },
919
+ "INPUT.ARROW_DOWN": {
920
+ target: "interacting",
921
+ actions: ["highlightNextItem"]
922
+ },
923
+ "INPUT.ARROW_UP": {
924
+ target: "interacting",
925
+ actions: ["highlightPrevItem"]
926
+ },
927
+ "INPUT.HOME": {
928
+ target: "interacting",
929
+ actions: ["highlightFirstItem"]
930
+ },
931
+ "INPUT.END": {
932
+ target: "interacting",
933
+ actions: ["highlightLastItem"]
934
+ },
935
+ "INPUT.ENTER": [
936
+ {
937
+ guard: and("isOpenControlled", "closeOnSelect"),
938
+ actions: ["selectHighlightedItem", "invokeOnClose"]
939
+ },
940
+ {
941
+ guard: "closeOnSelect",
942
+ target: "focused",
943
+ actions: ["selectHighlightedItem", "invokeOnClose", "setFinalFocus"]
944
+ },
945
+ {
946
+ actions: ["selectHighlightedItem"]
947
+ }
948
+ ],
949
+ "INPUT.CHANGE": [
950
+ {
951
+ guard: "autoHighlight",
952
+ actions: ["setInputValue"]
953
+ },
954
+ {
955
+ actions: ["setInputValue"]
956
+ }
957
+ ],
958
+ "LAYER.ESCAPE": [
959
+ {
960
+ guard: "isOpenControlled",
961
+ actions: ["invokeOnClose"]
962
+ },
963
+ {
964
+ target: "focused",
965
+ actions: ["invokeOnClose"]
966
+ }
967
+ ],
968
+ "ITEM.POINTER_MOVE": {
969
+ target: "interacting",
970
+ actions: ["setHighlightedItem"]
971
+ },
972
+ "ITEM.POINTER_LEAVE": {
973
+ actions: ["clearHighlightedItem"]
974
+ },
975
+ "LAYER.INTERACT_OUTSIDE": [
976
+ // == group 1 ==
977
+ {
978
+ guard: and("isOpenControlled", "isCustomValue", not("allowCustomValue")),
979
+ actions: ["revertInputValue", "invokeOnClose"]
980
+ },
981
+ {
982
+ guard: and("isCustomValue", not("allowCustomValue")),
983
+ target: "idle",
984
+ actions: ["revertInputValue", "invokeOnClose"]
985
+ },
986
+ // == group 2 ==
987
+ {
988
+ guard: "isOpenControlled",
989
+ actions: ["invokeOnClose"]
990
+ },
991
+ {
992
+ target: "idle",
993
+ actions: ["invokeOnClose"]
994
+ }
995
+ ],
996
+ "TRIGGER.CLICK": [
997
+ {
998
+ guard: "isOpenControlled",
999
+ actions: ["invokeOnClose"]
1000
+ },
1001
+ {
1002
+ target: "focused",
1003
+ actions: ["invokeOnClose"]
1004
+ }
1005
+ ],
1006
+ "ITEM.CLICK": [
1007
+ {
1008
+ guard: and("isOpenControlled", "closeOnSelect"),
1009
+ actions: ["selectItem", "invokeOnClose"]
1010
+ },
1011
+ {
1012
+ guard: "closeOnSelect",
1013
+ target: "focused",
1014
+ actions: ["selectItem", "invokeOnClose", "setFinalFocus"]
1015
+ },
1016
+ {
1017
+ actions: ["selectItem"]
1018
+ }
1019
+ ],
1020
+ CLOSE: [
1021
+ {
1022
+ guard: "isOpenControlled",
1023
+ actions: ["invokeOnClose"]
1024
+ },
1025
+ {
1026
+ target: "focused",
1027
+ actions: ["invokeOnClose", "setFinalFocus"]
1028
+ }
1029
+ ],
1030
+ "VALUE.CLEAR": [
1031
+ {
1032
+ guard: "isOpenControlled",
1033
+ actions: ["clearInputValue", "clearSelectedItems", "invokeOnClose"]
1034
+ },
1035
+ {
1036
+ target: "focused",
1037
+ actions: ["clearInputValue", "clearSelectedItems", "invokeOnClose", "setFinalFocus"]
1038
+ }
1039
+ ]
1040
+ }
1041
+ }
1042
+ }
1043
+ },
1044
+ {
1045
+ guards: {
1046
+ isInputValueEmpty: (ctx2) => ctx2.isInputValueEmpty,
1047
+ autoComplete: (ctx2) => ctx2.autoComplete && !ctx2.multiple,
1048
+ autoHighlight: (ctx2) => ctx2.autoHighlight,
1049
+ isFirstItemHighlighted: (ctx2) => ctx2.collection.first() === ctx2.highlightedValue,
1050
+ isLastItemHighlighted: (ctx2) => ctx2.collection.last() === ctx2.highlightedValue,
1051
+ isCustomValue: (ctx2) => ctx2.inputValue !== ctx2.valueAsString,
1052
+ allowCustomValue: (ctx2) => !!ctx2.allowCustomValue,
1053
+ hasHighlightedItem: (ctx2) => ctx2.highlightedValue != null,
1054
+ closeOnSelect: (ctx2) => !!ctx2.closeOnSelect,
1055
+ isOpenControlled: (ctx2) => !!ctx2["open.controlled"],
1056
+ openOnChange: (ctx2, evt) => {
1057
+ if (isBoolean(ctx2.openOnChange))
1058
+ return ctx2.openOnChange;
1059
+ return !!ctx2.openOnChange?.({ inputValue: evt.value });
1060
+ },
1061
+ restoreFocus: (_ctx, evt) => evt.restoreFocus == null ? true : !!evt.restoreFocus,
1062
+ isChangeEvent: (_ctx, evt) => evt.previousEvent?.type === "INPUT.CHANGE"
1063
+ },
1064
+ activities: {
1065
+ trackDismissableLayer(ctx2, _evt, { send }) {
1066
+ if (ctx2.disableLayer)
1067
+ return;
1068
+ const contentEl = () => dom.getContentEl(ctx2);
1069
+ return trackDismissableElement(contentEl, {
1070
+ defer: true,
1071
+ exclude: () => [dom.getInputEl(ctx2), dom.getTriggerEl(ctx2), dom.getClearTriggerEl(ctx2)],
1072
+ onFocusOutside: ctx2.onFocusOutside,
1073
+ onPointerDownOutside: ctx2.onPointerDownOutside,
1074
+ onInteractOutside: ctx2.onInteractOutside,
1075
+ onEscapeKeyDown(event) {
1076
+ event.preventDefault();
1077
+ event.stopPropagation();
1078
+ send("LAYER.ESCAPE");
1079
+ },
1080
+ onDismiss() {
1081
+ send({ type: "LAYER.INTERACT_OUTSIDE", restoreFocus: false });
1082
+ }
1083
+ });
1084
+ },
1085
+ hideOtherElements(ctx2) {
1086
+ return ariaHidden([dom.getInputEl(ctx2), dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)]);
1087
+ },
1088
+ computePlacement(ctx2) {
1089
+ const controlEl = () => dom.getControlEl(ctx2);
1090
+ const positionerEl = () => dom.getPositionerEl(ctx2);
1091
+ ctx2.currentPlacement = ctx2.positioning.placement;
1092
+ return getPlacement(controlEl, positionerEl, {
1093
+ ...ctx2.positioning,
1094
+ defer: true,
1095
+ onComplete(data) {
1096
+ ctx2.currentPlacement = data.placement;
1097
+ }
1098
+ });
1099
+ },
1100
+ // in event the options are fetched (async), we still want to auto-highlight the first option
1101
+ trackChildNodes(ctx2, _evt, { send }) {
1102
+ if (!ctx2.autoHighlight)
1103
+ return;
1104
+ const exec = () => send("CHILDREN_CHANGE");
1105
+ const contentEl = () => dom.getContentEl(ctx2);
1106
+ return observeChildren(contentEl, {
1107
+ callback: exec,
1108
+ defer: true
1109
+ });
1110
+ },
1111
+ scrollToHighlightedItem(ctx2, _evt, { getState }) {
1112
+ const inputEl = dom.getInputEl(ctx2);
1113
+ let cleanups = [];
1114
+ const exec = (immediate) => {
1115
+ const state = getState();
1116
+ const pointer = state.event.type.includes("POINTER");
1117
+ if (pointer || !ctx2.highlightedValue)
1118
+ return;
1119
+ const itemEl = dom.getHighlightedItemEl(ctx2);
1120
+ const contentEl = dom.getContentEl(ctx2);
1121
+ if (ctx2.scrollToIndexFn) {
1122
+ const highlightedIndex = ctx2.collection.indexOf(ctx2.highlightedValue);
1123
+ ctx2.scrollToIndexFn({ index: highlightedIndex, immediate });
1124
+ return;
1125
+ }
1126
+ const rafCleanup2 = raf(() => {
1127
+ scrollIntoView(itemEl, { rootEl: contentEl, block: "nearest" });
1128
+ });
1129
+ cleanups.push(rafCleanup2);
1130
+ };
1131
+ const rafCleanup = raf(() => exec(true));
1132
+ cleanups.push(rafCleanup);
1133
+ const observerCleanup = observeAttributes(inputEl, {
1134
+ attributes: ["aria-activedescendant"],
1135
+ callback: () => exec(false)
1136
+ });
1137
+ cleanups.push(observerCleanup);
1138
+ return () => {
1139
+ cleanups.forEach((cleanup) => cleanup());
1140
+ };
1141
+ }
1142
+ },
1143
+ actions: {
1144
+ reposition(ctx2, evt) {
1145
+ const controlEl = () => dom.getControlEl(ctx2);
1146
+ const positionerEl = () => dom.getPositionerEl(ctx2);
1147
+ getPlacement(controlEl, positionerEl, {
1148
+ ...ctx2.positioning,
1149
+ ...evt.options,
1150
+ defer: true,
1151
+ listeners: false,
1152
+ onComplete(data) {
1153
+ ctx2.currentPlacement = data.placement;
1154
+ }
1155
+ });
1156
+ },
1157
+ setHighlightedItem(ctx2, evt) {
1158
+ if (evt.value == null)
1159
+ return;
1160
+ set.highlightedValue(ctx2, evt.value);
1161
+ },
1162
+ clearHighlightedItem(ctx2) {
1163
+ set.highlightedValue(ctx2, null, true);
1164
+ },
1165
+ selectHighlightedItem(ctx2) {
1166
+ set.value(ctx2, ctx2.highlightedValue);
1167
+ },
1168
+ selectItem(ctx2, evt) {
1169
+ if (evt.value == null)
1170
+ return;
1171
+ set.value(ctx2, evt.value);
1172
+ },
1173
+ clearItem(ctx2, evt) {
1174
+ if (evt.value == null)
1175
+ return;
1176
+ const value = ctx2.value.filter((v) => v !== evt.value);
1177
+ set.value(ctx2, value);
1178
+ },
1179
+ setInitialFocus(ctx2) {
1180
+ raf(() => {
1181
+ dom.focusInputEl(ctx2);
1182
+ });
1183
+ },
1184
+ setFinalFocus(ctx2) {
1185
+ raf(() => {
1186
+ const triggerEl = dom.getTriggerEl(ctx2);
1187
+ if (triggerEl?.dataset.focusable == null) {
1188
+ dom.focusInputEl(ctx2);
1189
+ } else {
1190
+ dom.focusTriggerEl(ctx2);
1191
+ }
1192
+ });
1193
+ },
1194
+ syncInputValue(ctx2) {
1195
+ const inputEl = dom.getInputEl(ctx2);
1196
+ if (!inputEl)
1197
+ return;
1198
+ inputEl.value = ctx2.inputValue;
1199
+ queueMicrotask(() => {
1200
+ const { selectionStart, selectionEnd } = inputEl;
1201
+ if (Math.abs((selectionEnd ?? 0) - (selectionStart ?? 0)) !== 0)
1202
+ return;
1203
+ if (selectionStart !== 0)
1204
+ return;
1205
+ inputEl.setSelectionRange(inputEl.value.length, inputEl.value.length);
1206
+ });
1207
+ },
1208
+ setInputValue(ctx2, evt) {
1209
+ set.inputValue(ctx2, evt.value);
1210
+ },
1211
+ clearInputValue(ctx2) {
1212
+ set.inputValue(ctx2, "");
1213
+ },
1214
+ revertInputValue(ctx2) {
1215
+ const inputValue = match(ctx2.selectionBehavior, {
1216
+ replace: ctx2.hasSelectedItems ? ctx2.valueAsString : "",
1217
+ preserve: ctx2.inputValue,
1218
+ clear: ""
1219
+ });
1220
+ set.inputValue(ctx2, inputValue);
1221
+ },
1222
+ syncInitialValues(ctx2) {
1223
+ const selectedItems = ctx2.collection.items(ctx2.value);
1224
+ const valueAsString = ctx2.collection.itemsToString(selectedItems);
1225
+ ctx2.highlightedItem = ctx2.collection.item(ctx2.highlightedValue);
1226
+ ctx2.selectedItems = selectedItems;
1227
+ ctx2.valueAsString = valueAsString;
1228
+ ctx2.inputValue = match(ctx2.selectionBehavior, {
1229
+ preserve: ctx2.inputValue || valueAsString,
1230
+ replace: valueAsString,
1231
+ clear: ""
1232
+ });
1233
+ },
1234
+ syncSelectionBehavior(ctx2) {
1235
+ if (ctx2.multiple) {
1236
+ ctx2.selectionBehavior = "clear";
1237
+ }
1238
+ },
1239
+ setSelectedItems(ctx2, evt) {
1240
+ if (!isArray(evt.value))
1241
+ return;
1242
+ set.value(ctx2, evt.value);
1243
+ },
1244
+ clearSelectedItems(ctx2) {
1245
+ set.value(ctx2, []);
1246
+ },
1247
+ scrollContentToTop(ctx2) {
1248
+ if (ctx2.scrollToIndexFn) {
1249
+ ctx2.scrollToIndexFn({ index: 0, immediate: true });
1250
+ } else {
1251
+ const contentEl = dom.getContentEl(ctx2);
1252
+ if (!contentEl)
1253
+ return;
1254
+ contentEl.scrollTop = 0;
1255
+ }
1256
+ },
1257
+ invokeOnOpen(ctx2) {
1258
+ ctx2.onOpenChange?.({ open: true });
1259
+ },
1260
+ invokeOnClose(ctx2) {
1261
+ ctx2.onOpenChange?.({ open: false });
1262
+ },
1263
+ highlightFirstItem(ctx2) {
1264
+ raf(() => {
1265
+ const value = ctx2.collection.first();
1266
+ set.highlightedValue(ctx2, value);
1267
+ });
1268
+ },
1269
+ highlightFirstItemIfNeeded(ctx2) {
1270
+ if (!ctx2.autoHighlight)
1271
+ return;
1272
+ raf(() => {
1273
+ const value = ctx2.collection.first();
1274
+ set.highlightedValue(ctx2, value);
1275
+ });
1276
+ },
1277
+ highlightLastItem(ctx2) {
1278
+ raf(() => {
1279
+ const value = ctx2.collection.last();
1280
+ set.highlightedValue(ctx2, value);
1281
+ });
1282
+ },
1283
+ highlightNextItem(ctx2) {
1284
+ let value = null;
1285
+ if (ctx2.highlightedValue) {
1286
+ value = ctx2.collection.next(ctx2.highlightedValue);
1287
+ if (!value && ctx2.loopFocus)
1288
+ value = ctx2.collection.first();
1289
+ } else {
1290
+ value = ctx2.collection.first();
1291
+ }
1292
+ set.highlightedValue(ctx2, value);
1293
+ },
1294
+ highlightPrevItem(ctx2) {
1295
+ let value = null;
1296
+ if (ctx2.highlightedValue) {
1297
+ value = ctx2.collection.prev(ctx2.highlightedValue);
1298
+ if (!value && ctx2.loopFocus)
1299
+ value = ctx2.collection.last();
1300
+ } else {
1301
+ value = ctx2.collection.last();
1302
+ }
1303
+ set.highlightedValue(ctx2, value);
1304
+ },
1305
+ highlightFirstSelectedItem(ctx2) {
1306
+ raf(() => {
1307
+ const [value] = ctx2.collection.sort(ctx2.value);
1308
+ set.highlightedValue(ctx2, value);
1309
+ });
1310
+ },
1311
+ highlightFirstOrSelectedItem(ctx2) {
1312
+ raf(() => {
1313
+ let value = null;
1314
+ if (ctx2.hasSelectedItems) {
1315
+ value = ctx2.collection.sort(ctx2.value)[0];
1316
+ } else {
1317
+ value = ctx2.collection.first();
1318
+ }
1319
+ set.highlightedValue(ctx2, value);
1320
+ });
1321
+ },
1322
+ highlightLastOrSelectedItem(ctx2) {
1323
+ raf(() => {
1324
+ let value = null;
1325
+ if (ctx2.hasSelectedItems) {
1326
+ value = ctx2.collection.sort(ctx2.value)[0];
1327
+ } else {
1328
+ value = ctx2.collection.last();
1329
+ }
1330
+ set.highlightedValue(ctx2, value);
1331
+ });
1332
+ },
1333
+ autofillInputValue(ctx2, evt) {
1334
+ const inputEl = dom.getInputEl(ctx2);
1335
+ if (!ctx2.autoComplete || !inputEl || !evt.keypress)
1336
+ return;
1337
+ const valueText = ctx2.collection.valueToString(ctx2.highlightedValue);
1338
+ raf(() => {
1339
+ inputEl.value = valueText || ctx2.inputValue;
1340
+ });
1341
+ },
1342
+ setCollection(ctx2, evt) {
1343
+ ctx2.collection = evt.value;
1344
+ },
1345
+ syncSelectedItems(ctx2) {
1346
+ sync.valueChange(ctx2);
1347
+ },
1348
+ syncHighlightedItem(ctx2) {
1349
+ sync.highlightChange(ctx2);
1350
+ },
1351
+ toggleVisibility(ctx2, evt, { send }) {
1352
+ send({ type: ctx2.open ? "CONTROLLED.OPEN" : "CONTROLLED.CLOSE", previousEvent: evt });
1353
+ }
1354
+ }
1355
+ }
1356
+ );
1357
+ }
1358
+ var sync = {
1359
+ valueChange: (ctx) => {
1360
+ const prevSelectedItems = ctx.selectedItems;
1361
+ ctx.selectedItems = ctx.value.map((v) => {
1362
+ const foundItem = prevSelectedItems.find((item) => ctx.collection.itemToValue(item) === v);
1363
+ if (foundItem)
1364
+ return foundItem;
1365
+ return ctx.collection.item(v);
1366
+ });
1367
+ const valueAsString = ctx.collection.itemsToString(ctx.selectedItems);
1368
+ ctx.valueAsString = valueAsString;
1369
+ let inputValue;
1370
+ if (ctx.getSelectionValue) {
1371
+ inputValue = ctx.getSelectionValue({
1372
+ inputValue: ctx.inputValue,
1373
+ selectedItems: Array.from(ctx.selectedItems),
1374
+ valueAsString
1375
+ });
1376
+ } else {
1377
+ inputValue = match(ctx.selectionBehavior, {
1378
+ replace: ctx.valueAsString,
1379
+ preserve: ctx.inputValue,
1380
+ clear: ""
1381
+ });
1382
+ }
1383
+ set.inputValue(ctx, inputValue);
1384
+ },
1385
+ highlightChange: (ctx) => {
1386
+ ctx.highlightedItem = ctx.collection.item(ctx.highlightedValue);
1387
+ }
1388
+ };
1389
+ var invoke = {
1390
+ valueChange: (ctx) => {
1391
+ sync.valueChange(ctx);
1392
+ ctx.onValueChange?.({
1393
+ value: Array.from(ctx.value),
1394
+ items: Array.from(ctx.selectedItems)
1395
+ });
1396
+ },
1397
+ highlightChange: (ctx) => {
1398
+ sync.highlightChange(ctx);
1399
+ ctx.onHighlightChange?.({
1400
+ highlightedValue: ctx.highlightedValue,
1401
+ highlightedItem: ctx.highlightedItem
1402
+ });
1403
+ },
1404
+ inputChange: (ctx) => {
1405
+ ctx.onInputValueChange?.({ inputValue: ctx.inputValue });
1406
+ }
1407
+ };
1408
+ var set = {
1409
+ value: (ctx, value, force = false) => {
1410
+ if (isEqual(ctx.value, value))
1411
+ return;
1412
+ if (value == null && !force)
1413
+ return;
1414
+ if (value == null && force) {
1415
+ ctx.value = [];
1416
+ invoke.valueChange(ctx);
1417
+ return;
1418
+ }
1419
+ if (isArray(value)) {
1420
+ ctx.value = value;
1421
+ } else if (value != null) {
1422
+ ctx.value = ctx.multiple ? addOrRemove(ctx.value, value) : [value];
1423
+ }
1424
+ invoke.valueChange(ctx);
1425
+ },
1426
+ highlightedValue: (ctx, value, force = false) => {
1427
+ if (isEqual(ctx.highlightedValue, value))
1428
+ return;
1429
+ if (!value && !force)
1430
+ return;
1431
+ ctx.highlightedValue = value || null;
1432
+ invoke.highlightChange(ctx);
1433
+ },
1434
+ inputValue: (ctx, value) => {
1435
+ if (isEqual(ctx.inputValue, value))
1436
+ return;
1437
+ ctx.inputValue = value;
1438
+ invoke.inputChange(ctx);
1439
+ }
1440
+ };
1441
+ export {
1442
+ anatomy,
1443
+ collection,
1444
+ connect,
1445
+ machine
1446
+ };
2
1447
  //# sourceMappingURL=index.mjs.map