@oslokommune/punkt-elements 13.4.0 → 13.4.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 (49) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/{alert-B0OUR9oD.js → alert-B07oUpkq.js} +5 -4
  3. package/dist/{alert-BH0lJ2ny.cjs → alert-DQNBDKjT.cjs} +1 -1
  4. package/dist/{backlink-B13JTp9D.js → backlink-C2jbzu0U.js} +16 -15
  5. package/dist/backlink-JbBNi3qg.cjs +13 -0
  6. package/dist/{button-CDocR7iN.cjs → button-B8rdtaHB.cjs} +1 -1
  7. package/dist/{button-DrrEvUy9.js → button-DhispFOY.js} +1 -0
  8. package/dist/{card-uccD6Pnv.cjs → card-BUITGoqX.cjs} +10 -10
  9. package/dist/{card-BI1NZONj.js → card-Dtw26f7i.js} +96 -76
  10. package/dist/checkbox-Gn7Wtk9h.cjs +31 -0
  11. package/dist/checkbox-ym7z6cpt.js +142 -0
  12. package/dist/{combobox-BhcqC30d.cjs → combobox-DjO0RMUB.cjs} +1 -1
  13. package/dist/{combobox-D9dGKWuZ.js → combobox-yE4aYhTi.js} +1 -1
  14. package/dist/{consent-CftYu8Di.js → consent-BpcQFvbi.js} +1 -1
  15. package/dist/{consent-DrS71kvz.cjs → consent-hYeFWNFr.cjs} +1 -1
  16. package/dist/index.d.ts +3 -0
  17. package/dist/pkt-alert.cjs +1 -1
  18. package/dist/pkt-alert.js +1 -1
  19. package/dist/pkt-backlink.cjs +1 -1
  20. package/dist/pkt-backlink.js +1 -1
  21. package/dist/pkt-button.cjs +1 -1
  22. package/dist/pkt-button.js +1 -1
  23. package/dist/pkt-card.cjs +1 -1
  24. package/dist/pkt-card.js +1 -1
  25. package/dist/pkt-checkbox.cjs +1 -1
  26. package/dist/pkt-checkbox.js +1 -1
  27. package/dist/pkt-combobox.cjs +1 -1
  28. package/dist/pkt-combobox.js +1 -1
  29. package/dist/pkt-consent.cjs +1 -1
  30. package/dist/pkt-consent.js +1 -1
  31. package/dist/pkt-index.cjs +1 -1
  32. package/dist/pkt-index.js +7 -7
  33. package/package.json +2 -2
  34. package/src/components/accordion/accordion.test.ts +0 -4
  35. package/src/components/alert/alert.test.ts +348 -0
  36. package/src/components/alert/alert.ts +1 -0
  37. package/src/components/backlink/backlink.test.ts +286 -0
  38. package/src/components/backlink/backlink.ts +5 -3
  39. package/src/components/button/button.test.ts +514 -0
  40. package/src/components/button/button.ts +2 -0
  41. package/src/components/card/card.test.ts +592 -0
  42. package/src/components/card/card.ts +24 -1
  43. package/src/components/checkbox/checkbox.test.ts +535 -0
  44. package/src/components/checkbox/checkbox.ts +44 -1
  45. package/src/components/combobox/combobox.test.ts +737 -0
  46. package/src/components/combobox/combobox.ts +1 -1
  47. package/dist/backlink-C5jQRMwJ.cjs +0 -13
  48. package/dist/checkbox-CTRbpbye.js +0 -120
  49. package/dist/checkbox-wJ26voZd.cjs +0 -30
