vue3-select-component
Advanced tools
Comparing version
@@ -1,6 +0,6 @@ | ||
import { openBlock as c, createElementBlock as p, createElementVNode as g, defineComponent as H, ref as h, watch as P, normalizeClass as S, withKeys as Q, renderSlot as M, mergeModels as N, useModel as W, computed as x, onMounted as Y, onBeforeUnmount as ee, createTextVNode as _, toDisplayString as O, createCommentVNode as L, Fragment as q, renderList as K, createVNode as B, withDirectives as te, vModelText as le, createBlock as U, Teleport as ae, normalizeStyle as oe, withCtx as ne } from "vue"; | ||
import { openBlock as c, createElementBlock as p, createElementVNode as k, defineComponent as H, ref as h, watch as P, normalizeClass as S, withKeys as Q, renderSlot as g, mergeModels as N, useModel as W, computed as q, onMounted as Y, onBeforeUnmount as ee, createTextVNode as C, toDisplayString as _, createCommentVNode as L, Fragment as x, renderList as K, createVNode as B, withDirectives as te, vModelText as le, createBlock as U, Teleport as ae, normalizeStyle as oe, withCtx as ne } from "vue"; | ||
const V = (n, v) => { | ||
const t = n.__vccOpts || n; | ||
for (const [m, a] of v) | ||
t[m] = a; | ||
for (const [f, a] of v) | ||
t[f] = a; | ||
return t; | ||
@@ -11,3 +11,3 @@ }, ie = {}, se = { | ||
fill: "currentColor" | ||
}, ue = /* @__PURE__ */ g("path", { | ||
}, ue = /* @__PURE__ */ k("path", { | ||
"fill-rule": "evenodd", | ||
@@ -26,3 +26,3 @@ d: "M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z", | ||
fill: "currentColor" | ||
}, fe = /* @__PURE__ */ g("path", { d: "M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z" }, null, -1), me = [ | ||
}, fe = /* @__PURE__ */ k("path", { d: "M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z" }, null, -1), me = [ | ||
fe | ||
@@ -43,3 +43,3 @@ ]; | ||
setup(n, { emit: v }) { | ||
const t = n, m = v, a = h(null); | ||
const t = n, f = v, a = h(null); | ||
return P( | ||
@@ -60,6 +60,6 @@ () => t.isFocused, | ||
"aria-disabled": !1, | ||
onClick: s[0] || (s[0] = (y) => m("select")), | ||
onKeydown: s[1] || (s[1] = Q((y) => m("select"), ["enter"])) | ||
onClick: s[0] || (s[0] = (y) => f("select")), | ||
onKeydown: s[1] || (s[1] = Q((y) => f("select"), ["enter"])) | ||
}, [ | ||
M(r.$slots, "default") | ||
g(r.$slots, "default") | ||
], 34)); | ||
@@ -93,5 +93,5 @@ } | ||
}), | ||
emits: /* @__PURE__ */ N(["optionSelected", "optionDeselected"], ["update:modelValue"]), | ||
emits: /* @__PURE__ */ N(["optionSelected", "optionDeselected", "search"], ["update:modelValue"]), | ||
setup(n, { emit: v }) { | ||
const t = n, m = v, a = W(n, "modelValue"), r = h(null), s = h(null), y = h(null), o = h(""), i = h(!1), b = h(-1), w = x(() => { | ||
const t = n, f = v, a = W(n, "modelValue"), r = h(null), s = h(null), y = h(null), o = h(""), i = h(!1), b = h(-1), w = q(() => { | ||
const e = (l) => l.filter( | ||
@@ -108,3 +108,3 @@ (u) => !a.value.includes(u.value) | ||
return t.isMulti ? e(t.options) : t.options; | ||
}), f = x(() => { | ||
}), m = q(() => { | ||
if (t.isMulti) | ||
@@ -120,8 +120,8 @@ return a.value.map( | ||
i.value = !1, o.value = ""; | ||
}, C = (e) => { | ||
t.isMulti ? a.value.push(e.value) : a.value = e.value, m("optionSelected", e), o.value = "", t.closeOnSelect && (i.value = !1), s.value && s.value.blur(); | ||
}, O = (e) => { | ||
t.isMulti ? a.value.push(e.value) : a.value = e.value, f("optionSelected", e), o.value = "", t.closeOnSelect && (i.value = !1), s.value && s.value.blur(); | ||
}, Z = (e) => { | ||
t.isMulti && (a.value = a.value.filter((l) => l !== e.value), m("optionDeselected", e)); | ||
t.isMulti && (a.value = a.value.filter((l) => l !== e.value), f("optionDeselected", e)); | ||
}, j = () => { | ||
t.isMulti ? (a.value = [], m("optionDeselected", null)) : (a.value = void 0, m("optionDeselected", f.value[0])), i.value = !1, o.value = "", s.value && s.value.blur(); | ||
t.isMulti ? (a.value = [], f("optionDeselected", null)) : (a.value = void 0, f("optionDeselected", m.value[0])), i.value = !1, o.value = "", s.value && s.value.blur(); | ||
}, I = (e) => { | ||
@@ -131,7 +131,7 @@ if (i.value) { | ||
const u = w.value[b.value]; | ||
e.preventDefault(), u && C(u); | ||
e.preventDefault(), u && O(u); | ||
} | ||
if (e.code === "Space" && o.value.length === 0) { | ||
const u = w.value[b.value]; | ||
e.preventDefault(), u && C(u); | ||
e.preventDefault(), u && O(u); | ||
} | ||
@@ -161,3 +161,3 @@ e.key === "Escape" && (e.preventDefault(), i.value = !1, o.value = ""); | ||
() => { | ||
o.value && !i.value && $(); | ||
f("search", o.value), o.value && !i.value && $(); | ||
} | ||
@@ -176,6 +176,6 @@ ), Y(() => { | ||
}, [ | ||
g("div", { | ||
k("div", { | ||
class: S(["control", { focused: i.value }]) | ||
}, [ | ||
g("div", { | ||
k("div", { | ||
class: S(["value-container", { multi: e.isMulti }]), | ||
@@ -187,6 +187,6 @@ role: "combobox", | ||
"aria-labelledby": (u = e.aria) == null ? void 0 : u.labelledby, | ||
"aria-label": f.value.length ? f.value.map(e.getOptionLabel).join(", ") : "", | ||
"aria-label": m.value.length ? m.value.map(e.getOptionLabel).join(", ") : "", | ||
"aria-required": (D = e.aria) == null ? void 0 : D.required | ||
}, [ | ||
!t.isMulti && f.value[0] ? (c(), p("div", { | ||
!t.isMulti && m.value[0] ? (c(), p("div", { | ||
key: 0, | ||
@@ -196,10 +196,10 @@ class: "single-value", | ||
}, [ | ||
M(e.$slots, "value", { | ||
option: f.value[0] | ||
g(e.$slots, "value", { | ||
option: m.value[0] | ||
}, () => [ | ||
_(O(e.getOptionLabel(f.value[0])), 1) | ||
C(_(e.getOptionLabel(m.value[0])), 1) | ||
], !0) | ||
])) : L("", !0), | ||
t.isMulti && f.value.length ? (c(!0), p(q, { key: 1 }, K(f.value, (d, k) => (c(), p("button", { | ||
key: k, | ||
t.isMulti && m.value.length ? (c(!0), p(x, { key: 1 }, K(m.value, (d, M) => (c(), p("button", { | ||
key: M, | ||
type: "button", | ||
@@ -209,6 +209,6 @@ class: "multi-value", | ||
}, [ | ||
_(O(e.getMultiValueLabel(d)) + " ", 1), | ||
C(_(e.getMultiValueLabel(d)) + " ", 1), | ||
B(z) | ||
], 8, ge))), 128)) : L("", !0), | ||
te(g("input", { | ||
te(k("input", { | ||
id: e.inputId, | ||
@@ -227,3 +227,3 @@ ref_key: "input", | ||
disabled: e.isDisabled, | ||
placeholder: f.value.length === 0 ? e.placeholder : "", | ||
placeholder: m.value.length === 0 ? e.placeholder : "", | ||
onMousedown: l[2] || (l[2] = (d) => $()), | ||
@@ -235,4 +235,4 @@ onKeydown: G | ||
], 10, he), | ||
g("div", Me, [ | ||
f.value.length > 0 && e.isClearable ? (c(), p("button", { | ||
k("div", Me, [ | ||
m.value.length > 0 && e.isClearable ? (c(), p("button", { | ||
key: 0, | ||
@@ -245,7 +245,7 @@ type: "button", | ||
}, [ | ||
M(e.$slots, "clear", {}, () => [ | ||
g(e.$slots, "clear", {}, () => [ | ||
B(z) | ||
], !0) | ||
], 8, we)) : L("", !0), | ||
g("button", { | ||
k("button", { | ||
type: "button", | ||
@@ -257,3 +257,3 @@ class: "dropdown-icon", | ||
}, [ | ||
M(e.$slots, "dropdown", {}, () => [ | ||
g(e.$slots, "dropdown", {}, () => [ | ||
B(ce) | ||
@@ -282,15 +282,16 @@ ], !0) | ||
}, [ | ||
(c(!0), p(q, null, K(w.value, (d, k) => (c(), U(ye, { | ||
key: k, | ||
g(e.$slots, "menu-header", {}, void 0, !0), | ||
(c(!0), p(x, null, K(w.value, (d, M) => (c(), U(ye, { | ||
key: M, | ||
type: "button", | ||
class: S(["menu-option", { focused: b.value === k, selected: d.value === a.value }]), | ||
class: S(["menu-option", { focused: b.value === M, selected: d.value === a.value }]), | ||
menu: y.value, | ||
index: k, | ||
"is-focused": b.value === k, | ||
index: M, | ||
"is-focused": b.value === M, | ||
"is-selected": d.value === a.value, | ||
onSelect: (J) => C(d) | ||
onSelect: (J) => O(d) | ||
}, { | ||
default: ne(() => [ | ||
M(e.$slots, "option", { option: d }, () => [ | ||
_(O(e.getOptionLabel(d)), 1) | ||
g(e.$slots, "option", { option: d }, () => [ | ||
C(_(e.getOptionLabel(d)), 1) | ||
], !0) | ||
@@ -301,4 +302,4 @@ ]), | ||
w.value.length === 0 ? (c(), p("div", Se, [ | ||
M(e.$slots, "no-options", {}, () => [ | ||
_(" No results found ") | ||
g(e.$slots, "no-options", {}, () => [ | ||
C(" No results found ") | ||
], !0) | ||
@@ -311,5 +312,5 @@ ])) : L("", !0) | ||
} | ||
}), Ce = /* @__PURE__ */ V(De, [["__scopeId", "data-v-de4b2487"]]); | ||
}), Oe = /* @__PURE__ */ V(De, [["__scopeId", "data-v-fd716f05"]]); | ||
export { | ||
Ce as default | ||
Oe as default | ||
}; |
@@ -1,1 +0,1 @@ | ||
(function(e,y){typeof exports=="object"&&typeof module!="undefined"?module.exports=y(require("vue")):typeof define=="function"&&define.amd?define(["vue"],y):(e=typeof globalThis!="undefined"?globalThis:e||self,e["vue3-select-component"]=y(e.Vue))})(this,function(e){"use strict";const y=(i,p)=>{const l=i.__vccOpts||i;for(const[m,n]of p)l[m]=n;return l},E={},D={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor"},L=[e.createElementVNode("path",{"fill-rule":"evenodd",d:"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z","clip-rule":"evenodd"},null,-1)];function N(i,p){return e.openBlock(),e.createElementBlock("svg",D,L)}const O=y(E,[["render",N]]),T={},I={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor"},x=[e.createElementVNode("path",{d:"M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z"},null,-1)];function F(i,p){return e.openBlock(),e.createElementBlock("svg",I,x)}const w=y(T,[["render",F]]),z=e.defineComponent({__name:"MenuOption",props:{menu:{},index:{},isFocused:{type:Boolean},isSelected:{type:Boolean}},emits:["select"],setup(i,{emit:p}){const l=i,m=p,n=e.ref(null);return e.watch(()=>l.isFocused,()=>{if(l.isFocused&&l.menu){const d=l.menu.children[l.index],r=d.offsetTop,h=r+d.clientHeight,a=l.menu.scrollTop,s=l.menu.clientHeight;r<a?l.menu.scrollTop=r:h>a+s&&(l.menu.scrollTop=h-s)}}),(d,r)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"option",ref:n,tabindex:"-1",role:"option",class:e.normalizeClass({focused:d.isFocused,selected:d.isSelected}),"aria-disabled":!1,onClick:r[0]||(r[0]=h=>m("select")),onKeydown:r[1]||(r[1]=e.withKeys(h=>m("select"),["enter"]))},[e.renderSlot(d.$slots,"default")],34))}}),A=["aria-expanded","aria-describedby","aria-description","aria-labelledby","aria-label","aria-required"],q=["onClick"],K=["id","disabled","placeholder"],U={class:"indicators-container"},H=["disabled"],j=["disabled"],P=["aria-label","aria-multiselectable"],R={key:0,class:"no-results"};return y(e.defineComponent({__name:"Select",props:e.mergeModels({options:{},placeholder:{default:"Select an option"},isClearable:{type:Boolean,default:!0},isDisabled:{type:Boolean,default:!1},isSearchable:{type:Boolean,default:!0},isMulti:{type:Boolean,default:!1},closeOnSelect:{type:Boolean,default:!0},teleport:{default:void 0},inputId:{default:void 0},aria:{default:void 0},filterBy:{type:Function,default:(i,p,l)=>p.toLowerCase().includes(l.toLowerCase())},getOptionLabel:{type:Function,default:i=>i.label},getMultiValueLabel:{type:Function,default:i=>i.label}},{modelValue:{required:!0,validator:(i,p)=>p.isMulti?Array.isArray(i):!Array.isArray(i)},modelModifiers:{}}),emits:e.mergeModels(["optionSelected","optionDeselected"],["update:modelValue"]),setup(i,{emit:p}){const l=i,m=p,n=e.useModel(i,"modelValue"),d=e.ref(null),r=e.ref(null),h=e.ref(null),a=e.ref(""),s=e.ref(!1),b=e.ref(-1),k=e.computed(()=>{const t=o=>o.filter(c=>!n.value.includes(c.value));if(l.isSearchable&&a.value){const o=l.options.filter(c=>{const B=l.isMulti?l.getMultiValueLabel(c):l.getOptionLabel(c);return l.filterBy(c,B,a.value)});return l.isMulti?t(o):o}return l.isMulti?t(l.options):l.options}),f=e.computed(()=>{if(l.isMulti)return n.value.map(o=>l.options.find(c=>c.value===o));const t=l.options.find(o=>o.value===n.value);return t?[t]:[]}),g=t=>{s.value=!0,b.value=0,t!=null&&t.focusInput&&r.value&&r.value.focus()},Z=()=>{s.value=!1,a.value=""},M=t=>{l.isMulti?n.value.push(t.value):n.value=t.value,m("optionSelected",t),a.value="",l.closeOnSelect&&(s.value=!1),r.value&&r.value.blur()},X=t=>{l.isMulti&&(n.value=n.value.filter(o=>o!==t.value),m("optionDeselected",t))},G=()=>{l.isMulti?(n.value=[],m("optionDeselected",null)):(n.value=void 0,m("optionDeselected",f.value[0])),s.value=!1,a.value="",r.value&&r.value.blur()},V=t=>{if(s.value){if(t.key==="ArrowDown"&&(t.preventDefault(),b.value=Math.min(b.value+1,k.value.length-1)),t.key==="ArrowUp"&&(t.preventDefault(),b.value=Math.max(b.value-1,0)),t.key==="Enter"){const c=k.value[b.value];t.preventDefault(),c&&M(c)}if(t.code==="Space"&&a.value.length===0){const c=k.value[b.value];t.preventDefault(),c&&M(c)}t.key==="Escape"&&(t.preventDefault(),s.value=!1,a.value="");const o=l.isMulti?n.value.length>0:!!n.value;t.key==="Backspace"&&a.value.length===0&&o&&(t.preventDefault(),l.isMulti?n.value=n.value.slice(0,-1):n.value=void 0)}},J=t=>{!s.value&&a.value.length===0&&(t.preventDefault(),t.stopImmediatePropagation(),g())},Q=t=>{t.key==="Tab"?Z():t.key==="Space"&&J(t)},S=t=>{d.value&&!d.value.contains(t.target)&&(s.value=!1,a.value="")},C=()=>{if(d.value){const t=d.value.getBoundingClientRect();return{left:`${t.x}px`,top:`${t.y+t.height}px`}}return console.warn("Unable to calculate dynamic menu position because of missing internal DOM reference."),{top:"0px",left:"0px"}};return e.watch(()=>a.value,()=>{a.value&&!s.value&&g()}),e.onMounted(()=>{document.addEventListener("click",S),document.addEventListener("keydown",V)}),e.onBeforeUnmount(()=>{document.removeEventListener("click",S),document.removeEventListener("keydown",V)}),(t,o)=>{var c,B,$,_;return e.openBlock(),e.createElementBlock("div",{ref_key:"container",ref:d,dir:"auto",class:e.normalizeClass(["vue-select",{open:s.value,typing:s.value&&a.value.length>0,disabled:t.isDisabled}])},[e.createElementVNode("div",{class:e.normalizeClass(["control",{focused:s.value}])},[e.createElementVNode("div",{class:e.normalizeClass(["value-container",{multi:t.isMulti}]),role:"combobox","aria-expanded":s.value,"aria-describedby":t.placeholder,"aria-description":t.placeholder,"aria-labelledby":(c=t.aria)==null?void 0:c.labelledby,"aria-label":f.value.length?f.value.map(t.getOptionLabel).join(", "):"","aria-required":(B=t.aria)==null?void 0:B.required},[!l.isMulti&&f.value[0]?(e.openBlock(),e.createElementBlock("div",{key:0,class:"single-value",onClick:o[0]||(o[0]=u=>g({focusInput:!0}))},[e.renderSlot(t.$slots,"value",{option:f.value[0]},()=>[e.createTextVNode(e.toDisplayString(t.getOptionLabel(f.value[0])),1)],!0)])):e.createCommentVNode("",!0),l.isMulti&&f.value.length?(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:1},e.renderList(f.value,(u,v)=>(e.openBlock(),e.createElementBlock("button",{key:v,type:"button",class:"multi-value",onClick:W=>X(u)},[e.createTextVNode(e.toDisplayString(t.getMultiValueLabel(u))+" ",1),e.createVNode(w)],8,q))),128)):e.createCommentVNode("",!0),e.withDirectives(e.createElementVNode("input",{id:t.inputId,ref_key:"input",ref:r,"onUpdate:modelValue":o[1]||(o[1]=u=>a.value=u),class:"search-input",type:"text","aria-autocomplete":"list",autocapitalize:"none",autocomplete:"off",autocorrect:"off",spellcheck:"false",tabindex:"0",disabled:t.isDisabled,placeholder:f.value.length===0?t.placeholder:"",onMousedown:o[2]||(o[2]=u=>g()),onKeydown:Q},null,40,K),[[e.vModelText,a.value]])],10,A),e.createElementVNode("div",U,[f.value.length>0&&t.isClearable?(e.openBlock(),e.createElementBlock("button",{key:0,type:"button",class:"clear-button",tabindex:"-1",disabled:t.isDisabled,onClick:G},[e.renderSlot(t.$slots,"clear",{},()=>[e.createVNode(w)],!0)],8,H)):e.createCommentVNode("",!0),e.createElementVNode("button",{type:"button",class:"dropdown-icon",tabindex:"-1",disabled:t.isDisabled,onClick:o[3]||(o[3]=u=>g({focusInput:!0}))},[e.renderSlot(t.$slots,"dropdown",{},()=>[e.createVNode(O)],!0)],8,j)])],2),(e.openBlock(),e.createBlock(e.Teleport,{to:t.teleport,disabled:!t.teleport},[s.value?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"menu",ref:h,class:"menu",role:"listbox","aria-label":($=t.aria)==null?void 0:$.labelledby,"aria-multiselectable":t.isMulti,style:e.normalizeStyle({width:l.teleport?`${(_=d.value)==null?void 0:_.getBoundingClientRect().width}px`:"100%",top:l.teleport?C().top:"unset",left:l.teleport?C().left:"unset"})},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(k.value,(u,v)=>(e.openBlock(),e.createBlock(z,{key:v,type:"button",class:e.normalizeClass(["menu-option",{focused:b.value===v,selected:u.value===n.value}]),menu:h.value,index:v,"is-focused":b.value===v,"is-selected":u.value===n.value,onSelect:W=>M(u)},{default:e.withCtx(()=>[e.renderSlot(t.$slots,"option",{option:u},()=>[e.createTextVNode(e.toDisplayString(t.getOptionLabel(u)),1)],!0)]),_:2},1032,["class","menu","index","is-focused","is-selected","onSelect"]))),128)),k.value.length===0?(e.openBlock(),e.createElementBlock("div",R,[e.renderSlot(t.$slots,"no-options",{},()=>[e.createTextVNode(" No results found ")],!0)])):e.createCommentVNode("",!0)],12,P)):e.createCommentVNode("",!0)],8,["to","disabled"]))],2)}}}),[["__scopeId","data-v-de4b2487"]])}); | ||
(function(e,h){typeof exports=="object"&&typeof module!="undefined"?module.exports=h(require("vue")):typeof define=="function"&&define.amd?define(["vue"],h):(e=typeof globalThis!="undefined"?globalThis:e||self,e["vue3-select-component"]=h(e.Vue))})(this,function(e){"use strict";const h=(i,p)=>{const l=i.__vccOpts||i;for(const[f,n]of p)l[f]=n;return l},E={},D={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor"},L=[e.createElementVNode("path",{"fill-rule":"evenodd",d:"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z","clip-rule":"evenodd"},null,-1)];function N(i,p){return e.openBlock(),e.createElementBlock("svg",D,L)}const O=h(E,[["render",N]]),T={},I={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor"},F=[e.createElementVNode("path",{d:"M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z"},null,-1)];function x(i,p){return e.openBlock(),e.createElementBlock("svg",I,F)}const w=h(T,[["render",x]]),z=e.defineComponent({__name:"MenuOption",props:{menu:{},index:{},isFocused:{type:Boolean},isSelected:{type:Boolean}},emits:["select"],setup(i,{emit:p}){const l=i,f=p,n=e.ref(null);return e.watch(()=>l.isFocused,()=>{if(l.isFocused&&l.menu){const d=l.menu.children[l.index],r=d.offsetTop,y=r+d.clientHeight,a=l.menu.scrollTop,s=l.menu.clientHeight;r<a?l.menu.scrollTop=r:y>a+s&&(l.menu.scrollTop=y-s)}}),(d,r)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"option",ref:n,tabindex:"-1",role:"option",class:e.normalizeClass({focused:d.isFocused,selected:d.isSelected}),"aria-disabled":!1,onClick:r[0]||(r[0]=y=>f("select")),onKeydown:r[1]||(r[1]=e.withKeys(y=>f("select"),["enter"]))},[e.renderSlot(d.$slots,"default")],34))}}),A=["aria-expanded","aria-describedby","aria-description","aria-labelledby","aria-label","aria-required"],q=["onClick"],K=["id","disabled","placeholder"],U={class:"indicators-container"},H=["disabled"],j=["disabled"],P=["aria-label","aria-multiselectable"],R={key:0,class:"no-results"};return h(e.defineComponent({__name:"Select",props:e.mergeModels({options:{},placeholder:{default:"Select an option"},isClearable:{type:Boolean,default:!0},isDisabled:{type:Boolean,default:!1},isSearchable:{type:Boolean,default:!0},isMulti:{type:Boolean,default:!1},closeOnSelect:{type:Boolean,default:!0},teleport:{default:void 0},inputId:{default:void 0},aria:{default:void 0},filterBy:{type:Function,default:(i,p,l)=>p.toLowerCase().includes(l.toLowerCase())},getOptionLabel:{type:Function,default:i=>i.label},getMultiValueLabel:{type:Function,default:i=>i.label}},{modelValue:{required:!0,validator:(i,p)=>p.isMulti?Array.isArray(i):!Array.isArray(i)},modelModifiers:{}}),emits:e.mergeModels(["optionSelected","optionDeselected","search"],["update:modelValue"]),setup(i,{emit:p}){const l=i,f=p,n=e.useModel(i,"modelValue"),d=e.ref(null),r=e.ref(null),y=e.ref(null),a=e.ref(""),s=e.ref(!1),b=e.ref(-1),k=e.computed(()=>{const t=o=>o.filter(c=>!n.value.includes(c.value));if(l.isSearchable&&a.value){const o=l.options.filter(c=>{const B=l.isMulti?l.getMultiValueLabel(c):l.getOptionLabel(c);return l.filterBy(c,B,a.value)});return l.isMulti?t(o):o}return l.isMulti?t(l.options):l.options}),m=e.computed(()=>{if(l.isMulti)return n.value.map(o=>l.options.find(c=>c.value===o));const t=l.options.find(o=>o.value===n.value);return t?[t]:[]}),g=t=>{s.value=!0,b.value=0,t!=null&&t.focusInput&&r.value&&r.value.focus()},Z=()=>{s.value=!1,a.value=""},M=t=>{l.isMulti?n.value.push(t.value):n.value=t.value,f("optionSelected",t),a.value="",l.closeOnSelect&&(s.value=!1),r.value&&r.value.blur()},X=t=>{l.isMulti&&(n.value=n.value.filter(o=>o!==t.value),f("optionDeselected",t))},G=()=>{l.isMulti?(n.value=[],f("optionDeselected",null)):(n.value=void 0,f("optionDeselected",m.value[0])),s.value=!1,a.value="",r.value&&r.value.blur()},S=t=>{if(s.value){if(t.key==="ArrowDown"&&(t.preventDefault(),b.value=Math.min(b.value+1,k.value.length-1)),t.key==="ArrowUp"&&(t.preventDefault(),b.value=Math.max(b.value-1,0)),t.key==="Enter"){const c=k.value[b.value];t.preventDefault(),c&&M(c)}if(t.code==="Space"&&a.value.length===0){const c=k.value[b.value];t.preventDefault(),c&&M(c)}t.key==="Escape"&&(t.preventDefault(),s.value=!1,a.value="");const o=l.isMulti?n.value.length>0:!!n.value;t.key==="Backspace"&&a.value.length===0&&o&&(t.preventDefault(),l.isMulti?n.value=n.value.slice(0,-1):n.value=void 0)}},J=t=>{!s.value&&a.value.length===0&&(t.preventDefault(),t.stopImmediatePropagation(),g())},Q=t=>{t.key==="Tab"?Z():t.key==="Space"&&J(t)},V=t=>{d.value&&!d.value.contains(t.target)&&(s.value=!1,a.value="")},C=()=>{if(d.value){const t=d.value.getBoundingClientRect();return{left:`${t.x}px`,top:`${t.y+t.height}px`}}return console.warn("Unable to calculate dynamic menu position because of missing internal DOM reference."),{top:"0px",left:"0px"}};return e.watch(()=>a.value,()=>{f("search",a.value),a.value&&!s.value&&g()}),e.onMounted(()=>{document.addEventListener("click",V),document.addEventListener("keydown",S)}),e.onBeforeUnmount(()=>{document.removeEventListener("click",V),document.removeEventListener("keydown",S)}),(t,o)=>{var c,B,$,_;return e.openBlock(),e.createElementBlock("div",{ref_key:"container",ref:d,dir:"auto",class:e.normalizeClass(["vue-select",{open:s.value,typing:s.value&&a.value.length>0,disabled:t.isDisabled}])},[e.createElementVNode("div",{class:e.normalizeClass(["control",{focused:s.value}])},[e.createElementVNode("div",{class:e.normalizeClass(["value-container",{multi:t.isMulti}]),role:"combobox","aria-expanded":s.value,"aria-describedby":t.placeholder,"aria-description":t.placeholder,"aria-labelledby":(c=t.aria)==null?void 0:c.labelledby,"aria-label":m.value.length?m.value.map(t.getOptionLabel).join(", "):"","aria-required":(B=t.aria)==null?void 0:B.required},[!l.isMulti&&m.value[0]?(e.openBlock(),e.createElementBlock("div",{key:0,class:"single-value",onClick:o[0]||(o[0]=u=>g({focusInput:!0}))},[e.renderSlot(t.$slots,"value",{option:m.value[0]},()=>[e.createTextVNode(e.toDisplayString(t.getOptionLabel(m.value[0])),1)],!0)])):e.createCommentVNode("",!0),l.isMulti&&m.value.length?(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:1},e.renderList(m.value,(u,v)=>(e.openBlock(),e.createElementBlock("button",{key:v,type:"button",class:"multi-value",onClick:W=>X(u)},[e.createTextVNode(e.toDisplayString(t.getMultiValueLabel(u))+" ",1),e.createVNode(w)],8,q))),128)):e.createCommentVNode("",!0),e.withDirectives(e.createElementVNode("input",{id:t.inputId,ref_key:"input",ref:r,"onUpdate:modelValue":o[1]||(o[1]=u=>a.value=u),class:"search-input",type:"text","aria-autocomplete":"list",autocapitalize:"none",autocomplete:"off",autocorrect:"off",spellcheck:"false",tabindex:"0",disabled:t.isDisabled,placeholder:m.value.length===0?t.placeholder:"",onMousedown:o[2]||(o[2]=u=>g()),onKeydown:Q},null,40,K),[[e.vModelText,a.value]])],10,A),e.createElementVNode("div",U,[m.value.length>0&&t.isClearable?(e.openBlock(),e.createElementBlock("button",{key:0,type:"button",class:"clear-button",tabindex:"-1",disabled:t.isDisabled,onClick:G},[e.renderSlot(t.$slots,"clear",{},()=>[e.createVNode(w)],!0)],8,H)):e.createCommentVNode("",!0),e.createElementVNode("button",{type:"button",class:"dropdown-icon",tabindex:"-1",disabled:t.isDisabled,onClick:o[3]||(o[3]=u=>g({focusInput:!0}))},[e.renderSlot(t.$slots,"dropdown",{},()=>[e.createVNode(O)],!0)],8,j)])],2),(e.openBlock(),e.createBlock(e.Teleport,{to:t.teleport,disabled:!t.teleport},[s.value?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"menu",ref:y,class:"menu",role:"listbox","aria-label":($=t.aria)==null?void 0:$.labelledby,"aria-multiselectable":t.isMulti,style:e.normalizeStyle({width:l.teleport?`${(_=d.value)==null?void 0:_.getBoundingClientRect().width}px`:"100%",top:l.teleport?C().top:"unset",left:l.teleport?C().left:"unset"})},[e.renderSlot(t.$slots,"menu-header",{},void 0,!0),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(k.value,(u,v)=>(e.openBlock(),e.createBlock(z,{key:v,type:"button",class:e.normalizeClass(["menu-option",{focused:b.value===v,selected:u.value===n.value}]),menu:y.value,index:v,"is-focused":b.value===v,"is-selected":u.value===n.value,onSelect:W=>M(u)},{default:e.withCtx(()=>[e.renderSlot(t.$slots,"option",{option:u},()=>[e.createTextVNode(e.toDisplayString(t.getOptionLabel(u)),1)],!0)]),_:2},1032,["class","menu","index","is-focused","is-selected","onSelect"]))),128)),k.value.length===0?(e.openBlock(),e.createElementBlock("div",R,[e.renderSlot(t.$slots,"no-options",{},()=>[e.createTextVNode(" No results found ")],!0)])):e.createCommentVNode("",!0)],12,P)):e.createCommentVNode("",!0)],8,["to","disabled"]))],2)}}}),[["__scopeId","data-v-fd716f05"]])}); |
@@ -1,2 +0,5 @@ | ||
declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<__VLS_TypePropsToRuntimeProps<{ | ||
declare function __VLS_template(): { | ||
default?(_: {}): any; | ||
}; | ||
declare const __VLS_component: import('vue').DefineComponent<__VLS_TypePropsToRuntimeProps<{ | ||
menu: HTMLDivElement | null; | ||
@@ -15,5 +18,4 @@ index: number; | ||
onSelect?: (() => any) | undefined; | ||
}, {}, {}>, { | ||
default?(_: {}): any; | ||
}>; | ||
}, {}, {}>; | ||
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>; | ||
export default _default; | ||
@@ -20,0 +22,0 @@ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T; |
import { Option } from './types'; | ||
declare const _default: <GenericOption extends Option<OptionValue>, OptionValue = string>(__VLS_props: { | ||
onOptionSelected?: ((option: GenericOption) => any) | undefined; | ||
onOptionDeselected?: ((option: GenericOption | null) => any) | undefined; | ||
options: GenericOption[]; | ||
placeholder?: string | undefined; | ||
isClearable?: boolean | undefined; | ||
isDisabled?: boolean | undefined; | ||
isSearchable?: boolean | undefined; | ||
isMulti?: boolean | undefined; | ||
closeOnSelect?: boolean | undefined; | ||
teleport?: string | undefined; | ||
inputId?: string | undefined; | ||
aria?: { | ||
labelledby?: string | undefined; | ||
required?: boolean | undefined; | ||
} | undefined; | ||
filterBy?: ((option: GenericOption, label: string, search: string) => boolean) | undefined; | ||
getOptionLabel?: ((option: GenericOption) => string) | undefined; | ||
getMultiValueLabel?: ((option: GenericOption) => string) | undefined; | ||
modelValue: OptionValue | OptionValue[]; | ||
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, __VLS_ctx?: { | ||
emit: { | ||
(e: "optionSelected", option: GenericOption): void; | ||
(e: "optionDeselected", option: GenericOption | null): void; | ||
}; | ||
attrs: any; | ||
slots: { | ||
value?(_: { | ||
option: GenericOption; | ||
}): any; | ||
clear?(_: {}): any; | ||
dropdown?(_: {}): any; | ||
option?(_: { | ||
option: GenericOption; | ||
}): any; | ||
"no-options"?(_: {}): any; | ||
}; | ||
} | undefined, __VLS_expose?: ((exposed: import('vue').ShallowUnwrapRef<{}>) => void) | undefined, __VLS_setup?: Promise<{ | ||
props: { | ||
declare const _default: <GenericOption extends Option<OptionValue>, OptionValue = string>(__VLS_props: Awaited<typeof __VLS_setup>["props"], __VLS_ctx?: __VLS_Prettify<Pick<Awaited<typeof __VLS_setup>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{ | ||
props: __VLS_Prettify<__VLS_OmitKeepDiscriminatedUnion<(Partial<{}> & Omit<{ | ||
onSearch?: ((value: string) => any) | undefined; | ||
onOptionSelected?: ((option: GenericOption) => any) | undefined; | ||
onOptionDeselected?: ((option: GenericOption | null) => any) | undefined; | ||
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps & Readonly<import('vue').ExtractPropTypes<{}>> & { | ||
onSearch?: ((value: string) => any) | undefined; | ||
onOptionSelected?: ((option: GenericOption) => any) | undefined; | ||
onOptionDeselected?: ((option: GenericOption | null) => any) | undefined; | ||
}, never>) & ({ | ||
options: GenericOption[]; | ||
placeholder?: string | undefined; | ||
isClearable?: boolean | undefined; | ||
isDisabled?: boolean | undefined; | ||
isSearchable?: boolean | undefined; | ||
isMulti?: boolean | undefined; | ||
closeOnSelect?: boolean | undefined; | ||
teleport?: string | undefined; | ||
inputId?: string | undefined; | ||
/** | ||
* The placeholder text to display when no option is selected. | ||
*/ | ||
placeholder?: string; | ||
/** | ||
* When set to true, the input can be cleared by clicking the clear button. | ||
*/ | ||
isClearable?: boolean; | ||
/** | ||
* When set to true, disable the select component. | ||
*/ | ||
isDisabled?: boolean; | ||
/** | ||
* When set to true, allow the user to filter the options by typing in the search input. | ||
*/ | ||
isSearchable?: boolean; | ||
/** | ||
* When set to true, allow the user to select multiple options. This will change the | ||
* `selected` model to an array of strings. You should pass an array of strings to the | ||
* `v-model` directive when using this prop. | ||
*/ | ||
isMulti?: boolean; | ||
/** | ||
* When set to true, clear the search input when an option is selected. | ||
*/ | ||
closeOnSelect?: boolean; | ||
/** | ||
* Teleport the menu to another part of the DOM with higher priority such as `body`. | ||
* This way, you can avoid z-index issues. Menu position will be calculated using | ||
* JavaScript, instead of using CSS absolute & relative positioning. | ||
*/ | ||
teleport?: string; | ||
/** | ||
* The ID of the input element. This is useful for accessibility or forms. | ||
*/ | ||
inputId?: string; | ||
/** | ||
* ARIA attributes to describe the select component. This is useful for accessibility. | ||
*/ | ||
aria?: { | ||
labelledby?: string | undefined; | ||
required?: boolean | undefined; | ||
} | undefined; | ||
filterBy?: ((option: GenericOption, label: string, search: string) => boolean) | undefined; | ||
getOptionLabel?: ((option: GenericOption) => string) | undefined; | ||
getMultiValueLabel?: ((option: GenericOption) => string) | undefined; | ||
labelledby?: string; | ||
required?: boolean; | ||
}; | ||
/** | ||
* Callback to filter the options based on the search input. By default, it filters | ||
* the options based on the `label` property of the option. The label is retrieved using: | ||
* | ||
* - `getOptionLabel` when `isMulti` is `false`. | ||
* - `getMultiValueLabel` when `isMulti` is `true`. | ||
* | ||
* @param option The option to filter. | ||
* @param label The label of the option. | ||
* @param search The search input value. | ||
*/ | ||
filterBy?: (option: GenericOption, label: string, search: string) => boolean; | ||
/** | ||
* A function to get the label of an option. By default, it assumes the option is an | ||
* object with a `label` property. Used to display the selected option in the input & | ||
* inside the options menu. | ||
* | ||
* @param option The option to render. | ||
*/ | ||
getOptionLabel?: (option: GenericOption) => string; | ||
/** | ||
* A function to get the label of a multi-value option. By default, it assumes the | ||
* option is an object with a `label` property. Used only in the multi-value tag. | ||
* | ||
* @param option The option to render. | ||
*/ | ||
getMultiValueLabel?: (option: GenericOption) => string; | ||
} & { | ||
modelValue: OptionValue | OptionValue[]; | ||
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps; | ||
}), keyof import('vue').VNodeProps | keyof import('vue').AllowedComponentProps>> & {} & (import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps); | ||
expose(exposed: import('vue').ShallowUnwrapRef<{}>): void; | ||
attrs: any; | ||
slots: { | ||
slots: ReturnType<() => { | ||
value?(_: { | ||
@@ -70,2 +95,3 @@ option: GenericOption; | ||
dropdown?(_: {}): any; | ||
"menu-header"?(_: {}): any; | ||
option?(_: { | ||
@@ -75,6 +101,7 @@ option: GenericOption; | ||
"no-options"?(_: {}): any; | ||
}; | ||
}>; | ||
emit: { | ||
(e: "optionSelected", option: GenericOption): void; | ||
(e: "optionDeselected", option: GenericOption | null): void; | ||
(e: "search", value: string): void; | ||
}; | ||
@@ -84,42 +111,3 @@ }>) => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, { | ||
}> & { | ||
__ctx?: { | ||
props: { | ||
onOptionSelected?: ((option: GenericOption) => any) | undefined; | ||
onOptionDeselected?: ((option: GenericOption | null) => any) | undefined; | ||
options: GenericOption[]; | ||
placeholder?: string | undefined; | ||
isClearable?: boolean | undefined; | ||
isDisabled?: boolean | undefined; | ||
isSearchable?: boolean | undefined; | ||
isMulti?: boolean | undefined; | ||
closeOnSelect?: boolean | undefined; | ||
teleport?: string | undefined; | ||
inputId?: string | undefined; | ||
aria?: { | ||
labelledby?: string | undefined; | ||
required?: boolean | undefined; | ||
} | undefined; | ||
filterBy?: ((option: GenericOption, label: string, search: string) => boolean) | undefined; | ||
getOptionLabel?: ((option: GenericOption) => string) | undefined; | ||
getMultiValueLabel?: ((option: GenericOption) => string) | undefined; | ||
modelValue: OptionValue | OptionValue[]; | ||
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps; | ||
expose(exposed: import('vue').ShallowUnwrapRef<{}>): void; | ||
attrs: any; | ||
slots: { | ||
value?(_: { | ||
option: GenericOption; | ||
}): any; | ||
clear?(_: {}): any; | ||
dropdown?(_: {}): any; | ||
option?(_: { | ||
option: GenericOption; | ||
}): any; | ||
"no-options"?(_: {}): any; | ||
}; | ||
emit: { | ||
(e: "optionSelected", option: GenericOption): void; | ||
(e: "optionDeselected", option: GenericOption | null): void; | ||
}; | ||
} | undefined; | ||
__ctx?: Awaited<typeof __VLS_setup>; | ||
}; | ||
@@ -126,0 +114,0 @@ export default _default; |
{ | ||
"name": "vue3-select-component", | ||
"type": "module", | ||
"version": "0.2.4", | ||
"version": "0.3.0", | ||
"description": "A flexible & modern select-input control for Vue 3.", | ||
@@ -52,6 +52,6 @@ "author": "Thomas Cazade <cazade.thomas@gmail.com>", | ||
"devDependencies": { | ||
"@antfu/eslint-config": "2.18.0", | ||
"@antfu/eslint-config": "2.21.1", | ||
"@tsconfig/node20": "20.1.4", | ||
"@types/node": "20.12.12", | ||
"@vitejs/plugin-vue": "5.0.4", | ||
"@types/node": "20.14.7", | ||
"@vitejs/plugin-vue": "5.0.5", | ||
"@vitest/coverage-v8": "1.6.0", | ||
@@ -62,16 +62,16 @@ "@vue/test-utils": "2.4.6", | ||
"bumpp": "9.4.1", | ||
"eslint": "9.2.0", | ||
"happy-dom": "14.11.0", | ||
"npm-run-all2": "6.1.2", | ||
"eslint": "9.5.0", | ||
"happy-dom": "14.12.3", | ||
"npm-run-all2": "6.2.0", | ||
"postcss": "8.4.38", | ||
"sass": "1.77.1", | ||
"typescript": "5.4.5", | ||
"vite": "5.2.11", | ||
"sass": "1.77.6", | ||
"typescript": "5.5.2", | ||
"vite": "5.3.1", | ||
"vite-plugin-dts": "3.9.1", | ||
"vite-plugin-vue-devtools": "7.2.0", | ||
"vitepress": "1.1.4", | ||
"vite-plugin-vue-devtools": "7.3.2", | ||
"vitepress": "1.2.3", | ||
"vitest": "1.6.0", | ||
"vue": "3.4.27", | ||
"vue-tsc": "2.0.19" | ||
"vue": "3.4.29", | ||
"vue-tsc": "2.0.21" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
38764
0.39%513
-1.35%