@statistikzh/leu 0.14.4 → 0.15.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.
Files changed (140) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +8 -0
  3. package/dist/Accordion.js +2 -30
  4. package/dist/Button.d.ts +56 -68
  5. package/dist/Button.js +74 -52
  6. package/dist/ButtonGroup.d.ts +9 -9
  7. package/dist/ButtonGroup.js +30 -20
  8. package/dist/ChartWrapper.d.ts +38 -0
  9. package/dist/ChartWrapper.js +153 -0
  10. package/dist/Checkbox.d.ts +6 -21
  11. package/dist/Checkbox.js +17 -9
  12. package/dist/CheckboxGroup.d.ts +13 -14
  13. package/dist/CheckboxGroup.js +18 -11
  14. package/dist/Chip.js +1 -1
  15. package/dist/ChipGroup.js +1 -1
  16. package/dist/ChipLink.js +1 -1
  17. package/dist/ChipRemovable.js +1 -1
  18. package/dist/ChipSelectable.js +1 -1
  19. package/dist/Dialog.js +1 -1
  20. package/dist/Dropdown.js +3 -1
  21. package/dist/Icon.js +1 -1
  22. package/dist/Input.js +1 -1
  23. package/dist/{LeuElement-x8UlIDDl.js → LeuElement-BhAmogDy.js} +1 -1
  24. package/dist/Menu.js +1 -1
  25. package/dist/MenuItem.js +1 -1
  26. package/dist/Pagination.d.ts +40 -28
  27. package/dist/Pagination.js +39 -14
  28. package/dist/Placeholder.d.ts +27 -0
  29. package/dist/Placeholder.js +90 -0
  30. package/dist/Popup.js +1 -1
  31. package/dist/Radio.d.ts +6 -21
  32. package/dist/Radio.js +17 -9
  33. package/dist/RadioGroup.d.ts +28 -23
  34. package/dist/RadioGroup.js +29 -16
  35. package/dist/Range.js +1 -1
  36. package/dist/ScrollTop.d.ts +0 -1
  37. package/dist/ScrollTop.js +3 -1
  38. package/dist/Select.js +3 -1
  39. package/dist/Spinner.js +1 -1
  40. package/dist/Table.d.ts +0 -1
  41. package/dist/Table.js +3 -1
  42. package/dist/VisuallyHidden.js +1 -1
  43. package/dist/_tslib-CNEFicEt.js +30 -0
  44. package/dist/components/button/Button.d.ts +55 -67
  45. package/dist/components/button/Button.d.ts.map +1 -1
  46. package/dist/components/button/stories/button.stories.d.ts.map +1 -1
  47. package/dist/components/button-group/ButtonGroup.d.ts +9 -9
  48. package/dist/components/button-group/ButtonGroup.d.ts.map +1 -1
  49. package/dist/components/checkbox/Checkbox.d.ts +6 -21
  50. package/dist/components/checkbox/Checkbox.d.ts.map +1 -1
  51. package/dist/components/checkbox/CheckboxGroup.d.ts +13 -14
  52. package/dist/components/checkbox/CheckboxGroup.d.ts.map +1 -1
  53. package/dist/components/icon/stories/icon.stories.d.ts +10 -0
  54. package/dist/components/icon/stories/icon.stories.d.ts.map +1 -1
  55. package/dist/components/pagination/Pagination.d.ts +40 -27
  56. package/dist/components/pagination/Pagination.d.ts.map +1 -1
  57. package/dist/components/pagination/stories/pagination.stories.d.ts +10 -2
  58. package/dist/components/pagination/stories/pagination.stories.d.ts.map +1 -1
  59. package/dist/components/placeholder/Placeholder.d.ts +23 -0
  60. package/dist/components/placeholder/Placeholder.d.ts.map +1 -0
  61. package/dist/components/placeholder/leu-placeholder.d.ts +3 -0
  62. package/dist/components/placeholder/leu-placeholder.d.ts.map +1 -0
  63. package/dist/components/placeholder/stories/placeholder.stories.d.ts +27 -0
  64. package/dist/components/placeholder/stories/placeholder.stories.d.ts.map +1 -0
  65. package/dist/components/placeholder/test/placeholder.test.d.ts +2 -0
  66. package/dist/components/placeholder/test/placeholder.test.d.ts.map +1 -0
  67. package/dist/components/radio/Radio.d.ts +6 -21
  68. package/dist/components/radio/Radio.d.ts.map +1 -1
  69. package/dist/components/radio/RadioGroup.d.ts +28 -23
  70. package/dist/components/radio/RadioGroup.d.ts.map +1 -1
  71. package/dist/components/visualization/ChartWrapper.d.ts +34 -0
  72. package/dist/components/visualization/ChartWrapper.d.ts.map +1 -0
  73. package/dist/components/visualization/leu-chart-wrapper.d.ts +3 -0
  74. package/dist/components/visualization/leu-chart-wrapper.d.ts.map +1 -0
  75. package/dist/components/visualization/stories/chart-wrapper.stories.d.ts +28 -0
  76. package/dist/components/visualization/stories/chart-wrapper.stories.d.ts.map +1 -0
  77. package/dist/components/visualization/test/chart-wrapper.test.d.ts +2 -0
  78. package/dist/components/visualization/test/chart-wrapper.test.d.ts.map +1 -0
  79. package/dist/index.js +3 -2
  80. package/dist/leu-accordion.js +2 -1
  81. package/dist/leu-button-group.js +8 -1
  82. package/dist/leu-button.d.ts +0 -1
  83. package/dist/leu-button.js +3 -1
  84. package/dist/leu-chart-wrapper.d.ts +6 -0
  85. package/dist/leu-chart-wrapper.js +11 -0
  86. package/dist/leu-checkbox-group.js +5 -1
  87. package/dist/leu-checkbox.js +3 -1
  88. package/dist/leu-chip-group.js +1 -1
  89. package/dist/leu-chip-link.js +1 -1
  90. package/dist/leu-chip-removable.js +1 -1
  91. package/dist/leu-chip-selectable.js +1 -1
  92. package/dist/leu-dialog.js +1 -1
  93. package/dist/leu-dropdown.js +3 -1
  94. package/dist/leu-icon.js +1 -1
  95. package/dist/leu-input.js +1 -1
  96. package/dist/leu-menu-item.js +1 -1
  97. package/dist/leu-menu.js +1 -1
  98. package/dist/leu-pagination.d.ts +0 -1
  99. package/dist/leu-pagination.js +3 -1
  100. package/dist/leu-placeholder.d.ts +4 -0
  101. package/dist/leu-placeholder.js +7 -0
  102. package/dist/leu-popup.js +1 -1
  103. package/dist/leu-radio-group.js +4 -1
  104. package/dist/leu-radio.js +3 -1
  105. package/dist/leu-range.js +1 -1
  106. package/dist/leu-scroll-top.d.ts +0 -1
  107. package/dist/leu-scroll-top.js +3 -1
  108. package/dist/leu-select.js +3 -1
  109. package/dist/leu-spinner.js +1 -1
  110. package/dist/leu-table.d.ts +0 -1
  111. package/dist/leu-table.js +3 -1
  112. package/dist/leu-visually-hidden.js +1 -1
  113. package/dist/lib/a11y.d.ts +2 -2
  114. package/dist/vscode.html-custom-data.json +92 -22
  115. package/dist/vue/index.d.ts +78 -38
  116. package/dist/web-types.json +208 -66
  117. package/package.json +1 -1
  118. package/release-please-config.json +0 -2
  119. package/scripts/generate-component/templates/stories/[name].stories.ts +17 -4
  120. package/src/components/button/Button.ts +95 -79
  121. package/src/components/button/stories/button.stories.ts +5 -6
  122. package/src/components/button-group/ButtonGroup.ts +18 -13
  123. package/src/components/checkbox/Checkbox.ts +13 -15
  124. package/src/components/checkbox/CheckboxGroup.ts +20 -16
  125. package/src/components/icon/stories/icon.stories.ts +27 -0
  126. package/src/components/pagination/Pagination.ts +45 -32
  127. package/src/components/pagination/stories/pagination.stories.ts +28 -17
  128. package/src/components/placeholder/Placeholder.ts +33 -0
  129. package/src/components/placeholder/leu-placeholder.ts +5 -0
  130. package/src/components/placeholder/placeholder.css +59 -0
  131. package/src/components/placeholder/stories/placeholder.stories.ts +34 -0
  132. package/src/components/placeholder/test/placeholder.test.ts +31 -0
  133. package/src/components/radio/Radio.ts +13 -15
  134. package/src/components/radio/RadioGroup.ts +42 -28
  135. package/src/components/visualization/ChartWrapper.ts +75 -0
  136. package/src/components/visualization/chart-wrapper.css +78 -0
  137. package/src/components/visualization/leu-chart-wrapper.ts +5 -0
  138. package/src/components/visualization/stories/chart-wrapper.stories.ts +52 -0
  139. package/src/components/visualization/test/chart-wrapper.test.ts +74 -0
  140. package/src/lib/a11y.ts +2 -2
