@statistikzh/leu 0.3.0 → 0.4.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/deploy-github-pages.yaml +33 -0
- package/.storybook/main.js +27 -1
- package/.storybook/manager-head.html +1 -0
- package/.storybook/manager.js +9 -0
- package/.storybook/preview-head.html +1 -1
- package/.storybook/preview.js +59 -5
- package/.storybook/static/logo.svg +19 -0
- package/.storybook/theme.js +7 -0
- package/CHANGELOG.md +30 -0
- package/README.md +1 -1
- package/dist/Button.js +15 -18
- package/dist/ButtonGroup.js +5 -7
- package/dist/Checkbox.js +101 -84
- package/dist/CheckboxGroup.js +41 -37
- package/dist/{Chip-5f70d04f.js → Chip-dac7337d.js} +5 -1
- package/dist/ChipGroup.js +2 -5
- package/dist/ChipLink.js +4 -7
- package/dist/ChipRemovable.js +4 -7
- package/dist/ChipSelectable.js +4 -7
- package/dist/Dropdown.js +55 -26
- package/dist/Input.js +29 -28
- package/dist/Menu.js +2 -5
- package/dist/MenuItem.js +30 -15
- package/dist/Pagination.js +54 -54
- package/dist/Radio.js +7 -6
- package/dist/RadioGroup.js +41 -39
- package/dist/Select.js +55 -43
- package/dist/Table.js +137 -120
- package/dist/{defineElement-ba770aed.js → _rollupPluginBabelHelpers-20f659f4.js} +1 -15
- package/dist/defineElement-47d4f665.js +15 -0
- package/dist/index.js +29 -19
- package/dist/leu-button-group.js +7 -3
- package/dist/leu-button.js +6 -3
- package/dist/leu-checkbox-group.js +6 -3
- package/dist/leu-checkbox.js +6 -3
- package/dist/leu-chip-group.js +6 -3
- package/dist/leu-chip-link.js +7 -4
- package/dist/leu-chip-removable.js +7 -4
- package/dist/leu-chip-selectable.js +7 -4
- package/dist/leu-dropdown.js +13 -3
- package/dist/leu-input.js +7 -3
- package/dist/leu-menu-item.js +8 -3
- package/dist/leu-menu.js +6 -3
- package/dist/leu-pagination.js +8 -3
- package/dist/leu-popup-4bf6f1f4.js +216 -0
- package/dist/leu-radio-group.js +6 -3
- package/dist/leu-radio.js +6 -3
- package/dist/leu-select.js +14 -3
- package/dist/leu-table.js +9 -3
- package/package.json +24 -12
- package/scripts/generate-component/templates/[Name].js +0 -5
- package/scripts/generate-component/templates/[name].css +1 -1
- package/scripts/generate-component/templates/[namespace]-[name].js +5 -2
- package/src/components/accordion/Accordion.js +0 -6
- package/src/components/accordion/leu-accordion.js +5 -2
- package/src/components/accordion/stories/accordion.stories.js +7 -4
- package/src/components/accordion/test/accordion.test.js +92 -2
- package/src/components/breadcrumb/Breadcrumb.js +310 -0
- package/src/components/breadcrumb/breadcrumb.css +114 -0
- package/src/components/breadcrumb/leu-breadcrumb.js +6 -0
- package/src/components/breadcrumb/stories/breadcrumb.stories.js +73 -0
- package/src/components/breadcrumb/test/breadcrumb.test.js +141 -0
- package/src/components/button/Button.js +10 -15
- package/src/components/button/button.css +3 -3
- package/src/components/button/leu-button.js +5 -2
- package/src/components/button/stories/button.stories.js +58 -37
- package/src/components/button/test/button.test.js +112 -2
- package/src/components/button-group/ButtonGroup.js +1 -7
- package/src/components/button-group/leu-button-group.js +5 -2
- package/src/components/button-group/stories/button-group.stories.js +6 -0
- package/src/components/button-group/test/button-group.test.js +79 -3
- package/src/components/checkbox/Checkbox.js +6 -85
- package/src/components/checkbox/CheckboxGroup.js +8 -38
- package/src/components/checkbox/checkbox-group.css +29 -0
- package/src/components/checkbox/checkbox.css +76 -0
- package/src/components/checkbox/leu-checkbox-group.js +5 -2
- package/src/components/checkbox/leu-checkbox.js +5 -2
- package/src/components/checkbox/stories/checkbox-group.stories.js +44 -21
- package/src/components/checkbox/stories/checkbox.stories.js +7 -1
- package/src/components/checkbox/test/checkbox-group.test.js +124 -0
- package/src/components/checkbox/test/checkbox.test.js +72 -59
- package/src/components/chip/Chip.js +1 -0
- package/src/components/chip/ChipGroup.js +0 -5
- package/src/components/chip/ChipLink.js +1 -6
- package/src/components/chip/ChipRemovable.js +1 -6
- package/src/components/chip/ChipSelectable.js +1 -6
- package/src/components/chip/exports.js +4 -10
- package/src/components/chip/leu-chip-group.js +5 -2
- package/src/components/chip/leu-chip-link.js +5 -2
- package/src/components/chip/leu-chip-removable.js +5 -2
- package/src/components/chip/leu-chip-selectable.js +5 -2
- package/src/components/chip/stories/chip-group.stories.js +18 -6
- package/src/components/chip/stories/chip-link.stories.js +16 -4
- package/src/components/chip/stories/chip-removable.stories.js +15 -4
- package/src/components/chip/stories/chip-selectable.stories.js +13 -3
- package/src/components/chip/test/chip-group.test.js +124 -0
- package/src/components/chip/test/chip-link.test.js +58 -0
- package/src/components/chip/test/chip-removable.test.js +79 -0
- package/src/components/chip/test/chip-selectable.test.js +95 -0
- package/src/components/chip/test/chip.test.js +1 -1
- package/src/components/dropdown/Dropdown.js +52 -24
- package/src/components/dropdown/dropdown.css +1 -2
- package/src/components/dropdown/leu-dropdown.js +5 -2
- package/src/components/dropdown/stories/dropdown.stories.js +11 -5
- package/src/components/dropdown/test/dropdown.test.js +6 -6
- package/src/components/icon/icon.js +1 -1
- package/src/components/icon/test/icon.test.js +66 -0
- package/src/components/input/Input.js +18 -24
- package/src/components/input/input.css +9 -6
- package/src/components/input/leu-input.js +5 -2
- package/src/components/input/stories/input.stories.js +8 -2
- package/src/components/input/test/input.test.js +431 -4
- package/src/components/menu/Menu.js +0 -5
- package/src/components/menu/MenuItem.js +20 -13
- package/src/components/menu/leu-menu-item.js +5 -2
- package/src/components/menu/leu-menu.js +5 -2
- package/src/components/menu/menu-item.css +5 -2
- package/src/components/menu/stories/menu-item.stories.js +13 -4
- package/src/components/menu/stories/menu.stories.js +11 -5
- package/src/components/menu/test/menu-item.test.js +180 -0
- package/src/components/menu/test/menu.test.js +10 -2
- package/src/components/pagination/Pagination.js +53 -65
- package/src/components/pagination/leu-pagination.js +5 -2
- package/src/components/pagination/stories/pagination.stories.js +17 -9
- package/src/components/pagination/test/pagination.test.js +191 -5
- package/src/components/popup/Popup.js +200 -0
- package/src/components/popup/leu-popup.js +6 -0
- package/src/components/popup/popup.css +27 -0
- package/src/components/popup/stories/popup.stories.js +58 -0
- package/src/components/popup/test/popup.test.js +29 -0
- package/src/components/radio/Radio.js +2 -6
- package/src/components/radio/RadioGroup.js +6 -38
- package/src/components/radio/leu-radio-group.js +5 -2
- package/src/components/radio/leu-radio.js +5 -2
- package/src/components/radio/radio-group.css +29 -0
- package/src/components/radio/stories/radio-group.stories.js +38 -19
- package/src/components/radio/stories/radio.stories.js +7 -1
- package/src/components/radio/test/radio-group.test.js +86 -0
- package/src/components/radio/test/radio.test.js +108 -17
- package/src/components/select/Select.js +34 -31
- package/src/components/select/leu-select.js +5 -2
- package/src/components/select/select.css +13 -13
- package/src/components/select/stories/select.stories.js +15 -168
- package/src/components/select/test/fixtures.js +162 -0
- package/src/components/select/test/select.test.js +236 -12
- package/src/components/table/Table.js +43 -118
- package/src/components/table/leu-table.js +5 -2
- package/src/components/table/stories/table.stories.js +20 -10
- package/src/components/table/table.css +99 -0
- package/src/components/table/test/table.test.js +1 -1
- package/src/lib/utils.js +17 -0
- package/{web-dev-server-storybook.config.mjs → web-dev-server.config.mjs} +1 -2
- package/web-test-runner.config.mjs +15 -2
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { html } from "lit"
|
|
2
|
+
import { fixture, expect, oneEvent } from "@open-wc/testing"
|
|
3
|
+
import { ifDefined } from "lit/directives/if-defined.js"
|
|
4
|
+
import { spy } from "sinon"
|
|
5
|
+
|
|
6
|
+
import "../leu-menu-item.js"
|
|
7
|
+
|
|
8
|
+
async function defaultFixture(args = {}) {
|
|
9
|
+
return fixture(html`
|
|
10
|
+
<leu-menu-item
|
|
11
|
+
label=${args.label}
|
|
12
|
+
before=${ifDefined(args.before)}
|
|
13
|
+
after=${ifDefined(args.after)}
|
|
14
|
+
href=${ifDefined(args.href)}
|
|
15
|
+
?active=${args.active}
|
|
16
|
+
?disabled=${args.disabled}
|
|
17
|
+
></leu-menu-item>
|
|
18
|
+
`)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe("LeuMenuItem", () => {
|
|
22
|
+
it("is a defined element", async () => {
|
|
23
|
+
const el = customElements.get("leu-menu-item")
|
|
24
|
+
|
|
25
|
+
await expect(el).not.to.be.undefined
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it("passes the a11y audit", async () => {
|
|
29
|
+
const el = await defaultFixture({ label: "Download" })
|
|
30
|
+
|
|
31
|
+
await expect(el).shadowDom.to.be.accessible()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it("passes the a11y audit with a link", async () => {
|
|
35
|
+
const el = await defaultFixture({
|
|
36
|
+
label: "Download",
|
|
37
|
+
href: "https://zh.ch",
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
await expect(el).shadowDom.to.be.accessible()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it("renders a label", async () => {
|
|
44
|
+
const el = await defaultFixture({ label: "Download" })
|
|
45
|
+
|
|
46
|
+
const button = el.shadowRoot.querySelector("button")
|
|
47
|
+
|
|
48
|
+
expect(button).to.have.trimmed.text("Download")
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it("renders a button", async () => {
|
|
52
|
+
const el = await defaultFixture({ label: "Download" })
|
|
53
|
+
|
|
54
|
+
const button = el.shadowRoot.querySelector("button")
|
|
55
|
+
|
|
56
|
+
expect(button).to.exist
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it("renders a link", async () => {
|
|
60
|
+
const el = await defaultFixture({
|
|
61
|
+
label: "Kanton Zürich",
|
|
62
|
+
href: "https://zh.ch",
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
const link = el.shadowRoot.querySelector("a")
|
|
66
|
+
|
|
67
|
+
expect(link).to.exist
|
|
68
|
+
expect(link).to.have.attribute("href", "https://zh.ch")
|
|
69
|
+
expect(link).to.have.trimmed.text("Kanton Zürich")
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it("renders a before icon", async () => {
|
|
73
|
+
const el = await defaultFixture({ label: "Download", before: "download" })
|
|
74
|
+
|
|
75
|
+
const before = el.shadowRoot.querySelector(".before")
|
|
76
|
+
expect(before).to.exist
|
|
77
|
+
|
|
78
|
+
expect(el).shadowDom.to.equal(
|
|
79
|
+
"<button class='button'><span class='before'></span><span class='label'>Download</span></button>"
|
|
80
|
+
)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it("renders a before label", async () => {
|
|
84
|
+
const el = await defaultFixture({ label: "Download", before: "DE" })
|
|
85
|
+
|
|
86
|
+
const before = el.shadowRoot.querySelector(".before")
|
|
87
|
+
expect(before).to.exist
|
|
88
|
+
expect(before).to.have.trimmed.text("DE")
|
|
89
|
+
|
|
90
|
+
expect(el).shadowDom.to.equal(
|
|
91
|
+
"<button class='button'><span class='before'>DE</span><span class='label'>Download</span></button>"
|
|
92
|
+
)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it("renders a before placeholder", async () => {
|
|
96
|
+
const el = await defaultFixture({ label: "Download", before: "EMPTY" })
|
|
97
|
+
|
|
98
|
+
const before = el.shadowRoot.querySelector(".before")
|
|
99
|
+
expect(before).to.exist
|
|
100
|
+
expect(before).to.not.have.trimmed.text()
|
|
101
|
+
|
|
102
|
+
const iconPlaceholder = before.querySelector(".icon-placeholder")
|
|
103
|
+
expect(iconPlaceholder).to.exist
|
|
104
|
+
|
|
105
|
+
expect(el).shadowDom.to.equal(
|
|
106
|
+
"<button class='button'><span class='before'><div class='icon-placeholder'></div></span><span class='label'>Download</span></button>"
|
|
107
|
+
)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it("renders a after icon", async () => {
|
|
111
|
+
const el = await defaultFixture({ label: "Download", after: "download" })
|
|
112
|
+
|
|
113
|
+
const after = el.shadowRoot.querySelector(".after")
|
|
114
|
+
expect(after).to.exist
|
|
115
|
+
|
|
116
|
+
expect(el).shadowDom.to.equal(
|
|
117
|
+
"<button class='button'><span class='label'>Download</span><span class='after'></span></button>"
|
|
118
|
+
)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it("renders a after label", async () => {
|
|
122
|
+
const el = await defaultFixture({ label: "Download", after: "DE" })
|
|
123
|
+
|
|
124
|
+
const after = el.shadowRoot.querySelector(".after")
|
|
125
|
+
expect(after).to.exist
|
|
126
|
+
expect(after).to.have.trimmed.text("DE")
|
|
127
|
+
|
|
128
|
+
expect(el).shadowDom.to.equal(
|
|
129
|
+
"<button class='button'><span class='label'>Download</span><span class='after'>DE</span></button>"
|
|
130
|
+
)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it("renders a after placeholder", async () => {
|
|
134
|
+
const el = await defaultFixture({ label: "Download", after: "EMPTY" })
|
|
135
|
+
|
|
136
|
+
const after = el.shadowRoot.querySelector(".after")
|
|
137
|
+
expect(after).to.exist
|
|
138
|
+
expect(after).to.not.have.trimmed.text()
|
|
139
|
+
|
|
140
|
+
const iconPlaceholder = after.querySelector(".icon-placeholder")
|
|
141
|
+
expect(iconPlaceholder).to.exist
|
|
142
|
+
|
|
143
|
+
expect(el).shadowDom.to.equal(
|
|
144
|
+
"<button class='button'><span class='label'>Download</span><span class='after'><div class='icon-placeholder'></div></span></button>"
|
|
145
|
+
)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it("passes the disabled attribute to the button", async () => {
|
|
149
|
+
const el = await defaultFixture({ label: "Download", disabled: true })
|
|
150
|
+
|
|
151
|
+
const button = el.shadowRoot.querySelector("button")
|
|
152
|
+
expect(button).to.have.attribute("disabled")
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it("lets the click event bubble up", async () => {
|
|
156
|
+
const el = await defaultFixture({ label: "Download" })
|
|
157
|
+
|
|
158
|
+
const button = el.shadowRoot.querySelector("button")
|
|
159
|
+
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
button.click()
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
const event = await oneEvent(el, "click")
|
|
165
|
+
|
|
166
|
+
expect(event).to.exist
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it("does not let the click event bubble up when disabled", async () => {
|
|
170
|
+
const el = await defaultFixture({ label: "Download", disabled: true })
|
|
171
|
+
|
|
172
|
+
const button = el.shadowRoot.querySelector("button")
|
|
173
|
+
const clickSpy = spy()
|
|
174
|
+
button.addEventListener("click", clickSpy)
|
|
175
|
+
|
|
176
|
+
el.click()
|
|
177
|
+
|
|
178
|
+
expect(clickSpy).to.have.not.been.called
|
|
179
|
+
})
|
|
180
|
+
})
|
|
@@ -2,14 +2,22 @@ import { html } from "lit"
|
|
|
2
2
|
import { fixture, expect } from "@open-wc/testing"
|
|
3
3
|
|
|
4
4
|
import "../leu-menu.js"
|
|
5
|
+
import "../leu-menu-item.js"
|
|
5
6
|
|
|
6
7
|
async function defaultFixture() {
|
|
7
|
-
return fixture(html` <leu-menu
|
|
8
|
+
return fixture(html` <leu-menu>
|
|
9
|
+
<leu-menu-item label="Menu Item 1" before="EMPTY"></leu-menu-item>
|
|
10
|
+
<leu-menu-item label="Menu Item 2" before="check" active></leu-menu-item>
|
|
11
|
+
<leu-menu-item label="Menu Item 3" before="EMPTY"></leu-menu-item>
|
|
12
|
+
<hr />
|
|
13
|
+
<leu-menu-item label="Menu Item 3" before="pin" after="CH"></leu-menu-item>
|
|
14
|
+
<leu-menu-item label="Menu Item 4"></leu-menu-item>
|
|
15
|
+
</leu-menu>`)
|
|
8
16
|
}
|
|
9
17
|
|
|
10
18
|
describe("LeuMenu", () => {
|
|
11
19
|
it("is a defined element", async () => {
|
|
12
|
-
const el =
|
|
20
|
+
const el = customElements.get("leu-menu")
|
|
13
21
|
|
|
14
22
|
await expect(el).not.to.be.undefined
|
|
15
23
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { html, LitElement } from "lit"
|
|
2
|
-
import {
|
|
3
|
-
import { defineButtonElements } from "../button/Button.js"
|
|
2
|
+
import { live } from "lit/directives/live.js"
|
|
4
3
|
|
|
4
|
+
import "../button/leu-button.js"
|
|
5
5
|
import styles from "./pagination.css"
|
|
6
6
|
|
|
7
7
|
const MIN_PAGE = 1
|
|
@@ -12,16 +12,22 @@ const MIN_PAGE = 1
|
|
|
12
12
|
export class LeuPagination extends LitElement {
|
|
13
13
|
static styles = styles
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
static shadowRootOptions = {
|
|
19
|
+
...LitElement.shadowRootOptions,
|
|
20
|
+
delegatesFocus: true,
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
static events = {
|
|
16
24
|
range: {},
|
|
17
25
|
}
|
|
18
26
|
|
|
19
27
|
static properties = {
|
|
20
28
|
page: { type: Number, reflect: true },
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
_minPage: { type: Number, state: true },
|
|
29
|
+
itemsPerPage: { type: Number, reflect: true },
|
|
30
|
+
numOfItems: { type: Number, reflect: true },
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
constructor() {
|
|
@@ -29,45 +35,55 @@ export class LeuPagination extends LitElement {
|
|
|
29
35
|
/** @type {number} */
|
|
30
36
|
this.page = 1
|
|
31
37
|
/** @type {number} */
|
|
32
|
-
this.
|
|
38
|
+
this.numOfItems = 1
|
|
33
39
|
/** @type {number} */
|
|
34
|
-
this.
|
|
40
|
+
this.itemsPerPage = 1
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
get maxPage() {
|
|
38
|
-
return Math.ceil(this.
|
|
44
|
+
return Math.ceil(this.numOfItems / this.itemsPerPage)
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
get firstPage() {
|
|
42
|
-
return this.
|
|
48
|
+
return this.boundPage === MIN_PAGE
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
get lastPage() {
|
|
46
|
-
return this.
|
|
52
|
+
return this.boundPage === this.maxPage
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
/**
|
|
56
|
+
* The boundPage getter is necessary to ensure that the current page (this.page) is always within the valid range of pages.
|
|
57
|
+
* It prevents the page number from going below the minimum page limit (MIN_PAGE) or above the maximum page limit (this.maxPage).
|
|
58
|
+
* This is important for the correct functioning of the pagination system, as it prevents users from navigating to non-existent pages.
|
|
59
|
+
*
|
|
60
|
+
* @returns {number}
|
|
61
|
+
*/
|
|
62
|
+
get boundPage() {
|
|
63
|
+
return Math.min(Math.max(this.page, MIN_PAGE), this.maxPage)
|
|
51
64
|
}
|
|
52
65
|
|
|
53
66
|
numberUpdate(number) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
const prevPage = this.page
|
|
68
|
+
this.page = number
|
|
69
|
+
|
|
70
|
+
if (this.page !== prevPage) {
|
|
71
|
+
const startIndex = (this.boundPage - 1) * this.itemsPerPage
|
|
72
|
+
const endIndex = Math.min(startIndex + this.itemsPerPage, this.numOfItems)
|
|
73
|
+
this.dispatchEvent(
|
|
74
|
+
new CustomEvent("leu:pagechange", {
|
|
75
|
+
detail: {
|
|
76
|
+
startIndex,
|
|
77
|
+
endIndex,
|
|
78
|
+
page: this.boundPage,
|
|
79
|
+
},
|
|
80
|
+
bubbles: false,
|
|
81
|
+
})
|
|
82
|
+
)
|
|
83
|
+
}
|
|
67
84
|
}
|
|
68
85
|
|
|
69
86
|
change(event) {
|
|
70
|
-
// target.value = this.page // eslint-disable-line
|
|
71
87
|
this.numberUpdate(parseInt(event.target.value, 10) || 0)
|
|
72
88
|
}
|
|
73
89
|
|
|
@@ -79,46 +95,23 @@ export class LeuPagination extends LitElement {
|
|
|
79
95
|
}
|
|
80
96
|
|
|
81
97
|
keydown(event) {
|
|
82
|
-
|
|
83
|
-
"ArrowUp",
|
|
84
|
-
"ArrowDown",
|
|
85
|
-
"ArrowLeft",
|
|
86
|
-
"ArrowRight",
|
|
87
|
-
"Backspace",
|
|
88
|
-
"Enter",
|
|
89
|
-
"Tab",
|
|
90
|
-
]
|
|
91
|
-
const numberKeys = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
|
|
92
|
-
if (!numberKeys.includes(event.key) && !specialKeys.includes(event.key)) {
|
|
98
|
+
if (event.key === "ArrowUp") {
|
|
93
99
|
event.preventDefault()
|
|
94
|
-
|
|
95
|
-
if (event.key === "ArrowUp") {
|
|
96
|
-
event.preventDefault()
|
|
97
|
-
this.numberUpdate(this.page + 1)
|
|
98
|
-
}
|
|
99
|
-
if (event.key === "ArrowDown") {
|
|
100
|
-
event.preventDefault()
|
|
101
|
-
this.numberUpdate(this.page - 1)
|
|
102
|
-
}
|
|
100
|
+
this.numberUpdate(this.boundPage + 1)
|
|
103
101
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.numberUpdate(this.page)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
requestUpdate(name, oldValue, newValue) {
|
|
111
|
-
if (name === "itemsOnAPage") {
|
|
112
|
-
this.numberUpdate(this.page)
|
|
102
|
+
if (event.key === "ArrowDown") {
|
|
103
|
+
event.preventDefault()
|
|
104
|
+
this.numberUpdate(this.boundPage - 1)
|
|
113
105
|
}
|
|
114
|
-
return super.requestUpdate(name, oldValue, newValue)
|
|
115
106
|
}
|
|
116
107
|
|
|
117
108
|
render() {
|
|
118
109
|
return html`
|
|
119
110
|
<input
|
|
120
111
|
class="input"
|
|
121
|
-
|
|
112
|
+
min=${MIN_PAGE}
|
|
113
|
+
max=${this.maxPage}
|
|
114
|
+
.value=${live(this.boundPage.toString())}
|
|
122
115
|
@input=${this.input}
|
|
123
116
|
@change=${this.change}
|
|
124
117
|
@keydown=${this.keydown}
|
|
@@ -129,7 +122,7 @@ export class LeuPagination extends LitElement {
|
|
|
129
122
|
icon="angleLeft"
|
|
130
123
|
variant="secondary"
|
|
131
124
|
@click=${(_) => {
|
|
132
|
-
this.numberUpdate(this.
|
|
125
|
+
this.numberUpdate(this.boundPage - 1)
|
|
133
126
|
}}
|
|
134
127
|
?disabled=${this.firstPage}
|
|
135
128
|
></leu-button>
|
|
@@ -137,7 +130,7 @@ export class LeuPagination extends LitElement {
|
|
|
137
130
|
icon="angleRight"
|
|
138
131
|
variant="secondary"
|
|
139
132
|
@click=${(_) => {
|
|
140
|
-
this.numberUpdate(this.
|
|
133
|
+
this.numberUpdate(this.boundPage + 1)
|
|
141
134
|
}}
|
|
142
135
|
?disabled=${this.lastPage}
|
|
143
136
|
style="margin-left:4px;"
|
|
@@ -145,8 +138,3 @@ export class LeuPagination extends LitElement {
|
|
|
145
138
|
`
|
|
146
139
|
}
|
|
147
140
|
}
|
|
148
|
-
|
|
149
|
-
export function definePaginationElements() {
|
|
150
|
-
defineButtonElements()
|
|
151
|
-
defineElement("pagination", LeuPagination)
|
|
152
|
-
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineElement } from "../../lib/defineElement.js"
|
|
2
|
+
import { LeuPagination } from "./Pagination.js"
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
export { LeuPagination }
|
|
5
|
+
|
|
6
|
+
defineElement("pagination", LeuPagination)
|
|
@@ -56,18 +56,26 @@ const items = [
|
|
|
56
56
|
export default {
|
|
57
57
|
title: "Pagination",
|
|
58
58
|
component: "leu-pagination",
|
|
59
|
+
parameters: {
|
|
60
|
+
design: {
|
|
61
|
+
type: "figma",
|
|
62
|
+
url: "https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=17341-82468&mode=design&t=lzVrtq8lxYVJU5TB-11",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
function Template({
|
|
67
|
+
function Template({ startIndex, endIndex }, { id }) {
|
|
62
68
|
return html`
|
|
63
|
-
${items
|
|
69
|
+
${items
|
|
70
|
+
.slice(startIndex, endIndex)
|
|
71
|
+
.map((item) => html`<div>${item.label}</div>`)}
|
|
64
72
|
<leu-pagination
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
@
|
|
73
|
+
numOfItems=${items.length}
|
|
74
|
+
itemsPerPage="5"
|
|
75
|
+
@leu:pagechange=${(e) => {
|
|
68
76
|
updateStorybookArgss(id, {
|
|
69
|
-
|
|
70
|
-
|
|
77
|
+
startIndex: e.detail.startIndex,
|
|
78
|
+
endIndex: e.detail.endIndex,
|
|
71
79
|
})
|
|
72
80
|
}}
|
|
73
81
|
>
|
|
@@ -77,6 +85,6 @@ function Template({ min, max }, { id }) {
|
|
|
77
85
|
|
|
78
86
|
export const Regular = Template.bind({})
|
|
79
87
|
Regular.args = {
|
|
80
|
-
|
|
81
|
-
|
|
88
|
+
startIndex: 0,
|
|
89
|
+
endIndex: 5,
|
|
82
90
|
}
|
|
@@ -1,22 +1,208 @@
|
|
|
1
1
|
import { html } from "lit"
|
|
2
|
-
import { fixture, expect } from "@open-wc/testing"
|
|
2
|
+
import { fixture, expect, elementUpdated } from "@open-wc/testing"
|
|
3
|
+
import { ifDefined } from "lit/directives/if-defined.js"
|
|
4
|
+
import { sendKeys } from "@web/test-runner-commands"
|
|
5
|
+
import { spy } from "sinon"
|
|
3
6
|
|
|
4
7
|
import "../leu-pagination.js"
|
|
5
8
|
|
|
6
|
-
async function defaultFixture() {
|
|
7
|
-
return fixture(html
|
|
9
|
+
async function defaultFixture(args = {}) {
|
|
10
|
+
return fixture(html`<leu-pagination
|
|
11
|
+
numOfItems=${ifDefined(args.numOfItems)}
|
|
12
|
+
itemsPerPage=${ifDefined(args.itemsPerPage)}
|
|
13
|
+
page=${ifDefined(args.page)}
|
|
14
|
+
>
|
|
15
|
+
</leu-pagination>`)
|
|
8
16
|
}
|
|
9
17
|
|
|
10
18
|
describe("LeuPagination", () => {
|
|
11
19
|
it("is a defined element", async () => {
|
|
12
|
-
const el =
|
|
20
|
+
const el = customElements.get("leu-pagination")
|
|
13
21
|
|
|
14
22
|
await expect(el).not.to.be.undefined
|
|
15
23
|
})
|
|
16
24
|
|
|
17
25
|
it("passes the a11y audit", async () => {
|
|
18
|
-
const el = await defaultFixture(
|
|
26
|
+
const el = await defaultFixture({
|
|
27
|
+
numOfItems: 98,
|
|
28
|
+
itemsPerPage: 7,
|
|
29
|
+
page: 1,
|
|
30
|
+
})
|
|
19
31
|
|
|
20
32
|
await expect(el).shadowDom.to.be.accessible()
|
|
21
33
|
})
|
|
34
|
+
|
|
35
|
+
it("disables the previous button on the first page", async () => {
|
|
36
|
+
const el = await defaultFixture({
|
|
37
|
+
numOfItems: 98,
|
|
38
|
+
itemsPerPage: 7,
|
|
39
|
+
page: 1,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const previous = el.shadowRoot.querySelectorAll("leu-button")[0]
|
|
43
|
+
|
|
44
|
+
expect(previous).to.have.attribute("disabled")
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it("disables the next button on the last page", async () => {
|
|
48
|
+
const el = await defaultFixture({
|
|
49
|
+
numOfItems: 98,
|
|
50
|
+
itemsPerPage: 7,
|
|
51
|
+
page: 14,
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const next = el.shadowRoot.querySelectorAll("leu-button")[1]
|
|
55
|
+
|
|
56
|
+
expect(next).to.have.attribute("disabled")
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it("renders the correct number of available pages", async () => {
|
|
60
|
+
const el = await defaultFixture({
|
|
61
|
+
numOfItems: 98,
|
|
62
|
+
itemsPerPage: 7,
|
|
63
|
+
page: 1,
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
const label = el.shadowRoot.querySelectorAll(".label")
|
|
67
|
+
|
|
68
|
+
expect(label).to.have.trimmed.text("von 14")
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it("displays the current page", async () => {
|
|
72
|
+
const el = await defaultFixture({
|
|
73
|
+
numOfItems: 98,
|
|
74
|
+
itemsPerPage: 7,
|
|
75
|
+
page: 2,
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const input = el.shadowRoot.querySelector("input")
|
|
79
|
+
|
|
80
|
+
expect(input.value).to.equal("2")
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it("increments the page with a click on the next button", async () => {
|
|
84
|
+
const el = await defaultFixture({
|
|
85
|
+
numOfItems: 98,
|
|
86
|
+
itemsPerPage: 7,
|
|
87
|
+
page: 1,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
const next = el.shadowRoot.querySelectorAll("leu-button")[1]
|
|
91
|
+
|
|
92
|
+
next.click()
|
|
93
|
+
await elementUpdated(el)
|
|
94
|
+
|
|
95
|
+
expect(el.page).to.equal(2)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it("decrements the page with a click on the prev button", async () => {
|
|
99
|
+
const el = await defaultFixture({
|
|
100
|
+
numOfItems: 98,
|
|
101
|
+
itemsPerPage: 7,
|
|
102
|
+
page: 10,
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const next = el.shadowRoot.querySelectorAll("leu-button")[0]
|
|
106
|
+
|
|
107
|
+
next.click()
|
|
108
|
+
await elementUpdated(el)
|
|
109
|
+
|
|
110
|
+
expect(el.page).to.equal(9)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it("increments the page with pressing the arrow up key", async () => {
|
|
114
|
+
const el = await defaultFixture({
|
|
115
|
+
numOfItems: 98,
|
|
116
|
+
itemsPerPage: 7,
|
|
117
|
+
page: 1,
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
el.focus()
|
|
121
|
+
|
|
122
|
+
await sendKeys({
|
|
123
|
+
press: "ArrowUp",
|
|
124
|
+
})
|
|
125
|
+
await elementUpdated(el)
|
|
126
|
+
|
|
127
|
+
expect(el.page).to.equal(2)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
it("decrements the page with pressing the arrow down key", async () => {
|
|
131
|
+
const el = await defaultFixture({
|
|
132
|
+
numOfItems: 98,
|
|
133
|
+
itemsPerPage: 7,
|
|
134
|
+
page: 13,
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
el.focus()
|
|
138
|
+
|
|
139
|
+
await sendKeys({
|
|
140
|
+
press: "ArrowDown",
|
|
141
|
+
})
|
|
142
|
+
await elementUpdated(el)
|
|
143
|
+
|
|
144
|
+
expect(el.page).to.equal(12)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it("bounds the page to the max and min values", async () => {
|
|
148
|
+
const el = await defaultFixture({
|
|
149
|
+
numOfItems: 50,
|
|
150
|
+
itemsPerPage: 10,
|
|
151
|
+
page: 6,
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
const input = el.shadowRoot.querySelector("input")
|
|
155
|
+
|
|
156
|
+
expect(el.boundPage).to.equal(5)
|
|
157
|
+
expect(input.value).to.equal("5")
|
|
158
|
+
|
|
159
|
+
el.page = 0
|
|
160
|
+
await elementUpdated(el)
|
|
161
|
+
|
|
162
|
+
expect(el.boundPage).to.equal(1)
|
|
163
|
+
expect(input.value).to.equal("1")
|
|
164
|
+
|
|
165
|
+
el.focus()
|
|
166
|
+
|
|
167
|
+
await sendKeys({
|
|
168
|
+
press: "ArrowDown",
|
|
169
|
+
})
|
|
170
|
+
await elementUpdated(el)
|
|
171
|
+
|
|
172
|
+
expect(el.boundPage).to.equal(1)
|
|
173
|
+
expect(input.value).to.equal("1")
|
|
174
|
+
|
|
175
|
+
await sendKeys({ press: "ArrowUp" })
|
|
176
|
+
await sendKeys({ press: "ArrowUp" })
|
|
177
|
+
await sendKeys({ press: "ArrowUp" })
|
|
178
|
+
await sendKeys({ press: "ArrowUp" })
|
|
179
|
+
await sendKeys({ press: "ArrowUp" })
|
|
180
|
+
|
|
181
|
+
expect(el.boundPage).to.equal(5)
|
|
182
|
+
expect(input.value).to.equal("5")
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it("fires a leu:pagechange event", async () => {
|
|
186
|
+
const el = await defaultFixture({
|
|
187
|
+
numOfItems: 98,
|
|
188
|
+
itemsPerPage: 7,
|
|
189
|
+
page: 14,
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
const eventSpy = spy()
|
|
193
|
+
el.addEventListener("leu:pagechange", eventSpy)
|
|
194
|
+
|
|
195
|
+
const prevButton = el.shadowRoot.querySelectorAll("leu-button")[0]
|
|
196
|
+
const nextButton = el.shadowRoot.querySelectorAll("leu-button")[1]
|
|
197
|
+
|
|
198
|
+
nextButton.click()
|
|
199
|
+
prevButton.click()
|
|
200
|
+
|
|
201
|
+
el.focus()
|
|
202
|
+
|
|
203
|
+
await sendKeys({ press: "ArrowUp" })
|
|
204
|
+
await sendKeys({ press: "ArrowDown" })
|
|
205
|
+
|
|
206
|
+
expect(eventSpy).to.have.been.called.callCount(4)
|
|
207
|
+
})
|
|
22
208
|
})
|