UNPKG

maz-ui

Version:

A standalone components library for Vue.Js 3 & Nuxt.Js 3

1 lines 15.8 kB
import{t as _plugin_vue_export_helper_default}from"./_plugin-vue_export-helper.ChmETRGw.js";import{t as hasSlotContent}from"./hasSlotContent.akaXJLAp.js";import{useInstanceUniqId}from"../composables/useInstanceUniqId.js";import{useStringMatching}from"../composables/useStringMatching.js";import{t as MazInput_default}from"./MazInput.C8eCMnat.js";import{t as MazPopover_default}from"./MazPopover.BTvrYenI.js";import{Fragment,computed,createBlock,createCommentVNode,createElementBlock,createElementVNode,createSlots,createVNode,defineAsyncComponent,defineComponent,mergeModels,mergeProps,nextTick,normalizeClass,normalizeStyle,openBlock,ref,renderList,renderSlot,toDisplayString,unref,useModel,useTemplateRef,watch,withCtx,withModifiers}from"vue";import{MazMagnifyingGlass}from"@maz-ui/icons/lazy/MazMagnifyingGlass";import{useTranslations}from"@maz-ui/translations/composables/useTranslations";import{MazNoSymbol}from"@maz-ui/icons/lazy/MazNoSymbol";import{MazChevronDown}from"@maz-ui/icons/static/MazChevronDown";import{debounceCallback}from"@maz-ui/utils/helpers/debounceCallback";import{isClient}from"@maz-ui/utils/helpers/isClient";import{normalizeString}from"@maz-ui/utils/helpers/normalizeString";import '../assets/MazSelect.D74CtRIJ.css';var _hoisted_1=[`disabled`,`aria-label`];var _hoisted_2=[`id`];var _hoisted_3={key:0,class:`m-select-list__search-wrapper`};var _hoisted_4={class:`m-select-list__no-results`};var _hoisted_5={key:2,ref:`optionListWrapper`,class:`m-select-list__scroll-wrapper`,tabindex:`-1`};var _hoisted_6={class:`m-select-list-optgroup`};var _hoisted_7=[`tabindex`,`onClick`];var MazSelect_default=_plugin_vue_export_helper_default(defineComponent({inheritAttrs:!1,__name:`MazSelect`,props:mergeModels({style:{type:[Boolean,null,String,Object,Array],default:()=>void 0},class:{type:[Boolean,null,String,Object,Array],default:()=>void 0},id:{default:()=>void 0},label:{},placeholder:{},modelValue:{default:()=>void 0},options:{},optionValueKey:{default:`value`},optionLabelKey:{default:`label`},optionInputValueKey:{default:`label`},listPosition:{default:`auto`},preferPosition:{default:`bottom-start`},fallbackPosition:{default:`top-start`},itemHeight:{default:()=>void 0},maxListHeight:{default:240},maxListWidth:{default:()=>void 0},minListHeight:{default:()=>void 0},minListWidth:{default:()=>void 0},size:{default:`md`},color:{default:`primary`},search:{type:Boolean},searchFunction:{type:Function},searchThreshold:{default:.75},multiple:{type:Boolean,default:!1},required:{type:Boolean},disabled:{type:Boolean},block:{type:Boolean},autocomplete:{default:`off`},translations:{},formatInputValue:{type:Function},transition:{default:`scale-fade`}},{open:{default:!1},openModifiers:{}}),emits:mergeModels([`close`,`open`,`blur`,`focus`,`change`,`input`,`update:model-value`,`selected-option`],[`update:open`]),setup(__props,{expose:__expose,emit:__emit}){let emits=__emit;let MazCheckbox=defineAsyncComponent(()=>import(`../components/MazCheckbox.js`));let popoverComponent=useTemplateRef(`popover`);let inputRef=useTemplateRef(`input`);let searchInputRef=useTemplateRef(`searchInput`);let optionListElement=useTemplateRef(`optionListRef`);let optionListWrapperRef=useTemplateRef(`optionListWrapper`);let selectedTextColor=computed(()=>`hsl(var(--maz-${__props.color}))`);let selectedBgColor=computed(()=>`hsl(var(--maz-${__props.color}-500) / 0.1)`);let{t}=useTranslations();let messages=computed(()=>({searchPlaceholder:__props.translations?.searchPlaceholder||t(`select.searchPlaceholder`)}));let isOpen=useModel(__props,`open`);let instanceId=useInstanceUniqId({componentName:`MazSelect`,providedId:__props.id});function getOptionPayload(option){return{[__props.optionValueKey]:option,[__props.optionLabelKey]:option,[__props.optionInputValueKey]:option}}function getNormalizedOptionPayload(option){return{...option,[__props.optionValueKey]:option[__props.optionValueKey],[__props.optionLabelKey]:option[__props.optionLabelKey],[__props.optionInputValueKey]:option[__props.optionInputValueKey]}}function getNormalizedOptions(options){let normalizedOptions=[];if(!options?.length)return[];for(let option of options)typeof option==`string`||typeof option==`number`||typeof option==`boolean`?normalizedOptions.push(getOptionPayload(option)):typeof option==`object`&&`options`in option&&Array.isArray(option.options)?normalizedOptions.push({label:option.label,isOptGroup:!0},...option.options.map(opt=>typeof opt==`string`||typeof opt==`number`||typeof opt==`boolean`?getOptionPayload(opt):getNormalizedOptionPayload(opt))):normalizedOptions.push(getNormalizedOptionPayload(option));return normalizedOptions}let optionsNormalized=computed(()=>getNormalizedOptions(__props.options??[]));function isOptionInSelection(option){return isNullOrUndefined(option[__props.optionValueKey])?!1:__props.multiple?Array.isArray(__props.modelValue)&&__props.modelValue.includes(option[__props.optionValueKey]):__props.modelValue===option[__props.optionValueKey]}let selectedOptions=computed(()=>optionsNormalized.value?.filter(isOptionInSelection)??[]);function isNullOrUndefined(value){return value==null}function isSelectedOption(option){return(selectedOptions.value?.some(selectedOption=>selectedOption[__props.optionValueKey]===option[__props.optionValueKey])??!1)&&!isNullOrUndefined(option[__props.optionValueKey])}let inputValue=computed(()=>{if(__props.multiple&&__props.modelValue&&Array.isArray(__props.modelValue)){let values=__props.modelValue.map(value=>optionsNormalized.value?.find(option=>option[__props.optionValueKey]===value)?.[__props.optionInputValueKey]);return __props.formatInputValue?__props.formatInputValue(values):values.join(`, `)}let selectedOption=optionsNormalized.value?.find(option=>option[__props.optionValueKey]===__props.modelValue);let value=isNullOrUndefined(__props.modelValue)?void 0:selectedOption?.[__props.optionInputValueKey];return __props.formatInputValue?__props.formatInputValue(value):value});let searchQuery=ref();let query=ref(``);function searchInValue(value,query){return query&&value&&normalizeString(value).includes(normalizeString(query))}function getFilteredOptionWithQuery(query){return query?optionsNormalized.value?.filter(option=>{let searchValue=option[__props.optionLabelKey];let searchValue3=option[__props.optionValueKey];let searchValue2=option[__props.optionInputValueKey];let threshold=__props.searchThreshold;return searchInValue(searchValue,query)||searchInValue(searchValue2,query)||searchInValue(searchValue3,query)||typeof searchValue==`string`&&useStringMatching(searchValue,query,threshold).isMatching.value||typeof searchValue2==`string`&&useStringMatching(searchValue2,query,threshold).isMatching.value||typeof searchValue3==`string`&&useStringMatching(searchValue3,query,threshold).isMatching.value}):optionsNormalized.value}let optionList=computed(()=>__props.searchFunction&&__props.search&&searchQuery.value?getNormalizedOptions(__props.searchFunction(searchQuery.value,__props.options??[])??[]):getFilteredOptionWithQuery(searchQuery.value));async function onOpenList(){let selectedIndex=optionList.value?.findIndex(option=>isSelectedOption(option));await scrollToOptionIndex(selectedIndex),emits(`open`)}function focusMainInput(){inputRef.value?.$el?.querySelector(`input`)?.focus()}function emitInputMainInput(){inputRef.value?.$el?.querySelector(`input`)?.dispatchEvent(new Event(`input`))}function focusSearchInputAndSetQuery(q){searchQuery.value=q,searchInputRef.value?.$el?.querySelector(`input`)?.focus()}function searchOptionWithQuery(keyPressed){keyPressed===`Backspace`&&query.value&&query.value.length>0?query.value=query.value.slice(0,-1):query.value+=keyPressed;let filteredOptions=getFilteredOptionWithQuery(query.value);if(!filteredOptions?.length)return;let optionIndex=optionList.value?.findIndex(option=>option[__props.optionValueKey]===filteredOptions[0][__props.optionValueKey]);typeof optionIndex!=`number`||optionIndex===-1||(scrollToOptionIndex(optionIndex),debounceCallback(()=>{query.value=``},1e3))}let isLetterOrNumberRegex=/^([\dA-Za-z\u0400-\u04FF])$/;function mainInputKeyboardHandler(event){if(event.ctrlKey||event.metaKey||event.altKey)return;let keyPressed=event.key;(keyPressed===`ArrowDown`||keyPressed===`ArrowUp`||isLetterOrNumberRegex.test(keyPressed))&&!isOpen.value&&(event.preventDefault(),popoverComponent.value?.open()),isLetterOrNumberRegex.test(keyPressed)&&__props.search&&(event.preventDefault(),event.stopPropagation(),focusSearchInputAndSetQuery(keyPressed))}async function scrollToOptionIndex(index){if(await nextTick(),typeof index!=`number`||index<0)return;let item=optionListElement.value?.querySelector(`.m-select-list-item:nth-child(${index+1})`);if(item&&optionListWrapperRef.value){let wrapperRect=optionListWrapperRef.value.getBoundingClientRect();let itemRect=item.getBoundingClientRect();let scrollTop=item.offsetTop-wrapperRect.height/2-itemRect.height;optionListWrapperRef.value.scrollTo?.({top:scrollTop,behavior:`auto`}),setTimeout(()=>{item.focus({preventScroll:!0})},100)}}function updateValue(inputOption,mustCloseList=!0){mustCloseList&&!__props.multiple&&nextTick(()=>{popoverComponent.value?.close()}),searchQuery.value=``;let isAlreadySelected=selectedOptions.value?.some(option=>option[__props.optionValueKey]===inputOption[__props.optionValueKey]);let newValue=selectedOptions.value;isAlreadySelected&&__props.multiple?newValue=newValue?.filter(option=>option[__props.optionValueKey]!==inputOption[__props.optionValueKey]):__props.multiple?newValue.push(inputOption):newValue=[inputOption];let selectedValues=newValue.map(option=>option[__props.optionValueKey]);emits(`update:model-value`,__props.multiple?selectedValues:selectedValues[0]),emits(`selected-option`,inputOption),emitInputMainInput(),focusMainInput()}function keydownHandler(event){let keyPressed=event.key;if(keyPressed===`ArrowDown`||keyPressed===`ArrowUp`){event.preventDefault();let itemLength=optionList.value?.length;if(!itemLength)return;let currentElement=document.activeElement;let itemsElements=document.querySelectorAll(`#${instanceId.value}-option-list .m-select-list-item`);let currentIndex=[...itemsElements].indexOf(currentElement);if(currentIndex===-1){itemsElements[0]?.focus({preventScroll:!0});return}itemsElements[keyPressed===`ArrowDown`?(currentIndex+1)%itemLength:(currentIndex-1+itemLength)%itemLength]?.focus()}else !__props.search&&isLetterOrNumberRegex.test(keyPressed)&&searchOptionWithQuery(keyPressed)}function updateListPosition(){nextTick(()=>{popoverComponent.value?.updatePosition()})}return watch(isOpen,value=>{isClient()&&(value?document.addEventListener(`keydown`,keydownHandler):document.removeEventListener(`keydown`,keydownHandler))},{immediate:!0}),__expose({open:()=>{popoverComponent.value?.open()},close:()=>{popoverComponent.value?.close()}}),(_ctx,_cache)=>(openBlock(),createBlock(MazPopover_default,{id:`${unref(instanceId)}-popover`,ref:`popover`,modelValue:isOpen.value,"onUpdate:modelValue":_cache[5]||=$event=>isOpen.value=$event,class:normalizeClass([`m-select m-reset-css`,[{"--is-open":isOpen.value,"--disabled":__props.disabled},__props.class,`--${__props.size}`]]),style:normalizeStyle(__props.style),trigger:`click`,block:__props.block,transition:__props.transition,offset:0,position:__props.listPosition,disabled:__props.disabled,"prefer-position":__props.preferPosition,"fallback-position":__props.fallbackPosition,"position-reference":`#${unref(instanceId)}-popover .m-input-wrapper`,onClose:_cache[6]||=$event=>emits(`close`),onOpen:onOpenList},{trigger:withCtx(({close,open:openPicker,toggle:togglePopover})=>[createVNode(MazInput_default,mergeProps({id:unref(instanceId),ref:`input`,class:`m-select-input`},_ctx.$attrs,{required:__props.required,"border-active":isOpen.value,color:__props.color,"model-value":inputValue.value,size:__props.size,block:__props.block,placeholder:__props.placeholder,label:__props.label,autocomplete:__props.autocomplete,disabled:__props.disabled,readonly:``,onChange:_cache[0]||=$event=>emits(`change`,$event),onInput:_cache[1]||=$event=>emits(`input`,$event),onFocus:_cache[2]||=$event=>emits(`focus`,$event),onBlur:_cache[3]||=$event=>emits(`blur`,$event),onKeydown:mainInputKeyboardHandler}),createSlots({"right-icon":withCtx(()=>[renderSlot(_ctx.$slots,`right-icon`,{isOpen:isOpen.value,close,open:openPicker,toggle:togglePopover},()=>[createElementVNode(`button`,{tabindex:`-1`,disabled:__props.disabled,type:`button`,class:`m-select-input__toggle-button maz-custom`,"aria-label":`${isOpen.value?`collapse`:`expand`} list of options`},[createVNode(unref(MazChevronDown),{class:`m-select-chevron`})],8,_hoisted_1)],!0)]),_:2},[unref(hasSlotContent)(_ctx.$slots[`left-icon`])?{name:`left-icon`,fn:withCtx(()=>[renderSlot(_ctx.$slots,`left-icon`,{isOpen:isOpen.value,close,open:openPicker,toggle:togglePopover},void 0,!0)]),key:`0`}:void 0]),1040,[`id`,`required`,`border-active`,`color`,`model-value`,`size`,`block`,`placeholder`,`label`,`autocomplete`,`disabled`])]),default:withCtx(({close,open:openPicker,toggle:togglePopover})=>[createElementVNode(`div`,{id:`${unref(instanceId)}-option-list`,ref:`optionListRef`,class:normalizeClass([`m-select-list`,`--${__props.size}`]),style:normalizeStyle([{maxHeight:`${__props.maxListHeight}px`,maxWidth:`${__props.maxListWidth}px`,minHeight:`${__props.minListHeight}px`,minWidth:`${__props.minListWidth}px`,"--selected-bg-color":selectedBgColor.value,"--selected-text-color":selectedTextColor.value}])},[__props.search?(openBlock(),createElementBlock(`div`,_hoisted_3,[createVNode(MazInput_default,{ref:`searchInput`,modelValue:searchQuery.value,"onUpdate:modelValue":[_cache[4]||=$event=>searchQuery.value=$event,updateListPosition],size:`sm`,disabled:__props.disabled,color:__props.color,placeholder:messages.value.searchPlaceholder,name:`search`,inputmode:`search`,autocomplete:`off`,block:``,class:`m-select-list__search-input maz-flex-none`,"left-icon":unref(MazMagnifyingGlass)},null,8,[`modelValue`,`disabled`,`color`,`placeholder`,`left-icon`])])):createCommentVNode(``,!0),!optionList.value||optionList.value.length<=0?renderSlot(_ctx.$slots,`no-results`,{key:1},()=>[createElementVNode(`span`,_hoisted_4,[createVNode(unref(MazNoSymbol),{class:`maz-size-6 maz-text-foreground`})])],!0):(openBlock(),createElementBlock(`div`,_hoisted_5,[(openBlock(!0),createElementBlock(Fragment,null,renderList(optionList.value,(option,i)=>(openBlock(),createElementBlock(Fragment,{key:i},[option.label&&option.isOptGroup?renderSlot(_ctx.$slots,`optgroup`,{key:0,label:option.label},()=>[createElementVNode(`span`,_hoisted_6,toDisplayString(option.label),1)],!0):(openBlock(),createElementBlock(`button`,{key:1,type:`button`,tabindex:__props.multiple?-1:0,class:normalizeClass([`m-select-list-item maz-custom maz-flex-none`,[{"--is-selected":isSelectedOption(option),"--is-none-value":isNullOrUndefined(option[__props.optionValueKey])}]]),style:normalizeStyle(__props.itemHeight?{height:`${__props.itemHeight}px`}:void 0),onClick:withModifiers($event=>updateValue(option,!0),[`prevent`,`stop`])},[__props.multiple?(openBlock(),createBlock(unref(MazCheckbox),{key:0,"model-value":isSelectedOption(option),size:`sm`,color:__props.color},null,8,[`model-value`,`color`])):createCommentVNode(``,!0),renderSlot(_ctx.$slots,`default`,{option,isSelected:isSelectedOption(option),isOpen:isOpen.value,close,open:openPicker,toggle:togglePopover},()=>[createElementVNode(`span`,null,toDisplayString(option[__props.optionLabelKey]),1)],!0)],14,_hoisted_7))],64))),128))],512))],14,_hoisted_2)]),_:3},8,[`id`,`modelValue`,`class`,`style`,`block`,`transition`,`position`,`disabled`,`prefer-position`,`fallback-position`,`position-reference`]))}}),[[`__scopeId`,`data-v-bf616d59`]]);export{MazSelect_default as t};