@statistikzh/leu 0.23.0 → 0.24.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/.github/workflows/ci.yml +8 -8
- package/.github/workflows/deploy-github-pages.yaml +2 -2
- package/.github/workflows/publish.yml +30 -0
- package/.github/workflows/release-please.yml +1 -19
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +18 -0
- package/dist/Accordion.js +1 -1
- package/dist/Button.js +1 -1
- package/dist/ButtonGroup.js +1 -1
- package/dist/ChartWrapper.js +1 -1
- package/dist/Checkbox.js +1 -1
- package/dist/CheckboxGroup.js +1 -1
- package/dist/Chip.js +1 -1
- package/dist/ChipGroup.js +1 -1
- package/dist/ChipLink.js +1 -1
- package/dist/ChipRemovable.js +1 -1
- package/dist/ChipSelectable.js +1 -1
- package/dist/Dialog.js +1 -1
- package/dist/Dropdown.js +1 -1
- package/dist/FileInput.d.ts +0 -1
- package/dist/FileInput.js +1 -35
- package/dist/Icon.js +1 -1
- package/dist/Input.js +1 -1
- package/dist/{LeuElement-CWseJvWv.js → LeuElement-BfbOWTGZ.js} +1 -1
- package/dist/Menu.js +1 -1
- package/dist/MenuItem.js +1 -1
- package/dist/Message.js +1 -1
- package/dist/Pagination.js +1 -1
- package/dist/Placeholder.js +1 -1
- package/dist/Popup.js +1 -1
- package/dist/ProgressBar.js +1 -1
- package/dist/Radio.js +1 -1
- package/dist/RadioGroup.js +1 -1
- package/dist/Range.d.ts +51 -0
- package/dist/Range.js +143 -5
- package/dist/ScrollTop.js +1 -1
- package/dist/Select.js +1 -1
- package/dist/Spinner.js +1 -1
- package/dist/Table.js +1 -1
- package/dist/Tag.js +1 -1
- package/dist/VisuallyHidden.js +1 -1
- package/dist/components/file-input/FileInput.d.ts +2 -2
- package/dist/components/file-input/FileInput.d.ts.map +1 -1
- package/dist/components/range/Range.d.ts +51 -0
- package/dist/components/range/Range.d.ts.map +1 -1
- package/dist/components/range/stories/range.stories.d.ts +230 -0
- package/dist/components/range/stories/range.stories.d.ts.map +1 -0
- package/dist/components/range/test/range.test.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/leu-accordion.js +1 -1
- package/dist/leu-button-group.js +1 -1
- package/dist/leu-button.js +1 -1
- package/dist/leu-chart-wrapper.js +1 -1
- package/dist/leu-checkbox-group.js +1 -1
- package/dist/leu-checkbox.js +1 -1
- package/dist/leu-chip-group.js +1 -1
- package/dist/leu-chip-link.js +1 -1
- package/dist/leu-chip-removable.js +1 -1
- package/dist/leu-chip-selectable.js +1 -1
- package/dist/leu-dialog.js +1 -1
- package/dist/leu-dropdown.js +1 -1
- package/dist/leu-file-input.d.ts +0 -1
- package/dist/leu-file-input.js +1 -35
- package/dist/leu-icon.js +1 -1
- package/dist/leu-input.js +1 -1
- package/dist/leu-menu-item.js +1 -1
- package/dist/leu-menu.js +1 -1
- package/dist/leu-message.js +1 -1
- package/dist/leu-pagination.js +1 -1
- package/dist/leu-placeholder.js +1 -1
- package/dist/leu-popup.js +1 -1
- package/dist/leu-progress-bar.js +1 -1
- package/dist/leu-radio-group.js +1 -1
- package/dist/leu-radio.js +1 -1
- package/dist/leu-range.js +1 -1
- package/dist/leu-scroll-top.js +1 -1
- package/dist/leu-select.js +1 -1
- package/dist/leu-spinner.js +1 -1
- package/dist/leu-table.js +1 -1
- package/dist/leu-tag.js +1 -1
- package/dist/leu-visually-hidden.js +1 -1
- package/dist/vscode.html-custom-data.json +99 -50
- package/dist/vue/index.d.ts +84 -66
- package/dist/web-types.json +192 -98
- package/package.json +6 -2
- package/src/components/file-input/FileInput.ts +2 -2
- package/src/components/range/Range.ts +102 -3
- package/src/components/range/range.css +48 -1
- package/src/components/range/stories/range.stories.ts +182 -0
- package/src/components/range/test/range.test.ts +151 -6
- package/dist/components/range/stories/range-slider.stories.d.ts +0 -26
- package/dist/components/range/stories/range-slider.stories.d.ts.map +0 -1
- package/src/components/range/stories/range-slider.stories.ts +0 -142
|
@@ -6,8 +6,8 @@ import { classMap } from "lit/directives/class-map.js"
|
|
|
6
6
|
import { LeuElement } from "../../lib/LeuElement.js"
|
|
7
7
|
|
|
8
8
|
import styles from "./file-input.css"
|
|
9
|
-
import { LeuButton } from "
|
|
10
|
-
import { LeuIcon } from "../icon/
|
|
9
|
+
import { LeuButton } from "../button/Button.js"
|
|
10
|
+
import { LeuIcon } from "../icon/Icon.js"
|
|
11
11
|
import { LeuVisuallyHidden } from "../visually-hidden/VisuallyHidden.js"
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { html } from "lit"
|
|
1
|
+
import { html, nothing } from "lit"
|
|
2
2
|
|
|
3
3
|
import { property } from "lit/decorators.js"
|
|
4
4
|
import styles from "./range.css"
|
|
@@ -29,27 +29,87 @@ export class LeuRange extends LeuElement {
|
|
|
29
29
|
@property({ converter: defaultValueConverter, attribute: "value" })
|
|
30
30
|
defaultValue = [50]
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* The minimum value of the range slider.
|
|
34
|
+
*/
|
|
32
35
|
@property({ type: Number, reflect: true })
|
|
33
36
|
min: number = 0
|
|
34
37
|
|
|
38
|
+
/**
|
|
39
|
+
* The maximum value of the range slider.
|
|
40
|
+
*/
|
|
35
41
|
@property({ type: Number, reflect: true })
|
|
36
42
|
max: number = 100
|
|
37
43
|
|
|
44
|
+
/**
|
|
45
|
+
* The step size of the range slider.
|
|
46
|
+
*/
|
|
38
47
|
@property({ type: Number, reflect: true })
|
|
39
48
|
step: number = 1
|
|
40
49
|
|
|
41
50
|
@property({ type: String, reflect: true })
|
|
42
51
|
name: string = ""
|
|
43
52
|
|
|
53
|
+
/**
|
|
54
|
+
* The label of the range slider.
|
|
55
|
+
*/
|
|
44
56
|
@property({ type: String, reflect: true })
|
|
45
57
|
label: string = ""
|
|
46
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Whether to hide the label of the range slider.
|
|
61
|
+
* If true, the label will still be available for screen readers
|
|
62
|
+
* and is only visually hidden.
|
|
63
|
+
*/
|
|
64
|
+
@property({ type: Boolean, reflect: true, attribute: "hide-label" })
|
|
65
|
+
hideLabel: boolean = false
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Whether the range slider is disabled.
|
|
69
|
+
*/
|
|
47
70
|
@property({ type: Boolean, reflect: true })
|
|
48
71
|
disabled: boolean = false
|
|
49
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Whether to use a range with two handles.
|
|
75
|
+
*/
|
|
50
76
|
@property({ type: Boolean, reflect: true })
|
|
51
77
|
multiple: boolean = false
|
|
52
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Wheter to show tick marks below the range slider.
|
|
81
|
+
* One tick mark per step will be rendered.
|
|
82
|
+
*/
|
|
83
|
+
@property({ type: Boolean, reflect: true, attribute: "show-ticks" })
|
|
84
|
+
showTicks: boolean = false
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Whether to show the min and max labels below the range slider.
|
|
88
|
+
*/
|
|
89
|
+
@property({ type: Boolean, reflect: true, attribute: "show-range-labels" })
|
|
90
|
+
showRangeLabels: boolean = false
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A prefix to display before the value in the output element(s).
|
|
94
|
+
* Is ignored if a custom valueFormatter is provided.
|
|
95
|
+
*/
|
|
96
|
+
@property({ type: String, reflect: true })
|
|
97
|
+
prefix: string = ""
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* A suffix to display after the value in the output element(s).
|
|
101
|
+
* Is ignored if a custom valueFormatter is provided.
|
|
102
|
+
*/
|
|
103
|
+
@property({ type: String, reflect: true })
|
|
104
|
+
suffix: string = ""
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* A custom function to format the value displayed in the output element(s).
|
|
108
|
+
* If provided, the prefix and suffix properties will be ignored.
|
|
109
|
+
*/
|
|
110
|
+
@property({ attribute: false })
|
|
111
|
+
valueFormatter?: (value: number) => string
|
|
112
|
+
|
|
53
113
|
updated() {
|
|
54
114
|
this._updateStyles()
|
|
55
115
|
}
|
|
@@ -75,7 +135,7 @@ export class LeuRange extends LeuElement {
|
|
|
75
135
|
)
|
|
76
136
|
const normalizedValue = this._getNormalizedValue(input.valueAsNumber)
|
|
77
137
|
output.style.setProperty("--value", normalizedValue.toString())
|
|
78
|
-
output.value = input.
|
|
138
|
+
output.value = this.formatValue(input.valueAsNumber)
|
|
79
139
|
})
|
|
80
140
|
}
|
|
81
141
|
|
|
@@ -177,6 +237,33 @@ export class LeuRange extends LeuElement {
|
|
|
177
237
|
}
|
|
178
238
|
}
|
|
179
239
|
|
|
240
|
+
protected formatValue(value: number) {
|
|
241
|
+
if (this.valueFormatter) {
|
|
242
|
+
return this.valueFormatter(value)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return `${this.prefix}${value}${this.suffix}`
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
protected renderTicks() {
|
|
249
|
+
if (!this.showTicks) {
|
|
250
|
+
return nothing
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return html`<div class="ticks">
|
|
254
|
+
${Array.from(
|
|
255
|
+
{ length: (this.max - this.min) / this.step + 1 },
|
|
256
|
+
(_, i) => this.min + i * this.step,
|
|
257
|
+
).map(
|
|
258
|
+
(tick) =>
|
|
259
|
+
html`<span
|
|
260
|
+
class="tick"
|
|
261
|
+
style="left: ${this._getNormalizedValue(tick) * 100}%"
|
|
262
|
+
></span>`,
|
|
263
|
+
)}
|
|
264
|
+
</div>`
|
|
265
|
+
}
|
|
266
|
+
|
|
180
267
|
render() {
|
|
181
268
|
const inputs = this.multiple ? ["base", "ghost"] : ["base"]
|
|
182
269
|
|
|
@@ -184,6 +271,7 @@ export class LeuRange extends LeuElement {
|
|
|
184
271
|
|
|
185
272
|
return html`
|
|
186
273
|
<div
|
|
274
|
+
class="container"
|
|
187
275
|
role=${multiple ? "group" : undefined}
|
|
188
276
|
aria-labelledby=${multiple ? "group-label" : undefined}
|
|
189
277
|
>
|
|
@@ -196,7 +284,7 @@ export class LeuRange extends LeuElement {
|
|
|
196
284
|
html`<output
|
|
197
285
|
class="output"
|
|
198
286
|
for="input-${type}"
|
|
199
|
-
value=${defaultValue[index]}
|
|
287
|
+
value=${this.formatValue(defaultValue[index])}
|
|
200
288
|
></output>`,
|
|
201
289
|
)}
|
|
202
290
|
</div>
|
|
@@ -221,8 +309,19 @@ export class LeuRange extends LeuElement {
|
|
|
221
309
|
/>
|
|
222
310
|
`,
|
|
223
311
|
)}
|
|
312
|
+
${this.renderTicks()}
|
|
224
313
|
</div>
|
|
225
314
|
</div>
|
|
315
|
+
${this.showRangeLabels
|
|
316
|
+
? html`<div class="tick-labels">
|
|
317
|
+
<span class="tick-label tick-label--min"
|
|
318
|
+
>${this.formatValue(this.min)}</span
|
|
319
|
+
>
|
|
320
|
+
<span class="tick-label tick-label--max"
|
|
321
|
+
>${this.formatValue(this.max)}</span
|
|
322
|
+
>
|
|
323
|
+
</div>`
|
|
324
|
+
: nothing}
|
|
226
325
|
`
|
|
227
326
|
}
|
|
228
327
|
}
|
|
@@ -35,7 +35,9 @@
|
|
|
35
35
|
--range-value-color: var(--range-value-color-disabled);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
.container {
|
|
39
|
+
position: relative;
|
|
40
|
+
}
|
|
39
41
|
|
|
40
42
|
.label {
|
|
41
43
|
display: inline-block;
|
|
@@ -44,6 +46,17 @@
|
|
|
44
46
|
font: var(--leu-t-regular-regular-font);
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
:host([hide-label]) .label {
|
|
50
|
+
clip: rect(0 0 0 0);
|
|
51
|
+
border: 0;
|
|
52
|
+
height: 1px;
|
|
53
|
+
margin: -1px !important;
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
padding: 0 !important;
|
|
56
|
+
position: absolute;
|
|
57
|
+
width: 1px;
|
|
58
|
+
}
|
|
59
|
+
|
|
47
60
|
.outputs {
|
|
48
61
|
position: relative;
|
|
49
62
|
height: 1.5rem;
|
|
@@ -68,6 +81,8 @@
|
|
|
68
81
|
|
|
69
82
|
.inputs {
|
|
70
83
|
position: relative;
|
|
84
|
+
z-index: 1;
|
|
85
|
+
height: var(--range-thumb-diameter);
|
|
71
86
|
}
|
|
72
87
|
|
|
73
88
|
.range {
|
|
@@ -178,3 +193,35 @@
|
|
|
178
193
|
.range--ghost::-webkit-slider-runnable-track {
|
|
179
194
|
background: transparent;
|
|
180
195
|
}
|
|
196
|
+
|
|
197
|
+
/* Ticks */
|
|
198
|
+
|
|
199
|
+
.ticks {
|
|
200
|
+
position: absolute;
|
|
201
|
+
inset-block-start: calc(
|
|
202
|
+
var(--range-thumb-diameter) / 2 + var(--range-track-height)
|
|
203
|
+
);
|
|
204
|
+
inset-inline: calc(var(--range-thumb-diameter) / 2);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.tick {
|
|
208
|
+
z-index: -1;
|
|
209
|
+
position: absolute;
|
|
210
|
+
top: 50%;
|
|
211
|
+
width: 2px;
|
|
212
|
+
height: 0.5rem;
|
|
213
|
+
background-color: var(--range-track-background-color);
|
|
214
|
+
transform: translateY(-50%);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.tick-labels {
|
|
218
|
+
display: flex;
|
|
219
|
+
justify-content: space-between;
|
|
220
|
+
color: var(--leu-color-black-60);
|
|
221
|
+
font: var(--leu-t-tiny-regular-font);
|
|
222
|
+
margin-top: 0.25rem;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.tick-label--max {
|
|
226
|
+
text-align: right;
|
|
227
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/web-components"
|
|
2
|
+
import { html } from "lit"
|
|
3
|
+
import { ifDefined } from "lit/directives/if-defined.js"
|
|
4
|
+
|
|
5
|
+
import "../leu-range.js"
|
|
6
|
+
import type { LeuRange } from "../leu-range.js"
|
|
7
|
+
import "../../input/leu-input.js"
|
|
8
|
+
|
|
9
|
+
type StoryArgs = LeuRange
|
|
10
|
+
type Story = StoryObj<StoryArgs>
|
|
11
|
+
|
|
12
|
+
export default {
|
|
13
|
+
title: "Components/Range",
|
|
14
|
+
component: "leu-range",
|
|
15
|
+
parameters: {
|
|
16
|
+
design: {
|
|
17
|
+
type: "figma",
|
|
18
|
+
url: "https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=17340-81936&mode=design",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
args: {
|
|
22
|
+
label: "Bereich",
|
|
23
|
+
},
|
|
24
|
+
} satisfies Meta<StoryArgs>
|
|
25
|
+
|
|
26
|
+
const Template: Story = {
|
|
27
|
+
render: (args) =>
|
|
28
|
+
html` <leu-range
|
|
29
|
+
label=${args.label}
|
|
30
|
+
?disabled=${args.disabled}
|
|
31
|
+
?multiple=${args.multiple}
|
|
32
|
+
min=${ifDefined(args.min)}
|
|
33
|
+
max=${ifDefined(args.max)}
|
|
34
|
+
value=${ifDefined(args.value)}
|
|
35
|
+
step=${ifDefined(args.step)}
|
|
36
|
+
prefix=${ifDefined(args.prefix)}
|
|
37
|
+
suffix=${ifDefined(args.suffix)}
|
|
38
|
+
.valueFormatter=${args.valueFormatter}
|
|
39
|
+
?hide-label=${args["hide-label"]}
|
|
40
|
+
?show-ticks=${args["show-ticks"]}
|
|
41
|
+
?show-range-labels=${args["show-range-labels"]}
|
|
42
|
+
>
|
|
43
|
+
</leu-range>`,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const Regular = {
|
|
47
|
+
...Template,
|
|
48
|
+
args: { min: 0, max: 100, value: "15" },
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const Multiple = {
|
|
52
|
+
...Template,
|
|
53
|
+
args: { min: 1965, max: 2022, value: "1965, 2022", multiple: true },
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const Labeled = {
|
|
57
|
+
...Template,
|
|
58
|
+
args: { label: "Wert auswählen", min: 100000, max: 200000 },
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const HiddenLabel = {
|
|
62
|
+
...Template,
|
|
63
|
+
args: {
|
|
64
|
+
label: "Wert auswählen",
|
|
65
|
+
min: 100000,
|
|
66
|
+
max: 200000,
|
|
67
|
+
"hide-label": true,
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const Disabled = {
|
|
72
|
+
...Template,
|
|
73
|
+
args: { label: "Wert auswählen", min: 0, max: 100, disabled: true },
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const Step = {
|
|
77
|
+
...Template,
|
|
78
|
+
args: { min: 5, max: 123, step: 13 },
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const Ticks = {
|
|
82
|
+
...Template,
|
|
83
|
+
args: {
|
|
84
|
+
label: "Jahr auswählen",
|
|
85
|
+
min: 1962,
|
|
86
|
+
max: 2022,
|
|
87
|
+
step: 1,
|
|
88
|
+
"show-ticks": true,
|
|
89
|
+
"show-range-labels": true,
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const Suffix = {
|
|
94
|
+
...Template,
|
|
95
|
+
args: {
|
|
96
|
+
label: "Betrag auswählen",
|
|
97
|
+
min: 100,
|
|
98
|
+
max: 200,
|
|
99
|
+
step: 1,
|
|
100
|
+
suffix: " CHF",
|
|
101
|
+
"show-range-labels": true,
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const CustomFormatter = {
|
|
106
|
+
...Template,
|
|
107
|
+
args: {
|
|
108
|
+
label: "Schuljahr",
|
|
109
|
+
min: 15,
|
|
110
|
+
max: 24,
|
|
111
|
+
step: 1,
|
|
112
|
+
"show-range-labels": true,
|
|
113
|
+
valueFormatter: (value: number) => `${value}/${value + 1}`,
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function CombinedTemplate(args: StoryArgs) {
|
|
118
|
+
const values = (args.value ?? "").split(",").map((v) => Number(v.trim()))
|
|
119
|
+
function handleInputInput() {
|
|
120
|
+
const inputs = document.querySelectorAll("leu-input")
|
|
121
|
+
const range = document.querySelector("leu-range")
|
|
122
|
+
range.value = [inputs[0].value, inputs[1].value]
|
|
123
|
+
}
|
|
124
|
+
return html`
|
|
125
|
+
<leu-range
|
|
126
|
+
label=${args.label}
|
|
127
|
+
?disabled=${args.disabled}
|
|
128
|
+
?multiple=${args.multiple}
|
|
129
|
+
min=${ifDefined(args.min)}
|
|
130
|
+
max=${ifDefined(args.max)}
|
|
131
|
+
value=${ifDefined(args.value)}
|
|
132
|
+
step=${ifDefined(args.step)}
|
|
133
|
+
prefix=${ifDefined(args.prefix)}
|
|
134
|
+
suffix=${ifDefined(args.suffix)}
|
|
135
|
+
?hide-label=${args["hide-label"]}
|
|
136
|
+
?show-ticks=${args["show-ticks"]}
|
|
137
|
+
?show-range-labels=${args["show-range-labels"]}
|
|
138
|
+
@input=${(e) => {
|
|
139
|
+
const inputs = document.querySelectorAll("leu-input")
|
|
140
|
+
const valueList = e.target.valueAsArray
|
|
141
|
+
|
|
142
|
+
inputs[0].value = valueList[0]
|
|
143
|
+
inputs[1].value = valueList[1]
|
|
144
|
+
}}
|
|
145
|
+
>
|
|
146
|
+
</leu-range>
|
|
147
|
+
<div style="display: flex; gap: 1rem; margin-top: 1rem;">
|
|
148
|
+
<leu-input
|
|
149
|
+
label="Von"
|
|
150
|
+
?disabled=${args.disabled}
|
|
151
|
+
type="number"
|
|
152
|
+
min=${ifDefined(args.min)}
|
|
153
|
+
max=${ifDefined(args.max)}
|
|
154
|
+
value=${ifDefined(values[0])}
|
|
155
|
+
step=${ifDefined(args.step)}
|
|
156
|
+
size="small"
|
|
157
|
+
@input=${handleInputInput}
|
|
158
|
+
></leu-input>
|
|
159
|
+
<leu-input
|
|
160
|
+
label="Von"
|
|
161
|
+
?disabled=${args.disabled}
|
|
162
|
+
type="number"
|
|
163
|
+
min=${ifDefined(args.min)}
|
|
164
|
+
max=${ifDefined(args.max)}
|
|
165
|
+
value=${ifDefined(values[1])}
|
|
166
|
+
step=${ifDefined(args.step)}
|
|
167
|
+
size="small"
|
|
168
|
+
@input=${handleInputInput}
|
|
169
|
+
></leu-input>
|
|
170
|
+
</div>
|
|
171
|
+
`
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export const Combined = {
|
|
175
|
+
render: CombinedTemplate,
|
|
176
|
+
args: {
|
|
177
|
+
min: 1965,
|
|
178
|
+
max: 2022,
|
|
179
|
+
value: "1965, 2022",
|
|
180
|
+
multiple: true,
|
|
181
|
+
},
|
|
182
|
+
}
|
|
@@ -1,24 +1,169 @@
|
|
|
1
1
|
import { html } from "lit"
|
|
2
2
|
import { fixture, expect } from "@open-wc/testing"
|
|
3
|
+
import { ifDefined } from "lit/directives/if-defined.js"
|
|
3
4
|
|
|
4
5
|
import "../leu-range.js"
|
|
6
|
+
import type { LeuRange } from "../leu-range.js"
|
|
5
7
|
|
|
6
|
-
async function defaultFixture() {
|
|
7
|
-
return fixture(html`
|
|
8
|
-
<leu-range
|
|
8
|
+
async function defaultFixture(args = {}) {
|
|
9
|
+
return fixture<LeuRange>(html`
|
|
10
|
+
<leu-range
|
|
11
|
+
label=${args.label}
|
|
12
|
+
?disabled=${args.disabled}
|
|
13
|
+
?multiple=${args.multiple}
|
|
14
|
+
min=${ifDefined(args.min)}
|
|
15
|
+
max=${ifDefined(args.max)}
|
|
16
|
+
value=${ifDefined(args.value)}
|
|
17
|
+
step=${ifDefined(args.step)}
|
|
18
|
+
prefix=${ifDefined(args.prefix)}
|
|
19
|
+
suffix=${ifDefined(args.suffix)}
|
|
20
|
+
.valueFormatter=${args.valueFormatter}
|
|
21
|
+
?hide-label=${args["hide-label"]}
|
|
22
|
+
?show-ticks=${args["show-ticks"]}
|
|
23
|
+
?show-range-labels=${args["show-range-labels"]}
|
|
24
|
+
>
|
|
25
|
+
</leu-range>
|
|
9
26
|
`)
|
|
10
27
|
}
|
|
11
28
|
|
|
12
29
|
describe("LeuRange", () => {
|
|
13
30
|
it("is a defined element", async () => {
|
|
14
|
-
const el =
|
|
31
|
+
const el = customElements.get("leu-range")
|
|
15
32
|
|
|
16
|
-
|
|
33
|
+
expect(el).not.to.be.undefined
|
|
17
34
|
})
|
|
18
35
|
|
|
19
36
|
it("passes the a11y audit", async () => {
|
|
20
|
-
const el = await defaultFixture(
|
|
37
|
+
const el = await defaultFixture({
|
|
38
|
+
label: "Test Label",
|
|
39
|
+
min: 0,
|
|
40
|
+
max: 100,
|
|
41
|
+
value: 50,
|
|
42
|
+
})
|
|
21
43
|
|
|
22
44
|
await expect(el).shadowDom.to.be.accessible()
|
|
23
45
|
})
|
|
46
|
+
|
|
47
|
+
it("renders the label", async () => {
|
|
48
|
+
const el = await defaultFixture({ label: "Test Label" })
|
|
49
|
+
|
|
50
|
+
const label = el.shadowRoot?.querySelector(".label")
|
|
51
|
+
|
|
52
|
+
expect(label).to.exist
|
|
53
|
+
expect(label).to.contain.text("Test Label")
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it("renders the label visually hidden when 'hide-label' is set", async () => {
|
|
57
|
+
const el = await defaultFixture({ label: "Test Label", "hide-label": true })
|
|
58
|
+
|
|
59
|
+
const label = el.shadowRoot?.querySelector(".label")
|
|
60
|
+
|
|
61
|
+
expect(label).to.exist
|
|
62
|
+
expect(label).to.contain.text("Test Label")
|
|
63
|
+
await expect(el).shadowDom.to.be.accessible()
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it("renders the range labels", async () => {
|
|
67
|
+
const el = await defaultFixture({
|
|
68
|
+
min: 23,
|
|
69
|
+
max: 87,
|
|
70
|
+
"show-range-labels": true,
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const minLabel = el.shadowRoot?.querySelector(".tick-label--min")
|
|
74
|
+
const maxLabel = el.shadowRoot?.querySelector(".tick-label--max")
|
|
75
|
+
|
|
76
|
+
expect(minLabel).to.exist
|
|
77
|
+
expect(maxLabel).to.exist
|
|
78
|
+
|
|
79
|
+
expect(minLabel).to.contain.text("23")
|
|
80
|
+
expect(maxLabel).to.contain.text("87")
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it("renders tick marks when 'show-ticks' is set", async () => {
|
|
84
|
+
const el = await defaultFixture({
|
|
85
|
+
min: 0,
|
|
86
|
+
max: 10,
|
|
87
|
+
step: 3,
|
|
88
|
+
"show-ticks": true,
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
const ticksContainer = el.shadowRoot?.querySelector(".ticks")
|
|
92
|
+
expect(ticksContainer).to.exist
|
|
93
|
+
|
|
94
|
+
const ticks = ticksContainer?.querySelectorAll(".tick")
|
|
95
|
+
expect(ticks?.length).to.equal(4)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it("renders prefix and suffix", async () => {
|
|
99
|
+
const el = await defaultFixture({
|
|
100
|
+
prefix: "$",
|
|
101
|
+
suffix: " CHF",
|
|
102
|
+
min: 25,
|
|
103
|
+
max: 75,
|
|
104
|
+
value: 50,
|
|
105
|
+
"show-range-labels": true,
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
const minLabel = el.shadowRoot?.querySelector(".tick-label--min")
|
|
109
|
+
const maxLabel = el.shadowRoot?.querySelector(".tick-label--max")
|
|
110
|
+
const valueLabel = el.shadowRoot?.querySelector("output")
|
|
111
|
+
|
|
112
|
+
expect(minLabel).to.exist
|
|
113
|
+
expect(maxLabel).to.exist
|
|
114
|
+
expect(valueLabel).to.exist
|
|
115
|
+
|
|
116
|
+
expect(minLabel).to.contain.text("$25 CHF")
|
|
117
|
+
expect(maxLabel).to.contain.text("$75 CHF")
|
|
118
|
+
expect(valueLabel).to.contain.text("$50 CHF")
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it("uses custom valueFormatter if provided", async () => {
|
|
122
|
+
const el = await defaultFixture({
|
|
123
|
+
valueFormatter: (value: number) => `Value: ${value}`,
|
|
124
|
+
min: 10,
|
|
125
|
+
max: 90,
|
|
126
|
+
value: 50,
|
|
127
|
+
"show-range-labels": true,
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
const minLabel = el.shadowRoot?.querySelector(".tick-label--min")
|
|
131
|
+
const maxLabel = el.shadowRoot?.querySelector(".tick-label--max")
|
|
132
|
+
const valueLabel = el.shadowRoot?.querySelector("output")
|
|
133
|
+
|
|
134
|
+
expect(minLabel).to.exist
|
|
135
|
+
expect(maxLabel).to.exist
|
|
136
|
+
expect(valueLabel).to.exist
|
|
137
|
+
|
|
138
|
+
expect(minLabel).to.contain.text("Value: 10")
|
|
139
|
+
expect(maxLabel).to.contain.text("Value: 90")
|
|
140
|
+
expect(valueLabel).to.contain.text("Value: 50")
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
it("prefix and suffix are ignored when valueFormatter is provided", async () => {
|
|
144
|
+
const el = await defaultFixture({
|
|
145
|
+
prefix: "$",
|
|
146
|
+
suffix: " CHF",
|
|
147
|
+
valueFormatter: (value: number) => `${value}/${value + 1}`,
|
|
148
|
+
min: 10,
|
|
149
|
+
max: 15,
|
|
150
|
+
value: 12,
|
|
151
|
+
"show-range-labels": true,
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
const minLabel = el.shadowRoot?.querySelector(".tick-label--min")
|
|
155
|
+
const maxLabel = el.shadowRoot?.querySelector(".tick-label--max")
|
|
156
|
+
const valueLabel = el.shadowRoot?.querySelector("output")
|
|
157
|
+
|
|
158
|
+
expect(minLabel).to.contain.text("10/11")
|
|
159
|
+
expect(maxLabel).to.contain.text("15/16")
|
|
160
|
+
expect(valueLabel).to.contain.text("12/13")
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it("disables the range slider", async () => {
|
|
164
|
+
const el = await defaultFixture({ disabled: true })
|
|
165
|
+
|
|
166
|
+
const input = el.shadowRoot?.querySelector("input")
|
|
167
|
+
expect(input).to.have.attribute("disabled")
|
|
168
|
+
})
|
|
24
169
|
})
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import "../leu-range.js";
|
|
2
|
-
import "../../input/leu-input.js";
|
|
3
|
-
/**
|
|
4
|
-
* @type {import("@storybook/web-components").Meta}
|
|
5
|
-
*/
|
|
6
|
-
declare const _default: {
|
|
7
|
-
title: string;
|
|
8
|
-
component: string;
|
|
9
|
-
parameters: {
|
|
10
|
-
design: {
|
|
11
|
-
type: string;
|
|
12
|
-
url: string;
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
args: {
|
|
16
|
-
label: string;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
export default _default;
|
|
20
|
-
export declare const Regular: any;
|
|
21
|
-
export declare const Multiple: any;
|
|
22
|
-
export declare const Labeled: any;
|
|
23
|
-
export declare const Disabled: any;
|
|
24
|
-
export declare const Step: any;
|
|
25
|
-
export declare const Combined: any;
|
|
26
|
-
//# sourceMappingURL=range-slider.stories.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"range-slider.stories.d.ts","sourceRoot":"","sources":["../../../../src/components/range/stories/range-slider.stories.ts"],"names":[],"mappings":"AAGA,OAAO,iBAAiB,CAAA;AACxB,OAAO,0BAA0B,CAAA;AAEjC;;GAEG;;;;;;;;;;;;;;AACH,wBAYC;AAiBD,eAAO,MAAM,OAAO,KAAoB,CAAA;AAOxC,eAAO,MAAM,QAAQ,KAAoB,CAAA;AAQzC,eAAO,MAAM,OAAO,KAAoB,CAAA;AAOxC,eAAO,MAAM,QAAQ,KAAoB,CAAA;AAQzC,eAAO,MAAM,IAAI,KAAoB,CAAA;AAmErC,eAAO,MAAM,QAAQ,KAA4B,CAAA"}
|