@@ -1,6 +1,7 @@
1
1
  import { html, nothing } from "lit"
2
2
  import { classMap } from "lit/directives/class-map.js"
3
3
  import { ifDefined } from "lit/directives/if-defined.js"
4
+ import { property } from "lit/decorators.js"
4
5
 
5
6
  import { LeuIcon } from "../icon/Icon.js"
6
7
  import { LeuElement } from "../../lib/LeuElement.js"
@@ -9,31 +10,12 @@ import { ARIA_CHECKED_ROLES, ARIA_SELECTED_ROLES } from "../../lib/a11y.js"
9
10
 
10
11
  import styles from "./button.css"
11
12
 
12
- /*
13
- Design: https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=4-1444&mode=design&t=xu5Vii8jXKKCKDez-0
14
- Live Demo: zh.ch
15
- */
16
-
17
- const BUTTON_VARIANTS = ["primary", "secondary", "ghost"]
18
- Object.freeze(BUTTON_VARIANTS)
19
- export { BUTTON_VARIANTS }
20
-
21
- const BUTTON_SIZES = ["regular", "small"]
22
- Object.freeze(BUTTON_SIZES)
23
- export { BUTTON_SIZES }
24
-
25
- const BUTTON_TYPES = ["button", "submit", "reset"]
26
- Object.freeze(BUTTON_TYPES)
27
- export { BUTTON_TYPES }
28
-
29
- export const BUTTON_EXPANDED_OPTIONS = ["true", "false"]
30
- Object.freeze(BUTTON_EXPANDED_OPTIONS)
31
-
32
13
  /**
33
14
  * @tagname leu-button
34
15
  * @slot before - The icon to display before the label
35
16
  * @slot after - The icon to display after the label
36
17
  * @slot - The label of the button or the icon if no label is set
18
+ * @see https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=4-1444&mode=design&t=xu5Vii8jXKKCKDez-0
37
19
  */
