@oslokommune/punkt-elements 19.4.0 → 19.5.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 (171) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/{accordion-CZ0O4c0_.cjs → accordion-5lSFQToJ.cjs} +6 -6
  3. package/dist/{accordion-DFcdonl-.js → accordion-BJh6X1Ek.js} +6 -6
  4. package/dist/{alert-BhvjSA5X.js → alert-C0PiYnot.js} +29 -36
  5. package/dist/alert-IaZzEgyI.cjs +39 -0
  6. package/dist/{backlink-Bw6IcRIo.cjs → backlink-BRqhwUr2.cjs} +1 -1
  7. package/dist/{backlink-DIdgvE2j.js → backlink-BslFewn-.js} +1 -1
  8. package/dist/{breadcrumbs-BfgCx3Xj.js → breadcrumbs-Cr3GugPv.js} +1 -1
  9. package/dist/{breadcrumbs-C10K1XLP.cjs → breadcrumbs-DG4i5UCh.cjs} +1 -1
  10. package/dist/{button-B5rWxfei.js → button-B78im4wB.js} +16 -16
  11. package/dist/button-BNVTj7nB.cjs +32 -0
  12. package/dist/{calendar-U8xkRdgF.js → calendar-BLaRXUBl.js} +1 -1
  13. package/dist/{calendar-D-Ow5DAp.cjs → calendar-TcxvS-1_.cjs} +1 -1
  14. package/dist/{card-D2YYPZr5.js → card-CYKhPUNI.js} +12 -12
  15. package/dist/{card-DW1uklP6.cjs → card-CaLEuumN.cjs} +10 -10
  16. package/dist/{checkbox-C0zLtnCI.cjs → checkbox-DIyi1Cya.cjs} +1 -1
  17. package/dist/{checkbox-B2O0fkh9.js → checkbox-DKeErDb5.js} +1 -1
  18. package/dist/{combobox-DpXTwNr4.js → combobox-BKnHg_-E.js} +30 -30
  19. package/dist/{combobox-BgduqUpf.cjs → combobox-C7FUvv5T.cjs} +22 -22
  20. package/dist/components/alert/alert.d.ts +0 -2
  21. package/dist/{consent-CbJG04C1.js → consent-CleJMbVH.js} +1 -1
  22. package/dist/{consent-DxpJLExu.cjs → consent-Dl-R0iC3.cjs} +1 -1
  23. package/dist/{datepicker-BLBimRTT.js → datepicker-COFEJpB4.js} +10 -10
  24. package/dist/{datepicker-53rj_Qqx.cjs → datepicker-CeUpoQuG.cjs} +27 -27
  25. package/dist/directives/slot-content.d.ts +36 -1
  26. package/dist/element-with-slot-D7sTqOr3.cjs +1 -0
  27. package/dist/{element-with-slot-FD826ooP.js → element-with-slot-DQv0cbbD.js} +80 -21
  28. package/dist/{fileupload-BxfBFhFt.js → fileupload-CUPl41uN.js} +32 -32
  29. package/dist/{fileupload-4wgr4iAi.cjs → fileupload-CaZGBvZr.cjs} +21 -21
  30. package/dist/{footer-CBkKAuvh.js → footer-DdLls3F-.js} +14 -14
  31. package/dist/{footer-DOp_9VdY.cjs → footer-vy9NqT65.cjs} +9 -9
  32. package/dist/{header-Cs4t2XMM.cjs → header-CgP3-6-b.cjs} +50 -50
  33. package/dist/{header-CF-Re0nT.js → header-Cq6INZmI.js} +56 -56
  34. package/dist/{header-menu-C9k9xG9V.js → header-menu-ANj5nL2M.js} +2 -2
  35. package/dist/{header-menu-BnqZagI6.cjs → header-menu-BfkCp8jw.cjs} +1 -1
  36. package/dist/{heading-BRHCV_5J.js → heading-CUrZvkrM.js} +1 -1
  37. package/dist/{heading-u9Arof4p.cjs → heading-zoz-QZJ9.cjs} +1 -1
  38. package/dist/{helptext-DYgeTMtA.cjs → helptext-BCkwSz1m.cjs} +2 -2
  39. package/dist/{helptext-sRC8EJqL.js → helptext-DCT_9dw1.js} +2 -2
  40. package/dist/icon-Dnv6LtPC.cjs +1 -0
  41. package/dist/{icon-DmRyYNlY.js → icon-JigbxxF7.js} +16 -12
  42. package/dist/{input-element-B1BntJeJ.js → input-element-5hsxasU3.js} +1 -1
  43. package/dist/{input-element-W6Gklt2E.cjs → input-element-Ctkz5fQk.cjs} +1 -1
  44. package/dist/{input-wrapper-CSPPa4uc.cjs → input-wrapper-Cf__-4E-.cjs} +28 -28
  45. package/dist/{input-wrapper-C1zXIKBU.js → input-wrapper-DACDx6Ie.js} +45 -45
  46. package/dist/{link-DcxVUj8s.js → link-CmZwAw5u.js} +2 -2
  47. package/dist/link-LO_5_La8.cjs +7 -0
  48. package/dist/{linkcard-MJFR7FLT.js → linkcard-CQluSyJJ.js} +8 -8
  49. package/dist/{linkcard-CWeR6t2a.cjs → linkcard-UKsxADrP.cjs} +3 -3
  50. package/dist/{listbox-DEzd-dxF.js → listbox-Ct9jIV_5.js} +8 -8
  51. package/dist/{listbox-BoBwzL4p.cjs → listbox-g-vHHLkD.cjs} +20 -20
  52. package/dist/{loader-SJ6NauNT.cjs → loader-C_PH05aw.cjs} +2 -2
  53. package/dist/{loader-CqFQoJlM.js → loader-DzctJ9jW.js} +2 -2
  54. package/dist/{messagebox-DsKi_rKn.js → messagebox-DPFBuisE.js} +2 -2
  55. package/dist/messagebox-JWKMJEFc.cjs +13 -0
  56. package/dist/{modal-DaerHpVi.cjs → modal-BymjMIJi.cjs} +2 -2
  57. package/dist/{modal-CJqe6y-V.js → modal-CELmA0-8.js} +2 -2
  58. package/dist/pkt-accordion.cjs +1 -1
  59. package/dist/pkt-accordion.js +1 -1
  60. package/dist/pkt-alert.cjs +1 -1
  61. package/dist/pkt-alert.js +1 -1
  62. package/dist/pkt-backlink.cjs +1 -1
  63. package/dist/pkt-backlink.js +1 -1
  64. package/dist/pkt-breadcrumbs.cjs +1 -1
  65. package/dist/pkt-breadcrumbs.js +1 -1
  66. package/dist/pkt-button.cjs +1 -1
  67. package/dist/pkt-button.js +1 -1
  68. package/dist/pkt-calendar.cjs +1 -1
  69. package/dist/pkt-calendar.js +1 -1
  70. package/dist/pkt-card.cjs +1 -1
  71. package/dist/pkt-card.js +1 -1
  72. package/dist/pkt-checkbox.cjs +1 -1
  73. package/dist/pkt-checkbox.js +1 -1
  74. package/dist/pkt-combobox.cjs +1 -1
  75. package/dist/pkt-combobox.js +1 -1
  76. package/dist/pkt-consent.cjs +1 -1
  77. package/dist/pkt-consent.js +1 -1
  78. package/dist/pkt-datepicker.cjs +1 -1
  79. package/dist/pkt-datepicker.js +1 -1
  80. package/dist/pkt-fileupload.cjs +1 -1
  81. package/dist/pkt-fileupload.js +1 -1
  82. package/dist/pkt-footer.cjs +1 -1
  83. package/dist/pkt-footer.js +1 -1
  84. package/dist/pkt-header-menu.cjs +1 -1
  85. package/dist/pkt-header-menu.js +1 -1
  86. package/dist/pkt-header.cjs +1 -1
  87. package/dist/pkt-header.js +1 -1
  88. package/dist/pkt-heading.cjs +1 -1
  89. package/dist/pkt-heading.js +1 -1
  90. package/dist/pkt-helptext.cjs +1 -1
  91. package/dist/pkt-helptext.js +1 -1
  92. package/dist/pkt-icon.cjs +1 -1
  93. package/dist/pkt-icon.js +1 -1
  94. package/dist/pkt-index.cjs +1 -1
  95. package/dist/pkt-index.js +34 -34
  96. package/dist/pkt-input-wrapper.cjs +1 -1
  97. package/dist/pkt-input-wrapper.js +1 -1
  98. package/dist/pkt-link.cjs +1 -1
  99. package/dist/pkt-link.js +1 -1
  100. package/dist/pkt-linkcard.cjs +1 -1
  101. package/dist/pkt-linkcard.js +1 -1
  102. package/dist/pkt-listbox.cjs +1 -1
  103. package/dist/pkt-listbox.js +1 -1
  104. package/dist/pkt-loader.cjs +1 -1
  105. package/dist/pkt-loader.js +1 -1
  106. package/dist/pkt-messagebox.cjs +1 -1
  107. package/dist/pkt-messagebox.js +1 -1
  108. package/dist/pkt-modal.cjs +1 -1
  109. package/dist/pkt-modal.js +1 -1
  110. package/dist/{pkt-options-controller-Dz-rYCG1.cjs → pkt-options-controller-CpEZcomb.cjs} +1 -1
  111. package/dist/{pkt-options-controller-sUzxHa5A.js → pkt-options-controller-D7l18Iw0.js} +1 -1
  112. package/dist/pkt-progressbar.cjs +1 -1
  113. package/dist/pkt-progressbar.js +1 -1
  114. package/dist/pkt-radiobutton.cjs +1 -1
  115. package/dist/pkt-radiobutton.js +1 -1
  116. package/dist/pkt-searchinput.cjs +1 -1
  117. package/dist/pkt-searchinput.js +1 -1
  118. package/dist/pkt-select.cjs +1 -1
  119. package/dist/pkt-select.js +1 -1
  120. package/dist/pkt-tabs.cjs +1 -1
  121. package/dist/pkt-tabs.js +1 -1
  122. package/dist/pkt-tag.cjs +1 -1
  123. package/dist/pkt-tag.js +1 -1
  124. package/dist/pkt-textarea.cjs +1 -1
  125. package/dist/pkt-textarea.js +1 -1
  126. package/dist/pkt-textinput.cjs +1 -1
  127. package/dist/pkt-textinput.js +1 -1
  128. package/dist/pkt-timepicker.cjs +1 -1
  129. package/dist/pkt-timepicker.js +1 -1
  130. package/dist/{progressbar-BrVlAcQI.cjs → progressbar-CIXNSwTy.cjs} +2 -3
  131. package/dist/{progressbar-Bd0DjiAb.js → progressbar-DH5lIBpx.js} +6 -4
  132. package/dist/{radiobutton-B0V-jSEX.js → radiobutton-DP791tUe.js} +1 -1
  133. package/dist/{radiobutton-Cv1BlwLV.cjs → radiobutton-oEYrBiT6.cjs} +1 -1
  134. package/dist/{searchinput-7-VVdkss.cjs → searchinput-CbClDE-d.cjs} +1 -1
  135. package/dist/{searchinput-CgzigmiI.js → searchinput-Co8tcq-l.js} +1 -1
  136. package/dist/{select-BbcGPmPs.js → select-B97S4g1v.js} +18 -18
  137. package/dist/{select---PCiwmy.cjs → select-QobXCtIL.cjs} +13 -13
  138. package/dist/shared-types/icon.d.ts +39 -0
  139. package/dist/shared-types/index.d.ts +2 -0
  140. package/dist/{tabs-B134M9k2.js → tabs-B8blHQrL.js} +18 -18
  141. package/dist/{tabs-Dw9E06fL.cjs → tabs-CjX-GWvM.cjs} +15 -15
  142. package/dist/tag-B5dUg7AD.cjs +27 -0
  143. package/dist/{tag-wYnHhHLK.js → tag-Bns7Xj1O.js} +11 -11
  144. package/dist/{textarea-BcgVLLTt.js → textarea-DgW0hRV5.js} +17 -17
  145. package/dist/{textarea-pA_xv8lI.cjs → textarea-ZMbtZNp3.cjs} +10 -10
  146. package/dist/{textinput-Czz2affL.cjs → textinput-DfT_1aGb.cjs} +10 -10
  147. package/dist/{textinput-Dpj1X5yr.js → textinput-s-qz2xSC.js} +15 -15
  148. package/dist/{timepicker-BwDZkSpo.cjs → timepicker-BAa_VEnf.cjs} +10 -10
  149. package/dist/{timepicker-CfQMZlaP.js → timepicker-Crj4isb9.js} +16 -16
  150. package/package.json +2 -2
  151. package/src/components/alert/alert.test.ts +15 -0
  152. package/src/components/alert/alert.ts +0 -12
  153. package/src/components/combobox/combobox.ts +3 -3
  154. package/src/components/datepicker/datepicker.ts +5 -5
  155. package/src/components/helptext/helptext-association.test.ts +79 -0
  156. package/src/components/icon/icon.ts +6 -6
  157. package/src/components/input-wrapper/input-wrapper.test.ts +49 -0
  158. package/src/components/input-wrapper/input-wrapper.ts +6 -4
  159. package/src/components/progressbar/progressbar.test.ts +19 -0
  160. package/src/components/progressbar/progressbar.ts +2 -6
  161. package/src/components/select/select.ts +3 -3
  162. package/src/components/textarea/textarea.ts +3 -3
  163. package/src/components/textinput/textinput.ts +3 -3
  164. package/src/components/timepicker/timepicker.ts +3 -3
  165. package/dist/alert-D1bQjZ7C.cjs +0 -40
  166. package/dist/button-CmNrMH-c.cjs +0 -32
  167. package/dist/element-with-slot-2PHu2w7O.cjs +0 -1
  168. package/dist/icon-CoBsgGUR.cjs +0 -1
  169. package/dist/link-EMsHusF7.cjs +0 -7
  170. package/dist/messagebox-D5GYIdjE.cjs +0 -13
  171. package/dist/tag-HTYKd-iG.cjs +0 -27
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oslokommune/punkt-elements",
3
- "version": "19.4.0",
3
+ "version": "19.5.1",
4
4
  "description": "Komponentbiblioteket til Punkt, designsystem for Oslo kommune",
