@oslokommune/punkt-elements 16.26.7 → 17.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/dist/accordion-CbXDxOho.cjs +47 -0
  3. package/dist/{accordion-CBdIk9gw.js → accordion-DEUHQ4JD.js} +45 -35
  4. package/dist/{alert-HHTGY0sp.js → alert-CbtVGrHD.js} +31 -17
  5. package/dist/{alert-B8dLsiTz.cjs → alert-CkUnbPdA.cjs} +5 -5
  6. package/dist/base-elements/input-element.d.ts +1 -0
  7. package/dist/button-Cod17rKo.js +115 -0
  8. package/dist/{button-B5tQpKeG.cjs → button-gvDXtBMC.cjs} +5 -2
  9. package/dist/{calendar-DIzGBdbh.cjs → calendar-BVXW8DqC.cjs} +1 -1
  10. package/dist/{calendar-CjlUA-Lb.js → calendar-CjC4qlh6.js} +1 -1
  11. package/dist/{checkbox-Bt_sC_90.cjs → checkbox-8uxbeU30.cjs} +1 -1
  12. package/dist/{checkbox-D03BC2Va.js → checkbox-DJDphhqz.js} +1 -1
  13. package/dist/{combobox-CoQBTWqL.js → combobox-Du5yr-xM.js} +16 -2
  14. package/dist/combobox-hKrbYLUe.cjs +136 -0
  15. package/dist/components/accordion/accordion-context.d.ts +7 -0
  16. package/dist/components/accordion/accordion.d.ts +2 -0
  17. package/dist/components/accordion/accordionitem.d.ts +1 -0
  18. package/dist/components/alert/alert.d.ts +5 -0
  19. package/dist/components/alert/alert.test.d.ts +1 -0
  20. package/dist/components/button/button.d.ts +4 -1
  21. package/dist/components/datepicker/datepicker-base.d.ts +2 -0
  22. package/dist/components/datepicker/datepicker-utils.d.ts +2 -2
  23. package/dist/components/footer/footer-base.d.ts +44 -0
  24. package/dist/components/footer/footer-simple.d.ts +20 -0
  25. package/dist/components/footer/footer.accessibility.test.d.ts +0 -0
  26. package/dist/components/footer/footer.d.ts +22 -0
  27. package/dist/components/footer/footer.test.d.ts +0 -0
  28. package/dist/components/footer/index.d.ts +3 -0
  29. package/dist/components/footer/types.d.ts +16 -0
  30. package/dist/components/header/header-chrome-controller.d.ts +44 -0
  31. package/dist/components/header/header-global.accessibility.test.d.ts +0 -0
  32. package/dist/components/header/header-global.d.ts +78 -0
  33. package/dist/components/header/header-global.test.d.ts +0 -0
  34. package/dist/components/header/header-service.accessibility.test.d.ts +0 -0
  35. package/dist/components/header/header-service.d.ts +6 -21
  36. package/dist/components/header/header-service.test.d.ts +1 -1
  37. package/dist/components/header/header.d.ts +11 -3
  38. package/dist/components/header/header.test.d.ts +0 -0
  39. package/dist/components/header/index.d.ts +2 -1
  40. package/dist/components/header/types.d.ts +28 -2
  41. package/dist/components/header-menu/header-menu.d.ts +4 -5
  42. package/dist/components/header-menu/types.d.ts +1 -1
  43. package/dist/components/index.d.ts +5 -3
  44. package/dist/components/input-wrapper/input-wrapper.d.ts +2 -0
  45. package/dist/components/input-wrapper/input-wrapper.test.d.ts +1 -0
  46. package/dist/components/searchinput/searchinput.d.ts +5 -0
  47. package/dist/components/select/index.d.ts +1 -1
  48. package/dist/components/select/select.d.ts +2 -2
  49. package/dist/components/select/select.test.d.ts +1 -0
  50. package/dist/components/textarea/textarea.test.d.ts +2 -0
  51. package/dist/components/textinput/textinput.test.d.ts +1 -0
  52. package/dist/components/timepicker/timepicker.d.ts +2 -0
  53. package/dist/components/timepicker/timepicker.test.d.ts +3 -0
  54. package/dist/consent--Nw43WFU.cjs +18 -0
  55. package/dist/{consent-D5sY6JK3.js → consent-B2hSTCGC.js} +14 -7
  56. package/dist/consume-BiOhrhEy.js +167 -0
  57. package/dist/consume-DKf5SmP9.cjs +1 -0
  58. package/dist/{converters-BKGBRBpS.js → converters-BBfsEJV5.js} +25 -25
  59. package/dist/{converters-9jHlXDyy.cjs → converters-Cd0fPEly.cjs} +1 -1
  60. package/dist/{datepicker-BE5Ll0W4.js → datepicker--Fq8q-J3.js} +30 -12
  61. package/dist/{datepicker-x4xM3KQz.cjs → datepicker-CEoBYTBU.cjs} +11 -7
  62. package/dist/docs/components/alert.d.ts +3 -0
  63. package/dist/docs/components/footer.d.ts +9 -0
  64. package/dist/docs/components/form-sizes.d.ts +10 -0
  65. package/dist/docs/components/header-global-full.d.ts +20 -0
  66. package/dist/docs/components/header-global.d.ts +14 -0
  67. package/dist/docs/components/searchinput.d.ts +6 -3
  68. package/dist/fetch-header-footer-data-Pc32etrk.js +88 -0
  69. package/dist/fetch-header-footer-data-xohWFmYC.cjs +1 -0
  70. package/dist/fileupload-CGKUJrlj.cjs +401 -0
  71. package/dist/{fileupload-2hf8YNhO.js → fileupload-D4gQN64T.js} +156 -176
  72. package/dist/focus-trap-DG3pEuyJ.js +60 -0
  73. package/dist/focus-trap-DSv4Ifqm.cjs +1 -0
  74. package/dist/footer-BIrJeRuZ.js +303 -0
  75. package/dist/footer-Ber-jqM1.cjs +114 -0
  76. package/dist/footer.d.ts +1 -0
  77. package/dist/header-BFk1an4z.cjs +465 -0
  78. package/dist/header-Deg_LGJo.js +1287 -0
  79. package/dist/header-menu-BHqK4QA6.cjs +126 -0
  80. package/dist/{header-menu-C8b5vd3n.js → header-menu-GFtJKM4j.js} +25 -97
  81. package/dist/{helptext-OfqH5npD.js → helptext-C_brWCIT.js} +1 -1
  82. package/dist/{helptext-eckq4JEX.cjs → helptext-Cq5rNaAC.cjs} +1 -1
  83. package/dist/{input-element-ZGOWsvKM.cjs → input-element-B0qLbEdF.cjs} +1 -1
  84. package/dist/{input-element-BFHpeoV8.js → input-element-C0RnXi-J.js} +5 -2
  85. package/dist/{input-wrapper-DwwE0JcO.js → input-wrapper-BweP6t3O.js} +12 -0
  86. package/dist/{input-wrapper-BRjQB4zM.cjs → input-wrapper-DPkkiG7S.cjs} +13 -11
  87. package/dist/{input-wrapper-DaA98B5l.js → input-wrapper-fWV5P4MN.js} +22 -15
  88. package/dist/{input-wrapper-LcZjpt0L.cjs → input-wrapper-wh3fWIhk.cjs} +1 -1
  89. package/dist/modal-CPnFteYS.cjs +35 -0
  90. package/dist/{modal-C6pScpdG.js → modal-xNK_wpHk.js} +11 -20
  91. package/dist/pkt-accordion.cjs +1 -1
  92. package/dist/pkt-accordion.js +1 -1
  93. package/dist/pkt-alert.cjs +1 -1
  94. package/dist/pkt-alert.js +1 -1
  95. package/dist/pkt-button.cjs +1 -1
  96. package/dist/pkt-button.js +1 -1
  97. package/dist/pkt-calendar.cjs +1 -1
  98. package/dist/pkt-calendar.js +1 -1
  99. package/dist/pkt-checkbox.cjs +1 -1
  100. package/dist/pkt-checkbox.js +1 -1
  101. package/dist/pkt-combobox.cjs +1 -1
  102. package/dist/pkt-combobox.js +1 -1
  103. package/dist/pkt-consent.cjs +1 -1
  104. package/dist/pkt-consent.js +1 -1
  105. package/dist/pkt-datepicker.cjs +1 -1
  106. package/dist/pkt-datepicker.js +1 -1
  107. package/dist/pkt-fileupload.cjs +1 -1
  108. package/dist/pkt-fileupload.js +1 -1
  109. package/dist/pkt-footer.cjs +1 -0
  110. package/dist/pkt-footer.js +2 -0
  111. package/dist/pkt-header-menu.cjs +1 -1
  112. package/dist/pkt-header-menu.js +1 -1
  113. package/dist/pkt-header.cjs +1 -1
  114. package/dist/pkt-header.js +2 -2
  115. package/dist/pkt-helptext.cjs +1 -1
  116. package/dist/pkt-helptext.js +1 -1
  117. package/dist/pkt-index.cjs +1 -1
  118. package/dist/pkt-index.js +27 -26
  119. package/dist/pkt-input-wrapper.cjs +1 -1
  120. package/dist/pkt-input-wrapper.js +1 -1
  121. package/dist/pkt-modal.cjs +1 -1
  122. package/dist/pkt-modal.js +1 -1
  123. package/dist/pkt-radiobutton.cjs +1 -1
  124. package/dist/pkt-radiobutton.js +1 -1
  125. package/dist/pkt-searchinput.cjs +1 -1
  126. package/dist/pkt-searchinput.js +1 -1
  127. package/dist/pkt-select.cjs +1 -1
  128. package/dist/pkt-select.js +1 -1
  129. package/dist/pkt-tabs.cjs +1 -1
  130. package/dist/pkt-tabs.js +1 -1
  131. package/dist/pkt-textarea.cjs +1 -1
  132. package/dist/pkt-textarea.js +1 -1
  133. package/dist/pkt-textinput.cjs +1 -1
  134. package/dist/pkt-textinput.js +1 -1
  135. package/dist/pkt-timepicker.cjs +1 -1
  136. package/dist/pkt-timepicker.js +1 -1
  137. package/dist/{radiobutton-DGO6H2Ki.js → radiobutton-C6htwDrT.js} +1 -1
  138. package/dist/{radiobutton-DY1WWepJ.cjs → radiobutton-DjWBoSHv.cjs} +1 -1
  139. package/dist/scroll-lock-BN8lOhV5.cjs +1 -0
  140. package/dist/scroll-lock-DAbNKAUy.js +18 -0
  141. package/dist/searchinput-CfUVfpqL.js +156 -0
  142. package/dist/searchinput-DGjeN1YI.cjs +60 -0
  143. package/dist/{select-D4_HQFkh.cjs → select-CZvAW7W2.cjs} +2 -1
  144. package/dist/{select-BwHUIlwQ.js → select-CsBXXbLP.js} +4 -3
  145. package/dist/setupTests.d.ts +0 -0
  146. package/dist/shared-types/footer.d.ts +95 -0
  147. package/dist/shared-types/{header-menu.d.ts → header-footer.d.ts} +51 -4
  148. package/dist/shared-types/header.d.ts +1 -1
  149. package/dist/shared-types/index.d.ts +6 -4
  150. package/dist/shared-types/searchinput.d.ts +2 -0
  151. package/dist/shared-types/select.d.ts +3 -2
  152. package/dist/shared-types/size.d.ts +4 -0
  153. package/dist/shared-types/timepicker.d.ts +0 -6
  154. package/dist/shared-utils/datepicker-utils.d.ts +5 -4
  155. package/dist/shared-utils/fileupload/focus-trap.d.ts +4 -10
  156. package/dist/shared-utils/focus-trap/index.d.ts +22 -0
  157. package/dist/shared-utils/{header-menu → header-footer}/example-data.d.ts +5 -4
  158. package/dist/shared-utils/header-footer/external-domain.d.ts +26 -0
  159. package/dist/shared-utils/{header-menu → header-footer}/fetch-header-footer-data.d.ts +6 -2
  160. package/dist/shared-utils/{header-menu → header-footer}/index.d.ts +2 -1
  161. package/dist/shared-utils/{header-menu → header-footer}/select-megamenu.d.ts +1 -1
  162. package/dist/shared-utils/scroll-lock/index.d.ts +24 -0
  163. package/dist/tabs-BqrKLCjd.js +214 -0
  164. package/dist/tabs-q62MK_-r.cjs +40 -0
  165. package/dist/{textarea-D6M7ZhtA.js → textarea-Cm392CEI.js} +5 -3
  166. package/dist/{textarea-Bt_Zs8gq.cjs → textarea-sTcZxOIB.cjs} +3 -2
  167. package/dist/{textinput-EDKjcUdg.cjs → textinput-DqJbTglM.cjs} +3 -2
  168. package/dist/{textinput-oU2EvFsi.js → textinput-TSPcBcih.js} +5 -3
  169. package/dist/{timepicker-CgOL2sd9.cjs → timepicker-CqFYMV8q.cjs} +8 -7
  170. package/dist/{timepicker-_G0V_HV3.js → timepicker-DWbgTDKq.js} +10 -9
  171. package/package.json +3 -3
  172. package/src/components/accordion/accordion-context.ts +8 -0
  173. package/src/components/accordion/accordion.test.ts +44 -0
  174. package/src/components/accordion/accordion.ts +13 -3
  175. package/src/components/accordion/accordionitem.ts +9 -1
  176. package/src/components/alert/alert.test.ts +51 -2
  177. package/src/components/alert/alert.ts +11 -5
  178. package/src/components/breadcrumbs/breadcrumbs.test.ts +11 -3
  179. package/src/components/button/button.test.ts +23 -0
  180. package/src/components/button/button.ts +28 -3
  181. package/src/components/combobox/combobox.core.test.ts +20 -0
  182. package/src/components/combobox/combobox.ts +2 -0
  183. package/src/components/consent/consent.test.ts +6 -3
  184. package/src/components/consent/consent.ts +15 -7
  185. package/src/components/datepicker/datepicker-base.ts +5 -1
  186. package/src/components/datepicker/datepicker-utils.test.ts +10 -0
  187. package/src/components/datepicker/datepicker.core.test.ts +17 -0
  188. package/src/components/datepicker/datepicker.ts +8 -0
  189. package/src/components/footer/footer-base.ts +238 -0
  190. package/src/components/footer/footer-simple.ts +71 -0
  191. package/src/components/footer/footer.accessibility.test.ts +66 -0
  192. package/src/components/footer/footer.test.ts +238 -0
  193. package/src/components/footer/footer.ts +81 -0
  194. package/src/components/footer/index.ts +4 -0
  195. package/src/components/footer/types.ts +21 -0
  196. package/src/components/header/header-chrome-controller.ts +123 -0
  197. package/src/components/header/header-global.accessibility.test.ts +110 -0
  198. package/src/components/header/header-global.test.ts +329 -0
  199. package/src/components/header/header-global.ts +648 -0
  200. package/src/components/header/header-service.accessibility.test.ts +79 -0
  201. package/src/components/header/header-service.test.ts +32 -12
  202. package/src/components/header/header-service.ts +38 -162
  203. package/src/components/header/header-user-menu.ts +0 -1
  204. package/src/components/header/header.test.ts +84 -0
  205. package/src/components/header/header.ts +52 -5
  206. package/src/components/header/index.ts +6 -0
  207. package/src/components/header/types.ts +38 -0
  208. package/src/components/header-menu/header-menu.test.ts +131 -10
  209. package/src/components/header-menu/header-menu.ts +23 -24
  210. package/src/components/header-menu/types.ts +1 -1
  211. package/src/components/index.ts +18 -2
  212. package/src/components/input-wrapper/input-wrapper.test.ts +45 -0
  213. package/src/components/input-wrapper/input-wrapper.ts +17 -9
  214. package/src/components/modal/modal.ts +8 -9
  215. package/src/components/searchinput/searchinput.test.ts +43 -0
  216. package/src/components/searchinput/searchinput.ts +29 -12
  217. package/src/components/select/index.ts +1 -1
  218. package/src/components/select/select.test.ts +28 -0
  219. package/src/components/select/select.ts +4 -3
  220. package/src/components/textarea/textarea.test.ts +16 -0
  221. package/src/components/textarea/textarea.ts +3 -1
  222. package/src/components/textinput/textinput.test.ts +28 -0
  223. package/src/components/textinput/textinput.ts +3 -1
  224. package/src/components/timepicker/timepicker.test.ts +26 -0
  225. package/src/components/timepicker/timepicker.ts +12 -6
  226. package/dist/accordion-FISAiAbX.cjs +0 -47
  227. package/dist/button-C_YzTSuU.js +0 -96
  228. package/dist/combobox-D6H9rWPV.cjs +0 -135
  229. package/dist/consent-X3wvhteO.cjs +0 -10
  230. package/dist/fileupload-BLVrslUX.cjs +0 -401
  231. package/dist/header-CFrsaq0c.cjs +0 -310
  232. package/dist/header-D_xvPR4R.js +0 -801
  233. package/dist/header-menu-DMdP_c6X.cjs +0 -126
  234. package/dist/modal-DKU7PnjJ.cjs +0 -35
  235. package/dist/searchinput-CyO5k4Q4.js +0 -148
  236. package/dist/searchinput-DG6YetL1.cjs +0 -60
  237. package/dist/shared-utils/modal-scroll-lock.d.ts +0 -10
  238. package/dist/tabs-CGo0ODPa.cjs +0 -40
  239. package/dist/tabs-ChdR0D1C.js +0 -379
  240. /package/dist/shared-utils/{header-menu → header-footer}/icon-map.d.ts +0 -0
