@oslokommune/punkt-elements 19.19.1 → 20.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/dist/{accordion-Bg4CMrUM.cjs → accordion-5N_ptxrN.cjs} +1 -1
  3. package/dist/{accordion-BHVzR-6Z.js → accordion-C5cu1xXT.js} +5 -5
  4. package/dist/{alert-BAaZIR3e.js → alert-CA1fDbyc.js} +5 -5
  5. package/dist/{alert-Dy5N7qK-.cjs → alert-DkyTTo7S.cjs} +1 -1
  6. package/dist/{async-directive-C4LocQwR.js → async-directive-BcS8rfeC.js} +2 -2
  7. package/dist/{async-directive-DpyKp6qv.cjs → async-directive-DCLIOGR8.cjs} +1 -1
  8. package/dist/{backlink-Dlkyj0ns.js → backlink-CDBRcaAu.js} +3 -3
  9. package/dist/{backlink-BnWruRuj.cjs → backlink-CXOxMeyt.cjs} +1 -1
  10. package/dist/{breadcrumbs-Bfv8W2CF.js → breadcrumbs-5oUaCef3.js} +2 -2
  11. package/dist/{breadcrumbs-CyWtnx2B.cjs → breadcrumbs-zfUto2U5.cjs} +1 -1
  12. package/dist/{button-CF9k3ARf.js → button-Bswo1C0M.js} +5 -5
  13. package/dist/{button-BBFI3FuT.cjs → button-bVWAX98x.cjs} +1 -1
  14. package/dist/{calendar-BX3n3vhs.js → calendar-BOd-9PDd.js} +3 -3
  15. package/dist/{calendar-Dds9KFiE.cjs → calendar-CDTCgTJn.cjs} +1 -1
  16. package/dist/{card-Ddu0sQ0f.js → card-DH1kPnyi.js} +44 -42
  17. package/dist/card-njWrvrHm.cjs +67 -0
  18. package/dist/{checkbox-D9-KugOh.js → checkbox-DIJbuqWm.js} +5 -5
  19. package/dist/{checkbox-group-Dz1ypmbU.js → checkbox-group-DLLbWgQb.js} +3 -3
  20. package/dist/{checkbox-group-BlBgrzKG.cjs → checkbox-group-Kua6HuRE.cjs} +1 -1
  21. package/dist/{checkbox-B8foyiOW.cjs → checkbox-iMOdzpJ_.cjs} +2 -2
  22. package/dist/{class-map-BkEYw5uE.js → class-map-BDwVSgLb.js} +1 -1
  23. package/dist/{class-map-Bh6toDeV.cjs → class-map-C82GtM1w.cjs} +1 -1
  24. package/dist/{combobox-DLDvyuDh.cjs → combobox-BwAxmoG9.cjs} +1 -1
  25. package/dist/{combobox-BAkblu9M.js → combobox-H5FLG8BV.js} +12 -12
  26. package/dist/components/card/card.d.ts +0 -10
  27. package/dist/components/card/index.d.ts +2 -2
  28. package/dist/components/link/link.d.ts +1 -1
  29. package/dist/components/linkcard/linkcard.d.ts +0 -1
  30. package/dist/components/progressbar/progressbar.d.ts +4 -18
  31. package/dist/components/tabs/tabitem.d.ts +2 -1
  32. package/dist/components/tag/tag.d.ts +4 -2
  33. package/dist/{consent-DNHRe0zV.cjs → consent-UkinU27V.cjs} +1 -1
  34. package/dist/{consent-BTw6uqFf.js → consent-p-0n2b9x.js} +2 -2
  35. package/dist/{datepicker-C7F1Yc5N.cjs → datepicker-COar3rRT.cjs} +1 -1
  36. package/dist/{datepicker-9dmdHweu.js → datepicker-ZSwWg8xW.js} +11 -11
  37. package/dist/{directive-helpers-BAinC437.js → directive-helpers-BoDzpPID.js} +1 -1
  38. package/dist/{directive-helpers-Bv70GjQh.cjs → directive-helpers-r7akb6wX.cjs} +1 -1
  39. package/dist/{element-C6WTyJFE.cjs → element-CEarCnHH.cjs} +1 -1
  40. package/dist/{element-ckeMVgMz.js → element-DLgZkx5L.js} +1 -0
  41. package/dist/{element-with-slot-B0Vp_OuR.cjs → element-with-slot-CeKuRE3_.cjs} +1 -1
  42. package/dist/{element-with-slot-Dp2Gzv-Q.js → element-with-slot-mG-h7Sjw.js} +2 -2
  43. package/dist/{fileupload-M66Pd-QJ.cjs → fileupload-DXJtAagE.cjs} +1 -1
  44. package/dist/{fileupload-CEwnpxZj.js → fileupload-vPDmtXiM.js} +8 -8
  45. package/dist/{footer-HFL2sjAY.cjs → footer-CpE05IW2.cjs} +1 -1
  46. package/dist/{footer-DZ4aA6fj.js → footer-D8t0PCPC.js} +4 -4
  47. package/dist/{header-BYNzxXCo.js → header-Bo8uvddg.js} +11 -11
  48. package/dist/{header-BqheRQpR.cjs → header-DzYKgl-k.cjs} +1 -1
  49. package/dist/{header-menu-DxOSBiTJ.js → header-menu-BrjsNjBH.js} +4 -4
  50. package/dist/{header-menu-De2DNAXd.cjs → header-menu-Dq9lwNr1.cjs} +1 -1
  51. package/dist/{heading-B1Ey3XzB.js → heading-CMZmPEL9.js} +2 -2
  52. package/dist/{heading--hGRDNX9.cjs → heading-DAkjw2Am.cjs} +1 -1
  53. package/dist/{helptext-BVYv8Lm9.js → helptext-BFQzrOw4.js} +4 -4
  54. package/dist/{helptext-BbrFE48Y.cjs → helptext-Bse1LpRd.cjs} +1 -1
  55. package/dist/icon-5A378_yh.cjs +1 -0
  56. package/dist/{icon-CUU42bZ0.js → icon-C1oCGwEe.js} +2 -2
  57. package/dist/if-defined-Ci4ZQsgL.cjs +1 -0
  58. package/dist/{if-defined-D18nY_K_.js → if-defined-DiYi2v_Q.js} +1 -1
  59. package/dist/{input-element-D82laWtR.cjs → input-element-2LHxo0em.cjs} +1 -1
  60. package/dist/{input-element-DczlJQb1.js → input-element-De40zUox.js} +2 -2
  61. package/dist/{input-wrapper-QzdntWJX.cjs → input-wrapper-C_Rzwxx7.cjs} +2 -2
  62. package/dist/{input-wrapper-CHwWQgZP.js → input-wrapper-DkpJS1hR.js} +7 -7
  63. package/dist/{link-a1ZK4J1j.cjs → link-B7t4iOKk.cjs} +3 -3
  64. package/dist/{link-BU6t5Tt9.js → link-DZgG_8Ni.js} +15 -10
  65. package/dist/linkcard-DIG6VYpl.cjs +15 -0
  66. package/dist/linkcard-Dr-r8jBO.js +60 -0
  67. package/dist/{listbox-DFd-1faX.js → listbox-DAvIBH4P.js} +4 -4
  68. package/dist/{listbox-BbdUu-IV.cjs → listbox-HrH4JonS.cjs} +1 -1
  69. package/dist/{loader-Y8V3Q82X.js → loader-CFidlqSG.js} +4 -4
  70. package/dist/{loader-DwGMavG7.cjs → loader-DTIrOtTo.cjs} +1 -1
  71. package/dist/messagebox-BLYx3AL7.cjs +16 -0
  72. package/dist/{messagebox-wJcXW5hI.js → messagebox-B_07P0QA.js} +25 -16
  73. package/dist/{modal-C5AiVm5g.cjs → modal-BvTfLfFq.cjs} +1 -1
  74. package/dist/{modal-BafCTC4M.js → modal-CA_M2Ix6.js} +6 -6
  75. package/dist/{option-group-element-CWjgrFwS.cjs → option-group-element-CVNaBIlP.cjs} +1 -1
  76. package/dist/{option-group-element-ZNyUoLcm.js → option-group-element-DzM8YznZ.js} +3 -3
  77. package/dist/pkt-accordion.cjs +1 -1
  78. package/dist/pkt-accordion.js +1 -1
  79. package/dist/pkt-alert.cjs +1 -1
  80. package/dist/pkt-alert.js +1 -1
  81. package/dist/pkt-backlink.cjs +1 -1
  82. package/dist/pkt-backlink.js +1 -1
  83. package/dist/pkt-breadcrumbs.cjs +1 -1
  84. package/dist/pkt-breadcrumbs.js +1 -1
  85. package/dist/pkt-button.cjs +1 -1
  86. package/dist/pkt-button.js +1 -1
  87. package/dist/pkt-calendar.cjs +1 -1
  88. package/dist/pkt-calendar.js +1 -1
  89. package/dist/pkt-card.cjs +1 -1
  90. package/dist/pkt-card.js +1 -1
  91. package/dist/pkt-checkbox-group.cjs +1 -1
  92. package/dist/pkt-checkbox-group.js +1 -1
  93. package/dist/pkt-checkbox.cjs +1 -1
  94. package/dist/pkt-checkbox.js +1 -1
  95. package/dist/pkt-combobox.cjs +1 -1
  96. package/dist/pkt-combobox.js +1 -1
  97. package/dist/pkt-consent.cjs +1 -1
  98. package/dist/pkt-consent.js +1 -1
  99. package/dist/pkt-datepicker.cjs +1 -1
  100. package/dist/pkt-datepicker.js +1 -1
  101. package/dist/pkt-fileupload.cjs +1 -1
  102. package/dist/pkt-fileupload.js +1 -1
  103. package/dist/pkt-footer.cjs +1 -1
  104. package/dist/pkt-footer.js +1 -1
  105. package/dist/pkt-header-menu.cjs +1 -1
  106. package/dist/pkt-header-menu.js +1 -1
  107. package/dist/pkt-header.cjs +1 -1
  108. package/dist/pkt-header.js +1 -1
  109. package/dist/pkt-heading.cjs +1 -1
  110. package/dist/pkt-heading.js +1 -1
  111. package/dist/pkt-helptext.cjs +1 -1
  112. package/dist/pkt-helptext.js +1 -1
  113. package/dist/pkt-icon.cjs +1 -1
  114. package/dist/pkt-icon.js +1 -1
  115. package/dist/pkt-index.cjs +1 -1
  116. package/dist/pkt-index.js +37 -37
  117. package/dist/pkt-input-wrapper.cjs +1 -1
  118. package/dist/pkt-input-wrapper.js +1 -1
  119. package/dist/pkt-link.cjs +1 -1
  120. package/dist/pkt-link.js +1 -1
  121. package/dist/pkt-linkcard.cjs +1 -1
  122. package/dist/pkt-linkcard.js +1 -1
  123. package/dist/pkt-listbox.cjs +1 -1
  124. package/dist/pkt-listbox.js +1 -1
  125. package/dist/pkt-loader.cjs +1 -1
  126. package/dist/pkt-loader.js +1 -1
  127. package/dist/pkt-messagebox.cjs +1 -1
  128. package/dist/pkt-messagebox.js +1 -1
  129. package/dist/pkt-modal.cjs +1 -1
  130. package/dist/pkt-modal.js +1 -1
  131. package/dist/{pkt-options-controller-C193xcN4.cjs → pkt-options-controller-9zoH1OBW.cjs} +1 -1
  132. package/dist/{pkt-options-controller-CH8U6zlw.js → pkt-options-controller-CzvBlEPD.js} +1 -1
  133. package/dist/pkt-progressbar.cjs +1 -1
  134. package/dist/pkt-progressbar.js +1 -1
  135. package/dist/pkt-radio-group.cjs +1 -1
  136. package/dist/pkt-radio-group.js +1 -1
  137. package/dist/pkt-radiobutton.cjs +1 -1
  138. package/dist/pkt-radiobutton.js +1 -1
  139. package/dist/pkt-searchinput.cjs +1 -1
  140. package/dist/pkt-searchinput.js +1 -1
  141. package/dist/pkt-select.cjs +1 -1
  142. package/dist/pkt-select.js +1 -1
  143. package/dist/pkt-tabs.cjs +1 -1
  144. package/dist/pkt-tabs.js +1 -1
  145. package/dist/pkt-tag.cjs +1 -1
  146. package/dist/pkt-tag.js +1 -1
  147. package/dist/pkt-textarea.cjs +1 -1
  148. package/dist/pkt-textarea.js +1 -1
  149. package/dist/pkt-textinput.cjs +1 -1
  150. package/dist/pkt-textinput.js +1 -1
  151. package/dist/pkt-timepicker.cjs +1 -1
  152. package/dist/pkt-timepicker.js +1 -1
  153. package/dist/progressbar-BdqIhC1Z.cjs +30 -0
  154. package/dist/{progressbar-BukfOcRk.js → progressbar-CfCc2zhp.js} +50 -37
  155. package/dist/{radio-group-Bg6ODpT3.js → radio-group-BRY_74od.js} +3 -3
  156. package/dist/{radio-group-bpIEEMdL.cjs → radio-group-CsUgnEv0.cjs} +1 -1
  157. package/dist/{radiobutton-IcDc6ze2.cjs → radiobutton-CQhuG2lj.cjs} +2 -2
  158. package/dist/{radiobutton-DMvVv81Y.js → radiobutton-lHnq8wX_.js} +5 -5
  159. package/dist/{ref-CB7e9nMY.cjs → ref-B6p6mQkO.cjs} +1 -1
  160. package/dist/{ref-D4OwQYdf.js → ref-BAegS9BR.js} +2 -2
  161. package/dist/{repeat-CnnigVcj.cjs → repeat-CjvNrcUr.cjs} +1 -1
  162. package/dist/{repeat-BGbBqnfz.js → repeat-Cy1M16Di.js} +2 -2
  163. package/dist/{searchinput-BV2C1VbN.js → searchinput-BLGaXkP6.js} +4 -4
  164. package/dist/{searchinput-DqD_iLxV.cjs → searchinput-TAqMUJ0B.cjs} +1 -1
  165. package/dist/{select-DKBfPgJB.js → select-BvtUxW0Q.js} +7 -7
  166. package/dist/{select-CHqM6kI-.cjs → select-Dle67Uwv.cjs} +1 -1
  167. package/dist/shared-strings/nb.d.ts +3 -0
  168. package/dist/shared-types/card.d.ts +5 -17
  169. package/dist/shared-types/combobox.d.ts +3 -3
  170. package/dist/shared-types/icon.d.ts +2 -2
  171. package/dist/shared-types/index.d.ts +11 -9
  172. package/dist/shared-types/linkcard.d.ts +7 -4
  173. package/dist/shared-types/messagebox.d.ts +4 -2
  174. package/dist/shared-types/progressbar.d.ts +82 -5
  175. package/dist/shared-types/skin.d.ts +8 -2
  176. package/dist/{tabs-B2RjklQl.js → tabs-Bu_-WfCK.js} +5 -5
  177. package/dist/{tabs-BcnYrmjU.cjs → tabs-Dwk5PKzP.cjs} +1 -1
  178. package/dist/tag-1SSexs0H.cjs +27 -0
  179. package/dist/{tag-BOTH9kMz.js → tag-CkZ2Mn4a.js} +33 -11
  180. package/dist/{textarea-B5OfR-QI.cjs → textarea-DSX3jMlI.cjs} +1 -1
  181. package/dist/{textarea-Du1Z9JUu.js → textarea-Djp5L2Zd.js} +9 -9
  182. package/dist/{textinput-CRlErItw.js → textinput-CBrOZcvL.js} +8 -8
  183. package/dist/{textinput-C5KWIB21.cjs → textinput-CN2F3Q3H.cjs} +1 -1
  184. package/dist/{timepicker-DVqTAxt0.js → timepicker-CT4wfrgQ.js} +8 -8
  185. package/dist/{timepicker-RxsG0mCF.cjs → timepicker-CkaJkIGn.cjs} +1 -1
  186. package/package.json +3 -3
  187. package/src/components/card/card.test.ts +50 -53
  188. package/src/components/card/card.ts +14 -24
  189. package/src/components/card/index.ts +2 -2
  190. package/src/components/checkbox/checkbox.test.ts +3 -3
  191. package/src/components/checkbox/checkbox.ts +1 -1
  192. package/src/components/input-wrapper/input-wrapper.ts +1 -1
  193. package/src/components/link/link.test.ts +14 -18
  194. package/src/components/link/link.ts +2 -3
  195. package/src/components/linkcard/linkcard.test.ts +18 -6
  196. package/src/components/linkcard/linkcard.ts +5 -7
  197. package/src/components/messagebox/messagebox.test.ts +14 -1
  198. package/src/components/messagebox/messagebox.ts +13 -2
  199. package/src/components/progressbar/progressbar.test.ts +47 -5
  200. package/src/components/progressbar/progressbar.ts +49 -53
  201. package/src/components/radiobutton/radiobutton.test.ts +1 -1
  202. package/src/components/radiobutton/radiobutton.ts +1 -1
  203. package/src/components/tabs/tabitem.ts +6 -2
  204. package/src/components/tag/tag.test.ts +21 -12
  205. package/src/components/tag/tag.ts +12 -3
  206. package/dist/card-mi3VKIoy.cjs +0 -64
  207. package/dist/icon-CrG6o7ZE.cjs +0 -1
  208. package/dist/if-defined-CiML3MTM.cjs +0 -1
  209. package/dist/linkcard-Cu4Rh71U.cjs +0 -14
  210. package/dist/linkcard-DM0CQbwD.js +0 -56
  211. package/dist/messagebox-DR-s6tyr.cjs +0 -13
  212. package/dist/progressbar-YfHSPmqI.cjs +0 -31
  213. package/dist/tag-DrFK8Wq3.cjs +0 -27