38
20
  export class LeuButton extends LeuElement {
39
21
  static dependencies = {
@@ -42,72 +24,92 @@ export class LeuButton extends LeuElement {
42
24
 
43
25
  static styles = [LeuElement.styles, styles]
44
26
 
45
- /**
46
- * @internal
47
- */
48
27
  static shadowRootOptions = {
49
28
  ...LeuElement.shadowRootOptions,
50
29
  delegatesFocus: true,
51
30
  }
52
31
 
53
- /**
54
- * @internal
55
- */
56
- hasSlotController = new HasSlotController(this, [
32
+ private hasSlotController = new HasSlotController(this, [
57
33
  "before",
58
34
  "after",
59
35
  "[default]",
60
36
  ])
61
37
 
62
- static properties = {
63
- label: { type: String, reflect: true },
64
- size: { type: String, reflect: true },
65
- variant: { type: String, reflect: true },
66
- type: { type: String, reflect: true },
67
- componentRole: { type: String, reflect: true },
68
-
69
- disabled: { type: Boolean, reflect: true },
70
- round: { type: Boolean, reflect: true },
71
- active: { type: Boolean, reflect: true },
72
- inverted: { type: Boolean, reflect: true },
73
- expanded: { type: String, reflect: true },
74
- fluid: { type: Boolean, reflect: true },
75
- }
38
+ /**
39
+ * `aria-label` of the underlying button elements.
40
+ * Use it to provide a label when only an icon is visible.
41
+ */
42
+ @property({ type: String, reflect: true })
43
+ label: null | string = null
76
44
 
77
- constructor() {
78
- super()
79
- /** @type {string} */
80
- this.label = null
81
- /** @type {string} */
82
- this.size = "regular"
83
- /** @type {string} */
84
- this.variant = "primary"
85
- /** @type {"button" | "submit" | "reset"} */
86
- this.type = "button"
87
-
88
- /** @type {string} */
89
- this.componentRole = undefined
90
-
91
- /** @type {boolean} */
92
- this.disabled = false
93
- /** @type {boolean} - Only taken into account if no Label and an Icon is set */
94
- this.round = false
95
- /** @type {boolean} */
96
- this.active = false
97
- /** @type {boolean} - will be used on dark Background */
98
- this.inverted = false
99
-
100
- /** @type {boolean} - Alters the shape of the button to be full width of its parent container */
101
- this.fluid = false
102
-
103
- /**
104
- * Only taken into account if variant is "ghost"
105
- * @type {("true" | "false" | undefined)}
106
- */
107
- this.expanded = undefined
108
- }
45
+ /**
46
+ * The size of the button.
47
+ */
48
+ @property({ type: String, reflect: true })
49
+ size: "regular" | "small" = "regular"
50
+
51
+ /**
52
+ * The visual variant of the button.
53
+ */
54
+ @property({ type: String, reflect: true })
55
+ variant: "primary" | "secondary" | "ghost" = "primary"
56
+
57
+ /**
58
+ * The `type` of the underlying button element.
59
+ */
60
+ @property({ type: String, reflect: true })
61
+ type: "button" | "submit" | "reset" = "button"
62
+
63
+ /**
64
+ * The `role` of the underlying button element.
65
+ */
66
+ @property({ type: String, reflect: true })
67
+ componentRole?: string
68
+
69
+ /**
70
+ * Whether the button is disabled or not.
71
+ * @type {boolean}
72
+ */
73
+ @property({ type: Boolean, reflect: true })
74
+ disabled: boolean = false
75
+
76
+ /**
77
+ * Whether the button should be round.
78
+ * Can only be applied when the button contains an icon without a visible label.
79
+ * @type {boolean}
80
+ */
81
+ @property({ type: Boolean, reflect: true })
82
+ round: boolean = false
83
+
84
+ /**
85
+ * Whether the button is active or not.
86
+ * Depending on the `componentRole`, it applies `aria-checked` or `aria-selected` to the underlying button element.
87
+ */
88
+ @property({ type: Boolean, reflect: true })
89
+ active: boolean = false
90
+
91
+ /**
92
+ * Wheter the colors should be inverted. For use on dark backgrounds.
93
+ */
94
+ @property({ type: Boolean, reflect: true })
95
+ inverted: boolean = false
96
+
97
+ /**
98
+ * Whether the button is expanded or not.
99
+ * Only has an effect on the variant `ghost` to show an expanding icon.
100
+ * If the property is not set, the icon will not be shown.
101
+ * If it is set, the icon will either show an expanded or collapsed state.
102
+ */
103
+ @property({ type: String, reflect: true })
104
+ expanded?: "true" | "false"
105
+
106
+ /**
107
+ * Alters the shape of the button to be full width of its parent container
108
+ */
109
+ @property({ type: Boolean, reflect: true })
110
+ fluid: boolean = false
109
111
 
110
- renderExpandingIcon() {
112
+ private renderExpandingIcon() {
111
113
  if (typeof this.expanded !== "undefined" && this.variant === "ghost") {
112
114
  return html`<div class="icon-expanded">
113
115
  <leu-icon name="angleDropDown" size="24"></leu-icon>
@@ -117,16 +119,30 @@ export class LeuButton extends LeuElement {
117
119
  return nothing
118
120
  }
119
121
 
120
- getAriaAttributes() {
121
- const attributes = {
122
+ private getAriaAttributes() {
123
+ const attributes: {
124
+ role: string
125
+ label: string
126
+ checked?: "true" | "false"
127
+ selected?: "true" | "false"
128
+ } = {
122
129
  role: this.componentRole,
123
130
  label: this.label,
124
131
  }
125
132
 
133
+ // TODO: checked and selected roles are not mutually exclusive
126
134
  if (this.componentRole) {
127
- if (ARIA_CHECKED_ROLES.includes(this.componentRole)) {
135
+ if (
136
+ (ARIA_CHECKED_ROLES as ReadonlyArray<string>).includes(
137
+ this.componentRole,
138
+ )
139
+ ) {
128
140
  attributes.checked = this.active ? "true" : "false"
129
- } else if (ARIA_SELECTED_ROLES.includes(this.componentRole)) {
141
+ } else if (
142
+ (ARIA_SELECTED_ROLES as ReadonlyArray<string>).includes(
143
+ this.componentRole,
144
+ )
145
+ ) {
130
146
  attributes.selected = this.active ? "true" : "false"
131
147
  }
132
148
  }
@@ -134,7 +150,7 @@ export class LeuButton extends LeuElement {
134
150
  return attributes
135
151
  }
136
152
 
137
- hasTextContent() {
153
+ private hasTextContent() {
138
154
  return Array.from(this.childNodes).some(
139
155
  (node) =>
140
156
  node.nodeType === node.TEXT_NODE && node.textContent.trim() !== "",
@@ -4,12 +4,11 @@ import { classMap } from "lit/directives/class-map.js"
4
4
  import "../leu-button.js"
5
5
  import "../../icon/leu-icon.js"
6
6
  import { paths as iconPaths } from "../../icon/paths.js"
7
- import {
8
- BUTTON_VARIANTS,
9
- BUTTON_TYPES,
10
- BUTTON_SIZES,
11
- BUTTON_EXPANDED_OPTIONS,
12
- } from "../Button.js"
7
+
8
+ const BUTTON_VARIANTS = ["primary", "secondary", "ghost"] as const
9
+ const BUTTON_SIZES = ["regular", "small"] as const
10
+ const BUTTON_TYPES = ["button", "submit", "reset"] as const
11
+ const BUTTON_EXPANDED_OPTIONS = ["true", "false"] as const
13
12
 
14
13
  function copyContent(e) {
15
14
  navigator.clipboard.writeText(e.target.outerHTML.replace(/<!--.*?-->/g, ""))
@@ -1,13 +1,15 @@
1
1
  import { html } from "lit"
2
+
2
3
  import { LeuElement } from "../../lib/LeuElement.js"
4
+ import { LeuButton } from "../button/Button.js"
3
5
 
4
6
  import styles from "./button-group.css"
5
- import { LeuButton } from "../button/Button.js"
6
7
 
7
8
  /**
9
+ * A radio input-like button group component.
10
+ * It allows only one button to be active at a time.
8
11
  * @tagname leu-button-group
9
12
  * @slot - Slot for the buttons
10
- * @prop {string} value - The value of the currenty selected (active) button
11
13
  * @fires input - When the value of the group changes by clicking a button
12
14
  */
13
15
  export class LeuButtonGroup extends LeuElement {
@@ -16,13 +18,15 @@ export class LeuButtonGroup extends LeuElement {
16
18
  private _items: LeuButton[] = []
17
19
 
18
20
  /**
19
- * @param {import("../button/Button.js").LeuButton} button
20
- * @returns {string}
21
+ * Retrieves the value or the text content of a given LeuButton element.
21
22
  */
22
- static getButtonValue(button) {
23
- return button.getAttribute("value") ?? button.innerText.trim()
23
+ private static getButtonValue(button: LeuButton) {
24
+ return button.getAttribute("value") ?? button.textContent.trim()
24
25
  }
25
26
 
27
+ /**
28
+ * The value of the currently selected (active) button
29
+ */
26
30
  get value() {
27
31
  const activeButton = this._items.find((item) => item.active)
28
32
  return activeButton ? LeuButtonGroup.getButtonValue(activeButton) : null
@@ -36,7 +40,7 @@ export class LeuButtonGroup extends LeuElement {
36
40
  })
37
41
  }
38
42
 
39
- _handleSlotChange() {
43
+ private _handleSlotChange() {
40
44
  /**
41
45
  * Remove all event listeners that were added before.
42
46
  * Just because a slotchange event was fired, it doesn't mean that all of the
@@ -47,13 +51,15 @@ export class LeuButtonGroup extends LeuElement {
47
51
  })
48
52
 
49
53
  const slot = this.shadowRoot.querySelector("slot")
50
- this._items = slot.assignedElements({ flatten: true })
54
+ this._items = slot
55
+ .assignedElements({ flatten: true })
56
+ .filter((el) => el instanceof LeuButton)
51
57
 
52
58
  let foundActiveButtonBefore = false
53
59
 
54
60
  this._items.forEach((item) => {
55
61
  /* eslint-disable no-param-reassign */
56
- item.addEventListener("click", () => this._handleButtonClick(item))
62
+ item.addEventListener("click", this._handleButtonClick)
57
63
  item.componentRole = "menuitemradio"
58
64
 
59
65
  /**
@@ -70,10 +76,9 @@ export class LeuButtonGroup extends LeuElement {
70
76
  })
71
77
  }
72
78
 
73
- /**
74
- * @param {import("../button/Button.js").LeuButton} button
75
- */
76
- _handleButtonClick(button) {
79
+ private _handleButtonClick = (event: MouseEvent) => {
80
+ const button = event.currentTarget as LeuButton
81
+
77
82
  if (!button.active) {
78
83
  this.value = LeuButtonGroup.getButtonValue(button)
79
84
 
@@ -1,4 +1,5 @@
1
1
  import { html } from "lit"
2
+ import { property } from "lit/decorators.js"
2
3
 
3
4
  import { LeuElement } from "../../lib/LeuElement.js"
4
5
  import { LeuIcon } from "../icon/Icon.js"
@@ -21,29 +22,26 @@ export class LeuCheckbox extends LeuElement {
21
22
  delegatesFocus: true,
22
23
  }
23
24
 
24
- static properties = {
25
- checked: { type: Boolean, reflect: true },
26
- disabled: { type: Boolean, reflect: true },
27
- value: { type: String, reflect: true },
28
- name: { type: String, reflect: true },
29
- }
25
+ @property({ type: Boolean, reflect: true })
26
+ checked: boolean = false
30
27
 
31
- constructor() {
32
- super()
33
- this.checked = false
34
- this.disabled = false
35
- this.name = ""
36
- this.value = ""
37
- }
28
+ @property({ type: Boolean, reflect: true })
29
+ disabled: boolean = false
30
+
31
+ @property({ type: String, reflect: true })
32
+ value: string = ""
33
+
34
+ @property({ type: String, reflect: true })
35
+ name: string = ""
38
36
 
39
- handleChange(event) {
37
+ private handleChange(event: Event & { target: HTMLInputElement }) {
40
38
  this.checked = event.target.checked
41
39
 
42
40
  const customEvent = new CustomEvent(event.type, event)
43
41
  this.dispatchEvent(customEvent)
44
42
  }
45
43
 
46
- handleInput(event) {
44
+ private handleInput(event: InputEvent & { target: HTMLInputElement }) {
47
45
  this.checked = event.target.checked
48
46
  }
49
47
 
@@ -1,38 +1,42 @@
1
1
  import { html } from "lit"
2
2
  import { classMap } from "lit/directives/class-map.js"
3
+ import { property } from "lit/decorators.js"
3
4
 
4
5
  import { LeuElement } from "../../lib/LeuElement.js"
5
6
 
6
7
  import styles from "./checkbox-group.css"
8
+ import { LeuCheckbox } from "./Checkbox.js"
7
9
 
8
10
  /**
11
+ *
12
+ * @slot - Place the checkboxes inside the default slot.
9
13
  * @tagname leu-checkbox-group
10
14
  */
11
15
  export class LeuCheckboxGroup extends LeuElement {
12
16
  static styles = [LeuElement.styles, styles]
13
17
 
14
- static properties = {
15
- orientation: { type: String, reflect: true },
16
- label: { type: String, reflect: true },
17
- }
18
+ /**
19
+ * Defines how the checkboxes should be aligned.
20
+ */
21
+ @property({ type: String, reflect: true })
22
+ orientation: "horizontal" | "vertical" = "horizontal"
18
23
 
19
- constructor() {
20
- super()
21
- /** @type {"horizontal" | "vertical"} */
22
- this.orientation = "horizontal"
23
- this.items = []
24
- }
24
+ /**
25
+ * The label of the checkbox group
26
+ */
27
+ @property({ type: String, reflect: true })
28
+ label?: string
29
+
30
+ private items: LeuCheckbox[] = []
25
31
 
26
32
  get value() {
27
33
  return this.items.filter((i) => i.checked).map((i) => i.value)
28
34
  }
29
35
 
30
- handleSlotChange() {
31
- this.handleItems()
32
- }
33
-
34
- handleItems() {
35
- this.items = Array.from(this.querySelectorAll(":scope > *:not([slot])"))
36
+ private handleSlotChange() {
37
+ this.items = Array.from(
38
+ this.querySelectorAll(":scope > *:not([slot])"),
39
+ ).filter((el) => el instanceof LeuCheckbox)
36
40
  }
37
41
 
38
42
  render() {
@@ -45,3 +45,30 @@ Colored.args = {
45
45
  size: 24,
46
46
  color: "#d93c1a",
47
47
  }
48
+
49
+ export const Overview = {
50
+ render: ({ color, size }) => html`
51
+ <ul
52
+ style="font-family: var(--leu-font-family-regular); color: var(--leu-color-black-60); list-style: none; margin: 0; padding: 0;"
53
+ >
54
+ ${Object.keys(paths).map(
55
+ (name) =>
56
+ html`<li
57
+ style="display: flex; align-items: center; margin-bottom: 1rem; gap: 1rem;"
58
+ >
59
+ <leu-icon
60
+ style="color: ${color}; ${size
61
+ ? `--leu-icon-size: ${size}px`
62
+ : ""};"
63
+ name=${ifDefined(name)}
64
+ ></leu-icon>
65
+ ${name}
66
+ </li>`,
67
+ )}
68
+ </ul>
69
+ `,
70
+ args: {
71
+ size: 24,
72
+ color: "#000000",
73
+ },
74
+ }
@@ -1,5 +1,6 @@
1
1
  import { html } from "lit"
2
2
  import { live } from "lit/directives/live.js"
3
+ import { property, state } from "lit/decorators.js"
3
4
 
4
5
  import { LeuElement } from "../../lib/LeuElement.js"
5
6
  import { LeuButton } from "../button/Button.js"
@@ -30,32 +31,30 @@ export class LeuPagination extends LeuElement {
30
31
  delegatesFocus: true,
31
32
  }
32
33
 
33
- static properties = {
34
- defaultPage: { type: Number, reflect: true },
35
- itemsPerPage: { type: Number, reflect: true },
36
- numOfItems: { type: Number, reflect: true },
37
- _page: { state: true },
38
- }
39
-
40
- constructor() {
41
- super()
34
+ @property({ type: Number, reflect: true })
35
+ defaultPage?: number
42
36
 
43
- /** @type {Number} */
44
- this.numOfItems = 1
37
+ /**
38
+ * Number of items per page.
39
+ */
40
+ @property({ type: Number, reflect: true })
41
+ itemsPerPage: number = 1
45
42
 
46
- /** @type {Number} */
47
- this.itemsPerPage = 1
43
+ /**
44
+ * Total number of items to paginate.
45
+ */
46
+ @property({ type: Number, reflect: true })
47
+ numOfItems: number = 1
48
48
 
49
- /**
50
- * Internal page state that contains an
51
- * already clamped page number. Should only
52
- * be accessed through the `page` getter and
53
- * setter.
54
- * @type {Number}
55
- * @internal
56
- */
57
- this._page = 1
58
- }
49
+ /**
50
+ * Internal page state that contains an
51
+ * already clamped page number. Should only
52
+ * be accessed through the `page` getter and
53
+ * setter.
54
+ * @internal
55
+ */
56
+ @state()
57
+ private _page: number = 1
59
58
 
60
59
  attributeChangedCallback(name, oldVal, newVal) {
61
60
  super.attributeChangedCallback(name, oldVal, newVal)
@@ -65,6 +64,11 @@ export class LeuPagination extends LeuElement {
65
64
  }
66
65
  }
67
66
 
67
+ /**
68
+ * The current page number. This is a 1-based index.
69
+ * When setting this value, it will be clamped
70
+ * to the range of valid pages.
71
+ */
68
72
  get page() {
69
73
  return this._page
70
74
  }
@@ -73,10 +77,19 @@ export class LeuPagination extends LeuElement {
73
77
  this._page = this._clampPage(page)
74
78
  }
75
79
 
80
+ /**
81
+ * The index of the first item on the current page.
82
+ */
76
83
  get startIndex() {
77
84
  return (this.page - 1) * this.itemsPerPage
78
85
  }
79
86
 
87
+ /**
88
+ * The index of the last item on the current page.
89
+ * This is exclusive, meaning it is one past the last item.
90
+ *
91
+ * @todo This value should be inclusive, meaning it should be the index of the last item on the page.
92
+ */
80
93
  get endIndex() {
81
94
  return Math.min(this.startIndex + this.itemsPerPage, this.numOfItems)
82
95
  }
@@ -85,19 +98,19 @@ export class LeuPagination extends LeuElement {
85
98
  return Math.ceil(this.numOfItems / this.itemsPerPage)
86
99
  }
87
100
 
88
- _isFirstPage() {
101
+ private _isFirstPage() {
89
102
  return this.page === MIN_PAGE
90
103
  }
91
104
 
92
- _isLastPage() {
105
+ private _isLastPage() {
93
106
  return this.page === this._maxPage
94
107
  }
95
108
 
96
- _clampPage(page) {
109
+ private _clampPage(page: number) {
97
110
  return Math.min(Math.max(page, MIN_PAGE), this._maxPage)
98
111
  }
99
112
 
100
- _updatePage(page) {
113
+ private _updatePage(page) {
101
114
  const prevPage = this.page
102
115
  this.page = this._clampPage(page)
103
116
 
@@ -115,18 +128,18 @@ export class LeuPagination extends LeuElement {
115
128
  }
116
129
  }
117
130
 
118
- _handleChange(event) {
131
+ private _handleChange(event: Event & { target: HTMLInputElement }) {
119
132
  this._updatePage(parseInt(event.target.value, 10) || 0)
120
133
  }
121
134
 
122
- _handleInput(event) {
135
+ private _handleInput(event: InputEvent & { target: HTMLInputElement }) {
123
136
  if (event.target.value !== "") {
124
137
  event.preventDefault()
125
138
  this._handleChange(event)
126
139
  }
127
140
  }
128
141
 
129
- _handleKeyDown(event) {
142
+ private _handleKeyDown(event: KeyboardEvent & { target: HTMLInputElement }) {
130
143
  if (event.key === "ArrowUp") {
131
144
  event.preventDefault()
132
145
  this._updatePage(this.page + 1)
@@ -158,7 +171,7 @@ export class LeuPagination extends LeuElement {
158
171
  <leu-button
159
172
  variant="secondary"
160
173
  label="Vorherige Seite"
161
- @click=${(_) => {
174
+ @click=${() => {
162
175
  this._updatePage(this.page - 1)
163
176
  }}
164
177
  ?disabled=${this._isFirstPage()}
@@ -167,7 +180,7 @@ export class LeuPagination extends LeuElement {
167
180
  <leu-button
168
181
  variant="secondary"
169
182
  label="Nächste Seite"
170
- @click=${(_) => {
183
+ @click=${() => {
171
184
  this._updatePage(this.page + 1)
172
185
  }}
173
186
  ?disabled=${this._isLastPage()}