vue-search-input
Version:
A Vue.js 3 search input component, inspired by the global search input of Storybook and GitHub.
2 lines (1 loc) • 3.75 kB
JavaScript
(function(t,u){typeof exports=="object"&&typeof module<"u"?module.exports=u(require("vue")):typeof define=="function"&&define.amd?define(["vue"],u):(t=typeof globalThis<"u"?globalThis:t||self,t.VueSearchInput=u(t.Vue))})(this,function(t){"use strict";const u=(e,n,c=!0)=>{const l={};return Object.keys(e).forEach(r=>{(c?n.indexOf(r)===-1:n.indexOf(r)>=0)&&(l[r]=e[r])}),l},w=["search","text","password"],a=(e=!0)=>({type:Boolean,default:e}),S=t.defineComponent({name:"SearchInput",inheritAttrs:!1,props:{type:{type:String,default:"search",validator:e=>w.includes(e)},modelValue:{type:String,default:""},wrapperClass:{type:String,default:"search-input-wrapper"},searchIcon:a(),shortcutIcon:a(),clearIcon:a(),hideShortcutIconOnBlur:a(),clearOnEsc:a(),blurOnEsc:a(),selectOnFocus:a(),shortcutListenerEnabled:a(),shortcutKey:{type:String,default:"/"}},emits:["update:modelValue"],setup(e,{emit:n,attrs:c}){const l=t.ref(!1),r=t.ref(null),d=t.computed(()=>u(c,["class","style"])),s=t.computed(()=>{const o=u(c,["class","style"],!1);return o.class||(o.class=e.wrapperClass),o}),V=t.computed(()=>!!(e.clearIcon&&e.modelValue.length>0)),O=t.computed(()=>!!(e.shortcutIcon&&!l.value&&!e.hideShortcutIconOnBlur||e.shortcutIcon&&!l.value&&e.modelValue.length===0)),p=()=>{n("update:modelValue","")},$=o=>{n("update:modelValue",o.target.value)},k=o=>{o.key==="Escape"&&(e.clearOnEsc&&p(),e.blurOnEsc&&r.value.blur())},h=o=>{if(o.key===e.shortcutKey&&o.target!==r.value&&window.document.activeElement!==r.value&&!(o.target instanceof HTMLInputElement)&&!(o.target instanceof HTMLSelectElement)&&!(o.target instanceof HTMLTextAreaElement)){o.preventDefault();const i=[].slice.call(document.querySelectorAll('[data-search-input="true"]:not([data-shortcut-enabled="false"])')).filter(f=>!!(f.offsetWidth||f.offsetHeight||f.getClientRects().length)),y=i.length>1?i[0]:r.value;y?.focus(),e.selectOnFocus&&y?.select()}},m=()=>window.document.removeEventListener("keydown",h);return t.watch(()=>e.shortcutListenerEnabled,o=>{o?window.document.addEventListener("keydown",h):m()},{immediate:!0}),t.onBeforeUnmount(()=>{m()}),{inputRef:r,hasFocus:l,clear:p,onInput:$,onKeydown:k,attrsStyles:s,attrsWithoutStyles:d,showClearIcon:V,showShortcutIcon:O}}}),I=(e,n)=>{const c=e.__vccOpts||e;for(const[l,r]of n)c[l]=r;return c},E=["type","data-shortcut-enabled","value"];function g(e,n,c,l,r,d){return t.openBlock(),t.createElementBlock("div",t.normalizeProps(t.guardReactiveProps(e.attrsStyles)),[t.renderSlot(e.$slots,"prepend"),e.searchIcon?t.renderSlot(e.$slots,"search-icon",{key:0},()=>[n[6]||(n[6]=t.createElementVNode("i",{class:"search-icon search"},null,-1))]):t.createCommentVNode("",!0),t.renderSlot(e.$slots,"prepend-inner"),t.createElementVNode("input",t.mergeProps({ref:"inputRef",type:e.type,"data-search-input":"true","data-shortcut-enabled":e.shortcutListenerEnabled,value:e.modelValue},e.attrsWithoutStyles,{onInput:n[0]||(n[0]=(...s)=>e.onInput&&e.onInput(...s)),onFocus:n[1]||(n[1]=s=>e.hasFocus=!0),onBlur:n[2]||(n[2]=s=>e.hasFocus=!1),onKeydown:n[3]||(n[3]=(...s)=>e.onKeydown&&e.onKeydown(...s))}),null,16,E),t.renderSlot(e.$slots,"append"),e.showShortcutIcon?t.renderSlot(e.$slots,"shortcut-icon",{key:1},()=>[n[7]||(n[7]=t.createElementVNode("i",{class:"search-icon shortcut",title:'Press "/" to search'},null,-1))]):t.createCommentVNode("",!0),e.showClearIcon?t.renderSlot(e.$slots,"clear-icon",{key:2,clear:e.clear},()=>[t.createElementVNode("button",{class:"search-icon clear","aria-label":"Clear",onMousedown:n[4]||(n[4]=(...s)=>e.clear&&e.clear(...s)),onKeydown:n[5]||(n[5]=t.withKeys((...s)=>e.clear&&e.clear(...s),["space","enter"]))},null,32)]):t.createCommentVNode("",!0),t.renderSlot(e.$slots,"append-outer")],16)}return I(S,[["render",g]])});