@@ -28,13 +28,14 @@ expect.extend(toHaveNoViolations)
28
28
 
29
29
  // Test data constants
30
30
  const VALID_SKINS: TLinkCardSkin[] = [
31
- 'normal',
32
- 'no-padding',
31
+ 'gray',
32
+ 'outlined',
33
+ 'transparent',
34
+ 'white',
33
35
  'blue',
34
- 'beige',
35
36
  'green',
36
- 'gray',
37
- 'beige-outline',
37
+ 'beige',
38
+ 'normal',
38
39
  'gray-outline',
39
40
  ]
40
41
 
@@ -65,7 +66,6 @@ describe('PktLinkCard', () => {
65
66
  expect(linkCard.iconName).toBe('')
66
67
  expect(linkCard.openInNewTab).toBe(false)
67
68
  expect(linkCard.skin).toBeUndefined()
68
- expect(linkCard.external).toBe(false)
69
69
 
70
70
  expect(link.getAttribute('href')).toBe('#')
71
71
  expect(link.getAttribute('target')).toBe('_self')
@@ -221,6 +221,18 @@ describe('PktLinkCard', () => {
221
221
  }
222
222
  })
223
223
 
224
+ test('keeps light-only skins in light mode', async () => {
225
+ for (const skin of ['white', 'blue', 'green', 'beige'] as const) {
226
+ const { link } = await createLinkCardTest({ skin })
227
+ expect(link).toHaveAttribute('data-mode', 'light')
228
+ }
229
+
230
+ for (const skin of ['gray', 'outlined', 'transparent', 'normal', 'gray-outline'] as const) {
231
+ const { link } = await createLinkCardTest({ skin })
232
+ expect(link).not.toHaveAttribute('data-mode')
233
+ }
234
+ })
235
+
224
236
  test('handles skin property changes', async () => {
225
237
  const { linkCard, link } = await createLinkCardTest({ skin: 'blue' })
226
238
 
@@ -4,7 +4,7 @@ import { PktElementWithSlot } from '@/base-elements/element-with-slot'
4
4
  import { slotContent } from '@/directives/slot-content'
5
5
  import '@/components/icon'
6
6
  import { ifDefined } from 'lit/directives/if-defined.js'
7
- import type { IPktLinkCardBase, TLinkCardSkin } from 'shared-types'
7
+ import { LINKCARD_LIGHT_ONLY_SKINS, type IPktLinkCardBase, type TLinkCardSkin } from 'shared-types'
8
8
 
9
9
  export type { TLinkCardSkin }
10
10
 
@@ -14,7 +14,6 @@ export class PktLinkCard extends PktElementWithSlot<IPktLinkCard> implements IPk
14
14
  @property({ type: String, reflect: true }) title: string = ''
15
15
  @property({ type: String, reflect: true }) href: string = '#'
16
16
  @property({ type: String, reflect: true }) iconName: string = ''
17
- @property({ type: Boolean, reflect: true }) external: boolean = false
18
17
  @property({ type: Boolean, reflect: true }) openInNewTab: boolean = false
19
18
  @property({ type: String, reflect: true }) skin?: TLinkCardSkin = undefined
20
19
 
@@ -23,10 +22,6 @@ export class PktLinkCard extends PktElementWithSlot<IPktLinkCard> implements IPk
23
22
  .filter(Boolean)
24
23
  .join(' ')
25
24
 
26
- const titleClasses = ['pkt-linkcard__title', this.external && 'pkt-link pkt-link--external']
27
- .filter(Boolean)
28
- .join(' ')
29
-
30
25
  const s = this.pktStrings.get('linkcard')
31
26
  const newTabLabel = this.openInNewTab ? s.openInNewTab : ''
32
27
 
@@ -34,11 +29,14 @@ export class PktLinkCard extends PktElementWithSlot<IPktLinkCard> implements IPk
34
29
  <a
35
30
  href=${this.href}
36
31
  class=${classes}
32
+ data-mode=${ifDefined(
33
+ this.skin && LINKCARD_LIGHT_ONLY_SKINS.includes(this.skin) ? 'light' : undefined,
34
+ )}
37
35
  target=${this.openInNewTab ? '_blank' : '_self'}
38
36
  rel=${ifDefined(this.openInNewTab ? 'noopener noreferrer' : undefined)}
39
37
  >
40
38
  ${this.iconName && html`<pkt-icon class="pkt-link__icon" name="${this.iconName}"></pkt-icon>`}
41
- ${this.title && html`<div class=${titleClasses}>${this.title}</div>`}
39
+ ${this.title && html`<div class="pkt-linkcard__title">${this.title}</div>`}
42
40
  ${newTabLabel ? html`<span class="pkt-sr-only">${newTabLabel}</span>` : ''}
43
41
 
44
42
  <div class="pkt-linkcard__text">${slotContent(this)}</div>
@@ -72,7 +72,11 @@ describe('PktMessagebox', () => {
72
72
  expect(messagebox.closable).toBe(false)
73
73
  expect(messagebox.compact).toBe(false)
74
74
  expect(messagebox.title).toBe('')
75
- expect(messagebox.skin).toBe('beige')
75
+ expect(messagebox.skin).toBe('gray')
76
+
77
+ const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
78
+ expect(messageboxDiv?.classList.contains('pkt-messagebox--gray')).toBe(true)
79
+ expect(messageboxDiv?.hasAttribute('data-mode')).toBe(false)
76
80
  })
77
81
 
78
82
  test('sets properties correctly', async () => {
@@ -91,6 +95,15 @@ describe('PktMessagebox', () => {
91
95
  })
92
96
 
93
97
  describe('Skin variants', () => {
98
+ test('keeps light-only skins in light mode', async () => {
99
+ for (const skin of ['beige', 'blue', 'red', 'green'] as const) {
100
+ const { messagebox } = await createMessageboxTest({ skin })
101
+
102
+ const messageboxDiv = messagebox.querySelector('.pkt-messagebox')
103
+ expect(messageboxDiv?.getAttribute('data-mode')).toBe('light')
104
+ }
105
+ })
106
+
94
107
  test('applies beige skin correctly', async () => {
95
108
  const { messagebox } = await createMessageboxTest({ skin: 'beige' })
96
109
 
@@ -2,11 +2,17 @@ import { PktElementWithSlot } from '@/base-elements/element-with-slot'
2
2
  import { slotContent } from '@/directives/slot-content'
3
3
  import { html, nothing, PropertyValues } from 'lit'
4
4
  import { classMap } from 'lit/directives/class-map.js'
5
+ import { ifDefined } from 'lit/directives/if-defined.js'
5
6
  import { customElement, property, state } from 'lit/decorators.js'
6
7
 
7
8
  import '@/components/icon'
8
9
  import { updateClassAttribute } from '@/utils/classutils'
9
- import { MESSAGEBOX_DEFAULTS, type IPktMessageboxBase, type TMessageboxSkin } from 'shared-types'
10
+ import {
11
+ MESSAGEBOX_DEFAULTS,
12
+ MESSAGEBOX_LIGHT_ONLY_SKINS,
13
+ type IPktMessageboxBase,
14
+ type TMessageboxSkin,
15
+ } from 'shared-types'
10
16
 
11
17
  export type { TMessageboxSkin }
12
18
 
@@ -48,7 +54,12 @@ export class PktMessagebox extends PktElementWithSlot implements IPktMessagebox
48
54
  'pkt-hide': this._isClosed,
49
55
  }
50
56
 
51
- return html`<div class=${classMap(classes)}>
57
+ return html`<div
58
+ class=${classMap(classes)}
59
+ data-mode=${ifDefined(
60
+ this.skin && MESSAGEBOX_LIGHT_ONLY_SKINS.includes(this.skin) ? 'light' : undefined,
61
+ )}
62
+ >
52
63
  ${this.closable
53
64
  ? html`<div class="pkt-messagebox__close">
54
65
  <button
@@ -32,8 +32,11 @@ describe('PktProgressbar', () => {
32
32
  })
33
33
 
34
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'>
35
+ document.body.innerHTML =
36
+ '<pkt-progressbar id="min-framdrift" title="Framdrift"></pkt-progressbar>'
37
+ const progressbar = document.querySelector(
38
+ 'pkt-progressbar',
39
+ ) as CustomElementFor<'pkt-progressbar'>
37
40
  await progressbar.updateComplete
38
41
 
39
42
  expect(document.getElementById('min-framdrift')).toBe(progressbar)
@@ -57,7 +60,9 @@ describe('PktProgressbar', () => {
57
60
  const { progressbar } = await createProgressbarTest({ valueCurrent: 50 })
58
61
 
59
62
  expect(progressbar.valueCurrent).toBe(50)
60
- expect(progressbar.querySelector('.pkt-progressbar')?.getAttribute('role')).toBe('progressbar')
63
+ expect(progressbar.querySelector('.pkt-progressbar')?.getAttribute('role')).toBe(
64
+ 'progressbar',
65
+ )
61
66
  })
62
67
  })
63
68
 
@@ -134,6 +139,39 @@ describe('PktProgressbar', () => {
134
139
  expect(statusElement?.textContent?.trim()).toContain('25 av 50')
135
140
  })
136
141
 
142
+ test('shows fraction relative to valueMin', async () => {
143
+ const { progressbar } = await createProgressbarTest({
144
+ valueCurrent: 25,
145
+ valueMin: 20,
146
+ valueMax: 30,
147
+ statusType: 'fraction',
148
+ })
149
+
150
+ const bar = progressbar.querySelector('.pkt-progressbar')
151
+ const barContainer = progressbar.querySelector<HTMLElement>('.pkt-progressbar__container')
152
+ expect(progressbar.querySelector('.pkt-progressbar__status')?.textContent?.trim()).toBe(
153
+ '5 av 10',
154
+ )
155
+ expect(bar?.getAttribute('aria-valuetext')).toBe('5 av 10')
156
+ expect(barContainer?.style.getPropertyValue('--pkt-progress-width')).toBe('50%')
157
+ })
158
+
159
+ test('uses the same bar width for fraction and percentage', async () => {
160
+ const widths: string[] = []
161
+ for (const statusType of ['fraction', 'percentage'] as const) {
162
+ const { progressbar } = await createProgressbarTest({
163
+ valueCurrent: 10,
164
+ valueMin: 1,
165
+ valueMax: 10,
166
+ statusType,
167
+ })
168
+ const barContainer = progressbar.querySelector<HTMLElement>('.pkt-progressbar__container')
169
+ widths.push(barContainer?.style.getPropertyValue('--pkt-progress-width') ?? '')
170
+ document.body.innerHTML = ''
171
+ }
172
+ expect(widths).toEqual(['100%', '100%'])
173
+ })
174
+
137
175
  test('hides status when statusType is none', async () => {
138
176
  const { progressbar } = await createProgressbarTest({
139
177
  valueCurrent: 50,
@@ -182,7 +220,9 @@ describe('PktProgressbar', () => {
182
220
  progressbar.valueCurrent = 80
183
221
  await progressbar.updateComplete
184
222
 
185
- expect(progressbar.querySelector('.pkt-progressbar')?.getAttribute('aria-valuenow')).toBe('80')
223
+ expect(progressbar.querySelector('.pkt-progressbar')?.getAttribute('aria-valuenow')).toBe(
224
+ '80',
225
+ )
186
226
  })
187
227
  })
188
228
 
@@ -190,7 +230,9 @@ describe('PktProgressbar', () => {
190
230
  test('uses progressbar role by default', async () => {
191
231
  const { progressbar } = await createProgressbarTest()
192
232
 
193
- expect(progressbar.querySelector('.pkt-progressbar')?.getAttribute('role')).toBe('progressbar')
233
+ expect(progressbar.querySelector('.pkt-progressbar')?.getAttribute('role')).toBe(
234
+ 'progressbar',
235
+ )
194
236
  expect(progressbar.hasAttribute('role')).toBe(false)
195
237
  })
196
238
 
@@ -6,64 +6,58 @@ import { PktElement } from '@/base-elements/element'
6
6
  import { Ref, createRef, ref } from 'lit/directives/ref.js'
7
7
  import { styleMap } from 'lit/directives/style-map.js'
8
8
  import { uuidish } from 'shared-utils/utils'
9
+ import { formatString } from 'shared-strings'
10
+ import {
11
+ PROGRESSBAR_DEFAULTS,
12
+ type IPktProgressbarBase,
13
+ type TAriaLive,
14
+ type TProgressbarRole,
15
+ type TProgressbarSkin,
16
+ type TProgressbarStatusPlacement,
17
+ type TProgressbarStatusType,
18
+ type TProgressbarTitlePosition,
19
+ } from 'shared-types'
9
20
 
10
- import '@/components/icon'
11
- import type {
12
- TAriaLive,
21
+ export type {
13
22
  TProgressbarRole,
14
23
  TProgressbarSkin,
15
24
  TProgressbarStatusPlacement,
16
25
  TProgressbarStatusType,
17
26
  TProgressbarTitlePosition,
18
- } from 'shared-types'
19
-
20
- export type { TProgressbarRole, TProgressbarSkin, TProgressbarStatusPlacement, TProgressbarStatusType, TProgressbarTitlePosition }
27
+ }
21
28
 
22
- export interface IPktProgressbar {
23
- ariaLabel?: string | null
24
- ariaLabelledby?: string | null
29
+ export interface IPktProgressbar extends Omit<IPktProgressbarBase, 'ariaLive' | 'id'> {
25
30
  ariaLive?: TAriaLive | null
26
- ariaValueText?: string | null
27
31
  id?: string | null
28
- role?: TProgressbarRole
29
- skin?: TProgressbarSkin
30
- statusPlacement?: TProgressbarStatusPlacement
31
- statusType?: TProgressbarStatusType
32
- title?: string | null
33
- titlePosition?: TProgressbarTitlePosition
34
- valueCurrent: number
35
- valueMax?: number
36
- valueMin?: number
37
32
  }
38
33
 
39
- export class PktProgressbar extends PktElement implements IPktProgressbar {
40
- constructor() {
41
- super()
42
- }
34
+ export class PktProgressbar extends PktElement<IPktProgressbar> implements IPktProgressbar {
43
35
  // Public properties
44
36
  @property({ type: String }) ariaLabel: string | null = null
45
37
  @property({ type: String, reflect: true }) ariaLabelledby: string | null = null
46
38
  @property({ type: String, reflect: true }) ariaValueText: string | null = null
47
- @property({ type: String }) ariaLive: TAriaLive = 'polite'
39
+ @property({ type: String }) ariaLive: TAriaLive = PROGRESSBAR_DEFAULTS.ariaLive
48
40
  @property({ type: String, reflect: true }) id: string = uuidish()
49
- @property({ type: String }) role: TProgressbarRole = 'progressbar'
50
- @property({ type: String }) skin: TProgressbarSkin = 'dark-blue'
51
- @property({ type: String }) statusPlacement: TProgressbarStatusPlacement = 'following'
52
- @property({ type: String }) statusType: TProgressbarStatusType = 'none'
41
+ @property({ type: String }) role: TProgressbarRole = PROGRESSBAR_DEFAULTS.role
42
+ @property({ type: String }) skin: TProgressbarSkin = PROGRESSBAR_DEFAULTS.skin
43
+ @property({ type: String }) statusPlacement: TProgressbarStatusPlacement =
44
+ PROGRESSBAR_DEFAULTS.statusPlacement
45
+ @property({ type: String }) statusType: TProgressbarStatusType = PROGRESSBAR_DEFAULTS.statusType
53
46
  @property({ type: String, reflect: true }) title = ''
54
- @property({ type: String }) titlePosition: TProgressbarTitlePosition = 'left'
55
- @property({ type: Number, reflect: true }) valueCurrent = 0
56
- @property({ type: Number }) valueMax = 100
57
- @property({ type: Number }) valueMin = 0
47
+ @property({ type: String }) titlePosition: TProgressbarTitlePosition =
48
+ PROGRESSBAR_DEFAULTS.titlePosition
49
+ @property({ type: Number, reflect: true }) valueCurrent: number =
50
+ PROGRESSBAR_DEFAULTS.valueCurrent
51
+ @property({ type: Number }) valueMax: number = PROGRESSBAR_DEFAULTS.valueMax
52
+ @property({ type: Number }) valueMin: number = PROGRESSBAR_DEFAULTS.valueMin
58
53
 
59
54
  // State
60
55
  private labelWidth = 0
61
56
  @state() private progressbarId: string = this.id
62
- @state() private resolvedRole: TProgressbarRole = 'progressbar'
57
+ @state() private resolvedRole: TProgressbarRole = PROGRESSBAR_DEFAULTS.role
63
58
 
64
59
  // Private refs
65
60
  private labelRef: Ref<HTMLSpanElement> = createRef()
66
- private progressBarRef: Ref<HTMLDivElement> = createRef()
67
61
  private containerRef: Ref<HTMLDivElement> = createRef()
68
62
 
69
63
  protected willUpdate(changedProperties: Map<string | number | symbol, unknown>) {
@@ -97,17 +91,17 @@ export class PktProgressbar extends PktElement implements IPktProgressbar {
97
91
  render() {
98
92
  const hasStatus = this.statusType !== 'none'
99
93
  const totalSteps = this.valueMax - this.valueMin
100
- const percentageOfSteps = (this.valueCurrent / totalSteps) * 100
101
- const currentPercentage =
102
- this.statusType === 'fraction'
103
- ? Math.round(percentageOfSteps)
104
- : Math.round(((this.valueCurrent - this.valueMin) / (this.valueMax - this.valueMin)) * 100)
94
+ const currentStep = this.valueCurrent - this.valueMin
95
+ const currentPercentage = Math.round((currentStep / totalSteps) * 100)
105
96
 
106
- const formattedTitle = `${this.valueCurrent} av ${totalSteps}`
97
+ const formattedTitle = formatString(this.pktStrings.get('progressbar').fraction, {
98
+ current: currentStep,
99
+ total: totalSteps,
100
+ })
107
101
 
108
102
  const computedAriaValueText =
109
103
  this.statusType === 'fraction' && !this.ariaValueText
110
- ? `${this.valueCurrent} av ${this.valueMax - this.valueMin}`
104
+ ? formattedTitle
111
105
  : this.ariaValueText || ''
112
106
  const computedAriaLabelledby = this.ariaLabel
113
107
  ? undefined
@@ -132,7 +126,6 @@ export class PktProgressbar extends PktElement implements IPktProgressbar {
132
126
  })
133
127
 
134
128
  return html`<div
135
- ${ref(this.progressBarRef)}
136
129
  role=${this.resolvedRole}
137
130
  aria-live=${ifDefined(this.ariaLive || undefined)}
138
131
  aria-atomic="true"
@@ -152,25 +145,28 @@ export class PktProgressbar extends PktElement implements IPktProgressbar {
152
145
  '--pkt-progress-width': `${currentPercentage}%`,
153
146
  })}
154
147
  >
155
- ${this.title
156
- ? html`<p id=${`${this.progressbarId}-title`} class=${titleClasses}>${this.title}</p>`
157
- : nothing}
148
+ ${
149
+ this.title
150
+ ? html`<p id=${`${this.progressbarId}-title`} class=${titleClasses}>${this.title}</p>`
151
+ : nothing
152
+ }
158
153
 
159
154
  <div class="pkt-progressbar__bar-wrapper">
160
155
  <div class=${barClasses}></div>
161
156
  </div>
162
157
 
163
- ${hasStatus
164
- ? html`<div class=${statusClasses}>
165
- <span class=${placementClasses} ${ref(this.labelRef)}>
166
- ${this.statusType === 'percentage' ? `${currentPercentage}%` : formattedTitle}
167
- </span>
168
- </div>`
169
- : nothing}
158
+ ${
159
+ hasStatus
160
+ ? html`<div class=${statusClasses}>
161
+ <span class=${placementClasses} ${ref(this.labelRef)}>
162
+ ${this.statusType === 'percentage' ? `${currentPercentage}%` : formattedTitle}
163
+ </span>
164
+ </div>`
165
+ : nothing
166
+ }
170
167
  </div>
171
168
  </div>`
172
169
  }
173
-
174
170
  }
175
171
 
176
172
  export default PktProgressbar
@@ -187,7 +187,7 @@ describe('pkt-radiobutton', () => {
187
187
  optionalTag: true,
188
188
  })
189
189
 
190
- const tag = radiobutton.querySelector('.pkt-tag--blue-light')
190
+ const tag = radiobutton.querySelector('.pkt-tag--blue-pale')
191
191
  expect(tag).toBeInTheDocument()
192
192
  expect(tag?.textContent).toBe('Valgfritt')
193
193
  })
@@ -97,7 +97,7 @@ export class PktRadioButton extends PktInputElement<Props> implements IPktRadioB
97
97
  }
98
98
  ${
99
99
  this.optionalTag
100
- ? html`<span class=${tagClasses + ' pkt-tag--blue-light'}
100
+ ? html`<span class=${tagClasses + ' pkt-tag--blue-pale'}
101
101
  >${this.optionalText ?? formStrings.optional}</span
102
102
  >`
103
103
  : nothing
@@ -6,9 +6,10 @@ import { consume } from '@lit/context'
6
6
  import { createRef, Ref, ref } from 'lit/directives/ref.js'
7
7
  import { ifDefined } from 'lit/directives/if-defined.js'
8
8
  import { tabsContext, type TabsContext } from './tabs-context'
9
+ import type { TTagSkin } from 'shared-types'
9
10
  import '@/components/tag'
10
11
 
11
- export type TSkin = 'blue' | 'green' | 'red' | 'beige' | 'yellow' | 'grey' | 'gray' | 'blue-light'
12
+ export type TSkin = TTagSkin
12
13
 
13
14
  export interface IPktTabItem {
14
15
  active?: boolean
@@ -85,7 +86,10 @@ export class PktTabItem extends PktElementWithSlot<IPktTabItem> implements IPktT
85
86
  render() {
86
87
  const useArrowNav = this.context?.useArrowNav ?? true
87
88
  const isActive = this.active && !this.disabled
88
- const commonClasses = [isActive ? 'active' : '', this.disabled ? 'pkt-tabs__item--disabled' : '']
89
+ const commonClasses = [
90
+ isActive ? 'active' : '',
91
+ this.disabled ? 'pkt-tabs__item--disabled' : '',
92
+ ]
89
93
  .filter(Boolean)
90
94
  .join(' ')
91
95
  const role = useArrowNav ? 'tab' : undefined
@@ -2,6 +2,7 @@ import '@testing-library/jest-dom'
2
2
  import { axe, toHaveNoViolations } from 'jest-axe'
3
3
  import { fireEvent } from '@testing-library/dom'
4
4
  import { vi } from 'vitest'
5
+ import { TAG_SKINS, TAG_STATES } from 'shared-types'
5
6
  import { createElementTest, BaseTestConfig } from '../../tests/test-framework'
6
7
  import { CustomElementFor } from '../../tests/component-registry'
7
8
  import { type IPktTag } from './tag'
@@ -25,17 +26,8 @@ export const createTagTest = async (config: TagTestConfig = {}) => {
25
26
  expect.extend(toHaveNoViolations)
26
27
 
27
28
  // Test data constants
28
- const VALID_SKINS = [
29
- 'blue',
30
- 'blue-dark',
31
- 'blue-light',
32
- 'green',
33
- 'red',
34
- 'yellow',
35
- 'beige',
36
- 'gray',
37
- 'grey',
38
- ] as const
29
+ const VALID_SKINS = TAG_SKINS
30
+ const VALID_STATES = TAG_STATES
39
31
  const VALID_SIZES = ['small', 'medium', 'large'] as const
40
32
  const VALID_TYPES = ['button', 'reset', 'submit'] as const
41
33
 
@@ -54,7 +46,8 @@ describe('PktTag', () => {
54
46
  const { tag } = await createTagTest()
55
47
  expect(tag.closeTag).toBe(false)
56
48
  expect(tag.size).toBe('medium')
57
- expect(tag.skin).toBe('blue')
49
+ expect(tag.skin).toBe('gray')
50
+ expect(tag.state).toBe(null)
58
51
  expect(tag.type).toBe('button')
59
52
  })
60
53
 
@@ -76,6 +69,22 @@ describe('PktTag', () => {
76
69
  })
77
70
  })
78
71
 
72
+ describe('Forced States', () => {
73
+ test('applies forced state classes correctly', async () => {
74
+ for (const state of VALID_STATES) {
75
+ const { tag } = await createTagTest({ state })
76
+ const tagElement = tag.querySelector('span') || tag.querySelector('button')
77
+ expect(tagElement).toHaveClass(`pkt-tag--${state}`)
78
+ }
79
+ })
80
+
81
+ test('applies no state class by default', async () => {
82
+ const { tag } = await createTagTest()
83
+ const tagElement = tag.querySelector('span')
84
+ expect(tagElement?.className).not.toContain('pkt-tag--null')
85
+ })
86
+ })
87
+
79
88
  describe('Size Variations', () => {
80
89
  test('applies different size classes correctly', async () => {
81
90
  for (const size of VALID_SIZES) {
@@ -6,19 +6,25 @@ import { getSlotManager, slotContent } from '@/directives/slot-content'
6
6
  import specs from 'componentSpecs/tag.json'
7
7
 
8
8
  import '@/components/icon'
9
- import type { IAriaAttributes, THTMLButtonType, TPktSizeBase } from 'shared-types'
9
+ import type {
10
+ IAriaAttributes,
11
+ THTMLButtonType,
12
+ TTagSkin,
13
+ TTagState,
14
+ TPktSizeBase,
15
+ } from 'shared-types'
10
16
  import { PktIconName } from '@oslokommune/punkt-assets/dist/icons/icon'
11
17
  import { ifDefined } from 'lit/directives/if-defined.js'
12
18
  import { formatString, type IPktStringsProps } from 'shared-strings'
13
19
 
14
- export type TTagSkin =
15
- 'blue' | 'blue-dark' | 'blue-light' | 'green' | 'red' | 'yellow' | 'beige' | 'gray' | 'grey'
20
+ export type { TTagSkin, TTagState }
16
21
  export type TTagType = THTMLButtonType
17
22
 
18
23
  export interface IPktTag extends IPktStringsProps<'tag'> {
19
24
  closeTag?: boolean
20
25
  size?: TPktSizeBase
21
26
  skin?: TTagSkin
27
+ state?: TTagState | null
22
28
  textStyle?: string | null
23
29
  iconName?: PktIconName
24
30
  type?: TTagType
@@ -38,6 +44,7 @@ export class PktTag extends PktElementWithSlot<IPktTag> implements IPktTag {
38
44
  @property({ type: String, reflect: true }) size: TPktSizeBase = specs.props.size
39
45
  .default as TPktSizeBase
40
46
  @property({ type: String, reflect: true }) skin: TTagSkin = specs.props.skin.default as TTagSkin
47
+ @property({ type: String, reflect: true }) state: TTagState | null = null
41
48
  @property({ type: String, reflect: true }) textStyle: string | null = null
42
49
  @property({ type: String, reflect: true }) iconName: string | undefined = undefined
43
50
  @property({ type: String }) type: TTagType = specs.props.type.default as TTagType
@@ -89,6 +96,7 @@ export class PktTag extends PktElementWithSlot<IPktTag> implements IPktTag {
89
96
  'pkt-tag': true,
90
97
  [`pkt-tag--${this.size}`]: !!this.size,
91
98
  [`pkt-tag--${this.skin}`]: !!this.skin,
99
+ [`pkt-tag--${this.state}`]: !!this.state,
92
100
  [`pkt-tag--${this.textStyle}`]: !!this.textStyle,
93
101
  }
94
102
 
@@ -97,6 +105,7 @@ export class PktTag extends PktElementWithSlot<IPktTag> implements IPktTag {
97
105
  [`pkt-tag--${this.textStyle}`]: !!this.textStyle,
98
106
  [`pkt-tag--${this.size}`]: !!this.size,
99
107
  [`pkt-tag--${this.skin}`]: !!this.skin,
108
+ [`pkt-tag--${this.state}`]: !!this.state,
100
109
  'pkt-hide': this._isClosed,
101
110
  }
102
111
 
@@ -1,64 +0,0 @@
1
- const e=require("./element-C6WTyJFE.cjs"),t=require("./class-map-Bh6toDeV.cjs"),n=require("./format-B8meU8Tm.cjs"),r=require("./element-with-slot-B0Vp_OuR.cjs");require("./shared-types-BvRk9kiK.cjs"),require("./icon-CrG6o7ZE.cjs");const i=require("./if-defined-CiML3MTM.cjs");require("./tag-DrFK8Wq3.cjs");var a=[`outlined`,`outlined-beige`,`gray`,`blue`,`beige`,`green`],o={headingLevel:3,layout:`vertical`,skin:`outlined`,padding:`default`,tagPosition:`top`,openLinkInNewTab:!1,borderOnHover:!0,zoom:!1,imageShape:`square`,restrictImageHeight:!1},s=class extends r.t{constructor(...e){super(...e),this.ariaLabel=``,this.metaLead=null,this.borderOnHover=o.borderOnHover,this.zoom=o.zoom,this.imageAspect=null,this.restrictImageHeight=o.restrictImageHeight,this.clickCardLink=null,this.metaTrail=null,this.layout=o.layout,this.heading=``,this.headingLevel=o.headingLevel,this.image={src:``,alt:``},this.imageShape=o.imageShape,this.openLinkInNewTab=o.openLinkInNewTab,this.padding=o.padding,this.skin=o.skin,this.subheading=``,this.tagPosition=`top`,this.tags=[]}connectedCallback(){super.connectedCallback()}render(){let n={"pkt-card":!0,[`pkt-card--${this.skin}`]:this.skin,[`pkt-card--${this.layout}`]:this.layout,[`pkt-card--padding-${this.padding}`]:this.padding,"pkt-card--border-on-hover":this.borderOnHover,"pkt-card--zoom":this.zoom},r=this.ariaLabel?.trim()||(this.heading?`${this.heading} lenkekort`:`lenkekort`),a=this.ariaLabel?.trim()||(this.heading?this.heading:`kort`);return e._`
2
- <article
3
- class=${t.t(n)}
4
- aria-label=${i.t(this.clickCardLink?r:a)}
5
- >
6
- ${this.renderImage()}
7
- <div class="pkt-card__wrapper">
8
- ${this.tagPosition===`top`?this.renderTags():e.h}
9
- ${this.renderHeader()}
10
- ${this.renderSlot()}
11
- ${this.tagPosition===`bottom`?this.renderTags():e.h}
12
- ${this.renderMetadata()}
13
- </div>
14
- </article>
15
- `}renderImage(){let n={"pkt-card__image":!0,[`pkt-card__image-${this.imageShape}`]:this.imageShape,[`pkt-card__image-aspect-${this.imageAspect}`]:!!this.imageAspect,"pkt-card__image-restricted":this.restrictImageHeight};return e._`
16
- ${this.image.src&&e._`
17
- <div class=${t.t(n)}>
18
- <img src=${this.image.src} alt=${this.image.alt||``} />
19
- </div>
20
- `}
21
- `}renderHeadingTag(t,n){let r=this.headingLevel&&this.headingLevel>=1&&this.headingLevel<=6?this.headingLevel:3,i=`pkt-heading pkt-heading--medium pkt-heading--fw-regular ${t}`;switch(r){case 1:return e._`<h1 class=${i}>${n}</h1>`;case 2:return e._`<h2 class=${i}>${n}</h2>`;case 4:return e._`<h4 class=${i}>${n}</h4>`;case 5:return e._`<h5 class=${i}>${n}</h5>`;case 6:return e._`<h6 class=${i}>${n}</h6>`;default:return e._`<h3 class=${i}>${n}</h3>`}}renderHeading(){return!this.heading||this.clickCardLink?e.h:this.renderHeadingTag(`pkt-card__heading`,this.heading)}renderLinkHeading(){return this.clickCardLink?this.renderHeadingTag(`pkt-card__link-heading pkt-card__heading`,e._`<a
22
- class="pkt-card__link"
23
- href=${this.clickCardLink}
24
- target=${this.openLinkInNewTab?`_blank`:`_self`}
25
- rel=${i.t(this.openLinkInNewTab?`noopener noreferrer`:void 0)}
26
- >${this.heading}</a
27
- >`):e.h}renderSubheading(){return e._`
28
- ${this.subheading?e._` <p class="pkt-card__subheading ">${this.subheading}</p> `:e.h}
29
- `}renderHeader(){let t=!!this.heading||!!this.subheading;return e._`
30
- ${t?e._`
31
- <header class="pkt-card__header">
32
- ${this.renderHeading()}
33
- ${this.renderLinkHeading()}
34
- ${this.renderSubheading()}
35
- </header>
36
- `:e.h}
37
- `}renderTags(){let r={"pkt-card__tags":!0,[`pkt-card__tags-${this.tagPosition}`]:this.tagPosition};return e._`
38
- ${this.tags.length>0?e._`
39
- <div
40
- class=${t.t(r)}
41
- role="list"
42
- aria-label=${n.n(this.tags.length,this.pktStrings.get(`card`).tagsLabelOne,this.pktStrings.get(`card`).tagsLabelOther)}
43
- >
44
- ${this.tags.map(t=>e._`
45
- <pkt-tag
46
- role="listitem"
47
- textStyle="normal-text"
48
- size="medium"
49
- skin=${i.t(t.skin)}
50
- iconName=${i.t(t.iconName)}
51
- >
52
- <span>${t.text}</span>
53
- </pkt-tag>
54
- `)}
55
- </div>
56
- `:e.h}
57
- `}renderSlot(){return e._`<section class="pkt-card__content">${r.i(this)}</section>`}renderMetadata(){return e._`
58
- ${this.metaLead||this.metaTrail?e._`
59
- <footer class="pkt-card__metadata">
60
- ${this.metaLead?e._`<span class="pkt-card__metadata-lead">${this.metaLead}</span>`:e.h}
61
- ${this.metaTrail?e._`<span class="pkt-card__metadata-trail">${this.metaTrail}</span>`:e.h}
62
- </footer>
63
- `:e.h}
64
- `}};e.n([e.u({type:String})],s.prototype,`ariaLabel`,void 0),e.n([e.u({type:String})],s.prototype,`metaLead`,void 0),e.n([e.u({type:Boolean})],s.prototype,`borderOnHover`,void 0),e.n([e.u({type:Boolean})],s.prototype,`zoom`,void 0),e.n([e.u({type:String})],s.prototype,`imageAspect`,void 0),e.n([e.u({type:Boolean})],s.prototype,`restrictImageHeight`,void 0),e.n([e.u({type:String,reflect:!0})],s.prototype,`clickCardLink`,void 0),e.n([e.u({type:String})],s.prototype,`metaTrail`,void 0),e.n([e.u({type:String})],s.prototype,`layout`,void 0),e.n([e.u({type:String})],s.prototype,`heading`,void 0),e.n([e.u({type:Number,attribute:`headinglevel`})],s.prototype,`headingLevel`,void 0),e.n([e.u({type:Object})],s.prototype,`image`,void 0),e.n([e.u({type:String})],s.prototype,`imageShape`,void 0),e.n([e.u({type:Boolean})],s.prototype,`openLinkInNewTab`,void 0),e.n([e.u({type:String})],s.prototype,`padding`,void 0),e.n([e.u({type:String,converter:{fromAttribute:e=>{let t=a;return e&&t.includes(e)?e:(e&&!t.includes(e)&&console.warn(`Invalid skin value "${e}". Using default skin "${o.skin}".`),o.skin)},toAttribute:e=>e}})],s.prototype,`skin`,void 0),e.n([e.u({type:String})],s.prototype,`subheading`,void 0),e.n([e.u({type:String})],s.prototype,`tagPosition`,void 0),e.n([e.u({type:Array})],s.prototype,`tags`,void 0);try{e.d(`pkt-card`)(s)}catch{console.warn(`Forsøker å definere <pkt-card>, men den er allerede definert`)}var c=s;Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return c}});
@@ -1 +0,0 @@
1
- const e=require("./element-C6WTyJFE.cjs");require("./shared-types-BvRk9kiK.cjs");var t=`https://punkt-cdn.oslo.kommune.no/latest/icons/`,n=`https://punkt-cdn.oslo.kommune.no/latest/animations/`,r={name:``,path:t},i=class extends e.p{constructor(t){if(super(t),this.it=e.h,t.type!==e.m.CHILD)throw Error(this.constructor.directiveName+`() can only be used in child bindings`)}render(t){if(t===e.h||t==null)return this._t=void 0,this.it=t;if(t===e.g)return t;if(typeof t!=`string`)throw Error(this.constructor.directiveName+`() called with a non-string value`);if(t===this.it)return this._t;this.it=t;let n=[t];return n.raw=n,this._t={_$litType$:this.constructor.resultType,strings:n,values:[]}}};i.directiveName=`unsafeHTML`,i.resultType=1;var a=e.f(i),o=class extends i{};o.directiveName=`unsafeSVG`,o.resultType=2;var s=e.f(o);typeof window<`u`&&(window.pktFetch=window.pktFetch===void 0?fetch:window.pktFetch,window.pktIconPath=window.pktIconPath||r.path);var c=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"></svg>`,l={},u=2,d=1500,f=(()=>{try{return typeof Storage<`u`&&typeof sessionStorage<`u`}catch{return!1}})(),p=e=>window.pktFetch(e).then(t=>{if(!t.ok)throw Error(`Missing icon: `+e);return t.text()}),m=async(e,t=u)=>{try{return await p(e)}catch{return t>0?(await new Promise(e=>setTimeout(e,d)),m(e,t-1)):(console.error(`Failed to fetch icon: `+e),c)}},h=async(e,t)=>{let n=t+e+`.svg`;return f&&sessionStorage.getItem(n)?sessionStorage.getItem(n):n in l?l[n]:typeof window<`u`&&typeof window.pktFetch==`function`?(l[n]=m(n).then(e=>(e!==c&&f&&sessionStorage.setItem(n,e),delete l[n],e)),l[n]):c},g=class extends e.t{constructor(...e){super(...e),this.path=typeof window<`u`?window.pktIconPath:r.path,this.name=r.name,this.ariaHidden=null,this.ariaLabel=null,this.icon=s(c),this._updatedProps=[]}get effectiveAriaHidden(){return this.ariaHidden!==null&&this.ariaHidden!==void 0?this.ariaHidden===``||this.ariaHidden===`true`:!this.ariaLabel}get effectiveAriaLabel(){return this.effectiveAriaHidden?null:this.ariaLabel||this.name||null}connectedCallback(){super.connectedCallback(),this.classList.add(`pkt-icon`)}async attributeChangedCallback(e,t,n){super.attributeChangedCallback(e,t,n),(e===`name`||e===`path`)&&this.getIcon(this.name)}async updated(e){super.updated(e),(e.has(`name`)||e.has(`path`))&&this.getIcon(this.name),this.applyAriaToSvg()}applyAriaToSvg(){let e=this.querySelector(`svg`);if(!e)return;e.setAttribute(`aria-hidden`,String(this.effectiveAriaHidden));let t=this.effectiveAriaLabel;t?e.setAttribute(`aria-label`,t):e.removeAttribute(`aria-label`)}async getIcon(e=``){if(this._updatedProps.length>0){this.path||=typeof window<`u`?window.pktIconPath:r.path;try{this.icon=s(await h(this.name||``,this.path))}catch{this.icon=s(c)}this._updatedProps=[]}else this._updatedProps.includes(e)||this._updatedProps.push(e)}render(){return e._`${this.name&&this.icon}`}};e.n([e.u({type:String,reflect:!1})],g.prototype,`path`,void 0),e.n([e.u({type:String,reflect:!0})],g.prototype,`name`,void 0),e.n([e.u({type:String,attribute:`aria-hidden`,reflect:!0})],g.prototype,`ariaHidden`,void 0),e.n([e.u({type:String,attribute:`aria-label`,reflect:!0})],g.prototype,`ariaLabel`,void 0),e.n([e.u({type:SVGElement})],g.prototype,`icon`,void 0),e.n([e.u({type:Array,noAccessor:!0})],g.prototype,`_updatedProps`,void 0);try{e.d(`pkt-icon`)(g)}catch{console.warn(`Forsøker å definere <pkt-icon>, men den er allerede definert`)}var _=g;Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return _}});
@@ -1 +0,0 @@
1
- const e=require("./element-C6WTyJFE.cjs");var t=t=>t??e.h;Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return t}});