@statistikzh/leu 0.0.2

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 (141) hide show
  1. package/.editorconfig +29 -0
  2. package/.eslintrc.json +27 -0
  3. package/.github/workflows/publish.yml +19 -0
  4. package/.github/workflows/release-please.yml +19 -0
  5. package/.github/workflows/test.yml +38 -0
  6. package/.husky/commit-msg +4 -0
  7. package/.husky/pre-commit +4 -0
  8. package/.prettierignore +1 -0
  9. package/.storybook/main.js +11 -0
  10. package/.storybook/preview-head.html +5 -0
  11. package/.storybook/preview.js +23 -0
  12. package/CHANGELOG.md +63 -0
  13. package/CODE_OF_CONDUCT.md +128 -0
  14. package/CONTRIBUTING.md +31 -0
  15. package/LICENSE +21 -0
  16. package/README.md +170 -0
  17. package/commitlint.config.cjs +1 -0
  18. package/dist/Button-83c6df93.js +403 -0
  19. package/dist/Checkbox.js +144 -0
  20. package/dist/CheckboxGroup.js +82 -0
  21. package/dist/Chip-60af1402.js +162 -0
  22. package/dist/ChipGroup.js +79 -0
  23. package/dist/ChipLink.js +46 -0
  24. package/dist/ChipRemovable.js +43 -0
  25. package/dist/ChipSelectable.js +92 -0
  26. package/dist/Input.js +686 -0
  27. package/dist/Radio.js +156 -0
  28. package/dist/RadioGroup.js +194 -0
  29. package/dist/Select.js +859 -0
  30. package/dist/Table-72d305d7.js +506 -0
  31. package/dist/Table.js +8 -0
  32. package/dist/defineElement-47d4f665.js +15 -0
  33. package/dist/icon-b68c7e1e.js +202 -0
  34. package/dist/index.js +21 -0
  35. package/dist/leu-checkbox-group.js +6 -0
  36. package/dist/leu-checkbox.js +6 -0
  37. package/dist/leu-chip-group.js +5 -0
  38. package/dist/leu-chip-link.js +6 -0
  39. package/dist/leu-chip-removable.js +7 -0
  40. package/dist/leu-chip-selectable.js +6 -0
  41. package/dist/leu-input.js +9 -0
  42. package/dist/leu-radio-group.js +6 -0
  43. package/dist/leu-radio.js +5 -0
  44. package/dist/leu-select.js +12 -0
  45. package/dist/leu-table.js +10 -0
  46. package/dist/theme.css +51 -0
  47. package/index.js +10 -0
  48. package/package.json +85 -0
  49. package/postcss.config.cjs +14 -0
  50. package/rollup.config.js +54 -0
  51. package/scripts/generate-component/generate.js +167 -0
  52. package/scripts/generate-component/templates/[Name].js +33 -0
  53. package/scripts/generate-component/templates/[name].css +11 -0
  54. package/scripts/generate-component/templates/[namespace]-[name].js +3 -0
  55. package/scripts/generate-component/templates/stories/[name].stories.js +13 -0
  56. package/scripts/generate-component/templates/test/[name].test.js +22 -0
  57. package/src/components/button/Button.js +150 -0
  58. package/src/components/button/button.css +232 -0
  59. package/src/components/button/leu-button.js +3 -0
  60. package/src/components/button/stories/button.stories.js +333 -0
  61. package/src/components/button/test/button.test.js +22 -0
  62. package/src/components/button-group/ButtonGroup.js +63 -0
  63. package/src/components/button-group/button-group.css +10 -0
  64. package/src/components/button-group/leu-button-group.js +3 -0
  65. package/src/components/button-group/stories/button-group.stories.js +41 -0
  66. package/src/components/button-group/test/button-group.test.js +22 -0
  67. package/src/components/checkbox/Checkbox.js +142 -0
  68. package/src/components/checkbox/CheckboxGroup.js +80 -0
  69. package/src/components/checkbox/leu-checkbox-group.js +3 -0
  70. package/src/components/checkbox/leu-checkbox.js +3 -0
  71. package/src/components/checkbox/stories/checkbox-group.stories.js +52 -0
  72. package/src/components/checkbox/stories/checkbox.stories.js +43 -0
  73. package/src/components/checkbox/test/checkbox.test.js +101 -0
  74. package/src/components/chip/Chip.js +24 -0
  75. package/src/components/chip/ChipGroup.js +71 -0
  76. package/src/components/chip/ChipLink.js +45 -0
  77. package/src/components/chip/ChipRemovable.js +42 -0
  78. package/src/components/chip/ChipSelectable.js +91 -0
  79. package/src/components/chip/chip-group.css +5 -0
  80. package/src/components/chip/chip.css +130 -0
  81. package/src/components/chip/exports.js +10 -0
  82. package/src/components/chip/leu-chip-group.js +3 -0
  83. package/src/components/chip/leu-chip-link.js +3 -0
  84. package/src/components/chip/leu-chip-removable.js +3 -0
  85. package/src/components/chip/leu-chip-selectable.js +3 -0
  86. package/src/components/chip/stories/chip-group.stories.js +99 -0
  87. package/src/components/chip/stories/chip-link.stories.js +37 -0
  88. package/src/components/chip/stories/chip-removable.stories.js +28 -0
  89. package/src/components/chip/stories/chip-selectable.stories.js +46 -0
  90. package/src/components/chip/test/chip.test.js +22 -0
  91. package/src/components/dropdown/Dropdown.js +55 -0
  92. package/src/components/dropdown/dropdown.css +17 -0
  93. package/src/components/dropdown/leu-dropdown.js +3 -0
  94. package/src/components/dropdown/stories/dropdown.stories.js +25 -0
  95. package/src/components/dropdown/test/dropdown.test.js +31 -0
  96. package/src/components/icon/icon.js +201 -0
  97. package/src/components/input/Input.js +421 -0
  98. package/src/components/input/input.css +231 -0
  99. package/src/components/input/leu-input.js +3 -0
  100. package/src/components/input/stories/input.stories.js +185 -0
  101. package/src/components/input/test/input.test.js +22 -0
  102. package/src/components/menu/Menu.js +18 -0
  103. package/src/components/menu/MenuItem.js +95 -0
  104. package/src/components/menu/leu-menu-item.js +3 -0
  105. package/src/components/menu/leu-menu.js +3 -0
  106. package/src/components/menu/menu-item.css +72 -0
  107. package/src/components/menu/menu.css +14 -0
  108. package/src/components/menu/stories/menu-item.stories.js +51 -0
  109. package/src/components/menu/stories/menu.stories.js +21 -0
  110. package/src/components/menu/test/menu.test.js +22 -0
  111. package/src/components/pagination/Pagination.js +152 -0
  112. package/src/components/pagination/leu-pagination.js +3 -0
  113. package/src/components/pagination/pagination.css +49 -0
  114. package/src/components/pagination/stories/pagination.stories.js +82 -0
  115. package/src/components/pagination/test/pagination.test.js +22 -0
  116. package/src/components/radio/Radio.js +62 -0
  117. package/src/components/radio/RadioGroup.js +193 -0
  118. package/src/components/radio/leu-radio-group.js +3 -0
  119. package/src/components/radio/leu-radio.js +3 -0
  120. package/src/components/radio/radio.css +76 -0
  121. package/src/components/radio/stories/radio-group.stories.js +49 -0
  122. package/src/components/radio/stories/radio.stories.js +48 -0
  123. package/src/components/radio/test/radio.test.js +38 -0
  124. package/src/components/select/Select.js +350 -0
  125. package/src/components/select/leu-select.js +3 -0
  126. package/src/components/select/select.css +215 -0
  127. package/src/components/select/stories/select.stories.js +302 -0
  128. package/src/components/select/test/select.test.js +29 -0
  129. package/src/components/table/Table.js +301 -0
  130. package/src/components/table/leu-table.js +3 -0
  131. package/src/components/table/stories/table.stories.js +116 -0
  132. package/src/components/table/test/table.test.js +36 -0
  133. package/src/lib/defineElement.js +13 -0
  134. package/src/lib/hasSlotController.js +85 -0
  135. package/src/styles/custom-media.css +5 -0
  136. package/src/styles/custom-properties.css +51 -0
  137. package/src/styles/theme.css +1 -0
  138. package/stat_zh.png +0 -0
  139. package/stylelint.config.mjs +21 -0
  140. package/web-dev-server-storybook.config.mjs +19 -0
  141. package/web-test-runner.config.mjs +49 -0
