@mustib/web-components 0.0.0-alpha.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/README.md +17 -0
- package/components/mu-element.d.ts +107 -0
- package/components/mu-element.js +4 -0
- package/components/mu-icon.d.ts +25 -0
- package/components/mu-icon.js +65 -0
- package/components/mu-range-fill.d.ts +48 -0
- package/components/mu-range-fill.js +94 -0
- package/components/mu-range-thumb-value.d.ts +48 -0
- package/components/mu-range-thumb-value.js +137 -0
- package/components/mu-range-thumb.d.ts +120 -0
- package/components/mu-range-thumb.js +305 -0
- package/components/mu-range.d.ts +206 -0
- package/components/mu-range.js +661 -0
- package/components/mu-select-item.d.ts +29 -0
- package/components/mu-select-item.js +124 -0
- package/components/mu-select-items.d.ts +218 -0
- package/components/mu-select-items.js +570 -0
- package/components/mu-select-label-content.d.ts +38 -0
- package/components/mu-select-label-content.js +159 -0
- package/components/mu-select-label.d.ts +52 -0
- package/components/mu-select-label.js +352 -0
- package/components/mu-select.d.ts +63 -0
- package/components/mu-select.js +347 -0
- package/components/mu-transparent.d.ts +56 -0
- package/components/mu-transparent.js +75 -0
- package/components/mu-trigger.d.ts +129 -0
- package/components/mu-trigger.js +175 -0
- package/decorators.d.ts +34 -0
- package/decorators.js +50 -0
- package/index.d.ts +15 -0
- package/index.js +17 -0
- package/mu-element-CZDI_RCY.js +1117 -0
- package/package.json +45 -0
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
import { M as MUElement, E as EventAction, _ as __decorate, g as getElementBoundaries, d as debounce, a as disableElementScroll, e as enableElementScroll } from '../mu-element-CZDI_RCY.js';
|
|
2
|
+
import { property } from 'lit/decorators.js';
|
|
3
|
+
import { css, html } from 'lit';
|
|
4
|
+
import { MuSelectItem } from './mu-select-item.js';
|
|
5
|
+
import { MuTransparent } from './mu-transparent.js';
|
|
6
|
+
import { staticProperty } from '../decorators.js';
|
|
7
|
+
|
|
8
|
+
class MuSelectItems extends MUElement {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this.opened = false;
|
|
12
|
+
this.multiple = false;
|
|
13
|
+
this.noClearActiveOnClose = false;
|
|
14
|
+
this.position = 'fixed';
|
|
15
|
+
/**
|
|
16
|
+
* Controls how the items container behaves when opened.
|
|
17
|
+
*
|
|
18
|
+
* - `'static'`: Position is calculated once when opened or closed.
|
|
19
|
+
* - `'no-scroll'`: Like static, but page scroll is disabled.
|
|
20
|
+
* - `'dynamic'`: Position is recalculated on scroll.
|
|
21
|
+
*
|
|
22
|
+
* @default 'no-scroll'
|
|
23
|
+
*/
|
|
24
|
+
this.openMode = 'no-scroll';
|
|
25
|
+
this.eventActionData = {
|
|
26
|
+
eventAction: MuSelectItems.eventAction,
|
|
27
|
+
events: ['click', 'pointerover', 'pointerdown']
|
|
28
|
+
};
|
|
29
|
+
this._isReady = this.generateIsReadyPromise();
|
|
30
|
+
this._items = [];
|
|
31
|
+
this._itemsValuesMap = new Map();
|
|
32
|
+
this._itemsElementsMap = new Map();
|
|
33
|
+
this._selectedValues = new Set();
|
|
34
|
+
/**
|
|
35
|
+
* Calculates the position of the items container.
|
|
36
|
+
*/
|
|
37
|
+
this._calculateSizes = () => {
|
|
38
|
+
const boundaries = getElementBoundaries(this.parentElement);
|
|
39
|
+
const yAxisPosition = boundaries.elementTop >= boundaries.elementBottom ? 'top' : 'bottom';
|
|
40
|
+
this.setAttribute('items-y-axis', yAxisPosition);
|
|
41
|
+
this.style.setProperty('--items-max-height', Math.max(boundaries.elementTop, boundaries.elementBottom) + 'px');
|
|
42
|
+
if (this.position === 'fixed') {
|
|
43
|
+
this.style.setProperty('--items-position', 'fixed');
|
|
44
|
+
this.style.setProperty('--items-width', boundaries.width + 'px');
|
|
45
|
+
if (yAxisPosition === 'top') {
|
|
46
|
+
this.style.setProperty('--items-bottom', boundaries.elementBottom + boundaries.height + 'px');
|
|
47
|
+
this.style.setProperty('--items-top', 'unset');
|
|
48
|
+
this.style.setProperty('--items-transform-origin', 'bottom');
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.style.setProperty('--items-top', boundaries.elementTop + boundaries.height + 'px');
|
|
52
|
+
this.style.setProperty('--items-bottom', 'unset');
|
|
53
|
+
this.style.setProperty('--items-transform-origin', 'top');
|
|
54
|
+
}
|
|
55
|
+
this.style.setProperty('--items-left', boundaries.elementLeft + 'px');
|
|
56
|
+
this.style.setProperty('--items-right', boundaries.elementRight + 'px');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this.style.setProperty('--items-position', 'absolute');
|
|
60
|
+
this.style.setProperty('--items-width', '100%');
|
|
61
|
+
if (yAxisPosition === 'top') {
|
|
62
|
+
this.style.setProperty('--items-bottom', '100%');
|
|
63
|
+
this.style.setProperty('--items-top', 'unset');
|
|
64
|
+
this.style.setProperty('--items-transform-origin', 'bottom');
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
this.style.setProperty('--items-top', '100%');
|
|
68
|
+
this.style.setProperty('--items-bottom', 'unset');
|
|
69
|
+
this.style.setProperty('--items-transform-origin', 'top');
|
|
70
|
+
}
|
|
71
|
+
this.style.setProperty('--items-left', '0');
|
|
72
|
+
this.style.setProperty('--items-right', '0');
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
this._slotChangeHandler = () => {
|
|
79
|
+
const previouslySelectedValues = new Set(this._selectedValues);
|
|
80
|
+
const previouslyActiveItem = this._activeItem;
|
|
81
|
+
this._items = [];
|
|
82
|
+
this._activeItem = undefined;
|
|
83
|
+
this._itemsValuesMap.clear();
|
|
84
|
+
this._itemsElementsMap.clear();
|
|
85
|
+
const newSelectedValues = new Set();
|
|
86
|
+
const addItem = (element) => {
|
|
87
|
+
const { value } = element;
|
|
88
|
+
if (this._itemsValuesMap.has(value)) {
|
|
89
|
+
console.warn(`Item with value ${value} already exists in mu-select-items, it will be ignored`, element);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const item = {
|
|
93
|
+
element,
|
|
94
|
+
value,
|
|
95
|
+
selected: false,
|
|
96
|
+
active: false,
|
|
97
|
+
index: this._items.length
|
|
98
|
+
};
|
|
99
|
+
this._itemsValuesMap.set(value, item);
|
|
100
|
+
this._itemsElementsMap.set(element, item);
|
|
101
|
+
this._items.push(item);
|
|
102
|
+
if (previouslySelectedValues.has(value))
|
|
103
|
+
newSelectedValues.add(value);
|
|
104
|
+
if (previouslyActiveItem?.value === value)
|
|
105
|
+
this._addActiveItemState(item);
|
|
106
|
+
};
|
|
107
|
+
this.renderRoot.querySelector('slot#items-slot').assignedElements({ flatten: true }).forEach((child) => {
|
|
108
|
+
if ((child instanceof MuTransparent)) {
|
|
109
|
+
const contents = child.contents;
|
|
110
|
+
contents.forEach((content) => {
|
|
111
|
+
if (!(content instanceof MuSelectItem))
|
|
112
|
+
return;
|
|
113
|
+
addItem(content);
|
|
114
|
+
});
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (!(child instanceof MuSelectItem))
|
|
118
|
+
return;
|
|
119
|
+
addItem(child);
|
|
120
|
+
});
|
|
121
|
+
const removedSelected = previouslySelectedValues.difference(newSelectedValues);
|
|
122
|
+
if (removedSelected.size > 0) {
|
|
123
|
+
if (!this.isControlled) {
|
|
124
|
+
this._selectedValues.clear();
|
|
125
|
+
newSelectedValues.forEach(value => {
|
|
126
|
+
this._addSelectState(this._itemsValuesMap.get(value));
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const eventName = 'mu-select-items-change-orphans';
|
|
130
|
+
this.dispatchEvent(new CustomEvent(eventName, { bubbles: true, composed: true, detail: { orphanValues: Array.from(removedSelected), values: Array.from(newSelectedValues) } }));
|
|
131
|
+
}
|
|
132
|
+
if (!this._isReady.resolved)
|
|
133
|
+
this._isReady.resolve();
|
|
134
|
+
};
|
|
135
|
+
this._debounceDispatchChangeEvent = debounce(this._dispatchChangeEvent.bind(this), 50);
|
|
136
|
+
}
|
|
137
|
+
get isControlled() {
|
|
138
|
+
return this.value && this.value.length > 0;
|
|
139
|
+
}
|
|
140
|
+
get parentElement() {
|
|
141
|
+
const selector = this.getAttribute('parent-selector');
|
|
142
|
+
const element = selector ? this.closestPierce(selector) : super.parentElement;
|
|
143
|
+
return element;
|
|
144
|
+
}
|
|
145
|
+
get activeValue() {
|
|
146
|
+
return this._activeItem?.value;
|
|
147
|
+
}
|
|
148
|
+
getValue() {
|
|
149
|
+
return Array.from(this._selectedValues);
|
|
150
|
+
}
|
|
151
|
+
connectedCallback() {
|
|
152
|
+
super.connectedCallback();
|
|
153
|
+
this.role = 'listbox';
|
|
154
|
+
this.addEventListener('mu-transparent-slotchange', this._slotChangeHandler);
|
|
155
|
+
if (this.position === 'fixed') {
|
|
156
|
+
this._resizeObserver = new ResizeObserver(this._calculateSizes);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
*
|
|
161
|
+
*/
|
|
162
|
+
disconnectedCallback() {
|
|
163
|
+
super.disconnectedCallback();
|
|
164
|
+
window.removeEventListener('scroll', this._calculateSizes);
|
|
165
|
+
this._resizeObserver?.disconnect();
|
|
166
|
+
}
|
|
167
|
+
unselect(values) {
|
|
168
|
+
values.forEach(value => this._changeSelectState('remove', value));
|
|
169
|
+
}
|
|
170
|
+
unselectAll() {
|
|
171
|
+
this.unselect(this.getValue());
|
|
172
|
+
}
|
|
173
|
+
unselectLatestItem() {
|
|
174
|
+
this._changeSelectState('remove', this.getValue().pop());
|
|
175
|
+
}
|
|
176
|
+
toggleActiveItemSelect() {
|
|
177
|
+
this._changeSelectState('toggle', this._activeItem);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Focuses the first navigable item in the given direction.
|
|
181
|
+
*
|
|
182
|
+
* If an active item already exists, it will be focused.
|
|
183
|
+
*
|
|
184
|
+
* Used by parent to focus the first or last navigable item when opened
|
|
185
|
+
*/
|
|
186
|
+
focusFirstNavigableItem(direction) {
|
|
187
|
+
this.updateComplete.then(() => {
|
|
188
|
+
const item = this._activeItem || this._getNavigationItem({ direction, switchBack: true });
|
|
189
|
+
this._addActiveItemState(item);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
_getNavigationItem({ direction, switchBack = false, fromIndex = direction === 'next' ? -1 : this._items.length }) {
|
|
193
|
+
return this.getNavigationItem({
|
|
194
|
+
fromIndex,
|
|
195
|
+
direction,
|
|
196
|
+
switchBack,
|
|
197
|
+
items: this._items,
|
|
198
|
+
isNavigable: (item) => !(item.element.disabled || item.element.readonly || item.element.filteredOut)
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Add active state to the next or previous item from the current active item.
|
|
203
|
+
*/
|
|
204
|
+
switchActiveItem(direction, options) {
|
|
205
|
+
const { switchBack = true } = options ?? {};
|
|
206
|
+
const activeIndex = this._activeItem?.index;
|
|
207
|
+
const newActiveItem = this._getNavigationItem({ direction, switchBack, fromIndex: activeIndex });
|
|
208
|
+
return this._addActiveItemState(newActiveItem);
|
|
209
|
+
}
|
|
210
|
+
_addActiveItemState(item) {
|
|
211
|
+
if (!item || item.element.disabled || item.element.readonly || item.element.filteredOut)
|
|
212
|
+
return;
|
|
213
|
+
this.clearActiveItem();
|
|
214
|
+
item.element.active = item.active = true;
|
|
215
|
+
this._activeItem = item;
|
|
216
|
+
item.element.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' });
|
|
217
|
+
this._dispatchActiveItemChange({ id: item.element.id });
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
clearFilteredOutItems() {
|
|
221
|
+
this._items.forEach(item => {
|
|
222
|
+
item.element.filteredOut = false;
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
filterOutItems(value) {
|
|
226
|
+
this._items.forEach(item => {
|
|
227
|
+
const isFilteredOut = !item.value.toLowerCase().includes(value.toLowerCase());
|
|
228
|
+
item.element.filteredOut = isFilteredOut;
|
|
229
|
+
if (isFilteredOut && this._activeItem === item)
|
|
230
|
+
this.clearActiveItem();
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Dispatches an event with the active item id, so parent can update aria-activedescendant
|
|
235
|
+
*/
|
|
236
|
+
_dispatchActiveItemChange({ id }) {
|
|
237
|
+
const eventName = 'mu-select-items-active-item-change';
|
|
238
|
+
this.dispatchEvent(new CustomEvent(eventName, { bubbles: true, composed: true, detail: { id } }));
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
*
|
|
242
|
+
*/
|
|
243
|
+
clearActiveItem() {
|
|
244
|
+
if (this._activeItem) {
|
|
245
|
+
this._activeItem.element.active = false;
|
|
246
|
+
this._activeItem = undefined;
|
|
247
|
+
this._dispatchActiveItemChange({ id: undefined });
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
*
|
|
252
|
+
*/
|
|
253
|
+
getMuSelectItemFromEvent(e) {
|
|
254
|
+
const item = e.target instanceof HTMLElement ? e.target.closest('mu-select-item') : null;
|
|
255
|
+
if (item && !(item.disabled || item.readonly || item.filteredOut))
|
|
256
|
+
return this._itemsElementsMap.get(item);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
*
|
|
260
|
+
*/
|
|
261
|
+
_addSelectState(item) {
|
|
262
|
+
if (!item)
|
|
263
|
+
return;
|
|
264
|
+
item.element.selected = item.selected = true;
|
|
265
|
+
this._selectedValues.add(item.value);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
*
|
|
269
|
+
*/
|
|
270
|
+
_removeSelectState(item) {
|
|
271
|
+
if (!item)
|
|
272
|
+
return;
|
|
273
|
+
item.element.selected = item.selected = false;
|
|
274
|
+
this._selectedValues.delete(item.value);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
*
|
|
278
|
+
*/
|
|
279
|
+
_clearSelectState() {
|
|
280
|
+
for (const value of this._selectedValues) {
|
|
281
|
+
const item = this._itemsValuesMap.get(value);
|
|
282
|
+
this._removeSelectState(item);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
_dispatchChangeEvent(detail) {
|
|
286
|
+
const event = new CustomEvent('mu-select-items-change', {
|
|
287
|
+
detail,
|
|
288
|
+
bubbles: true,
|
|
289
|
+
composed: true,
|
|
290
|
+
cancelable: true
|
|
291
|
+
});
|
|
292
|
+
this.dispatchEvent(event);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Modifies the selection state of a specified item.
|
|
296
|
+
* @param type Specifies the operation to perform:
|
|
297
|
+
*
|
|
298
|
+
* `'add'` - Adds the item to the selection.
|
|
299
|
+
*
|
|
300
|
+
* `'add-only'` - Clears previous selections and adds the item.
|
|
301
|
+
*
|
|
302
|
+
* `'remove'` - Removes the item from the selection.
|
|
303
|
+
*
|
|
304
|
+
* `'toggle'` - Toggles the item's selection state.
|
|
305
|
+
*
|
|
306
|
+
* Upon completion, a 'muSelectItemsValueChange' event is dispatched.
|
|
307
|
+
*/
|
|
308
|
+
_changeSelectState(type, _item) {
|
|
309
|
+
const item = typeof _item === 'string' ? this._itemsValuesMap.get(_item) : _item;
|
|
310
|
+
if (!(item) || !item.element.interactable)
|
|
311
|
+
return;
|
|
312
|
+
let operation = type;
|
|
313
|
+
if (operation === 'toggle') {
|
|
314
|
+
operation = this._selectedValues.has(item.value) ? 'remove' : 'add';
|
|
315
|
+
}
|
|
316
|
+
const { isControlled } = this;
|
|
317
|
+
switch (operation) {
|
|
318
|
+
case 'add-only':
|
|
319
|
+
case 'add':
|
|
320
|
+
if (!this.multiple || operation === 'add-only') {
|
|
321
|
+
this._debounceDispatchChangeEvent({ values: [item.value], isCurrentSelection: !isControlled });
|
|
322
|
+
if (!isControlled) {
|
|
323
|
+
this._clearSelectState();
|
|
324
|
+
this._addSelectState(item);
|
|
325
|
+
}
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
this._debounceDispatchChangeEvent({ values: [...this._selectedValues, item.value], isCurrentSelection: !isControlled });
|
|
329
|
+
if (!isControlled) {
|
|
330
|
+
this._addSelectState(item);
|
|
331
|
+
}
|
|
332
|
+
return;
|
|
333
|
+
case 'remove':
|
|
334
|
+
this._debounceDispatchChangeEvent({ values: [...this._selectedValues].filter(value => value !== item.value), isCurrentSelection: !isControlled });
|
|
335
|
+
if (!isControlled) {
|
|
336
|
+
this._removeSelectState(item);
|
|
337
|
+
}
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* This method is called when the 'value' attribute changes or the first time 'defaultValue' is set.
|
|
343
|
+
*
|
|
344
|
+
* It does not fire the 'mu-select-items-change' event but instead fires the 'mu-select-items-change-forced' event.
|
|
345
|
+
*/
|
|
346
|
+
_changeSelectStateFromAttributeValue(value) {
|
|
347
|
+
if (!value)
|
|
348
|
+
return;
|
|
349
|
+
const validValues = (Array.isArray(value) ? value : value.split(',')).filter(value => {
|
|
350
|
+
if (value === '')
|
|
351
|
+
return false;
|
|
352
|
+
const isValid = this._itemsValuesMap.has(value);
|
|
353
|
+
if (!isValid)
|
|
354
|
+
console.warn(`No item found for value (${value}) in select items`, this);
|
|
355
|
+
return isValid;
|
|
356
|
+
});
|
|
357
|
+
if (validValues.length > 1 && !this.multiple) {
|
|
358
|
+
console.warn(`Trying to select ${validValues.length} items in a non-multiple select. Only the first one will be selected. If you want to allow multiple selection, please add the 'multiple' attribute to the element.`, this);
|
|
359
|
+
validValues.splice(0, validValues.length - 1);
|
|
360
|
+
}
|
|
361
|
+
const newSelectedValues = new Set(validValues);
|
|
362
|
+
const removedValues = this._selectedValues.difference(newSelectedValues);
|
|
363
|
+
removedValues.forEach(value => {
|
|
364
|
+
this._removeSelectState(this._itemsValuesMap.get(value));
|
|
365
|
+
});
|
|
366
|
+
validValues.forEach(value => {
|
|
367
|
+
const item = this._itemsValuesMap.get(value);
|
|
368
|
+
this._addSelectState(item);
|
|
369
|
+
});
|
|
370
|
+
const eventName = 'mu-select-items-change-forced';
|
|
371
|
+
this.dispatchEvent(new CustomEvent(eventName, { bubbles: true, composed: true, detail: { values: validValues } }));
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* This method handles open state changes
|
|
375
|
+
*/
|
|
376
|
+
_openChangeHandler() {
|
|
377
|
+
this._calculateSizes();
|
|
378
|
+
if (!this.opened && !this.noClearActiveOnClose) {
|
|
379
|
+
this.clearActiveItem();
|
|
380
|
+
}
|
|
381
|
+
switch (this.openMode) {
|
|
382
|
+
case 'static':
|
|
383
|
+
break;
|
|
384
|
+
case 'no-scroll':
|
|
385
|
+
this.opened ? disableElementScroll() : enableElementScroll();
|
|
386
|
+
break;
|
|
387
|
+
case 'dynamic':
|
|
388
|
+
this.opened ? window.addEventListener('scroll', this._calculateSizes) : window.removeEventListener('scroll', this._calculateSizes);
|
|
389
|
+
break;
|
|
390
|
+
default:
|
|
391
|
+
this.openMode;
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
if (this._resizeObserver) {
|
|
395
|
+
this._resizeObserver[this.opened ? 'observe' : 'unobserve'](this.parentElement);
|
|
396
|
+
this._resizeObserver[this.opened ? 'observe' : 'unobserve'](document.body);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
async getUpdateComplete() {
|
|
400
|
+
const result = await super.getUpdateComplete();
|
|
401
|
+
await this._isReady.promise;
|
|
402
|
+
return result;
|
|
403
|
+
}
|
|
404
|
+
async firstUpdated(_changedProperties) {
|
|
405
|
+
await this._isReady.promise;
|
|
406
|
+
if (this.defaultValue !== undefined) {
|
|
407
|
+
if (this.value) {
|
|
408
|
+
console.warn(`Both 'value' and 'defaultValue' attributes are set. 'defaultValue' will be ignored.`, this);
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
this._changeSelectStateFromAttributeValue(this.defaultValue);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
async updated(changedProperties) {
|
|
416
|
+
await this.updateComplete;
|
|
417
|
+
if (changedProperties.has('multiple')) {
|
|
418
|
+
this.setAttribute('aria-multiselectable', this.multiple ? 'true' : 'false');
|
|
419
|
+
}
|
|
420
|
+
if (changedProperties.has('disabled')) {
|
|
421
|
+
if (this.disabled) {
|
|
422
|
+
this.clearActiveItem();
|
|
423
|
+
this.ariaDisabled = 'true';
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
this.ariaDisabled = 'false';
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (changedProperties.has('opened')) {
|
|
430
|
+
this._openChangeHandler();
|
|
431
|
+
}
|
|
432
|
+
if (changedProperties.has('value')) {
|
|
433
|
+
this._changeSelectStateFromAttributeValue(this.value);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
render() {
|
|
437
|
+
return html `
|
|
438
|
+
<div id='container' part='container'>
|
|
439
|
+
<slot id='items-slot' @slotchange=${this._slotChangeHandler}></slot>
|
|
440
|
+
</div>
|
|
441
|
+
`;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
MuSelectItems.styles = [MUElement.cssBase, css `
|
|
445
|
+
#container {
|
|
446
|
+
--select-items-background-color: var(--mu-select-items-background-color, var(--mu-color-800));
|
|
447
|
+
--select-items-border-color: var(--mu-select-items-border-color, var(--mu-color-500));
|
|
448
|
+
--items-margin: var(--mu-base-rem);
|
|
449
|
+
position: var(--items-position);
|
|
450
|
+
top: var(--items-top);
|
|
451
|
+
bottom: var(--items-bottom);
|
|
452
|
+
left: var(--items-left);
|
|
453
|
+
right: var(--items-right);
|
|
454
|
+
width: var(--items-width);
|
|
455
|
+
margin-block: var(--items-margin);
|
|
456
|
+
transform-origin: var(--items-transform-origin);
|
|
457
|
+
overflow: auto;
|
|
458
|
+
max-height: min(calc(var(--items-max-height, 75vh) - (var(--items-margin) * 2)), 75vh);
|
|
459
|
+
scrollbar-width: thin;
|
|
460
|
+
display: grid;
|
|
461
|
+
gap: calc(var(--mu-base-rem) * 1);
|
|
462
|
+
padding: calc(var(--mu-base-rem));
|
|
463
|
+
background-color: var(--select-items-background-color);
|
|
464
|
+
transition-duration: .2s;
|
|
465
|
+
transition-timing-function: ease-in-out;
|
|
466
|
+
transition-property: opacity scale translate;
|
|
467
|
+
border-radius: calc(var(--mu-base-rem) * 1.5);
|
|
468
|
+
border: 1px solid var(--select-items-border-color);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
:host([opened][position='fixed']) #container {
|
|
472
|
+
transition-property: opacity;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
:host(:not([opened])) #container {
|
|
476
|
+
visibility: hidden;
|
|
477
|
+
opacity: 0;
|
|
478
|
+
scale: 1 .25;
|
|
479
|
+
translate: 0 -10%;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
@media (prefers-color-scheme: light) {
|
|
483
|
+
#container {
|
|
484
|
+
--select-items-background-color: var(--mu-select-items-background-color, var(--mu-color-100));
|
|
485
|
+
--select-items-border-color: var(--mu-select-items-border-color, var(--mu-color-300));
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
`];
|
|
489
|
+
MuSelectItems.eventAction = new EventAction({
|
|
490
|
+
currTargetSelector: 'mu-select-item',
|
|
491
|
+
getEventAttributeName(eventName) {
|
|
492
|
+
return `data-items-${eventName}`;
|
|
493
|
+
},
|
|
494
|
+
switches: {
|
|
495
|
+
opened({ event }) {
|
|
496
|
+
return event.currentTarget.opened;
|
|
497
|
+
},
|
|
498
|
+
closed({ event }) {
|
|
499
|
+
return !event.currentTarget.opened;
|
|
500
|
+
}
|
|
501
|
+
},
|
|
502
|
+
actions: {
|
|
503
|
+
'toggle-select'(data) {
|
|
504
|
+
const items = data.event.currentTarget;
|
|
505
|
+
if (!items.interactable)
|
|
506
|
+
return;
|
|
507
|
+
const item = items._itemsValuesMap.get(data.actionParam);
|
|
508
|
+
items._changeSelectState('toggle', item);
|
|
509
|
+
},
|
|
510
|
+
'select'(data) {
|
|
511
|
+
const items = data.event.currentTarget;
|
|
512
|
+
if (!items.interactable)
|
|
513
|
+
return;
|
|
514
|
+
const item = items._itemsValuesMap.get(data.actionParam);
|
|
515
|
+
items._changeSelectState('add', item);
|
|
516
|
+
},
|
|
517
|
+
'unselect'(data) {
|
|
518
|
+
const items = data.event.currentTarget;
|
|
519
|
+
if (!items.interactable)
|
|
520
|
+
return;
|
|
521
|
+
const item = items._itemsValuesMap.get(data.actionParam);
|
|
522
|
+
items._changeSelectState('remove', item);
|
|
523
|
+
},
|
|
524
|
+
'set-active'(data) {
|
|
525
|
+
const items = data.event.currentTarget;
|
|
526
|
+
if (!items.interactable)
|
|
527
|
+
return;
|
|
528
|
+
const item = items._itemsValuesMap.get(data.actionParam);
|
|
529
|
+
items._addActiveItemState(item);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
__decorate([
|
|
534
|
+
property({
|
|
535
|
+
reflect: true, type: Boolean,
|
|
536
|
+
})
|
|
537
|
+
], MuSelectItems.prototype, "opened", void 0);
|
|
538
|
+
__decorate([
|
|
539
|
+
staticProperty({
|
|
540
|
+
converter: Boolean,
|
|
541
|
+
})
|
|
542
|
+
], MuSelectItems.prototype, "multiple", void 0);
|
|
543
|
+
__decorate([
|
|
544
|
+
property({
|
|
545
|
+
reflect: true, type: Array,
|
|
546
|
+
converter: {
|
|
547
|
+
toAttribute(value, type) {
|
|
548
|
+
return Array.isArray(value) ? value.join(',') : value;
|
|
549
|
+
},
|
|
550
|
+
fromAttribute(value, type) {
|
|
551
|
+
return value?.split(',');
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
})
|
|
555
|
+
], MuSelectItems.prototype, "value", void 0);
|
|
556
|
+
__decorate([
|
|
557
|
+
staticProperty({ converter: Boolean })
|
|
558
|
+
], MuSelectItems.prototype, "noClearActiveOnClose", void 0);
|
|
559
|
+
__decorate([
|
|
560
|
+
staticProperty()
|
|
561
|
+
], MuSelectItems.prototype, "defaultValue", void 0);
|
|
562
|
+
__decorate([
|
|
563
|
+
staticProperty()
|
|
564
|
+
], MuSelectItems.prototype, "position", void 0);
|
|
565
|
+
__decorate([
|
|
566
|
+
staticProperty({ attribute: 'open-mode' })
|
|
567
|
+
], MuSelectItems.prototype, "openMode", void 0);
|
|
568
|
+
MuSelectItems.register("mu-select-items");
|
|
569
|
+
|
|
570
|
+
export { MuSelectItems };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { CSSResultGroup } from 'lit';
|
|
2
|
+
import { MUElement } from './mu-element.js';
|
|
3
|
+
import '@mustib/utils/browser';
|
|
4
|
+
|
|
5
|
+
declare const types: readonly ["label", "value", "autocomplete", "template"];
|
|
6
|
+
/**
|
|
7
|
+
* Use this element to define custom markup for the label and value.
|
|
8
|
+
*
|
|
9
|
+
* To inject the selected value, add the `data-is="content"` attribute to one of its children.
|
|
10
|
+
* The textContent of the element with this attribute will be replaced with the selected value.
|
|
11
|
+
* If there is no element with this attribute, the textContent of this element itself will be replaced.
|
|
12
|
+
*
|
|
13
|
+
* You also need to set the `type` attribute to either `"label"` or `"value"` so the parent label knows which element to update.
|
|
14
|
+
*/
|
|
15
|
+
declare class MuSelectLabelContent extends MUElement {
|
|
16
|
+
static styles: CSSResultGroup;
|
|
17
|
+
/**
|
|
18
|
+
* Generate template markup for the template type.
|
|
19
|
+
*/
|
|
20
|
+
static generateTemplate(instance: MuSelectLabelContent): any;
|
|
21
|
+
eventActionData: undefined;
|
|
22
|
+
_addEventActionAttributes: undefined;
|
|
23
|
+
type: typeof types[number];
|
|
24
|
+
active: boolean;
|
|
25
|
+
contentEl?: HTMLElement | null;
|
|
26
|
+
activeTemplateValue?: string;
|
|
27
|
+
_value: string[];
|
|
28
|
+
setValue(value: string[]): Promise<void>;
|
|
29
|
+
connectedCallback(): void;
|
|
30
|
+
protected render(): unknown;
|
|
31
|
+
}
|
|
32
|
+
declare global {
|
|
33
|
+
interface HTMLElementTagNameMap {
|
|
34
|
+
'mu-select-label-content': MuSelectLabelContent;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { MuSelectLabelContent };
|