@statistikzh/leu 0.21.1 → 0.22.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.
Files changed (193) hide show
  1. package/.github/workflows/release-please.yml +1 -2
  2. package/.nvmrc +1 -1
  3. package/.release-please-manifest.json +1 -1
  4. package/CHANGELOG.md +16 -0
  5. package/README.md +15 -10
  6. package/dist/Accordion.js +1 -1
  7. package/dist/Button.d.ts +1 -1
  8. package/dist/Button.js +1 -1
  9. package/dist/ButtonGroup.js +1 -1
  10. package/dist/ChartWrapper.js +1 -1
  11. package/dist/Checkbox.d.ts +1 -1
  12. package/dist/Checkbox.js +1 -1
  13. package/dist/CheckboxGroup.js +1 -1
  14. package/dist/Chip.d.ts +1 -7
  15. package/dist/Chip.js +7 -5
  16. package/dist/ChipGroup.d.ts +17 -36
  17. package/dist/ChipGroup.js +35 -33
  18. package/dist/ChipLink.d.ts +5 -21
  19. package/dist/ChipLink.js +14 -15
  20. package/dist/ChipRemovable.d.ts +4 -15
  21. package/dist/ChipRemovable.js +7 -9
  22. package/dist/ChipSelectable.d.ts +14 -37
  23. package/dist/ChipSelectable.js +24 -28
  24. package/dist/Dialog.d.ts +7 -18
  25. package/dist/Dialog.js +15 -18
  26. package/dist/Dropdown.d.ts +16 -24
  27. package/dist/Dropdown.js +23 -21
  28. package/dist/FileInput.d.ts +2 -1
  29. package/dist/FileInput.js +19 -5
  30. package/dist/Icon.d-itcQ94ym.d.ts +151 -0
  31. package/dist/Icon.d.ts +4 -156
  32. package/dist/Icon.js +1 -4
  33. package/dist/Input.d.ts +73 -141
  34. package/dist/Input.js +91 -88
  35. package/dist/{LeuElement-BLUQU9Eu.js → LeuElement-DfsEye-A.js} +1 -1
  36. package/dist/Menu.d.ts +2 -8
  37. package/dist/Menu.js +7 -9
  38. package/dist/MenuItem.d.ts +31 -59
  39. package/dist/MenuItem.js +30 -33
  40. package/dist/Message.d.ts +1 -1
  41. package/dist/Message.js +1 -1
  42. package/dist/Pagination.d.ts +1 -1
  43. package/dist/Pagination.js +1 -1
  44. package/dist/Placeholder.js +1 -1
  45. package/dist/Popup.js +1 -1
  46. package/dist/ProgressBar.js +1 -1
  47. package/dist/Radio.js +1 -1
  48. package/dist/RadioGroup.js +1 -1
  49. package/dist/Range.d.ts +22 -65
  50. package/dist/Range.js +36 -37
  51. package/dist/ScrollTop.d.ts +5 -7
  52. package/dist/ScrollTop.js +10 -15
  53. package/dist/Select.d.ts +2 -1
  54. package/dist/Select.js +1 -1
  55. package/dist/Spinner.js +1 -1
  56. package/dist/Table.d.ts +1 -1
  57. package/dist/Table.js +1 -1
  58. package/dist/Tag.js +1 -1
  59. package/dist/VisuallyHidden.js +1 -1
  60. package/dist/components/chart-wrapper/leu-chart-wrapper.d.ts +5 -0
  61. package/dist/components/chart-wrapper/leu-chart-wrapper.d.ts.map +1 -1
  62. package/dist/components/chip/Chip.d.ts +1 -7
  63. package/dist/components/chip/Chip.d.ts.map +1 -1
  64. package/dist/components/chip/ChipGroup.d.ts +15 -35
  65. package/dist/components/chip/ChipGroup.d.ts.map +1 -1
  66. package/dist/components/chip/ChipLink.d.ts +4 -20
  67. package/dist/components/chip/ChipLink.d.ts.map +1 -1
  68. package/dist/components/chip/ChipRemovable.d.ts +3 -14
  69. package/dist/components/chip/ChipRemovable.d.ts.map +1 -1
  70. package/dist/components/chip/ChipSelectable.d.ts +13 -36
  71. package/dist/components/chip/ChipSelectable.d.ts.map +1 -1
  72. package/dist/components/chip/stories/chip-group.stories.d.ts +1 -1
  73. package/dist/components/chip/stories/chip-group.stories.d.ts.map +1 -1
  74. package/dist/components/chip/stories/chip-link.stories.d.ts.map +1 -1
  75. package/dist/components/chip/stories/chip-selectable.stories.d.ts.map +1 -1
  76. package/dist/components/dialog/Dialog.d.ts +5 -17
  77. package/dist/components/dialog/Dialog.d.ts.map +1 -1
  78. package/dist/components/dropdown/Dropdown.d.ts +14 -23
  79. package/dist/components/dropdown/Dropdown.d.ts.map +1 -1
  80. package/dist/components/dropdown/stories/dropdown.stories.d.ts.map +1 -1
  81. package/dist/components/file-input/FileInput.d.ts +1 -0
  82. package/dist/components/file-input/FileInput.d.ts.map +1 -1
  83. package/dist/components/file-input/leu-file-input.d.ts +5 -0
  84. package/dist/components/file-input/leu-file-input.d.ts.map +1 -1
  85. package/dist/components/file-input/stories/file-input.stories.d.ts +4 -0
  86. package/dist/components/file-input/stories/file-input.stories.d.ts.map +1 -1
  87. package/dist/components/icon/Icon.d.ts +0 -6
  88. package/dist/components/icon/Icon.d.ts.map +1 -1
  89. package/dist/components/input/Input.d.ts +73 -140
  90. package/dist/components/input/Input.d.ts.map +1 -1
  91. package/dist/components/menu/Menu.d.ts +1 -7
  92. package/dist/components/menu/Menu.d.ts.map +1 -1
  93. package/dist/components/menu/MenuItem.d.ts +30 -57
  94. package/dist/components/menu/MenuItem.d.ts.map +1 -1
  95. package/dist/components/message/leu-message.d.ts +5 -0
  96. package/dist/components/message/leu-message.d.ts.map +1 -1
  97. package/dist/components/placeholder/leu-placeholder.d.ts +5 -0
  98. package/dist/components/placeholder/leu-placeholder.d.ts.map +1 -1
  99. package/dist/components/progress-bar/leu-progress-bar.d.ts +5 -0
  100. package/dist/components/progress-bar/leu-progress-bar.d.ts.map +1 -1
  101. package/dist/components/range/Range.d.ts +22 -65
  102. package/dist/components/range/Range.d.ts.map +1 -1
  103. package/dist/components/scroll-top/ScrollTop.d.ts +4 -6
  104. package/dist/components/scroll-top/ScrollTop.d.ts.map +1 -1
  105. package/dist/components/tag/leu-tag.d.ts +5 -0
  106. package/dist/components/tag/leu-tag.d.ts.map +1 -1
  107. package/dist/index.d.ts +11 -0
  108. package/dist/index.d.ts.map +1 -1
  109. package/dist/index.js +13 -4
  110. package/dist/leu-accordion.js +1 -1
  111. package/dist/leu-button-group.js +1 -1
  112. package/dist/leu-button.d.ts +1 -1
  113. package/dist/leu-button.js +1 -1
  114. package/dist/leu-chart-wrapper.d.ts +10 -1
  115. package/dist/leu-chart-wrapper.js +1 -1
  116. package/dist/leu-checkbox-group.js +1 -1
  117. package/dist/leu-checkbox.d.ts +1 -1
  118. package/dist/leu-checkbox.js +1 -1
  119. package/dist/leu-chip-group.d.ts +2 -0
  120. package/dist/leu-chip-group.js +5 -1
  121. package/dist/leu-chip-link.js +3 -1
  122. package/dist/leu-chip-removable.d.ts +1 -1
  123. package/dist/leu-chip-removable.js +3 -3
  124. package/dist/leu-chip-selectable.js +3 -1
  125. package/dist/leu-dialog.d.ts +2 -1
  126. package/dist/leu-dialog.js +3 -3
  127. package/dist/leu-dropdown.d.ts +2 -1
  128. package/dist/leu-dropdown.js +3 -3
  129. package/dist/leu-file-input.d.ts +11 -2
  130. package/dist/leu-file-input.js +11 -4
  131. package/dist/leu-icon.d.ts +1 -1
  132. package/dist/leu-icon.js +1 -1
  133. package/dist/leu-input.d.ts +2 -1
  134. package/dist/leu-input.js +3 -3
  135. package/dist/leu-menu-item.d.ts +2 -2
  136. package/dist/leu-menu-item.js +3 -3
  137. package/dist/leu-menu.d.ts +1 -1
  138. package/dist/leu-menu.js +3 -3
  139. package/dist/leu-message.d.ts +11 -2
  140. package/dist/leu-message.js +1 -1
  141. package/dist/leu-pagination.d.ts +1 -1
  142. package/dist/leu-pagination.js +1 -1
  143. package/dist/leu-placeholder.d.ts +10 -1
  144. package/dist/leu-placeholder.js +1 -1
  145. package/dist/leu-popup.js +1 -1
  146. package/dist/leu-progress-bar.d.ts +10 -1
  147. package/dist/leu-progress-bar.js +1 -1
  148. package/dist/leu-radio-group.js +1 -1
  149. package/dist/leu-radio.js +1 -1
  150. package/dist/leu-range.js +3 -1
  151. package/dist/leu-scroll-top.d.ts +1 -1
  152. package/dist/leu-scroll-top.js +3 -3
  153. package/dist/leu-select.d.ts +2 -1
  154. package/dist/leu-select.js +1 -1
  155. package/dist/leu-spinner.js +1 -1
  156. package/dist/leu-table.d.ts +1 -1
  157. package/dist/leu-table.js +1 -1
  158. package/dist/leu-tag.d.ts +10 -1
  159. package/dist/leu-tag.js +1 -1
  160. package/dist/leu-visually-hidden.js +1 -1
  161. package/dist/vscode.html-custom-data.json +115 -111
  162. package/dist/vue/index.d.ts +116 -131
  163. package/dist/web-types.json +303 -303
  164. package/package.json +1 -1
  165. package/scripts/generate-component/templates/[namespace]-[name].ts +6 -0
  166. package/src/components/chart-wrapper/leu-chart-wrapper.ts +6 -0
  167. package/src/components/chip/Chip.ts +3 -9
  168. package/src/components/chip/ChipGroup.ts +26 -39
  169. package/src/components/chip/ChipLink.ts +7 -18
  170. package/src/components/chip/ChipRemovable.ts +4 -11
  171. package/src/components/chip/ChipSelectable.ts +21 -35
  172. package/src/components/chip/stories/chip-group.stories.ts +4 -7
  173. package/src/components/chip/stories/chip-link.stories.ts +2 -4
  174. package/src/components/chip/stories/chip-selectable.stories.ts +4 -6
  175. package/src/components/chip/test/chip-group.test.ts +34 -31
  176. package/src/components/dialog/Dialog.ts +9 -22
  177. package/src/components/dropdown/Dropdown.ts +20 -24
  178. package/src/components/dropdown/stories/dropdown.stories.ts +6 -2
  179. package/src/components/dropdown/test/dropdown.test.ts +14 -2
  180. package/src/components/file-input/FileInput.ts +12 -1
  181. package/src/components/file-input/leu-file-input.ts +6 -0
  182. package/src/components/file-input/stories/file-input.stories.ts +7 -0
  183. package/src/components/icon/Icon.ts +0 -4
  184. package/src/components/input/Input.ts +108 -105
  185. package/src/components/menu/Menu.ts +3 -12
  186. package/src/components/menu/MenuItem.ts +37 -41
  187. package/src/components/message/leu-message.ts +6 -0
  188. package/src/components/placeholder/leu-placeholder.ts +6 -0
  189. package/src/components/progress-bar/leu-progress-bar.ts +6 -0
  190. package/src/components/range/Range.ts +51 -59
  191. package/src/components/scroll-top/ScrollTop.ts +8 -15
  192. package/src/components/tag/leu-tag.ts +6 -0
  193. package/src/index.ts +11 -0