@@ -0,0 +1,333 @@
1
+ import { html } from "lit"
2
+ import { ifDefined } from "lit/directives/if-defined.js"
3
+ import { classMap } from "lit/directives/class-map.js"
4
+ import "../leu-button.js"
5
+ import { ICON_NAMES } from "../../icon/icon.js"
6
+ import {
7
+ BUTTON_VARIANTS,
8
+ BUTTON_TYPES,
9
+ BUTTON_SIZES,
10
+ BUTTON_EXPANDED_OPTIONS,
11
+ } from "../Button.js"
12
+
13
+ function copyContent(params) {
14
+ const string = `<leu-button${Object.values(params)
15
+ .filter((o) => o)
16
+ .join("")}>\n</leu-button>`
17
+ navigator.clipboard.writeText(string)
18
+ }
19
+
20
+ export default {
21
+ title: "Button",
22
+ component: "leu-button",
23
+ }
24
+
25
+ function Template({
26
+ label,
27
+ round,
28
+ size,
29
+ active,
30
+ inverted,
31
+ variant,
32
+ disabled,
33
+ icon,
34
+ iconAfter,
35
+ type,
36
+ expanded,
37
+ }) {
38
+ const params = {
39
+ label: label ? ` label="${label}"` : undefined,
40
+ size: size === "small" ? ' size="small"' : undefined,
41
+ variant: variant !== "primary" ? ` variant="${variant}"` : undefined,
42
+ icon: icon ? ` icon="${icon}"` : undefined,
43
+ iconAfter: iconAfter ? ` icon="${iconAfter}"` : undefined,
44
+ round: round ? " round" : undefined,
45
+ active: active ? " active" : undefined,
46
+ disabled: disabled ? " disabled" : undefined,
47
+ inverted: inverted ? " inverted" : undefined,
48
+ expanded: expanded ? ` expanded="${expanded}"` : undefined,
49
+ }
50
+ const component = html`
51
+ <leu-button
52
+ label=${ifDefined(label)}
53
+ size=${ifDefined(size)}
54
+ variant=${ifDefined(variant)}
55
+ icon=${ifDefined(icon)}
56
+ iconAfter=${ifDefined(iconAfter)}
57
+ type=${ifDefined(type)}
58
+ expanded=${expanded}
59
+ ?round=${round}
60
+ ?active=${active}
61
+ ?inverted=${inverted}
62
+ ?disabled=${disabled}
63
+ @click=${() => copyContent(params)}
64
+ >
65
+ </leu-button>
66
+ <br />
67
+ <p>Click the button to copy the code to the clipboard</p>
68
+ `
69
+
70
+ return html`
71
+ <style>
72
+ * {
73
+ font-family: Helvetica;
74
+ }
75
+ </style>
76
+ <div
77
+ style="${inverted
78
+ ? "background:var(--leu-color-accent-blue);"
79
+ : ""}padding:40px;"
80
+ >
81
+ ${component}
82
+ </div>
83
+ `
84
+ }
85
+
86
+ export const Regular = Template.bind({})
87
+ Regular.argTypes = {
88
+ label: { type: "string" },
89
+ icon: { control: "select", options: ICON_NAMES },
90
+ iconAfter: { control: "select", options: ICON_NAMES },
91
+ type: { control: "radio", options: BUTTON_TYPES },
92
+ size: { control: "radio", options: BUTTON_SIZES },
93
+ variant: { control: "radio", options: BUTTON_VARIANTS },
94
+ expanded: { control: "radio", options: BUTTON_EXPANDED_OPTIONS },
95
+ }
96
+ Regular.args = {
97
+ label: "Click Mich...",
98
+ round: false,
99
+ disabled: false,
100
+ active: false,
101
+ inverted: false,
102
+
103
+ icon: null,
104
+ iconAfter: null,
105
+ size: null,
106
+ variant: null,
107
+ type: null,
108
+ }
109
+
110
+ const items = [
111
+ { label: "Normal" },
112
+ { label: "Active", active: true },
113
+ { label: "Disabled", disabled: true },
114
+
115
+ { label: "Normal", icon: "calendar" },
116
+ { label: "Active", icon: "calendar", active: true },
117
+ { label: "Disabled", icon: "calendar", disabled: true },
118
+
119
+ { label: "Normal", iconAfter: "calendar" },
120
+ { label: "Active", iconAfter: "calendar", active: true },
121
+ { label: "Disabled", iconAfter: "calendar", disabled: true },
122
+
123
+ { icon: "calendar" },
124
+ { icon: "calendar", active: true },
125
+ { icon: "calendar", disabled: true },
126
+
127
+ { icon: "calendar", round: true },
128
+ { icon: "calendar", round: true, active: true },
129
+ { icon: "calendar", round: true, disabled: true },
130
+ ]
131
+
132
+ const ghostItems = [
133
+ { label: "Normal", icon: "calendar" },
134
+ { label: "Active", icon: "calendar", active: true },
135
+ { label: "Disabled", icon: "calendar", disabled: true },
136
+
137
+ { label: "Normal", icon: "calendar", expanded: "closed" },
138
+ { label: "Active", icon: "calendar", active: true, expanded: "closed" },
139
+ { label: "Disabled", icon: "calendar", disabled: true, expanded: "closed" },
140
+
141
+ { label: "Normal", iconAfter: "calendar" },
142
+ { label: "Active", iconAfter: "calendar", active: true },
143
+ { label: "Disabled", iconAfter: "calendar", disabled: true },
144
+ ]
145
+
146
+ const sizes = [
147
+ {
148
+ size: "normal",
149
+ items,
150
+ },
151
+ {
152
+ size: "small",
153
+ items,
154
+ },
155
+ ]
156
+
157
+ const groups = [
158
+ {
159
+ inverted: false,
160
+ variant: "primary",
161
+ sizes,
162
+ },
163
+ {
164
+ inverted: false,
165
+ variant: "secondary",
166
+ sizes,
167
+ },
168
+ {
169
+ inverted: false,
170
+ variant: "ghost",
171
+ sizes: [{ size: "normal", items: ghostItems }],
172
+ },
173
+ {
174
+ inverted: true,
175
+ variant: "primary",
176
+ sizes,
177
+ },
178
+ {
179
+ inverted: true,
180
+ variant: "secondary",
181
+ sizes,
182
+ },
183
+ {
184
+ inverted: true,
185
+ variant: "ghost",
186
+ sizes: [{ size: "normal", items: ghostItems }],
187
+ },
188
+ ]
189
+
190
+ function TemplateDev() {
191
+ return html` <style>
192
+ .codeblock {
193
+ position: relative;
194
+ }
195
+ .codeblock > pre {
196
+ background-image: repeating-linear-gradient(
197
+ #acc,
198
+ #acc 8px,
199
+ #9bb 0,
200
+ #9bb 24px,
201
+ #acc 0,
202
+ #acc 32px
203
+ );
204
+ background-attachment: local;
205
+ border: 1px solid #999;
206
+ color: #000;
207
+ font-family: monospace;
208
+ font-size: 14px;
209
+ line-height: 16px;
210
+ max-height: 400px;
211
+ overflow: scroll;
212
+ overflow: auto;
213
+ padding: 8px;
214
+ resize: none;
215
+ unicode-bidi: embed;
216
+ width: 100%;
217
+ box-sizing: border-box;
218
+ }
219
+ .codeblock > leu-button {
220
+ position: absolute;
221
+ right: 10px;
222
+ top: 10px;
223
+ }
224
+ * {
225
+ font-family: Helvetica;
226
+ }
227
+ p {
228
+ margin: 0 20px;
229
+ }
230
+ h2 {
231
+ margin: 50px 0 20px 20px;
232
+ }
233
+ .group {
234
+ padding: 20px;
235
+ }
236
+ .inverted {
237
+ background: var(--leu-color-accent-blue);
238
+ color: #fff;
239
+ }
240
+ .main-table {
241
+ display: grid;
242
+ align-items: start;
243
+ grid-template-columns: auto auto;
244
+ gap: 10px;
245
+ padding: 10px;
246
+ }
247
+ .table {
248
+ display: grid;
249
+ align-items: center;
250
+ grid-template-columns: auto auto auto;
251
+ gap: 10px;
252
+ padding: 10px;
253
+ }
254
+ </style>
255
+ ${groups.map(
256
+ (group) =>
257
+ html`
258
+ <h2>${group.variant + (group.inverted ? " + inverted" : "")}</h2>
259
+ <div
260
+ class=${classMap({
261
+ "main-table": true,
262
+ group: true,
263
+ inverted: group.inverted,
264
+ })}
265
+ >
266
+ ${group.sizes.map(
267
+ (size) =>
268
+ html`
269
+ <div>
270
+ <div class=${classMap({ table: true })}>
271
+ ${size.items.map((item) => {
272
+ const params = {
273
+ label: item.label
274
+ ? ` label="${item.label}"`
275
+ : undefined,
276
+ size:
277
+ size.size === "small" ? ' size="small"' : undefined,
278
+ variant:
279
+ group.variant !== "primary"
280
+ ? ` variant="${group.variant}"`
281
+ : undefined,
282
+ icon: item.icon ? ` icon="${item.icon}"` : undefined,
283
+ iconAfter: item.iconAfter
284
+ ? ` icon="${item.iconAfter}"`
285
+ : undefined,
286
+ round: item.round ? " round" : undefined,
287
+ active: item.active ? " active" : undefined,
288
+ disabled: item.disabled ? " disabled" : undefined,
289
+ inverted: group.inverted ? " inverted" : undefined,
290
+ expanded: item.expanded
291
+ ? ` expanded="${item.expanded}"`
292
+ : undefined,
293
+ }
294
+ return html`
295
+ <leu-button
296
+ label=${ifDefined(item.label)}
297
+ size=${ifDefined(size.size)}
298
+ variant=${ifDefined(group.variant)}
299
+ icon=${ifDefined(item.icon)}
300
+ iconAfter=${ifDefined(item.iconAfter)}
301
+ expanded=${ifDefined(item.expanded)}
302
+ ?round=${item.round}
303
+ ?active=${item.active}
304
+ ?disabled=${item.disabled}
305
+ ?inverted=${group.inverted}
306
+ @click=${() => copyContent(params)}
307
+ >
308
+ </leu-button>
309
+ `
310
+ })}
311
+ </div>
312
+ </div>
313
+ `
314
+ )}
315
+ </div>
316
+ <p>Click the button to copy the code to the clipboard</p>
317
+ `
318
+ )}`
319
+ }
320
+
321
+ export const Dev = TemplateDev.bind({})
322
+ Dev.argTypes = {
323
+ label: { table: { disable: true } },
324
+ icon: { table: { disable: true } },
325
+ iconAfter: { table: { disable: true } },
326
+ size: { table: { disable: true } },
327
+ variant: { table: { disable: true } },
328
+ type: { table: { disable: true } },
329
+ disabled: { table: { disable: true } },
330
+ round: { table: { disable: true } },
331
+ active: { table: { disable: true } },
332
+ inverted: { table: { disable: true } },
333
+ }
@@ -0,0 +1,22 @@
1
+ import { html } from "lit"
2
+ import { fixture, expect } from "@open-wc/testing"
3
+
4
+ import "../leu-button.js"
5
+
6
+ async function defaultFixture() {
7
+ return fixture(html` <leu-button label="button"></leu-button>`)
8
+ }
9
+
10
+ describe("LeuButton", () => {
11
+ it("is a defined element", async () => {
12
+ const el = await customElements.get("leu-button")
13
+
14
+ await expect(el).not.to.be.undefined
15
+ })
16
+
17
+ it("passes the a11y audit", async () => {
18
+ const el = await defaultFixture()
19
+
20
+ await expect(el).shadowDom.to.be.accessible()
21
+ })
22
+ })
@@ -0,0 +1,63 @@
1
+ import { html, LitElement } from "lit"
2
+ import { defineElement } from "../../lib/defineElement.js"
3
+ import styles from "./button-group.css"
4
+ import { defineButtonElements } from "../button/Button.js"
5
+
6
+ /**
7
+ * @tagname leu-button-group
8
+ */
9
+ export class LeuButtonGroup extends LitElement {
10
+ static styles = styles
11
+
12
+ static properties = {
13
+ items: { type: Array, reflect: true },
14
+ value: { type: String, reflect: true },
15
+ }
16
+
17
+ constructor() {
18
+ super()
19
+ /** @type {Array} */
20
+ this.items = []
21
+ /** @type {string} */
22
+ this.value = null
23
+ }
24
+
25
+ _setValue(newValue) {
26
+ this.value = newValue
27
+
28
+ this.dispatchEvent(
29
+ new CustomEvent("input", {
30
+ bubbles: true,
31
+ composed: true,
32
+ detail: { value: newValue },
33
+ })
34
+ )
35
+ }
36
+
37
+ render() {
38
+ return html`
39
+ <div role="menubar" class="group">
40
+ ${this.items.map(
41
+ (item) =>
42
+ html`
43
+ <leu-button
44
+ label=${item}
45
+ variant=${this.value === item ? "primary" : "secondary"}
46
+ @click=${() => {
47
+ this._setValue(item)
48
+ }}
49
+ role="menuitemradio"
50
+ aria-checked=${this.value === item}
51
+ >
52
+ </leu-button>
53
+ `
54
+ )}
55
+ </div>
56
+ `
57
+ }
58
+ }
59
+
60
+ export function defineButtonGroupElements() {
61
+ defineButtonElements()
62
+ defineElement("button-group", LeuButtonGroup)
63
+ }
@@ -0,0 +1,10 @@
1
+ :host,
2
+ :host * {
3
+ box-sizing: border-box;
4
+ }
5
+
6
+ .group {
7
+ display: flex;
8
+ gap: 0.5rem;
9
+ flex-wrap: wrap;
10
+ }
@@ -0,0 +1,3 @@
1
+ import { defineButtonGroupElements } from "./ButtonGroup.js"
2
+
3
+ defineButtonGroupElements()
@@ -0,0 +1,41 @@
1
+ import { html } from "lit"
2
+ import "../leu-button-group.js"
3
+
4
+ // https://stackoverflow.com/questions/72566428/storybook-angular-how-to-dynamically-update-args-from-the-template
5
+ import { UPDATE_STORY_ARGS } from "@storybook/core-events" // eslint-disable-line
6
+ function updateStorybookArgss(id, args) {
7
+ const channel = window.__STORYBOOK_ADDONS_CHANNEL__
8
+ channel.emit(UPDATE_STORY_ARGS, {
9
+ storyId: id,
10
+ updatedArgs: args,
11
+ })
12
+ }
13
+
14
+ export default {
15
+ title: "ButtonGroup",
16
+ component: "leu-button-group",
17
+ }
18
+
19
+ function Template({ items, value }, { id }) {
20
+ return html`
21
+ <leu-button-group
22
+ .items=${items}
23
+ .value=${value}
24
+ @click=${(event) => {
25
+ updateStorybookArgss(id, {
26
+ value: event.target.value,
27
+ })
28
+ }}
29
+ >
30
+ </leu-button-group>
31
+ <br />
32
+ <br />
33
+ <pre>value = '${value}'</pre>
34
+ `
35
+ }
36
+
37
+ export const Regular = Template.bind({})
38
+ Regular.args = {
39
+ items: ["Eins", "Zwei", "Drei"],
40
+ value: "Zwei",
41
+ }
@@ -0,0 +1,22 @@
1
+ import { html } from "lit"
2
+ import { fixture, expect } from "@open-wc/testing"
3
+
4
+ import "../leu-button-group.js"
5
+
6
+ async function defaultFixture() {
7
+ return fixture(html` <leu-button-group /> `)
8
+ }
9
+
10
+ describe("LeuButtonGroup", () => {
11
+ it("is a defined element", async () => {
12
+ const el = await customElements.get("leu-button-group")
13
+
14
+ await expect(el).not.to.be.undefined
15
+ })
16
+
17
+ it("passes the a11y audit", async () => {
18
+ const el = await defaultFixture()
19
+
20
+ await expect(el).shadowDom.to.be.accessible()
21
+ })
22
+ })
@@ -0,0 +1,142 @@
1
+ import { html, css, LitElement } from "lit"
2
+ import { Icon } from "../icon/icon.js"
3
+ import { defineElement } from "../../lib/defineElement.js"
4
+
5
+ /**
6
+ * @tagname leu-checkbox
7
+ */
8
+ export class LeuCheckbox extends LitElement {
9
+ static styles = css`
10
+ :host {
11
+ --checkbox-color: var(--leu-color-black-40);
12
+ --checkbox-color-disabled: var(--leu-color-black-20);
13
+ --checkbox-color-focus: var(--leu-color-func-cyan);
14
+
15
+ --checkbox-label-color: var(--leu-color-black-100);
16
+ --checkbox-label-color-disabled: var(--checkbox-color-disabled);
17
+
18
+ --checkbox-tick-color: var(--leu-color-black-0);
19
+
20
+ --checkbox-font-regular: var(--leu-font-regular);
21
+
22
+ position: relative;
23
+
24
+ display: inline-flex;
25
+ align-items: flex-start;
26
+ gap: 0.5rem;
27
+
28
+ font-family: var(--checkbox-font-regular);
29
+ }
30
+
31
+ .checkbox {
32
+ --_length: 1.5rem;
33
+ appearance: none;
34
+ cursor: pointer;
35
+
36
+ width: var(--_length);
37
+ height: var(--_length);
38
+ margin: 0;
39
+
40
+ border: 2px solid var(--checkbox-color);
41
+ border-radius: 2px;
42
+
43
+ flex: 1 0 var(--_length);
44
+
45
+ display: grid;
46
+ place-items: center;
47
+ }
48
+
49
+ .checkbox:checked {
50
+ background-color: var(--checkbox-color);
51
+ }
52
+
53
+ .checkbox:is(:hover, :checked, :focus) {
54
+ --checkbox-color: var(--checkbox-color-focus);
55
+ }
56
+
57
+ .checkbox:focus-visible {
58
+ outline: 2px solid var(--checkbox-color-focus);
59
+ outline-offset: 2px;
60
+ }
61
+
62
+ .checkbox:disabled {
63
+ --checkbox-color: var(--checkbox-color-disabled);
64
+ cursor: not-allowed;
65
+ }
66
+
67
+ .label {
68
+ cursor: pointer;
69
+ color: var(--checkbox-label-color);
70
+ font-size: 1rem;
71
+ line-height: 1.5;
72
+ }
73
+
74
+ .checkbox:disabled + .label {
75
+ --checkbox-label-color: var(--checkbox-label-color-disabled);
76
+ cursor: not-allowed;
77
+ }
78
+
79
+ .icon {
80
+ position: absolute;
81
+ top: 0;
82
+ left: 0;
83
+ color: var(--checkbox-tick-color);
84
+ pointer-events: none;
85
+ }
86
+ `
87
+
88
+ static shadowRootOptions = {
89
+ ...LitElement.shadowRootOptions,
90
+ delegatesFocus: true,
91
+ }
92
+
93
+ static properties = {
94
+ checked: { type: Boolean, reflect: true },
95
+ disabled: { type: Boolean, reflect: true },
96
+ identifier: { type: String },
97
+ value: { type: String },
98
+ name: { type: String },
99
+ }
100
+
101
+ constructor() {
102
+ super()
103
+ this.checked = false
104
+ this.disabled = false
105
+ this.tabIndex = 0
106
+
107
+ this.checkIcon = Icon("check")
108
+ }
109
+
110
+ handleChange(event) {
111
+ this.checked = event.target.checked
112
+
113
+ const customEvent = new CustomEvent(event.type, event)
114
+ this.dispatchEvent(customEvent)
115
+ }
116
+
117
+ handleInput(event) {
118
+ this.checked = event.target.checked
119
+ }
120
+
121
+ render() {
122
+ return html`
123
+ <input
124
+ id=${this.identifier}
125
+ class="checkbox"
126
+ type="checkbox"
127
+ name="${this.name}"
128
+ @change=${this.handleChange}
129
+ @input=${this.handleInput}
130
+ .checked=${this.checked}
131
+ ?disabled=${this.disabled}
132
+ .value=${this.value}
133
+ />
134
+ <label for=${this.identifier} class="label"><slot></slot></label>
135
+ <div class="icon">${this.checkIcon}</div>
136
+ `
137
+ }
138
+ }
139
+
140
+ export function defineCheckboxElements() {
141
+ defineElement("checkbox", LeuCheckbox)
142
+ }