@@ -0,0 +1,156 @@
1
+ import { a as e, d as t, n, o as r, p as i, s as a, t as o } from "./element-BoJrqauR.js";
2
+ import { t as s } from "./class-map-CAQCRB1W.js";
3
+ import "./icon-DGFEIlco.js";
4
+ import { t as c } from "./if-defined-D0bnetLJ.js";
5
+ import { t as l } from "./focus-modality-controller-Dc2S-KqR.js";
6
+ //#region src/components/searchinput/searchinput.ts
7
+ var u = class extends o {
8
+ constructor(...e) {
9
+ super(...e), this.appearance = "local", this.inputSize = "medium", this.disabled = !1, this.fullwidth = !1, this.id = "", this.placeholder = "Søk…", this.value = "", this.focusModality = new l(this, ".pkt-searchinput");
10
+ }
11
+ willUpdate(e) {
12
+ super.willUpdate(e);
13
+ let t = this.getAttribute("aria-label");
14
+ t && (this.inputAriaLabel = t, this.removeAttribute("aria-label"));
15
+ }
16
+ get suggestionsId() {
17
+ return `${this.id}-suggestions`;
18
+ }
19
+ dispatchSearch() {
20
+ this.dispatchEvent(new CustomEvent("pkt-search", {
21
+ detail: { value: this.value },
22
+ bubbles: !0,
23
+ composed: !0
24
+ }));
25
+ }
26
+ onInput(e) {
27
+ let t = e.target;
28
+ this.value = t.value;
29
+ }
30
+ onInputKeydown(e) {
31
+ e.key === "Enter" && (this.action || e.preventDefault(), this.dispatchSearch());
32
+ }
33
+ onSearchClick(e) {
34
+ this.action || e.preventDefault(), this.dispatchSearch();
35
+ }
36
+ onSuggestionClick(e, t, n) {
37
+ let r = new CustomEvent("pkt-suggestion-click", {
38
+ detail: {
39
+ index: n,
40
+ suggestion: t
41
+ },
42
+ bubbles: !0,
43
+ composed: !0,
44
+ cancelable: !0
45
+ });
46
+ this.dispatchEvent(r) || e.preventDefault();
47
+ }
48
+ renderSuggestion(e, n) {
49
+ let r = i`
50
+ ${e.title ? i`<h3 class="pkt-searchinput__suggestion-title">${e.title}</h3>` : t}
51
+ ${e.text ? i`<p class="pkt-searchinput__suggestion-text">${e.text}</p>` : t}
52
+ `;
53
+ return e.href ? i`<a
54
+ href=${e.href}
55
+ class="pkt-searchinput__suggestion"
56
+ @click=${(t) => this.onSuggestionClick(t, e, n)}
57
+ >
58
+ ${r}
59
+ </a>` : e.nonInteractive ? i`<div class="pkt-searchinput__suggestion">${r}</div>` : i`<button
60
+ type="button"
61
+ class="pkt-searchinput__suggestion"
62
+ @click=${(t) => this.onSuggestionClick(t, e, n)}
63
+ >
64
+ ${r}
65
+ </button>`;
66
+ }
67
+ render() {
68
+ let e = s({
69
+ "pkt-searchinput": !0,
70
+ [`pkt-searchinput--${this.appearance}`]: !0,
71
+ [`pkt-searchinput--${this.inputSize}`]: !0,
72
+ "pkt-searchinput--fullwidth": this.fullwidth
73
+ }), n = s({
74
+ "pkt-searchinput__button": !0,
75
+ "pkt-input-icon": this.appearance === "local",
76
+ "pkt-btn": !0,
77
+ [`pkt-btn--${this.inputSize}`]: !0,
78
+ "pkt-btn--icon-only": !0,
79
+ "pkt-btn--tertiary": this.appearance === "local",
80
+ "pkt-btn--primary": this.appearance === "global" || this.appearance === "local-with-button",
81
+ "pkt-btn--yellow": this.appearance === "global"
82
+ }), r = s({
83
+ "pkt-input": !0,
84
+ [`pkt-input--${this.inputSize}`]: !0,
85
+ "pkt-input--fullwidth": this.fullwidth
86
+ }), a = this.appearance === "local" ? `pkt-input__container pkt-input__container--${this.inputSize}` : "pkt-searchinput__field", o = i`
87
+ ${this.label ? i`<label for=${c(this.id || void 0)} class="pkt-inputwrapper__label"
88
+ >${this.label}</label
89
+ >` : t}
90
+ <div class=${a}>
91
+ <input
92
+ class=${r}
93
+ type="search"
94
+ name=${this.name || this.id}
95
+ id=${this.id}
96
+ placeholder=${this.placeholder || "Søk…"}
97
+ .value=${this.value}
98
+ ?disabled=${this.disabled}
99
+ autocomplete="off"
100
+ aria-label=${c(this.inputAriaLabel)}
101
+ aria-autocomplete=${this.suggestions ? "list" : t}
102
+ aria-controls=${this.suggestions ? this.suggestionsId : t}
103
+ @input=${this.onInput}
104
+ @keydown=${this.onInputKeydown}
105
+ />
106
+ <button
107
+ type="submit"
108
+ class=${n}
109
+ ?disabled=${this.disabled}
110
+ @click=${this.onSearchClick}
111
+ >
112
+ <pkt-icon class="pkt-btn__icon" name="magnifying-glass-big"></pkt-icon>
113
+ <span class="pkt-btn__text">${this.label || this.placeholder || "Søk…"}</span>
114
+ </button>
115
+ </div>
116
+ ${this.suggestions ? i`<ul
117
+ id=${this.suggestionsId}
118
+ class="pkt-searchinput__suggestions"
119
+ aria-live="assertive"
120
+ >
121
+ ${this.suggestions.map((e, t) => i` <li>${this.renderSuggestion(e, t)}</li> `)}
122
+ </ul>` : t}
123
+ `;
124
+ return this.action ? i`<form
125
+ role="search"
126
+ class=${e}
127
+ action=${this.action}
128
+ method=${c(this.method)}
129
+ >
130
+ ${o}
131
+ </form>` : i`<div role="search" class=${e}>${o}</div>`;
132
+ }
133
+ };
134
+ n([r({ type: String })], u.prototype, "appearance", void 0), n([r({
135
+ type: String,
136
+ attribute: "input-size"
137
+ })], u.prototype, "inputSize", void 0), n([r({
138
+ type: Boolean,
139
+ reflect: !0
140
+ })], u.prototype, "disabled", void 0), n([r({
141
+ type: Boolean,
142
+ reflect: !0
143
+ })], u.prototype, "fullwidth", void 0), n([r({
144
+ type: String,
145
+ reflect: !0
146
+ })], u.prototype, "id", void 0), n([r({ type: String })], u.prototype, "label", void 0), n([r({ type: String })], u.prototype, "name", void 0), n([r({ type: String })], u.prototype, "placeholder", void 0), n([r({ type: String })], u.prototype, "value", void 0), n([r({ type: Array })], u.prototype, "suggestions", void 0), n([r({ type: String })], u.prototype, "action", void 0), n([r({ type: String })], u.prototype, "method", void 0), n([e()], u.prototype, "inputAriaLabel", void 0);
147
+ try {
148
+ a("pkt-searchinput")(u);
149
+ } catch {
150
+ console.warn("Forsøker å definere <pkt-searchinput>, men den er allerede definert");
151
+ }
152
+ //#endregion
153
+ //#region src/components/searchinput/index.ts
154
+ var d = u;
155
+ //#endregion
156
+ export { u as n, d as t };
@@ -0,0 +1,60 @@
1
+ const e=require("./element-DJzurxgt.cjs"),t=require("./class-map-CCZN5uS3.cjs");require("./icon-B8PVq2O6.cjs");const n=require("./if-defined-DrwbxQOj.cjs"),r=require("./focus-modality-controller-C1ocyv2J.cjs");var i=class extends e.t{constructor(...e){super(...e),this.appearance=`local`,this.inputSize=`medium`,this.disabled=!1,this.fullwidth=!1,this.id=``,this.placeholder=`Søk…`,this.value=``,this.focusModality=new r.t(this,`.pkt-searchinput`)}willUpdate(e){super.willUpdate(e);let t=this.getAttribute(`aria-label`);t&&(this.inputAriaLabel=t,this.removeAttribute(`aria-label`))}get suggestionsId(){return`${this.id}-suggestions`}dispatchSearch(){this.dispatchEvent(new CustomEvent(`pkt-search`,{detail:{value:this.value},bubbles:!0,composed:!0}))}onInput(e){let t=e.target;this.value=t.value}onInputKeydown(e){e.key===`Enter`&&(this.action||e.preventDefault(),this.dispatchSearch())}onSearchClick(e){this.action||e.preventDefault(),this.dispatchSearch()}onSuggestionClick(e,t,n){let r=new CustomEvent(`pkt-suggestion-click`,{detail:{index:n,suggestion:t},bubbles:!0,composed:!0,cancelable:!0});this.dispatchEvent(r)||e.preventDefault()}renderSuggestion(t,n){let r=e.p`
2
+ ${t.title?e.p`<h3 class="pkt-searchinput__suggestion-title">${t.title}</h3>`:e.d}
3
+ ${t.text?e.p`<p class="pkt-searchinput__suggestion-text">${t.text}</p>`:e.d}
4
+ `;return t.href?e.p`<a
5
+ href=${t.href}
6
+ class="pkt-searchinput__suggestion"
7
+ @click=${e=>this.onSuggestionClick(e,t,n)}
8
+ >
9
+ ${r}
10
+ </a>`:t.nonInteractive?e.p`<div class="pkt-searchinput__suggestion">${r}</div>`:e.p`<button
11
+ type="button"
12
+ class="pkt-searchinput__suggestion"
13
+ @click=${e=>this.onSuggestionClick(e,t,n)}
14
+ >
15
+ ${r}
16
+ </button>`}render(){let r=t.t({"pkt-searchinput":!0,[`pkt-searchinput--${this.appearance}`]:!0,[`pkt-searchinput--${this.inputSize}`]:!0,"pkt-searchinput--fullwidth":this.fullwidth}),i=t.t({"pkt-searchinput__button":!0,"pkt-input-icon":this.appearance===`local`,"pkt-btn":!0,[`pkt-btn--${this.inputSize}`]:!0,"pkt-btn--icon-only":!0,"pkt-btn--tertiary":this.appearance===`local`,"pkt-btn--primary":this.appearance===`global`||this.appearance===`local-with-button`,"pkt-btn--yellow":this.appearance===`global`}),a=t.t({"pkt-input":!0,[`pkt-input--${this.inputSize}`]:!0,"pkt-input--fullwidth":this.fullwidth}),o=this.appearance===`local`?`pkt-input__container pkt-input__container--${this.inputSize}`:`pkt-searchinput__field`,s=e.p`
17
+ ${this.label?e.p`<label for=${n.t(this.id||void 0)} class="pkt-inputwrapper__label"
18
+ >${this.label}</label
19
+ >`:e.d}
20
+ <div class=${o}>
21
+ <input
22
+ class=${a}
23
+ type="search"
24
+ name=${this.name||this.id}
25
+ id=${this.id}
26
+ placeholder=${this.placeholder||`Søk…`}
27
+ .value=${this.value}
28
+ ?disabled=${this.disabled}
29
+ autocomplete="off"
30
+ aria-label=${n.t(this.inputAriaLabel)}
31
+ aria-autocomplete=${this.suggestions?`list`:e.d}
32
+ aria-controls=${this.suggestions?this.suggestionsId:e.d}
33
+ @input=${this.onInput}
34
+ @keydown=${this.onInputKeydown}
35
+ />
36
+ <button
37
+ type="submit"
38
+ class=${i}
39
+ ?disabled=${this.disabled}
40
+ @click=${this.onSearchClick}
41
+ >
42
+ <pkt-icon class="pkt-btn__icon" name="magnifying-glass-big"></pkt-icon>
43
+ <span class="pkt-btn__text">${this.label||this.placeholder||`Søk…`}</span>
44
+ </button>
45
+ </div>
46
+ ${this.suggestions?e.p`<ul
47
+ id=${this.suggestionsId}
48
+ class="pkt-searchinput__suggestions"
49
+ aria-live="assertive"
50
+ >
51
+ ${this.suggestions.map((t,n)=>e.p` <li>${this.renderSuggestion(t,n)}</li> `)}
52
+ </ul>`:e.d}
53
+ `;return this.action?e.p`<form
54
+ role="search"
55
+ class=${r}
56
+ action=${this.action}
57
+ method=${n.t(this.method)}
58
+ >
59
+ ${s}
60
+ </form>`:e.p`<div role="search" class=${r}>${s}</div>`}};e.n([e.o({type:String})],i.prototype,`appearance`,void 0),e.n([e.o({type:String,attribute:`input-size`})],i.prototype,`inputSize`,void 0),e.n([e.o({type:Boolean,reflect:!0})],i.prototype,`disabled`,void 0),e.n([e.o({type:Boolean,reflect:!0})],i.prototype,`fullwidth`,void 0),e.n([e.o({type:String,reflect:!0})],i.prototype,`id`,void 0),e.n([e.o({type:String})],i.prototype,`label`,void 0),e.n([e.o({type:String})],i.prototype,`name`,void 0),e.n([e.o({type:String})],i.prototype,`placeholder`,void 0),e.n([e.o({type:String})],i.prototype,`value`,void 0),e.n([e.o({type:Array})],i.prototype,`suggestions`,void 0),e.n([e.o({type:String})],i.prototype,`action`,void 0),e.n([e.o({type:String})],i.prototype,`method`,void 0),e.n([e.a()],i.prototype,`inputAriaLabel`,void 0);try{e.s(`pkt-searchinput`)(i)}catch{console.warn(`Forsøker å definere <pkt-searchinput>, men den er allerede definert`)}var a=i;Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return a}});
@@ -1,5 +1,6 @@
1
- const e=require("./element-DJzurxgt.cjs"),t=require("./element-with-slot-BY7Jc-q8.cjs"),n=require("./if-defined-DrwbxQOj.cjs"),r=require("./ref-DO7TzO4O.cjs"),i=require("./input-element-ZGOWsvKM.cjs"),a=require("./pkt-options-controller-CPrfqepu.cjs");require("./input-wrapper-BRjQB4zM.cjs");var o=class extends i.t{constructor(...e){super(...e),this._optionsProp=[],this._options=[]}get options(){return this._options.map(e=>({...e,selected:this.isOptionSelected(e)}))}set options(e){this._optionsProp=e,this.requestUpdate(`_optionsProp`,this._options)}isOptionSelected(e){return Array.isArray(this.value)?this.value.includes(e.value):e.value===this.value}findOptionByValue(e){return this._options.find(t=>t.value===e)}getSelectedOptions(){return this._options.filter(e=>this.isOptionSelected(e))}parseOptions(){let e=this._optionsProp.length>0,t=this.optionsController?.nodes?.length&&this.optionsController.nodes.length>0;e?this._options=this._optionsProp:t&&(this._options=this.optionsController.options)}willUpdate(e){super.willUpdate(e),this.parseOptions()}};e.n([e.o({type:Array,attribute:`options`})],o.prototype,`_optionsProp`,void 0),e.n([e.a()],o.prototype,`_options`,void 0);var s=class extends o{constructor(){super(),this.inputRef=r.t(),this.value=``,this.selectedIndex=-1,this.selectedOptions=void 0,this.optionsController=new a.t(this)}connectedCallback(){super.connectedCallback(),this.parseOptions(),this._options.forEach(e=>{e.selected&&!this.value&&(this.value=e.value)})}add(e,t){let n={value:e.value||e.text,label:e.text||e.value,selected:e.selected,disabled:e.disabled};if(t===void 0)this._options.push(n);else if(typeof t==`number`)this._options.splice(t,0,n);else{let e=t.value||t.text,r=this._options.findIndex(t=>t.value===e);r>=0?this._options.splice(r,0,n):this._options.push(n)}e.selected&&(this.value=e.value||e.text,this.selectedIndex=this._options.findIndex(e=>e.value===this.value)),this.requestUpdate()}remove(e){typeof e==`number`&&(this.selectedIndex===e&&(this.value=this._options[0]?.value||``),this._options.splice(e,1),this.requestUpdate())}item(e){return this.inputRef.value?.item(e)}namedItem(e){return this.inputRef.value?.namedItem(e)}showPicker(){this.inputRef.value&&`showPicker`in this.inputRef.value&&this.inputRef.value.showPicker()}attributeChangedCallback(e,t,n){e===`options`&&(this._options=n?JSON.parse(n):[]),e===`value`&&this.value!==t&&(this.selectedIndex=this.touched?this.returnNumberOrNull(this.inputRef.value?.selectedIndex):this._options.findIndex(e=>e.value===n),this.selectedOptions=this.inputRef.value?.selectedOptions,this.valueChanged(n,t)),super.attributeChangedCallback(e,t,n)}update(e){super.update(e),e.has(`_optionsProp`)&&this._optionsProp.length>0&&(this._options=this._optionsProp,this.requestUpdate(`_options`),!this.value&&this._options.length>0&&(this.value=this._options[0].value,this.selectedIndex=0)),e.has(`value`)&&this.value!==e.get(`value`)&&(this.selectedIndex=this.touched?this.returnNumberOrNull(this.inputRef.value?.selectedIndex):this._options.findIndex(e=>e.value===this.value),this.selectedOptions=this.inputRef.value?.selectedOptions,this.valueChanged(this.value,e.get(`value`))),e.has(`id`)&&!this.name&&this.id&&(this.name=this.id)}firstUpdated(e){super.firstUpdated(e),this._optionsProp.length&&(this._options=this._optionsProp),!this.value&&this._options.length>0?(this.value=this._options[0].value,this.selectedIndex=0):this.selectedIndex=this._options.findIndex(e=>e.value===this.value),this.selectedOptions=this.inputRef.value?.selectedOptions}render(){let i=`pkt-input ${this.fullwidth?`pkt-input--fullwidth`:``}`;return e.p`
1
+ const e=require("./element-DJzurxgt.cjs"),t=require("./element-with-slot-BY7Jc-q8.cjs"),n=require("./if-defined-DrwbxQOj.cjs"),r=require("./ref-DO7TzO4O.cjs"),i=require("./input-element-B0qLbEdF.cjs"),a=require("./pkt-options-controller-CPrfqepu.cjs");require("./input-wrapper-DPkkiG7S.cjs");var o=class extends i.t{constructor(...e){super(...e),this._optionsProp=[],this._options=[]}get options(){return this._options.map(e=>({...e,selected:this.isOptionSelected(e)}))}set options(e){this._optionsProp=e,this.requestUpdate(`_optionsProp`,this._options)}isOptionSelected(e){return Array.isArray(this.value)?this.value.includes(e.value):e.value===this.value}findOptionByValue(e){return this._options.find(t=>t.value===e)}getSelectedOptions(){return this._options.filter(e=>this.isOptionSelected(e))}parseOptions(){let e=this._optionsProp.length>0,t=this.optionsController?.nodes?.length&&this.optionsController.nodes.length>0;e?this._options=this._optionsProp:t&&(this._options=this.optionsController.options)}willUpdate(e){super.willUpdate(e),this.parseOptions()}};e.n([e.o({type:Array,attribute:`options`})],o.prototype,`_optionsProp`,void 0),e.n([e.a()],o.prototype,`_options`,void 0);var s=class extends o{constructor(){super(),this.inputRef=r.t(),this.value=``,this.selectedIndex=-1,this.selectedOptions=void 0,this.optionsController=new a.t(this)}connectedCallback(){super.connectedCallback(),this.parseOptions(),this._options.forEach(e=>{e.selected&&!this.value&&(this.value=e.value)})}add(e,t){let n={value:e.value||e.text,label:e.text||e.value,selected:e.selected,disabled:e.disabled};if(t===void 0)this._options.push(n);else if(typeof t==`number`)this._options.splice(t,0,n);else{let e=t.value||t.text,r=this._options.findIndex(t=>t.value===e);r>=0?this._options.splice(r,0,n):this._options.push(n)}e.selected&&(this.value=e.value||e.text,this.selectedIndex=this._options.findIndex(e=>e.value===this.value)),this.requestUpdate()}remove(e){typeof e==`number`&&(this.selectedIndex===e&&(this.value=this._options[0]?.value||``),this._options.splice(e,1),this.requestUpdate())}item(e){return this.inputRef.value?.item(e)}namedItem(e){return this.inputRef.value?.namedItem(e)}showPicker(){this.inputRef.value&&`showPicker`in this.inputRef.value&&this.inputRef.value.showPicker()}attributeChangedCallback(e,t,n){e===`options`&&(this._options=n?JSON.parse(n):[]),e===`value`&&this.value!==t&&(this.selectedIndex=this.touched?this.returnNumberOrNull(this.inputRef.value?.selectedIndex):this._options.findIndex(e=>e.value===n),this.selectedOptions=this.inputRef.value?.selectedOptions,this.valueChanged(n,t)),super.attributeChangedCallback(e,t,n)}update(e){super.update(e),e.has(`_optionsProp`)&&this._optionsProp.length>0&&(this._options=this._optionsProp,this.requestUpdate(`_options`),!this.value&&this._options.length>0&&(this.value=this._options[0].value,this.selectedIndex=0)),e.has(`value`)&&this.value!==e.get(`value`)&&(this.selectedIndex=this.touched?this.returnNumberOrNull(this.inputRef.value?.selectedIndex):this._options.findIndex(e=>e.value===this.value),this.selectedOptions=this.inputRef.value?.selectedOptions,this.valueChanged(this.value,e.get(`value`))),e.has(`id`)&&!this.name&&this.id&&(this.name=this.id)}firstUpdated(e){super.firstUpdated(e),this._optionsProp.length&&(this._options=this._optionsProp),!this.value&&this._options.length>0?(this.value=this._options[0].value,this.selectedIndex=0):this.selectedIndex=this._options.findIndex(e=>e.value===this.value),this.selectedOptions=this.inputRef.value?.selectedOptions}render(){let i=`pkt-input pkt-input--${this.inputSize} ${this.fullwidth?`pkt-input--fullwidth`:``}`;return e.p`
2
2
  <pkt-input-wrapper
3
+ .size=${this.inputSize}
3
4
  ?counter=${this.counter}
4
5
  ?disabled=${this.disabled}
5
6
  ?hasError=${this.hasError}
@@ -2,9 +2,9 @@ import { a as e, n as t, o as n, p as r, s as i } from "./element-BoJrqauR.js";
2
2
  import { n as a } from "./element-with-slot-mXLg8gg8.js";
3
3
  import { t as o } from "./if-defined-D0bnetLJ.js";
4
4
  import { n as s, t as c } from "./ref-WGS0u7i2.js";
5
- import { t as l } from "./input-element-BFHpeoV8.js";
5
+ import { t as l } from "./input-element-C0RnXi-J.js";
6
6
  import { t as u } from "./pkt-options-controller-DMxYwnnj.js";
7
- import "./input-wrapper-DaA98B5l.js";
7
+ import "./input-wrapper-fWV5P4MN.js";
8
8
  //#region src/base-elements/options-input-element.ts
9
9
  var d = class extends l {
10
10
  constructor(...e) {
@@ -88,9 +88,10 @@ var f = class extends d {
88
88
  super.firstUpdated(e), this._optionsProp.length && (this._options = this._optionsProp), !this.value && this._options.length > 0 ? (this.value = this._options[0].value, this.selectedIndex = 0) : this.selectedIndex = this._options.findIndex((e) => e.value === this.value), this.selectedOptions = this.inputRef.value?.selectedOptions;
89
89
  }
90
90
  render() {
91
- let e = `pkt-input ${this.fullwidth ? "pkt-input--fullwidth" : ""}`;
91
+ let e = `pkt-input pkt-input--${this.inputSize} ${this.fullwidth ? "pkt-input--fullwidth" : ""}`;
92
92
  return r`
93
93
  <pkt-input-wrapper
94
+ .size=${this.inputSize}
94
95
  ?counter=${this.counter}
95
96
  ?disabled=${this.disabled}
96
97
  ?hasError=${this.hasError}
File without changes
@@ -0,0 +1,95 @@
1
+ /**
2
+ * footer.ts
3
+ *
4
+ * Framework-agnostic prop types for the reworked footer components
5
+ * (`PktFooter` / `pkt-footer` and `PktFooterSimple` / `pkt-footer-simple`).
6
+ *
7
+ * Both components render an optional grey "secondary" band with the
8
+ * consumer's custom content, stacked on top of the global (blue) footer
9
+ * whose content comes from the same CDN payload as the global header —
10
+ * see `header-footer.ts`.
11
+ */
12
+ import type { THeaderFooterApi, THeaderMenuLocale } from './header-footer';
13
+ /** Custom link in the secondary (grey) footer. */
14
+ export interface IPktFooterLink {
15
+ href: string;
16
+ text: string;
17
+ /**
18
+ * Mark the link as external: the link's top domain is shown in
19
+ * parentheses after the text ("Ledige stillinger (webcruiter.com)"),
20
+ * per Punkt's link-labelling guidance.
21
+ */
22
+ external?: boolean;
23
+ openInNewTab?: boolean;
24
+ }
25
+ /** Column of custom content in the secondary footer (1–3 per footer). */
26
+ export interface IPktFooterColumn {
27
+ title: string;
28
+ /** Optional free-text paragraph shown above the links. */
29
+ text?: string;
30
+ links?: IPktFooterLink[];
31
+ }
32
+ /**
33
+ * @deprecated The social-media row now comes from the global footer's
34
+ * payload. Only rendered when explicitly supplied.
35
+ */
36
+ export interface IPktFooterSocialLink {
37
+ href: string;
38
+ iconName?: string;
39
+ language?: string;
40
+ openInNewTab?: boolean;
41
+ }
42
+ /** Props shared by `PktFooter` and `PktFooterSimple` in both frameworks. */
43
+ export interface IPktFooterBase<IconType = string> {
44
+ /** Pre-fetched header/footer payload. If supplied, the component skips its own fetch. */
45
+ data?: THeaderFooterApi<IconType>;
46
+ /** Endpoint to fetch the header/footer payload from. */
47
+ dataUrl?: string;
48
+ /** Locale key to select from the payload. Defaults to `nb-NO`. */
49
+ locale?: THeaderMenuLocale;
50
+ /** Skip the global (blue) footer entirely, e.g. when CSP blocks the CDN. Default: false */
51
+ skipGlobal?: boolean;
52
+ /** Open custom links in a new tab. Applies to custom content only. Default: false */
53
+ openLinksInNewTab?: boolean;
54
+ /**
55
+ * Replace the payload's cookie-settings link (`#cb-trigger`) with
56
+ * Punkt's own consent dialog. When unset the cookie-settings link is
57
+ * hidden. Default: false
58
+ */
59
+ includeConsent?: boolean;
60
+ hotjarId?: string | null;
61
+ googleAnalyticsId?: string | null;
62
+ devMode?: boolean;
63
+ cookieDomain?: string | null;
64
+ cookieSecure?: string | null;
65
+ cookieExpiryDays?: string | null;
66
+ }
67
+ export interface IPktFooterProps<IconType = string> extends IPktFooterBase<IconType> {
68
+ /** Custom content columns for the secondary (grey) footer. */
69
+ columns?: IPktFooterColumn[];
70
+ /** @deprecated Use `columns`. Mapped to the first entry of `columns`. */
71
+ columnOne?: IPktFooterColumn;
72
+ /** @deprecated Use `columns`. Mapped to the second entry of `columns`. */
73
+ columnTwo?: IPktFooterColumn;
74
+ /**
75
+ * @deprecated The privacy link now comes from the global footer's payload.
76
+ * Only rendered (in the secondary footer) when explicitly set to a
77
+ * non-default value.
78
+ */
79
+ personvernOgInfoLink?: string;
80
+ /**
81
+ * @deprecated The accessibility link now comes from the global footer's
82
+ * payload. Only rendered (in the secondary footer) when explicitly set
83
+ * to a non-default value.
84
+ */
85
+ tilgjengelighetLink?: string;
86
+ /** @deprecated The social-media row now comes from the global footer's payload. */
87
+ socialLinks?: IPktFooterSocialLink[];
88
+ }
89
+ export interface IPktFooterSimpleProps<IconType = string> extends IPktFooterBase<IconType> {
90
+ /** Custom links shown as a compact row in the secondary (grey) footer. */
91
+ links?: IPktFooterLink[];
92
+ }
93
+ /** Historical defaults for the deprecated link props — used to detect explicit overrides. */
94
+ export declare const DEFAULT_FOOTER_PERSONVERN_URL = "https://www.oslo.kommune.no/personvern-og-informasjonskapsler/";
95
+ export declare const DEFAULT_FOOTER_TILGJENGELIGHET_URL = "https://www.oslo.kommune.no/tilgjengelighet/";
@@ -1,18 +1,20 @@
1
1
  /**
2
- * header-menu.ts
2
+ * header-footer.ts
3
3
  *
4
- * Type definitions for the global header mega menu, shared between
5
- * @oslokommune/punkt-elements and (eventually) @oslokommune/punkt-react.
4
+ * Type definitions for the global header/footer payload (mega menu,
5
+ * footer, search and contact), shared between @oslokommune/punkt-elements
6
+ * and @oslokommune/punkt-react.
6
7
  *
7
8
  * The shape mirrors the live API response from
8
9
  * https://cdn.web.oslo.kommune.no/header-footer/header-footer.json
9
- * which the legacy oslo.kommune.no header consumes.
10
+ * which the "live" oslo.kommune.no header consumes.
10
11
  */
11
12
  /**
12
13
  * Locale keys present in the live payload. Typed as a string union with a
13
14
  * `string & {}` escape hatch so additional locales can be added without
14
15
  * a type-level breaking change.
15
16
  */
17
+ import type { Representing, TLogOutButtonPlacement, THeaderPosition, THeaderScrollBehavior, User, UserMenuItem } from './header';
16
18
  export type THeaderMenuLocale = 'nb-NO' | 'en-GB' | (string & {});
17
19
  /** Plain link without an icon. */
18
20
  export interface IHeaderMenuLink {
@@ -104,5 +106,50 @@ export interface IPktHeaderMenu<IconType = string> {
104
106
  /** Pixel breakpoint below which sections collapse into accordions. */
105
107
  mobileBreakpoint?: number;
106
108
  }
109
+ /**
110
+ * Framework-agnostic props for the global (kommune-wide) header
111
+ * (`pkt-header-global` / `PktHeaderGlobal`). Elements narrows the
112
+ * boolean fields to `Booleanish` and React adds callback/className
113
+ * props on top — see each package's `header/types.ts`.
114
+ */
115
+ export interface IPktHeaderGlobal<IconType = string> {
116
+ /** Endpoint to fetch the header/footer payload from. */
117
+ dataUrl?: string;
118
+ /** Pre-fetched payload. If supplied, the component (and its menu) skips its own fetch. */
119
+ data?: THeaderFooterApi<IconType>;
120
+ /** Locale key to select from the payload. Defaults to `nb-NO`. */
121
+ locale?: THeaderMenuLocale;
122
+ /** Logo link URL. When omitted the logo is rendered without a link. */
123
+ logoLink?: string;
124
+ /** Override the CDN path the logo assets load from. Can also be set
125
+ * globally via `window.pktLogoPath`. */
126
+ logoPath?: string;
127
+ /** Show the search field. Default: true */
128
+ showSearch?: boolean;
129
+ /** Placeholder for the search field. Falls back to the payload's search placeholder, then 'Søk'. */
130
+ searchPlaceholder?: string;
131
+ /** Show the contact link (from the payload's `header.contact`). Default: true */
132
+ showContact?: boolean;
133
+ /** User object for the logged-in user. When set, the user menu is shown. */
134
+ user?: User;
135
+ /** User menu items. */
136
+ userMenu?: UserMenuItem<IconType>[];
137
+ /** Representation object. */
138
+ representing?: Representing;
139
+ /** Allow the user to change representation. */
140
+ canChangeRepresentation?: boolean;
141
+ /** Logout button placement. */
142
+ logOutButtonPlacement?: TLogOutButtonPlacement;
143
+ /** Header position. Default: 'fixed' */
144
+ position?: THeaderPosition;
145
+ /** Scroll behavior. Default: 'hide' */
146
+ scrollBehavior?: THeaderScrollBehavior;
147
+ /** Width below which the header switches to mobile layout. Default: 768 */
148
+ mobileBreakpoint?: number;
149
+ /** Width below which the header switches to tablet layout. Default: 1024 */
150
+ tabletBreakpoint?: number;
151
+ }
107
152
  /** Default URL of the live header/footer endpoint. */
108
153
  export declare const DEFAULT_HEADER_FOOTER_URL = "https://cdn.web.oslo.kommune.no/header-footer/header-footer.json";
154
+ /** Default logo link for both header variants (unless overridden or hidden). */
155
+ export declare const DEFAULT_HEADER_LOGO_LINK = "https://www.oslo.kommune.no";
@@ -81,7 +81,7 @@ export type TLogOutButtonPlacement = 'userMenu' | 'header' | 'both' | 'none';
81
81
  /**
82
82
  * Position options for the header
83
83
  */
84
- export type THeaderPosition = 'fixed' | 'relative';
84
+ export type THeaderPosition = 'fixed' | 'sticky' | 'relative';
85
85
  /**
86
86
  * Scroll behavior options for the header
87
87
  */
@@ -4,12 +4,13 @@ export type { TAriaBoolean, TAriaBooleanMixed, TAriaCurrent, TAriaHasPopup, TAri
4
4
  export type { THeadingLevel, THeadingSize, THeadingWeight } from './heading';
5
5
  export type { User, Representing, UserMenuItem, InternalMenuItemBase, InternalMenuLink, InternalMenuButton, TInternalMenuItem, TSlotMenuVariant, THeaderMenu, TLogOutButtonPlacement, THeaderPosition, THeaderScrollBehavior, } from './header';
6
6
  export { convertUserMenuItem } from './header';
7
- export type { THeaderMenuLocale, IHeaderMenuLink, IHeaderMenuIconLink, IHeaderMenuButton, IHeaderMenuServices, IHeaderMenuSection, IMegaMenu, IHeaderFooter, IHeaderFooterLocaleData, THeaderFooterApi, IPktHeaderMenu, } from './header-menu';
8
- export { DEFAULT_HEADER_FOOTER_URL } from './header-menu';
7
+ export type { THeaderMenuLocale, IHeaderMenuLink, IHeaderMenuIconLink, IHeaderMenuButton, IHeaderMenuServices, IHeaderMenuSection, IMegaMenu, IHeaderFooter, IHeaderFooterLocaleData, THeaderFooterApi, IPktHeaderMenu, IPktHeaderGlobal, } from './header-footer';
8
+ export { DEFAULT_HEADER_FOOTER_URL, DEFAULT_HEADER_LOGO_LINK } from './header-footer';
9
+ export type { IPktFooterLink, IPktFooterColumn, IPktFooterSocialLink, IPktFooterBase, IPktFooterProps, IPktFooterSimpleProps, } from './footer';
10
+ export { DEFAULT_FOOTER_PERSONVERN_URL, DEFAULT_FOOTER_TILGJENGELIGHET_URL } from './footer';
9
11
  export type { TLayout, TVerticalPosition, THorizontalPosition, TPosition, TPositionWithCenter, } from './layout';
10
12
  export type { THTMLButtonType, TSelectionMode } from './form';
11
- export type { TSelectOption } from './select';
12
- export type { TSize3, TSize5, TSize7 } from './size';
13
+ export type { TPktInputSize, TSize3, TSize5, TSize7 } from './size';
13
14
  export type { TAlertSkin, TMessageboxSkin, TAccordionSkin, TCardSkin, TTagSkin } from './skin';
14
15
  export type { IDateConstraints, ICalendarGridDimensions, IGridCellPosition, TDateRangeMap, ISelectionState, ISelectionOptions, } from './calendar';
15
16
  export type { IDatepickerStrings } from './datepicker';
@@ -18,6 +19,7 @@ export type { ITimepickerStrings } from './timepicker';
18
19
  export { defaultTimepickerStrings } from './timepicker';
19
20
  export type { TProgressbarRole, TProgressbarSkin, TProgressbarStatusPlacement, TProgressbarStatusType, TProgressbarTitlePosition, } from './progressbar';
20
21
  export type { IPktComboboxOption, TPktComboboxTagSkin, TPktComboboxDisplayValue, TPktComboboxTagPlacement, } from './combobox';
22
+ export type { IPktSelectOption, TSelectOption } from './select';
21
23
  export type { TPktSearchInputAppearance, TPktSearchInputMethod, IPktSearchInputSuggestion, IPktSearchInput, } from './searchinput';
22
24
  export type { TUploadStrategy as TFileUploadStrategy, TFileUploadItemRenderer, TFilesChangedReason, TFileValidator, TTransferProgress, IFileItem, IFileTransfer, IFileValidateDetail, ITransferCancelledDetail, IFilesChangedDetail, IFileUploadStrings, } from './fileupload';
23
25
  export { defaultFileUploadStrings } from './fileupload';
@@ -5,6 +5,7 @@
5
5
  * stay aligned. React extends suggestions with `ReactNode` and optional
6
6
  * `onClick` in the component layer — see `@oslokommune/punkt-react`.
7
7
  */
8
+ import type { TPktInputSize } from './size';
8
9
  export type TPktSearchInputAppearance = 'local' | 'local-with-button' | 'global';
9
10
  export type TPktSearchInputMethod = 'get' | 'post' | 'dialog';
10
11
  /**
@@ -28,6 +29,7 @@ export interface IPktSearchInputSuggestion {
28
29
  */
29
30
  export interface IPktSearchInput {
30
31
  appearance?: TPktSearchInputAppearance;
32
+ inputSize?: TPktInputSize;
31
33
  disabled?: boolean;
32
34
  fullwidth?: boolean;
33
35
  id: string;
@@ -3,10 +3,11 @@
3
3
  * Lives in shared-types so both `@oslokommune/punkt-elements` and
4
4
  * `@oslokommune/punkt-react` can re-export the same canonical type.
5
5
  */
6
- export type TSelectOption = {
6
+ export interface IPktSelectOption {
7
7
  value: string;
8
8
  label: string;
9
9
  selected?: boolean;
10
10
  disabled?: boolean;
11
11
  hidden?: boolean;
12
- };
12
+ }
13
+ export type TSelectOption = IPktSelectOption;
@@ -16,3 +16,7 @@ export type TSize5 = 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
16
16
  * Full 7-level size scale
17
17
  */
18
18
  export type TSize7 = 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge';
19
+ /**
20
+ * Sizes used in our input components
21
+ */
22
+ export type TPktInputSize = 'xsmall' | 'small' | 'medium';
@@ -1,9 +1,3 @@
1
- /**
2
- * timepicker.ts
3
- *
4
- * Type definitions for the timepicker component.
5
- * Used by both Elements and React implementations.
6
- */
7
1
  /**
8
2
  * Translation strings for the timepicker component.
9
3
  * Matches the shape of the `timepicker` key in no.json.
@@ -1,3 +1,4 @@
1
+ import type { TPktInputSize } from '../shared-types/size';
1
2
  /**
2
3
  * Shared datepicker utility functions used by both Elements and React packages.
3
4
  * Only framework-agnostic functions belong here.
@@ -23,11 +24,11 @@ export declare const filterDates: (dates: string[], min?: string | null, max?: s
23
24
  /**
24
25
  * Generates input CSS classes for datepicker.
25
26
  */
26
- export declare const getDatepickerInputClasses: (fullwidth: boolean, showRangeLabels: boolean, multiple: boolean, range: boolean, readonly?: boolean, inputType?: string) => Record<string, boolean>;
27
+ export declare const getDatepickerInputClasses: (fullwidth: boolean, showRangeLabels: boolean, multiple: boolean, range: boolean, readonly?: boolean, inputType?: string, inputSize?: TPktInputSize) => Record<string, boolean>;
27
28
  /**
28
29
  * Generates button CSS classes for calendar toggle button.
29
30
  */
30
- export declare const getDatepickerButtonClasses: () => Record<string, boolean>;
31
+ export declare const getDatepickerButtonClasses: (inputSize?: TPktInputSize) => Record<string, boolean>;
31
32
  /**
32
33
  * Generates range label CSS classes.
33
34
  */
@@ -62,8 +63,8 @@ declare const _default: {
62
63
  validateRangeOrder: (values: string[]) => boolean;
63
64
  sortDates: (dates: string[]) => string[];
64
65
  filterDates: (dates: string[], min?: string | null, max?: string | null, excludedDates?: string[], excludedWeekdays?: string[]) => string[];
65
- getDatepickerInputClasses: (fullwidth: boolean, showRangeLabels: boolean, multiple: boolean, range: boolean, readonly?: boolean, inputType?: string) => Record<string, boolean>;
66
- getDatepickerButtonClasses: () => Record<string, boolean>;
66
+ getDatepickerInputClasses: (fullwidth: boolean, showRangeLabels: boolean, multiple: boolean, range: boolean, readonly?: boolean, inputType?: string, inputSize?: TPktInputSize) => Record<string, boolean>;
67
+ getDatepickerButtonClasses: (inputSize?: TPktInputSize) => Record<string, boolean>;
67
68
  getRangeLabelClasses: (showRangeLabels: boolean) => Record<string, boolean>;
68
69
  processDateSelection: (detail: string | string[], multiple: boolean, range: boolean) => string;
69
70
  handleCalendarPosition: (popup: HTMLElement | null, input: HTMLElement | null, hasCounter?: boolean) => void;
@@ -1,12 +1,6 @@
1
1
  /**
2
- * Build a list of focusable elements inside a container (same selector used by
3
- * Lit and React fileupload preview modals). Hidden elements are filtered out.
2
+ * Re-export of the generic focus-trap helpers, kept here for backwards
3
+ * compatibility with existing `shared-utils/fileupload` imports. The canonical
4
+ * implementation now lives in `shared-utils/focus-trap`.
4
5
  */
5
- export declare function getFocusableElements(container: HTMLElement | null | undefined): HTMLElement[];
6
- /**
7
- * Keyboard handler that wraps Tab / Shift-Tab focus around the first and last
8
- * focusable elements inside a container. Returns `true` if the event was handled.
9
- *
10
- * Call from a `keydown` listener on the modal root.
11
- */
12
- export declare function trapTabInside(event: KeyboardEvent, container: HTMLElement | null | undefined): boolean;
6
+ export { getFocusableElements, trapTabInside } from '../focus-trap';
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Build a list of focusable elements inside a container (same selector used by
3
+ * the fileupload preview modals and the global header mega menu). Hidden
4
+ * elements are filtered out.
5
+ */
6
+ export declare function getFocusableElements(container: HTMLElement | null | undefined): HTMLElement[];
7
+ /**
8
+ * Like {@link getFocusableElements}, but descends open shadow roots, treats a
9
+ * native `<summary>` as focusable, and skips content hidden inside a collapsed
10
+ * `<details>`. Returned in flattened tree order. Use this when the container may
11
+ * hold web components or `<details>` accordions (e.g. the header mega menu).
12
+ */
13
+ export declare function getFocusableElementsDeep(container: HTMLElement | null | undefined): HTMLElement[];
14
+ /** Resolve the genuinely focused element, piercing nested open shadow roots. */
15
+ export declare function getDeepActiveElement(doc?: Document): HTMLElement | null;
16
+ /**
17
+ * Keyboard handler that wraps Tab / Shift-Tab focus around the first and last
18
+ * focusable elements inside a container. Returns `true` if the event was handled.
19
+ *
20
+ * Call from a `keydown` listener on the modal root.
21
+ */
22
+ export declare function trapTabInside(event: KeyboardEvent, container: HTMLElement | null | undefined): boolean;
@@ -1,9 +1,10 @@
1
- import type { THeaderFooterApi } from '../../shared-types/header-menu';
1
+ import type { THeaderFooterApi } from '../../shared-types/header-footer';
2
2
  /**
3
3
  * Example header/footer payload used by the dev/demo pages in both
4
- * Punkt Elements and Punkt React. Mirrors the live Oslo kommune
5
- * payload closely enough to exercise every region of the mega menu
6
- * (services grid, four section columns, footer + social links).
4
+ * Punkt Elements and Punkt React. Verbatim copy of the live Oslo
5
+ * kommune payload from
6
+ * https://cdn.web.oslo.kommune.no/header-footer/header-footer.json
7
+ * (hentet 2026-07-06).
7
8
  *
8
9
  * Tests use focused per-test fixtures with smaller shapes — this
9
10
  * dataset is for visual demos only.
@@ -0,0 +1,26 @@
1
+ /**
2
+ * External-link labelling for the global footer.
3
+ *
4
+ * Punkt's link-labelling guidance (punkt.oslo.kommune.no/god-praksis/merking-av-lenker/)
5
+ * prefers spelling out the destination domain in parentheses after the link
6
+ * text — "Ledige stillinger (webcruiter.com)" — over an external-link icon.
7
+ */
8
+ /**
9
+ * Return the top domain of an absolute http(s) URL, or `undefined` for
10
+ * relative URLs, fragments, and non-web schemes (`mailto:`, `tel:`).
11
+ * Unlike `getExternalDomainLabel` this does no internal-host check — use
12
+ * it when the consumer has explicitly flagged the link as external.
13
+ */
14
+ export declare function getLinkDomainLabel(url: string | undefined): string | undefined;
15
+ /**
16
+ * Return the top domain to display after an external link's text, or
17
+ * `undefined` when the link needs no label:
18
+ *
19
+ * - relative URLs and fragments (`/jobb`, `#cb-trigger`) — same site
20
+ * - non-http(s) schemes (`mailto:`, `tel:`) — not web navigation
21
+ * - hosts on `oslo.kommune.no` (or a subdomain) — internal
22
+ *
23
+ * `internalHost` can widen what counts as internal, e.g. for consumers
24
+ * hosting the payload themselves.
25
+ */
26
+ export declare function getExternalDomainLabel(url: string | undefined, internalHost?: string): string | undefined;