@madgex/design-system-ce 6.0.0 → 6.0.2
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.
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
<script setup>
|
|
59
59
|
import { computed, provide, ref, useTemplateRef } from 'vue';
|
|
60
60
|
import safeGet from 'just-safe-get';
|
|
61
|
-
import
|
|
61
|
+
import { useDebounceFn } from '@vueuse/core';
|
|
62
62
|
import Bourne from '@hapi/bourne';
|
|
63
63
|
import ComboboxClear from './ComboboxClear.vue';
|
|
64
64
|
import ListBox from './ListBox.vue';
|
|
@@ -161,6 +161,11 @@ const ariaInvalid = computed(() => {
|
|
|
161
161
|
* @param newOption
|
|
162
162
|
*/
|
|
163
163
|
function chooseOption(newOption) {
|
|
164
|
+
if (!newOption) {
|
|
165
|
+
// if no option, prevent 'undefined' being populated as search value/target values
|
|
166
|
+
console.error('attempted to choose an option, but option was falsy');
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
164
169
|
searchValue.value = getOptionLabel(newOption);
|
|
165
170
|
setTargetValues(newOption);
|
|
166
171
|
makeInactive();
|
|
@@ -196,9 +201,8 @@ function clearField() {
|
|
|
196
201
|
* if props.apiUrl is set, we fetch options from the API.
|
|
197
202
|
* `apiOptions` should always be populated with an array of objects.
|
|
198
203
|
*/
|
|
199
|
-
const debouncedFetchApiOptions =
|
|
204
|
+
const debouncedFetchApiOptions = useDebounceFn(async function fetchApiOptions() {
|
|
200
205
|
if (!props.apiUrl) return;
|
|
201
|
-
if (isLoading.value) return; // prevent overlapping fetch
|
|
202
206
|
const searchQuery = searchValue?.value?.trim();
|
|
203
207
|
try {
|
|
204
208
|
isLoading.value = true;
|
|
@@ -213,7 +217,7 @@ const debouncedFetchApiOptions = debounce(async function fetchApiOptions() {
|
|
|
213
217
|
} finally {
|
|
214
218
|
isLoading.value = false;
|
|
215
219
|
}
|
|
216
|
-
},
|
|
220
|
+
}, 350);
|
|
217
221
|
|
|
218
222
|
/**
|
|
219
223
|
* where do we grab the label from the option object?
|
|
@@ -264,13 +268,20 @@ function handleMouseDownOption(option) {
|
|
|
264
268
|
/**
|
|
265
269
|
* When expanded then enter key down selects an option,
|
|
266
270
|
* otherwise enter key will be native behaviour, eg submit form
|
|
271
|
+
* If no option is selected (user typed without selecting option but still pressed "enter"), just close menu, dont attempt to choose
|
|
267
272
|
* @param event
|
|
268
273
|
*/
|
|
269
274
|
function handleKeyDownEnter(event) {
|
|
270
275
|
if (expanded.value) {
|
|
271
276
|
event.preventDefault();
|
|
272
277
|
const selectedOption = visibleOptions.value?.[selectedIndex.value];
|
|
273
|
-
|
|
278
|
+
if (selectedOption) {
|
|
279
|
+
// choose if selectedOption is valid
|
|
280
|
+
chooseOption(selectedOption);
|
|
281
|
+
} else {
|
|
282
|
+
// just close dropdown when user presses "enter" without selecting anything
|
|
283
|
+
makeInactive();
|
|
284
|
+
}
|
|
274
285
|
}
|
|
275
286
|
}
|
|
276
287
|
function handleBlur() {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<script setup>
|
|
8
8
|
import { ref, watch } from 'vue';
|
|
9
|
-
import
|
|
9
|
+
import { useDebounceFn } from '@vueuse/core';
|
|
10
10
|
|
|
11
11
|
const props = defineProps({
|
|
12
12
|
visibleOptions: { type: Array, default: () => [] },
|
|
@@ -26,7 +26,7 @@ watch(
|
|
|
26
26
|
const resultCountMessage = ref(null);
|
|
27
27
|
|
|
28
28
|
/** debounced so there is a delay, so screen readers react properly to updates */
|
|
29
|
-
const debounceUpdateResultCountMessage =
|
|
29
|
+
const debounceUpdateResultCountMessage = useDebounceFn(function updateResultCountMessage() {
|
|
30
30
|
const messageTemplate = props.visibleOptions.length === 1 ? props.resultsMessage : props.resultsMessage_plural;
|
|
31
31
|
resultCountMessage.value = messageTemplate.replace('{count}', props.visibleOptions.length);
|
|
32
32
|
}, 1400);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{v as
|
|
1
|
+
import{v as A,x as S,a as v,i as d,f as $,u as x,q as h,b as U,y as V,t as q,z as P,A as N,e as H,r as y,B as b,C as L,p as K,j as R,D as ie,F as ue,l as ce,s as de}from"../runtime-dom.esm-bundler.js";function pe(a){return a&&a.__esModule&&Object.prototype.hasOwnProperty.call(a,"default")?a.default:a}var M=fe;function fe(a,e,s){if(!a)return s;var t,n;if(Array.isArray(e)&&(t=e.slice(0)),typeof e=="string"&&(t=e.split(".")),typeof e=="symbol"&&(t=[e]),!Array.isArray(t))throw new Error("props arg must be an array, a string or a symbol");for(;t.length;)if(n=t.shift(),!a||(a=a[n],a===void 0))return s;return a}typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const j=()=>{};function me(a,e){function s(...t){return new Promise((n,o)=>{Promise.resolve(a(()=>e.apply(this,t),{fn:e,thisArg:this,args:t})).then(n).catch(o)})}return s}function ve(a,e={}){let s,t,n=j;const o=c=>{clearTimeout(c),n(),n=j};let l;return c=>{const w=A(a),f=A(e.maxWait);return s&&o(s),w<=0||f!==void 0&&f<=0?(t&&(o(t),t=void 0),Promise.resolve(c())):new Promise((p,I)=>{n=e.rejectOnCancel?I:p,l=c,f&&!t&&(t=setTimeout(()=>{s&&o(s),t=void 0,p(l())},f)),s=setTimeout(()=>{t&&o(t),t=void 0,p(c())},w)})}}function W(a,e=200,s={}){return me(ve(e,s),a)}var k={},D;function he(){return D||(D=1,(function(a){const e={suspectRx:/"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*\:/};a.parse=function(s,...t){const n=typeof t[0]=="object"&&t[0],o=t.length>1||!n?t[0]:void 0,l=t.length>1&&t[1]||n||{},i=JSON.parse(s,o);return l.protoAction==="ignore"||!i||typeof i!="object"||!s.match(e.suspectRx)||a.scan(i,l),i},a.scan=function(s,t={}){let n=[s];for(;n.length;){const o=n;n=[];for(const l of o){if(Object.prototype.hasOwnProperty.call(l,"__proto__")){if(t.protoAction!=="remove")throw new SyntaxError("Object contains forbidden prototype property");delete l.__proto__}for(const i in l){const c=l[i];c&&typeof c=="object"&&n.push(l[i])}}}},a.safeParse=function(s,t){try{return a.parse(s,t)}catch{return null}}})(k)),k}var be=he();const ye=pe(be),ge=["aria-label","title"],_e={"aria-hidden":"true",focusable:"false",class:"mds-icon mds-icon--close mds-icon--sm"},xe=["href"],$e={__name:"ComboboxClear",setup(a){const e=S("iconPath"),s=S("clearInput");return(t,n)=>(d(),v("button",{class:"mds-combobox__clear mds-button mds-button--plain",type:"button",onClick:n[0]||(n[0]=o=>t.$emit("clear",o)),onKeydown:n[1]||(n[1]=h(o=>t.$emit("clear",o),["enter"])),"aria-label":x(s),title:x(s)},[(d(),v("svg",_e,[$("use",{href:`${x(e)}#icon-close`},null,8,xe)]))],40,ge))}},we=["hidden"],Ie={key:0,class:"mds-combobox-loading"},Se={"aria-hidden":"true",focusable:"true",class:"mds-icon mds-icon--spinner mds-icon--after"},Ce=["href"],Oe={class:"mds-visually-hidden"},Le={__name:"ListBox",props:{hidden:{type:Boolean,default:!0},isLoading:{type:Boolean,default:!0}},setup(a){const e=S("iconPath"),s=S("loadingText");return(t,n)=>(d(),v("ul",{class:"mds-combobox__listbox",role:"listbox",hidden:a.hidden},[a.isLoading?(d(),v("li",Ie,[(d(),v("svg",Se,[$("use",{href:`${x(e)}#icon-spinner`},null,8,Ce)])),$("span",Oe,q(x(s)),1)])):U("",!0),V(t.$slots,"default")],8,we))}},Me=["aria-selected","innerHTML"],ke={__name:"ListBoxOption",props:{optionLabel:{type:String,required:!0},focused:{type:Boolean,default:!1},searchValue:{type:String,default:""}},setup(a){const e=a,s=P("$listItem");N(()=>e.focused,n=>{n&&s.value?.scrollIntoView({block:"nearest",inline:"nearest"})});function t(){return e.optionLabel.replace(new RegExp(e.searchValue,"gi"),o=>`<span class="mds-combobox__option--marked">${o}</span>`)}return(n,o)=>(d(),v("li",{ref_key:"$listItem",ref:s,class:H(["mds-combobox__option",{"mds-combobox__option--focused":a.focused}]),role:"option","aria-selected":a.focused.toString(),onMousedown:o[0]||(o[0]=l=>n.$emit("mousedown",l)),innerHTML:t()},null,42,Me))}},Pe={role:"status",class:"mds-visually-hidden"},Te={__name:"ComboboxAriaLive",props:{visibleOptions:{type:Array,default:()=>[]},expanded:{type:Boolean,default:!1},resultsMessage:{type:String},resultsMessage_plural:{type:String}},setup(a){const e=a;N([()=>e.expanded,()=>e.visibleOptions],()=>{n()},{deep:!0});const s=y(null),t=W(function(){const l=e.visibleOptions.length===1?e.resultsMessage:e.resultsMessage_plural;s.value=l.replace("{count}",e.visibleOptions.length)},1400);function n(){s.value=null,e.expanded&&t()}return(o,l)=>(d(),v("div",Pe,q(s.value),1))}},Be=["id","value","name","placeholder","aria-controls","aria-expanded","aria-describedby","aria-activedescendant","aria-invalid"],Fe={__name:"Combobox.ce",props:{comboboxid:{type:String,required:!0},placeholder:{type:String,default:""},name:{type:[String,Boolean],default:!1},value:{type:String,default:""},options:{type:String,default:"[]"},iconpath:{type:String,default:"/assets/icons.svg"},dataAriaInvalid:{type:String,default:""},i18n:{type:String,default:""},describedbyId:{type:String,default:""},minSearchCharacters:{type:Number,default:2},apiUrl:{type:String,default:void 0},apiQueryKey:{type:String,default:"searchText"},apiOptionsPath:{type:String,default:void 0},optionLabelPath:{type:String,default:"label"}},setup(a){const e=a,s=P("$comboInput"),t=P("$targetInputs"),n=y(!1),o=y(null),l=y(e.value),i=y(!1),c=y([]),w=b(()=>{try{return ye.parse(e.options)}catch(r){return console.error(r),[]}}),f=b(()=>e.i18n?JSON.parse(e.i18n):{loadingText:"Loading",resultsMessage:"{count} result available",resultsMessage_plural:"{count} results available",clearInput:"clear input"}),p=b(()=>e.apiUrl?c.value:w.value.filter(r=>C(r).toLowerCase().includes(l.value.toLowerCase()))),I=b(()=>`${e.comboboxid}-listbox`);function T(r){if(typeof r=="number"&&r>-1)return`${e.comboboxid}-option-${r}`}const G=b(()=>n.value?"true":"false"),Q=b(()=>e.dataAriaInvalid?"true":"false");function B(r){if(!r){console.error("attempted to choose an option, but option was falsy");return}l.value=C(r),F(r),g(),o.value=null}function F(r){const m=Array.from(t.value?.querySelectorAll("[data-key]"));for(const u of m)u.value=r?M(r,u.getAttribute("data-key")):"",u.dispatchEvent(new Event("input",{bubbles:!0}))}function z(){n.value=!0}function g(){n.value=!1}function E(){l.value="",F()}const J=W(async function(){if(!e.apiUrl)return;const m=l?.value?.trim();try{i.value=!0;let u=await fetch(`${e.apiUrl}?${e.apiQueryKey}=${encodeURIComponent(m)}`);if(!u.ok)return;u=await u.json();const _=e.apiOptionsPath?M(u,e.apiOptionsPath):u;c.value=_||[]}finally{i.value=!1}},350);function C(r){const m=M(r,e.optionLabelPath);return String(m)}function X(r){o.value=null,l.value=r.target?r.target.value:"",O(),J()}function O(){l.value.length===0&&E(),l.value.length>=e.minSearchCharacters?z():g()}function Y(){O()}function Z(){E(),s.value?.focus()}function ee(r){B(r)}function te(r){if(n.value){r.preventDefault();const m=p.value?.[o.value];m?B(m):g()}}function ne(){g()}function ae(){n.value&&(o.value!==null?o.value=Math.min(o.value+1,p.value.length-1):o.value=0)}function oe(){n.value&&(o.value!==null?o.value=Math.max(o.value-1,0):o.value=p.value.length-1)}function se(){n.value&&(o.value=0)}function le(){n.value&&(o.value=p.value.length-1)}function re(){g()}return L("iconPath",e.iconpath),L("loadingText",f.value.loadingText),L("clearInput",f.value.clearInput),(r,m)=>(d(),v("div",{class:H(["mds-combobox",{"mds-combobox--active":n.value}]),onKeydown:[h(ae,["down"]),h(oe,["up"]),h(se,["home"]),h(le,["end"]),h(re,["esc"]),h(te,["enter"])]},[$("input",{id:a.comboboxid,ref_key:"$comboInput",ref:s,value:l.value,class:"mds-form-control",autocomplete:"off",type:"text",role:"combobox",name:a.name,placeholder:a.placeholder,"aria-controls":I.value,"aria-expanded":G.value,"aria-autocomplete":"list","aria-describedby":a.describedbyId,"aria-activedescendant":T(o.value),"aria-invalid":Q.value,onInput:X,onChange:O,onBlur:ne,onFocus:Y},null,40,Be),l.value.length>0?(d(),K($e,{key:0,onClear:Z})):U("",!0),R(Le,{id:I.value,hidden:!n.value,"aria-labelledby":`${a.comboboxid}-label`,"is-loading":i.value},{default:ie(()=>[(d(!0),v(ue,null,ce(p.value,(u,_)=>(d(),K(ke,{id:T(_),key:_,"option-label":C(u),focused:o.value===_,"search-value":l.value,onMousedown:Ee=>ee(u)},null,8,["id","option-label","focused","search-value","onMousedown"]))),128))]),_:1},8,["id","hidden","aria-labelledby","is-loading"]),R(Te,{"visible-options":p.value,expanded:n.value,"results-message":f.value.resultsMessage,"results-message_plural":f.value.resultsMessage_plural},null,8,["visible-options","expanded","results-message","results-message_plural"]),$("span",{ref_key:"$targetInputs",ref:t},[V(r.$slots,"target-inputs")],512)],34))}},Ke=de(Fe,{shadowRoot:!1});export{Ke as default};
|