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