@oslokommune/punkt-elements 17.1.3 → 18.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 (249) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/{accordion-BeLvLPrB.js → accordion-1_pdxTgJ.js} +27 -27
  3. package/dist/{accordion-B3GBlvUC.cjs → accordion-DobbH-Sv.cjs} +5 -5
  4. package/dist/{alert-Cs4Rmq_J.cjs → alert-COeHz6o2.cjs} +6 -6
  5. package/dist/{alert-DKK_Tb9J.js → alert-xspFetQ8.js} +26 -26
  6. package/dist/{async-directive-Da7TJpnq.cjs → async-directive-B5pcIMfO.cjs} +1 -1
  7. package/dist/{async-directive-BPf6K-V2.js → async-directive-D2Sht790.js} +5 -5
  8. package/dist/{backlink-D1y26pj3.js → backlink-C0jZFnZ2.js} +8 -8
  9. package/dist/{backlink-CMmrKTe4.cjs → backlink-ZMhqHaVs.cjs} +3 -3
  10. package/dist/base-elements/element.d.ts +13 -1
  11. package/dist/base-elements/input-element.d.ts +4 -2
  12. package/dist/{breadcrumbs-B6JGhJgC.cjs → breadcrumbs-BS64xd1s.cjs} +7 -7
  13. package/dist/{breadcrumbs-CcTQ3Grm.js → breadcrumbs-BvMownZN.js} +16 -16
  14. package/dist/{button-2-OSPJkj.js → button-C44vNLFC.js} +28 -28
  15. package/dist/{button-CE97NQIk.cjs → button-CR4CXtnj.cjs} +7 -7
  16. package/dist/{calendar-kn4SrtJy.cjs → calendar-DQ4byeom.cjs} +28 -27
  17. package/dist/{calendar-pOW3R5Pw.js → calendar-DgjCKMMV.js} +82 -68
  18. package/dist/{card-zQ0eKRMV.js → card-DhHqC265.js} +44 -44
  19. package/dist/{card-CETDFkxR.cjs → card-Dpqi6HVt.cjs} +26 -26
  20. package/dist/{checkbox-CH7NpINF.js → checkbox-BQ1K57AB.js} +23 -23
  21. package/dist/{checkbox-CQNr_sEg.cjs → checkbox-CXQxbiaX.cjs} +11 -11
  22. package/dist/{class-map-BeimMvPv.cjs → class-map-CzCE5pqG.cjs} +1 -1
  23. package/dist/{class-map-CnWCnBSX.js → class-map-F1DJHyb7.js} +3 -3
  24. package/dist/{combobox-Bvg0UO9w.cjs → combobox-BV4oDiII.cjs} +19 -18
  25. package/dist/{combobox-CRdYYlxu.js → combobox-DPck39I2.js} +55 -54
  26. package/dist/components/calendar/calendar.d.ts +21 -6
  27. package/dist/components/checkbox/checkbox.d.ts +4 -2
  28. package/dist/components/combobox/combobox-base.d.ts +2 -1
  29. package/dist/components/consent/strings.d.ts +1 -85
  30. package/dist/components/datepicker/datepicker-base.d.ts +0 -3
  31. package/dist/components/datepicker/datepicker-multiple.d.ts +0 -2
  32. package/dist/components/datepicker/datepicker-range.d.ts +0 -2
  33. package/dist/components/datepicker/datepicker-single.d.ts +0 -2
  34. package/dist/components/datepicker/datepicker-utils.d.ts +2 -1
  35. package/dist/components/fileupload/fileupload-base.d.ts +3 -2
  36. package/dist/components/header/header-service.d.ts +3 -1
  37. package/dist/components/header/header.d.ts +2 -1
  38. package/dist/components/helptext/helptext.d.ts +2 -1
  39. package/dist/components/index.d.ts +2 -0
  40. package/dist/components/input-wrapper/input-wrapper.d.ts +4 -2
  41. package/dist/components/radiobutton/radiobutton.d.ts +4 -2
  42. package/dist/components/searchinput/searchinput.d.ts +2 -1
  43. package/dist/{consent-DZEkhgJ1.js → consent-BneInZov.js} +10 -10
  44. package/dist/{consent-CyY3RyoC.cjs → consent-_N9foluG.cjs} +5 -5
  45. package/dist/controllers/strings-controller.d.ts +27 -0
  46. package/dist/{datepicker-VTqSDQk5.cjs → datepicker-9NX5qt2z.cjs} +38 -37
  47. package/dist/{datepicker-ButIas85.js → datepicker-nSSSr1U7.js} +104 -104
  48. package/dist/{directive-helpers-CI8YZqku.js → directive-helpers-BARw3nEZ.js} +1 -1
  49. package/dist/{directive-helpers-BlAV5EQD.cjs → directive-helpers-D6AAMFKs.cjs} +1 -1
  50. package/dist/docs/components/fileupload.d.ts +1 -0
  51. package/dist/element-B8OGznK0.cjs +2 -0
  52. package/dist/{element-ChsFgr_B.js → element-BKSPVgs2.js} +240 -100
  53. package/dist/{element-with-slot-Bj7nm7fO.cjs → element-with-slot-DTxILHVv.cjs} +1 -1
  54. package/dist/{element-with-slot-BvG9ctC-.js → element-with-slot-YUAUFRqw.js} +4 -4
  55. package/dist/fileupload-D05VSbEP.cjs +402 -0
  56. package/dist/{fileupload-D5IQ9HDe.js → fileupload-E0LGGNgj.js} +370 -380
  57. package/dist/{footer-DbYQUYNR.cjs → footer-DBApIdGh.cjs} +32 -32
  58. package/dist/{footer-DrR64HiK.js → footer-DYilVBMC.js} +91 -91
  59. package/dist/format-B8meU8Tm.cjs +1 -0
  60. package/dist/format-BTeSVkED.js +18 -0
  61. package/dist/{header-ClgIac6n.cjs → header-B7tbX-Ok.cjs} +84 -84
  62. package/dist/{header-menu-BAsUNKSx.cjs → header-menu-1FFWhvNc.cjs} +24 -24
  63. package/dist/{header-menu-hVPXsb8g.js → header-menu-D522-VTV.js} +75 -75
  64. package/dist/{header-KvJ1mGwA.js → header-v3GWAzOK.js} +267 -264
  65. package/dist/{heading-CFmiSuCQ.cjs → heading-CvytvcL7.cjs} +1 -1
  66. package/dist/{heading-g-_IUB5T.js → heading-rx_oSCqe.js} +16 -16
  67. package/dist/helptext-DYFdcylX.cjs +27 -0
  68. package/dist/{helptext-DZng1D5i.js → helptext-LShGPm-b.js} +18 -19
  69. package/dist/{icon-9iwd2F2l.cjs → icon-BmMC09mi.cjs} +1 -1
  70. package/dist/{icon-D-LA22xD.js → icon-HYU1f54x.js} +17 -17
  71. package/dist/{if-defined-CGzIlZ9-.js → if-defined-BF8XcDi5.js} +1 -1
  72. package/dist/if-defined-CVYApOgK.cjs +1 -0
  73. package/dist/{input-element-DBMNBplu.js → input-element-D07DmR34.js} +121 -120
  74. package/dist/input-element-DumGj_oJ.cjs +1 -0
  75. package/dist/input-wrapper-Cci_wTvD.js +308 -0
  76. package/dist/input-wrapper-DDfapoRX.cjs +58 -0
  77. package/dist/{link-DK7gvmnj.cjs → link-11g2ZNin.cjs} +4 -4
  78. package/dist/{link-D-Eqm5KH.js → link-CQK0SH4H.js} +13 -13
  79. package/dist/{linkcard-zqbg7Oqm.js → linkcard-B4GlmjJ6.js} +16 -16
  80. package/dist/linkcard-DNYsVlV6.cjs +13 -0
  81. package/dist/{listbox-Dc4rGdPi.cjs → listbox-BlFRhyI7.cjs} +15 -15
  82. package/dist/{listbox-va_E8afs.js → listbox-wd_OofyF.js} +100 -99
  83. package/dist/{loader-D_RDICnw.js → loader-0C3qVk16.js} +14 -14
  84. package/dist/{loader-CMUkVJmE.cjs → loader-B9u2qUlR.cjs} +5 -5
  85. package/dist/{messagebox-Cv8LaSxv.cjs → messagebox-BD5tGmT-.cjs} +5 -5
  86. package/dist/{messagebox-Cw-OWDya.js → messagebox-C-y1ICmr.js} +15 -15
  87. package/dist/{modal-BtInv031.cjs → modal-BzPGQYCs.cjs} +8 -8
  88. package/dist/{modal-D0t_X2dX.js → modal-Cghs3w-d.js} +20 -20
  89. package/dist/pkt-accordion.cjs +1 -1
  90. package/dist/pkt-accordion.js +1 -1
  91. package/dist/pkt-alert.cjs +1 -1
  92. package/dist/pkt-alert.js +1 -1
  93. package/dist/pkt-backlink.cjs +1 -1
  94. package/dist/pkt-backlink.js +1 -1
  95. package/dist/pkt-breadcrumbs.cjs +1 -1
  96. package/dist/pkt-breadcrumbs.js +1 -1
  97. package/dist/pkt-button.cjs +1 -1
  98. package/dist/pkt-button.js +1 -1
  99. package/dist/pkt-calendar.cjs +1 -1
  100. package/dist/pkt-calendar.js +1 -1
  101. package/dist/pkt-card.cjs +1 -1
  102. package/dist/pkt-card.js +1 -1
  103. package/dist/pkt-checkbox.cjs +1 -1
  104. package/dist/pkt-checkbox.js +1 -1
  105. package/dist/pkt-combobox.cjs +1 -1
  106. package/dist/pkt-combobox.js +1 -1
  107. package/dist/pkt-consent.cjs +1 -1
  108. package/dist/pkt-consent.js +1 -1
  109. package/dist/pkt-datepicker.cjs +1 -1
  110. package/dist/pkt-datepicker.js +1 -1
  111. package/dist/pkt-fileupload.cjs +1 -1
  112. package/dist/pkt-fileupload.js +1 -1
  113. package/dist/pkt-footer.cjs +1 -1
  114. package/dist/pkt-footer.js +1 -1
  115. package/dist/pkt-header-menu.cjs +1 -1
  116. package/dist/pkt-header-menu.js +1 -1
  117. package/dist/pkt-header.cjs +1 -1
  118. package/dist/pkt-header.js +1 -1
  119. package/dist/pkt-heading.cjs +1 -1
  120. package/dist/pkt-heading.js +1 -1
  121. package/dist/pkt-helptext.cjs +1 -1
  122. package/dist/pkt-helptext.js +1 -1
  123. package/dist/pkt-icon.cjs +1 -1
  124. package/dist/pkt-icon.js +1 -1
  125. package/dist/pkt-index.cjs +1 -1
  126. package/dist/pkt-index.js +35 -34
  127. package/dist/pkt-input-wrapper.cjs +1 -1
  128. package/dist/pkt-input-wrapper.js +1 -1
  129. package/dist/pkt-link.cjs +1 -1
  130. package/dist/pkt-link.js +1 -1
  131. package/dist/pkt-linkcard.cjs +1 -1
  132. package/dist/pkt-linkcard.js +1 -1
  133. package/dist/pkt-listbox.cjs +1 -1
  134. package/dist/pkt-listbox.js +1 -1
  135. package/dist/pkt-loader.cjs +1 -1
  136. package/dist/pkt-loader.js +1 -1
  137. package/dist/pkt-messagebox.cjs +1 -1
  138. package/dist/pkt-messagebox.js +1 -1
  139. package/dist/pkt-modal.cjs +1 -1
  140. package/dist/pkt-modal.js +1 -1
  141. package/dist/{pkt-options-controller-C5EBX2T0.cjs → pkt-options-controller-CEEAqXaB.cjs} +1 -1
  142. package/dist/{pkt-options-controller-B77vH3PE.js → pkt-options-controller-PtjhmTGk.js} +1 -1
  143. package/dist/pkt-progressbar.cjs +1 -1
  144. package/dist/pkt-progressbar.js +1 -1
  145. package/dist/pkt-radiobutton.cjs +1 -1
  146. package/dist/pkt-radiobutton.js +1 -1
  147. package/dist/pkt-searchinput.cjs +1 -1
  148. package/dist/pkt-searchinput.js +1 -1
  149. package/dist/pkt-select.cjs +1 -1
  150. package/dist/pkt-select.js +1 -1
  151. package/dist/pkt-tabs.cjs +1 -1
  152. package/dist/pkt-tabs.js +1 -1
  153. package/dist/pkt-tag.cjs +1 -1
  154. package/dist/pkt-tag.js +1 -1
  155. package/dist/pkt-textarea.cjs +1 -1
  156. package/dist/pkt-textarea.js +1 -1
  157. package/dist/pkt-textinput.cjs +1 -1
  158. package/dist/pkt-textinput.js +1 -1
  159. package/dist/pkt-timepicker.cjs +1 -1
  160. package/dist/pkt-timepicker.js +1 -1
  161. package/dist/{progressbar-CbcfLerF.js → progressbar-BexQQw1o.js} +21 -21
  162. package/dist/{progressbar-D5MmnQId.cjs → progressbar-X9mSvpjw.cjs} +5 -5
  163. package/dist/{radiobutton-BUnf3EPi.js → radiobutton-CkhTasn4.js} +24 -24
  164. package/dist/{radiobutton-DpsO1F-8.cjs → radiobutton-ln29Ad3U.cjs} +8 -8
  165. package/dist/{ref-CQoEIIp0.cjs → ref-CHbJYtKE.cjs} +1 -1
  166. package/dist/{ref-CWD6PjVd.js → ref-Chc_DZAb.js} +2 -2
  167. package/dist/{repeat-sY6B7fAT.cjs → repeat-CHDs__rN.cjs} +1 -1
  168. package/dist/{repeat-C02g7d5S.js → repeat-P9SMlKd5.js} +4 -4
  169. package/dist/searchinput-CPgMEAZZ.cjs +60 -0
  170. package/dist/{searchinput-DwnjsvJ1.js → searchinput-Da7dKHBH.js} +43 -43
  171. package/dist/{select-BOJi6H6T.cjs → select-DCuvdAuK.cjs} +4 -3
  172. package/dist/{select-DMre80qs.js → select-jabMSjft.js} +21 -20
  173. package/dist/shared-strings/consent.d.ts +71 -0
  174. package/dist/shared-strings/format.d.ts +21 -0
  175. package/dist/shared-strings/index.d.ts +14 -0
  176. package/dist/shared-strings/nb.d.ts +118 -0
  177. package/dist/shared-strings/resolve.d.ts +12 -0
  178. package/dist/shared-strings/store.d.ts +27 -0
  179. package/dist/shared-strings/types.d.ts +29 -0
  180. package/dist/shared-types/fileupload.d.ts +0 -27
  181. package/dist/shared-types/index.d.ts +1 -2
  182. package/dist/shared-utils/combobox/index.d.ts +1 -0
  183. package/dist/shared-utils/combobox/input-utils.d.ts +2 -1
  184. package/dist/shared-utils/combobox/messages.d.ts +7 -0
  185. package/dist/shared-utils/combobox/option-utils.d.ts +2 -1
  186. package/dist/shared-utils/combobox/selection-manager.d.ts +3 -2
  187. package/dist/{tabs-Cf9ai0FD.cjs → tabs-DV5CQNDL.cjs} +7 -7
  188. package/dist/{tabs-TvxgbrCF.js → tabs-D_hoi1zu.js} +32 -32
  189. package/dist/tag-BxYulmZn.cjs +27 -0
  190. package/dist/{tag-Ds6n1LIs.js → tag-DK5SgKry.js} +33 -32
  191. package/dist/tests/strings-override.test.d.ts +0 -0
  192. package/dist/{textarea-vfzIcXhX.js → textarea-BR7Riace.js} +30 -29
  193. package/dist/{textarea-BydiLM9Z.cjs → textarea-ffBD_VHq.cjs} +3 -2
  194. package/dist/{textinput-CMP2jPP_.js → textinput-CRNrsRNV.js} +28 -27
  195. package/dist/{textinput-DGdicNSx.cjs → textinput-CtHFzAux.cjs} +13 -12
  196. package/dist/timepicker-AfgJipo6.cjs +196 -0
  197. package/dist/{timepicker-ClwgYywH.js → timepicker-ixs_E5RY.js} +67 -64
  198. package/package.json +3 -3
  199. package/src/components/backlink/backlink.ts +1 -1
  200. package/src/components/breadcrumbs/breadcrumbs.ts +1 -1
  201. package/src/components/calendar/calendar.ts +56 -26
  202. package/src/components/checkbox/checkbox.test.ts +0 -2
  203. package/src/components/checkbox/checkbox.ts +8 -4
  204. package/src/components/combobox/combobox-base.ts +2 -1
  205. package/src/components/combobox/combobox-value.ts +10 -9
  206. package/src/components/combobox/combobox.selection.test.ts +5 -1
  207. package/src/components/combobox/combobox.ts +4 -1
  208. package/src/components/consent/strings.ts +1 -125
  209. package/src/components/datepicker/date-tags.ts +4 -1
  210. package/src/components/datepicker/datepicker-base.ts +2 -6
  211. package/src/components/datepicker/datepicker-multiple.ts +0 -3
  212. package/src/components/datepicker/datepicker-range.ts +4 -7
  213. package/src/components/datepicker/datepicker-single.ts +0 -3
  214. package/src/components/datepicker/datepicker-utils.test.ts +5 -5
  215. package/src/components/datepicker/datepicker-utils.ts +6 -11
  216. package/src/components/datepicker/datepicker.ts +8 -1
  217. package/src/components/fileupload/fileupload-base.ts +25 -16
  218. package/src/components/fileupload/fileupload-renderers.ts +2 -1
  219. package/src/components/fileupload/fileupload.test.ts +16 -0
  220. package/src/components/fileupload/fileupload.ts +19 -15
  221. package/src/components/header/header-global.ts +3 -3
  222. package/src/components/header/header-service.ts +13 -8
  223. package/src/components/header/header.ts +2 -1
  224. package/src/components/helptext/helptext.test.ts +1 -1
  225. package/src/components/helptext/helptext.ts +3 -3
  226. package/src/components/index.ts +9 -0
  227. package/src/components/input-wrapper/input-wrapper.ts +18 -10
  228. package/src/components/listbox/listbox.ts +3 -3
  229. package/src/components/radiobutton/radiobutton.ts +8 -4
  230. package/src/components/searchinput/searchinput.ts +5 -3
  231. package/src/components/select/select.ts +1 -0
  232. package/src/components/tag/tag.ts +2 -1
  233. package/src/components/textarea/textarea.ts +1 -0
  234. package/src/components/textinput/textinput.ts +1 -0
  235. package/src/components/timepicker/timepicker.ts +23 -21
  236. package/dist/element-BA8v6S7z.cjs +0 -2
  237. package/dist/fileupload-BeWiTAoW.cjs +0 -401
  238. package/dist/helptext-CTtKJcML.cjs +0 -27
  239. package/dist/if-defined-B89_ZeCj.cjs +0 -1
  240. package/dist/input-element-DYmQw-fH.cjs +0 -1
  241. package/dist/input-wrapper-BmxNvznr.js +0 -128
  242. package/dist/input-wrapper-D-fPaTbY.js +0 -176
  243. package/dist/input-wrapper-D5PR0rJn.cjs +0 -1
  244. package/dist/input-wrapper-Q-B-aBeb.cjs +0 -54
  245. package/dist/linkcard-B29cmZqh.cjs +0 -13
  246. package/dist/searchinput-Bh975rjX.cjs +0 -60
  247. package/dist/tag-CzojNU7z.cjs +0 -27
  248. package/dist/timepicker-DYrnLHqN.cjs +0 -195
  249. package/dist/translations/no.json.d.ts +0 -94
