@statistikzh/leu 0.25.0 → 0.27.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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +28 -0
- package/CONTRIBUTING.md +19 -8
- package/dist/{Accordion-CDNyrB8d.js → Accordion-DLsqXcK8.js} +1 -1
- package/dist/Accordion.js +2 -2
- package/dist/{Button-EdS9xr2J.js → Button-BSyDL_cV.js} +57 -17
- package/dist/{Button-DSGPIcjm.d.ts → Button-BgNUxmo_.d.ts} +6 -0
- package/dist/Button.d.ts +1 -1
- package/dist/Button.js +5 -4
- package/dist/{ButtonGroup-BQqf8o_d.js → ButtonGroup-BmSvl-Oc.js} +2 -2
- package/dist/ButtonGroup.js +6 -5
- package/dist/{ChartWrapper-LiNHTNRw.js → ChartWrapper-CvDvQsd5.js} +3 -3
- package/dist/ChartWrapper.d.ts +2 -2
- package/dist/ChartWrapper.js +3 -3
- package/dist/{Checkbox-BtDWmPab.js → Checkbox-Cl_X6gBJ.js} +3 -3
- package/dist/Checkbox.js +4 -4
- package/dist/{CheckboxGroup-C8MbwW9u.js → CheckboxGroup-BKhOmZYX.js} +2 -2
- package/dist/CheckboxGroup.js +5 -5
- package/dist/{Chip-Ch09jjYi.js → Chip-McVP3N_x.js} +1 -1
- package/dist/Chip.js +2 -2
- package/dist/{ChipGroup-PvqVW-tm.js → ChipGroup-DUGavZeU.js} +1 -1
- package/dist/ChipGroup.js +3 -3
- package/dist/ChipLink.js +2 -2
- package/dist/ChipRemovable.js +3 -3
- package/dist/ChipSelectable.js +2 -2
- package/dist/{Dialog-CV1JTkCn.js → Dialog-BlDd4T2u.js} +3 -3
- package/dist/Dialog.d.ts +1 -1
- package/dist/Dialog.js +3 -3
- package/dist/{Dropdown-DpFdFbA1.js → Dropdown-BLxSIe6p.js} +6 -6
- package/dist/Dropdown.d.ts +2 -2
- package/dist/Dropdown.js +9 -8
- package/dist/{FileInput-5apX17JT.js → FileInput-DntYrpZ-.js} +23 -8
- package/dist/FileInput.d.ts +12 -1
- package/dist/FileInput.js +7 -6
- package/dist/{Icon-DhAvH0XM.js → Icon-CbZXpyHU.js} +1 -1
- package/dist/Icon.js +2 -2
- package/dist/{Input-D2THgo7c.d.ts → Input-CeaAOB4p.d.ts} +6 -2
- package/dist/{Input-CnEz-2dK.js → Input-DBXX7ev8.js} +33 -12
- package/dist/Input.d.ts +1 -1
- package/dist/Input.js +4 -4
- package/dist/{LeuElement-B7NJzWwP.js → LeuElement-k4RjIeoG.js} +1 -1
- package/dist/{Menu-DpiheIPk.js → Menu-Cu8eIF1T.js} +2 -2
- package/dist/Menu.js +4 -4
- package/dist/{MenuItem-CZTqGg5R.js → MenuItem-Cs3KFhJm.js} +2 -2
- package/dist/MenuItem.js +3 -3
- package/dist/{Message-J4Kj7yHE.js → Message-C6Zlk_2p.js} +3 -3
- package/dist/Message.js +3 -3
- package/dist/{Pagination-CWqgusWZ.js → Pagination-CB2eVlXk.js} +4 -4
- package/dist/{Pagination-Be8TcBoC.d.ts → Pagination-CqkHh-Vd.d.ts} +1 -1
- package/dist/Pagination.d.ts +1 -1
- package/dist/Pagination.js +7 -6
- package/dist/{Placeholder-DMN6sMbp.js → Placeholder-DHMexMhK.js} +1 -1
- package/dist/Placeholder.js +2 -2
- package/dist/{Popup-JQjuj26v.js → Popup-8jhVy8gB.js} +1 -1
- package/dist/Popup.js +2 -2
- package/dist/{ProgressBar-CzN3fqiH.js → ProgressBar-CG0_lHfS.js} +1 -1
- package/dist/ProgressBar.js +2 -2
- package/dist/{Radio-CX8aCsff.js → Radio-DG3xqP3s.js} +1 -1
- package/dist/Radio.js +2 -2
- package/dist/{RadioGroup-CgEWQnC4.js → RadioGroup-BKCp9ICX.js} +2 -2
- package/dist/RadioGroup.js +3 -3
- package/dist/{Range-DoW_ZdKm.js → Range-7LrESv4K.js} +1 -1
- package/dist/Range.js +2 -2
- package/dist/{ScrollTop-DxChetWq.js → ScrollTop-CJJsfniA.js} +20 -20
- package/dist/ScrollTop.d.ts +6 -6
- package/dist/ScrollTop.js +6 -5
- package/dist/{Select-BCx79gOH.js → Select-CxEDXIBn.js} +154 -134
- package/dist/Select.d.ts +75 -73
- package/dist/Select.js +10 -9
- package/dist/{Spinner-DJR4gv3Y.js → Spinner-VhKfzI3Q.js} +1 -1
- package/dist/Spinner.d.ts +1 -1
- package/dist/Spinner.js +2 -2
- package/dist/{Table-DZz1ic3j.js → Table-rg_JCtsA.js} +3 -3
- package/dist/Table.d.ts +1 -1
- package/dist/Table.js +8 -7
- package/dist/{Tag-DsZS_8pl.js → Tag-BROUaDAZ.js} +1 -1
- package/dist/Tag.js +2 -2
- package/dist/{VisuallyHidden-BkllVjlz.js → VisuallyHidden-Co_txzxB.js} +1 -1
- package/dist/VisuallyHidden.js +2 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +31 -31
- package/dist/leu-accordion.js +2 -2
- package/dist/leu-button-group.js +6 -5
- package/dist/leu-button.d.ts +1 -1
- package/dist/leu-button.js +5 -4
- package/dist/leu-chart-wrapper.js +3 -3
- package/dist/leu-checkbox-group.js +5 -5
- package/dist/leu-checkbox.js +4 -4
- package/dist/leu-chip-group.js +3 -3
- package/dist/leu-chip-link.js +2 -2
- package/dist/leu-chip-removable.js +3 -3
- package/dist/leu-chip-selectable.js +2 -2
- package/dist/leu-dialog.js +3 -3
- package/dist/leu-dropdown.js +9 -8
- package/dist/leu-file-input.js +7 -6
- package/dist/leu-icon.js +2 -2
- package/dist/leu-input.d.ts +1 -1
- package/dist/leu-input.js +4 -4
- package/dist/leu-menu-item.js +3 -3
- package/dist/leu-menu.js +4 -4
- package/dist/leu-message.js +3 -3
- package/dist/leu-pagination.d.ts +1 -1
- package/dist/leu-pagination.js +7 -6
- package/dist/leu-placeholder.js +2 -2
- package/dist/leu-popup.js +2 -2
- package/dist/leu-progress-bar.js +2 -2
- package/dist/leu-radio-group.js +3 -3
- package/dist/leu-radio.js +2 -2
- package/dist/leu-range.js +2 -2
- package/dist/leu-scroll-top.js +6 -5
- package/dist/leu-select.js +10 -9
- package/dist/leu-spinner.d.ts +1 -1
- package/dist/leu-spinner.js +2 -2
- package/dist/leu-table.js +8 -7
- package/dist/leu-tag.js +2 -2
- package/dist/leu-visually-hidden.js +2 -2
- package/dist/vscode.html-custom-data.json +19 -27
- package/dist/vue/index.d.ts +18 -24
- package/dist/web-types.json +51 -60
- package/package.json +1 -1
- package/src/components/button/Button.ts +15 -3
- package/src/components/button/button.css +37 -9
- package/src/components/button/stories/button.stories.ts +23 -0
- package/src/components/button/test/button.test.ts +30 -3
- package/src/components/file-input/FileInput.ts +24 -5
- package/src/components/input/Input.ts +43 -8
- package/src/components/input/test/input.test.ts +106 -1
- package/src/components/scroll-top/ScrollTop.ts +18 -16
- package/src/components/select/Select.ts +198 -124
- package/src/components/select/select.css +4 -0
- package/src/components/select/stories/select.stories.ts +10 -0
- package/src/components/select/test/select.test.ts +440 -35
- /package/dist/{FormAssociatedMixin-BbFlza53.js → FormAssociatedMixin-DLPvFtbT.js} +0 -0
- /package/dist/{Spinner-CMo_o6Fy.d.ts → Spinner-CrM1enM0.d.ts} +0 -0
- /package/dist/{hasSlotController-DjdfnOQp.js → hasSlotController-DSBCVzPD.js} +0 -0
- /package/dist/{hasSlotController-BLtZurRh.d.ts → hasSlotController-DWPyZ52b.d.ts} +0 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { html, nothing, PropertyValues } from "lit"
|
|
2
2
|
import { classMap } from "lit/directives/class-map.js"
|
|
3
3
|
import { createRef, ref } from "lit/directives/ref.js"
|
|
4
|
+
import { property, state } from "lit/decorators.js"
|
|
4
5
|
|
|
5
6
|
import { ifDefined } from "lit/directives/if-defined.js"
|
|
6
7
|
import { LeuElement } from "../../lib/LeuElement.js"
|
|
7
8
|
import { HasSlotController } from "../../lib/hasSlotController.js"
|
|
9
|
+
import { FormAssociatedMixin } from "../../lib/mixins/FormAssociatedMixin.js"
|
|
8
10
|
|
|
9
11
|
import { LeuButton } from "../button/Button.js"
|
|
10
12
|
import { LeuMenu } from "../menu/Menu.js"
|
|
@@ -19,17 +21,9 @@ import styles from "./select.css?inline"
|
|
|
19
21
|
* @tagname leu-select
|
|
20
22
|
* @slot before - Optional content the appears before the option list
|
|
21
23
|
* @slot after - Optional content the appears after the option list
|
|
22
|
-
* @property {string} name - Reflects to the name attribute of the hidden input field that would be used in a form
|
|
23
|
-
* @property {boolean} open - The expanded state of the popup
|
|
24
|
-
* @property {string} label - The label of the select
|
|
25
|
-
* @property {array} value - List of selected values. If they're set from outside the component, the select element tries to find all the options with the given values and selects them.
|
|
26
|
-
* @property {boolean} clearable - Show a clearable button to reset the value
|
|
27
|
-
* @property {boolean} disabled - If the select should be disabled
|
|
28
|
-
* @property {boolean} filterable - Show an input field to filter the options inside the popup
|
|
29
|
-
* @property {boolean} multiple - Allow multiple selections
|
|
30
24
|
* @attribute {string} value - The selected values separated by commas.
|
|
31
25
|
*/
|
|
32
|
-
export class LeuSelect extends LeuElement {
|
|
26
|
+
export class LeuSelect extends FormAssociatedMixin(LeuElement) {
|
|
33
27
|
static dependencies = {
|
|
34
28
|
"leu-button": LeuButton,
|
|
35
29
|
"leu-menu": LeuMenu,
|
|
@@ -41,32 +35,96 @@ export class LeuSelect extends LeuElement {
|
|
|
41
35
|
|
|
42
36
|
static styles = [LeuElement.styles, styles]
|
|
43
37
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
38
|
+
/**
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
static shadowRootOptions = {
|
|
42
|
+
...LeuElement.shadowRootOptions,
|
|
43
|
+
delegatesFocus: true,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The label of the select
|
|
48
|
+
*/
|
|
49
|
+
@property({ type: String, reflect: true })
|
|
50
|
+
label: string = ""
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The default value of the select. Corresponds to the `value` HTML attribute.
|
|
54
|
+
*/
|
|
55
|
+
@property({
|
|
56
|
+
reflect: true,
|
|
57
|
+
attribute: "value",
|
|
58
|
+
converter: {
|
|
59
|
+
fromAttribute(value) {
|
|
60
|
+
if (value) {
|
|
61
|
+
return value.split(",").map((v) => v.trim())
|
|
62
|
+
}
|
|
63
|
+
return []
|
|
59
64
|
},
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
toAttribute(value: Array<string>) {
|
|
66
|
+
return value.length > 0 ? value.join(",") : null
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
defaultValue: Array<string> = []
|
|
71
|
+
|
|
72
|
+
/** @internal */
|
|
73
|
+
protected _value: Array<string> | undefined
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* List of selected values. If they're set from outside the component, the select element
|
|
77
|
+
* finds all the options that match the given values and selects them.
|
|
78
|
+
*/
|
|
79
|
+
@property({ type: Array, attribute: false })
|
|
80
|
+
set value(value: Array<string>) {
|
|
81
|
+
/**
|
|
82
|
+
* @todo Check if all of the value items are actually present in the options
|
|
83
|
+
*/
|
|
84
|
+
this._value = value
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get value(): Array<string> {
|
|
88
|
+
return this._value ?? this.defaultValue
|
|
68
89
|
}
|
|
69
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Show a clearable button to reset the value
|
|
93
|
+
*/
|
|
94
|
+
@property({ type: Boolean, reflect: true })
|
|
95
|
+
clearable: boolean = false
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Show an input field to filter the options inside the popup
|
|
99
|
+
*/
|
|
100
|
+
@property({ type: Boolean, reflect: true })
|
|
101
|
+
filterable: boolean = false
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Allow multiple selections
|
|
105
|
+
*/
|
|
106
|
+
@property({ type: Boolean, reflect: true })
|
|
107
|
+
multiple: boolean = false
|
|
108
|
+
|
|
109
|
+
/** Marks the input element as required */
|
|
110
|
+
@property({ type: Boolean, reflect: true })
|
|
111
|
+
required: boolean = false
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The expanded state of the popup
|
|
115
|
+
*/
|
|
116
|
+
@state()
|
|
117
|
+
protected open: boolean = false
|
|
118
|
+
|
|
119
|
+
@state()
|
|
120
|
+
protected _optionFilter: string = ""
|
|
121
|
+
|
|
122
|
+
@state()
|
|
123
|
+
protected _hasFilterResults: boolean = true
|
|
124
|
+
|
|
125
|
+
@state()
|
|
126
|
+
protected _displayValue: string = ""
|
|
127
|
+
|
|
70
128
|
static getOptionLabel(option) {
|
|
71
129
|
if (typeof option === "object" && option !== null) {
|
|
72
130
|
return option.label
|
|
@@ -74,48 +132,72 @@ export class LeuSelect extends LeuElement {
|
|
|
74
132
|
return option
|
|
75
133
|
}
|
|
76
134
|
|
|
135
|
+
/** @internal */
|
|
136
|
+
protected _deferedChangeEvent = false
|
|
137
|
+
|
|
138
|
+
/** @internal */
|
|
139
|
+
protected _optionFilterRef = createRef<LeuInput>()
|
|
140
|
+
|
|
141
|
+
/** @internal */
|
|
142
|
+
protected _toggleButtonRef = createRef<HTMLButtonElement>()
|
|
143
|
+
|
|
144
|
+
/** @internal */
|
|
145
|
+
protected _menuRef = createRef<LeuMenu>()
|
|
146
|
+
|
|
77
147
|
/**
|
|
78
148
|
* @internal
|
|
79
149
|
*/
|
|
80
150
|
hasSlotController = new HasSlotController(this, ["before", "after"])
|
|
81
151
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
this.disabled
|
|
86
|
-
|
|
87
|
-
this.multiple
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
/** @internal */
|
|
95
|
-
this._optionFilter = ""
|
|
96
|
-
|
|
97
|
-
/** @internal */
|
|
98
|
-
this._hasFilterResults = true
|
|
152
|
+
protected setFormValue(): void {
|
|
153
|
+
const isEmpty = this.value.length === 0 || !this.value.some((v) => v !== "") // At least one value is not an empty string
|
|
154
|
+
|
|
155
|
+
if (isEmpty || this.disabled) {
|
|
156
|
+
this.internals.setFormValue(null)
|
|
157
|
+
} else if (this.multiple) {
|
|
158
|
+
const formData = new FormData()
|
|
159
|
+
this.value.forEach((v) => formData.append(this.name ?? "", v))
|
|
160
|
+
this.internals.setFormValue(formData)
|
|
161
|
+
} else {
|
|
162
|
+
this.internals.setFormValue(this.value[0])
|
|
163
|
+
}
|
|
99
164
|
|
|
100
|
-
|
|
101
|
-
|
|
165
|
+
if (this.required && isEmpty) {
|
|
166
|
+
this.internals.setValidity(
|
|
167
|
+
{ valueMissing: true },
|
|
168
|
+
"Bitte wählen Sie eine Option aus.",
|
|
169
|
+
)
|
|
170
|
+
} else {
|
|
171
|
+
this.internals.setValidity({})
|
|
172
|
+
}
|
|
173
|
+
}
|
|
102
174
|
|
|
103
|
-
|
|
175
|
+
public formResetCallback() {
|
|
176
|
+
super.formResetCallback()
|
|
177
|
+
this.value = this.defaultValue
|
|
104
178
|
this._displayValue = ""
|
|
179
|
+
}
|
|
105
180
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
*/
|
|
109
|
-
this._optionFilterRef = createRef()
|
|
110
|
-
/**
|
|
111
|
-
* @type {import("lit/directives/ref").Ref<HTMLButtonElement>}
|
|
112
|
-
*/
|
|
113
|
-
this._toggleButtonRef = createRef()
|
|
181
|
+
protected willUpdate(changedProperties: PropertyValues<this>) {
|
|
182
|
+
super.willUpdate(changedProperties)
|
|
114
183
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
184
|
+
if (
|
|
185
|
+
changedProperties.has("defaultValue") &&
|
|
186
|
+
!changedProperties.has("value") &&
|
|
187
|
+
!this.hasInteracted
|
|
188
|
+
) {
|
|
189
|
+
this.value = this.defaultValue
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (
|
|
193
|
+
changedProperties.has("value") ||
|
|
194
|
+
changedProperties.has("defaultValue") ||
|
|
195
|
+
changedProperties.has("name") ||
|
|
196
|
+
changedProperties.has("disabled") ||
|
|
197
|
+
changedProperties.has("required")
|
|
198
|
+
) {
|
|
199
|
+
this.setFormValue()
|
|
200
|
+
}
|
|
119
201
|
}
|
|
120
202
|
|
|
121
203
|
connectedCallback() {
|
|
@@ -156,13 +238,16 @@ export class LeuSelect extends LeuElement {
|
|
|
156
238
|
}
|
|
157
239
|
}
|
|
158
240
|
|
|
241
|
+
public click() {
|
|
242
|
+
this._toggleButtonRef.value?.click()
|
|
243
|
+
}
|
|
244
|
+
|
|
159
245
|
/**
|
|
160
246
|
* Apply the current state to the menu items.
|
|
161
247
|
* - Set the active property when the value property has changed.
|
|
162
248
|
* - Hide menu items that do not match the filter.
|
|
163
249
|
*/
|
|
164
250
|
async _updateMenuItems(changed) {
|
|
165
|
-
/** @type {LeuMenu} */
|
|
166
251
|
const menu = this._menuRef.value
|
|
167
252
|
|
|
168
253
|
await menu.updateComplete
|
|
@@ -221,9 +306,8 @@ export class LeuSelect extends LeuElement {
|
|
|
221
306
|
/**
|
|
222
307
|
* Handles clicks outside of the component to close the dropdown.
|
|
223
308
|
* @internal
|
|
224
|
-
* @param {MouseEvent} event
|
|
225
309
|
*/
|
|
226
|
-
_handleDocumentClick = (event) => {
|
|
310
|
+
_handleDocumentClick = (event: MouseEvent) => {
|
|
227
311
|
if (!event.composedPath().includes(this) && this.open) {
|
|
228
312
|
this._closeDropdown()
|
|
229
313
|
}
|
|
@@ -231,9 +315,8 @@ export class LeuSelect extends LeuElement {
|
|
|
231
315
|
|
|
232
316
|
/**
|
|
233
317
|
* @internal
|
|
234
|
-
* @param {KeyboardEvent} event
|
|
235
318
|
*/
|
|
236
|
-
_handleKeyDown = (event) => {
|
|
319
|
+
_handleKeyDown = (event: KeyboardEvent) => {
|
|
237
320
|
if (event.key === "Escape") {
|
|
238
321
|
this._closeDropdown()
|
|
239
322
|
}
|
|
@@ -241,9 +324,8 @@ export class LeuSelect extends LeuElement {
|
|
|
241
324
|
|
|
242
325
|
/**
|
|
243
326
|
* @internal
|
|
244
|
-
* @param {KeyboardEvent} event
|
|
245
327
|
*/
|
|
246
|
-
async _handleToggleKeyDown(event) {
|
|
328
|
+
async _handleToggleKeyDown(event: KeyboardEvent) {
|
|
247
329
|
if (["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
|
|
248
330
|
event.preventDefault()
|
|
249
331
|
|
|
@@ -262,9 +344,8 @@ export class LeuSelect extends LeuElement {
|
|
|
262
344
|
|
|
263
345
|
/**
|
|
264
346
|
* @internal
|
|
265
|
-
* @param {KeyboardEvent} event
|
|
266
347
|
*/
|
|
267
|
-
_handleFilterInputKeyDown(event) {
|
|
348
|
+
_handleFilterInputKeyDown(event: KeyboardEvent) {
|
|
268
349
|
if (event.key === "ArrowDown") {
|
|
269
350
|
this._menuRef.value.focusItem(0)
|
|
270
351
|
} else if (event.key === "ArrowUp") {
|
|
@@ -274,7 +355,6 @@ export class LeuSelect extends LeuElement {
|
|
|
274
355
|
|
|
275
356
|
/**
|
|
276
357
|
* Determines the value or label that should be displayed inside the toggle button.
|
|
277
|
-
* @returns {String | nothing}
|
|
278
358
|
*/
|
|
279
359
|
_getDisplayValue() {
|
|
280
360
|
if (this.multiple) {
|
|
@@ -300,9 +380,10 @@ export class LeuSelect extends LeuElement {
|
|
|
300
380
|
this.dispatchEvent(changeevent)
|
|
301
381
|
}
|
|
302
382
|
|
|
303
|
-
_clearValue(event) {
|
|
383
|
+
_clearValue(event: MouseEvent) {
|
|
304
384
|
if (!this.disabled) {
|
|
305
385
|
event.stopPropagation()
|
|
386
|
+
this.hasInteracted = true
|
|
306
387
|
this.value = []
|
|
307
388
|
}
|
|
308
389
|
|
|
@@ -325,30 +406,29 @@ export class LeuSelect extends LeuElement {
|
|
|
325
406
|
}
|
|
326
407
|
}
|
|
327
408
|
|
|
328
|
-
_handleFilterInput(event) {
|
|
329
|
-
this._optionFilter = event.target.value
|
|
409
|
+
_handleFilterInput(event: InputEvent) {
|
|
410
|
+
this._optionFilter = (event.target as HTMLInputElement).value
|
|
330
411
|
}
|
|
331
412
|
|
|
332
413
|
/**
|
|
333
414
|
* Checks if the given value is selected.
|
|
334
|
-
* @param {String} menuItemValue
|
|
335
|
-
* @returns {Boolean}
|
|
336
415
|
*/
|
|
337
|
-
_isSelected(menuItemValue) {
|
|
416
|
+
_isSelected(menuItemValue: string) {
|
|
338
417
|
return this.value.includes(menuItemValue)
|
|
339
418
|
}
|
|
340
419
|
|
|
341
|
-
_handleMenuItemClick(event) {
|
|
420
|
+
_handleMenuItemClick(event: MouseEvent) {
|
|
342
421
|
if (!(event.target instanceof LeuMenuItem) || event.target.disabled) {
|
|
343
422
|
return
|
|
344
423
|
}
|
|
345
424
|
|
|
346
|
-
/** @type {LeuMenuItem} */
|
|
347
425
|
const menuItem = event.target
|
|
348
426
|
|
|
349
427
|
const value = menuItem.getValue()
|
|
350
428
|
const isSelected = this._isSelected(value)
|
|
351
429
|
|
|
430
|
+
this.hasInteracted = true
|
|
431
|
+
|
|
352
432
|
if (this.multiple) {
|
|
353
433
|
this.value = isSelected
|
|
354
434
|
? this.value.filter((v) => v !== value)
|
|
@@ -449,49 +529,43 @@ export class LeuSelect extends LeuElement {
|
|
|
449
529
|
"select--has-after": this.hasSlotController.test("after"),
|
|
450
530
|
}
|
|
451
531
|
|
|
452
|
-
/*
|
|
453
|
-
* We use the click event listener with the event delegation pattern
|
|
454
|
-
* so this is not a violation of the rule.
|
|
455
|
-
*/
|
|
456
|
-
|
|
457
532
|
return html`<div
|
|
458
|
-
|
|
459
|
-
|
|
533
|
+
class=${classMap(selectClasses)}
|
|
534
|
+
@keydown=${this._handleKeyDown}
|
|
535
|
+
>
|
|
536
|
+
<leu-popup
|
|
537
|
+
?active=${this.open}
|
|
538
|
+
placement="bottom-start"
|
|
539
|
+
flip
|
|
540
|
+
matchSize="width"
|
|
541
|
+
autoSize="height"
|
|
542
|
+
autoSizePadding="8"
|
|
460
543
|
>
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
: html` <p class="filter-message-empty" aria-live="polite">
|
|
488
|
-
Keine Resultate
|
|
489
|
-
</p>`}
|
|
490
|
-
${this._renderApplyButton()}
|
|
491
|
-
<slot name="after" class="after"></slot>
|
|
492
|
-
</div>
|
|
493
|
-
</leu-popup>
|
|
494
|
-
</div>
|
|
495
|
-
<input type="hidden" name=${this.name} .value=${this.value.join(",")} />`
|
|
544
|
+
${this._renderToggleButton()}
|
|
545
|
+
<div id="select-popup" class="select-menu-container">
|
|
546
|
+
<slot name="before" class="before"></slot>
|
|
547
|
+
${this._renderFilterInput()}
|
|
548
|
+
<leu-menu
|
|
549
|
+
ref=${ref(this._menuRef)}
|
|
550
|
+
role="listbox"
|
|
551
|
+
aria-multiselectable=${ifDefined(
|
|
552
|
+
this.multiple ? "true" : undefined,
|
|
553
|
+
)}
|
|
554
|
+
class="menu"
|
|
555
|
+
@click=${this._handleMenuItemClick}
|
|
556
|
+
aria-labelledby="select-label"
|
|
557
|
+
>
|
|
558
|
+
<slot @slotchange=${this._handleItemSlotChange}> </slot>
|
|
559
|
+
</leu-menu>
|
|
560
|
+
${this._hasFilterResults || this._optionFilter === ""
|
|
561
|
+
? nothing
|
|
562
|
+
: html` <p class="filter-message-empty" aria-live="polite">
|
|
563
|
+
Keine Resultate
|
|
564
|
+
</p>`}
|
|
565
|
+
${this._renderApplyButton()}
|
|
566
|
+
<slot name="after" class="after"></slot>
|
|
567
|
+
</div>
|
|
568
|
+
</leu-popup>
|
|
569
|
+
</div>`
|
|
496
570
|
}
|
|
497
571
|
}
|
|
@@ -33,6 +33,7 @@ function Template({
|
|
|
33
33
|
clearable = false,
|
|
34
34
|
filterable = false,
|
|
35
35
|
multiple = false,
|
|
36
|
+
required = false,
|
|
36
37
|
before,
|
|
37
38
|
after,
|
|
38
39
|
}) {
|
|
@@ -40,8 +41,10 @@ function Template({
|
|
|
40
41
|
<div style="margin-top: 50vh"></div>
|
|
41
42
|
<leu-select
|
|
42
43
|
class="dropdown"
|
|
44
|
+
name="select"
|
|
43
45
|
label=${ifDefined(label)}
|
|
44
46
|
.value=${ifDefined(value)}
|
|
47
|
+
?required=${required}
|
|
45
48
|
?clearable=${clearable}
|
|
46
49
|
?disabled=${disabled}
|
|
47
50
|
?filterable=${filterable}
|
|
@@ -104,6 +107,13 @@ Clearable.args = {
|
|
|
104
107
|
clearable: true,
|
|
105
108
|
}
|
|
106
109
|
|
|
110
|
+
export const Required = Template.bind({})
|
|
111
|
+
Required.args = {
|
|
112
|
+
label: "Gemeinde",
|
|
113
|
+
options: OPTIONS_EXAMPLES,
|
|
114
|
+
required: true,
|
|
115
|
+
}
|
|
116
|
+
|
|
107
117
|
export const Disabled = Template.bind({})
|
|
108
118
|
Disabled.args = {
|
|
109
119
|
label: "Gemeinde",
|