@@ -0,0 +1,535 @@
1
+ import '@testing-library/jest-dom'
2
+ import { axe, toHaveNoViolations } from 'jest-axe'
3
+ import { fireEvent } from '@testing-library/dom'
4
+
5
+ expect.extend(toHaveNoViolations)
6
+
7
+ import './checkbox'
8
+ import { PktCheckbox } from './checkbox'
9
+
10
+ const waitForCustomElements = async () => {
11
+ await customElements.whenDefined('pkt-checkbox')
12
+ }
13
+
14
+ // Helper function to create checkbox markup
15
+ const createCheckbox = async (checkboxProps = '') => {
16
+ const container = document.createElement('div')
17
+ container.innerHTML = `
18
+ <pkt-checkbox ${checkboxProps}></pkt-checkbox>
19
+ `
20
+ document.body.appendChild(container)
21
+ await waitForCustomElements()
22
+ return container
23
+ }
24
+
25
+ // Cleanup after each test
26
+ afterEach(() => {
27
+ document.body.innerHTML = ''
28
+ })
29
+
30
+ describe('PktCheckbox', () => {
31
+ describe('Rendering and basic functionality', () => {
32
+ test('renders without errors', async () => {
33
+ const container = await createCheckbox('id="test-checkbox" name="test" label="Test Checkbox"')
34
+
35
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
36
+ expect(checkbox).toBeInTheDocument()
37
+
38
+ await checkbox.updateComplete
39
+ expect(checkbox).toBeTruthy()
40
+
41
+ const inputElement = checkbox.querySelector('input[type="checkbox"]')
42
+ expect(inputElement).toBeInTheDocument()
43
+ })
44
+
45
+ test('renders with correct structure', async () => {
46
+ const container = await createCheckbox('id="test" name="test" label="Test Label"')
47
+
48
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
49
+ await checkbox.updateComplete
50
+
51
+ const wrapper = checkbox.querySelector('.pkt-input-check')
52
+ const inputDiv = wrapper?.querySelector('.pkt-input-check__input')
53
+ const input = inputDiv?.querySelector('.pkt-input-check__input-checkbox')
54
+ const label = inputDiv?.querySelector('.pkt-input-check__input-label')
55
+
56
+ expect(wrapper).toBeInTheDocument()
57
+ expect(inputDiv).toBeInTheDocument()
58
+ expect(input).toBeInTheDocument()
59
+ expect(label).toBeInTheDocument()
60
+ expect(label?.textContent?.trim()).toBe('Test Label')
61
+ })
62
+
63
+ test('renders input with correct attributes', async () => {
64
+ const container = await createCheckbox('id="test-id" name="test-name" value="test-value"')
65
+
66
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
67
+ await checkbox.updateComplete
68
+
69
+ const input = checkbox.querySelector('input[type="checkbox"]')
70
+ expect(input?.getAttribute('id')).toBe('test-id-internal')
71
+ expect(input?.getAttribute('name')).toBe('test-name-internal')
72
+ expect(input?.getAttribute('type')).toBe('checkbox')
73
+ })
74
+ })
75
+
76
+ describe('Properties and attributes', () => {
77
+ test('applies default properties correctly', async () => {
78
+ const container = await createCheckbox('id="test" name="test"')
79
+
80
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
81
+ await checkbox.updateComplete
82
+
83
+ expect(checkbox.value).toBe('')
84
+ expect(checkbox.checked).toBe(false)
85
+ expect(checkbox.defaultChecked).toBe(false)
86
+ expect(checkbox.hasTile).toBe(false)
87
+ expect(checkbox.isSwitch).toBe(false)
88
+ expect(checkbox.labelPosition).toBe('right')
89
+ expect(checkbox.hideLabel).toBe(false)
90
+ expect(checkbox.disabled).toBe(false)
91
+ expect(checkbox.optionalTag).toBe(false)
92
+ expect(checkbox.requiredTag).toBe(false)
93
+
94
+ const input = checkbox.querySelector('input[type="checkbox"]')
95
+ expect(input?.getAttribute('role')).toBe('checkbox')
96
+ })
97
+
98
+ test('handles value property correctly', async () => {
99
+ const container = await createCheckbox('id="test" name="test" value="test-value"')
100
+
101
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
102
+ await checkbox.updateComplete
103
+
104
+ expect(checkbox.value).toBe('test-value')
105
+ expect(checkbox.getAttribute('value')).toBe('test-value')
106
+
107
+ // Test value updates
108
+ checkbox.value = 'updated-value'
109
+ await checkbox.updateComplete
110
+
111
+ expect(checkbox.value).toBe('updated-value')
112
+ })
113
+
114
+ test('handles checked property correctly', async () => {
115
+ const container = await createCheckbox('id="test" name="test" checked')
116
+
117
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
118
+ await checkbox.updateComplete
119
+
120
+ expect(checkbox.checked).toBe(true)
121
+
122
+ const input = checkbox.querySelector('input[type="checkbox"]') as HTMLInputElement
123
+ expect(input?.checked).toBe(true)
124
+
125
+ // Test unchecked
126
+ checkbox.checked = false
127
+ await checkbox.updateComplete
128
+
129
+ expect(input?.checked).toBe(false)
130
+ })
131
+
132
+ test('handles defaultChecked property correctly', async () => {
133
+ const container = await createCheckbox('id="test" name="test"')
134
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
135
+
136
+ // Set defaultChecked before checked is set
137
+ checkbox.defaultChecked = true
138
+ await checkbox.updateComplete
139
+
140
+ expect(checkbox.defaultChecked).toBe(true)
141
+ expect(checkbox.checked).toBe(true)
142
+
143
+ // Wait for another update cycle to ensure DOM is updated
144
+ await checkbox.updateComplete
145
+
146
+ const input = checkbox.querySelector('input[type="checkbox"]') as HTMLInputElement
147
+ expect(input?.checked).toBe(true)
148
+ })
149
+
150
+ test('handles disabled property correctly', async () => {
151
+ const container = await createCheckbox('id="test" name="test" disabled')
152
+
153
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
154
+ await checkbox.updateComplete
155
+
156
+ expect(checkbox.disabled).toBe(true)
157
+
158
+ const input = checkbox.querySelector('input[type="checkbox"]') as HTMLInputElement
159
+ const label = checkbox.querySelector('.pkt-input-check__input-label')
160
+ expect(input?.disabled).toBe(true)
161
+ expect(label).toHaveClass('pkt-input-check__input-label--disabled')
162
+ })
163
+
164
+ test('handles labelPosition property correctly', async () => {
165
+ // Test left position
166
+ const container = await createCheckbox('id="test" name="test" label="Test"')
167
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
168
+ checkbox.labelPosition = 'left'
169
+ await checkbox.updateComplete
170
+
171
+ expect(checkbox.labelPosition).toBe('left')
172
+
173
+ let label = checkbox.querySelector('.pkt-input-check__input-label')
174
+ expect(label).toHaveClass('pkt-input-check__input-label--left')
175
+
176
+ // Test right position (default)
177
+ checkbox.labelPosition = 'right'
178
+ await checkbox.updateComplete
179
+
180
+ // Re-query the label element after DOM change
181
+ label = checkbox.querySelector('.pkt-input-check__input-label')
182
+ expect(label).toHaveClass('pkt-input-check__input-label--right')
183
+ expect(label).not.toHaveClass('pkt-input-check__input-label--left')
184
+ })
185
+
186
+ test('handles hideLabel property correctly', async () => {
187
+ const container = await createCheckbox('id="test" name="test" label="Hidden Label"')
188
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
189
+ checkbox.hideLabel = true
190
+ await checkbox.updateComplete
191
+
192
+ expect(checkbox.hideLabel).toBe(true)
193
+
194
+ const label = checkbox.querySelector('.pkt-input-check__input-label')
195
+ expect(label).toHaveClass('pkt-sr-only')
196
+ })
197
+
198
+ test('handles isSwitch property correctly', async () => {
199
+ const container = await createCheckbox('id="test" name="test"')
200
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
201
+ checkbox.isSwitch = true
202
+ await checkbox.updateComplete
203
+
204
+ expect(checkbox.isSwitch).toBe(true)
205
+
206
+ const input = checkbox.querySelector('input[type="checkbox"]')
207
+ expect(input?.getAttribute('role')).toBe('switch')
208
+ })
209
+
210
+ test('handles hasTile property correctly', async () => {
211
+ const container = await createCheckbox('id="test" name="test"')
212
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
213
+ checkbox.hasTile = true
214
+ await checkbox.updateComplete
215
+
216
+ expect(checkbox.hasTile).toBe(true)
217
+
218
+ const inputDiv = checkbox.querySelector('.pkt-input-check__input')
219
+ expect(inputDiv).toHaveClass('pkt-input-check__input--tile')
220
+
221
+ // Test disabled with tile
222
+ checkbox.disabled = true
223
+ await checkbox.updateComplete
224
+
225
+ expect(inputDiv).toHaveClass('pkt-input-check__input--tile-disabled')
226
+ })
227
+ })
228
+
229
+ describe('Label and helptext functionality', () => {
230
+ test('renders label correctly', async () => {
231
+ const container = await createCheckbox('id="test" name="test" label="Checkbox Label"')
232
+
233
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
234
+ await checkbox.updateComplete
235
+
236
+ expect(checkbox.label).toBe('Checkbox Label')
237
+
238
+ const label = checkbox.querySelector('.pkt-input-check__input-label')
239
+ expect(label?.textContent?.trim()).toBe('Checkbox Label')
240
+ expect(label?.getAttribute('for')).toBe('test-internal')
241
+ })
242
+
243
+ test('renders checkHelptext when provided', async () => {
244
+ const container = await createCheckbox(
245
+ 'id="test" name="test" label="Test" checkHelptext="This is help text"',
246
+ )
247
+
248
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
249
+ await checkbox.updateComplete
250
+
251
+ expect(checkbox.checkHelptext).toBe('This is help text')
252
+
253
+ const helptext = checkbox.querySelector('.pkt-input-check__input-helptext')
254
+ expect(helptext).toBeInTheDocument()
255
+ expect(helptext?.textContent).toBe('This is help text')
256
+ })
257
+
258
+ test('does not render helptext when not provided', async () => {
259
+ const container = await createCheckbox('id="test" name="test" label="Test"')
260
+
261
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
262
+ await checkbox.updateComplete
263
+
264
+ const helptext = checkbox.querySelector('.pkt-input-check__input-helptext')
265
+ expect(helptext).not.toBeInTheDocument()
266
+ })
267
+ })
268
+
269
+ describe('Tag functionality', () => {
270
+ test('renders custom tagText when provided', async () => {
271
+ const container = await createCheckbox(
272
+ 'id="test" name="test" label="Test" tagText="Custom Tag"',
273
+ )
274
+
275
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
276
+ await checkbox.updateComplete
277
+
278
+ expect(checkbox.tagText).toBe('Custom Tag')
279
+
280
+ const tagElement = checkbox.querySelector('.pkt-tag--gray')
281
+ expect(tagElement).toBeInTheDocument()
282
+ expect(tagElement?.textContent).toBe('Custom Tag')
283
+ })
284
+
285
+ test('renders optional tag when optionalTag is true', async () => {
286
+ const container = await createCheckbox('id="test" name="test" label="Test" optionalTag')
287
+
288
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
289
+ await checkbox.updateComplete
290
+
291
+ expect(checkbox.optionalTag).toBe(true)
292
+ expect(checkbox.optionalText).toBe('Valgfritt')
293
+
294
+ const optionalTag = checkbox.querySelector('.pkt-tag--blue-light')
295
+ expect(optionalTag).toBeInTheDocument()
296
+ expect(optionalTag?.textContent).toBe('Valgfritt')
297
+ })
298
+
299
+ test('renders required tag when requiredTag is true', async () => {
300
+ const container = await createCheckbox('id="test" name="test" label="Test" requiredTag')
301
+
302
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
303
+ await checkbox.updateComplete
304
+
305
+ expect(checkbox.requiredTag).toBe(true)
306
+ expect(checkbox.requiredText).toBe('Må fylles ut')
307
+
308
+ const requiredTag = checkbox.querySelector('.pkt-tag--beige')
309
+ expect(requiredTag).toBeInTheDocument()
310
+ expect(requiredTag?.textContent).toBe('Må fylles ut')
311
+ })
312
+
313
+ test('renders custom optional and required text', async () => {
314
+ const container = await createCheckbox(
315
+ 'id="test" name="test" label="Test" optionalTag optionalText="Custom Optional" requiredTag requiredText="Custom Required"',
316
+ )
317
+
318
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
319
+ await checkbox.updateComplete
320
+
321
+ expect(checkbox.optionalText).toBe('Custom Optional')
322
+ expect(checkbox.requiredText).toBe('Custom Required')
323
+
324
+ const optionalTag = checkbox.querySelector('.pkt-tag--blue-light')
325
+ const requiredTag = checkbox.querySelector('.pkt-tag--beige')
326
+ expect(optionalTag?.textContent).toBe('Custom Optional')
327
+ expect(requiredTag?.textContent).toBe('Custom Required')
328
+ })
329
+
330
+ test('renders multiple tags when multiple are enabled', async () => {
331
+ const container = await createCheckbox(
332
+ 'id="test" name="test" label="Test" tagText="Custom" optionalTag requiredTag',
333
+ )
334
+
335
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
336
+ await checkbox.updateComplete
337
+
338
+ const customTag = checkbox.querySelector('.pkt-tag--gray')
339
+ const optionalTag = checkbox.querySelector('.pkt-tag--blue-light')
340
+ const requiredTag = checkbox.querySelector('.pkt-tag--beige')
341
+
342
+ expect(customTag).toBeInTheDocument()
343
+ expect(optionalTag).toBeInTheDocument()
344
+ expect(requiredTag).toBeInTheDocument()
345
+ })
346
+ })
347
+
348
+ describe('User interaction', () => {
349
+ test('toggles checked state when clicked', async () => {
350
+ const container = await createCheckbox('id="test" name="test" label="Test"')
351
+
352
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
353
+ await checkbox.updateComplete
354
+
355
+ const input = checkbox.querySelector('input[type="checkbox"]') as HTMLInputElement
356
+ expect(input.checked).toBe(false)
357
+
358
+ // Click to check
359
+ fireEvent.click(input)
360
+ await checkbox.updateComplete
361
+
362
+ expect(input.checked).toBe(true)
363
+ expect(checkbox.checked).toBe(true)
364
+
365
+ // Click to uncheck
366
+ fireEvent.click(input)
367
+ await checkbox.updateComplete
368
+
369
+ expect(input.checked).toBe(false)
370
+ expect(checkbox.checked).toBe(false)
371
+ })
372
+
373
+ test('does not toggle when disabled', async () => {
374
+ const container = await createCheckbox('id="test" name="test" label="Test" disabled')
375
+
376
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
377
+ await checkbox.updateComplete
378
+
379
+ const input = checkbox.querySelector('input[type="checkbox"]') as HTMLInputElement
380
+ expect(input.checked).toBe(false)
381
+ expect(input.disabled).toBe(true)
382
+
383
+ // Try to click
384
+ fireEvent.click(input)
385
+ await checkbox.updateComplete
386
+
387
+ // Should remain unchecked
388
+ expect(input.checked).toBe(false)
389
+ expect(checkbox.checked).toBe(false)
390
+ })
391
+
392
+ test('handles focus and blur events', async () => {
393
+ const container = await createCheckbox('id="test" name="test" label="Test"')
394
+
395
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
396
+ await checkbox.updateComplete
397
+
398
+ const input = checkbox.querySelector('input[type="checkbox"]') as HTMLInputElement
399
+
400
+ // Test focus
401
+ fireEvent.focus(input)
402
+ await checkbox.updateComplete
403
+
404
+ // Test blur
405
+ fireEvent.blur(input)
406
+ await checkbox.updateComplete
407
+
408
+ // These should not throw errors and the element should remain functional
409
+ expect(checkbox).toBeInTheDocument()
410
+ })
411
+
412
+ test('marks as touched when interacted with', async () => {
413
+ const container = await createCheckbox('id="test" name="test" label="Test"')
414
+
415
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
416
+ await checkbox.updateComplete
417
+
418
+ const input = checkbox.querySelector('input[type="checkbox"]') as HTMLInputElement
419
+
420
+ // Initially not touched
421
+ expect(checkbox.touched).toBe(false)
422
+
423
+ // Click to interact
424
+ fireEvent.click(input)
425
+ await checkbox.updateComplete
426
+
427
+ // Should be marked as touched
428
+ expect(checkbox.touched).toBe(true)
429
+ })
430
+ })
431
+
432
+ describe('Label position and structure', () => {
433
+ test('places label on the right by default', async () => {
434
+ const container = await createCheckbox('id="test" name="test" label="Right Label"')
435
+
436
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
437
+ await checkbox.updateComplete
438
+
439
+ const inputDiv = checkbox.querySelector('.pkt-input-check__input')
440
+ const children = Array.from(inputDiv?.children || [])
441
+
442
+ // Should have input first, then label
443
+ expect(children[0]).toHaveAttribute('type', 'checkbox')
444
+ expect(children[1]).toHaveClass('pkt-input-check__input-label')
445
+ })
446
+
447
+ test('places label on the left when labelPosition is left', async () => {
448
+ const container = await createCheckbox(
449
+ 'id="test" name="test" label="Left Label" labelPosition="left"',
450
+ )
451
+
452
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
453
+ await checkbox.updateComplete
454
+
455
+ const inputDiv = checkbox.querySelector('.pkt-input-check__input')
456
+ const children = Array.from(inputDiv?.children || [])
457
+
458
+ // Should have label first, then input
459
+ expect(children[0]).toHaveClass('pkt-input-check__input-label')
460
+ expect(children[1]).toHaveAttribute('type', 'checkbox')
461
+ })
462
+ })
463
+
464
+ describe('Error handling', () => {
465
+ test('applies error styling when hasError is true', async () => {
466
+ const container = await createCheckbox('id="test" name="test" label="Test"')
467
+
468
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
469
+ checkbox.hasError = true
470
+ await checkbox.updateComplete
471
+
472
+ const input = checkbox.querySelector('.pkt-input-check__input-checkbox')
473
+ expect(input).toHaveClass('pkt-input-check__input-checkbox--error')
474
+ })
475
+
476
+ test('does not apply error styling when hasError is false', async () => {
477
+ const container = await createCheckbox('id="test" name="test" label="Test"')
478
+
479
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
480
+ await checkbox.updateComplete
481
+
482
+ const input = checkbox.querySelector('.pkt-input-check__input-checkbox')
483
+ expect(input).not.toHaveClass('pkt-input-check__input-checkbox--error')
484
+ })
485
+ })
486
+
487
+ describe('Accessibility', () => {
488
+ test('has no accessibility violations', async () => {
489
+ const container = await createCheckbox(
490
+ 'id="accessible-checkbox" name="test" label="Accessible Checkbox"',
491
+ )
492
+
493
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
494
+ await checkbox.updateComplete
495
+
496
+ const results = await axe(checkbox)
497
+ expect(results).toHaveNoViolations()
498
+ })
499
+
500
+ test('associates label with input correctly', async () => {
501
+ const container = await createCheckbox(
502
+ 'id="test-association" name="test" label="Associated Label"',
503
+ )
504
+
505
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
506
+ await checkbox.updateComplete
507
+
508
+ const input = checkbox.querySelector('input[type="checkbox"]')
509
+ const label = checkbox.querySelector('.pkt-input-check__input-label')
510
+
511
+ expect(input?.getAttribute('id')).toBe('test-association-internal')
512
+ expect(label?.getAttribute('for')).toBe('test-association-internal')
513
+ })
514
+
515
+ test('has correct role for switch when isSwitch is true', async () => {
516
+ const container = await createCheckbox('id="test" name="test" label="Test Switch" isSwitch')
517
+
518
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
519
+ await checkbox.updateComplete
520
+
521
+ const input = checkbox.querySelector('input[type="checkbox"]')
522
+ expect(input?.getAttribute('role')).toBe('switch')
523
+ })
524
+
525
+ test('has correct role for checkbox by default', async () => {
526
+ const container = await createCheckbox('id="test" name="test" label="Test Checkbox"')
527
+
528
+ const checkbox = container.querySelector('pkt-checkbox') as PktCheckbox
529
+ await checkbox.updateComplete
530
+
531
+ const input = checkbox.querySelector('input[type="checkbox"]')
532
+ expect(input?.getAttribute('role')).toBe('checkbox')
533
+ })
534
+ })
535
+ })
@@ -45,6 +45,13 @@ export class PktCheckbox extends PktInputElement {
45
45
  super.firstUpdated(_changedProperties)
46
46
  }
