@statistikzh/leu 0.13.1 → 0.14.1
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/.eslintrc.json +8 -0
- package/.github/workflows/ci.yml +78 -0
- package/.github/workflows/deploy-github-pages.yaml +2 -1
- package/.github/workflows/release-please.yml +2 -1
- package/.nvmrc +1 -0
- package/.prettierignore +1 -0
- package/.storybook/main.js +19 -3
- package/.storybook/preview.js +11 -0
- package/CHANGELOG.md +27 -0
- package/README.md +0 -67
- package/custom-elements-manifest.config.js +2 -2
- package/dist/Accordion.d.ts +1 -1
- package/dist/Accordion.js +8 -8
- package/dist/Button.d.ts +2 -2
- package/dist/Button.js +2 -2
- package/dist/ButtonGroup.d.ts +1 -1
- package/dist/ButtonGroup.js +1 -1
- package/dist/Checkbox.d.ts +1 -1
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox.js +2 -3
- package/dist/CheckboxGroup.d.ts +1 -1
- package/dist/CheckboxGroup.d.ts.map +1 -1
- package/dist/CheckboxGroup.js +1 -3
- package/dist/Chip.d.ts +1 -1
- package/dist/Chip.d.ts.map +1 -1
- package/dist/Chip.js +1 -3
- package/dist/ChipGroup.d.ts +1 -1
- package/dist/ChipGroup.d.ts.map +1 -1
- package/dist/ChipGroup.js +2 -2
- package/dist/ChipLink.js +1 -1
- package/dist/ChipRemovable.js +1 -1
- package/dist/ChipSelectable.js +1 -1
- package/dist/Dialog.d.ts +1 -1
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js +3 -5
- package/dist/Dropdown.d.ts +1 -1
- package/dist/Dropdown.js +3 -3
- package/dist/Icon.d.ts +2 -98
- package/dist/Icon.d.ts.map +1 -1
- package/dist/Icon.js +1 -1
- package/dist/Input.d.ts +8 -3
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +18 -12
- package/dist/{LeuElement-b670d77c.d.ts → LeuElement-DH0PPSMq.d.ts} +1 -1
- package/dist/LeuElement-DH0PPSMq.d.ts.map +1 -0
- package/dist/{LeuElement-b670d77c.js → LeuElement-DH0PPSMq.js} +2 -2
- package/dist/Menu.d.ts +2 -2
- package/dist/Menu.js +1 -1
- package/dist/MenuItem.d.ts +3 -3
- package/dist/MenuItem.js +1 -1
- package/dist/Pagination.d.ts +1 -1
- package/dist/Pagination.js +3 -3
- package/dist/Popup.d.ts +2 -2
- package/dist/Popup.d.ts.map +1 -1
- package/dist/Popup.js +1 -3
- package/dist/Radio.d.ts +1 -1
- package/dist/Radio.d.ts.map +1 -1
- package/dist/Radio.js +1 -3
- package/dist/RadioGroup.d.ts +1 -1
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +1 -3
- package/dist/Range.d.ts +1 -1
- package/dist/Range.d.ts.map +1 -1
- package/dist/Range.js +17 -19
- package/dist/ScrollTop.d.ts +1 -1
- package/dist/ScrollTop.d.ts.map +1 -1
- package/dist/ScrollTop.js +27 -3
- package/dist/Select.d.ts +3 -7
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +7 -18
- package/dist/Spinner.d.ts +1 -1
- package/dist/Spinner.js +1 -1
- package/dist/Table.d.ts +1 -1
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +3 -4
- package/dist/VisuallyHidden.d.ts +1 -1
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden.js +3 -5
- package/dist/{hasSlotController-c09741c5.d.ts → hasSlotController-CYd5tWew.d.ts} +1 -1
- package/dist/hasSlotController-CYd5tWew.d.ts.map +1 -0
- package/dist/{hasSlotController-c09741c5.js → hasSlotController-CYd5tWew.js} +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +5 -7
- package/dist/leu-accordion.js +1 -1
- package/dist/leu-button-group.js +1 -1
- package/dist/leu-button.js +2 -2
- 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 +2 -2
- package/dist/leu-dropdown.js +2 -2
- 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-pagination.js +2 -2
- package/dist/leu-popup.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 +2 -3
- package/dist/leu-select.js +2 -2
- package/dist/leu-spinner.js +1 -1
- package/dist/leu-table.js +2 -2
- package/dist/leu-visually-hidden.js +1 -1
- package/dist/theme.css +143 -107
- package/dist/vscode.html-custom-data.json +4 -33
- package/dist/vue/index.d.ts +11 -78
- package/dist/web-types.json +247 -243
- package/index.js +0 -1
- package/package.json +55 -51
- package/rollup.config.js +3 -3
- package/scripts/generate-component/generate.js +5 -5
- package/scripts/generate-component/templates/stories/[name].stories.js +1 -1
- package/src/components/accordion/Accordion.js +1 -1
- package/src/components/accordion/accordion.css +6 -3
- package/src/components/accordion/stories/accordion.stories.js +7 -6
- package/src/components/accordion/test/accordion.test.js +24 -20
- package/src/components/button/Button.js +1 -1
- package/src/components/button/stories/button.stories.js +44 -46
- package/src/components/button/test/button.test.js +10 -10
- package/src/components/button-group/ButtonGroup.js +1 -1
- package/src/components/button-group/stories/button-group.stories.js +3 -3
- package/src/components/checkbox/checkbox.css +1 -0
- package/src/components/checkbox/stories/checkbox-group.stories.js +1 -1
- package/src/components/checkbox/stories/checkbox.stories.js +1 -1
- package/src/components/chip/ChipSelectable.js +1 -1
- package/src/components/chip/stories/chip-group.stories.js +5 -5
- package/src/components/chip/stories/chip-link.stories.js +1 -1
- package/src/components/chip/stories/chip-removable.stories.js +1 -1
- package/src/components/chip/stories/chip-selectable.stories.js +1 -1
- package/src/components/chip/test/chip-group.test.js +25 -33
- package/src/components/chip/test/chip-link.test.js +5 -5
- package/src/components/chip/test/chip-removable.test.js +6 -8
- package/src/components/chip/test/chip-selectable.test.js +9 -11
- package/src/components/dialog/stories/dialog.stories.js +1 -1
- package/src/components/dialog/test/dialog.test.js +1 -1
- package/src/components/dropdown/stories/dropdown.stories.js +1 -1
- package/src/components/dropdown/test/dropdown.test.js +12 -13
- package/src/components/icon/stories/icon.stories.js +1 -1
- package/src/components/input/Input.js +26 -18
- package/src/components/input/input.css +2 -2
- package/src/components/input/stories/input.stories.js +1 -4
- package/src/components/input/test/input.test.js +26 -0
- package/src/components/menu/stories/menu-item.stories.js +3 -1
- package/src/components/menu/stories/menu.stories.js +1 -1
- package/src/components/menu/test/menu-item.test.js +3 -2
- package/src/components/menu/test/menu.test.js +24 -22
- package/src/components/pagination/Pagination.js +1 -1
- package/src/components/pagination/pagination.css +1 -1
- package/src/components/pagination/stories/pagination.stories.js +3 -2
- package/src/components/pagination/test/pagination.test.js +8 -6
- package/src/components/popup/Popup.js +4 -4
- package/src/components/popup/stories/popup.stories.js +1 -1
- package/src/components/popup/test/popup.test.js +6 -8
- package/src/components/radio/RadioGroup.js +2 -2
- package/src/components/radio/stories/radio-group.stories.js +1 -1
- package/src/components/radio/stories/radio.stories.js +1 -1
- package/src/components/range/Range.js +20 -21
- package/src/components/range/stories/range-slider.stories.js +1 -1
- package/src/components/scroll-top/stories/scroll-top.stories.js +1 -1
- package/src/components/select/Select.js +7 -18
- package/src/components/select/stories/select.stories.js +3 -3
- package/src/components/select/test/select.test.js +18 -16
- package/src/components/spinner/stories/spinner.stories.js +1 -1
- package/src/components/table/Table.js +4 -4
- package/src/components/table/stories/table.stories.js +1 -1
- package/src/components/table/test/table.test.js +3 -2
- package/src/components/visually-hidden/stories/visually-hidden.stories.js +1 -1
- package/src/components/visually-hidden/test/visually-hidden.test.js +6 -8
- package/src/docs/contributing.mdx +154 -0
- package/src/docs/installation.mdx +35 -0
- package/src/docs/theme.mdx +349 -0
- package/src/docs/usage.mdx +73 -0
- package/src/lib/LeuElement.js +2 -2
- package/src/lib/hasSlotController.js +1 -1
- package/src/styles/style.stories.js +4 -2
- package/tsconfig.build.json +4 -3
- package/web-dev-server.config.mjs +1 -0
- package/web-test-runner.config.mjs +1 -1
- package/.github/workflows/test.yml +0 -38
- package/.storybook/preview-head.html +0 -2
- package/dist/Breadcrumb.d.ts +0 -69
- package/dist/Breadcrumb.d.ts.map +0 -1
- package/dist/Breadcrumb.js +0 -391
- package/dist/LeuElement-b670d77c.d.ts.map +0 -1
- package/dist/hasSlotController-c09741c5.d.ts.map +0 -1
- package/dist/leu-breadcrumb.d.ts +0 -3
- package/dist/leu-breadcrumb.d.ts.map +0 -1
- package/dist/leu-breadcrumb.js +0 -17
- package/dist/utils-65469421.d.ts +0 -16
- package/dist/utils-65469421.d.ts.map +0 -1
- package/dist/utils-65469421.js +0 -35
- package/src/components/breadcrumb/Breadcrumb.js +0 -324
- package/src/components/breadcrumb/breadcrumb.css +0 -98
- package/src/components/breadcrumb/leu-breadcrumb.js +0 -5
- package/src/components/breadcrumb/stories/breadcrumb.stories.js +0 -73
- package/src/components/breadcrumb/test/breadcrumb.test.js +0 -141
|
@@ -7,12 +7,14 @@ import { spy } from "sinon"
|
|
|
7
7
|
import "../leu-pagination.js"
|
|
8
8
|
|
|
9
9
|
async function defaultFixture(args = {}) {
|
|
10
|
-
return fixture(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
return fixture(
|
|
11
|
+
html`<leu-pagination
|
|
12
|
+
numOfItems=${ifDefined(args.numOfItems)}
|
|
13
|
+
itemsPerPage=${ifDefined(args.itemsPerPage)}
|
|
14
|
+
defaultPage=${ifDefined(args.defaultPage)}
|
|
15
|
+
>
|
|
16
|
+
</leu-pagination>`,
|
|
17
|
+
)
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
describe("LeuPagination", () => {
|
|
@@ -130,7 +130,7 @@ export class LeuPopup extends LeuElement {
|
|
|
130
130
|
? `${rects.reference.height}px`
|
|
131
131
|
: ""
|
|
132
132
|
},
|
|
133
|
-
})
|
|
133
|
+
}),
|
|
134
134
|
)
|
|
135
135
|
} else {
|
|
136
136
|
// Cleanup styles if we're not matching width/height
|
|
@@ -159,7 +159,7 @@ export class LeuPopup extends LeuElement {
|
|
|
159
159
|
if (setMaxHeight) {
|
|
160
160
|
this.style.setProperty(
|
|
161
161
|
"--auto-size-available-height",
|
|
162
|
-
`${availableHeight}px
|
|
162
|
+
`${availableHeight}px`,
|
|
163
163
|
)
|
|
164
164
|
} else {
|
|
165
165
|
this.style.removeProperty("--auto-size-available-height")
|
|
@@ -168,13 +168,13 @@ export class LeuPopup extends LeuElement {
|
|
|
168
168
|
if (setMaxWidth) {
|
|
169
169
|
this.style.setProperty(
|
|
170
170
|
"--auto-size-available-width",
|
|
171
|
-
`${availableWidth}px
|
|
171
|
+
`${availableWidth}px`,
|
|
172
172
|
)
|
|
173
173
|
} else {
|
|
174
174
|
this.style.removeProperty("--auto-size-available-width")
|
|
175
175
|
}
|
|
176
176
|
},
|
|
177
|
-
})
|
|
177
|
+
}),
|
|
178
178
|
)
|
|
179
179
|
} else {
|
|
180
180
|
// Cleanup styles if we're not auto-sizing
|
|
@@ -4,14 +4,12 @@ import { fixture, expect } from "@open-wc/testing"
|
|
|
4
4
|
import "../leu-popup.js"
|
|
5
5
|
|
|
6
6
|
async function defaultFixture() {
|
|
7
|
-
return fixture(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
`
|
|
14
|
-
)
|
|
7
|
+
return fixture(html`
|
|
8
|
+
<leu-popup
|
|
9
|
+
><div slot="anchor"></div>
|
|
10
|
+
<p>Popup content</p></leu-popup
|
|
11
|
+
>
|
|
12
|
+
`)
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
describe("LeuPopup", () => {
|
|
@@ -143,10 +143,10 @@ export class LeuRadioGroup extends LeuElement {
|
|
|
143
143
|
|
|
144
144
|
initializeIndex() {
|
|
145
145
|
const index = this.items.findIndex(
|
|
146
|
-
(item) => item.hasAttribute("checked") && !item.hasAttribute("disabled")
|
|
146
|
+
(item) => item.hasAttribute("checked") && !item.hasAttribute("disabled"),
|
|
147
147
|
)
|
|
148
148
|
const nextEnabledIndex = this.items.findIndex(
|
|
149
|
-
(item) => !item.hasAttribute("disabled")
|
|
149
|
+
(item) => !item.hasAttribute("disabled"),
|
|
150
150
|
)
|
|
151
151
|
|
|
152
152
|
this._currentIndex = index >= 0 ? index : nextEnabledIndex
|
|
@@ -96,7 +96,7 @@ export class LeuRange extends LeuElement {
|
|
|
96
96
|
|
|
97
97
|
get valueAsArray() {
|
|
98
98
|
return Array.from(this.shadowRoot.querySelectorAll("input")).map(
|
|
99
|
-
(input) => input.valueAsNumber
|
|
99
|
+
(input) => input.valueAsNumber,
|
|
100
100
|
)
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -205,30 +205,29 @@ export class LeuRange extends LeuElement {
|
|
|
205
205
|
class="output"
|
|
206
206
|
for="input-${type}"
|
|
207
207
|
value=${defaultValue[index]}
|
|
208
|
-
></output
|
|
208
|
+
></output>`,
|
|
209
209
|
)}
|
|
210
210
|
</div>
|
|
211
211
|
<div class="inputs">
|
|
212
212
|
${inputs.map(
|
|
213
|
-
(type, index) =>
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
`
|
|
213
|
+
(type, index) => html`
|
|
214
|
+
<input
|
|
215
|
+
@input=${(e) => this._handleInput(index, e)}
|
|
216
|
+
@pointerdown=${multiple && !disabled && index === 0
|
|
217
|
+
? this._handlePointerDown
|
|
218
|
+
: undefined}
|
|
219
|
+
type="range"
|
|
220
|
+
class="range range--${type}"
|
|
221
|
+
id="input-${type}"
|
|
222
|
+
name=${this.name}
|
|
223
|
+
min=${this.min}
|
|
224
|
+
max=${this.max}
|
|
225
|
+
step=${this.step}
|
|
226
|
+
aria-label=${multiple ? RANGE_LABELS[index] : undefined}
|
|
227
|
+
?disabled=${disabled}
|
|
228
|
+
.value=${defaultValue[index].toString()}
|
|
229
|
+
/>
|
|
230
|
+
`,
|
|
232
231
|
)}
|
|
233
232
|
</div>
|
|
234
233
|
</div>
|
|
@@ -171,6 +171,10 @@ export class LeuSelect extends LeuElement {
|
|
|
171
171
|
const menuItems = menu.getMenuItems()
|
|
172
172
|
let hasFilterResults = false
|
|
173
173
|
|
|
174
|
+
if (changed.value && this.value.length === 0) {
|
|
175
|
+
this._displayValue = ""
|
|
176
|
+
}
|
|
177
|
+
|
|
174
178
|
/* eslint-disable no-param-reassign */
|
|
175
179
|
menuItems.forEach((menuItem) => {
|
|
176
180
|
if (changed.multiple) {
|
|
@@ -352,18 +356,6 @@ export class LeuSelect extends LeuElement {
|
|
|
352
356
|
}
|
|
353
357
|
}
|
|
354
358
|
|
|
355
|
-
/**
|
|
356
|
-
* Close the dropdown if the focus moves outside the component.
|
|
357
|
-
*/
|
|
358
|
-
_handlePopupFocusOut(event) {
|
|
359
|
-
if (
|
|
360
|
-
!this.contains(event.relatedTarget) &&
|
|
361
|
-
!this.shadowRoot.contains(event.relatedTarget)
|
|
362
|
-
) {
|
|
363
|
-
this._closeDropdown()
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
359
|
_renderFilterInput() {
|
|
368
360
|
if (this.filterable) {
|
|
369
361
|
return html` <leu-input
|
|
@@ -463,21 +455,18 @@ export class LeuSelect extends LeuElement {
|
|
|
463
455
|
autoSizePadding="8"
|
|
464
456
|
>
|
|
465
457
|
${this._renderToggleButton()}
|
|
466
|
-
<div
|
|
467
|
-
id="select-popup"
|
|
468
|
-
class="select-menu-container"
|
|
469
|
-
@focusout=${this._handlePopupFocusOut}
|
|
470
|
-
>
|
|
458
|
+
<div id="select-popup" class="select-menu-container">
|
|
471
459
|
<slot name="before" class="before"></slot>
|
|
472
460
|
${this._renderFilterInput()}
|
|
473
461
|
<leu-menu
|
|
474
462
|
ref=${ref(this._menuRef)}
|
|
475
463
|
role="listbox"
|
|
476
464
|
aria-multiselectable=${ifDefined(
|
|
477
|
-
this.multiple ? "true" : undefined
|
|
465
|
+
this.multiple ? "true" : undefined,
|
|
478
466
|
)}
|
|
479
467
|
class="menu"
|
|
480
468
|
@click=${this._handleMenuItemClick}
|
|
469
|
+
aria-labelledby="select-label"
|
|
481
470
|
>
|
|
482
471
|
<slot></slot>
|
|
483
472
|
</leu-menu>
|
|
@@ -8,7 +8,7 @@ import "../../menu/leu-menu-item.js"
|
|
|
8
8
|
import { MUNICIPALITIES } from "../test/fixtures.js"
|
|
9
9
|
|
|
10
10
|
export default {
|
|
11
|
-
title: "Select",
|
|
11
|
+
title: "Components/Select",
|
|
12
12
|
component: "leu-select",
|
|
13
13
|
parameters: {
|
|
14
14
|
design: {
|
|
@@ -59,7 +59,7 @@ function Template({
|
|
|
59
59
|
>
|
|
60
60
|
${LeuSelect.getOptionLabel(option)}
|
|
61
61
|
</leu-menu-item>
|
|
62
|
-
|
|
62
|
+
`,
|
|
63
63
|
)}
|
|
64
64
|
</leu-select>
|
|
65
65
|
<div style="margin-top: 50vh"></div>
|
|
@@ -68,7 +68,7 @@ function Template({
|
|
|
68
68
|
|
|
69
69
|
function TemplateSlots(args) {
|
|
70
70
|
const before = html`<div>before</div>`
|
|
71
|
-
const after = html`<div>after <input type="text"
|
|
71
|
+
const after = html`<div>after <input type="text" /></div>`
|
|
72
72
|
|
|
73
73
|
return Template({ ...args, before, after })
|
|
74
74
|
}
|
|
@@ -8,16 +8,18 @@ import "../../menu/leu-menu-item.js"
|
|
|
8
8
|
import { MUNICIPALITIES } from "./fixtures.js"
|
|
9
9
|
|
|
10
10
|
async function defaultFixture(args = {}) {
|
|
11
|
-
return fixture(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
return fixture(
|
|
12
|
+
html`<leu-select
|
|
13
|
+
label=${ifDefined(args.label)}
|
|
14
|
+
.value=${args.value ?? []}
|
|
15
|
+
?clearable=${args.clearable}
|
|
16
|
+
?disabled=${args.disabled}
|
|
17
|
+
?filterable=${args.filterable}
|
|
18
|
+
?multiple=${args.multiple}
|
|
19
|
+
>
|
|
20
|
+
${args.options.map((o) => html`<leu-menu-item>${o}</leu-menu-item>`)}
|
|
21
|
+
</leu-select> `,
|
|
22
|
+
)
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
describe("LeuSelect", () => {
|
|
@@ -114,7 +116,7 @@ describe("LeuSelect", () => {
|
|
|
114
116
|
const menuItems = Array.from(el.querySelectorAll("leu-menu-item"))
|
|
115
117
|
|
|
116
118
|
const menuItem = menuItems.find(
|
|
117
|
-
(item) => item.textContent === "Affoltern am Albis"
|
|
119
|
+
(item) => item.textContent === "Affoltern am Albis",
|
|
118
120
|
)
|
|
119
121
|
|
|
120
122
|
expect(menuItem).to.have.attribute("active")
|
|
@@ -204,7 +206,7 @@ describe("LeuSelect", () => {
|
|
|
204
206
|
|
|
205
207
|
const menuItems = el.querySelectorAll("leu-menu-item")
|
|
206
208
|
const visibleMenuItems = Array.from(menuItems).filter(
|
|
207
|
-
(menuItem) => !menuItem.hidden
|
|
209
|
+
(menuItem) => !menuItem.hidden,
|
|
208
210
|
)
|
|
209
211
|
expect(visibleMenuItems.length).to.equal(6)
|
|
210
212
|
})
|
|
@@ -231,7 +233,7 @@ describe("LeuSelect", () => {
|
|
|
231
233
|
|
|
232
234
|
const menuItems = el.querySelectorAll("leu-menu-item")
|
|
233
235
|
const visibleMenuItems = Array.from(menuItems).filter(
|
|
234
|
-
(menuItem) => !menuItem.hidden
|
|
236
|
+
(menuItem) => !menuItem.hidden,
|
|
235
237
|
)
|
|
236
238
|
|
|
237
239
|
expect(visibleMenuItems.length).to.equal(MUNICIPALITIES.length)
|
|
@@ -296,7 +298,7 @@ describe("LeuSelect", () => {
|
|
|
296
298
|
toggleButton.click()
|
|
297
299
|
|
|
298
300
|
const menuItem = Array.from(el.querySelectorAll("leu-menu-item")).find(
|
|
299
|
-
(item) => item.textContent === "Maur"
|
|
301
|
+
(item) => item.textContent === "Maur",
|
|
300
302
|
)
|
|
301
303
|
menuItem.click()
|
|
302
304
|
|
|
@@ -331,7 +333,7 @@ describe("LeuSelect", () => {
|
|
|
331
333
|
toggleButton.click()
|
|
332
334
|
|
|
333
335
|
const menuItem = Array.from(el.querySelectorAll("leu-menu-item")).find(
|
|
334
|
-
(item) => item.textContent === "Hedingen"
|
|
336
|
+
(item) => item.textContent === "Hedingen",
|
|
335
337
|
)
|
|
336
338
|
menuItem.click()
|
|
337
339
|
|
|
@@ -350,7 +352,7 @@ describe("LeuSelect", () => {
|
|
|
350
352
|
toggleButton.click()
|
|
351
353
|
|
|
352
354
|
const menuItem = Array.from(el.querySelectorAll("leu-menu-item")).find(
|
|
353
|
-
(item) => item.textContent === "Hedingen"
|
|
355
|
+
(item) => item.textContent === "Hedingen",
|
|
354
356
|
)
|
|
355
357
|
menuItem.click()
|
|
356
358
|
|
|
@@ -141,7 +141,7 @@ export class LeuTable extends LeuElement {
|
|
|
141
141
|
return this.itemsPerPage && this.itemsPerPage > 0
|
|
142
142
|
? this._sortedData.slice(
|
|
143
143
|
(this._page - 1) * this.itemsPerPage,
|
|
144
|
-
this._page * this.itemsPerPage
|
|
144
|
+
this._page * this.itemsPerPage,
|
|
145
145
|
)
|
|
146
146
|
: this._sortedData
|
|
147
147
|
}
|
|
@@ -214,7 +214,7 @@ export class LeuTable extends LeuElement {
|
|
|
214
214
|
: nothing}
|
|
215
215
|
</button>`
|
|
216
216
|
: col.name}
|
|
217
|
-
</th
|
|
217
|
+
</th>`,
|
|
218
218
|
)}
|
|
219
219
|
</tr>
|
|
220
220
|
</thead>
|
|
@@ -226,9 +226,9 @@ export class LeuTable extends LeuElement {
|
|
|
226
226
|
(col) =>
|
|
227
227
|
html`<td style=${bodyStyle(col, row)}>
|
|
228
228
|
${col.value(row)}
|
|
229
|
-
</td
|
|
229
|
+
</td>`,
|
|
230
230
|
)}
|
|
231
|
-
</tr
|
|
231
|
+
</tr>`,
|
|
232
232
|
)}
|
|
233
233
|
</tbody>
|
|
234
234
|
</table>
|
|
@@ -17,8 +17,9 @@ const data = [
|
|
|
17
17
|
]
|
|
18
18
|
|
|
19
19
|
async function defaultFixture() {
|
|
20
|
-
return fixture(
|
|
21
|
-
|
|
20
|
+
return fixture(
|
|
21
|
+
html`<leu-table .columns=${columns} .data=${data}> </leu-table>`,
|
|
22
|
+
)
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
describe("LeuTable", () => {
|
|
@@ -4,13 +4,11 @@ import { fixture, expect } from "@open-wc/testing"
|
|
|
4
4
|
import "../leu-visually-hidden.js"
|
|
5
5
|
|
|
6
6
|
async function defaultFixture() {
|
|
7
|
-
return fixture(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
`
|
|
13
|
-
)
|
|
7
|
+
return fixture(html`
|
|
8
|
+
<leu-visually-hidden>
|
|
9
|
+
This is a text that shouldn't be visible but still accessible.
|
|
10
|
+
</leu-visually-hidden>
|
|
11
|
+
`)
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
describe("LeuVisuallyHidden", () => {
|
|
@@ -30,7 +28,7 @@ describe("LeuVisuallyHidden", () => {
|
|
|
30
28
|
const el = await defaultFixture()
|
|
31
29
|
|
|
32
30
|
expect(el).dom.to.equal(
|
|
33
|
-
"<leu-visually-hidden>This is a text that shouldn't be visible but still accessible.</leu-visually-hidden>"
|
|
31
|
+
"<leu-visually-hidden>This is a text that shouldn't be visible but still accessible.</leu-visually-hidden>",
|
|
34
32
|
)
|
|
35
33
|
})
|
|
36
34
|
})
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Meta, Markdown } from "@storybook/blocks"
|
|
2
|
+
|
|
3
|
+
<Meta title="Introduction/Contributing" />
|
|
4
|
+
|
|
5
|
+
# Contributing
|
|
6
|
+
|
|
7
|
+
Contributing to this project is highly appreciated. We are happy to receive feedback, bug reports, feature requests, and pull requests.
|
|
8
|
+
|
|
9
|
+
## Web compenents
|
|
10
|
+
|
|
11
|
+
Leu is entirely built with the lit library and custom elements.
|
|
12
|
+
If you haven't worked with either of them before, [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements) has a good introduction to custom elements.
|
|
13
|
+
The [lit documentation](https://lit.dev/docs/) is a good starting point to get to know the library.
|
|
14
|
+
|
|
15
|
+
## Create a new component
|
|
16
|
+
|
|
17
|
+
To create a starting point for a new component, run
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
./scripts/generate-component/generate.js
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Running it with `--help` will show you all available options.
|
|
24
|
+
|
|
25
|
+
It creates a basic structure for a new component in the `src/components` directory.
|
|
26
|
+
|
|
27
|
+
## Linting and formatting
|
|
28
|
+
|
|
29
|
+
This project uses eslint and prettier to lint and format the code.
|
|
30
|
+
commitlint is also used the enforce conventional commit messages.
|
|
31
|
+
|
|
32
|
+
To scan the project for linting and formatting errors, run
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm run lint
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
To automatically fix linting and formatting errors, run
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm run format
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Testing with Web Test Runner
|
|
45
|
+
|
|
46
|
+
To execute a single test run:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run test
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
To run the tests in interactive watch mode run:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm run test:watch
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Demoing with Storybook
|
|
59
|
+
|
|
60
|
+
To run a local instance of Storybook for your component, run
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm run storybook
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Development guidelines
|
|
67
|
+
|
|
68
|
+
A few rules are necessary when developing a component library. The following conventions and guidelines should be followed when new features are implemented.
|
|
69
|
+
|
|
70
|
+
At the same time they're not set in stone. If the there is a good reason to change them open a pull request.
|
|
71
|
+
|
|
72
|
+
### Naming
|
|
73
|
+
|
|
74
|
+
Every element or custom property that will be globally available has to be prefixed with `leu`.
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
/* Custom elements */
|
|
78
|
+
class LeuRadio extends LeuElement {
|
|
79
|
+
...
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
window.customElements.define("leu-input", LeuInput)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```css
|
|
86
|
+
/* CSS custom property of the theme */
|
|
87
|
+
:root {
|
|
88
|
+
--leu-color-black-0: #000;
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Scoped styles
|
|
93
|
+
|
|
94
|
+
All CSS declarations have to live inside a custom element. This way we ensure that the styles won't interfere with the environment they're loaded into.
|
|
95
|
+
Styles that are shared between components should be defined as global custom properties inside the `styles/custom-properties.css`.
|
|
96
|
+
When a global custom property is used inside a component it could be a good practice to assign them to a local custom property with a semantic naming.
|
|
97
|
+
This only make a sense when the component has a certain complexity and the global custom property are used multiple times.
|
|
98
|
+
|
|
99
|
+
```css
|
|
100
|
+
:host {
|
|
101
|
+
--radio-color-disabled: var(--leu-color-black-20);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Value property
|
|
106
|
+
|
|
107
|
+
All custom elements that contain a value of some sort (like an input or select fields) have to implement a `value` property.
|
|
108
|
+
Everytime the value of the `value` property changes a `input` event has to be dispatched.
|
|
109
|
+
This behaviour matches the way [Observable](https://observablehq.com) handles and observes changes of values that are contained in arbitrary elements. We decided to take over this pattern as it is usable in every other environment too.
|
|
110
|
+
|
|
111
|
+
### Custom events
|
|
112
|
+
|
|
113
|
+
Name of custom events have to be prefixed with `leu:`.
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
this.dispatchEvent(new Event("leu:select", { bubbles: true, composed: true }))
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Dependencies
|
|
120
|
+
|
|
121
|
+
We try to use as little non-dev dependencies as possible. The following dependencies are used:
|
|
122
|
+
|
|
123
|
+
- `lit` is used to build all components.
|
|
124
|
+
- `@floating-ui/dom` is used to position tooltips etc.
|
|
125
|
+
|
|
126
|
+
### Composability
|
|
127
|
+
|
|
128
|
+
Components should be composable. This means that it should be possible to use them in combination with other components without any problems.
|
|
129
|
+
It can also make sense to split a component into multiple smaller components.
|
|
130
|
+
|
|
131
|
+
The `leu-dropdown` element is a good example for this.
|
|
132
|
+
|
|
133
|
+
```html
|
|
134
|
+
<leu-dropdown label="Download">
|
|
135
|
+
<leu-menu>
|
|
136
|
+
<leu-menu-item>PDF</leu-menu-item>
|
|
137
|
+
<leu-menu-item>CSV</leu-menu-item>
|
|
138
|
+
<leu-menu-item>Excel</leu-menu-item>
|
|
139
|
+
</leu-menu>
|
|
140
|
+
</leu-dropdown>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
It could've been built as a single element by passing data to a property. The component could then render the menu and the menu items itself inside the shadow dom.
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
html`<leu-dropdown
|
|
147
|
+
label="Download"
|
|
148
|
+
.items=${["PDF", "CSV", "Excel"]}
|
|
149
|
+
></leu-dropdown>`
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
But this approach would make it impossible to create and populate the element with only HTML. It also is much harderß to apply event listeners or custom attributes like `role` to specific child elements.
|
|
153
|
+
|
|
154
|
+
The `leu-table` element is (currently) built like that and shouldn't be used as an example for composability.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Meta, Markdown } from "@storybook/blocks"
|
|
2
|
+
|
|
3
|
+
<Meta title="Introduction/Installation" />
|
|
4
|
+
|
|
5
|
+
# Installation
|
|
6
|
+
|
|
7
|
+
You can load the leu library from a CDN or install it via npm.
|
|
8
|
+
|
|
9
|
+
## npm installation
|
|
10
|
+
|
|
11
|
+
For most projects, you will want to install the library via npm.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm i @statistikzh/leu
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## CDN
|
|
18
|
+
|
|
19
|
+
If you are in you're just using plain HTML and JavaScript without any build or transformation steps or just want to tinker around with the library, you can use a CDN.
|
|
20
|
+
Browsers can't resolve bare module imports without import maps. But we can use a CDN like esm.sh to resolve the imports for us.
|
|
21
|
+
This is also applicable in an environment like [Observable](https://observablehq.com).
|
|
22
|
+
|
|
23
|
+
If you're using this approach, **always** define the version you want to use. This way you can ensure that your application doesn't break when a new version is released.
|
|
24
|
+
|
|
25
|
+
> ⚠️ Be aware that most CDN (including esm.sh) are probably not GDPR compliant. Don't use this approach in a production environment.
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<link
|
|
29
|
+
rel="stylesheet"
|
|
30
|
+
href="https://esm.sh/@statistikzh/leu@0.13.1/dist/theme.css"
|
|
31
|
+
/>
|
|
32
|
+
<script type="module">
|
|
33
|
+
import "https://esm.sh/@statistikzh/leu@0.13.1/dist/leu-input.js"
|
|
34
|
+
</script>
|
|
35
|
+
```
|