@@ -3,7 +3,6 @@ import { classMap } from 'lit/directives/class-map.js'
3
3
  import { ifDefined } from 'lit/directives/if-defined.js'
4
4
  import { customElement, state } from 'lit/decorators.js'
5
5
 
6
- import { defaultFileUploadStrings } from 'shared-types'
7
6
  import { navigateCyclic, trapTabInside, type IFileAndTransfer } from 'shared-utils/fileupload'
8
7
 
9
8
  import '@/components/alert'
@@ -70,6 +69,7 @@ export class PktFileUpload extends PktFileUploadBase implements IPktFileUpload {
70
69
 
71
70
  return html`
72
71
  <pkt-input-wrapper
72
+ .strings=${this.strings}
73
73
  .forId=${`${this.id}-input`}
74
74
  .label=${this.label}
75
75
  .helptext=${this.helptext}
@@ -95,6 +95,7 @@ export class PktFileUpload extends PktFileUploadBase implements IPktFileUpload {
95
95
  private renderContent() {
96
96
  const filesAndTransfers = this.getSortedFilesAndTransfers()
97
97
  const previewableImages = this.getPreviewableImages(filesAndTransfers)
98
+ const fileuploadStrings = this.pktStrings.get('fileupload')
98
99
  const supportedFormatsText = this.getSupportedFormatsText()
99
100
  const helptextId = !this.label && this.helptext ? `${this.id}-helptext` : undefined
100
101
  const errorId = this.hasEffectiveError ? `${this.id}-error` : undefined
@@ -103,25 +104,25 @@ export class PktFileUpload extends PktFileUploadBase implements IPktFileUpload {
103
104
  const dropZoneCopy = isThumbnailView
104
105
  ? this.multiple
105
106
  ? {
106
- dragInactive: defaultFileUploadStrings.dropZoneDragMultipleThumbnail,
107
- dragActive: defaultFileUploadStrings.dropZoneDragActiveMultipleThumbnail,
108
- openFileDialog: defaultFileUploadStrings.dropZoneOpenFileDialogMultipleThumbnail,
107
+ dragInactive: fileuploadStrings.dropZoneDragMultipleThumbnail,
108
+ dragActive: fileuploadStrings.dropZoneDragActiveMultipleThumbnail,
109
+ openFileDialog: fileuploadStrings.dropZoneOpenFileDialogMultipleThumbnail,
109
110
  }
110
111
  : {
111
- dragInactive: defaultFileUploadStrings.dropZoneDragSingleThumbnail,
112
- dragActive: defaultFileUploadStrings.dropZoneDragActiveSingleThumbnail,
113
- openFileDialog: defaultFileUploadStrings.dropZoneOpenFileDialogSingleThumbnail,
112
+ dragInactive: fileuploadStrings.dropZoneDragSingleThumbnail,
113
+ dragActive: fileuploadStrings.dropZoneDragActiveSingleThumbnail,
114
+ openFileDialog: fileuploadStrings.dropZoneOpenFileDialogSingleThumbnail,
114
115
  }
115
116
  : this.multiple
116
117
  ? {
117
- dragInactive: defaultFileUploadStrings.dropZoneDragMultiple,
118
- dragActive: defaultFileUploadStrings.dropZoneDragActiveMultiple,
119
- openFileDialog: defaultFileUploadStrings.dropZoneOpenFileDialogMultiple,
118
+ dragInactive: fileuploadStrings.dropZoneDragMultiple,
119
+ dragActive: fileuploadStrings.dropZoneDragActiveMultiple,
120
+ openFileDialog: fileuploadStrings.dropZoneOpenFileDialogMultiple,
120
121
  }
121
122
  : {
122
- dragInactive: defaultFileUploadStrings.dropZoneDragSingle,
123
- dragActive: defaultFileUploadStrings.dropZoneDragActiveSingle,
124
- openFileDialog: defaultFileUploadStrings.dropZoneOpenFileDialogSingle,
123
+ dragInactive: fileuploadStrings.dropZoneDragSingle,
124
+ dragActive: fileuploadStrings.dropZoneDragActiveSingle,
125
+ openFileDialog: fileuploadStrings.dropZoneOpenFileDialogSingle,
125
126
  }
126
127
 
127
128
  return html`
@@ -194,7 +195,7 @@ export class PktFileUpload extends PktFileUploadBase implements IPktFileUpload {
194
195
  </p>
195
196
  ${supportedFormatsText
196
197
  ? html`<p class="pkt-fileupload__drop-zone__placeholder__formats">
197
- ${defaultFileUploadStrings.supportedFormatsPrefix} ${supportedFormatsText}
198
+ ${fileuploadStrings.supportedFormatsPrefix} ${supportedFormatsText}
198
199
  </p>`
199
200
  : null}
200
201
  </div>
@@ -351,13 +352,16 @@ export class PktFileUpload extends PktFileUploadBase implements IPktFileUpload {
351
352
 
352
353
  private renderPreviewModal(previewableImages: IFileAndTransfer[]) {
353
354
  if (!this.enableImagePreview || previewableImages.length === 0) return null
355
+ const fileuploadStrings = this.pktStrings.get('fileupload')
354
356
  const currentImage = previewableImages[this.previewCurrentIndex]
355
357
  if (!currentImage) return null
356
358
  const hasMultipleImages = previewableImages.length > 1
357
359
  const imageUrl = this.getThumbnailUrl(currentImage)
358
360
  const hasImage = !!imageUrl && !this.failedImageFileIds[currentImage.fileId]?.preview
359
361
  const filename =
360
- currentImage.attributes?.targetFilename || currentImage.file?.name || 'Forhåndsvisning'
362
+ currentImage.attributes?.targetFilename ||
363
+ currentImage.file?.name ||
364
+ fileuploadStrings.previewFallbackName
361
365
 
362
366
  return html`
363
367
  <pkt-modal
@@ -428,7 +428,7 @@ export class PktHeaderGlobal extends PktElement<IPktHeaderGlobal> implements IPk
428
428
  }
429
429
 
430
430
  private renderMenuToggle(localeData?: IHeaderFooterLocaleData) {
431
- const menuText = localeData?.i18n?.menu || 'Meny'
431
+ const menuText = localeData?.i18n?.menu || this.pktStrings.get('header').menu
432
432
  const isOpen = this.openMenu === 'menu'
433
433
  return html`
434
434
  <pkt-button
@@ -466,7 +466,7 @@ export class PktHeaderGlobal extends PktElement<IPktHeaderGlobal> implements IPk
466
466
  aria-controls=${SEARCH_PANEL_ID}
467
467
  @click=${() => this.toggleMenu('search')}
468
468
  >
469
- ${localeData.i18n?.search || 'Søk'}
469
+ ${localeData.i18n?.search || this.pktStrings.get('header').search}
470
470
  </pkt-button>
471
471
  `
472
472
  }
@@ -489,7 +489,7 @@ export class PktHeaderGlobal extends PktElement<IPktHeaderGlobal> implements IPk
489
489
  id=${search.input.id || 'pkt-header-global-search'}
490
490
  name=${ifDefined(search.input.name)}
491
491
  placeholder=${ifDefined(placeholder)}
492
- aria-label=${ifDefined(localeData.i18n?.search || 'Søk')}
492
+ aria-label=${ifDefined(localeData.i18n?.search || this.pktStrings.get('header').search)}
493
493
  action=${search.endpoint}
494
494
  method="get"
495
495
  @pkt-search=${(e: CustomEvent<{ value: string }>) => this.handleSearch(e.detail.value)}
@@ -40,7 +40,8 @@ export class PktHeaderService extends PktElementWithSlot<IPktHeader> implements
40
40
  @property({ type: String, attribute: 'logo-link' }) logoLink: string = DEFAULT_HEADER_LOGO_LINK
41
41
  @property({ type: String, attribute: 'logo-path' }) logoPath: string | undefined =
42
42
  typeof window !== 'undefined' ? window.pktLogoPath : defaultLogoPath
43
- @property({ type: String, attribute: 'search-placeholder' }) searchPlaceholder = 'Søk'
43
+ /** @deprecated Bruk `strings={{ header: { search: '' } }}` eller `setPktStrings()`. */
44
+ @property({ type: String, attribute: 'search-placeholder' }) searchPlaceholder?: string
44
45
  @property({ type: String, attribute: 'search-value' }) searchValue = ''
45
46
  @property({ type: Number, attribute: 'mobile-breakpoint' }) mobileBreakpoint: number = 768
46
47
  @property({ type: Number, attribute: 'tablet-breakpoint' }) tabletBreakpoint: number = 1280
@@ -333,6 +334,10 @@ export class PktHeaderService extends PktElementWithSlot<IPktHeader> implements
333
334
  )
334
335
  }
335
336
 
337
+ private get headerStrings() {
338
+ return this.pktStrings.get('header')
339
+ }
340
+
336
341
  private renderLogo() {
337
342
  if (this.hideLogo) return nothing
338
343
 
@@ -422,7 +427,7 @@ export class PktHeaderService extends PktElementWithSlot<IPktHeader> implements
422
427
  @click=${() => this.handleMenuToggle('slot')}
423
428
  aria-expanded=${this.openMenu === 'slot'}
424
429
  aria-controls="mobile-slot-menu"
425
- aria-label="Åpne meny"
430
+ aria-label=${this.headerStrings.openMenu}
426
431
  >
427
432
  ${this.slotMenuText}
428
433
  </pkt-button>
@@ -472,9 +477,9 @@ export class PktHeaderService extends PktElementWithSlot<IPktHeader> implements
472
477
  state=${this.openMenu === 'search' ? 'active' : 'normal'}
473
478
  aria-expanded=${this.openMenu === 'search'}
474
479
  aria-controls="mobile-search-menu"
475
- aria-label="Åpne søkefelt"
480
+ aria-label=${this.headerStrings.openSearch}
476
481
  >
477
- Søk
482
+ ${this.headerStrings.search}
478
483
  </pkt-button>
479
484
  <div class=${searchMenuClasses} ${ref(this.searchMenuRef)}>
480
485
  ${this.openMenu === 'search'
@@ -483,9 +488,9 @@ export class PktHeaderService extends PktElementWithSlot<IPktHeader> implements
483
488
  id="mobile-search-menu"
484
489
  class="pkt-header-service__search-input"
485
490
  type="search"
486
- label="Søk"
491
+ label=${this.headerStrings.search}
487
492
  useWrapper="false"
488
- placeholder=${this.searchPlaceholder}
493
+ placeholder=${this.searchPlaceholder ?? this.headerStrings.search}
489
494
  value=${this.searchValue}
490
495
  autofocus
491
496
  fullwidth
@@ -508,9 +513,9 @@ export class PktHeaderService extends PktElementWithSlot<IPktHeader> implements
508
513
  id="header-service-search"
509
514
  class="pkt-header-service__search-input"
510
515
  type="search"
511
- label="Søk"
516
+ label=${this.headerStrings.search}
512
517
  useWrapper="false"
513
- placeholder=${this.searchPlaceholder}
518
+ placeholder=${this.searchPlaceholder ?? this.headerStrings.search}
514
519
  value=${this.searchValue}
515
520
  @input=${this.handleSearchInputChange}
516
521
  @keydown=${this.handleSearchKeyDown}
@@ -44,7 +44,8 @@ export class PktHeader extends PktElementWithSlot<IPktHeader> implements IPktHea
44
44
  @property({ type: String, attribute: 'service-link' }) serviceLink?: string
45
45
  @property({ type: String, attribute: 'logo-link' }) logoLink?: string
46
46
  @property({ type: String, attribute: 'logo-path' }) logoPath?: string
47
- @property({ type: String, attribute: 'search-placeholder' }) searchPlaceholder = 'Søk'
47
+ /** @deprecated Bruk `strings={{ header: { search: '' } }}` eller `setPktStrings()`. */
48
+ @property({ type: String, attribute: 'search-placeholder' }) searchPlaceholder?: string
48
49
  @property({ type: String, attribute: 'search-value' }) searchValue = ''
49
50
  @property({ type: Number, attribute: 'mobile-breakpoint' }) mobileBreakpoint: number = 768
50
51
  @property({ type: Number, attribute: 'tablet-breakpoint' }) tabletBreakpoint: number = 1280
@@ -103,7 +103,7 @@ describe('PktHelptext', () => {
103
103
  expect(helptext.forId).toBeTruthy() // Should have a generated ID
104
104
  expect(helptext.helptext).toBe('')
105
105
  expect(helptext.helptextDropdown).toBe('')
106
- expect(helptext.helptextDropdownButton).toBeTruthy() // Should have default from specs
106
+ expect(helptext.helptextDropdownButton).toBeUndefined()
107
107
  expect(helptext.isHelpTextOpen).toBe(false)
108
108
  })
109
109
 
@@ -4,7 +4,6 @@ import { unsafeHTML } from 'lit/directives/unsafe-html.js'
4
4
  import { classMap } from 'lit/directives/class-map.js'
5
5
  import { customElement, property, state } from 'lit/decorators.js'
6
6
  import { uuidish } from 'shared-utils/utils'
7
- import specs from 'componentSpecs/input-wrapper.json'
8
7
  import '@/components/icon'
9
8
  import { slotContent } from '@/directives/slot-content'
10
9
 
@@ -18,8 +17,9 @@ export class PktHelptext extends PktElementWithSlot {
18
17
  @property({ type: String })
19
18
  helptextDropdown: string = ''
20
19
 
20
+ /** @deprecated Bruk `strings={{ forms: { readMore: '…' } }}` eller `setPktStrings()`. */
21
21
  @property({ type: String })
22
- helptextDropdownButton: string = specs.props.helptextDropdownButton.default
22
+ helptextDropdownButton?: string
23
23
 
24
24
  @state() isHelpTextOpen: boolean = false
25
25
 
@@ -55,7 +55,7 @@ export class PktHelptext extends PktElementWithSlot {
55
55
  class="pkt-btn__icon"
56
56
  name="${this.isHelpTextOpen ? 'chevron-thin-up' : 'chevron-thin-down'}"
57
57
  ></pkt-icon>
58
- <span class="pkt-btn__text">${unsafeHTML(this.helptextDropdownButton)}</span>
58
+ <span class="pkt-btn__text">${unsafeHTML(this.helptextDropdownButton ?? this.pktStrings.get('forms').readMore)}</span>
59
59
  </button>
60
60
  <div
61
61
  id="${this.forId}-helptext-expandable"
@@ -132,3 +132,12 @@ export type {
132
132
  TPktSearchInputAppearance,
133
133
  TPktSearchInputMethod,
134
134
  } from '@/components/searchinput'
135
+
136
+ export {
137
+ getPktStrings,
138
+ nb as pktStringsNb,
139
+ resetPktStrings,
140
+ setPktStrings,
141
+ subscribePktStrings,
142
+ } from 'shared-strings'
143
+ export type { TPktStrings, TPktStringsNamespace, TPktStringsOverride } from 'shared-strings'
@@ -1,7 +1,7 @@
1
1
  import { PktElementWithSlot } from '@/base-elements/element-with-slot'
2
2
  import { slotContent } from '@/directives/slot-content'
3
3
  import { counterStatusId, isCounterExceeded } from 'shared-utils/forms/described-by'
4
- import strings from '@/translations/no.json'
4
+ import { formatString } from 'shared-strings'
5
5
  import { ifDefined } from 'lit/directives/if-defined.js'
6
6
  import { html, nothing, PropertyValues } from 'lit'
7
7
  import { unsafeHTML } from 'lit/directives/unsafe-html.js'
@@ -58,9 +58,11 @@ export class PktInputWrapper extends PktElementWithSlot<Props> {
58
58
  @property({ type: String }) counterError: string | null = null
59
59
  @property({ type: String, reflect: false }) counterPosition: TCounterPosition = 'bottom'
60
60
  @property({ type: Boolean }) optionalTag: boolean = specs.props.optionalTag.default
61
- @property({ type: String }) optionalText: string = specs.props.optionalText.default
61
+ /** @deprecated Bruk `strings={{ forms: { optional: '…' } }}` eller `setPktStrings()`. */
62
+ @property({ type: String }) optionalText?: string
62
63
  @property({ type: Boolean }) requiredTag: boolean = specs.props.requiredTag.default
63
- @property({ type: String }) requiredText: string = specs.props.requiredText.default
64
+ /** @deprecated Bruk `strings={{ forms: { required: '…' } }}` eller `setPktStrings()`. */
65
+ @property({ type: String }) requiredText?: string
64
66
  @property({ type: String }) tagText: string | null = null
65
67
  @property({ type: Boolean }) hasError: boolean = specs.props.hasError.default
66
68
  @property({ type: String }) errorMessage: string = ''
@@ -102,16 +104,22 @@ export class PktInputWrapper extends PktElementWithSlot<Props> {
102
104
  ? `${this.forId}-helptext`
103
105
  : nothing
104
106
 
107
+ const formStrings = this.pktStrings.get('forms')
108
+
105
109
  const tagElement = () => {
106
110
  return html`
107
111
  ${this.tagText
108
112
  ? html`<span class=${tagClasses + ' pkt-tag--gray'}>${this.tagText}</span>`
109
113
  : nothing}
110
114
  ${this.optionalTag
111
- ? html`<span class=${tagClasses + ' pkt-tag--blue-light'}>${this.optionalText}</span>`
115
+ ? html`<span class=${tagClasses + ' pkt-tag--blue-light'}
116
+ >${this.optionalText ?? formStrings.optional}</span
117
+ >`
112
118
  : nothing}
113
119
  ${this.requiredTag
114
- ? html`<span class=${tagClasses + ' pkt-tag--beige'}>${this.requiredText}</span>`
120
+ ? html`<span class=${tagClasses + ' pkt-tag--beige'}
121
+ >${this.requiredText ?? formStrings.required}</span
122
+ >`
115
123
  : nothing}
116
124
  `
117
125
  }
@@ -149,8 +157,7 @@ export class PktInputWrapper extends PktElementWithSlot<Props> {
149
157
  .forId=${this.forId}
150
158
  .helptext=${this.helptext}
151
159
  .helptextDropdown=${this.helptextDropdown}
152
- .helptextDropdownButton=${this.helptextDropdownButton ||
153
- specs.props.helptextDropdownButton.default}
160
+ .helptextDropdownButton=${this.helptextDropdownButton ?? formStrings.readMore}
154
161
  @toggleHelpText=${(e: CustomEvent) => {
155
162
  this.toggleDropdown(e)
156
163
  }}
@@ -170,9 +177,10 @@ export class PktInputWrapper extends PktElementWithSlot<Props> {
170
177
  </div>
171
178
  <div class="pkt-sr-only" id=${counterStatusId(this.forId)} aria-live="polite">
172
179
  ${exceeded
173
- ? strings.forms.messages.counterExceeded
174
- .replace('{current}', String(this.counterCurrent ?? 0))
175
- .replace('{max}', String(this.counterMaxLength))
180
+ ? formatString(this.pktStrings.get('validation').counterExceeded, {
181
+ current: this.counterCurrent ?? 0,
182
+ max: this.counterMaxLength,
183
+ })
176
184
  : ''}
177
185
  </div>`
178
186
  }
@@ -1,7 +1,6 @@
1
1
  import { html, nothing, PropertyValues } from 'lit'
2
2
  import { customElement, property, state } from 'lit/decorators.js'
3
3
  import { ifDefined } from 'lit/directives/if-defined.js'
4
- import strings from '@/translations/no.json'
5
4
  import { PktElement } from '@/base-elements/element'
6
5
  import { repeat } from 'lit/directives/repeat.js'
7
6
  import { classMap } from 'lit/directives/class-map.js'
@@ -263,6 +262,7 @@ export class PktListbox extends PktElement implements IPktListbox {
263
262
  }
264
263
 
265
264
  private renderSearch() {
265
+ const listboxStrings = this.pktStrings.get('listbox')
266
266
  return this.includeSearch
267
267
  ? html`
268
268
  <div class="pkt-listbox__search">
@@ -272,9 +272,9 @@ export class PktListbox extends PktElement implements IPktListbox {
272
272
  <input
273
273
  class="pkt-txt-16-light"
274
274
  type="text"
275
- aria-label="Søk i listen"
275
+ aria-label=${listboxStrings.searchLabel}
276
276
  form=""
277
- placeholder=${this.searchPlaceholder || strings.forms.search.placeholder}
277
+ placeholder=${this.searchPlaceholder ?? listboxStrings.searchPlaceholder}
278
278
  @input=${this.handleSearchInput}
279
279
  @keydown=${this.handleSearchKeydown}
280
280
  .value=${this.searchValue}
@@ -29,9 +29,11 @@ export class PktRadioButton extends PktInputElement<Props> {
29
29
  @property({ type: String, reflect: true }) type: string = 'radio'
30
30
  @property({ type: String }) tagText: string | null = null
31
31
  @property({ type: Boolean }) optionalTag: boolean = false
32
- @property({ type: String }) optionalText: string = 'Valgfritt'
32
+ /** @deprecated Bruk `strings={{ forms: { optional: '…' } }}` eller `setPktStrings()`. */
33
+ @property({ type: String }) optionalText?: string
33
34
  @property({ type: Boolean }) requiredTag: boolean = false
34
- @property({ type: String }) requiredText: string = 'Må fylles ut'
35
+ /** @deprecated Bruk `strings={{ forms: { required: '…' } }}` eller `setPktStrings()`. */
36
+ @property({ type: String }) requiredText?: string
35
37
 
36
38
  @state() _checked: boolean = false
37
39
 
@@ -69,16 +71,18 @@ export class PktRadioButton extends PktInputElement<Props> {
69
71
 
70
72
  const tagClasses = 'pkt-tag pkt-tag--small pkt-tag--thin-text'
71
73
 
74
+ const formStrings = this.pktStrings.get('forms')
75
+
72
76
  const tags = () => {
73
77
  return html`
74
78
  ${this.tagText
75
79
  ? html`<span class=${tagClasses + ' pkt-tag--gray'}>${this.tagText}</span>`
76
80
  : nothing}
77
81
  ${this.optionalTag
78
- ? html`<span class=${tagClasses + ' pkt-tag--blue-light'}>${this.optionalText}</span>`
82
+ ? html`<span class=${tagClasses + ' pkt-tag--blue-light'}>${this.optionalText ?? formStrings.optional}</span>`
79
83
  : nothing}
80
84
  ${this.requiredTag
81
- ? html`<span class=${tagClasses + ' pkt-tag--beige'}>${this.requiredText}</span>`
85
+ ? html`<span class=${tagClasses + ' pkt-tag--beige'}>${this.requiredText ?? formStrings.required}</span>`
82
86
  : nothing}
83
87
  `
84
88
  }
@@ -30,7 +30,8 @@ export class PktSearchInput extends PktElement<IPktSearchInput> implements IPktS
30
30
  @property({ type: String, reflect: true }) id: string = ''
31
31
  @property({ type: String }) label: string | undefined
32
32
  @property({ type: String }) name: string | undefined
33
- @property({ type: String }) placeholder: string = 'Søk…'
33
+ /** @deprecated Bruk `strings={{ searchinput: { placeholder: '…' } }}` eller `setPktStrings()`. */
34
+ @property({ type: String }) placeholder?: string
34
35
  @property({ type: String }) value: string = ''
35
36
  @property({ type: Array }) suggestions: IPktSearchInputSuggestion[] | undefined
36
37
  @property({ type: String }) action: string | undefined
@@ -135,6 +136,7 @@ export class PktSearchInput extends PktElement<IPktSearchInput> implements IPktS
135
136
  }
136
137
 
137
138
  render() {
139
+ const searchStrings = this.pktStrings.get('searchinput')
138
140
  const wrapperClasses = classMap({
139
141
  'pkt-searchinput': true,
140
142
  [`pkt-searchinput--${this.appearance}`]: true,
@@ -173,7 +175,7 @@ export class PktSearchInput extends PktElement<IPktSearchInput> implements IPktS
173
175
  type="search"
174
176
  name=${this.name || this.id}
175
177
  id=${this.id}
176
- placeholder=${this.placeholder || 'Søk…'}
178
+ placeholder=${this.placeholder || searchStrings.placeholder}
177
179
  .value=${this.value}
178
180
  ?disabled=${this.disabled}
179
181
  autocomplete="off"
@@ -190,7 +192,7 @@ export class PktSearchInput extends PktElement<IPktSearchInput> implements IPktS
190
192
  @click=${this.onSearchClick}
191
193
  >
192
194
  <pkt-icon class="pkt-btn__icon" name="magnifying-glass-big"></pkt-icon>
193
- <span class="pkt-btn__text">${this.label || this.placeholder || 'Søk…'}</span>
195
+ <span class="pkt-btn__text">${this.label || this.placeholder || searchStrings.placeholder}</span>
194
196
  </button>
195
197
  </div>
196
198
  ${this.suggestions
@@ -182,6 +182,7 @@ export class PktSelect extends PktOptionsInputElement<{}, TSelectOption> impleme
182
182
 
183
183
  return html`
184
184
  <pkt-input-wrapper
185
+ .strings=${this.strings}
185
186
  .size=${this.inputSize}
186
187
  ?disabled=${this.disabled}
187
188
  ?hasError=${this.hasError}
@@ -10,6 +10,7 @@ import '@/components/icon'
10
10
  import type { IAriaAttributes, THTMLButtonType } from 'shared-types'
11
11
  import { PktIconName } from '@oslokommune/punkt-assets/dist/icons/icon'
12
12
  import { ifDefined } from 'lit/directives/if-defined.js'
13
+ import { formatString } from 'shared-strings'
13
14
 
14
15
  export type TTagSkin =
15
16
  | 'blue'
@@ -68,7 +69,7 @@ export class PktTag extends PktElementWithSlot<IPktTag> implements IPktTag {
68
69
  if (this.closeTag && !this.ariaLabel) {
69
70
  const label = this.querySelector('button span, .pkt-tag > span')?.textContent?.trim()
70
71
  if (label) {
71
- this._ariaDescription = `Klikk for å fjerne ${label}`
72
+ this._ariaDescription = formatString(this.pktStrings.get('tag').remove, { label })
72
73
  }
73
74
  }
74
75
  }
@@ -55,6 +55,7 @@ export class PktTextarea extends PktInputElement<Props> {
55
55
  const labelledBy = this.ariaLabelledby || `${this.id}-input-label`
56
56
 
57
57
  return html`<pkt-input-wrapper
58
+ .strings=${this.strings}
58
59
  label=${this.label}
59
60
  ?counter=${showCounter}
60
61
  ?hasFieldset=${this.effectiveHasFieldset(false)}
@@ -71,6 +71,7 @@ export class PktTextinput extends PktInputElement<Props> {
71
71
 
72
72
  return html`
73
73
  <pkt-input-wrapper
74
+ .strings=${this.strings}
74
75
  label="${this.label}"
75
76
  ?counter=${showCounter}
76
77
  ?hasFieldset=${this.effectiveHasFieldset(false)}
@@ -6,7 +6,7 @@ import { classMap } from 'lit/directives/class-map.js'
6
6
  import { PktInputElement } from '@/base-elements/input-element'
7
7
  import { slotContent } from '@/directives/slot-content'
8
8
  import { ElementProps } from '@/types/typeUtils'
9
- import strings from '@/translations/no.json'
9
+ import { formatString } from 'shared-strings'
10
10
  import { isValidTimeString, timeToMinutes } from 'shared-utils/timepicker/time-utils'
11
11
  import { getMinuteStep, getHourOptions, getMinuteOptions } from 'shared-utils/timepicker/options'
12
12
  import { stepTime } from 'shared-utils/timepicker/stepper'
@@ -71,8 +71,10 @@ export class PktTimepicker extends PktInputElement<Props> {
71
71
  const anchor = this.hoursInputRef.value
72
72
  if (!anchor) return
73
73
 
74
+ const messages = this.pktStrings.get('validation')
75
+
74
76
  if (this.required && !this.value) {
75
- this.internals.setValidity({ valueMissing: true }, strings.forms.messages.required, anchor)
77
+ this.internals.setValidity({ valueMissing: true }, messages.valueMissing, anchor)
76
78
  this._setAriaInvalid(true)
77
79
  return
78
80
  }
@@ -89,7 +91,7 @@ export class PktTimepicker extends PktInputElement<Props> {
89
91
  if (this.min && totalMinutes < timeToMinutes(String(this.min))) {
90
92
  this.internals.setValidity(
91
93
  { rangeUnderflow: true },
92
- strings.forms.messages.rangeUnderflowMin.replace('{min}', String(this.min)),
94
+ formatString(messages.rangeUnderflowMin, { min: String(this.min) }),
93
95
  anchor,
94
96
  )
95
97
  this._setAriaInvalid(true)
@@ -99,7 +101,7 @@ export class PktTimepicker extends PktInputElement<Props> {
99
101
  if (this.max && totalMinutes > timeToMinutes(String(this.max))) {
100
102
  this.internals.setValidity(
101
103
  { rangeOverflow: true },
102
- strings.forms.messages.rangeOverflowMax.replace('{max}', String(this.max)),
104
+ formatString(messages.rangeOverflowMax, { max: String(this.max) }),
103
105
  anchor,
104
106
  )
105
107
  this._setAriaInvalid(true)
@@ -109,13 +111,12 @@ export class PktTimepicker extends PktInputElement<Props> {
109
111
  if (this.step && totalMinutes % minuteStep !== 0) {
110
112
  const stepMessage =
111
113
  minuteStep === 60
112
- ? strings.forms.messages.timeStepMismatchHour
114
+ ? messages.timeStepMismatchHour
113
115
  : minuteStep === 30
114
- ? strings.forms.messages.timeStepMismatchHalfHour
115
- : strings.forms.messages.timeStepMismatch.replace(
116
- '{step}',
117
- `${minuteStep}, ${minuteStep * 2}, ${minuteStep * 3}`,
118
- )
116
+ ? messages.timeStepMismatchHalfHour
117
+ : formatString(messages.timeStepMismatch, {
118
+ step: `${minuteStep}, ${minuteStep * 2}, ${minuteStep * 3}`,
119
+ })
119
120
  this.internals.setValidity({ stepMismatch: true }, stepMessage, anchor)
120
121
  this._setAriaInvalid(true)
121
122
  return
@@ -583,7 +584,7 @@ export class PktTimepicker extends PktInputElement<Props> {
583
584
  id=${this.id + '-popup'}
584
585
  ?hidden=${!this._isOpen}
585
586
  role="group"
586
- aria-label=${this.strings.timepicker?.selectTime ?? 'Velg tidspunkt'}
587
+ aria-label=${this.pktStrings.get('timepicker').selectTime}
587
588
  @keydown=${this._handlePopupKeydown}
588
589
  @focusout=${(e: FocusEvent) => {
589
590
  if (!this.querySelector('.pkt-timepicker-popup')?.contains(e.relatedTarget as Node)) {
@@ -594,7 +595,7 @@ export class PktTimepicker extends PktInputElement<Props> {
594
595
  <div
595
596
  class="pkt-timepicker-popup__col"
596
597
  role="listbox"
597
- aria-label=${this.strings.timepicker?.hours ?? 'Timer'}
598
+ aria-label=${this.pktStrings.get('timepicker').hours}
598
599
  aria-orientation="vertical"
599
600
  >
600
601
  ${this._hourOptions.map((h) => this._renderOption(h, 'hour'))}
@@ -602,7 +603,7 @@ export class PktTimepicker extends PktInputElement<Props> {
602
603
  <div
603
604
  class="pkt-timepicker-popup__col"
604
605
  role="listbox"
605
- aria-label=${this.strings.timepicker?.minutes ?? 'Minutter'}
606
+ aria-label=${this.pktStrings.get('timepicker').minutes}
606
607
  aria-orientation="vertical"
607
608
  >
608
609
  ${this._minuteOptions.map((m) => this._renderOption(m, 'minute'))}
@@ -612,8 +613,8 @@ export class PktTimepicker extends PktInputElement<Props> {
612
613
  }
613
614
 
614
615
  private _renderContainer() {
615
- const hoursLabel = this.strings.timepicker?.hours ?? 'Timer'
616
- const minutesLabel = this.strings.timepicker?.minutes ?? 'Minutter'
616
+ const hoursLabel = this.pktStrings.get('timepicker').hours
617
+ const minutesLabel = this.pktStrings.get('timepicker').minutes
617
618
  const hoursAriaLabel = this.label ? `${hoursLabel}, ${this.label}` : hoursLabel
618
619
  const minutesAriaLabel = this.label ? `${minutesLabel}, ${this.label}` : minutesLabel
619
620
  return html`
@@ -631,13 +632,13 @@ export class PktTimepicker extends PktInputElement<Props> {
631
632
  class="pkt-input-icon pkt-btn pkt-btn--icon-only pkt-btn--tertiary pkt-btn--${this
632
633
  .inputSize} pkt-timepicker__button pkt-timepicker__button--prev"
633
634
  type="button"
634
- aria-label=${this.strings.timepicker?.prevTime ?? 'Forrige tidspunkt'}
635
+ aria-label=${this.pktStrings.get('timepicker').prevTime}
635
636
  ?disabled=${this.disabled}
636
637
  @click=${() => this._stepTime(-1)}
637
638
  >
638
639
  <pkt-icon name="chevron-thin-left"></pkt-icon>
639
640
  <span class="pkt-btn__text"
640
- >${this.strings.timepicker?.prevTime ?? 'Forrige tidspunkt'}</span
641
+ >${this.pktStrings.get('timepicker').prevTime}</span
641
642
  >
642
643
  </button>
643
644
  `
@@ -719,7 +720,7 @@ export class PktTimepicker extends PktInputElement<Props> {
719
720
  class="pkt-input-icon pkt-btn pkt-btn--icon-only pkt-btn--tertiary pkt-btn--${this
720
721
  .inputSize} pkt-timepicker__button"
721
722
  type="button"
722
- aria-label=${this.strings.timepicker?.openPicker ?? 'Åpne tidspunkt-velger'}
723
+ aria-label=${this.pktStrings.get('timepicker').openPicker}
723
724
  aria-haspopup="listbox"
724
725
  aria-expanded=${this._isOpen ? 'true' : 'false'}
725
726
  aria-controls=${this.id + '-popup'}
@@ -728,7 +729,7 @@ export class PktTimepicker extends PktInputElement<Props> {
728
729
  >
729
730
  <pkt-icon name="clock"></pkt-icon>
730
731
  <span class="pkt-btn__text"
731
- >${this.strings.timepicker?.openPicker ?? 'Åpne tidspunkt-velger'}</span
732
+ >${this.pktStrings.get('timepicker').openPicker}</span
732
733
  >
733
734
  </button>
734
735
  `
@@ -739,13 +740,13 @@ export class PktTimepicker extends PktInputElement<Props> {
739
740
  class="pkt-input-icon pkt-btn pkt-btn--icon-only pkt-btn--tertiary pkt-btn--${this
740
741
  .inputSize} pkt-timepicker__button pkt-timepicker__button--next"
741
742
  type="button"
742
- aria-label=${this.strings.timepicker?.nextTime ?? 'Neste tidspunkt'}
743
+ aria-label=${this.pktStrings.get('timepicker').nextTime}
743
744
  ?disabled=${this.disabled}
744
745
  @click=${() => this._stepTime(1)}
745
746
  >
746
747
  <pkt-icon name="chevron-thin-right"></pkt-icon>
747
748
  <span class="pkt-btn__text"
748
- >${this.strings.timepicker?.nextTime ?? 'Neste tidspunkt'}</span
749
+ >${this.pktStrings.get('timepicker').nextTime}</span
749
750
  >
750
751
  </button>
751
752
  `
@@ -771,6 +772,7 @@ export class PktTimepicker extends PktInputElement<Props> {
771
772
  render() {
772
773
  return html`
773
774
  <pkt-input-wrapper
775
+ .strings=${this.strings}
774
776
  label="${this.label}"
775
777
  ?disabled=${this.disabled}
776
778
  ?fullwidth=${this.fullwidth}