47
47
 
48
+ protected updated(changedProperties: PropertyValues): void {
49
+ if (changedProperties.has('defaultChecked') && !this.checked) {
50
+ this.checked = this.defaultChecked
51
+ }
52
+ super.updated(changedProperties)
53
+ }
54
+
48
55
  render() {
49
56
  const inputTileClasses = classMap({
50
57
  'pkt-input-check__input': true,
@@ -103,7 +110,8 @@ export class PktCheckbox extends PktInputElement {
103
110
  ?disabled=${this.disabled}
104
111
  name=${this.name + '-internal'}
105
112
  ${ref(this.inputRef)}
106
- @change=${this.toggleChecked}
113
+ @change=${this.handleChange}
114
+ @click=${this.handleClick}
107
115
  @blur=${this.onBlur}
108
116
  @focus=${this.onFocus}
109
117
  ?checked=${this.checked}
@@ -115,7 +123,42 @@ export class PktCheckbox extends PktInputElement {
115
123
  `
116
124
  }
117
125
 
126
+ private handleClick(e: Event) {
127
+ // Prevent click on disabled checkbox
128
+ if (this.disabled) {
129
+ e.preventDefault()
130
+ e.stopImmediatePropagation()
131
+ return false
132
+ }
133
+ }
134
+
135
+ private handleChange(e: Event) {
136
+ // Don't process change if disabled
137
+ if (this.disabled) {
138
+ e.preventDefault()
139
+ e.stopImmediatePropagation()
140
+ return false
141
+ }
142
+
143
+ this.toggleChecked(e)
144
+ }
145
+
118
146
  private toggleChecked(e: Event) {
147
+ // Don't toggle if disabled
148
+ if (this.disabled) {
149
+ e.preventDefault()
150
+ e.stopImmediatePropagation()
151
+ return
152
+ }
153
+
154
+ // Also check if the input element itself is disabled
155
+ const target = e.target as HTMLInputElement
156
+ if (target && target.disabled) {
157
+ e.preventDefault()
158
+ e.stopImmediatePropagation()
159
+ return
160
+ }
161
+
119
162
  e.stopImmediatePropagation()
120
163
  this.touched = true
121
164
  if (this.inputRef.value) {