@@ -1,5 +1,6 @@
1
1
  import { html, nothing } from "lit"
2
2
  import { createRef, ref } from "lit/directives/ref.js"
3
+ import { property } from "lit/decorators.js"
3
4
 
4
5
  import { LeuElement } from "../../lib/LeuElement.js"
5
6
  import { HasSlotController } from "../../lib/hasSlotController.js"
@@ -24,22 +25,18 @@ export class LeuDropdown extends LeuElement {
24
25
 
25
26
  static styles = [LeuElement.styles, styles]
26
27
 
27
- static properties = {
28
- label: { type: String, reflect: true },
29
- expanded: { type: Boolean, reflect: true },
30
- }
28
+ @property({ type: String, reflect: true })
29
+ label: string = ""
31
30
 
32
- hasSlotController = new HasSlotController(this, ["icon"])
31
+ @property({ type: Boolean, reflect: true })
32
+ expanded: boolean = false
33
33
 
34
- constructor() {
35
- super()
34
+ @property({ type: Boolean, reflect: true })
35
+ inverted: boolean = false
36
36
 
37
- this.label = ""
38
- this.expanded = false
37
+ protected hasSlotController = new HasSlotController(this, ["icon"])
39
38
 
40
- /** @type {import("lit/directives/ref").Ref<HTMLButtonElement>} */
41
- this._toggleRef = createRef()
42
- }
39
+ protected _toggleRef = createRef<HTMLButtonElement>()
43
40
 
44
41
  connectedCallback() {
45
42
  super.connectedCallback()
@@ -63,19 +60,19 @@ export class LeuDropdown extends LeuElement {
63
60
  menu.removeEventListener("click", this._menuItemClickHandler)
64
61
  }
65
62
 
66
- _documentClickHandler = (event) => {
63
+ protected _documentClickHandler = (event: MouseEvent) => {
67
64
  if (!event.composedPath().includes(this)) {
68
65
  this.expanded = false
69
66
  }
70
67
  }
71
68
 
72
- _keyUpHandler(event) {
69
+ protected _keyUpHandler = (event: KeyboardEvent) => {
73
70
  if (event.key === "Escape") {
74
71
  this.expanded = false
75
72
  }
76
73
  }
77
74
 
78
- async _keyDownToggleHandler(event) {
75
+ protected async _keyDownToggleHandler(event: KeyboardEvent) {
79
76
  if (["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
80
77
  event.preventDefault()
81
78
  const menu = this._getMenu()
@@ -92,7 +89,9 @@ export class LeuDropdown extends LeuElement {
92
89
  }
93
90
  }
94
91
 
95
- _menuItemClickHandler = (e) => {
92
+ protected _menuItemClickHandler = (
93
+ e: MouseEvent & { target: HTMLElement },
94
+ ) => {
96
95
  if (e.target.tagName.toLowerCase() === "leu-menu-item") {
97
96
  this.expanded = false
98
97
  this._toggleRef.value.focus()
@@ -102,9 +101,8 @@ export class LeuDropdown extends LeuElement {
102
101
  /**
103
102
  * Close the dropdown when the user presses the Escape or the Tab key.
104
103
  * Navigating the menu with the arrow keys is handled by the menu itself.
105
- * @param {KeyboardEvent} e
106
104
  */
107
- _keyDownMenuHandler = (e) => {
105
+ protected _keyDownMenuHandler = (e: KeyboardEvent) => {
108
106
  if (e.key === "Escape" || e.key === "Tab") {
109
107
  e.preventDefault()
110
108
  this.expanded = false
@@ -112,15 +110,12 @@ export class LeuDropdown extends LeuElement {
112
110
  }
113
111
  }
114
112
 
115
- _handleToggleClick() {
113
+ protected _handleToggleClick() {
116
114
  this.expanded = !this.expanded
117
115
  }
118
116
 
119
- /**
120
- * @returns {import("../menu/Menu").LeuMenu}
121
- */
122
- _getMenu() {
123
- return this.querySelector("leu-menu")
117
+ protected _getMenu() {
118
+ return this.querySelector<LeuMenu>("leu-menu")
124
119
  }
125
120
 
126
121
  render() {
@@ -141,6 +136,7 @@ export class LeuDropdown extends LeuElement {
141
136
  variant="ghost"
142
137
  expanded=${this.expanded ? "true" : "false"}
143
138
  ?active=${this.expanded}
139
+ ?inverted=${this.inverted}
144
140
  @click=${this._handleToggleClick}
145
141
  @keydown=${this._keyDownToggleHandler}
146
142
  >
@@ -24,8 +24,12 @@ export default {
24
24
  },
25
25
  }
26
26
 
27
- function Template({ label, expanded, icon }) {
28
- return html` <leu-dropdown label=${label} ?expanded=${expanded}>
27
+ function Template({ label, expanded, icon, inverted }) {
28
+ return html` <leu-dropdown
29
+ label=${label}
30
+ ?expanded=${expanded}
31
+ ?inverted=${inverted}
32
+ >
29
33
  ${icon ? html`<leu-icon name=${icon} slot="icon"></leu-icon>` : nothing}
30
34
  <leu-menu>
31
35
  <leu-menu-item
@@ -3,9 +3,13 @@ import { fixture, expect, elementUpdated } from "@open-wc/testing"
3
3
 
4
4
  import "../leu-dropdown.js"
5
5
 
6
- async function defaultFixture(args = { expanded: false }) {
6
+ async function defaultFixture(args = { expanded: false, inverted: false }) {
7
7
  return fixture(
8
- html` <leu-dropdown label="Download" ?expanded=${args.expanded}>
8
+ html` <leu-dropdown
9
+ label="Download"
10
+ ?expanded=${args.expanded}
11
+ ?inverted=${args.inverted}
12
+ >
9
13
  <leu-menu>
10
14
  <leu-menu-item>Als CSV Tabelle</leu-menu-item>
11
15
  <leu-menu-item>Als XLS Tabelle</leu-menu-item>
@@ -44,4 +48,12 @@ describe("LeuDropdown", () => {
44
48
 
45
49
  expect(el.expanded).to.be.false
46
50
  })
51
+
52
+ it("reflects the inverted property to the internal button", async () => {
53
+ const el = await defaultFixture({ inverted: true })
54
+ await elementUpdated(el)
55
+
56
+ const toggleButton = el.shadowRoot.querySelector("leu-button")
57
+ expect(toggleButton.inverted).to.be.true
58
+ })
47
59
  })
@@ -129,6 +129,10 @@ export class LeuFileInput extends LeuElement {
129
129
 
130
130
  protected removeFile(fileToRemove: File) {
131
131
  this.files = this.files.filter((file) => file !== fileToRemove)
132
+ this.dispatchChangeAndInputEvents()
133
+ }
134
+
135
+ protected dispatchChangeAndInputEvents() {
132
136
  this.dispatchEvent(
133
137
  new CustomEvent("input", {
134
138
  composed: true,
@@ -182,6 +186,8 @@ export class LeuFileInput extends LeuElement {
182
186
  }
183
187
 
184
188
  protected handleDrop = (event: DragEvent) => {
189
+ this.isDragging = false
190
+
185
191
  if (this.disabled) return
186
192
 
187
193
  event.preventDefault()
@@ -191,10 +197,15 @@ export class LeuFileInput extends LeuElement {
191
197
  const files = dt.files
192
198
  const acceptedFiles = [...files].filter((file) => this.isAcceptedFile(file))
193
199
 
200
+ if (acceptedFiles.length < 1) {
201
+ return
202
+ }
203
+
194
204
  this.files = this.multiple
195
205
  ? this.files.concat(acceptedFiles)
196
206
  : acceptedFiles.slice(0, 1)
197
- this.isDragging = false
207
+
208
+ this.dispatchChangeAndInputEvents()
198
209
  }
199
210
 
200
211
  isAcceptedFile(file: File): boolean {
@@ -3,3 +3,9 @@ import { LeuFileInput } from "./FileInput.js"
3
3
  export { LeuFileInput }
4
4
 
5
5
  LeuFileInput.define("leu-file-input")
6
+
7
+ declare global {
8
+ interface HTMLElementTagNameMap {
9
+ "leu-file-input": LeuFileInput
10
+ }
11
+ }
@@ -1,4 +1,5 @@
1
1
  import { Meta, StoryObj } from "@storybook/web-components"
2
+ import { action } from "@storybook/addon-actions"
2
3
  import { html } from "lit"
3
4
  import { ifDefined } from "lit/directives/if-defined.js"
4
5
 
@@ -11,6 +12,10 @@ type Story = StoryObj<StoryArgs>
11
12
  export default {
12
13
  title: "Components/FileInput",
13
14
  component: "leu-file-input",
15
+ args: {
16
+ oninput: action("input"),
17
+ onchange: action("change"),
18
+ },
14
19
  } satisfies Meta<StoryArgs>
15
20
 
16
21
  const Template: Story = {
@@ -22,6 +27,8 @@ const Template: Story = {
22
27
  ?disabled=${args.disabled}
23
28
  ?multiple=${args.multiple}
24
29
  ?required=${args.required}
30
+ @input=${args.oninput}
31
+ @change=${args.onchange}
25
32
  ></leu-file-input>
26
33
  `,
27
34
  }
@@ -18,10 +18,6 @@ import { paths, IconPathName } from "./paths.js"
18
18
  export class LeuIcon extends LeuElement {
19
19
  static styles = [LeuElement.styles, styles]
20
20
 
21
- static properties = {
22
- name: { type: String, reflect: true },
23
- }
24
-
25
21
  /**
26
22
  * The name of the icon to display.
27
23
  */
@@ -3,17 +3,32 @@ import { classMap } from "lit/directives/class-map.js"
3
3
  import { ifDefined } from "lit/directives/if-defined.js"
4
4
  import { live } from "lit/directives/live.js"
5
5
  import { createRef, ref } from "lit/directives/ref.js"
6
+ import { property, state } from "lit/decorators.js"
6
7
 
7
8
  import { LeuElement } from "../../lib/LeuElement.js"
8
9
  import { LeuIcon } from "../icon/Icon.js"
9
10
 
10
11
  import styles from "./input.css"
12
+ import { IconPathName } from "../icon/paths.js"
11
13
 
12
14
  export const SIZES = Object.freeze({
13
15
  SMALL: "small",
14
16
  REGULAR: "regular",
15
17
  })
16
18
 
19
+ type InputType =
20
+ | "date"
21
+ | "datetime-local"
22
+ | "email"
23
+ | "month"
24
+ | "number"
25
+ | "password"
26
+ | "search"
27
+ | "tel"
28
+ | "text"
29
+ | "time"
30
+ | "week"
31
+
17
32
  /**
18
33
  * TODO:
19
34
  * - Add section to docs about how to mark up suffix and prefix for screenreaders
@@ -38,27 +53,6 @@ const VALIDATION_MESSAGES = {
38
53
  /**
39
54
  * A text input element.
40
55
  *
41
- * @prop {boolean} disabled - Disables the input element.
42
- * @prop {boolean} required - Marks the input element as required.
43
- * @prop {boolean} clearable - Adds a button to clear the input element.
44
- * @prop {string} value - The value of the input element.
45
- * @prop {string} name - The name of the input element.
46
- * @prop {string} label - The label of the input element.
47
- * @prop {string} error - A custom error that is completely independent of the validity state. Useful for displaying server side errors.
48
- * @prop {string} size - The size of the input element.
49
- * @prop {string} icon - The icon that is displayed at the end of the input element.
50
- * @prop {string} prefix - A prefix that relates to the value of the input (e.g. CHF).
51
- * @prop {string} suffix - A suffix that relates to the value of the input (e.g. mm).
52
- * @prop {string} pattern - A regular expression that the value is checked against.
53
- * @prop {string} type - The type of the input element.
54
- * @prop {string} min - The minimum value of the input element.
55
- * @prop {string} max - The maximum value of the input element.
56
- * @prop {string} minlength - The minimum length of the input element.
57
- * @prop {string} maxlength - The maximum length of the input element.
58
- * @prop {object} validationMessages - Custom validation messages. The key is the name of the validity state and the value is the message.
59
- * @prop {boolean} novalidate - Disables the browser's validation.
60
- * @prop {string} step - The step value of the input element.
61
- *
62
56
  * @fires {CustomEvent} input - Dispatched when the value of the input element changes.
63
57
  * @fires {CustomEvent} change - Dispatched when the value of the input element changes and the input element loses focus.
64
58
  *
@@ -79,34 +73,88 @@ export class LeuInput extends LeuElement {
79
73
  delegatesFocus: true,
80
74
  }
81
75
 
82
- static properties = {
83
- disabled: { type: Boolean, reflect: true },
84
- required: { type: Boolean, reflect: true },
85
- clearable: { type: Boolean, reflect: true },
86
-
87
- value: { type: String, reflect: true },
88
- name: { type: String, reflect: true },
89
- error: { type: String, reflect: true },
90
-
91
- label: { type: String, reflect: true },
92
- prefix: { type: String, reflect: true },
93
- suffix: { type: String, reflect: true },
94
- size: { type: String, reflect: true },
95
- icon: { type: String, reflect: true },
96
-
97
- /* Validation attributes */
98
- pattern: { type: String, reflect: true },
99
- type: { type: String, reflect: true },
100
- min: { type: String, reflect: true },
101
- max: { type: String, reflect: true },
102
- maxlength: { type: String, reflect: true },
103
- minlength: { type: String, reflect: true },
104
- validationMessages: { type: Object },
105
- novalidate: { type: Boolean, reflect: true },
106
- step: { type: String, reflect: true },
107
-
108
- _validity: { state: true },
109
- }
76
+ /** Disables the input element. */
77
+ @property({ type: Boolean, reflect: true })
78
+ disabled: boolean = false
79
+
80
+ /** Marks the input element as required */
81
+ @property({ type: Boolean, reflect: true })
82
+ required: boolean = false
83
+
84
+ /** Adds a button to clear the input element */
85
+ @property({ type: Boolean, reflect: true })
86
+ clearable: boolean = false
87
+
88
+ /** The value of the input element. */
89
+ @property({ type: String, reflect: true })
90
+ value: string = ""
91
+
92
+ /** The name of the input element. */
93
+ @property({ type: String, reflect: true })
94
+ name: string = ""
95
+
96
+ /** A custom error that is completely independent of the validity state. Useful for displaying server side errors. */
97
+ @property({ type: String, reflect: true })
98
+ error: string = ""
99
+
100
+ /** The label of the input element */
101
+ @property({ type: String, reflect: true })
102
+ label: string = ""
103
+
104
+ /** A prefix that relates to the value of the input (e.g. CHF) */
105
+ @property({ type: String, reflect: true })
106
+ prefix: string
107
+
108
+ /** A suffix that relates to the value of the input (e.g. mm). */
109
+ @property({ type: String, reflect: true })
110
+ suffix: string
111
+
112
+ /** The size of the input element */
113
+ @property({ type: String, reflect: true })
114
+ size: "small" | "regular" = "regular"
115
+
116
+ /** The icon that is displayed at the end of the input element */
117
+ @property({ type: String, reflect: true })
118
+ icon: IconPathName
119
+
120
+ /** A regular expression that the value is checked against. */
121
+ @property({ type: String, reflect: true })
122
+ pattern: string
123
+
124
+ /** The type of the input element. */
125
+ @property({ type: String, reflect: true })
126
+ type: InputType = "text"
127
+
128
+ /** The minimum value of the input element. */
129
+ @property({ type: Number, reflect: true })
130
+ min: number
131
+
132
+ /** The maximum value of the input element. */
133
+ @property({ type: Number, reflect: true })
134
+ max: number
135
+
136
+ /** The step value of the input element. */
137
+ @property({ type: Number, reflect: true })
138
+ step: number
139
+
140
+ /** The maximum length of the input element. */
141
+ @property({ type: Number, reflect: true })
142
+ maxlength: number
143
+
144
+ /** The minimum length of the input element. */
145
+ @property({ type: Number, reflect: true })
146
+ minlength: number
147
+
148
+ /** Custom validation messages. The key is the name of the validity state and the value is the message. */
149
+ @property({ type: Object })
150
+ validationMessages: Record<string, string> = {}
151
+
152
+ /** Disables the browser's validation. */
153
+ @property({ type: Boolean, reflect: true })
154
+ novalidate: boolean = false
155
+
156
+ @state()
157
+ _validity: ValidityState | null = null
110
158
 
111
159
  static resolveErrorMessage(message, refernceValue) {
112
160
  if (typeof message === "function") {
@@ -116,28 +164,7 @@ export class LeuInput extends LeuElement {
116
164
  return message
117
165
  }
118
166
 
119
- constructor() {
120
- super()
121
-
122
- this.disabled = false
123
- this.required = false
124
- this.clearable = false
125
-
126
- /** @type {"small" | "regular"} */
127
- this.size = SIZES.REGULAR
128
-
129
- this.type = "text"
130
- this._validity = null
131
- this.validationMessages = {}
132
- this.novalidate = false
133
- this.value = ""
134
-
135
- /**
136
- * @internal
137
- * @type {import("lit/directives/ref.js").Ref<HTMLInputElement>}
138
- */
139
- this._inputRef = createRef()
140
- }
167
+ protected _inputRef = createRef<HTMLInputElement>()
141
168
 
142
169
  get valueAsNumber() {
143
170
  if (this.value === "") {
@@ -153,11 +180,8 @@ export class LeuInput extends LeuElement {
153
180
  * looks like the input element. But the actual input field does not
154
181
  * completely fill the wrapper element. Keyboard events don't need to be
155
182
  * handled because the actual input element is focusable.
156
- * @private
157
- * @param {MouseEvent|PointerEvent} event
158
- * @returns {void}
159
183
  */
160
- handleWrapperClick(event) {
184
+ protected handleWrapperClick(event: MouseEvent | PointerEvent) {
161
185
  if (event.target === event.currentTarget) {
162
186
  this._inputRef.value.focus()
163
187
  }
@@ -166,11 +190,8 @@ export class LeuInput extends LeuElement {
166
190
  /**
167
191
  * Method for handling the blur event of the input element.
168
192
  * Checks validity of the input element and sets the validity state.
169
- * @private
170
- * @param {FocusEvent & {target: HTMLInputElement}} event
171
- * @returns {void}
172
193
  */
173
- handleBlur(event) {
194
+ protected handleBlur(event: FocusEvent & { target: HTMLInputElement }) {
174
195
  this._validity = null
175
196
 
176
197
  if (!this.novalidate) {
@@ -181,11 +202,8 @@ export class LeuInput extends LeuElement {
181
202
  /**
182
203
  * Method for handling the invalid event of the input element.
183
204
  * Sets the validity state.
184
- * @private
185
- * @param {Event} event
186
- * @returns {void}
187
205
  */
188
- handleInvalid(event) {
206
+ protected handleInvalid(event: Event & { target: HTMLInputElement }) {
189
207
  this._validity = event.target.validity
190
208
  }
191
209
 
@@ -193,12 +211,9 @@ export class LeuInput extends LeuElement {
193
211
  * Method for handling the change event of the input element.
194
212
  * Sets the value property and dispatches a change event so that
195
213
  * the event can be handled outside the shadow DOM.
196
- * @private
197
- * @param {Event} event
198
214
  * @fires {CustomEvent} change
199
- * @returns {void}
200
215
  */
201
- handleChange(event) {
216
+ protected handleChange(event: Event & { target: HTMLInputElement }) {
202
217
  if (event.target.validity.valid) {
203
218
  this.value = event.target.value
204
219
  }
@@ -211,11 +226,8 @@ export class LeuInput extends LeuElement {
211
226
  * Method for handling the input event of the input element.
212
227
  * Sets the value property and dispatches an input event so that
213
228
  * the event can be handled outside the shadow DOM.
214
- * @private
215
- * @param {Event} event
216
- * @returns {void}
217
229
  */
218
- handleInput(event) {
230
+ protected handleInput(event: Event & { target: HTMLInputElement }) {
219
231
  this.value = event.target.value
220
232
 
221
233
  const customEvent = new CustomEvent("input", {
@@ -229,12 +241,10 @@ export class LeuInput extends LeuElement {
229
241
  * Method for clearing the input element.
230
242
  * Sets the value property to an empty string and dispatches
231
243
  * an input and a change event.
232
- * @private
233
- * @returns {void}
234
244
  * @fires {CustomEvent} input
235
245
  * @fires {CustomEvent} change
236
246
  */
237
- clear() {
247
+ protected clear() {
238
248
  this.value = ""
239
249
 
240
250
  this._inputRef.value.focus()
@@ -255,10 +265,8 @@ export class LeuInput extends LeuElement {
255
265
  * e.g.
256
266
  * `tooLong(this.maxlength)`
257
267
  * This way the framework user can create reasonable validation messages
258
- *
259
- * @returns {Object} validationMessages
260
268
  */
261
- getValidationMessages() {
269
+ protected getValidationMessages() {
262
270
  const validationMessages = {
263
271
  ...VALIDATION_MESSAGES,
264
272
  ...this.validationMessages,
@@ -299,7 +307,6 @@ export class LeuInput extends LeuElement {
299
307
 
300
308
  /**
301
309
  * Check input validation
302
- * @returns {boolean} if valid or not
303
310
  */
304
311
  checkValidity() {
305
312
  return this._inputRef.value?.checkValidity() ?? false
@@ -307,9 +314,8 @@ export class LeuInput extends LeuElement {
307
314
 
308
315
  /**
309
316
  * Creates an error list with an item for the given validity state.
310
- * @returns {import("lit").TemplateResult | nothing}
311
317
  */
312
- renderErrorMessages() {
318
+ protected renderErrorMessages() {
313
319
  if (!this.isInvalid()) {
314
320
  return nothing
315
321
  }
@@ -317,7 +323,7 @@ export class LeuInput extends LeuElement {
317
323
  const validationMessages = this.getValidationMessages()
318
324
  let errorMessages = this._validity
319
325
  ? Object.entries(validationMessages)
320
- .filter(([property]) => this._validity[property])
326
+ .filter(([prop]) => this._validity[prop])
321
327
  .map(([_, message]) => message)
322
328
  : []
323
329
 
@@ -337,11 +343,8 @@ export class LeuInput extends LeuElement {
337
343
  /**
338
344
  * Determines the content that is displayed after the input element.
339
345
  * This can be either an icon, a clear button or an error indicator icon.
340
- *
341
- * @private
342
- * @returns {import("lit").TemplateResult | nothing}
343
346
  */
344
- renderAfterContent() {
347
+ protected renderAfterContent() {
345
348
  if (this.isInvalid()) {
346
349
  return html`<div class="error-icon">
347
350
  <leu-icon name="caution"></leu-icon>
@@ -1,4 +1,5 @@
1
1
  import { html, PropertyValues } from "lit"
2
+ import { property } from "lit/decorators.js"
2
3
 
3
4
  import { LeuElement } from "../../lib/LeuElement.js"
4
5
 
@@ -22,18 +23,8 @@ export class LeuMenu extends LeuElement {
22
23
  delegatesFocus: true,
23
24
  }
24
25
 
25
- static properties = {
26
- selects: { type: String, reflect: true },
27
- }
28
-
29
- constructor() {
30
- super()
31
-
32
- /** @type {SelectsType} */
33
- this.selects = "none"
34
-
35
- this.value = undefined
36
- }
26
+ @property({ type: String, reflect: true })
27
+ selects: "single" | "multiple" | "none" = "none"
37
28
 
38
29
  connectedCallback() {
39
30
  super.connectedCallback()