5
5
  "homepage": "https://punkt.oslo.kommune.no",
6
6
  "author": "Team Designsystem, Oslo kommune",
@@ -84,5 +84,5 @@
84
84
  "engines": {
85
85
  "node": "^22.19.0 || ^24.0.0 || ^26.0.0"
86
86
  },
87
- "gitHead": "74057ff529f28056e96199ce2b2def5aee6ef9bf"
87
+ "gitHead": "ec50e19e909a893c46c4cea3a3b0de38e23d8666"
88
88
  }
@@ -37,6 +37,21 @@ afterEach(() => {
37
37
  })
38
38
 
39
39
  describe('PktAlert', () => {
40
+ describe('Host id', () => {
41
+ afterEach(() => {
42
+ document.body.innerHTML = ''
43
+ })
44
+
45
+ test('keeps the id on the host element', async () => {
46
+ document.body.innerHTML = '<pkt-alert id="min-alert">Melding</pkt-alert>'
47
+ const alert = document.querySelector('pkt-alert') as CustomElementFor<'pkt-alert'>
48
+ await alert.updateComplete
49
+
50
+ expect(document.getElementById('min-alert')).toBe(alert)
51
+ expect(document.querySelectorAll('[id="min-alert"]')).toHaveLength(1)
52
+ })
53
+ })
54
+
40
55
  describe('Rendering and basic functionality', () => {
41
56
  test('renders without errors', async () => {
42
57
  const { alert } = await createAlertTest({
@@ -1,5 +1,4 @@
1
1
  import { classMap } from 'lit/directives/class-map.js'
2
- import { ifDefined } from 'lit/directives/if-defined.js'
3
2
  import { customElement, property, state } from 'lit/decorators.js'
4
3
  import { html, nothing, PropertyValues } from 'lit'
5
4
  import { PktElementWithSlot } from '@/base-elements/element-with-slot'
@@ -51,7 +50,6 @@ export class PktAlert extends PktElementWithSlot<IPktAlert> implements IPktAlert
51
50
  ).default
52
51
  @property({ type: String, reflect: true }) date: string | null = null
53
52
  @property({ type: String }) role: string = 'status'
54
- @state() _hostId: string | null = null
55
53
  @property({ type: String, attribute: 'size' })
56
54
  size?: 'medium' | 'small' | 'xsmall'
57
55
  @state() _isClosed: boolean = false
@@ -63,15 +61,6 @@ export class PktAlert extends PktElementWithSlot<IPktAlert> implements IPktAlert
63
61
  this.ariaLiveAttr = (this.getAttribute('aria-live') as TAriaLive) || this.ariaLive
64
62
  }
65
63
 
66
- protected willUpdate(changed: PropertyValues): void {
67
- super.willUpdate(changed)
68
- const id = this.getAttribute('id')
69
- if (id) {
70
- this._hostId = id
71
- this.removeAttribute('id')
72
- }
73
- }
74
-
75
64
  attributeChangedCallback(name: string, _old: string | null, value: string | null): void {
76
65
  if (name === 'ariaLive') {
77
66
  this.ariaLiveAttr = value as TAriaLive
@@ -111,7 +100,6 @@ export class PktAlert extends PktElementWithSlot<IPktAlert> implements IPktAlert
111
100
  return html`
112
101
  <div
113
102
  class=${classMap(classes)}
114
- id=${ifDefined(this._hostId || undefined)}
115
103
  aria-live=${this.ariaLiveAttr}
116
104
  role=${this.role}
117
105
  >
@@ -13,7 +13,7 @@ import type {
13
13
  import { findOptionByValue, findOptionIndex } from 'shared-utils/combobox/option-utils'
14
14
  import { getSingleValueForInput } from 'shared-utils/combobox/input-utils'
15
15
  import { slotUtils, optionStateUtils } from './combobox-utils'
16
- import { slotContent } from '@/directives/slot-content'
16
+ import { forwardSlots } from '@/directives/slot-content'
17
17
  import { ComboboxHandlers } from './combobox-handlers'
18
18
  import { formatString } from 'shared-strings'
19
19
  import type { IPktStringsProps } from 'shared-strings'
@@ -338,6 +338,7 @@ export class PktCombobox extends ComboboxHandlers implements IPktCombobox {
338
338
  render() {
339
339
  return html`
340
340
  <pkt-input-wrapper
341
+ ${forwardSlots(this, ['helptext'])}
341
342
  .strings=${this.strings}
342
343
  .size=${this.inputSize}
343
344
  .label=${this.label}
@@ -363,7 +364,6 @@ export class PktCombobox extends ComboboxHandlers implements IPktCombobox {
363
364
  class="pkt-combobox__wrapper"
364
365
  @labelClick=${this.handleInputClick}
365
366
  >
366
- <div class="pkt-contents" slot="helptext">${slotContent(this, 'helptext')}</div>
367
367
  <div class="pkt-combobox" @focusout=${this.handleFocusOut}>
368
368
  <div
369
369
  class=${classMap({
@@ -467,7 +467,7 @@ export class PktCombobox extends ComboboxHandlers implements IPktCombobox {
467
467
  private _describedBy(): string | undefined {
468
468
  return describedByIds({
469
469
  id: this._hasTextInput ? `${this.id}-input` : `${this.id}-combobox`,
470
- hasHelptext: !!this.helptext,
470
+ hasHelptext: !!this.helptext || this.hasSlotContent('helptext'),
471
471
  ariaDescribedby: this.ariaDescribedby,
472
472
  })
473
473
  }
@@ -14,7 +14,7 @@ import './datepicker-popup'
14
14
  import './datepicker-single'
15
15
  import './datepicker-range'
16
16
  import './datepicker-multiple'
17
- import { slotContent } from '@/directives/slot-content'
17
+ import { forwardSlots } from '@/directives/slot-content'
18
18
  import {
19
19
  valueUtils,
20
20
  inputTypeUtils,
@@ -306,7 +306,7 @@ export class PktDatepicker extends PktInputElement<Props> {
306
306
  .inputSize=${this.inputSize}
307
307
  .internals=${this.internals}
308
308
  .hasError=${this.hasError}
309
- .hasHelptext=${Boolean(this.helptext || this.helptextDropdown)}
309
+ .hasHelptext=${Boolean(this.helptext || this.helptextDropdown || this.hasSlotContent('helptext'))}
310
310
  .strings=${this.strings}
311
311
  @toggle-calendar=${(e: CustomEvent) => this.toggleCalendar(e.detail)}
312
312
  @input-change=${() => this.onInput()}
@@ -345,7 +345,7 @@ export class PktDatepicker extends PktInputElement<Props> {
345
345
  .inputSize=${this.inputSize}
346
346
  .internals=${this.internals}
347
347
  .hasError=${this.hasError}
348
- .hasHelptext=${Boolean(this.helptext || this.helptextDropdown)}
348
+ .hasHelptext=${Boolean(this.helptext || this.helptextDropdown || this.hasSlotContent('helptext'))}
349
349
  .strings=${this.strings}
350
350
  @toggle-calendar=${(e: CustomEvent) => this.toggleCalendar(e.detail)}
351
351
  @input-change=${() => this.onInput()}
@@ -433,7 +433,7 @@ export class PktDatepicker extends PktInputElement<Props> {
433
433
  .inputSize=${this.inputSize}
434
434
  .internals=${this.internals}
435
435
  .hasError=${this.hasError}
436
- .hasHelptext=${Boolean(this.helptext || this.helptextDropdown)}
436
+ .hasHelptext=${Boolean(this.helptext || this.helptextDropdown || this.hasSlotContent('helptext'))}
437
437
  .strings=${this.strings}
438
438
  @toggle-calendar=${(e: CustomEvent) => this.toggleCalendar(e.detail)}
439
439
  @input-change=${() => this.onInput()}
@@ -505,6 +505,7 @@ export class PktDatepicker extends PktInputElement<Props> {
505
505
 
506
506
  return html`
507
507
  <pkt-input-wrapper
508
+ ${forwardSlots(this, ['helptext'])}
508
509
  .strings=${this.strings}
509
510
  label="${this.label}"
510
511
  forId="${this.id}-input"
@@ -529,7 +530,6 @@ export class PktDatepicker extends PktInputElement<Props> {
529
530
  .ariaDescribedby=${this.ariaDescribedby}
530
531
  .size=${this.inputSize}
531
532
  >
532
- <div class="pkt-contents" slot="helptext">${slotContent(this, 'helptext')}</div>
533
533
  ${this.multiple
534
534
  ? html`<pkt-date-tags
535
535
  .dates=${this._value}
@@ -82,6 +82,85 @@ describe('helptext association', () => {
82
82
  expect(input?.getAttribute('aria-label')).toBe('Velg fil')
83
83
  })
84
84
 
85
+ describe('helptext from the slot', () => {
86
+ const slotCases: Array<[string, string]> = [
87
+ ['pkt-textinput', ''],
88
+ ['pkt-textarea', ''],
89
+ ['pkt-select', ''],
90
+ ['pkt-datepicker', ''],
91
+ ['pkt-timepicker', ''],
92
+ ['pkt-combobox', ''],
93
+ ['pkt-combobox', 'allow-user-input'],
94
+ ]
95
+
96
+ const settle = async (host: HTMLElement & { updateComplete: Promise<unknown> }) => {
97
+ for (let i = 0; i < 3; i++) {
98
+ await new Promise((resolve) => setTimeout(resolve, 0))
99
+ await host.updateComplete
100
+ const nested = Array.from(
101
+ host.querySelectorAll<HTMLElement & { updateComplete: Promise<unknown> }>(
102
+ 'pkt-input-wrapper, pkt-helptext',
103
+ ),
104
+ )
105
+ await Promise.all(nested.map((el) => el.updateComplete))
106
+ }
107
+ }
108
+
109
+ const mountWithSlot = async (tag: string, attrs: string, slot: string) => {
110
+ document.body.innerHTML = `<${tag} id="felt" name="felt" label="Etikett" ${attrs}>${slot}</${tag}>`
111
+ await customElements.whenDefined(tag)
112
+ const host = document.querySelector(tag) as HTMLElement & { updateComplete: Promise<unknown> }
113
+ await settle(host)
114
+ return host
115
+ }
116
+
117
+ const controls = (host: HTMLElement) =>
118
+ host.localName === 'pkt-timepicker'
119
+ ? Array.from(host.querySelectorAll('[role="spinbutton"]'))
120
+ : [host.querySelector(CONTROL)]
121
+
122
+ const expectDescribedBySlot = (host: HTMLElement) => {
123
+ const helptext = host.querySelector('.pkt-inputwrapper__helptext')
124
+ expect(helptext?.textContent).toContain('Hjelp fra slot')
125
+ controls(host).forEach((control) => {
126
+ expect(control?.getAttribute('aria-describedby')?.split(' ')).toContain(helptext?.id)
127
+ })
128
+ }
129
+
130
+ test.each(slotCases)('%s %s renders slotted helptext inside the helptext element', async (tag, attrs) => {
131
+ const host = await mountWithSlot(tag, attrs, '<div slot="helptext">Hjelp fra slot</div>')
132
+
133
+ expectDescribedBySlot(host)
134
+ })
135
+
136
+ test.each(slotCases)('%s %s picks up slotted helptext added after the first render', async (tag, attrs) => {
137
+ const host = await mountWithSlot(tag, attrs, '')
138
+ controls(host).forEach((control) => {
139
+ expect(control?.getAttribute('aria-describedby') ?? '').not.toContain('helptext')
140
+ })
141
+
142
+ const slotted = document.createElement('div')
143
+ slotted.setAttribute('slot', 'helptext')
144
+ slotted.textContent = 'Hjelp fra slot'
145
+ host.appendChild(slotted)
146
+ await settle(host)
147
+
148
+ expectDescribedBySlot(host)
149
+ })
150
+
151
+ test.each(slotCases)('%s %s drops the link when slotted helptext is removed', async (tag, attrs) => {
152
+ const host = await mountWithSlot(tag, attrs, '<div slot="helptext" class="slotted">Hjelp fra slot</div>')
153
+ expectDescribedBySlot(host)
154
+
155
+ host.querySelector('.slotted')?.remove()
156
+ await settle(host)
157
+
158
+ controls(host).forEach((control) => {
159
+ expect(control?.getAttribute('aria-describedby') ?? '').not.toContain('helptext')
160
+ })
161
+ })
162
+ })
163
+
85
164
  test('no label carries the description', async () => {
86
165
  for (const [tag, attrs] of cases) {
87
166
  const host = await mount(tag, attrs)
@@ -4,13 +4,12 @@ import { PktIconName } from '@oslokommune/punkt-assets/dist/icons/icon'
4
4
  import { html, PropertyValues } from 'lit'
5
5
  import { customElement, property } from 'lit/decorators.js'
6
6
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js'
7
-
8
- const defaultPath = 'https://punkt-cdn.oslo.kommune.no/latest/icons/'
7
+ import { ICON_DEFAULTS } from 'shared-types'
9
8
 
10
9
  // Allow global override of icon fetch
11
10
  if (typeof window !== 'undefined') {
12
11
  window.pktFetch = window.pktFetch === undefined ? fetch : window.pktFetch
13
- window.pktIconPath = window.pktIconPath || defaultPath
12
+ window.pktIconPath = window.pktIconPath || ICON_DEFAULTS.path
14
13
  }
15
14
 
16
15
  const errorSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"></svg>'
@@ -77,10 +76,11 @@ type Props = ElementProps<PktIcon, 'path' | 'name' | 'ariaHidden' | 'ariaLabel'>
77
76
 
78
77
  export class PktIcon extends PktElement<Props> {
79
78
  @property({ type: String, reflect: false })
80
- path: string | undefined = typeof window !== 'undefined' ? window.pktIconPath : defaultPath
79
+ path: string | undefined =
80
+ typeof window !== 'undefined' ? window.pktIconPath : ICON_DEFAULTS.path
81
81
 
82
82
  @property({ type: String, reflect: true })
83
- name: PktIconName = ''
83
+ name: PktIconName = ICON_DEFAULTS.name
84
84
 
85
85
  @property({
86
86
  type: String,
@@ -145,7 +145,7 @@ export class PktIcon extends PktElement<Props> {
145
145
 
146
146
  protected async getIcon(name: PktIconName = '') {
147
147
  if (this._updatedProps.length > 0) {
148
- if (!this.path) this.path = typeof window !== 'undefined' ? window.pktIconPath : defaultPath
148
+ if (!this.path) this.path = typeof window !== 'undefined' ? window.pktIconPath : ICON_DEFAULTS.path
149
149
  try {
150
150
  this.icon = unsafeSVG(
151
151
  await downloadIconOrGetFromCache(this.name || '', this.path),
@@ -373,6 +373,55 @@ describe('PktInputWrapper', () => {
373
373
  })
374
374
  })
375
375
 
376
+ describe('Fieldset name and description', () => {
377
+ const mountFieldset = async (attributes: string, content = '') => {
378
+ document.body.innerHTML = `<pkt-input-wrapper forId="g" label="Gruppe" hasFieldset ${attributes}>${content}</pkt-input-wrapper>`
379
+ await customElements.whenDefined('pkt-input-wrapper')
380
+ const wrapper = document.querySelector('pkt-input-wrapper') as CustomElementFor<'pkt-input-wrapper'>
381
+ await wrapper.updateComplete
382
+ return wrapper.querySelector('fieldset') as HTMLFieldSetElement
383
+ }
384
+
385
+ const describedByIds = (fieldset: HTMLFieldSetElement) =>
386
+ (fieldset.getAttribute('aria-describedby') ?? '').split(' ').filter(Boolean)
387
+
388
+ afterEach(() => {
389
+ document.body.innerHTML = ''
390
+ })
391
+
392
+ test('links slotted helptext to the fieldset', async () => {
393
+ const fieldset = await mountFieldset('', '<div class="pkt-contents" slot="helptext">Velg ett</div>')
394
+
395
+ expect(describedByIds(fieldset)).toEqual(['g-helptext'])
396
+ })
397
+
398
+ test('renders slotted helptext inside the helptext element', async () => {
399
+ await mountFieldset('', '<div slot="helptext">Velg ett</div>')
400
+
401
+ expect(document.getElementById('g-helptext')?.textContent).toContain('Velg ett')
402
+ })
403
+
404
+ test('links slotted helptext added after the first render', async () => {
405
+ const fieldset = await mountFieldset('')
406
+ expect(fieldset.hasAttribute('aria-describedby')).toBe(false)
407
+ await new Promise((resolve) => setTimeout(resolve, 0))
408
+
409
+ const wrapper = document.querySelector('pkt-input-wrapper') as CustomElementFor<'pkt-input-wrapper'>
410
+ const slotted = document.createElement('div')
411
+ slotted.setAttribute('slot', 'helptext')
412
+ slotted.textContent = 'Velg ett'
413
+ wrapper.appendChild(slotted)
414
+ for (let i = 0; i < 3; i++) {
415
+ await new Promise((resolve) => setTimeout(resolve, 0))
416
+ await wrapper.updateComplete
417
+ await (wrapper.querySelector('pkt-helptext') as CustomElementFor<'pkt-helptext'>).updateComplete
418
+ }
419
+
420
+ expect(describedByIds(fieldset)).toEqual(['g-helptext'])
421
+ expect(document.getElementById('g-helptext')?.textContent).toContain('Velg ett')
422
+ })
423
+ })
424
+
376
425
  describe('Wrapper functionality', () => {
377
426
  test('handles useWrapper property values', async () => {
378
427
  // Test true value
@@ -1,5 +1,5 @@
1
1
  import { PktElementWithSlot } from '@/base-elements/element-with-slot'
2
- import { slotContent } from '@/directives/slot-content'
2
+ import { forwardSlots, slotContent } from '@/directives/slot-content'
3
3
  import { counterStatusId, isCounterExceeded } from 'shared-utils/forms/described-by'
4
4
  import { formatString, type IPktStringsProps } from 'shared-strings'
5
5
  import { ifDefined } from 'lit/directives/if-defined.js'
@@ -99,9 +99,10 @@ export class PktInputWrapper extends PktElementWithSlot<Props> {
99
99
  render() {
100
100
  const tagClasses = 'pkt-tag pkt-tag--small pkt-tag--thin-text'
101
101
 
102
+ const hasHelptext = !!this.helptext || this.hasSlotContent('helptext')
102
103
  const describedBy = this.ariaDescribedby
103
104
  ? this.ariaDescribedby
104
- : this.helptext
105
+ : hasHelptext
105
106
  ? `${this.forId}-helptext`
106
107
  : nothing
107
108
 
@@ -152,8 +153,10 @@ export class PktInputWrapper extends PktElementWithSlot<Props> {
152
153
  }
153
154
 
154
155
  const helptextElement = () => {
156
+ if (!hasHelptext && !this.helptextDropdown) return nothing
155
157
  return html`
156
158
  <pkt-helptext
159
+ ${forwardSlots(this, { helptext: null })}
157
160
  class="${ifDefined(!this.useWrapper ? 'pkt-hide' : undefined)}"
158
161
  .forId=${this.forId}
159
162
  .helptext=${this.helptext}
@@ -162,8 +165,7 @@ export class PktInputWrapper extends PktElementWithSlot<Props> {
162
165
  @toggleHelpText=${(e: CustomEvent) => {
163
166
  this.toggleDropdown(e)
164
167
  }}
165
- >${slotContent(this, 'helptext')}</pkt-helptext
166
- >
168
+ ></pkt-helptext>
167
169
  `
168
170
  }
169
171
 
@@ -26,6 +26,25 @@ afterEach(() => {
26
26
  })
27
27
 
28
28
  describe('PktProgressbar', () => {
29
+ describe('Host id', () => {
30
+ afterEach(() => {
31
+ document.body.innerHTML = ''
32
+ })
33
+
34
+ test('keeps the id on the host element', async () => {
35
+ document.body.innerHTML = '<pkt-progressbar id="min-framdrift" title="Framdrift"></pkt-progressbar>'
36
+ const progressbar = document.querySelector('pkt-progressbar') as CustomElementFor<'pkt-progressbar'>
37
+ await progressbar.updateComplete
38
+
39
+ expect(document.getElementById('min-framdrift')).toBe(progressbar)
40
+ expect(document.querySelectorAll('[id="min-framdrift"]')).toHaveLength(1)
41
+ expect(progressbar.querySelector('[role="progressbar"]')).toHaveAttribute(
42
+ 'aria-labelledby',
43
+ 'min-framdrift-title',
44
+ )
45
+ })
46
+ })
47
+
29
48
  describe('Rendering and basic functionality', () => {
30
49
  test('renders without errors', async () => {
31
50
  const { progressbar } = await createProgressbarTest()
@@ -45,7 +45,7 @@ export class PktProgressbar extends PktElement implements IPktProgressbar {
45
45
  @property({ type: String, reflect: true }) ariaLabelledby: string | null = null
46
46
  @property({ type: String, reflect: true }) ariaValueText: string | null = null
47
47
  @property({ type: String }) ariaLive: TAriaLive = 'polite'
48
- @property({ type: String }) id: string = uuidish()
48
+ @property({ type: String, reflect: true }) id: string = uuidish()
49
49
  @property({ type: String }) role: TProgressbarRole = 'progressbar'
50
50
  @property({ type: String }) skin: TProgressbarSkin = 'dark-blue'
51
51
  @property({ type: String }) statusPlacement: TProgressbarStatusPlacement = 'following'
@@ -67,10 +67,7 @@ export class PktProgressbar extends PktElement implements IPktProgressbar {
67
67
 
68
68
  protected willUpdate(changedProperties: Map<string | number | symbol, unknown>) {
69
69
  super.willUpdate(changedProperties)
70
- if (this.hasAttribute('id')) {
71
- this.progressbarId = this.getAttribute('id') || this.progressbarId
72
- this.removeAttribute('id')
73
- } else if (this.id) {
70
+ if (this.id) {
74
71
  this.progressbarId = this.id
75
72
  }
76
73
  // Verdien må fanges FØR removeAttribute: den utløser attributeChangedCallback,
@@ -131,7 +128,6 @@ export class PktProgressbar extends PktElement implements IPktProgressbar {
131
128
 
132
129
  return html`<div
133
130
  ${ref(this.progressBarRef)}
134
- id=${this.progressbarId}
135
131
  role=${this.resolvedRole}
136
132
  aria-live=${ifDefined(this.ariaLive || undefined)}
137
133
  aria-atomic="true"
@@ -4,7 +4,7 @@ import { Ref, createRef, ref } from 'lit/directives/ref.js'
4
4
  import { ifDefined } from 'lit/directives/if-defined.js'
5
5
  import { PktOptionsInputElement } from '@/base-elements/options-input-element'
6
6
  import { PktOptionsSlotController } from '@/controllers/pkt-options-controller'
7
- import { slotContent } from '@/directives/slot-content'
7
+ import { forwardSlots } from '@/directives/slot-content'
8
8
  import type { TSelectOption } from 'shared-types/select'
9
9
  import '@/components/input-wrapper'
10
10
  import { describedByIds } from 'shared-utils/forms/described-by'
@@ -182,6 +182,7 @@ export class PktSelect extends PktOptionsInputElement<{}, TSelectOption> impleme
182
182
 
183
183
  return html`
184
184
  <pkt-input-wrapper
185
+ ${forwardSlots(this, ['helptext'])}
185
186
  .strings=${this.strings}
186
187
  .size=${this.inputSize}
187
188
  ?disabled=${this.disabled}
@@ -209,7 +210,7 @@ export class PktSelect extends PktOptionsInputElement<{}, TSelectOption> impleme
209
210
  aria-describedby=${ifDefined(
210
211
  describedByIds({
211
212
  id: this.id + '-input',
212
- hasHelptext: !!this.helptext,
213
+ hasHelptext: !!this.helptext || this.hasSlotContent('helptext'),
213
214
  hasCounter: false,
214
215
  ariaDescribedby: this.ariaDescribedby,
215
216
  }),
@@ -251,7 +252,6 @@ export class PktSelect extends PktOptionsInputElement<{}, TSelectOption> impleme
251
252
  )
252
253
  : ''}
253
254
  </select>
254
- <div class="pkt-contents" slot="helptext">${slotContent(this, 'helptext')}</div>
255
255
  </pkt-input-wrapper>
256
256
  `
257
257
  }
@@ -5,7 +5,7 @@ import { Ref, createRef, ref } from 'lit/directives/ref.js'
5
5
  import { classMap } from 'lit/directives/class-map.js'
6
6
  import { live } from 'lit/directives/live.js'
7
7
  import { PktInputElement } from '@/base-elements/input-element'
8
- import { slotContent } from '@/directives/slot-content'
8
+ import { forwardSlots } from '@/directives/slot-content'
9
9
 
10
10
  import '@/components/input-wrapper'
11
11
  import '@/components/icon'
@@ -61,6 +61,7 @@ export class PktTextarea extends PktInputElement<Props> {
61
61
  const labelledBy = this.ariaLabelledby || `${this.id}-input-label`
62
62
 
63
63
  return html`<pkt-input-wrapper
64
+ ${forwardSlots(this, ['helptext'])}
64
65
  .strings=${this.strings}
65
66
  label=${this.label}
66
67
  ?counter=${showCounter}
@@ -85,7 +86,6 @@ export class PktTextarea extends PktInputElement<Props> {
85
86
  .tagText=${this.tagText}
86
87
  .size=${this.inputSize}
87
88
  >
88
- <div class="pkt-contents" slot="helptext">${slotContent(this, 'helptext')}</div>
89
89
  <textarea
90
90
  ${ref(this.inputRef)}
91
91
  class=${inputClasses}
@@ -103,7 +103,7 @@ export class PktTextarea extends PktInputElement<Props> {
103
103
  aria-describedby=${ifDefined(
104
104
  describedByIds({
105
105
  id: this.id + '-input',
106
- hasHelptext: !!this.helptext,
106
+ hasHelptext: !!this.helptext || this.hasSlotContent('helptext'),
107
107
  hasCounter: showCounter,
108
108
  ariaDescribedby: this.ariaDescribedby,
109
109
  }),
@@ -5,7 +5,7 @@ import { Ref, createRef, ref } from 'lit/directives/ref.js'
5
5
  import { ElementProps } from '@/types/typeUtils'
6
6
  import { classMap } from 'lit/directives/class-map.js'
7
7
  import { PktInputElement } from '@/base-elements/input-element'
8
- import { slotContent } from '@/directives/slot-content'
8
+ import { forwardSlots } from '@/directives/slot-content'
9
9
 
10
10
  import '@/components/input-wrapper'
11
11
  import '@/components/icon'
@@ -77,6 +77,7 @@ export class PktTextinput extends PktInputElement<Props> {
77
77
 
78
78
  return html`
79
79
  <pkt-input-wrapper
80
+ ${forwardSlots(this, ['helptext'])}
80
81
  .strings=${this.strings}
81
82
  label="${this.label}"
82
83
  ?counter=${showCounter}
@@ -101,7 +102,6 @@ export class PktTextinput extends PktInputElement<Props> {
101
102
  .tagText=${this.tagText}
102
103
  .size=${this.inputSize}
103
104
  >
104
- <div class="pkt-contents" slot="helptext">${slotContent(this, 'helptext')}</div>
105
105
  <div class=${`pkt-input__container pkt-input__container--${this.inputSize}`}>
106
106
  ${this.prefix ? html`<div class="pkt-input-prefix">${this.prefix}</div>` : nothing}
107
107
  <input
@@ -127,7 +127,7 @@ export class PktTextinput extends PktInputElement<Props> {
127
127
  aria-describedby=${ifDefined(
128
128
  describedByIds({
129
129
  id: this.id + '-input',
130
- hasHelptext: !!this.helptext,
130
+ hasHelptext: !!this.helptext || this.hasSlotContent('helptext'),
131
131
  hasCounter: showCounter,
132
132
  ariaDescribedby: this.ariaDescribedby,
133
133
  }),
@@ -4,7 +4,7 @@ import { Ref, createRef, ref } from 'lit/directives/ref.js'
4
4
  import { ifDefined } from 'lit/directives/if-defined.js'
5
5
  import { classMap } from 'lit/directives/class-map.js'
6
6
  import { PktInputElement } from '@/base-elements/input-element'
7
- import { slotContent } from '@/directives/slot-content'
7
+ import { forwardSlots } from '@/directives/slot-content'
8
8
  import { ElementProps } from '@/types/typeUtils'
9
9
  import { formatString, type IPktStringsProps } from 'shared-strings'
10
10
  import { isValidTimeString, timeToMinutes } from 'shared-utils/timepicker/time-utils'
@@ -149,7 +149,7 @@ export class PktTimepicker extends PktInputElement<Props> {
149
149
  private _describedBy(): string | undefined {
150
150
  return describedByIds({
151
151
  id: `${this.id}-hours`,
152
- hasHelptext: !!this.helptext,
152
+ hasHelptext: !!this.helptext || this.hasSlotContent('helptext'),
153
153
  ariaDescribedby: this.ariaDescribedby,
154
154
  })
155
155
  }
@@ -784,6 +784,7 @@ export class PktTimepicker extends PktInputElement<Props> {
784
784
  render() {
785
785
  return html`
786
786
  <pkt-input-wrapper
787
+ ${forwardSlots(this, ['helptext'])}
787
788
  .strings=${this.strings}
788
789
  label="${this.label}"
789
790
  ?disabled=${this.disabled}
@@ -806,7 +807,6 @@ export class PktTimepicker extends PktInputElement<Props> {
806
807
  .tagText=${this.tagText}
807
808
  .size=${this.inputSize}
808
809
  >
809
- <div class="pkt-contents" slot="helptext">${slotContent(this, 'helptext')}</div>
810
810
  ${!this.hidePicker && !this.stepArrows
811
811
  ? html`
812
812
  <div class="pkt-timepicker__anchor">
@@ -1,40 +0,0 @@
1
- const e=require("./element-BOmr9YLv.cjs"),t=require("./class-map-Drv0_anQ.cjs"),n=require("./if-defined-2mkIDgOm.cjs"),r=require("./format-B8meU8Tm.cjs"),i=require("./element-with-slot-2PHu2w7O.cjs"),a=require("./classutils-CbklAJDe.cjs"),o=require("./define-component-spec-DBNd2FJY.cjs");require("./icon-CoBsgGUR.cjs"),require("./button-CmNrMH-c.cjs");var s=[`off`,`polite`,`assertive`],c=[`info`,`success`,`warning`,`error`],l=[`medium`,`small`,`xsmall`],u={compact:!1},d=o.t({name:`pkt-alert`,react:`PktAlert`,"css-class":`pkt-alert`,"dark-mode":!0,isElement:!0,isPureReact:!0,events:{onClose:{reactOnly:!0,description:`React: Klikk-event for 'Lukk'-knappen`},close:{elementsOnly:!0,description:`Elements: Klikk-event for 'Lukk'-knappen`}},props:{title:{name:`Tittel`,description:`Tittelen som vises øverst i på meldingen`,type:`string`,category:`contents`},skin:{name:`Utseende`,description:`Hvordan type melding er dette?`,type:[...c],default:`info`,category:`ui`},date:{name:`Sist oppdatert`,description:`Dato som vises nederst i på meldingen`,type:`string`,category:`contents`},ariaLive:{name:`aria-live`,description:`Hvordan skal skjermleseren lese opp meldingen?`,type:[...s],default:`polite`,category:`accessibility`},size:{name:`Størrelse`,description:`Endrer størrelsen på ulike elementer i alerten.`,type:[...l],default:`medium`,category:`ui`},closeAlert:{name:`Vis 'Lukk'-knapp`,description:`Viser 'Lukk'-knappen`,type:`boolean`,default:!1,category:`ui`},compact:{name:`Kompakt`,description:`Kompakt visning av alerten.`,deprecated:"Bruk `size` i stedet; uten eksplisitt `size` gir compact størrelsen 'small'.",type:`boolean`,category:`ui`,default:u.compact}},slots:{default:{description:`Innholdet i meldingen`}}}),f=class extends i.t{constructor(){super(),this.compact=u.compact,this.title=``,this.skin=d.props.skin.default,this.ariaLive=d.props.ariaLive.default,this.ariaLiveAttr=null,this.closeAlert=d.props.closeAlert.default,this.date=null,this.role=`status`,this._hostId=null,this._isClosed=!1,this.close=e=>{this._isClosed=!0,this.dispatchEvent(new CustomEvent(`close`,{detail:{origin:e},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent(`on-close`,{detail:{origin:e},bubbles:!0,composed:!0}))},this._isClosed=!1}connectedCallback(){super.connectedCallback(),this.ariaLiveAttr=this.getAttribute(`aria-live`)||this.ariaLive}willUpdate(e){super.willUpdate(e);let t=this.getAttribute(`id`);t&&(this._hostId=t,this.removeAttribute(`id`))}attributeChangedCallback(e,t,n){e===`ariaLive`&&(this.ariaLiveAttr=n),super.attributeChangedCallback(e,t,n)}updated(e){super.updated(e),e.has(`ariaLive`)&&e.get(`ariaLive`)!==void 0&&(this.ariaLiveAttr=this.ariaLive),e.has(`_isClosed`)&&a.t(this,`pkt-hide`,this._isClosed)}render(){let a=this.size??(this.compact?`small`:`medium`),o={"pkt-alert":!0,[`pkt-alert--${a}`]:!0,[`pkt-alert--${this.skin}`]:!0,"pkt-hide":this._isClosed},s={"pkt-alert__grid":!0,"pkt-alert__noTitle":!this.title,"pkt-alert__noDate":!this.date};return e._`
2
- <div
3
- class=${t.t(o)}
4
- id=${n.t(this._hostId||void 0)}
5
- aria-live=${this.ariaLiveAttr}
6
- role=${this.role}
7
- >
8
- <div class=${t.t(s)}>
9
- <pkt-icon
10
- class="pkt-alert__icon"
11
- aria-hidden="true"
12
- name=${this.skin===`info`?`alert-information`:`alert-${this.skin}`}
13
- ></pkt-icon>
14
-
15
- ${this.closeAlert?e._`
16
- <div class="pkt-alert__close">
17
- <pkt-button
18
- tabindex="0"
19
- aria-label=${this.pktStrings.get(`generic`).close}
20
- size=${a}
21
- type="button"
22
- skin="tertiary"
23
- iconName="close"
24
- variant="icon-only"
25
- @click=${this.close}
26
- >
27
- <span class="sr-only">${this.pktStrings.get(`generic`).close}</span>
28
- </pkt-button>
29
- </div>
30
- `:e.h}
31
- ${this.title?e._`<div class="pkt-alert__title">${this.title}</div>`:e.h}
32
-
33
- <div class="pkt-alert__text">${i.r(this)}</div>
34
-
35
- ${this.date?e._`<div class="pkt-alert__date">
36
- ${r.t(this.pktStrings.get(`alert`).lastUpdated,{date:this.date})}
37
- </div>`:e.h}
38
- </div>
39
- </div>
40
- `}};e.n([e.u({type:Boolean,reflect:!1})],f.prototype,`compact`,void 0),e.n([e.u({type:String,reflect:!0})],f.prototype,`title`,void 0),e.n([e.u({type:String,reflect:!0})],f.prototype,`skin`,void 0),e.n([e.u({type:String})],f.prototype,`ariaLive`,void 0),e.n([e.u({type:String,reflect:!0,attribute:`aria-live`})],f.prototype,`ariaLiveAttr`,void 0),e.n([e.u({type:Boolean,reflect:!0})],f.prototype,`closeAlert`,void 0),e.n([e.u({type:String,reflect:!0})],f.prototype,`date`,void 0),e.n([e.u({type:String})],f.prototype,`role`,void 0),e.n([e.l()],f.prototype,`_hostId`,void 0),e.n([e.u({type:String,attribute:`size`})],f.prototype,`size`,void 0),e.n([e.l()],f.prototype,`_isClosed`,void 0);try{e.d(`pkt-alert`)(f)}catch{console.warn(`Forsøker å definere <pkt-alert>, men den er allerede definert`)}var p=f;Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return p}});