@madgex/design-system-ce 6.0.3 → 7.0.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/components/combobox/Combobox.ce.vue +169 -91
- package/components/combobox/ComboboxPill.vue +23 -0
- package/components/combobox/ListBoxOption.vue +2 -3
- package/components/text-editor/TextEditor.ce.vue +5 -0
- package/components/text-editor/TextEditorToolbar.vue +2 -2
- package/custom-elements/mds-combobox.js +3 -0
- package/dist/custom-elements/mds-combobox.js +1 -1
- package/dist/custom-elements/mds-text-editor.js +20 -20
- package/dist/runtime-dom.esm-bundler.js +2 -2
- package/package.json +3 -3
- package/types.d.ts +0 -0
|
@@ -10,36 +10,48 @@
|
|
|
10
10
|
@keydown.esc="handleKeyEsc"
|
|
11
11
|
@keydown.enter="handleKeyDownEnter"
|
|
12
12
|
>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
13
|
+
<!-- .mds-form-control class used to imitate an input in this wrapper, while having pills/search input inside it -->
|
|
14
|
+
<div class="mds-form-control" @click="handleClickInputWrapper">
|
|
15
|
+
<span class="mds-visually-hidden" v-if="multiple && vModel?.length">{{ i18nText.selectedOptionsLabel }}</span>
|
|
16
|
+
<ul class="mds-combobox__pills" v-if="multiple && vModel?.length">
|
|
17
|
+
<li v-for="option in vModel" :key="getOptionValue(option)">
|
|
18
|
+
<ComboboxPill :aria-label-remove="getPillAriaLabel(option)" @remove="handleClickPill(option)">
|
|
19
|
+
{{ getOptionLabel(option) }}
|
|
20
|
+
</ComboboxPill>
|
|
21
|
+
</li>
|
|
22
|
+
</ul>
|
|
23
|
+
<!-- no name so search input is not included in the <form> -->
|
|
24
|
+
<input
|
|
25
|
+
:id="comboboxId"
|
|
26
|
+
class="mds-combobox__search-input"
|
|
27
|
+
ref="$comboInput"
|
|
28
|
+
:value="searchTextVModel"
|
|
29
|
+
autocomplete="off"
|
|
30
|
+
type="text"
|
|
31
|
+
role="combobox"
|
|
32
|
+
:placeholder="placeholder"
|
|
33
|
+
:aria-controls="listBoxId"
|
|
34
|
+
:aria-expanded="ariaExpanded"
|
|
35
|
+
aria-autocomplete="list"
|
|
36
|
+
:aria-describedby="describedbyId"
|
|
37
|
+
:aria-activedescendant="getOptionIdByIndex(selectedIndex)"
|
|
38
|
+
:aria-invalid="ariaInvalid"
|
|
39
|
+
@input="handleInput"
|
|
40
|
+
@change="handleChange"
|
|
41
|
+
@blur="handleBlur"
|
|
42
|
+
@focus="handleFocus"
|
|
43
|
+
/>
|
|
44
|
+
<ComboboxClear v-if="searchTextVModel.length > 0" @clear="handleClear" />
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<ListBox :id="listBoxId" :hidden="!expanded" :aria-labelledby="`${comboboxId}-label`" :is-loading="isLoading">
|
|
36
48
|
<ListBoxOption
|
|
37
49
|
v-for="(option, index) in visibleOptions"
|
|
38
50
|
:id="getOptionIdByIndex(index)"
|
|
39
51
|
:key="index"
|
|
40
52
|
:option-label="getOptionLabel(option)"
|
|
41
53
|
:focused="selectedIndex === index"
|
|
42
|
-
:search-
|
|
54
|
+
:search-text="searchTextVModel"
|
|
43
55
|
@mousedown="handleMouseDownOption(option)"
|
|
44
56
|
/>
|
|
45
57
|
</ListBox>
|
|
@@ -50,13 +62,11 @@
|
|
|
50
62
|
:results-message_plural="i18nText.resultsMessage_plural"
|
|
51
63
|
/>
|
|
52
64
|
<!-- No default <slot/> used, so fallback child content is destroyed on mount -->
|
|
53
|
-
<!-- target-inputs <slot/> so we can easily find inputs to populate with option selection -->
|
|
54
|
-
<span ref="$targetInputs"><slot name="target-inputs"></slot></span>
|
|
55
65
|
</div>
|
|
56
66
|
</template>
|
|
57
67
|
|
|
58
68
|
<script setup>
|
|
59
|
-
import { computed, provide, ref, useTemplateRef } from 'vue';
|
|
69
|
+
import { computed, provide, ref, useHost, useTemplateRef, watch } from 'vue';
|
|
60
70
|
import safeGet from 'just-safe-get';
|
|
61
71
|
import { useDebounceFn } from '@vueuse/core';
|
|
62
72
|
import Bourne from '@hapi/bourne';
|
|
@@ -64,16 +74,16 @@ import ComboboxClear from './ComboboxClear.vue';
|
|
|
64
74
|
import ListBox from './ListBox.vue';
|
|
65
75
|
import ListBoxOption from './ListBoxOption.vue';
|
|
66
76
|
import ComboboxAriaLive from './ComboboxAriaLive.vue';
|
|
77
|
+
import ComboboxPill from './ComboboxPill.vue';
|
|
67
78
|
|
|
68
79
|
/*
|
|
69
80
|
* as this is a Web Component, all props are string-ish types, hence why `options` is JSON parsed, see `parsedPropOptions`.
|
|
70
81
|
* https://vuejs.org/guide/extras/web-components.html#props
|
|
71
82
|
*/
|
|
72
83
|
const props = defineProps({
|
|
73
|
-
|
|
84
|
+
comboboxId: { type: String, required: true },
|
|
74
85
|
placeholder: { type: String, default: '' },
|
|
75
|
-
name: { type:
|
|
76
|
-
value: { type: String, default: '' },
|
|
86
|
+
name: { type: String, required: true },
|
|
77
87
|
options: { type: String, default: '[]' },
|
|
78
88
|
iconpath: { type: String, default: '/assets/icons.svg' },
|
|
79
89
|
dataAriaInvalid: { type: String, default: '' },
|
|
@@ -88,74 +98,128 @@ const props = defineProps({
|
|
|
88
98
|
apiOptionsPath: { type: String, default: undefined },
|
|
89
99
|
/** where to grab the visual label from the option object e.g. 'label' or 'title' or 'nested.object.label' */
|
|
90
100
|
optionLabelPath: { type: String, default: 'label' },
|
|
101
|
+
/** where to grab the value from the option object e.g. 'value' or 'score' or 'nested.object.value' */
|
|
102
|
+
optionValuePath: { type: String, default: 'value' },
|
|
103
|
+
multiple: { type: Boolean, default: false },
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// host is the element in the DOM. We assume we are always a Vue CustomElement, so host should always exist
|
|
107
|
+
const host = useHost();
|
|
108
|
+
// combobox reports its value to the nearest `<form>` element https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals
|
|
109
|
+
// see ../../custom-elements/mds-combobox.js on supporting code making this work
|
|
110
|
+
const internals = host?.attachInternals();
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* `value` is defined with `defineModel` instead of `defineProps` so we can update its value.
|
|
114
|
+
*
|
|
115
|
+
* > Note: this defineModel + vModel + watch combination allows us to synchronise the HTML attribute, auto-parse the string to JSON value and setFormValue.
|
|
116
|
+
* > Recommended to keep this pattern for `value` attribute syncing/parsing.
|
|
117
|
+
* > Other patterns were tried but failed to achieve all of these goals and would cause subtle bugs.
|
|
118
|
+
* */
|
|
119
|
+
const vModelRawString = defineModel('value', { type: String, default: '' });
|
|
120
|
+
/** synchronise vModel to attribute */
|
|
121
|
+
watch(vModelRawString, (val) => host?.setAttribute('value', val), { immediate: true });
|
|
122
|
+
/** @type {import('vue').WritableComputedRef<object|Array<object>} parsed raw string of vModelRawString, this is the interface to use in our code */
|
|
123
|
+
const vModel = computed({
|
|
124
|
+
get() {
|
|
125
|
+
const defaultValue = props.multiple ? [] : null;
|
|
126
|
+
return Bourne.safeParse(vModelRawString.value) || defaultValue;
|
|
127
|
+
},
|
|
128
|
+
set(val) {
|
|
129
|
+
if (!val) vModelRawString.value = '';
|
|
130
|
+
else vModelRawString.value = JSON.stringify(val);
|
|
131
|
+
},
|
|
91
132
|
});
|
|
133
|
+
/** synchronise vModel with formValue - enables parent `<form>` to obtain this data */
|
|
134
|
+
watch(
|
|
135
|
+
vModel,
|
|
136
|
+
(val) => {
|
|
137
|
+
let formValue;
|
|
138
|
+
if (props.multiple) {
|
|
139
|
+
// if multiple, we can use `FormData` to populate multiple values of the same name
|
|
140
|
+
formValue = new FormData();
|
|
141
|
+
for (const option of val || []) {
|
|
142
|
+
const optVal = getOptionValue(option);
|
|
143
|
+
if (optVal) formValue.append(props.name, optVal);
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
formValue = getOptionValue(val);
|
|
147
|
+
}
|
|
148
|
+
internals?.setFormValue(formValue || '');
|
|
149
|
+
},
|
|
150
|
+
{ immediate: true },
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
/** `search-text` is defined with `defineModel` instead of `defineProps` for greater control */
|
|
154
|
+
const searchTextVModel = defineModel('search-text', {
|
|
155
|
+
type: String,
|
|
156
|
+
default: '',
|
|
157
|
+
get(val) {
|
|
158
|
+
return val;
|
|
159
|
+
},
|
|
160
|
+
set(val) {
|
|
161
|
+
// use attribute as source of truth
|
|
162
|
+
host?.setAttribute('search-text', val);
|
|
163
|
+
return val;
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
// initial prefill searchText if we are not multiple and vModel is set
|
|
167
|
+
if (!props.multiple && vModel.value && !searchTextVModel.value) {
|
|
168
|
+
searchTextVModel.value = getOptionLabel(vModel.value);
|
|
169
|
+
}
|
|
92
170
|
|
|
93
171
|
const $comboInput = useTemplateRef('$comboInput');
|
|
94
|
-
const $targetInputs = useTemplateRef('$targetInputs');
|
|
95
172
|
|
|
96
173
|
const expanded = ref(false);
|
|
97
174
|
/** `selectedIndex` aka "highlighted option", set by using keyboard controls */
|
|
98
175
|
const selectedIndex = ref(null);
|
|
99
|
-
|
|
176
|
+
|
|
100
177
|
const isLoading = ref(false);
|
|
101
178
|
/** used if apiUrl is set, otherwise `parsedPropOptions` is used */
|
|
102
179
|
const apiOptions = ref([]);
|
|
103
180
|
|
|
104
181
|
// as props must be string-ish types, we parse the `options` into a real array
|
|
105
|
-
const parsedPropOptions = computed(() =>
|
|
106
|
-
try {
|
|
107
|
-
return Bourne.parse(props.options);
|
|
108
|
-
} catch (e) {
|
|
109
|
-
console.error(e);
|
|
110
|
-
return [];
|
|
111
|
-
}
|
|
112
|
-
});
|
|
182
|
+
const parsedPropOptions = computed(() => Bourne.safeParse(props.options) || []);
|
|
113
183
|
|
|
114
184
|
const i18nText = computed(() => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
: {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
185
|
+
const defaults = {
|
|
186
|
+
loadingText: 'Loading',
|
|
187
|
+
resultsMessage: '{count} result available',
|
|
188
|
+
resultsMessage_plural: '{count} results available',
|
|
189
|
+
clearInput: 'clear input',
|
|
190
|
+
removePill: 'Remove {label}',
|
|
191
|
+
selectedOptionsLabel: 'Selected options:',
|
|
192
|
+
};
|
|
193
|
+
const overrides = props.i18n ? Bourne.safeParse(props.i18n) : {};
|
|
194
|
+
return { ...defaults, ...overrides };
|
|
123
195
|
});
|
|
124
|
-
|
|
196
|
+
/** filtered props.options or apiOptions, by searchTextVModel */
|
|
125
197
|
const visibleOptions = computed(() => {
|
|
126
|
-
if (
|
|
127
|
-
return parsedPropOptions.value.filter((opt) =>
|
|
128
|
-
getOptionLabel(opt).toLowerCase().includes(searchValue.value.toLowerCase()),
|
|
129
|
-
);
|
|
130
|
-
}
|
|
198
|
+
if (props.apiUrl) return apiOptions.value;
|
|
131
199
|
|
|
132
|
-
return
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return `${props.comboboxid}-listbox`;
|
|
200
|
+
return parsedPropOptions.value.filter((opt) =>
|
|
201
|
+
getOptionLabel(opt).toLowerCase().includes(searchTextVModel.value.toLowerCase()),
|
|
202
|
+
);
|
|
136
203
|
});
|
|
204
|
+
const listBoxId = computed(() => `${props.comboboxId}-listbox`);
|
|
137
205
|
|
|
138
206
|
/** generate an DOM `id` for a option, based on index number */
|
|
139
207
|
function getOptionIdByIndex(index) {
|
|
140
208
|
if (typeof index === 'number' && index > -1) {
|
|
141
|
-
return `${props.
|
|
209
|
+
return `${props.comboboxId}-option-${index}`;
|
|
142
210
|
}
|
|
143
211
|
return undefined;
|
|
144
212
|
}
|
|
145
213
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const ariaInvalid = computed(() => {
|
|
152
|
-
return props.dataAriaInvalid ? 'true' : 'false';
|
|
153
|
-
});
|
|
214
|
+
/** aria-expanded must be string to apply as an aria attribute */
|
|
215
|
+
const ariaExpanded = computed(() => (expanded.value ? 'true' : 'false'));
|
|
216
|
+
/** aria-invalid must be string to apply as an aria attribute */
|
|
217
|
+
const ariaInvalid = computed(() => (props.dataAriaInvalid ? 'true' : 'false'));
|
|
154
218
|
|
|
155
219
|
/**
|
|
156
220
|
* When user chooses an option:
|
|
157
221
|
* - set search input to chosen option's label
|
|
158
|
-
* - set
|
|
222
|
+
* - set value
|
|
159
223
|
* - close list menu
|
|
160
224
|
* - reset selectedIndex
|
|
161
225
|
* @param newOption
|
|
@@ -166,35 +230,29 @@ function chooseOption(newOption) {
|
|
|
166
230
|
console.error('attempted to choose an option, but option was falsy');
|
|
167
231
|
return;
|
|
168
232
|
}
|
|
169
|
-
|
|
170
|
-
|
|
233
|
+
// set value and searchText
|
|
234
|
+
if (!props.multiple) {
|
|
235
|
+
vModel.value = newOption;
|
|
236
|
+
searchTextVModel.value = getOptionLabel(newOption);
|
|
237
|
+
} else {
|
|
238
|
+
const existingOption = vModel.value?.find((_option) => getOptionValue(_option) === getOptionValue(newOption));
|
|
239
|
+
if (!existingOption) vModel.value = [...vModel.value, newOption];
|
|
240
|
+
searchTextVModel.value = '';
|
|
241
|
+
}
|
|
171
242
|
makeInactive();
|
|
172
243
|
selectedIndex.value = null;
|
|
173
244
|
}
|
|
174
245
|
|
|
175
|
-
/**
|
|
176
|
-
* Update target inputs with value from an option.
|
|
177
|
-
* If option is not supplied, target input values will be cleared
|
|
178
|
-
* @param {object?} option
|
|
179
|
-
*/
|
|
180
|
-
function setTargetValues(option) {
|
|
181
|
-
const targetInputs = Array.from($targetInputs.value?.querySelectorAll('[data-key]'));
|
|
182
|
-
for (const el of targetInputs) {
|
|
183
|
-
// if no option, clear target value
|
|
184
|
-
el.value = option ? safeGet(option, el.getAttribute('data-key')) : '';
|
|
185
|
-
// ensure external code like htmx reacts to the new value
|
|
186
|
-
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
246
|
function makeActive() {
|
|
190
247
|
expanded.value = true;
|
|
191
248
|
}
|
|
192
249
|
function makeInactive() {
|
|
193
250
|
expanded.value = false;
|
|
194
251
|
}
|
|
252
|
+
/** clear search text input, if not multiple mode, also clear vModel value */
|
|
195
253
|
function clearField() {
|
|
196
|
-
|
|
197
|
-
|
|
254
|
+
searchTextVModel.value = '';
|
|
255
|
+
if (!props.multiple) vModel.value = null;
|
|
198
256
|
}
|
|
199
257
|
|
|
200
258
|
/**
|
|
@@ -203,7 +261,7 @@ function clearField() {
|
|
|
203
261
|
*/
|
|
204
262
|
const debouncedFetchApiOptions = useDebounceFn(async function fetchApiOptions() {
|
|
205
263
|
if (!props.apiUrl) return;
|
|
206
|
-
const searchQuery =
|
|
264
|
+
const searchQuery = searchTextVModel?.value?.trim();
|
|
207
265
|
try {
|
|
208
266
|
isLoading.value = true;
|
|
209
267
|
let res = await fetch(`${props.apiUrl}?${props.apiQueryKey}=${encodeURIComponent(searchQuery)}`);
|
|
@@ -229,22 +287,36 @@ function getOptionLabel(option) {
|
|
|
229
287
|
const label = safeGet(option, props.optionLabelPath);
|
|
230
288
|
return String(label);
|
|
231
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* where do we grab the value from the option object?
|
|
292
|
+
* option.value or option['nested.object.value.path']
|
|
293
|
+
* @param {object} option
|
|
294
|
+
* @returns {string} value
|
|
295
|
+
*/
|
|
296
|
+
function getOptionValue(option) {
|
|
297
|
+
const val = safeGet(option, props.optionValuePath);
|
|
298
|
+
return String(val ?? '');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function getPillAriaLabel(option) {
|
|
302
|
+
return i18nText.value.removePill.replace('{label}', getOptionLabel(option));
|
|
303
|
+
}
|
|
232
304
|
|
|
233
305
|
/**
|
|
234
306
|
* - reset selectedIndex
|
|
235
|
-
* - copies the existing value into `
|
|
307
|
+
* - copies the existing value into `searchTextVModel` (because we manually handle input/change events)
|
|
236
308
|
* - fetch from api if applicable
|
|
237
309
|
* @param event input event
|
|
238
310
|
*/
|
|
239
311
|
function handleInput(event) {
|
|
240
312
|
selectedIndex.value = null;
|
|
241
|
-
|
|
313
|
+
searchTextVModel.value = event.target ? event.target.value : '';
|
|
242
314
|
handleChange();
|
|
243
315
|
debouncedFetchApiOptions();
|
|
244
316
|
}
|
|
245
317
|
function handleChange() {
|
|
246
|
-
if (
|
|
247
|
-
if (
|
|
318
|
+
if (searchTextVModel.value.length === 0) clearField();
|
|
319
|
+
if (searchTextVModel.value.length >= props.minSearchCharacters) {
|
|
248
320
|
makeActive();
|
|
249
321
|
} else {
|
|
250
322
|
makeInactive();
|
|
@@ -257,6 +329,12 @@ function handleClear() {
|
|
|
257
329
|
clearField();
|
|
258
330
|
$comboInput.value?.focus();
|
|
259
331
|
}
|
|
332
|
+
function handleClickInputWrapper() {
|
|
333
|
+
$comboInput.value?.focus();
|
|
334
|
+
}
|
|
335
|
+
function handleClickPill(option) {
|
|
336
|
+
vModel.value = vModel.value.filter((opt) => getOptionValue(opt) !== getOptionValue(option));
|
|
337
|
+
}
|
|
260
338
|
/**
|
|
261
339
|
* As the `Enter` key is handled seperately (see `handleKeyDownEnter`),
|
|
262
340
|
* we need this handler for mouse clicks on an option
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="mds-combobox__pill mds-border">
|
|
3
|
+
<span class="mds-combobox__pill-text"><slot /></span>
|
|
4
|
+
<button class="mds-combobox__pill-icon" type="button" :aria-label="ariaLabelRemove" @click="handleClickPill">
|
|
5
|
+
<svg aria-hidden="true" focusable="false" class="mds-icon mds-icon--close mds-icon--sm">
|
|
6
|
+
<use :href="`${iconPath}#icon-close`" />
|
|
7
|
+
</svg>
|
|
8
|
+
</button>
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
import { inject } from 'vue';
|
|
14
|
+
|
|
15
|
+
defineProps({
|
|
16
|
+
ariaLabelRemove: { type: String, required: true },
|
|
17
|
+
});
|
|
18
|
+
const emit = defineEmits(['remove']);
|
|
19
|
+
const iconPath = inject('iconPath');
|
|
20
|
+
function handleClickPill() {
|
|
21
|
+
emit('remove');
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
role="option"
|
|
6
6
|
:class="{ 'mds-combobox__option--focused': focused }"
|
|
7
7
|
:aria-selected="focused.toString()"
|
|
8
|
-
@mousedown="$emit('mousedown', $event)"
|
|
9
8
|
v-html="highlightOption()"
|
|
10
9
|
/>
|
|
11
10
|
</template>
|
|
@@ -16,7 +15,7 @@ import { useTemplateRef, watch } from 'vue';
|
|
|
16
15
|
const props = defineProps({
|
|
17
16
|
optionLabel: { type: String, required: true },
|
|
18
17
|
focused: { type: Boolean, default: false },
|
|
19
|
-
|
|
18
|
+
searchText: { type: String, default: '' },
|
|
20
19
|
});
|
|
21
20
|
|
|
22
21
|
const $listItem = useTemplateRef('$listItem');
|
|
@@ -31,7 +30,7 @@ watch(
|
|
|
31
30
|
);
|
|
32
31
|
function highlightOption() {
|
|
33
32
|
const optionLabelHtml = props.optionLabel.replace(
|
|
34
|
-
new RegExp(props.
|
|
33
|
+
new RegExp(props.searchText, 'gi'),
|
|
35
34
|
(match) => `<span class="mds-combobox__option--marked">${match}</span>`,
|
|
36
35
|
);
|
|
37
36
|
return optionLabelHtml;
|
|
@@ -20,6 +20,7 @@ export default {
|
|
|
20
20
|
customMenuButtons: this.customMenuButtons,
|
|
21
21
|
i18nText: this.i18nText,
|
|
22
22
|
ariaDescribedBy: this.describedbyId,
|
|
23
|
+
noMenu: this.noMenu,
|
|
23
24
|
};
|
|
24
25
|
},
|
|
25
26
|
props: {
|
|
@@ -47,6 +48,10 @@ export default {
|
|
|
47
48
|
type: String,
|
|
48
49
|
default: '',
|
|
49
50
|
},
|
|
51
|
+
noMenu: {
|
|
52
|
+
type: Boolean,
|
|
53
|
+
default: false,
|
|
54
|
+
},
|
|
50
55
|
},
|
|
51
56
|
data() {
|
|
52
57
|
return {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="mds-text-editor__menu" role="toolbar" :aria-label="i18nText.toolbarLabel" :aria-controls="id">
|
|
2
|
+
<div class="mds-text-editor__menu" role="toolbar" v-if="!noMenu" :aria-label="i18nText.toolbarLabel" :aria-controls="id">
|
|
3
3
|
<TextEditorButton
|
|
4
4
|
v-for="button in menuButtons"
|
|
5
5
|
:id="button.id"
|
|
@@ -35,7 +35,7 @@ export default {
|
|
|
35
35
|
// TextEditorPopoverLink,
|
|
36
36
|
},
|
|
37
37
|
|
|
38
|
-
inject: ['id', 'customMenuButtons', 'i18nText'],
|
|
38
|
+
inject: ['id', 'customMenuButtons', 'i18nText', 'noMenu'],
|
|
39
39
|
|
|
40
40
|
props: {
|
|
41
41
|
editor: {
|
|
@@ -4,5 +4,8 @@ import { defineCustomElement } from 'vue';
|
|
|
4
4
|
import Combobox from '../components/combobox/Combobox.ce.vue';
|
|
5
5
|
|
|
6
6
|
const MdsCombobox = defineCustomElement(Combobox, { shadowRoot: false });
|
|
7
|
+
// we must set `formAssociated` manually as combobox uses elementInternals and currently vue does not support this
|
|
8
|
+
// https://github.com/vuejs/core/issues/10948#issuecomment-2877323232
|
|
9
|
+
Object.defineProperty(MdsCombobox, 'formAssociated', { value: true, writable: false });
|
|
7
10
|
|
|
8
11
|
export default MdsCombobox;
|
|
@@ -1 +1 @@
|
|
|
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};
|
|
1
|
+
import{v as H,x as w,a as f,b as m,f as b,u as C,q as g,t as L,i as M,y as X,z as Y,A as k,e as Z,r as O,B as _e,C as N,D as B,F as U,l as W,p as G,k as R,E as Q,G as ge,H as _,I as xe,s as Se}from"../runtime-dom.esm-bundler.js";function $e(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var A=Ie;function Ie(t,e,o){if(!t)return o;var a,l;if(Array.isArray(e)&&(a=e.slice(0)),typeof e=="string"&&(a=e.split(".")),typeof e=="symbol"&&(a=[e]),!Array.isArray(a))throw new Error("props arg must be an array, a string or a symbol");for(;a.length;)if(l=a.shift(),!t||(t=t[l],t===void 0))return o;return t}typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const z=()=>{};function Ce(t,e){function o(...a){return new Promise((l,s)=>{Promise.resolve(t(()=>e.apply(this,a),{fn:e,thisArg:this,args:a})).then(l).catch(s)})}return o}function Pe(t,e={}){let o,a,l=z;const s=r=>{clearTimeout(r),l(),l=z};let i;return r=>{const c=H(t),h=H(e.maxWait);return o&&s(o),c<=0||h!==void 0&&h<=0?(a&&(s(a),a=void 0),Promise.resolve(r())):new Promise((x,T)=>{l=e.rejectOnCancel?T:x,i=r,h&&!a&&(a=setTimeout(()=>{o&&s(o),a=void 0,x(i())},h)),o=setTimeout(()=>{a&&s(a),a=void 0,x(r())},c)})}}function ee(t,e=200,o={}){return Ce(Pe(e,o),t)}var E={},J;function Oe(){return J||(J=1,(function(t){const e={suspectRx:/"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*\:/};t.parse=function(o,...a){const l=typeof a[0]=="object"&&a[0],s=a.length>1||!l?a[0]:void 0,i=a.length>1&&a[1]||l||{},p=JSON.parse(o,s);return i.protoAction==="ignore"||!p||typeof p!="object"||!o.match(e.suspectRx)||t.scan(p,i),p},t.scan=function(o,a={}){let l=[o];for(;l.length;){const s=l;l=[];for(const i of s){if(Object.prototype.hasOwnProperty.call(i,"__proto__")){if(a.protoAction!=="remove")throw new SyntaxError("Object contains forbidden prototype property");delete i.__proto__}for(const p in i){const r=i[p];r&&typeof r=="object"&&l.push(i[p])}}}},t.safeParse=function(o,a){try{return t.parse(o,a)}catch{return null}}})(E)),E}var we=Oe();const V=$e(we),Me=["aria-label","title"],Le={"aria-hidden":"true",focusable:"false",class:"mds-icon mds-icon--close mds-icon--sm"},ke=["href"],Te={__name:"ComboboxClear",setup(t){const e=w("iconPath"),o=w("clearInput");return(a,l)=>(f(),m("button",{class:"mds-combobox__clear mds-button mds-button--plain",type:"button",onClick:l[0]||(l[0]=s=>a.$emit("clear",s)),onKeydown:l[1]||(l[1]=g(s=>a.$emit("clear",s),["enter"])),"aria-label":C(o),title:C(o)},[(f(),m("svg",Le,[b("use",{href:`${C(e)}#icon-close`},null,8,ke)]))],40,Me))}},Fe=["hidden"],Be={key:0,class:"mds-combobox-loading"},Re={"aria-hidden":"true",focusable:"true",class:"mds-icon mds-icon--spinner mds-icon--after"},Ae=["href"],Ee={class:"mds-visually-hidden"},Ve={__name:"ListBox",props:{hidden:{type:Boolean,default:!0},isLoading:{type:Boolean,default:!0}},setup(t){const e=w("iconPath"),o=w("loadingText");return(a,l)=>(f(),m("ul",{class:"mds-combobox__listbox",role:"listbox",hidden:t.hidden},[t.isLoading?(f(),m("li",Be,[(f(),m("svg",Re,[b("use",{href:`${C(e)}#icon-spinner`},null,8,Ae)])),b("span",Ee,L(C(o)),1)])):M("",!0),X(a.$slots,"default")],8,Fe))}},Ke=["aria-selected","innerHTML"],De={__name:"ListBoxOption",props:{optionLabel:{type:String,required:!0},focused:{type:Boolean,default:!1},searchText:{type:String,default:""}},setup(t){const e=t,o=Y("$listItem");k(()=>e.focused,l=>{l&&o.value?.scrollIntoView({block:"nearest",inline:"nearest"})});function a(){return e.optionLabel.replace(new RegExp(e.searchText,"gi"),s=>`<span class="mds-combobox__option--marked">${s}</span>`)}return(l,s)=>(f(),m("li",{ref_key:"$listItem",ref:o,class:Z(["mds-combobox__option",{"mds-combobox__option--focused":t.focused}]),role:"option","aria-selected":t.focused.toString(),innerHTML:a()},null,10,Ke))}},je={role:"status",class:"mds-visually-hidden"},qe={__name:"ComboboxAriaLive",props:{visibleOptions:{type:Array,default:()=>[]},expanded:{type:Boolean,default:!1},resultsMessage:{type:String},resultsMessage_plural:{type:String}},setup(t){const e=t;k([()=>e.expanded,()=>e.visibleOptions],()=>{l()},{deep:!0});const o=O(null),a=ee(function(){const i=e.visibleOptions.length===1?e.resultsMessage:e.resultsMessage_plural;o.value=i.replace("{count}",e.visibleOptions.length)},1400);function l(){o.value=null,e.expanded&&a()}return(s,i)=>(f(),m("div",je,L(o.value),1))}},He={class:"mds-combobox__pill mds-border"},Ne={class:"mds-combobox__pill-text"},Ue=["aria-label"],We={"aria-hidden":"true",focusable:"false",class:"mds-icon mds-icon--close mds-icon--sm"},Ge=["href"],Qe={__name:"ComboboxPill",props:{ariaLabelRemove:{type:String,required:!0}},emits:["remove"],setup(t,{emit:e}){const o=e,a=w("iconPath");function l(){o("remove")}return(s,i)=>(f(),m("div",He,[b("span",Ne,[X(s.$slots,"default")]),b("button",{class:"mds-combobox__pill-icon",type:"button","aria-label":t.ariaLabelRemove,onClick:l},[(f(),m("svg",We,[b("use",{href:`${C(a)}#icon-close`},null,8,Ge)]))],8,Ue)]))}},ze={key:0,class:"mds-visually-hidden"},Je={key:1,class:"mds-combobox__pills"},Xe=["id","value","placeholder","aria-controls","aria-expanded","aria-describedby","aria-activedescendant","aria-invalid"],Ye={__name:"Combobox.ce",props:ge({comboboxId:{type:String,required:!0},placeholder:{type:String,default:""},name:{type:String,required:!0},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"},optionValuePath:{type:String,default:"value"},multiple:{type:Boolean,default:!1}},{value:{type:String,default:""},valueModifiers:{},"search-text":{type:String,default:""},"search-textModifiers":{}}),emits:["update:value","update:search-text"],setup(t){const e=t,o=_e(),a=o?.attachInternals(),l=N(t,"value");k(l,n=>o?.setAttribute("value",n),{immediate:!0});const s=_({get(){const n=e.multiple?[]:null;return V.safeParse(l.value)||n},set(n){n?l.value=JSON.stringify(n):l.value=""}});k(s,n=>{let u;if(e.multiple){u=new FormData;for(const d of n||[]){const v=y(d);v&&u.append(e.name,v)}}else u=y(n);a?.setFormValue(u||"")},{immediate:!0});const i=N(t,"search-text",{get(n){return n},set(n){return o?.setAttribute("search-text",n),n}});!e.multiple&&s.value&&!i.value&&(i.value=I(s.value));const p=Y("$comboInput"),r=O(!1),c=O(null),h=O(!1),x=O([]),T=_(()=>V.safeParse(e.options)||[]),S=_(()=>{const n={loadingText:"Loading",resultsMessage:"{count} result available",resultsMessage_plural:"{count} results available",clearInput:"clear input",removePill:"Remove {label}",selectedOptionsLabel:"Selected options:"},u=e.i18n?V.safeParse(e.i18n):{};return{...n,...u}}),$=_(()=>e.apiUrl?x.value:T.value.filter(n=>I(n).toLowerCase().includes(i.value.toLowerCase()))),K=_(()=>`${e.comboboxId}-listbox`);function D(n){if(typeof n=="number"&&n>-1)return`${e.comboboxId}-option-${n}`}const te=_(()=>r.value?"true":"false"),ne=_(()=>e.dataAriaInvalid?"true":"false");function j(n){if(!n){console.error("attempted to choose an option, but option was falsy");return}e.multiple?(s.value?.find(d=>y(d)===y(n))||(s.value=[...s.value,n]),i.value=""):(s.value=n,i.value=I(n)),P(),c.value=null}function ae(){r.value=!0}function P(){r.value=!1}function q(){i.value="",e.multiple||(s.value=null)}const oe=ee(async function(){if(!e.apiUrl)return;const u=i?.value?.trim();try{h.value=!0;let d=await fetch(`${e.apiUrl}?${e.apiQueryKey}=${encodeURIComponent(u)}`);if(!d.ok)return;d=await d.json();const v=e.apiOptionsPath?A(d,e.apiOptionsPath):d;x.value=v||[]}finally{h.value=!1}},350);function I(n){const u=A(n,e.optionLabelPath);return String(u)}function y(n){const u=A(n,e.optionValuePath);return String(u??"")}function le(n){return S.value.removePill.replace("{label}",I(n))}function se(n){c.value=null,i.value=n.target?n.target.value:"",F(),oe()}function F(){i.value.length===0&&q(),i.value.length>=e.minSearchCharacters?ae():P()}function ie(){F()}function re(){q(),p.value?.focus()}function ue(){p.value?.focus()}function ce(n){s.value=s.value.filter(u=>y(u)!==y(n))}function de(n){j(n)}function fe(n){if(r.value){n.preventDefault();const u=$.value?.[c.value];u?j(u):P()}}function pe(){P()}function me(){r.value&&(c.value!==null?c.value=Math.min(c.value+1,$.value.length-1):c.value=0)}function ve(){r.value&&(c.value!==null?c.value=Math.max(c.value-1,0):c.value=$.value.length-1)}function he(){r.value&&(c.value=0)}function be(){r.value&&(c.value=$.value.length-1)}function ye(){P()}return B("iconPath",e.iconpath),B("loadingText",S.value.loadingText),B("clearInput",S.value.clearInput),(n,u)=>(f(),m("div",{class:Z(["mds-combobox",{"mds-combobox--active":r.value}]),onKeydown:[g(me,["down"]),g(ve,["up"]),g(he,["home"]),g(be,["end"]),g(ye,["esc"]),g(fe,["enter"])]},[b("div",{class:"mds-form-control",onClick:ue},[t.multiple&&s.value?.length?(f(),m("span",ze,L(S.value.selectedOptionsLabel),1)):M("",!0),t.multiple&&s.value?.length?(f(),m("ul",Je,[(f(!0),m(U,null,W(s.value,d=>(f(),m("li",{key:y(d)},[R(Qe,{"aria-label-remove":le(d),onRemove:v=>ce(d)},{default:Q(()=>[xe(L(I(d)),1)]),_:2},1032,["aria-label-remove","onRemove"])]))),128))])):M("",!0),b("input",{id:t.comboboxId,class:"mds-combobox__search-input",ref_key:"$comboInput",ref:p,value:i.value,autocomplete:"off",type:"text",role:"combobox",placeholder:t.placeholder,"aria-controls":K.value,"aria-expanded":te.value,"aria-autocomplete":"list","aria-describedby":t.describedbyId,"aria-activedescendant":D(c.value),"aria-invalid":ne.value,onInput:se,onChange:F,onBlur:pe,onFocus:ie},null,40,Xe),i.value.length>0?(f(),G(Te,{key:2,onClear:re})):M("",!0)]),R(Ve,{id:K.value,hidden:!r.value,"aria-labelledby":`${t.comboboxId}-label`,"is-loading":h.value},{default:Q(()=>[(f(!0),m(U,null,W($.value,(d,v)=>(f(),G(De,{id:D(v),key:v,"option-label":I(d),focused:c.value===v,"search-text":i.value,onMousedown:et=>de(d)},null,8,["id","option-label","focused","search-text","onMousedown"]))),128))]),_:1},8,["id","hidden","aria-labelledby","is-loading"]),R(qe,{"visible-options":$.value,expanded:r.value,"results-message":S.value.resultsMessage,"results-message_plural":S.value.resultsMessage_plural},null,8,["visible-options","expanded","results-message","results-message_plural"])],34))}},Ze=Se(Ye,{shadowRoot:!1});Object.defineProperty(Ze,"formAssociated",{value:!0,writable:!1});export{Ze as default};
|